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
101 changes: 101 additions & 0 deletions src/env_state.F90
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,105 @@ subroutine f_env_state_air_dens(ptr_c, air_density) bind(C)

end subroutine

subroutine f_env_state_air_molar_dens(ptr_c, air_molar_density) bind(C)
type(env_state_t), pointer :: ptr_f => null()
type(c_ptr), intent(in) :: ptr_c
real(c_double), intent(out) :: air_molar_density

call c_f_pointer(ptr_c, ptr_f)

air_molar_density = env_state_air_molar_den(ptr_f)

end subroutine

subroutine f_env_state_get_latitude(ptr_c, latitude) bind(C)
type(env_state_t), pointer :: ptr_f => null()
type(c_ptr), intent(in) :: ptr_c
real(c_double), intent(out) :: latitude

call c_f_pointer(ptr_c, ptr_f)

latitude = ptr_f%latitude

end subroutine

subroutine f_env_state_set_latitude(ptr_c, latitude) bind(C)
type(env_state_t), pointer :: ptr_f => null()
type(c_ptr), intent(inout) :: ptr_c
real(c_double), intent(in) :: latitude

call c_f_pointer(ptr_c, ptr_f)

ptr_f%latitude = latitude

end subroutine

subroutine f_env_state_get_longitude(ptr_c, longitude) bind(C)
type(env_state_t), pointer :: ptr_f => null()
type(c_ptr), intent(in) :: ptr_c
real(c_double), intent(out) :: longitude

call c_f_pointer(ptr_c, ptr_f)

longitude = ptr_f%longitude

end subroutine

subroutine f_env_state_set_longitude(ptr_c, longitude) bind(C)
type(env_state_t), pointer :: ptr_f => null()
type(c_ptr), intent(inout) :: ptr_c
real(c_double), intent(in) :: longitude

call c_f_pointer(ptr_c, ptr_f)

ptr_f%longitude = longitude

end subroutine

subroutine f_env_state_get_altitude(ptr_c, altitude) bind(C)
type(env_state_t), pointer :: ptr_f => null()
type(c_ptr), intent(in) :: ptr_c
real(c_double), intent(out) :: altitude

call c_f_pointer(ptr_c, ptr_f)

altitude = ptr_f%altitude

end subroutine

subroutine f_env_state_set_altitude(ptr_c, altitude) bind(C)
type(env_state_t), pointer :: ptr_f => null()
type(c_ptr), intent(inout) :: ptr_c
real(c_double), intent(in) :: altitude

call c_f_pointer(ptr_c, ptr_f)

ptr_f%altitude = altitude

end subroutine

subroutine f_env_state_ppb_to_conc(ptr_c, ppb, conc) bind(C)
type(env_state_t), pointer :: ptr_f => null()
type(c_ptr), intent(in) :: ptr_c
real(c_double), intent(in) :: ppb
real(c_double), intent(out) :: conc

call c_f_pointer(ptr_c, ptr_f)

conc = env_state_ppb_to_conc(ptr_f, ppb)

end subroutine

subroutine f_env_state_conc_to_ppb(ptr_c, conc, ppb) bind(C)
type(env_state_t), pointer :: ptr_f => null()
type(c_ptr), intent(in) :: ptr_c
real(c_double), intent(out) :: ppb
real(c_double), intent(in) :: conc

call c_f_pointer(ptr_c, ptr_f)

ppb = env_state_conc_to_ppb(ptr_f, conc)

end subroutine

end module
94 changes: 93 additions & 1 deletion src/env_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,15 @@ extern "C" void f_env_state_get_pressure(const void *ptr, double *pressure) noex
extern "C" void f_env_state_get_elapsed_time(const void *ptr, double *elapsed_time) noexcept;
extern "C" void f_env_state_get_start_time(const void *ptr, double *start_time) noexcept;
extern "C" void f_env_state_air_dens(const void *ptr, double *air_density) noexcept;

extern "C" void f_env_state_air_molar_dens(const void *ptr, double *air_molar_density) noexcept;
extern "C" void f_env_state_set_latitude(const void *ptr, const double *latitude) noexcept;
extern "C" void f_env_state_get_latitude(const void *ptr, double *latitude) noexcept;
extern "C" void f_env_state_set_longitude(const void *ptr, const double *longitude) noexcept;
extern "C" void f_env_state_get_longitude(const void *ptr, double *longitude) noexcept;
extern "C" void f_env_state_set_altitude(const void *ptr, const double *altitude) noexcept;
extern "C" void f_env_state_get_altitude(const void *ptr, double *altitude) noexcept;
extern "C" void f_env_state_ppb_to_conc(const void *ptr, const double *ppb, double *conc) noexcept;
extern "C" void f_env_state_conc_to_ppb(const void *ptr, const double *conc, double *ppb) noexcept;

struct EnvState {
PMCResource ptr;
Expand Down Expand Up @@ -148,4 +156,88 @@ struct EnvState {
);
return air_density;
}

