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

Data Types

type  numericalsolutiontype
 
interface  synchronize_iface
 

Functions/Subroutines

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

Variables

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

Function/Subroutine Documentation

◆ add_exchange()

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

Add and exchange to thisexchangelist.

Parameters
thisNumericalSolutionType instance
[in]exchangemodel exchange instance

Definition at line 2297 of file NumericalSolution.f90.

2298  ! -- dummy variables
2299  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2300  class(BaseExchangeType), pointer, intent(in) :: exchange !< model exchange instance
2301  ! -- local variables
2302  class(NumericalExchangeType), pointer :: num_ex => null()
2303  !
2304  ! -- add exchange
2305  select type (exchange)
2306  class is (numericalexchangetype)
2307  num_ex => exchange
2308  call addnumericalexchangetolist(this%exchangelist, num_ex)
2309  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 2262 of file NumericalSolution.f90.

2263  ! -- dummy variables
2264  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2265  class(BaseModelType), pointer, intent(in) :: mp !< model instance
2266  ! -- local variables
2267  class(NumericalModelType), pointer :: m => null()
2268  !
2269  ! -- add a model
2270  select type (mp)
2271  class is (numericalmodeltype)
2272  m => mp
2273  call addnumericalmodeltolist(this%modellist, m)
2274  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 2848 of file NumericalSolution.f90.

2849  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2850  ! local
2851  integer(I4B) :: n
2852  real(DP) :: delx
2853 
2854  do n = 1, this%neq
2855  if (this%active(n) < 1) cycle
2856  delx = this%breduc * (this%x(n) - this%xtemp(n))
2857  this%x(n) = this%xtemp(n) + delx
2858  end do
2859 

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

3323  ! -- dummy variables
3324  class(*), pointer, intent(inout) :: obj !< generic object
3325  ! -- return variable
3326  class(NumericalSolutionType), pointer :: res !< output NumericalSolutionType
3327  !
3328  ! -- initialize return variable
3329  res => null()
3330  !
3331  ! -- determine if obj is associated
3332  if (.not. associated(obj)) return
3333  !
3334  ! -- set res
3335  select type (obj)
3336  class is (numericalsolutiontype)
3337  res => obj
3338  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 1993 of file NumericalSolution.f90.

1994  ! -- modules
1995  use inputoutputmodule, only: getunit
1996  ! -- dummy variables
1997  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1998  integer(I4B), intent(in) :: iu !< file unit number for summary file
1999  integer(I4B), intent(in) :: im !< model number
2000  integer(I4B), intent(in) :: itertot_timestep !< total iteration for the time step
2001  ! -- local variables
2002  character(len=LINELENGTH) :: title
2003  character(len=LINELENGTH) :: tag
2004  character(len=LENPAKLOC) :: loc_dvmax_str
2005  character(len=LENPAKLOC) :: loc_rmax_str
2006  integer(I4B) :: ntabrows
2007  integer(I4B) :: ntabcols
2008  integer(I4B) :: iinner
2009  integer(I4B) :: i0
2010  integer(I4B) :: iouter
2011  integer(I4B) :: j
2012  integer(I4B) :: k
2013  integer(I4B) :: locdv
2014  integer(I4B) :: locdr
2015  real(DP) :: dv !< the maximum change in the dependent variable
2016  real(DP) :: res !< the maximum value of the residual vector
2017  !
2018  ! -- initialize local variables
2019  loc_dvmax_str = ''
2020  loc_rmax_str = ''
2021  iouter = 1
2022  locdv = 0
2023  locdr = 0
2024  !
2025  ! -- initialize inner iteration summary table
2026  if (.not. associated(this%innertab)) then
2027  !
2028  ! -- create outer iteration table
2029  ! -- table dimensions
2030  ntabrows = itertot_timestep
2031  ntabcols = 7
2032  !
2033  ! -- initialize table and define columns
2034  title = trim(this%memory_path)//' INNER ITERATION SUMMARY'
2035  call table_cr(this%innertab, this%name, title)
2036  call this%innertab%table_df(ntabrows, ntabcols, iu)
2037  tag = 'TOTAL ITERATION'
2038  call this%innertab%initialize_column(tag, 10, alignment=tabright)
2039  tag = 'OUTER ITERATION'
2040  call this%innertab%initialize_column(tag, 10, alignment=tabright)
2041  tag = 'INNER ITERATION'
2042  call this%innertab%initialize_column(tag, 10, alignment=tabright)
2043  tag = 'MAXIMUM CHANGE'
2044  call this%innertab%initialize_column(tag, 15, alignment=tabright)
2045  tag = 'MAXIMUM CHANGE MODEL-(CELLID)'
2046  call this%innertab%initialize_column(tag, lenpakloc, alignment=tabright)
2047  tag = 'MAXIMUM RESIDUAL'
2048  call this%innertab%initialize_column(tag, 15, alignment=tabright)
2049  tag = 'MAXIMUM RESIDUAL MODEL-(CELLID)'
2050  call this%innertab%initialize_column(tag, lenpakloc, alignment=tabright)
2051  !
2052  ! -- reset the output unit and the number of rows (maxbound)
2053  else
2054  call this%innertab%set_maxbound(itertot_timestep)
2055  call this%innertab%set_iout(iu)
2056  end if
2057  !
2058  ! -- write the inner iteration summary to unit iu
2059  i0 = 0
2060  do k = 1, itertot_timestep
2061  iinner = this%cnvg_summary%itinner(k)
2062  if (iinner <= i0) then
2063  iouter = iouter + 1
2064  end if
2065  if (im > this%convnmod) then
2066  dv = dzero
2067  res = dzero
2068  do j = 1, this%convnmod
2069  if (abs(this%cnvg_summary%convdvmax(j, k)) > abs(dv)) then
2070  locdv = this%cnvg_summary%convlocdv(j, k)
2071  dv = this%cnvg_summary%convdvmax(j, k)
2072  end if
2073  if (abs(this%cnvg_summary%convrmax(j, k)) > abs(res)) then
2074  locdr = this%cnvg_summary%convlocr(j, k)
2075  res = this%cnvg_summary%convrmax(j, k)
2076  end if
2077  end do
2078  else
2079  locdv = this%cnvg_summary%convlocdv(im, k)
2080  locdr = this%cnvg_summary%convlocr(im, k)
2081  dv = this%cnvg_summary%convdvmax(im, k)
2082  res = this%cnvg_summary%convrmax(im, k)
2083  end if
2084  call this%sln_get_loc(locdv, loc_dvmax_str)
2085  call this%sln_get_loc(locdr, loc_rmax_str)
2086  !
2087  ! -- add data to innertab
2088  call this%innertab%add_term(k)
2089  call this%innertab%add_term(iouter)
2090  call this%innertab%add_term(iinner)
2091  call this%innertab%add_term(dv)
2092  call this%innertab%add_term(adjustr(trim(loc_dvmax_str)))
2093  call this%innertab%add_term(res)
2094  call this%innertab%add_term(adjustr(trim(loc_rmax_str)))
2095  !
2096  ! -- update i0
2097  i0 = iinner
2098  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 2106 of file NumericalSolution.f90.

