Streamer fluid modeling - An overview of ARCoS  1.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
cdr.c
Go to the documentation of this file.
1 
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <math.h>
15 #include <string.h>
16 #include <sys/time.h>
17 
18 #include "cdr.h"
19 #include "cstream.h"
20 #include "grid.h"
21 #include "interpol2.h"
22 #include "mapper.h"
23 #include "parameters.h"
24 #include "poisson.h"
25 #include "proto.h"
26 #include "react_table.h"
27 #include "rz_array.h"
28 #include "species.h"
29 #include "tree.h"
30 
32 decl_mapper_funcs(dens);
34 
36 double z_cutoff = 10000000.0;
37 double max_err = 0.0;
40 
42 
43 static void set_all_bnd (cdr_grid_t *grid,
44  int sign, int ir, int iz, int itheta,
45  int dim0, int inout,
46  int dim1, int dim1_from, int dim1_to,
47  int dim2, int dim2_from, int dim2_to);
48 static void set_axis_bnd (cdr_grid_t *grid);
49 static void max_update (double *x, double cmp);
50 static double f_ad (rz_array_t *dens, double efield, double dc, double mc,
51  int ir, int iz, int itheta, int dim);
52 
53 static double psi (double theta);
54 static void prepare_grid (cdr_grid_t *grid);
55 static double curv_at (cdr_grid_t *grid, rz_array_t *ar,
56  int ir, int iz, int itheta, double (*f) (double));
57 static int needs_refinement (cdr_grid_t *grid, int ir, int iz, int itheta,
58  int *in_edge);
59 static int any_needs_refinement (cdr_grid_t *grid, int ir, int iz,
60  int *in_edge);
61 static int brick_needs_refinement (cdr_grid_t *grid, int r0, int z0,
62  int r1, int z1, int *in_edge);
63 static void refine_in (cdr_grid_t *grid, int cr0, int cz0, int cr1, int cz1,
64  int contains_edge);
65 
66 static void restrict_from (cdr_grid_t *parent, cdr_grid_t *child);
67 static int match_grids (cdr_grid_t *fro, cdr_grid_t *to);
68 
69 double gauss2_xyz (double x, double y, double z);
70 int curr_seed = 0;
73 
74 void aux_dump_frames_r (cdr_grid_t *grid, FILE *fp);
75 
79 void
80 cdr_init (void)
81 {
85 
88 
89  react_table_read("input/default.mobility",&mu);
90  react_table_read("input/default.diffusion",&diff);
91 }
92 
94 void
95 cdr_end (void)
96 {
97  cdr_free_mappers (dens_mappers);
98  cdr_free_mappers (dens_bnd_mappers);
99 }
100 
102 cdr_grid_t*
103 cdr_new_3d_a (int r0, int z0, int r1, int z1, int ntheta)
104 {
105  rz_array_t *ez, *er, *etheta, *eabs, *charge, **dens, **d_dens, *photo;
106  cdr_grid_t *grid;
107  int i;
108  REAL *max_dens;
109 
110  debug (2, "cdr_new_3d_a (%d, %d, %d, %d)\n", r0, z0, r1, z1);
111 
112  ez = rz_new_3d_a (r0, z0, r1, z1, ntheta);
113  er = rz_new_3d_a (r0, z0, r1, z1, ntheta);
114  etheta = rz_new_3d_a (r0, z0, r1, z1, ntheta);
115  eabs = rz_new_3d_a (r0, z0, r1, z1, ntheta);
116  charge = rz_new_3d_a (r0, z0, r1, z1, ntheta);
117  photo = has_photoionization? rz_new_3d_a (r0, z0, r1, z1, ntheta): NULL;
118 
119  /* Apart from the real species, (electron, ions...) we can create
120  * a virtual species that enter into the possible reactions.
121  * For example, the absolute value of the electric field, eabs.
122  */
123  dens = (rz_array_t **) xmalloc (sizeof(rz_array_t*)
125  d_dens = (rz_array_t **) xmalloc (sizeof(rz_array_t*) * no_species);
126 
127  max_dens = (REAL *) xmalloc (sizeof(REAL) * no_species);
128 
129  for (i = 0; i < no_species; i++) {
130  dens[i] = rz_new_3d_a (r0, z0, r1, z1, ntheta);
131  d_dens[i] = rz_new_3d_a (r0, z0, r1, z1, ntheta);
132  }
133 
134  dens[no_species] = eabs;
135 
136  grid = (cdr_grid_t *) xmalloc (sizeof(cdr_grid_t));
137 
138  grid->r0 = r0;
139  grid->r1 = r1;
140  grid->z0 = z0;
141  grid->z1 = z1;
142  grid->charge = charge;
143  grid->er = er;
144  grid->ez = ez;
145  grid->etheta = etheta;
146  grid->eabs = eabs;
147  grid->photo = photo;
148 
149  grid->dens = dens;
150  grid->d_dens = d_dens;
151  grid->max_dens = max_dens;
152 
153  grid->ntheta = ntheta;
154 
155  grid->contains_edge = FALSE;
156 
157  init_leaf (grid);
158 
159  return grid;
160 }
161 
169 cdr_grid_t*
170 cdr_guest (cdr_grid_t *host, int r0, int z0, int r1, int z1)
171 {
172  rz_array_t *ez, *er, *etheta, *eabs, *charge, **dens, **d_dens, *photo;
173  cdr_grid_t *grid;
174  int i;
175  REAL *max_dens;
176 
177  debug (2, "cdr_guest (" grid_printf_str ",%d, %d, %d, %d)\n",
178  grid_printf_args(host), r0, z0, r1, z1);
179 
180  ez = rz_guest (host->ez, r0, z0, r1, z1);
181  er = rz_guest (host->er, r0, z0, r1, z1);
182  etheta = rz_guest (host->etheta, r0, z0, r1, z1);
183  eabs = rz_guest (host->eabs, r0, z0, r1, z1);
184  charge = rz_guest (host->charge, r0, z0, r1, z1);
185  photo = (has_photoionization?
186  rz_guest (host->photo, r0, z0, r1, z1): NULL);
187 
188  dens = (rz_array_t **) xmalloc (sizeof(rz_array_t*)
190  d_dens = (rz_array_t **) xmalloc (sizeof(rz_array_t*) * no_species);
191 
192  max_dens = (REAL *) xmalloc (sizeof(REAL) * no_species);
193 
194  for (i = 0; i < no_species; i++) {
195  dens[i] = rz_guest (host->dens[i], r0, z0, r1, z1);
196  d_dens[i] = rz_guest (host->d_dens[i], r0, z0, r1, z1);
197  }
198 
199  dens[no_species] = eabs;
200 
201  grid = (cdr_grid_t *) xmalloc (sizeof(cdr_grid_t));
202 
203  grid->r0 = r0;
204  grid->r1 = r1;
205  grid->z0 = z0;
206  grid->z1 = z1;
207 
208  grid->charge = charge;
209  grid->er = er;
210  grid->ez = ez;
211  grid->etheta = etheta;
212  grid->eabs = eabs;
213  grid->photo = photo;
214 
215  grid->dens = dens;
216  grid->d_dens = d_dens;
217  grid->max_dens = max_dens;
218 
219  grid->ntheta = host->ntheta;
220 
221  grid->contains_edge = FALSE;
222 
223  set_leaf (grid, host->parent, NULL, NULL, host->level);
224 
225  return grid;
226 }
227 
233 cdr_grid_t*
235 {
236  cdr_grid_t *n;
237 
238  debug (2, "cdr_like_a(" grid_printf_str ")\n",
239  grid_printf_args(grid));
240 
241  n = cdr_new_3d_a (grid->r0, grid->z0, grid->r1, grid->z1, grid->ntheta);
242  n->level = grid->level;
243  n->ext_bound = grid->ext_bound;
244  n->contains_edge = grid->contains_edge;
245 
246  return n;
247 }
248 
254 cdr_grid_t*
256 {
257  cdr_grid_t *n;
258  int itheta, s, nr, nz, nspecs;
259 
260  n = cdr_like_a (grid);
261 
262  nr = grid->r1 - grid->r0 + 4;
263  nz = grid->z1 - grid->z0 + 4;
264 
265  nspecs = no_species;
266 
267  /* When we use the efield as a refinement criterium, we also have to copy
268  * eabs (which is a @i virtual density).
269  */
270  if (ref_level_eabs >= 0 && ref_threshold_eabs >= 0.0) nspecs++;
271 
272 #pragma omp parallel private(s)
273  {
274 #pragma omp for
275  iter_grid_theta_n (grid, itheta, 2) {
276  for (s = 0; s < nspecs; s++) {
277  rz_copy_modes (grid->dens[s], grid->r0 - 2, grid->z0 - 2,
278  n->dens[s], n->r0 - 2, n->z0 - 2,
279  nr, nz, itheta, itheta);
280  }
281  }
282  }
283  return n;
284 }
285 
287 void
289 {
290  int i;
291 
292  rz_set_periodic (grid->etheta);
293 
294  for (i = 0; i < no_species; i++) {
295  /* For negative r, we have the values
296  * of the densities on an opposite itheta.
297  */
298 
299  rz_set_periodic (grid->dens[i]);
300  rz_set_periodic (grid->d_dens[i]);
301 
302  }
303 
304  /* I am not completely sure that this is actually neccesary */
305  rz_set_periodic (grid->er);
306  rz_set_periodic (grid->ez);
307 }
308 
311 
312 
313 void
314 cdr_free (cdr_grid_t *grid)
315 {
316  int i;
317 
318  debug (2, "cdr_free\n");
319 
320  rz_free (grid->charge);
321  rz_free (grid->er);
322  rz_free (grid->ez);
323  rz_free (grid->etheta);
324  rz_free (grid->eabs);
325  if (has_photoionization) rz_free (grid->photo);
326 
327  for (i = 0; i < no_species; i++) {
328  rz_free (grid->dens[i]);
329  rz_free (grid->d_dens[i]);
330  }
331 
332  free (grid->dens);
333  free (grid->d_dens);
334  free (grid->max_dens);
335 
336  free (grid);
337 }
338 
340 void
342 {
343  cdr_grid_t *leaf;
344 
345  debug (2, "cdr_free_r (" grid_printf_str ")\n", grid_printf_args (grid));
346 
347  free_childs (grid, leaf, cdr_free_r);
348 
349  cdr_free (grid);
350 }
351 
360 void
362 {
363  int s, r, z, t;
364  double s_charge;
365 
366  debug (3, "cdr_calc_charge\n");
367 
368  rz_set_zero (grid->charge);
369 
370  for (s = 0; s < no_species; s++) {
371  s_charge = spec_index[s]->charge;
372 
373 #pragma omp parallel private(r, z)
374  {
375 #pragma omp for
376  iter_grid_theta (grid, t) {
377  for (r = grid->r0 - 2; r < grid->r1 + 2; r++) {
378  for (z = grid->z0 - 2; z < grid->z1 + 2; z++) {
379  RZT (grid->charge, r, z, t) += (RZT (grid->dens[s], r, z, t)
380  * s_charge) / grid->ntheta;
381  }
382  }
383  }
384  }
385  }
386 }
387 
390 
391 
392 void
393 cdr_dft_charge_r (cdr_grid_t *grid, int sign)
394 {
395  cdr_grid_t *leaf;
396 
397  debug (2, "cdr_dft_charge_r(" grid_printf_str ")\n",
398  grid_printf_args(grid));
399 
400  iter_childs (grid, leaf) {
401  cdr_dft_charge_r (leaf, sign);
402  }
403 
404  dft_transform (grid->charge, grid->charge, sign);
405 }
406 
408 void
409 cdr_dft_field_r (cdr_grid_t *grid, int sign)
410 {
411  cdr_grid_t *leaf;
412 
413  debug (2, "cdr_dft_field_r(" grid_printf_str ")\n",
414  grid_printf_args(grid));
415 
416  iter_childs (grid, leaf) {
417  cdr_dft_field_r (leaf, sign);
418  }
419 
420  dft_transform (grid->er, grid->er, sign);
421  dft_transform (grid->ez, grid->ez, sign);
422 
423  dft_diff ((grid_t *) grid, grid->etheta);
424  dft_transform (grid->etheta, grid->etheta, sign);
425 }
426 
434 cdr_grid_t*
436 {
437  int r0_half, r1_half, z0_half, z1_half, itheta;
438  int r, z;
439 
440  cdr_grid_t *new_grid;
441 
442  debug (2, "cdr_create_coarser_a\n");
443 
444  r0_half = grid->r0 >> 1;
445  r1_half = (grid->r1 + 1) >> 1;
446 
447  z0_half = grid->z0 >> 1;
448  z1_half = (grid->z1 + 1) >> 1;
449 
450  new_grid = cdr_new_3d_a (r0_half, z0_half, r1_half, z1_half, grid->ntheta);
451 
452 #pragma omp parallel private (r, z)
453  {
456 #pragma omp for
457  iter_grid_3d_n (new_grid, r, z, itheta, 1) {
458  /* Start cylindrical */
459  /* Here we are interpolating the masses, but in many other places
460  * we interpolate the densities. Why?
461  */
462  RZT (new_grid->charge, r, z, itheta) =
463  0.25
464  * (cyl_q (r + 0.25) * (RZT (grid->charge, 2 * r, 2 * z, itheta)
465  + RZT (grid->charge, 2 * r, 2 * z + 1, itheta))
466  + cyl_q (r + 0.75) * (RZT (grid->charge, 2 * r + 1, 2 * z, itheta)
467  + RZT (grid->charge, 2 * r + 1, 2 * z + 1,
468  itheta)))
469  / cyl_q (r + 0.5);
470  /* End cylindrical */
471  }
472  }
473  return new_grid;
474 }
475 
479 cdr_grid_t*
481 {
482  int i;
483  cdr_grid_t *grid = NULL;
484 
485  debug (2, "cdr_add_coarser_grids_a\n");
486 
487  assert (n > 0);
488 
489  for (i = 0; i < n; i++) {
490  grid = cdr_create_coarser_a (prev_root);
491  set_leaf (grid, NULL, NULL, prev_root, prev_root->level - 1);
492 
493  prev_root->parent = grid;
494 
495  prev_root = grid;
496  }
497  return grid;
498 }
499 
507 void
509 {
510  int i;
511  cdr_grid_t *grid;
512 
513  debug (2, "cdr_free_coarser_grids_a\n");
514 
515  for (i = 0; i < n; i++) {
516  assert (NULL == prev_root->next);
517  grid = prev_root->first_child;
518  cdr_free (prev_root);
519  prev_root = grid;
520  }
521 
522  prev_root->parent = NULL;
523 }
524 
531 pois_grid_t**
532 cdr_calc_field_r (cdr_grid_t *cdr, int return_pois)
533 {
534  pois_grid_t **pois_modes;
535 
536  debug (2, "cdr_calc_field_r (" grid_printf_str ", %d)\n",
537  grid_printf_args(cdr), return_pois);
538 
539  if (cdr->ntheta != 1)
540  cdr_dft_charge_r (cdr, 1);
541 
542  pois_modes = pois_solve_a (cdr, pois_electrostatic);
543 
544  if (cdr->ntheta != 1)
545  cdr_dft_field_r (cdr, -1);
546 
547  cdr_add_ext_field_r (cdr);
548 
549  /* Formerly, I added the inhomogeneous field here. But this is problematic:
550  * see pois_add_inhom_phi_r in poisson.c for details.
551  *
552  * To return back to adding electric fields and not potentials, uncomment
553  * these lines:
554 
555  * if (pois_inhom) {
556  * q_factor = pois_inhom_q_factor (pois_modes[0]);
557  * debug (1, "q_factor = %g\n", q_factor);
558  *
559  * cdr_add_inhom_field_r (cdr, q_factor);
560  * }
561  */
562 
563  /* Calculates the absolute value of the field. */
564  cdr_calc_eabs_r (cdr);
565 
566  /* Impose periodic boundary conditions in theta. */
567  if (cdr->ntheta != 1)
568  cdr_set_periodic_r (cdr);
569 
570  if (!return_pois) {
571  int i;
572 
573  for (i = 0; i < max_ntheta; i++) {
574  pois_free_r (pois_modes[i]);
575  }
576  free (pois_modes);
577  pois_modes = NULL;
578  }
579  return pois_modes;
580 }
581 
594 void
596 {
597  int ir, iz, itheta;
598 
599  debug (2, "cdr_add_ext_field (" grid_printf_str ")\n",
600  grid_printf_args(grid));
601 
602 #pragma omp parallel private(ir, iz)
603  {
604  #pragma omp for
605  iter_grid_3d_n (grid, ir, iz, itheta, 2) {
606  RZT(grid->er, ir, iz, itheta) +=
607  ext_e_r (er_r_at (ir, grid->level),
608  er_z_at (iz, grid->level),
609  theta_at (itheta));
610 
611  RZT(grid->ez, ir, iz, itheta) +=
612  ext_e_z (ez_r_at (ir, grid->level),
613  ez_z_at (iz, grid->level),
614  theta_at (itheta));
615 
616  RZT(grid->etheta, ir, iz, itheta) +=
617  ext_e_theta (r_at (ir, grid->level),
618  z_at (iz, grid->level),
619  etheta_theta_at (itheta));
620  }
621  }
622 }
623 
626 
627 
628 
634 void
635 cdr_add_inhom_field_r (cdr_grid_t *grid, double q)
636 {
637  int ir, iz, itheta;
638  cdr_grid_t *child;
639 
640  debug (2, "cdr_add_inhom_field_r (" grid_printf_str ", q = %f)\n",
641  grid_printf_args(grid), q);
642 
643  assert (0 != pois_inhom);
644 
645 #pragma omp parallel private(ir, iz)
646  {
647  #pragma omp for
648  iter_grid_3d_n (grid, ir, iz, itheta, 2) {
649  RZT(grid->er, ir, iz, itheta) +=
650  q * pois_inhom_er (er_r_at (ir, grid->level),
651  er_z_at (iz, grid->level));
652 
653  RZT(grid->ez, ir, iz, itheta) +=
654  q * pois_inhom_ez (ez_r_at (ir, grid->level),
655  ez_z_at (iz, grid->level));
656  }
657  }
658  iter_childs (grid, child) {
659  cdr_add_inhom_field_r (child, q);
660  }
661 }
662 
667 void
669 {
670  int ir, iz, itheta;
671  double er, ez, etheta;
672 
673 #pragma omp parallel
674  {
675 #pragma omp for private(ir, iz, er, ez, etheta)
676  iter_grid_3d (grid, ir, iz, itheta) {
677  er = 0.5 * (RZT (grid->er, ir, iz, itheta)
678  + RZT (grid->er, ir - 1, iz, itheta));
679  ez = 0.5 * (RZT (grid->ez, ir, iz, itheta)
680  + RZT (grid->ez, ir, iz - 1, itheta));
681  if (grid->ntheta != 1) {
682  etheta = 0.5 * (RZT (grid->etheta, ir, iz, itheta)
683  + RZT (grid->etheta, ir, iz, itheta - 1));
684  } else {
685  etheta = 0;
686  }
687  RZT (grid->eabs, ir, iz, itheta) = sqrt (er * er + ez * ez
688  + etheta * etheta);
689 
690  }
691  }
692 }
693 
696 
697 /********************
698  * Time integration *
699 *********************/
700 
701 
702 void
704 {
705  int s, ir, iz, itheta;
706 
707 #pragma omp parallel
708  {
709 #pragma omp for private(ir, iz, s)
710  iter_grid_theta_n (grid, itheta, 2) {
711  iter_grid_n(grid, ir, iz, 2) {
712  for (s = 0; s < no_species; s++)
713  *RZTP (grid->dens[s], ir, iz, itheta) =
714  MYMAX(0, *RZTP (grid->dens[s], ir, iz, itheta));
715  }
716  }
717  }
718 }
719 
722 
723 
725 void
727 {
728  int r0, z0, r1, z1, ntheta;
729 
730  debug (2, "cdr_set_ext_bnd (" grid_printf_str " [grid->ext_bound = 0x%x])\n",
731  grid_printf_args(grid), grid->ext_bound);
732 
733  r0 = grid->r0;
734  z0 = grid->z0;
735  r1 = grid->r1;
736  z1 = grid->z1;
737  ntheta = grid->ntheta;
738 
739  /* Matching conditions (reduced to Hom. Neumann for ntheta = 1 at
740  r = r0 */
741  if (grid->ext_bound & BND_MASK (BND_LEFT)) {
742  set_axis_bnd (grid);
743  }
744 
745  /* At r = r1. */
746  if (grid->ext_bound & BND_MASK (BND_RIGHT))
747  set_all_bnd (grid, cdr_ext_bnd_cond[BND_RIGHT], r1 - 1, z0 - 2, 0,
748  R_INDX, 1,
749  Z_INDX, 0, z1 - z0 + 4,
750  THETA_INDX, 0, ntheta);
751 
752  /* At z = z0. */
753  if (grid->ext_bound & BND_MASK (BND_BOTTOM))
754  set_all_bnd (grid, cdr_ext_bnd_cond[BND_BOTTOM], r0 - 2, z0, 0,
755  Z_INDX, -1,
756  R_INDX, 0, r1 - r0 + 4,
757  THETA_INDX, 0, ntheta);
758 
759  /* At z = z1. */
760  if (grid->ext_bound & BND_MASK (BND_TOP))
761  set_all_bnd (grid, cdr_ext_bnd_cond[BND_TOP], r0 - 2, z1 - 1, 0,
762  Z_INDX, 1,
763  R_INDX, 0, r1 - r0 + 4,
764  THETA_INDX, 0, ntheta);
765 }
766 
769 
770 
773 static void
774 set_all_bnd (cdr_grid_t *grid,
775  int sign, int ir, int iz, int itheta, int dim0, int inout,
776  int dim1, int dim1_from, int dim1_to,
777  int dim2, int dim2_from, int dim2_to)
778 {
779  int s;
780 
781  for (s = 0; s < no_species; s++) {
782  rz_set_bnd (grid->dens[s], sign, RZTP (grid->dens[s], ir, iz, itheta),
783  dim0, inout,
784  dim1, dim1_from, dim1_to,
785  dim2, dim2_from, dim2_to);
786  }
787 }
788 
797 static void
799 {
800  int s, itheta, itheta2, ntheta;
801 
802  debug (2, "set_axis_bnd (" grid_printf_str ")\n",
803  grid_printf_args(grid));
804 
805  assert (0 == grid->r0);
806 
807  ntheta = grid->ntheta;
808 
809  for (s = 0; s < no_species; s++) {
810  iter_grid_theta (grid, itheta) {
811  itheta2 = (itheta + ntheta / 2) % ntheta;
812 
813  rz_copy_bnd (grid->dens[s], grid->dens[s],
814  /* sign = */ 1,
815  /* start_from = */ RZTP (grid->dens[s],
816  grid->r0, grid->z0 - 2, itheta2),
817  /* start_to = */ RZTP (grid->dens[s],
818  grid->r0, grid->z0 - 2, itheta),
820  Z_INDX, 0, grid->z1 - grid->z0 + 4,
821  THETA_INDX, 0, 1 /* <- relative to start_xxx */);
822  }
823  }
824 }
825 
829 void
831 {
832  react_apply_all (grid);
833 
834  cdr_advect_diffu_r (grid);
835 }
836 
837 /* See "An Adaptive Grid Refinement Strategy for the Simulation
838  * of Negative Streamers", C. Montijn, W. Hundsdorfer and U. Ebert
839  * for the computations and notation used in this function.
840  */
841 
847 #define pij(p_, stride_) \
848  (((*(p_)) - *((p_) - (stride_))) / (*((p_) + (stride_)) - *(p_)))
849 
851 static double
852 f_ad (rz_array_t *dens, double efield, double dc, double mc,
853  int ir, int iz, int itheta, int dim)
854 {
855  double sigma, psi_p, sigmasigma;
856  int ishift;
857  double *p;
858 
859  /* a p is the unmodified density-value in the cell (ir,iz,itheta).
860  * Normally this should be n_e, as only electrons are mobile.
861  */
862  p = RZTP (dens, ir, iz, itheta);
863 
864  ishift = (efield > 0? 0: 1);
865 
866  /* sigma is just
867  * sigma_{i , j} for efield < 0,
868  * sigma_{i + 1, j} for efield > 0
869  */
870  sigma = *(p + ishift * dens->strides[dim]);
871 
872  /* psi_p has to be
873  * psi( p_{i , j}) for efield < 0
874  * -psi(1/p_{i+1, j}) for efield > 0
875  */
876  psi_p = pij (p + ishift * dens->strides[dim], dens->strides[dim]);
877 
878  /* E > 0 ---> psi_p = -psi( 1 / p_ij )
879  * E < 0, p_ij == 0 ---> psi_p = 1
880  * E < 0, p_ij != 0 ---> psi_p = psi( 1 / p_ij )
881  */
882  psi_p = (efield > 0)? -psi (psi_p) : psi_p == 0? 1.0: psi (1.0 / psi_p);
883 
884  /* sigmasigma is (sigma_{i+1, j} - sigma_{i, j}) */
885  sigmasigma = (*p) - *(p + dens->strides[dim]);
886 
887  /* The first term corresponds to the advection term, the second to the
888  * diffusion term.
889  *
890  * See eq. 3.1.5~3.1.8 in the thesis of C. Montijn. Division by cell-size
891  * is done in the function calling this one.
892  */
893  return efield * mc * (sigma + psi_p * sigmasigma) + dc * sigmasigma;
894 }
895 
899 void
901 {
902  int ir, iz, itheta, s;
903  int ii;
904  double gdr_inv, gdz_inv, d_iso0, d_iso;
905 
906  double field;
907  int dimd, t, sg;
908  REAL *d_dens_p;
909  double r_inv, er_r;
910  rz_array_t *er,*ez,*etheta;
911 
912  debug (2, "cdr_advect_diffu (" grid_printf_str ")\n",
913  grid_printf_args(grid));
914 
915  gdr_inv = 1.0 / dr[grid->level];
916  gdz_inv = 1.0 / dz[grid->level];
917  er = grid->er;
918  ez = grid->ez;
919  etheta = grid->etheta;
920 
921  for (s = 0; s < no_species; s++) {
922  /* The charge / mass ratio of a species. */
923  double cm0, cm;
924  int *strides;
925  int ir, rmax, dim2;
926  rz_array_t *dens, *d_dens, **d_dens_copy;
927 
928  if (spec_index[s]->mass <= 0) continue;
929 
930  dens = grid->dens[s];
931  d_dens = grid->d_dens[s];
932  strides = dens->strides;
933  rmax = strides[1]; dim2 = strides[2]/strides[1];
934 
935  /* Make a copy of d_dens to be able to compare both versions
936  * of arcos_cdr_advect
937  int nr = grid->r1 - grid->r0 + 4;
938  int nz = grid->z1 - grid->z0 + 4;
939  d_dens_copy = (rz_array_t **) xmalloc (sizeof(rz_array_t*) * no_species);
940  rz_copy(d_dens,grid->r0,grid->z0,*d_dens_copy,grid->r0,grid->z0,nr,nz);
941 
942  strides = dens->strides;
943  */
944 
945  arcos_cdr_advect_vec(spec_index[s]->mass,spec_index[s]->charge,
946  dens->data,d_dens->data,er->data,er->len,
947  ez->data,ez->len,diffusion_coeff,
948  dr[grid->level],dz[grid->level],
949  sprite_module,grid->r0,grid->r1,grid->z0,grid->z1);
950 
951  /* rz_free(*d_dens_copy); */
952  }
953 }
954 
956 
957 
959 static double
960 psi (double theta)
961 {
962  if (theta < 0) return 0;
963  if (theta < 0.4) return theta;
964  if (theta < 4) return (1 + 0.5 * theta) / 3.0;
965  else return 1.0;
966 }
967 
970 double
972 {
973  int s, ir, iz, itheta, depth, is_3d;
974 
975  double dr_min, dz_min, rdtheta_min, emax_r, emax_z, emax_theta, dmax, ddmax;
976  double tau_a, tau_d, tau_rt, tau_f, max_diff;
977 
978  debug (2, "cdr_courant (" grid_printf_str ")\n", grid_printf_args(grid));
979 
980  is_3d = (grid->ntheta == 1? 0: 1);
981 
982  /* Should we better keep track of the level of the finest grid? */
983  depth = grid_max_depth_r ((grid_t *) grid);
984  dr_min = dr[depth];
985  dz_min = dz[depth];
986  rdtheta_min = dtheta * grid_rmin_r ((grid_t *) grid);
987 
988  /* This part is not parallel, but if needed it can be parallelized
989  * easily by creating vectors xmax[0...ntheta-1], where we would store
990  * the maximum for each ntheta.
991  */
992  emax_r = -1;
993  emax_z = -1;
994  emax_theta = -1;
995  dmax = -1;
996  ddmax = 0;
997 
998  iter_grid_3d (grid, ir, iz, itheta) {
999  double mu;
1000  if (sprite_module) {
1001  mu = 1.0 / spr_density_at (z_at (iz, grid->level));
1002  } else {
1003  mu = 1.0;
1004  }
1005  //mu = sprite_module? 1.0 / spr_density_at (z_at (iz, grid->level)): 1.0;
1006 
1007  max_update (&emax_r, mu * fabs (RZT (grid->er, ir, iz, itheta)));
1008  max_update (&emax_z, mu * fabs (RZT (grid->ez, ir, iz, itheta)));
1009  max_update (&emax_theta, mu * fabs (RZT(grid->etheta, ir, iz, itheta)));
1010 
1011  for (s = 0; s < no_species; s++) {
1012  if (spec_index[s]->mass > 0) {
1013  max_update (&dmax, mu * RZT(grid->dens[s], ir, iz, itheta));
1014  max_update (&ddmax, -(RZT(grid->d_dens[s], ir, iz, itheta) /
1015  RZT(grid->dens[s], ir, iz, itheta)));
1016  }
1017  }
1018  }
1019 
1020  /* This assert fails when the grid has become completely nan. In that
1021  * case, let us not waste cpu cycles any longer.
1022  */
1023  assert (emax_r >= 0 && emax_z >= 0 && emax_theta >= 0 && dmax >= 0);
1024 
1025  /* Advection. This one usually dominates. */
1026  tau_a = nu_a / (emax_r / dr_min + emax_z / dz_min
1027  + is_3d * emax_theta / rdtheta_min);
1028 
1029  /* Diffusion. */
1030  /* <ISOTROPIC DIFFUSION> */
1031  if (sprite_module) {
1032  double dens_z1, dens_z0;
1033  /* Since we do not know where the density is higher, we check at both
1034  * extremes of the domain. We are assuming that the density is monotonic
1035  * but nothing else (if it is not an exp. it works still).
1036  */
1037  dens_z0 = spr_density_at (z_at (grid->z0, grid->level));
1038  dens_z1 = spr_density_at (z_at (grid->z1, grid->level));
1039  max_diff = diffusion_coeff / MYMIN(dens_z0, dens_z1);
1040  } else {
1041  max_diff = 0.1; /* diffusion_coeff */
1042  }
1043 
1044  tau_d = nu_d / (max_diff / dr_min / dr_min
1045  + max_diff / dz_min / dz_min
1046  + is_3d * max_diff / rdtheta_min / rdtheta_min);
1047 
1048  /* </ISOTROPIC DIFFUSION> */
1049 
1050  /* Mainly reaction growth / decay time */
1051  /* tau_f = nu_f / ddmax; */
1052 
1053  /* If sigma is zero somewhere, tau_f turns inf even if nu_f is very large.
1054  * We correct this here. */
1055  /*if (tau_f == 0)*/ tau_f = tau_d; /* Just ignore tau_f please. */
1056 
1057  /* Dielectric relaxation time */
1058  tau_rt = nu_rt / dmax;
1059 
1060  return MYMIN (tau_a, MYMIN(tau_d, MYMIN(tau_f, tau_rt)));
1061 }
1062 
1063 static
1064 void max_update (double *x, double cmp)
1065 {
1066  if (*x < cmp) *x = cmp;
1067 }
1068 
1074 void
1075 cdr_update (cdr_grid_t *orig, cdr_grid_t *dest, double h)
1076 {
1077  int ir, iz, itheta, s;
1078 
1079  debug (2, "cdr_update (orig = " grid_printf_str ", dest = "
1080  grid_printf_str ", %f)\n",
1081  grid_printf_args(orig), grid_printf_args(dest), h);
1082 
1083  /* We assume that orig and dest have the same shape. */
1084  assert (orig->r0 == dest->r0 && orig->z0 == dest->z0 &&
1085  orig->r1 == dest->r1 && orig->z1 == dest->z1 &&
1086  orig->ntheta == dest->ntheta);
1087 
1088 #pragma omp parallel
1089  {
1090 #pragma omp for private(ir, iz, s)
1091  iter_grid_3d_n (orig, ir, iz, itheta, 2) {
1092  for (s = 0; s < no_species; s++) {
1093  RZT (dest->dens[s], ir, iz, itheta) =
1094  RZT (orig->dens[s], ir, iz, itheta)
1095  + h * RZT (orig->d_dens[s], ir, iz, itheta);
1096  }
1097  }
1098  }
1099  cdr_calc_charge (dest);
1100 }
1101 
1106 void
1107 cdr_rk2_update (cdr_grid_t *dens_0, cdr_grid_t *d_dens_1,
1108  cdr_grid_t *d_dens_2, cdr_grid_t *dest,
1109  double h)
1110 {
1111  int ir, iz, itheta, s;
1112 
1113  debug (2, "cdr_rk2_update (dens_0 = " grid_printf_str
1114  ",\n\t\td_dens_1 = " grid_printf_str
1115  ",\n\t\td_dens_2 = " grid_printf_str
1116  ",\n\t\tdest = " grid_printf_str ")\n",
1117  grid_printf_args(dens_0),
1118  grid_printf_args(d_dens_1),
1119  grid_printf_args(d_dens_2),
1120  grid_printf_args(dest));
1121 
1122 #pragma omp parallel
1123  {
1124 #pragma omp for private(ir, iz, s)
1125  iter_grid_3d_n (dest, ir, iz, itheta, 2) {
1126  for (s = 0; s < no_species; s++) {
1127  RZT (dest->dens[s], ir, iz, itheta) =
1128  RZT (dens_0->dens[s], ir, iz, itheta)
1129  + 0.5 * h * RZT (d_dens_1->d_dens[s], ir, iz, itheta)
1130  + 0.5 * h * RZT (d_dens_2->d_dens[s], ir, iz, itheta);
1131  }
1132  }
1133  }
1134  cdr_calc_charge (dest);
1135 }
1136 
1142 void
1144  cdr_grid_t *d_dens_2, cdr_grid_t *dest,
1145  double h)
1146 {
1147  cdr_grid_t *c_dens_0, *c_d_dens_1, *c_d_dens_2, *c_dest;
1148 
1149  cdr_rk2_update (dens_0, d_dens_1, d_dens_2, dest, h);
1150 
1151  c_dens_0 = dens_0->first_child;
1152  c_d_dens_1 = d_dens_1->first_child;
1153  c_d_dens_2 = d_dens_2->first_child;
1154 
1155  iter_childs (dest, c_dest) {
1156  cdr_rk2_update_r (c_dens_0, c_d_dens_1, c_d_dens_2, c_dest, h);
1157 
1158  c_dens_0 = c_dens_0->next;
1159  c_d_dens_1 = c_d_dens_1->next;
1160  c_d_dens_2 = c_d_dens_2->next;
1161  }
1162 }
1163 
1167 void
1169 {
1170  cdr_grid_t *child;
1171  cdr_update (grid, grid, h);
1172 
1173  iter_childs (grid, child) {
1174  cdr_self_update_r (child, h);
1175  }
1176 }
1177 
1183 void
1184 cdr_like_update_ar (cdr_grid_t *grid, cdr_grid_t *new_grid, double h)
1185 {
1186  cdr_grid_t *child, *new_child, *prev = NULL;
1187 
1188  cdr_update (grid, new_grid, h);
1189 
1190  iter_childs (grid, child) {
1191  new_child = cdr_like_a (child);
1192 
1193  /* We can't use add_child here because we read the children of the grid
1194  * in inverse order as we inserted them.
1195  */
1196  if (NULL == prev) {
1197  new_grid->first_child = new_child;
1198  } else {
1199  prev->next = new_child;
1200  }
1201  set_leaf (new_child, new_grid, NULL, NULL, new_grid->level + 1);
1202  grid_inherit_ext_bound ((grid_t *) new_child);
1203 
1204  prev = new_child;
1205 
1206  cdr_like_update_ar (child, new_child, h);
1207  }
1208 }
1209 
1211 //double
1212 //cdr_grid_error (cdr_grid_t *grid, cdr_grid_t *inter)
1213 //{
1214 // int ir, iz, itheta;
1215 // int spec_nr;
1216 // double vol, err, val;
1217 //
1218 // spec_nr = find_species_by_name("electrons");
1219 //
1220 // assert(spec_nr > -1);
1221 //
1222 // vol = dz[grid->level] * dr[grid->level];
1223 //
1224 // iter_grid_3d(grid, ir, iz, itheta)
1225 // {
1226 //
1227 // val = RZT(grid->dens[spec_nr], ir, iz, itheta);
1228 // err = val > 1e-12 ? (val - RZT(inter->dens[spec_nr], ir, iz, itheta)) / val : 0;
1229 // err = err > 0 ? err : -err;
1230 // if (max_err < err)
1231 // {
1232 // max_err = err;
1233 // }
1234 // }
1235 // return err;
1236 //}
1237 //
1239 //void
1240 //cdr_grid_error_r (cdr_grid_t *grid, cdr_grid_t *inter)
1241 //{
1242 // cdr_grid_t *g_child, *i_child;
1243 //
1244 // cdr_grid_error(grid, inter);
1245 //
1246 // i_child = inter->first_child;
1247 //
1248 // for (g_child = grid->first_child; g_child; g_child = g_child->next)
1249 // {
1250 // cdr_grid_error_r(g_child, i_child);
1251 //
1252 // i_child = i_child->next;
1253 // }
1254 //}
1255 
1261 double
1262 cdr_rk2 (cdr_grid_t *grid, double h, double t)
1263 {
1264  /* intermediate step. */
1265  cdr_grid_t *inter, *child;
1266  double courant_h;
1267 
1268  /* After this number of warnings about small timesteps, the code stops. */
1269  static int count_min_timestep = 5;
1270 
1271  debug (2, "cdr_rk2 (" grid_printf_str ", %f)\n",
1272  grid_printf_args(grid), h);
1273 
1274  cdr_nonegative_r (grid);
1275 
1276  /* We want to be sure that the boundaries are properly set. */
1277  prepare_grid (grid);
1278 
1279  /* Experimental: Moving z_max boundary -- DISABLED */
1280 
1281  cdr_calc_field_r (grid, /*return_pois = */ FALSE);
1282 
1283  /* If we are using the sprite module, we set here the proper magnitudes
1284  corresponding to the head altitude here. */
1285  if (sprite_module) spr_hook (grid);
1286 
1287  cdr_calc_d_dens (grid);
1288 
1289  /* The actual timestep is limited by the Courant stability criterium.
1290  *
1291  * Note that cdr_courant has to be called AFTER the computation of the fields.
1292  */
1293  courant_h = cdr_courant (grid);
1294  h = MYMIN (h, courant_h);
1295 
1296  if (h < warn_min_timestep) {
1297  warning ("Time step [h = %g] is rather small. If this is ok, reduce "
1298  "warn_time_step to remove this warning\n", h);
1299 
1300  if (0 == count_min_timestep--) {
1301  fatal ("Too many warnings about small timesteps.\n");
1302  }
1303  }
1304 
1305  inter = cdr_like_a (grid);
1306 
1307  /* We create a new tree and put there y + dy/dt * h at each level. */
1308  cdr_like_update_ar (grid, inter, h);
1309 
1310  /* Set the proper boundary conditions also in the intermediate step. */
1311  prepare_grid (inter);
1312 
1313  cdr_calc_field_r (inter, /* return_pois = */ FALSE);
1314  cdr_calc_d_dens (inter);
1315 
1316  /* This is something like grid = grid + h / 2 * F(grid) + h / 2 F(inter) */
1317  cdr_rk2_update_r (grid, grid, inter, grid, h);
1318 
1319  /* Also, for the refinement functions, the boundary conditions have to be
1320  * appropriately set.
1321  */
1322  prepare_grid (grid);
1323 
1324  cdr_free_r (inter);
1325 
1326  return h;
1327 }
1328 
1333 static void
1335 {
1336  /* Restrict the densities from finer to coarser grids. */
1337  cdr_restrict_r (grid);
1338 
1339  /* Sets the external boundaries. */
1340  cdr_set_ext_bnd_r (grid);
1341 
1342  /* Sets the boundaries of children grids interpolating from their parents. */
1343  cdr_set_bnd_r (grid);
1344 
1345  /* If two grids share a boundary, use the values of one to set the
1346  boundaries of the other. */
1347  cdr_match_r (grid, NULL);
1348 
1349  /* Sets periodic boundary conditions in theta. */
1350  cdr_set_periodic_r (grid);
1351 }
1352 
1353 /*****************************************************************
1354  * Refinement and mapping.
1355  *****************************************************************/
1356 
1362 void
1364 {
1365  cdr_grid_t *old, *new;
1366 
1367  old = *ptree;
1368 
1369  new = cdr_clone_a (old);
1370  cdr_calc_charge (new);
1371  cdr_refine_r (new, old);
1372 
1373  *ptree = new;
1374 
1375  cdr_free_r (old);
1376 }
1377 
1382 void
1384 {
1385  int start = TRUE;
1386  int s, ir, iz, itheta;
1387 
1388  debug (2, "cdr_calc_maxs (" grid_printf_str ")\n",
1389  grid_printf_args(grid));
1390 
1391  /* If we have a parent, we inherit the maxs from him. */
1392  if (grid->parent) {
1393  grid->max_charge = grid->parent->max_charge;
1394  for (s = 0; s < no_species; s++) {
1395  grid->max_dens[s] = grid->parent->max_dens[s];
1396  }
1397  return;
1398  }
1399 
1400  iter_grid_3d (grid, ir, iz, itheta) {
1401  if (start) {
1402  start = FALSE;
1403  grid->max_charge = fabs(RZT (grid->charge, ir, iz, itheta));
1404  for (s = 0; s < no_species; s++) {
1405  grid->max_dens[s] = RZT (grid->dens[s], ir, iz, itheta);
1406  }
1407  } else {
1408  max_update (&grid->max_charge, fabs(RZT (grid->charge, ir, iz, itheta)));
1409  for (s = 0; s < no_species; s++) {
1410  max_update (&grid->max_dens[s], RZT (grid->dens[s], ir, iz, itheta));
1411  }
1412  }
1413  }
1414 
1415  debug (2, "->max_charge = %g, ->max_dens[0] = %g, ->max_dens[1] = %g\n",
1416  grid->max_charge, grid->max_dens[0], grid->max_dens[1]);
1417 }
1418 
1428 static double
1429 curv_at (cdr_grid_t *grid, rz_array_t *ar, int ir, int iz, int itheta,
1430  double (*f) (double))
1431 {
1432  int i, level;
1433  REAL x[3];
1434  double dur, duz;
1435 
1436  for (i = 0; i < 3; i++) {
1437  x[i] = RZT (ar, ir - 1 + i, iz, itheta);
1438  x[i] = f? f(x[i]): x[i];
1439  }
1440 
1441  level = grid->level;
1442  /* <CYLINDRICAL> */
1443  dur = (cyl_er_r_at (ir, level) * (x[2] - x[1])
1444  - cyl_er_r_at (ir - 1, level) * (x[1] - x[0])) / cyl_r_at (ir, level);
1445  /* </CYLINDRICAL> */
1446 
1447  for (i = 0; i < 3; i++) {
1448  x[i] = RZT (ar, ir, iz - 1 + i, itheta);
1449  x[i] = f? f(x[i]): x[i];
1450  }
1451 
1452  duz = (x[2] - 2 * x[1] + x[0]);
1453 
1454  return fabs(dur) + fabs(duz);
1455 }
1456 
1460 static int
1461 needs_refinement (cdr_grid_t *grid, int ir, int iz, int itheta, int *in_edge)
1462 {
1463  double curv;
1464  int s;
1465  /* For sprites, the eabs refinement criterium may depend on the location. */
1466  int s_ref_level_eabs;
1467  double s_ref_threshold_eabs;
1468 
1469  /* If the maximum charge is below this number, we ignore the refinement
1470  * criterium.
1471  */
1472  const double epsilon_charge = 1e-8;
1473 
1474  if (!sprite_module || ref_level_eabs < 0) {
1475  s_ref_level_eabs = ref_level_eabs;
1476  s_ref_threshold_eabs = ref_threshold_eabs;
1477  } else {
1478  double z, back_dens;
1479  z = z_at (iz, grid->level);
1480  back_dens = spr_density_at (z);
1481 
1482  s_ref_threshold_eabs = ref_threshold_eabs * back_dens;
1483 
1484  /* log2 appears because whenever we increase the background density by a
1485  * factor 2, we should refine up to one more level.
1486  */
1487  s_ref_level_eabs = ref_level_eabs + (int) floor (log2 (back_dens));
1488  }
1489 
1490  /* Electric field refinement. If eabs > ref_threshold_eabs, refine up to
1491  * some predefined level.
1492  */
1493 
1494  if (grid->level < s_ref_level_eabs &&
1495  RZT (grid->eabs, ir, iz, itheta) > s_ref_threshold_eabs) {
1496  debug (4, "Refine grid " grid_printf_str
1497  " at ir = %d, iz = %d, itheta = %d\n"
1498  "\t because too high EABS [eabs = %g]\n",
1499  grid_printf_args(grid), ir, iz, itheta,
1500  RZT (grid->eabs, ir, iz, itheta));
1501 
1502  *in_edge = FALSE;
1503  return TRUE;
1504  }
1505 
1506  curv = curv_at (grid, grid->charge, ir, iz, itheta, NULL);
1507 
1508  if (grid->max_charge > epsilon_charge
1509  && curv / grid->max_charge > ref_threshold_charge) {
1510  debug (4, "Refine grid " grid_printf_str
1511  " at ir = %d, iz = %d, itheta = %d\n"
1512  "\t because too high CHARGE curvature [curv / max_charge = %g]\n",
1513  grid_printf_args(grid), ir, iz, itheta, curv / grid->max_charge);
1514 
1515  *in_edge = FALSE;
1516  return TRUE;
1517  }
1518 
1519  for (s = 0; s < no_species; s++) {
1520  /* We ignore immobile species: */
1521  if (spec_index[s]->mass <= 0) continue;
1522 
1523  curv = curv_at (grid, grid->dens[s], ir, iz, itheta, NULL);
1524  if (curv / grid->max_dens[s] > ref_threshold_dens) {
1525  debug (4, "Refine grid " grid_printf_str
1526  " at ir = %d, iz = %d, itheta = %d\n"
1527  "\t because too high DENS[%s] curvature [curv / max_dens = %g]\n",
1528  grid_printf_args(grid), ir, iz, itheta, spec_index[s]->name,
1529  curv / grid->max_dens[s]);
1530 
1531  *in_edge = FALSE;
1532  return TRUE;
1533  }
1534 
1535  /* If the grid contains the leading edge, the criterium of
1536  * refinement also takes into account the density.
1537  */
1538  if (*in_edge && RZT (grid->dens[s], ir, iz, itheta) > ref_threshold_edge) {
1539  debug (4, "Refine grid " grid_printf_str
1540  " at ir = %d, iz = %d, itheta = %d\n"
1541  "\t because too high DENS[%s] in leading edge [dens = %g]\n",
1542  grid_printf_args(grid), ir, iz, itheta, spec_index[s]->name,
1543  RZT (grid->dens[s], ir, iz, itheta));
1544  return TRUE;
1545  }
1546  }
1547 
1548  /* If we are close to the border, we also check the border itself.
1549  *
1550  * NOTE: Does this have any sense? We are anyway checking for
1551  * the boundaries, aren't we?
1552  */
1553  if (ir == grid->r0 + 1 && needs_refinement (grid, ir - 1, iz, itheta,
1554  in_edge))
1555  return TRUE;
1556 
1557  if (iz == grid->z0 + 1 && needs_refinement (grid, ir, iz - 1, itheta,
1558  in_edge))
1559  return TRUE;
1560 
1561  if (ir == grid->r1 - 2 && needs_refinement (grid, ir + 1, iz, itheta,
1562  in_edge))
1563  return TRUE;
1564 
1565  if (iz == grid->z1 - 2 && needs_refinement (grid, ir, iz + 1, itheta,
1566  in_edge))
1567  return TRUE;
1568 
1569  return FALSE;
1570 }
1571 
1581 static int
1582 any_needs_refinement (cdr_grid_t *grid, int ir, int iz, int *in_edge)
1583 {
1584  int itheta;
1585  int ret = FALSE;
1586  iter_grid_theta (grid, itheta) {
1587  if (needs_refinement (grid, ir, iz, itheta, in_edge)) {
1588  debug (6, grid_printf_str
1589  " needs refinement at ir = %d, iz = %d itheta = %d\n",
1590  grid_printf_args(grid), ir, iz, itheta);
1591  ret = TRUE;
1592  }
1593  if (ret && ! *in_edge) return TRUE;
1594  }
1595  return ret;
1596 }
1597 
1608 static int
1609 brick_needs_refinement (cdr_grid_t *grid, int r0, int z0, int r1, int z1,
1610  int *in_edge)
1611 {
1612  int ir, iz;
1613  int ret = FALSE;
1614 
1615  for (ir = r0; ir < r1; ir ++) {
1616  for (iz = z1 - 1; iz >= z0; iz--) {
1617  ret = (any_needs_refinement (grid, ir, iz, in_edge) || ret);
1618  if (ret && ! *in_edge) return TRUE;
1619  }
1620  }
1621  return ret;
1622 }
1623 
1625 void
1627 {
1628  int ir;
1629 
1630  debug (2, "cdr_refine (" grid_printf_str ")\n",
1631  grid_printf_args(grid));
1632 
1633  assert (grid->level <= cdr_max_level);
1634 
1635  /* Checks if the maximum refinement level has been reached. */
1636  if (grid->level == cdr_max_level) return;
1637 
1638  cdr_calc_maxs (grid);
1639 
1640  for (ir = grid->r0; ir < grid->r1; ir += cdr_brick_dr) {
1641  int irmax = MYMIN (grid->r1, ir + cdr_brick_dr);
1642  int tainted, building, z0 = -1, z1 = -1;
1643  int iz;
1644  int in_edge;
1645  int first_edge;
1646 
1647  first_edge = in_edge = grid->contains_edge;
1648 
1649  /* The leading edge extends downwards. */
1650  for (iz = grid->z0, building = FALSE;
1651  iz < grid->z1; iz += cdr_brick_dz) {
1652  int izmax = MYMIN (grid->z1, iz + cdr_brick_dz);
1653 
1654  tainted = brick_needs_refinement (grid, ir, iz, irmax, izmax,
1655  &first_edge);
1656  if (tainted) {
1657  z1 = izmax;
1658  if (!building) {
1659  z0 = iz;
1660  building = TRUE;
1661  }
1662  } else /* ! tainted */ {
1663  if (building) {
1664  assert (z0 >= 0 && z1 > 0);
1665  /* If a grid does not satisfy the curvature criterium anywhere
1666  * and is here only because of the density threshold (edge)
1667  * criterium, he does not deserve to be refined.
1668  */
1669  building = FALSE;
1670  if (!first_edge) {
1671  refine_in (grid, ir, z0, irmax, z1, in_edge);
1672  in_edge = FALSE;
1673  }
1674  }
1675  }
1676  }
1677  if (building) {
1678  assert (z0 >= 0 && z1 > 0);
1679  if (!first_edge) refine_in (grid, ir, z0, irmax, z1, in_edge);
1680  }
1681  }
1682 }
1683 
1688 static void
1689 refine_in (cdr_grid_t *grid, int cr0, int cz0, int cr1, int cz1,
1690  int contains_edge)
1691 {
1692  cdr_grid_t *child;
1693  int nr0, nr1, nz0, nz1;
1694 
1695  nr0 = cr0 << 1;
1696  nz0 = cz0 << 1;
1697  nr1 = cr1 << 1;
1698  nz1 = cz1 << 1;
1699 
1700  child = cdr_new_3d_a (nr0, nz0, nr1, nz1, grid->ntheta);
1701 
1702  add_child (grid, child);
1703  grid_inherit_ext_bound ((grid_t*) child);
1704 
1705  child->contains_edge = contains_edge;
1706 
1707  debug (3, "new child created {r0 = %d, z0 = %d, r1 = %d, z1 = %d, "
1708  "level = %d}\n", child->r0, child->z0, child->r1, child->z1,
1709  child->level);
1710 }
1711 
1719 void
1721 {
1722  cdr_grid_t *child;
1723  int itheta;
1724 
1725  cdr_calc_charge (grid);
1726 
1727  cdr_refine (grid);
1728 
1729  iter_childs (grid, child) {
1730  if (NULL != source) {
1731 #pragma omp parallel
1732  {
1733 #pragma omp for
1734  iter_grid_theta (child, itheta) {
1735  map_grid_r (dens_mappers, (grid_t *) source, (grid_t *) child,
1736  itheta,
1737  /* copy = */ TRUE,
1738  /* interpol = */ TRUE,
1739  /* coarsen = */ FALSE,
1740  /* s_buff = */ 0, /* t_buff = */ 2);
1741  }
1742  }
1743  } else {
1744  cdr_init_dens (child);
1745  }
1746  cdr_refine_r (child, source);
1747  }
1748 }
1749 
1750 /* Matching of the boundaries:
1751  *
1752  * The boundary conditions of a grid that has a common border with another
1753  * one at the same level have to be matched. This is the purpose of this set
1754  * of functions.
1755  */
1756 
1762 void
1764 {
1765  cdr_grid_t *child1, *child2;
1766  int match = TRUE;
1767 
1768  if (grid2) {
1769  debug (2, "cdr_match_r (grid1 = " grid_printf_str
1770  ", grid2 = " grid_printf_str ")\n",
1771  grid_printf_args (grid1), grid_printf_args (grid2));
1772  } else {
1773  debug (2, "cdr_match_r (grid1 = " grid_printf_str
1774  ", grid2 = NULL)\n", grid_printf_args (grid1));
1775  }
1776 
1777  if (NULL != grid2) {
1778  match = match_grids (grid1, grid2);
1779  }
1780 
1781  if (!match) return;
1782 
1783  iter_childs (grid1, child1) {
1784  debug (4, "\tchild1 = " grid_printf_str "\n",
1785  grid_printf_args (child1));
1786  iter_childs (grid1, child2) {
1787  debug (4, "\t\tchild2 = " grid_printf_str "\n",
1788  grid_printf_args (child2));
1789 
1790  cdr_match_r (child1, (child1 != child2)? child2: NULL);
1791  }
1792 
1793  if (NULL == grid2)
1794  continue;
1795 
1796  iter_childs (grid2, child2) {
1797  cdr_match_r (child1, child2);
1798  }
1799  }
1800 }
1801 
1807 static int
1809 {
1810  int s, x0, x1;
1811 
1812  debug (2, "match_grids (to = " grid_printf_str
1813  ", fro = " grid_printf_str ")\n",
1815 
1816  assert (to->level == fro->level);
1817 
1818  if (to->r1 == fro->r0) {
1819  x0 = MYMAX (to->z0 - 2, fro->z0 - 2);
1820  x1 = MYMIN (to->z1 + 2, fro->z1 + 2);
1821  if (x1 <= x0) return FALSE;
1822 
1823  for (s = 0; s < no_species; s++) {
1824  rz_copy_bnd (fro->dens[s], to->dens[s], 1,
1825  RZTP (fro->dens[s], fro->r0, x0, 0),
1826  RZTP (to->dens[s], to->r1 - 1, x0, 0),
1828  Z_INDX, 0, x1 - x0,
1829  THETA_INDX, 0, fro->ntheta);
1830  }
1831  return TRUE;
1832  }
1833 
1834  if (to->r0 == fro->r1) {
1835  x0 = MYMAX (to->z0 - 2, fro->z0 - 2);
1836  x1 = MYMIN (to->z1 + 2, fro->z1 + 2);
1837  if (x1 <= x0) return FALSE;
1838 
1839  for (s = 0; s < no_species; s++) {
1840  rz_copy_bnd (fro->dens[s], to->dens[s], 1,
1841  RZTP (fro->dens[s], fro->r1 - 1, x0, 0),
1842  RZTP (to->dens[s], to->r0, x0, 0),
1844  Z_INDX, 0, x1 - x0,
1845  THETA_INDX, 0, fro->ntheta);
1846  }
1847  return TRUE;
1848  }
1849 
1850  if (to->z1 == fro->z0) {
1851  x0 = MYMAX (to->r0 - 2, fro->r0 - 2);
1852  x1 = MYMIN (to->r1 + 2, fro->r1 + 2);
1853  if (x1 <= x0) return FALSE;
1854 
1855  for (s = 0; s < no_species; s++) {
1856  rz_copy_bnd (fro->dens[s], to->dens[s], 1,
1857  RZTP (fro->dens[s], x0, fro->z0, 0),
1858  RZTP (to->dens[s], x0, to->z1 - 1, 0),
1860  R_INDX, 0, x1 - x0,
1861  THETA_INDX, 0, fro->ntheta);
1862  }
1863  return TRUE;
1864  }
1865 
1866  if (to->z0 == fro->z1) {
1867  x0 = MYMAX (to->r0 - 2, fro->r0 - 2);
1868  x1 = MYMIN (to->r1 + 2, fro->r1 + 2);
1869  if (x1 <= x0) return FALSE;
1870 
1871  for (s = 0; s < no_species; s++) {
1872  rz_copy_bnd (fro->dens[s], to->dens[s], 1,
1873  RZTP (fro->dens[s], x0, fro->z1 - 1, 0),
1874  RZTP (to->dens[s], x0, to->z0, 0),
1876  R_INDX, 0, x1 - x0,
1877  THETA_INDX, 0, fro->ntheta);
1878  }
1879  return TRUE;
1880  }
1881  return FALSE;
1882 }
1883 
1887 void
1889 {
1890  cdr_grid_t *top, *bottom, *left, *right, *parent;
1891  int itheta;
1892 
1893  debug (2, "cdr_set_bnd (" grid_printf_str ")\n",
1894  grid_printf_args(grid));
1895 
1896  parent = grid->parent;
1897  if (NULL == parent) {
1898  assert (0 == grid->level);
1899  return;
1900  }
1901 
1902  /* Since our mapping functions are easier to implement when we map
1903  * between rectangular regions (grids) we map the boundary conditions
1904  * by creating from grid four "guest" grids that share memory with him
1905  * and that contains each of the four boundaries.
1906  */
1907  top = cdr_guest (grid, grid->r0 - 2, grid->z1,
1908  grid->r1 + 2, grid->z1 + 2);
1909  bottom = cdr_guest (grid, grid->r0 - 2, grid->z0 - 2,
1910  grid->r1 + 2, grid->z0);
1911  left = cdr_guest (grid, grid->r0 - 2, grid->z0,
1912  grid->r0, grid->z1);
1913  right = cdr_guest (grid, grid->r1, grid->z0,
1914  grid->r1 + 2, grid->z1);
1915 
1916 #pragma omp parallel
1917  {
1918 #pragma omp for
1919  iter_grid_theta (grid, itheta) {
1920  if (0 == (grid->ext_bound & BND_MASK (BND_TOP)))
1921  map_grid (dens_bnd_mappers, (grid_t *) parent, (grid_t *) top, itheta,
1922  FALSE, TRUE, FALSE, 1, 0);
1923 
1924  if (0 == (grid->ext_bound & BND_MASK (BND_BOTTOM)))
1925  map_grid (dens_bnd_mappers, (grid_t *) parent, (grid_t *) bottom, itheta,
1926  FALSE, TRUE, FALSE, 1, 0);
1927 
1928  if (0 == (grid->ext_bound & BND_MASK (BND_LEFT))) {
1929  assert (grid->r0 != 0);
1930  map_grid (dens_bnd_mappers, (grid_t *) parent, (grid_t *) left, itheta,
1931  FALSE, TRUE, FALSE, 1, 0);
1932 
1933  }
1934 
1935  if (0 == (grid->ext_bound & BND_MASK (BND_RIGHT)))
1936  map_grid (dens_bnd_mappers, (grid_t *) parent, (grid_t *) right, itheta,
1937  FALSE, TRUE, FALSE, 1, 0);
1938  }
1939  }
1940 
1941  cdr_free (top);
1942  cdr_free (bottom);
1943  cdr_free (left);
1944  cdr_free (right);
1945 }
1946 
1949 
1950 
1951 mapper_t**
1952 cdr_mappers_a (interpol_method_t *interp_method)
1953 {
1954  mapper_t *mapper, **mappers;
1955  int s, nmappers;
1956 
1957  nmappers = no_species;
1958 
1959  /* mapper->extra represent the species whose density we will map.
1960  * There are no_species species, but no_species + 1 represents
1961  * the abs value of the electric field, which is mapped only to use
1962  * as an electric field-based refinement criterium.
1963  */
1964  if (ref_level_eabs >= 0 && ref_threshold_eabs >= 0.0) nmappers++;
1965 
1966  mappers = (mapper_t **) xmalloc (sizeof(mapper_t*) * (nmappers + 1));
1967 
1968  for (s = 0; s < nmappers; s++) {
1969  mapper = (mapper_t *) xmalloc (sizeof(mapper_t));
1970  mapper->extra = s;
1971  mapper->interpol_method = interp_method;
1972  mapper->copy = dens_copy;
1973  mapper->interpol_set = dens_interpol_set;
1974  mapper->interpol = dens_interpol;
1975  mapper->coarsen = NULL;
1976  mapper->shift_r = 0;
1977  mapper->shift_z = 0;
1978  mappers[s] = mapper;
1979  }
1980 
1981  mappers[nmappers] = NULL;
1982 
1983  return mappers;
1984 }
1985 
1987 void
1989 {
1990  int s;
1991 
1992  for (s = 0; s < no_species; s++) {
1993  free (mappers[s]);
1994  }
1995  free (mappers);
1996 }
1997 
1999 void
2000 dens_copy (mapper_t *mapper, grid_t *source, grid_t *target,
2001  int ir, int iz, int itheta)
2002 {
2003  cdr_grid_t *cdr_s, *cdr_d;
2004 
2005  cdr_s = (cdr_grid_t*) source;
2006  cdr_d = (cdr_grid_t*) target;
2007 
2008  RZT (cdr_d->dens[mapper->extra], ir, iz, itheta) =
2009  RZT (cdr_s->dens[mapper->extra], ir, iz, itheta);
2010 }
2011 
2013 int
2014 dens_interpol_set (mapper_t *mapper, grid_t *source, interpol_t *interpol,
2015  int pr, int pz, int itheta)
2016 {
2017  cdr_grid_t *cdr;
2018 
2019  cdr = (cdr_grid_t*) source;
2020 
2021  interpol_set_stencil_at (source, interpol,
2022  r_at (pr, cdr->level),
2023  z_at (pz, cdr->level),
2024  cdr->dens[mapper->extra], pr, pz, itheta);
2025  return TRUE;
2026 }
2027 
2029 void
2030 dens_interpol (mapper_t *mapper, grid_t *source, grid_t *target,
2031  interpol_t *interpol,
2032  int ir, int iz, int itheta)
2033 {
2034  double r, z;
2035  cdr_grid_t *cdr;
2036 
2037  cdr = (cdr_grid_t *) target;
2038 
2039  r = r_at (ir, cdr->level);
2040  z = z_at (iz, cdr->level);
2041 
2042  RZT (cdr->dens[mapper->extra], ir, iz, itheta) =
2043  interpol_apply (interpol, r, z);
2044 }
2045 
2049 static void
2051 {
2052  int ir, iz, cr, cz, itheta, s;
2053  REAL sum;
2054 
2055  debug (2, "restrict_from (parent =" grid_printf_str
2056  ", child = " grid_printf_str ")\n",
2057  grid_printf_args(parent), grid_printf_args(child));
2058 
2059  assert (parent->level == child->level - 1);
2060 
2061 #pragma omp parallel private(sum, ir, iz, cr, cz, s)
2062  {
2063 #pragma omp for
2064  iter_grid_theta (parent, itheta) {
2065  iter_grid_parent (child, ir, iz) {
2066  for (s = 0; s < no_species; s++) {
2067  sum = 0;
2068  for (cr = (ir << 1); cr <= (ir << 1) + 1; cr++)
2069  for (cz = (iz << 1); cz <= (iz << 1) + 1; cz++)
2070  sum += cyl_r_at (cr, child->level)
2071  * RZT (child->dens[s], cr, cz, itheta);
2072  RZT (parent->dens[s], ir, iz, itheta) =
2073  0.25 * sum / cyl_r_at (ir, parent->level);
2074  }
2075  }
2076  }
2077  }
2078 }
2079 
2082 void
2084 {
2085  cdr_grid_t *child;
2086 
2087  iter_childs(grid, child) {
2088  restrict_from (grid, child);
2089  }
2090 }
2091 
2098 
2099 
2100 
2103 double
2104 gauss2_xyz (double x, double y, double z)
2105 {
2106  double q;
2107 
2110  * exp (- SQ(x - seed_index[curr_seed]->x0) / SQ(seed_index[curr_seed]->sigma_x)
2111  - SQ(y - seed_index[curr_seed]->y0) / SQ(seed_index[curr_seed]->sigma_y)
2112  - SQ(z - seed_index[curr_seed]->z0) / SQ(seed_index[curr_seed]->sigma_z));
2113  return q;
2114 }
2115 
2125 void
2126 cdr_set_dens (cdr_grid_t *cdr, int species, int mode, double factor,
2127  double (*f) (double, double, double))
2128 {
2129  int ir, iz, itheta;
2130  double ctheta, stheta, x, y;
2131  debug (2, "cdr_set_dens (" grid_printf_str ", %s, ...)\n",
2132  grid_printf_args(cdr), spec_index[species]->name);
2133 
2134 #pragma omp parallel private(ir, iz, ctheta, stheta, x, y)
2135  {
2136 #pragma omp for
2137  iter_grid_theta_n (cdr, itheta, 2) {
2138  //sincos (theta_at(itheta), &stheta, &ctheta);
2139  stheta=sin(theta_at(itheta));
2140  ctheta=cos(theta_at(itheta));
2141  iter_grid_r_n(cdr, ir, 2) {
2142  x = r_at(ir, cdr->level) * ctheta;
2143  y = r_at(ir, cdr->level) * stheta;
2144  iter_grid_z_n(cdr, iz, 2) {
2145  switch (mode) {
2146  case SET_DENS_OVERWRITE:
2147  *RZTP(cdr->dens[species], ir, iz, itheta) =
2148  factor * f (x, y, z_at(iz, cdr->level));
2149  break;
2150  case SET_DENS_ADD:
2151  *RZTP(cdr->dens[species], ir, iz, itheta) +=
2152  factor * f (x, y, z_at(iz, cdr->level));
2153  break;
2154  case SET_DENS_SUB:
2155  *RZTP(cdr->dens[species], ir, iz, itheta) -=
2156  factor * f (x, y, z_at(iz, cdr->level));
2157  break;
2158  }
2159  }
2160  }
2161  }
2162  }
2163 }
2164 
2166 double f_one(double x, double y, double z)
2167 {
2168  return 1.0;
2169 }
2170 
2172 void
2174 {
2175  int cnt;
2176 
2177  debug (2, "cdr_init_dens (" grid_printf_str ")\n",
2178  grid_printf_args(cdr));
2179 
2180  for (cnt = 0; cnt < no_species; cnt++)
2181  {
2182  cdr_set_dens(cdr, cnt, SET_DENS_OVERWRITE, 0.0, f_one);
2183  }
2184 
2185  for (cnt = 0; cnt < no_seed; cnt++)
2186  {
2187  curr_seed = cnt;
2188  if (seed_index[cnt]->type == 0)
2189  cdr_set_dens(cdr, seed_index[cnt]->species, SET_DENS_ADD, seed_index[cnt]->value, gauss2_xyz);
2190  if (seed_index[cnt]->type == 1)
2191  cdr_set_dens(cdr, seed_index[cnt]->species, SET_DENS_ADD, seed_index[cnt]->value, f_one);
2192  }
2193 }
2194 
2196 cdr_grid_t*
2198 {
2199  cdr_grid_t *cdr;
2200 
2202 
2203  cdr->level = 0;
2204  cdr->ext_bound = BND_MASK_ALL;
2205  cdr->contains_edge = TRUE;
2206 
2207  cdr_init_dens (cdr);
2208  cdr_refine_r (cdr, NULL);
2209 
2210  if (perturb_epsilon > 0.0 && max_ntheta > 1) {
2211  dft_dens_perturb_r (cdr, electrons, NULL);
2212 
2213  /* Maybe the perturbation has messed up the boundary conditions, so we
2214  * have to repair them.
2215  */
2216  cdr_set_ext_bnd_r (cdr);
2217  cdr_set_periodic_r (cdr);
2218  }
2219  return cdr;
2220 }
2221 
2225 void
2226 cdr_dump (cdr_grid_t *grid, const char *prefix, const char *name)
2227 {
2228  char *fname;
2229  int s, nt;
2230 
2231  int m = cdr_output_margin;
2232 
2233  /* To make it easier to produce plots in theta, we save one extra
2234  * theta that has to give the same data as the first one. Except if
2235  * we are working in 2D, where anyway we have only one possible theta (0)
2236  */
2237  nt = grid->ntheta == 1? 1: grid->ntheta + 1;
2238 
2239 
2240 #pragma omp parallel sections private(fname)
2241  {
2242 #pragma omp section
2243  {
2244  asprintf (&fname, "%s/r.%s.tsv", prefix, name);
2245  rz_axis_dump (fname, grid->r0 - m, grid->r1 + m, dr[grid->level]);
2246  free (fname);
2247  }
2248 #pragma omp section
2249  {
2250  asprintf (&fname, "%s/z.%s.tsv", prefix, name);
2251  rz_axis_dump (fname, grid->z0 - m , grid->z1 + m, dz[grid->level]);
2252  free (fname);
2253  }
2254 #pragma omp section
2255  {
2256  /* In all this function we use ntheta + 1 to make matlab's life easier.
2257  * Note that some of these variables have not been made periodic
2258  * and hence the value for ntheta may be undefined.
2259  */
2260  asprintf (&fname, "%s/theta.%s.tsv", prefix, name);
2261  rz_axis_dump (fname, 0, nt, dtheta);
2262  free (fname);
2263  }
2264 #pragma omp section
2265  {
2266  asprintf (&fname, "%s/charge.%s.tsv", prefix, name);
2267  rz_dump_3d (grid->charge, fname, "w", grid->r0 - m, grid->z0 - m,
2268  grid->r1 + m, grid->z1 + m, nt);
2269  free (fname);
2270  }
2271 #pragma omp section
2272  {
2273  asprintf (&fname, "%s/er.%s.tsv", prefix, name);
2274  rz_dump_3d (grid->er, fname, "w", grid->r0 - m, grid->z0 - m,
2275  grid->r1 + m, grid->z1 + m, nt);
2276  free (fname);
2277  }
2278 #pragma omp section
2279  {
2280  asprintf (&fname, "%s/ez.%s.tsv", prefix, name);
2281  rz_dump_3d (grid->ez, fname, "w", grid->r0 - m, grid->z0 - m,
2282  grid->r1 + m, grid->z1 + m, nt);
2283  free (fname);
2284  }
2285 #pragma omp section
2286  {
2287  asprintf (&fname, "%s/etheta.%s.tsv", prefix, name);
2288  rz_dump_3d (grid->etheta, fname, "w", grid->r0 - m, grid->z0 - m,
2289  grid->r1 + m, grid->z1 + m, nt);
2290  free (fname);
2291  }
2292 
2293 #pragma omp section
2294  {
2295  asprintf (&fname, "%s/eabs.%s.tsv", prefix, name);
2296  rz_dump_3d (grid->eabs, fname, "w", grid->r0 - m, grid->z0 - m,
2297  grid->r1 + m, grid->z1 + m, nt);
2298  free (fname);
2299  }
2300 
2301 #pragma omp section
2302  {
2303  if (has_photoionization) {
2304  asprintf (&fname, "%s/photo.%s.tsv", prefix, name);
2305  rz_dump_3d (grid->photo, fname, "w", grid->r0 - m, grid->z0 - m,
2306  grid->r1 + m, grid->z1 + m, nt);
2307  free (fname);
2308  }
2309  }
2310 
2311 #pragma omp section
2312  {
2313  for (s = 0; s < no_species; s++) {
2314  /* The densities */
2315  asprintf (&fname, "%s/%s.%s.tsv", prefix, spec_index[s]->name, name);
2316  rz_dump_3d (grid->dens[s], fname, "w", grid->r0 - m, grid->z0 - m,
2317  grid->r1 + m, grid->z1 + m, nt);
2318  free (fname);
2319 
2320  /* ...and their derivatives. */
2321  asprintf (&fname, "%s/d_%s.%s.tsv", prefix, spec_index[s]->name, name);
2322  rz_dump_3d (grid->d_dens[s], fname, "w", grid->r0 - m, grid->z0 - m,
2323  grid->r1 + m, grid->z1 + m, nt);
2324  free (fname);
2325  }
2326  }
2327  }
2328 }
2329 
2359 void
2360 cdr_dump_r (cdr_grid_t *grid, const char *prefix, const char *name,
2361  FILE *infp, double sim_time)
2362 {
2363  cdr_grid_t *child;
2364  char *cname;
2365  int i, nchilds;
2366  char codes[] = "abcdefghijklmnopqrstuvwxyz";
2367  FILE *fp;
2368 
2369  if (NULL == infp) {
2370  /* Root call */
2371  asprintf (&cname, "%s/tree.%s.dat", prefix, name);
2372  fp = fopen (cname, "w");
2373  if (NULL == fp) {
2374  fatal ("Could not open file %s/tree.%s.dat to write\n",
2375  prefix, name);
2376  }
2377  free (cname);
2378  fprintf (fp, "time %g\n", sim_time);
2379  } else {
2380  fp = infp;
2381  }
2382 
2383  /* We want to be sure that the charge that we plot is actually the
2384  * charge and not its Fourier transform.
2385  */
2386  cdr_calc_charge_r (grid);
2387 
2388  fprintf (fp, "open %s %d %d %d %d %d %d %d\n", name, grid->r0, grid->z0,
2389  grid->r1, grid->z1, grid->level, grid->ext_bound,
2391 
2392  cdr_dump (grid, prefix, name);
2393 
2394  nchilds = grid_howmany_children ((grid_t *) grid);
2395 
2396  for (i = 0; i < nchilds; i++) {
2397  child = (cdr_grid_t *) grid_get_child ((grid_t*) grid, nchilds - i - 1);
2398 
2399  assert (NULL != child);
2400 
2401  if (i > sizeof(codes) - 2)
2402  asprintf (&cname, "%s{%d}", name, i);
2403  else
2404  asprintf (&cname, "%s%c", name, codes[i]);
2405 
2406  cdr_dump_r (child, prefix, cname, fp, sim_time);
2407  free (cname);
2408  }
2409 
2410  fprintf (fp, "close %s\n", name);
2411 
2412  if (NULL == infp) {
2413  /* Root call */
2414  fclose (fp);
2415  }
2416 }
2417 
2424 cdr_grid_t *
2425 cdr_load_tree_r (const char *prefix, const char *name, FILE *infp)
2426 {
2427  char command[16], gridname[32], *fname;
2428  int r0, z0, r1, z1, level, ext_bound, margin, nt, s;
2429  int open_close;
2430  cdr_grid_t *grid = NULL, *leaf;
2431  FILE *fp;
2432 
2433  debug (2, "cdr_load_tree_r (prefix = \"%s\", name = \"%s\", ...)\n",
2434  prefix, name);
2435 
2436  nt = max_ntheta == 1? 1: max_ntheta + 1;
2437 
2438  if (NULL == infp) {
2439  asprintf (&fname, "%s/tree.%s.dat", prefix, name);
2440  fp = fopen (fname, "r");
2441  if (NULL == fp) {
2442  fatal ("Could not open file %s/tree.%s.dat to read\n",
2443  prefix, name);
2444  }
2445  free (fname);
2446  } else {
2447  fp = infp;
2448  }
2449 
2450  do {
2451  fscanf (fp, "%15s %15s", command, gridname);
2452  open_close = TRUE;
2453 
2454  /* We analyze some commands that do not create/close grids, now
2455  * restricted to set time.
2456  */
2457  if (0 == strcmp (command, "time")) {
2458  double new_time;
2459  sscanf (gridname, "%lf\n", &new_time);
2460  warning ("Starting time [%f] was read from %s/tree.%s.dat\n",
2461  new_time, prefix, name);
2462 
2463  start_t = new_time;
2464  open_close = FALSE;
2465  }
2466  } while (!open_close);
2467 
2468  if (0 == strcmp (command, "open")) {
2469  debug (3, "opening %s\n", gridname);
2470 
2471  fscanf (fp, "%d %d %d %d %d %d %d\n",
2472  &r0, &z0, &r1, &z1, &level, &ext_bound, &margin);
2473 
2474  grid = cdr_new_3d_a (r0, z0, r1, z1, max_ntheta);
2475  grid->ext_bound = ext_bound;
2476  grid->level = level;
2477 
2478  for (s = 0; s < no_species; s++) {
2479  /* The densities */
2480  asprintf (&fname, "%s/%s.%s.tsv", prefix, spec_index[s]->name, gridname);
2481  debug (3, "Loading %s\n", fname);
2482  rz_dump_3d (grid->dens[s], fname, "r",
2483  grid->r0 - margin, grid->z0 - margin,
2484  grid->r1 + margin, grid->z1 + margin, nt);
2485  free (fname);
2486  }
2487 
2488  do {
2489  leaf = cdr_load_tree_r (prefix, name, fp);
2490  if (NULL != leaf) {
2491  assert (leaf->level == grid->level + 1);
2492  add_child (grid, leaf);
2493  }
2494 
2495  } while (NULL != leaf);
2496  } else if (0 == strcmp (command, "close")) {
2497  debug (3, "closing %s\n", gridname);
2498  grid = NULL;
2499  }
2500 
2501  if (NULL == infp) {
2502  fclose (fp);
2503  }
2504  return grid;
2505 }
2506 
2510 void
2511 cdr_dump_frames (cdr_grid_t *grid, const char *prefix, const char *name)
2512 {
2513  FILE *fp;
2514  char *fname;
2515 
2516  asprintf (&fname, "%s/frames.%s.tsv", prefix, name);
2517  fp = fopen (fname, "w");
2518  free (fname);
2519 
2520  if (fp == NULL) {
2521  warning ("Unable to open %s\n", fname);
2522  return;
2523  }
2524  aux_dump_frames_r (grid, fp);
2525 
2526  fclose (fp);
2527 }
2528 
2530 void
2532 {
2533  cdr_grid_t *child;
2534  int level;
2535 
2536  level = grid->level;
2537 
2538  fprintf (fp, "%g %g %g %g %d\n",
2539  er_r_at (grid->r0 - 1, level), ez_z_at (grid->z0 - 1, level),
2540  er_r_at (grid->r1 - 1, level), ez_z_at (grid->z1 - 1, level),
2541  level);
2542 
2543  iter_childs(grid, child) {
2544  aux_dump_frames_r (child, fp);
2545  }
2546 }