Skip to content

Commit

Permalink
tidy up and add comments
Browse files Browse the repository at this point in the history
  • Loading branch information
TomMelt committed Feb 23, 2024
1 parent 0f68424 commit 78e35a4
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 111 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ Results
/run/applications/*
*.vtk
*.smesh
*.DS_Store
*.DS_Store
*.nc
__pycache__/
28 changes: 11 additions & 17 deletions core/src/Xios.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
/*!
* @file Xios.cpp
* @date 2023-10-12
* @author Dr Alexander Smith <as3402@cam.ac.uk>
* @author Dr Tom Meltzer <tdm39@cam.ac.uk>
* @brief Handler class for interfacing Nextsim-DG with the XIOS library
* @file Xios.cpp
* @author Tom Meltzer <tdm39@cam.ac.uk>
* @date Fri 23 Feb 13:43:16 GMT 2024
* @brief XIOS interface implementation
* @details
* The Xios class is designed to abstract away any complexity of iteracting
* with the XIOS library. It assumes XIOS 2.0. Design details are available
* in the Nextsim-DG wiki.
*
* This class focuses on initialising the XIOS server and client processes and
* syncronising calendar data with Nextsim by taking information from Nextsim
* and creating XIOS data structures or converting strings into the XIOS format
* and using the C-bindings to pass the data to an XIOS context.
* Implementation of XIOS interface
*
* XIOS_IODEF_PATH
* This C++ interface is designed to implement core functionality of XIOS so
* that it can be used in nextsimdg. It is by no means meant to be
* feature-complete. Initially the goal is to generate most of the XIOS
* configuration in the xml definition file `iodef.xml`. As required we will
* add more features to the C++ interface.
*
* TODO: Add XIOS Grid/Axis Class/Data Structure for storing data
* TODO: Add XIOS IO Process
*
* Users can enable XIOS by adding a line to the config file e.g.
* To enable XIOS in nextsim add the following lines to the config file.
* [xios]
* enable = true
*
Expand Down
14 changes: 9 additions & 5 deletions core/src/include/Xios.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
/*!
* @file Xios.hpp
* @date 7th February 2023
* @author Dr Alexander Smith <as3402@cam.ac.uk>
* @file Xios.hpp
* @author Tom Meltzer <tdm39@cam.ac.uk>
* @date Fri 23 Feb 13:43:16 GMT 2024
* @brief XIOS interface header
* @details
*
* Header file for XIOS interface
*
*/

#ifndef SRC_INCLUDE_XIOS_HPP
#define SRC_INCLUDE_XIOS_HPP

Expand Down Expand Up @@ -74,7 +78,7 @@ class Xios : public Configured<Xios> {
std::string contextId;
};

} /* end namespace Nextsim */
}

#endif // USE_XIOS
#endif
68 changes: 35 additions & 33 deletions core/src/include/xios_c_interface.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
/*!
* @file xios_c_interface.hpp
* @author Tom Meltzer <tdm39@cam.ac.uk>
* @date Fri 23 Feb 13:43:16 GMT 2024
* @brief C interface for xios library
* @details
* This interface is based on an earlier version provided by Laurent as part of
* the https://github.com/nextsimhub/xios_cpp_toy repo. This C interface is
* designed to connect with the underlying Fortran interface of XIOS 2.
*
* This can be expanded as we add more XIOS functionality to the nextsim XIOS
* C++ interface `Xios.cpp`.
*
*/
#ifndef XIOS_C_INTERFACE
#define XIOS_C_INTERFACE

Expand All @@ -8,56 +22,46 @@
#include <icdate.hpp>