2108  ! -- modules
2109  use inputoutputmodule, only: getunit
2110  ! -- dummy variables
2111  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2112  integer(I4B), intent(in) :: iu !< file unit number
2113  real(DP), intent(in) :: totim !< total simulation time
2114  integer(I4B), intent(in) :: kper !< stress period number
2115  integer(I4B), intent(in) :: kstp !< time step number
2116  integer(I4B), intent(in) :: kouter !< number of outer (Picard) iterations
2117  integer(I4B), intent(in) :: niter !< number of inner iteration in this time step
2118  integer(I4B), intent(in) :: istart !< starting iteration number for this time step
2119  integer(I4B), intent(in) :: kstart !< starting position in the conv* arrays
2120  ! -- local
2121  integer(I4B) :: itot
2122  integer(I4B) :: m_idx, j, k
2123  integer(I4B) :: kpos
2124  integer(I4B) :: loc_dvmax !< solution node number (row) of max. dep. var. change
2125  integer(I4B) :: loc_rmax !< solution node number (row) of max. residual
2126  integer(I4B) :: model_id, node_user
2127  real(DP) :: dvmax !< maximum dependent variable change
2128  real(DP) :: rmax !< maximum residual
2129  class(NumericalModelType), pointer :: num_mod => null()
2130  !
2131  ! -- initialize local variables
2132  itot = istart
2133  !
2134  ! -- write inner iteration results to the inner csv output file
2135  do k = 1, niter
2136  kpos = kstart + k - 1
2137  write (iu, '(*(G0,:,","))', advance='NO') &
2138  itot, totim, kper, kstp, kouter, k
2139  !
2140  ! -- solution summary
2141  dvmax = dzero
2142  rmax = dzero
2143  do j = 1, this%convnmod
2144  if (abs(this%cnvg_summary%convdvmax(j, kpos)) > abs(dvmax)) then
2145  loc_dvmax = this%cnvg_summary%convlocdv(j, kpos)
2146  dvmax = this%cnvg_summary%convdvmax(j, kpos)
2147  end if
2148  if (abs(this%cnvg_summary%convrmax(j, kpos)) > abs(rmax)) then
2149  loc_rmax = this%cnvg_summary%convlocr(j, kpos)
2150  rmax = this%cnvg_summary%convrmax(j, kpos)
2151  end if
2152  end do
2153  !
2154  ! -- no change, could be anywhere
2155  if (dvmax == dzero) loc_dvmax = 0
2156  if (rmax == dzero) loc_rmax = 0
2157  !
2158  ! -- get model number and user node number for max. dep. var. change
2159  if (loc_dvmax > 0) then
2160  call this%sln_get_nodeu(loc_dvmax, m_idx, node_user)
2161  num_mod => getnumericalmodelfromlist(this%modellist, m_idx)
2162  model_id = num_mod%id
2163  else
2164  model_id = 0
2165  node_user = 0
2166  end if
2167  write (iu, '(*(G0,:,","))', advance='NO') '', dvmax, model_id, node_user
2168  !
2169  ! -- get model number and user node number for max. residual
2170  if (loc_rmax > 0) then
2171  call this%sln_get_nodeu(loc_rmax, m_idx, node_user)
2172  num_mod => getnumericalmodelfromlist(this%modellist, m_idx)
2173  model_id = num_mod%id
2174  else
2175  model_id = 0
2176  node_user = 0
2177  end if
2178  write (iu, '(*(G0,:,","))', advance='NO') '', rmax, model_id, node_user
2179  !
2180  ! -- write ims acceleration parameters
2181  if (this%linsolver == ims_solver) then
2182  write (iu, '(*(G0,:,","))', advance='NO') &
2183  '', trim(adjustl(this%caccel(kpos)))
2184  end if
2185  !
2186  ! -- write information for each model
2187  if (this%convnmod > 1 .or. simulation_mode == "PARALLEL") then
2188  do j = 1, this%cnvg_summary%convnmod
2189  loc_dvmax = this%cnvg_summary%convlocdv(j, kpos)
2190  dvmax = this%cnvg_summary%convdvmax(j, kpos)
2191  loc_rmax = this%cnvg_summary%convlocr(j, kpos)
2192  rmax = this%cnvg_summary%convrmax(j, kpos)
2193  !
2194  ! -- get model number and user node number for max. dep. var. change
2195  if (loc_dvmax > 0) then
2196  call this%sln_get_nodeu(loc_dvmax, m_idx, node_user)
2197  else
2198  node_user = 0
2199  end if
2200  write (iu, '(*(G0,:,","))', advance='NO') '', dvmax, node_user
2201  !
2202  ! -- get model number and user node number for max. residual
2203  if (loc_rmax > 0) then
2204  call this%sln_get_nodeu(loc_rmax, m_idx, node_user)
2205  else
2206  node_user = 0
2207  end if
2208  write (iu, '(*(G0,:,","))', advance='NO') '', rmax, node_user
2209  end do
2210  end if
2211  !
2212  ! -- write line
2213  write (iu, '(a)') ''
2214  !
2215  ! -- update itot
2216  itot = itot + 1
2217  end do
2218  !
2219  ! -- flush file
2220  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 1839 of file NumericalSolution.f90.

