MODFLOW 6  version 6.7.0.dev2
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)
 @ 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 2340 of file NumericalSolution.f90.

2341  ! -- dummy variables
2342  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2343  class(BaseExchangeType), pointer, intent(in) :: exchange !< model exchange instance
2344  ! -- local variables
2345  class(NumericalExchangeType), pointer :: num_ex => null()
2346  !
2347  ! -- add exchange
2348  select type (exchange)
2349  class is (numericalexchangetype)
2350  num_ex => exchange
2351  call addnumericalexchangetolist(this%exchangelist, num_ex)
2352  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 2305 of file NumericalSolution.f90.

2306  ! -- dummy variables
2307  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2308  class(BaseModelType), pointer, intent(in) :: mp !< model instance
2309  ! -- local variables
2310  class(NumericalModelType), pointer :: m => null()
2311  !
2312  ! -- add a model
2313  select type (mp)
2314  class is (numericalmodeltype)
2315  m => mp
2316  call addnumericalmodeltolist(this%modellist, m)
2317  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 2891 of file NumericalSolution.f90.

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

◆ 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 3365 of file NumericalSolution.f90.

3366  ! -- dummy variables
3367  class(*), pointer, intent(inout) :: obj !< generic object
3368  ! -- return variable
3369  class(NumericalSolutionType), pointer :: res !< output NumericalSolutionType
3370  !
3371  ! -- initialize return variable
3372  res => null()
3373  !
3374  ! -- determine if obj is associated
3375  if (.not. associated(obj)) return
3376  !
3377  ! -- set res
3378  select type (obj)
3379  class is (numericalsolutiontype)
3380  res => obj
3381  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 2036 of file NumericalSolution.f90.

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

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

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

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

◆ 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 2357 of file NumericalSolution.f90.

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

◆ 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 2325 of file NumericalSolution.f90.

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

◆ 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 3389 of file NumericalSolution.f90.

3390  ! -- dummy variables
3391  type(ListType), intent(inout) :: list !< list of numerical solutions
3392  integer(I4B), intent(in) :: idx !< value to retrieve from the list
3393  ! -- return variables
3394  class(NumericalSolutionType), pointer :: res !< numerical solution
3395  ! -- local variables
3396  class(*), pointer :: obj
3397  !
3398  obj => list%GetItem(idx)
3399  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 1467 of file NumericalSolution.f90.

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

2273  use sparsematrixmodule
2274  ! -- modules
2275  use inputoutputmodule, only: getunit
2276  ! -- dummy variables
2277  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2278  character(len=*), intent(in) :: filename !< filename to save solution data
2279  ! -- local variables
2280  integer(I4B) :: inunit
2281  !
2282  select type (spm => this%system_matrix)
2283  class is (sparsematrixtype)
2284  inunit = getunit()
2285  open (unit=inunit, file=filename, status='unknown')
2286  write (inunit, *) 'ia'
2287  write (inunit, *) spm%ia
2288  write (inunit, *) 'ja'
2289  write (inunit, *) spm%ja
2290  write (inunit, *) 'amat'
2291  write (inunit, *) spm%amat
2292  write (inunit, *) 'rhs'
2293  write (inunit, *) this%rhs
2294  write (inunit, *) 'x'
2295  write (inunit, *) this%x
2296  close (inunit)
2297  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 1140 of file NumericalSolution.f90.

