MODFLOW 6  version 6.7.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)
 @ 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...
 
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 2248 of file NumericalSolution.f90.

2249  ! -- dummy variables
2250  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2251  class(BaseExchangeType), pointer, intent(in) :: exchange !< model exchange instance
2252  ! -- local variables
2253  class(NumericalExchangeType), pointer :: num_ex => null()
2254  !
2255  ! -- add exchange
2256  select type (exchange)
2257  class is (numericalexchangetype)
2258  num_ex => exchange
2259  call addnumericalexchangetolist(this%exchangelist, num_ex)
2260  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 2213 of file NumericalSolution.f90.

2214  ! -- dummy variables
2215  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2216  class(BaseModelType), pointer, intent(in) :: mp !< model instance
2217  ! -- local variables
2218  class(NumericalModelType), pointer :: m => null()
2219  !
2220  ! -- add a model
2221  select type (mp)
2222  class is (numericalmodeltype)
2223  m => mp
2224  call addnumericalmodeltolist(this%modellist, m)
2225  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 366 of file NumericalSolution.f90.

367  ! -- modules
369  ! -- dummy variables
370  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
371  ! -- local variables
372  class(NumericalModelType), pointer :: mp => null()
373  integer(I4B) :: i
374  integer(I4B) :: ieq
375  !
376  ! -- initialize the number of models in the solution
377  this%convnmod = this%modellist%Count()
378  !
379  ! -- allocate arrays
380  call mem_allocate(this%active, this%neq, 'IACTIVE', this%memory_path)
381  call mem_allocate(this%xtemp, this%neq, 'XTEMP', this%memory_path)
382  call mem_allocate(this%dxold, this%neq, 'DXOLD', this%memory_path)
383  call mem_allocate(this%hncg, 0, 'HNCG', this%memory_path)
384  call mem_allocate(this%lrch, 3, 0, 'LRCH', this%memory_path)
385  call mem_allocate(this%wsave, 0, 'WSAVE', this%memory_path)
386  call mem_allocate(this%hchold, 0, 'HCHOLD', this%memory_path)
387  call mem_allocate(this%deold, 0, 'DEOLD', this%memory_path)
388  call mem_allocate(this%convmodstart, this%convnmod + 1, 'CONVMODSTART', &
389  this%memory_path)
390  !
391  ! -- initialize allocated arrays
392  do i = 1, this%neq
393  this%xtemp(i) = dzero
394  this%dxold(i) = dzero
395  this%active(i) = 1 !default is active
396  end do
397  !
398  ! -- initialize convmodstart
399  ieq = 1
400  this%convmodstart(1) = ieq
401  do i = 1, this%modellist%Count()
402  mp => getnumericalmodelfromlist(this%modellist, i)
403  ieq = ieq + mp%neq
404  this%convmodstart(i + 1) = ieq
405  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 268 of file NumericalSolution.f90.

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

◆ apply_backtracking()

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

Definition at line 2776 of file NumericalSolution.f90.

2777  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2778  ! local
2779  integer(I4B) :: n
2780  real(DP) :: delx
2781 
2782  do n = 1, this%neq
2783  if (this%active(n) < 1) cycle
2784  delx = this%breduc * (this%x(n) - this%xtemp(n))
2785  this%x(n) = this%xtemp(n) + delx
2786  end do
2787 

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

3251  ! -- dummy variables
3252  class(*), pointer, intent(inout) :: obj !< generic object
3253  ! -- return variable
3254  class(NumericalSolutionType), pointer :: res !< output NumericalSolutionType
3255  !
3256  ! -- initialize return variable
3257  res => null()
3258  !
3259  ! -- determine if obj is associated
3260  if (.not. associated(obj)) return
3261  !
3262  ! -- set res
3263  select type (obj)
3264  class is (numericalsolutiontype)
3265  res => obj
3266  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 1944 of file NumericalSolution.f90.

1945  ! -- modules
1946  use inputoutputmodule, only: getunit
1947  ! -- dummy variables
1948  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1949  integer(I4B), intent(in) :: iu !< file unit number for summary file
1950  integer(I4B), intent(in) :: im !< model number
1951  integer(I4B), intent(in) :: itertot_timestep !< total iteration for the time step
1952  ! -- local variables
1953  character(len=LINELENGTH) :: title
1954  character(len=LINELENGTH) :: tag
1955  character(len=LENPAKLOC) :: loc_dvmax_str
1956  character(len=LENPAKLOC) :: loc_rmax_str
1957  integer(I4B) :: ntabrows
1958  integer(I4B) :: ntabcols
1959  integer(I4B) :: iinner
1960  integer(I4B) :: i0
1961  integer(I4B) :: iouter
1962  integer(I4B) :: j
1963  integer(I4B) :: k
1964  integer(I4B) :: locdv
1965  integer(I4B) :: locdr
1966  real(DP) :: dv !< the maximum change in the dependent variable
1967  real(DP) :: res !< the maximum value of the residual vector
1968  !
1969  ! -- initialize local variables
1970  loc_dvmax_str = ''
1971  loc_rmax_str = ''
1972  iouter = 1
1973  locdv = 0
1974  locdr = 0
1975  !
1976  ! -- initialize inner iteration summary table
1977  if (.not. associated(this%innertab)) then
1978  !
1979  ! -- create outer iteration table
1980  ! -- table dimensions
1981  ntabrows = itertot_timestep
1982  ntabcols = 7
1983  !
1984  ! -- initialize table and define columns
1985  title = trim(this%memory_path)//' INNER ITERATION SUMMARY'
1986  call table_cr(this%innertab, this%name, title)
1987  call this%innertab%table_df(ntabrows, ntabcols, iu)
1988  tag = 'TOTAL ITERATION'
1989  call this%innertab%initialize_column(tag, 10, alignment=tabright)
1990  tag = 'OUTER ITERATION'
1991  call this%innertab%initialize_column(tag, 10, alignment=tabright)
1992  tag = 'INNER ITERATION'
1993  call this%innertab%initialize_column(tag, 10, alignment=tabright)
1994  tag = 'MAXIMUM CHANGE'
1995  call this%innertab%initialize_column(tag, 15, alignment=tabright)
1996  tag = 'MAXIMUM CHANGE MODEL-(CELLID)'
1997  call this%innertab%initialize_column(tag, lenpakloc, alignment=tabright)
1998  tag = 'MAXIMUM RESIDUAL'
1999  call this%innertab%initialize_column(tag, 15, alignment=tabright)
2000  tag = 'MAXIMUM RESIDUAL MODEL-(CELLID)'
2001  call this%innertab%initialize_column(tag, lenpakloc, alignment=tabright)
2002  !
2003  ! -- reset the output unit and the number of rows (maxbound)
2004  else
2005  call this%innertab%set_maxbound(itertot_timestep)
2006  call this%innertab%set_iout(iu)
2007  end if
2008  !
2009  ! -- write the inner iteration summary to unit iu
2010  i0 = 0
2011  do k = 1, itertot_timestep
2012  iinner = this%cnvg_summary%itinner(k)
2013  if (iinner <= i0) then
2014  iouter = iouter + 1
2015  end if
2016  if (im > this%convnmod) then
2017  dv = dzero
2018  res = dzero
2019  do j = 1, this%convnmod
2020  if (abs(this%cnvg_summary%convdvmax(j, k)) > abs(dv)) then
2021  locdv = this%cnvg_summary%convlocdv(j, k)
2022  dv = this%cnvg_summary%convdvmax(j, k)
2023  end if
2024  if (abs(this%cnvg_summary%convrmax(j, k)) > abs(res)) then
2025  locdr = this%cnvg_summary%convlocr(j, k)
2026  res = this%cnvg_summary%convrmax(j, k)
2027  end if
2028  end do
2029  else
2030  locdv = this%cnvg_summary%convlocdv(im, k)
2031  locdr = this%cnvg_summary%convlocr(im, k)
2032  dv = this%cnvg_summary%convdvmax(im, k)
2033  res = this%cnvg_summary%convrmax(im, k)
2034  end if
2035  call this%sln_get_loc(locdv, loc_dvmax_str)
2036  call this%sln_get_loc(locdr, loc_rmax_str)
2037  !
2038  ! -- add data to innertab
2039  call this%innertab%add_term(k)
2040  call this%innertab%add_term(iouter)
2041  call this%innertab%add_term(iinner)
2042  call this%innertab%add_term(dv)
2043  call this%innertab%add_term(adjustr(trim(loc_dvmax_str)))
2044  call this%innertab%add_term(res)
2045  call this%innertab%add_term(adjustr(trim(loc_rmax_str)))
2046  !
2047  ! -- update i0
2048  i0 = iinner
2049  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 221 of file NumericalSolution.f90.

