3#include <AMReX_BCRec.H>
5#include <AMReX_FillPatchUtil.H>
6#include <AMReX_Geometry.H>
7#include <AMReX_Interpolater.H>
8#include <AMReX_MFIter.H>
9#include <AMReX_MultiFabUtil.H>
10#include <AMReX_Print.H>
33constexpr int SSTIndex = 0;
36make_unit_slab_geometry (Box
const& domain)
38 static constexpr Real lo[AMREX_SPACEDIM] = {0.0_rt, 0.0_rt, 0.0_rt};
39 static constexpr Real hi[AMREX_SPACEDIM] = {1.0_rt, 1.0_rt, 1.0_rt};
40 static constexpr int periodicity[AMREX_SPACEDIM] = {0, 0, 0};
42 return Geometry(domain, &rb, CoordSys::cartesian, periodicity);
46make_internal_bcs (
int ncomp)
48 Vector<BCRec> bcs(ncomp);
49 for (
auto& bc : bcs) {
50 for (
int dir = 0; dir < AMREX_SPACEDIM; ++dir) {
51 bc.setLo(dir, BCType::int_dir);
52 bc.setHi(dir, BCType::int_dir);
62 Real cur_time =
t_new[0];
63 const int step =
istep[0];
121 if (state.empty() || state[SSTIndex] ==
nullptr) {
return; }
125 const int k_sfc =
cons_new[lev]->boxArray().minimalBox().bigEnd(2);
129 BoxList bl2d =
cons_new[lev]->boxArray().boxList();
130 for (
auto& b : bl2d) { b.setRange(2, 0); }
131 BoxArray ba2d(std::move(bl2d));
132 MultiFab tmp(ba2d,
cons_new[lev]->DistributionMap(), 1, 0);
134 for (MFIter mfi(*
cons_new[lev]); mfi.isValid(); ++mfi) {
135 auto const& c =
cons_new[lev]->const_array(mfi);
136 auto t = tmp.array(mfi);
137 Box bx = makeSlab(mfi.validbox(), 2, k_sfc);
138 ParallelFor(bx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int) {
140 t(i, j, 0) = c(i, j, k_sfc,
Temp_comp) + 273.15_rt;
144 MultiFab& dst = *state[SSTIndex];
145 const Box src_domain = tmp.boxArray().minimalBox();
146 const Box dst_domain = dst.boxArray().minimalBox();
148 AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
149 src_domain.smallEnd(2) == src_domain.bigEnd(2) &&
150 dst_domain.smallEnd(2) == dst_domain.bigEnd(2),
151 "REMORA::PackSurfaceState expects 2D slab source and destination MultiFabs.");
152 AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
153 src_domain.smallEnd(0) == dst_domain.smallEnd(0) &&
154 src_domain.smallEnd(1) == dst_domain.smallEnd(1),
155 "REMORA::PackSurfaceState requires aligned atmosphere/ocean slab origins.");
157 const IntVect src_len = src_domain.length();
158 const IntVect dst_len = dst_domain.length();
159 AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
160 src_len[2] == 1 && dst_len[2] == 1,
161 "REMORA::PackSurfaceState expects unit-thickness source and destination slabs.");
163 const bool same_xy = (src_len[0] == dst_len[0] && src_len[1] == dst_len[1]);
164 const bool dst_finer =
165 (dst_len[0] >= src_len[0] && dst_len[1] >= src_len[1] &&
166 dst_len[0] % src_len[0] == 0 && dst_len[1] % src_len[1] == 0);
167 const bool dst_coarser =
168 (src_len[0] >= dst_len[0] && src_len[1] >= dst_len[1] &&
169 src_len[0] % dst_len[0] == 0 && src_len[1] % dst_len[1] == 0);
172 dst.ParallelCopy(tmp, 0, 0, 1);
177 const IntVect ratio(dst_len[0] / src_len[0], dst_len[1] / src_len[1], 1);
178 const auto src_geom = make_unit_slab_geometry(src_domain);
179 const auto dst_geom = make_unit_slab_geometry(dst_domain);
180 const auto bcs = make_internal_bcs(1);
181 amrex::InterpFromCoarseLevel(dst, IntVect(0), IntVect(0),
184 ratio, &pc_interp, bcs, 0);
189 const IntVect ratio(src_len[0] / dst_len[0], src_len[1] / dst_len[1], 1);
190 amrex::average_down(tmp, dst, 0, 1, ratio);
194 amrex::Abort(
"REMORA::PackSurfaceState requires matching horizontal extents and integer-ratio atmosphere/ocean slab resolutions.");
224 if (finest_level < 0) {
return; }
230 vec_uwind[0]->FillBoundary(geom[0].periodicity());
237 vec_vwind[0]->FillBoundary(geom[0].periodicity());
247 vec_Pair[0]->FillBoundary(geom[0].periodicity());
256 vec_qair[0]->FillBoundary(geom[0].periodicity());
265 vec_Tair[0]->plus(-273.15_rt, 0, 1);
266 vec_Tair[0]->FillBoundary(geom[0].periodicity());
275 vec_cloud[0]->FillBoundary(geom[0].periodicity());
282 vec_rain[0]->FillBoundary(geom[0].periodicity());
289 vec_srflx[0]->FillBoundary(geom[0].periodicity());
void PackSurfaceState(amrex::Vector< amrex::MultiFab * > &state, amrex::Real time)
Extracts SST from the 3D conservative state for the atmospheric driver.
amrex::Real last_plot_file_time
Simulation time when we last output a plotfile.
amrex::Vector< amrex::MultiFab * > cons_new
multilevel data container for current step's scalar data: temperature, salinity, passive tracer
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_vwind
Wind in the v direction, defined at rho-points.
int history_count
Counter for which time index we are writing to in the netcdf history file.
amrex::Real stop_time
Time to stop.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_rain
precipitation rate [kg/m^2/s]
amrex::Real EvolveOneStep(amrex::Real time, amrex::Real dt_request)
std::array< bool, AtmosState::NumTypes > driver_atmos_state_from_driver
provenance flags for driver-supplied atmospheric forcing lanes
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_uwind
Wind in the u direction, defined at rho-points.
amrex::Real check_int_time
Checkpoint output interval in seconds.
amrex::Real plot_int_time
Plotfile output interval in seconds.
void post_timestep(int nstep, amrex::Real time, amrex::Real dt_lev)
Called after every level 0 timestep.
int last_check_file_step
Step when we last output a checkpoint file.
void ComputeDt()
a wrapper for estTimeStep()
int plot_int
Plotfile output interval in iterations.
amrex::Vector< int > istep
which step?
void WriteCheckpointFile()
write checkpoint file to disk
amrex::Vector< amrex::Real > t_new
new time at each level
void ApplyAtmosphericStates(const amrex::Vector< amrex::MultiFab * > &states, amrex::Real time)
Receives atmospheric states from the driver and applies unit conversions.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_longwave_down
Downward longwave radiation.
void timeStep(int lev, amrex::Real time, int iteration)
advance a level by dt, includes a recursive call for finer levels
void timeStepML(amrex::Real time, int iteration)
advance all levels by dt, loops over finer levels
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_cloud
cloud cover fraction [0-1], defined at rho-points
int check_int
Checkpoint output interval in iterations.
void WritePlotFile(int istep)
main driver for writing AMReX plotfiles
int last_plot_file_step
Step when we last output a plotfile.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_srflx
Shortwave radiation flux [W/m²], defined at rho-points.
amrex::Real last_check_file_time
Simulation time when we last output a checkpoint file.
amrex::Vector< amrex::Real > dt
time step at each level
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_Pair
Air pressure [mb], defined at rho-points.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_qair
Specific humidity [kg/kg], defined at rho-points.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_Tair
Air temperature [°C], defined at rho-points.
@ Pair
atmospheric pressure [Pa from driver, mb in REMORA]
@ Vwind
10-m meridional wind [m/s]
@ Qair
specific humidity [kg/kg]
@ SWrad
downward shortwave radiation [W/m^2]
@ LWrad
downward longwave radiation [W/m^2]
@ Uwind
10-m zonal wind [m/s]
@ Rain
precipitation rate [kg/m^2/s]
@ Cloud
cloud fraction [0-1]
@ Tair
air temperature [K from driver, degC in REMORA]