extern "C" {
void cxios_init_client(
const char* client_id, int len_client_id, MPI_Fint* f_local_comm, MPI_Fint* f_return_comm);

// client methods
void cxios_init_client(const char* client_id, int len_client_id, MPI_Fint* f_local_comm, MPI_Fint* f_return_comm);
void cxios_finalize();

// context methods
void cxios_context_initialize(const char* context_id, int len_context_id, MPI_Fint* f_comm);
void cxios_context_is_initialized(const char* context_id, int len_context_id, bool* initialized);
void cxios_context_close_definition();
void cxios_context_finalize();

// Calendar init
void cxios_get_current_calendar_wrapper(xios::CCalendarWrapper** _ret);
// Date Utility

// datetime conversions
void cxios_date_convert_to_string(cxios_date date_c, char* str, int str_size);
// TODO: If I added this then consider void and making final arg cxios_date (again)
// cxios_date* cxios_date_convert_from_string(char* str, int str_size);
// cxios_date cxios_date_convert_from_string(const char* str, int str_size);
cxios_date cxios_date_convert_from_string(const char* str, int str_size);

// TODO: Can't be import definitions from the xios header file? Why does this file even exist?
void cxios_duration_convert_to_string(cxios_duration dur_c, char* str, int str_size);
// cxios_duration* cxios_duration_convert_from_string(const char* str, int str_size);

// Calendar Origin
void cxios_set_calendar_wrapper_date_time_origin(
xios::CCalendarWrapper* calendarWrapper_hdl, cxios_date time_origin_c);
void cxios_get_calendar_wrapper_date_time_origin(
xios::CCalendarWrapper* calendarWrapper_hdl, cxios_date* time_origin_c);
// calendar methods
void cxios_set_calendar_wrapper_date_time_origin(xios::CCalendarWrapper* calendarWrapper_hdl, cxios_date time_origin_c);
void cxios_get_calendar_wrapper_date_time_origin(xios::CCalendarWrapper* calendarWrapper_hdl, cxios_date* time_origin_c);
void cxios_set_calendar_wrapper_date_start_date(xios::CCalendarWrapper* calendarWrapper_hdl, cxios_date start_date_c);
void cxios_get_calendar_wrapper_date_start_date(xios::CCalendarWrapper* calendarWrapper_hdl, cxios_date* start_date_c);
void cxios_get_current_date(cxios_date* date);

// Calendar Start Date
void cxios_set_calendar_wrapper_date_start_date(
xios::CCalendarWrapper* calendarWrapper_hdl, cxios_date start_date_c);
void cxios_get_calendar_wrapper_date_start_date(
xios::CCalendarWrapper* calendarWrapper_hdl, cxios_date* start_date_c);
void cxios_update_calendar(int step);

// Calendar Timestep
void cxios_set_calendar_wrapper_timestep(
xios::CCalendarWrapper* calendar_wrapper_hdl, cxios_duration timestep_c);
void cxios_get_calendar_wrapper_timestep(
xios::CCalendarWrapper* calendar_wrapper_hdl, cxios_duration* timestep_c);
// timestep methods
void cxios_set_calendar_wrapper_timestep(xios::CCalendarWrapper* calendar_wrapper_hdl, cxios_duration timestep_c);
void cxios_get_calendar_wrapper_timestep(xios::CCalendarWrapper* calendar_wrapper_hdl, cxios_duration* timestep_c);
void cxios_update_calendar_timestep(xios::CCalendarWrapper* calendarWrapper_hdl);

void cxios_get_current_date(cxios_date* date);
// This doesn't work but I find that unexpected
// void cxios_get_timestep(cxios_duration *timestep);

// Grid Axis
// grid methods
void cxios_axis_handle_create(xios::CAxis** _ret, const char* _id, int _id_len);
void cxios_get_axis_n_glo(xios::CAxis* axis_hdl, int* n_glo);
void cxios_get_axis_value(xios::CAxis* axis_hdl, double* value, int* extent);

// domain methods
void cxios_domain_handle_create(xios::CDomain** _ret, const char* _id, int _id_len);
void cxios_get_domain_type(xios::CDomain* domain_hdl, char* type, int type_size);
void cxios_get_domain_ni_glo(xios::CDomain* domain_hdl, int* ni_glo);
Expand All @@ -69,11 +73,9 @@ void cxios_set_domain_jbegin(xios::CDomain* domain_hdl, int jbegin);
void cxios_set_domain_lonvalue_1d(xios::CDomain* domain_hdl, double* lonvalue_1d, int* extent);
void cxios_set_domain_latvalue_1d(xios::CDomain* domain_hdl, double* latvalue_1d, int* extent);

void cxios_update_calendar(int step);
void cxios_write_data_k82(const char* fieldid, int fieldid_size, double* data_k8, int data_Xsize,
int data_Ysize, int tileid);
void cxios_write_data_k83(const char* fieldid, int fieldid_size, double* data_k8, int data_Xsize,
int data_Ysize, int data_Zsize, int tileid);
// writing methods
void cxios_write_data_k82(const char* fieldid, int fieldid_size, double* data_k8, int data_Xsize, int data_Ysize, int tileid);
void cxios_write_data_k83(const char* fieldid, int fieldid_size, double* data_k8, int data_Xsize, int data_Ysize, int data_Zsize, int tileid);
};

