aboutsummaryrefslogtreecommitdiff
path: root/Python/pywarpx/callbacks.py
diff options
context:
space:
mode:
authorGravatar Axel Huebl <axel.huebl@plasma.ninja> 2023-08-12 11:17:38 -0700
committerGravatar GitHub <noreply@github.com> 2023-08-12 11:17:38 -0700
commit6c93d9fc13830d574c69ac7b166f5fbdb0809731 (patch)
tree8742df6045aa2bfdccb5a7991eae436e886e47d1 /Python/pywarpx/callbacks.py
parentf6760c8e6d64605f73476f9bc8292dc9d85df454 (diff)
downloadWarpX-6c93d9fc13830d574c69ac7b166f5fbdb0809731.tar.gz
WarpX-6c93d9fc13830d574c69ac7b166f5fbdb0809731.tar.zst
WarpX-6c93d9fc13830d574c69ac7b166f5fbdb0809731.zip
Transition to pyAMReX (#3474)
* pyAMReX: Build System * CI Updates (Changed Options) * Callback modernization (#4) * refactor callbacks.py * added binding code in `pyWarpX.cpp` to add or remove keys from the callback dictionary * minor PR cleanups Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja> * Added Python level reference to fetch the multifabs (#3) * pyAMReX: Build System * Added Python level reference to Ex_aux * Now uses the multifab map * Fix typo Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja> * Add initialization and finalize routines (#5) A basic PICMI input file will now run to completion. * Regression Tests: WarpX_PYTHON=ON * Update Imports to nD pyAMReX * IPO/LTO Control Although pybind11 relies heavily on IPO/LTO to create low-latency, small-binary bindings, some compilers will have troubles with that. Thus, we add a compile-time option to optionally disable it when needed. * Fix: Link Legacy WarpXWrappers.cpp * Wrap WarpX instance and start multi particle container * Fix test Python_pass_mpi_comm * Start wrapper for multiparticle container * Add return policy Co-authored-by: Axel Huebl <axel.huebl@plasma.ninja> * Update fields to use MultiFabs directly Remove EOL white space Removed old routines accessing MultiFabs Update to use "node_centered" * Fix compilation with Python * Update fields.py to use modified MultiFab tag names * Remove incorrect, unused code * Add function to extract the WarpX MultiParticleContainer * Complete class WarpXParticleContainer * Wrap functions getNprocs / getMyProc * restore `install___` callback API - could remove later if we want but should maintain backward compatibility for now * add `gett_new` and `getistep` functions wrappers; fix typos in `callbacks.py`; avoid error in getting `rho` from `fields.py` * Update callback call and `getNproc`/`getMyProc` function * Replace function add_n_particles * Fix setitem in fields.py for 1d and 2d * also update `gett_new()` in `_libwarpx.py` in case we want to keep that API * added binding for `WarpXParIter` - needed to port `libwarpx.depositChargeDensity()` which is an ongoing effort * Wrap function num_real_comp * added binding for `TotalNumberOfParticles` and continue progress on enabling 1d MCC test to run * add `SyncRho()` binding and create helper function in `libwarpx.depositChargeDensity` to manage scope of the particle iter * Clean up issues in fields.py * update bindings for `get_particle_structs` * Fix setitem in fields.py * switch order of initialization for particle container and particle iterator * switch deposit_charge loop to C++ code; bind `ApplyInverseVolumeScalingToChargeDensity` * move `WarpXParticleContainer.cpp` and `MultiParticleContainer.cpp` to new Particles folder * added binding for `ParticleBoundaryBuffer` * More fixes for fields.py * Fix: Backtraces from Python Add the Python executable name with an absolute path, so backtraces in AMReX work. See linked AMReX issue for details. * Cleaning * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix: Backtraces from Python Part II Do not add Python script name - it confuses the AMReX ParmParser to build its table. * Fix: CMake Dependencies for Wheel This fixes a racecondition during `pip_install`: it was possible that not all dimensions where yet build from pybind before we start packing them in the wheel for pip install. * MCC Test: Install Callbacks before Run Otherwise hangs in aquiring the gil during shutdown. * addition of `Python/pywarpx/particle_containers.py` and various associated bindings * Fix: CMake Superbuild w/ Shared AMReX We MUST build AMReX as a shared (so/dll/dylib) library, otherwise all the global state in it will cause split-brain situations, where our Python modules operate on different stacks. * add `clear_all()` to callbacks in order to remove all callbacks at finalize * add `-DWarpX_PYTHON=ON` to CI tests that failed to build * add `get_comp_index` and continue to port particle data bindings * Add AMReX Module as `libwarpx_so.amr` Attribute to pass through the already loaded AMReX module with the matching dimensionality to the simulation. * Fix for fields accounting for guard cells * Fix handling of ghost cells in fields * Update & Test: Particle Boundary Scraping * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * CI: Python Updates - modernize Python setups - drop CUDA 11.0 for good and go 11.3+ as documented already ``` Error #3246: Internal Compiler Error (codegen): "there was an error in verifying the lgenfe output!" ``` * CI: Python Updates (chmod) * Add support for cupy in fields.py * Add MultiFab reduction routines * CI: CUDA 11.3 is <= Ubuntu 20.04 * changed `AddNParticles` to take `amrex::Vector` arguments * setup.py: WarpX_PYTHON=ON * update various 2d and rz tests with new APIs * add `-DWarpX_PYTHON_IPO=OFF` to compile string for 2d and 3d Python CI tests to speed up linking * CI: -DpyAMReX_IPO=OFF * CI: -DpyAMReX_IPO=OFF actually adding `=OFF` * CI: Intel Python * CI: macOS Python Executable Ensure we always use the same `python3` executable, as specified by the `PATH` priority. * CMake: Python Multi-Config Build Add support for multi-config generators, especially on Windows. * __init__.py: Windows DLL Support Python 3.8+ on Windows: DLL search paths for dependent shared libraries Refs.: - https://github.com/python/cpython/issues/80266 - https://docs.python.org/3.8/library/os.html#os.add_dll_directory * CI: pywarpx Update our setup.py cannot install pyamrex yet as a dependency. * ABLASTR: `ablastr/export.H` Add a new header to export public globals that are not covered by `WINDOWS_EXPORT_ALL_SYMBOLS`. https://stackoverflow.com/questions/54560832/cmake-windows-export-all-symbols-does-not-cover-global-variables/54568678#54568678 * WarpX: EXPORT Globals in `.dll` files WarpX still uses a lot of globals: - `static` member variables - `extern` global variables These globals cannot be auto-exported with CMake's `WINDOWS_EXPORT_ALL_SYMBOLS` helper and thus we need to mark them manually for DLL export (and import) via the new ABLASTR `ablastr/export.H` helper macros. This starts to export symbols in the: - WarpX and particle container classes - callback hook database map - ES solver * CI: pywarpx Clang CXXFLAGS Down Move CXXFLAGS (`-Werror ...`) down until deps are installed. * GNUmake: Generate `ablastr/export.H` * CMake: More Symbol Exports for Windows * `WarpX-tests.ini`: Simplify Python no-IPO Also avoids subtle differences in compilation that increase compile time. * Update PICMI_inputs_EB_API.py for embedded_boundary_python_API CI test * Fix Python_magnetostatic_eb_3d * Update: Python_restart_runtime_components New Python APIs * Windows: no dllimport for now * CI: Skip `PYINSTALLOPTIONS` For Now * CMake: Dependency Bump Min-Versions for external packages picked up by `find_package`. * Fix F and G_fp names in fields.py * Tests: Disable `Python_pass_mpi_comm` * Wrappers: Cleanup * pyWarpX: Include Cleaning * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fields.py: Fix F and G Wrappers Correct MultiFab names (w/o components). * Remove unused in fields.py * Windows: New Export Headers - ABLASTR: `ablastr/export.H` - WarpX: `Utils/export.H` * removed `WarpInterface.py` since that functionality is now in `particle_containers.py`; removed parts of `WarpXWrappers.cpp` that have been ported to pyamrex * CMake: Link OBJECT Target PRIVATE * CMake: Remove OBJECT Target Simplify and make `app` link `lib` (default: static). Remove OBJECT target. * Fix in fields.py for the components index * Update get_particle_id/cpu As implemented in pyAMReX with https://github.com/AMReX-Codes/pyamrex/pull/165 * WarpX: Update for Private Constructor * Import AMReX Before pyd DLL Call Importing AMReX will add the `add_dll_directory` to a potentially shared amrex DLL on Windows. * Windows CI: Set PATH to amrex_Nd.dll * CMake: AMReX_INSTALL After Python In superbuild, Python can modify `AMReX_BUILD_SHARED_LIBS`. * Clang Win CI: Manually Install requirements Sporadic error is: ``` ... Installing collected packages: pyparsing, numpy, scipy, periodictable, picmistandard ERROR: Could not install packages due to an OSError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\hostedtoolcache\\windows\\Python\\3.11.4\\x64\\Lib\\site-packages\\numpy\\polynomial\\__init__.py' Consider using the `--user` option or check the permissions. ``` * Hopefully final fixes to fields.py * Update getProbLo/getProbHi * Set plasma length strength Co-authored-by: Remi Lehe <remi.lehe@normalesup.org> * Fix fields method to remove CodeQL notice * Update Comments & Some Finalize * Move: set_plasma_lens_strength to MPC --------- Co-authored-by: Roelof Groenewald <40245517+roelof-groenewald@users.noreply.github.com> Co-authored-by: David Grote <dpgrote@lbl.gov> Co-authored-by: Remi Lehe <remi.lehe@normalesup.org> Co-authored-by: Dave Grote <grote1@llnl.gov> Co-authored-by: Roelof Groenewald <regroenewald@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Diffstat (limited to 'Python/pywarpx/callbacks.py')
-rw-r--r--Python/pywarpx/callbacks.py410
1 files changed, 125 insertions, 285 deletions
diff --git a/Python/pywarpx/callbacks.py b/Python/pywarpx/callbacks.py
index 02a8f5aad..b8824d0ef 100644
--- a/Python/pywarpx/callbacks.py
+++ b/Python/pywarpx/callbacks.py
@@ -1,7 +1,9 @@
-# Copyright 2017 David Grote
+# Copyright 2017-2022 The WarpX Community
#
# This file is part of WarpX.
#
+# Authors: David Grote, Roelof Groenewald
+#
# License: BSD-3-Clause-LBNL
"""call back operations
@@ -10,41 +12,43 @@
These are the functions which allow installing user created functions so that
they are called at various places along the time step.
-For each call back type, the following three functions are defined.
- - install___: Installs a function to be called at that specified time
- - uninstall___: Uninstalls the function (so it won't be called anymore)
- - isinstalled___: Checks if the function is installed
+The following three functions allow the user to install, uninstall and verify
+the different call back types.
+ - installcallback: Installs a function to be called at that specified time
+ - uninstallcallback: Uninstalls the function (so it won't be called anymore)
+ - isinstalled: Checks if the function is installed
-These functions all take a function or instance method as an argument. Note that
-if an instance method is used, an extra reference to the method's object is saved.
+These functions all take a callback location name (string) and function or
+instance method as an argument. Note that if an instance method is used, an
+extra reference to the method's object is saved.
-The install can be done using a decorator, which has the prefix "callfrom". See example below.
+The install can be done using a decorator, which has the prefix "callfrom". See
+example below.
Functions can be called at the following times:
- - beforeInitEsolve <installbeforeInitEsolve>: before the initial solve for the E fields (i.e. before the PIC loop starts)
- - afterInitEsolve <installafterInitEsolve>: after the initial solve for the E fields (i.e. before the PIC loop starts)
- - afterinit <installafterinit>: immediately after the init is complete
- - beforeEsolve <installbeforeEsolve>: before the solve for E fields
- - poissonsolver <installpoissonsolver>: In place of the computePhi call but only in an electrostatic simulation
- - afterEsolve <installafterEsolve>: after the solve for E fields
- - beforedeposition <installbeforedeposition>: before the particle deposition (for charge and/or current)
- - afterdeposition <installafterdeposition>: after particle deposition (for charge and/or current)
- - beforestep <installbeforestep>: before the time step
- - afterstep <installafterstep>: after the time step
- - afterdiagnostics <installafterdiagnostics>: after diagnostic output
- - oncheckpointsignal <installoncheckpointsignal>: on a checkpoint signal
- - onbreaksignal <installonbreaksignal>: on a break signal. These callbacks will be the last ones executed
- before the simulation ends.
- - particlescraper <installparticlescraper>: just after the particle boundary conditions are applied
- but before lost particles are processed
- - particleloader <installparticleloader>: at the time that the standard particle loader is called
- - particleinjection <installparticleinjection>: called when particle injection happens, after the position
- advance and before deposition is called, allowing a user defined
- particle distribution to be injected each time step
- - appliedfields <installappliedfields>: allows directly specifying any fields to be applied to the particles
- during the advance
-
-To use a decorator, the syntax is as follows. This will install the function myplots to be called after each step.
+ - beforeInitEsolve: before the initial solve for the E fields (i.e. before the PIC loop starts)
+ - afterinit: immediately after the init is complete
+ - beforeEsolve: before the solve for E fields
+ - poissonsolver: In place of the computePhi call but only in an electrostatic simulation
+ - afterEsolve: after the solve for E fields
+ - beforedeposition: before the particle deposition (for charge and/or current)
+ - afterdeposition: after particle deposition (for charge and/or current)
+ - beforestep: before the time step
+ - afterstep: after the time step
+ - afterdiagnostics: after diagnostic output
+ - oncheckpointsignal: on a checkpoint signal
+ - onbreaksignal: on a break signal. These callbacks will be the last ones executed before the simulation ends.
+ - particlescraper: just after the particle boundary conditions are applied
+ but before lost particles are processed
+ - particleloader: at the time that the standard particle loader is called
+ - particleinjection: called when particle injection happens, after the position
+ advance and before deposition is called, allowing a user
+ defined particle distribution to be injected each time step
+ - appliedfields: allows directly specifying any fields to be applied to the particles
+ during the advance
+
+To use a decorator, the syntax is as follows. This will install the function
+``myplots`` to be called after each step.
@callfromafterstep
def myplots():
@@ -54,13 +58,10 @@ This is equivalent to the following:
def myplots():
ppzx()
-installafterstep(myplots)
+installcallback('afterstep', myplots)
"""
-from __future__ import generators
-
import copy
-import ctypes
import sys
import time
import types
@@ -84,12 +85,13 @@ class CallbackFunctions(object):
installed a method in one of the call back lists.
"""
- def __init__(self,name=None,lcallonce=0):
+ def __init__(self,name=None,lcallonce=0,singlefunconly=False):
self.funcs = []
self.time = 0.
self.timers = {}
self.name = name
self.lcallonce = lcallonce
+ self.singlefunconly = singlefunconly
def __call__(self,*args,**kw):
"""Call all of the functions in the list"""
@@ -100,9 +102,7 @@ class CallbackFunctions(object):
def clearlist(self):
"""Unregister/clear out all registered C callbacks"""
self.funcs = []
- libwarpx.libwarpx_so.warpx_clear_callback_py(
- ctypes.c_char_p(self.name.encode('utf-8'))
- )
+ libwarpx.libwarpx_so.remove_python_callback(self.name)
def __bool__(self):
"""Returns True if functions are installed, otherwise False"""
@@ -158,15 +158,15 @@ class CallbackFunctions(object):
def installfuncinlist(self,f):
"""Check if the specified function is installed"""
+ if self.singlefunconly and self.hasfuncsinstalled():
+ raise RuntimeError(
+ f"Only one function can be installed for callback {self.name}."
+ )
+
if len(self.funcs) == 0:
# If this is the first function installed, set the callback in the C++
# to call this class instance.
- # Note that the _c_func must be saved.
- _CALLBACK_FUNC_0 = ctypes.CFUNCTYPE(None)
- self._c_func = _CALLBACK_FUNC_0(self)
- libwarpx.libwarpx_so.warpx_set_callback_py(
- ctypes.c_char_p(self.name.encode('utf-8')), self._c_func
- )
+ libwarpx.libwarpx_so.add_python_callback(self.name, self)
if isinstance(f,types.MethodType):
# --- If the function is a method of a class instance, then save a full
# --- reference to that instance and the method name.
@@ -254,30 +254,51 @@ class CallbackFunctions(object):
#=============================================================================
+callback_instances = {
+ "beforeInitEsolve": {},
+ "afterInitEsolve": {},
+ "afterinit": {},
+ "beforecollisions": {},
+ "aftercollisions": {},
+ "beforeEsolve": {},
+ "poissonsolver": {'singlefunconly': True}, # external Poisson solver
+ "afterEsolve": {},
+ "beforedeposition": {},
+ "afterdeposition": {},
+ "particlescraper": {},
+ "particleloader": {},
+ "beforestep": {},
+ "afterstep": {},
+ "afterdiagnostics": {},
+ "afterrestart": {},
+ "oncheckpointsignal": {},
+ "onbreaksignal": {},
+ "particleinjection": {},
+ "appliedfields": {}
+}
+
# --- Now create the actual instances.
-_beforeInitEsolve = CallbackFunctions('beforeInitEsolve')
-_afterInitEsolve = CallbackFunctions('afterInitEsolve')
-_afterinit = CallbackFunctions('afterinit')
-_beforecollisions = CallbackFunctions('beforecollisions')
-_aftercollisions = CallbackFunctions('aftercollisions')
-_beforeEsolve = CallbackFunctions('beforeEsolve')
-_poissonsolver = CallbackFunctions('poissonsolver')
-_afterEsolve = CallbackFunctions('afterEsolve')
-_beforedeposition = CallbackFunctions('beforedeposition')
-_afterdeposition = CallbackFunctions('afterdeposition')
-_particlescraper = CallbackFunctions('particlescraper')
-_particleloader = CallbackFunctions('particleloader')
-_beforestep = CallbackFunctions('beforestep')
-_afterstep = CallbackFunctions('afterstep')
-_afterdiagnostics = CallbackFunctions('afterdiagnostics')
-_afterrestart = CallbackFunctions('afterrestart',lcallonce=1)
-_oncheckpointsignal = CallbackFunctions('oncheckpointsignal')
-_onbreaksignal = CallbackFunctions('onbreaksignal')
-_particleinjection = CallbackFunctions('particleinjection')
-_appliedfields = CallbackFunctions('appliedfields')
+for key, val in callback_instances.items():
+ callback_instances[key] = CallbackFunctions(name=key, **val)
+
+def installcallback(name, f):
+ "Adds a function to the list of functions called by this callback"
+ callback_instances[name].installfuncinlist(f)
+
+def uninstallcallback(name, f):
+ "Removes the function from the list of functions called by this callback"
+ callback_instances[name].uninstallfuncinlist(f)
+def isinstalled(name, f):
+ "Checks if the function is called by this callback"
+ return callback_instances[name].isinstalledfuncinlist(f)
+
+def clear_all():
+ for key, val in callback_instances.items():
+ val.clearlist()
#=============================================================================
+
def printcallbacktimers(tmin=1.,lminmax=False,ff=None):
"""Prints timings of installed functions.
- tmin=1.: only functions with time greater than tmin will be printed
@@ -285,18 +306,7 @@ def printcallbacktimers(tmin=1.,lminmax=False,ff=None):
- ff=None: If given, timings will be written to the file object instead of stdout
"""
if ff is None: ff = sys.stdout
- for c in [ _beforeInitEsolve, _afterInitEsolve,
- _afterinit,_beforeEsolve,_poissonsolver,_afterEsolve,
- _beforedeposition,_afterdeposition,
- _particlescraper,
- _particleloader,
- _beforestep,_afterstep,
- _afterdiagnostics,
- _afterrestart,
- _oncheckpointsignal,
- _onbreaksignal,
- _particleinjection,
- _appliedfields]:
+ for c in callback_instances.values():
for fname, time in c.timers.items():
#vlist = numpy.array(gather(time))
vlist = numpy.array([time])
@@ -316,299 +326,129 @@ def printcallbacktimers(tmin=1.,lminmax=False,ff=None):
ff.write('\n')
#=============================================================================
+
# ----------------------------------------------------------------------------
def callfrombeforeInitEsolve(f):
- installbeforeInitEsolve(f)
+ installcallback('beforeInitEsolve', f)
return f
def installbeforeInitEsolve(f):
- "Adds a function to the list of functions called before the initial E solve"
- _beforeInitEsolve.installfuncinlist(f)
-def uninstallbeforeInitEsolve(f):
- "Removes the function from the list of functions called before the initial E solve"
- _beforeInitEsolve.uninstallfuncinlist(f)
-def isinstalledbeforeInitEsolve(f):
- "Checks if the function is called before the initial E solve"
- return _beforeInitEsolve.isinstalledfuncinlist(f)
+ installcallback('beforeInitEsolve', f)
# ----------------------------------------------------------------------------
def callfromafterInitEsolve(f):
- installafterInitEsolve(f)
+ installcallback('afterInitEsolve', f)
return f
def installafterInitEsolve(f):
- "Adds a function to the list of functions called after the initial E solve"
- _afterInitEsolve.installfuncinlist(f)
-def uninstallafterInitEsolve(f):
- "Removes the function from the list of functions called after the initial E solve"
- _afterInitEsolve.uninstallfuncinlist(f)
-def isinstalledafterInitEsolve(f):
- "Checks if the function is called after the initial E solve"
- return _afterInitEsolve.isinstalledfuncinlist(f)
+ installcallback('afterInitEsolve', f)
# ----------------------------------------------------------------------------
def callfromafterinit(f):
- installafterinit(f)
+ installcallback('afterinit', f)
return f
def installafterinit(f):
- "Adds a function to the list of functions called after the init"
- _afterinit.installfuncinlist(f)
-def uninstallafterinit(f):
- "Removes the function from the list of functions called after the init"
- _afterinit.uninstallfuncinlist(f)
-def isinstalledafterinit(f):
- "Checks if the function is called after a init"
- return _afterinit.isinstalledfuncinlist(f)
+ installcallback('afterinit', f)
# ----------------------------------------------------------------------------
def callfrombeforecollisions(f):
- installbeforecollisions(f)
+ installcallback('beforecollisions', f)
return f
def installbeforecollisions(f):
- "Adds a function to the list of functions called before collisions"
- _beforecollisions.installfuncinlist(f)
-def uninstallbeforecollisions(f):
- "Removes the function from the list of functions called before collisions"
- _beforecollisions.uninstallfuncinlist(f)
-def isinstalledbeforecollisions(f):
- "Checks if the function is called before collisions"
- return _beforecollisions.isinstalledfuncinlist(f)
+ installcallback('beforecollisions', f)
# ----------------------------------------------------------------------------
def callfromaftercollisions(f):
- installaftercollisions(f)
+ installcallback('aftercollisions', f)
return f
def installaftercollisions(f):
- "Adds a function to the list of functions called after collisions"
- _aftercollisions.installfuncinlist(f)
-def uninstallaftercollisions(f):
- "Removes the function from the list of functions called after collisions"
- _aftercollisions.uninstallfuncinlist(f)
-def isinstalledaftercollisions(f):
- "Checks if the function is called after collisions"
- return _aftercollisions.isinstalledfuncinlist(f)
+ installcallback('aftercollisions', f)
# ----------------------------------------------------------------------------
def callfrombeforeEsolve(f):
- installbeforeEsolve(f)
+ installcallback('beforeEsolve', f)
return f
def installbeforeEsolve(f):
- "Adds a function to the list of functions called before an E solve"
- _beforeEsolve.installfuncinlist(f)
-def uninstallbeforeEsolve(f):
- "Removes the function from the list of functions called before an E solve"
- _beforeEsolve.uninstallfuncinlist(f)
-def isinstalledbeforeEsolve(f):
- "Checks if the function is called before an E solve"
- return _beforeEsolve.isinstalledfuncinlist(f)
+ installcallback('beforeEsolve', f)
# ----------------------------------------------------------------------------
def callfrompoissonsolver(f):
- installpoissonsolver(f)
+ installcallback('poissonsolver', f)
return f
def installpoissonsolver(f):
- """Installs an external function to solve Poisson's equation"""
- if _poissonsolver.hasfuncsinstalled():
- raise RuntimeError("Only one external Poisson solver can be installed.")
- _poissonsolver.installfuncinlist(f)
-def uninstallpoissonsolver(f):
- """Removes the external function to solve Poisson's equation"""
- _poissonsolver.uninstallfuncinlist(f)
-def isinstalledpoissonsolver(f):
- """Checks if the function is called to solve Poisson's equation"""
- return _poissonsolver.isinstalledfuncinlist(f)
+ installcallback('poissonsolver', f)
# ----------------------------------------------------------------------------
def callfromafterEsolve(f):
- installafterEsolve(f)
+ installcallback('afterEsolve', f)
return f
def installafterEsolve(f):
- "Adds a function to the list of functions called after an E solve"
- _afterEsolve.installfuncinlist(f)
-def uninstallafterEsolve(f):
- "Removes the function from the list of functions called after an E solve"
- _afterEsolve.uninstallfuncinlist(f)
-def isinstalledafterEsolve(f):
- "Checks if the function is called after an E solve"
- return _afterEsolve.isinstalledfuncinlist(f)
+ installcallback('afterEsolve', f)
# ----------------------------------------------------------------------------
def callfrombeforedeposition(f):
- installbeforedeposition(f)
+ installcallback('beforedeposition', f)
return f
def installbeforedeposition(f):
- "Adds a function to the list of functions called before a particle deposition"
- _beforedeposition.installfuncinlist(f)
-def uninstallbeforedeposition(f):
- "Removes the function from the list of functions called before a particle deposition"
- _beforedeposition.uninstallfuncinlist(f)
-def isinstalledbeforedeposition(f):
- "Checks if the function is called before a particle deposition"
- return _beforedeposition.isinstalledfuncinlist(f)
+ installcallback('beforedeposition', f)
# ----------------------------------------------------------------------------
def callfromafterdeposition(f):
- installafterdeposition(f)
+ installcallback('afterdeposition', f)
return f
def installafterdeposition(f):
- "Adds a function to the list of functions called after a particle deposition"
- _afterdeposition.installfuncinlist(f)
-def uninstallafterdeposition(f):
- "Removes the function from the list of functions called after a particle deposition"
- _afterdeposition.uninstallfuncinlist(f)
-def isinstalledafterdeposition(f):
- "Checks if the function is called after a particle deposition"
- return _afterdeposition.isinstalledfuncinlist(f)
+ installcallback('afterdeposition', f)
# ----------------------------------------------------------------------------
def callfromparticlescraper(f):
- installparticlescraper(f)
+ installcallback('particlescraper', f)
return f
def installparticlescraper(f):
- "Adds a function to the list of functions called to scrape particles"
- _particlescraper.installfuncinlist(f)
-def uninstallparticlescraper(f):
- "Removes the function from the list of functions called to scrape particles"
- _particlescraper.uninstallfuncinlist(f)
-def isinstalledparticlescraper(f):
- "Checks if the function is called to scrape particles"
- return _particlescraper.isinstalledfuncinlist(f)
+ installcallback('particlescraper', f)
# ----------------------------------------------------------------------------
def callfromparticleloader(f):
- installparticleloader(f)
+ installcallback('particleloader', f)
return f
def installparticleloader(f):
- "Adds a function to the list of functions called to load particles"
- _particleloader.installfuncinlist(f)
-def uninstallparticleloader(f):
- "Removes the function from the list of functions called to load particles"
- _particleloader.uninstallfuncinlist(f)
-def isinstalledparticleloader(f):
- "Checks if the function is called to load particles"
- return _particleloader.isinstalledfuncinlist(f)
+ installcallback('particleloader', f)
# ----------------------------------------------------------------------------
def callfrombeforestep(f):
- installbeforestep(f)
+ installcallback('beforestep', f)
return f
def installbeforestep(f):
- "Adds a function to the list of functions called before a step"
- _beforestep.installfuncinlist(f)
-def uninstallbeforestep(f):
- "Removes the function from the list of functions called before a step"
- _beforestep.uninstallfuncinlist(f)
-def isinstalledbeforestep(f):
- "Checks if the function is called before a step"
- return _beforestep.isinstalledfuncinlist(f)
+ installcallback('beforestep', f)
# ----------------------------------------------------------------------------
def callfromafterstep(f):
- installafterstep(f)
+ installcallback('afterstep', f)
return f
def installafterstep(f):
- "Adds a function to the list of functions called after a step"
- _afterstep.installfuncinlist(f)
-def uninstallafterstep(f):
- "Removes the function from the list of functions called after a step"
- _afterstep.uninstallfuncinlist(f)
-def isinstalledafterstep(f):
- "Checks if the function is called after a step"
- return _afterstep.isinstalledfuncinlist(f)
+ installcallback('afterstep', f)
# ----------------------------------------------------------------------------
def callfromafterdiagnostics(f):
- installafterdiagnostics(f)
+ installcallback('afterdiagnostics', f)
return f
def installafterdiagnostics(f):
- "Adds a function to the list of functions called after diagnostic output"
- _afterdiagnostics.installfuncinlist(f)
-def uninstallafterdiagnostics(f):
- "Removes the function from the list of functions called after diagnostic output"
- _afterdiagnostics.uninstallfuncinlist(f)
-def isinstalledafterdiagnostics(f):
- "Checks if the function is called after diagnostic output"
- return _afterdiagnostics.isinstalledfuncinlist(f)
-
-# ----------------------------------------------------------------------------
-def callfromafterrestart(f):
- raise Exception('restart call back not implemented yet')
- installafterrestart(f)
- return f
-def installafterrestart(f):
- "Adds a function to the list of functions called immediately after a restart"
- raise Exception('restart call back not implemented yet')
- _afterrestart.installfuncinlist(f)
-def uninstallafterrestart(f):
- "Removes the function from the list of functions called immediately after a restart"
- raise Exception('restart call back not implemented yet')
- _afterrestart.uninstallfuncinlist(f)
-def isinstalledafterrestart(f):
- "Checks if the function is called immediately after a restart"
- raise Exception('restart call back not implemented yet')
- return _afterrestart.isinstalledfuncinlist(f)
+ installcallback('afterdiagnostics', f)
# ----------------------------------------------------------------------------
def oncheckpointsignal(f):
- installoncheckpointsignal(f)
+ installcallback('oncheckpointsignal', f)
return f
def installoncheckpointsignal(f):
- "Adds a function to the list of functions called on checkpoint signal"
- _oncheckpointsignal.installfuncinlist(f)
-def uninstalloncheckpointsignal(f):
- "Removes the function from the list of functions called on checkpoint signal"
- _oncheckpointsignal.uninstallfuncinlist(f)
-def isinstalledoncheckpointsignal(f):
- "Checks if the function is called on checkpoint signal"
- return _oncheckpointsignal.isinstalledfuncinlist(f)
+ installcallback('oncheckpointsignal', f)
# ----------------------------------------------------------------------------
def onbreaksignal(f):
- installonbreaksignal(f)
+ installcallback('onbreaksignal', f)
return f
def installonbreaksignal(f):
- "Adds a function to the list of functions called on a break signal"
- _onbreaksignal.installfuncinlist(f)
-def uninstallonbreaksignal(f):
- "Removes the function from the list of functions called on a break signal"
- _onbreaksignal.uninstallfuncinlist(f)
-def isinstalledonbreaksignal(f):
- "Checks if the function is called on a break signal"
- return _onbreaksignal.isinstalledfuncinlist(f)
+ installcallback('onbreaksignal', f)
# ----------------------------------------------------------------------------
def callfromparticleinjection(f):
- installparticleinjection(f)
+ installcallback('particleinjection', f)
return f
def installparticleinjection(f):
- """
- Adds a user defined function that is to be called when particle
- injection happens, after the position advance and before deposition is
- called, allowing a user defined particle distribution to be injected
- each time step"""
- _particleinjection.installfuncinlist(f)
-def uninstallparticleinjection(f):
- "Removes the function installed by installparticleinjection"
- _particleinjection.uninstallfuncinlist(f)
-def isinstalledparticleinjection(f):
- "Checks if the function is called when particles injection happens"
- return _particleinjection.isinstalledfuncinlist(f)
-
-# ----------------------------------------------------------------------------
-def callfromappliedfields(f):
- raise Exception('applied fields call back not implemented yet')
- installappliedfields(f)
- return f
-def installappliedfields(f):
- """
- Adds a user defined function which can specify E and B fields which are applied
- to the particles during the particle advance.
- """
- raise Exception('applied fields call back not implemented yet')
- _appliedfields.installfuncinlist(f)
-def uninstallappliedfields(f):
- "Removes the function installed by installappliedfields"
- raise Exception('applied fields call back not implemented yet')
- _appliedfields.uninstallfuncinlist(f)
-def isinstalledappliedfields(f):
- "Checks if the function is called when which applies fields"
- raise Exception('applied fields call back not implemented yet')
- return _appliedfields.isinstalledfuncinlist(f)
+ installcallback('particleinjection', f)