Skip to content

Commit 8dc75f3

Browse files
committed
add: GasData bindings
1 parent 73a1543 commit 8dc75f3

File tree

3 files changed

+31
-279
lines changed

3 files changed

+31
-279
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ set(PyPartMC_sources
7272
aero_mode.F90
7373
aero_dist.F90
7474
env_state.F90
75+
gas_data.F90
7576
# json_resource.cpp spec_file_pypartmc.cpp sys.cpp
7677
# run_part.F90 run_part_opt.F90 util.F90 aero_data.F90 aero_state.F90 env_state.F90 gas_data.F90
7778
# gas_state.F90 scenario.F90 condense.F90 aero_particle.F90 bin_grid.F90

src/gas_data.hpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
#include "json_resource.hpp"
1010
#include "pmc_resource.hpp"
1111
#include "gas_data_parameters.hpp"
12-
#include "pybind11/stl.h"
13-
#include "pybind11_json/pybind11_json.hpp"
12+
#include "nanobind/nanobind.h"
13+
14+
#include "temp_nb_casters.hpp"
1415

1516
extern "C" void f_gas_data_ctor(void *ptr) noexcept;
1617
extern "C" void f_gas_data_dtor(void *ptr) noexcept;
@@ -26,14 +27,14 @@ struct GasData {
2627
PMCResource ptr;
2728
const nlohmann::json json;
2829

29-
GasData(const pybind11::tuple &tpl) :
30+
GasData(const nanobind::tuple &tpl) :
3031
ptr(f_gas_data_ctor, f_gas_data_dtor),
3132
json(tpl)
3233
{
3334
auto json_array = nlohmann::json::array();
3435
for (const auto item : tpl)
3536
json_array.push_back(nlohmann::json::object({{
36-
item.cast<std::string>(),
37+
nanobind::cast<std::string>(item),
3738
nlohmann::json::array()
3839
}}));
3940

@@ -82,16 +83,16 @@ struct GasData {
8283
);
8384

8485
char name[GAS_NAME_LEN];
85-
auto names = pybind11::tuple(len);
86+
nanobind::list names;
8687
for (int idx = 0; idx < len; idx++) {
8788
f_gas_data_spec_name_by_index(
8889
self.ptr.f_arg(),
8990
&idx,
9091
name
9192
);
92-
names[idx] = std::string(name);
93+
names.append(nanobind::str(name));
9394
}
94-
return names;
95+
return nanobind::tuple(names);
9596
}
9697
};
9798

src/pypartmc.cpp

Lines changed: 22 additions & 272 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include "aero_mode.hpp"
2626
// #include "aero_state.hpp"
2727
#include "env_state.hpp"
28-
// // #include "gas_data.hpp"
28+
#include "gas_data.hpp"
2929
// #include "gas_state.hpp"
3030
// #include "condense.hpp"
3131
#include "bin_grid.hpp"
@@ -34,264 +34,14 @@
3434
// #include "output.hpp"
3535
// #include "output_parameters.hpp"
3636

37-
#include <valarray>
37+
#include "temp_nb_casters.hpp"
3838

3939
#define STRINGIFY(x) #x
4040
#define MACRO_STRINGIFY(x) STRINGIFY(x)
4141

4242
namespace nb = nanobind;
4343
namespace nl = nlohmann;
4444

45-
namespace pyjson
46-
{
47-
inline nb::handle from_json(const nl::json& j)
48-
{
49-
if (j.is_null())
50-
{
51-
return nb::none();
52-
}
53-
else if (j.is_boolean())
54-
{
55-
return nb::bool_(j.get<bool>());
56-
}
57-
else if (j.is_number_integer())
58-
{
59-
return nb::int_(j.get<long>());
60-
}
61-
else if (j.is_number_float())
62-
{
63-
return nb::float_(j.get<double>());
64-
}
65-
else if (j.is_string())
66-
{
67-
std::string temp = j.get<std::string>();
68-
return nb::str(temp.c_str(), temp.length());
69-
}
70-
else if (j.is_array())
71-
{
72-
nb::list obj;
73-
for (const auto& el : j)
74-
{
75-
obj.append(from_json(el));
76-
}
77-
return std::move(obj);
78-
}
79-
else // Object
80-
{
81-
nb::dict obj;
82-
for (nl::json::const_iterator it = j.cbegin(); it != j.cend(); ++it)
83-
{
84-
std::string key = it.key();
85-
obj[nb::str(key.c_str(), key.length())] = from_json(it.value());
86-
}
87-
return obj.release();
88-
}
89-
}
90-
91-
inline nl::json to_json(const nb::handle& obj, std::set<const PyObject*> prevs)
92-
{
93-
if (obj.ptr() == nullptr || obj.is_none())
94-
{
95-
return nullptr;
96-
}
97-
if (nb::isinstance<nb::bool_>(obj))
98-
{
99-
return nb::cast<bool>(obj);
100-
}
101-
if (nb::isinstance<nb::int_>(obj))
102-
{
103-
return nb::cast<long>(obj);
104-
}
105-
if (nb::isinstance<nb::float_>(obj))
106-
{
107-
return nb::cast<double>(obj);
108-
}
109-
if (nb::isinstance<nb::bytes>(obj))
110-
{
111-
nb::module_ base64 = nb::module_::import_("base64");
112-
return nb::cast<std::string>(base64.attr("b64encode")(obj).attr("decode")("utf-8"));
113-
}
114-
if (nb::isinstance<nb::str>(obj))
115-
{
116-
return nb::cast<std::string>(obj);
117-
}
118-
if (nb::isinstance<nb::tuple>(obj) || nb::isinstance<nb::list>(obj))
119-
{
120-
auto insert_return = prevs.insert(obj.ptr());
121-
if (!insert_return.second) {
122-
throw std::runtime_error("Circular reference detected");
123-
}
124-
125-
auto out = nl::json::array();
126-
127-
for (const nb::handle value : obj)
128-
{
129-
out.push_back(to_json(value, prevs));
130-
}
131-
132-
return out;
133-
}
134-
if (nb::isinstance<nb::dict>(obj))
135-
{
136-
auto insert_return = prevs.insert(obj.ptr());
137-
if (!insert_return.second) {
138-
throw std::runtime_error("Circular reference detected");
139-
}
140-
141-
auto out = nl::json::object();
142-
143-
for (const nb::handle key : obj)
144-
{
145-
out[nb::cast<std::string>(nb::str(key))] = to_json(obj[key], prevs);
146-
}
147-
return out;
148-
}
149-
throw std::runtime_error("to_json not implemented for this type of object: ");
150-
// throw std::runtime_error("to_json not implemented for this type of object: " + nb::repr(obj).cast<std::string>());
151-
}
152-
}
153-
154-
// nlohmann_json serializers
155-
// namespace nlohmann
156-
// {
157-
// #define MAKE_NLJSON_SERIALIZER_DESERIALIZER(T) \
158-
// template <> \
159-
// struct adl_serializer<T> \
160-
// { \
161-
// inline static void to_json(json& j, const T& obj) \
162-
// { \
163-
// std::cout << "dupa dupa dupa" << std::endl; \
164-
// j = pyjson::to_json(obj); \
165-
// std::cout << "you just got JSONed!" << std::endl; \
166-
// } \
167-
// \
168-
// inline static nb::handle from_json(const json& j) \
169-
// { \
170-
// return pyjson::from_json(j); \
171-
// } \
172-
// };
173-
174-
// #define MAKE_NLJSON_SERIALIZER_ONLY(T) \
175-
// template <> \
176-
// struct adl_serializer<T> \
177-
// { \
178-
// inline static void to_json(json& j, const T& obj) \
179-
// { \
180-
// j = pyjson::to_json(obj); \
181-
// } \
182-
// };
183-
184-
// MAKE_NLJSON_SERIALIZER_DESERIALIZER(nb::object);
185-
186-
// MAKE_NLJSON_SERIALIZER_DESERIALIZER(nb::bool_);
187-
// MAKE_NLJSON_SERIALIZER_DESERIALIZER(nb::int_);
188-
// MAKE_NLJSON_SERIALIZER_DESERIALIZER(nb::float_);
189-
// MAKE_NLJSON_SERIALIZER_DESERIALIZER(nb::str);
190-
191-
// MAKE_NLJSON_SERIALIZER_DESERIALIZER(nb::list);
192-
// MAKE_NLJSON_SERIALIZER_DESERIALIZER(nb::tuple);
193-
// MAKE_NLJSON_SERIALIZER_DESERIALIZER(nb::dict);
194-
195-
// MAKE_NLJSON_SERIALIZER_ONLY(nb::handle);
196-
// // MAKE_NLJSON_SERIALIZER_ONLY(nb::detail::item_accessor);
197-
// // MAKE_NLJSON_SERIALIZER_ONLY(nb::detail::list_accessor);
198-
// // MAKE_NLJSON_SERIALIZER_ONLY(nb::detail::tuple_accessor);
199-
// // MAKE_NLJSON_SERIALIZER_ONLY(nb::detail::sequence_accessor);
200-
// // MAKE_NLJSON_SERIALIZER_ONLY(nb::detail::str_attr_accessor);
201-
// // MAKE_NLJSON_SERIALIZER_ONLY(nb::detail::obj_attr_accessor);
202-
203-
// #undef MAKE_NLJSON_SERIALIZER_DESERIALIZER
204-
// #undef MAKE_NLJSON_SERIALIZER_ONLY
205-
// }
206-
207-
// nanobind caster
208-
namespace nanobind
209-
{
210-
namespace detail
211-
{
212-
template <> struct type_caster<nl::json>
213-
{
214-
public:
215-
NB_TYPE_CASTER(nl::json, const_name("[") + const_name("JSON") +const_name("]"));
216-
217-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
218-
try {
219-
value = pyjson::to_json(src, std::set<const PyObject*>());
220-
return true;
221-
}
222-
catch (...)
223-
{
224-
return false;
225-
}
226-
}
227-
228-
template <typename T>
229-
static handle from_cpp(T &&src, rv_policy policy, cleanup_list *cleanup) {
230-
handle obj = pyjson::from_json(src);
231-
return obj;
232-
}
233-
};
234-
235-
template <typename Type> struct type_caster<std::valarray<Type>> {
236-
NB_TYPE_CASTER(std::valarray<Type>, const_name("[") + const_name("std::valarray") + const_name("]"))
237-
238-
using Caster = make_caster<Type>;
239-
240-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
241-
if (nb::isinstance<nb::list>(src)) {
242-
try {
243-
auto py_array = nb::cast<nb::list>(src);
244-
size_t size = py_array.size();
245-
246-
value.resize(size);
247-
248-
for (size_t i = 0; i < size; i++) {
249-
value[i] = nb::cast<Type>(py_array[i]);
250-
}
251-
252-
return true;
253-
}
254-
catch (...) {
255-
PyErr_Clear();
256-
return false;
257-
}
258-
}
259-
else if (nb::isinstance<nb::ndarray<Type, nb::ndim<1>>>(src)) {
260-
try {
261-
auto py_array = nb::cast<nb::ndarray<Type, nb::ndim<1>>>(src);
262-
size_t size = py_array.size();
263-
auto *data = py_array.data();
264-
265-
value.resize(size);
266-
267-
for (size_t i = 0; i < size; i++) {
268-
value[i] = data[i];
269-
}
270-
271-
return true;
272-
}
273-
catch (...) {
274-
PyErr_Clear();
275-
return false;
276-
}
277-
}
278-
279-
return false;
280-
}
281-
282-
template <typename T>
283-
static handle from_cpp(T &&src, rv_policy policy, cleanup_list *cleanup) {
284-
nb::list obj;
285-
for (const auto& elem : src) {
286-
obj.append(elem);
287-
}
288-
289-
return obj.release();
290-
}
291-
};
292-
}
293-
}
294-
29545
NB_MODULE(_PyPartMC, m) {
29646
// m.doc() = R"pbdoc(
29747
// PyPartMC is a Python interface to PartMC.
@@ -527,27 +277,27 @@ NB_MODULE(_PyPartMC, m) {
527277
// .def("zero", AeroState::zero, "remove all particles from an AeroState")
528278
// ;
529279

530-
// py::class_<GasData, std::shared_ptr<GasData>>(m, "GasData",
531-
// R"pbdoc(
532-
// Constant gas data.
280+
nb::class_<GasData>(m, "GasData",
281+
R"pbdoc(
282+
Constant gas data.
533283
534-
// Each gas species is identified by an integer \c i between 1 and
535-
// \c gas_data_n_spec(gas_data). Species \c i has name \c gas_data%%name(i).
536-
// The variable gas data describing the current mixing ratios is stored
537-
// in the gas_state_t structure, so the mixing ratio of species \c i
538-
// is gas_state%%mix_rat(i).
539-
// )pbdoc"
540-
// )
541-
// .def(py::init<const py::tuple&>())
542-
// .def("__len__", GasData::__len__,
543-
// "returns number of gas species")
544-
// .def_property_readonly("n_spec", GasData::__len__)
545-
// .def("__str__", GasData::__str__,
546-
// "returns a string with JSON representation of the object")
547-
// .def("spec_by_name", GasData::spec_by_name,
548-
// "returns the number of the species in gas with the given name")
549-
// .def_property_readonly("species", GasData::names, "returns list of gas species names")
550-
// ;
284+
Each gas species is identified by an integer \c i between 1 and
285+
\c gas_data_n_spec(gas_data). Species \c i has name \c gas_data%%name(i).
286+
The variable gas data describing the current mixing ratios is stored
287+
in the gas_state_t structure, so the mixing ratio of species \c i
288+
is gas_state%%mix_rat(i).
289+
)pbdoc"
290+
)
291+
.def(nb::init<const nb::tuple&>())
292+
.def("__len__", GasData::__len__,
293+
"returns number of gas species")
294+
.def_prop_ro("n_spec", GasData::__len__)
295+
.def("__str__", GasData::__str__,
296+
"returns a string with JSON representation of the object")
297+
.def("spec_by_name", GasData::spec_by_name,
298+
"returns the number of the species in gas with the given name")
299+
.def_prop_ro("species", GasData::names, "returns list of gas species names")
300+
;
551301

552302
nb::class_<EnvState>(m, "EnvState",
553303
R"pbdoc(

0 commit comments

Comments
 (0)