MODFLOW 6  version 6.7.0.dev0
USGS Modular Hydrologic Model
ConnectionBuilder.f90
Go to the documentation of this file.
2  use kindmodule, only: i4b, lgp
4  use simvariablesmodule, only: iout
5  use listmodule, only: listtype, isequaliface
14  cast_as_smc, &
17 
18  implicit none
19  private
20 
21  type, public :: connectionbuildertype
22  logical(LGP) :: dev_always_ifmod = .false. !< development option: force interface model on all exchanges
23  contains
24  procedure, pass(this) :: processsolution
25  procedure, private, pass(this) :: processexchanges
26  procedure, private, pass(this) :: setconnectionstosolution
27  procedure, private, pass(this) :: createmodelconnectivity
28  end type connectionbuildertype
29 
30 contains
31 
32  !> @brief Process the exchanges in the solution into model connections
33  !!
34  !! This routine processes all exchanges in a solution and,
35  !! when required, creates model connections of the proper
36  !! type (GWF-GWF, GWT-GWT, ...) for a subset. It removes this
37  !! subset of exchanges from the solution and replaces them with the
38  !! created connections.
39  !<
40  subroutine processsolution(this, solution)
41  class(connectionbuildertype) :: this !< the connection builder object
42  class(basesolutiontype), pointer :: solution !< the solution for which the exchanges are processed
43  ! local
44  class(numericalsolutiontype), pointer :: numSol
45  type(listtype) :: newConnections
46 
47  ! we only deal with Num. Sol. here
48  select type (solution)
49  class is (numericalsolutiontype)
50  numsol => solution
51  class default
52  return
53  end select
54 
55  ! create the connections and add local exchanges
56  call this%processExchanges(numsol%exchangelist, newconnections)
57  if (newconnections%Count() == 0) then
58  return
59  end if
60 
61  write (iout, '(1x,a,i0,a,a)') 'Created ', newconnections%Count(), &
62  ' model connections for solution ', trim(solution%name)
63 
64  ! create the topology of models participating in the interfaces
65  call this%createModelConnectivity(newconnections)
66 
67  ! replace numerical exchanges in solution with connections
68  call this%setConnectionsToSolution(newconnections, numsol)
69 
70  ! clean up local resources
71  call newconnections%Clear(destroy=.false.)
72 
73  end subroutine processsolution
74 
75  !> @brief Create connections from exchanges
76  !!
77  !! If the configuration demands it, this will create connections,
78  !! for the exchanges (one connection per exchange) add them to
79  !! the global list, and return them as @param newConnections
80  !<
81  subroutine processexchanges(this, exchanges, newConnections)
83  class(connectionbuildertype) :: this !< the connection builder object
84  type(listtype), pointer, intent(in) :: exchanges !< the list of exchanges to process
85  type(listtype), intent(inout) :: newConnections !< the newly created connections
86  ! local
87  class(disconnexchangetype), pointer :: conEx
88  class(baseexchangetype), pointer :: baseEx
89  integer(I4B) :: iex, ibasex
90  class(spatialmodelconnectiontype), pointer :: modelConnection
91  logical(LGP) :: isPeriodic
92 
93  do iex = 1, exchanges%Count()
94  conex => getdisconnexchangefromlist(exchanges, iex)
95  if (.not. associated(conex)) then
96  ! if it is not DisConnExchangeType, we can skip it
97  cycle
98  end if
99 
100  ! for now, if we have XT3D on the interface, we use a connection,
101  ! (this will be more generic in the future)
102  if (conex%use_interface_model() .or. conex%dev_ifmod_on &
103  .or. this%dev_always_ifmod) then
104 
105  ! we should not get period connections here
106  isperiodic = (conex%v_model1 == conex%v_model2)
107  if (isperiodic) then
108  write (*, *) 'Error (which should never happen): interface model '// &
109  'does not support periodic boundary condition'
110  call ustop()
111  end if
112 
113  if (conex%v_model1%is_local) then
114  ! create model connection for model 1
115  modelconnection => createmodelconnection(conex%model1, conex)
116  call add_smc_to_list(baseconnectionlist, modelconnection)
117  call add_smc_to_list(newconnections, modelconnection)
118  end if
119 
120  ! and for model 2
121  if (conex%v_model2%is_local) then
122  modelconnection => createmodelconnection(conex%model2, conex)
123  call add_smc_to_list(baseconnectionlist, modelconnection)
124  call add_smc_to_list(newconnections, modelconnection)
125  end if
126 
127  ! remove this exchange from the base list, ownership
128  ! now lies with the connection
129  do ibasex = 1, baseexchangelist%Count()
130  baseex => getbaseexchangefromlist(baseexchangelist, ibasex)
131  if (conex%id == baseex%id) then
132  call baseexchangelist%RemoveNode(ibasex, .false.)
133  exit
134  end if
135  end do
136 
137  end if
138  end do
139 
140  end subroutine processexchanges
141 
142  !> @brief Create a model connection of a given type
143  !!
144  !! This is a factory method to create the various types
145  !! of model connections
146  !<
147  function createmodelconnection(model, exchange) result(connection)
148  use simmodule, only: ustop
152  use gwfmodule, only: gwfmodeltype
153 
154  class(numericalmodeltype), pointer, intent(in) :: model !< the model for which the connection will be created
155  class(disconnexchangetype), pointer, intent(in) :: exchange !< the type of connection
156  class(spatialmodelconnectiontype), pointer :: connection !< the created connection
157 
158  ! different concrete connection types:
159  class(gwfgwfconnectiontype), pointer :: flowconnection => null()
160  class(gwtgwtconnectiontype), pointer :: transportconnection => null()
161  class(gwegweconnectiontype), pointer :: energytransportconnection => null()
162 
163  connection => null()
164 
165  ! select on type of connection to create
166  select case (exchange%typename)
167  case ('GWF-GWF')
168  allocate (gwfgwfconnectiontype :: flowconnection)
169  call flowconnection%construct(model, exchange)
170  connection => flowconnection
171  flowconnection => null()
172  case ('GWT-GWT')
173  allocate (gwtgwtconnectiontype :: transportconnection)
174  call transportconnection%construct(model, exchange)
175  connection => transportconnection
176  transportconnection => null()
177  case ('GWE-GWE')
178  allocate (gwegweconnectiontype :: energytransportconnection)
179  call energytransportconnection%construct(model, exchange)
180  connection => energytransportconnection
181  energytransportconnection => null()
182  case default
183  write (*, *) 'Error (which should never happen): '// &
184  'undefined exchangetype found'
185  call ustop()
186  end select
187 
188  end function createmodelconnection
189 
190  !> @brief Set connections to the solution
191  !!
192  !! This adds the connections to the solution and removes
193  !! those exchanges which are replaced by a connection
194  !<
195  subroutine setconnectionstosolution(this, connections, solution)
196  class(connectionbuildertype) :: this !< the connection builder object
197  type(listtype), intent(inout) :: connections !< the connections created for the solution
198  class(numericalsolutiontype), pointer, intent(in) :: solution !< the solution to which the connections are set
199  ! local
200  type(listtype) :: keepList
201  class(*), pointer :: exPtr, exPtr2, connPtr
202  class(spatialmodelconnectiontype), pointer :: conn
203  integer(I4B) :: iex, iconn
204  logical(LGP) :: keepExchange
205 
206  ! first add all exchanges not replaced by the connections to a list
207  do iex = 1, solution%exchangelist%Count()
208  exptr => solution%exchangelist%GetItem(iex)
209  ! will this exchange be replaced by a connection?
210  keepexchange = .true.
211  do iconn = 1, connections%Count()
212  conn => get_smc_from_list(connections, iconn)
213  exptr2 => conn%prim_exchange
214  if (associated(exptr2, exptr)) then
215  ! if so, don't add it to the list
216  keepexchange = .false.
217  exit
218  end if
219  end do
220 
221  if (keepexchange) then
222  call keeplist%Add(exptr)
223  end if
224  end do
225 
226  ! first add persisting exchanges
227  call solution%exchangelist%Clear(destroy=.false.)
228  do iex = 1, keeplist%Count()
229  exptr => keeplist%GetItem(iex)
230  call solution%exchangelist%Add(exptr)
231  end do
232 
233  ! now add connections
234  do iconn = 1, connections%Count()
235  connptr => connections%GetItem(iconn)
236  call solution%exchangelist%Add(connptr)
237  end do
238 
239  ! clean up
240  call keeplist%Clear(destroy=.false.)
241 
242  end subroutine setconnectionstosolution
243 
244  !> @brief Create connectivity of models which contribute to the interface
245  !!
246  !! This loops over all connections and creates a halo with all
247  !! models from the numerical solution. The model halo will be used to
248  !! extend the interface grid to include cells from models which are
249  !< indirectly connected, through yet another exchange object.
250  subroutine createmodelconnectivity(this, connections)
251  class(connectionbuildertype) :: this !< the connection builder object
252  type(listtype), intent(inout) :: connections !< all connections that are created for this solution
253  ! local
254  integer(I4B) :: iconn
255  class(spatialmodelconnectiontype), pointer :: modelConn
256 
257  ! create halo for the model connections
258  do iconn = 1, connections%Count()
259  modelconn => get_smc_from_list(connections, iconn)
260  call modelconn%createModelHalo()
261  end do
262 
263  end subroutine createmodelconnectivity
264 
265 end module connectionbuildermodule
class(baseexchangetype) function, pointer, public getbaseexchangefromlist(list, idx)
Retrieve a specific BaseExchangeType object from a list.
subroutine processsolution(this, solution)
Process the exchanges in the solution into model connections.
class(spatialmodelconnectiontype) function, pointer createmodelconnection(model, exchange)
Create a model connection of a given type.
subroutine setconnectionstosolution(this, connections, solution)
Set connections to the solution.
subroutine createmodelconnectivity(this, connections)
Create connectivity of models which contribute to the interface.
subroutine processexchanges(this, exchanges, newConnections)
Create connections from exchanges.
class(disconnexchangetype) function, pointer, public getdisconnexchangefromlist(list, idx)
Definition: gwf.f90:1
This module defines variable data types.
Definition: kind.f90:8
type(listtype), public baseexchangelist
Definition: mf6lists.f90:25
type(listtype), public baseconnectionlist
Definition: mf6lists.f90:28
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public ustop(stopmess, ioutlocal)
Stop the simulation.
Definition: Sim.f90:312
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
integer(i4b) function, public count_errors()
Return number of errors.
Definition: Sim.f90:59
This module contains simulation variables.
Definition: SimVariables.f90:9
integer(i4b) iout
file unit number for simulation output
class(spatialmodelconnectiontype) function, pointer, public get_smc_from_list(list, idx)
Get the connection from a list.
class(spatialmodelconnectiontype) function, pointer, public cast_as_smc(obj)
Cast to SpatialModelConnectionType.
subroutine, public add_smc_to_list(list, conn)
Add connection to a list.
Exchange based on connection between discretizations of DisBaseType. The data specifies the connectio...
Connects a GWE model to other GWE models in space. Derives from NumericalExchangeType so the solution...
Connecting a GWF model to other models in space, implements NumericalExchangeType so the solution can...
Connects a GWT model to other GWT models in space. Derives from NumericalExchangeType so the solution...
A generic heterogeneous doubly-linked list.
Definition: List.f90:14
Class to manage spatial connection of a model to one or more models of the same type....