Skip to content

Commit f4e9203

Browse files
committed
Python Bindings
1 parent 768035c commit f4e9203

File tree

5 files changed

+114
-4
lines changed

5 files changed

+114
-4
lines changed

src/CompensatedReal.H

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,9 @@ namespace impactx
213213
*/
214214
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
215215
CompensatedReal operator+(CompensatedReal const& rhs) const {
216-
CompensatedReal result = *this;
216+
CompensatedReal result(*this);
217217
result += rhs;
218-
return result;
218+
return CompensatedReal(result);
219219
}
220220

221221
/** Subtraction operator with CompensatedReal
@@ -225,9 +225,9 @@ namespace impactx
225225
*/
226226
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
227227
CompensatedReal operator-(CompensatedReal const& rhs) const {
228-
CompensatedReal result = *this;
228+
CompensatedReal result(*this);
229229
result -= rhs;
230-
return result;
230+
return CompensatedReal(result);
231231
}
232232

233233
/** Equality comparison

src/python/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#
55
target_sources(pyImpactX
66
PRIVATE
7+
CompensatedReal.cpp
78
distribution.cpp
89
elements.cpp
910
ImpactX.cpp

src/python/CompensatedReal.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/* Copyright 2022-2024 The ImpactX Community
2+
*
3+
* Authors: Axel Huebl, Chad Mitchell
4+
* License: BSD-3-Clause-LBNL
5+
*/
6+
#include "pyImpactX.H"
7+
8+
#include <CompensatedReal.H>
9+
#include <AMReX_REAL.H>
10+
11+
#include <cmath>
12+
13+
namespace py = pybind11;
14+
using namespace impactx;
15+
16+
17+
void init_compensatedreal(py::module& m)
18+
{
19+
// Expose the CompensatedParticleReal typedef
20+
py::class_<CompensatedParticleReal>(m, "CompensatedParticleReal")
21+
.def(py::init<>(),
22+
"Default (zero) constructor for compensated ParticleReal type"
23+
)
24+
.def(py::init<amrex::ParticleReal>(),
25+
py::arg("value"),
26+
"Constructor from a ParticleReal value"
27+
)
28+
.def(py::init<CompensatedParticleReal const&>(),
29+
py::arg("other"),
30+
"Copy constructor"
31+
)
32+
.def("assign", &CompensatedParticleReal::assign,
33+
py::arg("value"),
34+
py::return_value_policy::reference_internal,
35+
"Assign a new value and reset compensation"
36+
)
37+
38+
// Arithmetic operators
39+
.def(py::self += amrex::ParticleReal())
40+
.def(py::self -= amrex::ParticleReal())
41+
.def(py::self + amrex::ParticleReal())
42+
.def(py::self - amrex::ParticleReal())
43+
.def(amrex::ParticleReal() + py::self)
44+
.def(amrex::ParticleReal() - py::self)
45+
.def(py::self += py::self)
46+
.def(py::self -= py::self)
47+
.def(py::self + py::self)
48+
.def(py::self - py::self)
49+
50+
// Comparison operators
51+
.def(py::self == amrex::ParticleReal())
52+
.def(py::self != amrex::ParticleReal())
53+
.def(py::self < amrex::ParticleReal())
54+
.def(py::self <= amrex::ParticleReal())
55+
.def(py::self > amrex::ParticleReal())
56+
.def(py::self >= amrex::ParticleReal())
57+
.def(py::self == py::self)
58+
.def(py::self != py::self)
59+
.def(py::self < py::self)
60+
.def(py::self <= py::self)
61+
.def(py::self > py::self)
62+
.def(py::self >= py::self)
63+
64+
// Value access
65+
.def_property_readonly("value", &CompensatedParticleReal::value,
66+
"Get the final compensated value (main + first-order + second-order compensation)"
67+
)
68+
69+
// conversion to float for compatibility
70+
.def("__float__", &CompensatedParticleReal::value,
71+
"Convert to Python float"
72+
)
73+
.def("__abs__", [](CompensatedParticleReal const& self) {
74+
return std::abs(self.value());
75+
}, "Convert to absolute value")
76+
77+
// Utility methods
78+
.def("reset_compensation", &CompensatedParticleReal::reset_compensation,
79+
py::return_value_policy::reference_internal,
80+
"Reset compensation variables to zero"
81+
)
82+
83+
// String representation
84+
.def("__repr__", [](CompensatedParticleReal const& self) {
85+
return "CompensatedParticleReal(" + std::to_string(self.value()) + ")";
86+
})
87+
.def("__str__", [](CompensatedParticleReal const& self) {
88+
return std::to_string(self.value());
89+
})
90+
91+
.def_readonly_static("__doc__",
92+
"A compensated floating-point type specialized for ParticleReal values.\n"
93+
"\n"
94+
"This provides high-precision arithmetic for particle tracking calculations\n"
95+
"using the second-order iterative Kahan-Babuska algorithm.\n"
96+
"\n"
97+
"The algorithm follows Klein (2006) to provide high-precision arithmetic that avoids\n"
98+
"floating-point precision errors when dealing with large numbers of small values.\n"
99+
"\n"
100+
"References:\n"
101+
"- https://en.wikipedia.org/wiki/Kahan_summation_algorithm#Further_enhancements\n"
102+
"- Klein (2006). \"A generalized Kahan–Babuška-Summation-Algorithm\". in\n"
103+
" Computing. 76 (3–4). Springer-Verlag: 279–293. doi:10.1007/s00607-005-0139-x"
104+
)
105+
;
106+
}

src/python/pyImpactX.H

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <pybind11/pybind11.h>
1313
#include <pybind11/functional.h>
1414
// include <pybind11/numpy.h> // not yet used
15+
#include <pybind11/operators.h>
1516
#include <pybind11/stl.h>
1617
#include <pybind11/stl_bind.h>
1718

src/python/pyImpactX.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ using namespace impactx;
2020

2121

2222
// forward declarations of exposed classes
23+
void init_compensatedreal(py::module&);
2324
void init_distribution(py::module&);
2425
void init_elements(py::module&);
2526
void init_ImpactX(py::module&);
@@ -45,6 +46,7 @@ PYBIND11_MODULE(impactx_pybind, m) {
4546
)pbdoc";
4647

4748
// note: order from parent to child classes
49+
init_compensatedreal(m);
4850
init_distribution(m);
4951
init_refparticle(m);
5052
init_impactxparticlecontainer(m);

0 commit comments

Comments
 (0)