11 #include <configure.hpp>
15 #include <athena/athena.hpp>
16 #include <athena/coordinates/coordinates.hpp>
17 #include <athena/mesh/mesh.hpp>
18 #include <athena/outputs/user_outputs.hpp>
37 NetcdfOutput::NetcdfOutput(OutputParameters oparams) : OutputType(oparams) {}
45 void NetcdfOutput::WriteOutputFile(Mesh *pm, ParameterInput *pin,
bool flag) {
49 for (
int b = 0;
b < pm->nblocal; ++
b) {
50 MeshBlock *pmb = pm->my_blocks(
b);
51 auto prad = pmb->pimpl->prad;
63 if (output_params.include_ghost_zones) {
66 if (out_js != out_je) {
70 if (out_ks != out_ke) {
78 if (!TransformOutputData(pmb)) {
88 snprintf(number,
sizeof(number),
"%05d", output_params.file_number);
90 snprintf(blockid,
sizeof(blockid),
"block%d", pmb->gid);
92 fname.assign(output_params.file_basename);
94 fname.append(blockid);
96 fname.append(output_params.file_id);
102 std::stringstream msg;
105 nc_create(fname.c_str(), NC_NETCDF4, &ifile);
108 int ncells1 = out_ie - out_is + 1;
109 int ncells2 = out_je - out_js + 1;
110 int ncells3 = out_ke - out_ks + 1;
111 int nfaces1 = ncells1;
112 if (ncells1 > 1) nfaces1++;
113 int nfaces2 = ncells2;
114 if (ncells2 > 1) nfaces2++;
115 int nfaces3 = ncells3;
116 if (ncells3 > 1) nfaces3++;
118 int nrays = prad->GetNumOutgoingRays();
121 int idt, idx1, idx2, idx3, idx1f, idx2f, idx3f, iray;
123 nc_def_dim(ifile,
"time", NC_UNLIMITED, &idt);
125 nc_def_dim(ifile,
"x1", ncells1, &idx1);
126 if (ncells1 > 1) nc_def_dim(ifile,
"x1f", nfaces1, &idx1f);
128 nc_def_dim(ifile,
"x2", ncells2, &idx2);
129 if (ncells2 > 1) nc_def_dim(ifile,
"x2f", nfaces2, &idx2f);
131 nc_def_dim(ifile,
"x3", ncells3, &idx3);
132 if (ncells3 > 1) nc_def_dim(ifile,
"x3f", nfaces3, &idx3f);
134 if (nrays > 0) nc_def_dim(ifile,
"ray", nrays, &iray);
137 int ivt, ivx1, ivx2, ivx3, ivx1f, ivx2f, ivx3f, imu, iphi;
138 int loc[4] = {(int)pmb->loc.lx1, (
int)pmb->loc.lx2, (int)pmb->loc.lx3,
142 nc_def_var(ifile,
"time", NC_FLOAT, 1, &idt, &ivt);
143 nc_put_att_text(ifile, ivt,
"axis", 1,
"T");
144 nc_put_att_text(ifile, ivt,
"units", 1,
"s");
145 nc_put_att_text(ifile, ivt,
"long_name", 4,
"time");
147 nc_def_var(ifile,
"x1", NC_FLOAT, 1, &idx1, &ivx1);
148 nc_put_att_text(ifile, ivx1,
"axis", 1,
"Z");
149 nc_put_att_text(ifile, ivx1,
"units", 1,
"m");
150 nc_put_att_text(ifile, ivx1,
"long_name", 27,
151 "Z-coordinate at cell center");
154 pos[1] = pmb->pmy_mesh->mesh_size.nx1;
155 pos[2] = ncells1 * loc[0] + 1;
156 pos[3] = ncells1 * (loc[0] + 1);
157 nc_put_att_int(ifile, ivx1,
"domain_decomposition", NC_INT, 4, pos);
159 nc_def_var(ifile,
"x1f", NC_FLOAT, 1, &idx1f, &ivx1f);
160 nc_put_att_text(ifile, ivx1f,
"units", 1,
"m");
161 nc_put_att_text(ifile, ivx1f,
"long_name", 25,
162 "Z-coordinate at cell face");
165 nc_put_att_int(ifile, ivx1f,
"domain_decomposition", NC_INT, 4, pos);
168 nc_def_var(ifile,
"x2", NC_FLOAT, 1, &idx2, &ivx2);
169 nc_put_att_text(ifile, ivx2,
"axis", 1,
"Y");
170 nc_put_att_text(ifile, ivx2,
"units", 1,
"m");
171 nc_put_att_text(ifile, ivx2,
"long_name", 27,
172 "Y-coordinate at cell center");
175 pos[1] = pmb->pmy_mesh->mesh_size.nx2;
176 pos[2] = ncells2 * loc[1] + 1;
177 pos[3] = ncells2 * (loc[1] + 1);
178 nc_put_att_int(ifile, ivx2,
"domain_decomposition", NC_INT, 4, pos);
180 nc_def_var(ifile,
"x2f", NC_FLOAT, 1, &idx2f, &ivx2f);
181 nc_put_att_text(ifile, ivx2f,
"units", 1,
"m");
182 nc_put_att_text(ifile, ivx2f,
"long_name", 25,
183 "Y-coordinate at cell face");
186 nc_put_att_int(ifile, ivx2f,
"domain_decomposition", NC_INT, 4, pos);
189 nc_def_var(ifile,
"x3", NC_FLOAT, 1, &idx3, &ivx3);
190 nc_put_att_text(ifile, ivx3,
"axis", 1,
"X");
191 nc_put_att_text(ifile, ivx3,
"units", 1,
"m");
192 nc_put_att_text(ifile, ivx3,
"long_name", 27,
193 "X-coordinate at cell center");
196 pos[1] = pmb->pmy_mesh->mesh_size.nx3;
197 pos[2] = ncells3 * loc[2] + 1;
198 pos[3] = ncells3 * (loc[2] + 1);
199 nc_put_att_int(ifile, ivx3,
"domain_decomposition", NC_INT, 4, pos);
201 nc_def_var(ifile,
"x3f", NC_FLOAT, 1, &idx3f, &ivx3f);
202 nc_put_att_text(ifile, ivx3f,
"units", 1,
"m");
203 nc_put_att_text(ifile, ivx3f,
"long_name", 25,
204 "X-coordinate at cell face");
207 nc_put_att_int(ifile, ivx3f,
"domain_decomposition", NC_INT, 4, pos);
211 nc_def_var(ifile,
"mu_out", NC_FLOAT, 1, &iray, &imu);
212 nc_put_att_text(ifile, imu,
"units", 1,
"1");
213 nc_put_att_text(ifile, imu,
"long_name", 18,
"cosine polar angle");
214 nc_def_var(ifile,
"phi_out", NC_FLOAT, 1, &iray, &iphi);
215 nc_put_att_text(ifile, iphi,
"units", 3,
"rad");
216 nc_put_att_text(ifile, iphi,
"long_name", 15,
"azimuthal angle");
219 nc_put_att_int(ifile, NC_GLOBAL,
"NumFilesInSet", NC_INT, 1, &pm->nbtotal);
220 if ((output_params.variable.compare(
"diag") == 0) ||
221 (output_params.variable.compare(
"flux") == 0)) {
222 float dt = (float)pm->dt / 2;
223 nc_put_att_float(ifile, NC_GLOBAL,
"Time_shift_for_DiagFlux_variables",
227 OutputData *pdata = pfirst_data_;
231 while (pdata !=
nullptr) {
232 std::string grid = pmeta->GetGridType(pdata->name);
235 pdata = pdata->pnext;
238 int iaxis[4] = {idt, idx1, idx2, idx3};
239 int iaxis1[4] = {idt, idx1f, idx2, idx3};
240 int iaxis2[4] = {idt, idx1, idx2f, idx3};
241 int iaxis3[4] = {idt, idx1, idx2, idx3f};
242 int iaxisr[4] = {idt, iray, idx2, idx3};
243 int *var_ids =
new int[total_vars];
246 pdata = pfirst_data_;
247 while (pdata !=
nullptr) {
248 std::string name, attr;
249 std::vector<std::string> varnames;
250 std::string grid = pmeta->GetGridType(pdata->name);
253 for (
int n = 0; n < nvar; ++n) {
254 size_t pos = pdata->name.find(
'?');
256 if (pos < pdata->name.length()) {
257 varnames.push_back(pdata->name.substr(0, pos) +
258 pdata->name.substr(pos + 1));
260 varnames.push_back(pdata->name);
264 snprintf(c,
sizeof(c),
"%d", n + 1);
265 if (pos < pdata->name.length()) {
266 varnames.push_back(pdata->name.substr(0, pos) + c +
267 pdata->name.substr(pos + 1));
269 varnames.push_back(pdata->name + c);
274 for (
int n = 0; n < nvar; ++n) {
277 nc_def_var(ifile, name.c_str(), NC_FLOAT, 4, iaxisr, ivar);
278 else if (grid ==
"CCF")
279 nc_def_var(ifile, name.c_str(), NC_FLOAT, 4, iaxis1, ivar);
280 else if ((grid ==
"CFC") && (ncells2 > 1))
281 nc_def_var(ifile, name.c_str(), NC_FLOAT, 4, iaxis2, ivar);
282 else if ((grid ==
"FCC") && (ncells3 > 1))
283 nc_def_var(ifile, name.c_str(), NC_FLOAT, 4, iaxis3, ivar);
284 else if (grid ==
"--C")
285 nc_def_var(ifile, name.c_str(), NC_FLOAT, 2, iaxis, ivar);
286 else if (grid ==
"--F")
287 nc_def_var(ifile, name.c_str(), NC_FLOAT, 2, iaxis1, ivar);
288 else if (grid ==
"---")
289 nc_def_var(ifile, name.c_str(), NC_FLOAT, 1, iaxis, ivar);
291 nc_def_var(ifile, name.c_str(), NC_FLOAT, 4, iaxis, ivar);
294 attr = pmeta->GetUnits(pdata->name);
296 nc_put_att_text(ifile, *ivar,
"units", attr.length(), attr.c_str());
300 attr = pmeta->GetLongName(pdata->name);
302 nc_put_att_text(ifile, *ivar,
"long_name", attr.length(),
308 pdata = pdata->pnext;
314 float *
data =
new float[nfaces1 * nfaces2 * nfaces3];
315 size_t start[4] = {0, 0, 0, 0};
316 size_t count[4] = {1, (size_t)ncells1, (
size_t)ncells2, (size_t)ncells3};
317 size_t count1[4] = {1, (size_t)nfaces1, (
size_t)ncells2, (size_t)ncells3};
318 size_t count2[4] = {1, (size_t)ncells1, (
size_t)nfaces2, (size_t)ncells3};
319 size_t count3[4] = {1, (size_t)ncells1, (
size_t)ncells2, (size_t)nfaces3};
320 size_t countr[4] = {1, (size_t)nrays, (
size_t)ncells2, (size_t)ncells3};
322 float time = (float)pm->time;
323 nc_put_vara_float(ifile, ivt, start, count, &
time);
325 for (
int i = out_is; i <= out_ie; ++i)
326 data[i - out_is] = (
float)(pmb->pcoord->x1v(i));
327 nc_put_var_float(ifile, ivx1,
data);
330 for (
int i = out_is; i <= out_ie + 1; ++i)
331 data[i - out_is] = (
float)(pmb->pcoord->x1f(i));
332 nc_put_var_float(ifile, ivx1f,
data);
335 for (
int j = out_js;
j <= out_je; ++
j)
336 data[
j - out_js] = (
float)(pmb->pcoord->x2v(
j));
337 nc_put_var_float(ifile, ivx2,
data);
340 for (
int j = out_js;
j <= out_je + 1; ++
j)
341 data[
j - out_js] = (
float)(pmb->pcoord->x2f(
j));
342 nc_put_var_float(ifile, ivx2f,
data);
345 for (
int k = out_ks; k <= out_ke; ++k)
346 data[k - out_ks] = (
float)(pmb->pcoord->x3v(k));
347 nc_put_var_float(ifile, ivx3,
data);
350 for (
int k = out_ks; k <= out_ke + 1; ++k)
351 data[k - out_ks] = (
float)(pmb->pcoord->x1f(k));
352 nc_put_var_float(ifile, ivx3f,
data);
357 for (
int b = 0;
b < prad->GetNumBands(); ++
b) {
358 auto p = prad->GetBand(
b);
359 for (
int n = 0; n <
p->GetNumOutgoingRays(); ++n)
360 data[m++] = (
float)(
p->GetCosinePolarAngle(n));
362 nc_put_var_float(ifile, imu,
data);
365 for (
int b = 0;
b < prad->GetNumBands(); ++
b) {
366 auto p = prad->GetBand(
b);
367 for (
int n = 0; n <
p->GetNumOutgoingRays(); ++n)
368 data[m++] = (
float)(
p->GetAzimuthalAngle(n));
370 nc_put_var_float(ifile, iphi,
data);
374 pdata = pfirst_data_;
375 while (pdata !=
nullptr) {
376 std::string grid = pmeta->GetGridType(pdata->name);
380 for (
int n = 0; n < nvar; n++) {
382 for (
int m = 0; m < nrays; ++m)
383 for (
int j = out_js;
j <= out_je; ++
j)
384 for (
int k = out_ks; k <= out_ke; ++k)
385 *it++ = (
float)pdata->data(n, m, k,
j);
386 nc_put_vara_float(ifile, *ivar++, start, countr,
data);
388 }
else if (grid ==
"CCF") {
389 for (
int n = 0; n < nvar; n++) {
391 for (
int i = out_is; i <= out_ie + 1; ++i)
392 for (
int j = out_js;
j <= out_je; ++
j)
393 for (
int k = out_ks; k <= out_ke; ++k)
394 *it++ = (
float)pdata->data(n, k,
j, i);
395 nc_put_vara_float(ifile, *ivar++, start, count1,
data);
397 }
else if ((grid ==
"CFC") && (ncells2 > 1)) {
398 for (
int n = 0; n < nvar; n++) {
400 for (
int i = out_is; i <= out_ie; ++i)
401 for (
int j = out_js;
j <= out_je + 1; ++
j)
402 for (
int k = out_ks; k <= out_ke; ++k)
403 *it++ = (
float)pdata->data(n, k,
j, i);
404 nc_put_vara_float(ifile, *ivar++, start, count2,
data);
406 }
else if ((grid ==
"FCC") && (ncells3 > 1)) {
407 for (
int n = 0; n < nvar; n++) {
409 for (
int i = out_is; i <= out_ie; ++i)
410 for (
int j = out_js;
j <= out_je; ++
j)
411 for (
int k = out_ks; k <= out_ke + 1; ++k)
412 *it++ = (
float)pdata->data(n, k,
j, i);
413 nc_put_vara_float(ifile, *ivar++, start, count3,
data);
415 }
else if (grid ==
"--C") {
416 for (
int n = 0; n < nvar; n++) {
418 for (
int i = out_is; i <= out_ie; ++i)
419 *it++ = (
float)pdata->data(n, i);
420 nc_put_vara_float(ifile, *ivar++, start, count,
data);
422 }
else if (grid ==
"--F") {
423 for (
int n = 0; n < nvar; n++) {
425 for (
int i = out_is; i <= out_ie + 1; ++i)
426 *it++ = (
float)pdata->data(n, i);
427 nc_put_vara_float(ifile, *ivar++, start, count1,
data);
429 }
else if (grid ==
"---") {
430 for (
int n = 0; n < nvar; n++) {
432 *it++ = (float)pdata->data(n);
433 nc_put_vara_float(ifile, *ivar++, start, count,
data);
436 for (
int n = 0; n < nvar; n++) {
438 for (
int i = out_is; i <= out_ie; ++i)
439 for (
int j = out_js;
j <= out_je; ++
j)
440 for (
int k = out_ks; k <= out_ke; ++k)
441 *it++ = (
float)pdata->data(n, k,
j, i);
442 nc_put_vara_float(ifile, *ivar++, start, count,
data);
449 pdata = pdata->pnext;
461 output_params.file_number++;
462 output_params.next_time += output_params.dt;
463 pin->SetInteger(output_params.block_name,
"file_number",
464 output_params.file_number);
465 pin->SetReal(output_params.block_name,
"next_time", output_params.next_time);
int get_num_variables(std::string grid, AthenaArray< Real > const &data)