ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_NCWpsFile.H File Reference
#include <sstream>
#include <string>
#include <ctime>
#include <atomic>
#include "AMReX_FArrayBox.H"
#include "AMReX_IArrayBox.H"
#include "ERF_NCInterface.H"
Include dependency graph for ERF_NCWpsFile.H:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  NDArray< DataType >
 

Typedefs

using PlaneVector = amrex::Vector< amrex::FArrayBox >
 

Enumerations

enum class  NC_Data_Dims_Type {
  Time_BT_SN_WE , Time_SN_WE , Time_BT , Time ,
  Time_BdyWidth_BT_SN , Time_BdyWidth_BT_WE , Time_BdyWidth_SN , Time_BdyWidth_WE
}
 

Functions

int BuildFABsFromWRFBdyFile (const std::string &fname, amrex::Vector< amrex::Vector< amrex::FArrayBox >> &bdy_data_xlo, amrex::Vector< amrex::Vector< amrex::FArrayBox >> &bdy_data_xhi, amrex::Vector< amrex::Vector< amrex::FArrayBox >> &bdy_data_ylo, amrex::Vector< amrex::Vector< amrex::FArrayBox >> &bdy_data_yhi)
 
AMREX_FORCE_INLINE std::time_t getEpochTime (const std::string &dateTime, const std::string &dateTimeFormat)
 
template<typename DType >
void ReadNetCDFFile (const std::string &fname, amrex::Vector< std::string > names, amrex::Vector< NDArray< DType > > &arrays)
 
template<class FAB , typename DType >
void fill_fab_from_arrays (int iv, amrex::Vector< NDArray< float >> &nc_arrays, const std::string &var_name, NC_Data_Dims_Type &NC_dim_type, FAB &temp)
 
template<class FAB , typename DType >
void BuildFABsFromNetCDFFile (const amrex::Box &domain, const std::string &fname, amrex::Vector< std::string > nc_var_names, amrex::Vector< enum NC_Data_Dims_Type > NC_dim_types, amrex::Vector< FAB * > fab_vars)
 

Typedef Documentation

◆ PlaneVector

using PlaneVector = amrex::Vector<amrex::FArrayBox>

Enumeration Type Documentation

◆ NC_Data_Dims_Type

enum NC_Data_Dims_Type
strong
Enumerator
Time_BT_SN_WE 
Time_SN_WE 
Time_BT 
Time 
Time_BdyWidth_BT_SN 
Time_BdyWidth_BT_WE 
Time_BdyWidth_SN 
Time_BdyWidth_WE 

Function Documentation

◆ BuildFABsFromNetCDFFile()

template<class FAB , typename DType >
void BuildFABsFromNetCDFFile ( const amrex::Box &  domain,
const std::string &  fname,
amrex::Vector< std::string >  nc_var_names,
amrex::Vector< enum NC_Data_Dims_Type NC_dim_types,
amrex::Vector< FAB * >  fab_vars 
)

Function to read NetCDF variables and fill the corresponding Array4's

Parameters
fnameName of the NetCDF file to be read
nc_var_namesVariable names in the NetCDF file
NC_dim_typesNetCDF data dimension types
fab_varsFab data we are to fill
304 {
305  int ioproc = amrex::ParallelDescriptor::IOProcessorNumber(); // I/O rank
306 
307  amrex::Vector<NDArray<float>> nc_arrays(nc_var_names.size());
308 
309  if (amrex::ParallelDescriptor::IOProcessor())
310  {
311  ReadNetCDFFile(fname, nc_var_names, nc_arrays);
312  }
313 
314  for (int iv = 0; iv < nc_var_names.size(); iv++)
315  {
316  FAB tmp;
317  if (amrex::ParallelDescriptor::IOProcessor()) {
318  fill_fab_from_arrays<FAB,DType>(iv, nc_arrays, nc_var_names[iv], NC_dim_types[iv], tmp);
319  }
320 
321  int ncomp = tmp.nComp();
322  amrex::Box box = tmp.box();
323 
324  amrex::ParallelDescriptor::Bcast(&box, 1, ioproc);
325  amrex::ParallelDescriptor::Bcast(&ncomp, 1, ioproc);
326 
327  if (!amrex::ParallelDescriptor::IOProcessor()) {
328 #ifdef AMREX_USE_GPU
329  tmp.resize(box,ncomp,amrex::The_Pinned_Arena());
330 #else
331  tmp.resize(box,ncomp);
332 #endif
333  }
334 
335  amrex::ParallelDescriptor::Bcast(tmp.dataPtr(), tmp.size(), ioproc);
336 
337  // Shift box by the domain lower corner
338  amrex::Box fab_bx = tmp.box();
339  amrex::Dim3 dom_lb = lbound(domain);
340  fab_bx += amrex::IntVect(dom_lb.x,dom_lb.y,dom_lb.z);
341  // fab_vars points to data on device
342  fab_vars[iv]->resize(fab_bx,1);
343 #ifdef AMREX_USE_GPU
344  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
345  tmp.dataPtr(), tmp.dataPtr() + tmp.size(),
346  fab_vars[iv]->dataPtr());
347 #else
348  // Provided by BaseFab inheritance through FArrayBox
349  fab_vars[iv]->copy(tmp,tmp.box(),0,fab_bx,0,1);
350 #endif
351  }
352 }
void ReadNetCDFFile(const std::string &fname, amrex::Vector< std::string > names, amrex::Vector< NDArray< DType > > &arrays)
Definition: ERF_NCWpsFile.H:157
Here is the call graph for this function:

◆ BuildFABsFromWRFBdyFile()

int BuildFABsFromWRFBdyFile ( const std::string &  fname,
amrex::Vector< amrex::Vector< amrex::FArrayBox >> &  bdy_data_xlo,
amrex::Vector< amrex::Vector< amrex::FArrayBox >> &  bdy_data_xhi,
amrex::Vector< amrex::Vector< amrex::FArrayBox >> &  bdy_data_ylo,
amrex::Vector< amrex::Vector< amrex::FArrayBox >> &  bdy_data_yhi 
)

◆ fill_fab_from_arrays()

template<class FAB , typename DType >
void fill_fab_from_arrays ( int  iv,
amrex::Vector< NDArray< float >> &  nc_arrays,
const std::string &  var_name,
NC_Data_Dims_Type NC_dim_type,
FAB &  temp 
)

Helper function for reading data from NetCDF file into a provided FAB.

Parameters
ivIndex for which variable we are going to fill
nc_arraysArrays of data from NetCDF file
var_nameVariable name
NC_dim_typeDimension type for the variable as stored in the NetCDF file
tempFAB where we store the variable data from the NetCDF Arrays
230 {
231  int ns1, ns2, ns3;
232  if (NC_dim_type == NC_Data_Dims_Type::Time_BT) {
233  ns1 = nc_arrays[iv].get_vshape()[1];
234  ns2 = 1;
235  ns3 = 1;
236  // amrex::Print() << "TYPE BT " << ns1 << std::endl;
237  } else if (NC_dim_type == NC_Data_Dims_Type::Time_SN_WE) {
238  ns1 = 1;
239  ns2 = nc_arrays[iv].get_vshape()[1];
240  ns3 = nc_arrays[iv].get_vshape()[2];
241  // amrex::Print() << "TYPE SN WE " << ns2 << " " << ns3 << std::endl;
242  } else if (NC_dim_type == NC_Data_Dims_Type::Time_BT_SN_WE) {
243  ns1 = nc_arrays[iv].get_vshape()[1];
244  ns2 = nc_arrays[iv].get_vshape()[2];
245  ns3 = nc_arrays[iv].get_vshape()[3];
246  // amrex::Print() << "TYPE BT SN WE " << ns1 << " " << ns2 << " " << ns3 << std::endl;
247  } else {
248  amrex::Abort("Dont know this NC_Data_Dims_Type");
249  }
250 
251  // TODO: The box will only start at (0,0,0) at level 0 -- we need to generalize this
252  amrex::Box my_box(amrex::IntVect(0,0,0), amrex::IntVect(ns3-1,ns2-1,ns1-1));
253 
254  if (var_name == "PH" || var_name == "PHB") {
255  my_box.setType(amrex::IndexType(amrex::IntVect(0,0,1)));
256  } else if (var_name == "U" || var_name == "UU" ||
257  var_name == "MAPFAC_U" || var_name == "MAPFAC_UY")
258  {
259  my_box.setType(amrex::IndexType(amrex::IntVect(1,0,0)));
260  } else if (var_name == "V" || var_name == "VV" ||
261  var_name == "MAPFAC_V" || var_name == "MAPFAC_VY")
262  {
263  my_box.setType(amrex::IndexType(amrex::IntVect(0,1,0)));
264  } else if (var_name == "W" || var_name == "WW") {
265  my_box.setType(amrex::IndexType(amrex::IntVect(0,0,1)));
266  }
267 
268  amrex::Arena* Arena_Used = amrex::The_Arena();
269 #ifdef AMREX_USE_GPU
270  // Make sure temp lives on CPU since nc_arrays lives on CPU only
271  Arena_Used = amrex::The_Pinned_Arena();
272 #endif
273  temp.resize(my_box,1, Arena_Used);
274  amrex::Array4<DType> fab_arr = temp.array();
275 
276  int ioff = temp.box().smallEnd()[0];
277  int joff = temp.box().smallEnd()[1];
278 
279  auto num_pts = my_box.numPts();
280 
281  for (int n(0); n < num_pts; ++n) {
282  int k = n / (ns2*ns3);
283  int j = (n - k*(ns2*ns3)) / ns3 + joff;
284  int i = n - k*(ns2*ns3) - (j-joff) * ns3 + ioff;
285  fab_arr(i,j,k,0) = static_cast<DType>(*(nc_arrays[iv].get_data()+n));
286  }
287 }

