diff options
author | 2023-08-12 11:17:38 -0700 | |
---|---|---|
committer | 2023-08-12 11:17:38 -0700 | |
commit | 6c93d9fc13830d574c69ac7b166f5fbdb0809731 (patch) | |
tree | 8742df6045aa2bfdccb5a7991eae436e886e47d1 /Python/pywarpx/callbacks.py | |
parent | f6760c8e6d64605f73476f9bc8292dc9d85df454 (diff) | |
download | WarpX-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.py | 410 |
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) |