222  ! -- modules
223  use simvariablesmodule, only: iout
225  ! -- dummy variables
226  class(NumericalSolutionType), pointer :: num_sol !< the create solution
227  character(len=*), intent(in) :: filename !< solution input file name
228  integer(I4B), intent(in) :: id !< solution id
229  ! -- local variables
230  integer(I4B) :: inunit
231  class(BaseSolutionType), pointer :: solbase => null()
232  character(len=LENSOLUTIONNAME) :: solutionname
233  !
234  ! -- Create a new solution and add it to the basesolutionlist container
235  solbase => num_sol
236  write (solutionname, '(a, i0)') 'SLN_', id
237  !
238  num_sol%name = solutionname
239  num_sol%memory_path = create_mem_path(solutionname)
240  allocate (num_sol%modellist)
241  allocate (num_sol%exchangelist)
242  !
243  call num_sol%allocate_scalars()
244  !
245  call addbasesolutiontolist(basesolutionlist, solbase)
246  !
247  num_sol%id = id
248  !
249  ! -- Open solution input file for reading later after problem size is known
250  ! Check to see if the file is already opened, which can happen when
251  ! running in single model mode
252  inquire (file=filename, number=inunit)
253 
254  if (inunit < 0) inunit = getunit()
255  num_sol%iu = inunit
256  write (iout, '(/a,a)') ' Creating solution: ', num_sol%name
257  call openfile(num_sol%iu, iout, filename, 'IMS')
258  !
259  ! -- Initialize block parser
260  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 2057 of file NumericalSolution.f90.

2059  ! -- modules
2060  use inputoutputmodule, only: getunit
2061  ! -- dummy variables
2062  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2063  integer(I4B), intent(in) :: iu !< file unit number
2064  real(DP), intent(in) :: totim !< total simulation time
2065  integer(I4B), intent(in) :: kper !< stress period number
2066  integer(I4B), intent(in) :: kstp !< time step number
2067  integer(I4B), intent(in) :: kouter !< number of outer (Picard) iterations
2068  integer(I4B), intent(in) :: niter !< number of inner iteration in this time step
2069  integer(I4B), intent(in) :: istart !< starting iteration number for this time step
2070  integer(I4B), intent(in) :: kstart !< starting position in the conv* arrays
2071  ! -- local
2072  integer(I4B) :: itot
2073  integer(I4B) :: m_idx, j, k
2074  integer(I4B) :: kpos
2075  integer(I4B) :: loc_dvmax !< solution node number (row) of max. dep. var. change
2076  integer(I4B) :: loc_rmax !< solution node number (row) of max. residual
2077  integer(I4B) :: model_id, node_user
2078  real(DP) :: dvmax !< maximum dependent variable change
2079  real(DP) :: rmax !< maximum residual
2080  class(NumericalModelType), pointer :: num_mod => null()
2081  !
2082  ! -- initialize local variables
2083  itot = istart
2084  !
2085  ! -- write inner iteration results to the inner csv output file
2086  do k = 1, niter
2087  kpos = kstart + k - 1
2088  write (iu, '(*(G0,:,","))', advance='NO') &
2089  itot, totim, kper, kstp, kouter, k
2090  !
2091  ! -- solution summary
2092  dvmax = dzero
2093  rmax = dzero
2094  do j = 1, this%convnmod
2095  if (abs(this%cnvg_summary%convdvmax(j, kpos)) > abs(dvmax)) then
2096  loc_dvmax = this%cnvg_summary%convlocdv(j, kpos)
2097  dvmax = this%cnvg_summary%convdvmax(j, kpos)
2098  end if
2099  if (abs(this%cnvg_summary%convrmax(j, kpos)) > abs(rmax)) then
2100  loc_rmax = this%cnvg_summary%convlocr(j, kpos)
2101  rmax = this%cnvg_summary%convrmax(j, kpos)
2102  end if
2103  end do
2104  !
2105  ! -- no change, could be anywhere
2106  if (dvmax == dzero) loc_dvmax = 0
2107  if (rmax == dzero) loc_rmax = 0
2108  !
2109  ! -- get model number and user node number for max. dep. var. change
2110  if (loc_dvmax > 0) then
2111  call this%sln_get_nodeu(loc_dvmax, m_idx, node_user)
2112  num_mod => getnumericalmodelfromlist(this%modellist, m_idx)
2113  model_id = num_mod%id
2114  else
2115  model_id = 0
2116  node_user = 0
2117  end if
2118  write (iu, '(*(G0,:,","))', advance='NO') '', dvmax, model_id, node_user
2119  !
2120  ! -- get model number and user node number for max. residual
2121  if (loc_rmax > 0) then
2122  call this%sln_get_nodeu(loc_rmax, m_idx, node_user)
2123  num_mod => getnumericalmodelfromlist(this%modellist, m_idx)
2124  model_id = num_mod%id
2125  else
2126  model_id = 0
2127  node_user = 0
2128  end if
2129  write (iu, '(*(G0,:,","))', advance='NO') '', rmax, model_id, node_user
2130  !
2131  ! -- write ims acceleration parameters
2132  if (this%linsolver == ims_solver) then
2133  write (iu, '(*(G0,:,","))', advance='NO') &
2134  '', trim(adjustl(this%caccel(kpos)))
2135  end if
2136  !
2137  ! -- write information for each model
2138  if (this%convnmod > 1 .or. simulation_mode == "PARALLEL") then
2139  do j = 1, this%cnvg_summary%convnmod
2140  loc_dvmax = this%cnvg_summary%convlocdv(j, kpos)
2141  dvmax = this%cnvg_summary%convdvmax(j, kpos)
2142  loc_rmax = this%cnvg_summary%convlocr(j, kpos)
2143  rmax = this%cnvg_summary%convrmax(j, kpos)
2144  !
2145  ! -- get model number and user node number for max. dep. var. change
2146  if (loc_dvmax > 0) then
2147  call this%sln_get_nodeu(loc_dvmax, m_idx, node_user)
2148  else
2149  node_user = 0
2150  end if
2151  write (iu, '(*(G0,:,","))', advance='NO') '', dvmax, node_user
2152  !
2153  ! -- get model number and user node number for max. residual
2154  if (loc_rmax > 0) then
2155  call this%sln_get_nodeu(loc_rmax, m_idx, node_user)
2156  else
2157  node_user = 0
2158  end if
2159  write (iu, '(*(G0,:,","))', advance='NO') '', rmax, node_user
2160  end do
2161  end if
2162  !
2163  ! -- write line
2164  write (iu, '(a)') ''
2165  !
2166  ! -- update itot
2167  itot = itot + 1
2168  end do
2169  !
2170  ! -- flush file
2171  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 1805 of file NumericalSolution.f90.

