Skip to content

Commit 52e9f73

Browse files
jcurtis2slayoo
andauthored
Access to more information in aero_particle (+ execute rand_init before each test, not just once per test session) (#286)
Co-authored-by: Sylwester Arabas <[email protected]>
1 parent cad317d commit 52e9f73

File tree

8 files changed

+422
-2
lines changed

8 files changed

+422
-2
lines changed

src/aero_data.F90

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,15 @@ subroutine f_aero_data_get_species_density(ptr_c, idx, val) bind(C)
185185

186186
end subroutine
187187

188+
subroutine f_aero_data_n_source(ptr_c, n_source) bind(C)
189+
type(aero_data_t), pointer :: ptr_f => null()
190+
type(c_ptr), intent(in) :: ptr_c
191+
integer(c_int) :: n_source
192+
193+
call c_f_pointer(ptr_c, ptr_f)
194+
195+
n_source = aero_data_n_source(ptr_f)
196+
197+
end subroutine
198+
188199
end module

src/aero_data.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ extern "C" void f_aero_data_dtor(void *ptr) noexcept;
1414
extern "C" void f_aero_data_from_json(const void *ptr) noexcept;
1515
extern "C" void f_aero_data_spec_by_name(const void *ptr, int *value, const char *name_data, const int *name_size) noexcept;
1616
extern "C" void f_aero_data_len(const void *ptr, int *len) noexcept;
17+
extern "C" void f_aero_data_n_source(const void *ptr, int *len) noexcept;
1718
extern "C" void f_aero_data_set_frac_dim(void *ptr, const double*) noexcept;
1819
extern "C" void f_aero_data_get_frac_dim(const void *ptr, double*) noexcept;
1920
extern "C" void f_aero_data_set_vol_fill_factor(void *ptr, const double*) noexcept;
@@ -193,5 +194,16 @@ struct AeroData {
193194
return data;
194195
}
195196

197+
static std::size_t n_source(const AeroData &self) {
198+
int len;
199+
f_aero_data_n_source(
200+
self.ptr.f_arg(),
201+
&len
202+
);
203+
if (len == -1)
204+
throw std::runtime_error("No sources defined.");
205+
return len;
206+
}
207+
196208
};
197209

src/aero_particle.F90

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,4 +387,141 @@ subroutine f_aero_particle_set_vols( &
387387
)
388388
end subroutine
389389

