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 409 of file Python/Module.cpp.

410{
411 // Export ModuleType enum.
413
414 // Define ModuleWrap to be implicitly convertible to a Module, since it
415 // seems that doesn't sometimes get picked up.
416 py::implicitly_convertible<std::shared_ptr<ModuleWrap<Module>>,
417 std::shared_ptr<Module>>();
418 py::implicitly_convertible<std::shared_ptr<ModuleWrap<InputModule>>,
419 std::shared_ptr<Module>>();
420 py::implicitly_convertible<std::shared_ptr<ModuleWrap<OutputModule>>,
421 std::shared_ptr<Module>>();
422 py::implicitly_convertible<std::shared_ptr<ModuleWrap<ProcessModule>>,
423 std::shared_ptr<Module>>();
424
425 // Wrapper for the Module class. Note that since Module contains a pure
426 // virtual function, we need the ModuleWrap helper class to handle this for
427 // us. In the lightweight wrappers above, we therefore need to ensure we're
428 // passing std::shared_ptr<Module> as the first argument, otherwise they
429 // won't accept objects constructed from Python.
430 py::class_<ModuleWrap<Module>, std::shared_ptr<ModuleWrap<Module>>,
431 boost::noncopyable>("Module", py::init<FieldSharedPtr>())
432
433 // Process function for this module.
434 .def("Process", py::pure_virtual(&Module_Process))
435 .def("Run", py::pure_virtual(&Module_Process))
436
437 // Configuration options.
438 .def("RegisterConfig", Module_RegisterConfig,
439 (py::arg("key"), py::arg("value") = ""))
440 .def("PrintConfig", &Module::PrintConfig)
441 .def("SetDefaults", &Module::SetDefaults)
442 .def("GetStringConfig", Module_GetConfig<std::string>)
443 .def("GetFloatConfig", Module_GetConfig<double>)
444 .def("GetIntConfig", Module_GetConfig<int>)
445 .def("GetBoolConfig", Module_GetConfig<bool>)
446 .def("AddConfigOption", ModuleWrap_AddConfigOption<Module>,
447 (py::arg("key"), py::arg("defValue"), py::arg("desc"),
448 py::arg("isBool") = false))
449
450 // Allow direct access to field object through a property.
451 .def_readwrite("field", &ModuleWrap<Module>::m_f)
452
453 // Factory functions.
454 .def("Register", &Module_Register)
455 .staticmethod("Register");
456
458
459 PythonModuleClass<InputModule>("InputModule");
460 PythonModuleClass<ProcessModule>("ProcessModule");
461 PythonModuleClass<OutputModule>("OutputModule");
462}
#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:74
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 165 of file Python/Module.cpp.

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

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 128 of file Python/Module.cpp.

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

◆ Module_Process()

void Module_Process ( ModuleSharedPtr  m)

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

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

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 337 of file Python/Module.cpp.

339{
340 // Create a module register helper, which will call the C++ function to
341 // create the module.
343
344 // Register this with the module factory using std::bind to grab a function
345 // pointer to that particular object's function.
347 ModuleKey(modType, modName), std::bind(&ModuleRegisterHelper::create,
348 helper, std::placeholders::_1));
349
350 // Create a capsule that will be embedded in the __main__ namespace. So
351 // deallocation will occur, but only once Python ends or the Python module
352 // is deallocated.
353 std::string modkey =
354 "_" + std::string(ModuleTypeMap[modType]) + "_" + modName;
355
356#if PY_MAJOR_VERSION == 2
357 py::object capsule(
358 py::handle<>(PyCObject_FromVoidPtr(helper, ModuleCapsuleDestructor)));
359#else
360 py::object capsule(
361 py::handle<>(PyCapsule_New(helper, 0, ModuleCapsuleDestructor)));
362#endif
363
364 // Embed this in __main__.
365 py::import("__main__").attr(modkey.c_str()) = capsule;
366}
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:198

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 262 of file Python/Module.cpp.

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

Referenced by export_Module().

◆ ModuleCapsuleDestructor()

void ModuleCapsuleDestructor ( PyObject *  ptr)

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

308{
310 (ModuleRegisterHelper *)PyCapsule_GetPointer(ptr, 0);
311 delete tmp;
312}

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 269 of file Python/Module.cpp.

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