Skip to content

Commit f23beec

Browse files
authored
bin_grid news incl. tests (kudos @jcurtis2); tests/pypi workflow cleanup (DLL loading); fix dll path in __init__.py
1 parent 5c71d59 commit f23beec

File tree

7 files changed

+279
-20
lines changed

7 files changed

+279
-20
lines changed

.github/workflows/tests+artifacts+pypi.yml

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,7 @@ jobs:
5454
with:
5555
python-version: ${{ matrix.python-version }}
5656

57-
- run: pip install pytest build
58-
59-
- run: DEBUG=1 VERBOSE=1 pip install --verbose -e .
60-
61-
- run: pytest -v -s -We -p no:unraisableexception tests
62-
63-
- run: DEBUG=0 VERBOSE=1 pip install --verbose -e .
64-
65-
- run: pytest -v -s -We -p no:unraisableexception tests
57+
- run: pip install pytest build wheel
6658

6759
- run: |
6860
python -m build 2>&1 | tee build.log
@@ -71,12 +63,6 @@ jobs:
7163
- if: matrix.platform == 'ubuntu-latest'
7264
run: rm dist/*
7365

74-
- if: matrix.platform != 'ubuntu-latest'
75-
uses: actions/upload-artifact@v2
76-
with:
77-
name: dist
78-
path: dist
79-
8066
- if: matrix.platform == 'ubuntu-latest'
8167
run: python -c "import sys; vi=sys.version_info; abitag='m' if vi.minor<8 else ''; print(f'PV=cp{vi.major}{vi.minor}-cp{vi.major}{vi.minor}{abitag}')" >> $GITHUB_ENV
8268

@@ -88,11 +74,39 @@ jobs:
8874
pre-build-command: 'git config --global --add safe.directory "*"'
8975

9076
- if: matrix.platform == 'ubuntu-latest'
91-
uses: actions/upload-artifact@v2
77+
run: rm dist/*-linux_*
78+
79+
- uses: actions/upload-artifact@v2
9280
with:
9381
name: dist
94-
path: dist/*-manylinux*.whl
82+
path: dist
83+
84+
# TODO: should be doable on any OS
85+
- if: matrix.platform == 'windows-latest' || matrix.platform == 'ubuntu-latest'
86+
run: |
87+
pip install dist/*.whl
88+
pip show --verbose PyPartMC
9589
90+
- if: startsWith(matrix.platform, 'macos-')
91+
run: |
92+
DEBUG=0 VERBOSE=1 pip install --verbose -e .
93+
94+
### make sure PyPartMC is not picked up from a local folder
95+
- run: |
96+
cd tests
97+
python -v -c "import PyPartMC"
98+
pytest -v -s -We -p no:unraisableexception .
99+
100+
# TODO: worth checking but perhaps in a separater workflow? (here conflicts with build dir created for manylinux by other user)
101+
# - run: DEBUG=1 VERBOSE=1 pip install --verbose -e .
102+
#
103+
# - run: pytest -v -s -We -p no:unraisableexception tests
104+
#
105+
# - run: DEBUG=0 VERBOSE=1 pip install --verbose -e .
106+
#
107+
# - run: pytest -v -s -We -p no:unraisableexception tests
108+
109+
### uncomment to gain ssh access in case of failure
96110
# - if: ${{ failure() }}
97111
# uses: mxschmitt/action-tmate@v3
98112
# with:

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ endmacro(add_prefix)
3535
set(PyPartMC_sources
3636
pypartmc.cpp gimmicks.cpp fake_netcdf.cpp fake_mpi.cpp fake_spec_file.cpp
3737
run_part.F90 run_part_opt.F90 util.F90 aero_data.F90 aero_state.F90 env_state.F90 gas_data.F90
38-
gas_state.F90 scenario.F90 condense.F90
38+
gas_state.F90 scenario.F90 condense.F90 bin_grid.F90
3939
)
4040
add_prefix(src/ PyPartMC_sources)
4141

PyPartMC/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ def __build_extension_env():
1010
cookies = []
1111
# https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew
1212
if hasattr(os, "add_dll_directory"):
13+
basepath = os.path.dirname(os.path.abspath(__file__))
14+
dllspath = os.path.join(basepath, '..')
15+
os.environ['PATH'] = dllspath + os.pathsep + os.environ['PATH']
1316
for path in os.environ.get("PATH", "").split(os.pathsep):
1417
if path and Path(path).is_absolute() and Path(path).is_dir():
1518
cookies.append(os.add_dll_directory(path))
@@ -39,5 +42,5 @@ def __build_extension_env():
3942

4043
with __build_extension_env():
4144
from _PyPartMC import *
42-
from _PyPartMC import __all__
45+
from _PyPartMC import __all__, __version__
4346
import _PyPartMC

src/bin_grid.F90

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
!###################################################################################################
2+
! This file is a part of PyPartMC licensed under the GNU General Public License v3 (LICENSE file) #
3+
! Copyright (C) 2022 University of Illinois Urbana-Champaign #
4+
! Authors: https://github.com/open-atmos/PyPartMC/graphs/contributors #
5+
!###################################################################################################
6+
7+
module PyPartMC_bin_grid
8+
use iso_c_binding
9+
use pmc_bin_grid
10+
implicit none
11+
12+
contains
13+
14+
subroutine f_bin_grid_ctor(ptr_c) bind(C)
15+
type(bin_grid_t), pointer :: ptr_f => null()
16+
type(c_ptr), intent(out) :: ptr_c
17+
18+
allocate(ptr_f)
19+
ptr_c = c_loc(ptr_f)
20+
end subroutine
21+
22+
subroutine f_bin_grid_dtor(ptr_c) bind(C)
23+
type(bin_grid_t), pointer :: ptr_f => null()
24+
type(c_ptr), intent(in) :: ptr_c
25+
26+
call c_f_pointer(ptr_c, ptr_f)
27+
deallocate(ptr_f)
28+
end subroutine
29+
30+
subroutine f_bin_grid_init(ptr_c, n_bin, bin_grid_type, min, max) bind(C)
31+
type(c_ptr), intent(in) :: ptr_c
32+
type(bin_grid_t), pointer :: bin_grid => null()
33+
integer(c_int), intent(in) :: n_bin
34+
integer(c_int), intent(in) :: bin_grid_type
35+
real(c_double), intent(in) :: min
36+
real(c_double), intent(in) :: max
37+
38+
call c_f_pointer(ptr_c, bin_grid)
39+
call bin_grid_make(bin_grid, bin_grid_type, n_bin, min, max)
40+
41+
end subroutine
42+
43+
subroutine f_bin_grid_size(ptr_c, val) bind(C)
44+
type(c_ptr), intent(in) :: ptr_c
45+
type(bin_grid_t), pointer :: bin_grid => null()
46+
integer(c_int), intent(out) :: val
47+
48+
call c_f_pointer(ptr_c, bin_grid)
49+
val = bin_grid_size(bin_grid)
50+
51+
end subroutine
52+
53+
subroutine f_bin_grid_edges(ptr_c, arr_data, arr_size) bind(C)
54+
type(c_ptr), intent(in) :: ptr_c
55+
type(bin_grid_t), pointer :: bin_grid => null()
56+
integer(c_int), intent(in) :: arr_size
57+
real(c_double), dimension(arr_size), intent(out) :: arr_data
58+
59+
call c_f_pointer(ptr_c, bin_grid)
60+
arr_data = bin_grid%edges
61+
end subroutine
62+
63+
subroutine f_bin_grid_centers(ptr_c, arr_data, arr_size) bind(C)
64+
type(c_ptr), intent(in) :: ptr_c
65+
type(bin_grid_t), pointer :: bin_grid => null()
66+
integer(c_int), intent(in) :: arr_size
67+
real(c_double), dimension(arr_size), intent(out) :: arr_data
68+
69+
call c_f_pointer(ptr_c, bin_grid)
70+
arr_data = bin_grid%centers
71+
end subroutine
72+
73+
end module

src/bin_grid.hpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*##################################################################################################
2+
# This file is a part of PyPartMC licensed under the GNU General Public License v3 (LICENSE file) #
3+
# Copyright (C) 2022 University of Illinois Urbana-Champaign #
4+
# Authors: https://github.com/open-atmos/PyPartMC/graphs/contributors #
5+
##################################################################################################*/
6+
7+
#pragma once
8+
9+
#include "pmc_resource.hpp"
10+
#include "pybind11/stl.h"
11+
12+
extern "C" void f_bin_grid_ctor(void *ptr) noexcept;
13+
extern "C" void f_bin_grid_dtor(void *ptr) noexcept;
14+
extern "C" void f_bin_grid_init(
15+
const void *ptr,
16+
const int *n_bin,
17+
const int *type,
18+
const double *min,
19+
const double *max
20+
) noexcept;
21+
extern "C" void f_bin_grid_size(const void *ptr, int *val) noexcept;
22+
extern "C" void f_bin_grid_edges(const void *ptr, void *arr_data, const int *arr_size) noexcept;
23+
extern "C" void f_bin_grid_centers(const void *ptr, void *arr_data, const int *arr_size) noexcept;
24+
25+
struct BinGrid {
26+
PMCResource ptr;
27+
28+
BinGrid(const int &n_bin, const std::string &grid_type, const double &min, const double &max) :
29+
ptr(f_bin_grid_ctor, f_bin_grid_dtor)
30+
{
31+
int type;
32+
type = 0;
33+
if (grid_type == "log") type = 1;
34+
if (grid_type == "linear") type = 2;
35+
if (type == 0) throw std::invalid_argument( "Invalid grid spacing." );
36+
f_bin_grid_init(ptr.f_arg(), &n_bin, &type, &min, &max);
37+
}
38+
39+
static std::size_t __len__(const BinGrid &self) {
40+
int len;
41+
f_bin_grid_size(&self.ptr, &len);
42+
return len;
43+
}
44+
45+
static std::valarray<double> edges(const BinGrid &self)
46+
{
47+
int len;
48+
f_bin_grid_size(&self.ptr, &len);
49+
len++;
50+
std::valarray<double> data(len);
51+
f_bin_grid_edges(&self.ptr, begin(data), &len);
52+
return data;
53+
}
54+
55+
static std::valarray<double> centers(const BinGrid &self)
56+
{
57+
int len;
58+
f_bin_grid_size(&self.ptr, &len);
59+
std::valarray<double> data(len);
60+
f_bin_grid_centers(&self.ptr, begin(data), &len);
61+
return data;
62+
}
63+
};

