MODFLOW 6  version 6.7.0.dev0
USGS Modular Hydrologic Model
VirtualGwfExchange.f90
Go to the documentation of this file.
2  use kindmodule, only: i4b, lgp
9  implicit none
10  private
11 
12  public :: add_virtual_gwf_exchange
13 
14  !> For synchronization of GWF specific exchange data:
15  !< the exchange movers.
16  type, public, extends(virtualexchangetype) :: virtualgwfexchangetype
17  type(virtualinttype), pointer :: inmvr => null()
18  type(virtualinttype), pointer :: mvr_maxmvr => null()
19  type(virtualdbl1dtype), pointer :: mvr_qpactual_m1 => null()
20  type(virtualdbl1dtype), pointer :: mvr_qpactual_m2 => null()
21  type(virtualdbl1dtype), pointer :: mvr_qavailable_m1 => null()
22  type(virtualdbl1dtype), pointer :: mvr_qavailable_m2 => null()
23  type(virtualint1dtype), pointer :: mvr_id_mapped_m1 => null()
24  type(virtualint1dtype), pointer :: mvr_id_mapped_m2 => null()
25  ! private
26  logical(LGP), private :: has_mvr !< backing field for function
27  contains
28  procedure :: create => vfx_create
29  procedure :: prepare_stage => vfx_prepare_stage
30  procedure :: destroy => vfx_destroy
31  procedure :: get_send_items => vfx_get_send_items
32  procedure :: get_recv_items => vfx_get_recv_items
33  procedure :: has_mover => vfx_has_mover
34  ! private
35  procedure, private :: allocate_data
36  procedure, private :: deallocate_data
37  procedure, private :: init_virtual_data
38  end type virtualgwfexchangetype
39 
40 contains
41 
42 !> @brief Add a virtual GWF-GWF exchange to the simulation
43 !<
44  subroutine add_virtual_gwf_exchange(name, exchange_id, model1_id, model2_id)
45  integer(I4B) :: exchange_id
46  character(len=*) :: name
47  integer(I4B) :: model1_id
48  integer(I4B) :: model2_id
49  ! local
50  class(virtualgwfexchangetype), pointer :: v_exg
51  class(*), pointer :: obj_ptr
52 
53  allocate (v_exg)
54  call v_exg%create(name, exchange_id, model1_id, model2_id)
55 
56  obj_ptr => v_exg
57  call virtual_exchange_list%Add(obj_ptr)
58 
59  end subroutine add_virtual_gwf_exchange
60 
61 !> @brief Create a virtual GWF-GWF exchange
62 !<
63  subroutine vfx_create(this, name, exg_id, m1_id, m2_id)
64  class(virtualgwfexchangetype) :: this
65  character(len=*) :: name
66  integer(I4B) :: exg_id
67  integer(I4B) :: m1_id
68  integer(I4B) :: m2_id
69 
70  call this%VirtualExchangeType%create(name, exg_id, m1_id, m2_id)
71  this%container_type = vdc_gwfexg_type
72 
73  call this%allocate_data()
74  call this%init_virtual_data()
75 
76  this%has_mvr = .false.
77 
78  end subroutine vfx_create
79 
80  subroutine init_virtual_data(this)
81  class(virtualgwfexchangetype) :: this
82  ! local
83  logical(LGP) :: is_nodem1_local
84  logical(LGP) :: is_nodem2_local
85 
86  is_nodem1_local = this%v_model1%is_local
87  is_nodem2_local = this%v_model2%is_local
88  call this%set(this%inmvr%base(), 'INMVR', '', map_all_type)
89  call this%set(this%mvr_maxmvr%base(), 'MAXMVR', 'MVR', map_all_type)
90  ! these follow locality of nodem1,2
91  call this%set(this%mvr_qpactual_m1%base(), 'QPACTUAL_M1', 'MVR', &
92  map_all_type, is_nodem1_local)
93  call this%set(this%mvr_qpactual_m2%base(), 'QPACTUAL_M2', 'MVR', &
94  map_all_type, is_nodem2_local)
95  call this%set(this%mvr_qavailable_m1%base(), 'QAVAILABLE_M1', 'MVR', &
96  map_all_type, is_nodem1_local)
97  call this%set(this%mvr_qavailable_m2%base(), 'QAVAILABLE_M2', 'MVR', &
98  map_all_type, is_nodem2_local)
99  call this%set(this%mvr_id_mapped_m1%base(), 'ID_MAPPED_M1', 'MVR', &
100  map_all_type, is_nodem1_local)
101  call this%set(this%mvr_id_mapped_m2%base(), 'ID_MAPPED_M2', 'MVR', &
102  map_all_type, is_nodem2_local)
103 
104  end subroutine init_virtual_data
105 
106  subroutine vfx_prepare_stage(this, stage)
107  class(virtualgwfexchangetype) :: this
108  integer(I4B) :: stage
109  ! local
110  integer(I4B) :: nmax
111 
112  ! prepare base exchange data items
113  call this%VirtualExchangeType%prepare_stage(stage)
114 
115  if (stage == stg_aft_exg_df) then
116 
117  call this%map(this%inmvr%base(), (/stg_aft_exg_df/))
118 
119  else if (stage == stg_aft_con_cr) then
120 
121  ! at this point we know:
122  if (this%inmvr%get() > 0) then
123  this%has_mvr = .true.
124  end if
125 
126  else if (stage == stg_bfr_con_ar) then
127 
128  ! only when MVR is active
129  if (this%inmvr%get() > 0) then
130  call this%map(this%mvr_maxmvr%base(), (/stg_bfr_con_ar/))
131  end if
132 
133  else if (stage == stg_aft_con_ar) then
134 
135  ! only when MVR is active
136  if (this%inmvr%get() > 0) then
137  nmax = this%mvr_maxmvr%get()
138  if (nmax > 0) then
139  call this%map(this%mvr_qpactual_m1%base(), nmax, (/stg_bfr_exg_fc/))
140  call this%map(this%mvr_qpactual_m2%base(), nmax, (/stg_bfr_exg_fc/))
141  call this%map(this%mvr_qavailable_m1%base(), nmax, (/stg_bfr_exg_fc/))
142  call this%map(this%mvr_qavailable_m2%base(), nmax, (/stg_bfr_exg_fc/))
143  call this%map(this%mvr_id_mapped_m1%base(), nmax, (/stg_aft_con_rp/))
144  call this%map(this%mvr_id_mapped_m2%base(), nmax, (/stg_aft_con_rp/))
145  else
146  call this%map(this%mvr_qpactual_m1%base(), 0, (/stg_never/))
147  call this%map(this%mvr_qpactual_m2%base(), 0, (/stg_never/))
148  call this%map(this%mvr_qavailable_m1%base(), 0, (/stg_never/))
149  call this%map(this%mvr_qavailable_m2%base(), 0, (/stg_never/))
150  call this%map(this%mvr_id_mapped_m1%base(), 0, (/stg_never/))
151  call this%map(this%mvr_id_mapped_m2%base(), 0, (/stg_never/))
152  end if
153  end if
154 
155  end if
156 
157  end subroutine vfx_prepare_stage
158 
159  subroutine vfx_get_recv_items(this, stage, rank, virtual_items)
160  class(virtualgwfexchangetype) :: this
161  integer(I4B) :: stage
162  integer(I4B) :: rank
163  type(stlvecint) :: virtual_items
164  ! local
165  integer(I4B) :: qpactual_m1_idx, qpactual_m2_idx
166  integer(I4B) :: qavailable_m1_idx, qavailable_m2_idx
167  integer(I4B) :: id_mapped_m1_idx, id_mapped_m2_idx
168  class(*), pointer :: vdi
169 
170  ! get base items to receive
171  call this%VirtualExchangeType%get_recv_items(stage, rank, &
172  virtual_items)
173 
174  ! add more MVR items that follow nodem1/nodem2 pattern,
175  ! see comments in VirtualExchange for more details.
176  vdi => this%mvr_qpactual_m1
177  qpactual_m1_idx = this%virtual_data_list%GetIndex(vdi)
178  vdi => this%mvr_qpactual_m2
179  qpactual_m2_idx = this%virtual_data_list%GetIndex(vdi)
180  vdi => this%mvr_qavailable_m1
181  qavailable_m1_idx = this%virtual_data_list%GetIndex(vdi)
182  vdi => this%mvr_qavailable_m2
183  qavailable_m2_idx = this%virtual_data_list%GetIndex(vdi)
184  vdi => this%mvr_id_mapped_m1
185  id_mapped_m1_idx = this%virtual_data_list%GetIndex(vdi)
186  vdi => this%mvr_id_mapped_m2
187  id_mapped_m2_idx = this%virtual_data_list%GetIndex(vdi)
188 
189  if (this%v_model1%is_local .and. &
190  this%v_model2%orig_rank == rank) then
191  ! this is our dual exchange on the other rank,
192  ! only receive qpactual_m2
193  if (this%mvr_qpactual_m2%check_stage(stage)) then
194  call virtual_items%push_back(qpactual_m2_idx)
195  end if
196  if (this%mvr_qavailable_m2%check_stage(stage)) then
197  call virtual_items%push_back(qavailable_m2_idx)
198  end if
199  if (this%mvr_id_mapped_m2%check_stage(stage)) then
200  call virtual_items%push_back(id_mapped_m2_idx)
201  end if
202  else if (this%v_model2%is_local .and. &
203  this%v_model1%orig_rank == rank) then
204  ! the reverse case...
205  if (this%mvr_qpactual_m1%check_stage(stage)) then
206  call virtual_items%push_back(qpactual_m1_idx)
207  end if
208  if (this%mvr_qavailable_m1%check_stage(stage)) then
209  call virtual_items%push_back(qavailable_m1_idx)
210  end if
211  if (this%mvr_id_mapped_m1%check_stage(stage)) then
212  call virtual_items%push_back(id_mapped_m1_idx)
213  end if
214  end if
215 
216  end subroutine vfx_get_recv_items
217 
218  subroutine vfx_get_send_items(this, stage, rank, virtual_items)
219  class(virtualgwfexchangetype) :: this
220  integer(I4B) :: stage
221  integer(I4B) :: rank
222  type(stlvecint) :: virtual_items
223  ! local
224  integer(I4B) :: qpactual_m1_idx, qpactual_m2_idx
225  integer(I4B) :: qavailable_m1_idx, qavailable_m2_idx
226  integer(I4B) :: id_mapped_m1_idx, id_mapped_m2_idx
227  class(*), pointer :: vdi
228 
229  ! get base items to send
230  call this%VirtualExchangeType%get_send_items(stage, rank, &
231  virtual_items)
232 
233  ! add more MVR items that follow nodem1/nodem2 pattern
234  vdi => this%mvr_qpactual_m1
235  qpactual_m1_idx = this%virtual_data_list%GetIndex(vdi)
236  vdi => this%mvr_qpactual_m2
237  qpactual_m2_idx = this%virtual_data_list%GetIndex(vdi)
238  vdi => this%mvr_qavailable_m1
239  qavailable_m1_idx = this%virtual_data_list%GetIndex(vdi)
240  vdi => this%mvr_qavailable_m2
241  qavailable_m2_idx = this%virtual_data_list%GetIndex(vdi)
242  vdi => this%mvr_id_mapped_m1
243  id_mapped_m1_idx = this%virtual_data_list%GetIndex(vdi)
244  vdi => this%mvr_id_mapped_m2
245  id_mapped_m2_idx = this%virtual_data_list%GetIndex(vdi)
246 
247  if (this%v_model1%is_local .and. &
248  this%v_model2%orig_rank == rank) then
249  ! this is our dual exchange on the other rank,
250  ! only add qpactual_m1
251  if (this%mvr_qpactual_m1%check_stage(stage)) then
252  call virtual_items%push_back(qpactual_m1_idx)
253  end if
254  if (this%mvr_qavailable_m1%check_stage(stage)) then
255  call virtual_items%push_back(qavailable_m1_idx)
256  end if
257  if (this%mvr_id_mapped_m1%check_stage(stage)) then
258  call virtual_items%push_back(id_mapped_m1_idx)
259  end if
260  else if (this%v_model2%is_local .and. &
261  this%v_model1%orig_rank == rank) then
262  ! the reverse case...
263  if (this%mvr_qpactual_m2%check_stage(stage)) then
264  call virtual_items%push_back(qpactual_m2_idx)
265  end if
266  if (this%mvr_qavailable_m2%check_stage(stage)) then
267  call virtual_items%push_back(qavailable_m2_idx)
268  end if
269  if (this%mvr_id_mapped_m2%check_stage(stage)) then
270  call virtual_items%push_back(id_mapped_m2_idx)
271  end if
272  end if
273 
274  end subroutine vfx_get_send_items
275 
276  !> @brief Override
277  !<
278  function vfx_has_mover(this) result(has_mover)
279  class(virtualgwfexchangetype) :: this
280  logical(LGP) :: has_mover
281 
282  has_mover = this%has_mvr
283 
284  end function vfx_has_mover
285 
286  subroutine allocate_data(this)
287  class(virtualgwfexchangetype) :: this
288 
289  allocate (this%inmvr)
290  allocate (this%mvr_maxmvr)
291  allocate (this%mvr_qpactual_m1)
292  allocate (this%mvr_qpactual_m2)
293  allocate (this%mvr_qavailable_m1)
294  allocate (this%mvr_qavailable_m2)
295  allocate (this%mvr_id_mapped_m1)
296  allocate (this%mvr_id_mapped_m2)
297 
298  end subroutine allocate_data
299 
300  subroutine deallocate_data(this)
301  class(virtualgwfexchangetype) :: this
302 
303  deallocate (this%inmvr)
304  deallocate (this%mvr_maxmvr)
305  deallocate (this%mvr_qpactual_m1)
306  deallocate (this%mvr_qpactual_m2)
307  deallocate (this%mvr_qavailable_m1)
308  deallocate (this%mvr_qavailable_m2)
309  deallocate (this%mvr_id_mapped_m1)
310  deallocate (this%mvr_id_mapped_m2)
311 
312  end subroutine deallocate_data
313 
314  subroutine vfx_destroy(this)
315  class(virtualgwfexchangetype) :: this
316 
317  call this%VirtualExchangeType%destroy()
318  call this%deallocate_data()
319 
320  end subroutine vfx_destroy
321 
322 end module virtualgwfexchangemodule
This module defines variable data types.
Definition: kind.f90:8
integer(i4b), parameter, public stg_aft_con_ar
afterr connection allocate read
Definition: SimStages.f90:18
integer(i4b), parameter, public stg_aft_exg_df
after exchange define
Definition: SimStages.f90:12
integer(i4b), parameter, public stg_never
never
Definition: SimStages.f90:9
integer(i4b), parameter, public stg_aft_con_cr
after connection create
Definition: SimStages.f90:13
integer(i4b), parameter, public stg_bfr_exg_fc
before exchange formulate (per solution)
Definition: SimStages.f90:23
integer(i4b), parameter, public stg_bfr_con_ar
before connection allocate read
Definition: SimStages.f90:17
integer(i4b), parameter, public stg_aft_con_rp
after connection read prepare
Definition: SimStages.f90:20
subroutine destroy(this)
Definition: STLVecInt.f90:170
integer(i4b), parameter, public map_all_type
Definition: VirtualBase.f90:13
integer(i4b), parameter, public vdc_gwfexg_type
type(listtype), public virtual_exchange_list
subroutine deallocate_data(this)
subroutine init_virtual_data(this)
subroutine allocate_data(this)
subroutine, public add_virtual_gwf_exchange(name, exchange_id, model1_id, model2_id)
Add a virtual GWF-GWF exchange to the simulation.
logical(lgp) function vfx_has_mover(this)
Override.
subroutine vfx_create(this, name, exg_id, m1_id, m2_id)
Create a virtual GWF-GWF exchange.
subroutine vfx_get_recv_items(this, stage, rank, virtual_items)
subroutine vfx_get_send_items(this, stage, rank, virtual_items)
subroutine vfx_prepare_stage(this, stage)
The Virtual Exchange is based on two Virtual Models and is therefore not always strictly local or rem...
For synchronization of GWF specific exchange data: