-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathemf.h
194 lines (158 loc) · 5.03 KB
/
emf.h
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
191
192
193
194
#ifndef EMF_H_
#define EMF_H_
#include "zpic.h"
#include "utils.h"
#include "bnd.h"
#include "vec3grid.h"
#include "current.h"
#include "moving_window.h"
#include <string>
namespace emf {
enum field { e, b };
namespace bc {
enum type { none = 0, periodic, pec, pmc };
}
typedef bnd<bc::type> bc_type;
}
class EMF {
/// @brief Boundary condition
emf::bc_type bc;
/// @brief cell size
const float2 dx;
/// @brief time step
const double dt;
/// @brief Iteration number
int iter;
/// @brief Moving window information
MovingWindow moving_window;
/**
* @brief Move simulation window if needed
*
*/
void move_window();
/**
* @brief Process boundary conditions
*
*/
void process_bc();
public:
/// @brief Electric field
vec3grid<float3> * E;
/// @brief Magnetic field
vec3grid<float3> * B;
/// @brief Simulation box size
const float2 box;
/**
* @brief Construct a new EMF object
*
* @param ntiles Number of tiles in x,y direction
* @param nx Tile size (#cells)
* @param box Simulation box size (sim. units)
* @param dt Time step
*/
EMF( uint2 const ntiles, uint2 const nx, float2 const box, double const dt, Partition & part );
/**
* @brief Destroy the EMF object
*
*/
~EMF() {
delete (E);
delete (B);
}
friend std::ostream& operator<<(std::ostream& os, const EMF obj) {
os << "EMF object\n";
return os;
}
/**
* @brief Get the iteration number
*
* @return auto
*/
auto get_iter() { return iter; }
/**
* @brief Get the boundary condition values
*
* @return emf::bc_type
*/
emf::bc_type get_bc( ) { return bc; }
void set_bc( emf::bc_type new_bc ) {
// Validate parameters
if ( (new_bc.x.lower == emf::bc::periodic) || (new_bc.x.upper == emf::bc::periodic) ) {
if ( new_bc.x.lower != new_bc.x.upper ) {
std::cerr << "(*error*) EMF boundary type mismatch along x.\n";
std::cerr << "(*error*) When choosing periodic boundaries both lower and upper types must be set to emf::bc::periodic.\n";
exit(1);
}
}
if ( (new_bc.y.lower == emf::bc::periodic) || (new_bc.y.upper == emf::bc::periodic) ) {
if ( new_bc.y.lower != new_bc.y.upper ) {
std::cerr << "(*error*) EMF boundary type mismatch along y.\n";
std::cerr << "(*error*) When choosing periodic boundaries both lower and upper types must be set to emf::bc::periodic.\n";
exit(1);
}
}
if ( E -> part.periodic.x && new_bc.x.lower != emf::bc::periodic ) {
std::cerr << "(*error*) Only periodic x boundaries are supported with periodic x parallel partitions.\n";
exit(1);
}
if ( E -> part.periodic.y && new_bc.y.lower != emf::bc::periodic ) {
std::cerr << "(*error*) Only periodic y boundaries are supported with periodic y parallel partitions.\n";
exit(1);
}
// Store new values
bc = new_bc;
std::string bc_name[] = {"none", "periodic", "pec", "pmc"};
std::cout << "(*info*) EMF boundary conditions\n";
std::cout << "(*info*) x : [ " << bc_name[ bc.x.lower ] << ", " << bc_name[ bc.x.upper ] << " ]\n";
std::cout << "(*info*) y : [ " << bc_name[ bc.y.lower ] << ", " << bc_name[ bc.y.upper ] << " ]\n";
}
/**
* @brief Sets moving window algorithm
*
* This method can only be called before the simulation has started (iter = 0)
*
* @return int 0 on success, -1 on error
*/
int set_moving_window() {
if ( iter == 0 ) {
if ( E -> part.periodic.x ) {
std::cerr << "(*error*) Unable to set_moving_window() with periodic x partition\n";
return -1;
}
moving_window.init( dx.x );
bc.x.lower = bc.x.upper = emf::bc::none;
return 0;
} else {
std::cerr << "(*error*) set_moving_window() called with iter != 0\n";
return -1;
}
}
/**
* @brief Advance EM field 1 iteration assuming no current
*
*/
void advance( );
/**
* @brief Advance EM field 1 iteration
*
* @param current Current density
*/
void advance( Current & current );
/**
* @brief Save EM field component to file
*
* @param field Which field to save (E or B)
* @param fc Which field component to save (x, y or z)
*/
void save( emf::field const field, const fcomp::cart fc );
/**
* @brief Get EM field energy
*
* @note The energy will be recalculated each time this routine is called
*
* @param ene_E Electric field energy
* @param ene_b Magnetic field energy
*/
void get_energy( double3 & ene_E, double3 & ene_b );
};
#endif