1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
|
# Copyright 2019 David Grote
#
# This file is part of WarpX.
#
# License: BSD-3-Clause-LBNL
# This sets up an interface between Warp and WarpX, allowing access to WarpX data using
# classes from Warp.
# The routine warp_species will return an instance of the Species class from Warp,
# giving nearly all of the capability of that class, including accessing the data
# using down selection and all of the plots.
# The class WarpX_EM3D inherits from Warp's EM3D class. It primarily provides
# access to the field plotting routines.
import warp
from pywarpx import PGroup
from . import fields
# The particle weight is always the first pid
warp.top.wpid = 1
def warp_species(warp_type, picmi_species, level=0):
"""Returns a Warp species that has a reference to the WarpX particles.
"""
pgroups = PGroup.PGroups(ispecie=picmi_species.species_number, level=level)
return warp.Species(type=warp_type, pgroups=pgroups)
class _WarpX_FIELDtype(object):
"""Mirrors part of the EM3D_FIELDtype type from Warp
yf
"""
def __init__(self, yf):
self.yf = yf
class _WarpX_BLOCKtype(object):
"""Mirrors part of the EM3D_BLOCKtype type from Warp
core
xmin, ymin, zmin
xmax, ymax, zmax
dx, dy, dz
xrbnd, yrbnd, zrbnd
"""
def __init__(self, fields, picmi_grid):
self.core = _WarpX_FIELDtype(fields)
self.picmi_grid = picmi_grid
self.xmin = self.picmi_grid.lower_bound[0]
if self.picmi_grid.number_of_dimensions == 3:
self.ymin = self.picmi_grid.lower_bound[1]
else:
self.ymin = 0.
self.zmin = self.picmi_grid.lower_bound[-1]
self.xmax = self.picmi_grid.upper_bound[0]
if self.picmi_grid.number_of_dimensions == 3:
self.ymax = self.picmi_grid.upper_bound[1]
else:
self.ymax = 0.
self.zmax = self.picmi_grid.upper_bound[-1]
self.dx = (self.xmax - self.xmin)/self.picmi_grid.number_of_cells[0]
if self.picmi_grid.number_of_dimensions == 3:
self.dy = (self.ymax - self.ymin)/self.picmi_grid.number_of_cells[1]
else:
self.dy = 1.
self.dz = (self.zmax - self.zmin)/self.picmi_grid.number_of_cells[-1]
self.xrbnd = 0
self.yrbnd = 0
self.zrbnd = 0
class _WarpX_YEEFIELDtype(object):
"""Mirrors part of the EM3D_YEEFIELDtype type from Warp
Exp, Eyp, Ezp
Bxp, Byp, Bzp
Ex, Ey, Ez
Bx, By, Bz
Jx, Jy, Jz
"""
def __init__(self, level=0):
self.level = level
self._Ex_wrap = fields.ExWrapper(level, include_ghosts=True)
self._Ey_wrap = fields.EyWrapper(level, include_ghosts=True)
self._Ez_wrap = fields.EzWrapper(level, include_ghosts=True)
self._Bx_wrap = fields.BxWrapper(level, include_ghosts=True)
self._By_wrap = fields.ByWrapper(level, include_ghosts=True)
self._Bz_wrap = fields.BzWrapper(level, include_ghosts=True)
self._Jx_wrap = fields.JxWrapper(level, include_ghosts=True)
self._Jy_wrap = fields.JyWrapper(level, include_ghosts=True)
self._Jz_wrap = fields.JzWrapper(level, include_ghosts=True)
self._Ex_wrap._getlovects() # --- Calculated nghosts
self.nxguard = self._Ex_wrap.nghosts
self.nyguard = self._Ex_wrap.nghosts
self.nzguard = self._Ex_wrap.nghosts
def _get_wrapped_array(self, wrapper):
result = wrapper[...]
if len(result.shape) == 2:
# --- Add the middle dimension that Warp is expecting
result.shape = [result.shape[0], 1, result.shape[1]]
return result
@property
def Exp(self):
return self._get_wrapped_array(self._Ex_wrap)
@property
def Eyp(self):
return self._get_wrapped_array(self._Ey_wrap)
@property
def Ezp(self):
return self._get_wrapped_array(self._Ez_wrap)
@property
def Bxp(self):
return self._get_wrapped_array(self._Bx_wrap)
@property
def Byp(self):
return self._get_wrapped_array(self._By_wrap)
@property
def Bzp(self):
return self._get_wrapped_array(self._Bz_wrap)
@property
def Ex(self):
return self._get_wrapped_array(self._Ex_wrap)
@property
def Ey(self):
return self._get_wrapped_array(self._Ey_wrap)
@property
def Ez(self):
return self._get_wrapped_array(self._Ez_wrap)
@property
def Bx(self):
return self._get_wrapped_array(self._Bx_wrap)
@property
def By(self):
return self._get_wrapped_array(self._By_wrap)
@property
def Bz(self):
return self._get_wrapped_array(self._Bz_wrap)
@property
def Jx(self):
return self._get_wrapped_array(self._Jx_wrap)
@property
def Jy(self):
return self._get_wrapped_array(self._Jy_wrap)
@property
def Jz(self):
return self._get_wrapped_array(self._Jz_wrap)
class WarpX_EM3D(warp.EM3D):
"""Mirrors part of the Warp EM3D class, mostly diagnostics.
"""
def __init__(self, picmi_grid, level=0):
self.picmi_grid = picmi_grid
self.level = level
# --- Only define what is necessary for the diagnostics
self.fields = _WarpX_YEEFIELDtype(level)
self.block = _WarpX_BLOCKtype(self.fields, picmi_grid)
self.isactive = True
self.l_1dz = (picmi_grid.number_of_dimensions == 1)
self.l_2dxz = (picmi_grid.number_of_dimensions == 2)
try:
picmi_grid.nr
except AttributeError:
self.l_2drz = False
else:
self.l_2drz = True
self.l4symtry = False
self.l2symtry = False
self.nx = picmi_grid.number_of_cells[0]
if not self.l_2dxz:
self.ny = picmi_grid.number_of_cells[1]
else:
self.ny = 0
self.nz = picmi_grid.number_of_cells[-1]
self.zgrid = 0. # --- This should be obtained from WarpX
|