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, isuppress_output)
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, isuppress_output)
248  ! dummy
249  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
250  integer(I4B), intent(in) :: kiter !< Picard iteration (1 for explicit)
251  integer(I4B), intent(in) :: isuppress_output !< flag for suppressing output
252  ! local
253  class(explicitmodeltype), pointer :: mp => null()
254  integer(I4B) :: im
255  logical :: any_pending
256  real(DP) :: ttsoln
257 
258  call code_timer(0, ttsoln, this%ttsoln)
259 
260  ! Outer loop: repeat until no model has pending work
261  do
262  ! Solve every model in the solution
263  do im = 1, this%modellist%Count()
264  mp => getexplicitmodelfromlist(this%modellist, im)
265  call mp%model_solve(isuppress_output)
266  end do
267 
268  ! Continue if any have pending work
269  any_pending = .false.
270  do im = 1, this%modellist%Count()
271  mp => getexplicitmodelfromlist(this%modellist, im)
272  if (mp%has_pending()) then
273  any_pending = .true.
274  exit
275  end if
276  end do
277  if (.not. any_pending) exit
278  end do
279 
280  call code_timer(1, ttsoln, this%ttsoln)
281  this%icnvg = 1
282  end subroutine solve
283 
284  !> @brief Finalize solve
285  subroutine finalizesolve(this, kiter, isgcnvg, isuppress_output)
286  ! dummy
287  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
288  integer(I4B), intent(in) :: kiter !< Picard iteration number (always 1 for explicit)
289  integer(I4B), intent(inout) :: isgcnvg !< solution group convergence flag
290  integer(I4B), intent(in) :: isuppress_output !< flag for suppressing output
291  ! local
292  integer(I4B) :: im
293  class(explicitmodeltype), pointer :: mp => null()
294 
295  ! Calculate flow for each model
296  do im = 1, this%modellist%Count()
297  mp => getexplicitmodelfromlist(this%modellist, im)
298  call mp%model_cq(this%icnvg, isuppress_output)
299  end do
300 
301  ! Budget terms for each model
302  do im = 1, this%modellist%Count()
303  mp => getexplicitmodelfromlist(this%modellist, im)
304  call mp%model_bd(this%icnvg, isuppress_output)
305  end do
306  end subroutine finalizesolve
307 
308  !> @brief Save output
309  subroutine save(this, filename)
310  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
311  character(len=*), intent(in) :: filename !< filename to save solution data
312  integer(I4B) :: inunit
313  inunit = getunit()
314  open (unit=inunit, file=filename, status='unknown')
315  write (inunit, *) 'The save routine currently writes nothing'
316  close (inunit)
317  end subroutine save
318 
319  !> @brief Add explicit model to list
320  subroutine add_model(this, mp)
321  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
322  class(basemodeltype), pointer, intent(in) :: mp !< model instance
323  class(explicitmodeltype), pointer :: m => null()
324  select type (mp)
325  class is (explicitmodeltype)
326  m => mp
327  call addexplicitmodeltolist(this%modellist, m)
328  end select
329  end subroutine add_model
330 
331  !> @brief Get a pointer to a list of models in the solution
332  function get_models(this) result(models)
333  type(listtype), pointer :: models !< pointer to the model list
334  class(explicitsolutiontype) :: this !< ExplicitSolutionType instance
335  models => this%modellist
336  end function get_models
337 
338  !> @brief Add exchange to list of exchanges
339  subroutine add_exchange(this, exchange)
340  class(explicitsolutiontype) :: this
341  class(baseexchangetype), pointer, intent(in) :: exchange
342  class(*), pointer :: obj
343  obj => exchange
344  call this%exchangelist%Add(obj)
345  end subroutine add_exchange
346 
347  !> @brief Get list of exchanges
348  function get_exchanges(this) result(exchanges)
349  class(explicitsolutiontype) :: this
350  type(listtype), pointer :: exchanges
351  exchanges => this%exchangelist
352  end function get_exchanges
353 
354 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