Skip to content
Draft
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
52 changes: 52 additions & 0 deletions src/gas_state.F90
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,56 @@ subroutine f_gas_state_set_size(ptr_c, gas_data_ptr_c) bind(C)
call gas_state_set_size(ptr_f, gas_data_n_spec(gas_data_ptr_f))

end subroutine

subroutine f_gas_state_molar_conc_to_ppb(ptr_c, env_state_ptr_c) bind(C)
type(c_ptr), intent(inout) :: ptr_c
type(c_ptr), intent(in) :: env_state_ptr_c
type(gas_state_t), pointer :: ptr_f => null()
type(env_state_t), pointer :: env_state_ptr_f => null()

call c_f_pointer(ptr_c, ptr_f)
call c_f_pointer(env_state_ptr_c, env_state_ptr_f)

call gas_state_molar_conc_to_ppb(ptr_f, env_state_ptr_f)

end subroutine

subroutine f_gas_state_scale(ptr_c, alpha) bind(C)
type(c_ptr), intent(inout) :: ptr_c
type(gas_state_t), pointer :: ptr_f => null()
real(kind=c_double), intent(in) :: alpha

call c_f_pointer(ptr_c, ptr_f)

call gas_state_scale(ptr_f, alpha)

end subroutine

subroutine f_gas_state_add(ptr_c, delta_gas_state_ptr_c) bind(C)
type(c_ptr), intent(inout) :: ptr_c
type(c_ptr), intent(in) :: delta_gas_state_ptr_c
type(gas_state_t), pointer :: ptr_f => null()
type(gas_state_t), pointer :: delta_gas_state_ptr_f => null()

call c_f_pointer(ptr_c, ptr_f)
call c_f_pointer(delta_gas_state_ptr_c, delta_gas_state_ptr_f)

call gas_state_add(ptr_f, delta_gas_state_ptr_f)

end subroutine

subroutine f_gas_state_add_scaled(ptr_c, delta_gas_state_ptr_c, alpha) bind(C)
type(c_ptr), intent(inout) :: ptr_c
type(c_ptr), intent(in) :: delta_gas_state_ptr_c
type(gas_state_t), pointer :: ptr_f => null()
type(gas_state_t), pointer :: delta_gas_state_ptr_f => null()
real(kind=c_double), intent(in) :: alpha

call c_f_pointer(ptr_c, ptr_f)
call c_f_pointer(delta_gas_state_ptr_c, delta_gas_state_ptr_f)

call gas_state_add_scaled(ptr_f, delta_gas_state_ptr_f, alpha)

end subroutine

end module
33 changes: 32 additions & 1 deletion src/gas_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "json_resource.hpp"
#include "pmc_resource.hpp"
#include "gas_data.hpp"
#include "env_state.hpp"

extern "C" void f_gas_state_ctor(void *ptr) noexcept;
extern "C" void f_gas_state_dtor(void *ptr) noexcept;
Expand All @@ -19,7 +20,15 @@ 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, 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);
extern "C" void f_gas_state_mix_rats(const void *ptr, const double *data, const int *len) noexcept;
extern "C" void f_gas_state_molar_conc_to_ppb(const void *ptr, const void *envstate_ptr) noexcept;
extern "C" void f_gas_state_scale(const void *ptr_c, const double *alpha) noexcept;
extern "C" void f_gas_state_add(const void *ptr_c, const void *delta_ptr) noexcept;
extern "C" void f_gas_state_add_scaled(
const void *ptr_c,
const void *delta_ptr,
const double *alpha
) noexcept;

struct GasState {
PMCResource ptr;
Expand Down Expand Up @@ -126,4 +135,26 @@ struct GasState {
);
guard.check_parameters();
}

static void molar_conc_to_ppb(const GasState &self, const EnvState &env_state) {

f_gas_state_molar_conc_to_ppb(self.ptr.f_arg(), env_state.ptr.f_arg());
}

static void scale(const GasState &self, const double &alpha) {

f_gas_state_scale(self.ptr.f_arg(), &alpha);
}

static void add(const GasState &self, const GasState &delta_gas_state) {

f_gas_state_add(self.ptr.f_arg(), delta_gas_state.ptr.f_arg());
}