1141  ! -- modules
1142  use tdismodule, only: kstp, kper
1143  ! -- dummy variables
1144  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1145  !
1146  ! -- write headers to CSV file
1147  if (kper == 1 .and. kstp == 1) then
1148  call this%writeCSVHeader()
1149  end if
1150 
1151  ! write PTC info on models to iout
1152  call this%writePTCInfoToFile(kper)
1153 
1154  ! reset convergence flag and inner solve counter
1155  this%icnvg = 0
1156  this%itertot_timestep = 0
1157  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  !
924  if (this%linear_settings%ilinmeth == cg_method) then
925  this%isymmetric = 1
926  end if
927  !
928  ! -- call secondary subroutine to initialize and read linear
929  ! solver parameters IMSLINEAR solver
930  if (this%solver_mode == "IMS") then
931  allocate (this%imslinear)
932  WRITE (iout, *) '***IMS LINEAR SOLVER WILL BE USED***'
933  call this%imslinear%imslinear_allocate(this%name, iout, this%iprims, &
934  this%mxiter, this%neq, &
935  this%system_matrix, this%rhs, &
936  this%x, this%linear_settings)
937  !
938  ! -- petsc linear solver flag
939  else if (this%solver_mode == "PETSC") then
940  call this%linear_solver%initialize(this%system_matrix, &
941  this%linear_settings, &
942  this%cnvg_summary)
943  !
944  ! -- incorrect linear solver flag
945  else
946  write (errmsg, '(a)') &
947  'Incorrect value for linear solution method specified.'
948  call store_error(errmsg)
949  end if
950  !
951  ! -- write message about matrix symmetry
952  if (this%isymmetric == 1) then
953  write (iout, '(1x,a,/)') 'A symmetric matrix will be solved'
954  else
955  write (iout, '(1x,a,/)') 'An asymmetric matrix will be solved'
956  end if
957  !
958  ! -- If CG, then go through each model and each exchange and check
959  ! for asymmetry
960  if (this%isymmetric == 1) then
961  !
962  ! -- Models
963  do i = 1, this%modellist%Count()
964  mp => getnumericalmodelfromlist(this%modellist, i)
965  if (mp%get_iasym() /= 0) then
966  write (errmsg, fmterrasym) 'MODEL', trim(adjustl(mp%name))
967  call store_error(errmsg)
968  end if
969  end do
970  !
971  ! -- Exchanges
972  do i = 1, this%exchangelist%Count()
973  cp => getnumericalexchangefromlist(this%exchangelist, i)
974  if (cp%get_iasym() /= 0) then
975  write (errmsg, fmterrasym) 'EXCHANGE', trim(adjustl(cp%name))
976  call store_error(errmsg)
977  end if
978  end do
979  !
980  end if
981 
982  !
983  ! determine if the x and rhs should be scaled
984  this%idv_scale = this%sln_get_idvscale()
985 
986  if (this%idv_scale > 0) then
987  write (iout, '(2(1x,a,/),1x,a,/,6x,a,/)') &
988  'X and RHS will be scaled to avoid very large positive or negative', &
989  'dependent variable values in the model IMS package.', &
990  'NOTE: Specified outer and inner DVCLOSE values in the model IMS &
991  &package', 'will be relative closure criteria.'
992  else if (this%idv_scale < 0) then
993  write (errmsg, '(2(a,1x))') &
994  'dependent_variable_scaling must be specified for all models in', &
995  'the solution and can only be used with GWT and GWE models. '
996  call store_error(errmsg)
997  end if
998  !
999  !
1000  ! -- write solver data to output file
1001  !
1002  ! -- non-linear solver data
1003  WRITE (iout, 9002) this%dvclose, this%mxiter, &
1004  this%iprims, this%nonmeth, this%linsolver
1005  !
1006  ! -- standard outer iteration formats
1007 9002 FORMAT(1x, 'OUTER ITERATION CONVERGENCE CRITERION (DVCLOSE) = ', e15.6, &
1008  /1x, 'MAXIMUM NUMBER OF OUTER ITERATIONS (MXITER) = ', i0, &
1009  /1x, 'SOLVER PRINTOUT INDEX (IPRIMS) = ', i0, &
1010  /1x, 'NONLINEAR ITERATION METHOD (NONLINMETH) = ', i0, &
1011  /1x, 'LINEAR SOLUTION METHOD (LINMETH) = ', i0)
1012  !
1013  if (this%nonmeth == 1) then ! simple
1014  write (iout, 9003) this%gamma
1015  else if (this%nonmeth == 2) then ! cooley
1016  write (iout, 9004) this%gamma
1017  else if (this%nonmeth == 3) then ! delta bar delta
1018  write (iout, 9005) this%theta, this%akappa, this%gamma, this%amomentum
1019  end if
1020  !
1021  ! -- write backtracking information
1022  if (this%numtrack /= 0) write (iout, 9006) this%numtrack, this%btol, &
1023  this%breduc, this%res_lim
1024  !
1025  ! -- under-relaxation formats (simple, cooley, dbd)
1026 9003 FORMAT(1x, 'UNDER-RELAXATION FACTOR (GAMMA) = ', e15.6)
1027 9004 FORMAT(1x, 'UNDER-RELAXATION PREVIOUS HISTORY FACTOR (GAMMA) = ', e15.6)
1028 9005 FORMAT(1x, 'UNDER-RELAXATION WEIGHT REDUCTION FACTOR (THETA) = ', e15.6, &
1029  /1x, 'UNDER-RELAXATION WEIGHT INCREASE INCREMENT (KAPPA) = ', e15.6, &
1030  /1x, 'UNDER-RELAXATION PREVIOUS HISTORY FACTOR (GAMMA) = ', e15.6, &
1031  /1x, 'UNDER-RELAXATION MOMENTUM TERM (AMOMENTUM) = ', e15.6)
1032  !
1033  ! -- backtracking formats
1034 9006 FORMAT(1x, 'MAXIMUM NUMBER OF BACKTRACKS (NUMTRACK) = ', i0, &
1035  /1x, 'BACKTRACKING TOLERANCE FACTOR (BTOL) = ', e15.6, &
1036  /1x, 'BACKTRACKING REDUCTION FACTOR (BREDUC) = ', e15.6, &
1037  /1x, 'BACKTRACKING RESIDUAL LIMIT (RES_LIM) = ', e15.6)
1038  !
1039  ! -- linear solver data
1040  if (this%linsolver == ims_solver) then
1041  call this%imslinear%imslinear_summary(this%mxiter)
1042  else
1043  call this%linear_solver%print_summary()
1044  end if
1045 
1046  ! -- write summary of solver error messages
1047  ierr = count_errors()
1048  if (ierr > 0) then
1049  call this%parser%StoreErrorUnit()
1050  end if
1051  !
1052  ! reallocate space for nonlinear arrays and initialize
1053  call mem_reallocate(this%hncg, this%mxiter, 'HNCG', this%name)
1054  call mem_reallocate(this%lrch, 3, this%mxiter, 'LRCH', this%name)
1055 
1056  ! delta-bar-delta under-relaxation
1057  if (this%nonmeth == 3) then
1058  call mem_reallocate(this%wsave, this%neq, 'WSAVE', this%name)
1059  call mem_reallocate(this%hchold, this%neq, 'HCHOLD', this%name)
1060  call mem_reallocate(this%deold, this%neq, 'DEOLD', this%name)
1061  do i = 1, this%neq
1062  this%wsave(i) = dzero
1063  this%hchold(i) = dzero
1064  this%deold(i) = dzero
1065  end do
1066  end if
1067  this%hncg = dzero
1068  this%lrch = 0
1069 
1070  ! allocate space for saving solver convergence history
1071  if (this%iprims == 2 .or. this%icsvinnerout > 0) then
1072  this%nitermax = this%linear_settings%iter1 * this%mxiter
1073  else
1074  this%nitermax = 1
1075  end if
1076 
1077  allocate (this%caccel(this%nitermax))
1078 
1079  !
1080  ! -- resize convergence report
1081  call this%cnvg_summary%reinit(this%nitermax)
1082  !
1083  ! -- check for numerical solution errors
1084  ierr = count_errors()
1085  if (ierr > 0) then
1086  call this%parser%StoreErrorUnit()
1087  end if
1088  !
1089  ! -- close ims input file
1090  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 2718 of file NumericalSolution.f90.

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

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

