Canoe
Comprehensive Atmosphere N' Ocean Engine
debug.cpp
Go to the documentation of this file.
1 // \brief writes debug output data, max and min quantities and their locations
3 // that are output
4 // frequently in time to trace extreme values.
5 
6 // C/C++
7 #include <cfloat>
8 #include <cstdio>
9 #include <cstdlib>
10 #include <iomanip>
11 #include <iostream>
12 #include <sstream>
13 #include <stdexcept>
14 #include <string>
15 
16 // canoe
17 #include <configure.hpp>
18 
19 // athena
20 #include <athena/athena.hpp>
21 #include <athena/coordinates/coordinates.hpp>
22 #include <athena/globals.hpp>
23 #include <athena/hydro/hydro.hpp>
24 #include <athena/mesh/mesh.hpp>
25 #include <athena/outputs/user_outputs.hpp>
26 
27 //----------------------------------------------------------------------------------------
29 // \brief Writes a history file
30 
31 void DebugOutput::WriteOutputFile(Mesh *pm, ParameterInput *pin, bool flag) {
32  struct {
33  Real value;
34  int rank;
35  } vmin[NHYDRO], vmax[NHYDRO];
36 
37  struct {
38  Real x1, x2, x3;
39  } xmin[NHYDRO], xmax[NHYDRO];
40 
41  for (int n = 0; n < NHYDRO; ++n) {
42  vmin[n].value = FLT_MAX;
43  vmin[n].rank = Globals::my_rank;
44  vmax[n].value = FLT_MIN;
45  vmax[n].rank = Globals::my_rank;
46  xmin[n].x1 = xmin[n].x2 = xmin[n].x3 = FLT_MAX;
47  xmax[n].x1 = xmax[n].x2 = xmax[n].x3 = FLT_MIN;
48  }
49 
50  // Loop over MeshBlocks
51  for (int b = 0; b < pm->nblocal; ++b) {
52  MeshBlock *pmb = pm->my_blocks(b);
53  Hydro *phydro = pmb->phydro;
54  Coordinates *pcoord = pmb->pcoord;
55 
56  int is = pmb->is, js = pmb->js, ks = pmb->ks;
57  int ie = pmb->ie, je = pmb->je, ke = pmb->ke;
58  // out_is=pmb->is; out_ie=pmb->ie;
59  // out_js=pmb->js; out_je=pmb->je;
60  // out_ks=pmb->ks; out_ke=pmb->ke;
61  // ghost cells are included in the calculations
62  // out_is -= NGHOST; out_ie += NGHOST;
63  // if (out_js != out_je) {out_js -= NGHOST; out_je += NGHOST;}
64  // if (out_ks != out_ke) {out_ks -= NGHOST; out_ke += NGHOST;}
65 
66  // calculate maximum and minimum values over cells
67  for (int n = 0; n < NHYDRO; ++n)
68  for (int k = ks; k <= ke; ++k)
69  for (int j = js; j <= je; ++j)
70  for (int i = is; i <= ie; ++i) {
71  if (phydro->w(n, k, j, i) < vmin[n].value) {
72  vmin[n].value = phydro->w(n, k, j, i);
73  xmin[n].x1 = pcoord->x1v(i);
74  xmin[n].x2 = pcoord->x2v(j);
75  xmin[n].x3 = pcoord->x3v(k);
76  }
77  if (phydro->w(n, k, j, i) > vmax[n].value) {
78  vmax[n].value = phydro->w(n, k, j, i);
79  xmax[n].x1 = pcoord->x1v(i);
80  xmax[n].x2 = pcoord->x2v(j);
81  xmax[n].x3 = pcoord->x3v(k);
82  }
83  }
84  }
85 
86 #ifdef MPI_PARALLEL
87  // gather all nodes and synchronize
88  // TODO(cli): xmin, xmax semm not correct
89  MPI_Allreduce(MPI_IN_PLACE, vmin, NHYDRO, MPI_REAL_INT, MPI_MINLOC,
90  MPI_COMM_WORLD);
91  MPI_Allreduce(MPI_IN_PLACE, vmax, NHYDRO, MPI_REAL_INT, MPI_MAXLOC,
92  MPI_COMM_WORLD);
93 
94  // distribute the coordinates of the extreme values to master node
95  MPI_Status status;
96  MPI_Request request[2 * NHYDRO];
97  for (int n = 0; n < 2 * NHYDRO; ++n) request[n] = MPI_REQUEST_NULL;
98 
99  // send and receive coordinate for min values
100  for (int n = 0; n < NHYDRO; ++n) {
101  if (Globals::my_rank == 0) {
102  if (Globals::my_rank == vmin[n].rank)
103  continue;
104  else
105  MPI_Irecv(xmin + n, 3, MPI_ATHENA_REAL, vmin[n].rank, n, MPI_COMM_WORLD,
106  request + n);
107  } else {
108  if (Globals::my_rank == vmin[n].rank)
109  MPI_Isend(xmin + n, 3, MPI_ATHENA_REAL, 0, n, MPI_COMM_WORLD,
110  request + n);
111  else
112  continue;
113  }
114  }
115 
116  // send and receive coordinate for max values
117  for (int n = 0; n < NHYDRO; ++n) {
118  if (Globals::my_rank == 0) {
119  if (Globals::my_rank == vmax[n].rank)
120  continue;
121  else
122  MPI_Irecv(xmax + n, 3, MPI_ATHENA_REAL, vmax[n].rank, n + NHYDRO,
123  MPI_COMM_WORLD, request + NHYDRO + n);
124  } else {
125  if (Globals::my_rank == vmax[n].rank)
126  MPI_Isend(xmax + n, 3, MPI_ATHENA_REAL, 0, n + NHYDRO, MPI_COMM_WORLD,
127  request + NHYDRO + n);
128  else
129  continue;
130  }
131  }
132 
133  // blocks and waits for master node to receive all data
134  for (int n = 0; n < 2 * NHYDRO; ++n) MPI_Wait(request + n, &status);
135 #endif
136 
137  // only the master rank writes the file
138  // create filename: "file_basename" + ".hst". There is no file number.
139  if (Globals::my_rank == 0) {
140  std::string fname;
141  fname.assign(output_params.file_basename);
142  fname.append(".dbg");
143 
144  // open file for output
145  FILE *pfile;
146  std::stringstream msg;
147  if ((pfile = fopen(fname.c_str(), "a")) == NULL) {
148  msg << "### FATAL ERROR in function [OutputType::DebugFile]" << std::endl
149  << "Output file '" << fname << "' could not be opened";
150  ATHENA_ERROR(msg);
151  }
152 
153  // If this is the first output, write header
154  int iout = 1;
155  if (output_params.file_number == 0) {
156  fprintf(pfile, "# Athena++ debug data\n"); // descriptor is first line
157  fprintf(pfile, "# [%d]=time ", iout++);
158  fprintf(pfile, "[%d]=id ", iout++);
159  fprintf(pfile, "[%d]=dmin ", iout++);
160  fprintf(pfile, "[%d]=dmax ", iout++);
161  fprintf(pfile, "[%d]=x1min ", iout++);
162  fprintf(pfile, "[%d]=x1max ", iout++);
163  fprintf(pfile, "[%d]=x2min ", iout++);
164  fprintf(pfile, "[%d]=x2max ", iout++);
165  fprintf(pfile, "[%d]=x3min ", iout++);
166  fprintf(pfile, "[%d]=x3max ", iout++);
167  fprintf(pfile, "\n"); // terminate line
168  }
169 
170  // write debug variables
171  for (int n = 0; n < NHYDRO; ++n) {
172  if (n == 0)
173  fprintf(pfile, output_params.data_format.c_str(), pm->time);
174  else
175  fprintf(pfile, " ");
176  fprintf(pfile, " -- %2d -- ", n);
177  fprintf(pfile, output_params.data_format.c_str(), vmin[n].value);
178  fprintf(pfile, output_params.data_format.c_str(), vmax[n].value);
179  fprintf(pfile, output_params.data_format.c_str(), xmin[n].x1);
180  fprintf(pfile, output_params.data_format.c_str(), xmax[n].x1);
181  fprintf(pfile, output_params.data_format.c_str(), xmin[n].x2);
182  fprintf(pfile, output_params.data_format.c_str(), xmax[n].x2);
183  fprintf(pfile, output_params.data_format.c_str(), xmin[n].x3);
184  fprintf(pfile, output_params.data_format.c_str(), xmax[n].x3);
185  fprintf(pfile, "\n");
186  }
187  fclose(pfile);
188  }
189 
190  // increment counters, clean up
191  output_params.file_number++;
192  output_params.next_time += output_params.dt;
193  pin->SetInteger(output_params.block_name, "file_number",
194  output_params.file_number);
195  pin->SetReal(output_params.block_name, "next_time", output_params.next_time);
196 
197  return;
198 }