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