Skip to content

Commit

Permalink
Adjust Schism formulation and test to exploit new NetCDF mesh data pr…
Browse files Browse the repository at this point in the history
…ovider
  • Loading branch information
PhilMiller committed Sep 18, 2024
1 parent 5d2ed33 commit 1b29181
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 22 deletions.
8 changes: 6 additions & 2 deletions include/realizations/coastal/SchismFormulation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,18 @@ class SchismFormulation final : public CoastalFormulation
std::unique_ptr<models::bmi::Bmi_Fortran_Adapter> bmi_;

enum ForcingSelector { METEO, OFFSHORE, INFLOW };
static std::map<std::string, ForcingSelector> expected_input_variables_;
struct InputMapping { ForcingSelector selector; std::string name; };
static std::map<std::string, InputMapping> expected_input_variables_;
std::map<std::string, std::string> input_variable_units_;
std::map<std::string, std::string> input_variable_type_;
std::map<std::string, size_t> input_variable_count_;

static std::vector<std::string> exported_output_variable_names_;
std::map<std::string, std::string> output_variable_units_;
std::map<std::string, std::string> output_variable_type_;
std::map<std::string, size_t> output_variable_count_;

std::chrono::time_point<std::chrono::steady_clock> current_time_;
std::chrono::time_point<std::chrono::system_clock> current_time_;
std::chrono::seconds time_step_length_;

// TODO: Some of these maybe should be members of
Expand Down
49 changes: 33 additions & 16 deletions src/realizations/coastal/SchismFormulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,26 @@

const static auto s_schism_registration_function = "register_bmi";

std::map<std::string, SchismFormulation::ForcingSelector> SchismFormulation::expected_input_variables_ =
std::map<std::string, SchismFormulation::InputMapping> SchismFormulation::expected_input_variables_ =
{
/* Meteorological Forcings */
// RAINRATE - precipitation
{"RAINRATE", SchismFormulation::METEO},
{"RAINRATE", { SchismFormulation::METEO, "RAINRATE"}},
// SFCPRS - surface atmospheric pressure
{"SFCPRS", SchismFormulation::METEO},
{"SFCPRS", { SchismFormulation::METEO, "PSFC"}},
// SPFH2m - specific humidity at 2m
{"SPFH2m", SchismFormulation::METEO},
{"SPFH2m", { SchismFormulation::METEO, "Q2D"}},
// TMP2m - temperature at 2m
{"TMP2m", SchismFormulation::METEO},
{"TMP2m", { SchismFormulation::METEO, "T2D"}},
// UU10m, VV10m - wind velocity components at 10m
{"UU10m", SchismFormulation::METEO},
{"VV10m", SchismFormulation::METEO},
{"UU10m", { SchismFormulation::METEO, "U2D"}},
{"VV10m", { SchismFormulation::METEO, "V2D"}},

/* Input Boundary Conditions */
// ETA2_bnd - water surface elevation at the boundaries
{"ETA2_bnd", SchismFormulation::OFFSHORE},
{"ETA2_bnd", { SchismFormulation::OFFSHORE, "ETA2_bnd"}},
// Q_bnd - flows at boundaries
{"Q_bnd", SchismFormulation::INFLOW},
{"Q_bnd", { SchismFormulation::INFLOW, "Q_bnd"}},
};

std::vector<std::string> SchismFormulation::exported_output_variable_names_ =
Expand Down Expand Up @@ -57,7 +57,7 @@ SchismFormulation::SchismFormulation(
, init_config_path
, /* model_time_step_fixed = */ true
, s_schism_registration_function
, MPI_COMM_WORLD
, MPI_COMM_SELF
);
}

Expand All @@ -77,6 +77,20 @@ void SchismFormulation::initialize()
input_variable_count_[name] = mesh_size(name);
}

auto const& output_vars = bmi_->GetOutputVarNames();

for (auto const& name : output_vars) {
//if (expected_output_variables_.find(name) == expected_output_variables_.end()) {
// throw std::runtime_error("SCHISM instance requests unexpected output variable '" + name + "'");
//}

output_variable_units_[name] = bmi_->GetVarUnits(name);
output_variable_type_[name] = bmi_->GetVarType(name);
output_variable_count_[name] = mesh_size(name);
}

time_step_length_ = std::chrono::seconds((long long)bmi_->GetTimeStep());

set_inputs();
}

Expand All @@ -92,9 +106,11 @@ void SchismFormulation::finalize()
void SchismFormulation::set_inputs()
{
for (auto var : expected_input_variables_) {
auto& name = var.first;
auto selector = var.second;
auto points = MeshPointsSelector{name, current_time_, time_step_length_, input_variable_units_[name], all_points};
auto const& name = var.first;
auto const& mapping = var.second;
auto selector = mapping.selector;
auto const& source_name = mapping.name;
auto points = MeshPointsSelector{source_name, current_time_, time_step_length_, input_variable_units_[name], all_points};

ProviderType* provider = [this, selector](){
switch(selector) {
Expand All @@ -104,13 +120,15 @@ void SchismFormulation::set_inputs()
default: throw std::runtime_error("Unknown SCHISM provider selector type");
}
}();
std::vector<double> values = provider->get_values(points);
bmi_->SetValue(name, values.data());
std::vector<double> buffer(mesh_size(name));
provider->get_values(points, buffer);
bmi_->SetValue(name, buffer.data());
}
}

