MODFLOW 6  version 6.7.0.dev3
USGS Modular Hydrologic Model
spatialmodelconnectionmodule Module Reference

Data Types

type  spatialmodelconnectiontype
 Class to manage spatial connection of a model to one or more models of the same type. Spatial connection here means that the model domains (spatial discretization) are adjacent and connected via DisConnExchangeType object(s). The connection itself is a Numerical Exchange as well, and part of a Numerical Solution providing the amat and rhs. More...
 

Functions/Subroutines

subroutine spatialconnection_ctor (this, model, exchange, name)
 Construct the spatial connection base. More...
 
subroutine createmodelhalo (this)
 Find all models that might participate in this interface. More...
 
recursive subroutine addmodelneighbors (this, model_id, virtual_exchanges, depth, is_root, mask)
 Add neighbors and nbrs-of-nbrs to the model tree. More...
 
subroutine spatialcon_df (this)
 Define this connection, this is where the discretization (DISU) for the interface model is. More...
 
subroutine spatialcon_ar (this)
 Allocate the connection,. More...
 
subroutine spatialcon_setmodelptrs (this)
 set model pointers to connection More...
 
subroutine spatialcon_connect (this)
 map interface model connections to our sparse matrix, More...
 
subroutine maskownerconnections (this)
 Mask the owner's connections. More...
 
subroutine createcoefficientmatrix (this, sparse)
 Add connections, handled by the interface model,. More...
 
subroutine validateconnection (this)
 Validate this connection. More...
 
subroutine cfg_dv (this, var_name, subcomp_name, map_type, sync_stages, exg_var_name)
 Add a variable from the interface model to be synchronized at the configured stages by copying from the source memory in the models/exchanges that are part. More...
 
class(spatialmodelconnectiontype) function, pointer, public cast_as_smc (obj)
 Cast to SpatialModelConnectionType. More...
 
subroutine, public add_smc_to_list (list, conn)
 Add connection to a list. More...
 
class(spatialmodelconnectiontype) function, pointer, public get_smc_from_list (list, idx)
 Get the connection from a list. More...
 

Function/Subroutine Documentation

◆ add_smc_to_list()

subroutine, public spatialmodelconnectionmodule::add_smc_to_list ( type(listtype), intent(inout)  list,
class(spatialmodelconnectiontype), intent(in), pointer  conn 
)
Parameters
[in,out]listthe list
[in]connthe connection

Definition at line 700 of file SpatialModelConnection.f90.

701  implicit none
702  ! -- dummy
703  type(ListType), intent(inout) :: list !< the list
704  class(SpatialModelConnectionType), pointer, intent(in) :: conn !< the connection
705  ! -- local
706  class(*), pointer :: obj
707  !
708  obj => conn
709  call list%Add(obj)
Here is the caller graph for this function:

◆ addmodelneighbors()

