MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
VirtualTspExchange.f90
Go to the documentation of this file.
2  use kindmodule, only: i4b, lgp
9  implicit none
10  private
11 
12  public :: add_virtual_tsp_exchange
13 
14  !> GWE and GWT work fully analogously, so we can do
15  !! with only one virtual exchange for both, at least for now
16  !!
17  !< Performance-TODO: why synchronize movers when the exchange is not primary?!
18  type, public, extends(virtualexchangetype) :: virtualtspexchangetype
19  type(virtualinttype), pointer :: inmvt => null()
20  type(virtualdbl1dtype), pointer :: gwfsimvals => null()
21  type(virtualinttype), pointer :: mvt_maxmvt => null()
22  type(virtualdbl1dtype), pointer :: mvt_quantity_m1 => null()
23  type(virtualdbl1dtype), pointer :: mvt_quantity_m2 => null()
24  logical(LGP) :: quantities_mapped
25  ! private
26  logical(LGP), private :: has_mvt !< backing field for function
27  contains
28  procedure :: create => vtx_create
29  procedure :: destroy => vtx_destroy
30  procedure :: prepare_stage => vtx_prepare_stage
31  procedure :: get_send_items => vtx_get_send_items
32  procedure :: get_recv_items => vtx_get_recv_items
33  procedure :: has_mover => vtx_has_mover
34  ! private
35  procedure, private :: init_virtual_data
36  procedure, private :: allocate_data
37  procedure, private :: deallocate_data
38  end type virtualtspexchangetype
39 
40 contains
41 
42 !> @brief Add a virtual GWT-GWT or GWE-GWE exchange to the simulation
43 !<
44  subroutine add_virtual_tsp_exchange(name, exchange_id, m1_id, m2_id, qtype)
45  character(len=*) :: name
46  integer(I4B) :: exchange_id
47  integer(I4B) :: m1_id !< id model 1
48  integer(I4B) :: m2_id !< id model 2
49  character(len=*) :: qtype !< quantity type (for GWE and GWT)
50  ! local
51  class(virtualtspexchangetype), pointer :: v_exg
52  class(*), pointer :: obj_ptr
53 
54  allocate (v_exg)
55 
56  call v_exg%create(name, exchange_id, m1_id, m2_id)
57  if (qtype == "concentration") then
58  v_exg%container_type = vdc_gwtexg_type
59  else if (qtype == "temperature") then
60  v_exg%container_type = vdc_gweexg_type
61  end if
62 
63  obj_ptr => v_exg
64  call virtual_exchange_list%Add(obj_ptr)
65  end subroutine add_virtual_tsp_exchange
66 
67 !> @brief Create a virtual GWT-GWT exchange
68 !<
69  subroutine vtx_create(this, name, exg_id, m1_id, m2_id)
70  class(virtualtspexchangetype) :: this
71  character(len=*) :: name
72  integer(I4B) :: exg_id
73  integer(I4B) :: m1_id
74  integer(I4B) :: m2_id
75 
76  ! create base
77  call this%VirtualExchangeType%create(name, exg_id, m1_id, m2_id)
78 
79  call this%allocate_data()
80  call this%init_virtual_data()
81 
82  this%quantities_mapped = .false.
83  this%has_mvt = .false.
84 
85  end subroutine vtx_create
86 
87  subroutine init_virtual_data(this)
88  class(virtualtspexchangetype) :: this
89 
90  call this%set(this%inmvt%base(), 'INMVT', '', map_all_type)
91  call this%set(this%gwfsimvals%base(), 'GWFSIMVALS', '', map_all_type)
92  call this%set(this%mvt_maxmvt%base(), 'MAXMVT', 'MVT', map_all_type)
93  call this%set(this%mvt_quantity_m1%base(), 'QUANTITY_M1', 'MVT', &
94  map_all_type, this%v_model1%is_local)
95  call this%set(this%mvt_quantity_m2%base(), 'QUANTITY_M2', 'MVT', &
96  map_all_type, this%v_model2%is_local)
97 
98  end subroutine init_virtual_data
99 
100  subroutine vtx_prepare_stage(this, stage)
101  class(virtualtspexchangetype) :: this
102  integer(I4B) :: stage
103  ! local
104  integer(I4B) :: nexg, nmax
105 
106  ! prepare base exchange data items
107  call this%VirtualExchangeType%prepare_stage(stage)
108 
109  if (stage == stg_aft_exg_df) then
110 
111  ! always synchronize mover flag
112  call this%map(this%inmvt%base(), (/stg_aft_exg_df/))
113 
114  else if (stage == stg_aft_con_cr) then
115 
116  ! at this point we know:
117  if (this%inmvt%get() > 0) then
118  this%has_mvt = .true.
119  end if
120 
121  else if (stage == stg_bfr_con_ar) then
122 
123  nexg = this%nexg%get()
124  call this%map(this%gwfsimvals%base(), nexg, (/stg_bfr_exg_ad/))
125 
126  ! only when MVT is locally active (i.e. primary exchange)
127  if (this%has_mvt .and. this%is_local) then
128  call this%map(this%mvt_maxmvt%base(), (/stg_bfr_con_ar/))
129  end if
130 
131  else if (stage == stg_bfr_exg_ad) then
132 
133  ! only when MVT is locally active
134  nmax = 0
135  if (this%has_mvt .and. this%is_local) nmax = this%mvt_maxmvt%get()
136 
137  ! only map the arrays once, after the first read prepare is done
138  if (.not. this%quantities_mapped) then
139  if (nmax > 0) then
140  call this%map(this%mvt_quantity_m1%base(), nmax, (/stg_bfr_exg_fc/))
141  call this%map(this%mvt_quantity_m2%base(), nmax, (/stg_bfr_exg_fc/))
142  else
143  call this%map(this%mvt_quantity_m1%base(), 0, (/stg_never/))
144  call this%map(this%mvt_quantity_m2%base(), 0, (/stg_never/))
145  end if
146  this%quantities_mapped = .true.
147  end if
148  end if
149 
150  end subroutine vtx_prepare_stage
151 
152  subroutine vtx_get_recv_items(this, stg, rank, vi)
153  class(virtualtspexchangetype) :: this
154  integer(I4B) :: stg !< stage
155  integer(I4B) :: rank !< rank of remote process
156  type(stlvecint) :: vi !< virtual data items
157 
158  ! get base items to receive
159  call this%VirtualExchangeType%get_recv_items(stg, rank, vi)
160 
161  ! add more MVT items that follow nodem1/nodem2 pattern,
162  ! see comments in VirtualExchange for more details
163  if (this%is_local .and. rank == this%orig_rank) then
164  if (this%mvt_quantity_m1%is_remote) then
165  ! only receive for model1
166  call this%add_vdi_for_stage(this%mvt_quantity_m1%base(), stg, vi)
167  end if
168  if (this%mvt_quantity_m2%is_remote) then
169  ! only receive for model2
170  call this%add_vdi_for_stage(this%mvt_quantity_m2%base(), stg, vi)
171  end if
172  end if
173 
174  end subroutine vtx_get_recv_items
175 
176  subroutine vtx_get_send_items(this, stg, rank, vi)
177  class(virtualtspexchangetype) :: this
178  integer(I4B) :: stg !< stage
179  integer(I4B) :: rank !< rank of remote process
180  type(stlvecint) :: vi !< virtual data items
181 
182  ! get base items to send
183  call this%VirtualExchangeType%get_send_items(stg, rank, vi)
184 
185  ! add more MVT items that follow nodem1/nodem2 pattern,
186  ! see comments in VirtualExchange for more details
187  if (this%is_local .and. rank == this%orig_rank) then
188  if (.not. this%mvt_quantity_m1%is_remote) then
189  ! only send for model1
190  call this%add_vdi_for_stage(this%mvt_quantity_m1%base(), stg, vi)
191  end if
192  if (.not. this%mvt_quantity_m2%is_remote) then
193  ! only send for model2
194  call this%add_vdi_for_stage(this%mvt_quantity_m2%base(), stg, vi)
195  end if
196  end if
197 
198  end subroutine vtx_get_send_items
199 
200  !> @brief Override
201  !<
202  function vtx_has_mover(this) result(has_mover)
203  class(virtualtspexchangetype) :: this
204  logical(LGP) :: has_mover
205 
206  has_mover = this%has_mvt
207 
208  end function vtx_has_mover
209 
210  subroutine vtx_destroy(this)
211  class(virtualtspexchangetype) :: this
212 
213  call this%VirtualExchangeType%destroy()
214  call this%deallocate_data()
215 
216  end subroutine vtx_destroy
217 
218  subroutine allocate_data(this)
219  class(virtualtspexchangetype) :: this
220 
221  allocate (this%inmvt)
222  allocate (this%gwfsimvals)
223  allocate (this%mvt_maxmvt)
224  allocate (this%mvt_quantity_m1)
225  allocate (this%mvt_quantity_m2)
226 
227  end subroutine allocate_data
228 
229  subroutine deallocate_data(this)
230  class(virtualtspexchangetype) :: this
231 
232  deallocate (this%inmvt)
233  deallocate (this%gwfsimvals)
234  deallocate (this%mvt_maxmvt)
235  deallocate (this%mvt_quantity_m1)
236  deallocate (this%mvt_quantity_m2)
237 
238  end subroutine deallocate_data
239 
240 end module virtualtspexchangemodule
This module defines variable data types.
Definition: kind.f90:8
integer(i4b), parameter, public stg_aft_exg_df
after exchange define
Definition: SimStages.f90:12
integer(i4b), parameter, public stg_bfr_exg_ad
before exchange advance (per solution)
Definition: SimStages.f90:21
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
subroutine destroy(this)
Definition: STLVecInt.f90:183
integer(i4b), parameter, public map_all_type
Definition: VirtualBase.f90:13
integer(i4b), parameter, public vdc_gwtexg_type
integer(i4b), parameter, public vdc_gweexg_type
type(listtype), public virtual_exchange_list
subroutine deallocate_data(this)
subroutine init_virtual_data(this)
subroutine allocate_data(this)
subroutine vtx_create(this, name, exg_id, m1_id, m2_id)
Create a virtual GWT-GWT exchange.
subroutine vtx_get_recv_items(this, stg, rank, vi)
subroutine vtx_prepare_stage(this, stage)
subroutine, public add_virtual_tsp_exchange(name, exchange_id, m1_id, m2_id, qtype)
Add a virtual GWT-GWT or GWE-GWE exchange to the simulation.
subroutine vtx_get_send_items(this, stg, rank, vi)
logical(lgp) function vtx_has_mover(this)
Override.
The Virtual Exchange is based on two Virtual Models and is therefore not always strictly local or rem...
GWE and GWT work fully analogously, so we can do with only one virtual exchange for both,...