Skip to content

Commit d0d1121

Browse files
jcurtis2slayoo
andauthored
Add ability to run a PartMC simulation in notebook (#191)
Co-authored-by: Sylwester Arabas <[email protected]>
1 parent 7a0e602 commit d0d1121

21 files changed

+571
-143
lines changed

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
shallow = true
55
[submodule "partmc"]
66
path = gitmodules/partmc
7-
url = https://github.com/slayoo/partmc
7+
url = https://github.com/compdyn/partmc
88
shallow = true
99
[submodule "pybind11_json"]
1010
path = gitmodules/pybind11_json

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ default_stages: [commit]
44

55
repos:
66
- repo: https://github.com/psf/black
7-
rev: 22.6.0
7+
rev: 23.1.0
88
hooks:
99
- id: black
1010

1111
- repo: https://github.com/timothycrosley/isort
12-
rev: 5.10.1
12+
rev: 5.12.0
1313
hooks:
1414
- id: isort
1515
args: ["--profile", "black"]
1616

1717
- repo: https://github.com/pre-commit/pre-commit-hooks
18-
rev: v4.3.0
18+
rev: v4.4.0
1919
hooks:
2020
- id: trailing-whitespace
2121
- id: end-of-file-fixer

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
####################################################################################################
66

77
cmake_minimum_required(VERSION 3.4...3.18)
8+
9+
if (NOT EXISTS "${CMAKE_SOURCE_DIR}/gitmodules/pybind11/include/pybind11/pybind11.h" )
10+
message(FATAL_ERROR "git submodules not initialised.\n Please run `git submodule update --init`")
11+
endif()
12+
813
project(_PyPartMC LANGUAGES C CXX Fortran)
914

1015
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,6 @@ No CMAKE_Fortran_COMPILER could be found.
9292
```
9393
Try installing a Fortran compiler (e.g., `brew reinstall gcc`)
9494

95-
```
96-
warning: no files found matching 'gitmodules/...
97-
```
98-
Since git clone was done without recursive option, try: `git submodule update --init`
9995

10096
## Notes for developers
10197
#### How to debug

setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ def build_extension(self, ext): # pylint: disable=too-many-branches
7777
pass
7878

7979
else:
80-
8180
# Single config generators are handled "normally"
8281
single_config = any(x in cmake_generator for x in ("NMake", "Ninja"))
8382

src/aero_state.F90

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -42,50 +42,56 @@ subroutine f_aero_state_init(ptr_c, n_part, aero_data_ptr_c) bind(C)
4242
character(len=10), parameter, dimension(2) :: mode_names = ["init_small","init_large"]
4343
integer :: n_spec, n_modes, i_mode, i_spec
4444
integer :: n_part_added, source
45+
logical, parameter :: hardcoded_init = .true.
4546

4647
call c_f_pointer(ptr_c, ptr_f)
4748
call c_f_pointer(aero_data_ptr_c, aero_data_ptr_f)
4849

4950
call aero_state_zero(ptr_f)
50-
call aero_state_set_weight(ptr_f, aero_data_ptr_f, AERO_STATE_WEIGHT_FLAT)
51-
call aero_state_set_n_part_ideal(ptr_f, n_part)
52-
5351
call fractal_set_spherical(aero_data_ptr_f%fractal)
5452

55-
n_modes = 2 ! TODO #141
56-
n_spec = aero_data_n_spec(aero_data_ptr_f)
57-
if (n_spec > 1) then
58-
allocate(aero_dist_init%mode(n_modes))
59-
do i_mode = 1,n_modes
60-
aero_dist_init%mode(i_mode)%name = mode_names(i_mode)
61-
aero_dist_init%mode(i_mode)%type = AERO_MODE_TYPE_LOG_NORMAL
62-
aero_dist_init%mode(i_mode)%char_radius = diams(i_mode) / 2
63-
aero_dist_init%mode(i_mode)%log10_std_dev_radius = &
64-
log10(std(i_mode))
65-
aero_dist_init%mode(i_mode)%num_conc = num_conc(i_mode)
66-
allocate(aero_dist_init%mode(i_mode)%vol_frac(n_spec))
67-
aero_dist_init%mode(i_mode)%vol_frac = 0.0
68-
if (i_mode == 1) then
69-
i_spec = aero_data_spec_by_name(aero_data_ptr_f, "SO4")
70-
aero_dist_init%mode(i_mode)%vol_frac(i_spec) = 1.0
71-
else
72-
i_spec = aero_data_spec_by_name(aero_data_ptr_f, "OC")
73-
aero_dist_init%mode(i_mode)%vol_frac(i_spec) = .8
74-
i_spec = aero_data_spec_by_name(aero_data_ptr_f, "BC")
75-
aero_dist_init%mode(i_mode)%vol_frac(i_spec) = .2
53+
if (hardcoded_init) then
54+
n_modes = 2 ! TODO #141
55+
n_spec = aero_data_n_spec(aero_data_ptr_f)
56+
if (n_spec > 1) then
57+
allocate(aero_dist_init%mode(n_modes))
58+
do i_mode = 1,n_modes
59+
aero_dist_init%mode(i_mode)%name = mode_names(i_mode)
60+
aero_dist_init%mode(i_mode)%type = AERO_MODE_TYPE_LOG_NORMAL
61+
aero_dist_init%mode(i_mode)%char_radius = diams(i_mode) / 2
62+
aero_dist_init%mode(i_mode)%log10_std_dev_radius = &
63+
log10(std(i_mode))
64+
aero_dist_init%mode(i_mode)%num_conc = num_conc(i_mode)
65+
allocate(aero_dist_init%mode(i_mode)%vol_frac(n_spec))
66+
aero_dist_init%mode(i_mode)%vol_frac = 0.0
67+
if (i_mode == 1) then
68+
i_spec = aero_data_spec_by_name(aero_data_ptr_f, "SO4")
69+
aero_dist_init%mode(i_mode)%vol_frac(i_spec) = 1.0
70+
else
71+
i_spec = aero_data_spec_by_name(aero_data_ptr_f, "OC")
72+
aero_dist_init%mode(i_mode)%vol_frac(i_spec) = .8
73+
i_spec = aero_data_spec_by_name(aero_data_ptr_f, "BC")
74+
aero_dist_init%mode(i_mode)%vol_frac(i_spec) = .2
75+
end if
76+
allocate(aero_dist_init%mode(i_mode)%vol_frac_std(n_spec))
77+
aero_dist_init%mode(i_mode)%vol_frac_std = 0.0
78+
source = aero_data_source_by_name(aero_data_ptr_f, mode_names(i_mode))
79+
aero_dist_init%mode(i_mode)%source = source
80+
end do
7681
end if
77-
allocate(aero_dist_init%mode(i_mode)%vol_frac_std(n_spec))
78-
aero_dist_init%mode(i_mode)%vol_frac_std = 0.0
79-
source = aero_data_source_by_name(aero_data_ptr_f, mode_names(i_mode))
80-
aero_dist_init%mode(i_mode)%source = source
81-
end do
82-
83-
call aero_state_add_aero_dist_sample(ptr_f, aero_data_ptr_f, &
84-
aero_dist_init, 1d0, 0d0, &
85-
.true., & ! TODO #121 run_part_opt%allow_doubling, &
86-
.true., & ! TODO #121 run_part_opt%allow_halving)
87-
n_part_added)
8882
end if
83+
84+
call aero_state_set_weight(ptr_f, aero_data_ptr_f, AERO_STATE_WEIGHT_NUMMASS_SOURCE)
85+
call aero_state_set_n_part_ideal(ptr_f, n_part)
86+
87+
if (hardcoded_init) then
88+
call aero_state_add_aero_dist_sample(ptr_f, aero_data_ptr_f, &
89+
aero_dist_init, 1d0, 0d0, &
90+
.true., & ! TODO #121 run_part_opt%allow_doubling, &
91+
.true., & ! TODO #121 run_part_opt%allow_halving)
92+
n_part_added)
93+
end if
94+
8995
end subroutine
9096

9197
subroutine f_aero_state_len(ptr_c, len) bind(C)

src/env_state.F90

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ subroutine f_env_state_ctor(ptr_c) bind(C)
1717
type(c_ptr), intent(out) :: ptr_c
1818

1919
allocate(ptr_f)
20+
ptr_f%elapsed_time = 0
2021
ptr_c = c_loc(ptr_f)
2122
end subroutine
2223

@@ -115,4 +116,26 @@ subroutine f_env_state_get_pressure(ptr_c, pressure) bind(C)
115116

116117
end subroutine
117118

119+
subroutine f_env_state_get_elapsed_time(ptr_c, elapsed_time) bind(C)
120+
type(env_state_t), pointer :: ptr_f => null()
121+
type(c_ptr), intent(in) :: ptr_c
122+
real(c_double), intent(out) :: elapsed_time
123+
124+
call c_f_pointer(ptr_c, ptr_f)
125+
126+
elapsed_time = ptr_f%elapsed_time
127+
128+
end subroutine
129+
130+
subroutine f_env_state_get_start_time(ptr_c, start_time) bind(C)
131+
type(env_state_t), pointer :: ptr_f => null()
132+
type(c_ptr), intent(in) :: ptr_c
133+
real(c_double), intent(out) :: start_time
134+
135+
call c_f_pointer(ptr_c, ptr_f)
136+
137+
start_time = ptr_f%start_time
138+
139+
end subroutine
140+
118141
end module

src/env_state.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ extern "C" void f_env_state_set_height(const void *ptr, const double *height) no
1919
extern "C" void f_env_state_get_height(const void *ptr, double *height) noexcept;
2020
extern "C" void f_env_state_set_pressure(const void *ptr, const double *pressure) noexcept;
2121
extern "C" void f_env_state_get_pressure(const void *ptr, double *pressure) noexcept;
22+
extern "C" void f_env_state_get_elapsed_time(const void *ptr, double *elapsed_time) noexcept;
23+
extern "C" void f_env_state_get_start_time(const void *ptr, double *start_time) noexcept;
24+
2225

2326
struct EnvState {
2427
PMCResource ptr;
@@ -91,4 +94,24 @@ struct EnvState {
9194
);
9295
return pressure;
9396
}
97+
98+
static auto get_elapsed_time(const EnvState &self) {
99+
double elapsed_time;
100+
101+
f_env_state_get_elapsed_time(
102+
self.ptr.f_arg(),
103+
&elapsed_time
104+
);
105+
return elapsed_time;
106+
}
107+
108+
static auto get_start_time(const EnvState &self) {
109+
double start_time;
110+
111+
f_env_state_get_start_time(
112+
self.ptr.f_arg(),
113+
&start_time
114+
);
115+
return start_time;
116+
}
94117
};

src/pypartmc.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ PYBIND11_MODULE(_PyPartMC, m) {
3434
)pbdoc";
3535

3636
m.def("run_part", &run_part, "Do a particle-resolved Monte Carlo simulation.");
37+
m.def("run_part_timestep", &run_part_timestep, "Do a single time step");
38+
m.def("run_part_timeblock", &run_part_timeblock, "Do a time block");
3739
m.def("condense_equilib_particles", &condense_equilib_particles, R"pbdoc(
3840
Call condense_equilib_particle() on each particle in the aerosol
3941
to ensure that every particle has its water content in
@@ -205,6 +207,10 @@ PYBIND11_MODULE(_PyPartMC, m) {
205207
"returns the current temperature of the environment state")
206208
.def_property_readonly("rh", EnvState::rh,
207209
"returns the current relative humidity of the environment state")
210+
.def_property_readonly("elapsed_time", EnvState::get_elapsed_time,
211+
"returns time since start_time (s).")
212+
.def_property_readonly("start_time", EnvState::get_start_time,
213+
"returns start time (s since 00:00 UTC on start_day)")
208214
.def_property("height", &EnvState::get_height, &EnvState::set_height)
209215
.def_property("pressure", &EnvState::get_pressure, &EnvState::set_pressure)
210216
;
@@ -251,6 +257,8 @@ PYBIND11_MODULE(_PyPartMC, m) {
251257
)
252258
.def("__str__", Scenario::__str__,
253259
"returns a string with JSON representation of the object")
260+
.def("init_env_state", Scenario::init_env_state,
261+
"initializes the EnvState")
254262
;
255263

256264
py::class_<GasState>(m,
@@ -386,6 +394,8 @@ PYBIND11_MODULE(_PyPartMC, m) {
386394
"Scenario",
387395
"condense_equilib_particles",
388396
"run_part",
397+
"run_part_timeblock",
398+
"run_part_timestep",
389399
"pow2_above",
390400
"condense_equilib_particle",
391401
"histogram_1d",

0 commit comments

Comments
 (0)