◆ sln_buildsystem()

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

Definition at line 1979 of file NumericalSolution.f90.

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

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

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

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

◆ 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 2973 of file NumericalSolution.f90.

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

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

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

1099  ! -- modules
1100  use tdismodule, only: kstp, kper, delt
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_submit_delt(kstp, kper, delt_temp, this%memory_path, idir=idir)
1132  end if
subroutine, public ats_submit_delt(kstp, kper, dt, sloc, idir)
@ brief Allow and external caller to submit preferred time step
Definition: ats.f90:493
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
real(dp), pointer, public delt
length of the current time step
Definition: tdis.f90:29
Here is the call graph for this function:

◆ sln_fp()

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

Finalize a solution.

Parameters
thisNumericalSolutionType instance

Definition at line 1177 of file NumericalSolution.f90.

1178  use simvariablesmodule, only: iout
1179  ! -- dummy variables
1180  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1181  !
1182  ! -- write timer output
1183  if (idevelopmode == 1) then
1184  write (iout, '(//1x,a,1x,a,1x,a)') &
1185  'Solution', trim(adjustl(this%name)), 'summary'
1186  write (iout, "(1x,70('-'))")
1187  write (iout, '(1x,a,1x,g0,1x,a)') &
1188  'Total formulate time: ', this%ttform, 'seconds'
1189  write (iout, '(1x,a,1x,g0,1x,a,/)') &
1190  'Total solution time: ', this%ttsoln, 'seconds'
1191  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 3183 of file NumericalSolution.f90.

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

