CONOPT
Loading...
Searching...
No Matches
fvinclin2.f90
Go to the documentation of this file.
1!> @file fvinclin2.f90
2!! @ingroup FORT1THREAD_EXAMPLES
3!!
4!!
5!! This is the pindyck example rewritten to use the FVincLin
6!! way of defining nonlinear functions. The nonlinear functions
7!! must contain both linear and nonlinear terms.
8!! In this FvincLin2 example we also define the linear derivatives
9!! that appear in the nonlinear constraints.
10!!
11!!
12!! For more information about the individual callbacks, please have a look at the source code.
13
14!> Main program. A simple setup and call of CONOPT
15!!
16Program fvinclin2
17 Use proginfo
18 Use coidef
19 Use data_t
20 Implicit none
21!
22! Declare the user callback routines as Integer, External:
23!
24 Integer, External :: pin_readmatrix ! Mandatory Matrix definition routine defined below
25 Integer, External :: pin_fdeval ! Function and Derivative evaluation routine
26 ! needed a nonlinear model.
27 Integer, External :: std_status ! Standard callback for displaying solution status
28 Integer, External :: pin_solution ! Specialized callback for displaying solution values
29 Integer, External :: std_message ! Standard callback for managing messages
30 Integer, External :: std_errmsg ! Standard callback for managing error messages
31#if defined(itl)
32!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_ReadMatrix
33!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_FDEval
34!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Std_Status
35!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_Solution
36!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Std_Message
37!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Std_ErrMsg
38#endif
39!
40! Control vector
41!
42 INTEGER :: numcallback
43 INTEGER, Dimension(:), Pointer :: cntvect
44 INTEGER :: coi_error
45!
46! Other variables
47!
48 INTEGER :: major, minor, patch
49
50 call startup
51!
52! Create and initialize a Control Vector
53!
54 numcallback = coidef_size()
55 Allocate( cntvect(numcallback) )
56 coi_error = coidef_inifort( cntvect )
57
58! Write which version of CONOPT we are using.
59
60 call coiget_version( major, minor, patch )
61 write(*,"('Solving Pindyck Model using CONOPT version ',i2,'.',i2,'.',i2)") major, minor, patch
62!
63! Define the number of time periods, T.
64!
65 t = 16
66!
67! Tell CONOPT about the size of the model by populating the Control Vector:
68!
69! Number of variables (excl. slacks): 7 per period
70!
71 coi_error = max( coi_error, coidef_numvar( cntvect, 7 * t ) )
72!
73! Number of equations: 1 objective + 6 per period
74!
75 coi_error = max( coi_error, coidef_numcon( cntvect, 1 + 6 * t ) )
76!
77! Number of nonzeros in the Jacobian. See the counting in ReadMatrix below:
78! For each period there is 1 in the objective, 16 for unlagged
79! variables and 4 for lagged variables.
80!
81 coi_error = max( coi_error, coidef_numnz( cntvect, 17 * t + 4 * (t-1) ) )
82!
83! Number of nonlinear nonzeros. 5 unlagged for each period.
84!
85 coi_error = max( coi_error, coidef_numnlnz( cntvect, 5 * t ) )
86!
87! Direction: +1 = maximization.
88!
89 coi_error = max( coi_error, coidef_optdir( cntvect, 1 ) )
90!
91! Objective: Constraint no 1
92!
93 coi_error = max( coi_error, coidef_objcon( cntvect, 1 ) )
94!
95! Define that functions will include linear terms
96!
97 coi_error = max( coi_error, coidef_fvinclin( cntvect, +1 ) )
98!
99! Turn function debugging on in the initial point to check if it is consistent
100! with FVincLin2:
101!
102 coi_error = max( coi_error, coidef_debugfv( cntvect, -1 ) )
103!
104! Tell CONOPT about the callback routines:
105!
106 coi_error = max( coi_error, coidef_readmatrix( cntvect, pin_readmatrix ) )
107 coi_error = max( coi_error, coidef_fdeval( cntvect, pin_fdeval ) )
108 coi_error = max( coi_error, coidef_status( cntvect, std_status ) )
109 coi_error = max( coi_error, coidef_solution( cntvect, pin_solution ) )
110 coi_error = max( coi_error, coidef_message( cntvect, std_message ) )
111 coi_error = max( coi_error, coidef_errmsg( cntvect, std_errmsg ) )
112
113#if defined(LICENSE_INT_1) && defined(LICENSE_INT_2) && defined(LICENSE_INT_3) && defined(LICENSE_TEXT)
114 coi_error = max( coi_error, coidef_license( cntvect, license_int_1, license_int_2, license_int_3, license_text) )
115#endif
116
117 If ( coi_error .ne. 0 ) THEN
118 write(*,*)
119 write(*,*) '**** Fatal Error while loading CONOPT Callback routines.'
120 write(*,*)
121 call flog( "Skipping Solve due to setup errors", 1 )
122 ENDIF
123!
124! Save the solution so we can check the duals:
125!
126 do_allocate = .true.
127!
128 coi_error = coi_solve( cntvect )
129
130 Deallocate( cntvect )
131
132 write(*,*)
133 write(*,*) 'End of FVincLin2 Model. Return code=',coi_error
134
135 If ( coi_error /= 0 ) then
136 call flog( "Errors encountered during solution", 1 )
137 elseif ( stacalls == 0 .or. solcalls == 0 ) then
138 call flog( "Status or Solution routine was not called", 1 )
139 elseif ( sstat /= 1 .or. mstat /= 2 ) then
140 call flog( "Solver and Model Status was not as expected (1,2)", 1 )
141 elseif ( abs( obj-1170.4863d0 ) > 0.0001d0 ) then
142 call flog( "Incorrect objective returned", 1 )
143 Else
144 Call checkdual( 'FVincLin2', maximize )
145 endif
146
147 call flog( "Successful Solve", 0 )
148
149end Program fvinclin2
150!
151! =====================================================================
152! Define information about the model structure
153!
154
155!> Define information about the model
156!!
157!! @include{doc} readMatrix_params.dox
158Integer Function pin_readmatrix( lower, curr, upper, vsta, type, rhs, esta, &
159 colsta, rowno, value, nlflag, n, m, nz, usrmem )
160#if defined(itl)
161!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_ReadMatrix
162#endif
163 Use data_t
164 implicit none
165 integer, intent (in) :: n ! number of variables
166 integer, intent (in) :: m ! number of constraints
167 integer, intent (in) :: nz ! number of nonzeros
168 real*8, intent (in out), dimension(n) :: lower ! vector of lower bounds
169 real*8, intent (in out), dimension(n) :: curr ! vector of initial values
170 real*8, intent (in out), dimension(n) :: upper ! vector of upper bounds
171 integer, intent (in out), dimension(n) :: vsta ! vector of initial variable status
172 ! (not defined here)
173 integer, intent (out), dimension(m) :: type ! vector of equation types
174 integer, intent (in out), dimension(m) :: esta ! vector of initial equation status
175 ! (not defined here)
176 real*8, intent (in out), dimension(m) :: rhs ! vector of right hand sides
177 integer, intent (in out), dimension(n+1) :: colsta ! vector with start of column indices
178 integer, intent (out), dimension(nz) :: rowno ! vector of row numbers
179 integer, intent (in out), dimension(nz) :: nlflag ! vector of nonlinearity flags
180 real*8, intent (in out), dimension(nz) :: value ! vector of matrix values
181 real*8 usrmem(*) ! optional user memory
182
183 Integer :: it, is, i, icol, iz
184!
185! Define the information for the columns.
186!
187! We should not supply status information, vsta.
188!
189! We order the variables as follows:
190! td, cs, s, d, r, p, and rev. All variables for period 1 appears
191! first followed by all variables for period 2 etc.
192!
193! td, cs, s, and d have lower bounds of 0, r and p have lower
194! bounds of 1, and rev has no lower bound.
195! All have infinite upper bounds (default).
196! The initial value of td is 18, s is 7, cs is 7*t, d is td-s,
197! p is 14, and r is r(t-1)-d. No initial value for rev.
198!
199 do it = 1, t
200 is = 7*(it-1)
201 lower(is+1) = 0.d0
202 lower(is+2) = 0.d0
203 lower(is+3) = 0.d0
204 lower(is+4) = 0.d0
205 lower(is+5) = 1.d0
206 lower(is+6) = 1.d0
207 curr(is+1) = 18.d0
208 curr(is+2) = 7.d0*it
209 curr(is+3) = 7.d0
210 curr(is+4) = curr(is+1) - curr(is+3)
211 if ( it .gt. 1 ) then
212 curr(is+5) = curr(is+5-7) - curr(is+4)
213 else
214 curr(is+5) = 500.d0 - curr(is+4)
215 endif
216 curr(is+6) = 14.d0
217 enddo
218!
219! Define the information for the rows
220!
221! We order the constraints as follows: The objective is first,
222! followed by tddef, sdef, csdef, ddef, rdef, and revdef for
223! the first period, the same for the second period, etc.
224!
225! The objective is a nonbinding constraint:
226!
227 type(1) = 3
228!
229! All others are equalities:
230!
231 do i = 2, m
232 type(i) = 0
233 enddo
234!
235! Right hand sides: In all periods except the first, only tddef
236! has a nonzero right hand side of 1+2.3*1.015**(t-1).
237! In the initial period there are contributions from lagged
238! variables in the constraints that have lagged variables.
239!
240 do it = 1, t
241 is = 1 + 6*(it-1)
242 rhs(is+1) = 1.d0+2.3d0*1.015d0**(it-1)
243 enddo
244!
245! tddef: + 0.87*td(0)
246!
247 rhs(2) = rhs(2) + 0.87d0*18.d0
248!
249! sdef: +0.75*s(0)
250!
251 rhs(3) = 0.75d0*6.5d0
252!
253! csdef: +1*cs(0)
254!
255 rhs(4) = 0.d0
256!
257! rdef: +1*r(0)
258!
259 rhs(6) = 500.d0
260!
261! Define the structure and content of the Jacobian:
262! To help define the Jacobian pattern and values it can be useful to
263! make a picture of the Jacobian. We describe the variables for one
264! period and the constraints they are part of:
265!
266! td cs s d r p rev
267! Obj (1+r)**(1-t)
268! Period t:
269! tddef 1.0 0.13
270! sdef NL 1.0 NL
271! csdef 1.0 -1.0
272! ddef -1.0 1.0 1.0
273! rdef 1.0 1.0
274! revdef NL NL NL 1.0
275! Period t+1:
276! tddef -0.87
277! sdef -0.75
278! csdef -1.0
279! ddef
280! rdef -1.0
281! revdef
282!
283! The Jacobian has to be sorted column-wise so we will just define
284! the elements column by column according to the table above:
285!
286 iz = 1
287 icol = 1
288 do it = 1, t
289!
290! is points to the position before the first equation for the period
291!
292 is = 1 + 6*(it-1)
293!
294! Column td:
295!
296 colsta(icol) = iz
297 icol = icol + 1
298 rowno(iz) = is+1
299 value(iz) = +1.d0
300 nlflag(iz) = 0
301 iz = iz + 1
302 rowno(iz) = is+4
303 value(iz) = -1.d0
304 nlflag(iz) = 0
305 iz = iz + 1
306 if ( it .lt. t ) then
307 rowno(iz) = is+7
308 value(iz) = -0.87d0
309 nlflag(iz) = 0
310 iz = iz + 1
311 endif
312!
313! Column cs
314!
315 colsta(icol) = iz
316 icol = icol + 1
317 rowno(iz) = is+2
318 nlflag(iz) = 1
319 iz = iz + 1
320 rowno(iz) = is+3
321 value(iz) = +1.d0
322 nlflag(iz) = 0
323 iz = iz + 1
324 if ( it .lt. t ) then
325 rowno(iz) = is+9
326 value(iz) = -1.d0
327 nlflag(iz) = 0
328 iz = iz + 1
329 endif
330!
331! Column s
332!
333 colsta(icol) = iz
334 icol = icol + 1
335 rowno(iz) = is+2
336 value(iz) = +1.d0
337 nlflag(iz) = 0
338 iz = iz + 1
339 rowno(iz) = is+3
340 value(iz) = -1.d0
341 nlflag(iz) = 0
342 iz = iz + 1
343 rowno(iz) = is+4
344 value(iz) = +1.d0
345 nlflag(iz) = 0
346 iz = iz + 1
347 if ( it .lt. t ) then
348 rowno(iz) = is+8
349 value(iz) = -0.75d0
350 nlflag(iz) = 0
351 iz = iz + 1
352 endif
353!
354! Column d:
355!
356 colsta(icol) = iz
357 icol = icol + 1
358 rowno(iz) = is+4
359 value(iz) = +1.d0
360 nlflag(iz) = 0
361 iz = iz + 1
362 rowno(iz) = is+5
363 value(iz) = +1.d0
364 nlflag(iz) = 0
365 iz = iz + 1
366 rowno(iz) = is+6
367 nlflag(iz) = 1
368 iz = iz + 1
369!
370! Column r:
371!
372 colsta(icol) = iz
373 icol = icol + 1
374 rowno(iz) = is+5
375 value(iz) = +1.d0
376 nlflag(iz) = 0
377 iz = iz + 1
378 rowno(iz) = is+6
379 nlflag(iz) = 1
380 iz = iz + 1
381 if ( it .lt. t ) then
382 rowno(iz) = is+11
383 value(iz) = -1.d0
384 nlflag(iz) = 0
385 iz = iz + 1
386 endif
387!
388! Column p:
389!
390 colsta(icol) = iz
391 icol = icol + 1
392 rowno(iz) = is+1
393 value(iz) = +0.13d0
394 nlflag(iz) = 0
395 iz = iz + 1
396 rowno(iz) = is+2
397 nlflag(iz) = 1
398 iz = iz + 1
399 rowno(iz) = is+6
400 nlflag(iz) = 1
401 iz = iz + 1
402!
403! Column rev:
404!
405 colsta(icol) = iz
406 icol = icol + 1
407 rowno(iz) = +1
408 value(iz) = 1.05d0**(1-it)
409 nlflag(iz) = 0
410 iz = iz + 1
411 rowno(iz) = is+6
412 value(iz) = 1.d0
413 nlflag(iz) = 0
414 iz = iz + 1
415 enddo
416 colsta(icol) = iz
417
419
420end Function pin_readmatrix
421!
422! =====================================================================
423! Compute nonlinear terms and non-constant Jacobian elements
424!
425
426!> Compute nonlinear terms and non-constant Jacobian elements
427!!
428!! @include{doc} fdeval_params.dox
429Integer Function pin_fdeval( x, g, jac, rowno, jcnm, mode, ignerr, errcnt, &
430 n, nz, thread, usrmem )
431#if defined(itl)
432!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_FDEval
433#endif
434 Use data_t
435 implicit none
436 integer, intent (in) :: n ! number of variables
437 integer, intent (in) :: rowno ! number of the row to be evaluated
438 integer, intent (in) :: nz ! number of nonzeros in this row
439 real*8, intent (in), dimension(n) :: x ! vector of current solution values
440 real*8, intent (in out) :: g ! constraint value
441 real*8, intent (in out), dimension(n) :: jac ! vector of derivatives for current constraint
442 integer, intent (in), dimension(nz) :: jcnm ! list of variables that appear nonlinearly
443 ! in this row. Ffor information only.
444 integer, intent (in) :: mode ! evaluation mode: 1 = function value
445 ! 2 = derivatives, 3 = both
446 integer, intent (in) :: ignerr ! if 1 then errors can be ignored as long
447 ! as errcnt is incremented
448 integer, intent (in out) :: errcnt ! error counter to be incremented in case
449 ! of function evaluation errors.
450 integer, intent (in) :: thread
451 real*8 usrmem(*) ! optional user memory
452
453 integer it, is
454 real*8 h1, h2
455!
456! Compute the number of the period
457!
458 pin_fdeval = 0
459 it = (rowno+4) / 6
460 is = 7*(it-1)
461 if ( rowno == (it-1)*6+3 ) then
462!
463! sdef equation. All terms: s - 0.75*s(t-1) -(1.1+0.1*p)*1.02**(-cs/7)
464!
465 h1 = (1.1d0+0.1d0*x(is+6))
466 h2 = 1.02d0**(-x(is+2)/7.d0)
467 if ( mode == 1 .or. mode == 3 ) then
468 g = x(is+3) -h1*h2
469 if ( it > 1 ) g = g - 0.75d0*x(is+3-7) ! 0.75*s(t-1) only it t > 1
470 endif
471 if ( mode == 2 .or. mode == 3 ) then
472 jac(is+2) = h1*h2*log(1.02d0)/7.d0
473 jac(is+6) = -h2*0.1d0
474 jac(is+3) = 1.0d0 ! Linear
475 if ( it > 1 ) jac(is+3-7) = -0.75d0 ! Linear
476 endif
477 elseif ( rowno == (it-1)*6+7 ) then
478!
479! revdef equation. All terms: rev - d*(p-250/r)
480!
481 if ( mode == 1 .or. mode == 3 ) then
482 g = x(is+7) -x(is+4)*(x(is+6)-250.d0/x(is+5))
483 endif
484 if ( mode == 2 .or. mode == 3 ) then
485 jac(is+4) = -(x(is+6)-250.d0/x(is+5))
486 jac(is+5) = -x(is+4)*250d0/x(is+5)**2
487 jac(is+6) = -x(is+4)
488 jac(is+7) = 1.0d0 ! Linear
489 endif
490 else
491!
492! Error - this equation is not nonlinear
493!
494 write(*,*)
495 write(*,*) 'Error. FDEval called with rowno=',rowno
496 write(*,*)
497 pin_fdeval = 1
498 endif
499
500end Function pin_fdeval
501
502Integer Function pin_solution( XVAL, XMAR, XBAS, XSTA, YVAL, YMAR, YBAS, YSTA, N, M, USRMEM )
503#if defined(itl)
504!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_Solution
505#endif
506!
507! Specialized solution callback routine with names for variables and constraints
508!
509 Use proginfo
510 Use data_t
511 IMPLICIT NONE
512 INTEGER, Intent(IN) :: n, m
513 INTEGER, Intent(IN), Dimension(N) :: xbas, xsta
514 INTEGER, Intent(IN), Dimension(M) :: ybas, ysta
515 real*8, Intent(IN), Dimension(N) :: xval, xmar
516 real*8, Intent(IN), Dimension(M) :: yval, ymar
517 real*8, Intent(IN OUT) :: usrmem(*)
518 character*6, parameter, dimension(7) :: vname = (/'td ','cs ','s ','d ','r ','p ','rev '/)
519 character*6, parameter, dimension(6) :: ename = (/'tddef ','sdef ','csdef ','ddef ','rdef ','revdef'/)
520
521 INTEGER :: i, it, i1
522 CHARACTER*5, Parameter, Dimension(4) :: stat = (/ 'Lower','Upper','Basic','Super' /)
523
524 WRITE(10,"(/' Variable Solution value Reduced cost B-stat'/)")
525 i = 0
526 do it = 1, t
527 DO i1 = 1, 7
528 i = i + 1
529 WRITE(10,"(1X,A6,i2,1p,E20.6,E16.6,4X,A5 )") vname(i1), it, xval(i), xmar(i), stat(1+xbas(i))
530 ENDDO
531 enddo
532
533 WRITE(10,"(/' Constrnt Activity level Marginal cost B-stat'/)")
534 i = 1
535 WRITE(10,"(1x,'Objective',1P,E19.6,E16.6,4X,A5 )") yval(i), ymar(i), stat(1+ybas(i))
536 do it = 1, t
537 do i1 = 1, 6
538 i = i + 1
539 WRITE(10,"(1x,A6,i2,1P,E20.6,E16.6,4X,A5 )") ename(i1),it, yval(i), ymar(i), stat(1+ybas(i))
540 enddo
541 ENDDO
542
543 solcalls = solcalls + 1
544 pin_solution = 0
545
546END Function pin_solution
integer function std_status(modsta, solsta, iter, objval, usrmem)
Definition comdecl.f90:82
subroutine checkdual(case, minmax)
Definition comdecl.f90:365
integer function std_message(smsg, dmsg, nmsg, llen, usrmem, msgv)
Definition comdecl.f90:203
integer function std_errmsg(rowno, colno, posno, msglen, usrmem, msg)
Definition comdecl.f90:248
integer function pin_fdeval(x, g, jac, rowno, jcnm, mode, ignerr, errcnt, n, nz, thread, usrmem)
Compute nonlinear terms and non-constant Jacobian elements.
Definition fvboth.f90:436
integer function pin_readmatrix(lower, curr, upper, vsta, type, rhs, esta, colsta, rowno, value, nlflag, n, m, nz, usrmem)
Define information about the model.
Definition fvboth.f90:165
integer function pin_solution(xval, xmar, xbas, xsta, yval, ymar, ybas, ysta, n, m, usrmem)
Definition fvboth.f90:545
program fvinclin2
Main program. A simple setup and call of CONOPT.
Definition fvinclin2.f90:16
integer function coidef_fdeval(cntvect, coi_fdeval)
define callback routine for performing function and derivative evaluations.
integer function coidef_errmsg(cntvect, coi_errmsg)
define callback routine for returning error messages for row, column or Jacobian elements.
integer function coidef_message(cntvect, coi_message)
define callback routine for handling messages returned during the solution process.
integer function coidef_readmatrix(cntvect, coi_readmatrix)
define callback routine for providing the matrix data to CONOPT.
integer function coidef_status(cntvect, coi_status)
define callback routine for returning the completion status.
integer function coidef_solution(cntvect, coi_solution)
define callback routine for returning the final solution values.
integer function coidef_debugfv(cntvect, debugfv)
turn Debugging of FDEval on and off.
integer function coidef_fvinclin(cntvect, fvinclin)
include the linear terms in function evaluations.
integer function coidef_license(cntvect, licint1, licint2, licint3, licstring)
define the License Information.
Definition coistart.f90:680
integer function coidef_numvar(cntvect, numvar)
defines the number of variables in the model.
Definition coistart.f90:358
integer function coidef_objcon(cntvect, objcon)
defines the Objective Constraint.
Definition coistart.f90:629
integer function coidef_numnz(cntvect, numnz)
defines the number of nonzero elements in the Jacobian.
Definition coistart.f90:437
integer function coidef_optdir(cntvect, optdir)
defines the Optimization Direction.
Definition coistart.f90:552
integer function coidef_numnlnz(cntvect, numnlnz)
defines the Number of Nonlinear Nonzeros.
Definition coistart.f90:476
integer function coidef_numcon(cntvect, numcon)
defines the number of constraints in the model.
Definition coistart.f90:398
integer function coidef_size()
returns the size the Control Vector must have, measured in standard Integer units.
Definition coistart.f90:176
integer function coidef_inifort(cntvect)
initialisation method for Fortran applications.
Definition coistart.f90:314
subroutine coiget_version(major, minor, patch)
returns the version number. It can be used to ensure that the modeler is linked to the correct versio...
Definition coistart.f90:67
integer function coi_solve(cntvect)
method for starting the solving process of CONOPT.
Definition coistart.f90:14
real *8 obj
Definition comdecl.f90:10
integer solcalls
Definition comdecl.f90:9
integer sstat
Definition comdecl.f90:12
integer stacalls
Definition comdecl.f90:8
subroutine flog(msg, code)
Definition comdecl.f90:56
logical do_allocate
Definition comdecl.f90:21
integer, parameter maximize
Definition comdecl.f90:25
integer mstat
Definition comdecl.f90:11
subroutine startup
Definition comdecl.f90:35