PLUTO
input_data.c
Go to the documentation of this file.
1 /* ///////////////////////////////////////////////////////////////////// */
2 /*!
3  \file
4  \brief Provide basic functionality for reading input data files.
5 
6  Collects a number of functions for opening, reading and assigning
7  initial conditions from user-supplied data file(s).
8  The geometry and dimensions of the input grid can be different from
9  the actual grid employed by PLUTO, as long as the coordinate geometry
10  transformation has been implemented.
11  The input grid and data files should employ the same format and
12  conventions employed by PLUTO.
13 
14  - Gridfile: coordinates should be written using the PLUTO 4.0 grid format.
15  - Datafile: variables should be written in sequence in a single binary
16  file using single or double precision.
17  The file extension must be ".flt" or ".dbl" for the former and
18  the latter, respectively.
19 
20  Note that not all of the variables should be present and the input
21  array ::get_var specifies which ones are to be searched for.
22 
23  The InputDataSet() initialize the module and by assigning values to
24  global variables such as size, geometry and dimensions of the input grid.
25  Data values are read through the function InputDataRead() while
26  InputDataInterpolate() can be finally used to map input data onto the
27  grid employed by PLUTO using bi- or tri-linear interpolation to fill the
28  data array at the desired coordinate location.
29 
30  \authors A. Mignone (mignone@ph.unito.it)\n
31  P. Tzeferacos
32  \date Aug 27, 2012
33 */
34 /* ///////////////////////////////////////////////////////////////////// */
35 #include"pluto.h"
36 #define ID_MAX_NVAR 256
37 
38 static int id_nvar; /**< Number of variables to be read on input. */
39 static int id_var_indx[ID_MAX_NVAR]; /**< The variable index. */
40 static int id_nx1; /**< Size of input grid in the x1 direction. */
41 static int id_nx2; /**< Size of input grid in the x2 direction. */
42 static int id_nx3; /**< Size of input grid in the x3 direction. */
43 
44 static int id_geom; /**< Geometry of the input grid. */
45 
46 static double *id_x1; /**< Array of point coordinates of the x1 input grid. */
47 static double *id_x2; /**< Array of point coordinates of the x2 input grid. */
48 static double *id_x3; /**< Array of point coordinates of the x3 input grid. */
49 
50 static double ***Vin[ID_MAX_NVAR]; /**< An array of 3D data values containing the
51  initial data file variables. */
52 
53 /* ********************************************************************* */
54 void InputDataSet (char *grid_fname, int *get_var)
55 /*!
56  * Initialize access to input data file by assigning values to
57  * grid-related information (geometry, number of points, etc...).
58  * This function should be called just once for input-data initialization.
59  *
60  * \param [in] gname the grid file name
61  * \param [in] get_var an array of integers specifying which variables
62  * have to be read from the input data.
63  * \return Thi function has no return value.
64  *
65  * The following tasks are performed.
66  *********************************************************************** */
67 {
68  int i, ip, nv, success;
69  size_t dsize, dcount;
70  char *sub_str, sline[256];
71  const char delimiters[] = " \t\r\f\n";
72  double xl, xr;
73  fpos_t file_pos;
74  FILE *fp;
75 
76  print1 ("> Input data:\n\n");
77 
78 /* --------------------------------------------------------------------- */
79 /*! - Scan grid data file and try to determine the grid geometry
80  (::id_geom). Search for tag "GEOMETRY:" and read the word that
81  follows. */
82 /* --------------------------------------------------------------------- */
83 
84  fp = fopen(grid_fname,"r");
85  if (fp == NULL){
86  print1 ("! InputDataSet: grid file %s not found\n",grid_fname);
87  QUIT_PLUTO(1);
88  }
89  success = 0;
90  while(!success){
91  fgets(sline,512,fp);
92  sub_str = strtok(sline, delimiters);
93  while (sub_str != NULL){
94  if (!strcmp(sub_str,"GEOMETRY:")) {
95  sub_str = strtok(NULL, delimiters);
96  success = 1;
97  break;
98  }
99  sub_str = strtok(NULL, delimiters);
100  }
101  }
102 
103  if (!strcmp(sub_str,"CARTESIAN")) id_geom = CARTESIAN;
104  else if (!strcmp(sub_str,"CYLINDRICAL")) id_geom = CYLINDRICAL;
105  else if (!strcmp(sub_str,"POLAR")) id_geom = POLAR;
106  else if (!strcmp(sub_str,"SPHERICAL")) id_geom = SPHERICAL;
107  else{
108  print1 ("! InputDataSet: unknown geometry\n");
109  QUIT_PLUTO(1);
110  }
111 
112  print1 (" Input grid file: %s\n", grid_fname);
113  print1 (" Input grid geometry: %s\n", sub_str);
114 
115 /* --------------------------------------------------------------------- */
116 /*! - Move file pointer until the first line that does not
117  begin with a "#". */
118 /* --------------------------------------------------------------------- */
119 
120  success = 0;
121  while(!success){
122  fgetpos(fp, &file_pos);
123  fgets(sline,512,fp);
124  if (sline[0] != '#') success = 1;
125  }
126 
127  fsetpos(fp, &file_pos);
128 
129 /* --------------------------------------------------------------------- */
130 /*! - Start reading number of points and grid coordinates. For the
131  input x1 direction these are stored inside the module variables
132  ::id_nx1 and ::id_x1. */
133 /* --------------------------------------------------------------------- */
134 
135  fscanf (fp,"%d \n",&id_nx1);
136  id_x1 = ARRAY_1D(id_nx1, double);
137  for (i = 0; i < id_nx1; i++){
138  fscanf(fp,"%d %lf %lf\n", &ip, &xl, &xr);
139  id_x1[i] = 0.5*(xl + xr);
140  }
141 
142  fscanf (fp,"%d \n",&id_nx2);
143  id_x2 = ARRAY_1D(id_nx2, double);
144  for (i = 0; i < id_nx2; i++){
145  fscanf(fp,"%d %lf %lf\n", &ip, &xl, &xr);
146  id_x2[i] = 0.5*(xl + xr);
147  }
148 
149  fscanf (fp,"%d \n",&id_nx3);
150  id_x3 = ARRAY_1D(id_nx3, double);
151  for (i = 0; i < id_nx3; i++){
152  fscanf(fp,"%d %lf %lf\n", &ip, &xl, &xr);
153  id_x3[i] = 0.5*(xl + xr);
154  }
155  fclose(fp);
156 
157 /* -- reset grid with 1 point -- */
158 
159  if (id_nx1 == 1) id_x1[0] = 0.0;
160  if (id_nx2 == 1) id_x2[0] = 0.0;
161  if (id_nx3 == 1) id_x3[0] = 0.0;
162 
163  print1 (" Input grid extension: x1 = [%12.3e, %12.3e] (%d points)\n",
164  id_x1[0], id_x1[id_nx1-1], id_nx1);
165  print1 ("\t\t\t x2 = [%12.3e, %12.3e] (%d points)\n",
166  id_x2[0], id_x2[id_nx2-1], id_nx2);
167  print1 ("\t\t\t x3 = [%12.3e, %12.3e] (%d points)\n",
168  id_x3[0], id_x3[id_nx3-1], id_nx3);
169 
170 
171 /* --------------------------------------------------------------------- */
172 /*! - Find out how many and which variables we have to read (:id_nvar
173  and ::id_var_indx).
174  Stop counting variables as soon as the first occurrence of "-1"
175  in get_var is encountered */
176 /* --------------------------------------------------------------------- */
177 
178  id_nvar = 0;
179  for (nv = 0; nv < ID_MAX_NVAR; nv++){
180  if (get_var[nv] != -1) {
181  id_nvar++;
182  id_var_indx[nv] = get_var[nv];
183  }else{
184  break;
185  }
186  }
187  print1 (" Number of variables: %d\n",id_nvar);
188 }
189 
190 /* ********************************************************************* */
191 void InputDataRead (char *data_fname, char *endianity)
192 /*!
193  * Read input data file and store the contents into the local storage
194  * array ::Vin. Memory allocation is also done here.
195  * The grid size and number of variables must have
196  * previously set by calling InputDataSet().
197  *
198  * \param [in] data_fname the data file name
199  * \param [in] endianity an input string ("little" or "big") giving
200  * the byte-order of how the input data file
201  * was originally written.
202  * If an empty string is supplied, no change is
203  * made.
204  * \return This function has no return value.
205  *********************************************************************** */
206 {
207  int i, j, k, nv, swap_endian=NO;
208  size_t dsize, dcount;
209  double udbl;
210  float uflt;
211  char ext[] = " ";
212  FILE *fp;
213 
214 /* ----------------------------------------------------
215  Check endianity
216  ---------------------------------------------------- */
217 
218  if ( (!strcmp(endianity,"big") && IsLittleEndian()) ||
219  (!strcmp(endianity,"little") && !IsLittleEndian())) {
220  swap_endian = YES;
221  }
222 
223  print1 (" Input data file: %s (endianity: %s) \n",
224  data_fname, endianity);
225 
226 /* ------------------------------------------------------
227  Get data type from file extensions (dbl or flt).
228  ------------------------------------------------------ */
229 
230  dcount = strlen(data_fname);
231  for (i = 0; i < 3; i++) ext[i] = data_fname[dcount-3+i];
232 
233  if (!strcmp(ext,"dbl")){
234  print1 (" Precision: (double)\n");
235  dsize = sizeof(double);
236  } else if (!strcmp(ext,"flt")) {
237  print1 (" Precision:\t\t (single)\n");
238  dsize = sizeof(float);
239  } else {
240  print1 ("! InputDataRead: unsupported data type '%s'\n",ext);
241  QUIT_PLUTO(1);
242  }
243 
244 /* -------------------------------------------------------
245  Read and store data values
246  ------------------------------------------------------- */
247 
248  fp = fopen(data_fname, "rb");
249  if (fp == NULL){
250  print1 ("! InputDataRead: file %s does not exist\n");
251  QUIT_PLUTO(1);
252  }
253  for (nv = 0; nv < id_nvar; nv++){
254  if (Vin[nv] == NULL) Vin[nv] = ARRAY_3D(id_nx3, id_nx2, id_nx1, double);
255 
256  dcount = 1;
257 
258  if (dsize == sizeof(double)){
259  for (k = 0; k < id_nx3; k++){
260  for (j = 0; j < id_nx2; j++){
261  for (i = 0; i < id_nx1; i++){
262  if (fread (&udbl, dsize, dcount, fp) != dcount){
263  print1 ("! InputDataRead: error reading data %d.\n",nv);
264  break;
265  }
266  if (swap_endian) SWAP_VAR(udbl);
267  Vin[nv][k][j][i] = udbl;
268  }}}
269  }else{
270  for (k = 0; k < id_nx3; k++){
271  for (j = 0; j < id_nx2; j++){
272  for (i = 0; i < id_nx1; i++){
273  if (fread (&uflt, dsize, dcount, fp) != dcount){
274  print1 ("! InputDataRead: error reading data %d.\n",nv);
275  break;
276  }
277  if (swap_endian) SWAP_VAR(uflt);
278  Vin[nv][k][j][i] = uflt;
279  }}}
280  }
281  }
282  fclose(fp);
283  print1 ("\n");
284 }
285 
286 /* ********************************************************************* */
287 void InputDataInterpolate (double *vs, double x1, double x2, double x3)
288 /*!
289  * Perform bi- or tri-linear interpolation on external
290  * dataset to compute vs[] at the given point {x1,x2,x3}.
291  *
292  * \param [in] vs interpolated value
293  * \param [in] x1 coordinate point at which at interpolates are desired
294  * \param [in] x2 coordinate point at which at interpolates are desired
295  * \param [in] x3 coordinate point at which at interpolates are desired
296  * \return This function has no return value.
297  *
298  * The function performs the following tasks.
299  *********************************************************************** */
300 {
301  int il = 0, jl = 0, kl = 0;
302  int ih, jh, kh;
303  int im, jm, km;
304  int i, j, k, nv, inv;
305  double xx, yy, zz;
306  double ***V;
307 
308 /* --------------------------------------------------------------------- */
309 /*! - Convert PLUTO coordinates to input grid geometry if necessary. */
310 /* --------------------------------------------------------------------- */
311 
312  #if GEOMETRY == CARTESIAN
313  if (id_geom == GEOMETRY) {
314 
315  /* same coordinate system: nothing to do */
316 
317  }else if (id_geom == CYLINDRICAL) {
318  double R, z, phi;
319  R = sqrt(x1*x1 + x2*x2);
320  phi = atan2(x2,x1);
321  if (phi < 0.0) phi += 2.0*CONST_PI;
322  z = x3;
323 
324  x1 = R; x2 = z; x3 = phi;
325  }else if (id_geom == POLAR) {
326  double R, phi, z;
327  R = sqrt(x1*x1 + x2*x2);
328  phi = atan2(x2,x1);
329  if (phi < 0.0) phi += 2.0*CONST_PI;
330  z = x3;
331 
332  x1 = R; x2 = phi; x3 = z;
333  }else if (id_geom == SPHERICAL){
334  double r, theta, phi;
335  r = D_EXPAND(x1*x1, + x2*x2, + x3*x3);
336  r = sqrt(r);
337  theta = acos(x3/r);
338  phi = atan2(x2,x1);
339  if (phi < 0.0) phi += 2.0*CONST_PI;
340  if (theta < 0.0) theta += 2.0*CONST_PI;
341 
342  x1 = r; x2 = theta; x3 = phi;
343  }else{
344  print1 ("! InputDataInterpolate: invalid or unsupported coordinate transformation.\n");
345  QUIT_PLUTO(1);
346  }
347  #elif GEOMETRY == CYLINDRICAL
348  if (id_geom == GEOMETRY) {
349 
350  /* same coordinate system: nothing to do */
351 
352  }else if (id_geom == SPHERICAL) {
353  double r, theta, phi;
354  r = D_EXPAND(x1*x1, + x2*x2, + 0.0);
355  r = sqrt(r);
356  theta = acos(x2/r);
357  phi = 0.0;
358  if (theta < 0.0) theta += 2.0*CONST_PI;
359 
360  x1 = r; x2 = theta; x3 = phi;
361  }else{
362  print1 ("! InputDataInterpolate: invalid or unsupported coordinate transformation.\n");
363  QUIT_PLUTO(1);
364  }
365  #elif GEOMETRY == POLAR
366  if (id_geom == GEOMETRY) {
367 
368  /* same coordinate system: nothing to do */
369 
370  }else if (id_geom == CARTESIAN) {
371  double x, y, z;
372  x = x1*cos(x2);
373  y = x1*sin(x2);
374  z = x3;
375 
376  x1 = x; x2 = y; x3 = z;
377  }else{
378  print1 ("! InputDataInterpolate: invalid or unsupported coordinate transformation.\n");
379  QUIT_PLUTO(1);
380  }
381  #elif GEOMETRY == SPHERICAL
382  if (id_geom == GEOMETRY) {
383 
384  /* same coordinate system: nothing to do */
385 
386 
387  }else if (id_geom == CARTESIAN) {
388  double x, y, z;
389  x = x1*sin(x2)*cos(x3);
390  y = x1*sin(x2)*sin(x3);
391  z = x1*cos(x2);
392 
393  x1 = x; x2 = y; x3 = z;
394  }else{
395  print1 ("! InputDataInterpolate: invalid or unsupported coordinate transformation.\n");
396  QUIT_PLUTO(1);
397  }
398  #endif
399 
400 /* --------------------------------------------------------------------- */
401 /*! - Make sure point (x1,x2,x3) does not fall outside input grid range.
402  Limit to input grid edge otherwise. */
403 /* --------------------------------------------------------------------- */
404 
405  D_EXPAND(if (x1 < id_x1[0]) x1 = id_x1[0];
406  else if (x1 > id_x1[id_nx1-1]) x1 = id_x1[id_nx1-1]; ,
407 
408  if (x2 < id_x2[0]) x2 = id_x2[0];
409  else if (x2 > id_x2[id_nx2-1]) x2 = id_x2[id_nx2-1]; ,
410 
411  if (x3 < id_x3[0]) x3 = id_x3[0];
412  else if (x3 > id_x3[id_nx3-1]) x3 = id_x3[id_nx3-1]; )
413 
414 /* --------------------------------------------------------------------- */
415 /*! - Use table lookup by binary search to find the indices
416  il, jl and kl such that grid points of PLUTO fall between
417  [il, il+1], [jl, jl+1], [kl, kl+1]. */
418 /* --------------------------------------------------------------------- */
419 
420  il = 0;
421  ih = id_nx1 - 1;
422  while (il != (ih-1)){
423  im = (il+ih)/2;
424  if (x1 <= id_x1[im]) ih = im;
425  else il = im;
426  }
427 
428  if (id_nx2 > 1){
429  jl = 0;
430  jh = id_nx2 - 1;
431  while (jl != (jh-1)){
432  jm = (jl+jh)/2;
433  if (x2 <= id_x2[jm]) jh = jm;
434  else jl = jm;
435  }
436  }
437 
438  if (id_nx3 > 1){
439  kl = 0;
440  kh = id_nx3 - 1;
441  while (kl != (kh - 1)){
442  km = (kl+kh)/2;
443  if (x3 <= id_x3[km]) kh = km;
444  else kl = km;
445  }
446  }
447 
448 /* --------------------------------------------------------------------- */
449 /*! - Define normalized coordinates between [0,1]:
450  - x[il+1] < x1[i] < x[il+1] ==> 0 < xx < 1
451  - y[jl+1] < x2[j] < y[jl+1] ==> 0 < yy < 1
452  - z[kl+1] < x3[k] < z[kl+1] ==> 0 < zz < 1 */
453 /* --------------------------------------------------------------------- */
454 
455  xx = yy = zz = 0.0; /* initialize normalized coordinates */
456 
457  if (id_nx1 > 1) xx = (x1 - id_x1[il])/(id_x1[il+1] - id_x1[il]);
458  if (id_nx2 > 1) yy = (x2 - id_x2[jl])/(id_x2[jl+1] - id_x2[jl]);
459  if (id_nx3 > 1) zz = (x3 - id_x3[kl])/(id_x3[kl+1] - id_x3[kl]);
460 
461 /* --------------------------------------------------------------------- */
462 /*! - Perform bi- or tri-linear interpolation. */
463 /* --------------------------------------------------------------------- */
464 
465  for (nv = 0; nv < id_nvar; nv++) {
466  inv = id_var_indx[nv];
467  V = Vin[nv];
468  vs[inv] = V[kl][jl][il]*(1.0 - xx)*(1.0 - yy)*(1.0 - zz)
469  + V[kl][jl][il+1]*xx*(1.0 - yy)*(1.0 - zz);
470  if (id_nx2 > 1){
471  vs[inv] += V[kl][jl+1][il]*(1.0 - xx)*yy*(1.0 - zz)
472  + V[kl][jl+1][il+1]*xx*yy*(1.0 - zz);
473  }
474  if (id_nx3 > 1){
475  vs[inv] += V[kl+1][jl][il]*(1.0 - xx)*(1.0 - yy)*zz
476  + V[kl+1][jl][il+1]*xx*(1.0 - yy)*zz
477  + V[kl+1][jl+1][il]*(1.0 - xx)*yy*zz
478  + V[kl+1][jl+1][il+1]*xx*yy*zz;
479  }
480  }
481 }
482 
483 /* ********************************************************************* */
484 void InputDataFree (void)
485 /*!
486  * Free memory stored by user-supplied data.
487  *
488  *********************************************************************** */
489 {
490  int nv;
491  for (nv = 0; nv < id_nvar; nv++){
492  free ((char *) Vin[nv][0][0]);
493  free ((char *) Vin[nv][0]);
494  free ((char *) Vin[nv]);
495  }
496 }
497 
static double * id_x2
Array of point coordinates of the x2 input grid.
Definition: input_data.c:47
static int id_var_indx[ID_MAX_NVAR]
The variable index.
Definition: input_data.c:39
void print1(const char *fmt,...)
Definition: amrPluto.cpp:511
static int id_nx3
Size of input grid in the x3 direction.
Definition: input_data.c:42
static double *** Vin[ID_MAX_NVAR]
An array of 3D data values containing the initial data file variables.
Definition: input_data.c:50
#define YES
Definition: pluto.h:25
#define SPHERICAL
Definition: pluto.h:36
#define ARRAY_3D(nx, ny, nz, type)
Definition: prototypes.h:172
static int id_nx1
Size of input grid in the x1 direction.
Definition: input_data.c:40
void InputDataFree(void)
Definition: input_data.c:484
void InputDataInterpolate(double *vs, double x1, double x2, double x3)
Definition: input_data.c:287
#define SWAP_VAR(x)
Definition: macros.h:115
#define POLAR
Definition: pluto.h:35
static double * id_x1
Array of point coordinates of the x1 input grid.
Definition: input_data.c:46
static int id_nx2
Size of input grid in the x2 direction.
Definition: input_data.c:41
void InputDataRead(char *data_fname, char *endianity)
Definition: input_data.c:191
int j
Definition: analysis.c:2
int IsLittleEndian(void)
Definition: tools.c:40
int k
Definition: analysis.c:2
#define GEOMETRY
Definition: definitions_01.h:4
#define CARTESIAN
Definition: pluto.h:33
#define CYLINDRICAL
Definition: pluto.h:34
PLUTO main header file.
#define ARRAY_1D(nx, type)
Definition: prototypes.h:170
static int id_geom
Geometry of the input grid.
Definition: input_data.c:44
D_EXPAND(tot/[n]=(double) grid[IDIR].np_int_glob;, tot/[n]=(double) grid[JDIR].np_int_glob;, tot/[n]=(double) grid[KDIR].np_int_glob;)
Definition: analysis.c:27
int i
Definition: analysis.c:2
void InputDataSet(char *grid_fname, int *get_var)
Definition: input_data.c:54
FILE * fp
Definition: analysis.c:7
#define CONST_PI
.
Definition: pluto.h:269
#define ID_MAX_NVAR
Definition: input_data.c:36
static int id_nvar
Number of variables to be read on input.
Definition: input_data.c:38
#define QUIT_PLUTO(e_code)
Definition: macros.h:125
#define NO
Definition: pluto.h:26
static double * id_x3
Array of point coordinates of the x3 input grid.
Definition: input_data.c:48