Skip to content

Commit 0cdeea7

Browse files
committed
Resolve "Refactor IO"
new io framework error reporting with value-or-error type type layout definitions separated from file formats and io
1 parent 5413594 commit 0cdeea7

57 files changed

Lines changed: 4234 additions & 2830 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,11 @@ https://hpc-against-corona.pages.gitlab.dlr.de/epidemiology/master/documentation
3535
By standard *epidemiology* library is bundled with
3636
* spdlog (https://github.com/gabime/spdlog)
3737
* eigen v3.3 (http://gitlab.com/libeigen/eigen and http://eigen.tuxfamily.org)
38+
* boost outcome and optional (https://www.boost.org/)
3839

3940
See thirdparty/CMakeLists.txt for details.
4041

41-
In order to use IO of parameters and simulation results (*epidemiology_io* library), the tools
42-
* tixi3 (https://github.com/DLR-SC/tixi) and
43-
* hdf5 (https://www.hdfgroup.org/ e.g., via apt install libhdf5-serial-dev)
44-
45-
need to be installed.
42+
In order to use IO of parameters and simulation results (*epidemiology_io* library), the tool HDF5 (https://www.hdfgroup.org/ e.g., via apt install libhdf5-serial-dev) needs to be installed.
4643

4744
In addition, *epidemiology_io* is bundled with
4845
* jsoncpp (https://github.com/open-source-parsers/jsoncpp)

cpp/CMakeLists.txt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ project(epidemiology VERSION 0.1.0)
44

55
option(EPI_USE_BUNDLED_SPDLOG "Use spdlog bundled with epi" ON)
66
option(EPI_USE_BUNDLED_EIGEN "Use eigen bundled with epi" ON)
7-
option(EPI_BUILD_EPI_IO "Build epidemiology_io library (requires TiXI and HDF5)" OFF)
7+
option(EPI_BUILD_EPI_IO "Build epidemiology_io library (requires HDF5)" OFF)
88
option(EPI_USE_BUNDLED_BOOST "Use boost bundled with epi (only for epi-io)" ON)
99
option(EPI_USE_BUNDLED_JSONCPP "Use jsoncpp bundled with epi (only for epi-io)" ON)
1010

@@ -124,7 +124,7 @@ target_include_directories(epidemiology PUBLIC
124124

125125

126126
target_compile_features(epidemiology PUBLIC cxx_std_14)
127-
target_link_libraries(epidemiology PUBLIC spdlog::spdlog Eigen3::Eigen)
127+
target_link_libraries(epidemiology PUBLIC spdlog::spdlog Eigen3::Eigen Boost::boost)
128128
target_compile_options(epidemiology PRIVATE
129129
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:GNU>>: -Wall -Wextra -Werror -Wshadow --pedantic-errors -Wno-deprecated-copy>
130130
$<$<CXX_COMPILER_ID:MSVC>: /W4 /WX>)
@@ -140,6 +140,8 @@ if (EPI_BUILD_EPI_IO)
140140
epidemiology_io/io.h
141141
epidemiology_io/mobility_io.cpp
142142
epidemiology_io/mobility_io.h
143+
epidemiology_io/json_serializer.h
144+
epidemiology_io/json_serializer.cpp
143145
)
144146

145147

@@ -149,8 +151,8 @@ if (EPI_BUILD_EPI_IO)
149151
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
150152
)
151153

152-
target_link_libraries(epidemiology_io PUBLIC epidemiology tixi3
153-
PRIVATE jsoncpp ${HDF5_CXX_LIBRARIES} Boost::filesystem Boost::disable_autolinking)
154+
target_link_libraries(epidemiology_io PUBLIC epidemiology jsoncpp
155+
PRIVATE ${HDF5_CXX_LIBRARIES} Boost::filesystem Boost::disable_autolinking)
154156
target_include_directories(epidemiology_io PRIVATE ${HDF5_INCLUDE_DIRS})
155157

156158
target_compile_definitions(epidemiology_io PUBLIC "-DHAVE_EPI_IO")

cpp/cmake/BuildBoost.cmake

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
set (BOOST_DIR ${PROJECT_BINARY_DIR}/boost_1_72_0)
2-
set (BOOST_ARCHIVE ${PROJECT_SOURCE_DIR}/thirdparty/boost_1_72_0.tar.gz)
3-
set (Boost_VERSION "1.72.0")
1+
set (BOOST_DIR ${PROJECT_BINARY_DIR}/boost_1_75_0)
2+
set (BOOST_ARCHIVE ${PROJECT_SOURCE_DIR}/thirdparty/boost_1_75_0.tar.gz)
3+
set (Boost_VERSION "1.75.0")
44
set (BOOST_LIB_TYPE STATIC)
55

66
if (NOT EXISTS ${BOOST_DIR})

cpp/epidemiology/migration/migration.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,35 @@ class MigrationParameters
179179
}
180180
/** @} */
181181

182+
/**
183+
* serialize this.
184+
* @see epi::serialize
185+
*/
186+
template<class IOContext>
187+
void serialize(IOContext& io) const
188+
{
189+
auto obj = io.create_object("MigrationParameters");
190+
obj.add_element("Coefficients", m_coefficients);
191+
obj.add_element("DynamicNPIs", m_dynamic_npis);
192+
}
193+
194+
/**
195+
* deserialize an object of this class.
196+
* @see epi::deserialize
197+
*/
198+
template<class IOContext>
199+
static IOResult<MigrationParameters> deserialize(IOContext& io)
200+
{
201+
auto obj = io.expect_object("MigrationParameters");
202+
auto c = obj.expect_element("Coefficients", Tag<MigrationCoefficientGroup>{});
203+
auto d = obj.expect_element("DynamicNPIs", Tag<DynamicNPIs>{});
204+
return apply(io, [](auto && c_, auto&& d_) {
205+
MigrationParameters params(c_);
206+
params.set_dynamic_npis_infected(d_);
207+
return params;
208+
}, c, d);
209+
}
210+
182211
private:
183212
MigrationCoefficientGroup m_coefficients; //one per group and compartment
184213
DynamicNPIs m_dynamic_npis;

cpp/epidemiology/model/populations.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,15 @@ template <class... Categories>
3535
class Populations : public CustomIndexArray<UncertainValue, Categories...>
3636
{
3737
public:
38-
39-
using Index = typename CustomIndexArray<UncertainValue, Categories...>::Index;
38+
using Base = CustomIndexArray<UncertainValue, Categories...>;
39+
using Index = typename Base::Index;
4040

4141
template <class... Ts,
4242
typename std::enable_if_t<std::is_constructible<UncertainValue, Ts...>::value>* = nullptr>
4343
explicit Populations(Index const& sizes, Ts... args)
44-
: CustomIndexArray<UncertainValue, Categories...>(sizes, args...)
44+
: Base(sizes, args...)
4545
{}
4646

47-
4847
/**
4948
* @brief get_num_compartments returns the number of compartments
5049
*
@@ -138,7 +137,7 @@ class Populations : public CustomIndexArray<UncertainValue, Categories...>
138137
*/
139138
ScalarType get_total() const
140139
{
141-
return this->array().sum();
140+
return this->array().template cast<ScalarType>().sum();
142141
}
143142

144143

@@ -234,7 +233,15 @@ class Populations : public CustomIndexArray<UncertainValue, Categories...>
234233
}
235234
}
236235

237-
236+
/**
237+
* deserialize an object of this class.
238+
* @see epi::deserialize
239+
*/
240+
template<class IOContext>
241+
static IOResult<Populations> deserialize(IOContext& io)
242+
{
243+
return Base::deserialize(io, Tag<Populations>{});
244+
}
238245
};
239246

240247

cpp/epidemiology/secir/age_group.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef AGEGROUP_H
22
#define AGEGROUP_H
33

4+
#include "epidemiology/utils/index.h"
5+
46
namespace epi {
57

68
/**

cpp/epidemiology/secir/contact_matrix.h

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,56 @@ class DampingMatrixExpression
185185
PrintTo(self.m_dampings, os);
186186
}
187187

188+
/**
189+
* serialize this.
190+
* @see epi::serialize
191+
*/
192+
template<class IOContext>
193+
void serialize(IOContext& io) const
194+
{
195+
auto obj = io.create_object("DampingMatrixExpression");
196+
obj.add_element("Baseline", get_baseline());
197+
obj.add_element("Minimum", get_minimum());
198+
obj.add_list("Dampings", get_dampings().begin(), get_dampings().end());
199+
}
200+
201+
protected:
202+
/**
203+
* deserialize an object of a class derived from this.
204+
*/
205+
template<class IOContext, class Derived>
206+
static IOResult<Derived> deserialize(IOContext& io, Tag<Derived>)
207+
{
208+
auto obj = io.expect_object("DampingMatrixExpression");
209+
auto b = obj.expect_element("Baseline", Tag<Matrix>{});
210+
auto m = obj.expect_element("Minimum", Tag<Matrix>{});
211+
auto d = obj.expect_list("Dampings", Tag<typename DampingsType::value_type>{});
212+
return apply(io, [](auto&& b_, auto&& m_, auto&& d_) -> IOResult<Derived> {
213+
if (Shape::get_shape_of(b_) != Shape::get_shape_of(m_)) {
214+
return failure(StatusCode::InvalidValue, "Baseline and Minimum must have the same shape.");
215+
}
216+
auto r = Derived(b_, m_);
217+
for (auto&& e : d_) {
218+
if (e.get_shape() != Shape::get_shape_of(b_)) {
219+
return failure(StatusCode::InvalidValue, "Dampings must have the same shape as the Baseline.");
220+
}
221+
r.add_damping(e);
222+
}
223+
return success(r);
224+
}, b, m, d);
225+
}
226+
227+
public:
228+
/**
229+
* deserialize an object of this class.
230+
* @see epi::deserialize
231+
*/
232+
template<class IOContext>
233+
static IOResult<DampingMatrixExpression> deserialize(IOContext& io)
234+
{
235+
return deserialize(io, Tag<DampingMatrixExpression>{});
236+
}
237+
188238
private:
189239
Matrix m_baseline;
190240
Matrix m_minimum;
@@ -231,6 +281,14 @@ class DampingMatrixExpressionGroup
231281
assert(il.size() > 0);
232282
}
233283

284+
private:
285+
DampingMatrixExpressionGroup(const std::vector<value_type>& v)
286+
: m_matrices(v)
287+
{
288+
assert(v.size() > 0);
289+
}
290+
291+
public:
234292
/**
235293
* access one matrix.
236294
*/
@@ -351,6 +409,57 @@ class DampingMatrixExpressionGroup
351409
}
352410
}
353411

412+
/**
413+
* serialize this.
414+
* @see epi::serialize
415+
*/
416+
template <class IOContext>
417+
void serialize(IOContext& io) const
418+
{
419+
auto obj = io.create_object("DampingMatrixExpressionGroup");
420+
obj.add_list("Matrices", begin(), end());
421+
}
422+
423+
protected:
424+
/**
425+
* deserialize an object of a class derived from this.
426+
* @see epi::deserialize
427+
*/
428+
template <class IOContext, class Derived>
429+
static IOResult<Derived> deserialize(IOContext& io, Tag<Derived>)
430+
{
431+
auto obj = io.expect_object("DampingMatrixExpressionGroup");
432+
auto m = obj.expect_list("Matrices", Tag<value_type>{});
433+
return apply(
434+
io,
435+
[](auto&& m_) -> IOResult<Derived> {
436+
//validation
437+
if (m_.empty()) {
438+
return failure(StatusCode::InvalidValue, "DampingMatrixExpressionGroup must have at least one matrix.");
439+
}
440+
auto shape = m_[0].get_shape();
441+
for (size_t i = 1; i < m_.size(); ++i) {
442+
if (m_[i].get_shape() != shape) {
443+
return failure(StatusCode::InvalidValue, "Elements of DampingMatrixExpressionGroup must all have the same shape.");
444+
}
445+
}
446+
447+
return success(Derived(m_));
448+
},
449+
m);
450+
}
451+
452+
public:
453+
/**
454+
* deserialize an object of this class.
455+
* @see epi::deserialize
456+
*/
457+
template <class IOContext>
458+
static IOResult<DampingMatrixExpressionGroup> deserialize(IOContext& io)
459+
{
460+
return deserialize(io, Tag<DampingMatrixExpressionGroup>{});
461+
}
462+
354463
private:
355464
std::vector<value_type> m_matrices;
356465
};
@@ -380,6 +489,16 @@ class ContactMatrix : public DampingMatrixExpression<SquareDampings>
380489
Eigen::Index get_num_groups() const
381490
{
382491
return Base::get_shape().rows();
492+
}
493+
494+
/**
495+
* deserialize an object of this class.
496+
* @see epi::deserialize
497+
*/
498+
template <class IOContext>
499+
static IOResult<ContactMatrix> deserialize(IOContext& io)
500+
{
501+
return Base::deserialize(io, Tag<ContactMatrix>{});
383502
}
384503
};
385504

@@ -401,6 +520,16 @@ class ContactMatrixGroup : public DampingMatrixExpressionGroup<ContactMatrix>
401520
{
402521
return (*this)[0].get_num_groups();
403522
}
523+
524+
/**
525+
* deserialize an object of this class.
526+
* @see epi::deserialize
527+
*/
528+
template <class IOContext>
529+
static IOResult<ContactMatrixGroup> deserialize(IOContext& io)
530+
{
531+
return Base::deserialize(io, Tag<ContactMatrixGroup>{});
532+
}
404533
};
405534

406535
} // namespace epi

0 commit comments

Comments
 (0)