1806  ! -- modules
1807  use tdismodule, only: kper, kstp
1808  ! -- dummy variables
1809  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1810  integer(I4B), intent(in) :: kiter !< Picard iteration number after convergence or failure
1811  integer(I4B), intent(inout) :: isgcnvg !< solution group convergence flag
1812  integer(I4B), intent(in) :: isuppress_output !< flag for suppressing output
1813  ! -- local variables
1814  integer(I4B) :: ic, im
1815  class(NumericalModelType), pointer :: mp => null()
1816  class(NumericalExchangeType), pointer :: cp => null()
1817  ! -- formats for convergence info
1818  character(len=*), parameter :: fmtnocnvg = &
1819  "(1X,'Solution ', i0, ' did not converge for stress period ', i0, &
1820  &' and time step ', i0)"
1821  character(len=*), parameter :: fmtcnvg = &
1822  "(1X, I0, ' CALLS TO NUMERICAL SOLUTION ', 'IN TIME STEP ', I0, &
1823  &' STRESS PERIOD ',I0,/1X,I0,' TOTAL ITERATIONS')"
1824  !
1825  ! -- finalize the outer iteration table
1826  if (this%iprims > 0) then
1827  call this%outertab%finalize_table()
1828  end if
1829  !
1830  ! -- write convergence info
1831  !
1832  ! -- convergence was achieved
1833  if (this%icnvg /= 0) then
1834  if (this%iprims > 0) then
1835  write (iout, fmtcnvg) kiter, kstp, kper, this%itertot_timestep
1836  end if
1837  !
1838  ! -- convergence was not achieved
1839  else
1840  write (iout, fmtnocnvg) this%id, kper, kstp
1841  end if
1842  !
1843  ! -- write inner iteration convergence summary
1844  if (this%iprims == 2) then
1845  !
1846  ! -- write summary for each model
1847  do im = 1, this%modellist%Count()
1848  mp => getnumericalmodelfromlist(this%modellist, im)
1849  call this%convergence_summary(mp%iout, im, this%itertot_timestep)
1850  end do
1851  !
1852  ! -- write summary for entire solution
1853  call this%convergence_summary(iout, this%convnmod + 1, &
1854  this%itertot_timestep)
1855  end if
1856  !
1857  ! -- set solution group convergence flag
1858  if (this%icnvg == 0) isgcnvg = 0
1859  !
1860  ! -- Calculate flow for each model
1861  do im = 1, this%modellist%Count()
1862  mp => getnumericalmodelfromlist(this%modellist, im)
1863  call mp%model_cq(this%icnvg, isuppress_output)
1864  end do
1865  !
1866  ! -- Calculate flow for each exchange
1867  do ic = 1, this%exchangelist%Count()
1868  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1869  call cp%exg_cq(isgcnvg, isuppress_output, this%id)
1870  end do
1871  !
1872  ! -- Budget terms for each model
1873  do im = 1, this%modellist%Count()
1874  mp => getnumericalmodelfromlist(this%modellist, im)
1875  call mp%model_bd(this%icnvg, isuppress_output)
1876  end do
1877  !
1878  ! -- Budget terms for each exchange
1879  do ic = 1, this%exchangelist%Count()
1880  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1881  call cp%exg_bd(isgcnvg, isuppress_output, this%id)
1882  end do
1883 
integer(i4b), pointer, public kstp
current time step number
Definition: tdis.f90:24
integer(i4b), pointer, public kper
current stress period number
Definition: tdis.f90:23
Here is the call graph for this function:

◆ get_backtracking_flag()

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

Definition at line 2746 of file NumericalSolution.f90.

2747  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2748  integer(I4B) :: bt_flag !< backtracking flag (1) backtracking performed (0) backtracking not performed
2749  ! local
2750  integer(I4B) :: n
2751  real(DP) :: dx
2752  real(DP) :: dx_abs
2753  real(DP) :: dx_abs_max
2754 
2755  ! default is off
2756  bt_flag = 0
2757 
2758  ! find max. change
2759  dx_abs_max = 0.0
2760  do n = 1, this%neq
2761  if (this%active(n) < 1) cycle
2762  dx = this%x(n) - this%xtemp(n)
2763  dx_abs = abs(dx)
2764  if (dx_abs > dx_abs_max) dx_abs_max = dx_abs
2765  end do
2766 
2767  ! if backtracking, set flag
2768  if (this%breduc * dx_abs_max >= this%dvclose) then
2769  bt_flag = 1
2770  end if
2771 

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

2266  class(NumericalSolutionType) :: this !< instance of the numerical solution
2267  type(ListType), pointer :: exchanges !< pointer to the exchange list
2268 
2269  exchanges => this%exchangelist
2270 

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

2234  ! -- return variable
2235  type(ListType), pointer :: models !< pointer to the model list
2236  ! -- dummy variables
2237  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2238 
2239  models => this%modellist
2240 

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

3275  ! -- dummy variables
3276  type(ListType), intent(inout) :: list !< list of numerical solutions
3277  integer(I4B), intent(in) :: idx !< value to retrieve from the list
3278  ! -- return variables
3279  class(NumericalSolutionType), pointer :: res !< numerical solution
3280  ! -- local variables
3281  class(*), pointer :: obj
3282  !
3283  obj => list%GetItem(idx)
3284  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 1415 of file NumericalSolution.f90.

1416  ! -- dummy variables
1417  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1418  ! -- local variables
1419  integer(I4B) :: ic
1420  integer(I4B) :: im
1421  class(NumericalExchangeType), pointer :: cp => null()
1422  class(NumericalModelType), pointer :: mp => null()
1423 
1424  ! synchronize for AD
1425  call this%synchronize(stg_bfr_exg_ad, this%synchronize_ctx)
1426 
1427  ! -- Exchange advance
1428  do ic = 1, this%exchangelist%Count()
1429  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1430  call cp%exg_ad()
1431  end do
1432 
1433  ! -- Model advance
1434  do im = 1, this%modellist%Count()
1435  mp => getnumericalmodelfromlist(this%modellist, im)
1436  call mp%model_ad()
1437  end do
1438 
1439  ! advance solution
1440  call this%sln_ad()
1441 
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 2180 of file NumericalSolution.f90.

2181  use sparsematrixmodule
2182  ! -- modules
2183  use inputoutputmodule, only: getunit
2184  ! -- dummy variables
2185  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2186  character(len=*), intent(in) :: filename !< filename to save solution data
2187  ! -- local variables
2188  integer(I4B) :: inunit
2189  !
2190  select type (spm => this%system_matrix)
2191  class is (sparsematrixtype)
2192  inunit = getunit()
2193  open (unit=inunit, file=filename, status='unknown')
2194  write (inunit, *) 'ia'
2195  write (inunit, *) spm%ia
2196  write (inunit, *) 'ja'
2197  write (inunit, *) spm%ja
2198  write (inunit, *) 'amat'
2199  write (inunit, *) spm%amat
2200  write (inunit, *) 'rhs'
2201  write (inunit, *) this%rhs
2202  write (inunit, *) 'x'
2203  write (inunit, *) this%x
2204  close (inunit)
2205  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 1090 of file NumericalSolution.f90.