#endif
46 changes: 36 additions & 10 deletions core/test/XiosInit_test.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
/*!
* @file XiosInit_test.cpp
* @author Tom Meltzer <tdm39@cam.ac.uk>
* @date Fri 23 Feb 13:43:16 GMT 2024
* @brief Tests for XIOS C++ interface
* @details
* This test is designed to test all core functionality of the C++ interface
* for XIOS.
*
* Due to the fact that XIOS relies on MPI, it is not convenient to split the
* tests out into individual test routines. Each one would require a lot of
* boilerplate, so they have all been group in this test.
*
*/
#include <cstdio>
#include <doctest/extensions/doctest_mpi.h>
#include "include/Xios.hpp"
Expand All @@ -7,7 +21,10 @@
/*!
* TestXiosInitialization
*
* This test checks the Xios core implementation
* This test checks all core functionality of the C++ interface for XIOS. It
* needs to be run with 2 ranks i.e.,
*
* `mpirun -n 2 ./testXiosInit_MPI2`
*
*/
MPI_TEST_CASE("TestXiosInitialization", 2)
Expand All @@ -20,17 +37,17 @@ MPI_TEST_CASE("TestXiosInitialization", 2)
std::unique_ptr<std::istream> pcstream(new std::stringstream(config.str()));
Nextsim::Configurator::addStream(std::move(pcstream));

// initialized instance of xios_handler
Nextsim::Xios xios_handler;
std::string datetime;

REQUIRE(xios_handler.isInitialized());

// read calendar start date and verify datetime string
cxios_date start = xios_handler.getCalendarStart();
datetime = xios_handler.convertXiosDatetimeToString(start);
std::string datetime = xios_handler.convertXiosDatetimeToString(start);
REQUIRE(datetime == "2023-03-17T17:11:00Z");

// read calendar origin date and verify datetime string
cxios_date origin = xios_handler.getCalendarOrigin();
// convert cxios_date to string for comparison
datetime = xios_handler.convertXiosDatetimeToString(origin);
REQUIRE(datetime == "2020-01-23T00:08:15Z");

Expand All @@ -56,18 +73,20 @@ MPI_TEST_CASE("TestXiosInitialization", 2)
datetime = xios_handler.convertXiosDatetimeToString(start);
REQUIRE(datetime == "2023-03-17T17:37:00Z");

// same steps as calendar start date
// same steps as calendar start date but for calendar Origin
origin = xios_handler.getCalendarOrigin();
origin.second = 1;
xios_handler.setCalendarOrigin(origin);
origin = xios_handler.getCalendarOrigin();
datetime = xios_handler.convertXiosDatetimeToString(origin);
REQUIRE(datetime == "2020-01-23T00:08:01Z");

// similar approach for timestep
// get Calendar timestep and modify it
duration = xios_handler.getCalendarTimestep();
duration.year = 0.5;
// set Calendar timestep
xios_handler.setCalendarTimestep(duration);
// verify timestep has been successfully modified
duration = xios_handler.getCalendarTimestep();
REQUIRE(duration.year == doctest::Approx(0.5));
REQUIRE(duration.month == doctest::Approx(0.0));
Expand All @@ -79,33 +98,40 @@ MPI_TEST_CASE("TestXiosInitialization", 2)

xios_handler.context_finalize();

// check the getCurrentDate method
xios::CDate current;
current = xios_handler.getCurrentDate();
std::string current_date = {};
current_date = current.toString().c_str();
REQUIRE(current_date == "2023-03-17 17:37:00");

// create some fake data to test writing methods
int ni = 30;
int nj = 30;
double* field_A = new double[ni * nj];
for (int idx = 0; idx < ni * nj; idx++) {
field_A[idx] = 1.0 * idx;
}

// create field
std::string fieldId = { "field_A" };

int step;
step = xios_handler.getCalendarStep();
// verify calendar step is starting from zero
int step = xios_handler.getCalendarStep();
REQUIRE(step == 0);

// simulate 4 iterations (timesteps)
for (int ts = 1; ts <= 4; ts++) {
// update the current timestep
xios_handler.updateCalendar(ts);
// send data to XIOS to be written to disk
xios_handler.write(fieldId, field_A, ni, nj);
// verify timestep
step = xios_handler.getCalendarStep();
REQUIRE(step == ts);
}

// clean up
delete[] field_A;

xios_handler.finalize();
}
45 changes: 0 additions & 45 deletions run/iodef.xml

This file was deleted.

0 comments on commit 78e35a4

Please sign in to comment.