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