MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
numericalsolutionmodule Module Reference

Data Types

type  numericalsolutiontype
 
interface  synchronize_iface
 

Functions/Subroutines

subroutine, public create_numerical_solution (num_sol, filename, id)
 @ brief Create a new solution More...
 
subroutine allocate_scalars (this)
 @ brief Allocate scalars More...
 
subroutine allocate_arrays (this)
 @ brief Allocate arrays More...
 
subroutine sln_df (this)
 @ brief Define the solution More...
 
subroutine sln_ar (this)
 @ brief Allocate and read data More...
 
subroutine sln_dt (this)
 @ brief Calculate delt More...
 
subroutine sln_ad (this)
 @ brief Advance solution More...
 
subroutine sln_ot (this)
 @ brief Output solution More...
 
subroutine sln_fp (this)
 @ brief Finalize solution More...
 
subroutine sln_da (this)
 @ brief Deallocate solution More...
 
subroutine sln_ca (this, isgcnvg, isuppress_output)
 @ brief Solve solution More...
 
subroutine writecsvheader (this)
 @ brief CSV header More...
 
subroutine writeptcinfotofile (this, kper)
 @ brief PTC header More...
 
subroutine preparesolve (this)
 @ brief prepare to solve More...
 
subroutine solve (this, kiter, isuppress_output)
 @ brief Build and solve the simulation More...
 
subroutine finalizesolve (this, kiter, isgcnvg, isuppress_output)
 @ brief finalize a solution More...
 
subroutine sln_buildsystem (this, kiter, inewton)
 
subroutine convergence_summary (this, iu, im, itertot_timestep)
 @ brief Solution convergence summary More...
 
subroutine csv_convergence_summary (this, iu, totim, kper, kstp, kouter, niter, istart, kstart)
 @ brief Solution convergence CSV summary More...
 
subroutine save (this, filename)
 @ brief Save solution data to a file More...
 
subroutine add_model (this, mp)
 @ brief Add a model More...
 
type(listtype) function, pointer get_models (this)
 Get a list of models. More...
 
subroutine add_exchange (this, exchange)
 Add exchange. More...
 
type(listtype) function, pointer get_exchanges (this)
 Returns a pointer to the list of exchanges in this solution. More...
 
subroutine sln_connect (this)
 @ brief Assign solution connections More...
 
subroutine sln_reset (this)
 @ brief Reset the solution More...
 
subroutine sln_ls (this, kiter, kstp, kper, in_iter, iptc, ptcf)
 @ brief Solve the linear system of equations More...
 
subroutine sln_setouter (this, ifdparam)
 @ brief Set default Picard iteration variables More...
 
subroutine sln_backtracking (this, mp, cp, kiter)
 @ brief Perform backtracking More...
 
subroutine sln_backtracking_xupdate (this, bt_flag)
 @ brief Backtracking update of the dependent variable More...
 
integer(i4b) function get_backtracking_flag (this)
 Check if backtracking should be applied for this solution,. More...
 
integer(i4b) function sln_get_idvscale (this)
 Check if dependent variable scalining should be applied for this solution,. More...
 
subroutine apply_backtracking (this)
 Update x with backtracking. More...
 
subroutine sln_l2norm (this, l2norm)
 @ brief Calculate the solution L-2 norm for all active cells using More...
 
subroutine sln_maxval (this, nsize, v, vmax)
 @ brief Get the maximum value from a vector More...
 
subroutine sln_calcdx (this, neq, active, x, xtemp, dx)
 @ brief Calculate dependent-variable change More...
 
subroutine sln_calc_ptc (this, iptc, ptcf)
 Calculate pseudo-transient continuation factor. More...
 
subroutine sln_calc_residual (this, vec_resid)
 Calculate the current residual vector r = A*x - b,. More...
 
subroutine sln_underrelax (this, kiter, bigch, neq, active, x, xtemp)
 @ brief Under-relaxation More...
 
subroutine sln_get_dxmax (this, hncg, lrch)
 @ brief Determine maximum dependent-variable change More...
 
logical(lgp) function sln_has_converged (this, max_dvc)
 
integer(i4b) function sln_package_convergence (this, dpak, cpakout, iend)
 Check package convergence. More...
 
integer(i4b) function sln_sync_newtonur_flag (this, inewtonur)
 Synchronize Newton Under-relaxation flag. More...
 
logical(lgp) function sln_nur_has_converged (this, dxold_max, hncg)
 Custom convergence check for when Newton UR has been applied. More...
 
subroutine sln_get_loc (this, nodesln, str)
 @ brief Get cell location string More...
 
subroutine sln_get_nodeu (this, nodesln, im, nodeu)
 @ brief Get user node number More...
 
class(numericalsolutiontype) function, pointer, public castasnumericalsolutionclass (obj)
 @ brief Cast a object as a Numerical Solution More...
 
class(numericalsolutiontype) function, pointer, public getnumericalsolutionfromlist (list, idx)
 @ brief Get a numerical solution More...
 

Variables

integer(i4b), parameter ims_solver = 1
 
integer(i4b), parameter petsc_solver = 2
 

Function/Subroutine Documentation

◆ add_exchange()