1091  ! -- modules
1092  use tdismodule, only: kstp, kper
1093  ! -- dummy variables
1094  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1095  !
1096  ! -- write headers to CSV file
1097  if (kper == 1 .and. kstp == 1) then
1098  call this%writeCSVHeader()
1099  end if
1100 
1101  ! write PTC info on models to iout
1102  call this%writePTCInfoToFile(kper)
1103 
1104  ! reset convergence flag and inner solve counter
1105  this%icnvg = 0
1106  this%itertot_timestep = 0
1107  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 503 of file NumericalSolution.f90.

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

2627  ! -- dummy variables
2628  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2629  class(NumericalModelType), pointer :: mp !< model pointer (currently null())
2630  class(NumericalExchangeType), pointer :: cp !< exchange pointer (currently null())
2631  integer(I4B), intent(in) :: kiter !< Picard iteration number
2632  ! -- local variables
2633  character(len=7) :: cmsg
2634  integer(I4B) :: nb
2635  integer(I4B) :: btflag
2636  integer(I4B) :: ibflag
2637  integer(I4B) :: ibtcnt
2638  real(DP) :: resin
2639  !
2640  ! -- initialize local variables
2641  ibflag = 0
2642 
2643  !
2644  ! -- refill amat and rhs with standard conductance
2645  call this%sln_buildsystem(kiter, inewton=0)
2646 
2647  !
2648  ! -- calculate initial l2 norm
2649  if (kiter == 1) then
2650  call this%sln_l2norm(this%res_prev)
2651  resin = this%res_prev
2652  ibflag = 0
2653  else
2654  call this%sln_l2norm(this%res_new)
2655  resin = this%res_new
2656  end if
2657  ibtcnt = 0
2658  if (kiter > 1) then
2659  if (this%res_new > this%res_prev * this%btol) then
2660  !
2661  ! -- iterate until backtracking complete
2662  btloop: do nb = 1, this%numtrack
2663  !
2664  ! -- backtrack the dependent variable
2665  call this%sln_backtracking_xupdate(btflag)
2666  !
2667  ! -- dependent-variable change less than dvclose
2668  if (btflag == 0) then
2669  ibflag = 4
2670  exit btloop
2671  end if
2672  !
2673  ibtcnt = nb
2674 
2675  ! recalculate linear system (amat and rhs)
2676  call this%sln_buildsystem(kiter, inewton=0)
2677 
2678  !
2679  ! -- calculate updated l2norm
2680  call this%sln_l2norm(this%res_new)
2681  !
2682  ! -- evaluate if back tracking can be terminated
2683  if (nb == this%numtrack) then
2684  ibflag = 2
2685  exit btloop
2686  end if
2687  if (this%res_new < this%res_prev * this%btol) then
2688  ibflag = 1
2689  exit btloop
2690  end if
2691  if (this%res_new < this%res_lim) then
2692  exit btloop
2693  end if
2694  end do btloop
2695  end if
2696  ! -- save new residual
2697  this%res_prev = this%res_new
2698  end if
2699  !
2700  ! -- write back backtracking results
2701  if (this%iprims > 0) then
2702  if (ibtcnt > 0) then
2703  cmsg = ' '
2704  else
2705  cmsg = '*'
2706  end if
2707  !
2708  ! -- add data to outertab
2709  call this%outertab%add_term('Backtracking')
2710  call this%outertab%add_term(kiter)
2711  call this%outertab%add_term(' ')
2712  if (this%numtrack > 0) then
2713  call this%outertab%add_term(ibflag)
2714  call this%outertab%add_term(ibtcnt)
2715  call this%outertab%add_term(resin)
2716  call this%outertab%add_term(this%res_prev)
2717  end if
2718  call this%outertab%add_term(' ')
2719  call this%outertab%add_term(cmsg)
2720  call this%outertab%add_term(' ')
2721  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 2730 of file NumericalSolution.f90.

2731  ! -- dummy variables
2732  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2733  integer(I4B), intent(inout) :: bt_flag !< backtracking flag (1) backtracking performed (0) backtracking not performed
2734 
2735  bt_flag = this%get_backtracking_flag()
2736 
2737  ! perform backtracking if ...
2738  if (bt_flag > 0) then
2739  call this%apply_backtracking()
2740  end if
2741 

◆ sln_buildsystem()

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

Definition at line 1887 of file NumericalSolution.f90.

1888  class(NumericalSolutionType) :: this
1889  integer(I4B), intent(in) :: kiter
1890  integer(I4B), intent(in) :: inewton
1891  ! local
1892  integer(I4B) :: im, ic
1893  class(NumericalModelType), pointer :: mp
1894  class(NumericalExchangeType), pointer :: cp
1895  !
1896  ! -- Set amat and rhs to zero
1897  call this%sln_reset()
1898 
1899  ! reset models
1900  do im = 1, this%modellist%Count()
1901  mp => getnumericalmodelfromlist(this%modellist, im)
1902  call mp%model_reset()
1903  end do
1904 
1905  ! synchronize for CF
1906  call this%synchronize(stg_bfr_exg_cf, this%synchronize_ctx)
1907 
1908  !
1909  ! -- Calculate the matrix terms for each exchange
1910  do ic = 1, this%exchangelist%Count()
1911  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1912  call cp%exg_cf(kiter)
1913  end do
1914  !
1915  ! -- Calculate the matrix terms for each model
1916  do im = 1, this%modellist%Count()
1917  mp => getnumericalmodelfromlist(this%modellist, im)
1918  call mp%model_cf(kiter)
1919  end do
1920 
1921  ! synchronize for FC
1922  call this%synchronize(stg_bfr_exg_fc, this%synchronize_ctx)
1923 
1924  !
1925  ! -- Add exchange coefficients to the solution
1926  do ic = 1, this%exchangelist%Count()
1927  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1928  call cp%exg_fc(kiter, this%system_matrix, this%rhs, inewton)
1929  end do
1930  !
1931  ! -- Add model coefficients to the solution
1932  do im = 1, this%modellist%Count()
1933  mp => getnumericalmodelfromlist(this%modellist, im)
1934  call mp%model_fc(kiter, this%system_matrix, inewton)
1935  end do
1936 
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 1265 of file NumericalSolution.f90.

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

2883  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2884  integer(I4B) :: iptc !< PTC (1) or not (0)
2885  real(DP) :: ptcf !< the PTC factor calculated
2886  ! local
2887  integer(I4B) :: im
2888  class(NumericalModelType), pointer :: mp
2889  class(VectorBaseType), pointer :: vec_resid
2890 
2891  iptc = 0
2892  ptcf = dzero
2893 
2894  ! calc. residual vector
2895  vec_resid => this%system_matrix%create_vec(this%neq)
2896  call this%sln_calc_residual(vec_resid)
2897 
2898  ! determine ptc
2899  do im = 1, this%modellist%Count()
2900  mp => getnumericalmodelfromlist(this%modellist, im)
2901  call mp%model_ptc(vec_resid, iptc, ptcf)
2902  end do
2903 
2904  ! clean up temp. vector
2905  call vec_resid%destroy()
2906  deallocate (vec_resid)
2907 
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 2912 of file NumericalSolution.f90.

