MODFLOW 6  version 6.7.0.dev0
USGS Modular Hydrologic Model
petscconvergencemodule Module Reference

Data Types

type  petsccnvgctxtype
 x vector from the previous iteration More...
 
interface  CnvgCheckFunc
 
interface  CnvgDestroyFunc
 
interface  KSPSetConvergenceTest
 

Functions/Subroutines

subroutine create (this, mat, settings, summary)
 
subroutine, public petsc_cnvg_check (ksp, n, rnorm_L2, flag, context, ierr)
 Routine to check the convergence following the configuration. More...
 
function apply_check (ctx, nit, dvmax, rnorm_inf, rnorm_L2)
 Apply the IMS convergence check. More...
 
subroutine fill_cnvg_summary (summary, dx, res, n)
 Fill the convergence summary from the context. More...
 
subroutine destroy (this)
 

Variables

real(dp), parameter, private rnorm_l2_tol = DPREC
 

Function/Subroutine Documentation

◆ apply_check()

function petscconvergencemodule::apply_check ( class(petsccnvgctxtype ctx,
integer(i4b)  nit,
real(dp)  dvmax,
real(dp)  rnorm_inf,
real(dp)  rnorm_L2 
)
private
Parameters
nititeration number
dvmaxinfinity norm of dep. var. change
rnorm_infinfinity norm of residual change
rnorm_l2L2-norm of residual change
rnorm_l2the convergence status

Definition at line 200 of file PetscConvergence.F90.

201  use tdismodule, only: kstp
203  class(PetscCnvgCtxType) :: ctx
204  integer(I4B) :: nit !< iteration number
205  real(DP) :: dvmax !< infinity norm of dep. var. change
206  real(DP) :: rnorm_inf !< infinity norm of residual change
207  real(DP) :: rnorm_L2 !< L2-norm of residual change
208  kspconvergedreason :: flag !< the convergence status
209  ! local
210  real(DP) :: epfact
211  real(DP) :: rcnvg
212 
213  ! Set to 'not converged'
214  flag = ksp_converged_iterating
215  ctx%icnvg_ims = 0
216 
217  epfact = ims_base_epfact(ctx%icnvgopt, kstp)
218 
219  if (ctx%icnvgopt == 2 .or. &
220  ctx%icnvgopt == 3 .or. &
221  ctx%icnvgopt == 4) then
222  rcnvg = rnorm_l2
223  else
224  rcnvg = rnorm_inf
225  end if
226  call ims_base_testcnvg(ctx%icnvgopt, ctx%icnvg_ims, nit, &
227  dvmax, rcnvg, ctx%rnorm_L2_init, &
228  epfact, ctx%dvclose, ctx%rclose)
229 
230  if (ctx%icnvg_ims /= 0) then
231  ! Set to 'converged'
232  flag = ksp_converged_happy_breakdown
233  end if
234 
This module contains the IMS linear accelerator subroutines.
subroutine ims_base_testcnvg(Icnvgopt, Icnvg, Iiter, Dvmax, Rmax, Rmax0, Epfact, Dvclose, Rclose)
@ brief Test for solver convergence
real(dp) function ims_base_epfact(icnvgopt, kstp)
Function returning EPFACT.
integer(i4b), pointer, public kstp
current time step number
Definition: tdis.f90:24
Here is the call graph for this function:
Here is the caller graph for this function:

◆ create()

subroutine petscconvergencemodule::create ( class(petsccnvgctxtype this,
pointer  mat,
type(imslinearsettingstype), pointer  settings,
type(convergencesummarytype), pointer  summary 
)
private

Definition at line 72 of file PetscConvergence.F90.

73  class(PetscCnvgCtxType) :: this
74  mat, pointer :: mat
75  type(ImsLinearSettingsType), pointer :: settings
76  type(ConvergenceSummaryType), pointer :: summary
77  ! local
78  petscerrorcode :: ierr
79 
80  this%icnvg_ims = 0
81  this%icnvgopt = settings%icnvgopt
82  this%dvclose = settings%dvclose
83  this%rclose = settings%rclose
84  this%max_its = settings%iter1
85  this%cnvg_summary => summary
86  call matcreatevecs(mat, this%x_old, petsc_null_vec, ierr)
87  chkerrq(ierr)
88  call matcreatevecs(mat, this%delta_x, petsc_null_vec, ierr)
89  chkerrq(ierr)
90  call matcreatevecs(mat, this%residual, petsc_null_vec, ierr)
91  chkerrq(ierr)
92 

◆ destroy()

subroutine petscconvergencemodule::destroy ( class(petsccnvgctxtype this)
private

Definition at line 304 of file PetscConvergence.F90.

305  class(PetscCnvgCtxType) :: this
306  ! local
307  integer(I4B) :: ierr
308 
309  call vecdestroy(this%x_old, ierr)
310  chkerrq(ierr)
311  call vecdestroy(this%delta_x, ierr)
312  chkerrq(ierr)
313  call vecdestroy(this%residual, ierr)
314  chkerrq(ierr)
315 

◆ fill_cnvg_summary()

subroutine petscconvergencemodule::fill_cnvg_summary ( type(convergencesummarytype), pointer  summary,
  dx,
  res,
  n 
)
Parameters
summarythe convergence summary
summarythe vector with changes in x
summarythe residual vector
summarythe PETSc iteration number

Definition at line 239 of file PetscConvergence.F90.

240  type(ConvergenceSummaryType), pointer :: summary !< the convergence summary
241  vec :: dx !< the vector with changes in x
242  vec :: res !< the residual vector
243  petscint :: n !< the PETSc iteration number
244  ! local
245  petscreal, dimension(:), pointer :: local_dx, local_res
246  petscreal :: dvmax_model, rmax_model
247  petscerrorcode :: ierr
248  petscint :: idx_dv, idx_r
249  petscint :: i, j, istart, iend
250  petscint :: iter_cnt
251 
252  ! increment iteration counter
253  summary%iter_cnt = summary%iter_cnt + 1
254  iter_cnt = summary%iter_cnt
255 
256  if (summary%nitermax > 1) then
257  summary%itinner(iter_cnt) = n
258  do i = 1, summary%convnmod
259  summary%convdvmax(i, iter_cnt) = dzero
260  summary%convlocdv(i, iter_cnt) = 0
261  summary%convrmax(i, iter_cnt) = dzero
262  summary%convlocr(i, iter_cnt) = 0
263  end do
264  end if
265 
266  ! get dv and dr per local model (readonly!)
267  call vecgetarrayreadf90(dx, local_dx, ierr)
268  chkerrq(ierr)
269  call vecgetarrayreadf90(res, local_res, ierr)
270  chkerrq(ierr)
271  do i = 1, summary%convnmod
272  ! reset
273  dvmax_model = dzero
274  idx_dv = 0
275  rmax_model = dzero
276  idx_r = 0
277  ! get first and last model index
278  istart = summary%model_bounds(i)
279  iend = summary%model_bounds(i + 1) - 1
280  do j = istart, iend
281  if (abs(local_dx(j)) > abs(dvmax_model)) then
282  dvmax_model = local_dx(j)
283  idx_dv = j
284  end if
285  if (abs(local_res(j)) > abs(rmax_model)) then
286  rmax_model = local_res(j)
287  idx_r = j
288  end if
289  end do
290  if (summary%nitermax > 1) then
291  summary%convdvmax(i, iter_cnt) = dvmax_model
292  summary%convlocdv(i, iter_cnt) = idx_dv
293  summary%convrmax(i, iter_cnt) = rmax_model
294  summary%convlocr(i, iter_cnt) = idx_r
295  end if
296  end do
297  call vecrestorearrayf90(dx, local_dx, ierr)
298  chkerrq(ierr)
299  call vecrestorearrayf90(res, local_res, ierr)
300  chkerrq(ierr)
301 
Here is the caller graph for this function:

◆ petsc_cnvg_check()

subroutine, public petscconvergencemodule::petsc_cnvg_check (   ksp,
  n,
  rnorm_L2,
  flag,
class(petsccnvgctxtype), pointer  context,
  ierr 
)
Parameters
contexterror

Definition at line 97 of file PetscConvergence.F90.

98  ksp :: ksp !< Iterative context
99  petscint :: n !< Iteration number
100  petscreal :: rnorm_l2 !< 2-norm (preconditioned) residual value
101  kspconvergedreason :: flag !< Converged reason
102  class(PetscCnvgCtxType), pointer :: context !< context
103  petscerrorcode :: ierr !< error
104  ! local
105  petscreal, parameter :: min_one = -1.0
106  petscreal :: xnorm_inf, rnorm0, rnorm_inf_ims, rnorm_l2_ims
107  vec :: x, res
108  type(ConvergenceSummaryType), pointer :: summary
109 
110  summary => context%cnvg_summary
111 
112  ! NB: KSPBuildResidual needs to have its vector destroyed
113  ! to avoid a memory leak, KSPBuildSolution doesn't...
114  call kspbuildsolution(ksp, petsc_null_vec, x, ierr)
115  chkerrq(ierr)
116 
117  ! for CG the KSPBuildResidual returns the work vector directly,
118  ! but BCGS (and possibly others) will do the matrix multiplication
119  call kspbuildresidual(ksp, petsc_null_vec, petsc_null_vec, res, ierr)
120  chkerrq(ierr)
121 
122  rnorm0 = huge(rnorm0)
123  if (context%icnvgopt == 2 .or. &
124  context%icnvgopt == 3 .or. &
125  context%icnvgopt == 4) then
126  call vecnorm(res, norm_2, rnorm_l2_ims, ierr)
127  rnorm0 = rnorm_l2_ims
128  chkerrq(ierr)
129  else if (context%icnvgopt == 100) then
130  rnorm0 = rnorm_l2
131  end if
132 
133  ! n == 0 is before the iteration starts
134  if (n == 0) then
135  context%rnorm_L2_init = rnorm0
136  if (rnorm_l2 < rnorm_l2_tol) then
137  ! exact solution found
138  flag = ksp_converged_happy_breakdown
139  else
140  call veccopy(x, context%x_old, ierr)
141  chkerrq(ierr)
142  flag = ksp_converged_iterating
143  end if
144  ! early return
145  call vecdestroy(res, ierr)
146  chkerrq(ierr)
147  return
148  end if
149 
150  call vecwaxpy(context%delta_x, min_one, context%x_old, x, ierr)
151  chkerrq(ierr)
152 
153  call vecnorm(context%delta_x, norm_infinity, xnorm_inf, ierr)
154  chkerrq(ierr)
155 
156  rnorm_inf_ims = huge(rnorm_inf_ims)
157  if (context%icnvgopt == 0 .or. context%icnvgopt == 1) then
158  call vecnorm(res, norm_infinity, rnorm_inf_ims, ierr)
159  chkerrq(ierr)
160  end if
161 
162  call veccopy(x, context%x_old, ierr)
163  chkerrq(ierr)
164 
165  ! fill the summary for reporting
166  call fill_cnvg_summary(summary, context%delta_x, res, n)
167 
168  if (rnorm_l2 < rnorm_l2_tol) then
169  ! exact solution, set to 'converged'
170  flag = ksp_converged_happy_breakdown
171  else if (context%icnvgopt < 100) then
172  ! IMS check on convergence
173  flag = apply_check(context, n, xnorm_inf, rnorm_inf_ims, rnorm_l2_ims)
174  else if (context%icnvgopt == 100) then
175  ! use PETSc rnorm directly
176  flag = ksp_converged_iterating
177  if (xnorm_inf < context%dvclose .and. rnorm_l2 < context%rclose) then
178  flag = ksp_converged_happy_breakdown
179  end if
180  else
181  ! invalid option somehow
182  write (errmsg, '(a,i0)') "Invalid convergence option: ", context%icnvgopt
183  call store_error(errmsg, .true.)
184  end if
185 
186  if (flag == ksp_converged_iterating) then
187  ! not yet converged, max. iters reached? Then stop.
188  if (n == context%max_its) then
189  flag = ksp_diverged_its
190  end if
191  end if
192 
193  call vecdestroy(res, ierr)
194  chkerrq(ierr)
195 
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ rnorm_l2_tol

real(dp), parameter, private petscconvergencemodule::rnorm_l2_tol = DPREC
private

Definition at line 18 of file PetscConvergence.F90.

18  real(DP), private, parameter :: RNORM_L2_TOL = dprec