subroutine numericalsolutionmodule::add_exchange ( class(numericalsolutiontype this,
class(baseexchangetype), intent(in), pointer  exchange 
)
private

Add and exchange to thisexchangelist.

Parameters
thisNumericalSolutionType instance
[in]exchangemodel exchange instance

Definition at line 2342 of file NumericalSolution.f90.

2343  ! -- dummy variables
2344  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2345  class(BaseExchangeType), pointer, intent(in) :: exchange !< model exchange instance
2346  ! -- local variables
2347  class(NumericalExchangeType), pointer :: num_ex => null()
2348  !
2349  ! -- add exchange
2350  select type (exchange)
2351  class is (numericalexchangetype)
2352  num_ex => exchange
2353  call addnumericalexchangetolist(this%exchangelist, num_ex)
2354  end select
Here is the call graph for this function:

◆ add_model()

subroutine numericalsolutionmodule::add_model ( class(numericalsolutiontype this,
class(basemodeltype), intent(in), pointer  mp 
)

Add a model to solution.

Parameters
thisNumericalSolutionType instance
[in]mpmodel instance

Definition at line 2307 of file NumericalSolution.f90.

2308  ! -- dummy variables
2309  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2310  class(BaseModelType), pointer, intent(in) :: mp !< model instance
2311  ! -- local variables
2312  class(NumericalModelType), pointer :: m => null()
2313  !
2314  ! -- add a model
2315  select type (mp)
2316  class is (numericalmodeltype)
2317  m => mp
2318  call addnumericalmodeltolist(this%modellist, m)
2319  end select
Here is the call graph for this function:

◆ allocate_arrays()

subroutine numericalsolutionmodule::allocate_arrays ( class(numericalsolutiontype this)

Allocate arrays for a new solution.

Parameters
thisNumericalSolutionType instance

Definition at line 387 of file NumericalSolution.f90.

388  ! -- modules
390  ! -- dummy variables
391  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
392  ! -- local variables
393  class(NumericalModelType), pointer :: mp => null()
394  integer(I4B) :: i
395  integer(I4B) :: ieq
396  !
397  ! -- initialize the number of models in the solution
398  this%convnmod = this%modellist%Count()
399  !
400  ! -- allocate arrays
401  call mem_allocate(this%active, this%neq, 'IACTIVE', this%memory_path)
402  call mem_allocate(this%xtemp, this%neq, 'XTEMP', this%memory_path)
403  call mem_allocate(this%dxold, this%neq, 'DXOLD', this%memory_path)
404  call mem_allocate(this%hncg, 0, 'HNCG', this%memory_path)
405  call mem_allocate(this%lrch, 3, 0, 'LRCH', this%memory_path)
406  call mem_allocate(this%wsave, 0, 'WSAVE', this%memory_path)
407  call mem_allocate(this%hchold, 0, 'HCHOLD', this%memory_path)
408  call mem_allocate(this%deold, 0, 'DEOLD', this%memory_path)
409  call mem_allocate(this%convmodstart, this%convnmod + 1, 'CONVMODSTART', &
410  this%memory_path)
411  !
412  ! -- initialize allocated arrays
413  do i = 1, this%neq
414  this%xtemp(i) = dzero
415  this%dxold(i) = dzero
416  this%active(i) = 1 !default is active
417  end do
418  !
419  ! -- initialize convmodstart
420  ieq = 1
421  this%convmodstart(1) = ieq
422  do i = 1, this%modellist%Count()
423  mp => getnumericalmodelfromlist(this%modellist, i)
424  ieq = ieq + mp%neq
425  this%convmodstart(i + 1) = ieq
426  end do
Here is the call graph for this function:

◆ allocate_scalars()

subroutine numericalsolutionmodule::allocate_scalars ( class(numericalsolutiontype this)

Allocate scalars for a new solution.

Definition at line 285 of file NumericalSolution.f90.

286  ! -- modules
288  ! -- dummy variables
289  class(NumericalSolutionType) :: this
290  !
291  ! -- allocate scalars
292  call mem_allocate(this%id, 'ID', this%memory_path)
293  call mem_allocate(this%iu, 'IU', this%memory_path)
294  call mem_allocate(this%ttform, 'TTFORM', this%memory_path)
295  call mem_allocate(this%ttsoln, 'TTSOLN', this%memory_path)
296  call mem_allocate(this%isymmetric, 'ISYMMETRIC', this%memory_path)
297  call mem_allocate(this%neq, 'NEQ', this%memory_path)
298  call mem_allocate(this%matrix_offset, 'MATRIX_OFFSET', this%memory_path)
299  call mem_allocate(this%dvclose, 'DVCLOSE', this%memory_path)
300  call mem_allocate(this%bigchold, 'BIGCHOLD', this%memory_path)
301  call mem_allocate(this%bigch, 'BIGCH', this%memory_path)
302  call mem_allocate(this%relaxold, 'RELAXOLD', this%memory_path)
303  call mem_allocate(this%res_prev, 'RES_PREV', this%memory_path)
304  call mem_allocate(this%res_new, 'RES_NEW', this%memory_path)
305  call mem_allocate(this%icnvg, 'ICNVG', this%memory_path)
306  call mem_allocate(this%itertot_timestep, 'ITERTOT_TIMESTEP', this%memory_path)
307  call mem_allocate(this%iouttot_timestep, 'IOUTTOT_TIMESTEP', this%memory_path)
308  call mem_allocate(this%itertot_sim, 'INNERTOT_SIM', this%memory_path)
309  call mem_allocate(this%mxiter, 'MXITER', this%memory_path)
310  call mem_allocate(this%linsolver, 'LINSOLVER', this%memory_path)
311  call mem_allocate(this%nonmeth, 'NONMETH', this%memory_path)
312  call mem_allocate(this%iprims, 'IPRIMS', this%memory_path)
313  call mem_allocate(this%theta, 'THETA', this%memory_path)
314  call mem_allocate(this%akappa, 'AKAPPA', this%memory_path)
315  call mem_allocate(this%gamma, 'GAMMA', this%memory_path)
316  call mem_allocate(this%amomentum, 'AMOMENTUM', this%memory_path)
317  call mem_allocate(this%breduc, 'BREDUC', this%memory_path)
318  call mem_allocate(this%btol, 'BTOL', this%memory_path)
319  call mem_allocate(this%res_lim, 'RES_LIM', this%memory_path)
320  call mem_allocate(this%numtrack, 'NUMTRACK', this%memory_path)
321  call mem_allocate(this%ibflag, 'IBFLAG', this%memory_path)
322  call mem_allocate(this%icsvouterout, 'ICSVOUTEROUT', this%memory_path)
323  call mem_allocate(this%icsvinnerout, 'ICSVINNEROUT', this%memory_path)
324  call mem_allocate(this%nitermax, 'NITERMAX', this%memory_path)
325  call mem_allocate(this%convnmod, 'CONVNMOD', this%memory_path)
326  call mem_allocate(this%iallowptc, 'IALLOWPTC', this%memory_path)
327  call mem_allocate(this%iptcopt, 'IPTCOPT', this%memory_path)
328  call mem_allocate(this%iptcout, 'IPTCOUT', this%memory_path)
329  call mem_allocate(this%l2norm0, 'L2NORM0', this%memory_path)
330  call mem_allocate(this%ptcdel, 'PTCDEL', this%memory_path)
331  call mem_allocate(this%ptcdel0, 'PTCDEL0', this%memory_path)
332  call mem_allocate(this%ptcexp, 'PTCEXP', this%memory_path)
333  call mem_allocate(this%atsfrac, 'ATSFRAC', this%memory_path)
334  call mem_allocate(this%idv_scale, 'IDV_SCALE', this%memory_path)
335  call mem_allocate(this%dscale, 'DSCALE', this%memory_path)
336  !
337  ! -- initialize scalars
338  this%isymmetric = 0
339  this%id = 0
340  this%iu = 0
341  this%ttform = dzero
342  this%ttsoln = dzero
343  this%neq = 0
344  this%dvclose = dzero
345  this%bigchold = dzero
346  this%bigch = dzero
347  this%relaxold = dzero
348  this%res_prev = dzero
349  this%icnvg = 0
350  this%itertot_timestep = 0
351  this%iouttot_timestep = 0
352  this%itertot_sim = 0
353  this%mxiter = 0
354  this%linsolver = ims_solver
355  this%nonmeth = 0
356  this%iprims = 0
357  this%theta = done
358  this%akappa = dzero
359  this%gamma = done
360  this%amomentum = dzero
361  this%breduc = dzero
362  this%btol = 0
363  this%res_lim = dzero
364  this%numtrack = 0
365  this%ibflag = 0
366  this%icsvouterout = 0
367  this%icsvinnerout = 0
368  this%nitermax = 0
369  this%convnmod = 0
370  this%iallowptc = 1
371  this%iptcopt = 0
372  this%iptcout = 0
373  this%l2norm0 = dzero
374  this%ptcdel = dzero
375  this%ptcdel0 = dzero
376  this%ptcexp = done
377  this%atsfrac = donethird
378  this%idv_scale = 0
379  this%dscale = done

◆ apply_backtracking()

subroutine numericalsolutionmodule::apply_backtracking ( class(numericalsolutiontype this)
private
Parameters
thisNumericalSolutionType instance

Definition at line 2893 of file NumericalSolution.f90.

2894  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2895  ! local
2896  integer(I4B) :: n
2897  real(DP) :: delx
2898 
2899  do n = 1, this%neq
2900  if (this%active(n) < 1) cycle
2901  delx = this%breduc * (this%x(n) - this%xtemp(n))
2902  this%x(n) = this%xtemp(n) + delx
2903  end do
2904 

◆ castasnumericalsolutionclass()

class(numericalsolutiontype) function, pointer, public numericalsolutionmodule::castasnumericalsolutionclass ( class(*), intent(inout), pointer  obj)

Get a numerical solution from a list.

Parameters
[in,out]objgeneric object
Returns
output NumericalSolutionType

Definition at line 3367 of file NumericalSolution.f90.

3368  ! -- dummy variables
3369  class(*), pointer, intent(inout) :: obj !< generic object
3370  ! -- return variable
3371  class(NumericalSolutionType), pointer :: res !< output NumericalSolutionType
3372  !
3373  ! -- initialize return variable
3374  res => null()
3375  !
3376  ! -- determine if obj is associated
3377  if (.not. associated(obj)) return
3378  !
3379  ! -- set res
3380  select type (obj)
3381  class is (numericalsolutiontype)
3382  res => obj
3383  end select
Here is the caller graph for this function:

◆ convergence_summary()

subroutine numericalsolutionmodule::convergence_summary ( class(numericalsolutiontype this,
integer(i4b), intent(in)  iu,
integer(i4b), intent(in)  im,
integer(i4b), intent(in)  itertot_timestep 
)
private

Save convergence summary to a File.

Parameters
thisNumericalSolutionType instance
[in]iufile unit number for summary file
[in]immodel number
[in]itertot_timesteptotal iteration for the time step

Definition at line 2038 of file NumericalSolution.f90.

2039  ! -- modules
2040  use inputoutputmodule, only: getunit
2041  ! -- dummy variables
2042  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2043  integer(I4B), intent(in) :: iu !< file unit number for summary file
2044  integer(I4B), intent(in) :: im !< model number
2045  integer(I4B), intent(in) :: itertot_timestep !< total iteration for the time step
2046  ! -- local variables
2047  character(len=LINELENGTH) :: title
2048  character(len=LINELENGTH) :: tag
2049  character(len=LENPAKLOC) :: loc_dvmax_str
2050  character(len=LENPAKLOC) :: loc_rmax_str
2051  integer(I4B) :: ntabrows
2052  integer(I4B) :: ntabcols
2053  integer(I4B) :: iinner
2054  integer(I4B) :: i0
2055  integer(I4B) :: iouter
2056  integer(I4B) :: j
2057  integer(I4B) :: k
2058  integer(I4B) :: locdv
2059  integer(I4B) :: locdr
2060  real(DP) :: dv !< the maximum change in the dependent variable
2061  real(DP) :: res !< the maximum value of the residual vector
2062  !
2063  ! -- initialize local variables
2064  loc_dvmax_str = ''
2065  loc_rmax_str = ''
2066  iouter = 1
2067  locdv = 0
2068  locdr = 0
2069  !
2070  ! -- initialize inner iteration summary table
2071  if (.not. associated(this%innertab)) then
2072  !
2073  ! -- create outer iteration table
2074  ! -- table dimensions
2075  ntabrows = itertot_timestep
2076  ntabcols = 7
2077  !
2078  ! -- initialize table and define columns
2079  title = trim(this%memory_path)//' INNER ITERATION SUMMARY'
2080  call table_cr(this%innertab, this%name, title)
2081  call this%innertab%table_df(ntabrows, ntabcols, iu)
2082  tag = 'TOTAL ITERATION'
2083  call this%innertab%initialize_column(tag, 10, alignment=tabright)
2084  tag = 'OUTER ITERATION'
2085  call this%innertab%initialize_column(tag, 10, alignment=tabright)
2086  tag = 'INNER ITERATION'
2087  call this%innertab%initialize_column(tag, 10, alignment=tabright)
2088  tag = 'MAXIMUM CHANGE'
2089  call this%innertab%initialize_column(tag, 15, alignment=tabright)
2090  tag = 'MAXIMUM CHANGE MODEL-(CELLID)'
2091  call this%innertab%initialize_column(tag, lenpakloc, alignment=tabright)
2092  tag = 'MAXIMUM RESIDUAL'
2093  call this%innertab%initialize_column(tag, 15, alignment=tabright)
2094  tag = 'MAXIMUM RESIDUAL MODEL-(CELLID)'
2095  call this%innertab%initialize_column(tag, lenpakloc, alignment=tabright)
2096  !
2097  ! -- reset the output unit and the number of rows (maxbound)
2098  else
2099  call this%innertab%set_maxbound(itertot_timestep)
2100  call this%innertab%set_iout(iu)
2101  end if
2102  !
2103  ! -- write the inner iteration summary to unit iu
2104  i0 = 0
2105  do k = 1, itertot_timestep
2106  iinner = this%cnvg_summary%itinner(k)
2107  if (iinner <= i0) then
2108  iouter = iouter + 1
2109  end if
2110  if (im > this%convnmod) then
2111  dv = dzero
2112  res = dzero
2113  do j = 1, this%convnmod
2114  if (abs(this%cnvg_summary%convdvmax(j, k)) > abs(dv)) then
2115  locdv = this%cnvg_summary%convlocdv(j, k)
2116  dv = this%cnvg_summary%convdvmax(j, k)
2117  end if
2118  if (abs(this%cnvg_summary%convrmax(j, k)) > abs(res)) then
2119  locdr = this%cnvg_summary%convlocr(j, k)
2120  res = this%cnvg_summary%convrmax(j, k)
2121  end if
2122  end do
2123  else
2124  locdv = this%cnvg_summary%convlocdv(im, k)
2125  locdr = this%cnvg_summary%convlocr(im, k)
2126  dv = this%cnvg_summary%convdvmax(im, k)
2127  res = this%cnvg_summary%convrmax(im, k)
2128  end if
2129  call this%sln_get_loc(locdv, loc_dvmax_str)
2130  call this%sln_get_loc(locdr, loc_rmax_str)
2131  !
2132  ! -- add data to innertab
2133  call this%innertab%add_term(k)
2134  call this%innertab%add_term(iouter)
2135  call this%innertab%add_term(iinner)
2136  call this%innertab%add_term(dv)
2137  call this%innertab%add_term(adjustr(trim(loc_dvmax_str)))
2138  call this%innertab%add_term(res)
2139  call this%innertab%add_term(adjustr(trim(loc_rmax_str)))
2140  !
2141  ! -- update i0
2142  i0 = iinner
2143  end do
integer(i4b) function, public getunit()
Get a free unit number.
Here is the call graph for this function:

◆ create_numerical_solution()

subroutine, public numericalsolutionmodule::create_numerical_solution ( class(numericalsolutiontype), pointer  num_sol,
character(len=*), intent(in)  filename,
integer(i4b), intent(in)  id 
)

Create a new solution using the data in filename, assign this new solution an id number and store the solution in the basesolutionlist. Also open the filename for later reading.

Parameters
num_solthe create solution
[in]filenamesolution input file name
[in]idsolution id

Definition at line 238 of file NumericalSolution.f90.

239  ! -- modules
240  use simvariablesmodule, only: iout
242  ! -- dummy variables
243  class(NumericalSolutionType), pointer :: num_sol !< the create solution
244  character(len=*), intent(in) :: filename !< solution input file name
245  integer(I4B), intent(in) :: id !< solution id
246  ! -- local variables
247  integer(I4B) :: inunit
248  class(BaseSolutionType), pointer :: solbase => null()
249  character(len=LENSOLUTIONNAME) :: solutionname
250  !
251  ! -- Create a new solution and add it to the basesolutionlist container
252  solbase => num_sol
253  write (solutionname, '(a, i0)') 'SLN_', id
254  !
255  num_sol%name = solutionname
256  num_sol%memory_path = create_mem_path(solutionname)
257  allocate (num_sol%modellist)
258  allocate (num_sol%exchangelist)
259  !
260  call num_sol%allocate_scalars()
261  !
262  call addbasesolutiontolist(basesolutionlist, solbase)
263  !
264  num_sol%id = id
265  !
266  ! -- Open solution input file for reading later after problem size is known
267  ! Check to see if the file is already opened, which can happen when
268  ! running in single model mode
269  inquire (file=filename, number=inunit)
270 
271  if (inunit < 0) inunit = getunit()
272  num_sol%iu = inunit
273  write (iout, '(/a,a)') ' Creating solution: ', num_sol%name
274  call openfile(num_sol%iu, iout, filename, 'IMS')
275  !
276  ! -- Initialize block parser
277  call num_sol%parser%Initialize(num_sol%iu, iout)
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
This module contains simulation variables.
Definition: SimVariables.f90:9
integer(i4b) iout
file unit number for simulation output
Here is the call graph for this function:
Here is the caller graph for this function:

◆ csv_convergence_summary()

subroutine numericalsolutionmodule::csv_convergence_summary ( class(numericalsolutiontype this,
integer(i4b), intent(in)  iu,
real(dp), intent(in)  totim,
integer(i4b), intent(in)  kper,
integer(i4b), intent(in)  kstp,
integer(i4b), intent(in)  kouter,
integer(i4b), intent(in)  niter,
integer(i4b), intent(in)  istart,
integer(i4b), intent(in)  kstart 
)

Save convergence summary to a comma-separated value file.

Parameters
thisNumericalSolutionType instance
[in]iufile unit number
[in]totimtotal simulation time
[in]kperstress period number
[in]kstptime step number
[in]kouternumber of outer (Picard) iterations
[in]niternumber of inner iteration in this time step
[in]istartstarting iteration number for this time step
[in]kstartstarting position in the conv* arrays

Definition at line 2151 of file NumericalSolution.f90.

2153  ! -- modules
2154  use inputoutputmodule, only: getunit
2155  ! -- dummy variables
2156  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2157  integer(I4B), intent(in) :: iu !< file unit number
2158  real(DP), intent(in) :: totim !< total simulation time
2159  integer(I4B), intent(in) :: kper !< stress period number
2160  integer(I4B), intent(in) :: kstp !< time step number
2161  integer(I4B), intent(in) :: kouter !< number of outer (Picard) iterations
2162  integer(I4B), intent(in) :: niter !< number of inner iteration in this time step
2163  integer(I4B), intent(in) :: istart !< starting iteration number for this time step
2164  integer(I4B), intent(in) :: kstart !< starting position in the conv* arrays
2165  ! -- local
2166  integer(I4B) :: itot
2167  integer(I4B) :: m_idx, j, k
2168  integer(I4B) :: kpos
2169  integer(I4B) :: loc_dvmax !< solution node number (row) of max. dep. var. change
2170  integer(I4B) :: loc_rmax !< solution node number (row) of max. residual
2171  integer(I4B) :: model_id, node_user
2172  real(DP) :: dvmax !< maximum dependent variable change
2173  real(DP) :: rmax !< maximum residual
2174  class(NumericalModelType), pointer :: num_mod => null()
2175  !
2176  ! -- initialize local variables
2177  itot = istart
2178  !
2179  ! -- write inner iteration results to the inner csv output file
2180  do k = 1, niter
2181  kpos = kstart + k - 1
2182  write (iu, '(*(G0,:,","))', advance='NO') &
2183  itot, totim, kper, kstp, kouter, k
2184  !
2185  ! -- solution summary
2186  dvmax = dzero
2187  rmax = dzero
2188  do j = 1, this%convnmod
2189  if (abs(this%cnvg_summary%convdvmax(j, kpos)) > abs(dvmax)) then
2190  loc_dvmax = this%cnvg_summary%convlocdv(j, kpos)
2191  dvmax = this%cnvg_summary%convdvmax(j, kpos)
2192  end if
2193  if (abs(this%cnvg_summary%convrmax(j, kpos)) > abs(rmax)) then
2194  loc_rmax = this%cnvg_summary%convlocr(j, kpos)
2195  rmax = this%cnvg_summary%convrmax(j, kpos)
2196  end if
2197  end do
2198  !
2199  ! -- no change, could be anywhere
2200  if (dvmax == dzero) loc_dvmax = 0
2201  if (rmax == dzero) loc_rmax = 0
2202  !
2203  ! -- get model number and user node number for max. dep. var. change
2204  if (loc_dvmax > 0) then
2205  call this%sln_get_nodeu(loc_dvmax, m_idx, node_user)
2206  num_mod => getnumericalmodelfromlist(this%modellist, m_idx)
2207  model_id = num_mod%id
2208  else
2209  model_id = 0
2210  node_user = 0
2211  end if
2212  write (iu, '(*(G0,:,","))', advance='NO') '', dvmax, model_id, node_user
2213  !
2214  ! -- get model number and user node number for max. residual
2215  if (loc_rmax > 0) then
2216  call this%sln_get_nodeu(loc_rmax, m_idx, node_user)
2217  num_mod => getnumericalmodelfromlist(this%modellist, m_idx)
2218  model_id = num_mod%id
2219  else
2220  model_id = 0
2221  node_user = 0
2222  end if
2223  write (iu, '(*(G0,:,","))', advance='NO') '', rmax, model_id, node_user
2224  !
2225  ! -- write ims acceleration parameters
2226  if (this%linsolver == ims_solver) then
2227  write (iu, '(*(G0,:,","))', advance='NO') &
2228  '', trim(adjustl(this%caccel(kpos)))
2229  end if
2230  !
2231  ! -- write information for each model
2232  if (this%convnmod > 1 .or. simulation_mode == "PARALLEL") then
2233  do j = 1, this%cnvg_summary%convnmod
2234  loc_dvmax = this%cnvg_summary%convlocdv(j, kpos)
2235  dvmax = this%cnvg_summary%convdvmax(j, kpos)
2236  loc_rmax = this%cnvg_summary%convlocr(j, kpos)
2237  rmax = this%cnvg_summary%convrmax(j, kpos)
2238  !
2239  ! -- get model number and user node number for max. dep. var. change
2240  if (loc_dvmax > 0) then
2241  call this%sln_get_nodeu(loc_dvmax, m_idx, node_user)
2242  else
2243  node_user = 0
2244  end if
2245  write (iu, '(*(G0,:,","))', advance='NO') '', dvmax, node_user
2246  !
2247  ! -- get model number and user node number for max. residual
2248  if (loc_rmax > 0) then
2249  call this%sln_get_nodeu(loc_rmax, m_idx, node_user)
2250  else
2251  node_user = 0
2252  end if
2253  write (iu, '(*(G0,:,","))', advance='NO') '', rmax, node_user
2254  end do
2255  end if
2256  !
2257  ! -- write line
2258  write (iu, '(a)') ''
2259  !
2260  ! -- update itot
2261  itot = itot + 1
2262  end do
2263  !
2264  ! -- flush file
2265  flush (iu)
Here is the call graph for this function:

◆ finalizesolve()

subroutine numericalsolutionmodule::finalizesolve ( class(numericalsolutiontype this,
integer(i4b), intent(in)  kiter,
integer(i4b), intent(inout)  isgcnvg,
integer(i4b), intent(in)  isuppress_output 
)

Finalize the solution. Called after the outer iteration loop.

Parameters
thisNumericalSolutionType instance
[in]kiterPicard iteration number after convergence or failure
[in,out]isgcnvgsolution group convergence flag
[in]isuppress_outputflag for suppressing output

Definition at line 1884 of file NumericalSolution.f90.

1885  ! -- modules
1886  use tdismodule, only: kper, kstp
1887  ! -- dummy variables
1888  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1889  integer(I4B), intent(in) :: kiter !< Picard iteration number after convergence or failure
1890  integer(I4B), intent(inout) :: isgcnvg !< solution group convergence flag
1891  integer(I4B), intent(in) :: isuppress_output !< flag for suppressing output
1892  ! -- local variables
1893  integer(I4B) :: ic, im
1894  class(NumericalModelType), pointer :: mp => null()
1895  class(NumericalExchangeType), pointer :: cp => null()
1896  ! -- formats for convergence info
1897  character(len=*), parameter :: fmtnocnvg = &
1898  "(1X,'Solution ', i0, ' did not converge for stress period ', i0, &
1899  &' and time step ', i0)"
1900  character(len=*), parameter :: fmtcnvg = &
1901  "(1X, I0, ' CALLS TO NUMERICAL SOLUTION ', 'IN TIME STEP ', I0, &
1902  &' STRESS PERIOD ',I0,/1X,I0,' TOTAL ITERATIONS')"
1903 
1904  ! start timer
1905  call g_prof%start("Finalize solve"//this%id_postfix, this%tmr_final_solve)
1906 
1907  !
1908  ! -- finalize the outer iteration table
1909  if (this%iprims > 0) then
1910  call this%outertab%finalize_table()
1911  end if
1912  !
1913  ! -- write convergence info
1914  !
1915  ! -- convergence was achieved
1916  if (this%icnvg /= 0) then
1917  if (this%iprims > 0) then
1918  write (iout, fmtcnvg) kiter, kstp, kper, this%itertot_timestep
1919  end if
1920  !
1921  ! -- convergence was not achieved
1922  else
1923  write (iout, fmtnocnvg) this%id, kper, kstp
1924  end if
1925  !
1926  ! -- write inner iteration convergence summary
1927  if (this%iprims == 2) then
1928  !
1929  ! -- write summary for each model
1930  do im = 1, this%modellist%Count()
1931  mp => getnumericalmodelfromlist(this%modellist, im)
1932  call this%convergence_summary(mp%iout, im, this%itertot_timestep)
1933  end do
1934  !
1935  ! -- write summary for entire solution
1936  call this%convergence_summary(iout, this%convnmod + 1, &
1937  this%itertot_timestep)
1938  end if
1939  !
1940  ! -- set solution group convergence flag
1941  if (this%icnvg == 0) isgcnvg = 0
1942 
1943  call g_prof%start("Calculate flows", this%tmr_flows)
1944 
1945  !
1946  ! -- Calculate flow for each model
1947  do im = 1, this%modellist%Count()
1948  mp => getnumericalmodelfromlist(this%modellist, im)
1949  call mp%model_cq(this%icnvg, isuppress_output)
1950  end do
1951  !
1952  ! -- Calculate flow for each exchange
1953  do ic = 1, this%exchangelist%Count()
1954  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1955  call cp%exg_cq(isgcnvg, isuppress_output, this%id)
1956  end do
1957 
1958  call g_prof%stop(this%tmr_flows)
1959  call g_prof%start("Calculate budgets", this%tmr_budgets)
1960 
1961  !
1962  ! -- Budget terms for each model
1963  do im = 1, this%modellist%Count()
1964  mp => getnumericalmodelfromlist(this%modellist, im)
1965  call mp%model_bd(this%icnvg, isuppress_output)
1966  end do
1967  !
1968  ! -- Budget terms for each exchange
1969  do ic = 1, this%exchangelist%Count()
1970  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1971  call cp%exg_bd(isgcnvg, isuppress_output, this%id)
1972  end do
1973 
1974  ! stop timer
1975  call g_prof%stop(this%tmr_budgets)
1976  call g_prof%stop(this%tmr_final_solve)
1977 
integer(i4b), pointer, public kstp
current time step number
Definition: tdis.f90:27
integer(i4b), pointer, public kper
current stress period number
Definition: tdis.f90:26
Here is the call graph for this function:

◆ get_backtracking_flag()

integer(i4b) function numericalsolutionmodule::get_backtracking_flag ( class(numericalsolutiontype this)
private
Parameters
thisNumericalSolutionType instance
Returns
backtracking flag (1) backtracking performed (0) backtracking not performed

Definition at line 2840 of file NumericalSolution.f90.

2841  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2842  integer(I4B) :: bt_flag !< backtracking flag (1) backtracking performed (0) backtracking not performed
2843  ! local
2844  integer(I4B) :: n
2845  real(DP) :: dx
2846  real(DP) :: dx_abs
2847  real(DP) :: dx_abs_max
2848 
2849  ! default is off
2850  bt_flag = 0
2851 
2852  ! find max. change
2853  dx_abs_max = 0.0
2854  do n = 1, this%neq
2855  if (this%active(n) < 1) cycle
2856  dx = this%x(n) - this%xtemp(n)
2857  dx_abs = abs(dx)
2858  if (dx_abs > dx_abs_max) dx_abs_max = dx_abs
2859  end do
2860 
2861  ! if backtracking, set flag
2862  if (this%breduc * dx_abs_max >= this%dvclose) then
2863  bt_flag = 1
2864  end if
2865 

◆ get_exchanges()

type(listtype) function, pointer numericalsolutionmodule::get_exchanges ( class(numericalsolutiontype this)
private
Parameters
thisinstance of the numerical solution
Returns
pointer to the exchange list

Definition at line 2359 of file NumericalSolution.f90.

2360  class(NumericalSolutionType) :: this !< instance of the numerical solution
2361  type(ListType), pointer :: exchanges !< pointer to the exchange list
2362 
2363  exchanges => this%exchangelist
2364 

◆ get_models()

type(listtype) function, pointer numericalsolutionmodule::get_models ( class(numericalsolutiontype this)
private

Returns a pointer to the list of models in this solution.

Returns
pointer to the model list
Parameters
thisNumericalSolutionType instance

Definition at line 2327 of file NumericalSolution.f90.

2328  ! -- return variable
2329  type(ListType), pointer :: models !< pointer to the model list
2330  ! -- dummy variables
2331  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2332 
2333  models => this%modellist
2334 

◆ getnumericalsolutionfromlist()

class(numericalsolutiontype) function, pointer, public numericalsolutionmodule::getnumericalsolutionfromlist ( type(listtype), intent(inout)  list,
integer(i4b), intent(in)  idx 
)

Get a numerical solution from a list.

Parameters
[in,out]listlist of numerical solutions
[in]idxvalue to retrieve from the list
Returns
numerical solution

Definition at line 3391 of file NumericalSolution.f90.

3392  ! -- dummy variables
3393  type(ListType), intent(inout) :: list !< list of numerical solutions
3394  integer(I4B), intent(in) :: idx !< value to retrieve from the list
3395  ! -- return variables
3396  class(NumericalSolutionType), pointer :: res !< numerical solution
3397  ! -- local variables
3398  class(*), pointer :: obj
3399  !
3400  obj => list%GetItem(idx)
3401  res => castasnumericalsolutionclass(obj)
Here is the call graph for this function:

◆ preparesolve()

subroutine numericalsolutionmodule::preparesolve ( class(numericalsolutiontype this)
private

Prepare for the system solve by advancing the simulation.

Parameters
thisNumericalSolutionType instance

Definition at line 1468 of file NumericalSolution.f90.

1469  ! -- dummy variables
1470  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1471  ! -- local variables
1472  integer(I4B) :: ic
1473  integer(I4B) :: im
1474  class(NumericalExchangeType), pointer :: cp => null()
1475  class(NumericalModelType), pointer :: mp => null()
1476 
1477  ! start timer
1478  call g_prof%start("Prepare solve"//this%id_postfix, this%tmr_prep_solve)
1479 
1480  ! synchronize for AD
1481  call this%synchronize(stg_bfr_exg_ad, this%synchronize_ctx)
1482 
1483  ! -- Exchange advance
1484  do ic = 1, this%exchangelist%Count()
1485  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1486  call cp%exg_ad()
1487  end do
1488 
1489  ! -- Model advance
1490  do im = 1, this%modellist%Count()
1491  mp => getnumericalmodelfromlist(this%modellist, im)
1492  call mp%model_ad()
1493  end do
1494 
1495  ! advance solution
1496  call this%sln_ad()
1497 
1498  ! stop timer
1499  call g_prof%stop(this%tmr_prep_solve)
1500 
Here is the call graph for this function:

◆ save()

subroutine numericalsolutionmodule::save ( class(numericalsolutiontype this,
character(len=*), intent(in)  filename 
)

Save solution ia vector, ja vector , coefficient matrix, right-hand side vector, and the dependent-variable vector to a file.

Parameters
thisNumericalSolutionType instance
[in]filenamefilename to save solution data

Definition at line 2274 of file NumericalSolution.f90.

2275  use sparsematrixmodule
2276  ! -- modules
2277  use inputoutputmodule, only: getunit
2278  ! -- dummy variables
2279  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2280  character(len=*), intent(in) :: filename !< filename to save solution data
2281  ! -- local variables
2282  integer(I4B) :: inunit
2283  !
2284  select type (spm => this%system_matrix)
2285  class is (sparsematrixtype)
2286  inunit = getunit()
2287  open (unit=inunit, file=filename, status='unknown')
2288  write (inunit, *) 'ia'
2289  write (inunit, *) spm%ia
2290  write (inunit, *) 'ja'
2291  write (inunit, *) spm%ja
2292  write (inunit, *) 'amat'
2293  write (inunit, *) spm%amat
2294  write (inunit, *) 'rhs'
2295  write (inunit, *) this%rhs
2296  write (inunit, *) 'x'
2297  write (inunit, *) this%x
2298  close (inunit)
2299  end select
Here is the call graph for this function:

◆ sln_ad()

subroutine numericalsolutionmodule::sln_ad ( class(numericalsolutiontype this)

Advance solution.

Parameters
thisNumericalSolutionType instance

Definition at line 1141 of file NumericalSolution.f90.

1142  ! -- modules
1143  use tdismodule, only: kstp, kper
1144  ! -- dummy variables
1145  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1146  !
1147  ! -- write headers to CSV file
1148  if (kper == 1 .and. kstp == 1) then
1149  call this%writeCSVHeader()
1150  end if
1151 
1152  ! write PTC info on models to iout
1153  call this%writePTCInfoToFile(kper)
1154 
1155  ! reset convergence flag and inner solve counter
1156  this%icnvg = 0
1157  this%itertot_timestep = 0
1158  this%iouttot_timestep = 0

◆ sln_ar()

subroutine numericalsolutionmodule::sln_ar ( class(numericalsolutiontype this)

Allocate and read data for a solution.

Parameters
thisNumericalSolutionType instance

Definition at line 535 of file NumericalSolution.f90.

536  ! -- modules
538  use simvariablesmodule, only: iout
541  ! -- dummy variables
542  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
543  ! -- local variables
544  class(NumericalModelType), pointer :: mp => null()
545  class(NumericalExchangeType), pointer :: cp => null()
546  character(len=linelength) :: warnmsg
547  character(len=linelength) :: keyword
548  character(len=linelength) :: fname
549  character(len=linelength) :: msg
550  integer(I4B) :: i
551  integer(I4B) :: ifdparam, mxvl, npp
552  integer(I4B) :: ierr
553  logical(LGP) :: isfound, endOfBlock
554  integer(I4B) :: ival
555  real(DP) :: rval
556  character(len=*), parameter :: fmtcsvout = &
557  "(4x, 'CSV OUTPUT WILL BE SAVED TO FILE: ', a, &
558  &/4x, 'OPENED ON UNIT: ', I7)"
559  character(len=*), parameter :: fmtptcout = &
560  "(4x, 'PTC OUTPUT WILL BE SAVED TO FILE: ', a, &
561  &/4x, 'OPENED ON UNIT: ', I7)"
562  character(len=*), parameter :: fmterrasym = &
563  "(a,' **',a,'** PRODUCES AN ASYMMETRIC COEFFICIENT MATRIX, BUT THE &
564  &CONJUGATE GRADIENT METHOD WAS SELECTED. USE BICGSTAB INSTEAD. ')"
565  !
566  ! identify package and initialize.
567  WRITE (iout, 1) this%iu
568 00001 FORMAT(1x, /1x, 'IMS -- ITERATIVE MODEL SOLUTION PACKAGE, VERSION 6', &
569  ', 4/28/2017', /, 9x, 'INPUT READ FROM UNIT', i5)
570  !
571  ! -- initialize
572  i = 1
573  ifdparam = 1
574  npp = 0
575  mxvl = 0
576  !
577  ! -- get options block
578  call this%parser%GetBlock('OPTIONS', isfound, ierr, &
579  supportopenclose=.true., blockrequired=.false.)
580  !
581  ! -- parse options block if detected
582  if (isfound) then
583  write (iout, '(/1x,a)') 'PROCESSING IMS OPTIONS'
584  do
585  call this%parser%GetNextLine(endofblock)
586  if (endofblock) exit
587  call this%parser%GetStringCaps(keyword)
588  select case (keyword)
589  case ('PRINT_OPTION')
590  call this%parser%GetStringCaps(keyword)
591  if (keyword .eq. 'NONE') then
592  this%iprims = 0
593  else if (keyword .eq. 'SUMMARY') then
594  this%iprims = 1
595  else if (keyword .eq. 'ALL') then
596  this%iprims = 2
597  else
598  write (errmsg, '(3a)') &
599  'Unknown IMS print option (', trim(keyword), ').'
600  call store_error(errmsg)
601  end if
602  case ('COMPLEXITY')
603  call this%parser%GetStringCaps(keyword)
604  if (keyword .eq. 'SIMPLE') then
605  ifdparam = 1
606  WRITE (iout, 21)
607  else if (keyword .eq. 'MODERATE') then
608  ifdparam = 2
609  WRITE (iout, 23)
610  else if (keyword .eq. 'COMPLEX') then
611  ifdparam = 3
612  WRITE (iout, 25)
613  else
614  write (errmsg, '(3a)') &
615  'Unknown IMS COMPLEXITY option (', trim(keyword), ').'
616  call store_error(errmsg)
617  end if
618  case ('CSV_OUTER_OUTPUT')
619  call this%parser%GetStringCaps(keyword)
620  if (keyword == 'FILEOUT') then
621  call this%parser%GetString(fname)
622  if (nr_procs > 1) then
623  call append_processor_id(fname, proc_id)
624  end if
625  this%icsvouterout = getunit()
626  call openfile(this%icsvouterout, iout, fname, 'CSV_OUTER_OUTPUT', &
627  filstat_opt='REPLACE')
628  write (iout, fmtcsvout) trim(fname), this%icsvouterout
629  else
630  write (errmsg, '(a)') 'Optional CSV_OUTER_OUTPUT '// &
631  'keyword must be followed by FILEOUT'
632  call store_error(errmsg)
633  end if
634  case ('CSV_INNER_OUTPUT')
635  call this%parser%GetStringCaps(keyword)
636  if (keyword == 'FILEOUT') then
637  call this%parser%GetString(fname)
638  if (nr_procs > 1) then
639  call append_processor_id(fname, proc_id)
640  end if
641  this%icsvinnerout = getunit()
642  call openfile(this%icsvinnerout, iout, fname, 'CSV_INNER_OUTPUT', &
643  filstat_opt='REPLACE')
644  write (iout, fmtcsvout) trim(fname), this%icsvinnerout
645  else
646  write (errmsg, '(a)') 'Optional CSV_INNER_OUTPUT '// &
647  'keyword must be followed by FILEOUT'
648  call store_error(errmsg)
649  end if
650  case ('NO_PTC')
651  call this%parser%GetStringCaps(keyword)
652  select case (keyword)
653  case ('ALL')
654  ival = 0
655  msg = 'ALL'
656  case ('FIRST')
657  ival = -1
658  msg = 'THE FIRST'
659  case default
660  ival = 0
661  msg = 'ALL'
662  end select
663  this%iallowptc = ival
664  write (iout, '(3x,A)') 'PSEUDO-TRANSIENT CONTINUATION DISABLED FOR'// &
665  ' '//trim(adjustl(msg))//' STRESS-PERIOD(S)'
666  case ('ATS_OUTER_MAXIMUM_FRACTION')
667  rval = this%parser%GetDouble()
668  if (rval < dzero .or. rval > dhalf) then
669  write (errmsg, '(a,G0)') 'Value for ATS_OUTER_MAXIMUM_FRAC must be &
670  &between 0 and 0.5. Found ', rval
671  call store_error(errmsg)
672  end if
673  this%atsfrac = rval
674  write (iout, '(3x,A,G0)') 'ADAPTIVE TIME STEP SETTING FOUND. FRACTION &
675  &OF OUTER MAXIMUM USED TO INCREASE OR DECREASE TIME STEP SIZE IS ',&
676  &this%atsfrac
677  !
678  ! -- DEPRECATED OPTIONS
679  case ('CSV_OUTPUT')
680  call this%parser%GetStringCaps(keyword)
681  if (keyword == 'FILEOUT') then
682  call this%parser%GetString(fname)
683  this%icsvouterout = getunit()
684  call openfile(this%icsvouterout, iout, fname, 'CSV_OUTPUT', &
685  filstat_opt='REPLACE')
686  write (iout, fmtcsvout) trim(fname), this%icsvouterout
687  !
688  ! -- create warning message
689  write (warnmsg, '(a)') &
690  'OUTER ITERATION INFORMATION WILL BE SAVED TO '//trim(fname)
691  !
692  ! -- create deprecation warning
693  call deprecation_warning('OPTIONS', 'CSV_OUTPUT', '6.1.1', &
694  warnmsg, this%parser%GetUnit())
695  else
696  write (errmsg, '(a)') 'Optional CSV_OUTPUT '// &
697  'keyword must be followed by FILEOUT'
698  call store_error(errmsg)
699  end if
700  !
701  ! -- right now these are options that are only available in the
702  ! development version and are not included in the documentation.
703  ! These options are only available when IDEVELOPMODE in
704  ! constants module is set to 1
705  case ('DEV_PTC')
706  call this%parser%DevOpt()
707  this%iallowptc = 1
708  write (iout, '(1x,A)') 'PSEUDO-TRANSIENT CONTINUATION ENABLED'
709  case ('DEV_PTC_OUTPUT')
710  call this%parser%DevOpt()
711  this%iallowptc = 1
712  call this%parser%GetStringCaps(keyword)
713  if (keyword == 'FILEOUT') then
714  call this%parser%GetString(fname)
715  if (nr_procs > 1) then
716  call append_processor_id(fname, proc_id)
717  end if
718  this%iptcout = getunit()
719  call openfile(this%iptcout, iout, fname, 'PTC-OUT', &
720  filstat_opt='REPLACE')
721  write (iout, fmtptcout) trim(fname), this%iptcout
722  else
723  write (errmsg, '(a)') &
724  'Optional PTC_OUTPUT keyword must be followed by FILEOUT'
725  call store_error(errmsg)
726  end if
727  case ('DEV_PTC_OPTION')
728  call this%parser%DevOpt()
729  this%iallowptc = 1
730  this%iptcopt = 1
731  write (iout, '(1x,A)') &
732  'PSEUDO-TRANSIENT CONTINUATION USES BNORM AND L2NORM TO '// &
733  'SET INITIAL VALUE'
734  case ('DEV_PTC_EXPONENT')
735  call this%parser%DevOpt()
736  rval = this%parser%GetDouble()
737  if (rval < dzero) then
738  write (errmsg, '(a)') 'PTC_EXPONENT must be > 0.'
739  call store_error(errmsg)
740  else
741  this%iallowptc = 1
742  this%ptcexp = rval
743  write (iout, '(1x,A,1x,g15.7)') &
744  'PSEUDO-TRANSIENT CONTINUATION EXPONENT', this%ptcexp
745  end if
746  case ('DEV_PTC_DEL0')
747  call this%parser%DevOpt()
748  rval = this%parser%GetDouble()
749  if (rval < dzero) then
750  write (errmsg, '(a)') 'IMS sln_ar: PTC_DEL0 must be > 0.'
751  call store_error(errmsg)
752  else
753  this%iallowptc = 1
754  this%ptcdel0 = rval
755  write (iout, '(1x,A,1x,g15.7)') &
756  'PSEUDO-TRANSIENT CONTINUATION INITIAL TIMESTEP', this%ptcdel0
757  end if
758  case default
759  write (errmsg, '(a,2(1x,a))') &
760  'Unknown IMS option (', trim(keyword), ').'
761  call store_error(errmsg)
762  end select
763  end do
764  write (iout, '(1x,a)') 'END OF IMS OPTIONS'
765  else
766  write (iout, '(1x,a)') 'NO IMS OPTION BLOCK DETECTED.'
767  end if
768 
769 00021 FORMAT(1x, 'SIMPLE OPTION:', /, &
770  1x, 'DEFAULT SOLVER INPUT VALUES FOR FAST SOLUTIONS')
771 00023 FORMAT(1x, 'MODERATE OPTION:', /, 1x, 'DEFAULT SOLVER', &
772  ' INPUT VALUES REFLECT MODERATELY NONLINEAR MODEL')
773 00025 FORMAT(1x, 'COMPLEX OPTION:', /, 1x, 'DEFAULT SOLVER', &
774  ' INPUT VALUES REFLECT STRONGLY NONLINEAR MODEL')
775 
776  !-------READ NONLINEAR ITERATION PARAMETERS AND LINEAR SOLVER SELECTION INDEX
777  ! -- set default nonlinear parameters
778  call this%sln_setouter(ifdparam)
779  !
780  ! -- get NONLINEAR block
781  call this%parser%GetBlock('NONLINEAR', isfound, ierr, &
782  supportopenclose=.true., blockrequired=.false.)
783  !
784  ! -- parse NONLINEAR block if detected
785  if (isfound) then
786  write (iout, '(/1x,a)') 'PROCESSING IMS NONLINEAR'
787  do
788  call this%parser%GetNextLine(endofblock)
789  if (endofblock) exit
790  call this%parser%GetStringCaps(keyword)
791  ! -- parse keyword
792  select case (keyword)
793  case ('OUTER_DVCLOSE')
794  this%dvclose = this%parser%GetDouble()
795  case ('OUTER_MAXIMUM')
796  this%mxiter = this%parser%GetInteger()
797  case ('UNDER_RELAXATION')
798  call this%parser%GetStringCaps(keyword)
799  ival = 0
800  if (keyword == 'NONE') then
801  ival = 0
802  else if (keyword == 'SIMPLE') then
803  ival = 1
804  else if (keyword == 'COOLEY') then
805  ival = 2
806  else if (keyword == 'DBD') then
807  ival = 3
808  else
809  write (errmsg, '(3a)') &
810  'Unknown UNDER_RELAXATION specified (', trim(keyword), ').'
811  call store_error(errmsg)
812  end if
813  this%nonmeth = ival
814  case ('LINEAR_SOLVER')
815  call this%parser%GetStringCaps(keyword)
816  ival = ims_solver
817  if (keyword .eq. 'DEFAULT' .or. &
818  keyword .eq. 'LINEAR') then
819  ival = ims_solver
820  else
821  write (errmsg, '(3a)') &
822  'Unknown LINEAR_SOLVER specified (', trim(keyword), ').'
823  call store_error(errmsg)
824  end if
825  this%linsolver = ival
826  case ('UNDER_RELAXATION_THETA')
827  this%theta = this%parser%GetDouble()
828  case ('UNDER_RELAXATION_KAPPA')
829  this%akappa = this%parser%GetDouble()
830  case ('UNDER_RELAXATION_GAMMA')
831  this%gamma = this%parser%GetDouble()
832  case ('UNDER_RELAXATION_MOMENTUM')
833  this%amomentum = this%parser%GetDouble()
834  case ('BACKTRACKING_NUMBER')
835  this%numtrack = this%parser%GetInteger()
836  IF (this%numtrack > 0) this%ibflag = 1
837  case ('BACKTRACKING_TOLERANCE')
838  this%btol = this%parser%GetDouble()
839  case ('BACKTRACKING_REDUCTION_FACTOR')
840  this%breduc = this%parser%GetDouble()
841  case ('BACKTRACKING_RESIDUAL_LIMIT')
842  this%res_lim = this%parser%GetDouble()
843  !
844  ! -- deprecated variables
845  case ('OUTER_HCLOSE')
846  this%dvclose = this%parser%GetDouble()
847  !
848  ! -- create warning message
849  write (warnmsg, '(a)') &
850  'SETTING OUTER_DVCLOSE TO OUTER_HCLOSE VALUE'
851  !
852  ! -- create deprecation warning
853  call deprecation_warning('NONLINEAR', 'OUTER_HCLOSE', '6.1.1', &
854  warnmsg, this%parser%GetUnit())
855  case ('OUTER_RCLOSEBND')
856  !
857  ! -- create warning message
858  write (warnmsg, '(a)') &
859  'OUTER_DVCLOSE IS USED TO EVALUATE PACKAGE CONVERGENCE'
860  !
861  ! -- create deprecation warning
862  call deprecation_warning('NONLINEAR', 'OUTER_RCLOSEBND', '6.1.1', &
863  warnmsg, this%parser%GetUnit())
864  case default
865  write (errmsg, '(3a)') &
866  'Unknown IMS NONLINEAR keyword (', trim(keyword), ').'
867  call store_error(errmsg)
868  end select
869  end do
870  write (iout, '(1x,a)') 'END OF IMS NONLINEAR DATA'
871  else
872  if (ifdparam .EQ. 0) then
873  write (errmsg, '(a)') 'NO IMS NONLINEAR block detected.'
874  call store_error(errmsg)
875  end if
876  end if
877  !
878  if (this%theta < dem3) then
879  this%theta = dem3
880  end if
881  !
882  ! -- backtracking should only be used if this%nonmeth > 0
883  if (this%nonmeth < 1) then
884  this%ibflag = 0
885  end if
886  !
887  ! -- check that MXITER is greater than zero
888  if (this%mxiter <= 0) then
889  write (errmsg, '(a)') 'Outer iteration number must be > 0.'
890  call store_error(errmsg)
891  END IF
892  !
893  ! -- write under-relaxation option
894  if (this%nonmeth > 0) then
895  WRITE (iout, *) '**UNDER-RELAXATION WILL BE USED***'
896  WRITE (iout, *)
897  elseif (this%nonmeth == 0) then
898  WRITE (iout, *) '***UNDER-RELAXATION WILL NOT BE USED***'
899  WRITE (iout, *)
900  else
901  WRITE (errmsg, '(a)') &
902  'Incorrect value for variable NONMETH was specified.'
903  call store_error(errmsg)
904  end if
905  !
906  ! -- ensure gamma is > 0 for simple
907  if (this%nonmeth == 1) then
908  if (this%gamma == 0) then
909  WRITE (errmsg, '(a)') &
910  'GAMMA must be greater than zero if SIMPLE under-relaxation is used.'
911  call store_error(errmsg)
912  end if
913  end if
914 
915  if (this%solver_mode == 'PETSC') then
916  this%linsolver = petsc_solver
917  end if
918 
919  ! configure linear settings
920  call this%linear_settings%init(this%memory_path)
921  call this%linear_settings%preset_config(ifdparam)
922  call this%linear_settings%read_from_file(this%parser, iout)
923  call this%linear_settings%check_settings()
924  !
925  if (this%linear_settings%ilinmeth == cg_method) then
926  this%isymmetric = 1
927  end if
928  !
929  ! -- call secondary subroutine to initialize and read linear
930  ! solver parameters IMSLINEAR solver
931  if (this%solver_mode == "IMS") then
932  allocate (this%imslinear)
933  WRITE (iout, *) '***IMS LINEAR SOLVER WILL BE USED***'
934  call this%imslinear%imslinear_allocate(this%name, iout, this%iprims, &
935  this%mxiter, this%neq, &
936  this%system_matrix, this%rhs, &
937  this%x, this%linear_settings)
938  !
939  ! -- petsc linear solver flag
940  else if (this%solver_mode == "PETSC") then
941  call this%linear_solver%initialize(this%system_matrix, &
942  this%linear_settings, &
943  this%cnvg_summary)
944  !
945  ! -- incorrect linear solver flag
946  else
947  write (errmsg, '(a)') &
948  'Incorrect value for linear solution method specified.'
949  call store_error(errmsg)
950  end if
951  !
952  ! -- write message about matrix symmetry
953  if (this%isymmetric == 1) then
954  write (iout, '(1x,a,/)') 'A symmetric matrix will be solved'
955  else
956  write (iout, '(1x,a,/)') 'An asymmetric matrix will be solved'
957  end if
958  !
959  ! -- If CG, then go through each model and each exchange and check
960  ! for asymmetry
961  if (this%isymmetric == 1) then
962  !
963  ! -- Models
964  do i = 1, this%modellist%Count()
965  mp => getnumericalmodelfromlist(this%modellist, i)
966  if (mp%get_iasym() /= 0) then
967  write (errmsg, fmterrasym) 'MODEL', trim(adjustl(mp%name))
968  call store_error(errmsg)
969  end if
970  end do
971  !
972  ! -- Exchanges
973  do i = 1, this%exchangelist%Count()
974  cp => getnumericalexchangefromlist(this%exchangelist, i)
975  if (cp%get_iasym() /= 0) then
976  write (errmsg, fmterrasym) 'EXCHANGE', trim(adjustl(cp%name))
977  call store_error(errmsg)
978  end if
979  end do
980  !
981  end if
982 
983  !
984  ! determine if the x and rhs should be scaled
985  this%idv_scale = this%sln_get_idvscale()
986 
987  if (this%idv_scale > 0) then
988  write (iout, '(2(1x,a,/),1x,a,/,6x,a,/)') &
989  'X and RHS will be scaled to avoid very large positive or negative', &
990  'dependent variable values in the model IMS package.', &
991  'NOTE: Specified outer and inner DVCLOSE values in the model IMS &
992  &package', 'will be relative closure criteria.'
993  else if (this%idv_scale < 0) then
994  write (errmsg, '(2(a,1x))') &
995  'dependent_variable_scaling must be specified for all models in', &
996  'the solution and can only be used with GWT and GWE models. '
997  call store_error(errmsg)
998  end if
999  !
1000  !
1001  ! -- write solver data to output file
1002  !
1003  ! -- non-linear solver data
1004  WRITE (iout, 9002) this%dvclose, this%mxiter, &
1005  this%iprims, this%nonmeth, this%linsolver
1006  !
1007  ! -- standard outer iteration formats
1008 9002 FORMAT(1x, 'OUTER ITERATION CONVERGENCE CRITERION (DVCLOSE) = ', e15.6, &
1009  /1x, 'MAXIMUM NUMBER OF OUTER ITERATIONS (MXITER) = ', i0, &
1010  /1x, 'SOLVER PRINTOUT INDEX (IPRIMS) = ', i0, &
1011  /1x, 'NONLINEAR ITERATION METHOD (NONLINMETH) = ', i0, &
1012  /1x, 'LINEAR SOLUTION METHOD (LINMETH) = ', i0)
1013  !
1014  if (this%nonmeth == 1) then ! simple
1015  write (iout, 9003) this%gamma
1016  else if (this%nonmeth == 2) then ! cooley
1017  write (iout, 9004) this%gamma
1018  else if (this%nonmeth == 3) then ! delta bar delta
1019  write (iout, 9005) this%theta, this%akappa, this%gamma, this%amomentum
1020  end if
1021  !
1022  ! -- write backtracking information
1023  if (this%numtrack /= 0) write (iout, 9006) this%numtrack, this%btol, &
1024  this%breduc, this%res_lim
1025  !
1026  ! -- under-relaxation formats (simple, cooley, dbd)
1027 9003 FORMAT(1x, 'UNDER-RELAXATION FACTOR (GAMMA) = ', e15.6)
1028 9004 FORMAT(1x, 'UNDER-RELAXATION PREVIOUS HISTORY FACTOR (GAMMA) = ', e15.6)
1029 9005 FORMAT(1x, 'UNDER-RELAXATION WEIGHT REDUCTION FACTOR (THETA) = ', e15.6, &
1030  /1x, 'UNDER-RELAXATION WEIGHT INCREASE INCREMENT (KAPPA) = ', e15.6, &
1031  /1x, 'UNDER-RELAXATION PREVIOUS HISTORY FACTOR (GAMMA) = ', e15.6, &
1032  /1x, 'UNDER-RELAXATION MOMENTUM TERM (AMOMENTUM) = ', e15.6)
1033  !
1034  ! -- backtracking formats
1035 9006 FORMAT(1x, 'MAXIMUM NUMBER OF BACKTRACKS (NUMTRACK) = ', i0, &
1036  /1x, 'BACKTRACKING TOLERANCE FACTOR (BTOL) = ', e15.6, &
1037  /1x, 'BACKTRACKING REDUCTION FACTOR (BREDUC) = ', e15.6, &
1038  /1x, 'BACKTRACKING RESIDUAL LIMIT (RES_LIM) = ', e15.6)
1039  !
1040  ! -- linear solver data
1041  if (this%linsolver == ims_solver) then
1042  call this%imslinear%imslinear_summary(this%mxiter)
1043  else
1044  call this%linear_solver%print_summary()
1045  end if
1046 
1047  ! -- write summary of solver error messages
1048  ierr = count_errors()
1049  if (ierr > 0) then
1050  call this%parser%StoreErrorUnit()
1051  end if
1052  !
1053  ! reallocate space for nonlinear arrays and initialize
1054  call mem_reallocate(this%hncg, this%mxiter, 'HNCG', this%name)
1055  call mem_reallocate(this%lrch, 3, this%mxiter, 'LRCH', this%name)
1056 
1057  ! delta-bar-delta under-relaxation
1058  if (this%nonmeth == 3) then
1059  call mem_reallocate(this%wsave, this%neq, 'WSAVE', this%name)
1060  call mem_reallocate(this%hchold, this%neq, 'HCHOLD', this%name)
1061  call mem_reallocate(this%deold, this%neq, 'DEOLD', this%name)
1062  do i = 1, this%neq
1063  this%wsave(i) = dzero
1064  this%hchold(i) = dzero
1065  this%deold(i) = dzero
1066  end do
1067  end if
1068  this%hncg = dzero
1069  this%lrch = 0
1070 
1071  ! allocate space for saving solver convergence history
1072  if (this%iprims == 2 .or. this%icsvinnerout > 0) then
1073  this%nitermax = this%linear_settings%iter1 * this%mxiter
1074  else
1075  this%nitermax = 1
1076  end if
1077 
1078  allocate (this%caccel(this%nitermax))
1079 
1080  !
1081  ! -- resize convergence report
1082  call this%cnvg_summary%reinit(this%nitermax)
1083  !
1084  ! -- check for numerical solution errors
1085  ierr = count_errors()
1086  if (ierr > 0) then
1087  call this%parser%StoreErrorUnit()
1088  end if
1089  !
1090  ! -- close ims input file
1091  call this%parser%Clear()
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
Here is the call graph for this function:

◆ sln_backtracking()

subroutine numericalsolutionmodule::sln_backtracking ( class(numericalsolutiontype), intent(inout)  this,
class(numericalmodeltype), pointer  mp,
class(numericalexchangetype), pointer  cp,
integer(i4b), intent(in)  kiter 
)
private

Perform backtracking on the solution in the maximum number of backtrack iterations (nbtrack) is greater than 0 and the backtracking criteria are exceeded.

Parameters
[in,out]thisNumericalSolutionType instance
mpmodel pointer (currently null())
cpexchange pointer (currently null())
[in]kiterPicard iteration number

Definition at line 2720 of file NumericalSolution.f90.

2721  ! -- dummy variables
2722  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2723  class(NumericalModelType), pointer :: mp !< model pointer (currently null())
2724  class(NumericalExchangeType), pointer :: cp !< exchange pointer (currently null())
2725  integer(I4B), intent(in) :: kiter !< Picard iteration number
2726  ! -- local variables
2727  character(len=7) :: cmsg
2728  integer(I4B) :: nb
2729  integer(I4B) :: btflag
2730  integer(I4B) :: ibflag
2731  integer(I4B) :: ibtcnt
2732  real(DP) :: resin
2733  !
2734  ! -- initialize local variables
2735  ibflag = 0
2736 
2737  !
2738  ! -- refill amat and rhs with standard conductance
2739  call this%sln_buildsystem(kiter, inewton=0)
2740 
2741  !
2742  ! -- calculate initial l2 norm
2743  if (kiter == 1) then
2744  call this%sln_l2norm(this%res_prev)
2745  resin = this%res_prev
2746  ibflag = 0
2747  else
2748  call this%sln_l2norm(this%res_new)
2749  resin = this%res_new
2750  end if
2751  ibtcnt = 0
2752  if (kiter > 1) then
2753  if (this%res_new > this%res_prev * this%btol) then
2754  !
2755  ! -- iterate until backtracking complete
2756  btloop: do nb = 1, this%numtrack
2757  !
2758  ! -- backtrack the dependent variable
2759  call this%sln_backtracking_xupdate(btflag)
2760  !
2761  ! -- dependent-variable change less than dvclose
2762  if (btflag == 0) then
2763  ibflag = 4
2764  exit btloop
2765  end if
2766  !
2767  ibtcnt = nb
2768 
2769  ! recalculate linear system (amat and rhs)
2770  call this%sln_buildsystem(kiter, inewton=0)
2771 
2772  !
2773  ! -- calculate updated l2norm
2774  call this%sln_l2norm(this%res_new)
2775  !
2776  ! -- evaluate if back tracking can be terminated
2777  if (nb == this%numtrack) then
2778  ibflag = 2
2779  exit btloop
2780  end if
2781  if (this%res_new < this%res_prev * this%btol) then
2782  ibflag = 1
2783  exit btloop
2784  end if
2785  if (this%res_new < this%res_lim) then
2786  exit btloop
2787  end if
2788  end do btloop
2789  end if
2790  ! -- save new residual
2791  this%res_prev = this%res_new
2792  end if
2793  !
2794  ! -- write back backtracking results
2795  if (this%iprims > 0) then
2796  if (ibtcnt > 0) then
2797  cmsg = ' '
2798  else
2799  cmsg = '*'
2800  end if
2801  !
2802  ! -- add data to outertab
2803  call this%outertab%add_term('Backtracking')
2804  call this%outertab%add_term(kiter)
2805  call this%outertab%add_term(' ')
2806  if (this%numtrack > 0) then
2807  call this%outertab%add_term(ibflag)
2808  call this%outertab%add_term(ibtcnt)
2809  call this%outertab%add_term(resin)
2810  call this%outertab%add_term(this%res_prev)
2811  end if
2812  call this%outertab%add_term(' ')
2813  call this%outertab%add_term(cmsg)
2814  call this%outertab%add_term(' ')
2815  end if

◆ sln_backtracking_xupdate()

subroutine numericalsolutionmodule::sln_backtracking_xupdate ( class(numericalsolutiontype), intent(inout)  this,
integer(i4b), intent(inout)  bt_flag 
)
private

Backtracking update of the dependent variable if the calculated backtracking update exceeds the dependent variable closure criteria.

Parameters
[in,out]thisNumericalSolutionType instance
[in,out]bt_flagbacktracking flag (1) backtracking performed (0) backtracking not performed

Definition at line 2824 of file NumericalSolution.f90.

2825  ! -- dummy variables
2826  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2827  integer(I4B), intent(inout) :: bt_flag !< backtracking flag (1) backtracking performed (0) backtracking not performed
2828 
2829  bt_flag = this%get_backtracking_flag()
2830 
2831  ! perform backtracking if ...
2832  if (bt_flag > 0) then
2833  call this%apply_backtracking()
2834  end if
2835 

◆ sln_buildsystem()

subroutine numericalsolutionmodule::sln_buildsystem ( class(numericalsolutiontype this,
integer(i4b), intent(in)  kiter,
integer(i4b), intent(in)  inewton 
)

Definition at line 1981 of file NumericalSolution.f90.

1982  class(NumericalSolutionType) :: this
1983  integer(I4B), intent(in) :: kiter
1984  integer(I4B), intent(in) :: inewton
1985  ! local
1986  integer(I4B) :: im, ic
1987  class(NumericalModelType), pointer :: mp
1988  class(NumericalExchangeType), pointer :: cp
1989  !
1990  ! -- Set amat and rhs to zero
1991  call this%sln_reset()
1992 
1993  ! reset models
1994  do im = 1, this%modellist%Count()
1995  mp => getnumericalmodelfromlist(this%modellist, im)
1996  call mp%model_reset()
1997  end do
1998 
1999  ! synchronize for CF
2000  call this%synchronize(stg_bfr_exg_cf, this%synchronize_ctx)
2001 
2002  !
2003  ! -- Calculate the matrix terms for each exchange
2004  do ic = 1, this%exchangelist%Count()
2005  cp => getnumericalexchangefromlist(this%exchangelist, ic)
2006  call cp%exg_cf(kiter)
2007  end do
2008  !
2009  ! -- Calculate the matrix terms for each model
2010  do im = 1, this%modellist%Count()
2011  mp => getnumericalmodelfromlist(this%modellist, im)
2012  call mp%model_cf(kiter)
2013  end do
2014 
2015  ! synchronize for FC
2016  call this%synchronize(stg_bfr_exg_fc, this%synchronize_ctx)
2017 
2018  !
2019  ! -- Add exchange coefficients to the solution
2020  do ic = 1, this%exchangelist%Count()
2021  cp => getnumericalexchangefromlist(this%exchangelist, ic)
2022  call cp%exg_fc(kiter, this%system_matrix, this%rhs, inewton)
2023  end do
2024  !
2025  ! -- Add model coefficients to the solution
2026  do im = 1, this%modellist%Count()
2027  mp => getnumericalmodelfromlist(this%modellist, im)
2028  call mp%model_fc(kiter, this%system_matrix, inewton)
2029  end do
2030 
Here is the call graph for this function:

◆ sln_ca()

subroutine numericalsolutionmodule::sln_ca ( class(numericalsolutiontype this,
integer(i4b), intent(inout)  isgcnvg,
integer(i4b), intent(in)  isuppress_output 
)

Solve the models in this solution for kper and kstp.

Parameters
thisNumericalSolutionType instance
[in,out]isgcnvgsolution group convergence flag
[in]isuppress_outputflag for suppressing output

Definition at line 1318 of file NumericalSolution.f90.

1319  ! -- dummy variables
1320  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1321  integer(I4B), intent(inout) :: isgcnvg !< solution group convergence flag
1322  integer(I4B), intent(in) :: isuppress_output !< flag for suppressing output
1323  ! -- local variables
1324  class(NumericalModelType), pointer :: mp => null()
1325  character(len=LINELENGTH) :: line
1326  character(len=LINELENGTH) :: fmt
1327  integer(I4B) :: im
1328  integer(I4B) :: kiter ! non-linear iteration counter
1329 
1330  ! advance the models, exchanges, and solution
1331  call this%prepareSolve()
1332 
1333  select case (isim_mode)
1334  case (mvalidate)
1335  line = 'mode="validation" -- Skipping matrix assembly and solution.'
1336  fmt = "(/,1x,a,/)"
1337  do im = 1, this%modellist%Count()
1338  mp => getnumericalmodelfromlist(this%modellist, im)
1339  call mp%model_message(line, fmt=fmt)
1340  end do
1341  case (mnormal)
1342  ! nonlinear iteration loop for this solution
1343  outerloop: do kiter = 1, this%mxiter
1344 
1345  ! perform a single iteration
1346  call this%solve(kiter, isuppress_output)
1347 
1348  ! exit if converged
1349  if (this%icnvg == 1) then
1350  exit outerloop
1351  end if
1352 
1353  end do outerloop
1354 
1355  ! finish up, write convergence info, CSV file, budgets and flows, ...
1356  call this%finalizeSolve(kiter, isgcnvg, isuppress_output)
1357  end select
Here is the call graph for this function:

◆ sln_calc_ptc()

subroutine numericalsolutionmodule::sln_calc_ptc ( class(numericalsolutiontype this,
integer(i4b)  iptc,
real(dp)  ptcf 
)
private
Parameters
thisNumericalSolutionType instance
iptcPTC (1) or not (0)
ptcfthe PTC factor calculated

Definition at line 2999 of file NumericalSolution.f90.

3000  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3001  integer(I4B) :: iptc !< PTC (1) or not (0)
3002  real(DP) :: ptcf !< the PTC factor calculated
3003  ! local
3004  integer(I4B) :: im
3005  class(NumericalModelType), pointer :: mp
3006  class(VectorBaseType), pointer :: vec_resid
3007 
3008  iptc = 0
3009  ptcf = dzero
3010 
3011  ! calc. residual vector
3012  vec_resid => this%system_matrix%create_vec(this%neq)
3013  call this%sln_calc_residual(vec_resid)
3014 
3015  ! determine ptc
3016  do im = 1, this%modellist%Count()
3017  mp => getnumericalmodelfromlist(this%modellist, im)
3018  call mp%model_ptc(vec_resid, iptc, ptcf)
3019  end do
3020 
3021  ! clean up temp. vector
3022  call vec_resid%destroy()
3023  deallocate (vec_resid)
3024 
Here is the call graph for this function:

◆ sln_calc_residual()

subroutine numericalsolutionmodule::sln_calc_residual ( class(numericalsolutiontype this,
class(vectorbasetype), pointer  vec_resid 
)
private
Parameters
thisNumericalSolutionType instance
vec_residthe residual vector

Definition at line 3029 of file NumericalSolution.f90.

3030  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3031  class(VectorBaseType), pointer :: vec_resid !< the residual vector
3032  ! local
3033  integer(I4B) :: n
3034 
3035  call this%system_matrix%multiply(this%vec_x, vec_resid) ! r = A*x
3036 
3037  call vec_resid%axpy(-1.0_dp, this%vec_rhs) ! r = r - b
3038 
3039  do n = 1, this%neq
3040  if (this%active(n) < 1) then
3041  call vec_resid%set_value_local(n, 0.0_dp) ! r_i = 0 if inactive
3042  end if
3043  end do
3044 

◆ sln_calcdx()

subroutine numericalsolutionmodule::sln_calcdx ( class(numericalsolutiontype), intent(inout)  this,
integer(i4b), intent(in)  neq,
integer(i4b), dimension(neq), intent(in)  active,
real(dp), dimension(neq), intent(in)  x,
real(dp), dimension(neq), intent(in)  xtemp,
real(dp), dimension(neq), intent(inout)  dx 
)
private

Calculate the dependent-variable change for every cell.

Parameters
[in,out]thisNumericalSolutionType instance
[in]neqnumber of equations
[in]activeactive cell flag (1)
[in]xcurrent dependent-variable
[in]xtempprevious dependent-variable
[in,out]dxdependent-variable change

Definition at line 2975 of file NumericalSolution.f90.

2976  ! -- dummy variables
2977  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2978  integer(I4B), intent(in) :: neq !< number of equations
2979  integer(I4B), dimension(neq), intent(in) :: active !< active cell flag (1)
2980  real(DP), dimension(neq), intent(in) :: x !< current dependent-variable
2981  real(DP), dimension(neq), intent(in) :: xtemp !< previous dependent-variable
2982  real(DP), dimension(neq), intent(inout) :: dx !< dependent-variable change
2983  ! -- local
2984  integer(I4B) :: n
2985  !
2986  ! -- calculate dependent-variable change
2987  do n = 1, neq
2988  ! -- skip inactive nodes
2989  if (active(n) < 1) then
2990  dx(n) = dzero
2991  else
2992  dx(n) = x(n) - xtemp(n)
2993  end if
2994  end do

◆ sln_connect()

subroutine numericalsolutionmodule::sln_connect ( class(numericalsolutiontype this)
private

Assign solution connections. This is the main workhorse method for a solution. The method goes through all the models and all the connections and builds up the sparse matrix. Steps are (1) add internal model connections, (2) add cross terms, (3) allocate solution arrays, (4) create mapping arrays, and (5) fill cross term values if necessary.

Parameters
thisNumericalSolutionType instance

Definition at line 2376 of file NumericalSolution.f90.

2377  ! -- modules
2379  ! -- dummy variables
2380  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2381  ! -- local variables
2382  class(NumericalModelType), pointer :: mp => null()
2383  class(NumericalExchangeType), pointer :: cp => null()
2384  integer(I4B) :: im
2385  integer(I4B) :: ic
2386  !
2387  ! -- Add internal model connections to sparse
2388  do im = 1, this%modellist%Count()
2389  mp => getnumericalmodelfromlist(this%modellist, im)
2390  call mp%model_ac(this%sparse)
2391  end do
2392  !
2393  ! -- synchronize before AC
2394  call this%synchronize(stg_bfr_exg_ac, this%synchronize_ctx)
2395  !
2396  ! -- Add the cross terms to sparse
2397  do ic = 1, this%exchangelist%Count()
2398  cp => getnumericalexchangefromlist(this%exchangelist, ic)
2399  call cp%exg_ac(this%sparse)
2400  end do
2401  !
2402  ! -- The number of non-zero array values are now known so
2403  ! -- ia and ja can be created from sparse. then destroy sparse
2404  call this%sparse%sort()
2405  call this%system_matrix%init(this%sparse, this%name)
2406  call this%sparse%destroy()
2407  !
2408  ! -- Create mapping arrays for each model. Mapping assumes
2409  ! -- that each row has the diagonal in the first position,
2410  ! -- however, rows do not need to be sorted.
2411  do im = 1, this%modellist%Count()
2412  mp => getnumericalmodelfromlist(this%modellist, im)
2413  call mp%model_mc(this%system_matrix)
2414  end do
2415  !
2416  ! -- Create arrays for mapping exchange connections to global solution
2417  do ic = 1, this%exchangelist%Count()
2418  cp => getnumericalexchangefromlist(this%exchangelist, ic)
2419  call cp%exg_mc(this%system_matrix)
2420  end do
Here is the call graph for this function:

◆ sln_da()

subroutine numericalsolutionmodule::sln_da ( class(numericalsolutiontype this)

Deallocate a solution.

Parameters
thisNumericalSolutionType instance

Definition at line 1200 of file NumericalSolution.f90.

1201  ! -- modules
1203  ! -- dummy variables
1204  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1205  !
1206  ! -- IMSLinearModule
1207  if (this%linsolver == ims_solver) then
1208  call this%imslinear%imslinear_da()
1209  deallocate (this%imslinear)
1210  end if
1211  !
1212  ! -- lists
1213  call this%modellist%Clear()
1214  call this%exchangelist%Clear()
1215  deallocate (this%modellist)
1216  deallocate (this%exchangelist)
1217 
1218  call this%system_matrix%destroy()
1219  deallocate (this%system_matrix)
1220  call this%vec_x%destroy()
1221  deallocate (this%vec_x)
1222  call this%vec_rhs%destroy()
1223  deallocate (this%vec_rhs)
1224 
1225  !
1226  ! -- character arrays
1227  deallocate (this%caccel)
1228  !
1229  ! -- inner iteration table object
1230  if (associated(this%innertab)) then
1231  call this%innertab%table_da()
1232  deallocate (this%innertab)
1233  nullify (this%innertab)
1234  end if
1235  !
1236  ! -- outer iteration table object
1237  if (associated(this%outertab)) then
1238  call this%outertab%table_da()
1239  deallocate (this%outertab)
1240  nullify (this%outertab)
1241  end if
1242  !
1243  ! -- arrays
1244  call mem_deallocate(this%active)
1245  call mem_deallocate(this%xtemp)
1246  call mem_deallocate(this%dxold)
1247  call mem_deallocate(this%hncg)
1248  call mem_deallocate(this%lrch)
1249  call mem_deallocate(this%wsave)
1250  call mem_deallocate(this%hchold)
1251  call mem_deallocate(this%deold)
1252  call mem_deallocate(this%convmodstart)
1253  !
1254  ! -- convergence report
1255  call this%cnvg_summary%destroy()
1256  deallocate (this%cnvg_summary)
1257  !
1258  ! -- linear solver
1259  call this%linear_solver%destroy()
1260  deallocate (this%linear_solver)
1261  !
1262  ! -- linear solver settings
1263  call this%linear_settings%destroy()
1264  deallocate (this%linear_settings)
1265  !
1266  ! -- Scalars
1267  call mem_deallocate(this%id)
1268  call mem_deallocate(this%iu)
1269  call mem_deallocate(this%ttform)
1270  call mem_deallocate(this%ttsoln)
1271  call mem_deallocate(this%isymmetric)
1272  call mem_deallocate(this%neq)
1273  call mem_deallocate(this%matrix_offset)
1274  call mem_deallocate(this%dvclose)
1275  call mem_deallocate(this%bigchold)
1276  call mem_deallocate(this%bigch)
1277  call mem_deallocate(this%relaxold)
1278  call mem_deallocate(this%res_prev)
1279  call mem_deallocate(this%res_new)
1280  call mem_deallocate(this%icnvg)
1281  call mem_deallocate(this%itertot_timestep)
1282  call mem_deallocate(this%iouttot_timestep)
1283  call mem_deallocate(this%itertot_sim)
1284  call mem_deallocate(this%mxiter)
1285  call mem_deallocate(this%linsolver)
1286  call mem_deallocate(this%nonmeth)
1287  call mem_deallocate(this%iprims)
1288  call mem_deallocate(this%theta)
1289  call mem_deallocate(this%akappa)
1290  call mem_deallocate(this%gamma)
1291  call mem_deallocate(this%amomentum)
1292  call mem_deallocate(this%breduc)
1293  call mem_deallocate(this%btol)
1294  call mem_deallocate(this%res_lim)
1295  call mem_deallocate(this%numtrack)
1296  call mem_deallocate(this%ibflag)
1297  call mem_deallocate(this%icsvouterout)
1298  call mem_deallocate(this%icsvinnerout)
1299  call mem_deallocate(this%nitermax)
1300  call mem_deallocate(this%convnmod)
1301  call mem_deallocate(this%iallowptc)
1302  call mem_deallocate(this%iptcopt)
1303  call mem_deallocate(this%iptcout)
1304  call mem_deallocate(this%l2norm0)
1305  call mem_deallocate(this%ptcdel)
1306  call mem_deallocate(this%ptcdel0)
1307  call mem_deallocate(this%ptcexp)
1308  call mem_deallocate(this%atsfrac)
1309  call mem_deallocate(this%idv_scale)
1310  call mem_deallocate(this%dscale)

◆ sln_df()

subroutine numericalsolutionmodule::sln_df ( class(numericalsolutiontype this)

Define a new solution. Must be called after the models and exchanges have been added to solution. The order of the steps is (1) Allocate neq and nja, (2) Assign model offsets and solution ids, (3) Allocate and initialize the solution arrays, (4) Point each model's x and rhs arrays, and (5) Initialize the sparsematrix instance

Parameters
thisNumericalSolutionType instance

Definition at line 438 of file NumericalSolution.f90.

439  ! modules
442  ! -- dummy variables
443  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
444  ! -- local variables
445  class(NumericalModelType), pointer :: mp => null()
446  integer(I4B) :: i
447  integer(I4B), allocatable, dimension(:) :: rowmaxnnz
448  integer(I4B) :: ncol, irow_start, irow_end
449  integer(I4B) :: mod_offset
450  !
451  ! -- set sol id and determine nr. of equation in this solution
452  do i = 1, this%modellist%Count()
453  mp => getnumericalmodelfromlist(this%modellist, i)
454  call mp%set_idsoln(this%id)
455  this%neq = this%neq + mp%neq
456  end do
457  !
458  ! -- set up the (possibly parallel) linear system
459  if (simulation_mode == 'PARALLEL') then
460  this%solver_mode = 'PETSC'
461  else
462  this%solver_mode = 'IMS'
463  end if
464  !
465  ! -- allocate settings structure
466  allocate (this%linear_settings)
467  !
468  ! -- create linear system matrix and compatible vectors
469  this%linear_solver => create_linear_solver(this%solver_mode, this%name)
470  this%system_matrix => this%linear_solver%create_matrix()
471  this%vec_x => this%system_matrix%create_vec_mm(this%neq, 'X', &
472  this%memory_path)
473  this%x => this%vec_x%get_array()
474  this%vec_rhs => this%system_matrix%create_vec_mm(this%neq, 'RHS', &
475  this%memory_path)
476  this%rhs => this%vec_rhs%get_array()
477  !
478  call this%vec_rhs%get_ownership_range(irow_start, irow_end)
479  ncol = this%vec_rhs%get_size()
480  !
481  ! -- calculate and set offsets
482  mod_offset = irow_start - 1
483  this%matrix_offset = irow_start - 1
484  do i = 1, this%modellist%Count()
485  mp => getnumericalmodelfromlist(this%modellist, i)
486  call mp%set_moffset(mod_offset)
487  mod_offset = mod_offset + mp%neq
488  end do
489  !
490  ! -- Allocate and initialize solution arrays
491  call this%allocate_arrays()
492  !
493  ! -- Create convergence summary report
494  allocate (this%cnvg_summary)
495  call this%cnvg_summary%init(this%modellist%Count(), this%convmodstart, &
496  this%memory_path)
497  !
498  ! -- Go through each model and point x, ibound, and rhs to solution
499  do i = 1, this%modellist%Count()
500  mp => getnumericalmodelfromlist(this%modellist, i)
501  call mp%set_xptr(this%x, this%matrix_offset, 'X', this%name)
502  call mp%set_rhsptr(this%rhs, this%matrix_offset, 'RHS', this%name)
503  call mp%set_iboundptr(this%active, this%matrix_offset, 'IBOUND', this%name)
504  end do
505  !
506  ! -- Create the sparsematrix instance
507  allocate (rowmaxnnz(this%neq))
508  do i = 1, this%neq
509  rowmaxnnz(i) = 4
510  end do
511  call this%sparse%init(this%neq, ncol, rowmaxnnz)
512  this%sparse%offset = this%matrix_offset
513  deallocate (rowmaxnnz)
514  !
515  ! -- Assign connections, fill ia/ja, map connections
516  call this%sln_connect()
517 
518  ! add timers
519  write (this%id_postfix, '(a,i0,a)') " (", this%id, ")"
520  this%tmr_prep_solve = -1
521  this%tmr_solve = -1
522  this%tmr_final_solve = -1
523  this%tmr_formulate = -1
524  this%tmr_linsolve = -1
525  this%tmr_flows = -1
526  this%tmr_budgets = -1
527 
character(len=linelength) simulation_mode
Here is the call graph for this function:

◆ sln_dt()

subroutine numericalsolutionmodule::sln_dt ( class(numericalsolutiontype this)

Calculate time step length.

Parameters
thisNumericalSolutionType instance

Definition at line 1099 of file NumericalSolution.f90.

1100  ! -- modules
1101  use tdismodule, only: kstp, kper, delt, ats
1102  use constantsmodule, only: dtwo, dthree
1103  ! -- dummy variables
1104  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1105  ! -- local variables
1106  integer(I4B) :: idir
1107  real(DP) :: delt_temp
1108  real(DP) :: fact_lower
1109  real(DP) :: fact_upper
1110  !
1111  ! -- increase or decrease delt based on kiter fraction. atsfrac should be
1112  ! a value of about 1/3. If the number of outer iterations is less than
1113  ! 1/3 of mxiter, then increase step size. If the number of outer
1114  ! iterations is greater than 2/3 of mxiter, then decrease step size.
1115  if (this%atsfrac > dzero) then
1116  delt_temp = delt
1117  fact_lower = this%mxiter * this%atsfrac
1118  fact_upper = this%mxiter - fact_lower
1119  if (this%iouttot_timestep < int(fact_lower)) then
1120  ! -- increase delt according to tsfactats
1121  idir = 1
1122  else if (this%iouttot_timestep > int(fact_upper)) then
1123  ! -- decrease delt according to tsfactats
1124  idir = -1
1125  else
1126  ! -- do not change delt
1127  idir = 0
1128  end if
1129  !
1130  ! -- submit stable dt for upcoming step
1131  call ats%ats_submit_delt(kstp, kper, delt_temp, &
1132  this%memory_path, idir=idir)
1133  end if
This module contains simulation constants.
Definition: Constants.f90:9
real(dp), parameter dtwo
real constant 2
Definition: Constants.f90:79
real(dp), parameter dthree
real constant 3
Definition: Constants.f90:80
class(atstype), pointer, public ats
Definition: tdis.f90:48
real(dp), pointer, public delt
length of the current time step
Definition: tdis.f90:32

◆ sln_fp()

subroutine numericalsolutionmodule::sln_fp ( class(numericalsolutiontype this)
private

Finalize a solution.

Parameters
thisNumericalSolutionType instance

Definition at line 1178 of file NumericalSolution.f90.

1179  use simvariablesmodule, only: iout
1180  ! -- dummy variables
1181  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1182  !
1183  ! -- write timer output
1184  if (idevelopmode == 1) then
1185  write (iout, '(//1x,a,1x,a,1x,a)') &
1186  'Solution', trim(adjustl(this%name)), 'summary'
1187  write (iout, "(1x,70('-'))")
1188  write (iout, '(1x,a,1x,g0,1x,a)') &
1189  'Total formulate time: ', this%ttform, 'seconds'
1190  write (iout, '(1x,a,1x,g0,1x,a,/)') &
1191  'Total solution time: ', this%ttsoln, 'seconds'
1192  end if

◆ sln_get_dxmax()

subroutine numericalsolutionmodule::sln_get_dxmax ( class(numericalsolutiontype), intent(inout)  this,
real(dp), intent(inout)  hncg,
integer(i4b), intent(inout)  lrch 
)
private

Determine the maximum dependent-variable change at the end of a Picard iteration.

Parameters
[in,out]thisNumericalSolutionType instance
[in,out]hncgmaximum dependent-variable change
[in,out]lrchlocation of the maximum dependent-variable change

Definition at line 3185 of file NumericalSolution.f90.

3186  ! -- dummy variables
3187  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
3188  real(DP), intent(inout) :: hncg !< maximum dependent-variable change
3189  integer(I4B), intent(inout) :: lrch !< location of the maximum dependent-variable change
3190  ! -- local variables
3191  integer(I4B) :: nb
3192  real(DP) :: bigch
3193  real(DP) :: abigch
3194  integer(I4B) :: n
3195  real(DP) :: hdif
3196  real(DP) :: ahdif
3197  !
3198  ! -- determine the maximum change
3199  nb = 0
3200  bigch = dzero
3201  abigch = dzero
3202  do n = 1, this%neq
3203  if (this%active(n) < 1) cycle
3204  hdif = this%x(n) - this%xtemp(n)
3205  ahdif = abs(hdif)
3206  if (ahdif > abigch) then
3207  bigch = hdif
3208  abigch = ahdif
3209  nb = n
3210  end if
3211  end do
3212  !
3213  !-----store maximum change value and location
3214  hncg = bigch
3215  lrch = nb

◆ sln_get_idvscale()

integer(i4b) function numericalsolutionmodule::sln_get_idvscale ( class(numericalsolutiontype this)
private
Parameters
thisNumericalSolutionType instance
Returns
backtracking flag (1) backtracking performed (0) backtracking not performed

Definition at line 2870 of file NumericalSolution.f90.

2871  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2872  integer(I4B) :: idv_scale !< backtracking flag (1) backtracking performed (0) backtracking not performed
2873  ! local
2874  class(NumericalModelType), pointer :: mp => null()
2875  integer(I4B) :: i
2876 
2877  idv_scale = 0
2878  do i = 1, this%modellist%Count()
2879  mp => getnumericalmodelfromlist(this%modellist, i)
2880  if (mp%get_idv_scale() /= 0) then
2881  idv_scale = 1
2882  else
2883  if (idv_scale == 1) then
2884  idv_scale = -1
2885  end if
2886  end if
2887  end do
2888 
Here is the call graph for this function:

◆ sln_get_loc()

subroutine numericalsolutionmodule::sln_get_loc ( class(numericalsolutiontype), intent(inout)  this,
integer(i4b), intent(in)  nodesln,
character(len=*), intent(inout)  str 
)
private

Get the cell location string for the provided solution node number.

Parameters
[in,out]thisNumericalSolutionType instance
[in]nodeslnsolution node number
[in,out]strstring with user node number

Definition at line 3287 of file NumericalSolution.f90.

3288  ! -- dummy variables
3289  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
3290  integer(I4B), intent(in) :: nodesln !< solution node number
3291  character(len=*), intent(inout) :: str !< string with user node number
3292  ! -- local variables
3293  class(NumericalModelType), pointer :: mp => null()
3294  integer(I4B) :: i
3295  integer(I4B) :: istart
3296  integer(I4B) :: iend
3297  integer(I4B) :: noder
3298  integer(I4B) :: nglo
3299  !
3300  ! -- initialize dummy variables
3301  str = ''
3302  !
3303  ! -- initialize local variables
3304  noder = 0
3305  !
3306  ! -- when parallel, account for offset
3307  nglo = nodesln + this%matrix_offset
3308  !
3309  ! -- calculate and set offsets
3310  do i = 1, this%modellist%Count()
3311  mp => getnumericalmodelfromlist(this%modellist, i)
3312  istart = 0
3313  iend = 0
3314  call mp%get_mrange(istart, iend)
3315  if (nglo >= istart .and. nglo <= iend) then
3316  noder = nglo - istart + 1
3317  call mp%get_mcellid(noder, str)
3318  exit
3319  end if
3320  end do
Here is the call graph for this function:

◆ sln_get_nodeu()

subroutine numericalsolutionmodule::sln_get_nodeu ( class(numericalsolutiontype), intent(inout)  this,
integer(i4b), intent(in)  nodesln,
integer(i4b), intent(inout)  im,
integer(i4b), intent(inout)  nodeu 
)
private

Get the user node number from a model for the provided solution node number.

Parameters
[in,out]thisNumericalSolutionType instance
[in]nodeslnsolution node number
[in,out]imsolution model index (index in model list for this solution)
[in,out]nodeuuser node number

Definition at line 3328 of file NumericalSolution.f90.

3329  ! -- dummy variables
3330  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
3331  integer(I4B), intent(in) :: nodesln !< solution node number
3332  integer(I4B), intent(inout) :: im !< solution model index (index in model list for this solution)
3333  integer(I4B), intent(inout) :: nodeu !< user node number
3334  ! -- local variables
3335  class(NumericalModelType), pointer :: mp => null()
3336  integer(I4B) :: i
3337  integer(I4B) :: istart
3338  integer(I4B) :: iend
3339  integer(I4B) :: noder, nglo
3340  !
3341  ! -- initialize local variables
3342  noder = 0
3343  !
3344  ! -- when parallel, account for offset
3345  nglo = nodesln + this%matrix_offset
3346  !
3347  ! -- calculate and set offsets
3348  do i = 1, this%modellist%Count()
3349  mp => getnumericalmodelfromlist(this%modellist, i)
3350  istart = 0
3351  iend = 0
3352  call mp%get_mrange(istart, iend)
3353  if (nglo >= istart .and. nglo <= iend) then
3354  noder = nglo - istart + 1
3355  call mp%get_mnodeu(noder, nodeu)
3356  im = i
3357  exit
3358  end if
3359  end do
Here is the call graph for this function:

◆ sln_has_converged()

logical(lgp) function numericalsolutionmodule::sln_has_converged ( class(numericalsolutiontype this,
real(dp)  max_dvc 
)
private
Parameters
thisNumericalSolutionType instance
max_dvcthe maximum dependent variable change
Returns
True, when converged

Definition at line 3218 of file NumericalSolution.f90.

3219  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3220  real(DP) :: max_dvc !< the maximum dependent variable change
3221  logical(LGP) :: has_converged !< True, when converged
3222 
3223  has_converged = .false.
3224  if (abs(max_dvc) <= this%dvclose) then
3225  has_converged = .true.
3226  end if
3227 

◆ sln_l2norm()

subroutine numericalsolutionmodule::sln_l2norm ( class(numericalsolutiontype this,
real(dp)  l2norm 
)
private

A = the linear system matrix x = the dependent variable vector b = the right-hand side vector

 r = A * x - b

r_i = 0 if cell i is inactive L2norm = || r ||_2

Parameters
thisNumericalSolutionType instance
l2normcalculated L-2 norm

Definition at line 2918 of file NumericalSolution.f90.

2919  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2920  real(DP) :: l2norm !< calculated L-2 norm
2921  ! local
2922  class(VectorBaseType), pointer :: vec_resid
2923 
2924  ! calc. residual vector
2925  vec_resid => this%system_matrix%create_vec(this%neq)
2926  call this%sln_calc_residual(vec_resid)
2927 
2928  ! 2-norm
2929  l2norm = vec_resid%norm2()
2930 
2931  ! clean up temp. vector
2932  call vec_resid%destroy()
2933  deallocate (vec_resid)

◆ sln_ls()

subroutine numericalsolutionmodule::sln_ls ( class(numericalsolutiontype), intent(inout)  this,
integer(i4b), intent(in)  kiter,
integer(i4b), intent(in)  kstp,
integer(i4b), intent(in)  kper,
integer(i4b), intent(inout)  in_iter,
integer(i4b), intent(inout)  iptc,
real(dp), intent(in)  ptcf 
)
private

Solve the linear system of equations. Steps include (1) matrix cleanup, (2) add pseudo-transient continuation terms, and (3) residual reduction.

Parameters
[in,out]thisNumericalSolutionType instance

Definition at line 2444 of file NumericalSolution.f90.

2445  ! -- dummy variables
2446  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2447  integer(I4B), intent(in) :: kiter
2448  integer(I4B), intent(in) :: kstp
2449  integer(I4B), intent(in) :: kper
2450  integer(I4B), intent(inout) :: in_iter
2451  integer(I4B), intent(inout) :: iptc
2452  real(DP), intent(in) :: ptcf
2453  ! -- local variables
2454  logical(LGP) :: lsame
2455  integer(I4B) :: ieq
2456  integer(I4B) :: irow_glo
2457  integer(I4B) :: itestmat
2458  integer(I4B) :: ipos
2459  integer(I4B) :: icol_s
2460  integer(I4B) :: icol_e
2461  integer(I4B) :: jcol
2462  integer(I4B) :: iptct
2463  integer(I4B) :: iallowptc
2464  real(DP) :: adiag
2465  real(DP) :: diagval
2466  real(DP) :: l2norm
2467  real(DP) :: ptcval
2468  real(DP) :: bnorm
2469  character(len=50) :: fname
2470  character(len=*), parameter :: fmtfname = "('mf6mat_', i0, '_', i0, &
2471  &'_', i0, '_', i0, '.txt')"
2472  !
2473  ! -- take care of loose ends for all nodes before call to solver
2474  do ieq = 1, this%neq
2475  !
2476  ! -- get (global) cell id
2477  irow_glo = ieq + this%matrix_offset
2478  !
2479  ! -- store x in temporary location
2480  this%xtemp(ieq) = this%x(ieq)
2481  !
2482  ! -- make adjustments to the continuity equation for the node
2483  ! -- adjust small diagonal coefficient in an active cell
2484  if (this%active(ieq) > 0) then
2485  diagval = -done
2486  adiag = abs(this%system_matrix%get_diag_value(irow_glo))
2487  if (adiag < dem15) then
2488  call this%system_matrix%set_diag_value(irow_glo, diagval)
2489  this%rhs(ieq) = this%rhs(ieq) + diagval * this%x(ieq)
2490  end if
2491  ! -- Dirichlet boundary or no-flow cell
2492  else
2493  call this%system_matrix%set_diag_value(irow_glo, done)
2494  call this%system_matrix%zero_row_offdiag(irow_glo)
2495  this%rhs(ieq) = this%x(ieq)
2496  end if
2497  end do
2498  !
2499  ! -- complete adjustments for Dirichlet boundaries for a symmetric matrix
2500  if (this%isymmetric == 1 .and. simulation_mode == "SEQUENTIAL") then
2501  do ieq = 1, this%neq
2502  if (this%active(ieq) > 0) then
2503  icol_s = this%system_matrix%get_first_col_pos(ieq)
2504  icol_e = this%system_matrix%get_last_col_pos(ieq)
2505  do ipos = icol_s, icol_e
2506  jcol = this%system_matrix%get_column(ipos)
2507  if (jcol == ieq) cycle
2508  if (this%active(jcol) < 0) then
2509  this%rhs(ieq) = this%rhs(ieq) - &
2510  (this%system_matrix%get_value_pos(ipos) * &
2511  this%x(jcol))
2512  call this%system_matrix%set_value_pos(ipos, dzero)
2513  end if
2514 
2515  end do
2516  end if
2517  end do
2518  end if
2519  !
2520  ! -- pseudo transient continuation
2521  !
2522  ! -- set iallowptc
2523  ! -- no_ptc_option is FIRST
2524  if (this%iallowptc < 0) then
2525  if (kper > 1) then
2526  iallowptc = 1
2527  else
2528  iallowptc = 0
2529  end if
2530  !
2531  ! -- no_ptc_option is ALL (0) or using PTC (1)
2532  else
2533  iallowptc = this%iallowptc
2534  end if
2535  !
2536  ! -- set iptct
2537  iptct = iptc * iallowptc
2538  !
2539  ! -- calculate or modify pseudo transient continuation terms and add
2540  ! to amat diagonals
2541  if (iptct /= 0) then
2542  call this%sln_l2norm(l2norm)
2543  ! -- confirm that the l2norm exceeds previous l2norm
2544  ! if not, there is no need to add ptc terms
2545  if (kiter == 1) then
2546  if (kper > 1 .or. kstp > 1) then
2547  if (l2norm <= this%l2norm0) then
2548  iptc = 0
2549  end if
2550  end if
2551  else
2552  lsame = is_close(l2norm, this%l2norm0)
2553  if (lsame) then
2554  iptc = 0
2555  end if
2556  end if
2557  end if
2558  iptct = iptc * iallowptc
2559  if (iptct /= 0) then
2560  if (kiter == 1) then
2561  if (this%iptcout > 0) then
2562  write (this%iptcout, '(A10,6(1x,A15))') 'OUTER ITER', &
2563  ' PTCDEL', ' L2NORM0', ' L2NORM', &
2564  ' RHSNORM', ' 1/PTCDEL', ' RHSNORM/L2NORM'
2565  end if
2566  if (this%ptcdel0 > dzero) then
2567  this%ptcdel = this%ptcdel0
2568  else
2569  if (this%iptcopt == 0) then
2570  !
2571  ! -- ptcf is the reciprocal of the pseudo-time step
2572  this%ptcdel = done / ptcf
2573  else
2574  bnorm = dzero
2575  do ieq = 1, this%neq
2576  if (this%active(ieq) .gt. 0) then
2577  bnorm = bnorm + this%rhs(ieq) * this%rhs(ieq)
2578  end if
2579  end do
2580  bnorm = sqrt(bnorm)
2581  this%ptcdel = bnorm / l2norm
2582  end if
2583  end if
2584  else
2585  if (l2norm > dzero) then
2586  this%ptcdel = this%ptcdel * (this%l2norm0 / l2norm)**this%ptcexp
2587  else
2588  this%ptcdel = dzero
2589  end if
2590  end if
2591  if (this%ptcdel > dzero) then
2592  ptcval = done / this%ptcdel
2593  else
2594  ptcval = done
2595  end if
2596  bnorm = dzero
2597  do ieq = 1, this%neq
2598  irow_glo = ieq + this%matrix_offset
2599  if (this%active(ieq) > 0) then
2600  diagval = abs(this%system_matrix%get_diag_value(irow_glo))
2601  bnorm = bnorm + this%rhs(ieq) * this%rhs(ieq)
2602  call this%system_matrix%add_diag_value(irow_glo, -ptcval)
2603  this%rhs(ieq) = this%rhs(ieq) - ptcval * this%x(ieq)
2604  end if
2605  end do
2606  bnorm = sqrt(bnorm)
2607  if (this%iptcout > 0) then
2608  write (this%iptcout, '(i10,5(1x,e15.7),1(1x,f15.6))') &
2609  kiter, this%ptcdel, this%l2norm0, l2norm, bnorm, &
2610  ptcval, bnorm / l2norm
2611  end if
2612  this%l2norm0 = l2norm
2613  end if
2614  !
2615  ! -- save rhs, amat to a file
2616  ! to enable set itestmat to 1 and recompile
2617  !-------------------------------------------------------
2618  itestmat = 0
2619  if (itestmat == 1) then
2620  write (fname, fmtfname) this%id, kper, kstp, kiter
2621  print *, 'Saving amat to: ', trim(adjustl(fname))
2622 
2623  itestmat = getunit()
2624  open (itestmat, file=trim(adjustl(fname)))
2625  write (itestmat, *) 'NODE, RHS, AMAT FOLLOW'
2626  do ieq = 1, this%neq
2627  irow_glo = ieq + this%matrix_offset
2628  icol_s = this%system_matrix%get_first_col_pos(irow_glo)
2629  icol_e = this%system_matrix%get_last_col_pos(irow_glo)
2630  write (itestmat, '(*(G0,:,","))') &
2631  irow_glo, &
2632  this%rhs(ieq), &
2633  (this%system_matrix%get_column(ipos), ipos=icol_s, icol_e), &
2634  (this%system_matrix%get_value_pos(ipos), ipos=icol_s, icol_e)
2635  end do
2636  close (itestmat)
2637  !stop
2638  end if
2639  !-------------------------------------------------------
2640  !
2641  ! -- call appropriate linear solver
2642  !
2643  ! -- ims linear solver - linmeth option 1
2644  if (this%linsolver == ims_solver) then
2645  call this%imslinear%imslinear_apply(this%icnvg, kstp, kiter, in_iter, &
2646  this%nitermax, this%convnmod, &
2647  this%convmodstart, this%caccel, &
2648  this%cnvg_summary)
2649  else if (this%linsolver == petsc_solver) then
2650  call this%linear_solver%solve(kiter, this%vec_rhs, &
2651  this%vec_x, this%cnvg_summary)
2652  in_iter = this%linear_solver%iteration_number
2653  this%icnvg = this%linear_solver%is_converged
2654  end if
Here is the call graph for this function:

◆ sln_maxval()

subroutine numericalsolutionmodule::sln_maxval ( class(numericalsolutiontype this,
integer(i4b), intent(in)  nsize,
real(dp), dimension(nsize), intent(in)  v,
real(dp), intent(inout)  vmax 
)
private

Return the maximum value in a vector using a normalized form.

Parameters
thisNumericalSolutionType instance
[in]nsizelength of vector
[in]vinput vector
[in,out]vmaxmaximum value

Definition at line 2941 of file NumericalSolution.f90.

2942  ! -- dummy variables
2943  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2944  integer(I4B), intent(in) :: nsize !< length of vector
2945  real(DP), dimension(nsize), intent(in) :: v !< input vector
2946  real(DP), intent(inout) :: vmax !< maximum value
2947  ! -- local variables
2948  integer(I4B) :: n
2949  real(DP) :: d
2950  real(DP) :: denom
2951  real(DP) :: dnorm
2952  !
2953  ! -- determine maximum value
2954  vmax = v(1)
2955  do n = 2, nsize
2956  d = v(n)
2957  denom = abs(vmax)
2958  if (denom == dzero) then
2959  denom = dprec
2960  end if
2961  !
2962  ! -- calculate normalized value
2963  dnorm = abs(d) / denom
2964  if (dnorm > done) then
2965  vmax = d
2966  end if
2967  end do

◆ sln_nur_has_converged()

logical(lgp) function numericalsolutionmodule::sln_nur_has_converged ( class(numericalsolutiontype this,
real(dp), intent(in)  dxold_max,
real(dp), intent(in)  hncg 
)
private
Parameters
thisNumericalSolutionType instance
[in]dxold_maxthe maximum dependent variable change for unrelaxed cells
[in]hncglargest dep. var. change at end of Picard iteration
Returns
True, when converged

Definition at line 3268 of file NumericalSolution.f90.

3270  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3271  real(DP), intent(in) :: dxold_max !< the maximum dependent variable change for unrelaxed cells
3272  real(DP), intent(in) :: hncg !< largest dep. var. change at end of Picard iteration
3273  logical(LGP) :: has_converged !< True, when converged
3274 
3275  has_converged = .false.
3276  if (abs(dxold_max) <= this%dvclose .and. &
3277  abs(hncg) <= this%dvclose) then
3278  has_converged = .true.
3279  end if
3280 

◆ sln_ot()

subroutine numericalsolutionmodule::sln_ot ( class(numericalsolutiontype this)

Output solution data. Currently does nothing.

Parameters
thisNumericalSolutionType instance

Definition at line 1166 of file NumericalSolution.f90.

1167  ! -- dummy variables
1168  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1169  !
1170  ! -- Nothing to do here

◆ sln_package_convergence()

integer(i4b) function numericalsolutionmodule::sln_package_convergence ( class(numericalsolutiontype this,
real(dp), intent(in)  dpak,
character(len=lenpakloc), intent(in)  cpakout,
integer(i4b), intent(in)  iend 
)
private
Parameters
thisNumericalSolutionType instance
[in]dpakNewton Under-relaxation flag
[in]cpakoutstring with package that caused failure
[in]iendflag indicating if last inner iteration (iend=1)

Definition at line 3232 of file NumericalSolution.f90.

3233  ! dummy
3234  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3235  real(DP), intent(in) :: dpak !< Newton Under-relaxation flag
3236  character(len=LENPAKLOC), intent(in) :: cpakout !< string with package that caused failure
3237  integer(I4B), intent(in) :: iend !< flag indicating if last inner iteration (iend=1)
3238  ! local
3239  integer(I4B) :: ivalue
3240  ivalue = 1
3241  if (abs(dpak) > this%dvclose) then
3242  ivalue = 0
3243  ! -- write message to stdout
3244  if (iend /= 0) then
3245  write (errmsg, '(3a)') &
3246  'PACKAGE (', trim(cpakout), ') CAUSED CONVERGENCE FAILURE'
3247  call write_message(errmsg)
3248  end if
3249  end if
3250 
Here is the call graph for this function:

◆ sln_reset()

subroutine numericalsolutionmodule::sln_reset ( class(numericalsolutiontype this)

Reset the solution by setting the coefficient matrix and right-hand side vectors to zero.

Parameters
thisNumericalSolutionType instance

Definition at line 2429 of file NumericalSolution.f90.

2430  ! -- dummy variables
2431  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2432  !
2433  ! -- reset the solution
2434  call this%system_matrix%zero_entries()
2435  call this%vec_rhs%zero_entries()

◆ sln_setouter()

subroutine numericalsolutionmodule::sln_setouter ( class(numericalsolutiontype), intent(inout)  this,
integer(i4b), intent(in)  ifdparam 
)
private

Set default Picard iteration variables based on passed complexity option.

Parameters
[in,out]thisNumericalSolutionType instance
[in]ifdparamcomplexity option (1) simple (2) moderate (3) complex

Definition at line 2663 of file NumericalSolution.f90.

2664  ! -- dummy variables
2665  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2666  integer(I4B), intent(in) :: ifdparam !< complexity option (1) simple (2) moderate (3) complex
2667  !
2668  ! -- simple option
2669  select case (ifdparam)
2670  case (1)
2671  this%dvclose = dem3
2672  this%mxiter = 25
2673  this%nonmeth = 0
2674  this%theta = done
2675  this%akappa = dzero
2676  this%gamma = done
2677  this%amomentum = dzero
2678  this%numtrack = 0
2679  this%btol = dzero
2680  this%breduc = dzero
2681  this%res_lim = dzero
2682  !
2683  ! -- moderate
2684  case (2)
2685  this%dvclose = dem2
2686  this%mxiter = 50
2687  this%nonmeth = 3
2688  this%theta = 0.9d0
2689  this%akappa = 0.0001d0
2690  this%gamma = dzero
2691  this%amomentum = dzero
2692  this%numtrack = 0
2693  this%btol = dzero
2694  this%breduc = dzero
2695  this%res_lim = dzero
2696  !
2697  ! -- complex
2698  case (3)
2699  this%dvclose = dem1
2700  this%mxiter = 100
2701  this%nonmeth = 3
2702  this%theta = 0.8d0
2703  this%akappa = 0.0001d0
2704  this%gamma = dzero
2705  this%amomentum = dzero
2706  this%numtrack = 20
2707  this%btol = 1.05d0
2708  this%breduc = 0.1d0
2709  this%res_lim = 0.002d0
2710  end select

◆ sln_sync_newtonur_flag()

integer(i4b) function numericalsolutionmodule::sln_sync_newtonur_flag ( class(numericalsolutiontype this,
integer(i4b), intent(in)  inewtonur 
)
private
Parameters
thisNumericalSolutionType instance
[in]inewtonurNewton Under-relaxation flag
Returns
Default is set to current value (1 = under-relaxation applied)

Definition at line 3255 of file NumericalSolution.f90.

3256  ! dummy
3257  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3258  integer(I4B), intent(in) :: inewtonur !< Newton Under-relaxation flag
3259  ! local
3260  integer(I4B) :: ivalue !< Default is set to current value (1 = under-relaxation applied)
3261 
3262  ivalue = inewtonur
3263 

◆ sln_underrelax()

subroutine numericalsolutionmodule::sln_underrelax ( class(numericalsolutiontype this,
integer(i4b), intent(in)  kiter,
real(dp), intent(in)  bigch,
integer(i4b), intent(in)  neq,
integer(i4b), dimension(neq), intent(in)  active,
real(dp), dimension(neq), intent(inout)  x,
real(dp), dimension(neq), intent(in)  xtemp 
)
private

Under relax using the simple, cooley, or delta-bar-delta methods.

Parameters
thisNumericalSolutionType instance
[in]kiterPicard iteration number
[in]bigchmaximum dependent-variable change
[in]neqnumber of equations
[in]activeactive cell flag (1)
[in,out]xcurrent dependent-variable
[in]xtempprevious dependent-variable

Definition at line 3052 of file NumericalSolution.f90.

3053  ! -- dummy variables
3054  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3055  integer(I4B), intent(in) :: kiter !< Picard iteration number
3056  real(DP), intent(in) :: bigch !< maximum dependent-variable change
3057  integer(I4B), intent(in) :: neq !< number of equations
3058  integer(I4B), dimension(neq), intent(in) :: active !< active cell flag (1)
3059  real(DP), dimension(neq), intent(inout) :: x !< current dependent-variable
3060  real(DP), dimension(neq), intent(in) :: xtemp !< previous dependent-variable
3061  ! -- local variables
3062  integer(I4B) :: n
3063  real(DP) :: ww
3064  real(DP) :: delx
3065  real(DP) :: relax
3066  real(DP) :: es
3067  real(DP) :: aes
3068  real(DP) :: amom
3069  !
3070  ! -- option for using simple dampening (as done by MODFLOW-2005 PCG)
3071  if (this%nonmeth == 1) then
3072  do n = 1, neq
3073  !
3074  ! -- skip inactive nodes
3075  if (active(n) < 1) cycle
3076  !
3077  ! -- compute step-size (delta x)
3078  delx = x(n) - xtemp(n)
3079  this%dxold(n) = delx
3080 
3081  ! -- dampen dependent variable solution
3082  x(n) = xtemp(n) + this%gamma * delx
3083  end do
3084  !
3085  ! -- option for using cooley underrelaxation
3086  else if (this%nonmeth == 2) then
3087  !
3088  ! -- set bigch
3089  this%bigch = bigch
3090  !
3091  ! -- initialize values for first iteration
3092  if (kiter == 1) then
3093  relax = done
3094  this%relaxold = done
3095  this%bigchold = bigch
3096  else
3097  !
3098  ! -- compute relaxation factor
3099  es = this%bigch / (this%bigchold * this%relaxold)
3100  aes = abs(es)
3101  if (es < -done) then
3102  relax = dhalf / aes
3103  else
3104  relax = (dthree + es) / (dthree + aes)
3105  end if
3106  end if
3107  this%relaxold = relax
3108  !
3109  ! -- modify cooley to use weighted average of past changes
3110  this%bigchold = (done - this%gamma) * this%bigch + this%gamma * &
3111  this%bigchold
3112  !
3113  ! -- compute new dependent variable after under-relaxation
3114  if (relax < done) then
3115  do n = 1, neq
3116  !
3117  ! -- skip inactive nodes
3118  if (active(n) < 1) cycle
3119  !
3120  ! -- update dependent variable
3121  delx = x(n) - xtemp(n)
3122  this%dxold(n) = delx
3123  x(n) = xtemp(n) + relax * delx
3124  end do
3125  end if
3126  !
3127  ! -- option for using delta-bar-delta scheme to under-relax for all equations
3128  else if (this%nonmeth == 3) then
3129  do n = 1, neq
3130  !
3131  ! -- skip inactive nodes
3132  if (active(n) < 1) cycle
3133  !
3134  ! -- compute step-size (delta x) and initialize d-b-d parameters
3135  delx = x(n) - xtemp(n)
3136  !
3137  ! -- initialize values for first iteration
3138  if (kiter == 1) then
3139  this%wsave(n) = done
3140  this%hchold(n) = dem20
3141  this%deold(n) = dzero
3142  end if
3143  !
3144  ! -- compute new relaxation term as per delta-bar-delta
3145  ww = this%wsave(n)
3146  !
3147  ! for flip-flop condition, decrease factor
3148  if (this%deold(n) * delx < dzero) then
3149  ww = this%theta * this%wsave(n)
3150  ! -- when change is of same sign, increase factor
3151  else
3152  ww = this%wsave(n) + this%akappa
3153  end if
3154  if (ww > done) ww = done
3155  this%wsave(n) = ww
3156  !
3157  ! -- compute weighted average of past changes in hchold
3158  if (kiter == 1) then
3159  this%hchold(n) = delx
3160  else
3161  this%hchold(n) = (done - this%gamma) * delx + &
3162  this%gamma * this%hchold(n)
3163  end if
3164  !
3165  ! -- store slope (change) term for next iteration
3166  this%deold(n) = delx
3167  this%dxold(n) = delx
3168  !
3169  ! -- compute accepted step-size and new dependent variable
3170  amom = dzero
3171  if (kiter > 4) amom = this%amomentum
3172  delx = delx * ww + amom * this%hchold(n)
3173  x(n) = xtemp(n) + delx
3174  end do
3175  !
3176  end if

◆ solve()

subroutine numericalsolutionmodule::solve ( class(numericalsolutiontype this,
integer(i4b), intent(in)  kiter,
integer(i4b), intent(in)  isuppress_output 
)
private

Builds and solve the system for this numerical solution. It roughly consists of the following steps (1) backtracking, (2) reset amat and rhs (3) calculate matrix terms (*_cf), (4) add coefficients to matrix (*_fc), (6) newton-raphson, (6) PTC, (7) linear solve, (8) convergence checks, (9) write output, and (10) underrelaxation

Parameters
thisNumericalSolutionType instance
[in]kiterPicard iteration number
[in]isuppress_outputflag for suppressing output

Definition at line 1513 of file NumericalSolution.f90.

1514  ! -- modules
1515  use tdismodule, only: kstp, kper, totim
1516  ! -- dummy variables
1517  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1518  integer(I4B), intent(in) :: kiter !< Picard iteration number
1519  integer(I4B), intent(in) :: isuppress_output !< flag for suppressing output
1520  ! -- local variables
1521  class(NumericalModelType), pointer :: mp => null()
1522  class(NumericalExchangeType), pointer :: cp => null()
1523  character(len=LINELENGTH) :: title
1524  character(len=LINELENGTH) :: tag
1525  character(len=LENPAKLOC) :: cmod
1526  character(len=LENPAKLOC) :: cpak
1527  character(len=LENPAKLOC) :: cpakout
1528  character(len=LENPAKLOC) :: strh
1529  character(len=25) :: cval
1530  character(len=7) :: cmsg
1531  integer(I4B) :: ic
1532  integer(I4B) :: im, m_idx, model_id
1533  integer(I4B) :: icsv0
1534  integer(I4B) :: kcsv0
1535  integer(I4B) :: ntabrows
1536  integer(I4B) :: ntabcols
1537  integer(I4B) :: i0, i1
1538  integer(I4B) :: itestmat, n
1539  integer(I4B) :: iter
1540  integer(I4B) :: inewtonur
1541  integer(I4B) :: locmax_nur
1542  integer(I4B) :: iend
1543  integer(I4B) :: icnvgmod
1544  integer(I4B) :: iptc
1545  integer(I4B) :: node_user
1546  integer(I4B) :: ipak
1547  integer(I4B) :: ipos0
1548  integer(I4B) :: ipos1
1549  real(DP) :: dxmax_nur
1550  real(DP) :: dxold_max
1551  real(DP) :: ptcf
1552  real(DP) :: ttform
1553  real(DP) :: ttsoln
1554  real(DP) :: dpak
1555  real(DP) :: outer_hncg
1556 
1557  ! start timer
1558  call g_prof%start("Solve"//this%id_postfix, this%tmr_solve)
1559 
1560  !
1561  ! -- initialize local variables
1562  icsv0 = max(1, this%itertot_sim + 1)
1563  kcsv0 = max(1, this%itertot_timestep + 1)
1564  !
1565  ! -- create header for outer iteration table
1566  if (this%iprims > 0) then
1567  if (.not. associated(this%outertab)) then
1568  !
1569  ! -- create outer iteration table
1570  ! -- table dimensions
1571  ntabrows = 1
1572  ntabcols = 6
1573  if (this%numtrack > 0) then
1574  ntabcols = ntabcols + 4
1575  end if
1576  !
1577  ! -- initialize table and define columns
1578  title = trim(this%memory_path)//' OUTER ITERATION SUMMARY'
1579  call table_cr(this%outertab, this%name, title)
1580  call this%outertab%table_df(ntabrows, ntabcols, iout, &
1581  finalize=.false.)
1582  tag = 'OUTER ITERATION STEP'
1583  call this%outertab%initialize_column(tag, 25, alignment=tableft)
1584  tag = 'OUTER ITERATION'
1585  call this%outertab%initialize_column(tag, 10, alignment=tabright)
1586  tag = 'INNER ITERATION'
1587  call this%outertab%initialize_column(tag, 10, alignment=tabright)
1588  if (this%numtrack > 0) then
1589  tag = 'BACKTRACK FLAG'
1590  call this%outertab%initialize_column(tag, 10, alignment=tabright)
1591  tag = 'BACKTRACK ITERATIONS'
1592  call this%outertab%initialize_column(tag, 10, alignment=tabright)
1593  tag = 'INCOMING RESIDUAL'
1594  call this%outertab%initialize_column(tag, 15, alignment=tabright)
1595  tag = 'OUTGOING RESIDUAL'
1596  call this%outertab%initialize_column(tag, 15, alignment=tabright)
1597  end if
1598  tag = 'MAXIMUM CHANGE'
1599  call this%outertab%initialize_column(tag, 15, alignment=tabright)
1600  tag = 'STEP SUCCESS'
1601  call this%outertab%initialize_column(tag, 7, alignment=tabright)
1602  tag = 'MAXIMUM CHANGE MODEL-(CELLID) OR MODEL-PACKAGE-(NUMBER)'
1603  call this%outertab%initialize_column(tag, 34, alignment=tabright)
1604  end if
1605  end if
1606  !
1607  ! -- backtracking
1608  if (this%numtrack > 0) then
1609  call this%sln_backtracking(mp, cp, kiter)
1610  end if
1611  !
1612  call code_timer(0, ttform, this%ttform)
1613  call g_prof%start("Formulate", this%tmr_formulate)
1614  !
1615  ! -- (re)build the solution matrix
1616  call this%sln_buildsystem(kiter, inewton=1)
1617  !
1618  ! -- Calculate pseudo-transient continuation factor for each model
1619  call this%sln_calc_ptc(iptc, ptcf)
1620  !
1621  ! -- Add model Newton-Raphson terms to solution
1622  do im = 1, this%modellist%Count()
1623  mp => getnumericalmodelfromlist(this%modellist, im)
1624  call mp%model_nr(kiter, this%system_matrix, 1)
1625  end do
1626  call code_timer(1, ttform, this%ttform)
1627  call g_prof%stop(this%tmr_formulate)
1628 
1629  ! x and rhs scaling
1630  if (this%idv_scale /= 0) then
1631  call this%sln_maxval(this%neq, this%x, this%dscale)
1632  call ims_misc_dvscale(0, this%neq, this%dscale, this%x, this%rhs)
1633  end if
1634  !
1635  ! -- linear solve
1636  call code_timer(0, ttsoln, this%ttsoln)
1637  call g_prof%start("Linear solve", this%tmr_linsolve)
1638  call this%sln_ls(kiter, kstp, kper, iter, iptc, ptcf)
1639  call g_prof%stop(this%tmr_linsolve)
1640  call code_timer(1, ttsoln, this%ttsoln)
1641  !
1642  ! -- increment counters storing the total number of linear and
1643  ! non-linear iterations for this timestep and the total
1644  ! number of linear iterations for all timesteps
1645  this%itertot_timestep = this%itertot_timestep + iter
1646  this%iouttot_timestep = this%iouttot_timestep + 1
1647  this%itertot_sim = this%itertot_sim + iter
1648  !
1649  ! -- save matrix to a file
1650  ! to enable set itestmat to 1 and recompile
1651  !-------------------------------------------------------
1652  itestmat = 0
1653  if (itestmat /= 0) then
1654  open (99, file='sol_MF6.TXT')
1655  WRITE (99, *) 'MATRIX SOLUTION FOLLOWS'
1656  WRITE (99, '(10(I8,G15.4))') (n, this%x(n), n=1, this%NEQ)
1657  close (99)
1658  call pstop()
1659  end if
1660  !-------------------------------------------------------
1661  !
1662  ! -- check convergence of solution
1663  call this%sln_get_dxmax(this%hncg(kiter), this%lrch(1, kiter))
1664  if (this%icnvg /= 0) then
1665  this%icnvg = 0
1666  if (this%sln_has_converged(this%hncg(kiter))) then
1667  this%icnvg = 1
1668  end if
1669  end if
1670  !
1671  ! -- set failure flag
1672  if (this%icnvg == 0) then
1673  cmsg = ' '
1674  else
1675  cmsg = '*'
1676  end if
1677  !
1678  ! -- set flag if this is the last outer iteration
1679  iend = 0
1680  if (kiter == this%mxiter) then
1681  iend = 1
1682  end if
1683  !
1684  ! -- write maximum dependent-variable change from linear solver to list file
1685  if (this%iprims > 0) then
1686  cval = 'Model'
1687  call this%sln_get_loc(this%lrch(1, kiter), strh)
1688  !
1689  ! -- add data to outertab
1690  call this%outertab%add_term(cval)
1691  call this%outertab%add_term(kiter)
1692  call this%outertab%add_term(iter)
1693  if (this%numtrack > 0) then
1694  call this%outertab%add_term(' ')
1695  call this%outertab%add_term(' ')
1696  call this%outertab%add_term(' ')
1697  call this%outertab%add_term(' ')
1698  end if
1699  call this%outertab%add_term(this%hncg(kiter))
1700  call this%outertab%add_term(cmsg)
1701  call this%outertab%add_term(trim(strh))
1702  end if
1703  !
1704  ! -- Additional convergence check for exchanges
1705  do ic = 1, this%exchangelist%Count()
1706  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1707  call cp%exg_cc(this%icnvg)
1708  end do
1709  !
1710  ! -- additional convergence check for model packages
1711  icnvgmod = this%icnvg
1712  cpak = ' '
1713  ipak = 0
1714  dpak = dzero
1715  do im = 1, this%modellist%Count()
1716  mp => getnumericalmodelfromlist(this%modellist, im)
1717  call mp%get_mcellid(0, cmod)
1718  call mp%model_cc(this%itertot_sim, kiter, iend, icnvgmod, &
1719  cpak, ipak, dpak)
1720  if (ipak /= 0) then
1721  ipos0 = index(cpak, '-', back=.true.)
1722  ipos1 = len_trim(cpak)
1723  write (cpakout, '(a,a,"-(",i0,")",a)') &
1724  trim(cmod), cpak(1:ipos0 - 1), ipak, cpak(ipos0:ipos1)
1725  else
1726  cpakout = ' '
1727  end if
1728  end do
1729  !
1730  ! -- evaluate package convergence - only done if convergence is achieved
1731  if (this%icnvg == 1) then
1732  this%icnvg = this%sln_package_convergence(dpak, cpakout, iend)
1733  !
1734  ! -- write maximum change in package convergence check
1735  if (this%iprims > 0) then
1736  cval = 'Package'
1737  if (this%icnvg /= 1) then
1738  cmsg = ' '
1739  else
1740  cmsg = '*'
1741  end if
1742  if (len_trim(cpakout) > 0) then
1743  !
1744  ! -- add data to outertab
1745  call this%outertab%add_term(cval)
1746  call this%outertab%add_term(kiter)
1747  call this%outertab%add_term(' ')
1748  if (this%numtrack > 0) then
1749  call this%outertab%add_term(' ')
1750  call this%outertab%add_term(' ')
1751  call this%outertab%add_term(' ')
1752  call this%outertab%add_term(' ')
1753  end if
1754  call this%outertab%add_term(dpak)
1755  call this%outertab%add_term(cmsg)
1756  call this%outertab%add_term(cpakout)
1757  end if
1758  end if
1759  end if
1760  !
1761  ! -- under-relaxation - only done if convergence not achieved
1762  if (this%icnvg /= 1) then
1763  if (this%nonmeth > 0) then
1764  call this%sln_underrelax(kiter, this%hncg(kiter), this%neq, &
1765  this%active, this%x, this%xtemp)
1766  else
1767  call this%sln_calcdx(this%neq, this%active, &
1768  this%x, this%xtemp, this%dxold)
1769  end if
1770  !
1771  ! -- adjust heads by newton under-relaxation, if necessary
1772  inewtonur = 0
1773  dxmax_nur = dzero
1774  locmax_nur = 0
1775  do im = 1, this%modellist%Count()
1776  mp => getnumericalmodelfromlist(this%modellist, im)
1777  i0 = mp%moffset + 1 - this%matrix_offset
1778  i1 = i0 + mp%neq - 1
1779  call mp%model_nur(mp%neq, this%x(i0:i1), this%xtemp(i0:i1), &
1780  this%dxold(i0:i1), inewtonur, dxmax_nur, locmax_nur)
1781  end do
1782  !
1783  ! -- synchronize Newton Under-relaxation flag
1784  inewtonur = this%sln_sync_newtonur_flag(inewtonur)
1785  !
1786  ! -- check for convergence if newton under-relaxation applied
1787  if (inewtonur /= 0) then
1788  !
1789  ! -- calculate maximum change in heads in cells that have
1790  ! not been adjusted by newton under-relxation
1791  call this%sln_maxval(this%neq, this%dxold, dxold_max)
1792  !
1793  ! -- evaluate convergence
1794  if (this%sln_nur_has_converged(dxold_max, this%hncg(kiter))) then
1795  !
1796  ! -- converged
1797  this%icnvg = 1
1798  !
1799  ! -- reset outer dependent-variable change and location for output
1800  call this%sln_get_dxmax(this%hncg(kiter), this%lrch(1, kiter))
1801  !
1802  ! -- write revised dependent-variable change data after
1803  ! newton under-relaxation
1804  if (this%iprims > 0) then
1805  cval = 'Newton under-relaxation'
1806  cmsg = '*'
1807  call this%sln_get_loc(this%lrch(1, kiter), strh)
1808  !
1809  ! -- add data to outertab
1810  call this%outertab%add_term(cval)
1811  call this%outertab%add_term(kiter)
1812  call this%outertab%add_term(iter)
1813  if (this%numtrack > 0) then
1814  call this%outertab%add_term(' ')
1815  call this%outertab%add_term(' ')
1816  call this%outertab%add_term(' ')
1817  call this%outertab%add_term(' ')
1818  end if
1819  call this%outertab%add_term(this%hncg(kiter))
1820  call this%outertab%add_term(cmsg)
1821  call this%outertab%add_term(trim(strh))
1822  end if
1823  end if
1824  end if
1825  end if
1826  !
1827  ! -- write to outer iteration csv file
1828  if (this%icsvouterout > 0) then
1829  !
1830  ! -- set outer dependent-variable change variable
1831  outer_hncg = this%hncg(kiter)
1832  !
1833  ! -- model convergence error
1834  if (abs(outer_hncg) > abs(dpak)) then
1835  !
1836  ! -- get model number and user node number
1837  call this%sln_get_nodeu(this%lrch(1, kiter), m_idx, node_user)
1838  mp => getnumericalmodelfromlist(this%modellist, m_idx)
1839  model_id = mp%id
1840  cpakout = ''
1841  else if (outer_hncg == dzero .and. dpak == dzero) then ! zero change, location could be any
1842  model_id = 0
1843  node_user = 0
1844  !
1845  ! -- then it's a package convergence error
1846  else
1847  !
1848  ! -- set convergence error, model number, user node number,
1849  ! and package name
1850  outer_hncg = dpak
1851  ipos0 = index(cmod, '_')
1852  read (cmod(1:ipos0 - 1), *) model_id
1853  node_user = ipak
1854  ipos0 = index(cpak, '-', back=.true.)
1855  cpakout = cpak(1:ipos0 - 1)
1856  end if
1857 
1858  write (this%icsvouterout, '(*(G0,:,","))') &
1859  this%itertot_sim, totim, kper, kstp, kiter, iter, &
1860  outer_hncg, model_id, trim(cpakout), node_user
1861  end if
1862  !
1863  ! -- write to inner iteration csv file
1864  if (this%icsvinnerout > 0) then
1865  call this%csv_convergence_summary(this%icsvinnerout, totim, kper, kstp, &
1866  kiter, iter, icsv0, kcsv0)
1867  end if
1868 
1869  ! undo x and rhs scaling
1870  if (this%idv_scale /= 0) then
1871  call ims_misc_dvscale(1, this%neq, this%dscale, this%x, this%rhs)
1872  end if
1873 
1874  ! stop timer
1875  call g_prof%stop(this%tmr_solve)
1876 
real(dp), pointer, public totim
time relative to start of simulation
Definition: tdis.f90:35
Here is the call graph for this function:

◆ writecsvheader()

subroutine numericalsolutionmodule::writecsvheader ( class(numericalsolutiontype this)
private

Write header for solver output to comma-separated value files.

Parameters
thisNumericalSolutionType instance

Definition at line 1365 of file NumericalSolution.f90.

1366  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1367  ! local variables
1368  integer(I4B) :: im
1369  class(NumericalModelType), pointer :: mp => null()
1370  !
1371  ! -- outer iteration csv header
1372  if (this%icsvouterout > 0) then
1373  write (this%icsvouterout, '(*(G0,:,","))') &
1374  'total_inner_iterations', 'totim', 'kper', 'kstp', 'nouter', &
1375  'inner_iterations', 'solution_outer_dvmax', &
1376  'solution_outer_dvmax_model', 'solution_outer_dvmax_package', &
1377  'solution_outer_dvmax_node'
1378  end if
1379  !
1380  ! -- inner iteration csv header
1381  if (this%icsvinnerout > 0) then
1382  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1383  'total_inner_iterations', 'totim', 'kper', 'kstp', 'nouter', &
1384  'ninner', 'solution_inner_dvmax', 'solution_inner_dvmax_model', &
1385  'solution_inner_dvmax_node'
1386  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1387  '', 'solution_inner_rmax', 'solution_inner_rmax_model', &
1388  'solution_inner_rmax_node'
1389  ! solver items specific to ims solver
1390  if (this%linsolver == ims_solver) then
1391  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1392  '', 'solution_inner_alpha'
1393  if (this%imslinear%ilinmeth == 2) then
1394  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1395  '', 'solution_inner_omega'
1396  end if
1397  end if
1398  ! -- check for more than one model - ims only
1399  if (this%convnmod > 1 .or. simulation_mode == "PARALLEL") then
1400  do im = 1, this%modellist%Count()
1401  mp => getnumericalmodelfromlist(this%modellist, im)
1402  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1403  '', trim(adjustl(mp%name))//'_inner_dvmax', &
1404  trim(adjustl(mp%name))//'_inner_dvmax_node', &
1405  trim(adjustl(mp%name))//'_inner_rmax', &
1406  trim(adjustl(mp%name))//'_inner_rmax_node'
1407  end do
1408  end if
1409  write (this%icsvinnerout, '(a)') ''
1410  end if
Here is the call graph for this function:

◆ writeptcinfotofile()

subroutine numericalsolutionmodule::writeptcinfotofile ( class(numericalsolutiontype this,
integer(i4b), intent(in)  kper 
)
private

Write header for pseudo-transient continuation information to a file.

Parameters
thisNumericalSolutionType instance
[in]kpercurrent stress period number

Definition at line 1418 of file NumericalSolution.f90.

1419  ! -- dummy variables
1420  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1421  integer(I4B), intent(in) :: kper !< current stress period number
1422  ! -- local variable
1423  integer(I4B) :: n, im, iallowptc, iptc
1424  class(NumericalModelType), pointer :: mp => null()
1425 
1426  ! -- determine if PTC will be used in any model
1427  n = 1
1428  do im = 1, this%modellist%Count()
1429  !
1430  ! -- set iallowptc
1431  ! -- no_ptc_option is FIRST
1432  if (this%iallowptc < 0) then
1433  if (kper > 1) then
1434  iallowptc = 1
1435  else
1436  iallowptc = 0
1437  end if
1438  ! -- no_ptc_option is ALL (0) or using PTC (1)
1439  else
1440  iallowptc = this%iallowptc
1441  end if
1442 
1443  if (iallowptc > 0) then
1444  mp => getnumericalmodelfromlist(this%modellist, im)
1445  call mp%model_ptcchk(iptc)
1446  else
1447  iptc = 0
1448  end if
1449 
1450  if (iptc /= 0) then
1451  if (n == 1) then
1452  write (iout, '(//)')
1453  n = 0
1454  end if
1455  write (iout, '(1x,a,1x,i0,1x,3a)') &
1456  'PSEUDO-TRANSIENT CONTINUATION WILL BE APPLIED TO MODEL', im, '("', &
1457  trim(adjustl(mp%name)), '") DURING THIS TIME STEP'
1458  end if
1459  end do
1460 
Here is the call graph for this function:

Variable Documentation

◆ ims_solver

integer(i4b), parameter numericalsolutionmodule::ims_solver = 1
private

Definition at line 55 of file NumericalSolution.f90.

55  integer(I4B), parameter :: IMS_SOLVER = 1

◆ petsc_solver

integer(i4b), parameter numericalsolutionmodule::petsc_solver = 2
private

Definition at line 56 of file NumericalSolution.f90.

56  integer(I4B), parameter :: PETSC_SOLVER = 2