2869  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2870  integer(I4B) :: idv_scale !< backtracking flag (1) backtracking performed (0) backtracking not performed
2871  ! local
2872  class(NumericalModelType), pointer :: mp => null()
2873  integer(I4B) :: i
2874 
2875  idv_scale = 0
2876  do i = 1, this%modellist%Count()
2877  mp => getnumericalmodelfromlist(this%modellist, i)
2878  if (mp%get_idv_scale() /= 0) then
2879  idv_scale = 1
2880  else
2881  if (idv_scale == 1) then
2882  idv_scale = -1
2883  end if
2884  end if
2885  end do
2886 
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 3285 of file NumericalSolution.f90.

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

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

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

◆ 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 2916 of file NumericalSolution.f90.

2917  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2918  real(DP) :: l2norm !< calculated L-2 norm
2919  ! local
2920  class(VectorBaseType), pointer :: vec_resid
2921 
2922  ! calc. residual vector
2923  vec_resid => this%system_matrix%create_vec(this%neq)
2924  call this%sln_calc_residual(vec_resid)
2925 
2926  ! 2-norm
2927  l2norm = vec_resid%norm2()
2928 
2929  ! clean up temp. vector
2930  call vec_resid%destroy()
2931  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 2442 of file NumericalSolution.f90.

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

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

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

◆ sln_ot()

subroutine numericalsolutionmodule::sln_ot ( class(numericalsolutiontype this)

Output solution data. Currently does nothing.

Parameters
thisNumericalSolutionType instance

Definition at line 1165 of file NumericalSolution.f90.

1166  ! -- dummy variables
1167  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1168  !
1169  ! -- 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 3230 of file NumericalSolution.f90.

3231  ! dummy
3232  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3233  real(DP), intent(in) :: dpak !< Newton Under-relaxation flag
3234  character(len=LENPAKLOC), intent(in) :: cpakout !< string with package that caused failure
3235  integer(I4B), intent(in) :: iend !< flag indicating if last inner iteration (iend=1)
3236  ! local
3237  integer(I4B) :: ivalue
3238  ivalue = 1
3239  if (abs(dpak) > this%dvclose) then
3240  ivalue = 0
3241  ! -- write message to stdout
3242  if (iend /= 0) then
3243  write (errmsg, '(3a)') &
3244  'PACKAGE (', trim(cpakout), ') CAUSED CONVERGENCE FAILURE'
3245  call write_message(errmsg)
3246  end if
3247  end if
3248 
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 2427 of file NumericalSolution.f90.

2428  ! -- dummy variables
2429  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2430  !
2431  ! -- reset the solution
2432  call this%system_matrix%zero_entries()
2433  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 2661 of file NumericalSolution.f90.

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

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

◆ 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 3050 of file NumericalSolution.f90.

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

◆ solve()

subroutine numericalsolutionmodule::solve ( class(numericalsolutiontype this,
integer(i4b), intent(in)  kiter 
)
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

Definition at line 1512 of file NumericalSolution.f90.

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

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

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