MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
ImsLinear.f90
Go to the documentation of this file.
2 
3  use kindmodule, only: dp, i4b
5  izero, dzero, dprec, dsame, &
6  dem8, dem6, dem5, dem4, dem3, dem2, dem1, &
7  dhalf, done, dtwo, &
8  vdebug
18 
19  IMPLICIT NONE
20  private
21 
22  TYPE, PUBLIC :: imslineardatatype
23  character(len=LENMEMPATH) :: memorypath !< the path for storing variables in the memory manager
24  integer(I4B), POINTER :: iout => null() !< simulation listing file unit
25  integer(I4B), POINTER :: iprims => null() !< print flag
26  ! input variables (pointing to fields in input structure)
27  real(dp), pointer :: dvclose => null() !< dependent variable closure criterion
28  real(dp), pointer :: rclose => null() !< residual closure criterion
29  integer(I4B), pointer :: icnvgopt => null() !< convergence option
30  integer(I4B), pointer :: iter1 => null() !< max. iterations
31  integer(I4B), pointer :: ilinmeth => null() !< linear solver method
32  integer(I4B), pointer :: iscl => null() !< scaling method
33  integer(I4B), pointer :: iord => null() !< reordering method
34  integer(I4B), pointer :: north => null() !< number of orthogonalizations
35 
36  real(dp), pointer :: relax => null() !< relaxation factor
37  integer(I4B), pointer :: level => null() !< nr. of preconditioner levels
38  real(dp), pointer :: droptol => null() !< drop tolerance for preconditioner
39  !
40  integer(I4B), POINTER :: ipc => null() !< preconditioner flag
41  integer(I4B), POINTER :: iacpc => null() !< preconditioner CRS row pointers
42  integer(I4B), POINTER :: niterc => null() !<
43  integer(I4B), POINTER :: niabcgs => null() !< size of working vectors for BCGS linear accelerator
44  integer(I4B), POINTER :: niapc => null() !< preconditioner number of rows
45  integer(I4B), POINTER :: njapc => null() !< preconditioner number of non-zero entries
46  real(dp), POINTER :: epfact => null() !< factor for decreasing convergence criteria in seubsequent Picard iterations
47  real(dp), POINTER :: l2norm0 => null() !< initial L2 norm
48  ! -- ilut variables
49  integer(I4B), POINTER :: njlu => null() !< length of jlu work vector
50  integer(I4B), POINTER :: njw => null() !< length of jw work vector
51  integer(I4B), POINTER :: nwlu => null() !< length of wlu work vector
52  ! -- pointers to solution variables
53  integer(I4B), POINTER :: neq => null() !< number of equations (rows in matrix)
54  integer(I4B), POINTER :: nja => null() !< number of non-zero values in amat
55  integer(I4B), dimension(:), pointer, contiguous :: ia => null() !< position of start of each row
56  integer(I4B), dimension(:), pointer, contiguous :: ja => null() !< column pointer
57  real(dp), dimension(:), pointer, contiguous :: amat => null() !< coefficient matrix
58  real(dp), dimension(:), pointer, contiguous :: rhs => null() !< right-hand side of equation
59  real(dp), dimension(:), pointer, contiguous :: x => null() !< dependent variable
60  ! VECTORS
61  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: dscale => null() !< scaling factor
62  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: dscale2 => null() !< unscaling factor
63  integer(I4B), POINTER, DIMENSION(:), CONTIGUOUS :: iapc => null() !< position of start of each row in preconditioner matrix
64  integer(I4B), POINTER, DIMENSION(:), CONTIGUOUS :: japc => null() !< preconditioner matrix column pointer
65  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: apc => null() !< preconditioner coefficient matrix
66  integer(I4B), POINTER, DIMENSION(:), CONTIGUOUS :: lorder => null() !< reordering mapping
67  integer(I4B), POINTER, DIMENSION(:), CONTIGUOUS :: iorder => null() !< mapping to restore reordered matrix
68  integer(I4B), POINTER, DIMENSION(:), CONTIGUOUS :: iaro => null() !< position of start of each row in reordered matrix
69  integer(I4B), POINTER, DIMENSION(:), CONTIGUOUS :: jaro => null() !< reordered matrix column pointer
70  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: aro => null() !< reordered coefficient matrix
71  ! WORKING ARRAYS
72  integer(I4B), POINTER, DIMENSION(:), CONTIGUOUS :: iw => null() !< integer working array
73  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: w => null() !< real working array
74  integer(I4B), POINTER, DIMENSION(:), CONTIGUOUS :: id => null() !< integer working array
75  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: d => null() !< real working array
76  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: p => null() !< real working array
77  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: q => null() !< real working array
78  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: z => null() !< real working array
79  ! BICGSTAB WORKING ARRAYS
80  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: t => null() !< BICGSTAB real working array
81  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: v => null() !< BICGSTAB real working array
82  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: dhat => null() !< BICGSTAB real working array
83  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: phat => null() !< BICGSTAB real working array
84  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: qhat => null() !< rBICGSTAB eal working array
85  ! POINTERS FOR USE WITH BOTH ORIGINAL AND RCM ORDERINGS
86  integer(I4B), POINTER, DIMENSION(:), CONTIGUOUS :: ia0 => null() !< pointer to current CRS row pointers
87  integer(I4B), POINTER, DIMENSION(:), CONTIGUOUS :: ja0 => null() !< pointer to current CRS column pointers
88  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: a0 => null() !< pointer to current coefficient matrix
89  ! ILUT WORKING ARRAYS
90  integer(I4B), POINTER, DIMENSION(:), CONTIGUOUS :: jlu => null() !< ilut integer working array
91  integer(I4B), POINTER, DIMENSION(:), CONTIGUOUS :: jw => null() !< ilut integer working array
92  real(dp), POINTER, DIMENSION(:), CONTIGUOUS :: wlu => null() !< ilut real working array
93 
94  ! PROCEDURES (METHODS)
95  CONTAINS
96  PROCEDURE :: imslinear_allocate => imslinear_ar
97  procedure :: imslinear_summary
98  PROCEDURE :: imslinear_apply => imslinear_ap
99  procedure :: imslinear_da => imslinear_da
100  procedure, private :: allocate_scalars
101  ! -- PRIVATE PROCEDURES
102  PROCEDURE, PRIVATE :: set_imslinear_input => imslinear_set_input
103  END TYPE imslineardatatype
104 
105 CONTAINS
106 
107  !> @ brief Allocate storage and read data
108  !!
109  !! Allocate storage for linear accelerators and read data
110  !!
111  !<
112  SUBROUTINE imslinear_ar(this, NAME, IOUT, IPRIMS, MXITER, &
113  NEQ, matrix, RHS, X, linear_settings)
114  ! -- modules
117  use simmodule, only: store_error, count_errors, &
119  ! -- dummy variables
120  CLASS(imslineardatatype), INTENT(INOUT) :: this !< ImsLinearDataType instance
121  CHARACTER(LEN=LENSOLUTIONNAME), INTENT(IN) :: NAME !< solution name
122  integer(I4B), INTENT(IN) :: IOUT !< simulation listing file unit
123  integer(I4B), TARGET, INTENT(IN) :: IPRIMS !< print option
124  integer(I4B), INTENT(IN) :: MXITER !< maximum outer iterations
125  integer(I4B), TARGET, INTENT(IN) :: NEQ !< number of equations
126  class(matrixbasetype), pointer :: matrix
127  real(DP), DIMENSION(NEQ), TARGET, INTENT(INOUT) :: RHS !< right-hand side
128  real(DP), DIMENSION(NEQ), TARGET, INTENT(INOUT) :: X !< dependent variables
129  type(imslinearsettingstype), pointer :: linear_settings !< the settings form the IMS file
130  ! -- local variables
131  character(len=LINELENGTH) :: errmsg
132  integer(I4B) :: n
133  integer(I4B) :: i0
134  integer(I4B) :: iscllen, iolen
135 
136  !
137  ! -- DEFINE NAME
138  this%memoryPath = create_mem_path(name, 'IMSLINEAR')
139  !
140  ! -- SET pointers to IMS settings
141  this%DVCLOSE => linear_settings%dvclose
142  this%RCLOSE => linear_settings%rclose
143  this%ICNVGOPT => linear_settings%icnvgopt
144  this%ITER1 => linear_settings%iter1
145  this%ILINMETH => linear_settings%ilinmeth
146  this%ISCL => linear_settings%iscl
147  this%IORD => linear_settings%iord
148  this%NORTH => linear_settings%north
149  this%RELAX => linear_settings%relax
150  this%LEVEL => linear_settings%level
151  this%DROPTOL => linear_settings%droptol
152  !
153  ! -- SET POINTERS TO SOLUTION STORAGE
154  this%IPRIMS => iprims
155  this%NEQ => neq
156  call matrix%get_aij(this%IA, this%JA, this%AMAT)
157  call mem_allocate(this%NJA, 'NJA', this%memoryPath)
158  this%NJA = size(this%AMAT)
159  this%RHS => rhs
160  this%X => x
161  !
162  ! -- ALLOCATE SCALAR VARIABLES
163  call this%allocate_scalars()
164  !
165  ! -- initialize iout
166  this%iout = iout
167  !
168  ! -- DEFAULT VALUES
169  this%IPC = ipc_unknown
170  !
171  this%IACPC = 0
172  !
173  ! -- PRINT A MESSAGE IDENTIFYING IMSLINEAR SOLVER PACKAGE
174  write (iout, 2000)
175 02000 FORMAT(1x, /1x, 'IMSLINEAR -- UNSTRUCTURED LINEAR SOLUTION', &
176  ' PACKAGE, VERSION 8, 04/28/2017')
177  !
178  ! -- DETERMINE PRECONDITIONER
179  this%IPC = resolve_ipc(this%LEVEL, this%RELAX)
180  !
181  ! -- ERROR CHECKING FOR OPTIONS
182  IF (this%ISCL < 0) this%ISCL = 0
183  IF (this%ISCL > 2) THEN
184  WRITE (errmsg, '(A)') 'IMSLINEAR7AR ISCL MUST BE <= 2'
185  call store_error(errmsg)
186  END IF
187  IF (this%IORD < 0) this%IORD = 0
188  IF (this%IORD > 2) THEN
189  WRITE (errmsg, '(A)') 'IMSLINEAR7AR IORD MUST BE <= 2'
190  call store_error(errmsg)
191  END IF
192  IF (this%NORTH < 0) THEN
193  WRITE (errmsg, '(A)') 'IMSLINEAR7AR NORTH MUST >= 0'
194  call store_error(errmsg)
195  END IF
196  IF (this%RCLOSE == dzero) THEN
197  IF (this%ICNVGOPT /= 3) THEN
198  WRITE (errmsg, '(A)') 'IMSLINEAR7AR RCLOSE MUST > 0.0'
199  call store_error(errmsg)
200  END IF
201  END IF
202  IF (this%RELAX < dzero) THEN
203  WRITE (errmsg, '(A)') 'IMSLINEAR7AR RELAX MUST BE >= 0.0'
204  call store_error(errmsg)
205  END IF
206  IF (this%RELAX > done) THEN
207  WRITE (errmsg, '(A)') 'IMSLINEAR7AR RELAX MUST BE <= 1.0'
208  call store_error(errmsg)
209  END IF
210  !
211  ! -- INITIALIZE IMSLINEAR VARIABLES
212  this%NITERC = 0
213  !
214  ! -- ALLOCATE AND INITIALIZE MEMORY FOR IMSLINEAR
215  iscllen = 1
216  IF (this%ISCL .NE. 0) iscllen = neq
217  CALL mem_allocate(this%DSCALE, iscllen, 'DSCALE', trim(this%memoryPath))
218  CALL mem_allocate(this%DSCALE2, iscllen, 'DSCALE2', trim(this%memoryPath))
219  !
220  ! -- allocate and initialize the preconditioner work arrays
221  call precond_allocate(this)
222  !
223  ! -- ALLOCATE SPACE FOR PERMUTATION VECTOR
224  i0 = 1
225  iolen = 1
226  IF (this%IORD .NE. 0) THEN
227  i0 = this%NEQ
228  iolen = this%NJA
229  END IF
230  CALL mem_allocate(this%LORDER, i0, 'LORDER', trim(this%memoryPath))
231  CALL mem_allocate(this%IORDER, i0, 'IORDER', trim(this%memoryPath))
232  CALL mem_allocate(this%IARO, i0 + 1, 'IARO', trim(this%memoryPath))
233  CALL mem_allocate(this%JARO, iolen, 'JARO', trim(this%memoryPath))
234  CALL mem_allocate(this%ARO, iolen, 'ARO', trim(this%memoryPath))
235  !
236  ! -- ALLOCATE WORKING VECTORS FOR IMSLINEAR SOLVER
237  CALL mem_allocate(this%ID, this%NEQ, 'ID', trim(this%memoryPath))
238  CALL mem_allocate(this%D, this%NEQ, 'D', trim(this%memoryPath))
239  CALL mem_allocate(this%P, this%NEQ, 'P', trim(this%memoryPath))
240  CALL mem_allocate(this%Q, this%NEQ, 'Q', trim(this%memoryPath))
241  CALL mem_allocate(this%Z, this%NEQ, 'Z', trim(this%memoryPath))
242  !
243  ! -- ALLOCATE MEMORY FOR BCGS WORKING ARRAYS
244  this%NIABCGS = 1
245  IF (this%ILINMETH == 2) THEN
246  this%NIABCGS = this%NEQ
247  END IF
248  CALL mem_allocate(this%T, this%NIABCGS, 'T', trim(this%memoryPath))
249  CALL mem_allocate(this%V, this%NIABCGS, 'V', trim(this%memoryPath))
250  CALL mem_allocate(this%DHAT, this%NIABCGS, 'DHAT', trim(this%memoryPath))
251  CALL mem_allocate(this%PHAT, this%NIABCGS, 'PHAT', trim(this%memoryPath))
252  CALL mem_allocate(this%QHAT, this%NIABCGS, 'QHAT', trim(this%memoryPath))
253  !
254  ! -- INITIALIZE IMSLINEAR VECTORS
255  DO n = 1, iscllen
256  this%DSCALE(n) = done
257  this%DSCALE2(n) = done
258  END DO
259  !
260  ! -- WORKING VECTORS
261  DO n = 1, this%NEQ
262  this%ID(n) = izero
263  this%D(n) = dzero
264  this%P(n) = dzero
265  this%Q(n) = dzero
266  this%Z(n) = dzero
267  END DO
268  DO n = 1, this%NIAPC
269  this%IW(n) = izero
270  this%W(n) = dzero
271  END DO
272  !
273  ! -- BCGS WORKING VECTORS
274  DO n = 1, this%NIABCGS
275  this%T(n) = dzero
276  this%V(n) = dzero
277  this%DHAT(n) = dzero
278  this%PHAT(n) = dzero
279  this%QHAT(n) = dzero
280  END DO
281  !
282  ! -- ILUT AND MILUT WORKING VECTORS
283  DO n = 1, this%NJLU
284  this%JLU(n) = izero
285  END DO
286  DO n = 1, this%NJW
287  this%JW(n) = izero
288  END DO
289  DO n = 1, this%NWLU
290  this%WLU(n) = dzero
291  END DO
292  !
293  ! -- REORDERING VECTORS
294  DO n = 1, i0 + 1
295  this%IARO(n) = izero
296  END DO
297  DO n = 1, iolen
298  this%JARO(n) = izero
299  this%ARO(n) = dzero
300  END DO
301  !
302  ! -- REVERSE CUTHILL MCKEE AND MINIMUM DEGREE ORDERING
303  IF (this%IORD .NE. 0) THEN
304  CALL ims_base_calc_order(this%IORD, this%NEQ, this%NJA, this%IA, &
305  this%JA, this%LORDER, this%IORDER)
306  END IF
307  !
308  ! -- ALLOCATE MEMORY FOR STORING ITERATION CONVERGENCE DATA
309  end SUBROUTINE imslinear_ar
310 
311  !> @ brief Write summary of settings
312  !!
313  !! Write summary of linear accelerator settings.
314  !!
315  !<
316  subroutine imslinear_summary(this, mxiter)
317  ! -- dummy variables
318  class(imslineardatatype), intent(inout) :: this !< ImsLinearDataType instance
319  integer(I4B), intent(in) :: mxiter !< maximum number of outer iterations
320  ! -- local variables
321  CHARACTER(LEN=10) :: clin(0:2)
322  CHARACTER(LEN=31) :: clintit(0:2)
323  CHARACTER(LEN=20) :: cipc(0:4)
324  CHARACTER(LEN=20) :: cscale(0:2)
325  CHARACTER(LEN=25) :: corder(0:2)
326  CHARACTER(LEN=16), DIMENSION(0:4) :: ccnvgopt
327  CHARACTER(LEN=15) :: clevel
328  CHARACTER(LEN=15) :: cdroptol
329  integer(I4B) :: i
330  integer(I4B) :: j
331  ! -- data
332  DATA clin/'UNKNOWN ', &
333  &'CG ', &
334  &'BCGS '/
335  DATA clintit/' UNKNOWN ', &
336  &' CONJUGATE-GRADIENT ', &
337  &'BICONJUGATE-GRADIENT STABILIZED'/
338  DATA cipc/'UNKNOWN ', &
339  &'INCOMPLETE LU ', &
340  &'MOD. INCOMPLETE LU ', &
341  &'INCOMPLETE LUT ', &
342  &'MOD. INCOMPLETE LUT '/
343  DATA cscale/'NO SCALING ', &
344  &'SYMMETRIC SCALING ', &
345  &'L2 NORM SCALING '/
346  DATA corder/'ORIGINAL ORDERING ', &
347  &'RCM ORDERING ', &
348  &'MINIMUM DEGREE ORDERING '/
349  DATA ccnvgopt/'INFINITY NORM ', &
350  &'INFINITY NORM S ', &
351  &'L2 NORM ', &
352  &'RELATIVE L2NORM ', &
353  &'L2 NORM W. REL. '/
354  ! -- formats
355 02010 FORMAT(1x, /, 7x, 'SOLUTION BY THE', 1x, a31, 1x, 'METHOD', &
356  /, 1x, 66('-'), /, &
357  ' MAXIMUM OF ', i0, ' CALLS OF SOLUTION ROUTINE', /, &
358  ' MAXIMUM OF ', i0, &
359  ' INTERNAL ITERATIONS PER CALL TO SOLUTION ROUTINE', /, &
360  ' LINEAR ACCELERATION METHOD =', 1x, a, /, &
361  ' MATRIX PRECONDITIONING TYPE =', 1x, a, /, &
362  ' MATRIX SCALING APPROACH =', 1x, a, /, &
363  ' MATRIX REORDERING APPROACH =', 1x, a, /, &
364  ' NUMBER OF ORTHOGONALIZATIONS =', 1x, i0, /, &
365  ' HEAD CHANGE CRITERION FOR CLOSURE =', e15.5, /, &
366  ' RESIDUAL CHANGE CRITERION FOR CLOSURE =', e15.5, /, &
367  ' RESIDUAL CONVERGENCE OPTION =', 1x, i0, /, &
368  ' RESIDUAL CONVERGENCE NORM =', 1x, a, /, &
369  ' RELAXATION FACTOR =', e15.5)
370 02015 FORMAT(' NUMBER OF LEVELS =', a15, /, &
371  ' DROP TOLERANCE =', a15, //)
372 2030 FORMAT(1x, a20, 1x, 6(i6, 1x))
373 2040 FORMAT(1x, 20('-'), 1x, 6(6('-'), 1x))
374 2050 FORMAT(1x, 62('-'),/) !
375 ! -- -----------------------------------------------------------
376  !
377  ! -- initialize clevel and cdroptol
378  clevel = ''
379  cdroptol = ''
380  !
381  ! -- write common variables to all linear accelerators
382  write (this%iout, 2010) &
383  clintit(this%ILINMETH), mxiter, this%ITER1, &
384  clin(this%ILINMETH), cipc(this%IPC), &
385  cscale(this%ISCL), corder(this%IORD), &
386  this%NORTH, this%DVCLOSE, this%RCLOSE, &
387  this%ICNVGOPT, ccnvgopt(this%ICNVGOPT), &
388  this%RELAX
389  if (this%level > 0) then
390  write (clevel, '(i15)') this%level
391  end if
392  if (this%droptol > dzero) then
393  write (cdroptol, '(e15.5)') this%droptol
394  end if
395  IF (this%level > 0 .or. this%droptol > dzero) THEN
396  write (this%iout, 2015) trim(adjustl(clevel)), &
397  trim(adjustl(cdroptol))
398  ELSE
399  write (this%iout, '(//)')
400  END IF
401 
402  if (this%iord /= 0) then
403  !
404  ! -- WRITE SUMMARY OF REORDERING INFORMATION TO LIST FILE
405  if (this%iprims == 2) then
406  DO i = 1, this%neq, 6
407  write (this%iout, 2030) 'ORIGINAL NODE :', &
408  (j, j=i, min(i + 5, this%neq))
409  write (this%iout, 2040)
410  write (this%iout, 2030) 'REORDERED INDEX :', &
411  (this%lorder(j), j=i, min(i + 5, this%neq))
412  write (this%iout, 2030) 'REORDERED NODE :', &
413  (this%iorder(j), j=i, min(i + 5, this%neq))
414  write (this%iout, 2050)
415  END DO
416  END IF
417  end if
418  end subroutine imslinear_summary
419 
420  !> @ brief Allocate and initialize scalars
421  !!
422  !! Allocate and initialize linear accelerator scalars
423  !!
424  !<
425  subroutine allocate_scalars(this)
426  ! -- modules
428  ! -- dummy variables
429  class(imslineardatatype), intent(inout) :: this !< ImsLinearDataType instance
430  !
431  ! -- allocate scalars
432  call mem_allocate(this%iout, 'IOUT', this%memoryPath)
433  call mem_allocate(this%ipc, 'IPC', this%memoryPath)
434  call mem_allocate(this%iacpc, 'IACPC', this%memoryPath)
435  call mem_allocate(this%niterc, 'NITERC', this%memoryPath)
436  call mem_allocate(this%niabcgs, 'NIABCGS', this%memoryPath)
437  call mem_allocate(this%niapc, 'NIAPC', this%memoryPath)
438  call mem_allocate(this%njapc, 'NJAPC', this%memoryPath)
439  call mem_allocate(this%epfact, 'EPFACT', this%memoryPath)
440  call mem_allocate(this%l2norm0, 'L2NORM0', this%memoryPath)
441  call mem_allocate(this%njlu, 'NJLU', this%memoryPath)
442  call mem_allocate(this%njw, 'NJW', this%memoryPath)
443  call mem_allocate(this%nwlu, 'NWLU', this%memoryPath)
444  !
445  ! -- initialize scalars
446  this%iout = 0
447  this%ipc = 0
448  this%iacpc = 0
449  this%niterc = 0
450  this%niabcgs = 0
451  this%niapc = 0
452  this%njapc = 0
453  this%epfact = dzero
454  this%l2norm0 = 0
455  this%njlu = 0
456  this%njw = 0
457  this%nwlu = 0
458  end subroutine allocate_scalars
459 
460  !> @ brief Deallocate memory
461  !!
462  !! Deallocate linear accelerator memory.
463  !!
464  !<
465  subroutine imslinear_da(this)
466  ! -- modules
468  ! -- dummy variables
469  class(imslineardatatype), intent(inout) :: this !< linear datatype instance
470  !
471  ! -- arrays
472  call mem_deallocate(this%dscale)
473  call mem_deallocate(this%dscale2)
474  call precond_destroy(this)
475  call mem_deallocate(this%lorder)
476  call mem_deallocate(this%iorder)
477  call mem_deallocate(this%iaro)
478  call mem_deallocate(this%jaro)
479  call mem_deallocate(this%aro)
480  call mem_deallocate(this%id)
481  call mem_deallocate(this%d)
482  call mem_deallocate(this%p)
483  call mem_deallocate(this%q)
484  call mem_deallocate(this%z)
485  call mem_deallocate(this%t)
486  call mem_deallocate(this%v)
487  call mem_deallocate(this%dhat)
488  call mem_deallocate(this%phat)
489  call mem_deallocate(this%qhat)
490  !
491  ! -- scalars
492  call mem_deallocate(this%iout)
493  call mem_deallocate(this%ipc)
494  call mem_deallocate(this%iacpc)
495  call mem_deallocate(this%niterc)
496  call mem_deallocate(this%niabcgs)
497  call mem_deallocate(this%niapc)
498  call mem_deallocate(this%njapc)
499  call mem_deallocate(this%epfact)
500  call mem_deallocate(this%l2norm0)
501  call mem_deallocate(this%njlu)
502  call mem_deallocate(this%njw)
503  call mem_deallocate(this%nwlu)
504  call mem_deallocate(this%NJA)
505  !
506  ! -- nullify pointers
507  nullify (this%iprims)
508  nullify (this%neq)
509  nullify (this%nja)
510  nullify (this%ia)
511  nullify (this%ja)
512  nullify (this%amat)
513  nullify (this%rhs)
514  nullify (this%x)
515  end subroutine imslinear_da
516 
517  !> @brief Allocate and initialize the preconditioner work arrays
518  !!
519  !! Determines the preconditioner array dimensions from the current
520  !! NEQ/NJA/LEVEL/IPC and allocates the ILU-family work arrays
521  !! (IAPC/JAPC/APC/IW/W/JLU/JW/WLU); for ILU0/MILU0 the IAPC/JAPC sparsity is
522  !! generated. Separated from imslinear_ar so the preconditioner can be
523  !! (re)allocated at runtime.
524  !<
525  subroutine precond_allocate(this)
527  ! -- dummy variables
528  class(imslineardatatype), intent(inout) :: this !< ImsLinearDataType instance
529  ! -- local variables
530  integer(I4B) :: n
531  !
532  ! -- release any existing preconditioner arrays so this routine is
533  ! idempotent and can be called again to reallocate at runtime
534  if (associated(this%IAPC)) call precond_destroy(this)
535  !
536  ! -- determine dimensions for preconditioning arrays
537  call ims_calc_pcdims(this%NEQ, this%NJA, this%IA, this%LEVEL, this%IPC, &
538  this%NIAPC, this%NJAPC, this%NJLU, this%NJW, this%NWLU)
539  !
540  ! -- allocate base preconditioner vectors
541  call mem_allocate(this%IAPC, this%NIAPC + 1, 'IAPC', trim(this%memoryPath))
542  call mem_allocate(this%JAPC, this%NJAPC, 'JAPC', trim(this%memoryPath))
543  call mem_allocate(this%APC, this%NJAPC, 'APC', trim(this%memoryPath))
544  !
545  ! -- allocate ILU0/MILU0 non-zero row entry vectors
546  call mem_allocate(this%IW, this%NIAPC, 'IW', trim(this%memoryPath))
547  call mem_allocate(this%W, this%NIAPC, 'W', trim(this%memoryPath))
548  !
549  ! -- allocate ILUT vectors
550  call mem_allocate(this%JLU, this%NJLU, 'JLU', trim(this%memoryPath))
551  call mem_allocate(this%JW, this%NJW, 'JW', trim(this%memoryPath))
552  call mem_allocate(this%WLU, this%NWLU, 'WLU', trim(this%memoryPath))
553  !
554  ! -- generate IAPC and JAPC for ILU0 and MILU0
555  if (this%IPC == ipc_ilu0 .or. this%IPC == ipc_milu0) then
556  call ims_base_pccrs(this%NEQ, this%NJA, this%IA, this%JA, &
557  this%IAPC, this%JAPC)
558  end if
559  !
560  ! -- initialize preconditioner values
561  do n = 1, this%NJAPC
562  this%APC(n) = dzero
563  end do
564  end subroutine precond_allocate
565 
566  !> @brief Deallocate the preconditioner work arrays
567  !!
568  !! Preconditioner-only teardown, separated from imslinear_da so the
569  !! preconditioner can be destroyed and reallocated at runtime without
570  !! disturbing the solver work arrays.
571  !<
572  subroutine precond_destroy(this)
574  ! -- dummy variables
575  class(imslineardatatype), intent(inout) :: this !< ImsLinearDataType instance
576  !
577  ! -- mem_deallocate is a no-op in the memory manager, so releasing the named
578  ! store entries (and nullifying the aliases below) is what actually frees
579  ! these arrays and lets the preconditioner be reallocated at runtime
580  call memorystore_release('IAPC', trim(this%memoryPath))
581  call memorystore_release('JAPC', trim(this%memoryPath))
582  call memorystore_release('APC', trim(this%memoryPath))
583  call memorystore_release('IW', trim(this%memoryPath))
584  call memorystore_release('W', trim(this%memoryPath))
585  call memorystore_release('JLU', trim(this%memoryPath))
586  call memorystore_release('JW', trim(this%memoryPath))
587  call memorystore_release('WLU', trim(this%memoryPath))
588  !
589  nullify (this%IAPC)
590  nullify (this%JAPC)
591  nullify (this%APC)
592  nullify (this%IW)
593  nullify (this%W)
594  nullify (this%JLU)
595  nullify (this%JW)
596  nullify (this%WLU)
597  end subroutine precond_destroy
598 
599  !> @ brief Set default settings
600  !!
601  !! Set default linear accelerator settings.
602  !!
603  !<
604  SUBROUTINE imslinear_set_input(this, IFDPARAM)
605  ! -- dummy variables
606  CLASS(imslineardatatype), INTENT(INOUT) :: this !< ImsLinearDataType instance
607  integer(I4B), INTENT(IN) :: IFDPARAM !< complexity option
608  ! -- code
609  SELECT CASE (ifdparam)
610  !
611  ! -- Simple option
612  CASE (1)
613  this%ITER1 = 50
614  this%ILINMETH = 1
615  this%IPC = ipc_ilu0
616  this%ISCL = 0
617  this%IORD = 0
618  this%DVCLOSE = dem3
619  this%RCLOSE = dem1
620  this%RELAX = dzero
621  this%LEVEL = 0
622  this%DROPTOL = dzero
623  this%NORTH = 0
624  !
625  ! -- Moderate
626  CASE (2)
627  this%ITER1 = 100
628  this%ILINMETH = 2
629  this%IPC = ipc_milu0
630  this%ISCL = 0
631  this%IORD = 0
632  this%DVCLOSE = dem2
633  this%RCLOSE = dem1
634  this%RELAX = 0.97d0
635  this%LEVEL = 0
636  this%DROPTOL = dzero
637  this%NORTH = 0
638  !
639  ! -- Complex
640  CASE (3)
641  this%ITER1 = 500
642  this%ILINMETH = 2
643  this%IPC = ipc_ilut
644  this%ISCL = 0
645  this%IORD = 0
646  this%DVCLOSE = dem1
647  this%RCLOSE = dem1
648  this%RELAX = dzero
649  this%LEVEL = 5
650  this%DROPTOL = dem4
651  this%NORTH = 2
652  END SELECT
653  end SUBROUTINE imslinear_set_input
654 
655  !> @ brief Base linear accelerator subroutine
656  !!
657  !! Base linear accelerator subroutine that scales and reorders
658  !! the system of equations, if necessary, updates the preconditioner,
659  !! and calls the appropriate linear accelerator.
660  !!
661  !<
662  SUBROUTINE imslinear_ap(this, ICNVG, KSTP, KITER, IN_ITER, &
663  NCONV, CONVNMOD, CONVMODSTART, &
664  CACCEL, summary)
665  ! -- modules
666  USE simmodule
667  ! -- dummy variables
668  CLASS(imslineardatatype), INTENT(INOUT) :: this !< ImsLinearDataType instance
669  integer(I4B), INTENT(INOUT) :: ICNVG !< convergence flag (1) non-convergence (0)
670  integer(I4B), INTENT(IN) :: KSTP !< time step number
671  integer(I4B), INTENT(IN) :: KITER !< outer iteration number
672  integer(I4B), INTENT(INOUT) :: IN_ITER !< inner iteration number
673  ! -- convergence information dummy variables
674  integer(I4B), INTENT(IN) :: NCONV !<
675  integer(I4B), INTENT(IN) :: CONVNMOD !<
676  integer(I4B), DIMENSION(CONVNMOD + 1), INTENT(INOUT) :: CONVMODSTART !<
677  character(len=31), DIMENSION(NCONV), INTENT(INOUT) :: CACCEL !<
678  type(convergencesummarytype), pointer, intent(in) :: summary !< Convergence summary report
679  ! -- local variables
680  integer(I4B) :: n
681  integer(I4B) :: innerit
682  integer(I4B) :: irc
683  integer(I4B) :: itmax
684  real(DP) :: dnrm2
685  !
686  ! -- set epfact based on timestep
687  this%EPFACT = ims_base_epfact(this%ICNVGOPT, kstp)
688  !
689  ! -- SCALE PROBLEM
690  IF (this%ISCL .NE. 0) THEN
691  CALL ims_base_scale(0, this%ISCL, &
692  this%NEQ, this%NJA, this%IA, this%JA, &
693  this%AMAT, this%X, this%RHS, &
694  this%DSCALE, this%DSCALE2)
695  END IF
696  !
697  ! -- PERMUTE ROWS, COLUMNS, AND RHS
698  IF (this%IORD /= 0) THEN
699  CALL dperm(this%NEQ, this%AMAT, this%JA, this%IA, &
700  this%ARO, this%JARO, this%IARO, &
701  this%LORDER, this%ID, 1)
702  CALL dvperm(this%NEQ, this%X, this%LORDER)
703  CALL dvperm(this%NEQ, this%RHS, this%LORDER)
704  this%IA0 => this%IARO
705  this%JA0 => this%JARO
706  this%A0 => this%ARO
707  ELSE
708  this%IA0 => this%IA
709  this%JA0 => this%JA
710  this%A0 => this%AMAT
711  END IF
712  !
713  ! -- UPDATE PRECONDITIONER
714  CALL ims_base_pcu(this%iout, this%NJA, this%NEQ, this%NIAPC, this%NJAPC, &
715  this%IPC, this%RELAX, this%A0, this%IA0, this%JA0, &
716  this%APC, this%IAPC, this%JAPC, this%IW, this%W, &
717  this%LEVEL, this%DROPTOL, this%NJLU, this%NJW, &
718  this%NWLU, this%JLU, this%JW, this%WLU)
719  !
720  ! -- INITIALIZE SOLUTION VARIABLE AND ARRAYS
721  IF (kiter == 1) then
722  this%NITERC = 0
723  summary%iter_cnt = 0
724  end if
725  irc = 1
726  icnvg = 0
727  DO n = 1, this%NEQ
728  this%D(n) = dzero
729  this%P(n) = dzero
730  this%Q(n) = dzero
731  this%Z(n) = dzero
732  END DO
733  !
734  ! -- CALCULATE INITIAL RESIDUAL
735  call ims_base_residual(this%NEQ, this%NJA, this%X, this%RHS, this%D, &
736  this%A0, this%IA0, this%JA0)
737  this%L2NORM0 = dnrm2(this%NEQ, this%D, 1)
738  !
739  ! -- CHECK FOR EXACT SOLUTION
740  itmax = this%ITER1
741  IF (this%L2NORM0 == dzero) THEN
742  itmax = 0
743  icnvg = 1
744  END IF
745  !
746  ! -- SOLUTION BY THE CONJUGATE GRADIENT METHOD
747  IF (this%ILINMETH == 1) THEN
748  CALL ims_base_cg(icnvg, itmax, innerit, &
749  this%NEQ, this%NJA, this%NIAPC, this%NJAPC, &
750  this%IPC, this%ICNVGOPT, this%NORTH, &
751  this%DVCLOSE, this%RCLOSE, this%L2NORM0, &
752  this%EPFACT, this%IA0, this%JA0, this%A0, &
753  this%IAPC, this%JAPC, this%APC, &
754  this%X, this%RHS, this%D, this%P, this%Q, this%Z, &
755  this%NJLU, this%IW, this%JLU, &
756  nconv, convnmod, convmodstart, &
757  caccel, summary)
758  !
759  ! -- SOLUTION BY THE BICONJUGATE GRADIENT STABILIZED METHOD
760  ELSE IF (this%ILINMETH == 2) THEN
761  CALL ims_base_bcgs(icnvg, itmax, innerit, &
762  this%NEQ, this%NJA, this%NIAPC, this%NJAPC, &
763  this%IPC, this%ICNVGOPT, this%NORTH, &
764  this%ISCL, this%DSCALE, &
765  this%DVCLOSE, this%RCLOSE, this%L2NORM0, &
766  this%EPFACT, this%IA0, this%JA0, this%A0, &
767  this%IAPC, this%JAPC, this%APC, &
768  this%X, this%RHS, this%D, this%P, this%Q, &
769  this%T, this%V, this%DHAT, this%PHAT, this%QHAT, &
770  this%NJLU, this%IW, this%JLU, &
771  nconv, convnmod, convmodstart, &
772  caccel, summary)
773  END IF
774  !
775  ! -- BACK PERMUTE AMAT, SOLUTION, AND RHS
776  IF (this%IORD /= 0) THEN
777  CALL dperm(this%NEQ, this%A0, this%JA0, this%IA0, &
778  this%AMAT, this%JA, this%IA, &
779  this%IORDER, this%ID, 1)
780  CALL dvperm(this%NEQ, this%X, this%IORDER)
781  CALL dvperm(this%NEQ, this%RHS, this%IORDER)
782  END IF
783  !
784  ! -- UNSCALE PROBLEM
785  IF (this%ISCL .NE. 0) THEN
786  CALL ims_base_scale(1, this%ISCL, &
787  this%NEQ, this%NJA, this%IA, this%JA, &
788  this%AMAT, this%X, this%RHS, &
789  this%DSCALE, this%DSCALE2)
790  END IF
791  !
792  ! -- SET IMS INNER ITERATION NUMBER (IN_ITER) TO NUMBER OF
793  ! IMSLINEAR INNER ITERATIONS (innerit)
794  in_iter = innerit
795  end SUBROUTINE imslinear_ap
796 
797 END MODULE imslinearmodule
This module contains block parser methods.
Definition: BlockParser.f90:7
This module contains simulation constants.
Definition: Constants.f90:9
real(dp), parameter dsame
real constant for values that are considered the same based on machine precision
Definition: Constants.f90:122
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
integer(i4b), parameter lensolutionname
maximum length of the solution name
Definition: Constants.f90:21
real(dp), parameter dem8
real constant 1e-8
Definition: Constants.f90:111
real(dp), parameter dem1
real constant 1e-1
Definition: Constants.f90:103
real(dp), parameter dhalf
real constant 1/2
Definition: Constants.f90:68
real(dp), parameter dem3
real constant 1e-3
Definition: Constants.f90:106
integer(i4b), parameter izero
integer constant zero
Definition: Constants.f90:51
real(dp), parameter dem4
real constant 1e-4
Definition: Constants.f90:107
real(dp), parameter dem6
real constant 1e-6
Definition: Constants.f90:109
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
real(dp), parameter dem5
real constant 1e-5
Definition: Constants.f90:108
real(dp), parameter dprec
real constant machine precision
Definition: Constants.f90:120
@ vdebug
write debug output
Definition: Constants.f90:190
real(dp), parameter dem2
real constant 1e-2
Definition: Constants.f90:105
real(dp), parameter dtwo
real constant 2
Definition: Constants.f90:79
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
This module contains the IMS linear accelerator subroutines.
subroutine ims_base_pcu(IOUT, NJA, NEQ, NIAPC, NJAPC, IPC, RELAX, AMAT, IA, JA, APC, IAPC, JAPC, IW, W, LEVEL, DROPTOL, NJLU, NJW, NWLU, JLU, JW, WLU)
@ brief Update the preconditioner
subroutine ims_base_cg(ICNVG, ITMAX, INNERIT, NEQ, NJA, NIAPC, NJAPC, IPC, ICNVGOPT, NORTH, DVCLOSE, RCLOSE, L2NORM0, EPFACT, IA0, JA0, A0, IAPC, JAPC, APC, X, B, D, P, Q, Z, NJLU, IW, JLU, NCONV, CONVNMOD, CONVMODSTART, CACCEL, summary)
@ brief Preconditioned Conjugate Gradient linear accelerator
subroutine ims_base_pccrs(NEQ, NJA, IA, JA, IAPC, JAPC)
@ brief Generate CRS pointers for the preconditioner
subroutine ims_base_bcgs(ICNVG, ITMAX, INNERIT, NEQ, NJA, NIAPC, NJAPC, IPC, ICNVGOPT, NORTH, ISCL, DSCALE, DVCLOSE, RCLOSE, L2NORM0, EPFACT, IA0, JA0, A0, IAPC, JAPC, APC, X, B, D, P, Q, T, V, DHAT, PHAT, QHAT, NJLU, IW, JLU, NCONV, CONVNMOD, CONVMODSTART, CACCEL, summary)
@ brief Preconditioned BiConjugate Gradient Stabilized linear accelerator
subroutine ims_calc_pcdims(neq, nja, ia, level, ipc, niapc, njapc, njlu, njw, nwlu)
subroutine ims_base_scale(IOPT, ISCL, NEQ, NJA, IA, JA, AMAT, X, B, DSCALE, DSCALE2)
@ brief Scale the coefficient matrix
real(dp) function ims_base_epfact(icnvgopt, kstp)
Function returning EPFACT.
subroutine ims_base_calc_order(IORD, NEQ, NJA, IA, JA, LORDER, IORDER)
@ brief Calculate LORDER AND IORDER
subroutine ims_base_residual(NEQ, NJA, X, B, D, A, IA, JA)
Calculate residual.
subroutine allocate_scalars(this)
@ brief Allocate and initialize scalars
Definition: ImsLinear.f90:426
subroutine precond_allocate(this)
Allocate and initialize the preconditioner work arrays.
Definition: ImsLinear.f90:526
subroutine imslinear_summary(this, mxiter)
@ brief Write summary of settings
Definition: ImsLinear.f90:317
subroutine imslinear_set_input(this, IFDPARAM)
@ brief Set default settings
Definition: ImsLinear.f90:605
subroutine imslinear_da(this)
@ brief Deallocate memory
Definition: ImsLinear.f90:466
subroutine precond_destroy(this)
Deallocate the preconditioner work arrays.
Definition: ImsLinear.f90:573
subroutine imslinear_ar(this, NAME, IOUT, IPRIMS, MXITER, NEQ, matrix, RHS, X, linear_settings)
@ brief Allocate storage and read data
Definition: ImsLinear.f90:114
subroutine imslinear_ap(this, ICNVG, KSTP, KITER, IN_ITER, NCONV, CONVNMOD, CONVMODSTART, CACCEL, summary)
@ brief Base linear accelerator subroutine
Definition: ImsLinear.f90:665
@, public ipc_ilu0
ILU0 (incomplete LU, zero fill)
@, public ipc_unknown
preconditioner type not set
@, public ipc_milu0
modified ILU0
pure integer(i4b) function, public resolve_ipc(level, relax)
Resolve the preconditioner enum from the ILU controls.
@, public ipc_ilut
ILUT (incomplete LU with threshold)
This module defines variable data types.
Definition: kind.f90:8
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
subroutine, public memorystore_release(varname, memory_path)
Release a single variable from the memory store.
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
integer(i4b) function, public count_errors()
Return number of errors.
Definition: Sim.f90:59
subroutine, public deprecation_warning(cblock, cvar, cver, endmsg, iunit)
Store deprecation warning message.
Definition: Sim.f90:256
subroutine dvperm(n, x, perm)
Definition: sparsekit.f90:62
subroutine dperm(nrow, a, ja, ia, ao, jao, iao, perm, qperm, job)
Definition: sparsekit.f90:354
This structure stores the generic convergence info for a solution.