MODFLOW 6  version 6.5.0.dev2
MODFLOW 6 Code Documentation
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_calculate_delt (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 2295 of file NumericalSolution.f90.

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

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

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

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

◆ apply_backtracking()

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

Definition at line 2841 of file NumericalSolution.f90.

2842  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2843  ! local
2844  integer(I4B) :: n
2845  real(DP) :: delx
2846 
2847  do n = 1, this%neq
2848  if (this%active(n) < 1) cycle
2849  delx = this%breduc * (this%x(n) - this%xtemp(n))
2850  this%x(n) = this%xtemp(n) + delx
2851  end do
2852 

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

3337  ! -- dummy variables
3338  class(*), pointer, intent(inout) :: obj !< generic object
3339  ! -- return variable
3340  class(NumericalSolutionType), pointer :: res !< output NumericalSolutionType
3341  !
3342  ! -- initialize return variable
3343  res => null()
3344  !
3345  ! -- determine if obj is associated
3346  if (.not. associated(obj)) return
3347  !
3348  ! -- set res
3349  select type (obj)
3350  class is (numericalsolutiontype)
3351  res => obj
3352  end select
3353  !
3354  ! -- return
3355  return
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 1977 of file NumericalSolution.f90.

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

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

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

2812  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2813  integer(I4B) :: bt_flag !< backtracking flag (1) backtracking performed (0) backtracking not performed
2814  ! local
2815  integer(I4B) :: n
2816  real(DP) :: dx
2817  real(DP) :: dx_abs
2818  real(DP) :: dx_abs_max
2819 
2820  ! default is off
2821  bt_flag = 0
2822 
2823  ! find max. change
2824  dx_abs_max = 0.0
2825  do n = 1, this%neq
2826  if (this%active(n) < 1) cycle
2827  dx = this%x(n) - this%xtemp(n)
2828  dx_abs = abs(dx)
2829  if (dx_abs > dx_abs_max) dx_abs_max = dx_abs
2830  end do
2831 
2832  ! if backtracking, set flag
2833  if (this%breduc * dx_abs_max >= this%dvclose) then
2834  bt_flag = 1
2835  end if
2836 

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

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

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

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

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

3364  ! -- dummy variables
3365  type(ListType), intent(inout) :: list !< list of numerical solutions
3366  integer(I4B), intent(in) :: idx !< value to retrieve from the list
3367  ! -- return variables
3368  class(NumericalSolutionType), pointer :: res !< numerical solution
3369  ! -- local variables
3370  class(*), pointer :: obj
3371  !
3372  obj => list%GetItem(idx)
3373  res => castasnumericalsolutionclass(obj)
3374  !
3375  return
Here is the call graph for this function:
Here is the caller 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 1448 of file NumericalSolution.f90.

1449  ! -- dummy variables
1450  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1451  ! -- local variables
1452  integer(I4B) :: ic
1453  integer(I4B) :: im
1454  class(NumericalExchangeType), pointer :: cp => null()
1455  class(NumericalModelType), pointer :: mp => null()
1456 
1457  ! synchronize for AD
1458  call this%synchronize(stg_bfr_exg_ad, this%synchronize_ctx)
1459 
1460  ! -- Exchange advance
1461  do ic = 1, this%exchangelist%Count()
1462  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1463  call cp%exg_ad()
1464  end do
1465 
1466  ! -- Model advance
1467  do im = 1, this%modellist%Count()
1468  mp => getnumericalmodelfromlist(this%modellist, im)
1469  call mp%model_ad()
1470  end do
1471 
1472  ! advance solution
1473  call this%sln_ad()
1474 
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 2220 of file NumericalSolution.f90.

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

1105  ! -- modules
1106  use tdismodule, only: kstp, kper
1107  ! -- dummy variables
1108  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1109  !
1110  ! -- write headers to CSV file
1111  if (kper == 1 .and. kstp == 1) then
1112  call this%writeCSVHeader()
1113  end if
1114 
1115  ! write PTC info on models to iout
1116  call this%writePTCInfoToFile(kper)
1117 
1118  ! reset convergence flag and inner solve counter
1119  this%icnvg = 0
1120  this%itertot_timestep = 0
1121  this%iouttot_timestep = 0
1122 
1123  return

◆ sln_ar()

subroutine numericalsolutionmodule::sln_ar ( class(numericalsolutiontype this)

Allocate and read data for a solution.

Parameters
thisNumericalSolutionType instance

Definition at line 515 of file NumericalSolution.f90.

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

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

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

2796  ! -- dummy variables
2797  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2798  integer(I4B), intent(inout) :: bt_flag !< backtracking flag (1) backtracking performed (0) backtracking not performed
2799 
2800  bt_flag = this%get_backtracking_flag()
2801 
2802  ! perform backtracking if ...
2803  if (bt_flag > 0) then
2804  call this%apply_backtracking()
2805  end if
2806 

◆ sln_buildsystem()

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

Definition at line 1920 of file NumericalSolution.f90.

1921  class(NumericalSolutionType) :: this
1922  integer(I4B), intent(in) :: kiter
1923  integer(I4B), intent(in) :: inewton
1924  ! local
1925  integer(I4B) :: im, ic
1926  class(NumericalModelType), pointer :: mp
1927  class(NumericalExchangeType), pointer :: cp
1928  !
1929  ! -- Set amat and rhs to zero
1930  call this%sln_reset()
1931 
1932  ! reset models
1933  do im = 1, this%modellist%Count()
1934  mp => getnumericalmodelfromlist(this%modellist, im)
1935  call mp%model_reset()
1936  end do
1937 
1938  ! synchronize for CF
1939  call this%synchronize(stg_bfr_exg_cf, this%synchronize_ctx)
1940 
1941  !
1942  ! -- Calculate the matrix terms for each exchange
1943  do ic = 1, this%exchangelist%Count()
1944  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1945  call cp%exg_cf(kiter)
1946  end do
1947  !
1948  ! -- Calculate the matrix terms for each model
1949  do im = 1, this%modellist%Count()
1950  mp => getnumericalmodelfromlist(this%modellist, im)
1951  call mp%model_cf(kiter)
1952  end do
1953 
1954  ! synchronize for FC
1955  call this%synchronize(stg_bfr_exg_fc, this%synchronize_ctx)
1956 
1957  !
1958  ! -- Add exchange coefficients to the solution
1959  do ic = 1, this%exchangelist%Count()
1960  cp => getnumericalexchangefromlist(this%exchangelist, ic)
1961  call cp%exg_fc(kiter, this%system_matrix, this%rhs, inewton)
1962  end do
1963  !
1964  ! -- Add model coefficients to the solution
1965  do im = 1, this%modellist%Count()
1966  mp => getnumericalmodelfromlist(this%modellist, im)
1967  call mp%model_fc(kiter, this%system_matrix, inewton)
1968  end do
1969 
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 1290 of file NumericalSolution.f90.

1291  ! -- dummy variables
1292  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1293  integer(I4B), intent(inout) :: isgcnvg !< solution group convergence flag
1294  integer(I4B), intent(in) :: isuppress_output !< flag for suppressing output
1295  ! -- local variables
1296  class(NumericalModelType), pointer :: mp => null()
1297  character(len=LINELENGTH) :: line
1298  character(len=LINELENGTH) :: fmt
1299  integer(I4B) :: im
1300  integer(I4B) :: kiter ! non-linear iteration counter
1301 ! ------------------------------------------------------------------------------
1302 
1303  ! advance the models, exchanges, and solution
1304  call this%prepareSolve()
1305 
1306  select case (isim_mode)
1307  case (mvalidate)
1308  line = 'mode="validation" -- Skipping matrix assembly and solution.'
1309  fmt = "(/,1x,a,/)"
1310  do im = 1, this%modellist%Count()
1311  mp => getnumericalmodelfromlist(this%modellist, im)
1312  call mp%model_message(line, fmt=fmt)
1313  end do
1314  case (mnormal)
1315  ! nonlinear iteration loop for this solution
1316  outerloop: do kiter = 1, this%mxiter
1317 
1318  ! perform a single iteration
1319  call this%solve(kiter)
1320 
1321  ! exit if converged
1322  if (this%icnvg == 1) then
1323  exit outerloop
1324  end if
1325 
1326  end do outerloop
1327 
1328  ! finish up, write convergence info, CSV file, budgets and flows, ...
1329  call this%finalizeSolve(kiter, isgcnvg, isuppress_output)
1330  end select
1331  !
1332  ! -- return
1333  return
1334 
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 2955 of file NumericalSolution.f90.

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

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

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

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

◆ sln_calculate_delt()

subroutine numericalsolutionmodule::sln_calculate_delt ( class(numericalsolutiontype this)

Calculate time step length.

Parameters
thisNumericalSolutionType instance

Definition at line 1060 of file NumericalSolution.f90.

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

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

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

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

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

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

1147  use simvariablesmodule, only: iout
1148  ! -- dummy variables
1149  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1150  !
1151  ! -- write timer output
1152  if (idevelopmode == 1) then
1153  write (iout, '(//1x,a,1x,a,1x,a)') &
1154  'Solution', trim(adjustl(this%name)), 'summary'
1155  write (iout, "(1x,70('-'))")
1156  write (iout, '(1x,a,1x,g0,1x,a)') &
1157  'Total formulate time: ', this%ttform, 'seconds'
1158  write (iout, '(1x,a,1x,g0,1x,a,/)') &
1159  'Total solution time: ', this%ttsoln, 'seconds'
1160  end if
1161  !
1162  ! -- return
1163  return

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

3146  ! -- dummy variables
3147  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
3148  real(DP), intent(inout) :: hncg !< maximum dependent-variable change
3149  integer(I4B), intent(inout) :: lrch !< location of the maximum dependent-variable change
3150  ! -- local variables
3151  integer(I4B) :: nb
3152  real(DP) :: bigch
3153  real(DP) :: abigch
3154  integer(I4B) :: n
3155  real(DP) :: hdif
3156  real(DP) :: ahdif
3157  !
3158  ! -- determine the maximum change
3159  nb = 0
3160  bigch = dzero
3161  abigch = dzero
3162  do n = 1, this%neq
3163  if (this%active(n) < 1) cycle
3164  hdif = this%x(n) - this%xtemp(n)
3165  ahdif = abs(hdif)
3166  if (ahdif > abigch) then
3167  bigch = hdif
3168  abigch = ahdif
3169  nb = n
3170  end if
3171  end do
3172  !
3173  !-----store maximum change value and location
3174  hncg = bigch
3175  lrch = nb
3176  !
3177  ! -- return
3178  return

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

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

3295  ! -- dummy variables
3296  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
3297  integer(I4B), intent(in) :: nodesln !< solution node number
3298  integer(I4B), intent(inout) :: im !< solution model index (index in model list for this solution)
3299  integer(I4B), intent(inout) :: nodeu !< user node number
3300  ! -- local variables
3301  class(NumericalModelType), pointer :: mp => null()
3302  integer(I4B) :: i
3303  integer(I4B) :: istart
3304  integer(I4B) :: iend
3305  integer(I4B) :: noder, nglo
3306  !
3307  ! -- initialize local variables
3308  noder = 0
3309  !
3310  ! -- when parallel, account for offset
3311  nglo = nodesln + this%matrix_offset
3312  !
3313  ! -- calculate and set offsets
3314  do i = 1, this%modellist%Count()
3315  mp => getnumericalmodelfromlist(this%modellist, i)
3316  istart = 0
3317  iend = 0
3318  call mp%get_mrange(istart, iend)
3319  if (nglo >= istart .and. nglo <= iend) then
3320  noder = nglo - istart + 1
3321  call mp%get_mnodeu(noder, nodeu)
3322  im = i
3323  exit
3324  end if
3325  end do
3326  !
3327  ! -- return
3328  return
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 3181 of file NumericalSolution.f90.

3182  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3183  real(DP) :: max_dvc !< the maximum dependent variable change
3184  logical(LGP) :: has_converged !< True, when converged
3185 
3186  has_converged = .false.
3187  if (abs(max_dvc) <= this%dvclose) then
3188  has_converged = .true.
3189  end if
3190 

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

2867  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2868  real(DP) :: l2norm !< calculated L-2 norm
2869  ! local
2870  class(VectorBaseType), pointer :: vec_resid
2871 
2872  ! calc. residual vector
2873  vec_resid => this%system_matrix%create_vec(this%neq)
2874  call this%sln_calc_residual(vec_resid)
2875 
2876  ! 2-norm
2877  l2norm = vec_resid%norm2()
2878 
2879  ! clean up temp. vector
2880  call vec_resid%destroy()
2881  deallocate (vec_resid)
2882 
2883  return

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

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

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

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

3233  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3234  real(DP), intent(in) :: dxold_max !< the maximum dependent variable change for unrelaxed cells
3235  real(DP), intent(in) :: hncg !< largest dep. var. change at end of Picard iteration
3236  logical(LGP) :: has_converged !< True, when converged
3237 
3238  has_converged = .false.
3239  if (abs(dxold_max) <= this%dvclose .and. &
3240  abs(hncg) <= this%dvclose) then
3241  has_converged = .true.
3242  end if
3243 

◆ sln_ot()

subroutine numericalsolutionmodule::sln_ot ( class(numericalsolutiontype this)

Output solution data. Currently does nothing.

Parameters
thisNumericalSolutionType instance

Definition at line 1131 of file NumericalSolution.f90.

1132  ! -- dummy variables
1133  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1134  !
1135  ! -- Nothing to do here
1136  !
1137  ! -- return
1138  return

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

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

2389  ! -- dummy variables
2390  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
2391  !
2392  ! -- reset the solution
2393  call this%system_matrix%zero_entries()
2394  call this%vec_rhs%zero_entries()
2395  !
2396  ! -- return
2397  return

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

2629  ! -- dummy variables
2630  class(NumericalSolutionType), intent(inout) :: this !< NumericalSolutionType instance
2631  integer(I4B), intent(in) :: ifdparam !< complexity option (1) simple (2) moderate (3) complex
2632  !
2633  ! -- simple option
2634  select case (ifdparam)
2635  case (1)
2636  this%dvclose = dem3
2637  this%mxiter = 25
2638  this%nonmeth = 0
2639  this%theta = done
2640  this%akappa = dzero
2641  this%gamma = done
2642  this%amomentum = dzero
2643  this%numtrack = 0
2644  this%btol = dzero
2645  this%breduc = dzero
2646  this%res_lim = dzero
2647  !
2648  ! -- moderate
2649  case (2)
2650  this%dvclose = dem2
2651  this%mxiter = 50
2652  this%nonmeth = 3
2653  this%theta = 0.9d0
2654  this%akappa = 0.0001d0
2655  this%gamma = dzero
2656  this%amomentum = dzero
2657  this%numtrack = 0
2658  this%btol = dzero
2659  this%breduc = dzero
2660  this%res_lim = dzero
2661  !
2662  ! -- complex
2663  case (3)
2664  this%dvclose = dem1
2665  this%mxiter = 100
2666  this%nonmeth = 3
2667  this%theta = 0.8d0
2668  this%akappa = 0.0001d0
2669  this%gamma = dzero
2670  this%amomentum = dzero
2671  this%numtrack = 20
2672  this%btol = 1.05d0
2673  this%breduc = 0.1d0
2674  this%res_lim = 0.002d0
2675  end select
2676  !
2677  ! -- return
2678  return

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

3219  ! dummy
3220  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
3221  integer(I4B), intent(in) :: inewtonur !< Newton Under-relaxation flag
3222  ! local
3223  integer(I4B) :: ivalue !< Default is set to current value (1 = under-relaxation applied)
3224 
3225  ivalue = inewtonur
3226 

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

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

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

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

1343  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1344  ! local variables
1345  integer(I4B) :: im
1346  class(NumericalModelType), pointer :: mp => null()
1347  !
1348  ! -- outer iteration csv header
1349  if (this%icsvouterout > 0) then
1350  write (this%icsvouterout, '(*(G0,:,","))') &
1351  'total_inner_iterations', 'totim', 'kper', 'kstp', 'nouter', &
1352  'inner_iterations', 'solution_outer_dvmax', &
1353  'solution_outer_dvmax_model', 'solution_outer_dvmax_package', &
1354  'solution_outer_dvmax_node'
1355  end if
1356  !
1357  ! -- inner iteration csv header
1358  if (this%icsvinnerout > 0) then
1359  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1360  'total_inner_iterations', 'totim', 'kper', 'kstp', 'nouter', &
1361  'ninner', 'solution_inner_dvmax', 'solution_inner_dvmax_model', &
1362  'solution_inner_dvmax_node'
1363  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1364  '', 'solution_inner_rmax', 'solution_inner_rmax_model', &
1365  'solution_inner_rmax_node'
1366  ! solver items specific to ims solver
1367  if (this%linsolver == ims_solver) then
1368  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1369  '', 'solution_inner_alpha'
1370  if (this%imslinear%ilinmeth == 2) then
1371  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1372  '', 'solution_inner_omega'
1373  end if
1374  end if
1375  ! -- check for more than one model - ims only
1376  if (this%convnmod > 1) then
1377  do im = 1, this%modellist%Count()
1378  mp => getnumericalmodelfromlist(this%modellist, im)
1379  write (this%icsvinnerout, '(*(G0,:,","))', advance='NO') &
1380  '', trim(adjustl(mp%name))//'_inner_dvmax', &
1381  trim(adjustl(mp%name))//'_inner_dvmax_node', &
1382  trim(adjustl(mp%name))//'_inner_rmax', &
1383  trim(adjustl(mp%name))//'_inner_rmax_node'
1384  end do
1385  end if
1386  write (this%icsvinnerout, '(a)') ''
1387  end if
1388  !
1389  ! -- return
1390  return
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 1398 of file NumericalSolution.f90.

1399  ! -- dummy variables
1400  class(NumericalSolutionType) :: this !< NumericalSolutionType instance
1401  integer(I4B), intent(in) :: kper !< current stress period number
1402  ! -- local variable
1403  integer(I4B) :: n, im, iallowptc, iptc
1404  class(NumericalModelType), pointer :: mp => null()
1405 
1406  ! -- determine if PTC will be used in any model
1407  n = 1
1408  do im = 1, this%modellist%Count()
1409  !
1410  ! -- set iallowptc
1411  ! -- no_ptc_option is FIRST
1412  if (this%iallowptc < 0) then
1413  if (kper > 1) then
1414  iallowptc = 1
1415  else
1416  iallowptc = 0
1417  end if
1418  ! -- no_ptc_option is ALL (0) or using PTC (1)
1419  else
1420  iallowptc = this%iallowptc
1421  end if
1422 
1423  if (iallowptc > 0) then
1424  mp => getnumericalmodelfromlist(this%modellist, im)
1425  call mp%model_ptcchk(iptc)
1426  else
1427  iptc = 0
1428  end if
1429 
1430  if (iptc /= 0) then
1431  if (n == 1) then
1432  write (iout, '(//)')
1433  n = 0
1434  end if
1435  write (iout, '(1x,a,1x,i0,1x,3a)') &
1436  'PSEUDO-TRANSIENT CONTINUATION WILL BE APPLIED TO MODEL', im, '("', &
1437  trim(adjustl(mp%name)), '") DURING THIS TIME STEP'
1438  end if
1439  end do
1440 
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