static auto air_molar_density(const EnvState &self) {
double air_molar_density;

f_env_state_air_molar_dens(
self.ptr.f_arg(),
&air_molar_density
);
return air_molar_density;
}

static void set_latitude(const EnvState &self, const double latitude) {
f_env_state_set_latitude(
self.ptr.f_arg(),
&latitude
);
}

static auto get_latitude(const EnvState &self) {
double latitude;

f_env_state_get_latitude(
self.ptr.f_arg(),
&latitude
);
return latitude;
}

static void set_longitude(const EnvState &self, const double longitude) {
f_env_state_set_longitude(
self.ptr.f_arg(),
&longitude
);
}

static auto get_longitude(const EnvState &self) {
double longitude;

f_env_state_get_longitude(
self.ptr.f_arg(),
&longitude
);
return longitude;
}

static void set_altitude(const EnvState &self, const double altitude) {
f_env_state_set_altitude(
self.ptr.f_arg(),
&altitude
);
}

static auto get_altitude(const EnvState &self) {
double altitude;

f_env_state_get_altitude(
self.ptr.f_arg(),
&altitude
);
return altitude;
}

static auto ppb_to_conc(const EnvState &self, const double ppb) {
double conc;

f_env_state_ppb_to_conc(
self.ptr.f_arg(),
&ppb,
&conc
);
return conc;
}

static auto conc_to_ppb(const EnvState &self, const double conc) {
double ppb;

f_env_state_conc_to_ppb(
self.ptr.f_arg(),
&conc,
&ppb
);
return ppb;
}

};
10 changes: 10 additions & 0 deletions src/pypartmc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,10 +424,20 @@ NB_MODULE(_PyPartMC, m) {
"Box height (m).")
.def_prop_rw("pressure", &EnvState::get_pressure, &EnvState::set_pressure,
"Ambient pressure (Pa).")
.def_prop_rw("latitude", &EnvState::get_latitude, &EnvState::set_latitude,
"Latitude (degrees).")
.def_prop_rw("longitude", &EnvState::get_longitude, &EnvState::set_longitude,
"Longitude (degrees).")
.def_prop_rw("altitude", &EnvState::get_altitude, &EnvState::set_altitude,
"Altitude (m).")
.def_prop_ro("air_density", &EnvState::air_density,
"Air density (kg m^{-3}).")
.def_prop_ro("air_molar_density", &EnvState::air_molar_density,
"Air molar density (mol m^{-3}).")
.def_prop_rw("additive_kernel_coefficient", &EnvState::get_additive_kernel_coefficient, &EnvState::set_additive_kernel_coefficient,
"Scaling coefficient for additive coagulation kernel.")
.def("ppb_to_conc", &EnvState::ppb_to_conc, "Convert (ppb) to (molecules m^{-3}).")
.def("conc_to_ppb", &EnvState::conc_to_ppb, "Convert (molecules m^{-3}) to (ppb).")
;

nb::class_<Photolysis>(m,
Expand Down
72 changes: 72 additions & 0 deletions tests/test_env_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import gc

import numpy as np
import pytest

import PyPartMC as ppmc
Expand Down Expand Up @@ -72,6 +73,42 @@ def test_pressure():
# assert
assert value == sut.pressure

@staticmethod
def test_latitude():
# arrange
sut = ppmc.EnvState(ENV_STATE_CTOR_ARG_MINIMAL)
value = 40.0

# act
sut.latitude = value

# assert
assert value == sut.latitude

@staticmethod
def test_longitude():
# arrange
sut = ppmc.EnvState(ENV_STATE_CTOR_ARG_MINIMAL)
value = 180.0

# act
sut.longitude = value

# assert
assert value == sut.longitude

@staticmethod
def test_altitude():
# arrange
sut = ppmc.EnvState(ENV_STATE_CTOR_ARG_MINIMAL)
value = 200.0

# act
sut.altitude = value

# assert
assert value == sut.altitude

@staticmethod
def test_additive_kernel_coefficient():
# arrange
Expand Down Expand Up @@ -119,3 +156,38 @@ def test_air_density():

# assert
assert 1 * si.kg / si.m**3 < env_state.air_density < 1.5 * si.kg / si.m**3

@staticmethod
def test_air_molar_density():
# arrange
gas_data = ppmc.GasData(GAS_DATA_CTOR_ARG_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)

# assert
assert (
1 * si.mol / si.m**3 < env_state.air_molar_density < 100 * si.mol / si.m**3
)

@staticmethod
def test_conc_ppb_conversions():
# arrange
gas_data = ppmc.GasData(GAS_DATA_CTOR_ARG_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)

# act
conc_orig = 1.0
ppb = env_state.conc_to_ppb(conc_orig)
ppb_orig = 1.0
conc = env_state.ppb_to_conc(ppb_orig)

# assert
assert ppb < conc_orig
assert ppb_orig < conc
np.testing.assert_almost_equal(env_state.ppb_to_conc(ppb), conc_orig)
np.testing.assert_almost_equal(env_state.conc_to_ppb(conc), ppb_orig)
Loading