◆ getEpochTime()

AMREX_FORCE_INLINE std::time_t getEpochTime ( const std::string &  dateTime,
const std::string &  dateTimeFormat 
)
134 {
135  // Create a stream which we will use to parse the string,
136  // which we provide to constructor of stream to fill the buffer.
137  std::istringstream ss{ dateTime };
138 
139  // Create a tm object to store the parsed date and time.
140  std::tm tmTime;
141  memset(&tmTime, 0, sizeof(tmTime));
142 
143  // Now we read from buffer using get_time manipulator
144  // and formatting the input appropriately.
145  strptime(dateTime.c_str(), dateTimeFormat.c_str(), &tmTime);
146 
147  // Convert the tm structure to time_t value and return.
148  // Here we use timegm since the output should be relative to UTC.
149  auto epoch = timegm(&tmTime);
150  // Print() << "Time Stamp: "<< std::put_time(&tmTime, "%c")
151  // << " , Epoch: " << epoch << std::endl;
152 
153  return epoch;
154 }

◆ ReadNetCDFFile()

template<typename DType >
void ReadNetCDFFile ( const std::string &  fname,
amrex::Vector< std::string >  names,
amrex::Vector< NDArray< DType > > &  arrays 
)
159 {
160  AMREX_ASSERT(arrays.size() == names.size());
161 
162  if (amrex::ParallelDescriptor::IOProcessor())
163  {
164  auto ncf = ncutils::NCFile::open(fname, NC_CLOBBER | NC_NETCDF4);
165 
166  /*
167  // get the dimension information
168  int Time = static_cast<int>(ncf.dim("Time").len());
169  int DateStrLen = static_cast<int>(ncf.dim("DateStrLen").len());
170  int west_east = static_cast<int>(ncf.dim("west_east").len());
171  int south_north = static_cast<int>(ncf.dim("south_north").len());
172  int bottom_top = static_cast<int>(ncf.dim("bottom_top").len());
173  int bottom_top_stag = static_cast<int>(ncf.dim("bottom_top_stag").len());
174  int west_east_stag = static_cast<int>(ncf.dim("west_east_stag").len());
175  int south_north_stag = static_cast<int>(ncf.dim("south_north_stag").len());
176  int bdy_width = static_cast<int>(ncf.dim("bdy_width").len());
177  */
178 
179  // amrex::Print() << "Reading the dimensions from the netcdf file " << "\n";
180  for (auto n=0; n<arrays.size(); ++n) {
181  // read the data from NetCDF file
182  std::string vname_to_write = names[n];
183  std::string vname_to_read = names[n];
184  if (vname_to_read.substr(0,2) == "R_") {
185  vname_to_read = names[n+4]; // This allows us to read "T" instead -- we will over-write this later
186  }
187 
188  /*
189  amrex::AllPrint() << "About to read " << vname_to_read
190  << " while filling the array for " << vname_to_write << std::endl;
191  */
192 
193  std::vector<size_t> shape = ncf.var(vname_to_read).shape();
194  arrays[n] = NDArray<DType>(vname_to_read,shape);
195  DType* dataPtr = arrays[n].get_data();
196 
197  std::vector<size_t> start(shape.size(), 0);
198 
199  // auto numPts = arrays[n].ndim();
200  // amrex::Print() << "NetCDF Variable name = " << vname_to_read << std::endl;
201  // amrex::Print() << "numPts read from NetCDF file/var = " << numPts << std::endl;
202  // amrex::Print() << "Dims of the variable = (";
203  // for (auto &dim:shape)
204  // amrex::Print() << dim << ", " ;
205  // amrex::Print() << ")" << std::endl;
206 
207  ncf.var(vname_to_read).get(dataPtr, start, shape);
208  }
209  ncf.close();
210  }
211 }
static NCFile open(const std::string &name, const int cmode=NC_NOWRITE)
Definition: ERF_NCInterface.cpp:674
Definition: ERF_NCWpsFile.H:51

Referenced by BuildFABsFromNetCDFFile().

Here is the call graph for this function:
Here is the caller graph for this function: