CONOPT
Loading...
Searching...
No Matches
mp_pinthread4.f90
Go to the documentation of this file.
1!> @file mp_pinthread4.f90
2!! @ingroup FORTOPENMP_EXAMPLES
3!!
4!!
5!! This is a CONOPT implementation of the Pindyck model from the
6!! GAMS model library. The implementation is similar to the one
7!! in pindyck.f90, but this time we first solve the model for
8!! a number of periods in parallel, using periods between 21 and 40.
9!! We have three loops over periods:
10!! First loop is done sequentially
11!! The second loop is done in parallel using a static schedule and
12!! The third loop is done in parallel using a dynamic schedule.
13!!
14!!
15!! For more information about the individual callbacks, please have a look at the source code.
16
17Module data
18 IMPLICIT NONE
19 integer, Parameter :: tmin = 21, tmax = 60
20 integer, Parameter :: vpp = 7 ! Variables per period
21 integer, Parameter :: epp = 6 ! Equations per period
22 real*8, Dimension(Tmax, Tmax*Vpp) :: xkeep ! Store solutions for all periods
23 real*8, Dimension(Tmax, Tmax*Vpp) :: xkeep1 ! Store solutions for all periods
24 real*8, Dimension(Tmax, Tmax*Vpp) :: xkeep2 ! Store solutions for all periods
25 Integer, Dimension(Tmax) :: thbase, thstatic, thdynamic, thguided
26 Integer :: maxthreadini ! Value of COIGET_MaxThreads at startup
27 Logical :: test_fdeval ! Used to determine if we should test COIDEF_MaxThreads inside FDEval
28 Logical :: inparallel !
30 Integer, Dimension(:), Pointer :: cntvect
31 End Type controlv
32 Type (controlv), Dimension(:), Pointer :: cntvect1 ! CONOPT Control vectors, one for each thread
33! INTEGER, Dimension(:,:), Allocatable :: CntVect ! Moved to Data to be available in FDEval
34End Module data
35
36!> Main program. A simple setup and call of CONOPT
37!!
38Program pinthread
39 Use proginfop
40 Use coidef
41 Use data
42 Use omp_lib
43 IMPLICIT NONE
44!
45! Declare the user callback routines as Integer, External:
46!
47 Integer, External :: pin_readmatrix ! Mandatory Matrix definition routine defined below
48 Integer, External :: pin_fdeval ! Function and Derivative evaluation routine
49 ! needed a nonlinear model.
50 Integer, External :: pin_status ! Callback for displaying solution status
51 Integer, External :: pin_solution ! Specialized callback for displaying solution values
52 Integer, External :: pin_message ! Specialized Callback for managing messages
53 Integer, External :: pin_errmsg ! Specialized Callback for managing error messages
54 Integer, External :: pin_option ! Define options using a callback. Files cannot be used
55 ! for multithreading since they can be shared and not
56 ! read in the proper order.
57#if defined(itl)
58!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_ReadMatrix
59!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_FDEval
60!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_Status
61!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_Solution
62!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_Message
63!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_ErrMsg
64!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_Option
65#endif
66!
67! COIDEF_UsrMem and COIDEF_WorkMem are not in the Coidef module and must be
68! explicitly declared if used.
69!
70 INTEGER, External :: coidef_usrmem
71#if defined(itl)
72!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: COIDEF_UsrMem
73!DEC$ ATTRIBUTES DECORATE, ALIAS: 'COIDEF_USRMEM'::COIDEF_UsrMem
74#endif
75!
76! Control vector
77!
78 Integer, Dimension(:), pointer :: cntvect ! CONOPT Control vector for current thread
79 real*8, Dimension(:), Allocatable :: usrmem
80 INTEGER :: coi_error
81!
82! Data needed to manage the dynamics and the threads.
83!
84 Integer :: t, i
85 Integer :: maxthreadomp, maxthreadcon, maxthread, thread
86 real*8 time0, time1, time2, time3, time4
87 Logical dif12, dif13, dif23
88 Integer :: ndif12, ndif13, ndif23
89
90 call startup
91!
92! Create and initialize one Control Vector for each possible thread
93! plus a Usrmem vector to be used to communicate the number of periods
94! to the model routines.
95!
96 If ( debug ) Then
97 open(12,file='Thread1.txt',status='Unknown');
98 open(13,file='Thread2.txt',status='Unknown');
99 open(14,file='Thread3.txt',status='Unknown');
100 open(15,file='Thread4.txt',status='Unknown');
101 Endif
102!
103! Make a quick test of the COIGET_MaxThread routines. We need a
104! control vector so we create a temporary one.
105!
106 coi_error = coi_createfort( cntvect )
107 maxthreadomp = omp_get_max_threads()
108 write(*,*) 'Initial MaxThread=',maxthreadomp,' from OpenMP'
109 maxthreadcon = coiget_maxthreads( cntvect )
110 write(*,*) 'Initial MaxThread=',maxthreadcon,' from COIGET_MaxThreads'
111 If ( maxthreadcon /= maxthreadomp ) Then
112 call flog( "Error in COIGET_MaxThread functions", 1 )
113 Endif
114 If ( maxthreadomp < 4 ) then
115 maxthread = 4
116 call omp_set_num_threads(maxthread)
117 write(*,*) 'Revised MaxThread=',maxthread
118 Else
119 maxthread = maxthreadomp
120 Endif
121 maxthreadcon = coiget_maxthreads( cntvect )
122 write(*,*) 'Revised MaxThread=',maxthreadcon,' from COIGET_MaxThreads'
123 maxthreadini = maxthreadcon
124 coi_error = coi_free( cntvect )
125 test_fdeval = .true.
126 inparallel = .false.
127!
128! Create a vector of Control Vectors in CntVect1 and allocate and
129! initialize the individual vectors for each thread.
130!
131 Allocate( cntvect1( maxthread ) )
132 Allocate( usrmem(2*maxthread) )
133 DO thread = 1, maxthread
134 coi_error = max( coi_error, coi_createfort( cntvect ) )
135 cntvect1(thread)%CntVect => cntvect
136!
137! Populate the elements in the control vector with information that is
138! independent of the number of periods.
139!
140 coi_error = coidef_inifort( cntvect )
141!
142! Direction: +1 = maximization.
143!
144 coi_error = max( coi_error, coidef_optdir( cntvect, 1 ) )
145!
146! Objective: Constraint no 1
147!
148 coi_error = max( coi_error, coidef_objcon( cntvect, 1 ) ) ! Objective is constraint 1
149!
150! Tell CONOPT about the callback routines:
151!
152 coi_error = max( coi_error, coidef_readmatrix( cntvect, pin_readmatrix ) )
153 coi_error = max( coi_error, coidef_fdeval( cntvect, pin_fdeval ) )
154 coi_error = max( coi_error, coidef_status( cntvect, pin_status ) )
155 coi_error = max( coi_error, coidef_solution( cntvect, pin_solution ) )
156 coi_error = max( coi_error, coidef_message( cntvect, pin_message ) )
157 coi_error = max( coi_error, coidef_errmsg( cntvect, pin_errmsg ) )
158 If ( debug ) &
159 coi_error = max( coi_error, coidef_option( cntvect, pin_option ) )
160!
161! Add the Usrmem address that depends on the thread
162!
163 coi_error = max( coi_error, coidef_usrmem( cntvect, usrmem(2*thread-1) ) )
164
165#if defined(LICENSE_INT_1) && defined(LICENSE_INT_2) && defined(LICENSE_INT_3) && defined(LICENSE_TEXT)
166 coi_error = max( coi_error, coidef_license( cntvect, license_int_1, license_int_2, license_int_3, license_text) )
167#endif
168 Enddo
169
170 If ( coi_error .ne. 0 ) THEN
171 write(*,*)
172 write(*,*) '**** Fatal Error while loading CONOPT Callback routines.'
173 write(*,*)
174 call flog( "Skipping First Solve due to setup errors", 1 )
175 ENDIF
176!
177! Store special values in Xkeep.
178!
179 xkeep(tmin:tmax,1:tmax*vpp) = -1234.5d0 ! Store solutions for all periods
180!
181! Now perform the actual optimizations, looping over the number of periods
182! In the first loop we run the models sequentially to have a base for
183! comparison.
184!
185 thread = 1
186 cntvect => cntvect1(thread)%CntVect
187 time0 = omp_get_wtime()
188 DO t = tmin, tmax
189 thbase(t) = thread
190 write(*,*) 'Sequential: Solving period',t,' using thread',thread
191 write(11,*) 'Sequential: Starting period',t,' using thread',thread
192 If ( debug ) &
193 write(10,*) 'Sequential: Starting period',t,' using thread',thread
194 usrmem(2*thread-1) = dfloat(t) ! Define the content of Usrmem as T
195 usrmem(2*thread ) = dfloat(thread) ! and Thread
196!
197! Number of variables (excl. slacks): Vpp per period
198!
199 coi_error = max( coi_error, coidef_numvar( cntvect, vpp * t ) )
200!
201! Number of equations: 1 objective + Epp per period
202!
203 coi_error = max( coi_error, coidef_numcon( cntvect, 1 + epp * t ) )
204!
205! Number of nonzeros in the Jacobian. See the counting in ReadMatrix below:
206! For each period there is 1 in the objective, 16 for unlagged
207! variables and 4 for lagged variables.
208!
209 coi_error = max( coi_error, coidef_numnz( cntvect, 17 * t + 4 * (t-1) ) )
210!
211! Number of nonlinear nonzeros. 5 unlagged for each period.
212!
213 coi_error = max( coi_error, coidef_numnlnz( cntvect, 5 * t ) )
214!
215 coi_error = coi_solve( cntvect )
216 If ( coi_error .ne. 0 ) THEN
217 write(*,*)
218 write(*,*) '**** Fatal Error while Solving for T=',t,' COI_Error=',coi_error
219 write(*,*)
220 call flog( "Errors encountered during Solve.", 1 )
221 Endif
222 Enddo
223 time1 = omp_get_wtime() - time0
224 xkeep1(tmin:tmax,1:tmax*vpp) = xkeep(tmin:tmax,1:tmax*vpp)
225 time0 = omp_get_wtime()
226 write(*,*) 'Finished single-thread loop. Going to start static multi-threading loop'
227 write(11,*) 'Finished single-thread loop. Going to start static multi-threading loop'
228 If ( debug ) &
229 write(10,*) 'Finished single-thread loop. Going to start static multi-threading loop'
230!
231! Now run the loop again this time in reverse order and in parallel - static.
232!
233 test_fdeval = .true.
234 inparallel = .true.
235 coi_error = 0
236!$OMP PARALLEL DEFAULT(SHARED)
237!$OMP DO PRIVATE(Thread, MaxThreadCON, CntVect) SCHEDULE(Static) Reduction(+:COI_Error)
238 DO t = tmax, tmin, -1
239 thread = 1+omp_get_thread_num()
240 thstatic(t) = thread
241 cntvect => cntvect1(thread)%CntVect
242 write(*,*) 'Static: Solving period',t,' using thread',thread
243 write(11,*) 'Static: Starting period',t,' using thread',thread
244 If ( debug ) &
245 write(10,*) 'Static: Starting period',t,' using thread',thread
246 usrmem(2*thread-1) = dfloat(t) ! Define the content of Usrmem as T
247 usrmem(2*thread ) = dfloat(thread) ! and Thread
248!
249! Number of variables (excl. slacks): Vpp per period
250!
251 coi_error = max( coi_error, coidef_numvar( cntvect, vpp * t ) )
252!
253! Number of equations: 1 objective + Epp per period
254!
255 coi_error = max( coi_error, coidef_numcon( cntvect, 1 + epp * t ) )
256!
257! Number of nonzeros in the Jacobian. See the counting in ReadMatrix below:
258! For each period there is 1 in the objective, 16 for unlagged
259! variables and 4 for lagged variables.
260!
261 coi_error = max( coi_error, coidef_numnz( cntvect, 17 * t + 4 * (t-1) ) )
262!
263! Number of nonlinear nonzeros. 5 unlagged for each period.
264!
265 coi_error = max( coi_error, coidef_numnlnz( cntvect, 5 * t ) )
266 maxthreadcon = coiget_maxthreads( cntvect )
267 If ( maxthreadcon /= 1 ) Then
268 coi_error = 1000
269 write(*,*)
270 write(*,*) '**** Fatal Error in MaxThread while Solving Parallel for T=',t
271 write(*,*)
272 Else
273 coi_error = coi_solve( cntvect )
274 coi_error = abs(coi_error)
275 Endif
276 Enddo
277!$OMP END PARALLEL
278 If ( coi_error .ne. 0 ) THEN
279 write(*,*)
280 write(*,*) '**** Fatal Error while Solving Static OMP loop. COI_Error=',coi_error
281 write(*,*)
282 call flog( "Errors encountered during Solvein Static OMP loop.", 1 )
283 Endif
284 time2 = omp_get_wtime() - time0
285 xkeep2(tmin:tmax,1:tmax*vpp) = xkeep(tmin:tmax,1:tmax*vpp)
286 time0 = omp_get_wtime()
287 write(*,*) 'Finished static multi-thread loop. Going to start dynamic multi-threading loop'
288 write(11,*) 'Finished static multi-thread loop. Going to start dynamic multi-threading loop'
289 If ( debug ) &
290 write(10,*) 'Finished static multi-thread loop. Going to start dynamic multi-threading loop'
291!
292! Now run the loop again this time in reverse order and in parallel - dynamic.
293!
294!$OMP PARALLEL DEFAULT(SHARED)
295!$OMP DO PRIVATE(Thread, CntVect) SCHEDULE(Dynamic) Reduction(+:COI_Error)
296 DO t = tmax, tmin, -1
297 thread = 1+omp_get_thread_num()
298 thdynamic(t) = thread
299 cntvect => cntvect1(thread)%CntVect
300 write(*,*) 'Dynamic: Solving period',t,' using thread',thread
301 write(11,*) 'Dynamic: Starting period',t,' using thread',thread
302 If ( debug ) &
303 write(10,*) 'Dynamic: Starting period',t,' using thread',thread
304 usrmem(2*thread-1) = dfloat(t) ! Define the content of Usrmem as T
305 usrmem(2*thread ) = dfloat(thread) ! and Thread
306!
307! Number of variables (excl. slacks): Vpp per period
308!
309 coi_error = max( coi_error, coidef_numvar( cntvect, vpp * t ) )
310!
311! Number of equations: 1 objective + Epp per period
312!
313 coi_error = max( coi_error, coidef_numcon( cntvect, 1 + epp * t ) )
314!
315! Number of nonzeros in the Jacobian. See the counting in ReadMatrix below:
316! For each period there is 1 in the objective, 16 for unlagged
317! variables and 4 for lagged variables.
318!
319 coi_error = max( coi_error, coidef_numnz( cntvect, 17 * t + 4 * (t-1) ) )
320!
321! Number of nonlinear nonzeros. 5 unlagged for each period.
322!
323 coi_error = max( coi_error, coidef_numnlnz( cntvect, 5 * t ) )
324!
325 coi_error = coi_solve( cntvect )
326 coi_error = abs(coi_error)
327 Enddo
328!$OMP END PARALLEL
329 If ( coi_error .ne. 0 ) THEN
330 write(*,*)
331 write(*,*) '**** Fatal Error while Solving Dynamic OMP loop. COI_Error=',coi_error
332 write(*,*)
333 call flog( "Errors encountered during Solvein Dynamic OMP loop.", 1 )
334 Endif
335 time3 = omp_get_wtime() - time0
336 time0 = omp_get_wtime()
337 write(*,*) 'Finished dynamic multi-thread loop. Going to start guided multi-threading loop'
338 write(11,*) 'Finished dynamic multi-thread loop. Going to start guided multi-threading loop'
339 If ( debug ) &
340 write(10,*) 'Finished dynamic multi-thread loop. Going to start guided multi-threading loop'
341!
342! Now run the loop again this time in reverse order and in parallel.
343!
344!$OMP PARALLEL DEFAULT(SHARED)
345!$OMP DO PRIVATE(Thread, CntVect) SCHEDULE(Guided) Reduction(+:COI_Error)
346 DO t = tmax, tmin, -1
347 thread = 1+omp_get_thread_num()
348 thguided(t) = thread
349 cntvect => cntvect1(thread)%CntVect
350 write(*,*) 'Guided: Solving period',t,' using thread',thread
351 write(11,*) 'Guided: Starting period',t,' using thread',thread
352 If ( debug ) &
353 write(10,*) 'Guided: Starting period',t,' using thread',thread
354 usrmem(2*thread-1) = dfloat(t) ! Define the content of Usrmem as T
355 usrmem(2*thread ) = dfloat(thread) ! and Thread
356!
357! Number of variables (excl. slacks): Vpp per period
358!
359 coi_error = max( coi_error, coidef_numvar( cntvect, vpp * t ) )
360!
361! Number of equations: 1 objective + Epp per period
362!
363 coi_error = max( coi_error, coidef_numcon( cntvect, 1 + epp * t ) )
364!
365! Number of nonzeros in the Jacobian. See the counting in ReadMatrix below:
366! For each period there is 1 in the objective, 16 for unlagged
367! variables and 4 for lagged variables.
368!
369 coi_error = max( coi_error, coidef_numnz( cntvect, 17 * t + 4 * (t-1) ) )
370!
371! Number of nonlinear nonzeros. 5 unlagged for each period.
372!
373 coi_error = max( coi_error, coidef_numnlnz( cntvect, 5 * t ) )
374!
375 coi_error = coi_solve( cntvect )
376 coi_error = abs(coi_error)
377 Enddo
378!$OMP END PARALLEL
379 If ( coi_error .ne. 0 ) THEN
380 write(*,*)
381 write(*,*) '**** Fatal Error while Solving Guided OMP loop. COI_Error=',coi_error
382 write(*,*)
383 call flog( "Errors encountered during Solvein Guided OMP loop.", 1 )
384 Endif
385 write(*,*) 'Finished guided multi-thread loop.'
386 write(11,*) 'Finished guided multi-thread loop.'
387 If ( debug ) &
388 write(10,*) 'Finished guided multi-thread loop.'
389 time4 = omp_get_wtime() - time0
390!
391! Clean up
392!
393 DO thread = 1, maxthread
394 coi_error = max( coi_error, coi_free( cntvect1(thread)%CntVect ) )
395 Enddo
396 Deallocate( cntvect1 )
397
398 write(*,*)
399 write(*,*) 'End of PinThread Model.'
400 write(*,*)
401!
402 dif12 = .false.; ndif12 = 0
403 Do t = tmin, tmax
404 Do i=1,t*vpp
405 if ( xkeep1(t,i) .ne. xkeep2(t,i) ) then
406 dif12 = .true.
407 ndif12 = ndif12 + 1
408 if ( ndif12 <= 10 ) &
409 write(*,1000) t, i, thbase(t),' XBase =',xkeep1(t,i), thstatic(t),' XStat =',xkeep2(t,i), (xkeep1(t,i)-xkeep2(t,i))
410 endif
411 Enddo
412 Enddo
413 write(*,*)
414 write(*,*) 'Difference between base and static solutions =',dif12
415 write(*,*)
416 dif13 = .false.; ndif13 = 0
417 Do t = tmin, tmax
418 Do i=1,t*vpp
419 if ( xkeep(t,i) .ne. xkeep1(t,i) ) then
420 dif13 = .true.
421 ndif13 = ndif13 + 1
422 if ( ndif13 <= 10 ) &
423 write(*,1000) t, i, thbase(t),' XBase =',xkeep1(t,i), thdynamic(t),' XDynm =',xkeep(t,i), (xkeep1(t,i)-xkeep(t,i))
424 endif
425 Enddo
426 Enddo
427 write(*,*)
428 write(*,*) 'Difference between base and dynamic solutions =',dif13
429 write(*,*)
430 dif23 = .false.; ndif23 = 0
431 Do t = tmin, tmax
432 Do i=1,t*vpp
433 if ( xkeep(t,i) .ne. xkeep2(t,i) ) then
434 dif23 = .true.
435 ndif23 = ndif23 + 1
436 if ( ndif23 <= 10 ) &
437 write(*,1000) t, i, thstatic(t),' XStat =',xkeep2(t,i), thdynamic(t),' XDynm =',xkeep(t,i), (xkeep2(t,i)-xkeep(t,i))
438 endif
439 Enddo
440 Enddo
441 write(*,*)
442 write(*,*) 'Difference between static and dynamic solutions=',dif23
443 write(*,*)
4441000 Format('T=',i2,' I=',i3,' Thread=',i2,a9,1p,e22.14/ &
445 10x, ' Thread=',i2,a9,1p,e22.14,' Diff=',1p,e22.14)
446 write(*,*) 'MaxThread =',maxthread
447 write(*,*) 'Time Single thread =',time1
448 write(*,*) 'Time Static Multi thread =',time2
449 write(*,*) 'Time Dynamic Multi thread =',time3
450 write(*,*) 'Time Guided Multi thread =',time4
451 write(*,*) 'Speedup, static =',time1/time2
452 write(*,*) 'Speedup, dynamic =',time1/time3
453 write(*,*) 'Efficiency, static =',time1/time2/maxthread
454 write(*,*) 'Efficiency, dynamic =',time1/time3/maxthread
455 write(*,*) 'Efficiency, guided =',time1/time4/maxthread
456
457#if defined (nocomp)
458!
459! A compiler problem for Intel 11.0.074 and 11.1.065 (in scalar products) means that
460! solutions are not reproducible.
461!
462 call flog( "Successful Solve", 0 )
463#else
464 if ( dif12 ) then
465 call flog("Base and Static solutions are not identical",1)
466 else if ( dif13 ) then
467 call flog("Base and Dynamic solutions are not identical",1)
468 else if ( dif23 ) then
469 call flog("Static and Dynamic solutions are not identical",1)
470 else
471 call flog( "Successful Solve", 0 )
472 endif
473#endif
474
475end Program pinthread
476
477
478!> Sets runtime options
479!!
480!! @include{doc} option_params.dox
481Integer Function pin_option( ncall, rval, ival, lval, usrmem, name )
482#if defined(itl)
483!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_Option
484#endif
485 integer ncall, ival, lval
486 character(Len=*) :: name
487 real*8 rval
488 real*8 usrmem(*) ! optional user memory
489
490 Select Case (ncall)
491 case (1)
492 name = 'locon3'
493 ival = 0
494 case (2)
495 name = 'lotria'
496 ival = 0
497 case default
498 name = ' '
499 end Select
500 pin_option = 0
501
502end Function pin_option
503!
504! =====================================================================
505! Define information about the model structure
506!
507
508!> Define information about the model
509!!
510!! @include{doc} readMatrix_params.dox
511Integer Function pin_readmatrix( lower, curr, upper, vsta, type, rhs, esta, &
512 colsta, rowno, value, nlflag, n, m, nz, usrmem )
513#if defined(itl)
514!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_ReadMatrix
515#endif
516 Use data
517 IMPLICIT NONE
518 integer, intent (in) :: n ! number of variables
519 integer, intent (in) :: m ! number of constraints
520 integer, intent (in) :: nz ! number of nonzeros
521 real*8, intent (in out), dimension(n) :: lower ! vector of lower bounds
522 real*8, intent (in out), dimension(n) :: curr ! vector of initial values
523 real*8, intent (in out), dimension(n) :: upper ! vector of upper bounds
524 integer, intent (in out), dimension(n) :: vsta ! vector of initial variable status
525 ! Defined during restarts
526 integer, intent (out), dimension(m) :: type ! vector of equation types
527 integer, intent (in out), dimension(m) :: esta ! vector of initial equation status
528 ! Defined during restarts
529 real*8, intent (in out), dimension(m) :: rhs ! vector of right hand sides
530 integer, intent (in out), dimension(n+1) :: colsta ! vector with start of column indices
531 integer, intent (out), dimension(nz) :: rowno ! vector of row numbers
532 integer, intent (in out), dimension(nz) :: nlflag ! vector of nonlinearity flags
533 real*8, intent (in out), dimension(nz) :: value ! vector of matrix values
534 real*8 usrmem(*) ! optional user memory
535
536 Integer :: it, is, i, icol, iz
537 Integer :: t ! Number of periods for this solve
538!
539! Define the information for the columns.
540!
541! We should not supply status information, vsta.
542!
543! We order the variables as follows:
544! td, cs, s, d, r, p, and rev. All variables for period 1 appears
545! first followed by all variables for period 2 etc.
546!
547! td, cs, s, and d have lower bounds of 0, r and p have lower
548! bounds of 1, and rev has no lower bound.
549! All have infinite upper bounds (default).
550! The initial value of td is 18, s is 7, cs is 7*t, d is td-s,
551! p is 14, and r is r(t-1)-d. No initial value for rev.
552!
553 t = usrmem(1)
554 do it = 1, t
555 is = vpp*(it-1)
556 lower(is+1) = 0.d0
557 lower(is+2) = 0.d0
558 lower(is+3) = 0.d0
559 lower(is+4) = 0.d0
560 lower(is+5) = 1.d0
561 lower(is+6) = 1.d0
562 curr(is+1) = 18.d0
563 curr(is+2) = 7.d0*it
564 curr(is+3) = 7.d0
565 curr(is+4) = curr(is+1) - curr(is+3)
566 if ( it .gt. 1 ) then
567 curr(is+5) = curr(is+5-vpp) - curr(is+4)
568 else
569 curr(is+5) = 500.d0 - curr(is+4)
570 endif
571 curr(is+6) = 14.d0
572 enddo
573!
574! Define the information for the rows
575!
576! We order the constraints as follows: The objective is first,
577! followed by tddef, sdef, csdef, ddef, rdef, and revdef for
578! the first period, the same for the second period, etc.
579!
580! The objective is a nonbinding constraint:
581!
582 type(1) = 3
583!
584! All others are equalities:
585!
586 do i = 2, m
587 type(i) = 0
588 enddo
589!
590! Right hand sides: In all periods except the first, only tddef
591! has a nonzero right hand side of 1+2.3*1.015**(t-1).
592! In the initial period there are contributions from lagged
593! variables in the constraints that have lagged variables.
594!
595 do it = 1, t
596 is = 1 + 6*(it-1)
597 rhs(is+1) = 1.d0+2.3d0*1.015d0**(it-1)
598 enddo
599!
600! tddef: + 0.87*td(0)
601!
602 rhs(2) = rhs(2) + 0.87d0*18.d0
603!
604! sdef: +0.75*s(0)
605!
606 rhs(3) = 0.75d0*6.5d0
607!
608! csdef: +1*cs(0)
609!
610 rhs(4) = 0.d0
611!
612! rdef: +1*r(0)
613!
614 rhs(6) = 500.d0
615!
616! Define the structure and content of the Jacobian:
617! To help define the Jacobian pattern and values it can be useful to
618! make a picture of the Jacobian. We describe the variables for one
619! period and the constraints they are part of:
620!
621! td cs s d r p rev
622! Obj (1+r)**(1-t)
623! Period t:
624! tddef 1.0 0.13
625! sdef NL 1.0 NL
626! csdef 1.0 -1.0
627! ddef -1.0 1.0 1.0
628! rdef 1.0 1.0
629! revdef NL NL NL 1.0
630! Period t+1:
631! tddef -0.87
632! sdef -0.75
633! csdef -1.0
634! ddef
635! rdef -1.0
636! revdef
637!
638! The Jacobian has to be sorted column-wise so we will just define
639! the elements column by column according to the table above:
640!
641 iz = 1
642 icol = 1
643 do it = 1, t
644!
645! is points to the position before the first equation for the period
646!
647 is = 1 + 6*(it-1)
648!
649! Column td:
650!
651 colsta(icol) = iz
652 icol = icol + 1
653 rowno(iz) = is+1
654 value(iz) = +1.d0
655 nlflag(iz) = 0
656 iz = iz + 1
657 rowno(iz) = is+4
658 value(iz) = -1.d0
659 nlflag(iz) = 0
660 iz = iz + 1
661 if ( it .lt. t ) then
662 rowno(iz) = is+7
663 value(iz) = -0.87d0
664 nlflag(iz) = 0
665 iz = iz + 1
666 endif
667!
668! Column cs
669!
670 colsta(icol) = iz
671 icol = icol + 1
672 rowno(iz) = is+2
673 nlflag(iz) = 1
674 iz = iz + 1
675 rowno(iz) = is+3
676 value(iz) = +1.d0
677 nlflag(iz) = 0
678 iz = iz + 1
679 if ( it .lt. t ) then
680 rowno(iz) = is+9
681 value(iz) = -1.d0
682 nlflag(iz) = 0
683 iz = iz + 1
684 endif
685!
686! Column s
687!
688 colsta(icol) = iz
689 icol = icol + 1
690 rowno(iz) = is+2
691 value(iz) = +1.d0
692 nlflag(iz) = 0
693 iz = iz + 1
694 rowno(iz) = is+3
695 value(iz) = -1.d0
696 nlflag(iz) = 0
697 iz = iz + 1
698 rowno(iz) = is+4
699 value(iz) = +1.d0
700 nlflag(iz) = 0
701 iz = iz + 1
702 if ( it .lt. t ) then
703 rowno(iz) = is+8
704 value(iz) = -0.75d0
705 nlflag(iz) = 0
706 iz = iz + 1
707 endif
708!
709! Column d:
710!
711 colsta(icol) = iz
712 icol = icol + 1
713 rowno(iz) = is+4
714 value(iz) = +1.d0
715 nlflag(iz) = 0
716 iz = iz + 1
717 rowno(iz) = is+5
718 value(iz) = +1.d0
719 nlflag(iz) = 0
720 iz = iz + 1
721 rowno(iz) = is+6
722 nlflag(iz) = 1
723 iz = iz + 1
724!
725! Column r:
726!
727 colsta(icol) = iz
728 icol = icol + 1
729 rowno(iz) = is+5
730 value(iz) = +1.d0
731 nlflag(iz) = 0
732 iz = iz + 1
733 rowno(iz) = is+6
734 nlflag(iz) = 1
735 iz = iz + 1
736 if ( it .lt. t ) then
737 rowno(iz) = is+11
738 value(iz) = -1.d0
739 nlflag(iz) = 0
740 iz = iz + 1
741 endif
742!
743! Column p:
744!
745 colsta(icol) = iz
746 icol = icol + 1
747 rowno(iz) = is+1
748 value(iz) = +0.13d0
749 nlflag(iz) = 0
750 iz = iz + 1
751 rowno(iz) = is+2
752 nlflag(iz) = 1
753 iz = iz + 1
754 rowno(iz) = is+6
755 nlflag(iz) = 1
756 iz = iz + 1
757!
758! Column rev:
759!
760 colsta(icol) = iz
761 icol = icol + 1
762 rowno(iz) = +1
763 value(iz) = 1.05d0**(1-it)
764 nlflag(iz) = 0
765 iz = iz + 1
766 rowno(iz) = is+6
767 value(iz) = 1.d0
768 nlflag(iz) = 0
769 iz = iz + 1
770 enddo
771 colsta(icol) = iz
772
774
775end Function pin_readmatrix
776!
777! =====================================================================
778! Compute nonlinear terms and non-constant Jacobian elements
779!
780
781!> Compute nonlinear terms and non-constant Jacobian elements
782!!
783!! @include{doc} fdeval_params.dox
784Integer Function pin_fdeval( x, g, jac, rowno, jcnm, mode, ignerr, errcnt, &
785 n, nz, thread, usrmem )
786#if defined(itl)
787!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_FDEval
788#endif
789 Use data
790 Use proginfop
791 Use coidef
792 IMPLICIT NONE
793 integer, intent (in) :: n ! number of variables
794 integer, intent (in) :: rowno ! number of the row to be evaluated
795 integer, intent (in) :: nz ! number of nonzeros in this row
796 real*8, intent (in), dimension(n) :: x ! vector of current solution values
797 real*8, intent (in out) :: g ! constraint value
798 real*8, intent (in out), dimension(n) :: jac ! vector of derivatives for current constraint
799 integer, intent (in), dimension(nz) :: jcnm ! list of variables that appear nonlinearly
800 ! in this row. Ffor information only.
801 integer, intent (in) :: mode ! evaluation mode: 1 = function value
802 ! 2 = derivatives, 3 = both
803 integer, intent (in) :: ignerr ! if 1 then errors can be ignored as long
804 ! as errcnt is incremented
805 integer, intent (in out) :: errcnt ! error counter to be incremented in case
806 ! of function evaluation errors.
807 integer, intent (in) :: thread
808 real*8 usrmem(*) ! optional user memory
809
810 integer it, is
811 real*8 h1, h2
812 Integer :: maxthreads
813
814 if ( test_fdeval ) then
815!
816! This test is a little artificial and needs a control vector that is not
817! really available here -- but anyway, just test the return value in
818! this case.
819!
820 maxthreads = coiget_maxthreads( cntvect1(1+thread)%CntVect )
821 if ( inparallel ) then
822 If ( maxthreads /= 1 ) Then
823 write(*,*)
824 write(*,*) 'In parallel FDEval. COIGET_MaxThreads=',maxthreads,' and expected 1.'
825 write(*,*)
826 call flog( "Error in COIGET_MaxThreads in Parallel FDEval", 1 )
827 Endif
828 Else
829 If ( maxthreads /= maxthreadini ) Then
830 write(*,*)
831 write(*,*) 'In parallel FDEval. COIGET_MaxThreads=',maxthreads,' and expected',maxthreadini
832 write(*,*)
833 call flog( "Error in COIGET_MaxThreads in Sequential FDEval", 1 )
834 Endif
835 Endif
836 test_fdeval = .false.
837 Endif
838!
839! Compute the number of the period
840!
841 it = (rowno+4) / epp
842 is = vpp*(it-1)
843 if ( rowno == (it-1)*epp+3 ) then
844!
845! sdef equation. Nonlinear term = -(1.1+0.1*p)*1.02**(-cs/7)
846!
847 h1 = (1.1d0+0.1d0*x(is+6))
848 h2 = 1.02d0**(-x(is+2)/7.d0)
849 if ( mode == 1 .or. mode == 3 ) then
850 g = -h1*h2
851 endif
852 if ( mode == 2 .or. mode == 3 ) then
853 jac(is+2) = h1*h2*log(1.02d0)/7.d0
854 jac(is+6) = -h2*0.1d0
855 endif
856 elseif ( rowno == (it-1)*epp+7 ) then
857!
858! revdef equation. Nonlinear term = -d*(p-250/r)
859!
860 if ( mode == 1 .or. mode == 3 ) then
861 g = -x(is+4)*(x(is+6)-250.d0/x(is+5))
862 endif
863 if ( mode == 2 .or. mode == 3 ) then
864 jac(is+4) = -(x(is+6)-250.d0/x(is+5))
865 jac(is+5) = -x(is+4)*250d0/x(is+5)**2
866 jac(is+6) = -x(is+4)
867 endif
868 else
869!
870! Error - this equation is not nonlinear
871!
872 write(*,*)
873 write(*,*) 'Error. FDEval called with rowno=',rowno
874 write(*,*)
875 pin_fdeval = 1
876 Return
877 endif
878 pin_fdeval = 0
879
880end Function pin_fdeval
881
882INTEGER FUNCTION pin_solution( XVAL, XMAR, XBAS, XSTA, YVAL, YMAR, YBAS, YSTA, N, M, USRMEM )
883#if defined(itl)
884!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_Solution
885#endif
886
887 Use data
888 IMPLICIT NONE
889 INTEGER, Intent(IN) :: n, m
890 INTEGER, Intent(IN), Dimension(N) :: xbas, xsta
891 INTEGER, Intent(IN), Dimension(M) :: ybas, ysta
892 real*8, Intent(IN), Dimension(N) :: xval, xmar
893 real*8, Intent(IN), Dimension(M) :: yval, ymar
894 real*8, Intent(IN OUT) :: usrmem(*)
895
896 Integer :: t ! number of periods for this solve
897
898 t = usrmem(1)
899 xkeep(t, 1:n) = xval(1:n) ! Store the primal solution values
900 pin_solution = 0
901 Return
902
903END FUNCTION pin_solution
904!
905! Routines for Message, Status, Solution, and ErrMsg.
906!
907Integer Function pin_status( MODSTA, SOLSTA, ITER, OBJVAL, USRMEM )
908#if defined(itl)
909!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_Status
910#endif
911!
912 Use proginfop
913 IMPLICIT NONE
914 INTEGER, Intent(IN) :: modsta, solsta, iter
915 real*8, Intent(IN) :: objval
916 real*8, Intent(IN OUT) :: usrmem(*)
917
918 stacalls = stacalls + 1
919 obj = objval
920 mstat = modsta
921 sstat = solsta
922
923 pin_status = 0
924
925END Function pin_status
926
927Integer Function pin_message( SMSG, DMSG, NMSG, LLEN, USRMEM, MSGV )
928#if defined(itl)
929!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_Message
930#endif
931!
932 Use proginfop
933 IMPLICIT NONE
934
935 INTEGER, Intent(IN) :: smsg, dmsg, nmsg
936 INTEGER, Intent(IN) , Dimension(*) :: llen
937 CHARACTER(Len=133), Intent(IN), Dimension(*) :: msgv
938 real*8, Intent(IN OUT) :: usrmem(*)
939
940 integer :: t, thread, i
941 t = usrmem(1)
942!
943! Time-perion Tagged messages in the parallel world
944!
945 do i = 1, nmsg
946 write(11,"(i2,':',A)") t, msgv(i)(1:llen(i))
947 enddo
948 If ( debug ) then
949 thread = usrmem(2)
950 do i = 1, dmsg
951 write(11+thread,"(i2,':',A)") t, msgv(i)(1:llen(i))
952 enddo
953 Endif
954
955 pin_message = 0
956
957END Function pin_message
958
959Integer Function pin_errmsg( ROWNO, COLNO, POSNO, MSGLEN, USRMEM, MSG )
960#if defined(itl)
961!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Pin_ErrMsg
962#endif
963!
964 Use proginfop
965 IMPLICIT NONE
966
967 INTEGER, Intent(IN) :: rowno, colno, posno, msglen
968 CHARACTER(Len=*), Intent(IN) :: msg
969 real*8, Intent(IN OUT) :: usrmem(*)
970!
971! Time-period tagged messages in the parallel world
972!
973 Integer :: t, thread
974 t = usrmem(1)
975!
976! If Rowno = 0 then the message is about a Column.
977! If Colno = 0 then the message is abuut a Row.
978! Otherwise, the message is about (Rowno,Colno)
979!
980 IF ( rowno .EQ. 0 ) THEN ! Must be a column (error) message
981 WRITE(11,1001) t, colno, msg(1:msglen)
982 ELSEIF ( colno .EQ. 0 ) THEN ! Must be a row (error) message
983 WRITE(11,1002) t, rowno, msg(1:msglen)
984 ELSE ! Must be a (row,col) (error) message
985 WRITE(11,1000) t, colno, rowno, msg(1:msglen)
986 ENDIF
987 If ( debug ) Then
988 thread = usrmem(2)
989 IF ( rowno .EQ. 0 ) THEN ! Must be a column (error) message
990 WRITE(11+thread,1001) t, colno, msg(1:msglen)
991 ELSEIF ( colno .EQ. 0 ) THEN ! Must be a row (error) message
992 WRITE(11+thread,1002) t, rowno, msg(1:msglen)
993 ELSE ! Must be a (row,col) (error) message
994 WRITE(11+thread,1000) t, colno, rowno, msg(1:msglen)
995 ENDIF
996 Endif
997 pin_errmsg = 0
9981001 FORMAT(i2,':Variable',i8,' : ',a)
9991002 FORMAT(i2,':Equation',i8,' : ',a)
10001000 FORMAT(i2,':Variable',i8,' appearing in Equation',i8,' : ',a)
1001
1002END Function pin_errmsg
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_usrmem(cntvect, usrmem)
provides a pointer to user memory that is available in all callback functions. NOTE: this is not a ca...
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_inifort(cntvect)
initialisation method for Fortran applications.
Definition coistart.f90:314
integer function coiget_maxthreads(cntvect)
returns the maximum number of threads that can be used by CONOPT.
Definition coistart.f90:95
integer function coi_solve(cntvect)
method for starting the solving process of CONOPT.
Definition coistart.f90:14
program pinthread
Main program. A simple setup and call of CONOPT.
integer function pin_errmsg(rowno, colno, posno, msglen, usrmem, msg)
integer function pin_status(modsta, solsta, iter, objval, usrmem)
integer function pin_message(smsg, dmsg, nmsg, llen, usrmem, msgv)
integer, parameter tmin
logical inparallel
integer, dimension(tmax) thguided
integer, parameter epp
integer, dimension(tmax) thstatic
type(controlv), dimension(:), pointer cntvect1
integer, parameter vpp
logical test_fdeval
integer, dimension(tmax) thbase
integer, parameter tmax
integer, dimension(tmax) thdynamic
integer maxthreadini
subroutine flog(msg, code)
Definition comdeclp.f90:42
real *8 obj
Definition comdeclp.f90:13
logical debug
Definition comdeclp.f90:17
subroutine startup
Definition comdeclp.f90:25
integer function pin_option(ncall, rval, ival, lval, usrmem, name)
Sets runtime options.
Definition pinopt.f90:542