19 integer(I4B),
pointer :: nper => null()
20 integer(I4B),
pointer :: maxats => null()
21 real(dp),
public,
pointer :: dtstable => null()
22 integer(I4B),
dimension(:),
pointer,
contiguous :: kperats => null()
23 integer(I4B),
dimension(:),
pointer,
contiguous :: iperats => null()
24 real(dp),
dimension(:),
pointer,
contiguous :: dt0 => null()
25 real(dp),
dimension(:),
pointer,
contiguous :: dtmin => null()
26 real(dp),
dimension(:),
pointer,
contiguous :: dtmax => null()
27 real(dp),
dimension(:),
pointer,
contiguous :: dtadj => null()
28 real(dp),
dimension(:),
pointer,
contiguous :: dtfailadj => null()
60 integer(I4B),
intent(in) :: kper
63 if (
associated(this%kperats))
then
64 if (this%kperats(kper) > 0)
then
79 integer(I4B),
intent(in) :: inunit
80 integer(I4B),
intent(in) :: nper_tdis
83 character(len=*),
parameter :: fmtheader = &
84 "(1X,/1X,'ATS -- ADAPTIVE TIME STEP PACKAGE,', / &
85 &' VERSION 1 : 03/18/2021 - INPUT READ FROM UNIT ',I0)"
88 call this%ats_allocate_scalars()
91 write (
iout, fmtheader) inunit
94 call this%parser%initialize(inunit,
iout)
97 call this%ats_read_options()
100 this%nper = nper_tdis
103 call this%ats_read_dimensions()
104 call this%ats_allocate_arrays()
107 call this%ats_read_timing()
110 call this%ats_input_table()
113 call this%ats_check_timing()
116 call this%ats_process_input()
119 call this%parser%Clear()
156 call mem_allocate(this%kperats, this%nper,
'KPERATS',
'ATS')
157 call mem_allocate(this%iperats, this%maxats,
'IPERATS',
'ATS')
159 call mem_allocate(this%dtmin, this%maxats,
'DTMIN',
'ATS')
160 call mem_allocate(this%dtmax, this%maxats,
'DTMAX',
'ATS')
161 call mem_allocate(this%dtadj, this%maxats,
'DTADJ',
'ATS')
162 call mem_allocate(this%dtfailadj, this%maxats,
'DTFAILADJ',
'ATS')
170 do n = 1, this%maxats
173 this%dtmin(n) =
dzero
174 this%dtmax(n) =
dzero
175 this%dtadj(n) =
dzero
176 this%dtfailadj(n) =
dzero
213 character(len=LINELENGTH) :: keyword
215 logical :: isfound, endOfBlock
219 call this%parser%GetBlock(
'OPTIONS', isfound, ierr, &
220 supportopenclose=.true., blockrequired=.false.)
224 write (
iout,
'(1x,a)')
'PROCESSING ATS OPTIONS'
226 call this%parser%GetNextLine(endofblock)
228 call this%parser%GetStringCaps(keyword)
229 select case (keyword)
231 write (
errmsg,
'(a,a)')
'Unknown ATS option: ', &
234 call this%parser%StoreErrorUnit()
237 write (
iout,
'(1x,a)')
'END OF ATS OPTIONS'
250 character(len=LINELENGTH) :: keyword
252 logical :: isfound, endOfBlock
254 character(len=*),
parameter :: fmtmaxats = &
255 &
"(1X,I0,' ADAPTIVE TIME STEP RECORDS(S) WILL FOLLOW IN PERIODDATA')"
258 call this%parser%GetBlock(
'DIMENSIONS', isfound, ierr, &
259 supportopenclose=.true.)
263 write (
iout,
'(1x,a)')
'PROCESSING ATS DIMENSIONS'
265 call this%parser%GetNextLine(endofblock)
267 call this%parser%GetStringCaps(keyword)
268 select case (keyword)
270 this%maxats = this%parser%GetInteger()
271 write (
iout, fmtmaxats) this%maxats
273 write (
errmsg,
'(a,a)')
'Unknown ATS dimension: ', &
276 call this%parser%StoreErrorUnit()
279 write (
iout,
'(1x,a)')
'END OF ATS DIMENSIONS'
281 write (
errmsg,
'(a)')
'Required DIMENSIONS block not found.'
283 call this%parser%StoreErrorUnit()
299 logical :: isfound, endOfBlock
303 call this%parser%GetBlock(
'PERIODDATA', isfound, ierr, &
304 supportopenclose=.true.)
308 write (
iout,
'(1x,a)')
'READING ATS PERIODDATA'
309 do n = 1, this%maxats
310 call this%parser%GetNextLine(endofblock)
314 this%iperats(n) = this%parser%GetInteger()
315 this%dt0(n) = this%parser%GetDouble()
316 this%dtmin(n) = this%parser%GetDouble()
317 this%dtmax(n) = this%parser%GetDouble()
318 this%dtadj(n) = this%parser%GetDouble()
319 this%dtfailadj(n) = this%parser%GetDouble()
323 call this%parser%terminateblock()
327 call this%parser%StoreErrorUnit()
329 write (
iout,
'(1x,a)')
'END READING ATS PERIODDATA'
331 write (
errmsg,
'(a)')
'Required PERIODDATA block not found.'
333 call this%parser%StoreErrorUnit()
346 integer(I4B) :: kkper
350 do n = 1, this%maxats
351 kkper = this%iperats(n)
352 if (kkper > 0 .and. kkper <= this%nper)
then
353 this%kperats(kkper) = n
369 character(len=LINELENGTH) :: tag
370 type(
tabletype),
pointer :: inputtab => null()
373 call table_cr(inputtab,
'ATS',
'ATS PERIOD DATA')
374 call inputtab%table_df(this%maxats, 7,
iout)
378 call inputtab%initialize_column(tag, 10, alignment=
tableft)
380 call inputtab%initialize_column(tag, 10, alignment=
tableft)
382 call inputtab%initialize_column(tag, 10, alignment=
tabcenter)
384 call inputtab%initialize_column(tag, 10, alignment=
tabcenter)
386 call inputtab%initialize_column(tag, 10, alignment=
tabcenter)
388 call inputtab%initialize_column(tag, 10, alignment=
tabcenter)
390 call inputtab%initialize_column(tag, 10, alignment=
tabcenter)
393 do n = 1, this%maxats
394 call inputtab%add_term(n)
395 call inputtab%add_term(this%iperats(n))
396 call inputtab%add_term(this%dt0(n))
397 call inputtab%add_term(this%dtmin(n))
398 call inputtab%add_term(this%dtmax(n))
399 call inputtab%add_term(this%dtadj(n))
400 call inputtab%add_term(this%dtfailadj(n))
404 call inputtab%table_da()
405 deallocate (inputtab)
420 write (
iout,
'(1x,a)')
'PROCESSING ATS INPUT'
421 do n = 1, this%maxats
424 if (this%iperats(n) < 1)
then
425 write (
errmsg,
'(a, i0, a, i0)') &
426 'IPERATS must be greater than zero. Found ', this%iperats(n), &
427 ' for ATS PERIODDATA record ', n
430 if (this%iperats(n) > this%nper)
then
431 write (
warnmsg,
'(a, i0, a, i0)') &
432 'IPERATS greater than NPER. Found ', this%iperats(n), &
433 ' for ATS PERIODDATA record ', n
438 if (this%dt0(n) <
dzero)
then
439 write (
errmsg,
'(a, g15.7, a, i0)') &
440 'DT0 must be >= zero. Found ', this%dt0(n), &
441 ' for ATS PERIODDATA record ', n
446 if (this%dtmin(n) <=
dzero)
then
447 write (
errmsg,
'(a, g15.7, a, i0)') &
448 'DTMIN must be > zero. Found ', this%dtmin(n), &
449 ' for ATS PERIODDATA record ', n
454 if (this%dtmax(n) <=
dzero)
then
455 write (
errmsg,
'(a, g15.7, a, i0)') &
456 'DTMAX must be > zero. Found ', this%dtmax(n), &
457 ' for ATS PERIODDATA record ', n
462 if (this%dtmin(n) > this%dtmax(n))
then
463 write (
errmsg,
'(a, 2g15.7, a, i0)') &
464 'DTMIN must be < dtmax. Found ', this%dtmin(n), this%dtmax(n), &
465 ' for ATS PERIODDATA record ', n
470 if (this%dtadj(n) .ne.
dzero .and. this%dtadj(n) <
done)
then
471 write (
errmsg,
'(a, g15.7, a, i0)') &
472 'DTADJ must be 0 or >= 1.0. Found ', this%dtadj(n), &
473 ' for ATS PERIODDATA record ', n
478 if (this%dtfailadj(n) .ne.
dzero .and. this%dtfailadj(n) <
done)
then
479 write (
errmsg,
'(a, g15.7, a, i0)') &
480 'DTFAILADJ must be 0 or >= 1.0. Found ', this%dtfailadj(n), &
481 ' for ATS PERIODDATA record ', n
489 call this%parser%StoreErrorUnit()
491 write (
iout,
'(1x,a)')
'DONE PROCESSING ATS INPUT'
503 integer(I4B),
intent(in) :: kper
506 character(len=*),
parameter :: fmtspts = &
507 "(28X,'ATS IS OVERRIDING TIME STEPPING FOR THIS PERIOD',/ &
508 &28X,'INITIAL TIME STEP SIZE (DT0) = ',G15.7,/ &
509 &28X,'MINIMUM TIME STEP SIZE (DTMIN) = ',G15.7,/ &
510 &28X,'MAXIMUM TIME STEP SIZE (DTMAX) = ',G15.7,/ &
511 &28X,'MULTIPLIER/DIVIDER FOR TIME STEP (DTADJ) = ',G15.7,/ &
512 &28X,'DIVIDER FOR FAILED TIME STEP (DTFAILADJ) = ',G15.7,/ &
514 n = this%kperats(kper)
515 write (
iout, fmtspts) this%dt0(n), this%dtmin(n), this%dtmax(n), &
516 this%dtadj(n), this%dtfailadj(n)
529 integer(I4B),
intent(in) :: kstp
530 integer(I4B),
intent(in) :: kper
531 real(DP),
intent(in) :: dt
532 character(len=*),
intent(in) :: sloc
533 integer(I4B),
intent(in),
optional :: idir
538 character(len=*),
parameter :: fmtdtsubmit = &
539 &
"(1x, 'ATS: ', A,' submitted a preferred time step size of ', G15.7)"
541 if (this%isAdaptivePeriod(kper))
then
542 n = this%kperats(kper)
543 tsfact = this%dtadj(n)
544 if (tsfact >
done)
then
549 if (
present(idir))
then
552 dt_temp = dt / tsfact
553 else if (idir == 1)
then
554 dt_temp = dt * tsfact
559 if (kstp > 1 .and. dt_temp >
dzero)
then
560 write (
iout, fmtdtsubmit) trim(adjustl(sloc)), dt_temp
562 if (dt_temp >
dzero .and. dt_temp < this%dtstable)
then
564 this%dtstable = dt_temp
580 integer(I4B),
intent(in) :: kstp
581 integer(I4B),
intent(in) :: kper
582 real(DP),
intent(inout) :: pertim
583 real(DP),
intent(in) :: perlencurrent
584 real(DP),
intent(inout) :: delt
589 character(len=*),
parameter :: fmtdt = &
590 "(1x, 'ATS: time step set to ', G15.7, ' for step ', i0, &
591 &' and period ', i0)"
594 n = this%kperats(kper)
605 if (this%dt0(n) /=
dzero)
then
613 if (this%dtstable /=
dnodata)
then
620 if (delt < this%dtmin(n))
then
623 if (delt > this%dtmax(n))
then
628 if (tstart + delt > perlencurrent - this%dtmin(n))
then
629 delt = perlencurrent - tstart
633 write (
iout, fmtdt) delt, kstp, kper
643 delt, finishedTrying)
647 integer(I4B),
intent(in) :: kstp
648 integer(I4B),
intent(in) :: kper
649 integer(I4B),
intent(in) :: lastStepFailed
650 real(DP),
intent(inout) :: delt
651 logical,
intent(inout) :: finishedTrying
654 real(DP) :: delt_temp
657 character(len=*),
parameter :: fmttsi = &
658 "(1X, 'Failed solution for step ', i0, ' and period ', i0, &
659 &' will be retried using time step of ', G15.7)"
660 if (this%isAdaptivePeriod(kper))
then
661 if (laststepfailed /= 0)
then
663 n = this%kperats(kper)
664 tsfact = this%dtfailadj(n)
665 if (tsfact >
done)
then
666 delt_temp = delt / tsfact
667 if (delt_temp >= this%dtmin(n))
then
668 finishedtrying = .false.
670 write (
iout, fmttsi) kstp, kper, delt
687 integer(I4B),
intent(in) :: kper
688 real(DP),
intent(inout) :: pertim
689 real(DP),
intent(in) :: perlencurrent
690 logical(LGP),
intent(inout) :: endofperiod
695 n = this%kperats(kper)
696 if (abs(pertim - perlencurrent) < this%dtmin(n))
then
subroutine ats_reset_delt(this, kstp, kper, lastStepFailed, delt, finishedTrying)
@ brief Reset time step because failure has occurred
subroutine ats_allocate_scalars(this)
@ brief Allocate scalars
subroutine ats_set_endofperiod(this, kper, pertim, perlencurrent, endofperiod)
@ brief Set end of period indicator
subroutine ats_check_timing(this)
@ brief Check timing
subroutine ats_da(this)
@ brief Deallocate variables
subroutine ats_process_input(this)
@ brief Process input
subroutine ats_submit_delt(this, kstp, kper, dt, sloc, idir)
@ brief Allow and external caller to submit preferred time step
subroutine ats_input_table(this)
@ brief Write input table
subroutine ats_read_timing(this)
@ brief Read timing
subroutine ats_allocate_arrays(this)
@ brief Allocate arrays
subroutine ats_period_message(this, kper)
@ brief Write period message
subroutine ats_set_delt(this, kstp, kper, pertim, perlencurrent, delt)
@ brief Set time step
logical(lgp) function isadaptiveperiod(this, kper)
@ brief Determine if period is adaptive
subroutine ats_init(this, inunit, nper_tdis)
@ brief Create ATS object
subroutine ats_read_dimensions(this)
@ brief Read dimensions
subroutine ats_read_options(this)
@ brief Read options
This module contains block parser methods.
This module contains simulation constants.
integer(i4b), parameter linelength
maximum length of a standard line
@ tabcenter
centered table column
@ tableft
left justified table column
real(dp), parameter dnodata
real no data constant
real(dp), parameter dzero
real constant zero
real(dp), parameter done
real constant 1
This module defines variable data types.
This module contains simulation methods.
subroutine, public store_warning(msg, substring)
Store warning message.
subroutine, public store_error(msg, terminate)
Store an error message.
integer(i4b) function, public count_errors()
Return number of errors.
This module contains simulation variables.
character(len=maxcharlen) errmsg
error message string
character(len=maxcharlen) warnmsg
warning message string
integer(i4b) iout
file unit number for simulation output
subroutine, public table_cr(this, name, title)