2913  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2914  class(VectorBaseType), pointer :: vec_resid !< the residual vector
2915  ! local
2916  integer(I4B) :: n
2917 
2918  call this%system_matrix%multiply(this%vec_x, vec_resid) ! r = A*x
2919 
2920  call vec_resid%axpy(-1.0_dp, this%vec_rhs) ! r = r - b
2921 
2922  do n = 1, this%neq
2923  if (this%active(n) < 1) then
2924  call vec_resid%set_value_local(n, 0.0_dp) ! r_i = 0 if inactive
2925  end if
2926  end do
2927 

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

2859  ! -- dummy variables
2860  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2861  integer(I4B), intent(in) :: neq !< number of equations
2862  integer(I4B), dimension(neq), intent(in) :: active !< active cell flag (1)
2863  real(DP), dimension(neq), intent(in) :: x !< current dependent-variable
2864  real(DP), dimension(neq), intent(in) :: xtemp !< previous dependent-variable
2865  real(DP), dimension(neq), intent(inout) :: dx !< dependent-variable change
2866  ! -- local
2867  integer(I4B) :: n
2868  !
2869  ! -- calculate dependent-variable change
2870  do n = 1, neq
2871  ! -- skip inactive nodes
2872  if (active(n) < 1) then
2873  dx(n) = dzero
2874  else
2875  dx(n) = x(n) - xtemp(n)
2876  end if
2877  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 2282 of file NumericalSolution.f90.

2283  ! -- modules
2285  ! -- dummy variables
2286  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2287  ! -- local variables
2288  class(NumericalModelType), pointer :: mp => null()
2289  class(NumericalExchangeType), pointer :: cp => null()
2290  integer(I4B) :: im
2291  integer(I4B) :: ic
2292  !
2293  ! -- Add internal model connections to sparse
2294  do im = 1, this%modellist%Count()
2295  mp => getnumericalmodelfromlist(this%modellist, im)
2296  call mp%model_ac(this%sparse)
2297  end do
2298  !
2299  ! -- synchronize before AC
2300  call this%synchronize(stg_bfr_exg_ac, this%synchronize_ctx)
2301  !
2302  ! -- Add the cross terms to sparse
2303  do ic = 1, this%exchangelist%Count()
2304  cp => getnumericalexchangefromlist(this%exchangelist, ic)
2305  call cp%exg_ac(this%sparse)
2306  end do
2307  !
2308  ! -- The number of non-zero array values are now known so
2309  ! -- ia and ja can be created from sparse. then destroy sparse
2310  call this%sparse%sort()
2311  call this%system_matrix%init(this%sparse, this%name)
2312  call this%sparse%destroy()
2313  !
2314  ! -- Create mapping arrays for each model. Mapping assumes
2315  ! -- that each row has the diagonal in the first position,
2316  ! -- however, rows do not need to be sorted.
2317  do im = 1, this%modellist%Count()
2318  mp => getnumericalmodelfromlist(this%modellist, im)
2319  call mp%model_mc(this%system_matrix)
2320  end do
2321  !
2322  ! -- Create arrays for mapping exchange connections to global solution
2323  do ic = 1, this%exchangelist%Count()
2324  cp => getnumericalexchangefromlist(this%exchangelist, ic)
2325  call cp%exg_mc(this%system_matrix)
2326  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 1149 of file NumericalSolution.f90.

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

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

418  ! modules
421  ! -- dummy variables
422  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
423  ! -- local variables
424  class(NumericalModelType), pointer :: mp => null()
425  integer(I4B) :: i
426  integer(I4B), allocatable, dimension(:) :: rowmaxnnz
427  integer(I4B) :: ncol, irow_start, irow_end
428  integer(I4B) :: mod_offset
429  !
430  ! -- set sol id and determine nr. of equation in this solution
431  do i = 1, this%modellist%Count()
432  mp => getnumericalmodelfromlist(this%modellist, i)
433  call mp%set_idsoln(this%id)
434  this%neq = this%neq + mp%neq
435  end do
436  !
437  ! -- set up the (possibly parallel) linear system
438  if (simulation_mode == 'PARALLEL') then
439  this%solver_mode = 'PETSC'
440  else
441  this%solver_mode = 'IMS'
442  end if
443  !
444  ! -- allocate settings structure
445  allocate (this%linear_settings)
446  !
447  ! -- create linear system matrix and compatible vectors
448  this%linear_solver => create_linear_solver(this%solver_mode, this%name)
449  this%system_matrix => this%linear_solver%create_matrix()
450  this%vec_x => this%system_matrix%create_vec_mm(this%neq, 'X', &
451  this%memory_path)
452  this%x => this%vec_x%get_array()
453  this%vec_rhs => this%system_matrix%create_vec_mm(this%neq, 'RHS', &
454  this%memory_path)
455  this%rhs => this%vec_rhs%get_array()
456  !
457  call this%vec_rhs%get_ownership_range(irow_start, irow_end)
458  ncol = this%vec_rhs%get_size()
459  !
460  ! -- calculate and set offsets
461  mod_offset = irow_start - 1
462  this%matrix_offset = irow_start - 1
463  do i = 1, this%modellist%Count()
464  mp => getnumericalmodelfromlist(this%modellist, i)
465  call mp%set_moffset(mod_offset)
466  mod_offset = mod_offset + mp%neq
467  end do
468  !
469  ! -- Allocate and initialize solution arrays
470  call this%allocate_arrays()
471  !
472  ! -- Create convergence summary report
473  allocate (this%cnvg_summary)
474  call this%cnvg_summary%init(this%modellist%Count(), this%convmodstart, &
475  this%memory_path)
476  !
477  ! -- Go through each model and point x, ibound, and rhs to solution
478  do i = 1, this%modellist%Count()
479  mp => getnumericalmodelfromlist(this%modellist, i)
480  call mp%set_xptr(this%x, this%matrix_offset, 'X', this%name)
481  call mp%set_rhsptr(this%rhs, this%matrix_offset, 'RHS', this%name)
482  call mp%set_iboundptr(this%active, this%matrix_offset, 'IBOUND', this%name)
483  end do
484  !
485  ! -- Create the sparsematrix instance
486  allocate (rowmaxnnz(this%neq))
487  do i = 1, this%neq
488  rowmaxnnz(i) = 4
489  end do
490  call this%sparse%init(this%neq, ncol, rowmaxnnz)
491  this%sparse%offset = this%matrix_offset
492  deallocate (rowmaxnnz)
493  !
494  ! -- Assign connections, fill ia/ja, map connections
495  call this%sln_connect()
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 1048 of file NumericalSolution.f90.

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

◆ sln_fp()

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

Finalize a solution.

Parameters
thisNumericalSolutionType instance

Definition at line 1127 of file NumericalSolution.f90.

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

3069  ! -- dummy variables
3070  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
3071  real(DP), intent(inout) :: hncg !< maximum dependent-variable change
3072  integer(I4B), intent(inout) :: lrch !< location of the maximum dependent-variable change
3073  ! -- local variables
3074  integer(I4B) :: nb
3075  real(DP) :: bigch
3076  real(DP) :: abigch
3077  integer(I4B) :: n
3078  real(DP) :: hdif
3079  real(DP) :: ahdif
3080  !
3081  ! -- determine the maximum change
3082  nb = 0
3083  bigch = dzero
3084  abigch = dzero
3085  do n = 1, this%neq
3086  if (this%active(n) < 1) cycle
3087  hdif = this%x(n) - this%xtemp(n)
3088  ahdif = abs(hdif)
3089  if (ahdif > abigch) then
3090  bigch = hdif
3091  abigch = ahdif
3092  nb = n
3093  end if
3094  end do
3095  !
3096  !-----store maximum change value and location
3097  hncg = bigch
3098  lrch = nb

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

