MODFLOW 6 version 6.9.0.dev0
USGS Modular Hydrologic Model
Loading...
Searching...
No Matches
ParticleReleaseSchedule.f90
Go to the documentation of this file.
1!> @brief Particle release scheduling.
3
6 use kindmodule, only: i4b, dp
7 use mathutilmodule, only: is_close
10
11 implicit none
12 private
15
16 !> @brief Particle release scheduling utility.
17 !!
18 !! The release schedule composes a time selection object for any
19 !! explicitly specified release times, and a time step selection
20 !! object for release times specified in period/time step terms.
21 !!
22 !! Release time coincidence is computed within a given tolerance;
23 !! times closer than the tolerance are merged into a single time.
24 !!
25 !! The release schedule must be refreshed each time step. This is
26 !! achieved by calling `advance()`. After this, the `times` array
27 !! is a debounced/consolidated schedule for the current time step.
28 !<
30 real(dp), allocatable :: times(:) !< release times
31 real(dp) :: tolerance !< release time coincidence tolerance
32 type(timeselecttype), pointer :: time_select !< time selection
33 type(timestepselecttype), pointer :: step_select !< time step selection
34 contains
35 procedure :: advance
36 procedure :: any
37 procedure :: count
38 procedure :: destroy
39 procedure :: log
40 procedure :: schedule
42
43contains
44
45 !> @brief Create a new release schedule.
46 function create_release_schedule(tolerance) result(schedule_)
47 real(dp), intent(in) :: tolerance !< coincident release time tolerance
48 type(particlereleasescheduletype), pointer :: schedule_ !< schedule pointer
49
50 allocate (schedule_)
51 allocate (schedule_%times(0))
52 allocate (schedule_%time_select)
53 allocate (schedule_%step_select)
54 call schedule_%time_select%init()
55 call schedule_%step_select%init()
56 schedule_%tolerance = tolerance
57 end function create_release_schedule
58
59 !> @brief Deallocate the release schedule.
60 subroutine destroy(this)
61 class(particlereleasescheduletype), intent(inout) :: this !< this instance
62
63 deallocate (this%times)
64 call this%time_select%deallocate()
65 call this%step_select%deallocate()
66 deallocate (this%time_select)
67 deallocate (this%step_select)
68 end subroutine destroy
69
70 !> @brief Write the release schedule to the given output unit.
71 subroutine log(this, iout)
72 class(particlereleasescheduletype), intent(inout) :: this !< this instance
73 integer(I4B), intent(in) :: iout !< output unit
74 character(len=*), parameter :: fmt = &
75 &"(6x,A,': ',50(G0,' '))"
76
77 if (this%any()) then
78 write (iout, fmt) 'RELEASE SCHEDULE', this%times
79 else
80 write (iout, "(1x,a,1x,a)") 'NO RELEASES SCHEDULED'
81 end if
82 end subroutine log
83
84 !> @brief Add a release time to the schedule.
85 !!
86 !! To schedule multiple release times at once, expand
87 !! and populate the time selection object by hand. DO
88 !! NOT attempt to manipulate the times array; this is
89 !! a read-only property which the schedule maintains.
90 !<
91 subroutine schedule(this, trelease)
92 class(particlereleasescheduletype), intent(inout) :: this
93 real(DP), intent(in) :: trelease
94 call expandarray(this%times)
95 this%times(size(this%times)) = trelease
96 end subroutine schedule
97
98 !> @brief Refresh the schedule for the current time step.
99 !!
100 !! This involves several tasks: first, advance the time
101 !! selection. Then, if period-block release setting lines
102 !! are provided, reinitialize the time step selection for
103 !! the given period. Finally, refresh the schedule array,
104 !! deduplicating any times closer than the set tolerance.
105 !<
106 subroutine advance(this, lines)
107 use tdismodule, only: totimc, kstp, endofperiod
108 class(particlereleasescheduletype), intent(inout) :: this
109 character(len=LINELENGTH), intent(in), optional :: lines(:)
110 integer(I4B) :: it, i
111 real(DP) :: tprevious
112 real(DP) :: trelease
113
114 ! Advance the time selection.
115 call this%time_select%advance()
116
117 ! Reinitialize the time step selection if new
118 ! period-block release settings are provided.
119 if (present(lines)) then
120 call this%step_select%init()
121 do i = 1, size(lines)
122 call this%step_select%read(lines(i))
123 end do
124 end if
125
126 ! Reinitialize the release time schedule.
127 if (allocated(this%times)) deallocate (this%times)
128 allocate (this%times(0))
129
130 tprevious = -done
131 trelease = -done
132
133 ! Add a release time configured by period-block settings, if one
134 ! is scheduled this time step and doesn't coincide with any
135 ! explicitly configured release time (see above).
136 if (this%step_select%is_selected(kstp, endofperiod=endofperiod)) then
137 trelease = totimc
138 if (.not. this%time_select%contains_close(trelease, this%tolerance)) then
139 call this%schedule(trelease)
140 tprevious = trelease
141 end if
142 end if
143
144 ! Schedule explicitly specified release times, up
145 ! to the configured tolerance of coincidence
146 if (this%time_select%any()) then
147 do it = this%time_select%selection(1), this%time_select%selection(2)
148 trelease = this%time_select%times(it)
149 if (tprevious >= dzero .and. is_close( &
150 tprevious, &
151 trelease, &
152 atol=this%tolerance)) cycle
153
154 call this%schedule(trelease)
155 tprevious = trelease
156 end do
157 end if
158 end subroutine advance
159
160 !> @brief Check if any releases are scheduled.
161 !!
162 !! Note: be sure to call advance() before calling this function,
163 !! or the result may still be associated with a prior time step.
164 !<
165 logical function any(this) result(a)
166 class(particlereleasescheduletype) :: this
167 a = this%count() > 0
168 end function any
169
170 !> @brief Return the number of releases scheduled.
171 !!
172 !! Note: be sure to call advance() before calling this function,
173 !! or the result may still be associated with a prior time step.
174 !<
175 integer function count(this) result(n)
176 class(particlereleasescheduletype) :: this
177 n = size(this%times)
178 end function count
179
This module contains simulation constants.
Definition Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition Constants.f90:45
real(dp), parameter dzero
real constant zero
Definition Constants.f90:65
real(dp), parameter done
real constant 1
Definition Constants.f90:76
This module defines variable data types.
Definition kind.f90:8
pure logical function, public is_close(a, b, rtol, atol, symmetric)
Check if a real value is approximately equal to another.
Definition MathUtil.f90:46
Particle release scheduling.
subroutine destroy(this)
Deallocate the release schedule.
subroutine schedule(this, trelease)
Add a release time to the schedule.
type(particlereleasescheduletype) function, pointer, public create_release_schedule(tolerance)
Create a new release schedule.
logical(lgp), pointer, public endofperiod
flag indicating end of stress period
Definition tdis.f90:30
real(dp), pointer, public totimc
simulation time at start of time step
Definition tdis.f90:36
integer(i4b), pointer, public kstp
current time step number
Definition tdis.f90:27
Specify times for some event to occur.
Definition TimeSelect.f90:2
subroutine advance(this)
Update the selection to the current time step.
integer(i4b) function count(this)
Return the number of times currently selected.
subroutine log(this, iout, verb)
Show the current time selection, if any.
logical(lgp) function any(this)
Check if any times are currently selected.
Time step selection module.
Represents a series of instants at which some event should occur.