aboutsummaryrefslogtreecommitdiff
path: root/Python/pywarpx/PICMI.py
diff options
context:
space:
mode:
authorGravatar Dave Grote <grote1@llnl.gov> 2017-05-19 16:21:15 -0700
committerGravatar Dave Grote <grote1@llnl.gov> 2017-05-19 16:21:15 -0700
commit5404acf864e72b6f10727fd5c1493ee59c555395 (patch)
treeacbb234b49e77b17d8c7e7558bd4a22c5a8b717e /Python/pywarpx/PICMI.py
parent50ccb9af554901086b8ba4c003e9218e975c6967 (diff)
downloadWarpX-5404acf864e72b6f10727fd5c1493ee59c555395.tar.gz
WarpX-5404acf864e72b6f10727fd5c1493ee59c555395.tar.zst
WarpX-5404acf864e72b6f10727fd5c1493ee59c555395.zip
Added code satisfying the PICMI standard
Diffstat (limited to 'Python/pywarpx/PICMI.py')
-rw-r--r--Python/pywarpx/PICMI.py199
1 files changed, 199 insertions, 0 deletions
diff --git a/Python/pywarpx/PICMI.py b/Python/pywarpx/PICMI.py
new file mode 100644
index 000000000..3e7e7185f
--- /dev/null
+++ b/Python/pywarpx/PICMI.py
@@ -0,0 +1,199 @@
+"""Classes following the PICMI standard
+"""
+import numpy as np
+from pywarpx import *
+
+pi = 3.14159265358979323 # ratio of a circle's circumference to its diameter
+euler = 0.57721566490153386 # Euler-Masceroni constant. Base of the natural logarithm.
+amu = 1.660538921e-27 # Atomic Mass Unit [kg]
+clight = 2.99792458e+8 # Speed of light in vacuum (exact) [m/s]
+echarge = 1.602176565e-19 # Elementary charge [C]
+emass = 9.10938291e-31 # Electron mass [kg]
+mu0 = 4.e-7*pi # Permeability of free space [kg.m/(s.s.A.A)=H/m=T.m/A]
+eps0 = 1./(mu0*clight*clight) # Permittivity of free space [F/m]
+boltzmann = 1.3806488e-23 # Boltzmann's constant [J/K]
+avogadro = 6.02214129e23 # Avogadro's Number [atoms/mole]
+planck = 6.62606957e-34 # Planck's constant [J.s]
+
+class Grid(object):
+ """
+ - `Grid`
+ - **type**: *object*
+ - `Nx=nx` - **type**: *integer* - "Number of cells along X (Nb nodes=nx+1)."
+ - `Ny=ny` - **type**: *integer* - "Number of cells along Y (Nb nodes=ny+1)."
+ - `Nr=nr` - **type**: *integer* - "Number of cells along R (Nb nodes=nr+1)."
+ - `Nz=nz` - **type**: *integer* - "Number of cells along Z (Nb nodes=nz+1)."
+ - `Nm=nm` - **type**: *integer* - "Number of azimuthal modes."
+ - `Xmin=xmin` - **type**: *double* - "Position of first node along X."
+ - `Xmax=xmax` - **type**: *double* - "Position of last node along X."
+ - `Ymin=ymin` - **type**: *double* - "Position of first node along Y."
+ - `Ymax=ymax` - **type**: *double* - "Position of last node along Y."
+ - `Rmax=rmax` - **type**: *double* - "Position of last node along R."
+ - `Zmin=zmin` - **type**: *double* - "Position of first node along Z."
+ - `Zmax=zmax` - **type**: *double* - "Position of last node along Z."
+ - `bcxmin` - **type**: *string* - "Boundary condition at min X: periodic/open/dirichlet/neumann."
+ - `bcxmax` - **type**: *string* - "Boundary condition at max X: periodic/open/dirichlet/neumann."
+ - `bcymin` - **type**: *string* - "Boundary condition at min Y: periodic/open/dirichlet/neumann."
+ - `bcymax` - **type**: *string* - "Boundary condition at max Y: periodic/open/dirichlet/neumann."
+ - `bcrmax` - **type**: *string* - "Boundary condition at max R: open/dirichlet/neumann."
+ - `bczmin` - **type**: *string* - "Boundary condition at min Z: periodic/open/dirichlet/neumann."
+ - `bczmax` - **type**: *string* - "Boundary condition at max Z: periodic/open/dirichlet/neumann."
+
+ - max_grid_size
+ - max_level
+ - coord_sys
+ """
+
+ def __init__(self, nx=None, ny=None, nr=None, nz=None, nm=None,
+ xmin=None, xmax=None, ymin=None, ymax=None, rmax=None, zmin=None, zmax=None,
+ bcxmin=None, bcxmax=None, bcymin=None, bcymax=None, bcrmax=None, bczmin=None, bczmax=None,
+ **kw):
+ self.nx = nx
+ self.ny = ny
+ self.nr = nr
+ self.nz = nz
+ self.nm = nm
+ self.xmin = xmin
+ self.xmax = xmax
+ self.ymin = ymin
+ self.ymax = ymax
+ self.rmax = rmax
+ self.zmin = zmin
+ self.zmax = zmax
+ self.bcxmin = bcxmin
+ self.bcxmax = bcxmax
+ self.bcymin = bcymin
+ self.bcymax = bcymax
+ self.bcrmax = bcrmax
+ self.bczmin = bczmin
+ self.bczmax = bczmax
+
+ amr.n_cell = '%d %d %d'%(nx, ny, nz)
+
+ # Maximum allowable size of each subdomain in the problem domain;
+ # this is used to decompose the domain for parallel calculations.
+ amr.max_grid_size = kw.get('max_grid_size', 32)
+
+ # Maximum level in hierarchy (for now must be 0, i.e., one level in total)
+ amr.max_level = kw.get('max_level', 0)
+
+ # Geometry
+ geometry.coord_sys = kw.get('coord_sys', 0) # 0: Cartesian
+ geometry.is_periodic = '%d %d %d'%(bcxmin=='periodic', bcymin=='periodic', bczmin=='periodic') # Is periodic?
+ geometry.prob_lo = '%7.0e %7.0e %7.0e'%(xmin, ymin, zmin) # physical domain
+ geometry.prob_hi = '%7.0e %7.0e %7.0e'%(xmax, ymax, zmax)
+
+
+class EM_solver(object):
+ Methods_list = ['Yee', 'CK', 'CKC', 'Lehe', 'PSTD', 'PSATD', 'GPSTD']
+ def __init__(self, Method=None,
+ norderx=None, nordery=None, norderr=None, norderz=None,
+ l_nodal=None,
+ current_deposition_algo=None, charge_deposition_algo=None,
+ field_gathering_algo=None, particle_pusher_algo=None, **kw):
+
+ assert Method is None or Method in EM_solver.Methods_list, Exception('Method has incorrect value')
+
+ if current_deposition_algo is not None:
+ algo.current_deposition = current_deposition_algo
+ if charge_deposition_algo is not None:
+ algo.charge_deposition = charge_deposition_algo
+ if field_gathering_algo is not None:
+ algo.field_gathering = field_gathering_algo
+ if particle_pusher_algo is not None:
+ algo.particle_pusher = particle_pusher_algo
+
+
+class Particle(object):
+ def __init__(self, Charge=None, charge=None, Q=None, q=None,
+ Mass=None, mass=None, M=None, m=None,
+ Symbol=None, symbol=None, S=None, s=None,
+ Name=None, name=None, N=None, n=None, **kw):
+ # --- Accept multpiple names, but use 'charge', 'mass', 'symbol', 'name' internally.
+ if Charge is not None: charge = Charge
+ if Q is not None: charge = Q
+ if q is not None: charge = q
+ if Mass is not None: mass = Mass
+ if M is not None: mass = M
+ if m is not None: mass = m
+ if Symbol is not None: symbol = Symbol
+ if S is not None: symbol = S
+ if s is not None: symbol = s
+ if Name is not None: name = Name
+ if N is not None: name = N
+ if n is not None: name = n
+ self.charge = charge
+ self.mass = mass
+ self.symbol = symbol
+
+Electron = Particle(q=-echarge, m=emass, symbol='e-', name='Electron')
+Positron = Particle(q=echarge, m=emass, symbol='e+', name='Positron')
+Proton = Particle(q=echarge, m=1.6726231e-27, symbol='p', name='Proton')
+AntiProton = Particle(q=-echarge, m=1.6726231e-27, symbol='p-', name='Antiproton')
+Neutron = Particle(q=0. , m=1.6749286e-27, symbol='n', name='Neutron')
+Muon = Particle(q=-echarge, m=1.883531475e-28, symbol='mu-', name='Muon')
+Antimuon = Particle(q=echarge, m=1.883531475e-28, symbol='mu+', name='Antimuon')
+Photon = Particle(q=0., m=0., symbol='gnu', name='Photon')
+
+
+class Species(object):
+ def __init__(self,
+ Type=None, type=None,
+ Name=None, name=None,
+ Sid=None, sid=None,
+ Charge_state=None, charge_state=None,
+ Charge=None, charge=None, Q=None, q=None,
+ Mass=None, mass=None, M=None, m=None,
+ Weight=None, weight=None, W=None, w=None, **kw):
+ # --- Accept multpiple names, but use 'type', 'name', 'sid', 'charge_state', 'charge', 'mass', 'weight'
+ if Type is not None: type = Type
+ if Name is not None: name = Name
+ if Sid is not None: sid = Sid
+ if Charge_state is not None: charge_state = Charge_state
+ if Charge is not None: charge = Charge
+ if Q is not None: charge = Q
+ if q is not None: charge = q
+ if Mass is not None: mass = Mass
+ if M is not None: mass = M
+ if m is not None: mass = m
+ if Weight is not None: weight = Weight
+ if W is not None: weight = W
+ if w is not None: weight = w
+ self.type = type
+ self.name = name
+ self.sid = sid
+ self.charg_state = charg_state
+ self.charge = charge
+ self.mass = mass
+ self.weight = weight
+
+ self.species_number = particles.nspecies
+ particles.nspecies = particles.nspecies + 1
+ particles.species_names = particles.species_names + ' ' + name
+
+ def add_particles(self, n=None,
+ x=None, y=None, z=None,
+ ux=None, uy=None, uz=None, w=None,
+ unique_particles=None, **kw):
+ pid = np.array([w]).T
+ add_particles(self.species_number, x, y, z, ux, uy, uz, pid, unique_particles)
+
+
+class Simulation(object):
+ def __init__(self, plot_int=None, verbose=None, cfl=None):
+ amr.plot_int = plot_int
+ warpx.verbose = verbose
+ warpx.cfl = cfl
+
+ self.amrex = AMReX()
+ self.amrex.init()
+ warpx.init()
+
+ def step(self, nsteps=-1):
+ warpx.evolve(nsteps)
+
+ def finalize(self):
+ warpx.finalize()
+ self.amrex.finalize()
+
+