3171  ! -- dummy variables
3172  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
3173  integer(I4B), intent(in) :: nodesln !< solution node number
3174  character(len=*), intent(inout) :: str !< string with user node number
3175  ! -- local variables
3176  class(NumericalModelType), pointer :: mp => null()
3177  integer(I4B) :: i
3178  integer(I4B) :: istart
3179  integer(I4B) :: iend
3180  integer(I4B) :: noder
3181  integer(I4B) :: nglo
3182  !
3183  ! -- initialize dummy variables
3184  str = ''
3185  !
3186  ! -- initialize local variables
3187  noder = 0
3188  !
3189  ! -- when parallel, account for offset
3190  nglo = nodesln + this%matrix_offset
3191  !
3192  ! -- calculate and set offsets
3193  do i = 1, this%modellist%Count()
3194  mp => getnumericalmodelfromlist(this%modellist, i)
3195  istart = 0
3196  iend = 0
3197  call mp%get_mrange(istart, iend)
3198  if (nglo >= istart .and. nglo <= iend) then
3199  noder = nglo - istart + 1
3200  call mp%get_mcellid(noder, str)
3201  exit
3202  end if
3203  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 3211 of file NumericalSolution.f90.

3212  ! -- dummy variables
3213  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
3214  integer(I4B), intent(in) :: nodesln !< solution node number
3215  integer(I4B), intent(inout) :: im !< solution model index (index in model list for this solution)
3216  integer(I4B), intent(inout) :: nodeu !< user node number
3217  ! -- local variables
3218  class(NumericalModelType), pointer :: mp => null()
3219  integer(I4B) :: i
3220  integer(I4B) :: istart
3221  integer(I4B) :: iend
3222  integer(I4B) :: noder, nglo
3223  !
3224  ! -- initialize local variables
3225  noder = 0
3226  !
3227  ! -- when parallel, account for offset
3228  nglo = nodesln + this%matrix_offset
3229  !
3230  ! -- calculate and set offsets
3231  do i = 1, this%modellist%Count()
3232  mp => getnumericalmodelfromlist(this%modellist, i)
3233  istart = 0
3234  iend = 0
3235  call mp%get_mrange(istart, iend)
3236  if (nglo >= istart .and. nglo <= iend) then
3237  noder = nglo - istart + 1
3238  call mp%get_mnodeu(noder, nodeu)
3239  im = i
3240  exit
3241  end if
3242  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 3101 of file NumericalSolution.f90.

3102  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3103  real(DP) :: max_dvc !< the maximum dependent variable change
3104  logical(LGP) :: has_converged !< True, when converged
3105 
3106  has_converged = .false.
3107  if (abs(max_dvc) <= this%dvclose) then
3108  has_converged = .true.
3109  end if
3110 

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

2802  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2803  real(DP) :: l2norm !< calculated L-2 norm
2804  ! local
2805  class(VectorBaseType), pointer :: vec_resid
2806 
2807  ! calc. residual vector
2808  vec_resid => this%system_matrix%create_vec(this%neq)
2809  call this%sln_calc_residual(vec_resid)
2810 
2811  ! 2-norm
2812  l2norm = vec_resid%norm2()
2813 
2814  ! clean up temp. vector
2815  call vec_resid%destroy()
2816  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 2350 of file NumericalSolution.f90.

