Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
scenario.cpp
Go to the documentation of this file.
1/*
2 * This file is part of Vlasiator.
3 * Copyright 2010-2016 Finnish Meteorological Institute
4 *
5 * For details of usage, see the COPYING file and read the "Rules of the Road"
6 * at http://www.physics.helsinki.fi/vlasiator/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22#include <random>
23#include <iostream>
24#include "scenario.h"
25#include "field.h"
26
27#define cross_product(av,bv) (av).cross(bv)
28#define dot_product(av,bv) (av).dot(bv)
29#define vector_length(v) (v).norm()
30#define normalize_vector(v) (v).normalized()
31
33
34 ParticleContainer particles;
35
37 /* Look up builk velocity in the V-field */
38 Vec3d bulk_vel = V(vpos);
39
40 particles.push_back(Particle(PhysicalConstantsSI::mp, PhysicalConstantsSI::e, vpos, bulk_vel));
41
42 return particles;
43}
44
45void singleParticleScenario::afterPush(int step, double time, ParticleContainer& particles,
46 Field& E, Field& B, Field& V) {
47
48 Vec3d& x = particles[0].x;
49 Vec3d& v = particles[0].v;
50
51 std::cout << 0 << " " << time << "\t" << x[0] << " " << x[1] << " " << x[2] << "\t"
52 << v[0] << " " << v[1] << " " << v[2] << std::endl;
53}
54
55
56
58
59 ParticleContainer particles;
60
61 std::default_random_engine generator(ParticleParameters::random_seed);
62 Distribution* velocity_distribution=ParticleParameters::distribution(generator);
63
65
66 /* Look up builk velocity in the V-field */
67 Vec3d bulk_vel = V(vpos);
68
69 for(unsigned int i=0; i< ParticleParameters::num_particles; i++) {
70 /* Create a particle with velocity drawn from the given distribution ... */
71 Particle p = velocity_distribution->next_particle();
72 /* Shift it by the bulk velocity ... */
73 p.v += bulk_vel;
74 /* And put it in place. */
75 p.x=vpos;
76 particles.push_back(p);
77 }
78
79 delete velocity_distribution;
80
81 return particles;
82}
83
84void distributionScenario::newTimestep(int input_file_counter, int step, double time, ParticleContainer& particles,
85 Field& E, Field& B, Field& V) {
86
87 char filename_buffer[256];
88
89 snprintf(filename_buffer,256, ParticleParameters::output_filename_pattern.c_str(),input_file_counter-1);
90 writeParticles(particles, filename_buffer);
91}
92
94 writeParticles(particles, "particles_final.vlsv");
95}
96
97void precipitationScenario::afterPush(int step, double time, ParticleContainer& particles,
98 Field& E, Field& B, Field& V) {
99
100 for(unsigned int i=0; i<particles.size(); i++) {
101
102 if(!isfinite(vector_length(particles[i].x))) {
103 // skip disabled particles
104 continue;
105 }
106
107 // Check if the particle hit a boundary. If yes, mark it as disabled.
108 // Original starting x of this particle
109 double start_pos = ParticleParameters::precip_start_x +
112 int start_timestep = i / ParticleParameters::num_particles;
114
115 // Record latitude and energy
116 double latitude = atan2(particles[i].x[2],particles[i].x[0]);
117 printf("%u %i %lf %lf %lf\n",i, start_timestep, start_pos, latitude, .5*particles[i].m *
118 dot_product(particles[i].v,particles[i].v)/PhysicalConstantsSI::e);
119
120 // Disable by setting position to NaN and velocity to 0
121 particles[i].x = Vec3d(std::numeric_limits<double>::quiet_NaN(),0.,0.);
122 particles[i].v = Vec3d(0,0,0);
123 } else if (particles[i].x[0] <= ParticleParameters::precip_start_x) {
124
125 // Record marker value for lost particle
126 printf("%u %i %lf -5. -1.\n", i, start_timestep, start_pos);
127 // Disable by setting position to NaN and velocity to 0
128 particles[i].x = Vec3d(std::numeric_limits<double>::quiet_NaN(),0.,0.);
129 particles[i].v = Vec3d(0,0,0);
130 }
131 }
132}
133
134void precipitationScenario::newTimestep(int input_file_counter, int step, double time, ParticleContainer& particles,
135 Field& E, Field& B, Field& V) {
136
137 // Create particles along the negative x-axis, from inner boundary
138 // up to outer one
139 for(unsigned int i=0; i< ParticleParameters::num_particles; i++) {
140
141 // Choose x coordinate
142 double start_x = ParticleParameters::precip_start_x +
145 Vec3d pos(start_x,0,0);
146
147 // Find cell with minimum B value in this plane
148 double min_B = 99999999999.;
149 for(double z=-1e7; z<1e7; z+=1e5) {
150 Vec3d candidate_pos(start_x,0,z);
151 double B_here = vector_length(B(candidate_pos));
152 if(B_here < min_B) {
153 pos = candidate_pos;
154 min_B = B_here;
155 }
156 }
157
158 // Add a particle at this location, with bulk velocity at its starting point
159 particles.push_back(Particle(PhysicalConstantsSI::mp, PhysicalConstantsSI::e, pos, V(pos)));
160 }
161
162 // Write out the state
163 char filename_buffer[256];
164
165 snprintf(filename_buffer,256, ParticleParameters::output_filename_pattern.c_str(),input_file_counter-1);
166 writeParticles(particles, filename_buffer);
167}
168
169
171
172 ParticleContainer particles;
173
174 std::cerr << "Reading initial particle data from stdin" << std::endl
175 << "(format: x y z vx vy vz)" << std::endl;
176
177 while(std::cin) {
178 double x0,x1,x2,v0,v1,v2;
179 std::cin >> x0 >> x1 >> x2 >> v0 >> v1 >> v2;
180 if(std::cin) {
182 Vec3d(x0,x1,x2), Vec3d(v0,v1,v2)));
183 }
184 }
185
186 return particles;
187}
188
189void analysatorScenario::newTimestep(int input_file_counter, int step, double time, ParticleContainer& particles,
190 Field& E, Field& B, Field& V) {
191
192 for(unsigned int i=0; i< particles.size(); i++) {
193 Vec3d& x = particles[i].x;
194 Vec3d& v = particles[i].v;
195 std::cout << i << " " << time << "\t" << x[0] << " " << x[1] << " " << x[2] << "\t"
196 << v[0] << " " << v[1] << " " << v[2] << std::endl;
197 }
198}
199
200void shockReflectivityScenario::newTimestep(int input_file_counter, int step, double time,
201 ParticleContainer& particles, Field& E, Field& B, Field& V) {
202
203 const int num_points = 200;
204
205 std::default_random_engine generator(ParticleParameters::random_seed+step);
206 Distribution* velocity_distribution=ParticleParameters::distribution(generator);
207
208 // Create particles along a parabola, in front of the shock
209 for(unsigned int i=0; i< num_points; i++) {
210
211 // Choose y coordinate
212 double start_y = ParticleParameters::reflect_start_y +
213 ((double)i)/num_points *
215
216 // Calc x-coordinate from it
217 double x = start_y / ParticleParameters::reflect_start_y;
218 x*=-x;
219 x *= ParticleParameters::reflect_y_scale - 10e6*(time-250.)/435.;
220 x += ParticleParameters::reflect_x_offset + 10e6*(time-250.)/435.;
221
222 Vec3d pos(x,start_y,0);
223 // Add a particle at this location, with bulk velocity at its starting point
224 // TODO: Multiple
225 //particles.push_back(Particle(PhysicalConstantsSI::mp, PhysicalConstantsSI::e, pos, V(pos)));
226
227 /* Look up builk velocity in the V-field */
228 Vec3d bulk_vel = V(pos);
229
230 for(unsigned int i=0; i< ParticleParameters::num_particles; i++) {
231 /* Create a particle with velocity drawn from the given distribution ... */
232 Particle p = velocity_distribution->next_particle();
233 /* Shift it by the bulk velocity ... */
234 p.v += bulk_vel;
235 /* And put it in place. */
236 p.x=pos;
237 particles.push_back(p);
238 }
239
240 }
241
242 delete velocity_distribution;
243
244 // Write out the state
245 char filename_buffer[256];
246
247 snprintf(filename_buffer,256, ParticleParameters::output_filename_pattern.c_str(),input_file_counter-1);
248 writeParticles(particles, filename_buffer);
249}
250
251void shockReflectivityScenario::afterPush(int step, double time, ParticleContainer& particles,
252 Field& E, Field& B, Field& V) {
253
254 for(unsigned int i=0; i<particles.size(); i++) {
255
256 if(!isfinite(vector_length(particles[i].x))) {
257 // skip disabled particles
258 continue;
259 }
260
261 //Get particle's y-coordinate
262 double y = particles[i].x[1];
263
264 // Get x for it's shock boundary (approx)
266 x*=-x;
267 x *= ParticleParameters::reflect_y_scale - 10e6*(time-250.)/435.;
268 x += ParticleParameters::reflect_x_offset + 10e6*(time-250.)/435.;
269
270 // Boundaries are somewhat left or right of it
271 double boundary_left = x - ParticleParameters::reflect_downstream_boundary;
272 double boundary_right = x + ParticleParameters::reflect_upstream_boundary;
273
274 // Check if the particle hit a boundary. If yes, mark it as disabled.
275 // Original starting x of this particle
276 int start_timestep = i / 200 / ParticleParameters::num_particles;
277 double start_time = ParticleParameters::start_time + start_timestep * ParticleParameters::input_dt;
278 if(particles[i].x[0] < boundary_left) {
279 // Record it is transmitted.
280 transmitted.addValue(Vec2d(y,start_time));
281
282 // Disable by setting position to NaN and velocity to 0
283 particles[i].x = Vec3d(std::numeric_limits<double>::quiet_NaN(),0.,0.);
284 particles[i].v = Vec3d(0,0,0);
285 } else if (particles[i].x[0] > boundary_right) {
286
287 //Record it as reflected
288 reflected.addValue(Vec2d(y,start_time));
289
290 // Disable by setting position to NaN and velocity to 0
291 particles[i].x = Vec3d(std::numeric_limits<double>::quiet_NaN(),0.,0.);
292 particles[i].v = Vec3d(0.,0.,0.);
293 }
294 }
295}
296
298 transmitted.save("transmitted.dat");
299 transmitted.writeBovAscii("transmitted.dat.bov",0,"transmitted.dat");
300 reflected.save("reflected.dat");
301 reflected.writeBovAscii("reflected.dat.bov",0,"reflected.dat");
302}
303
304
305
306
308
309 // Open output files for transmission and reflection
310 traFile = fopen("transmitted.dat","w");
311 refFile = fopen("reflected.dat","w");
312
313 ParticleContainer particles;
314
315 /* Prepare randomization engines */
316 std::default_random_engine generator(ParticleParameters::random_seed);
317 Distribution* velocity_distribution=ParticleParameters::distribution(generator);
318
319 std::random_device rd;
320 std::mt19937 gen(rd());
324
325 /* Loop over particles to generate */
326 for(unsigned int i=0; i< ParticleParameters::num_particles; i++) {
327 /* Create a particle at a random position within the initialisation box */
328 Real posx = disx(gen);
329 Real posy = disy(gen);
330 Real posz = disz(gen);
331 Vec3d vpos(posx, posy, posz);
332
333 /* Look up bulk velocity in the V-field */
334 Vec3d bulk_vel = V(vpos);
335
336 /* Create a particle with velocity drawn from the given distribution ... */
337 Particle p = velocity_distribution->next_particle();
338 /* Shift it by the bulk velocity ... */
339 p.v += bulk_vel;
340 /* And put it in place. */
341 p.x=vpos;
342 particles.push_back(p);
343 }
344
345 delete velocity_distribution;
346 return particles;
347}
348
349void ipShockScenario::newTimestep(int input_file_counter, int step, double time, ParticleContainer& particles,
350 Field& E, Field& B, Field& V) {
351
352 char filename_buffer[256];
353
354 snprintf(filename_buffer,256, ParticleParameters::output_filename_pattern.c_str(),input_file_counter-1);
355 writeParticles(particles, filename_buffer); //Generates VLSV file
356}
357
358void ipShockScenario::afterPush(int step, double time, ParticleContainer& particles,
359 Field& E, Field& B, Field& V) {
360
361 /* Perform transmission / reflection check for each particle */
362 for(unsigned int i=0; i<particles.size(); i++) {
363
364 if(!isfinite(vector_length(particles[i].x))) {
365 // skip disabled particles
366 continue;
367 }
368
369 //Get particle's x-coordinate
370 double x = particles[i].x[0];
371
372 // Check if the particle hit a boundary.
373 // If yes, print it and mark it as disabled.
374 if(particles[i].x[0] < ParticleParameters::ipshock_transmit) {
375 // Record it as transmitted.
376 //transmitted.addValue(Vec2d(y,start_time));
377
378 // Write particle information to a file
379 fprintf(traFile,"%lf %lf %lf %lf %lf %lf %lf %lf %lf\n", time,
380 particles[i].x[0], particles[i].x[1], particles[i].x[2],
381 particles[i].v[0], particles[i].v[1], particles[i].v[2],
382 .5 * particles[i].m * dot_product(particles[i].v, particles[i].v) / PhysicalConstantsSI::e,
383 dot_product(normalize_vector(particles[i].v), normalize_vector(B(particles[i].x))) );
384
385 // Disable by setting position to NaN and velocity to 0
386 particles[i].x = Vec3d(std::numeric_limits<double>::quiet_NaN(),0.,0.);
387 particles[i].v = Vec3d(0,0,0);
388 } else if (particles[i].x[0] > ParticleParameters::ipshock_reflect) {
389 // Record it as reflected
390 //reflected.addValue(Vec2d(y,start_time));
391
392 // Write particle information to a file
393 // Write particle information to a file
394 fprintf(refFile,"%lf %lf %lf %lf %lf %lf %lf %lf %lf\n", time,
395 particles[i].x[0], particles[i].x[1], particles[i].x[2],
396 particles[i].v[0], particles[i].v[1], particles[i].v[2],
397 .5 * particles[i].m * dot_product(particles[i].v, particles[i].v) / PhysicalConstantsSI::e,
398 dot_product(normalize_vector(particles[i].v), normalize_vector(B(particles[i].x))) );
399
400 // Disable by setting position to NaN and velocity to 0
401 particles[i].x = Vec3d(std::numeric_limits<double>::quiet_NaN(),0.,0.);
402 particles[i].v = Vec3d(0.,0.,0.);
403 }
404 }
405 fflush(traFile);
406 fflush(refFile);
407}
408
410 writeParticles(particles, "particles_final.vlsv");
411 /* histograms */
412 //transmitted.save("transmitted.dat");
413 //transmitted.writeBovAscii("transmitted.dat.bov",0,"transmitted.dat");
414 //reflected.save("reflected.dat");
415 //reflected.writeBovAscii("reflected.dat.bov",0,"reflected.dat");
416
419}
420
421
422
423Scenario* createScenario(std::string name) {
424 std::map<std::string, Scenario*(*)()> scenario_lookup;
425 scenario_lookup["single"]=&createScenario<singleParticleScenario>;
426 scenario_lookup["distribution"]=&createScenario<distributionScenario>;
427 scenario_lookup["precipitation"]=&createScenario<precipitationScenario>;
428 scenario_lookup["analysator"]=&createScenario<analysatorScenario>;
429 scenario_lookup["reflectivity"]=&createScenario<shockReflectivityScenario>;
430 scenario_lookup["ipshock"]=&createScenario<ipShockScenario>;
431
432 if(scenario_lookup.find(name) == scenario_lookup.end()) {
433 std::cerr << "Error: can't find particle pusher mode \"" << name << "\". Aborting." << std::endl;
434 exit(0);
435 }
436
437 return scenario_lookup[name]();
438}
fclose(file)
for i
Definition Dispersion.m:24
Numerical propagation V
Definition Dispersion.m:98
virtual Particle next_particle()=0
static const double mp
Definition physconst.h:53
static const double e
Definition physconst.h:55
float Real
Definition definitions.h:41
#define normalize_vector(v)
#define Vec3d
#define dot_product(av, bv)
#define vector_length(v)
#define Vec2d
Definition histogram.h:29
void writeParticles(const ParticleContainer &p, const char *filename)
Definition particles.cpp:43
std::vector< Particle, aligned_allocator< Particle, 32 > > ParticleContainer
Definition particles.h:45
Scenario * createScenario(std::string name)
Definition scenario.cpp:423
Scenario * createScenario()
Definition scenario.h:135
Definition field.h:34
static Distribution *(* distribution)(std::default_random_engine &)
static std::default_random_engine::result_type random_seed
static Real reflect_downstream_boundary
static Real precip_inner_boundary
static Real ipshock_inject_y1
static Real ipshock_inject_z1
static std::string output_filename_pattern
static uint64_t num_particles
static Real ipshock_inject_z0
static Real ipshock_inject_x1
static Real ipshock_inject_x0
static Real reflect_upstream_boundary
static Real ipshock_inject_y0
void newTimestep(int input_file_counter, int step, double time, ParticleContainer &particles, Field &E, Field &B, Field &V)
Definition scenario.cpp:189
ParticleContainer initialParticles(Field &E, Field &B, Field &V)
Definition scenario.cpp:170
void finalize(ParticleContainer &particles, Field &E, Field &B, Field &V)
Definition scenario.cpp:93
void newTimestep(int input_file_counter, int step, double time, ParticleContainer &particles, Field &E, Field &B, Field &V)
Definition scenario.cpp:84
ParticleContainer initialParticles(Field &E, Field &B, Field &V)
Definition scenario.cpp:57
void afterPush(int step, double time, ParticleContainer &particles, Field &E, Field &B, Field &V)
Definition scenario.cpp:358
void newTimestep(int input_file_counter, int step, double time, ParticleContainer &particles, Field &E, Field &B, Field &V)
Definition scenario.cpp:349
void finalize(ParticleContainer &particles, Field &E, Field &B, Field &V)
Definition scenario.cpp:409
ParticleContainer initialParticles(Field &E, Field &B, Field &V)
Definition scenario.cpp:307
void newTimestep(int input_file_counter, int step, double time, ParticleContainer &particles, Field &E, Field &B, Field &V)
Definition scenario.cpp:134
void afterPush(int step, double time, ParticleContainer &particles, Field &E, Field &B, Field &V)
Definition scenario.cpp:97
void afterPush(int step, double time, ParticleContainer &particles, Field &E, Field &B, Field &V)
Definition scenario.cpp:251
void newTimestep(int input_file_counter, int step, double time, ParticleContainer &particles, Field &E, Field &B, Field &V)
Definition scenario.cpp:200
LinearHistogram2D reflected
Definition scenario.h:105
void finalize(ParticleContainer &particles, Field &E, Field &B, Field &V)
Definition scenario.cpp:297
LinearHistogram2D transmitted
Definition scenario.h:104
virtual void afterPush(int step, double time, ParticleContainer &particles, Field &E, Field &B, Field &V)
Definition scenario.cpp:45
ParticleContainer initialParticles(Field &E, Field &B, Field &V)
Definition scenario.cpp:32