REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_ReadFromBdryNetcdf.cpp
Go to the documentation of this file.
1#include "REMORA_NCFile.H"
2#include "AMReX_FArrayBox.H"
3#include "REMORA_DataStruct.H"
5
6using namespace amrex;
7
8#ifdef REMORA_USE_NETCDF
9
10namespace REMORABdyTypes {
11 enum {
15 y_hi
16 };
17}
18
19/**
20 * @param domain computational domain
21 * @param nc_bdry_file name of file with boundary data
22 * @param bdy_data_xlo container for xlo boundary data
23 * @param bdy_data_xhi container for xhi boundary data
24 * @param bdy_data_ylo container for ylo boundary data
25 * @param bdy_data_yhi container for yhi boundary data
26 * @param width number of cells to read in boundary region
27 * @param start_bdy_time time when boundary data starts
28 * @param bdry_time_varname name of time variable
29 * @param phys_bc_need_data whether physical boundary condition data is needed for a given side and variable
30 */
31Real
32read_bdry_from_netcdf (const Box& domain, const std::string& nc_bdry_file,
33 Vector<Vector<FArrayBox>>& bdy_data_xlo,
34 Vector<Vector<FArrayBox>>& bdy_data_xhi,
35 Vector<Vector<FArrayBox>>& bdy_data_ylo,
36 Vector<Vector<FArrayBox>>& bdy_data_yhi,
37 int& width, Real& start_bdy_time,
38 std::string bdry_time_varname,
39 amrex::GpuArray<amrex::GpuArray<bool, AMREX_SPACEDIM*2>,BdyVars::NumTypes+1>& phys_bc_need_data)
40{
41 amrex::Print() << "Loading boundary data from NetCDF file " << nc_bdry_file << std::endl;
42
43 int ioproc = ParallelDescriptor::IOProcessorNumber(); // I/O rank
44
45 const auto& lo = domain.loVect();
46 const auto& hi = domain.hiVect();
47
48 // *******************************************************************************
49
50 int ntimes;
51 Real timeInterval;
52 const std::string dateTimeFormat ="%Y-%m-%d_%H:%M:%S";
53
54 Vector<Real> ocean_times;
55 // Check units of time stamps. Should be days.
56 std::string unit_str;
57 unit_str = ReadNetCDFVarAttrStr(nc_bdry_file, bdry_time_varname, "units"); // works on proc 0
58 if (ParallelDescriptor::IOProcessor())
59 {
60 if (unit_str.find("days") == std::string::npos) {
61 amrex::Print() << "Units of " << bdry_time_varname << " given as: " << unit_str << std::endl;
62 amrex::Abort("Units must be in days.");
63 }
64 }
65 // Read the time stamps
66 using RARRAY = NDArray<Real>;
67 amrex::Vector<RARRAY> array_ts(1);
68 ReadNetCDFFile(nc_bdry_file, {bdry_time_varname}, array_ts); // filled only on proc 0
69 if (ParallelDescriptor::IOProcessor())
70 {
71 ntimes = array_ts[0].get_vshape()[0];
72 ocean_times.resize(ntimes);
73
74 // amrex::Print() << " NTIMES " << ntimes << std::endl;
75 for (int nt(0); nt < ntimes; nt++)
76 {
77 // Convert ocean time from days to seconds
78 ocean_times[nt] = (*(array_ts[0].get_data() + nt)) * 60._rt * 60._rt * 24._rt;
79 // amrex::Print() << "TIMES " << ocean_times[nt] << std::endl;
80 }
81
82 start_bdy_time = ocean_times[0];
83 timeInterval = ocean_times[1] - ocean_times[0];
84
85 for (int nt(1); nt < ntimes; nt++)
86 {
87 AMREX_ALWAYS_ASSERT(std::abs(ocean_times[nt] - ocean_times[nt-1] - timeInterval) / timeInterval <= 1e-8_rt);
88 }
89 }
90
91 ParallelDescriptor::Bcast(&start_bdy_time,1,ioproc);
92 ParallelDescriptor::Bcast(&ntimes,1,ioproc);
93 ParallelDescriptor::Bcast(&timeInterval,1,ioproc);
94
95 // Even though we may not read in all the variables, we need to make the arrays big enough for them (for now)
96
97 int nt_prior = bdy_data_xlo.size();
98 // Our outermost loop is time
99 bdy_data_xlo.resize(ntimes + nt_prior);
100 bdy_data_xhi.resize(ntimes + nt_prior);
101 bdy_data_ylo.resize(ntimes + nt_prior);
102 bdy_data_yhi.resize(ntimes + nt_prior);
103
104 amrex::IntVect plo(lo);
105 amrex::IntVect phi(hi);
106
107 // ******************************************************************
108 // Read the netcdf file and fill these FABs
109 // NOTE: the order and number of these must match the BdyVars enum!
110 // BdyVars: U, V, R, T, QV, MU, PC
111 // ******************************************************************
112 Vector<std::string> nc_var_names;
113 Vector<std::string> nc_var_names_full; // All possible NC variable names for boundary, both used and unused
114 Vector<std::string> nc_var_prefix = {"u","v","temp","salt","ubar","vbar","zeta"};
115
116 for (int ip = 0; ip < nc_var_prefix.size(); ++ip)
117 {
118 if (phys_bc_need_data[ip][Orientation(Direction::x,Orientation::low)] == true) {
119 nc_var_names.push_back(nc_var_prefix[ip] + "_west");
120 }
121 if (phys_bc_need_data[ip][Orientation(Direction::x,Orientation::high)] == true) {
122 nc_var_names.push_back(nc_var_prefix[ip] + "_east");
123 }
124 if (phys_bc_need_data[ip][Orientation(Direction::y,Orientation::low)] == true) {
125 nc_var_names.push_back(nc_var_prefix[ip] + "_south");
126 }
127 if (phys_bc_need_data[ip][Orientation(Direction::y,Orientation::high)] == true) {
128 nc_var_names.push_back(nc_var_prefix[ip] + "_north");
129 }
130 nc_var_names_full.push_back(nc_var_prefix[ip] + "_west");
131 nc_var_names_full.push_back(nc_var_prefix[ip] + "_east");
132 nc_var_names_full.push_back(nc_var_prefix[ip] + "_south");
133 nc_var_names_full.push_back(nc_var_prefix[ip] + "_north");
134 }
135 int nvars_full = nc_var_names_full.size();
136
137 using RARRAY = NDArray<Real>;
138 amrex::Vector<RARRAY> arrays(nc_var_names.size());
139
140 // The width of the boundary region we need to read is 1
141 width = 1;
142
143 ReadNetCDFFile(nc_bdry_file, nc_var_names, arrays); // does work on proc 0 only
144 if (ParallelDescriptor::IOProcessor())
145 {
146 // Assert that the data has the same number of time snapshots
147 int itimes = static_cast<int>(arrays[0].get_vshape()[0]);
148 AMREX_ALWAYS_ASSERT(itimes == ntimes);
149
150 // amrex::Print() << "VSHAPE " << arrays[0].get_vshape()[0] << " "
151 // << arrays[0].get_vshape()[1] << " "
152 // << arrays[0].get_vshape()[2] << " "
153 // << arrays[0].get_vshape()[3] << std::endl;
154
155 }
156 ParallelDescriptor::Bcast(&width,1,ioproc);
157
158 int iv_read = 0; // counter to loop through the variables that have been read, which have different indexing than the theroetical full variable list
159 // This loops over every variable on every face, so nvars should be 4 * number of "ivartype" below
160 for (int iv = 0; iv < nvars_full; iv++)
161 {
162 // amrex::Print() << "Building FAB for the NetCDF variable : " << nc_var_names[iv] << std::endl;
163
164 int bdyVarType;
165
166 std::string first1 = nc_var_names_full[iv].substr(0,1);
167 std::string first4 = nc_var_names_full[iv].substr(0,4);
168
169 if (first4 == "salt") {
170 bdyVarType = BdyVars::s;
171 } else if (first4 == "ubar") {
172 bdyVarType = BdyVars::ubar;
173 } else if (first4 == "vbar") {
174 bdyVarType = BdyVars::vbar;
175 } else if (first4 == "zeta") {
176 bdyVarType = BdyVars::zeta;
177 } else if (first1 == "u") {
178 bdyVarType = BdyVars::u;
179 } else if (first1 == "v") {
180 bdyVarType = BdyVars::v;
181 } else if (first4 == "temp") {
182 bdyVarType = BdyVars::t;
183 } else {
184 amrex::Print() << "Trying to read " << first1 << " or " << first4 << std::endl;
185 amrex::Abort("dont know this variable");
186 }
187
188 std::string last4 = nc_var_names_full[iv].substr(nc_var_names_full[iv].size()-4, 4);
189 std::string last5 = nc_var_names_full[iv].substr(nc_var_names_full[iv].size()-5, 5);
190 int bdyType;
191
192 if (last4 == "west") {
193 bdyType = REMORABdyTypes::x_lo;
194 } else if (last4 == "east") {
195 bdyType = REMORABdyTypes::x_hi;
196 } else if (last5 == "south") {
197 bdyType = REMORABdyTypes::y_lo;
198 } else if (last5 == "north") {
199 bdyType = REMORABdyTypes::y_hi;
200 }
201
202 plo[0] = lo[0]; plo[1] = lo[1]; plo[2] = lo[2];
203 phi[0] = hi[0]; phi[1] = hi[1]; phi[2] = hi[2];
204 const Box pbx(plo, phi);
205
206 Arena* Arena_Used = The_Arena();
207#ifdef AMREX_USE_GPU
208 Arena_Used = The_Pinned_Arena();
209#endif
210
211 // Push back boxes for all variables, even if they will not be used. This ensures that
212 // fill_from_bdyfiles can figure out where to look for the data
213 if (bdyType == REMORABdyTypes::x_lo) {
214
215 // *******************************************************************************
216 // xlo bdy
217 // *******************************************************************************
218 Box bx_for_u(IntVect(lo[0], lo[1]-1, lo[2]), IntVect(lo[0], hi[1]+1, hi[2]), IntVect(1,0,0));
219 // amrex::Print() << "XLO:BX FOR U " << bx_for_u << std::endl;
220
221 Box bx_for_v(IntVect(lo[0]-1, lo[1], lo[2]), IntVect(lo[0]-1, hi[1]+1, hi[2]), IntVect(0,1,0));
222 // amrex::Print() << "XLO:BX FOR V " << bx_for_v << std::endl;
223
224 Box bx_for_t(IntVect(lo[0]-1, lo[1]-1, lo[2]), IntVect(lo[0]-1, hi[1]+1, hi[2]));
225 // amrex::Print() << "XLO:BX FOR T " << bx_for_t << std::endl;
226
227 if (bdyVarType == BdyVars::u) {
228 for (int nt(0); nt < ntimes; ++nt) {
229 bdy_data_xlo[nt + nt_prior].push_back(FArrayBox(bx_for_u, 1, Arena_Used)); // u
230 }
231 } else if (bdyVarType == BdyVars::v) {
232 for (int nt(0); nt < ntimes; ++nt) {
233 bdy_data_xlo[nt + nt_prior].push_back(FArrayBox(bx_for_v , 1, Arena_Used)); // v
234 }
235 } else if (bdyVarType == BdyVars::t) {
236 for (int nt(0); nt < ntimes; ++nt) {
237 bdy_data_xlo[nt + nt_prior].push_back(FArrayBox(bx_for_t, 1, Arena_Used)); // temp
238 }
239 } else if (bdyVarType == BdyVars::s) {
240 for (int nt(0); nt < ntimes; ++nt) {
241 bdy_data_xlo[nt + nt_prior].push_back(FArrayBox(bx_for_t, 1, Arena_Used)); // salt
242 }
243 } else if (bdyVarType == BdyVars::ubar) {
244 Box xlo_ubar(makeSlab(bx_for_u,2,0));
245 for (int nt(0); nt < ntimes; ++nt) {
246 bdy_data_xlo[nt + nt_prior].push_back(FArrayBox(xlo_ubar, 1, Arena_Used)); // ubar
247 }
248 } else if (bdyVarType == BdyVars::vbar) {
249 Box xlo_vbar(makeSlab(bx_for_v,2,0));
250 for (int nt(0); nt < ntimes; ++nt) {
251 bdy_data_xlo[nt + nt_prior].push_back(FArrayBox(xlo_vbar, 1, Arena_Used)); // ubar
252 }
253 } else if (bdyVarType == BdyVars::zeta) {
254 Box xlo_zeta(makeSlab(bx_for_t,2,0));
255 for (int nt(0); nt < ntimes; ++nt) {
256 bdy_data_xlo[nt + nt_prior].push_back(FArrayBox(xlo_zeta, 1, Arena_Used)); // ubar
257 }
258 }
259
260 } else if (bdyType == REMORABdyTypes::x_hi) {
261
262 // *******************************************************************************
263 // xhi bdy
264 // *******************************************************************************
265
266 Box bx_for_u(IntVect(hi[0]+1, lo[1]-1, lo[2]), IntVect(hi[0]+1, hi[1]+1, hi[2]), IntVect(1,0,0));
267 // amrex::Print() << "XHI:BX FOR U " << bx_for_u << std::endl;
268
269 Box bx_for_v(IntVect(hi[0]+1, lo[1], lo[2]), IntVect(hi[0]+1, hi[1]+1, hi[2]), IntVect(0,1,0));
270 // amrex::Print() << "XHI:BX FOR V " << bx_for_v << std::endl;
271
272 Box bx_for_t(IntVect(hi[0]+1, lo[1]-1, lo[2]), IntVect(hi[0]+1, hi[1]+1, hi[2]));
273 // amrex::Print() << "XHI:BX FOR T " << bx_for_t << std::endl;
274
275 if (bdyVarType == BdyVars::u) {
276 for (int nt(0); nt < ntimes; ++nt) {
277 bdy_data_xhi[nt + nt_prior].push_back(FArrayBox(bx_for_u, 1, Arena_Used)); // u
278 }
279 } else if (bdyVarType == BdyVars::v) {
280 for (int nt(0); nt < ntimes; ++nt) {
281 bdy_data_xhi[nt + nt_prior].push_back(FArrayBox(bx_for_v , 1, Arena_Used)); // v
282 }
283 } else if (bdyVarType == BdyVars::t) {
284 for (int nt(0); nt < ntimes; ++nt) {
285 bdy_data_xhi[nt + nt_prior].push_back(FArrayBox(bx_for_t, 1, Arena_Used)); // temp
286 }
287 } else if (bdyVarType == BdyVars::s) {
288 for (int nt(0); nt < ntimes; ++nt) {
289 bdy_data_xhi[nt + nt_prior].push_back(FArrayBox(bx_for_t, 1, Arena_Used)); // salt
290 }
291 } else if (bdyVarType == BdyVars::ubar) {
292 Box xhi_ubar(makeSlab(bx_for_u,2,0));
293 for (int nt(0); nt < ntimes; ++nt) {
294 bdy_data_xhi[nt + nt_prior].push_back(FArrayBox(xhi_ubar, 1, Arena_Used)); // ubar
295 }
296 } else if (bdyVarType == BdyVars::vbar) {
297 Box xhi_vbar(makeSlab(bx_for_v,2,0));
298 for (int nt(0); nt < ntimes; ++nt) {
299 bdy_data_xhi[nt + nt_prior].push_back(FArrayBox(xhi_vbar, 1, Arena_Used)); // ubar
300 }
301 } else if (bdyVarType == BdyVars::zeta) {
302 Box xhi_zeta(makeSlab(bx_for_t,2,0));
303 for (int nt(0); nt < ntimes; ++nt) {
304 bdy_data_xhi[nt + nt_prior].push_back(FArrayBox(xhi_zeta, 1, Arena_Used)); // ubar
305 }
306 }
307
308 } else if (bdyType == REMORABdyTypes::y_lo) {
309
310 // *******************************************************************************
311 // ylo bdy
312 // *******************************************************************************
313
314 Box bx_for_v(IntVect(lo[0]-1, lo[1], lo[2]), IntVect(hi[0]+1, lo[1], hi[2]), IntVect(0,1,0));
315 // amrex::Print() << "YLO:BX FOR V " << bx_for_v << std::endl;
316
317 Box bx_for_u(IntVect(lo[0], lo[1]-1, lo[2]), IntVect(hi[0]+1, lo[1]-1, hi[2]), IntVect(1,0,0));
318 // amrex::Print() << "YLO:BX FOR U " << bx_for_u << std::endl;
319
320 Box bx_for_t(IntVect(lo[0]-1, lo[1]-1, lo[2]), IntVect(hi[0]+1, lo[1]-1, hi[2]));
321 // amrex::Print() << "YLO:BX FOR T " << bx_for_t << std::endl;
322
323 if (bdyVarType == BdyVars::u) {
324 for (int nt(0); nt < ntimes; ++nt) {
325 bdy_data_ylo[nt + nt_prior].push_back(FArrayBox(bx_for_u , 1, Arena_Used)); // u
326 }
327 } else if (bdyVarType == BdyVars::v) {
328 for (int nt(0); nt < ntimes; ++nt) {
329 bdy_data_ylo[nt + nt_prior].push_back(FArrayBox(bx_for_v, 1, Arena_Used)); // v
330 }
331 } else if (bdyVarType == BdyVars::t) {
332 for (int nt(0); nt < ntimes; ++nt) {
333 bdy_data_ylo[nt + nt_prior].push_back(FArrayBox(bx_for_t, 1, Arena_Used)); // temp
334 }
335 } else if (bdyVarType == BdyVars::s) {
336 for (int nt(0); nt < ntimes; ++nt) {
337 bdy_data_ylo[nt + nt_prior].push_back(FArrayBox(bx_for_t, 1, Arena_Used)); // salt
338 }
339 } else if (bdyVarType == BdyVars::ubar) {
340 Box ylo_ubar(makeSlab(bx_for_u,2,0));
341 for (int nt(0); nt < ntimes; ++nt) {
342 bdy_data_ylo[nt + nt_prior].push_back(FArrayBox(ylo_ubar, 1, Arena_Used)); // ubar
343 }
344 } else if (bdyVarType == BdyVars::vbar) {
345 Box ylo_vbar(makeSlab(bx_for_v,2,0));
346 for (int nt(0); nt < ntimes; ++nt) {
347 bdy_data_ylo[nt + nt_prior].push_back(FArrayBox(ylo_vbar, 1, Arena_Used)); // ubar
348 }
349 } else if (bdyVarType == BdyVars::zeta) {
350 Box ylo_zeta(makeSlab(bx_for_t,2,0));
351 for (int nt(0); nt < ntimes; ++nt) {
352 bdy_data_ylo[nt + nt_prior].push_back(FArrayBox(ylo_zeta, 1, Arena_Used)); // ubar
353 }
354 }
355
356 } else if (bdyType == REMORABdyTypes::y_hi) {
357
358 // *******************************************************************************
359 // yhi bdy
360 // *******************************************************************************
361
362 Box bx_for_v(IntVect(lo[0]-1, hi[1]+1, lo[2]), IntVect(hi[0]+1, hi[1]+1, hi[2]), IntVect(0,1,0));
363 // amrex::Print() << "YHI:BX FOR V " << bx_for_v << std::endl;
364
365 Box bx_for_u(IntVect(lo[0], hi[1]+1, lo[2]), IntVect(hi[0]+1, hi[1]+1, hi[2]), IntVect(1,0,0));
366 // amrex::Print() << "YHI:BX FOR U " << bx_for_u << std::endl;
367
368 Box bx_for_t(IntVect(lo[0]-1, hi[1]+1, lo[2]), IntVect(hi[0]+1, hi[1]+1, hi[2]));
369 // amrex::Print() << "YHI:BX FOR T " << bx_for_t << std::endl;
370
371 if (bdyVarType == BdyVars::u) {
372 for (int nt(0); nt < ntimes; ++nt) {
373 bdy_data_yhi[nt + nt_prior].push_back(FArrayBox(bx_for_u , 1, Arena_Used)); // u
374 }
375 } else if (bdyVarType == BdyVars::v) {
376 for (int nt(0); nt < ntimes; ++nt) {
377 bdy_data_yhi[nt + nt_prior].push_back(FArrayBox(bx_for_v, 1, Arena_Used)); // v
378 }
379 } else if (bdyVarType == BdyVars::t) {
380 for (int nt(0); nt < ntimes; ++nt) {
381 bdy_data_yhi[nt + nt_prior].push_back(FArrayBox(bx_for_t, 1, Arena_Used)); // temp
382 }
383 } else if (bdyVarType == BdyVars::s) {
384 for (int nt(0); nt < ntimes; ++nt) {
385 bdy_data_yhi[nt + nt_prior].push_back(FArrayBox(bx_for_t, 1, Arena_Used)); // salt
386 }
387 } else if (bdyVarType == BdyVars::ubar) {
388 Box yhi_ubar(makeSlab(bx_for_u,2,0));
389 for (int nt(0); nt < ntimes; ++nt) {
390 bdy_data_yhi[nt + nt_prior].push_back(FArrayBox(yhi_ubar, 1, Arena_Used)); // ubar
391 }
392 } else if (bdyVarType == BdyVars::vbar) {
393 Box yhi_vbar(makeSlab(bx_for_v,2,0));
394 for (int nt(0); nt < ntimes; ++nt) {
395 bdy_data_yhi[nt + nt_prior].push_back(FArrayBox(yhi_vbar, 1, Arena_Used)); // ubar
396 }
397 } else if (bdyVarType == BdyVars::zeta) {
398 Box yhi_zeta(makeSlab(bx_for_t,2,0));
399 for (int nt(0); nt < ntimes; ++nt) {
400 bdy_data_yhi[nt + nt_prior].push_back(FArrayBox(yhi_zeta, 1, Arena_Used)); // ubar
401 }
402 }
403 }
404
405 // Only fill data if the variable we're looking at was read in.
406 if (count(nc_var_names.begin(), nc_var_names.end(), nc_var_names_full[iv])) {
407 long n_plane;
408 // Now fill the data
409 if (ParallelDescriptor::IOProcessor())
410 {
411 // amrex::Print() << "SHAPE0 " << arrays[iv].get_vshape()[0] << std::endl;
412 // amrex::Print() << "SHAPE1 " << arrays[iv].get_vshape()[1] << std::endl;
413 // amrex::Print() << "SHAPE2 " << arrays[iv].get_vshape()[2] << std::endl;
414 // amrex::Print() << "SHAPE3 " << arrays[iv].get_vshape()[3] << std::endl;
415
416 int nx, ny, nz;
417
418 Array4<Real> fab_arr;
419 Box my_box;
420
421 if (bdyType == REMORABdyTypes::x_lo) {
422 my_box = bdy_data_xlo[0][bdyVarType].box();
423 } else if (bdyType == REMORABdyTypes::x_hi) {
424 my_box = bdy_data_xhi[0][bdyVarType].box();
425 } else if (bdyType == REMORABdyTypes::y_lo) {
426 my_box = bdy_data_ylo[0][bdyVarType].box();
427 } else if (bdyType == REMORABdyTypes::y_hi) {
428 my_box = bdy_data_yhi[0][bdyVarType].box();
429 }
430
431 {
432 if ( (bdyType == REMORABdyTypes::x_lo) || (bdyType == REMORABdyTypes::x_hi) ) {
433
434 if (my_box.length()[2] == 1) {
435 nz = 1;
436 ny = arrays[iv_read].get_vshape()[1];
437 } else {
438 nz = arrays[iv_read].get_vshape()[1];
439 ny = arrays[iv_read].get_vshape()[2];
440 }
441 n_plane = ny * nz;
442
443 AMREX_ALWAYS_ASSERT(my_box.numPts() == n_plane);
444
445 int i = my_box.smallEnd()[0];
446 int joff = my_box.smallEnd()[1];
447
448 for (int nt(0); nt < ntimes; ++nt)
449 {
450 if (bdyType == REMORABdyTypes::x_lo) {
451 fab_arr = bdy_data_xlo[nt + nt_prior][bdyVarType].array();
452 } else if (bdyType == REMORABdyTypes::x_hi) {
453 fab_arr = bdy_data_xhi[nt + nt_prior][bdyVarType].array();
454 }
455 int n_off = nt * n_plane;
456
457 for (int n(0); n < n_plane; ++n) {
458 int k = n / ny;
459 int j = n - (k * ny);
460 fab_arr(i, j+joff, k, 0) = static_cast<Real>(*(arrays[iv_read].get_data() + n + n_off));
461 }
462 }
463
464 } else if ( (bdyType == REMORABdyTypes::y_lo) || (bdyType == REMORABdyTypes::y_hi) ) {
465
466 if (my_box.length()[2] == 1) {
467 nz = 1;
468 nx = arrays[iv_read].get_vshape()[1];
469 } else {
470 nz = arrays[iv_read].get_vshape()[1];
471 nx = arrays[iv_read].get_vshape()[2];
472 }
473 n_plane = nx * nz;
474
475 AMREX_ALWAYS_ASSERT(my_box.numPts() == n_plane);
476
477 int j = my_box.smallEnd()[1];
478 int ioff = my_box.smallEnd()[0];
479
480 for (int nt(0); nt < ntimes; ++nt)
481 {
482 if (bdyType == REMORABdyTypes::y_lo) {
483 fab_arr = bdy_data_ylo[nt + nt_prior][bdyVarType].array();
484 } else if (bdyType == REMORABdyTypes::y_hi) {
485 fab_arr = bdy_data_yhi[nt + nt_prior][bdyVarType].array();
486 }
487 int n_off = nt * n_plane;
488
489 for (int n(0); n < n_plane; ++n) {
490 int k = n / nx;
491 int i = n - (k * nx);
492
493 fab_arr(i+ioff, j, k, 0) = static_cast<Real>(*(arrays[iv_read].get_data() + n + n_off));
494 }
495 }
496 } // bdyType
497 } // bdyVarType
498 } // if ParalleDescriptor::IOProcessor()
499 iv_read += 1;
500 } // count
501 } // nc_var_names
502
503 // We put a barrier here so the rest of the processors wait to do anything until they have the data
504 amrex::ParallelDescriptor::Barrier();
505
506 // When an FArrayBox is built, space is allocated on every rank. However, we only
507 // filled the data in these FABs on the IOProcessor. So here we broadcast
508 // the data to every rank.
509 for (int nt = nt_prior; nt < bdy_data_xlo.size(); nt++)
510 {
511 for (int i = 0; i < bdy_data_xlo[nt].size(); i++)
512 {
513 ParallelDescriptor::Bcast(bdy_data_xlo[nt][i].dataPtr(),bdy_data_xlo[nt][i].box().numPts(),ioproc);
514 }
515 }
516 for (int nt = nt_prior; nt < bdy_data_ylo.size(); nt++)
517 {
518 for (int i = 0; i < bdy_data_ylo[nt].size(); i++)
519 {
520 ParallelDescriptor::Bcast(bdy_data_ylo[nt][i].dataPtr(),bdy_data_ylo[nt][i].box().numPts(),ioproc);
521 }
522 }
523 for (int nt = nt_prior; nt < bdy_data_xhi.size(); nt++)
524 {
525 for (int i = 0; i < bdy_data_xhi[nt].size(); i++)
526 {
527 ParallelDescriptor::Bcast(bdy_data_xhi[nt][i].dataPtr(),bdy_data_xhi[nt][i].box().numPts(),ioproc);
528 }
529 }
530 for (int nt = nt_prior; nt < bdy_data_yhi.size(); nt++)
531 {
532 for (int i = 0; i < bdy_data_yhi[nt].size(); i++)
533 {
534 ParallelDescriptor::Bcast(bdy_data_yhi[nt][i].dataPtr(),bdy_data_yhi[nt][i].box().numPts(),ioproc);
535 }
536 }
537
538 // Make sure all processors know how timeInterval
539 ParallelDescriptor::Bcast(&timeInterval,1,ioproc);
540
541 int total_times = nt_prior + ntimes;
542 // Make sure all processors know how many times are stored
543 ParallelDescriptor::Bcast(&total_times,1,ioproc);
544
545 // Return the number of seconds between the boundary plane data
546 return timeInterval;
547}
548#endif // REMORA_USE_NETCDF
void ReadNetCDFFile(const std::string &fname, amrex::Vector< std::string > names, amrex::Vector< NDArray< DType > > &arrays, bool one_time=false, int fill_time=0)
Read in data from netcdf file and save to data arrays.
std::string ReadNetCDFVarAttrStr(const std::string &fname, const std::string &var_name, const std::string &attr_name)
Helper function for reading a single variable attribute.
Real read_bdry_from_netcdf(const Box &domain, const std::string &nc_bdry_file, Vector< Vector< FArrayBox > > &bdy_data_xlo, Vector< Vector< FArrayBox > > &bdy_data_xhi, Vector< Vector< FArrayBox > > &bdy_data_ylo, Vector< Vector< FArrayBox > > &bdy_data_yhi, int &width, Real &start_bdy_time, std::string bdry_time_varname, amrex::GpuArray< amrex::GpuArray< bool, AMREX_SPACEDIM *2 >, BdyVars::NumTypes+1 > &phys_bc_need_data)
NDArray is the datatype designed to hold any data, including scalars, multidimensional arrays,...