2351  ! -- dummy variables
2352  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2353  integer(I4B), intent(in) :: kiter
2354  integer(I4B), intent(in) :: kstp
2355  integer(I4B), intent(in) :: kper
2356  integer(I4B), intent(inout) :: in_iter
2357  integer(I4B), intent(inout) :: iptc
2358  real(DP), intent(in) :: ptcf
2359  ! -- local variables
2360  logical(LGP) :: lsame
2361  integer(I4B) :: ieq
2362  integer(I4B) :: irow_glo
2363  integer(I4B) :: itestmat
2364  integer(I4B) :: ipos
2365  integer(I4B) :: icol_s
2366  integer(I4B) :: icol_e
2367  integer(I4B) :: jcol
2368  integer(I4B) :: iptct
2369  integer(I4B) :: iallowptc
2370  real(DP) :: adiag
2371  real(DP) :: diagval
2372  real(DP) :: l2norm
2373  real(DP) :: ptcval
2374  real(DP) :: bnorm
2375  character(len=50) :: fname
2376  character(len=*), parameter :: fmtfname = "('mf6mat_', i0, '_', i0, &
2377  &'_', i0, '_', i0, '.txt')"
2378  !
2379  ! -- take care of loose ends for all nodes before call to solver
2380  do ieq = 1, this%neq
2381  !
2382  ! -- get (global) cell id
2383  irow_glo = ieq + this%matrix_offset
2384  !
2385  ! -- store x in temporary location
2386  this%xtemp(ieq) = this%x(ieq)
2387  !
2388  ! -- make adjustments to the continuity equation for the node
2389  ! -- adjust small diagonal coefficient in an active cell
2390  if (this%active(ieq) > 0) then
2391  diagval = -done
2392  adiag = abs(this%system_matrix%get_diag_value(irow_glo))
2393  if (adiag < dem15) then
2394  call this%system_matrix%set_diag_value(irow_glo, diagval)
2395  this%rhs(ieq) = this%rhs(ieq) + diagval * this%x(ieq)
2396  end if
2397  ! -- Dirichlet boundary or no-flow cell
2398  else
2399  call this%system_matrix%set_diag_value(irow_glo, done)
2400  call this%system_matrix%zero_row_offdiag(irow_glo)
2401  this%rhs(ieq) = this%x(ieq)
2402  end if
2403  end do
2404  !
2405  ! -- complete adjustments for Dirichlet boundaries for a symmetric matrix
2406  if (this%isymmetric == 1 .and. simulation_mode == "SEQUENTIAL") then
2407  do ieq = 1, this%neq
2408  if (this%active(ieq) > 0) then
2409  icol_s = this%system_matrix%get_first_col_pos(ieq)
2410  icol_e = this%system_matrix%get_last_col_pos(ieq)
2411  do ipos = icol_s, icol_e
2412  jcol = this%system_matrix%get_column(ipos)
2413  if (jcol == ieq) cycle
2414  if (this%active(jcol) < 0) then
2415  this%rhs(ieq) = this%rhs(ieq) - &
2416  (this%system_matrix%get_value_pos(ipos) * &
2417  this%x(jcol))
2418  call this%system_matrix%set_value_pos(ipos, dzero)
2419  end if
2420 
2421  end do
2422  end if
2423  end do
2424  end if
2425  !
2426  ! -- pseudo transient continuation
2427  !
2428  ! -- set iallowptc
2429  ! -- no_ptc_option is FIRST
2430  if (this%iallowptc < 0) then
2431  if (kper > 1) then
2432  iallowptc = 1
2433  else
2434  iallowptc = 0
2435  end if
2436  !
2437  ! -- no_ptc_option is ALL (0) or using PTC (1)
2438  else
2439  iallowptc = this%iallowptc
2440  end if
2441  !
2442  ! -- set iptct
2443  iptct = iptc * iallowptc
2444  !
2445  ! -- calculate or modify pseudo transient continuation terms and add
2446  ! to amat diagonals
2447  if (iptct /= 0) then
2448  call this%sln_l2norm(l2norm)
2449  ! -- confirm that the l2norm exceeds previous l2norm
2450  ! if not, there is no need to add ptc terms
2451  if (kiter == 1) then
2452  if (kper > 1 .or. kstp > 1) then
2453  if (l2norm <= this%l2norm0) then
2454  iptc = 0
2455  end if
2456  end if
2457  else
2458  lsame = is_close(l2norm, this%l2norm0)
2459  if (lsame) then
2460  iptc = 0
2461  end if
2462  end if
2463  end if
2464  iptct = iptc * iallowptc
2465  if (iptct /= 0) then
2466  if (kiter == 1) then
2467  if (this%iptcout > 0) then
2468  write (this%iptcout, '(A10,6(1x,A15))') 'OUTER ITER', &
2469  ' PTCDEL', ' L2NORM0', ' L2NORM', &
2470  ' RHSNORM', ' 1/PTCDEL', ' RHSNORM/L2NORM'
2471  end if
2472  if (this%ptcdel0 > dzero) then
2473  this%ptcdel = this%ptcdel0
2474  else
2475  if (this%iptcopt == 0) then
2476  !
2477  ! -- ptcf is the reciprocal of the pseudo-time step
2478  this%ptcdel = done / ptcf
2479  else
2480  bnorm = dzero
2481  do ieq = 1, this%neq
2482  if (this%active(ieq) .gt. 0) then
2483  bnorm = bnorm + this%rhs(ieq) * this%rhs(ieq)
2484  end if
2485  end do
2486  bnorm = sqrt(bnorm)
2487  this%ptcdel = bnorm / l2norm
2488  end if
2489  end if
2490  else
2491  if (l2norm > dzero) then
2492  this%ptcdel = this%ptcdel * (this%l2norm0 / l2norm)**this%ptcexp
2493  else
2494  this%ptcdel = dzero
2495  end if
2496  end if
2497  if (this%ptcdel > dzero) then
2498  ptcval = done / this%ptcdel
2499  else
2500  ptcval = done
2501  end if
2502  bnorm = dzero
2503  do ieq = 1, this%neq
2504  irow_glo = ieq + this%matrix_offset
2505  if (this%active(ieq) > 0) then
2506  diagval = abs(this%system_matrix%get_diag_value(irow_glo))
2507  bnorm = bnorm + this%rhs(ieq) * this%rhs(ieq)
2508  call this%system_matrix%add_diag_value(irow_glo, -ptcval)
2509  this%rhs(ieq) = this%rhs(ieq) - ptcval * this%x(ieq)
2510  end if
2511  end do
2512  bnorm = sqrt(bnorm)
2513  if (this%iptcout > 0) then
2514  write (this%iptcout, '(i10,5(1x,e15.7),1(1x,f15.6))') &
2515  kiter, this%ptcdel, this%l2norm0, l2norm, bnorm, &
2516  ptcval, bnorm / l2norm
2517  end if
2518  this%l2norm0 = l2norm
2519  end if
2520  !
2521  ! -- save rhs, amat to a file
2522  ! to enable set itestmat to 1 and recompile
2523  !-------------------------------------------------------
2524  itestmat = 0
2525  if (itestmat == 1) then
2526  write (fname, fmtfname) this%id, kper, kstp, kiter
2527  print *, 'Saving amat to: ', trim(adjustl(fname))
2528 
2529  itestmat = getunit()
2530  open (itestmat, file=trim(adjustl(fname)))
2531  write (itestmat, *) 'NODE, RHS, AMAT FOLLOW'
2532  do ieq = 1, this%neq
2533  irow_glo = ieq + this%matrix_offset
2534  icol_s = this%system_matrix%get_first_col_pos(irow_glo)
2535  icol_e = this%system_matrix%get_last_col_pos(irow_glo)
2536  write (itestmat, '(*(G0,:,","))') &
2537  irow_glo, &
2538  this%rhs(ieq), &
2539  (this%system_matrix%get_column(ipos), ipos=icol_s, icol_e), &
2540  (this%system_matrix%get_value_pos(ipos), ipos=icol_s, icol_e)
2541  end do
2542  close (itestmat)
2543  !stop
2544  end if
2545  !-------------------------------------------------------
2546  !
2547  ! -- call appropriate linear solver
2548  !
2549  ! -- ims linear solver - linmeth option 1
2550  if (this%linsolver == ims_solver) then
2551  call this%imslinear%imslinear_apply(this%icnvg, kstp, kiter, in_iter, &
2552  this%nitermax, this%convnmod, &
2553  this%convmodstart, this%caccel, &
2554  this%cnvg_summary)
2555  else if (this%linsolver == petsc_solver) then
2556  call this%linear_solver%solve(kiter, this%vec_rhs, &
2557  this%vec_x, this%cnvg_summary)
2558  in_iter = this%linear_solver%iteration_number
2559  this%icnvg = this%linear_solver%is_converged
2560  end if
Here is the call graph for this function:

◆ sln_maxval()