static void add_scaled(const GasState &self, const GasState &delta_gas_state,
const double &alpha) {

f_gas_state_add_scaled(self.ptr.f_arg(), delta_gas_state.ptr.f_arg(), &alpha);
}

};
6 changes: 6 additions & 0 deletions src/pypartmc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,12 @@ NB_MODULE(_PyPartMC, m) {
"Return the mixing ratio of a gas species.")
.def_prop_rw("mix_rats", &GasState::mix_rats, &GasState::set_mix_rats,
"Provide access (read or write) to the array of mixing ratios.")
.def("molar_conc_to_ppb", &GasState::molar_conc_to_ppb,
"Convert (mol m^{-3}) to (ppb).")
.def("scale", &GasState::scale, "Scale a gas state.")
.def("add", &GasState::add, "Adds the given gas_state_delta.")
.def("add_scaled", &GasState::add_scaled,
"Adds the given gas_state_delta scaled by alpha to an existing gas_state.")
;

nb::class_<RunPartOpt>(m,
Expand Down
75 changes: 75 additions & 0 deletions tests/test_gas_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@
import gc
import platform

import numpy as np
import pytest

import PyPartMC as ppmc

from .common import ENV_STATE_CTOR_ARG_MINIMAL
from .test_aero_data import AERO_DATA_CTOR_ARG_MINIMAL
from .test_gas_data import GAS_DATA_CTOR_ARG_MINIMAL
from .test_scenario import SCENARIO_CTOR_ARG_MINIMAL

GAS_DATA_MINIMAL = ppmc.GasData(GAS_DATA_CTOR_ARG_MINIMAL)

Expand Down Expand Up @@ -103,6 +107,77 @@ def test_get_mix_rats():
# assert
assert len(sut.mix_rats) == len(sut)

@staticmethod
def test_scale():
# arrange
gas_data = ppmc.GasData(
(
"SO2",
"CO",
)
)
sut = ppmc.GasState(gas_data)
gas_state_init_values = ({"SO2": [0.1]}, {"CO": [0.5]})
sut.mix_rats = gas_state_init_values

# act
alpha = 5.0
sut.scale(alpha)

# 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 * alpha

@staticmethod
def test_molar_conc_to_ppb():
# arrange
gas_data = GAS_DATA_MINIMAL
aero_data = ppmc.AeroData(AERO_DATA_CTOR_ARG_MINIMAL)
scenario = ppmc.Scenario(gas_data, aero_data, SCENARIO_CTOR_ARG_MINIMAL)
env_state = ppmc.EnvState(ENV_STATE_CTOR_ARG_MINIMAL)
scenario.init_env_state(env_state, 0.0)
sut = ppmc.GasState(GAS_DATA_MINIMAL)
sut.mix_rats = GAS_STATE_MINIMAL

# act
sut.molar_conc_to_ppb(env_state)

# assert
assert sut.mix_rats[0] > GAS_STATE_MINIMAL[0][list(gas_data.species)[0]][0]

@staticmethod
def test_add():
sut = ppmc.GasState(GAS_DATA_MINIMAL)
sut.mix_rats = GAS_STATE_MINIMAL
gas_state_delta = ppmc.GasState(GAS_DATA_MINIMAL)
gas_state_delta.mix_rats = GAS_STATE_MINIMAL
tot_mix_rats = np.add(sut.mix_rats, gas_state_delta.mix_rats)

# act
sut.add(gas_state_delta)

assert sut.mix_rats == tot_mix_rats

@staticmethod
def test_add_scaled():
sut = ppmc.GasState(GAS_DATA_MINIMAL)
sut.mix_rats = GAS_STATE_MINIMAL
gas_state_delta = ppmc.GasState(GAS_DATA_MINIMAL)
gas_state_delta.mix_rats = GAS_STATE_MINIMAL
alpha = 2.5
tot_mix_rats = np.add(sut.mix_rats, np.array(gas_state_delta.mix_rats) * alpha)

# act
sut.add_scaled(gas_state_delta, alpha)

assert sut.mix_rats == tot_mix_rats

@staticmethod
def test_set_mix_rats_from_json():
# arrange
Expand Down
Loading