Nektar++
Classes | Functions
Python/Module.cpp File Reference
#include <FieldUtils/Module.h>
#include <LibUtilities/Python/NekPyConfig.hpp>
#include <boost/program_options.hpp>
#include <boost/python/raw_function.hpp>

Go to the source code of this file.

Classes

struct  ModuleWrap< MODTYPE >
 Module wrapper to handle virtual function calls in Module and its subclasses as defined by the template parameter. More...
 
struct  ModuleTypeProxy< MODTYPE >
 
struct  ModuleTypeProxy< InputModule >
 
struct  ModuleTypeProxy< ProcessModule >
 
struct  ModuleTypeProxy< OutputModule >
 
class  ModuleRegisterHelper
 
struct  ModuleWrapConverter< MODTYPE >
 
struct  PythonModuleClass< MODTYPE >
 

Functions

void Module_Process (ModuleSharedPtr m)
 
template<typename T >
Module_GetConfig (std::shared_ptr< Module > mod, const std::string &key)
 
template<typename MODTYPE >
ModuleSharedPtr Module_Create (py::tuple args, py::dict kwargs)
 Lightweight wrapper for Module factory creation function. More...
 
void Module_RegisterConfig (std::shared_ptr< Module > mod, std::string const &key, std::string const &value)
 Lightweight wrapper for FieldUtils::Module::RegisterConfig. More...
 
template<typename MODTYPE >
void ModuleWrap_AddConfigOption (std::shared_ptr< ModuleWrap< MODTYPE > > mod, std::string const &key, std::string const &defValue, std::string const &desc, bool isBool)
 
void ModuleCapsuleDestructor (PyObject *ptr)
 
void Module_Register (ModuleType const &modType, std::string const &modName, py::object &obj)
 Lightweight wrapper for the Module factory RegisterCreatorFunction, to support the ability for Python subclasses of Module to register themselves with the Nektar++ Module factory. More...
 
void export_Module ()
 

Function Documentation

◆ export_Module()

void export_Module ( )

Definition at line 408 of file Python/Module.cpp.

409{
410 // Export ModuleType enum.
412
413 // Define ModuleWrap to be implicitly convertible to a Module, since it
414 // seems that doesn't sometimes get picked up.
415 py::implicitly_convertible<std::shared_ptr<ModuleWrap<Module>>,
416 std::shared_ptr<Module>>();
417 py::implicitly_convertible<std::shared_ptr<ModuleWrap<InputModule>>,
418 std::shared_ptr<Module>>();
419 py::implicitly_convertible<std::shared_ptr<ModuleWrap<OutputModule>>,
420 std::shared_ptr<Module>>();
421 py::implicitly_convertible<std::shared_ptr<ModuleWrap<ProcessModule>>,
422 std::shared_ptr<Module>>();
423
424 // Wrapper for the Module class. Note that since Module contains a pure
425 // virtual function, we need the ModuleWrap helper class to handle this for
426 // us. In the lightweight wrappers above, we therefore need to ensure we're
427 // passing std::shared_ptr<Module> as the first argument, otherwise they
428 // won't accept objects constructed from Python.
429 py::class_<ModuleWrap<Module>, std::shared_ptr<ModuleWrap<Module>>,
430 boost::noncopyable>("Module", py::init<FieldSharedPtr>())
431
432 // Process function for this module.
433 .def("Process", py::pure_virtual(&Module_Process))
434 .def("Run", py::pure_virtual(&Module_Process))
435
436 // Configuration options.
437 .def("RegisterConfig", Module_RegisterConfig,
438 (py::arg("key"), py::arg("value") = ""))
439 .def("PrintConfig", &Module::PrintConfig)
440 .def("SetDefaults", &Module::SetDefaults)
441 .def("GetStringConfig", Module_GetConfig<std::string>)
442 .def("GetFloatConfig", Module_GetConfig<double>)
443 .def("GetIntConfig", Module_GetConfig<int>)
444 .def("GetBoolConfig", Module_GetConfig<bool>)
445 .def("AddConfigOption", ModuleWrap_AddConfigOption<Module>,
446 (py::arg("key"), py::arg("defValue"), py::arg("desc"),
447 py::arg("isBool") = false))
448
449 // Allow direct access to field object through a property.
450 .def_readwrite("field", &ModuleWrap<Module>::m_f)
451
452 // Factory functions.
453 .def("Register", &Module_Register)
454 .staticmethod("Register");
455
457
458 PythonModuleClass<InputModule>("InputModule");
459 PythonModuleClass<ProcessModule>("ProcessModule");
460 PythonModuleClass<OutputModule>("OutputModule");
461}
#define NEKPY_WRAP_ENUM_STRING(ENUMNAME, MAPNAME)
Definition: NekPyConfig.hpp:78
void Module_RegisterConfig(std::shared_ptr< Module > mod, std::string const &key, std::string const &value)
Lightweight wrapper for FieldUtils::Module::RegisterConfig.
void Module_Process(ModuleSharedPtr m)
void Module_Register(ModuleType const &modType, std::string const &modName, py::object &obj)
Lightweight wrapper for the Module factory RegisterCreatorFunction, to support the ability for Python...
const std::string ModuleTypeMap[]
Definition: Module.h:72
Module wrapper to handle virtual function calls in Module and its subclasses as defined by the templa...