subroutine numericalsolutionmodule::sln_maxval ( class(numericalsolutiontype), intent(inout)  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
[in,out]thisNumericalSolutionType instance
[in]nsizelength of vector
[in]vinput vector
[in,out]vmaxmaximum value

Definition at line 2824 of file NumericalSolution.f90.

2825  ! -- dummy variables
2826  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2827  integer(I4B), intent(in) :: nsize !< length of vector
2828  real(DP), dimension(nsize), intent(in) :: v !< input vector
2829  real(DP), intent(inout) :: vmax !< maximum value
2830  ! -- local variables
2831  integer(I4B) :: n
2832  real(DP) :: d
2833  real(DP) :: denom
2834  real(DP) :: dnorm
2835  !
2836  ! -- determine maximum value
2837  vmax = v(1)
2838  do n = 2, nsize
2839  d = v(n)
2840  denom = abs(vmax)
2841  if (denom == dzero) then
2842  denom = dprec
2843  end if
2844  !
2845  ! -- calculate normalized value
2846  dnorm = abs(d) / denom
2847  if (dnorm > done) then
2848  vmax = d
2849  end if
2850  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 3151 of file NumericalSolution.f90.

3153  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3154  real(DP), intent(in) :: dxold_max !< the maximum dependent variable change for unrelaxed cells
3155  real(DP), intent(in) :: hncg !< largest dep. var. change at end of Picard iteration
3156  logical(LGP) :: has_converged !< True, when converged
3157 
3158  has_converged = .false.
3159  if (abs(dxold_max) <= this%dvclose .and. &
3160  abs(hncg) <= this%dvclose) then
3161  has_converged = .true.
3162  end if
3163 

◆ sln_ot()

subroutine numericalsolutionmodule::sln_ot ( class(numericalsolutiontype this)

Output solution data. Currently does nothing.

Parameters
thisNumericalSolutionType instance

Definition at line 1115 of file NumericalSolution.f90.

1116  ! -- dummy variables
1117  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1118  !
1119  ! -- 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 3115 of file NumericalSolution.f90.

3116  ! dummy
3117  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3118  real(DP), intent(in) :: dpak !< Newton Under-relaxation flag
3119  character(len=LENPAKLOC), intent(in) :: cpakout !< string with package that caused failure
3120  integer(I4B), intent(in) :: iend !< flag indicating if last inner iteration (iend=1)
3121  ! local
3122  integer(I4B) :: ivalue
3123  ivalue = 1
3124  if (abs(dpak) > this%dvclose) then
3125  ivalue = 0
3126  ! -- write message to stdout
3127  if (iend /= 0) then
3128  write (errmsg, '(3a)') &
3129  'PACKAGE (', trim(cpakout), ') CAUSED CONVERGENCE FAILURE'
3130  call write_message(errmsg)
3131  end if
3132  end if
3133 
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 2335 of file NumericalSolution.f90.

2336  ! -- dummy variables
2337  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2338  !
2339  ! -- reset the solution
2340  call this%system_matrix%zero_entries()
2341  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 2569 of file NumericalSolution.f90.

2570  ! -- dummy variables
2571  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2572  integer(I4B), intent(in) :: ifdparam !< complexity option (1) simple (2) moderate (3) complex
2573  !
2574  ! -- simple option
2575  select case (ifdparam)
2576  case (1)
2577  this%dvclose = dem3
2578  this%mxiter = 25
2579  this%nonmeth = 0
2580  this%theta = done
2581  this%akappa = dzero
2582  this%gamma = done
2583  this%amomentum = dzero
2584  this%numtrack = 0
2585  this%btol = dzero
2586  this%breduc = dzero
2587  this%res_lim = dzero
2588  !
2589  ! -- moderate
2590  case (2)
2591  this%dvclose = dem2
2592  this%mxiter = 50
2593  this%nonmeth = 3
2594  this%theta = 0.9d0
2595  this%akappa = 0.0001d0
2596  this%gamma = dzero
2597  this%amomentum = dzero
2598  this%numtrack = 0
2599  this%btol = dzero
2600  this%breduc = dzero
2601  this%res_lim = dzero
2602  !
2603  ! -- complex
2604  case (3)
2605  this%dvclose = dem1
2606  this%mxiter = 100
2607  this%nonmeth = 3
2608  this%theta = 0.8d0
2609  this%akappa = 0.0001d0
2610  this%gamma = dzero
2611  this%amomentum = dzero
2612  this%numtrack = 20
2613  this%btol = 1.05d0
2614  this%breduc = 0.1d0
2615  this%res_lim = 0.002d0
2616  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 3138 of file NumericalSolution.f90.

3139  ! dummy
3140  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3141  integer(I4B), intent(in) :: inewtonur !< Newton Under-relaxation flag
3142  ! local
3143  integer(I4B) :: ivalue !< Default is set to current value (1 = under-relaxation applied)
3144 
3145  ivalue = inewtonur
3146 

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

2936  ! -- dummy variables
2937  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2938  integer(I4B), intent(in) :: kiter !< Picard iteration number
2939  real(DP), intent(in) :: bigch !< maximum dependent-variable change
2940  integer(I4B), intent(in) :: neq !< number of equations
2941  integer(I4B), dimension(neq), intent(in) :: active !< active cell flag (1)
2942  real(DP), dimension(neq), intent(inout) :: x !< current dependent-variable
2943  real(DP), dimension(neq), intent(in) :: xtemp !< previous dependent-variable
2944  ! -- local variables
2945  integer(I4B) :: n
2946  real(DP) :: ww
2947  real(DP) :: delx
2948  real(DP) :: relax
2949  real(DP) :: es
2950  real(DP) :: aes
2951  real(DP) :: amom
2952  !
2953  ! -- option for using simple dampening (as done by MODFLOW-2005 PCG)
2954  if (this%nonmeth == 1) then
2955  do n = 1, neq
2956  !
2957  ! -- skip inactive nodes
2958  if (active(n) < 1) cycle
2959  !
2960  ! -- compute step-size (delta x)
2961  delx = x(n) - xtemp(n)
2962  this%dxold(n) = delx
2963 
2964  ! -- dampen dependent variable solution
2965  x(n) = xtemp(n) + this%gamma * delx
2966  end do
2967  !
2968  ! -- option for using cooley underrelaxation
2969  else if (this%nonmeth == 2) then
2970  !
2971  ! -- set bigch
2972  this%bigch = bigch
2973  !
2974  ! -- initialize values for first iteration
2975  if (kiter == 1) then
2976  relax = done
2977  this%relaxold = done
2978  this%bigchold = bigch
2979  else
2980  !
2981  ! -- compute relaxation factor
2982  es = this%bigch / (this%bigchold * this%relaxold)
2983  aes = abs(es)
2984  if (es < -done) then
2985  relax = dhalf / aes
2986  else
2987  relax = (dthree + es) / (dthree + aes)
2988  end if
2989  end if
2990  this%relaxold = relax
2991  !
2992  ! -- modify cooley to use weighted average of past changes
2993  this%bigchold = (done - this%gamma) * this%bigch + this%gamma * &
2994  this%bigchold
2995  !
2996  ! -- compute new dependent variable after under-relaxation
2997  if (relax < done) then
2998  do n = 1, neq
2999  !
3000  ! -- skip inactive nodes
3001  if (active(n) < 1) cycle
3002  !
3003  ! -- update dependent variable
3004  delx = x(n) - xtemp(n)
3005  this%dxold(n) = delx
3006  x(n) = xtemp(n) + relax * delx
3007  end do
3008  end if
3009  !
3010  ! -- option for using delta-bar-delta scheme to under-relax for all equations
3011  else if (this%nonmeth == 3) then
3012  do n = 1, neq
3013  !
3014  ! -- skip inactive nodes
3015  if (active(n) < 1) cycle
3016  !
3017  ! -- compute step-size (delta x) and initialize d-b-d parameters
3018  delx = x(n) - xtemp(n)
3019  !
3020  ! -- initialize values for first iteration
3021  if (kiter == 1) then
3022  this%wsave(n) = done
3023  this%hchold(n) = dem20
3024  this%deold(n) = dzero
3025  end if
3026  !
3027  ! -- compute new relaxation term as per delta-bar-delta
3028  ww = this%wsave(n)
3029  !
3030  ! for flip-flop condition, decrease factor
3031  if (this%deold(n) * delx < dzero) then
3032  ww = this%theta * this%wsave(n)
3033  ! -- when change is of same sign, increase factor
3034  else
3035  ww = this%wsave(n) + this%akappa
3036  end if
3037  if (ww > done) ww = done
3038  this%wsave(n) = ww
3039  !
3040  ! -- compute weighted average of past changes in hchold
3041  if (kiter == 1) then
3042  this%hchold(n) = delx
3043  else
3044  this%hchold(n) = (done - this%gamma) * delx + &
3045  this%gamma * this%hchold(n)
3046  end if
3047  !
3048  ! -- store slope (change) term for next iteration
3049  this%deold(n) = delx
3050  this%dxold(n) = delx
3051  !
3052  ! -- compute accepted step-size and new dependent variable
3053  amom = dzero
3054  if (kiter > 4) amom = this%amomentum
3055  delx = delx * ww + amom * this%hchold(n)
3056  x(n) = xtemp(n) + delx
3057  end do
3058  !
3059  end if

◆ solve()

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

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

Parameters
thisNumericalSolutionType instance
[in]kiterPicard iteration number

Definition at line 1454 of file NumericalSolution.f90.

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

◆ writecsvheader()

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

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

Parameters
thisNumericalSolutionType instance

Definition at line 1312 of file NumericalSolution.f90.

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

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

Variable Documentation

◆ ims_solver

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

Definition at line 53 of file NumericalSolution.f90.

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

◆ petsc_solver

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

Definition at line 54 of file NumericalSolution.f90.

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