MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
ExplicitSolution.f90
Go to the documentation of this file.
1 !> @brief Explicit solutions for solving explicit models.
2 !!
3 !! Explicit solutions manage and solve explicit models. An
4 !! explicit model solves itself, as opposed to a numerical
5 !! model which requires a numerical solution procedure. An
6 !! explicit solution involves a double loop: an outer loop
7 !! that continues until no model has pending work, as well
8 !! as an inner loop that scrolls through the models in the
9 !! solution and tells each to solve itself. The outer loop
10 !! is necessary because the explicit models may be coupled
11 !! by exchanges; models may send work during each solve to
12 !! other models. The outer loop continues until all models
13 !! have completed all work.
14 !<
16  use kindmodule, only: i4b, dp
17  use timermodule, only: code_timer
27  use listmodule, only: listtype
28  use listsmodule, only: basesolutionlist
32  use inputoutputmodule, only: getunit
33 
34  implicit none
35  private
36 
37  public :: create_explicit_solution
38  public :: explicitsolutiontype
39 
40  !> @brief Manages and solves explicit models.
42  character(len=LENMEMPATH) :: memorypath !< the path for storing solution variables in the memory manager
43  type(listtype), pointer :: modellist !< list of models in solution
44  type(listtype), pointer :: exchangelist !< list of exchanges in solution
45  integer(I4B), pointer :: id !< solution number
46  integer(I4B), pointer :: iu !< input file unit
47  real(dp), pointer :: ttsoln !< timer - total solution time
48  integer(I4B), pointer :: icnvg => null() !< convergence flag
49  type(blockparsertype) :: parser !< block parser object
50  contains
51  procedure :: sln_df
52  procedure :: sln_ar
53  procedure :: sln_dt
54  procedure :: sln_ad
55  procedure :: sln_ot
56  procedure :: sln_ca
57  procedure :: sln_fp
58  procedure :: sln_da
59  procedure :: add_model
60  procedure :: add_exchange
61  procedure :: get_models
62  procedure :: get_exchanges
63  procedure :: save
64 
65  procedure, private :: allocate_scalars
66 
67  ! Expose these for use through the BMI/XMI:
68  procedure, public :: preparesolve
69  procedure, public :: solve
70  procedure, public :: finalizesolve
71 
72  end type explicitsolutiontype
73 
74 contains
75 
76  !> @brief Create a new solution
77  !!
78  !! Create a new solution using the data in filename, assign this new
79  !! solution an id number and store the solution in the basesolutionlist.
80  !! Also open the filename for later reading.
81  !<
82  subroutine create_explicit_solution(exp_sol, filename, id)
83  ! modules
85  ! dummy
86  class(explicitsolutiontype), pointer :: exp_sol !< the create solution
87  character(len=*), intent(in) :: filename !< solution input file name
88  integer(I4B), intent(in) :: id !< solution id
89  ! local
90  integer(I4B) :: inunit
91  class(basesolutiontype), pointer :: solbase => null()
92  character(len=LENSOLUTIONNAME) :: solutionname
93 
94  ! Create a new solution and add it to the basesolutionlist container
95  solbase => exp_sol
96  write (solutionname, '(a, i0)') 'SLN_', id
97  exp_sol%name = solutionname
98  exp_sol%memoryPath = create_mem_path(solutionname)
99  allocate (exp_sol%modellist)
100  allocate (exp_sol%exchangelist)
101  call exp_sol%allocate_scalars()
103  exp_sol%id = id
104 
105  ! Open solution input file for reading later after problem size is known
106  ! Check to see if the file is already opened, which can happen when
107  ! running in single model mode
108  inquire (file=filename, number=inunit)
109  if (inunit < 0) inunit = getunit()
110  exp_sol%iu = inunit
111  write (iout, '(/a,a/)') ' Creating explicit solution (EMS): ', exp_sol%name
112  call openfile(exp_sol%iu, iout, filename, 'EMS')
113 
114  ! Initialize block parser
115  call exp_sol%parser%Initialize(exp_sol%iu, iout)
116  end subroutine create_explicit_solution
117 
118  !> @brief Allocate scalars
119  subroutine allocate_scalars(this)
120  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
121 
122  ! allocate
123  call mem_allocate(this%id, 'ID', this%memoryPath)
124  call mem_allocate(this%iu, 'IU', this%memoryPath)
125  call mem_allocate(this%ttsoln, 'TTSOLN', this%memoryPath)
126  call mem_allocate(this%icnvg, 'ICNVG', this%memoryPath)
127 
128  ! initialize
129  this%id = 0
130  this%iu = 0
131  this%ttsoln = dzero
132  this%icnvg = 0
133  end subroutine allocate_scalars
134 
135  !> @brief Define the solution
136  subroutine sln_df(this)
137  class(explicitsolutiontype) :: this
138  end subroutine
139 
140  !> @brief Allocate and read
141  subroutine sln_ar(this)
142  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
143  ! close ems input file
144  call this%parser%Clear()
145  end subroutine sln_ar
146 
147  !> @brief Calculate time step length
148  subroutine sln_dt(this)
149  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
150  end subroutine sln_dt
151 
152  !> @brief Advance the solution
153  subroutine sln_ad(this)
154  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
155 
156  ! reset convergence flag
157  this%icnvg = 0
158  end subroutine sln_ad
159 
160  !> @brief Output
161  subroutine sln_ot(this)
162  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
163  end subroutine sln_ot
164 
165  subroutine sln_fp(this)
166  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
167  end subroutine sln_fp
168 
169  !> @brief Deallocate
170  subroutine sln_da(this)
171  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
172 
173  ! lists
174  call this%modellist%Clear()
175  deallocate (this%modellist)
176  call this%exchangelist%Clear()
177  deallocate (this%exchangelist)
178 
179  ! scalars
180  call mem_deallocate(this%id)
181  call mem_deallocate(this%iu)
182  call mem_deallocate(this%ttsoln)
183  call mem_deallocate(this%icnvg)
184  end subroutine sln_da
185 
186  !> @brief Calculate
187  subroutine sln_ca(this, isgcnvg, isuppress_output)
188  ! dummy
189  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
190  integer(I4B), intent(inout) :: isgcnvg !< solution group convergence flag
191  integer(I4B), intent(in) :: isuppress_output !< flag for suppressing output
192  ! local
193  class(explicitmodeltype), pointer :: mp => null()
194  character(len=LINELENGTH) :: line
195  character(len=LINELENGTH) :: fmt
196  integer(I4B) :: im
197  integer(I4B) :: kiter
198 
199  kiter = 1
200 
201  call this%prepareSolve()
202 
203  select case (isim_mode)
204  case (mvalidate)
205  line = 'mode="validation" -- Skipping assembly and solution.'
206  fmt = "(/,1x,a,/)"
207  do im = 1, this%modellist%Count()
208  mp => getexplicitmodelfromlist(this%modellist, im)
209  call mp%model_message(line, fmt=fmt)
210  end do
211  case (mnormal)
212 
213  ! solve the models
214  call this%solve(kiter)
215 
216  ! finish up
217  call this%finalizeSolve(kiter, isgcnvg, isuppress_output)
218  end select
219  end subroutine sln_ca
220 
221  !> @brief Prepare to solve
222  subroutine preparesolve(this)
223  ! dummy
224  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
225  ! local
226  integer(I4B) :: i
227  class(explicitmodeltype), pointer :: mp => null()
228  class(baseexchangetype), pointer :: ep => null()
229 
230  ! advance exchanges
231  do i = 1, this%exchangelist%Count()
232  ep => getbaseexchangefromlist(this%exchangelist, i)
233  call ep%exg_ad()
234  end do
235 
236  ! advance models
237  do i = 1, this%modellist%Count()
238  mp => getexplicitmodelfromlist(this%modellist, i)
239  call mp%model_ad()
240  end do
241 
242  ! advance solution
243  call this%sln_ad()
244  end subroutine preparesolve
245 
246  !> @brief Solve models
247  subroutine solve(this, kiter)
248  ! dummy
249  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
250  integer(I4B), intent(in) :: kiter !< Picard iteration (1 for explicit)
251  ! local
252  class(explicitmodeltype), pointer :: mp => null()
253  integer(I4B) :: im
254  logical :: any_pending
255  real(DP) :: ttsoln
256 
257  call code_timer(0, ttsoln, this%ttsoln)
258 
259  ! Outer loop: repeat until no model has pending work
260  do
261  ! Solve every model in the solution
262  do im = 1, this%modellist%Count()
263  mp => getexplicitmodelfromlist(this%modellist, im)
264  call mp%model_solve()
265  end do
266 
267  ! Continue if any have pending work
268  any_pending = .false.
269  do im = 1, this%modellist%Count()
270  mp => getexplicitmodelfromlist(this%modellist, im)
271  if (mp%has_pending()) then
272  any_pending = .true.
273  exit
274  end if
275  end do
276  if (.not. any_pending) exit
277  end do
278 
279  call code_timer(1, ttsoln, this%ttsoln)
280  this%icnvg = 1
281  end subroutine solve
282 
283  !> @brief Finalize solve
284  subroutine finalizesolve(this, kiter, isgcnvg, isuppress_output)
285  ! dummy
286  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
287  integer(I4B), intent(in) :: kiter !< Picard iteration number (always 1 for explicit)
288  integer(I4B), intent(inout) :: isgcnvg !< solution group convergence flag
289  integer(I4B), intent(in) :: isuppress_output !< flag for suppressing output
290  ! local
291  integer(I4B) :: im
292  class(explicitmodeltype), pointer :: mp => null()
293 
294  ! Calculate flow for each model
295  do im = 1, this%modellist%Count()
296  mp => getexplicitmodelfromlist(this%modellist, im)
297  call mp%model_cq(this%icnvg, isuppress_output)
298  end do
299 
300  ! Budget terms for each model
301  do im = 1, this%modellist%Count()
302  mp => getexplicitmodelfromlist(this%modellist, im)
303  call mp%model_bd(this%icnvg, isuppress_output)
304  end do
305  end subroutine finalizesolve
306 
307  !> @brief Save output
308  subroutine save(this, filename)
309  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
310  character(len=*), intent(in) :: filename !< filename to save solution data
311  integer(I4B) :: inunit
312  inunit = getunit()
313  open (unit=inunit, file=filename, status='unknown')
314  write (inunit, *) 'The save routine currently writes nothing'
315  close (inunit)
316  end subroutine save
317 
318  !> @brief Add explicit model to list
319  subroutine add_model(this, mp)
320  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
321  class(basemodeltype), pointer, intent(in) :: mp !< model instance
322  class(explicitmodeltype), pointer :: m => null()
323  select type (mp)
324  class is (explicitmodeltype)
325  m => mp
326  call addexplicitmodeltolist(this%modellist, m)
327  end select
328  end subroutine add_model
329 
330  !> @brief Get a pointer to a list of models in the solution
331  function get_models(this) result(models)
332  type(listtype), pointer :: models !< pointer to the model list
333  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
334  models => this%modellist
335  end function get_models
336 
337  !> @brief Add exchange to list of exchanges
338  subroutine add_exchange(this, exchange)
339  class(explicitsolutiontype) :: this
340  class(baseexchangetype), pointer, intent(in) :: exchange
341  class(*), pointer :: obj
342  obj => exchange
343  call this%exchangelist%Add(obj)
344  end subroutine add_exchange
345 
346  !> @brief Get list of exchanges
347  function get_exchanges(this) result(exchanges)
348  class(explicitsolutiontype) :: this
349  type(listtype), pointer :: exchanges
350  exchanges => this%exchangelist
351  end function get_exchanges
352 
353 end module explicitsolutionmodule
class(baseexchangetype) function, pointer, public getbaseexchangefromlist(list, idx)
Retrieve a specific BaseExchangeType object from a list.
subroutine, public addbasesolutiontolist(list, solution)
This module contains block parser methods.
Definition: BlockParser.f90:7
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
@ mvalidate
validation mode - do not run time steps
Definition: Constants.f90:205
@ mnormal
normal output mode
Definition: Constants.f90:206
integer(i4b), parameter lensolutionname
maximum length of the solution name
Definition: Constants.f90:21
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
Models that solve themselves.
class(explicitmodeltype) function, pointer, public getexplicitmodelfromlist(list, idx)
@ brief Get generic object from list and return as explicit model
subroutine, public addexplicitmodeltolist(list, model)
@ brief Add explicit model to a generic list
Explicit solutions for solving explicit models.
subroutine preparesolve(this)
Prepare to solve.
type(listtype) function, pointer get_models(this)
Get a pointer to a list of models in the solution.
subroutine, public create_explicit_solution(exp_sol, filename, id)
Create a new solution.
subroutine add_model(this, mp)
Add explicit model to list.
subroutine add_exchange(this, exchange)
Add exchange to list of exchanges.
type(listtype) function, pointer get_exchanges(this)
Get list of exchanges.
subroutine save(this, filename)
Save output.
subroutine finalizesolve(this, kiter, isgcnvg, isuppress_output)
Finalize solve.
subroutine allocate_scalars(this)
Allocate scalars.
integer(i4b) function, public getunit()
Get a free unit number.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
This module defines variable data types.
Definition: kind.f90:8
type(listtype), public basesolutionlist
Definition: mf6lists.f90:19
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
This module contains simulation variables.
Definition: SimVariables.f90:9
integer(i4b) iout
file unit number for simulation output
integer(i4b) isim_mode
simulation mode
subroutine, public code_timer(it, t1, ts)
Get end time and calculate elapsed time.
Definition: Timer.f90:159
Highest level model type. All models extend this parent type.
Definition: BaseModel.f90:16
Base type for models that solve themselves.
Manages and solves explicit models.
A generic heterogeneous doubly-linked list.
Definition: List.f90:14