References Module_Process(), Module_Register(), Module_RegisterConfig(), Nektar::FieldUtils::ModuleTypeMap, and NEKPY_WRAP_ENUM_STRING.

Referenced by BOOST_PYTHON_MODULE().

◆ Module_Create()

template<typename MODTYPE >
ModuleSharedPtr Module_Create ( py::tuple  args,
py::dict  kwargs 
)

Lightweight wrapper for Module factory creation function.

Parameters
modTypeModule type (input/process/output).
modNameModule name (typically filename extension).
fieldField that will be passed between modules.
Template Parameters
MODTYPESubclass of Module (e.g #InputModule, #OutputModule)

Definition at line 164 of file Python/Module.cpp.

165{
167
169
170 if (modType == eProcessModule && py::len(args) != 2)
171 {
172 throw NekError("ProcessModule.Create() requires two arguments: "
173 "module name and a Field object.");
174 }
175 else if (modType != eProcessModule && py::len(args) < 2)
176 {
177 throw NekError(ModuleTypeMap[modType] +
178 "Module.Create() requires "
179 "two arguments: module name and a Field object; "
180 "optionally a filename.");
181 }
182
183 std::string modName = py::extract<std::string>(args[0]);
184 ModuleKey modKey = std::make_pair(modType, modName);
185
186 if (!py::extract<FieldSharedPtr>(args[1]).check())
187 {
188 throw NekError("Second argument to Create() should be a Field object.");
189 }
190
191 FieldSharedPtr field = py::extract<FieldSharedPtr>(args[1]);
192 ModuleSharedPtr mod = GetModuleFactory().CreateInstance(modKey, field);
193
194 if (modType == eInputModule)
195 {
196 // For input modules we can try to interpret the remaining arguments as
197 // input files. Assume that the file's type is identical to the module
198 // name.
199 for (int i = 2; i < py::len(args); ++i)
200 {
201 std::string in_fname = py::extract<std::string>(args[i]);
202 mod->RegisterConfig("infile", in_fname);
203 mod->AddFile(modName, in_fname);
204 }
205 }
206 else if (modType == eOutputModule && py::len(args) >= 3)
207 {
208 // For output modules we can try to interpret the remaining argument as
209 // an output file.
210 mod->RegisterConfig("outfile", py::extract<std::string>(args[2]));
211 }
212
213 // Process keyword arguments.
214 py::list items = kwargs.items();
215
216 for (int i = 0; i < py::len(items); ++i)
217 {
218 std::string arg = py::extract<std::string>(items[i][0]);
219
220 if (arg == "infile" && modKey.first == eInputModule)
221 {
222 py::extract<py::dict> dict_check(items[i][1]);
223
224 if (!dict_check.check())
225 {
226 throw NekError("infile should be a dictionary.");
227 }
228
229 py::dict ftype_fname_dict = py::extract<py::dict>(items[i][1]);
230 py::list ft_fn_items = ftype_fname_dict.items();
231 for (int i = 0; i < py::len(ft_fn_items); ++i)
232 {
233 std::string f_type =
234 py::extract<std::string>(ft_fn_items[i][0]);
235 std::string f_name = py::extract<std::string>(
236 ft_fn_items[i][1].attr("__str__")());
237 mod->RegisterConfig(arg, f_name);
238 mod->AddFile(f_type, f_name);
239 }
240 }
241 else
242 {
243 std::string val =
244 py::extract<std::string>(items[i][1].attr("__str__")());
245 mod->RegisterConfig(arg, val);
246 }
247 }
248
249 mod->SetDefaults();
250
251 return mod;
252}
Nektar::ErrorUtil::NekError NekError
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:143
std::shared_ptr< Field > FieldSharedPtr
Definition: Field.hpp:990
std::pair< ModuleType, std::string > ModuleKey
Definition: Module.h:180
std::shared_ptr< Module > ModuleSharedPtr
Definition: Module.h:329
ModuleFactory & GetModuleFactory()
Definition: Module.cpp:47

References Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::CreateInstance(), Nektar::FieldUtils::eInputModule, Nektar::FieldUtils::eOutputModule, Nektar::FieldUtils::eProcessModule, Nektar::FieldUtils::GetModuleFactory(), and Nektar::FieldUtils::ModuleTypeMap.

◆ Module_GetConfig()

template<typename T >
T Module_GetConfig ( std::shared_ptr< Module mod,
const std::string &  key 
)

Definition at line 127 of file Python/Module.cpp.

128{
129 return mod->GetConfigOption(key).as<T>();
130}

◆ Module_Process()

void Module_Process ( ModuleSharedPtr  m)

Definition at line 101 of file Python/Module.cpp.

102{
103 if (m->m_f->m_nParts > 1)
104 {
105 if (m->GetModulePriority() == eOutput)
106 {
107 m->m_f->m_comm = m->m_f->m_partComm;
108 if (m->GetModuleName() != "OutputInfo")
109 {
110 m->RegisterConfig("writemultiplefiles");
111 }
112 }
113 else if (m->GetModulePriority() == eCreateGraph)
114 {
115 m->m_f->m_comm = m->m_f->m_partComm;
116 }
117 else
118 {
119 m->m_f->m_comm = m->m_f->m_defComm;
120 }
121 }
122 m->SetDefaults();
123 m->Process(m->m_f->m_vm);
124}

References Nektar::FieldUtils::eCreateGraph, and Nektar::FieldUtils::eOutput.

Referenced by export_Module(), and PythonModuleClass< MODTYPE >::PythonModuleClass().

◆ Module_Register()

void Module_Register ( ModuleType const &  modType,
std::string const &  modName,
py::object &  obj 
)

Lightweight wrapper for the Module factory RegisterCreatorFunction, to support the ability for Python subclasses of Module to register themselves with the Nektar++ Module factory.

This function wraps the NekFactory RegisterCreatorFunction. This function expects a function pointer to a C++ object that will construct a Module. In this case we therefore need to construct a function call that will construct our Python object (which is a subclass of Module), and then pass this back to Boost.Python to give the Python object back.

We have to do some indirection here to get this to work, but we can achieve this with the following strategy:

  • Create a ModuleRegisterHelper object, which as an argument will store the Python class instance that will be instantiated from the Python side.
  • Using std::bind, construct a function pointer to the helper's creation function, ModuleRegisterHelper::create.
  • Create a Python capsule that will contain the ModuleRegisterHelper instance, and register this in the global namespace of the current module. This then ties the capsule to the lifetime of the module.

Definition at line 336 of file Python/Module.cpp.

338{
339 // Create a module register helper, which will call the C++ function to
340 // create the module.
342
343 // Register this with the module factory using std::bind to grab a function
344 // pointer to that particular object's function.
346 ModuleKey(modType, modName), std::bind(&ModuleRegisterHelper::create,
347 helper, std::placeholders::_1));
348
349 // Create a capsule that will be embedded in the __main__ namespace. So
350 // deallocation will occur, but only once Python ends or the Python module
351 // is deallocated.
352 std::string modkey =
353 "_" + std::string(ModuleTypeMap[modType]) + "_" + modName;
354
355#if PY_MAJOR_VERSION == 2
356 py::object capsule(
357 py::handle<>(PyCObject_FromVoidPtr(helper, ModuleCapsuleDestructor)));
358#else
359 py::object capsule(
360 py::handle<>(PyCapsule_New(helper, nullptr, ModuleCapsuleDestructor)));
361#endif
362
363 // Embed this in __main__.
364 py::import("__main__").attr(modkey.c_str()) = capsule;
365}
void ModuleCapsuleDestructor(PyObject *ptr)
ModuleSharedPtr create(FieldSharedPtr field)
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:197