src/pypartmc.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
#include "pybind11/pybind11.h"
88
#include "nlohmann/json.hpp"
99
#include "pybind11_json/pybind11_json.hpp"
10-
#include "pybind11/numpy.h"
1110

1211
#include "util.hpp"
1312
#include "run_part.hpp"
@@ -18,6 +17,7 @@
1817
#include "gas_data.hpp"
1918
#include "gas_state.hpp"
2019
#include "condense.hpp"
20+
#include "bin_grid.hpp"
2121

2222
#define STRINGIFY(x) #x
2323
#define MACRO_STRINGIFY(x) STRINGIFY(x)
@@ -173,6 +173,12 @@ PYBIND11_MODULE(_PyPartMC, m) {
173173
.def(py::init<const nlohmann::json&>())
174174
;
175175

176+
py::class_<BinGrid>(m,"BinGrid")
177+
.def(py::init<const double, const py::str, const double, const double>())
178+
.def("__len__", BinGrid::__len__)
179+
.def_property_readonly("edges", BinGrid::edges)
180+
.def_property_readonly("centers", BinGrid::centers)
181+
;
176182
// TODO: auto util = m.def_submodule("util", "TODO");
177183
m.def(
178184
"pow2_above", &pow2_above, py::return_value_policy::copy,
@@ -185,6 +191,7 @@ PYBIND11_MODULE(_PyPartMC, m) {
185191
"__version__",
186192
"AeroData",
187193
"AeroState",
194+
"BinGrid",
188195
"EnvState",
189196
"GasData",
190197
"GasState",

tests/test_bin_grid.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
####################################################################################################
2+
# This file is a part of PyPartMC licensed under the GNU General Public License v3 (LICENSE file) #
3+
# Copyright (C) 2022 University of Illinois Urbana-Champaign #
4+
# Authors: https://github.com/open-atmos/PyPartMC/graphs/contributors #
5+
####################################################################################################
6+
7+
import numpy as np
8+
import PyPartMC as ppmc
9+
10+
11+
class TestBinGrid:
12+
@staticmethod
13+
def test_ctor():
14+
# arrange
15+
pass
16+
17+
# act
18+
sut = ppmc.BinGrid(123, "log", 1, 100)
19+
20+
# assert
21+
assert sut is not None
22+
23+
@staticmethod
24+
def test_len():
25+
# arrange
26+
grid_size = 666
27+
sut = ppmc.BinGrid(grid_size, "log", 1, 100)
28+
29+
# act
30+
size = len(sut)
31+
32+
# assert
33+
assert size == grid_size
34+
35+
@staticmethod
36+
def test_bin_edges_len():
37+
# arrange
38+
grid_size = 100
39+
sut = ppmc.BinGrid(grid_size, "log", 1, 100)
40+
41+
# act
42+
edges = sut.edges
43+
44+
# assert
45+
assert grid_size + 1 == len(edges)
46+
47+
@staticmethod
48+
def test_bin_edges_values():
49+
# arrange
50+
n_bins = 10
51+
left_edge = 1
52+
right_edge = 100
53+
sut = ppmc.BinGrid(n_bins, "log", left_edge, right_edge)
54+
55+
# act
56+
edges = sut.edges
57+
58+
# assert
59+
np.testing.assert_array_almost_equal(
60+
np.logspace(np.log10(left_edge), np.log10(right_edge), n_bins+1),
61+
edges
62+
)
63+
64+
@staticmethod
65+
def test_bin_centers_len():
66+
# arrange
67+
grid_size = 44
68+
sut = ppmc.BinGrid(grid_size, "log", 1, 100)
69+
70+
# act
71+
centers = sut.centers
72+
73+
# assert
74+
assert grid_size == len(centers)
75+
76+
@staticmethod
77+
def test_bin_centers_values():
78+
# arrange
79+
n_bins = 10
80+
left_edge = 1
81+
right_edge = 100
82+
sut = ppmc.BinGrid(n_bins, "log", left_edge, right_edge)
83+
84+
# act
85+
centers = sut.centers
86+
87+
# assert
88+
np.testing.assert_array_almost_equal(
89+
np.logspace(np.log10(left_edge), np.log10(right_edge), 2*n_bins+1)[1:-1:2],
90+
centers
91+
)
92+
93+
@staticmethod
94+
def test_invalid_grid():
95+
grid_size = 100
96+
try:
97+
_ = ppmc.BinGrid(grid_size, "X", 1, 100)
98+
except ValueError as error:
99+
assert str(error) == "Invalid grid spacing."

0 commit comments

Comments
 (0)