ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_ReadCustomBinaryIC.H
Go to the documentation of this file.
1 #ifndef ERF_READCUSTOMBINARYIC_H_
2 #define ERF_READCUSTOMBINARYIC_H_
3 
4 #include <array>
5 #include <fstream>
6 #include <limits>
7 
8 #include "ERF_DataStruct.H"
9 
10 /*
11  * Routine to read in the custom written binary file into vectors
12  * of variables
13  */
14 
15 inline void
16 ReadCustomBinaryIC (const std::string filename,
17  amrex::Vector<amrex::Real>& latvec_h,
18  amrex::Vector<amrex::Real>& lonvec_h,
19  amrex::Vector<amrex::Real>& xvec_h,
20  amrex::Vector<amrex::Real>& yvec_h,
21  amrex::Vector<amrex::Real>& zvec_h,
22  amrex::Vector<amrex::Real>& rho_h,
23  amrex::Vector<amrex::Real>& uvel_h,
24  amrex::Vector<amrex::Real>& vvel_h,
25  amrex::Vector<amrex::Real>& wvel_h,
26  amrex::Vector<amrex::Real>& theta_h,
27  amrex::Vector<amrex::Real>& qv_h,
28  amrex::Vector<amrex::Real>& qc_h,
29  amrex::Vector<amrex::Real>& qr_h)
30 {
31  int nx = 0, ny = 0, nz = 0, ndata = 0;
32  float value;
33 
34  // Open the binary file in input mode
35  std::ifstream infile(filename, std::ios::binary);
36  if (!infile) {
37  amrex::Abort("Error: Could not open file " + filename);
38  }
39 
40  auto read_or_abort = [&](auto& dest, const std::string& field_name) {
41  infile.read(reinterpret_cast<char*>(&dest), sizeof(dest));
42  if (!infile) {
43  amrex::Abort("Error reading " + field_name + " from " + filename);
44  }
45  };
46 
47  auto read_float_vector = [&](amrex::Vector<amrex::Real>& dest,
48  amrex::Long count,
49  const std::string& field_name)
50  {
51  if (count < 0) {
52  amrex::Abort("Error: negative element count for " + field_name + " in " + filename);
53  }
54 
55  dest.reserve(dest.size() + count);
56  for (amrex::Long idx = 0; idx < count; ++idx) {
57  read_or_abort(value, field_name);
58  dest.emplace_back(value);
59  }
60  };
61 
62  // Read the four integers
63  read_or_abort(nx, "nx");
64  read_or_abort(ny, "ny");
65  read_or_abort(nz, "nz");
66  read_or_abort(ndata, "ndata");
67 
68  if (nx <= 0 || ny <= 0 || nz <= 0) {
69  amrex::Abort("Error: invalid custom binary dimensions in " + filename);
70  }
71 
72  if (ndata < 0 || ndata > 8) {
73  amrex::Abort("Error: unsupported number of data fields in " + filename);
74  }
75 
76  // The dimensions come from the file: form the element counts in 64 bits, refusing any
77  // whose byte count would overflow, and check the file holds that many values before
78  // reserving room for them
79  constexpr amrex::Long max_count = std::numeric_limits<amrex::Long>::max()
80  / static_cast<amrex::Long>(sizeof(float));
81  const amrex::Long nxy = static_cast<amrex::Long>(nx) * ny;
82  if (nz > max_count / nxy) {
83  amrex::Abort("Error: custom binary dimensions too large in " + filename);
84  }
85  const amrex::Long nxyz = nxy * nz;
86 
87  // 2 nxy + nx + ny + nz + ndata nxyz values, without overflowing
88  amrex::Long nvalues = 2*nxy + nx + ny + nz;
89  if (nvalues > max_count || (ndata > 0 && nxyz > (max_count - nvalues) / ndata)) {
90  amrex::Abort("Error: custom binary dimensions too large in " + filename);
91  }
92  nvalues += ndata * nxyz;
93 
94  const auto data_start = infile.tellg();
95  infile.seekg(0, std::ios::end);
96  const auto bytes_left = static_cast<amrex::Long>(infile.tellg() - data_start);
97  infile.seekg(data_start);
98  if (!infile || bytes_left < nvalues * static_cast<amrex::Long>(sizeof(float))) {
99  amrex::Abort("Error: " + filename + " is shorter than its dimensions say");
100  }
101 
102  read_float_vector(latvec_h, nxy, "latitude");
103  read_float_vector(lonvec_h, nxy, "longitude");
104  read_float_vector(xvec_h, nx, "x coordinates");
105  read_float_vector(yvec_h, ny, "y coordinates");
106  read_float_vector(zvec_h, nz, "z coordinates");
107 
108  std::array<amrex::Vector<amrex::Real>*, 8> data_fields = {
109  &rho_h, &uvel_h, &vvel_h, &wvel_h, &theta_h, &qv_h, &qc_h, &qr_h
110  };
111 
112  // Read the file
113  for (int idx = 0; idx < ndata; ++idx) {
114  read_float_vector(*data_fields[idx], nxyz,
115  "data field " + std::to_string(idx));
116  }
117 }
118 #endif
const int nx
Definition: ERF_InitCustomPertVels_CloudChamber.H:14
const int ny
Definition: ERF_InitCustomPertVels_CloudChamber.H:15
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int idx(int i, int j, int k, int nx, int ny)
Definition: ERF_InitForEnsemble.cpp:404
void ReadCustomBinaryIC(const std::string filename, amrex::Vector< amrex::Real > &latvec_h, amrex::Vector< amrex::Real > &lonvec_h, amrex::Vector< amrex::Real > &xvec_h, amrex::Vector< amrex::Real > &yvec_h, amrex::Vector< amrex::Real > &zvec_h, amrex::Vector< amrex::Real > &rho_h, amrex::Vector< amrex::Real > &uvel_h, amrex::Vector< amrex::Real > &vvel_h, amrex::Vector< amrex::Real > &wvel_h, amrex::Vector< amrex::Real > &theta_h, amrex::Vector< amrex::Real > &qv_h, amrex::Vector< amrex::Real > &qc_h, amrex::Vector< amrex::Real > &qr_h)
Definition: ERF_ReadCustomBinaryIC.H:16
Vector< Real > rho_h(khi+1, zero)