aboutsummaryrefslogtreecommitdiff
path: root/Source/Python/pyWarpX.cpp
blob: 64db77153bd4f2d9679911f31bcc53a736d3f816 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* Copyright 2021-2023 The WarpX Community
 *
 * Authors: Axel Huebl
 * License: BSD-3-Clause-LBNL
 */
#include "pyWarpX.H"
#include "WarpX_py.H"

#include <WarpX.H>  // todo: move this out to Python/WarpX.cpp
#include <Utils/WarpXUtil.H>  // todo: move to its own Python/Utils.cpp
#include <Utils/WarpXVersion.H>
#include <Initialization/WarpXAMReXInit.H>

#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
#define CONCAT_NAME(PRE, SUF) PRE ## SUF

// see: CMakeLists.txt, setup.py and __init__.py
#if defined(WARPX_DIM_1D_Z)
#  define PYWARPX_MODULE_NAME CONCAT_NAME(warpx_pybind_, 1d)
#elif defined(WARPX_DIM_XZ)
#  define PYWARPX_MODULE_NAME CONCAT_NAME(warpx_pybind_, 2d)
#elif defined(WARPX_DIM_RZ)
#  define PYWARPX_MODULE_NAME CONCAT_NAME(warpx_pybind_, rz)
#elif defined(WARPX_DIM_3D)
#  define PYWARPX_MODULE_NAME CONCAT_NAME(warpx_pybind_, 3d)
#endif

//using namespace warpx;


// forward declarations of exposed classes
void init_BoundaryBufferParIter (py::module&);
void init_MultiParticleContainer (py::module&);
void init_ParticleBoundaryBuffer (py::module&);
void init_PinnedMemoryParticleContainer (py::module&);
void init_WarpXParIter (py::module&);
void init_WarpXParticleContainer (py::module&);
void init_WarpX(py::module&);

PYBIND11_MODULE(PYWARPX_MODULE_NAME, m) {
    // make sure AMReX types are known
#if defined(WARPX_DIM_3D)
    auto amr = py::module::import("amrex.space3d");
#elif defined(WARPX_DIM_1D_Z)
    auto amr = py::module::import("amrex.space1d");
#else
    auto amr = py::module::import("amrex.space2d");
#endif

    m.doc() = R"pbdoc(
            warpx_pybind
            --------------
            .. currentmodule:: warpx_pybind_(1d|2d|3d|rz)

            .. autosummary::
               :toctree: _generate
               WarpX
    )pbdoc";

    // note: order from parent to child classes
    init_PinnedMemoryParticleContainer(m);
    init_WarpXParticleContainer(m);
    init_WarpXParIter(m);
    init_BoundaryBufferParIter(m);
    init_ParticleBoundaryBuffer(m);
    init_MultiParticleContainer(m);
    init_WarpX(m);

    // expose our amrex module
    m.attr("amr") = amr;

    // API runtime version
    //   note PEP-440 syntax: x.y.zaN but x.y.z.devN
#ifdef PYWARPX_VERSION_INFO
    m.attr("__version__") = MACRO_STRINGIFY(PYWARPX_VERSION_INFO);
#else
    // note: not necessarily PEP-440 compliant
    m.attr("__version__") = WarpX::Version();
#endif

    // authors
    m.attr("__author__") =
        "Jean-Luc Vay, David P. Grote, Maxence Thevenet, Remi Lehe, Andrew Myers, Weiqun Zhang, Axel Huebl, et al.";

    // API runtime build-time feature variants
    // m.attr("variants") = warpx::getVariants();
    // TODO allow to query runtime versions of all dependencies

    // license SPDX identifier
    m.attr("__license__") = "BSD-3-Clause-LBNL";

    // TODO broken numpy if not at least v1.15.0: raise warning
    // auto numpy = py::module::import("numpy");
    // auto npversion = numpy.attr("__version__");
    // std::cout << "numpy version: " << py::str(npversion) << std::endl;

    m.def("amrex_init",
        [](const py::list args) {
            amrex::Vector<std::string> cargs;
            amrex::Vector<char*> argv;

            // Populate the "command line"
            for (const auto& v: args)
                cargs.push_back(v.cast<std::string>());
            for (auto& v: cargs)
                argv.push_back(&v[0]);
            int argc = argv.size();

            // note: +1 since there is an extra char-string array element,
            //       that ANSII C requires to be a simple NULL entry
            //       https://stackoverflow.com/a/39096006/2719194
            argv.push_back(NULL);
            char** tmp = argv.data();

            const bool build_parm_parse = (cargs.size() > 1);
            // TODO: handle version with MPI
            return warpx::initialization::amrex_init(argc, tmp, build_parm_parse);
        }, py::return_value_policy::reference,
        "Initialize AMReX library");
    m.def("amrex_finalize", [] () { amrex::Finalize(); },
        "Close out the amrex related data");

    // Expose functions to get the processor number
    m.def("getNProcs", [](){return amrex::ParallelDescriptor::NProcs();} );
    m.def("getMyProc", [](){return amrex::ParallelDescriptor::MyProc();} );

    // Expose the python callback function installation and removal functions
    m.def("add_python_callback", &InstallPythonCallback);
    m.def("remove_python_callback", &ClearPythonCallback);
    m.def("execute_python_callback", &ExecutePythonCallback, py::arg("name"));
}