References ModuleRegisterHelper::create(), Nektar::FieldUtils::GetModuleFactory(), ModuleCapsuleDestructor(), Nektar::FieldUtils::ModuleTypeMap, and Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::RegisterCreatorFunction().

Referenced by export_Module().

◆ Module_RegisterConfig()

void Module_RegisterConfig ( std::shared_ptr< Module mod,
std::string const &  key,
std::string const &  value 
)

Lightweight wrapper for FieldUtils::Module::RegisterConfig.

Parameters
modModule to call
keyConfiguration key.
valueOptional value (some configuration options are boolean).

Definition at line 261 of file Python/Module.cpp.

263{
264 mod->RegisterConfig(key, value);
265}

Referenced by export_Module().

◆ ModuleCapsuleDestructor()

void ModuleCapsuleDestructor ( PyObject *  ptr)

Definition at line 306 of file Python/Module.cpp.

307{
309 (ModuleRegisterHelper *)PyCapsule_GetPointer(ptr, nullptr);
310 delete tmp;
311}

Referenced by Module_Register().

◆ ModuleWrap_AddConfigOption()

template<typename MODTYPE >
void ModuleWrap_AddConfigOption ( std::shared_ptr< ModuleWrap< MODTYPE > >  mod,
std::string const &  key,
std::string const &  defValue,
std::string const &  desc,
bool  isBool 
)

Definition at line 268 of file Python/Module.cpp.

272{
273 mod->AddConfigOption(key, defValue, desc, isBool);
274}