390+
subroutine f_aero_particle_absorb_cross_sect( &
391+
aero_particle_ptr_c, &
392+
absorb_cross_sect &
393+
) bind(C)
394+
395+
type(aero_particle_t), pointer :: aero_particle_ptr_f => null()
396+
type(c_ptr), intent(in) :: aero_particle_ptr_c
397+
real(c_double), intent(out) :: absorb_cross_sect
398+
399+
call c_f_pointer(aero_particle_ptr_c, aero_particle_ptr_f)
400+
401+
absorb_cross_sect = aero_particle_ptr_f%absorb_cross_sect
402+
403+
end subroutine
404+
405+
subroutine f_aero_particle_scatter_cross_sect( &
406+
aero_particle_ptr_c, &
407+
scatter_cross_sect &
408+
) bind(C)
409+
410+
type(aero_particle_t), pointer :: aero_particle_ptr_f => null()
411+
type(c_ptr), intent(in) :: aero_particle_ptr_c
412+
real(c_double), intent(out) :: scatter_cross_sect
413+
414+
call c_f_pointer(aero_particle_ptr_c, aero_particle_ptr_f)
415+
416+
scatter_cross_sect = aero_particle_ptr_f%scatter_cross_sect
417+
418+
end subroutine
419+
420+
subroutine f_aero_particle_asymmetry( &
421+
aero_particle_ptr_c, &
422+
asymmetry &
423+
) bind(C)
424+
425+
type(aero_particle_t), pointer :: aero_particle_ptr_f => null()
426+
type(c_ptr), intent(in) :: aero_particle_ptr_c
427+
real(c_double), intent(out) :: asymmetry
428+
429+
call c_f_pointer(aero_particle_ptr_c, aero_particle_ptr_f)
430+
431+
asymmetry = aero_particle_ptr_f%asymmetry
432+
433+
end subroutine
434+
435+
subroutine f_aero_particle_greatest_create_time( &
436+
aero_particle_ptr_c, &
437+
greatest_create_time &
438+
) bind(C)
439+
440+
type(aero_particle_t), pointer :: aero_particle_ptr_f => null()
441+
type(c_ptr), intent(in) :: aero_particle_ptr_c
442+
real(c_double), intent(out) :: greatest_create_time
443+
444+
call c_f_pointer(aero_particle_ptr_c, aero_particle_ptr_f)
445+
446+
greatest_create_time = aero_particle_ptr_f%greatest_create_time
447+
448+
end subroutine
449+
450+
subroutine f_aero_particle_least_create_time( &
451+
aero_particle_ptr_c, &
452+
least_create_time &
453+
) bind(C)
454+
455+
type(aero_particle_t), pointer :: aero_particle_ptr_f => null()
456+
type(c_ptr), intent(in) :: aero_particle_ptr_c
457+
real(c_double), intent(out) :: least_create_time
458+
459+
call c_f_pointer(aero_particle_ptr_c, aero_particle_ptr_f)
460+
461+
least_create_time = aero_particle_ptr_f%least_create_time
462+
463+
end subroutine
464+
465+
subroutine f_aero_particle_n_orig_part( &
466+
aero_particle_ptr_c, &
467+
n_orig_part, &
468+
n_orig_part_size &
469+
) bind(C)
470+
471+
type(aero_particle_t), pointer :: aero_particle_ptr_f => null()
472+
type(c_ptr), intent(in) :: aero_particle_ptr_c
473+
integer(c_int), intent(in) :: n_orig_part_size
474+
integer(c_int), dimension(n_orig_part_size), intent(out) :: n_orig_part
475+
476+
call c_f_pointer(aero_particle_ptr_c, aero_particle_ptr_f)
477+
478+
n_orig_part = aero_particle_ptr_f%n_orig_part
479+
480+
end subroutine
481+
482+
subroutine f_aero_particle_id( &
483+
aero_particle_ptr_c, &
484+
id &
485+
) bind(C)
486+
487+
type(aero_particle_t), pointer :: aero_particle_ptr_f => null()
488+
type(c_ptr), intent(in) :: aero_particle_ptr_c
489+
integer(c_int), intent(out) :: id
490+
491+
call c_f_pointer(aero_particle_ptr_c, aero_particle_ptr_f)
492+
493+
id = aero_particle_ptr_f%id
494+
495+
end subroutine
496+
497+
subroutine f_aero_particle_refract_shell( &
498+
aero_particle_ptr_c, &
499+
refract_shell &
500+
) bind(C)
501+
502+
type(aero_particle_t), pointer :: aero_particle_ptr_f => null()
503+
type(c_ptr), intent(in) :: aero_particle_ptr_c
504+
complex(c_double_complex), intent(out) :: refract_shell
505+
506+
call c_f_pointer(aero_particle_ptr_c, aero_particle_ptr_f)
507+
508+
refract_shell = aero_particle_ptr_f%refract_shell
509+
510+
end subroutine
511+
512+
subroutine f_aero_particle_refract_core( &
513+
aero_particle_ptr_c, &
514+
refract_core &
515+
) bind(C)
516+
517+
type(aero_particle_t), pointer :: aero_particle_ptr_f => null()
518+
type(c_ptr), intent(in) :: aero_particle_ptr_c
519+
complex(c_double_complex), intent(out) :: refract_core
520+
521+
call c_f_pointer(aero_particle_ptr_c, aero_particle_ptr_f)
522+
523+
refract_core = aero_particle_ptr_f%refract_core
524+
525+
end subroutine
526+
390527
end module

