5#include "AMReX_FillPatchUtil.H"
6#include "AMReX_Interpolater.H"
7#include "AMReX_ParallelDescriptor.H"
14#ifdef REMORA_USE_NETCDF
42 amrex::Print() <<
"Loading " <<
field_name <<
" from NetCDF file(s)" << std::endl;
48 if (
field_name.find(
"wind") != std::string::npos) {
80 if (amrex::ParallelDescriptor::IOProcessor())
92 "NetCDF time variable cycle_length attribute must be scalar");
98 amrex::Abort(
"NetCDF time series variable " +
field_name +
107 amrex::Abort(
"Unsupported NetCDF time series rank for variable " +
109 std::to_string(
field_rank) +
". Expected rank 1 for " +
110 "uniform time-only data or rank " +
112 " for spatial data.");
118 const int ioproc = amrex::ParallelDescriptor::IOProcessorNumber();
129 amrex::Vector<NDArray<double>>
array_ts(1);
131 if (amrex::ParallelDescriptor::IOProcessor())
145 [&](
const auto&
x) { return x == file_is_cycle.front(); });
147 [&](
const auto&
x) { return x == file_cycle_length.front(); });
150 amrex::Abort(
"If one time series file in a set has a cycle, they all must, and cycle lengths must be equal");
160 if (amrex::ParallelDescriptor::IOProcessor()) {
163 amrex::Error(
"Time series data must be given at at least two times");
166 int ioproc = amrex::ParallelDescriptor::IOProcessorNumber();
168 if (!(amrex::ParallelDescriptor::IOProcessor())) {
203 const amrex::Vector<amrex::Geometry>&
geom,
204 const amrex::Vector<amrex::IntVect>&
ref_ratio) {
230 amrex::Abort(
"Time " + std::to_string(
time) +
" (mapped to " + std::to_string(
l_time)
231 +
") is not spanned by the time series for '" +
field_name +
"', which covers ["
234 +
"]. Extend the forcing file to cover the run, or give its time variable a"
235 +
" cycle_length attribute so it repeats. The file's times were placed on the"
236 +
" model clock from the reference date in their units attribute (the mapping"
237 +
" is printed when the series is loaded), so also check remora.time_ref and"
238 +
" remora.start_time.");
261#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
307 amrex::Interpolater*
mapper =
nullptr;
309 if (
idx_type == amrex::IndexType(amrex::IntVect(0,0,0))) {
310 mapper = &amrex::cell_cons_interp;
312 mapper = &amrex::face_cons_linear_interp;
327 const amrex::Vector<amrex::IntVect>&
ref_ratio)
const {
328 amrex::IntVect
rr(1,1,1);
329 for (
int l = 0;
l <
lev; ++
l) {
337const amrex::MultiFab*
345 "NCTimeSeries '" +
field_name +
"' was last interpolated for level "
347 +
". Call update_interpolated_to_time for this level first.");
360 amrex::Print() <<
"Reading in " <<
field_name <<
" at time index " <<
itime
365 "NetCDF time series file layout was not initialized");
373 if (amrex::ParallelDescriptor::IOProcessor()) {
374 const std::vector<MPI_Offset> shape =
array_dat[0].get_vshape();
376 shape.size() == 1 && shape[0] == 1,
377 "Uniform NetCDF time series read did not produce one value");
381 const int ioproc = amrex::ParallelDescriptor::IOProcessorNumber();
389 amrex::Vector<amrex::FArrayBox*>
NC_fabs;
390 amrex::Vector<std::string>
NC_names;
406#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
410 for ( amrex::MFIter
mfi(*
mf,
false);
mfi.isValid(); ++
mfi )
412 amrex::FArrayBox &
fab = (*mf)[
mfi];
constexpr amrex::Real zero
mf_h setVal(geomdata.ProbHi(2))
AMREX_ALWAYS_ASSERT(!NSPeriodic||!EWPeriodic)
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.
double ReadNetCDFTimeOffsetDays(const std::string &fname, const std::string &time_name, double time_ref, bool units_required, bool announce)
Offset, in days, that puts a file's time variable onto the model clock.
static PhysBCFunctNoOp null_bc_for_fill
amrex::Vector< std::unique_ptr< amrex::MultiFab > > mf_interpolated_lev
Interpolated data on each requested AMR level if save_interpolated=true.
bool is2d
Whether the field we're reading in is 2d.
void read_in_at_time(amrex::MultiFab *mf, int itime)
Read in data from file at time index itime and fill into mf.
amrex::Vector< int > file_itime_offset
Offset to access a particular time within its file.
double time_before
Time in ocean_times immediately before the last time interpolated to.
NCTimeSeries(const amrex::Vector< std::string > &a_file_names, const std::string a_field_name, const std::string a_time_name, const amrex::Box &a_domain, amrex::MultiFab *a_mf_var, bool a_is2d, bool a_save_interpolated, double a_time_ref)
Constructor.
amrex::MultiFab * mf_interp_lev0
Multifab storing temporally interpolated data on level 0.
bool is_cycle
Whether the time series is a cycle.
void Initialize()
Read in time array from file and allocate data arrays.
amrex::Vector< int > file_is_spatially_uniform
Whether each file stores this field as one value per time record.
amrex::MultiFab * mf_before
Multifab to store data at time_before.
amrex::Vector< double > ocean_times
int i_time_before
Time index immediately before the last time interpolated to.
std::string field_name
Field name in netcdf file.
amrex::IntVect cumulative_ref_ratio(int lev, const amrex::Vector< amrex::IntVect > &ref_ratio) const
Build cumulative refinement ratio from level 0 to lev.
amrex::Vector< std::string > file_names
File names to read from.
amrex::MultiFab * mf_after
Multifab to store data at time_after.
double cycle_length
If a cycle, what is the cycle length?
std::string time_name
Field name for time series in netcdf file.
amrex::Vector< int > file_for_time
File index to access a particular time.
const amrex::MultiFab * get_interpolated_mf(int lev) const
Access interpolated data saved for a specific level.
void update_interpolated_to_time(double time, int lev, amrex::MultiFab *mf_lev, const amrex::Vector< amrex::Geometry > &geom, const amrex::Vector< amrex::IntVect > &ref_ratio)
Calculate interpolated values at time, in seconds on the model clock, and fill data for level lev.
double time_after
Time in ocean_times immediately after the last time interpolated to.
static NCFile open(const std::string &name, const int cmode=NC_NOWRITE, MPI_Comm comm=MPI_COMM_WORLD, MPI_Info info=MPI_INFO_NULL)
Open an existing file.
NDArray is the datatype designed to hold any data, including scalars, multidimensional arrays,...