Skip to content

Commit c117d01

Browse files
jcurtis2slayoo
andauthored
added ability to get a particle from an aero_state (#187)
Co-authored-by: Sylwester Arabas <[email protected]>
1 parent 14f66e6 commit c117d01

File tree

4 files changed

+123
-0
lines changed

4 files changed

+123
-0
lines changed

src/aero_state.F90

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,4 +276,32 @@ subroutine f_aero_state_copy(ptr_c,ptr_new_c) bind(C)
276276
ptr_new_f = ptr_f
277277
end subroutine
278278

279+
subroutine f_aero_state_particle(ptr_c, ptr_particle_c, index) bind(C)
280+
type(c_ptr) :: ptr_c, ptr_particle_c
281+
integer(c_int) :: index
282+
type(aero_state_t), pointer :: ptr_f => null()
283+
type(aero_particle_t), pointer :: ptr_particle_f => null()
284+
285+
call c_f_pointer(ptr_c,ptr_f)
286+
call c_f_pointer(ptr_particle_c, ptr_particle_f)
287+
288+
ptr_particle_f = ptr_f%apa%particle(index + 1)
289+
290+
end subroutine
291+
292+
subroutine f_aero_state_rand_particle(ptr_c, ptr_particle_c) bind(C)
293+
type(c_ptr) :: ptr_c, ptr_particle_c
294+
integer(c_int) :: index
295+
type(aero_state_t), pointer :: ptr_f => null()
296+
type(aero_particle_t), pointer :: ptr_particle_f => null()
297+
298+
call c_f_pointer(ptr_c,ptr_f)
299+
call c_f_pointer(ptr_particle_c, ptr_particle_f)
300+
301+
call aero_state_rand_particle(ptr_f, index)
302+
303+
ptr_particle_f = ptr_f%apa%particle(index)
304+
305+
end subroutine
306+
279307
end module

src/aero_state.hpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "pmc_resource.hpp"
1010
#include "aero_data.hpp"
11+
#include "aero_particle.hpp"
1112
#include "env_state.hpp"
1213
#include "bin_grid.hpp"
1314
#include "pybind11/stl.h"
@@ -104,6 +105,17 @@ extern "C" void f_aero_state_copy(
104105
const void *aero_dataptr
105106
) noexcept;
106107

108+
extern "C" void f_aero_state_particle(
109+
const void *ptr_c,
110+
const void *ptr_particle_c,
111+
const int *index
112+
) noexcept;
113+
114+
extern "C" void f_aero_state_rand_particle(
115+
const void *ptr_c,
116+
const void *ptr_particle_c
117+
) noexcept;
118+
107119
struct AeroState {
108120
PMCResource ptr;
109121
std::shared_ptr<AeroData> aero_data;
@@ -315,4 +327,31 @@ struct AeroState {
315327
);
316328
return ptr;
317329
}
330+
331+
static AeroParticle* get_particle(
332+
const AeroState &self,
333+
const int &idx
334+
) {
335+
int len = AeroData::__len__(*self.aero_data);
336+
std::valarray<double> data(len);
337+
338+
AeroParticle *ptr = new AeroParticle(self.aero_data, data);
339+
if (idx < 0 || idx >= (int)__len__(self))
340+
throw std::out_of_range("Index out of range");
341+
f_aero_state_particle(self.ptr.f_arg(), ptr, &idx);
342+
343+
return ptr;
344+
}
345+
346+
static AeroParticle* get_random_particle(
347+
const AeroState &self
348+
) {
349+
int len = AeroData::__len__(*self.aero_data);
350+
std::valarray<double> data(len);
351+
352+
AeroParticle *ptr = new AeroParticle(self.aero_data, data);
353+
f_aero_state_rand_particle(self.ptr.f_arg(), ptr);
354+
355+
return ptr;
356+
}
318357
};

src/pypartmc.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ PYBIND11_MODULE(_PyPartMC, m) {
161161
"returns the mixing state parameters (chi,d_alpha,d_gamma) of the population")
162162
.def("bin_average_comp", AeroState::bin_average_comp,
163163
"composition-averages population using BinGrid")
164+
.def("particle", AeroState::get_particle,
165+
"returns the particle of a given index")
166+
.def("rand_particle", AeroState::get_random_particle,
167+
"returns a random particle from the population")
164168
;
165169

166170
py::class_<GasData, std::shared_ptr<GasData>>(m, "GasData",

tests/test_aero_state.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,55 @@ def test_bin_average_comp(sut_minimal): # pylint: disable=redefined-outer-name
162162

163163
# assert
164164
# TODO #179
165+
166+
@staticmethod
167+
def test_get_particle(sut_minimal): # pylint: disable=redefined-outer-name
168+
# act
169+
particle = sut_minimal.particle(1)
170+
171+
# assert
172+
assert isinstance(particle, ppmc.AeroParticle)
173+
174+
@staticmethod
175+
def test_get_random_particle(sut_minimal): # pylint: disable=redefined-outer-name
176+
# act
177+
particle = sut_minimal.rand_particle()
178+
179+
# assert
180+
assert isinstance(particle, ppmc.AeroParticle)
181+
182+
@staticmethod
183+
def test_check_correct_particle(
184+
sut_minimal,
185+
): # pylint: disable=redefined-outer-name
186+
# act
187+
i_part = 20
188+
particle = sut_minimal.particle(i_part)
189+
diameters = sut_minimal.diameters
190+
191+
# assert
192+
assert particle.diameter == diameters[i_part]
193+
194+
@staticmethod
195+
def test_different_particles(sut_minimal): # pylint: disable=redefined-outer-name
196+
# act
197+
i_part = 20
198+
particle_1 = sut_minimal.particle(i_part)
199+
particle_2 = sut_minimal.particle(i_part + 1)
200+
201+
# assert
202+
assert particle_1.diameter != particle_2.diameter
203+
204+
@staticmethod
205+
@pytest.mark.parametrize("idx", (-1, 500))
206+
def test_get_item_out_of_range(
207+
sut_minimal, idx
208+
): # pylint: disable=redefined-outer-name
209+
# act
210+
try:
211+
_ = sut_minimal.particle(idx)
212+
except IndexError:
213+
return
214+
215+
# assert
216+
assert False

0 commit comments

Comments
 (0)