src/aero_particle.hpp

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "aero_data.hpp"
1111
#include "env_state.hpp"
1212
#include "pybind11/stl.h"
13+
#include <complex>
1314

1415
extern "C" void f_aero_particle_ctor(void *ptr) noexcept;
1516
extern "C" void f_aero_particle_dtor(void *ptr) noexcept;
@@ -35,6 +36,15 @@ extern "C" void f_aero_particle_crit_diameter(const void *aero_particle_ptr, con
3536
extern "C" void f_aero_particle_coagulate(const void *aero_particle_1_ptr, const void *aero_particle_2_ptr, void *new_particle_ptr) noexcept;
3637
extern "C" void f_aero_particle_zero(void *aero_particle_ptr, const void *aero_data_ptr) noexcept;
3738
extern "C" void f_aero_particle_set_vols(void *aero_particle_ptr, const int *vol_size, const void *volumes) noexcept;
39+
extern "C" void f_aero_particle_absorb_cross_sect(const void *aero_particle_ptr, double *val) noexcept;
40+
extern "C" void f_aero_particle_scatter_cross_sect(const void *aero_particle_ptr, double *val) noexcept;
41+
extern "C" void f_aero_particle_asymmetry(const void *aero_particle_ptr, double *val) noexcept;
42+
extern "C" void f_aero_particle_greatest_create_time(const void *aero_particle_ptr, double *val) noexcept;
43+
extern "C" void f_aero_particle_least_create_time(const void *aero_particle_ptr, double *val) noexcept;
44+
extern "C" void f_aero_particle_n_orig_part(const void *aero_particle_ptr, void *arr_data, const int *arr_size) noexcept;
45+
extern "C" void f_aero_particle_id(const void *aero_particle_ptr, int *val) noexcept;
46+
extern "C" void f_aero_particle_refract_shell(const void *aero_particle_ptr, std::complex<double> *val) noexcept;
47+
extern "C" void f_aero_particle_refract_core(const void *aero_particle_ptr, std::complex<double> *val) noexcept;
3848

3949
namespace py = pybind11;
4050
struct AeroParticle {
@@ -272,4 +282,87 @@ struct AeroParticle {
272282
);
273283
}
274284

275-
};
285+
static auto scatter_cross_sect(const AeroParticle &self) {
286+
double val;
287+
f_aero_particle_scatter_cross_sect(
288+
self.ptr.f_arg(),
289+
&val
290+
);
291+
return val;
292+
}
293+
294+
static auto absorb_cross_sect(const AeroParticle &self) {
295+
double val;
296+
f_aero_particle_absorb_cross_sect(
297+
self.ptr.f_arg(),
298+
&val
299+
);
300+
return val;
301+
}
302+
303+
static auto asymmetry(const AeroParticle &self) {
304+
double val;
305+
f_aero_particle_asymmetry(
306+
self.ptr.f_arg(),
307+
&val
308+
);
309+
return val;
310+
}
311+
312+
static auto n_orig_part(const AeroParticle &self) {
313+
int len = AeroData::n_source(*self.aero_data);
314+
std::valarray<int> data(len);
315+
316+
f_aero_particle_n_orig_part(
317+
self.ptr.f_arg(),
318+
begin(data),
319+
&len
320+
);
321+
return data;
322+
}
323+
324+
static auto least_create_time(const AeroParticle &self) {
325+
double val;
326+
f_aero_particle_least_create_time(
327+
self.ptr.f_arg(),
328+
&val
329+
);
330+
return val;
331+
}
332+
333+
static auto greatest_create_time(const AeroParticle &self) {
334+
double val;
335+
f_aero_particle_greatest_create_time(
336+
self.ptr.f_arg(),
337+
&val
338+
);
339+
return val;
340+
}
341+
342+
static auto id(const AeroParticle &self) {
343+
int val;
344+
f_aero_particle_id(
345+
self.ptr.f_arg(),
346+
&val
347+
);
348+
return val;
349+
}
350+
351+
static auto refract_shell(const AeroParticle &self) {
352+
std::complex<double> refract_shell;
353+
f_aero_particle_refract_shell(
354+
self.ptr.f_arg(),
355+
&refract_shell
356+
);
357+
return refract_shell;
358+
}
359+
360+
static auto refract_core(const AeroParticle &self) {
361+
std::complex<double> refract_core;
362+
f_aero_particle_refract_core(
363+
self.ptr.f_arg(),
364+
&refract_core
365+
);
366+
return refract_core;
367+
}
368+
};

