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