From 8a181f9222a7de2a77c5c871904c80d2150520a1 Mon Sep 17 00:00:00 2001 From: Jeffrey Curtis Date: Tue, 11 Apr 2023 08:32:02 -0500 Subject: [PATCH] added ability to set GasState values from a JSON object (#204) Co-authored-by: Sylwester Arabas --- src/gas_state.F90 | 5 ++--- src/gas_state.hpp | 10 +++++++++- src/pypartmc.cpp | 6 +++--- tests/test_gas_state.py | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/gas_state.F90 b/src/gas_state.F90 index ce3654eb..5d501500 100644 --- a/src/gas_state.F90 +++ b/src/gas_state.F90 @@ -61,13 +61,12 @@ subroutine f_gas_state_from_json(ptr_c, gas_data_ptr_c) bind(C) type(gas_state_t), pointer :: ptr_f => null() type(c_ptr), intent(in) :: ptr_c type(c_ptr), intent(in) :: gas_data_ptr_c - + type(spec_file_t) :: file type(gas_data_t), pointer :: gas_data_ptr_f => null() - integer :: ncid call c_f_pointer(ptr_c, ptr_f) call c_f_pointer(gas_data_ptr_c, gas_data_ptr_f) - call gas_state_input_netcdf(ptr_f, ncid, gas_data_ptr_f) + call spec_file_read_gas_state(file, gas_data_ptr_f, ptr_f) end subroutine subroutine f_gas_state_to_json(ptr_c) bind(C) diff --git a/src/gas_state.hpp b/src/gas_state.hpp index 9bfb2cc6..1c202fa5 100644 --- a/src/gas_state.hpp +++ b/src/gas_state.hpp @@ -18,7 +18,7 @@ extern "C" void f_gas_state_set_item(const void *ptr, const int *idx, const doub extern "C" void f_gas_state_get_item(const void *ptr, const int *idx, double *val) noexcept; extern "C" void f_gas_state_len(const void *ptr, int *len) noexcept; extern "C" void f_gas_state_to_json(const void *ptr) noexcept; -extern "C" void f_gas_state_from_json(const void *ptr) noexcept; +extern "C" void f_gas_state_from_json(const void *ptr, const void *gasdata_ptr) noexcept; extern "C" void f_gas_state_set_size(const void *ptr, const void *gasdata_ptr) noexcept; extern "C" void f_gas_state_mix_rats(const void *ptr, const double *data, const int *len); @@ -116,4 +116,12 @@ struct GasState { } return data; } + + static void set_mix_rats(const GasState &self, const nlohmann::json &json) { + + gimmick_ptr() = std::make_unique(json); + f_gas_state_from_json(self.ptr.f_arg(), + self.gas_data->ptr.f_arg()); + gimmick_ptr().reset(); // TODO #117: guard + } }; diff --git a/src/pypartmc.cpp b/src/pypartmc.cpp index c851ba87..be706c53 100644 --- a/src/pypartmc.cpp +++ b/src/pypartmc.cpp @@ -291,8 +291,8 @@ PYBIND11_MODULE(_PyPartMC, m) { "sets the GasState to the size of GasData") .def("mix_rat", GasState::mix_rat, "returns the mixing ratio of a gas species") - .def_property_readonly("mix_rats", GasState::mix_rats, - "returns array of mixing ratios") + .def_property("mix_rats", &GasState::mix_rats, &GasState::set_mix_rats, + "provides access (read of write) to the array of mixing ratios") ; py::class_(m, @@ -314,7 +314,7 @@ PYBIND11_MODULE(_PyPartMC, m) { py::class_(m,"AeroMode") .def(py::init()) .def_property("num_conc", &AeroMode::get_num_conc, &AeroMode::set_num_conc, - "returns the total number concentration of a mode") + "provides access (read or write) to the total number concentration of a mode") .def("num_dist", &AeroMode::num_dist, "returns the binned number concenration of a mode") .def_property("vol_frac", &AeroMode::get_vol_frac, diff --git a/tests/test_gas_state.py b/tests/test_gas_state.py index a26727dd..8d62c241 100644 --- a/tests/test_gas_state.py +++ b/tests/test_gas_state.py @@ -15,6 +15,9 @@ GAS_DATA_MINIMAL = ppmc.GasData(GAS_DATA_CTOR_ARG_MINIMAL) +GAS_STATE_MINIMAL = ({"SO2": [0.1]},) + + class TestGasState: @staticmethod def test_ctor_valid(): @@ -97,3 +100,33 @@ def test_get_mix_rats(): # assert assert len(sut.mix_rats) == len(sut) + + @staticmethod + def test_set_mix_rats_from_json(): + # arrange + gas_data = ppmc.GasData( + ( + "SO2", + "NO2", + "NO", + "CO", + ) + ) + sut = ppmc.GasState(gas_data) + + # act + gas_state_init_values = ({"SO2": [0.1]}, {"CO": [0.5]}) + sut.mix_rats = gas_state_init_values + + # assert + idx_set = [] + for item in gas_state_init_values: + keys = item.keys() + assert len(keys) == 1 + key = tuple(keys)[0] + val = tuple(item.values())[0][0] + idx_set.append(gas_data.spec_by_name(key)) + assert sut[gas_data.spec_by_name(key)] == val + for i_spec in range(gas_data.n_spec): + if not i_spec in idx_set: + assert sut[i_spec] == 0