src/pypartmc.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "pybind11/pybind11.h"
88
#include "nlohmann/json.hpp"
99
#include "pybind11_json/pybind11_json.hpp"
10+
#include "pybind11/complex.h"
1011

1112
#include "util.hpp"
1213
#include "rand.hpp"
@@ -76,6 +77,7 @@ PYBIND11_MODULE(_PyPartMC, m) {
7677
.def(py::init<const nlohmann::json&>())
7778
.def("spec_by_name", AeroData::spec_by_name)
7879
.def("__len__", AeroData::__len__)
80+
.def_property_readonly("n_source", AeroData::n_source)
7981
.def_property("frac_dim", &AeroData::get_frac_dim, &AeroData::set_frac_dim)
8082
.def_property("vol_fill_factor", &AeroData::get_vol_fill_factor, &AeroData::set_vol_fill_factor)
8183
.def_property("prime_radius", &AeroData::get_prime_radius, &AeroData::set_prime_radius)
@@ -128,6 +130,23 @@ PYBIND11_MODULE(_PyPartMC, m) {
128130
"Returns the average of the solute kappas (1).")
129131
.def_property_readonly("moles", AeroParticle::moles,
130132
"Total moles in the particle (1).")
133+
.def_property_readonly("absorb_cross_sect", AeroParticle::absorb_cross_sect,
134+
"Absorption cross-section (m^-2).")
135+
.def_property_readonly("scatter_cross_sect", AeroParticle::scatter_cross_sect,
136+
"Scattering cross-section (m^-2).")
137+
.def_property_readonly("asymmetry", AeroParticle::asymmetry,
138+
"Asymmetry parameter (1).")
139+
.def_property_readonly("refract_shell", AeroParticle::refract_shell,
140+
"Refractive index of the shell (1).")
141+
.def_property_readonly("refract_core", AeroParticle::refract_core,
142+
"Refractive index of the core (1).")
143+
.def_property_readonly("n_orig_part", AeroParticle::n_orig_part,
144+
"Number of original particles from each source that coagulated to form particle.")
145+
.def_property_readonly("least_create_time", AeroParticle::least_create_time,
146+
"First time a constituent was created (s).")
147+
.def_property_readonly("greatest_create_time", AeroParticle::greatest_create_time,
148+
"Last time a constituent was created (s).")
149+
.def_property_readonly("id", AeroParticle::id, "Unique ID number.")
131150
.def("mobility_diameter", AeroParticle::mobility_diameter,
132151
"Mobility diameter of the particle (m).")
133152
.def_property_readonly("density", AeroParticle::density,

tests/conftest.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import pytest
2+
13
import PyPartMC as ppmc
24

3-
ppmc.rand_init(44)
5+
6+
@pytest.fixture(autouse=True)
7+
def rand_init():
8+
ppmc.rand_init(44)

tests/test_aero_data.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,3 +362,15 @@ def test_ctor_error_on_nonunique_keys():
362362

363363
# assert
364364
assert str(exc_info.value) == "Species names must be unique"
365+
366+
@staticmethod
367+
def test_n_source_uninitialized():
368+
# arrange
369+
sut = ppmc.AeroData(AERO_DATA_CTOR_ARG_FULL)
370+
371+
# act
372+
with pytest.raises(Exception) as exc_info:
373+
_ = sut.n_source
374+
375+
# assert
376+
assert str(exc_info.value) == "No sources defined."

0 commit comments

Comments
 (0)