MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
Mapper.f90
Go to the documentation of this file.
2  use kindmodule, only: i4b, lgp
14  use listmodule
15  implicit none
16  private
17 
18  public :: mappertype
19 
20  type :: mappertype
21  type(listtype) :: mapped_data_list
22  contains
23  procedure :: init
24  procedure :: add_exchange_vars
25  procedure :: add_interface_vars
26  procedure :: scatter
27  procedure :: destroy
28 
29  procedure, private :: add_dist_vars
30  procedure, private :: map_model_data
31  procedure, private :: map_exg_data
32  procedure, private :: map_data
33  procedure, private :: map_data_full
34  end type mappertype
35 
36 contains
37 
38  subroutine init(this)
39  class(mappertype) :: this
40 
41  end subroutine init
42 
43  !> @brief Add virtual exchange variables
44  !<
45  subroutine add_exchange_vars(this)
46  use simstagesmodule
51  class(mappertype) :: this
52  ! local
53  integer(I4B) :: iconn
54  class(spatialmodelconnectiontype), pointer :: conn
55  class(virtualexchangetype), pointer :: vx
56  character(len=LENMEMPATH) :: virt_mem_path, local_mem_path
57 
58  do iconn = 1, baseconnectionlist%Count()
60  vx => get_virtual_exchange(conn%prim_exchange%id)
61  if (.not. vx%v_model1%is_local) then
62  virt_mem_path = vx%get_vrt_mem_path('NODEM1', '')
63  call this%map_data_full(0, 'NODEM1', conn%prim_exchange%memoryPath, &
64  'NODEM1', virt_mem_path, (/stg_bfr_con_df/))
65 
66  ! these are only present when there is a MVR:
67  if (vx%has_mover() .and. vx%container_type == vdc_gwfexg_type) then
68  local_mem_path = create_mem_path(vx%name, 'MVR')
69  virt_mem_path = vx%get_vrt_mem_path('QPACTUAL_M1', 'MVR')
70  call this%map_data_full(conn%owner%idsoln, 'QPACTUAL_M1', &
71  local_mem_path, 'QPACTUAL_M1', &
72  virt_mem_path, (/stg_bfr_exg_fc/))
73  virt_mem_path = vx%get_vrt_mem_path('QAVAILABLE_M1', 'MVR')
74  call this%map_data_full(conn%owner%idsoln, 'QAVAILABLE_M1', &
75  local_mem_path, 'QAVAILABLE_M1', &
76  virt_mem_path, (/stg_bfr_exg_fc/))
77  virt_mem_path = vx%get_vrt_mem_path('ID_MAPPED_M1', 'MVR')
78  call this%map_data_full(conn%owner%idsoln, 'ID_MAPPED_M1', &
79  local_mem_path, 'ID_MAPPED_M1', &
80  virt_mem_path, (/stg_aft_con_rp/))
81  end if
82  ! the same for MVT (both GWE and GWT)
83  if (vx%has_mover() .and. (vx%container_type == vdc_gwtexg_type .or. &
84  vx%container_type == vdc_gweexg_type)) then
85  local_mem_path = create_mem_path(vx%name, 'MVT')
86  virt_mem_path = vx%get_vrt_mem_path('QUANTITY_M1', 'MVT')
87  call this%map_data_full(conn%owner%idsoln, 'QUANTITY_M1', &
88  local_mem_path, 'QUANTITY_M1', &
89  virt_mem_path, (/stg_bfr_exg_fc/))
90  end if
91  end if
92  if (.not. vx%v_model2%is_local) then
93  virt_mem_path = vx%get_vrt_mem_path('NODEM2', '')
94  call this%map_data_full(0, 'NODEM2', conn%prim_exchange%memoryPath, &
95  'NODEM2', virt_mem_path, (/stg_bfr_con_df/))
96 
97  ! these are only present when there is a mover:
98  if (vx%has_mover() .and. vx%container_type == vdc_gwfexg_type) then
99  local_mem_path = create_mem_path(vx%name, 'MVR')
100  virt_mem_path = vx%get_vrt_mem_path('QPACTUAL_M2', 'MVR')
101  call this%map_data_full(conn%owner%idsoln, 'QPACTUAL_M2', &
102  local_mem_path, 'QPACTUAL_M2', &
103  virt_mem_path, (/stg_bfr_exg_fc/))
104  virt_mem_path = vx%get_vrt_mem_path('QAVAILABLE_M2', 'MVR')
105  call this%map_data_full(conn%owner%idsoln, 'QAVAILABLE_M2', &
106  local_mem_path, 'QAVAILABLE_M2', &
107  virt_mem_path, (/stg_bfr_exg_fc/))
108  virt_mem_path = vx%get_vrt_mem_path('ID_MAPPED_M2', 'MVR')
109  call this%map_data_full(conn%owner%idsoln, 'ID_MAPPED_M2', &
110  local_mem_path, 'ID_MAPPED_M2', &
111  virt_mem_path, (/stg_aft_con_rp/))
112  end if
113  ! the same for MVT (both GWE and GWT)
114  if (vx%has_mover() .and. (vx%container_type == vdc_gwtexg_type .or. &
115  vx%container_type == vdc_gweexg_type)) then
116  local_mem_path = create_mem_path(vx%name, 'MVT')
117  virt_mem_path = vx%get_vrt_mem_path('QUANTITY_M2', 'MVT')
118  call this%map_data_full(conn%owner%idsoln, 'QUANTITY_M2', &
119  local_mem_path, 'QUANTITY_M2', &
120  virt_mem_path, (/stg_bfr_exg_fc/))
121  end if
122  end if
123  end do
124 
125  end subroutine add_exchange_vars
126 
127  !> @brief Add distributed interface variables as memory mapped items
128  !<
129  subroutine add_interface_vars(this)
133  class(mappertype) :: this
134  ! local
135  integer(I4B) :: iconn
136  class(spatialmodelconnectiontype), pointer :: conn
137 
138  do iconn = 1, baseconnectionlist%Count()
139  conn => get_smc_from_list(baseconnectionlist, iconn)
140  ! add the variables for this interface model to our mapper
141  call this%add_dist_vars(conn%owner%idsoln, &
142  conn%iface_dist_vars, &
143  conn%interface_map)
144  end do
145 
146  end subroutine add_interface_vars
147 
148  subroutine add_dist_vars(this, sol_id, var_list, iface_map)
149  class(mappertype) :: this
150  integer(I4B) :: sol_id
151  type(listtype) :: var_list
152  type(interfacemaptype), pointer :: iface_map
153  ! local
154  integer(I4B) :: i, m, e
155  type(distvartype), pointer :: dist_var
156 
157  ! loop over variables
158  do i = 1, var_list%Count()
159  dist_var => getdistvarfromlist(var_list, i)
160  if (dist_var%map_type == sync_nds .or. & ! models
161  dist_var%map_type == sync_con) then
162  do m = 1, iface_map%nr_models
163  call this%map_model_data(sol_id, iface_map, m, dist_var)
164  end do
165  else if (dist_var%map_type == sync_exg) then ! exchanges
166  do e = 1, iface_map%nr_exchanges
167  call this%map_exg_data(sol_id, iface_map, e, dist_var)
168  end do
169  end if
170  end do
171 
172  end subroutine add_dist_vars
173 
174  !> @brief Map data from model memory to a target memory entry,
175  !! with the specified map. The source and target items have
176  !< the same name and (optionally) subcomponent name.
177  !call this%map_model_data(sol_id, interface_map%model_ids(m), &
178  !dist_var, idx_map)
179  subroutine map_model_data(this, sol_id, iface_map, model_idx, dist_var)
180  use simmodule, only: ustop
181  class(mappertype) :: this !< this mapper instance
182  integer(I4B) :: sol_id !< the numerical solution where synchr. is controlled
183  type(interfacemaptype), pointer :: iface_map !< the full interface map
184  integer(I4B) :: model_idx !< the model index (not id) in the interface map
185  type(distvartype), pointer :: dist_var !< the distributed variable to map
186  ! local
187  character(len=LENVARNAME) :: src_var_name
188  character(len=LENMEMPATH) :: src_mem_path, tgt_mem_path
189  class(virtualmodeltype), pointer :: v_model
190  type(indexmaptype), pointer :: idx_map
191  integer(I4B), dimension(:), pointer, contiguous :: lookup_table
192  class(virtualdatatype), pointer :: vd
193 
194  v_model => get_virtual_model(iface_map%model_ids(model_idx))
195  vd => v_model%get_virtual_data(dist_var%var_name, dist_var%subcomp_name)
196 
197  ! pick the right index map: connection based or node based,
198  ! and reduced data items require a lookup table
199  lookup_table => null()
200  if (dist_var%map_type == sync_nds) then
201  idx_map => iface_map%node_maps(model_idx)
202  if (vd%is_reduced) then
203  lookup_table => v_model%element_luts(map_node_type)%remote_to_virtual
204  end if
205  else if (dist_var%map_type == sync_con) then
206  idx_map => iface_map%conn_maps(model_idx)
207  if (vd%is_reduced) then
208  lookup_table => v_model%element_luts(map_conn_type)%remote_to_virtual
209  end if
210  else
211  write (*, *) "Unknown map type for distributed variable ", dist_var%var_name
212  call ustop()
213  end if
214 
215  if (len_trim(dist_var%subcomp_name) > 0) then
216  tgt_mem_path = create_mem_path(dist_var%comp_name, dist_var%subcomp_name)
217  else
218  tgt_mem_path = create_mem_path(dist_var%comp_name)
219  end if
220 
221  src_var_name = dist_var%var_name
222  src_mem_path = v_model%get_vrt_mem_path(src_var_name, dist_var%subcomp_name)
223  call this%map_data(sol_id, &
224  src_var_name, tgt_mem_path, idx_map%tgt_idx, &
225  src_var_name, src_mem_path, idx_map%src_idx, &
226  null(), lookup_table, dist_var%sync_stages)
227 
228  end subroutine map_model_data
229 
230  !> @brief Map memory from a Exchange to the specified memory entry,
231  !< using the index map
232  subroutine map_exg_data(this, sol_id, iface_map, exg_idx, dist_var)
233  class(mappertype) :: this
234  integer(I4B) :: sol_id !< the numerical solution where synchr. is controlled
235  type(interfacemaptype), pointer :: iface_map !< the full interface map
236  integer(I4B), intent(in) :: exg_idx !< the index (not id) for the exchange
237  type(distvartype), pointer :: dist_var !< the distributed variable to map
238  ! local
239  character(len=LENMEMPATH) :: src_mem_path, tgt_mem_path
240  class(virtualexchangetype), pointer :: v_exchange
241  type(indexmapsgntype), pointer :: idx_map
242 
243  v_exchange => get_virtual_exchange(iface_map%exchange_ids(exg_idx))
244 
245  idx_map => iface_map%exchange_maps(exg_idx)
246 
247  if (len_trim(dist_var%subcomp_name) > 0) then
248  tgt_mem_path = create_mem_path(dist_var%comp_name, dist_var%subcomp_name)
249  else
250  tgt_mem_path = create_mem_path(dist_var%comp_name)
251  end if
252 
253  src_mem_path = v_exchange%get_vrt_mem_path(dist_var%exg_var_name, '')
254  call this%map_data(sol_id, &
255  dist_var%var_name, tgt_mem_path, idx_map%tgt_idx, &
256  dist_var%exg_var_name, src_mem_path, idx_map%src_idx, &
257  idx_map%sign, null(), dist_var%sync_stages)
258 
259  end subroutine map_exg_data
260 
261  !> @brief Full copy between two variables in memory
262  subroutine map_data_full(this, controller_id, tgt_name, tgt_path, &
263  src_name, src_path, stages)
264  class(mappertype) :: this
265  integer(I4B) :: controller_id
266  character(len=*), intent(in) :: tgt_name
267  character(len=*), intent(in) :: tgt_path
268  character(len=*), intent(in) :: src_name
269  character(len=*), intent(in) :: src_path
270  integer(I4B), dimension(:), intent(in) :: stages
271 
272  call this%map_data(controller_id, tgt_name, tgt_path, null(), &
273  src_name, src_path, null(), &
274  null(), null(), stages)
275 
276  end subroutine map_data_full
277 
278  !> @brief Generic mapping between two variables in memory, using
279  !< an optional sign conversion
280  subroutine map_data(this, controller_id, tgt_name, tgt_path, tgt_idx, &
281  src_name, src_path, src_idx, sign_array, &
282  lookup_table, stages)
283  class(mappertype) :: this
284  integer(I4B) :: controller_id
285  character(len=*), intent(in) :: tgt_name
286  character(len=*), intent(in) :: tgt_path
287  integer(I4B), dimension(:), pointer :: tgt_idx
288  character(len=*), intent(in) :: src_name
289  character(len=*), intent(in) :: src_path
290  integer(I4B), dimension(:), pointer :: src_idx
291  integer(I4B), dimension(:), pointer :: sign_array
292  integer(I4B), dimension(:), pointer :: lookup_table
293  integer(I4B), dimension(:), intent(in) :: stages
294  ! local
295  integer(I4B) :: istage, i
296  type(mappedmemorytype), pointer :: mapped_data
297  class(*), pointer :: obj
298 
299  ! loop and set stage bits
300  istage = 0
301  do i = 1, size(stages)
302  istage = ibset(istage, stages(i))
303  end do
304 
305  ! create MappedVariable and add to list
306  allocate (mapped_data)
307  mapped_data%controller_id = controller_id
308  mapped_data%sync_stage = istage
309  mapped_data%src_name = src_name
310  mapped_data%src_path = src_path
311  mapped_data%src => null()
312  mapped_data%tgt_name = tgt_name
313  mapped_data%tgt_path = tgt_path
314  mapped_data%tgt => null()
315  mapped_data%copy_all = .not. associated(src_idx)
316  mapped_data%src_idx => src_idx
317  mapped_data%tgt_idx => tgt_idx
318  mapped_data%sign => sign_array
319  mapped_data%lut => lookup_table
320  obj => mapped_data
321  call this%mapped_data_list%Add(obj)
322 
323  end subroutine map_data
324 
325  !> @brief Scatter the mapped memory, typically into
326  !< the memory space of the interface models
327  subroutine scatter(this, controller_id, stage)
328  class(mappertype) :: this
329  integer(I4B) :: controller_id
330  integer(I4B), intent(in) :: stage
331  ! local
332  integer(I4B) :: i
333  class(*), pointer :: obj
334  class(mappedmemorytype), pointer :: mapped_data
335 
336  ! sync all variables (src => tgt) for a given stage
337  do i = 1, this%mapped_data_list%Count()
338  obj => this%mapped_data_list%GetItem(i)
339  mapped_data => castasmappeddata(obj)
340  if (controller_id > 0 .and. &
341  mapped_data%controller_id /= controller_id) cycle
342  if (.not. check_stage(mapped_data%sync_stage, stage)) cycle
343 
344  ! copy data
345  call mapped_data%sync()
346  end do
347 
348  end subroutine scatter
349 
350  function check_stage(var_stage, current_stage) result(is_sync)
351  integer(I4B) :: var_stage
352  integer(I4B) :: current_stage
353  logical(LGP) :: is_sync
354 
355  is_sync = iand(var_stage, ibset(0, current_stage)) == ibset(0, current_stage)
356 
357  end function check_stage
358 
359  subroutine destroy(this)
360  class(mappertype) :: this
361 
362  call this%mapped_data_list%Clear(destroy=.true.)
363 
364  end subroutine destroy
365 
366 end module mappermodule
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter lenvarname
maximum length of a variable name
Definition: Constants.f90:17
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
class(distvartype) function, pointer, public getdistvarfromlist(list, idx)
integer(i4b), parameter, public sync_nds
synchronize over nodes
integer(i4b), parameter, public sync_exg
synchronize as exchange variable
integer(i4b), parameter, public sync_con
synchronize over connections
subroutine destroy(this)
subroutine init(this, nr_models, nr_exchanges)
This module defines variable data types.
Definition: kind.f90:8
type(listtype), public baseconnectionlist
Definition: mf6lists.f90:28
class(mappedmemorytype) function, pointer, public castasmappeddata(obj)
subroutine map_data(this, controller_id, tgt_name, tgt_path, tgt_idx, src_name, src_path, src_idx, sign_array, lookup_table, stages)
Generic mapping between two variables in memory, using.
Definition: Mapper.f90:283
subroutine map_model_data(this, sol_id, iface_map, model_idx, dist_var)
Map data from model memory to a target memory entry, with the specified map. The source and target it...
Definition: Mapper.f90:180
subroutine map_exg_data(this, sol_id, iface_map, exg_idx, dist_var)
Map memory from a Exchange to the specified memory entry,.
Definition: Mapper.f90:233
subroutine add_dist_vars(this, sol_id, var_list, iface_map)
Definition: Mapper.f90:149
subroutine add_interface_vars(this)
Add distributed interface variables as memory mapped items.
Definition: Mapper.f90:130
subroutine add_exchange_vars(this)
Add virtual exchange variables.
Definition: Mapper.f90:46
logical(lgp) function check_stage(var_stage, current_stage)
Definition: Mapper.f90:351
subroutine map_data_full(this, controller_id, tgt_name, tgt_path, src_name, src_path, stages)
Full copy between two variables in memory.
Definition: Mapper.f90:264
subroutine scatter(this, controller_id, stage)
Scatter the mapped memory, typically into.
Definition: Mapper.f90:328
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public ustop(stopmess, ioutlocal)
Stop the simulation.
Definition: Sim.f90:312
integer(i4b), parameter, public stg_bfr_exg_fc
before exchange formulate (per solution)
Definition: SimStages.f90:23
integer(i4b), parameter, public stg_aft_con_rp
after connection read prepare
Definition: SimStages.f90:20
integer(i4b), parameter, public stg_bfr_con_df
before connection define
Definition: SimStages.f90:14
class(spatialmodelconnectiontype) function, pointer, public get_smc_from_list(list, idx)
Get the connection from a list.
integer(i4b), parameter, public map_conn_type
Definition: VirtualBase.f90:15
integer(i4b), parameter, public map_node_type
Definition: VirtualBase.f90:14
integer(i4b), parameter, public vdc_gwtexg_type
integer(i4b), parameter, public vdc_gwfexg_type
integer(i4b), parameter, public vdc_gweexg_type
class(virtualexchangetype) function, pointer, public get_virtual_exchange(exg_id)
Returns a virtual exchange with the specified id.
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....
This is a generic data structure to virtualize pieces of memory in 2 distinct ways:
Definition: VirtualBase.f90:35
The Virtual Exchange is based on two Virtual Models and is therefore not always strictly local or rem...