MODFLOW 6  version 6.7.0.dev3
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 2341 of file NumericalSolution.f90.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

◆ preparesolve()

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

Prepare for the system solve by advancing the simulation.

Parameters
thisNumericalSolutionType instance

Definition at line 1468 of file NumericalSolution.f90.

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

◆ save()

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

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

Parameters
thisNumericalSolutionType instance
[in]filenamefilename to save solution data

Definition at line 2273 of file NumericalSolution.f90.

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

◆ sln_ad()

subroutine numericalsolutionmodule::sln_ad ( class(numericalsolutiontype this)

Advance solution.

Parameters
thisNumericalSolutionType instance

Definition at line 1141 of file NumericalSolution.f90.

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

◆ sln_ar()

subroutine numericalsolutionmodule::sln_ar ( class(numericalsolutiontype this)

Allocate and read data for a solution.

Parameters
thisNumericalSolutionType instance

Definition at line 535 of file NumericalSolution.f90.

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

◆ sln_backtracking()

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

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

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

Definition at line 2719 of file NumericalSolution.f90.

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

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

◆ sln_buildsystem()

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

Definition at line 1980 of file NumericalSolution.f90.

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

◆ sln_ca()

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

Solve the models in this solution for kper and kstp.

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

Definition at line 1318 of file NumericalSolution.f90.

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

◆ sln_calc_ptc()

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

Definition at line 2998 of file NumericalSolution.f90.

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

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

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

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

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

◆ sln_da()

subroutine numericalsolutionmodule::sln_da ( class(numericalsolutiontype this)

Deallocate a solution.

Parameters
thisNumericalSolutionType instance

Definition at line 1200 of file NumericalSolution.f90.

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

◆ sln_df()

subroutine numericalsolutionmodule::sln_df ( class(numericalsolutiontype this)

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

Parameters
thisNumericalSolutionType instance

Definition at line 438 of file NumericalSolution.f90.

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

◆ sln_dt()

subroutine numericalsolutionmodule::sln_dt ( class(numericalsolutiontype this)

Calculate time step length.

Parameters
thisNumericalSolutionType instance

Definition at line 1099 of file NumericalSolution.f90.

1100  ! -- modules
1101  use tdismodule, only: kstp, kper, delt
1103  use constantsmodule, only: dtwo, dthree
1104  ! -- dummy variables
1105  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1106  ! -- local variables
1107  integer(I4B) :: idir
1108  real(DP) :: delt_temp
1109  real(DP) :: fact_lower
1110  real(DP) :: fact_upper
1111  !
1112  ! -- increase or decrease delt based on kiter fraction. atsfrac should be
1113  ! a value of about 1/3. If the number of outer iterations is less than
1114  ! 1/3 of mxiter, then increase step size. If the number of outer
1115  ! iterations is greater than 2/3 of mxiter, then decrease step size.
1116  if (this%atsfrac > dzero) then
1117  delt_temp = delt
1118  fact_lower = this%mxiter * this%atsfrac
1119  fact_upper = this%mxiter - fact_lower
1120  if (this%iouttot_timestep < int(fact_lower)) then
1121  ! -- increase delt according to tsfactats
1122  idir = 1
1123  else if (this%iouttot_timestep > int(fact_upper)) then
1124  ! -- decrease delt according to tsfactats
1125  idir = -1
1126  else
1127  ! -- do not change delt
1128  idir = 0
1129  end if
1130  !
1131  ! -- submit stable dt for upcoming step
1132  call ats_submit_delt(kstp, kper, delt_temp, this%memory_path, idir=idir)
1133  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 1178 of file NumericalSolution.f90.

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

◆ sln_get_dxmax()

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

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

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

Definition at line 3184 of file NumericalSolution.f90.

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

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

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

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

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

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

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

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

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

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

◆ sln_ot()

subroutine numericalsolutionmodule::sln_ot ( class(numericalsolutiontype this)

Output solution data. Currently does nothing.

Parameters
thisNumericalSolutionType instance

Definition at line 1166 of file NumericalSolution.f90.

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

◆ sln_package_convergence()

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

Definition at line 3231 of file NumericalSolution.f90.

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

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

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

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

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

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

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

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

◆ writeptcinfotofile()

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

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

Parameters
thisNumericalSolutionType instance
[in]kpercurrent stress period number

Definition at line 1418 of file NumericalSolution.f90.

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

Variable Documentation

◆ ims_solver

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

Definition at line 55 of file NumericalSolution.f90.

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

◆ petsc_solver

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

Definition at line 56 of file NumericalSolution.f90.

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