Skip to content

Commit b579f34

Browse files
authored
Merge pull request #61 from nextsimdg/issue60_physics_module
Issue60 Physics Module
2 parents 5bc2e3a + 9c70b14 commit b579f34

File tree

9 files changed

+178
-76
lines changed

9 files changed

+178
-76
lines changed

core/src/include/ElementData.hpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
#ifndef SRC_INCLUDE_ELEMENTDATA_HPP
88
#define SRC_INCLUDE_ELEMENTDATA_HPP
99

10+
#include "Configured.hpp"
1011
#include "ExternalData.hpp"
12+
#include "ModuleLoader.hpp"
1113
#include "PrognosticData.hpp"
14+
#include "include/IPhysics1d.hpp"
1215
#include "include/PhysicsData.hpp"
1316

1417
namespace Nextsim {
@@ -22,31 +25,44 @@ class UnusedData : public BaseElementData {
2225
* @brief The class which holds all the data for a single element of the model.
2326
*
2427
* @details Inherits from PrognosticData, PhysicsData and ExternalData. The
25-
* physics implementation is provided as a template argument.
28+
* physics implementation is provided as a per-instance module.
2629
*/
27-
template <class Phys>
2830
class ElementData : public PrognosticData,
2931
public PhysicsData,
3032
public ExternalData,
31-
public Phys,
3233
public UnusedData,
33-
public Configured<ElementData<Phys>> {
34+
public Configured<ElementData> {
3435
public:
35-
ElementData() = default;
36+
ElementData()
37+
{
38+
m_physicsImplData = std::move(ModuleLoader::getLoader().getInstance<IPhysics1d>());
39+
}
3640
~ElementData() = default;
3741

3842
using PrognosticData::operator=;
3943
using PhysicsData::operator=;
4044
using ExternalData::operator=;
41-
using Phys::operator=;
4245

4346
//! Configures the PrognosticData and physics implementation aspects of the
4447
//! object.
4548
void configure() override
4649
{
4750
PrognosticData::configure();
48-
Phys::configure();
51+
Nextsim::tryConfigure(&ModuleLoader::getLoader().getImplementation<IPhysics1d>());
52+
}
53+
54+
void updateDerivedData(const PrognosticData& prog, const ExternalData& exter, PhysicsData& phys)
55+
{
56+
m_physicsImplData->updateDerivedData(prog, exter, phys);
4957
}
58+
59+
void calculate(const PrognosticData& prog, const ExternalData& exter, PhysicsData& phys)
60+
{
61+
m_physicsImplData->calculate(prog, exter, phys);
62+
}
63+
64+
private:
65+
std::unique_ptr<IPhysics1d> m_physicsImplData;
5066
};
5167

5268
} /* namespace Nextsim */

core/test/CMakeLists.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,23 @@ add_executable(testScopedTimer
8888
target_link_libraries(testScopedTimer PRIVATE Catch2::Catch2)
8989
target_include_directories(testScopedTimer PRIVATE "${SRC_DIR}")
9090

91+
set(PhysicsDir "${PROJECT_SOURCE_DIR}/physics/src")
92+
set(PhysicsModulesDir "${PhysicsDir}/modules")
93+
add_executable(testElementData
94+
"ElementData_test.cpp"
95+
"${SRC_DIR}/ElementData.cpp"
96+
"${SRC_DIR}/ModuleLoader.cpp"
97+
"${SRC_DIR}/Configurator.cpp"
98+
"${SRC_DIR}/ConfiguredModule.cpp"
99+
"${SRC_DIR}/PrognosticData.cpp"
100+
"${PhysicsModulesDir}/NextsimPhysics.cpp"
101+
"${PhysicsModulesDir}/SMUIceAlbedo.cpp"
102+
"${PhysicsModulesDir}/CCSMIceAlbedo.cpp"
103+
"${PhysicsModulesDir}/SMU2IceAlbedo.cpp"
104+
"${PhysicsModulesDir}/BasicIceOceanHeatFlux.cpp"
105+
"${PhysicsModulesDir}/HiblerConcentration.cpp"
106+
"${PhysicsModulesDir}/ThermoIce0.cpp"
107+
)
91108

109+
target_include_directories(testElementData PRIVATE "${ModuleLoaderIppTargetDirectory}" "${SRC_DIR}" "${PhysicsDir}" "${PhysicsModulesDir}")
110+
target_link_libraries(testElementData PRIVATE "${Boost_LIBRARIES}" Catch2::Catch2)

core/test/ElementData_test.cpp

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,77 @@
44
* @author Tim Spain <[email protected]>
55
*/
66

7-
#include <ElementData.hpp>
7+
#define CATCH_CONFIG_MAIN
8+
#include <catch2/catch.hpp>
9+
#include <sstream>
10+
11+
#include "include/ConfiguredModule.hpp"
12+
#include "include/ElementData.hpp"
13+
#include "include/IIceAlbedo.hpp"
14+
#include "include/ModuleLoader.hpp"
15+
#include "include/NextsimPhysics.hpp"
816

917
namespace Nextsim {
1018

19+
TEST_CASE("Physics test using NextsimPhysics", "[ElementData]")
20+
{
21+
// Largely copied from the "Melting conditions" test of NextsimPhysics
22+
Configurator::clear();
23+
std::stringstream config;
24+
config << "[Modules]" << std::endl;
25+
config << "Nextsim::IFreezingPoint = Nextsim::UnescoFreezing" << std::endl;
26+
config << "Nextsim::IIceAlbedo = Nextsim::CCSMIceAlbedo" << std::endl;
27+
config << "Nextsim::IPhysics1d = Nextsim::NextsimPhysics" << std::endl;
28+
config << std::endl;
29+
config << "[CCSMIceAlbedo]" << std::endl;
30+
config << "iceAlbedo = 0.63" << std::endl;
31+
config << "snowAlbedo = 0.88" << std::endl;
32+
33+
std::unique_ptr<std::istream> pcstream(new std::stringstream(config.str()));
34+
Configurator::addStream(std::move(pcstream));
35+
36+
double tair = 3; //˚C
37+
double tdew = 2; //˚C
38+
double pair = 100000; // Pa, slightly low pressure
39+
double sst = -1; //˚C
40+
double sss = 32; // PSU
41+
std::array<double, N_ICE_TEMPERATURES> tice = { -1., -1., -1. }; //˚C
42+
double hice = 0.1; // m
43+
double cice = 0.5;
44+
double hsnow = 0.01; // m
45+
double dml = 10.; // m
46+
47+
ModuleLoader::getLoader().setAllDefaults();
48+
ConfiguredModule::parseConfigurator();
49+
tryConfigure(ModuleLoader::getLoader().getImplementation<IIceAlbedo>());
50+
51+
ElementData data;
52+
data.configure(); // Configure with the UNESCO freezing point
53+
54+
data = PrognosticData::generate(hice, cice, sst, sss, hsnow, tice);
55+
data.setTimestep(600.); // s. Very long TS to get below freezing
56+
57+
data.airTemperature() = tair;
58+
data.dewPoint2m() = tdew;
59+
data.airPressure() = pair;
60+
data.mixedLayerDepth() = dml;
61+
data.incomingLongwave() = 330;
62+
data.incomingShortwave() = 50;
63+
data.snowfall() = 0;
64+
65+
data.windSpeed() = 5;
66+
67+
data.updateDerivedData(data, data, data);
68+
REQUIRE(1.26488 == Approx(data.airDensity()).epsilon(1e-4));
69+
REQUIRE(0.00441973 == Approx(data.specificHumidityAir()).epsilon(1e-4));
70+
REQUIRE(0.0035214 == Approx(data.specificHumidityIce()).epsilon(1e-4));
71+
REQUIRE(1012.86 == Approx(data.heatCapacityWetAir()).epsilon(1e-4));
72+
73+
data.calculate(data, data, data);
74+
75+
REQUIRE(0.12846 == Approx(data.updatedIceTrueThickness()).epsilon(1e-4));
76+
REQUIRE(0.01957732 == Approx(data.updatedSnowTrueThickness()).epsilon(1e-4));
77+
REQUIRE(0.368269 == Approx(data.updatedIceConcentration()).epsilon(1e-4));
78+
REQUIRE(0.0 == Approx(data.updatedIceSurfaceTemperature()).epsilon(1e-4));
79+
}
1180
} /* namespace Nextsim */

physics/src/Physics1dBase.cpp

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,9 @@
88

99
namespace Nextsim {
1010

11-
template <class Phys> void Physics1dBase::physics1d(ElementData<Phys>& data)
11+
void Physics1dBase::physics1d(ElementData& data)
1212
{
13-
Phys::updateDerivedData(data);
14-
Phys::massFluxOpenWater(data);
15-
Phys::momentumFluxOpenWater(data);
16-
Phys::heatFluxOpenWater(data);
17-
18-
Phys::massFluxIceAtmosphere(data);
19-
// Ice momentum fluxes are handled by the dynamics
20-
Phys::heatFluxIceAtmosphere(data);
21-
22-
Phys::massFluxIceOcean(data);
23-
// Ice momentum fluxes are handled by the dynamics
24-
Phys::heatFluxIceOcean(data);
13+
data.updateDerivedData(data, data, data);
14+
data.calculate(data, data, data);
2515
}
2616
} /* namespace Nextsim */

physics/src/include/Physics1dBase.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class Physics1dBase {
2424
virtual ~Physics1dBase() = default;
2525

2626
//! Performs the one dimensional physics calculations.
27-
template <class Phys> void physics1d(ElementData<Phys>&);
27+
void physics1d(ElementData&);
2828
};
2929

3030
} /* namespace Nextsim */

physics/src/modules/NextsimPhysics.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,12 +172,12 @@ void NextsimPhysics::heatFluxIceAtmosphere(
172172
m_Qlhi = m_subl * latentHeatIce(prog.iceTemperatures()[0]);
173173
double dmdot_dT = dragIce_t * phys.airDensity() * phys.windSpeed()
174174
* specHumIce.dq_dT(prog.iceTemperatures()[0], exter.airPressure());
175-
m_dQ_dT += latentHeatIce(prog.iceTemperatures()[0]) * dmdot_dT;
175+
double dQlh_dT = latentHeatIce(prog.iceTemperatures()[0]) * dmdot_dT;
176176

177177
// Sensible heat flux
178178
m_Qshi = dragIce_t * phys.airDensity() * phys.heatCapacityWetAir() * phys.windSpeed()
179179
* (prog.iceTemperatures()[0] - exter.airTemperature());
180-
m_dQ_dT += dragIce_t * phys.airDensity() * phys.heatCapacityWetAir() * phys.windSpeed();
180+
double dQsh_dT = dragIce_t * phys.airDensity() * phys.heatCapacityWetAir() * phys.windSpeed();
181181

182182
// Shortwave flux
183183
double albedoValue = iIceAlbedoImpl->albedo(prog.iceTemperatures()[0],
@@ -186,11 +186,13 @@ void NextsimPhysics::heatFluxIceAtmosphere(
186186

187187
// Longwave flux
188188
m_Qlwi = stefanBoltzmannLaw(prog.iceTemperatures()[0]) - exter.incomingLongwave();
189-
m_dQ_dT
190-
+= 4 / kelvin(prog.iceTemperatures()[0]) * stefanBoltzmannLaw(prog.iceTemperatures()[0]);
189+
double dQlw_dT
190+
= 4 / kelvin(prog.iceTemperatures()[0]) * stefanBoltzmannLaw(prog.iceTemperatures()[0]);
191191

192192
// Total flux
193193
m_Qia = m_Qlhi + m_Qshi + m_Qlwi + m_Qswi;
194+
// Overall temperature dependence of flux
195+
m_dQ_dT = dQlh_dT + dQsh_dT + dQlw_dT;
194196
}
195197

196198
void NextsimPhysics::massFluxIceOcean(

physics/src/modules/include/NextsimPhysics.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class IThermodynamics;
2525
class IIceOceanHeatFlux;
2626
class IConcentrationModel;
2727

28-
template <class Phys> class ElementData;
28+
class ElementData;
2929

3030
class NextsimPhysics;
3131

physics/src/modules/modules.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,11 @@
3131
"implementations": [
3232
"Nextsim::ThermoIce0"
3333
]
34+
},
35+
{
36+
"name": "Nextsim::IPhysics1d",
37+
"implementations": [
38+
"Nextsim::NextsimPhysics"
39+
]
3440
}
3541
]

0 commit comments

Comments
 (0)