Canoe
Comprehensive Atmosphere N' Ocean Engine
convective_heat_flx.cpp
Go to the documentation of this file.
1 // C/C++ headers
2 // MPI headers
3 #ifdef MPI_PARALLEL
4 #include <mpi.h>
5 #endif
6 
7 #include "../coordinates/coordinates.hpp"
8 #include "../reconstruct/interpolation.hpp"
9 #include "../thermodynamics/thermodynamics.hpp"
10 #include "diagnostics.hpp"
11 
12 ConvectiveHeatFlx::ConvectiveHeatFlx(MeshBlock *pmb)
13  : Diagnostics(pmb, "conv_heat_flx") {
14  type = "VECTORS";
15  grid = "--C";
16  long_name = "Z-coordinate convective heat flux (eddy and mean)";
17  units = "W/(m^2)";
18  eddy_.NewAthenaArray(NHYDRO, ncells3_, ncells2_, ncells1_);
19  mean_.NewAthenaArray(NHYDRO, ncells3_, ncells2_, ncells1_);
20  // eddy heating rate and mean heating rate
21  data.NewAthenaArray(4, 1, 1, ncells1_);
22 }
23 
24 ConvectiveHeatFlx::~ConvectiveHeatFlx() {
25  eddy_.DeleteAthenaArray();
26  mean_.DeleteAthenaArray();
27  data.DeleteAthenaArray();
28 }
29 
30 void ConvectiveHeatFlx::Progress(AthenaArray<Real> const &w) {
31  MeshBlock *pmb = pmy_block_;
32  Coordinates *pcoord = pmb->pcoord;
33  Thermodynamics *pthermo = pmb->pthermo;
34 
35  int is = pmb->is, js = pmb->js, ks = pmb->ks;
36  int ie = pmb->ie, je = pmb->je, ke = pmb->ke;
37 
38  Real *data_sum = new Real[(NHYDRO + 1) * ncells1_];
39  std::fill(data_sum, data_sum + (NHYDRO + 1) * ncells1_, 0.);
40 
41  // calculate horizontal mean
42  for (int k = ks; k <= ke; ++k)
43  for (int j = js; j <= je; ++j) {
44  pcoord->CellVolume(k, j, is, ie, vol_);
45  for (int i = is; i <= ie; ++i) {
46  for (int n = 0; n < IPR; ++n)
47  data_sum[n * ncells1_ + i] += vol_(i) * w(n, k, j, i);
48  data_sum[IPR * ncells1_ + i] +=
49  vol_(i) * pthermo->GetTemp(w.at(k, j, i));
50  data_sum[NHYDRO * ncells1_ + i] += vol_(i);
51  }
52  }
53 
54 #ifdef MPI_PARALLEL
55  // sum over all ranks
56  MPI_Allreduce(MPI_IN_PLACE, data_sum, (NHYDRO + 1) * ncells1_,
57  MPI_ATHENA_REAL, MPI_SUM, MPI_COMM_WORLD);
58 #endif
59 
60  // calculate eddy term
61  for (int k = ks; k <= ke; ++k)
62  for (int j = js; j <= je; ++j)
63  for (int i = is; i <= ie; ++i) {
64  Real vol = data_sum[NHYDRO * ncells1_ + i];
65  for (int n = 0; n < IPR; ++n) {
66  mean_(n, k, j, i) = data_sum[n * ncells1_ + i] / vol;
67  eddy_(n, k, j, i) = w(n, k, j, i) - mean_(n, k, j, i);
68  }
69  mean_(IPR, k, j, i) = data_sum[IPR * ncells1_ + i] / vol;
70  eddy_(IPR, k, j, i) =
71  pthermo->GetTemp(w.at(k, j, i)) - mean_(IPR, k, j, i);
72  }
73 
74  // take horizontal average
75  if (ncycle == 0) std::fill(data.data(), data.data() + data.GetSize(), 0.);
76 
77  for (int k = ks; k <= ke; ++k)
78  for (int j = js; j <= je; ++j) {
79  pcoord->CellVolume(k, j, is, ie, vol_);
80  for (int i = is; i <= ie; ++i) {
81  Real Cp = pthermo->GetMeanCp(w.at(k, j, i));
82  data(0, i) += Cp * mean_(IDN, k, j, i) * eddy_(IPR, k, j, i) *
83  eddy_(IVX, k, j, i) * vol_(i);
84  data(1, i) += Cp * mean_(IDN, k, j, i) * mean_(IPR, k, j, i) *
85  mean_(IVX, k, j, i) * vol_(i);
86  data(2, i) += -mean_(IDN, k, j, i) * mean_(IVX, k, j, i) * 24.79;
87  data(3, i) += -eddy_(IDN, k, j, i) * eddy_(IVX, k, j, i) * 24.79;
88  }
89  }
90 
91  ncycle++;
92  delete[] data_sum;
93 }
94 
95 void ConvectiveHeatFlx::Finalize(AthenaArray<Real> const &w) {
96  MeshBlock *pmb = pmy_block_;
97 
98  int is = pmb->is, js = pmb->js, ks = pmb->ks;
99  int ie = pmb->ie, je = pmb->je, ke = pmb->ke;
100 
101  Real *total_vol = new Real[ncells1_];
102  std::fill(total_vol, total_vol + ncells1_, 0.);
103 
104  // calculate total volume
105  for (int k = ks; k <= ke; ++k)
106  for (int j = js; j <= je; ++j) {
107  pmb->pcoord->CellVolume(k, j, is, ie, vol_);
108  for (int i = is; i <= ie; ++i) total_vol[i] += vol_(i);
109  }
110 
111  // take time and spatial average
112  if (ncycle > 0) {
113  // sum over all ranks
114 #ifdef MPI_PARALLEL
115  MPI_Allreduce(MPI_IN_PLACE, data.data(), data.GetSize(), MPI_ATHENA_REAL,
116  MPI_SUM, MPI_COMM_WORLD);
117  MPI_Allreduce(MPI_IN_PLACE, total_vol, ncells1_, MPI_ATHENA_REAL, MPI_SUM,
118  MPI_COMM_WORLD);
119 #endif
120  for (int n = 0; n < 4; ++n)
121  for (int i = is; i <= ie; ++i) data(n, i) /= ncycle * total_vol[i];
122  }
123 
124  // clear cycle;
125  delete[] total_vol;
126  ncycle = 0;
127 }
Real GetTemp(MeshBlock const *pmb, int k, int j, int i) const
Calculate temperature from primitive variable.