Streamer fluid modeling - An overview of ARCoS  1.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
cstream.c
Go to the documentation of this file.
1 
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <math.h>
8 #include <time.h>
9 #define ALLOC_PARAMS
10 
11 #include "cstream.h"
12 #include "parameters.h"
13 #include "proto.h"
14 #include "species.h"
15 
16 double E_x, E_y, E_z;
20 extern double pois_inhom_fixed_q_t;
24 double *dr, *dz, dtheta;
27 double *dr_start, *dz_start;
28 
29 double *w2k, *wk;
36 char *invok_name = "cstream";
39 const double twopi = 6.283185307179586477L;
42 const double invfourpi = 0.079577471545947667884441882L;
45 const double invpi32 = 0.179587122125166561689081L;
53 void
55 {
56  debug (1, "entry init_parameters\n");
57  /* An identification name for this run */
58  prog_id = "example";
59 
60  /* Output directory. */
61  output_dir = "output/";
62 
63  /* Kinetics input file */
64  kin_input = "input/kinetic_example.cfg";
65 
66  /* If restart is TRUE, the simulation will continue with data from a previous run */
67  restart = 0;
68 
69  /* If restart is TRUE, the name of the file with data from previous run, otherwise empty */
70  load_file = "";
71 
72  /* Time interval for output to be written to disk */
73  output_dt = 0.100;
74 
75  /* Output of the Poisson grids, including the potential? */
76  pois_output = 0;
77 
78  /* Margin outside the grids in the output of the cdr equation */
80 
81  /* Margin outside the grids in the output of the poisson equation */
83 
84  /* If the time steps are smaller than this number, the program issues a warning */
85  warn_min_timestep = 1e-06;
86 
87  /* Maximum disk space, in Mb, to use */
88  max_disk_space_mb = 1048576;
89 
90  /* Number of R and Z gridpoints at level 0 */
91  gridpoints_r = 600;
92  gridpoints_z = 600;
93 
94  /* Number of azimuthal gridcells and modes */
95  max_ntheta = 1;
96 
97  /* Initial and end time */
98  start_t = 0.0;
99  end_t = 0.12;
100 
101  /* Attempted timestep. The actual timestep may be larger */
102  attempt_dt = 50.0;
103 
104  /* Extra levels for the Poisson solver */
105  extra_pois_levels = 2;
106 
107  /* Maximum level of refinement. Use a big number here */
108  max_levels = 64;
109 
110  /* Error threshold that leads to refinement in the Poisson code. */
111  pois_max_error = 0.001;
112 
113  /* Maximum level of refinement in the Poisson equation. */
114  pois_max_level = 3;
115 
116  /* Extra levels for the photo-ionization solver */
117  extra_photo_levels = -1;
118 
119  /* Maximum level of refinement in the photo-ionization solver. */
120  photo_max_level = 4;
121 
122  /* Error threshold that leads to refinement in the photo-ionization code. */
123  photo_max_error = 0.01;
124 
125  /* Photo-ionization boundary condition at r = L_r, z = 0, z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet */
126  photo_bnd_right = -1;
127  photo_bnd_bottom = -1;
128  photo_bnd_top = -1;
129 
130  /* Extra levels for the photo-ionization solver */
132 
133  /* Maximum level of refinement in the photo-ionization solver. */
134  photo_max_level_2 = 4;
135 
136  /* Error threshold that leads to refinement in the photo-ionization code. */
137  photo_max_error_2 = 0.01;
138 
139  /* Photo-ionization boundary condition at r = L_r, z = 0, z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet */
140  photo_bnd_right_2 = -1;
141  photo_bnd_bottom_2 = -1;
142  photo_bnd_top_2 = -1;
143 
144  /* Particles boundary condition at z = 0, z = L_z, r = L_r. 1 for Hom. Neumann, -1 for Hom. Dirichlet */
145  cdr_bnd_bottom = 1;
146  cdr_bnd_top = 1;
147  cdr_bnd_right = 1;
148 
149  /* Potential boundary condition at r = L_r, z = 0, z = L_z. 1 for Hom. Neumann, -1 for Hom. Dirichlet */
150  pois_bnd_right = -1;
151  pois_bnd_bottom = -1;
152  pois_bnd_top = -1;
153 
154  /* Maximum advection and diffusion Courant number */
155  nu_a = 0.2;
156  nu_d = 0.2;
157 
158  /* Maximum ratio of dt/relaxation time */
159  nu_rt = 0.2;
160 
161  /* Maximum ratio of change of the densities (set to a very large number to ignore) */
162  nu_f = 1e+20;
163 
164  /* Refinement threshold for the electric field */
165  ref_threshold_eabs = 0.2;
166 
167  /* Maximum refinement level reached through ref_threshold_eabs */
168  ref_level_eabs = 4;
169 
170  /* Refinement threshold for the curvature of the charge, densities */
171  ref_threshold_charge = 0.004;
172  ref_threshold_dens = 0.004;
173 
174  /* Refinement threshold for the densities in the leading edge */
175  ref_threshold_edge = 10000.0;
176 
177  /* r-length and z-length of the minimal refinement area in the cdr equation */
178  cdr_brick_dr = 8;
179  cdr_brick_dz = 8;
180 
181  /* Maximum level of refinement in the Fluid equation. */
182  cdr_max_level = 3;
183 
184  /* Interpolation method for the grid interior, and grid boundaries (0=zero_masses, 1=quadratic_masses [default], 2=wackers_masses, 3=quadlog */
185  cdr_interp_in = 1;
186  cdr_interp_bnd = 1;
187 
188  /* Length in r and z of the complete domain */
189  L_r = 13044.0;
190  L_z = 13044.0;
191 
192  /* Isotropic difussion coefficient */
193  diffusion_coeff = 0.1;
194 
195  /* Whether the code includes photoionization or not */
197 
198  /* The name of a file from which we can read the photoionization parameters */
199  photoionization_file = "input/air760torr.photo";
200 
201  /* Rate of dissociative attachment */
202  attachment_rate = 0.0;
203 
204  /* E0 in the exp(-E0/E) factor in the attachment expression. */
205  attachment_E0 = 0.0;
206 
207  /* x-, y- and z-component of the external electric field */
208  E0_x = 0.0;
209  E0_y = 0.0;
210  E0_z = -0.06;
211 
212  /* Rise time of the electric field (0 for instantaneous rise) */
213  rise_time = 0.0;
214 
215  /* Time to switch off the electric field (0.0 means never) */
216  off_time = 0.0;
217 
218  /* x-, y- and z-width of the initial seed */
219  seed_sigma_x = 0.0;
220  seed_sigma_y = 0.0;
221  seed_sigma_z = 0.0;
222 
223  /* Number of electrons in the initial seed */
224  seed_N = 0.0;
225 
226  /* Initial at z=0 densities of electrons and ions */
227  background_ionization = 0.0;
228 
229  /* Length of exponential increase of the pre-ionization (for atmospherical models) */
231 
232  /* Use the point-plane geometry? */
233  pois_inhom = 1;
234 
235  /* Number of mirror charges to use */
237 
238  /* Length and radius of the needle */
239  needle_length = 2500.0;
240  needle_radius = 400.0;
241 
242  /* If nonzero, the charge is fixed, not floating (simulation of charged clouds close to the earth surface) */
243  pois_inhom_fixed_q = 0.0;
244 
245  /* Constant ionization rate */
246  constant_source = 0.0;
247 
248  /* Initial perturbation to the axisymmetric configuration */
249  perturb_epsilon = 0.0;
250 
251  /* Perturb only modes up to perturb_max_k (large number to perturb all) */
252  perturb_max_k = 1024;
253 
254  /* 1 if the sprite module is activated, 0 otherwise */
255  sprite_module = 0;
256 
257  /* Lenght of exponential decay of the density w/r to altitude */
258  dens_decay_len = 0.0;
259 
260  /* Density at z = 0 */
261  sprite_dens_0 = 0.0;
262 
263  /* Quenching density */
264  sprite_dens_q = 0.0;
265 
266  /* Sign of the sprite head that we are following (the other will not be reliable */
267  sprite_sign = -1;
268  debug (1, "exit init_parameters\n");
269 }
270 
271  int n, i;
275 static void
277 {
278  int n, i;
279  double root_dr, root_dz;
280 
281  root_dr = L_r / gridpoints_r;
282  root_dz = L_z / gridpoints_z;
283 
284  n = max_levels + extra_pois_levels + 1;
285 
286  dr_start = (double *) xmalloc(sizeof(double) * n);
287  dz_start = (double *) xmalloc(sizeof(double) * n);
288 
291 
292  dr_start[0] = root_dr * (1 << extra_pois_levels);
293  dz_start[0] = root_dz * (1 << extra_pois_levels);
294 
295  for (i = 1; i < n; i++) {
296  dr_start[i] = dr_start[i - 1] / 2.0;
297  dz_start[i] = dz_start[i - 1] / 2.0;
298 
299  debug (3, "dr[%d] = %e\n", i - extra_pois_levels,
300  dr[i - extra_pois_levels]);
301  debug (3, "dz[%d] = %e\n", i - extra_pois_levels,
302  dz[i - extra_pois_levels]);
303  }
304 
305  dtheta = twopi / max_ntheta;
306 }
307 
309 static void
310 init_wk_a (void)
311 {
312  int k;
313  double twobydtheta2;
314 
315  debug (2, "init_w2k_a()\n");
316 
317  w2k = (double*) xmalloc (sizeof(double) * max_ntheta);
318  wk = (double*) xmalloc (sizeof(double) * max_ntheta);
319 
320  twobydtheta2 = 2. / (dtheta * dtheta);
321 
322  for (k = 0; k < max_ntheta / 2 + (max_ntheta % 2); k++) {
323  double w2k_ = twobydtheta2 * (1 - cos (k * dtheta));
324  double re_wk, im_wk;
325 
326  re_wk = (cos (k * dtheta) - 1) / dtheta;
327  im_wk = sin (k * dtheta) / dtheta;
328 
329  wk[k] = re_wk;
330  w2k[k]= w2k_;
331 
332  if (k != 0) {
333  wk[max_ntheta - k] = im_wk;
334  w2k[max_ntheta - k] = w2k_;
335  }
336  }
337 
338  if ((max_ntheta % 2) == 0) {
339  w2k[max_ntheta / 2] = twobydtheta2 * (1 - cos (k * dtheta));
340  wk[max_ntheta / 2] = (cos (k * dtheta) - 1) / dtheta;
341  }
342 
343  assert (wk[0] == 0.);
344 }
345 
347 static void
349 {
350  free (dr_start);
351  free (dz_start);
352 }
353 
355 static void
356 free_wk (void)
357 {
358  free (wk);
359  free (w2k);
360 }
361 
363 void
365 {
366  /* For the perturbations, it is better to start with different seeds at
367  each run. */
368  srand (time (0));
369 
370  init_gridsizes_a ();
371  init_wk_a ();
372  react_init ();
373  cdr_init ();
374  pois_init ();
375  photo_init ();
376  if (has_photoionization) {
377  printf("Photoionization\n");
379  } else {
380  printf("No photoionization\n");
381  }
382 
383  if (sprite_module) spr_init ();
384 }
385 
387 void
389 {
391  free_gridsizes ();
392  free_wk ();
393  cdr_end ();
394 }
395 
396 
399 void
401 {
402  static int rise_reached = FALSE, off_reached = FALSE;
403  double factor;
404 
405  if (rise_reached && off_reached)
406  return;
407 
408  if (t >= rise_time) {
409  rise_reached = TRUE;
410  }
411 
412  if (t >= off_time || off_time == 0.0) {
413  off_reached = TRUE;
414  }
415 
416  /* We make sure that we never use a field _larger_ than E0 and that
417  if rise_time is 0 we do not calculate t / 0.0. */
418  factor = t >= rise_time? 1.0: (t / rise_time);
419 
420  factor = (off_time > 0.0 && t >= off_time)? 0.0: factor;
421 
422  E_x = factor * E0_x;
423  E_y = factor * E0_y;
424  E_z = factor * E0_z;
425 
426  if (pois_inhom_fixed_q != 0.0) {
428  }
429 
430  return;
431 }
432 
434 double
435 e0_r (double r, double z, double theta)
436 {
437  return E_x * cos (theta) + E_y * sin (theta);
438 }
439 
441 double
442 e0_z (double r, double z, double theta)
443 {
444  return E_z;
445 }
446 
448 double
449 e0_theta (double r, double z, double theta)
450 {
451  return -E_x * cos (theta) + E_y * sin (theta);
452 }
453 
455 decl_field_comp(r) = e0_r;
457 decl_field_comp(z) = e0_z;
459 decl_field_comp(theta) = e0_theta;