Nektar++
FilterEnergy.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: FilterEnergy.cpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: Output kinetic energy and enstrophy.
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <iomanip>
36 
37 #include <boost/core/ignore_unused.hpp>
38 
41 
42 using namespace std;
43 
44 namespace Nektar
45 {
46 namespace SolverUtils
47 {
48 std::string FilterEnergy::className =
50  "Energy", FilterEnergy::create);
51 
52 FilterEnergy::FilterEnergy(const LibUtilities::SessionReaderSharedPtr &pSession,
53  const std::weak_ptr<EquationSystem> &pEquation,
54  const ParamMap &pParams)
55  : Filter(pSession, pEquation), m_index(-1), m_homogeneous(false), m_planes()
56 {
57  std::string outName;
58 
59  // OutputFile
60  auto it = pParams.find("OutputFile");
61  if (it == pParams.end())
62  {
63  outName = m_session->GetSessionName();
64  }
65  else
66  {
67  ASSERTL0(it->second.length() > 0, "Missing parameter 'OutputFile'.");
68  outName = it->second;
69  }
70  outName += ".eny";
71 
72  m_comm = pSession->GetComm();
73  if (m_comm->GetRank() == 0)
74  {
75  m_outFile.open(outName.c_str());
76  ASSERTL0(m_outFile.good(), "Unable to open: '" + outName + "'");
77  m_outFile.setf(ios::scientific, ios::floatfield);
78  m_outFile << "# Time Kinetic energy "
79  << "Enstrophy" << endl
80  << "# ---------------------------------------------"
81  << "--------------" << endl;
82  }
83  pSession->LoadParameter("LZ", m_homogeneousLength, 0.0);
84 
85  // OutputFrequency
86  it = pParams.find("OutputFrequency");
87  ASSERTL0(it != pParams.end(), "Missing parameter 'OutputFrequency'.");
88  LibUtilities::Equation equ(m_session->GetInterpreter(), it->second);
89  m_outputFrequency = round(equ.Evaluate());
90 }
91 
93 {
94 }
95 
98  const NekDouble &time)
99 {
100  m_index = -1;
102 
103  ASSERTL0(pFields[0]->GetExpType() != MultiRegions::e1D,
104  "1D expansion not supported for energy filter");
105 
106  ASSERTL0(pFields[0]->GetExpType() != MultiRegions::e2D,
107  "2D expansion not supported for energy filter");
108 
109  ASSERTL0(pFields[0]->GetExpType() != MultiRegions::e3DH2D,
110  "Homogeneous 2D expansion not supported for energy filter");
111 
112  if (pFields[0]->GetExpType() == MultiRegions::e3DH1D)
113  {
114  m_homogeneous = true;
115  }
116 
117  // Calculate area/volume of domain.
118  if (m_homogeneous)
119  {
120  m_planes = pFields[0]->GetZIDs();
121  areaField = pFields[0]->GetPlane(0);
122  }
123  else
124  {
125  areaField = pFields[0];
126  }
127 
128  Array<OneD, NekDouble> inarray(areaField->GetNpoints(), 1.0);
129  m_area = areaField->Integral(inarray);
130 
131  if (m_homogeneous)
132  {
134  }
135 
136  // Output values at initial time.
137  v_Update(pFields, time);
138 }
139 
142  const NekDouble &time)
143 {
144  int i, nPoints = pFields[0]->GetNpoints();
145 
146  m_index++;
147 
148  if (m_index % m_outputFrequency > 0)
149  {
150  return;
151  }
152 
153  // Lock equation system pointer
154  auto equ = m_equ.lock();
155  ASSERTL0(equ, "Weak pointer expired");
156 
157  auto fluidEqu = std::dynamic_pointer_cast<FluidInterface>(equ);
158  ASSERTL0(fluidEqu, "Energy filter is incompatible with this solver.");
159 
160  // Store physical values in an array
161  Array<OneD, Array<OneD, NekDouble>> physfields(pFields.size());
162  for (i = 0; i < pFields.size(); ++i)
163  {
164  physfields[i] = pFields[i]->GetPhys();
165  }
166 
167  // Calculate kinetic energy.
168  NekDouble Ek = 0.0;
169  Array<OneD, NekDouble> tmp(nPoints, 0.0);
170  Array<OneD, NekDouble> density;
172  for (i = 0; i < 3; ++i)
173  {
174  u[i] = Array<OneD, NekDouble>(nPoints);
175  }
176  fluidEqu->GetVelocity(physfields, u);
177 
178  for (i = 0; i < 3; ++i)
179  {
180  if (m_homogeneous && pFields[i]->GetWaveSpace())
181  {
182  pFields[i]->HomogeneousBwdTrans(nPoints, u[i], u[i]);
183  }
184 
185  Vmath::Vvtvp(nPoints, u[i], 1, u[i], 1, tmp, 1, tmp, 1);
186  }
187 
188  if (!fluidEqu->HasConstantDensity())
189  {
190  density = Array<OneD, NekDouble>(nPoints);
191  fluidEqu->GetDensity(physfields, density);
192  Vmath::Vmul(nPoints, density, 1, tmp, 1, tmp, 1);
193  }
194 
195  if (m_homogeneous)
196  {
197  Array<OneD, NekDouble> tmp2(nPoints, 0.0);
198  pFields[0]->HomogeneousFwdTrans(nPoints, tmp, tmp2);
199  Ek = pFields[0]->GetPlane(0)->Integral(tmp2) * m_homogeneousLength;
200  }
201  else
202  {
203  Ek = pFields[0]->Integral(tmp);
204  }
205 
206  Ek /= 2.0 * m_area;
207 
208  if (m_comm->GetRank() == 0)
209  {
210  m_outFile << setw(17) << setprecision(8) << time << setw(22)
211  << setprecision(11) << Ek;
212  }
213 
214  bool waveSpace[3] = {pFields[0]->GetWaveSpace(), pFields[1]->GetWaveSpace(),
215  pFields[2]->GetWaveSpace()};
216 
217  if (m_homogeneous)
218  {
219  for (i = 0; i < 3; ++i)
220  {
221  pFields[i]->SetWaveSpace(false);
222  }
223  }
224 
225  // First calculate vorticity field.
226  Array<OneD, NekDouble> tmp2(nPoints), tmp3(nPoints);
227  Vmath::Zero(nPoints, tmp, 1);
228  for (i = 0; i < 3; ++i)
229  {
230  int f1 = (i + 2) % 3, c2 = f1;
231  int c1 = (i + 1) % 3, f2 = c1;
232  pFields[f1]->PhysDeriv(c1, u[f1], tmp2);
233  pFields[f2]->PhysDeriv(c2, u[f2], tmp3);
234  Vmath::Vsub(nPoints, tmp2, 1, tmp3, 1, tmp2, 1);
235  Vmath::Vvtvp(nPoints, tmp2, 1, tmp2, 1, tmp, 1, tmp, 1);
236  }
237 
238  if (!fluidEqu->HasConstantDensity())
239  {
240  Vmath::Vmul(nPoints, density, 1, tmp, 1, tmp, 1);
241  }
242 
243  if (m_homogeneous)
244  {
245  for (i = 0; i < 3; ++i)
246  {
247  pFields[i]->SetWaveSpace(waveSpace[i]);
248  }
249  pFields[0]->HomogeneousFwdTrans(nPoints, tmp, tmp);
250  Ek = pFields[0]->GetPlane(0)->Integral(tmp) * m_homogeneousLength;
251  }
252  else
253  {
254  Ek = pFields[0]->Integral(tmp);
255  }
256 
257  Ek /= 2.0 * m_area;
258 
259  if (m_comm->GetRank() == 0)
260  {
261  m_outFile << setw(22) << setprecision(11) << Ek << endl;
262  }
263 }
264 
267  const NekDouble &time)
268 {
269  boost::ignore_unused(pFields, time);
270  m_outFile.close();
271 }
272 
274 {
275  return true;
276 }
277 
278 } // namespace SolverUtils
279 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
virtual SOLVER_UTILS_EXPORT void v_Initialise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pField, const NekDouble &time) override
virtual SOLVER_UTILS_EXPORT void v_Update(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pField, const NekDouble &time) override
virtual SOLVER_UTILS_EXPORT void v_Finalise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pField, const NekDouble &time) override
LibUtilities::CommSharedPtr m_comm
Definition: FilterEnergy.h:87
SOLVER_UTILS_EXPORT ~FilterEnergy()
Array< OneD, unsigned int > m_planes
Definition: FilterEnergy.h:88
virtual SOLVER_UTILS_EXPORT bool v_IsTimeDependent() override
LibUtilities::SessionReaderSharedPtr m_session
Definition: Filter.h:85
const std::weak_ptr< EquationSystem > m_equ
Definition: Filter.h:86
std::map< std::string, std::string > ParamMap
Definition: Filter.h:67
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
FilterFactory & GetFilterFactory()
Definition: Filter.cpp:41
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.cpp:209
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition: Vmath.cpp:574
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:492
void Vsub(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Subtract vector z = x-y.
Definition: Vmath.cpp:419