Program Listing for File PrognosticData.cpp¶
↰ Return to documentation for file (core/src/PrognosticData.cpp)
#include "include/PrognosticData.hpp"
#include "include/FieldAdvection.hpp"
#include "include/Finalizer.hpp"
#include "include/NextsimModule.hpp"
#include "include/gridNames.hpp"
namespace Nextsim {
static const std::string checkFieldsKey = "debug.check_fields";
static const std::string checkFieldsFastKey = "debug.check_fields_fast";
static const std::map<int, std::string> keyMap
= { { PrognosticData::CHECKFIELDS_KEY, checkFieldsKey },
{ PrognosticData::CHECKFIELDSFAST_KEY, checkFieldsFastKey } };
static constexpr bool checkFieldsDefault = false;
static constexpr bool checkFieldsFastDefault = true;
PrognosticData::PrognosticData()
: m_dt(1)
, hiceAccessor(getStore(), RW, ModelArray::AdvectionType, std::pair(0.0, 50.0))
, ciceAccessor(getStore(), RW, ModelArray::AdvectionType, std::pair(0.0, 1.0))
, damageAccessor(getStore(), RW, ModelArray::AdvectionType, std::pair(0.0, 1.0))
, hsnowAccessor(getStore(), RW, ModelArray::AdvectionType, std::pair(0.0, 10.0))
, pAtmBdy(nullptr)
, pOcnBdy(nullptr)
, pDynamics(nullptr)
, pColumnPhysics(nullptr)
{
}
void PrognosticData::configure()
{
// Register finalizers before calling configure.
Finalizer::registerUnique(Module::finalize<IAtmosphereBoundary>);
Finalizer::registerUnique(Module::finalize<IOceanBoundary>);
Finalizer::registerUnique(Module::finalize<IDynamics>);
pAtmBdy = &Module::getImplementation<IAtmosphereBoundary>();
tryConfigure(pAtmBdy);
pOcnBdy = &Module::getImplementation<IOceanBoundary>();
tryConfigure(pOcnBdy);
pDynamics = &Module::getImplementation<IDynamics>();
tryConfigure(pDynamics);
pColumnPhysics = &Module::getImplementation<IColumnPhysics>();
tryConfigure(pColumnPhysics);
checkAll() = Configured::getConfiguration(keyMap.at(CHECKFIELDS_KEY), checkFieldsDefault);
checkFast
= Configured::getConfiguration(keyMap.at(CHECKFIELDSFAST_KEY), checkFieldsFastDefault);
if (checkAll()) {
for (const auto& field : ModelArrayAccessorBase<RO>::getAll(getStore())) {
addChecks({ { field.first, field.second } });
}
} else if (checkFast) {
addChecks({
{ "thickness", hiceAccessor },
{ "concentration", ciceAccessor },
});
}
}
// Copies an HField from a source ModelArray that is either an HField or a DGField.
void copyMeanComponent(const ModelArray& source, ModelArray& sink)
{
if (source.nComponents() > 1) {
sink.setData(source.data().col(0));
} else {
sink = source;
}
}
void PrognosticData::setData(const ModelState::DataMap& ms)
{
AdvectedField& hice = hiceAccessor.getHostRW();
AdvectedField& cice = ciceAccessor.getHostRW();
AdvectedField& hsnow = hsnowAccessor.getHostRW();
AdvectedField& damage = damageAccessor.getHostRW();
if (ms.count(maskName)) {
setOceanMask(ms.at(maskName));
} else {
noLandMask();
}
// Copy the full DG data
hice = 0;
cice = 0;
hsnow = 0;
damage = 0;
hice = ms.at(hiceName);
cice = ms.at(ciceName);
hsnow = ms.at(hsnowName);
// Damage is an optional field, and defaults to 1 in the mean field, 0 in higher components
// if absent.
if (ms.count(damageName) > 0) {
damage = ms.at(damageName);
} else {
damage.component(0) = 1.;
}
pAtmBdy->setData(ms);
pOcnBdy->setData(ms);
pDynamics->setData(ms);
pColumnPhysics->setData(ms);
}
void PrognosticData::update(const TimestepTime& tst)
{
// Prepare everything
pOcnBdy->updateBefore(tst);
pAtmBdy->update(tst);
pDynamics->prepareAdvection();
// Take the updated values of the true ice and snow thicknesses, and reset hice0 and hsnow0
// ColumnPhysics updates its own fields during update
pColumnPhysics->update(tst);
// Dynamics
pDynamics->update(tst);
// Update the ocean after ice growth (or send fields to the coupler)
pOcnBdy->updateAfter(tst);
try {
checkFields();
} catch (const std::exception& e) {
throw std::runtime_error("PrognosticData::update: " + std::string(e.what()));
}
}
// Gets the diagnostic data from all subcomponents
ModelState PrognosticData::getStateDiagnostic() const
{
ModelState state = getStatePrognostic();
// Get the prognostic data from the dynamics, including the full dynamics state
state.merge(pDynamics->getStateDiagnostic());
state.merge(pColumnPhysics->getStateDiagnostic());
state.merge(pAtmBdy->getStateDiagnostic());
state.merge(pOcnBdy->getStateDiagnostic());
return state;
}
// Gets the prognostic data from all subcomponents
ModelState PrognosticData::getStatePrognostic() const
{
ModelState state = { {
{ maskName, ModelArray(oceanMask()) }, // make a copy
{ hiceName, hiceAccessor.getHostRO() },
{ ciceName, ciceAccessor.getHostRO() },
{ hsnowName, hsnowAccessor.getHostRO() },
},
ModelComponent::getConfiguration() };
// Get the prognostic data from the dynamics, including the full dynamics state
state.merge(pDynamics->getStatePrognostic());
state.merge(pColumnPhysics->getStatePrognostic());
state.merge(pAtmBdy->getStatePrognostic());
state.merge(pOcnBdy->getStatePrognostic());
return state;
}
PrognosticData::HelpMap& PrognosticData::getHelpText(HelpMap& map, bool getAll)
{
map["debug"]
= { { checkFieldsKey, ConfigType::BOOLEAN, { "true", "false" },
ConfigurationHelp::toString(checkFieldsDefault), "",
"Set to true to check if all variables in the ModelArrayStore fall within a "
"reasonable physical range." },
{ checkFieldsFastKey, ConfigType::BOOLEAN, { "true", "false" },
ConfigurationHelp::toString(checkFieldsFastDefault), "",
"Set to true to check if thickness, concentration, and velocities fall within a "
"reasonable physical range." } };
return map;
}
PrognosticData::HelpMap& PrognosticData::getHelpRecursive(HelpMap& map, bool getAll)
{
Module::getHelpRecursive<IAtmosphereBoundary>(map, getAll);
Module::getHelpRecursive<IOceanBoundary>(map, getAll);
Module::getHelpRecursive<IDynamics>(map, getAll);
Module::getHelpRecursive<IColumnPhysics>(map, getAll);
getHelpText(map, getAll);
return map;
}
} /* namespace Nextsim */