1840  ! -- modules
1841  use tdismodule, only: kper, kstp
1842  ! -- dummy variables
1843  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1844  integer(I4B), intent(in) :: kiter !< Picard iteration number after convergence or failure
1845  integer(I4B), intent(inout) :: isgcnvg !< solution group convergence flag
1846  integer(I4B), intent(in) :: isuppress_output !< flag for suppressing output
1847  ! -- local variables
1848  integer(I4B) :: ic, im
1849  class(NumericalModelType), pointer :: mp => null()
1850  class(NumericalExchangeType), pointer :: cp => null()
1851  ! -- formats for convergence info
1852  character(len=*), parameter :: fmtnocnvg = &
1853  "(1X,'Solution ', i0, ' did not converge for stress period ', i0, &
1854  &' and time step ', i0)"
1855  character(len=*), parameter :: fmtcnvg = &
1856  "(1X, I0, ' CALLS TO NUMERICAL SOLUTION ', 'IN TIME STEP ', I0, &
1857  &' STRESS PERIOD ',I0,/1X,I0,' TOTAL ITERATIONS')"
1858 
1859  ! start timer
1860  call g_prof%start("Finalize solve"//this%id_postfix, this%tmr_final_solve)
1861 
1862  !
1863  ! -- finalize the outer iteration table
1864  if (this%iprims > 0) then
1865  call this%outertab%finalize_table()
1866  end if
1867  !
1868  ! -- write convergence info
1869  !
1870  ! -- convergence was achieved
1871  if (this%icnvg /= 0) then
1872  if (this%iprims > 0) then
1873  write (iout, fmtcnvg) kiter, kstp, kper, this%itertot_timestep
1874  end if
1875  !
1876  ! -- convergence was not achieved
1877  else
1878  write (iout, fmtnocnvg) this%id, kper, kstp
1879  end if
1880  !
1881  ! -- write inner iteration convergence summary
1882  if (this%iprims == 2) then
1883  !
1884  ! -- write summary for each model
1885  do im = 1, this%modellist%Count()
1886  mp => getnumericalmodelfromlist(this%modellist, im)
1887  call this%convergence_summary(mp%iout, im, this%itertot_timestep)
1888  end do
1889  !
1890  ! -- write summary for entire solution
1891  call this%convergence_summary(iout, this%convnmod + 1, &
1892  this%itertot_timestep)
1893  end if
1894  !
1895  ! -- set solution group convergence flag
1896  if (this%icnvg == 0) isgcnvg = 0
1897 
1898  call g_prof%start("Calculate flows", this%tmr_flows)
1899 
1900  !
1901  ! -- Calculate flow for each model
1902  do im = 1, this%modellist%Count()
1903  mp => getnumericalmodelfromlist(this%modellist, im)
1904  call mp%model_cq(this%icnvg, isuppress_output)
1905  end do
1906  !
1907  ! -- Calculate flow for each exchange
1908  do ic = 1, this%exchangelist%Count()
1909  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1910  call cp%exg_cq(isgcnvg, isuppress_output, this%id)
1911  end do
1912 
1913  call g_prof%stop(this%tmr_flows)
1914  call g_prof%start("Calculate budgets", this%tmr_budgets)
1915 
1916  !
1917  ! -- Budget terms for each model
1918  do im = 1, this%modellist%Count()
1919  mp => getnumericalmodelfromlist(this%modellist, im)
1920  call mp%model_bd(this%icnvg, isuppress_output)
1921  end do
1922  !
1923  ! -- Budget terms for each exchange
1924  do ic = 1, this%exchangelist%Count()
1925  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1926  call cp%exg_bd(isgcnvg, isuppress_output, this%id)
1927  end do
1928 
1929  ! stop timer
1930  call g_prof%stop(this%tmr_budgets)
1931  call g_prof%stop(this%tmr_final_solve)
1932 
integer(i4b), pointer, public kstp
current time step number
Definition: tdis.f90:27
integer(i4b), pointer, public kper
current stress period number
Definition: tdis.f90:26
Here is the call graph for this function:

◆ get_backtracking_flag()

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

Definition at line 2795 of file NumericalSolution.f90.

2796  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2797  integer(I4B) :: bt_flag !< backtracking flag (1) backtracking performed (0) backtracking not performed
2798  ! local
2799  integer(I4B) :: n
2800  real(DP) :: dx
2801  real(DP) :: dx_abs
2802  real(DP) :: dx_abs_max
2803 
2804  ! default is off
2805  bt_flag = 0
2806 
2807  ! find max. change
2808  dx_abs_max = 0.0
2809  do n = 1, this%neq
2810  if (this%active(n) < 1) cycle
2811  dx = this%x(n) - this%xtemp(n)
2812  dx_abs = abs(dx)
2813  if (dx_abs > dx_abs_max) dx_abs_max = dx_abs
2814  end do
2815 
2816  ! if backtracking, set flag
2817  if (this%breduc * dx_abs_max >= this%dvclose) then
2818  bt_flag = 1
2819  end if
2820 

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

2315  class(NumericalSolutionType) :: this !< instance of the numerical solution
2316  type(ListType), pointer :: exchanges !< pointer to the exchange list
2317 
2318  exchanges => this%exchangelist
2319 

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

2283  ! -- return variable
2284  type(ListType), pointer :: models !< pointer to the model list
2285  ! -- dummy variables
2286  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2287 
2288  models => this%modellist
2289 

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

3347  ! -- dummy variables
3348  type(ListType), intent(inout) :: list !< list of numerical solutions
3349  integer(I4B), intent(in) :: idx !< value to retrieve from the list
3350  ! -- return variables
3351  class(NumericalSolutionType), pointer :: res !< numerical solution
3352  ! -- local variables
3353  class(*), pointer :: obj
3354  !
3355  obj => list%GetItem(idx)
3356  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 1423 of file NumericalSolution.f90.

1424  ! -- dummy variables
1425  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1426  ! -- local variables
1427  integer(I4B) :: ic
1428  integer(I4B) :: im
1429  class(NumericalExchangeType), pointer :: cp => null()
1430  class(NumericalModelType), pointer :: mp => null()
1431 
1432  ! start timer
1433  call g_prof%start("Prepare solve"//this%id_postfix, this%tmr_prep_solve)
1434 
1435  ! synchronize for AD
1436  call this%synchronize(stg_bfr_exg_ad, this%synchronize_ctx)
1437 
1438  ! -- Exchange advance
1439  do ic = 1, this%exchangelist%Count()
1440  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1441  call cp%exg_ad()
1442  end do
1443 
1444  ! -- Model advance
1445  do im = 1, this%modellist%Count()
1446  mp => getnumericalmodelfromlist(this%modellist, im)
1447  call mp%model_ad()
1448  end do
1449 
1450  ! advance solution
1451  call this%sln_ad()
1452 
1453  ! stop timer
1454  call g_prof%stop(this%tmr_prep_solve)
1455 
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 2229 of file NumericalSolution.f90.

2230  use sparsematrixmodule
2231  ! -- modules
2232  use inputoutputmodule, only: getunit
2233  ! -- dummy variables
2234  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2235  character(len=*), intent(in) :: filename !< filename to save solution data
2236  ! -- local variables
2237  integer(I4B) :: inunit
2238  !
2239  select type (spm => this%system_matrix)
2240  class is (sparsematrixtype)
2241  inunit = getunit()
2242  open (unit=inunit, file=filename, status='unknown')
2243  write (inunit, *) 'ia'
2244  write (inunit, *) spm%ia
2245  write (inunit, *) 'ja'
2246  write (inunit, *) spm%ja
2247  write (inunit, *) 'amat'
2248  write (inunit, *) spm%amat
2249  write (inunit, *) 'rhs'
2250  write (inunit, *) this%rhs
2251  write (inunit, *) 'x'
2252  write (inunit, *) this%x
2253  close (inunit)
2254  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 1096 of file NumericalSolution.f90.

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

2676  ! -- dummy variables
2677  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2678  class(NumericalModelType), pointer :: mp !< model pointer (currently null())
2679  class(NumericalExchangeType), pointer :: cp !< exchange pointer (currently null())
2680  integer(I4B), intent(in) :: kiter !< Picard iteration number
2681  ! -- local variables
2682  character(len=7) :: cmsg
2683  integer(I4B) :: nb
2684  integer(I4B) :: btflag
2685  integer(I4B) :: ibflag
2686  integer(I4B) :: ibtcnt
2687  real(DP) :: resin
2688  !
2689  ! -- initialize local variables
2690  ibflag = 0
2691 
2692  !
2693  ! -- refill amat and rhs with standard conductance
2694  call this%sln_buildsystem(kiter, inewton=0)
2695 
2696  !
2697  ! -- calculate initial l2 norm
2698  if (kiter == 1) then
2699  call this%sln_l2norm(this%res_prev)
2700  resin = this%res_prev
2701  ibflag = 0
2702  else
2703  call this%sln_l2norm(this%res_new)
2704  resin = this%res_new
2705  end if
2706  ibtcnt = 0
2707  if (kiter > 1) then
2708  if (this%res_new > this%res_prev * this%btol) then
2709  !
2710  ! -- iterate until backtracking complete
2711  btloop: do nb = 1, this%numtrack
2712  !
2713  ! -- backtrack the dependent variable
2714  call this%sln_backtracking_xupdate(btflag)
2715  !
2716  ! -- dependent-variable change less than dvclose
2717  if (btflag == 0) then
2718  ibflag = 4
2719  exit btloop
2720  end if
2721  !
2722  ibtcnt = nb
2723 
2724  ! recalculate linear system (amat and rhs)
2725  call this%sln_buildsystem(kiter, inewton=0)
2726 
2727  !
2728  ! -- calculate updated l2norm
2729  call this%sln_l2norm(this%res_new)
2730  !
2731  ! -- evaluate if back tracking can be terminated
2732  if (nb == this%numtrack) then
2733  ibflag = 2
2734  exit btloop
2735  end if
2736  if (this%res_new < this%res_prev * this%btol) then
2737  ibflag = 1
2738  exit btloop
2739  end if
2740  if (this%res_new < this%res_lim) then
2741  exit btloop
2742  end if
2743  end do btloop
2744  end if
2745  ! -- save new residual
2746  this%res_prev = this%res_new
2747  end if
2748  !
2749  ! -- write back backtracking results
2750  if (this%iprims > 0) then
2751  if (ibtcnt > 0) then
2752  cmsg = ' '
2753  else
2754  cmsg = '*'
2755  end if
2756  !
2757  ! -- add data to outertab
2758  call this%outertab%add_term('Backtracking')
2759  call this%outertab%add_term(kiter)
2760  call this%outertab%add_term(' ')
2761  if (this%numtrack > 0) then
2762  call this%outertab%add_term(ibflag)
2763  call this%outertab%add_term(ibtcnt)
2764  call this%outertab%add_term(resin)
2765  call this%outertab%add_term(this%res_prev)
2766  end if
2767  call this%outertab%add_term(' ')
2768  call this%outertab%add_term(cmsg)
2769  call this%outertab%add_term(' ')
2770  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 2779 of file NumericalSolution.f90.

2780  ! -- dummy variables
2781  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2782  integer(I4B), intent(inout) :: bt_flag !< backtracking flag (1) backtracking performed (0) backtracking not performed
2783 
2784  bt_flag = this%get_backtracking_flag()
2785 
2786  ! perform backtracking if ...
2787  if (bt_flag > 0) then
2788  call this%apply_backtracking()
2789  end if
2790 

◆ sln_buildsystem()

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

Definition at line 1936 of file NumericalSolution.f90.

1937  class(NumericalSolutionType) :: this
1938  integer(I4B), intent(in) :: kiter
1939  integer(I4B), intent(in) :: inewton
1940  ! local
1941  integer(I4B) :: im, ic
1942  class(NumericalModelType), pointer :: mp
1943  class(NumericalExchangeType), pointer :: cp
1944  !
1945  ! -- Set amat and rhs to zero
1946  call this%sln_reset()
1947 
1948  ! reset models
1949  do im = 1, this%modellist%Count()
1950  mp => getnumericalmodelfromlist(this%modellist, im)
1951  call mp%model_reset()
1952  end do
1953 
1954  ! synchronize for CF
1955  call this%synchronize(stg_bfr_exg_cf, this%synchronize_ctx)
1956 
1957  !
1958  ! -- Calculate the matrix terms for each exchange
1959  do ic = 1, this%exchangelist%Count()
1960  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1961  call cp%exg_cf(kiter)
1962  end do
1963  !
1964  ! -- Calculate the matrix terms for each model
1965  do im = 1, this%modellist%Count()
1966  mp => getnumericalmodelfromlist(this%modellist, im)
1967  call mp%model_cf(kiter)
1968  end do
1969 
1970  ! synchronize for FC
1971  call this%synchronize(stg_bfr_exg_fc, this%synchronize_ctx)
1972 
1973  !
1974  ! -- Add exchange coefficients to the solution
1975  do ic = 1, this%exchangelist%Count()
1976  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1977  call cp%exg_fc(kiter, this%system_matrix, this%rhs, inewton)
1978  end do
1979  !
1980  ! -- Add model coefficients to the solution
1981  do im = 1, this%modellist%Count()
1982  mp => getnumericalmodelfromlist(this%modellist, im)
1983  call mp%model_fc(kiter, this%system_matrix, inewton)
1984  end do
1985 
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 1273 of file NumericalSolution.f90.

1274  ! -- dummy variables
1275  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1276  integer(I4B), intent(inout) :: isgcnvg !< solution group convergence flag
1277  integer(I4B), intent(in) :: isuppress_output !< flag for suppressing output
1278  ! -- local variables
1279  class(NumericalModelType), pointer :: mp => null()
1280  character(len=LINELENGTH) :: line
1281  character(len=LINELENGTH) :: fmt
1282  integer(I4B) :: im
1283  integer(I4B) :: kiter ! non-linear iteration counter
1284 
1285  ! advance the models, exchanges, and solution
1286  call this%prepareSolve()
1287 
1288  select case (isim_mode)
1289  case (mvalidate)
1290  line = 'mode="validation" -- Skipping matrix assembly and solution.'
1291  fmt = "(/,1x,a,/)"
1292  do im = 1, this%modellist%Count()
1293  mp => getnumericalmodelfromlist(this%modellist, im)
1294  call mp%model_message(line, fmt=fmt)
1295  end do
1296  case (mnormal)
1297  ! nonlinear iteration loop for this solution
1298  outerloop: do kiter = 1, this%mxiter
1299 
1300  ! perform a single iteration
1301  call this%solve(kiter, isuppress_output)
1302 
1303  ! exit if converged
1304  if (this%icnvg == 1) then
1305  exit outerloop
1306  end if
1307 
1308  end do outerloop
1309 
1310  ! finish up, write convergence info, CSV file, budgets and flows, ...
1311  call this%finalizeSolve(kiter, isgcnvg, isuppress_output)
1312  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 2954 of file NumericalSolution.f90.

2955  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2956  integer(I4B) :: iptc !< PTC (1) or not (0)
2957  real(DP) :: ptcf !< the PTC factor calculated
2958  ! local
2959  integer(I4B) :: im
2960  class(NumericalModelType), pointer :: mp
2961  class(VectorBaseType), pointer :: vec_resid
2962 
2963  iptc = 0
2964  ptcf = dzero
2965 
2966  ! calc. residual vector
2967  vec_resid => this%system_matrix%create_vec(this%neq)
2968  call this%sln_calc_residual(vec_resid)
2969 
2970  ! determine ptc
2971  do im = 1, this%modellist%Count()
2972  mp => getnumericalmodelfromlist(this%modellist, im)
2973  call mp%model_ptc(vec_resid, iptc, ptcf)
2974  end do
2975 
2976  ! clean up temp. vector
2977  call vec_resid%destroy()
2978  deallocate (vec_resid)
2979 
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 2984 of file NumericalSolution.f90.

2985  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2986  class(VectorBaseType), pointer :: vec_resid !< the residual vector
2987  ! local
2988  integer(I4B) :: n
2989 
2990  call this%system_matrix%multiply(this%vec_x, vec_resid) ! r = A*x
2991 
2992  call vec_resid%axpy(-1.0_dp, this%vec_rhs) ! r = r - b
2993 
2994  do n = 1, this%neq
2995  if (this%active(n) < 1) then
2996  call vec_resid%set_value_local(n, 0.0_dp) ! r_i = 0 if inactive
2997  end if
2998  end do
2999 

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

2931  ! -- dummy variables
2932  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2933  integer(I4B), intent(in) :: neq !< number of equations
2934  integer(I4B), dimension(neq), intent(in) :: active !< active cell flag (1)
2935  real(DP), dimension(neq), intent(in) :: x !< current dependent-variable
2936  real(DP), dimension(neq), intent(in) :: xtemp !< previous dependent-variable
2937  real(DP), dimension(neq), intent(inout) :: dx !< dependent-variable change
2938  ! -- local
2939  integer(I4B) :: n
2940  !
2941  ! -- calculate dependent-variable change
2942  do n = 1, neq
2943  ! -- skip inactive nodes
2944  if (active(n) < 1) then
2945  dx(n) = dzero
2946  else
2947  dx(n) = x(n) - xtemp(n)
2948  end if
2949  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 2331 of file NumericalSolution.f90.

2332  ! -- modules
2334  ! -- dummy variables
2335  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2336  ! -- local variables
2337  class(NumericalModelType), pointer :: mp => null()
2338  class(NumericalExchangeType), pointer :: cp => null()
2339  integer(I4B) :: im
2340  integer(I4B) :: ic
2341  !
2342  ! -- Add internal model connections to sparse
2343  do im = 1, this%modellist%Count()
2344  mp => getnumericalmodelfromlist(this%modellist, im)
2345  call mp%model_ac(this%sparse)
2346  end do
2347  !
2348  ! -- synchronize before AC
2349  call this%synchronize(stg_bfr_exg_ac, this%synchronize_ctx)
2350  !
2351  ! -- Add the cross terms to sparse
2352  do ic = 1, this%exchangelist%Count()
2353  cp => getnumericalexchangefromlist(this%exchangelist, ic)
2354  call cp%exg_ac(this%sparse)
2355  end do
2356  !
2357  ! -- The number of non-zero array values are now known so
2358  ! -- ia and ja can be created from sparse. then destroy sparse
2359  call this%sparse%sort()
2360  call this%system_matrix%init(this%sparse, this%name)
2361  call this%sparse%destroy()
2362  !
2363  ! -- Create mapping arrays for each model. Mapping assumes
2364  ! -- that each row has the diagonal in the first position,
2365  ! -- however, rows do not need to be sorted.
2366  do im = 1, this%modellist%Count()
2367  mp => getnumericalmodelfromlist(this%modellist, im)
2368  call mp%model_mc(this%system_matrix)
2369  end do
2370  !
2371  ! -- Create arrays for mapping exchange connections to global solution
2372  do ic = 1, this%exchangelist%Count()
2373  cp => getnumericalexchangefromlist(this%exchangelist, ic)
2374  call cp%exg_mc(this%system_matrix)
2375  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 1155 of file NumericalSolution.f90.

1156  ! -- modules
1158  ! -- dummy variables
1159  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1160  !
1161  ! -- IMSLinearModule
1162  if (this%linsolver == ims_solver) then
1163  call this%imslinear%imslinear_da()
1164  deallocate (this%imslinear)
1165  end if
1166  !
1167  ! -- lists
1168  call this%modellist%Clear()
1169  call this%exchangelist%Clear()
1170  deallocate (this%modellist)
1171  deallocate (this%exchangelist)
1172 
1173  call this%system_matrix%destroy()
1174  deallocate (this%system_matrix)
1175  call this%vec_x%destroy()
1176  deallocate (this%vec_x)
1177  call this%vec_rhs%destroy()
1178  deallocate (this%vec_rhs)
1179 
1180  !
1181  ! -- character arrays
1182  deallocate (this%caccel)
1183  !
1184  ! -- inner iteration table object
1185  if (associated(this%innertab)) then
1186  call this%innertab%table_da()
1187  deallocate (this%innertab)
1188  nullify (this%innertab)
1189  end if
1190  !
1191  ! -- outer iteration table object
1192  if (associated(this%outertab)) then
1193  call this%outertab%table_da()
1194  deallocate (this%outertab)
1195  nullify (this%outertab)
1196  end if
1197  !
1198  ! -- arrays
1199  call mem_deallocate(this%active)
1200  call mem_deallocate(this%xtemp)
1201  call mem_deallocate(this%dxold)
1202  call mem_deallocate(this%hncg)
1203  call mem_deallocate(this%lrch)
1204  call mem_deallocate(this%wsave)
1205  call mem_deallocate(this%hchold)
1206  call mem_deallocate(this%deold)
1207  call mem_deallocate(this%convmodstart)
1208  !
1209  ! -- convergence report
1210  call this%cnvg_summary%destroy()
1211  deallocate (this%cnvg_summary)
1212  !
1213  ! -- linear solver
1214  call this%linear_solver%destroy()
1215  deallocate (this%linear_solver)
1216  !
1217  ! -- linear solver settings
1218  call this%linear_settings%destroy()
1219  deallocate (this%linear_settings)
1220  !
1221  ! -- Scalars
1222  call mem_deallocate(this%id)
1223  call mem_deallocate(this%iu)
1224  call mem_deallocate(this%ttform)
1225  call mem_deallocate(this%ttsoln)
1226  call mem_deallocate(this%isymmetric)
1227  call mem_deallocate(this%neq)
1228  call mem_deallocate(this%matrix_offset)
1229  call mem_deallocate(this%dvclose)
1230  call mem_deallocate(this%bigchold)
1231  call mem_deallocate(this%bigch)
1232  call mem_deallocate(this%relaxold)
1233  call mem_deallocate(this%res_prev)
1234  call mem_deallocate(this%res_new)
1235  call mem_deallocate(this%icnvg)
1236  call mem_deallocate(this%itertot_timestep)
1237  call mem_deallocate(this%iouttot_timestep)
1238  call mem_deallocate(this%itertot_sim)
1239  call mem_deallocate(this%mxiter)
1240  call mem_deallocate(this%linsolver)
1241  call mem_deallocate(this%nonmeth)
1242  call mem_deallocate(this%iprims)
1243  call mem_deallocate(this%theta)
1244  call mem_deallocate(this%akappa)
1245  call mem_deallocate(this%gamma)
1246  call mem_deallocate(this%amomentum)
1247  call mem_deallocate(this%breduc)
1248  call mem_deallocate(this%btol)
1249  call mem_deallocate(this%res_lim)
1250  call mem_deallocate(this%numtrack)
1251  call mem_deallocate(this%ibflag)
1252  call mem_deallocate(this%icsvouterout)
1253  call mem_deallocate(this%icsvinnerout)
1254  call mem_deallocate(this%nitermax)
1255  call mem_deallocate(this%convnmod)
1256  call mem_deallocate(this%iallowptc)
1257  call mem_deallocate(this%iptcopt)
1258  call mem_deallocate(this%iptcout)
1259  call mem_deallocate(this%l2norm0)
1260  call mem_deallocate(this%ptcdel)
1261  call mem_deallocate(this%ptcdel0)
1262  call mem_deallocate(this%ptcexp)
1263  call mem_deallocate(this%atsfrac)
1264  call mem_deallocate(this%idv_scale)
1265  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 1054 of file NumericalSolution.f90.

1055  ! -- modules
1056  use tdismodule, only: kstp, kper, delt, ats
1057  use constantsmodule, only: dtwo, dthree
1058  ! -- dummy variables
1059  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1060  ! -- local variables
1061  integer(I4B) :: idir
1062  real(DP) :: delt_temp
1063  real(DP) :: fact_lower
1064  real(DP) :: fact_upper
1065  !
1066  ! -- increase or decrease delt based on kiter fraction. atsfrac should be
1067  ! a value of about 1/3. If the number of outer iterations is less than
1068  ! 1/3 of mxiter, then increase step size. If the number of outer
1069  ! iterations is greater than 2/3 of mxiter, then decrease step size.
1070  if (this%atsfrac > dzero) then
1071  delt_temp = delt
1072  fact_lower = this%mxiter * this%atsfrac
1073  fact_upper = this%mxiter - fact_lower
1074  if (this%iouttot_timestep < int(fact_lower)) then
1075  ! -- increase delt according to tsfactats
1076  idir = 1
1077  else if (this%iouttot_timestep > int(fact_upper)) then
1078  ! -- decrease delt according to tsfactats
1079  idir = -1
1080  else
1081  ! -- do not change delt
1082  idir = 0
1083  end if
1084  !
1085  ! -- submit stable dt for upcoming step
1086  call ats%ats_submit_delt(kstp, kper, delt_temp, &
1087  this%memory_path, idir=idir)
1088  end if
This module contains simulation constants.
Definition: Constants.f90:9
real(dp), parameter dtwo
real constant 2
Definition: Constants.f90:79
real(dp), parameter dthree
real constant 3
Definition: Constants.f90:80
class(atstype), pointer, public ats
Definition: tdis.f90:48
real(dp), pointer, public delt
length of the current time step
Definition: tdis.f90:32

◆ sln_fp()

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

Finalize a solution.

Parameters
thisNumericalSolutionType instance

Definition at line 1133 of file NumericalSolution.f90.

1134  use simvariablesmodule, only: iout
1135  ! -- dummy variables
1136  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1137  !
1138  ! -- write timer output
1139  if (idevelopmode == 1) then
1140  write (iout, '(//1x,a,1x,a,1x,a)') &
1141  'Solution', trim(adjustl(this%name)), 'summary'
1142  write (iout, "(1x,70('-'))")
1143  write (iout, '(1x,a,1x,g0,1x,a)') &
1144  'Total formulate time: ', this%ttform, 'seconds'
1145  write (iout, '(1x,a,1x,g0,1x,a,/)') &
1146  'Total solution time: ', this%ttsoln, 'seconds'
1147  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 3140 of file NumericalSolution.f90.

3141  ! -- dummy variables
3142  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
3143  real(DP), intent(inout) :: hncg !< maximum dependent-variable change
3144  integer(I4B), intent(inout) :: lrch !< location of the maximum dependent-variable change
3145  ! -- local variables
3146  integer(I4B) :: nb
3147  real(DP) :: bigch
3148  real(DP) :: abigch
3149  integer(I4B) :: n
3150  real(DP) :: hdif
3151  real(DP) :: ahdif
3152  !
3153  ! -- determine the maximum change
3154  nb = 0
3155  bigch = dzero
3156  abigch = dzero
3157  do n = 1, this%neq
3158  if (this%active(n) < 1) cycle
3159  hdif = this%x(n) - this%xtemp(n)
3160  ahdif = abs(hdif)
3161  if (ahdif > abigch) then
3162  bigch = hdif
3163  abigch = ahdif
3164  nb = n
3165  end if
3166  end do
3167  !
3168  !-----store maximum change value and location
3169  hncg = bigch
3170  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 2825 of file NumericalSolution.f90.

2826  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2827  integer(I4B) :: idv_scale !< backtracking flag (1) backtracking performed (0) backtracking not performed
2828  ! local
2829  class(NumericalModelType), pointer :: mp => null()
2830  integer(I4B) :: i
2831 
2832  idv_scale = 0
2833  do i = 1, this%modellist%Count()
2834  mp => getnumericalmodelfromlist(this%modellist, i)
2835  if (mp%get_idv_scale() /= 0) then
2836  idv_scale = 1
2837  else
2838  if (idv_scale == 1) then
2839  idv_scale = -1
2840  end if
2841  end if
2842  end do
2843 
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 3242 of file NumericalSolution.f90.

3243  ! -- dummy variables
3244  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
3245  integer(I4B), intent(in) :: nodesln !< solution node number
3246  character(len=*), intent(inout) :: str !< string with user node number
3247  ! -- local variables
3248  class(NumericalModelType), pointer :: mp => null()
3249  integer(I4B) :: i
3250  integer(I4B) :: istart
3251  integer(I4B) :: iend
3252  integer(I4B) :: noder
3253  integer(I4B) :: nglo
3254  !
3255  ! -- initialize dummy variables
3256  str = ''
3257  !
3258  ! -- initialize local variables
3259  noder = 0
3260  !
3261  ! -- when parallel, account for offset
3262  nglo = nodesln + this%matrix_offset
3263  !
3264  ! -- calculate and set offsets
3265  do i = 1, this%modellist%Count()
3266  mp => getnumericalmodelfromlist(this%modellist, i)
3267  istart = 0
3268  iend = 0
3269  call mp%get_mrange(istart, iend)
3270  if (nglo >= istart .and. nglo <= iend) then
3271  noder = nglo - istart + 1
3272  call mp%get_mcellid(noder, str)
3273  exit
3274  end if
3275  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 3283 of file NumericalSolution.f90.

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

3174  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3175  real(DP) :: max_dvc !< the maximum dependent variable change
3176  logical(LGP) :: has_converged !< True, when converged
3177 
3178  has_converged = .false.
3179  if (abs(max_dvc) <= this%dvclose) then
3180  has_converged = .true.
3181  end if
3182 

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

2874  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2875  real(DP) :: l2norm !< calculated L-2 norm
2876  ! local
2877  class(VectorBaseType), pointer :: vec_resid
2878 
2879  ! calc. residual vector
2880  vec_resid => this%system_matrix%create_vec(this%neq)
2881  call this%sln_calc_residual(vec_resid)
2882 
2883  ! 2-norm
2884  l2norm = vec_resid%norm2()
2885 
2886  ! clean up temp. vector
2887  call vec_resid%destroy()
2888  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 2399 of file NumericalSolution.f90.

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

2897  ! -- dummy variables
2898  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2899  integer(I4B), intent(in) :: nsize !< length of vector
2900  real(DP), dimension(nsize), intent(in) :: v !< input vector
2901  real(DP), intent(inout) :: vmax !< maximum value
2902  ! -- local variables
2903  integer(I4B) :: n
2904  real(DP) :: d
2905  real(DP) :: denom
2906  real(DP) :: dnorm
2907  !
2908  ! -- determine maximum value
2909  vmax = v(1)
2910  do n = 2, nsize
2911  d = v(n)
2912  denom = abs(vmax)
2913  if (denom == dzero) then
2914  denom = dprec
2915  end if
2916  !
2917  ! -- calculate normalized value
2918  dnorm = abs(d) / denom
2919  if (dnorm > done) then
2920  vmax = d
2921  end if
2922  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 3223 of file NumericalSolution.f90.

3225  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3226  real(DP), intent(in) :: dxold_max !< the maximum dependent variable change for unrelaxed cells
3227  real(DP), intent(in) :: hncg !< largest dep. var. change at end of Picard iteration
3228  logical(LGP) :: has_converged !< True, when converged
3229 
3230  has_converged = .false.
3231  if (abs(dxold_max) <= this%dvclose .and. &
3232  abs(hncg) <= this%dvclose) then
3233  has_converged = .true.
3234  end if
3235 

◆ sln_ot()

subroutine numericalsolutionmodule::sln_ot ( class(numericalsolutiontype this)

Output solution data. Currently does nothing.

Parameters
thisNumericalSolutionType instance

Definition at line 1121 of file NumericalSolution.f90.

1122  ! -- dummy variables
1123  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1124  !
1125  ! -- 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 3187 of file NumericalSolution.f90.

3188  ! dummy
3189  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3190  real(DP), intent(in) :: dpak !< Newton Under-relaxation flag
3191  character(len=LENPAKLOC), intent(in) :: cpakout !< string with package that caused failure
3192  integer(I4B), intent(in) :: iend !< flag indicating if last inner iteration (iend=1)
3193  ! local
3194  integer(I4B) :: ivalue
3195  ivalue = 1
3196  if (abs(dpak) > this%dvclose) then
3197  ivalue = 0
3198  ! -- write message to stdout
3199  if (iend /= 0) then
3200  write (errmsg, '(3a)') &
3201  'PACKAGE (', trim(cpakout), ') CAUSED CONVERGENCE FAILURE'
3202  call write_message(errmsg)
3203  end if
3204  end if
3205 
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 2384 of file NumericalSolution.f90.

2385  ! -- dummy variables
2386  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2387  !
2388  ! -- reset the solution
2389  call this%system_matrix%zero_entries()
2390  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 2618 of file NumericalSolution.f90.

2619  ! -- dummy variables
2620  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2621  integer(I4B), intent(in) :: ifdparam !< complexity option (1) simple (2) moderate (3) complex
2622  !
2623  ! -- simple option
2624  select case (ifdparam)
2625  case (1)
2626  this%dvclose = dem3
2627  this%mxiter = 25
2628  this%nonmeth = 0
2629  this%theta = done
2630  this%akappa = dzero
2631  this%gamma = done
2632  this%amomentum = dzero
2633  this%numtrack = 0
2634  this%btol = dzero
2635  this%breduc = dzero
2636  this%res_lim = dzero
2637  !
2638  ! -- moderate
2639  case (2)
2640  this%dvclose = dem2
2641  this%mxiter = 50
2642  this%nonmeth = 3
2643  this%theta = 0.9d0
2644  this%akappa = 0.0001d0
2645  this%gamma = dzero
2646  this%amomentum = dzero
2647  this%numtrack = 0
2648  this%btol = dzero
2649  this%breduc = dzero
2650  this%res_lim = dzero
2651  !
2652  ! -- complex
2653  case (3)
2654  this%dvclose = dem1
2655  this%mxiter = 100
2656  this%nonmeth = 3
2657  this%theta = 0.8d0
2658  this%akappa = 0.0001d0
2659  this%gamma = dzero
2660  this%amomentum = dzero
2661  this%numtrack = 20
2662  this%btol = 1.05d0
2663  this%breduc = 0.1d0
2664  this%res_lim = 0.002d0
2665  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 3210 of file NumericalSolution.f90.

3211  ! dummy
3212  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3213  integer(I4B), intent(in) :: inewtonur !< Newton Under-relaxation flag
3214  ! local
3215  integer(I4B) :: ivalue !< Default is set to current value (1 = under-relaxation applied)
3216 
3217  ivalue = inewtonur
3218 

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

3008  ! -- dummy variables
3009  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3010  integer(I4B), intent(in) :: kiter !< Picard iteration number
3011  real(DP), intent(in) :: bigch !< maximum dependent-variable change
3012  integer(I4B), intent(in) :: neq !< number of equations
3013  integer(I4B), dimension(neq), intent(in) :: active !< active cell flag (1)
3014  real(DP), dimension(neq), intent(inout) :: x !< current dependent-variable
3015  real(DP), dimension(neq), intent(in) :: xtemp !< previous dependent-variable
3016  ! -- local variables
3017  integer(I4B) :: n
3018  real(DP) :: ww
3019  real(DP) :: delx
3020  real(DP) :: relax
3021  real(DP) :: es
3022  real(DP) :: aes
3023  real(DP) :: amom
3024  !
3025  ! -- option for using simple dampening (as done by MODFLOW-2005 PCG)
3026  if (this%nonmeth == 1) then
3027  do n = 1, neq
3028  !
3029  ! -- skip inactive nodes
3030  if (active(n) < 1) cycle
3031  !
3032  ! -- compute step-size (delta x)
3033  delx = x(n) - xtemp(n)
3034  this%dxold(n) = delx
3035 
3036  ! -- dampen dependent variable solution
3037  x(n) = xtemp(n) + this%gamma * delx
3038  end do
3039  !
3040  ! -- option for using cooley underrelaxation
3041  else if (this%nonmeth == 2) then
3042  !
3043  ! -- set bigch
3044  this%bigch = bigch
3045  !
3046  ! -- initialize values for first iteration
3047  if (kiter == 1) then
3048  relax = done
3049  this%relaxold = done
3050  this%bigchold = bigch
3051  else
3052  !
3053  ! -- compute relaxation factor
3054  es = this%bigch / (this%bigchold * this%relaxold)
3055  aes = abs(es)
3056  if (es < -done) then
3057  relax = dhalf / aes
3058  else
3059  relax = (dthree + es) / (dthree + aes)
3060  end if
3061  end if
3062  this%relaxold = relax
3063  !
3064  ! -- modify cooley to use weighted average of past changes
3065  this%bigchold = (done - this%gamma) * this%bigch + this%gamma * &
3066  this%bigchold
3067  !
3068  ! -- compute new dependent variable after under-relaxation
3069  if (relax < done) then
3070  do n = 1, neq
3071  !
3072  ! -- skip inactive nodes
3073  if (active(n) < 1) cycle
3074  !
3075  ! -- update dependent variable
3076  delx = x(n) - xtemp(n)
3077  this%dxold(n) = delx
3078  x(n) = xtemp(n) + relax * delx
3079  end do
3080  end if
3081  !
3082  ! -- option for using delta-bar-delta scheme to under-relax for all equations
3083  else if (this%nonmeth == 3) then
3084  do n = 1, neq
3085  !
3086  ! -- skip inactive nodes
3087  if (active(n) < 1) cycle
3088  !
3089  ! -- compute step-size (delta x) and initialize d-b-d parameters
3090  delx = x(n) - xtemp(n)
3091  !
3092  ! -- initialize values for first iteration
3093  if (kiter == 1) then
3094  this%wsave(n) = done
3095  this%hchold(n) = dem20
3096  this%deold(n) = dzero
3097  end if
3098  !
3099  ! -- compute new relaxation term as per delta-bar-delta
3100  ww = this%wsave(n)
3101  !
3102  ! for flip-flop condition, decrease factor
3103  if (this%deold(n) * delx < dzero) then
3104  ww = this%theta * this%wsave(n)
3105  ! -- when change is of same sign, increase factor
3106  else
3107  ww = this%wsave(n) + this%akappa
3108  end if
3109  if (ww > done) ww = done
3110  this%wsave(n) = ww
3111  !
3112  ! -- compute weighted average of past changes in hchold
3113  if (kiter == 1) then
3114  this%hchold(n) = delx
3115  else
3116  this%hchold(n) = (done - this%gamma) * delx + &
3117  this%gamma * this%hchold(n)
3118  end if
3119  !
3120  ! -- store slope (change) term for next iteration
3121  this%deold(n) = delx
3122  this%dxold(n) = delx
3123  !
3124  ! -- compute accepted step-size and new dependent variable
3125  amom = dzero
3126  if (kiter > 4) amom = this%amomentum
3127  delx = delx * ww + amom * this%hchold(n)
3128  x(n) = xtemp(n) + delx
3129  end do
3130  !
3131  end if

◆ solve()

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

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

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

Definition at line 1468 of file NumericalSolution.f90.

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

◆ writecsvheader()

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

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

Parameters
thisNumericalSolutionType instance

Definition at line 1320 of file NumericalSolution.f90.

1321  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1322  ! local variables
1323  integer(I4B) :: im
1324  class(NumericalModelType), pointer :: mp => null()
1325  !
1326  ! -- outer iteration csv header
1327  if (this%icsvouterout > 0) then
1328  write (this%icsvouterout, '(*(G0,:,","))') &
1329  'total_inner_iterations', 'totim', 'kper', 'kstp', 'nouter', &
1330  'inner_iterations', 'solution_outer_dvmax', &
1331  'solution_outer_dvmax_model', 'solution_outer_dvmax_package', &
1332  'solution_outer_dvmax_node'
1333  end if
1334  !
1335  ! -- inner iteration csv header
1336  if (this%icsvinnerout > 0) then
1337  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1338  'total_inner_iterations', 'totim', 'kper', 'kstp', 'nouter', &
1339  'ninner', 'solution_inner_dvmax', 'solution_inner_dvmax_model', &
1340  'solution_inner_dvmax_node'
1341  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1342  '', 'solution_inner_rmax', 'solution_inner_rmax_model', &
1343  'solution_inner_rmax_node'
1344  ! solver items specific to ims solver
1345  if (this%linsolver == ims_solver) then
1346  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1347  '', 'solution_inner_alpha'
1348  if (this%imslinear%ilinmeth == 2) then
1349  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1350  '', 'solution_inner_omega'
1351  end if
1352  end if
1353  ! -- check for more than one model - ims only
1354  if (this%convnmod > 1 .or. simulation_mode == "PARALLEL") then
1355  do im = 1, this%modellist%Count()
1356  mp => getnumericalmodelfromlist(this%modellist, im)
1357  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1358  '', trim(adjustl(mp%name))//'_inner_dvmax', &
1359  trim(adjustl(mp%name))//'_inner_dvmax_node', &
1360  trim(adjustl(mp%name))//'_inner_rmax', &
1361  trim(adjustl(mp%name))//'_inner_rmax_node'
1362  end do
1363  end if
1364  write (this%icsvinnerout, '(a)') ''
1365  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 1373 of file NumericalSolution.f90.

1374  ! -- dummy variables
1375  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1376  integer(I4B), intent(in) :: kper !< current stress period number
1377  ! -- local variable
1378  integer(I4B) :: n, im, iallowptc, iptc
1379  class(NumericalModelType), pointer :: mp => null()
1380 
1381  ! -- determine if PTC will be used in any model
1382  n = 1
1383  do im = 1, this%modellist%Count()
1384  !
1385  ! -- set iallowptc
1386  ! -- no_ptc_option is FIRST
1387  if (this%iallowptc < 0) then
1388  if (kper > 1) then
1389  iallowptc = 1
1390  else
1391  iallowptc = 0
1392  end if
1393  ! -- no_ptc_option is ALL (0) or using PTC (1)
1394  else
1395  iallowptc = this%iallowptc
1396  end if
1397 
1398  if (iallowptc > 0) then
1399  mp => getnumericalmodelfromlist(this%modellist, im)
1400  call mp%model_ptcchk(iptc)
1401  else
1402  iptc = 0
1403  end if
1404 
1405  if (iptc /= 0) then
1406  if (n == 1) then
1407  write (iout, '(//)')
1408  n = 0
1409  end if
1410  write (iout, '(1x,a,1x,i0,1x,3a)') &
1411  'PSEUDO-TRANSIENT CONTINUATION WILL BE APPLIED TO MODEL', im, '("', &
1412  trim(adjustl(mp%name)), '") DURING THIS TIME STEP'
1413  end if
1414  end do
1415 
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