aboutsummaryrefslogtreecommitdiff
path: root/Python/pywarpx/WarpInterface.py
blob: 0a18993891af08237d1f1d6ae35343163b34626f (plain) (blame)
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
# 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.

from pywarpx import PGroup
import warp

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