void SchismFormulation::update()
{
current_time_ += time_step_length_;
set_inputs();
bmi_->Update();
}
Expand Down Expand Up @@ -166,5 +184,4 @@ size_t SchismFormulation::mesh_size(std::string const& variable_name)
return nbytes / itemsize;
}


#endif // NGEN_WITH_BMI_FORTRAN && NGEN_WITH_MPI
72 changes: 68 additions & 4 deletions test/coastal/SchismFormulation_Test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
#include <utilities/parallel_utils.h>

#include "realizations/coastal/SchismFormulation.hpp"
#include <limits>
#include <iostream>
#include <NetCDFMeshPointsDataProvider.hpp>

const static std::string library_path = "/Users/phil/Code/noaa/BUILD/bmischism_2024-08-19-ngen/libtestbmifortranmodel.dylib";
const static std::string init_config_path = "/Users/phil/Code/noaa/SCHISM_Lake_Champlain_BMI_test/namelist.input";
const static std::string met_forcing_netcdf_path = "/Users/phil/Code/noaa/NextGen_Forcings_Engine_SCHISM_Lake_Champlain_2015120100.nc";

#if 0
struct Schism_Formulation_IT : public ::testing::Test
Expand Down Expand Up @@ -54,13 +58,13 @@ struct MockProvider : data_access::DataProvider<double, MeshPointsSelector>
size_t get_ts_index_for_time(const time_t &epoch_time) const override { return 1; }

data_type get_value(const selection_type& selector, data_access::ReSampleMethod m) override { return data[0]; }
std::vector<double> get_values(const selection_type& selector, data_access::ReSampleMethod) override
std::vector<data_type> get_values(const selection_type& selector, data_access::ReSampleMethod m) override { throw ""; return data; }
void get_values(const selection_type& selector, boost::span<double> out_data) override
{
auto default_value = input_variables_defaults[selector.variable_name];
for (auto& val : data) {
for (auto& val : out_data) {
val = default_value;
}
return data;
}
};

Expand All @@ -70,17 +74,77 @@ int main(int argc, char **argv)
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);

auto provider = std::make_shared<MockProvider>();

std::tm start_time_tm{};
start_time_tm.tm_year = 2015 - 1900;
start_time_tm.tm_mon = 12 - 1;
start_time_tm.tm_mday = 1;
auto start_time_t = std::mktime(&start_time_tm);

std::tm stop_time_tm{};
stop_time_tm.tm_year = 2015 - 1900;
stop_time_tm.tm_mon = 12 - 1;
stop_time_tm.tm_mday = 2;
auto stop_time_t = std::mktime(&stop_time_tm);

auto netcdf_met_provider = std::make_shared<data_access::NetCDFMeshPointsDataProvider>(met_forcing_netcdf_path,
std::chrono::system_clock::from_time_t(start_time_t),
std::chrono::system_clock::from_time_t(stop_time_t));
auto schism = std::make_unique<SchismFormulation>(/*id=*/ "test_schism_formulation",
library_path,
init_config_path,
provider,
netcdf_met_provider,
provider,
provider
);

schism->initialize();

for (int i = 0; i < 3; ++i)
schism->update();

using namespace std::chrono_literals;

auto report = [](std::vector<double> const& data, std::string name) {
double min = 10e6, max = -10e6;
for (int i = 0; i < data.size(); ++i) {
double val = data[i];
if (std::isnan(val)) {
std::cout << "Nan found at " << i << std::endl;
break;
}

min = std::min(val, min);
max = std::max(val, max);
}
std::cout << name << " ranges from " << min << " to " << max << std::endl;
};

std::vector<double> bedlevel(278784, std::numeric_limits<double>::quiet_NaN());
MeshPointsSelector bedlevel_selector{"BEDLEVEL", std::chrono::system_clock::now(), 3600s, "m", all_points};
schism->get_values(bedlevel_selector, bedlevel);
report(bedlevel, "BEDLEVEL");

std::vector<double> eta2(278784, std::numeric_limits<double>::quiet_NaN());
MeshPointsSelector eta2_selector{"ETA2", std::chrono::system_clock::now(), 3600s, "m", all_points};
schism->get_values(eta2_selector, eta2);
report(eta2, "ETA2");

std::vector<double> vx(278784, std::numeric_limits<double>::quiet_NaN());
MeshPointsSelector vx_selector{"VX", std::chrono::system_clock::now(), 3600s, "m s-1", all_points};
schism->get_values(vx_selector, vx);
report(vx, "VX");

std::vector<double> vy(278784, std::numeric_limits<double>::quiet_NaN());
MeshPointsSelector vy_selector{"VY", std::chrono::system_clock::now(), 3600s, "m s-1", all_points};
schism->get_values(vy_selector, vy);
report(vy, "VY");

schism->update();
schism->get_values(vx_selector, vx);
schism->get_values(vy_selector, vy);
report(vx, "VX");
report(vy, "VY");

schism->finalize();
MPI_Finalize();
Expand Down

0 comments on commit 1b29181

Please sign in to comment.