Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions components/omega/configs/Default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,19 @@ Omega:
Contents:
- State
- Base
# Forcing is the external forcing in standalone mode.
# It contains the surface stress, surface fluxes
# and the surface restoring target files (if appl.).
Forcing:
UsePointerFile: false
Filename: forcing.nc
Comment thread
cbegeman marked this conversation as resolved.
Mode: read
Precision: double
Freq: 1
FreqUnits: Never
UseStartEnd: false
Contents:
- Forcing
# Restarts are used to initialize for all job submissions after the very
# first startup job. We use UseStartEnd with a start time just after the
# simulation start time so that omega does not attempt to use a restart
Expand Down
30 changes: 30 additions & 0 deletions components/omega/src/ocn/Forcing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "Forcing.h"
#include "Field.h"
#include "IOStream.h"
#include "Logging.h"
#include "Pacer.h"

Expand Down Expand Up @@ -58,6 +59,7 @@ Forcing *Forcing::create(const std::string &Name, const HorzMesh *Mesh,
}

// Initialize the default forcing instance and read configuration.
// Reads the forcing fields from streams at startup (for now).
void Forcing::init() {
if (DefaultForcing != nullptr) {
return;
Expand All @@ -78,6 +80,10 @@ void Forcing::init() {

Config *OmegaConfig = Config::getOmegaConfig();
DefaultForcing->readConfigOptions(OmegaConfig);
// for now, forcing fields are read at start-up only.
// to be extended to include switch from standalone to coupled.
// to be moved to a Forcing->prepareForStep(SimTime) method later.
DefaultForcing->readStreamIntoArrays();
}

// Return the default forcing instance.
Expand Down Expand Up @@ -159,4 +165,28 @@ I4 Forcing::exchangeHalo() const {
return Err;
}

// Read forcing fields from input stream.
// To be extended with time indexing later.
void Forcing::readStreamIntoArrays() {
Error Err;

std::string StreamName = "Forcing";

// Attempt to read stream; if unavailable, log and fall back to zero forcing.
Comment thread
alicebarthel marked this conversation as resolved.
Err = IOStream::read(StreamName);
if (Err.isFail()) {
LOG_INFO("Forcing: Error while reading {} stream, using zero forcing",
StreamName);
deepCopy(SfcStressForcing.ZonalStressCell, 0._Real);
deepCopy(SfcStressForcing.MeridStressCell, 0._Real);
}

I4 HaloErr = exchangeHalo();
if (HaloErr != 0) {
ABORT_ERROR("Forcing: Error exchanging halo for startup forcing fields");
}

computeAll();
}

} // namespace OMEGA
3 changes: 3 additions & 0 deletions components/omega/src/ocn/Forcing.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ class Forcing {
/// Unregister surface stress fields from IO streams
void unregisterFields() const;

/// Read forcing fields from input stream at startup
void readStreamIntoArrays();

/// Compute all forcing variables
void computeAll() const;

Expand Down
4 changes: 2 additions & 2 deletions components/omega/src/ocn/OceanRun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ int ocnRun(TimeInstant &CurrTime ///< [inout] current sim time
// track step count
++IStep;

// call forcing routines, anything needed pre-timestep
DefForcing->computeAll();
// placeholder: call needed pre-timestep compute here
// (e.g. forcing routine)

// do forward time step
// first call to doStep can sometimes take very long
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ SfcStressForcingVars::SfcStressForcingVars(const std::string &Suffix,
void SfcStressForcingVars::registerFields(
const std::string &MeshName // name of horizontal mesh
) const {

const Real FillValue = -9.99e30;
int NDims = 1;
int NDims = 1;
std::vector<std::string> DimNames(NDims);
std::string DimSuffix;
if (MeshName == "Default") {
Expand Down
4 changes: 4 additions & 0 deletions components/omega/test/infra/IOStreamTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ void initIOStreamTest(Clock *&ModelClock // Model clock
// Initialize Tracers
Tracers::init();

// IOStream::validateAll() depends on Forcing::init() so Forcing fields
// are registered before stream validation.
Forcing::init();

// Initialize Aux State
AuxiliaryState::init();

Expand Down
23 changes: 17 additions & 6 deletions components/omega/test/ocn/ForcingTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ constexpr char DefaultMeshFile[] = "OmegaSphereMesh.nc";
using TestSetup = TestSetupSphere;
#endif

Forcing *TestForcing = nullptr;

int testSfcStressForcingVars(Real RTol) {
int Err = 0;
TestSetup Setup;
Expand Down Expand Up @@ -150,7 +152,16 @@ int initForcingTest(const std::string &MeshFile) {
}

HorzMesh::init(ModelClock);
Forcing::init();

const HorzMesh *DefMesh = HorzMesh::getDefault();
Halo *DefHalo = Halo::getDefault();
TestForcing = Forcing::create("Default", DefMesh, DefHalo);
if (TestForcing == nullptr) {
ABORT_ERROR("ForcingTest: failed creating default forcing instance");
}

Config *OmegaConfig = Config::getOmegaConfig();
TestForcing->readConfigOptions(OmegaConfig);

return 0;
}
Expand All @@ -168,12 +179,12 @@ void finalizeForcingTest() {
}

int testForcingInitAndConfig() {
// Verify Forcing::init consumes Omega.SfcStress config and maps InterpType.
// Verify forcing setup consumes Omega.SfcStress config and maps InterpType.
int Err = 0;

Forcing *DefForcing = Forcing::getDefault();
Forcing *DefForcing = TestForcing;
if (DefForcing == nullptr) {
LOG_ERROR("ForcingTest: default forcing instance is null");
LOG_ERROR("ForcingTest: test forcing instance is null");
return 1;
}

Expand Down Expand Up @@ -203,7 +214,7 @@ int testForcingInitAndConfig() {
}

if (DefForcing->SfcStressForcing.InterpChoice != ExpectedChoice) {
LOG_ERROR("ForcingTest: InterpChoice mismatch after Forcing::init");
LOG_ERROR("ForcingTest: InterpChoice mismatch after forcing setup");
Err++;
}

Expand All @@ -220,7 +231,7 @@ int testForcingComputeAll() {
int Err = 0;

const HorzMesh *Mesh = HorzMesh::getDefault();
Forcing *DefForcing = Forcing::getDefault();
Forcing *DefForcing = TestForcing;
if (Mesh == nullptr || DefForcing == nullptr) {
LOG_ERROR("ForcingTest: missing mesh or forcing for compute test");
return 1;
Expand Down
6 changes: 6 additions & 0 deletions components/omega/test/ocn/StateTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "Eos.h"
#include "Error.h"
#include "Field.h"
#include "Forcing.h"
#include "Halo.h"
#include "HorzMesh.h"
#include "IO.h"
Expand Down Expand Up @@ -91,6 +92,10 @@ void initStateTest() {
// Initialize tracers
Tracers::init();

// IOStream::validateAll() depends on Forcing::init() so Forcing fields
// are registered before stream validation.
Forcing::init();

// Initialize Aux State variables
AuxiliaryState::init();

Expand Down Expand Up @@ -414,6 +419,7 @@ int main(int argc, char *argv[]) {
// Finalize Omega objects
OceanState::clear();
Tracers::clear();
Forcing::clear();
AuxiliaryState::clear();
PressureGrad::clear();
VertMix::destroyInstance();
Expand Down
Loading