recursive subroutine spatialmodelconnectionmodule::addmodelneighbors ( class(spatialmodelconnectiontype this,
integer(i4b)  model_id,
type(listtype virtual_exchanges,
integer(i4b), value  depth,
logical(lgp)  is_root,
integer(i4b), optional  mask 
)
private
Parameters
thisthis connection
model_idthe model (id) to add neighbors for
virtual_exchangeslist with all virtual exchanges
depththe maximal number of exchanges between
is_roottrue when called for neighbor from primary exchange
maskdon't add this one as a neighbor

Definition at line 155 of file SpatialModelConnection.f90.

159  class(SpatialModelConnectionType) :: this !< this connection
160  integer(I4B) :: model_id !< the model (id) to add neighbors for
161  type(ListType) :: virtual_exchanges !< list with all virtual exchanges
162  integer(I4B), value :: depth !< the maximal number of exchanges between
163  logical(LGP) :: is_root !< true when called for neighbor from primary exchange
164  integer(I4B), optional :: mask !< don't add this one as a neighbor
165  ! local
166  integer(I4B) :: i, n
167  class(VirtualExchangeType), pointer :: v_exg
168  integer(I4B) :: neighbor_id
169  integer(I4B) :: model_mask
170  type(STLVecInt) :: models_at_depth !< model ids at a certain depth, to
171  !! recurse on for nbrs-of-nbrs search
172 
173  if (.not. present(mask)) then
174  model_mask = 0
175  else
176  model_mask = mask
177  end if
178 
179  call models_at_depth%init()
180 
181  if (is_root) then
182  ! first layer in the recursive search
183  call models_at_depth%push_back_unique(model_id)
184 
185  ! fetch primary neighbor
186  if (this%prim_exchange%v_model1%id == this%owner%id) then
187  neighbor_id = this%prim_exchange%v_model2%id
188  else
189  neighbor_id = this%prim_exchange%v_model1%id
190  end if
191  ! add
192  call models_at_depth%push_back_unique(neighbor_id)
193  call this%halo_models%push_back_unique(neighbor_id)
194  call this%halo_exchanges%push_back_unique(this%prim_exchange%id)
195  else
196  ! find all direct neighbors of the model and add them,
197  ! avoiding duplicates
198  do i = 1, virtual_exchanges%Count()
199  neighbor_id = -1
200  v_exg => get_virtual_exchange_from_list(virtual_exchanges, i)
201  if (v_exg%v_model1%id == model_id) then
202  neighbor_id = v_exg%v_model2%id
203  else if (v_exg%v_model2%id == model_id) then
204  neighbor_id = v_exg%v_model1%id
205  end if
206 
207  ! check if there is a neighbor, and it is not masked
208  ! (to prevent back-and-forth connections)
209  if (neighbor_id > 0) then
210  ! check if masked
211  if (neighbor_id == model_mask) cycle
212  call models_at_depth%push_back_unique(neighbor_id)
213  call this%halo_models%push_back_unique(neighbor_id)
214  call this%halo_exchanges%push_back_unique(v_exg%id)
215  end if
216  end do
217  end if
218 
219  depth = depth - 1
220  if (depth == 0) then
221  ! and we're done with this branch
222  call models_at_depth%destroy()
223  return
224  end if
225 
226  ! now recurse on the neighbors up to the specified depth
227  do n = 1, models_at_depth%size
228  call this%addModelNeighbors(models_at_depth%at(n), virtual_exchanges, &
229  depth, .false., model_id)
230  end do
231 
232  ! we're done with the tree
233  call models_at_depth%destroy()
234 
class(virtualexchangetype) function, pointer, public get_virtual_exchange(exg_id)
Returns a virtual exchange with the specified id.
Here is the call graph for this function:

◆ cast_as_smc()

class(spatialmodelconnectiontype) function, pointer, public spatialmodelconnectionmodule::cast_as_smc ( class(*), intent(inout), pointer  obj)
Parameters
[in,out]objobject to be cast
Returns
the instance of SpatialModelConnectionType

Definition at line 684 of file SpatialModelConnection.f90.

685  implicit none
686  class(*), pointer, intent(inout) :: obj !< object to be cast
687  class(SpatialModelConnectionType), pointer :: res !< the instance of SpatialModelConnectionType
688  !
689  res => null()
690  if (.not. associated(obj)) return
691  !
692  select type (obj)
693  class is (spatialmodelconnectiontype)
694  res => obj
695  end select
Here is the caller graph for this function:

◆ cfg_dv()

subroutine spatialmodelconnectionmodule::cfg_dv ( class(spatialmodelconnectiontype this,
character(len=*)  var_name,
character(len=*)  subcomp_name,
integer(i4b)  map_type,
integer(i4b), dimension(:)  sync_stages,
character(len=*), optional  exg_var_name 
)
private
Parameters
thisthis connection
var_namename of variable, e.g. "K11"
subcomp_namesubcomponent, e.g. "NPF"
map_typetype of variable map
sync_stagesstages to sync
exg_var_nameneeded for exchange variables, e.g. SIMVALS

Definition at line 655 of file SpatialModelConnection.f90.

657  class(SpatialModelConnectionType) :: this !< this connection
658  character(len=*) :: var_name !< name of variable, e.g. "K11"
659  character(len=*) :: subcomp_name !< subcomponent, e.g. "NPF"
660  integer(I4B) :: map_type !< type of variable map
661  integer(I4B), dimension(:) :: sync_stages !< stages to sync
662  character(len=*), optional :: exg_var_name !< needed for exchange variables, e.g. SIMVALS
663  ! local
664  type(DistVarType), pointer :: dist_var => null()
665  class(*), pointer :: obj
666 
667  if (.not. present(exg_var_name)) exg_var_name = ''
668 
669  allocate (dist_var)
670  dist_var%var_name = var_name
671  dist_var%subcomp_name = subcomp_name
672  dist_var%comp_name = this%interface_model%name
673  dist_var%map_type = map_type
674  dist_var%sync_stages = sync_stages
675  dist_var%exg_var_name = exg_var_name
676 
677  obj => dist_var
678  call this%iface_dist_vars%Add(obj)
679 

◆ createcoefficientmatrix()

subroutine spatialmodelconnectionmodule::createcoefficientmatrix ( class(spatialmodelconnectiontype this,
type(sparsematrix), intent(inout)  sparse 
)
Parameters
thisthis connection
[in,out]sparsethe sparse matrix with the cell connections

Definition at line 610 of file SpatialModelConnection.f90.

611  use simmodule, only: ustop
612  class(SpatialModelConnectionType) :: this !< this connection
613  type(sparsematrix), intent(inout) :: sparse !< the sparse matrix with the cell connections
614 
615  call sparse%sort()
616  call this%matrix%init(sparse, this%memoryPath)
617 
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public ustop(stopmess, ioutlocal)
Stop the simulation.
Definition: Sim.f90:312
Here is the call graph for this function:

◆ createmodelhalo()

subroutine spatialmodelconnectionmodule::createmodelhalo ( class(spatialmodelconnectiontype this)
private
Parameters
thisthis connection

Definition at line 142 of file SpatialModelConnection.f90.

143  class(SpatialModelConnectionType) :: this !< this connection
144 
145  call this%halo_models%init()
146  call this%halo_exchanges%init()
147 
148  call this%addModelNeighbors(this%owner%id, virtual_exchange_list, &
149  this%exg_stencil_depth, .true.)
150 

◆ get_smc_from_list()

class(spatialmodelconnectiontype) function, pointer, public spatialmodelconnectionmodule::get_smc_from_list ( type(listtype), intent(inout)  list,
integer(i4b), intent(in)  idx 
)
Parameters
[in,out]listthe list
[in]idxthe index of the connection
Returns
the returned connection

Definition at line 714 of file SpatialModelConnection.f90.

715  type(ListType), intent(inout) :: list !< the list
716  integer(I4B), intent(in) :: idx !< the index of the connection
717  class(SpatialModelConnectionType), pointer :: res !< the returned connection
718 
719  ! local
720  class(*), pointer :: obj
721  obj => list%GetItem(idx)
722  res => cast_as_smc(obj)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ maskownerconnections()

subroutine spatialmodelconnectionmodule::maskownerconnections ( class(spatialmodelconnectiontype this)
private

Determine which connections are handled by the interface model (using the connections object in its discretization) and

Parameters
thisthe connection

Definition at line 332 of file SpatialModelConnection.f90.

333  use csrutilsmodule, only: getcsrindex
334  class(SpatialModelConnectionType) :: this !< the connection
335  ! local
336  integer(I4B) :: ipos, n, m, nloc, mloc, csr_idx
337  type(ConnectionsType), pointer :: conn
338 
339  ! set the mask on connections that are calculated by the interface model
340  conn => this%interface_model%dis%con
341  do n = 1, conn%nodes
342  ! only for connections internal to the owning model
343  if (.not. this%ig_builder%idxToGlobal(n)%v_model == this%owner) then
344  cycle
345  end if
346  nloc = this%ig_builder%idxToGlobal(n)%index
347 
348  do ipos = conn%ia(n) + 1, conn%ia(n + 1) - 1
349  m = conn%ja(ipos)
350  if (.not. this%ig_builder%idxToGlobal(m)%v_model == this%owner) then
351  cycle
352  end if
353  mloc = this%ig_builder%idxToGlobal(m)%index
354 
355  if (conn%mask(ipos) > 0) then
356  ! calculated by interface model, set local model's mask to zero
357  csr_idx = getcsrindex(nloc, mloc, this%owner%ia, this%owner%ja)
358  if (csr_idx == -1) then
359  ! this can only happen with periodic boundary conditions,
360  ! then there is no need to set the mask
361  if (this%ig_builder%isPeriodic(nloc, mloc)) cycle
362 
363  write (*, *) 'Error: cannot find cell connection in global system'
364  call ustop()
365  end if
366 
367  if (this%owner%dis%con%mask(csr_idx) > 0) then
368  call this%owner%dis%con%set_mask(csr_idx, 0)
369  else
370  ! edge case, this connection is already being calculated
371  ! so we ignore it here. This can happen in the overlap
372  ! between two different exchanges when a larger stencil
373  ! (XT3D) is applied.
374  call conn%set_mask(ipos, 0)
375  end if
376  end if
377  end do
378  end do
379 
integer(i4b) function, public getcsrindex(i, j, ia, ja)
Return index for element i,j in CSR storage,.
Definition: CsrUtils.f90:13
Here is the call graph for this function:

◆ spatialcon_ar()

subroutine spatialmodelconnectionmodule::spatialcon_ar ( class(spatialmodelconnectiontype this)
private
Parameters
thisthis connection

Definition at line 267 of file SpatialModelConnection.f90.

268  class(SpatialModelConnectionType) :: this !< this connection
269  ! local
270  integer(I4B) :: iface_idx, glob_idx
271  class(GridConnectionType), pointer :: gc
272 
273  ! fill mapping to global index (which can be
274  ! done now because moffset is set in sln_df)
275  gc => this%ig_builder
276  do iface_idx = 1, gc%nrOfCells
277  glob_idx = gc%idxToGlobal(iface_idx)%index + &
278  gc%idxToGlobal(iface_idx)%v_model%moffset%get()
279  gc%idxToGlobalIdx(iface_idx) = glob_idx
280  end do
281 

◆ spatialcon_connect()

subroutine spatialmodelconnectionmodule::spatialcon_connect ( class(spatialmodelconnectiontype this)
private
Parameters
thisthis connection

Definition at line 307 of file SpatialModelConnection.f90.

308  class(SpatialModelConnectionType) :: this !< this connection
309  ! local
310  type(sparsematrix) :: sparse
311  class(MatrixBaseType), pointer :: matrix_base
312 
313  call sparse%init(this%neq, this%neq, 7)
314  call this%interface_model%model_ac(sparse)
315 
316  ! create amat from sparse
317  call this%createCoefficientMatrix(sparse)
318  call sparse%destroy()
319 
320  ! map connections
321  matrix_base => this%matrix
322  call this%interface_model%model_mc(matrix_base)
323  call this%maskOwnerConnections()
324 

◆ spatialcon_df()

subroutine spatialmodelconnectionmodule::spatialcon_df ( class(spatialmodelconnectiontype this)
Parameters
thisthis connection

Definition at line 240 of file SpatialModelConnection.f90.

241  class(SpatialModelConnectionType) :: this !< this connection
242  ! local
243  integer(I4B) :: i
244  class(VirtualModelType), pointer :: v_model
245 
246  ! create the grid connection data structure
247  this%nr_connections = this%getNrOfConnections()
248  call this%ig_builder%construct(this%owner, &
249  this%nr_connections, &
250  this%name)
251  this%ig_builder%internalStencilDepth = this%int_stencil_depth
252  this%ig_builder%exchangeStencilDepth = this%exg_stencil_depth
253  this%ig_builder%haloExchanges => this%halo_exchanges
254  do i = 1, this%halo_models%size
255  v_model => get_virtual_model(this%halo_models%at(i))
256  call this%ig_builder%addToRegionalModels(v_model)
257  end do
258  call this%setupGridConnection()
259 
260  this%neq = this%ig_builder%nrOfCells
261  call this%allocateArrays()
262 

◆ spatialcon_setmodelptrs()

subroutine spatialmodelconnectionmodule::spatialcon_setmodelptrs ( class(spatialmodelconnectiontype this)
private
Parameters
thisthis connection

Definition at line 286 of file SpatialModelConnection.f90.

287  class(SpatialModelConnectionType) :: this !< this connection
288 
289  ! point x, ibound, and rhs to connection
290  this%interface_model%x => this%x
291  call mem_checkin(this%interface_model%x, 'X', &
292  this%interface_model%memoryPath, 'X', &
293  this%memoryPath)
294  this%interface_model%rhs => this%rhs
295  call mem_checkin(this%interface_model%rhs, 'RHS', &
296  this%interface_model%memoryPath, 'RHS', &
297  this%memoryPath)
298  this%interface_model%ibound => this%active
299  call mem_checkin(this%interface_model%ibound, 'IBOUND', &
300  this%interface_model%memoryPath, 'IBOUND', &
301  this%memoryPath)
302 

◆ spatialconnection_ctor()

subroutine spatialmodelconnectionmodule::spatialconnection_ctor ( class(spatialmodelconnectiontype this,
class(numericalmodeltype), intent(in), pointer  model,
class(disconnexchangetype), intent(in), pointer  exchange,
character(len=*), intent(in)  name 
)

This constructor is typically called from a derived class.

Parameters
thisthe connection
[in]modelthe model that owns the connection
[in]exchangethe primary exchange from which the connection is created
[in]namethe connection name (for memory management mostly)

Definition at line 112 of file SpatialModelConnection.f90.

113  class(SpatialModelConnectionType) :: this !< the connection
114  class(NumericalModelType), intent(in), pointer :: model !< the model that owns the connection
115  class(DisConnExchangeType), intent(in), pointer :: exchange !< the primary exchange from which
116  !! the connection is created
117  character(len=*), intent(in) :: name !< the connection name (for memory management mostly)
118 
119  this%name = name
120  this%memoryPath = create_mem_path(this%name)
121 
122  this%owner => model
123  this%prim_exchange => exchange
124 
125  allocate (this%ig_builder)
126  allocate (this%halo_models)
127  allocate (this%halo_exchanges)
128  allocate (this%matrix)
129  call this%allocateScalars()
130 
131  this%int_stencil_depth = 1
132  this%exg_stencil_depth = 1
133  this%nr_connections = 0
134 
135  ! this should be set in derived ctor
136  this%interface_model => null()
137 
Here is the call graph for this function:
Here is the caller graph for this function:

◆ validateconnection()

subroutine spatialmodelconnectionmodule::validateconnection ( class(spatialmodelconnectiontype this)
Parameters
thisthis connection

Definition at line 622 of file SpatialModelConnection.f90.

623  class(SpatialModelConnectionType) :: this !< this connection
624  ! local
625  class(DisConnExchangeType), pointer :: conEx => null()
626  character(len=LINELENGTH) :: errmsg
627 
628  conex => this%prim_exchange
629  if (conex%ixt3d > 0) then
630  ! if XT3D, we need these angles:
631  if (conex%v_model1%con_ianglex%get() == 0) then
632  write (errmsg, '(a,a,a,a,a)') 'XT3D configured on the exchange ', &
633  trim(conex%name), ' but the discretization in model ', &
634  trim(conex%v_model1%name), ' has no ANGLDEGX specified'
635  call store_error(errmsg)
636  end if
637  if (conex%v_model2%con_ianglex%get() == 0) then
638  write (errmsg, '(a,a,a,a,a)') 'XT3D configured on the exchange ', &
639  trim(conex%name), ' but the discretization in model ', &
640  trim(conex%v_model2%name), ' has no ANGLDEGX specified'
641  call store_error(errmsg)
642  end if
643  end if
644 
645  if (count_errors() > 0) then
646  call ustop()
647  end if
648 
Here is the call graph for this function: