Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
5b178d3
New IOceanBoundary derived module
einola May 3, 2024
0acbdf8
Put MLD into m_couplingArrays of IOceanBoundary.hpp
einola May 3, 2024
190299c
More details on where the OASIS calls go in OASISCoupledOcean
einola May 7, 2024
1a155c9
Merge remote-tracking branch 'origin/develop' into issue459_oasis_oce…
einola Aug 14, 2024
023b916
Get the MPI communicator to atm and ocean boundary
einola Aug 15, 2024
4f18732
Move as much of OASIS initialisation as I can to its own class
einola Aug 15, 2024
03b555e
Code cleanup
einola Aug 15, 2024
5549c7e
Add a destructor in OASISCoupled.hpp and call it
einola Aug 15, 2024
c227f13
More comments on how the oasis calls should look like
einola Aug 15, 2024
3713ea8
Add some OASIS calls to OASISCoupled.hpp
einola Aug 16, 2024
c9ebce5
Implement OASIS calls
einola Aug 20, 2024
3e51d86
Revert a merge mistake
einola Aug 20, 2024
ab0c304
Add OASIS time
einola Aug 21, 2024
a2e6c05
Clang formatting
einola Aug 21, 2024
3e6ccdc
Use a map for the coupling id
einola Aug 21, 2024
e8d3633
Options for the couplingId code
einola Aug 21, 2024
db21d61
Small bug fix for OASISCoupledOcean::configure
einola Aug 22, 2024
2af34fb
Merge remote-tracking branch 'origin/develop' into issue459_oasis_oce…
einola Aug 23, 2024
b9d2da5
A few comments for the OASIS team
einola Aug 29, 2024
be7905d
Minor cleaning
einola Aug 27, 2024
9411b83
Move common OASIS calls out of OASISCoupled class
einola Sep 9, 2024
f7b404a
Comments where the grid writing should be
einola Sep 9, 2024
058e86a
Move initOasis to ModelMetadata.cpp
einola Sep 9, 2024
7f8c587
Minor cleaning
einola Sep 9, 2024
d266c17
Moving oasis init & get_localcomm
einola Sep 10, 2024
a3877b0
Minor cleaning
einola Sep 10, 2024
10ffd76
Change target_include_directories to PUBLIC
einola Sep 10, 2024
6b2a99f
Revert removing OASIS_CHECK_ERR from get and put calls
einola Sep 10, 2024
133aca2
Add netcdf hooks to the oasis bit of CMakeLists.txt
einola Sep 10, 2024
9275539
Small changes to FindOASIS.cmake
einola Sep 13, 2024
bf7cd78
First steps in implementing a unit test for OASISCoupledOcean
einola Sep 13, 2024
27a72db
Issue #459 : update input and output coupling field labels lists at c…
andreapiacentini Sep 16, 2024
83cdb29
Issue #459 : complete first working version of the unit test for OASI…
andreapiacentini Sep 16, 2024
9dcf27e
Merge branch 'issue669_coupler_fluxes' into issue459_oasis_ocean_coup…
einola Feb 11, 2025
9db81c8
Get the code to compile after merge
einola Feb 12, 2025
1e3eee3
Put actual data in the oasis put calls
einola Feb 12, 2025
28e58b4
CMakeLists.txt formatting
einola Feb 12, 2025
2cac4d5
CMakeLists.txt formatting
einola Feb 12, 2025
d74a741
Minor cleaning
einola Feb 12, 2025
a616c35
Add SSH to the test
einola Feb 13, 2025
a570b63
Appropriate defaults for OASISCoupledOcean.hpp
einola Feb 13, 2025
6ada6ed
Merge branch 'develop' into issue459_oasis_ocean_coupling
einola Feb 13, 2025
88139c2
Merge branch 'issue669_coupler_fluxes' into issue459_oasis_ocean_coup…
einola Feb 13, 2025
a82d3ec
Expanded OASISCoupledOcean_test.cpp and bugfixes
einola Feb 15, 2025
9df3368
Reverse the direction of heatfluxes sent through OASIS
einola Feb 15, 2025
bc835ac
Rename variable for default for exchanging first layer
einola Mar 21, 2025
b086649
Set taux and tauy in IDynamics.hpp
einola Mar 21, 2025
7136ebb
Move definition of dimension0 and 1
einola Mar 21, 2025
761ebba
[issue459] MPI/IO compliant restart filename
andreapiacentini Mar 28, 2025
7bdc523
[issue459] Enable help-config for OASISCoupledOcean
andreapiacentini Mar 28, 2025
edc3758
[issue459] Fix ocean density
andreapiacentini Mar 28, 2025
eae6a08
[issue459] Try to please to the clang format check
andreapiacentini Mar 28, 2025
42c0bd8
Merge branch 'develop' into issue459_oasis_ocean_coupling
einola Apr 25, 2025
f914a45
Merge branch 'develop' into issue459_oasis_ocean_coupling
einola Jun 5, 2025
02416af
Minor fix after merge
einola Jun 5, 2025
bba76aa
Clang-format
einola Jun 6, 2025
7d7e27d
Merge branch 'develop' into issue459_oasis_ocean_coupling
einola Jun 15, 2025
a7aeed1
Merge branch 'develop' into issue459_oasis_ocean_coupling
einola Jul 30, 2025
a62cff7
Merge branch 'issue899_thermo_clean' into issue459_oasis_ocean_coupling
einola Jul 30, 2025
db9e053
Fix CMakeLists.txt formatting
einola Jul 31, 2025
9a3d715
Dockerfile for an image with OASIS installed
einola Aug 1, 2025
afbd83e
Remove netCDF requirements from ENABLE_OASIS case
einola Aug 20, 2025
9733f67
Explicitly allow running OpenMPI as root in dev docker image
einola Aug 21, 2025
d4c2688
Also compile pyoasis when compiling OASIS
einola Aug 21, 2025
7235a79
Install extra python libraries and modify paths in entrypoint.sh
einola Aug 21, 2025
3b0dd20
Search explicitly for all the component libraries of OASIS
einola Aug 21, 2025
9697409
Minor cleaning and comments for FindOASIS.cmake
einola Aug 22, 2025
37b40fe
Merge remote-tracking branch 'origin/develop' into issue459_oasis_oce…
einola Aug 22, 2025
3426158
Update OASISCoupledOcean_test.cpp so that it compiles
einola Aug 25, 2025
8bc61b5
Update CMakeLists.txt for testOASISCoupledOcean
einola Aug 25, 2025
42e7a7d
Merge remote-tracking branch 'origin/develop' into issue459_oasis_oce…
einola Aug 29, 2025
8660e3b
Add FracQsr to exchange fields
einola Sep 1, 2025
cd4848f
Rename the key for sending ice cover to the ocean
einola Sep 1, 2025
1199a01
Reformatting to appease linter
einola Sep 1, 2025
93a5ac3
Missing definition for FracQSWKey
einola Sep 1, 2025
e25f58a
Set fracSWAbs to one in TOPAZOcean
einola Sep 1, 2025
5a1a591
Be more careful with FracQSW
einola Sep 2, 2025
3cd099a
Merge remote-tracking branch 'origin/develop' into issue459_oasis_oce…
einola Sep 2, 2025
3bd14b7
Send mean component of cice to OASIS
einola Sep 5, 2025
4c156a0
Better variable name
einola Sep 5, 2025
7a55edc
Add vector rotation in send and receive calls for OASIS
einola Sep 19, 2025
4d8fdf4
Rotate the ice-ocean stress vectors before sending
einola Sep 23, 2025
e5b72e7
Resize ModelArrays before oasis_get
einola Sep 24, 2025
9d12d5a
Switch the rotation functions
einola Sep 25, 2025
3be6952
Interpolation to and from U/V points
einola Oct 2, 2025
f27b30b
Fix stupid bugs introduced in last commit
einola Oct 2, 2025
6c3a5b4
Minor cleaning
einola Oct 6, 2025
76f4fac
Resize arrays before use
einola Oct 7, 2025
dc681bd
Use HField for everything
einola Oct 8, 2025
ce7e4d2
Debugging output for the coupling code
einola Oct 9, 2025
d5d8650
Remove A->C and C->A grid interpolations
einola Oct 15, 2025
462530d
Merge branch 'develop' into issue459_oasis_ocean_coupling
einola Oct 17, 2025
f19f9bf
Merge branch 'develop' into issue459_oasis_ocean_coupling
einola Nov 5, 2025
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
10 changes: 9 additions & 1 deletion core/src/Model.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*!
* @file Model.cpp
* @date 12 Aug 2021
* @date 09 Sep 2024
* @author Tim Spain <timothy.spain@nersc.no>
* @author Kacper Kornet <kk562@cam.ac.uk>
*/
Expand Down Expand Up @@ -47,6 +47,9 @@ static std::map<int, std::string> modelConfigKeyMap = {
{ Model::MISSINGVALUE_KEY, "model.missing_value" },
{ Model::RESTARTPERIOD_KEY, "model.restart_period" },
{ Model::RESTARTOUTFILE_KEY, "model.restart_file" },
#ifdef USE_OASIS
{ Model::WRITEOASISGRID_KEY, "oasis.write_grid" },
#endif
};

// Merge the configuration from ModelConfig into the Model keyMap.
Expand Down Expand Up @@ -136,6 +139,11 @@ void Model::configure()
// Get the coordinates from the ModelState for persistence
m_etadata.extractCoordinates(initialState);

#ifdef USE_OASIS
const bool writeOasisGrid = Configured::getConfiguration(keyMap.at(WRITEOASISGRID_KEY), false);
m_etadata.initOasis(writeOasisGrid);
#endif

modelStep.setData(pData);
modelStep.setMetadata(m_etadata);
modelStep.setRestartDetails(restartPeriod, finalFileName);
Expand Down
11 changes: 10 additions & 1 deletion core/src/PrognosticData.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
* @file PrognosticData.cpp
*
* @date 1 Jul 2024
* @date 09 Sep 2024
* @author Tim Spain <timothy.spain@nersc.no>
* @author Einar Ólason <einar.olason@nersc.no>
*/
Expand All @@ -12,6 +12,10 @@
#include "include/Module.hpp"
#include "include/gridNames.hpp"

#ifdef USE_OASIS
#include <oasis_c.h>
#endif

namespace Nextsim {

PrognosticData::PrognosticData()
Expand Down Expand Up @@ -78,6 +82,11 @@ void PrognosticData::setMetadata(const Nextsim::ModelMetadata& metadata)
{
pAtmBdy->setMetadata(metadata);
pOcnBdy->setMetadata(metadata);

#ifdef USE_OASIS
// OASIS finalising definition - can only be called once
OASIS_CHECK_ERR(oasis_c_enddef());
#endif
}

void PrognosticData::update(const TimestepTime& tst)
Expand Down
5 changes: 4 additions & 1 deletion core/src/include/Model.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*!
* @file Model.hpp
* @date 12 Aug 2021
* @date 09 Sep 2024
* @author Tim Spain <timothy.spain@nersc.no>
* @author Kacper Kornet <kk562@cam.ac.uk>
*/
Expand Down Expand Up @@ -49,6 +49,9 @@ class Model : public Configured<Model> {
// Other Model configuration keys, not to be written to the restart file.
RESTARTPERIOD_KEY,
RESTARTOUTFILE_KEY,
#ifdef USE_OASIS
WRITEOASISGRID_KEY,
#endif
};

ConfigMap getConfig() const;
Expand Down
47 changes: 46 additions & 1 deletion core/src/include/ModelMetadata.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
* @file ModelMetadata.hpp
*
* @date Jun 29, 2022
* @date 09 Sep 2024
* @author Tim Spain <timothy.spain@nersc.no>
*/

Expand All @@ -18,6 +18,9 @@
#ifdef USE_MPI
#include <mpi.h>
#endif
#ifdef USE_OASIS
#include <oasis_c.h>
#endif

namespace Nextsim {

Expand All @@ -42,6 +45,10 @@ class ModelMetadata {
ModelMetadata() = default;
#endif

#ifdef USE_OASIS
int OASISPartitionId;
#endif

/*!
* @brief Sets the initial or current model time
*
Expand Down Expand Up @@ -99,6 +106,44 @@ class ModelMetadata {
int localCornerX, localCornerY, localExtentX, localExtentY, globalExtentX, globalExtentY;
#endif

#ifdef USE_OASIS
void initOasis(const bool writeOasisGrid)
{
// Set the partitioning
/* From the manual: "[ig_paral is a] vector of integers describing the local grid partition
* in the global index space; has a different expression depending on the type of the
* partition; in OASIS3-MCT, 5 types of partition are supported: Serial (no partition),
* Apple, Box, Orange, and Points" - it looks like we should use "Box", so partInfo[0] = 2
* (aka. ig_paral).
*
* #Box partition#
* Each partition is a rectangular region of the global domain, described by the global
* offset of its upper left corner, and its local extents in the X and Y dimensions. The
* global extent in the X dimension must also be given. In this case, we have ig_paral(1:5):
* - ig_paral(1) = 2 (indicates a Box partition)
* - ig_paral(2) = the upper left corner global offset
* - ig paral(3) = the local extent in x
* - ig_paral(4) = the local extent in y
* - ig_paral(5) = the global extent in x.
*
* metdatata contains: localCornerX, localCornerY, localExtentX, localExtentY,
* globalExtentX, globalExtentY;
*/
// TODO: The contents of metadata is not certain!
const int offset = globalExtentX * localCornerY + localCornerX;
const std::vector<int> partInfo
= { OASIS_Box, offset, localExtentX, localExtentY, globalExtentX };

const int globalSize = globalExtentX * globalExtentY;
const std::string compName = "nextsim"; // Not useful for any setups we have in mind
OASIS_CHECK_ERR(oasis_c_def_partition(
&OASISPartitionId, OASIS_Box_Params, &partInfo[0], globalSize, compName.c_str()));

// TODO: Writing out grid information should be possible, but optional
if (writeOasisGrid) { }
}
#endif

private:
TimePoint m_time;
ConfigMap m_config;
Expand Down
21 changes: 19 additions & 2 deletions core/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*!
* @file main.cpp
* @date 11 Aug 2021
* @date 09 Sep 2024
* @author Tim Spain <timothy.spain@nersc.no>
* @author Kacper Kornet <kk562@cam.ac.uk>
*/
Expand All @@ -9,6 +9,9 @@
#ifdef USE_MPI
#include <mpi.h>
#endif
#ifdef USE_OASIS
#include <oasis_c.h>
#endif

#include "include/CommandLineParser.hpp"
#include "include/ConfigurationHelpPrinter.hpp"
Expand All @@ -20,7 +23,18 @@
int main(int argc, char* argv[])
{
#ifdef USE_MPI
MPI_Comm modelCommunicator;
MPI_Init(&argc, &argv);
#ifdef USE_OASIS
/* We must call these oasis routines before any MPI communication takes place, to make sure we
* have the right communicator, i.e. modelCommunictor and not MPI_COMM_WORLD. */
int compID; // Not actually used. Only useful for debugging
const std::string compName = "nextsim"; // Not useful for any setups we have in mind
OASIS_CHECK_ERR(oasis_c_init_comp(&compID, compName.c_str(), OASIS_COUPLED));
OASIS_CHECK_ERR(oasis_c_get_localcomm(&modelCommunicator));
#else
modelCommunicator = MPI_COMM_WORLD;
#endif // USE_OASIS
#endif // USE_MPI

// Pass the command line to Configurator to handle
Expand Down Expand Up @@ -49,7 +63,7 @@ int main(int argc, char* argv[])
} else {
// Construct the Model
#ifdef USE_MPI
Nextsim::Model model(MPI_COMM_WORLD);
Nextsim::Model model(modelCommunicator);
#else
Nextsim::Model model;
#endif
Expand All @@ -59,6 +73,9 @@ int main(int argc, char* argv[])
model.run();
}
#ifdef USE_MPI
#ifdef USE_OASIS
OASIS_CHECK_ERR(oasis_c_terminate());
#endif
MPI_Finalize();
#endif

Expand Down
75 changes: 6 additions & 69 deletions physics/src/include/OASISCoupled.hpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
/*!
* @file OASISCoupled.hpp
*
* @date 29 Aug 2024
* @date 09 Sep 2024
* @author Einar Ólason <einar.olason@nersc.no>
*/

#ifndef OASISCOUPLED_HPP
#define OASISCOUPLED_HPP

#include "include/ModelMetadata.hpp"
#ifdef USE_OASIS
#include <oasis_c.h>
#endif
Expand All @@ -17,82 +16,20 @@ namespace Nextsim {

class OASISCoupled {
public:
#ifdef USE_OASIS
~OASISCoupled() { OASIS_CHECK_ERR(!oasis_c_terminate()); }
#else
~OASISCoupled() { }
const std::string OASISError
= "Cannot access OASIS interface, as OASIS support was not activated at compile time.\n";
#endif

virtual std::string getName() const { return "OASISCoupled"; }

#ifdef USE_OASIS
int partitionID, OASISTime;
void setMetadata(const ModelMetadata& metadata)
{
// Set the "OASIS time" (seconds since start) to zero
// TODO: We need to figure out if this is ok to do when restarting
OASISTime = 0;

// Set the communicators
// Some of these three may need to be global to the class
int compID;
MPI_Comm localComm;
MPI_Comm coupledComm;

// compName could be configurable, but I don't see the need
const std::string compName = "nextsim";
OASIS_CHECK_ERR(oasis_c_init_comp_with_comm(
&compID, compName.c_str(), OASIS_COUPLED, metadata.mpiComm));

// Eric didn't include those, but it seems they should be necessary
OASIS_CHECK_ERR(oasis_c_get_localcomm(&localComm));
OASIS_CHECK_ERR(oasis_c_create_couplcomm(OASIS_COUPLED, localComm, &coupledComm));

// Set the partitioning
/* From the manual: "[ig_paral is a] vector of integers describing the local grid partition
* in the global index space; has a different expression depending on the type of the
* partition; in OASIS3-MCT, 5 types of partition are supported: Serial (no partition),
* Apple, Box, Orange, and Points" - it looks like we should use "Box", so partInfo[0] = 2
* (aka. ig_paral).
*
* #Box partition#
* Each partition is a rectangular region of the global domain, described by the global
* offset of its upper left corner, and its local extents in the X and Y dimensions. The
* global extent in the X dimension must also be given. In this case, we have ig_paral(1:5):
* - ig_paral(1) = 2 (indicates a Box partition)
* - ig_paral(2) = the upper left corner global offset
* - ig paral(3) = the local extent in x
* - ig_paral(4) = the local extent in y
* - ig_paral(5) = the global extent in x.
*
* metdatata contains: localCornerX, localCornerY, localExtentX, localExtentY,
* globalExtentX, globalExtentY;
*/
// TODO: The contents of metadata is not certain!
const int offset = metadata.globalExtentX * metadata.localCornerY + metadata.localCornerX;
const std::vector<int> partInfo = { OASIS_Box, offset, metadata.localExtentX,
metadata.localExtentY, metadata.globalExtentX };

const int globalSize = metadata.globalExtentX * metadata.globalExtentY;
OASIS_CHECK_ERR(oasis_c_def_partition(
&partitionID, OASIS_Box_Params, &partInfo[0], globalSize, compName.c_str()));

// TODO: Writing out grid information should be possible, but optional
int OASISTime;

// def_var and end_def calls are called by the child class
}
// Set the "OASIS time" (seconds since start) to zero
OASISCoupled() { OASISTime = 0; }

// Increment the "OASIS" time by the number of seconds in the time step
// Could be any time unit
// Must be called at the end of the child class' update or updateAfter call.
void updateOASISTime(const TimestepTime& tst) { OASISTime += tst.step.seconds(); }
#else
virtual void setMetadata(const ModelMetadata& metadata)
{
std::string message = __func__ + std::string(": OASIS support not compiled in.\n");
throw std::runtime_error(message);
}
const std::string OASISError = std::string(": OASIS support not compiled in.\n");
#endif
};

Expand Down
20 changes: 8 additions & 12 deletions physics/src/modules/OceanBoundaryModule/OASISCoupledOcean.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
* @file OASISCoupledOcean.cpp
*
* @date 27 Aug 2024
* @date 09 Sep 2024
* @author Tim Spain <timothy.spain@nersc.no>
* @author Einar Ólason <einar.olason@nersc.no>
*/
Expand All @@ -15,30 +15,26 @@ namespace Nextsim {

void OASISCoupledOcean::setMetadata(const ModelMetadata& metadata)
{
// The parent class knows how to set the communicators and partitions
OASISCoupled::setMetadata(metadata);

#ifdef USE_OASIS
// OASIS defining variable

/* Populate the couplingId map with the id string and number pair. We need to do this seperately
* for the input (get) and output (put) variables. */
// TODO: coplingID should be a map of <std::string, std::pair> where the pair is idNumber and
// pointer to the ModelArray
for (std::string idString : cplStringsIn) {
int idNumber;
OASIS_CHECK_ERR(oasis_c_def_var(
&idNumber, idString.c_str(), partitionID, bundleSize, OASIS_IN, OASIS_DOUBLE));
OASIS_CHECK_ERR(oasis_c_def_var(&idNumber, idString.c_str(), metadata.OASISPartitionId,
bundleSize, OASIS_IN, OASIS_DOUBLE));
couplingId[idString] = idNumber;
}

for (std::string idString : cplStringsOut) {
int idNumber;
OASIS_CHECK_ERR(oasis_c_def_var(
&idNumber, idString.c_str(), partitionID, bundleSize, OASIS_OUT, OASIS_DOUBLE));
OASIS_CHECK_ERR(oasis_c_def_var(&idNumber, idString.c_str(), metadata.OASISPartitionId,
bundleSize, OASIS_OUT, OASIS_DOUBLE));
couplingId[idString] = idNumber;
}

// OASIS finalising definition
OASIS_CHECK_ERR(oasis_c_enddef());
#else
throw std::runtime_error(std::string(__func__) + ": " + OASISError);
#endif
Expand Down Expand Up @@ -108,7 +104,7 @@ void OASISCoupledOcean::updateAfter(const TimestepTime& tst)
OASIS_DOUBLE, OASIS_COL_MAJOR, &dummy[0], OASIS_No_Restart, &kinfo));

OASIS_CHECK_ERR(oasis_c_put(couplingId.at(EMPKey), OASISTime, dimension0, dimension1, 1,
OASIS_DOUBLE, OASIS_COL_MAJOR, &emp[0], OASIS_No_Restart, &kinfo));
OASIS_DOUBLE, OASIS_COL_MAJOR, &dummy[0], OASIS_No_Restart, &kinfo));

OASIS_CHECK_ERR(oasis_c_put(couplingId.at(QSWKey), OASISTime, dimension0, dimension1, 1,
OASIS_DOUBLE, OASIS_COL_MAJOR, &dummy[0], OASIS_No_Restart, &kinfo));
Expand Down