Nektar++
FilterModalEnergy.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File FilterModalEnergy.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 values of the modal energy
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 FilterModalEnergy::className = GetFilterFactory().
49  RegisterCreatorFunction("ModalEnergy", FilterModalEnergy::create);
50 
51 /**
52  * Constructor.
53  */
54 FilterModalEnergy::FilterModalEnergy(
56  const std::weak_ptr<EquationSystem> &pEquation,
57  const ParamMap &pParams) :
58  Filter(pSession, pEquation)
59 {
60  // OutputFile
61  auto it = pParams.find("OutputFile");
62  if (it == pParams.end())
63  {
64  m_outputFile = m_session->GetSessionName();
65  }
66  else
67  {
68  ASSERTL0(it->second.length() > 0, "Missing parameter 'OutputFile'.");
69  m_outputFile = it->second;
70  }
71  if (!(m_outputFile.length() >= 4
72  && m_outputFile.substr(m_outputFile.length() - 4) == ".mdl"))
73  {
74  m_outputFile += ".mdl";
75  }
76 
77  // OutputFrequency
78  it = pParams.find("OutputFrequency");
79  if (it == pParams.end())
80  {
82  }
83  else
84  {
86  m_session->GetInterpreter(), it->second);
87  m_outputFrequency = round(equ.Evaluate());
88  }
89 
90 
91  m_session->MatchSolverInfo("Homogeneous", "1D", m_isHomogeneous1D, false);
92  m_session->MatchSolverInfo("Homogeneous", "2D", m_isHomogeneous2D, false);
93  m_session->MatchSolverInfo("CalculatePerturbationEnergy", "True",
94  m_PertEnergy, false);
95  m_session->LoadParameter ("NumQuadPointsError", m_NumQuadPointsError, 0);
96  m_EqTypeStr = m_session->GetSolverInfo("EQTYPE");
97 
98  // OutputPlane
100  {
101  m_session->LoadParameter("LZ", m_LhomZ);
102 
103  it = pParams.find("OutputPlane");
104  if (it == pParams.end())
105  {
106  m_outputPlane = 0;
107  }
108  else
109  {
111  m_session->GetInterpreter(), it->second);
112  m_outputPlane = round(equ.Evaluate());
113  }
114  }
115 
117 }
118 
119 /**
120  * Destructor.
121  */
123 {
124 
125 }
126 
127 /**
128  * Initialize the parallel communication and the output stream.
129  */
132  const NekDouble &time)
133 {
134  LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
135 
136  if (vComm->GetRank() == 0)
137  {
138  // Open output stream
139  bool adaptive;
140  m_session->MatchSolverInfo("Driver", "Adaptive",
141  adaptive, false);
142  if (adaptive)
143  {
144  m_outputStream.open(m_outputFile.c_str(), ofstream::app);
145  }
146  else
147  {
148  m_outputStream.open(m_outputFile.c_str());
149  }
151  {
152  m_outputStream << "# Time, Fourier Mode, Energy ";
153  m_outputStream << endl;
154  }
155  else
156  {
157  m_outputStream << "# Time, Energy ";
158  m_outputStream << endl;
159  }
160 
161  }
162 
163  m_index = 0;
164  v_Update(pFields, time);
165 }
166 
167 
168 /**
169  * Update the modal energy every m_outputFrequency.
170  */
173  const NekDouble &time)
174 {
175  // Only output every m_outputFrequency
176  if ((m_index++) % m_outputFrequency)
177  {
178  return;
179  }
180 
181  LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
182 
183  // Homogeneous 1D implementation
184  if (m_isHomogeneous1D)
185  {
186  int colrank = vComm->GetColumnComm()->GetRank();
187  int nproc = vComm->GetColumnComm()->GetSize();
188  m_npointsZ = (m_session->GetParameter("HomModesZ"));
189  int locsize = m_npointsZ/nproc/2;
190 
191  Array<OneD, NekDouble> energy (locsize, 0.0);
192  Array<OneD, NekDouble> energy_tmp(locsize, 0.0);
194 
195  // Calculate the energy of the perturbation for stability
196  // analysis
197  if (m_PertEnergy)
198  {
199  // Compressible Flow Solver
200  if (m_EqTypeStr=="EulerCFE" ||
201  m_EqTypeStr=="EulerADCFE" ||
202  m_EqTypeStr=="NavierStokesCFE")
203  {
204  ASSERTL0(false, "Stability analysis module not "
205  "implemented for the Compressible Flow "
206  "Solver. Please remove the function BaseFlow "
207  "from your .xml file");
208  }
209  // Incompressible Navier-Stokes Solver
210  else
211  {
214  SetUpBaseFields(graphShrPtr);
215  string file = m_session->
216  GetFunctionFilename("BaseFlow", 0);
217  ImportFldBase(file);
218 
219  for (int i = 0; i < pFields.size()-1; ++i)
220  {
221  Vmath::Vsub(pFields[i]->GetNcoeffs(),
222  pFields[i]->GetCoeffs(), 1,
223  m_base [i]->GetCoeffs(), 1,
224  pFields[i]->UpdateCoeffs(), 1);
225 
226  energy_tmp = pFields[i]->HomogeneousEnergy();
227  Vmath::Vadd(locsize, energy_tmp, 1,
228  energy, 1, energy, 1);
229 
230  Vmath::Vadd(pFields[i]->GetNcoeffs(),
231  pFields[i]->GetCoeffs(), 1,
232  m_base[i]->GetCoeffs(), 1,
233  pFields[i]->UpdateCoeffs(), 1);
234  }
235  }
236  }
237  // Calculate the modal energy for general simulation
238  else
239  {
240  // Compressible Flow Solver
241  if (m_EqTypeStr=="EulerCFE" ||
242  m_EqTypeStr=="EulerADCFE" ||
243  m_EqTypeStr=="NavierStokesCFE")
244  {
245  // Extracting kinetic energy
246  for (int i = 1; i < pFields.size()-1; ++i)
247  {
248  energy_tmp = pFields[i]->HomogeneousEnergy();
249  Vmath::Vadd(locsize, energy_tmp, 1,
250  energy, 1, energy, 1);
251  }
252  }
253  // Incompressible Navier-Stokes Solver
254  else
255  {
256  // Extracting kinetic energy
257  for (int i = 0; i < pFields.size()-1; ++i)
258  {
259  energy_tmp = pFields[i]->HomogeneousEnergy();
260  Vmath::Vadd(locsize, energy_tmp, 1,
261  energy, 1, energy, 1);
262  }
263  }
264  }
265 
266  // Send to root process
267  if (colrank == 0)
268  {
269  int j, m = 0;
270 
271  for (j = 0; j < energy.size(); ++j, ++m)
272  {
273  m_outputStream << setw(10) << time
274  << setw(5) << m
275  << setw(18) << energy[j] << endl;
276  }
277 
278  for (int i = 1; i < nproc; ++i)
279  {
280  vComm->GetColumnComm()->Recv(i, energy);
281 
282  for (j = 0; j < energy.size(); ++j, ++m)
283  {
284  m_outputStream << setw(10) << time
285  << setw(5) << m
286  << setw(18) << energy[j] << endl;
287  }
288  }
289  }
290  else
291  {
292  vComm->GetColumnComm()->Send(0, energy);
293  }
294  }
295  // Homogeneous 2D implementation
296  else if (m_isHomogeneous2D)
297  {
298  ASSERTL0(false, "3D Homogeneous 2D energy "
299  "dumping not implemented yet");
300  }
301  // General implementation
302  else
303  {
304  // Compressible Flow Solver
305  if (m_EqTypeStr=="EulerCFE" ||
306  m_EqTypeStr=="EulerADCFE" ||
307  m_EqTypeStr=="NavierStokesCFE")
308  {
309  // Total energy
310  NekDouble energy = 0.0;
311  for (int i = 1; i < pFields.size()-1; ++i)
312  {
313  pFields[i]->SetPhysState(true);
314  NekDouble norm = L2Error(pFields, i, time);
315  energy += norm * norm;
316  }
317 
318  m_outputStream << setprecision(6) << time;
319  m_outputStream.width(25);
320  m_outputStream << setprecision(8) << 0.5*energy;
321  m_outputStream << endl;
322  }
323  // Incompressible Navier-Stokes Solver
324  else
325  {
326  // Kinetic energy
327  NekDouble energy = 0.0;
328  for (int i = 0; i < pFields.size()-1; ++i)
329  {
330  pFields[i]->SetPhysState(true);
331  NekDouble norm = L2Error(pFields, i, time);
332  energy += norm * norm;
333  }
334  m_outputStream << setprecision(6) << time;
335  m_outputStream.width(25);
336  m_outputStream << setprecision(8) << 0.5*energy;
337  m_outputStream << endl;
338  }
339  }
340 }
341 
342 /**
343  * Close the output stream.
344  */
347  const NekDouble &time)
348 {
349  boost::ignore_unused(time);
350 
351  if (pFields[0]->GetComm()->GetRank() == 0)
352  {
353  m_outputStream.close();
354  }
355 }
356 
357 /**
358  * Calculate the L2 norm of a given field for calculating the
359  * modal energy.
360  */
363  unsigned int field,
364  const NekDouble &time)
365 {
366  boost::ignore_unused(time);
367 
368  NekDouble L2error = -1.0;
369  LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
370 
371  if (m_NumQuadPointsError == 0)
372  {
373  if (pFields[field]->GetPhysState() == false)
374  {
375  pFields[field]->BwdTrans(pFields[field]->GetCoeffs(),
376  pFields[field]->UpdatePhys());
377  }
378  }
379 
380  L2error = pFields[field]->L2(pFields[field]->GetPhys());
381  return L2error;
382 }
383 
384 /**
385  * Setup the base fields in case of stability analyses.
386  */
389 {
390  int i;
391  int m_expdim = graphShrPtr->GetMeshDimension();
392 
393  //definition of the projection tipe:
394  if(m_session->DefinesSolverInfo("PROJECTION"))
395  {
396  std::string ProjectStr = m_session->GetSolverInfo("PROJECTION");
397 
398  if ((ProjectStr == "Continuous") ||
399  (ProjectStr == "Galerkin") ||
400  (ProjectStr == "CONTINUOUS") ||
401  (ProjectStr == "GALERKIN"))
402  {
404  }
405  else if ((ProjectStr == "MixedCGDG") ||
406  (ProjectStr == "Mixed_CG_Discontinuous"))
407  {
409  }
410  else if(ProjectStr == "DisContinuous")
411  {
413  }
414  else
415  {
416  ASSERTL0(false, "PROJECTION value not recognised");
417  }
418  }
419  else
420  {
421  cerr << "Projection type not specified in SOLVERINFO,"
422  "defaulting to continuous Galerkin" << endl;
424  }
425 
426  if (m_session->DefinesSolverInfo("ModeType"))
427  {
428  m_session->MatchSolverInfo("ModeType", "SingleMode",
429  m_SingleMode, false);
430  m_session->MatchSolverInfo("ModeType", "HalfMode",
431  m_HalfMode, false);
432  m_session->MatchSolverInfo("ModeType", "MultipleModes",
433  m_MultipleModes, false);
434  }
435 
436  m_session->MatchSolverInfo("USEFFT","FFTW", m_useFFT, false);
437  m_session->MatchSolverInfo("DEALIASING", "True",
438  m_homogen_dealiasing, false);
439 
440  // Stability Analysis flags
441  if (m_session->DefinesSolverInfo("ModeType"))
442  {
443  if (m_SingleMode)
444  {
445  m_npointsZ = 2;
446  }
447  else if (m_HalfMode)
448  {
449  m_npointsZ = 1;
450  }
451  else if (m_MultipleModes)
452  {
453  m_npointsZ = m_session->GetParameter("HomModesZ");
454  }
455  else
456  {
457  ASSERTL0(false, "SolverInfo ModeType not valid");
458  }
459  }
460  else
461  {
462  m_npointsZ = m_session->GetParameter("HomModesZ");
463  }
464 
467  {
468  switch (m_expdim)
469  {
470  case 1:
471  {
472  for(i = 0; i < m_base.size(); i++)
473  {
475  ::AllocateSharedPtr(m_session, graphShrPtr,
476  m_session->GetVariable(0));
477  }
478  }
479  break;
480  case 2:
481  {
482  if (m_isHomogeneous1D)
483  {
484  if (m_SingleMode)
485  {
486  const LibUtilities::PointsKey PkeyZ(
487  m_npointsZ,
489  const LibUtilities::BasisKey BkeyZ(
491  m_npointsZ, PkeyZ);
492 
493  for (i = 0 ; i < m_base.size(); i++)
494  {
495  m_base[i] = MemoryManager<MultiRegions::
496  ContField3DHomogeneous1D>::
497  AllocateSharedPtr(
498  m_session, BkeyZ, m_LhomZ,
500  graphShrPtr,
501  m_session->GetVariable(i));
502 
503  m_base[i]->SetWaveSpace(true);
504  }
505  }
506  else if (m_HalfMode)
507  {
508  //1 plane field (half mode expansion)
509  const LibUtilities::PointsKey PkeyZ(
510  m_npointsZ,
512  const LibUtilities::BasisKey BkeyZ(
514  m_npointsZ,PkeyZ);
515 
516  for (i = 0 ; i < m_base.size(); i++)
517  {
518  m_base[i] = MemoryManager<MultiRegions::
519  ContField3DHomogeneous1D>::
520  AllocateSharedPtr(
521  m_session, BkeyZ, m_LhomZ,
523  graphShrPtr,
524  m_session->GetVariable(i));
525 
526  m_base[i]->SetWaveSpace(true);
527  }
528  }
529  else
530  {
531  const LibUtilities::PointsKey PkeyZ(
532  m_npointsZ,
534  const LibUtilities::BasisKey BkeyZ(
536 
537  for (i = 0 ; i < m_base.size(); i++)
538  {
539  m_base[i] = MemoryManager<MultiRegions::
540  ContField3DHomogeneous1D>::
541  AllocateSharedPtr(
542  m_session, BkeyZ, m_LhomZ,
544  graphShrPtr,
545  m_session->GetVariable(i));
546 
547  m_base[i]->SetWaveSpace(false);
548  }
549  }
550  }
551  else
552  {
553  i = 0;
557  m_session,graphShrPtr,
558  m_session->GetVariable(i));
559 
560  m_base[0] = firstbase;
561 
562  for (i = 1 ; i < m_base.size(); i++)
563  {
564  m_base[i] = MemoryManager<MultiRegions::
565  ContField>::AllocateSharedPtr(
566  *firstbase, graphShrPtr,
567  m_session->GetVariable(i));
568  }
569  }
570  }
571  break;
572  case 3:
573  {
576  AllocateSharedPtr(m_session, graphShrPtr,
577  m_session->GetVariable(0));
578  m_base[0] = firstbase;
579  for (i = 1 ; i < m_base.size(); i++)
580  {
581  m_base[i] = MemoryManager<MultiRegions::
582  ContField>::AllocateSharedPtr(
583  *firstbase, graphShrPtr,
584  m_session->GetVariable(0));
585  }
586  }
587  break;
588  default:
590  "Expansion dimension not recognised");
591  break;
592  }
593  }
594  else
595  {
596  switch (m_expdim)
597  {
598  case 1:
599  {
600  // need to use zero for variable as may be more base
601  // flows than variables
602  for (i = 0 ; i < m_base.size(); i++)
603  {
604  m_base[i] = MemoryManager<MultiRegions::
605  DisContField>::AllocateSharedPtr(
606  m_session, graphShrPtr,
607  m_session->GetVariable(0));
608  }
609  break;
610  }
611  case 2:
612  {
613  for (i = 0 ; i < m_base.size(); i++)
614  {
615  m_base[i] = MemoryManager<MultiRegions::
616  DisContField>::AllocateSharedPtr(
617  m_session, graphShrPtr,
618  m_session->GetVariable(0));
619  }
620  break;
621  }
622  case 3:
623  NEKERROR(ErrorUtil::efatal, "3D not set up");
624  break;
625  default:
627  "Expansion dimension not recognised");
628  break;
629  }
630  }
631 }
632 
633 /**
634  * Import the base flow fld file.
635  */
637  std::string pInfile)
638 {
639  std::vector<LibUtilities::FieldDefinitionsSharedPtr> FieldDef;
640  std::vector<std::vector<NekDouble> > FieldData;
641 
642  // Get Homogeneous
643  m_fld->Import(pInfile,FieldDef,FieldData);
644 
645  int nvar = m_session->GetVariables().size();
646  if(m_session->DefinesSolverInfo("HOMOGENEOUS"))
647  {
648  std::string HomoStr = m_session->GetSolverInfo("HOMOGENEOUS");
649  }
650  // Copy FieldData into m_fields
651  for (int j = 0; j < nvar; ++j)
652  {
653  for (int i = 0; i < FieldDef.size(); ++i)
654  {
655  bool flag =
656  FieldDef[i]->m_fields[j] == m_session->GetVariable(j);
657 
658  ASSERTL0(flag, (std::string("Order of ") + pInfile
659  + std::string(" data and that defined in "
660  "m_boundaryconditions differs")).c_str());
661 
662  m_base[j]->ExtractDataToCoeffs(FieldDef[i], FieldData[i],
663  FieldDef[i]->m_fields[j],
664  m_base[j]->UpdateCoeffs());
665  }
666  }
667 }
668 
669 /**
670  * Flag for time-dependent flows.
671  */
673 {
674  return true;
675 }
676 }
677 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
Describes the specification for a Basis.
Definition: Basis.h:50
NekDouble Evaluate() const
Definition: Equation.cpp:95
static std::shared_ptr< FieldIO > CreateDefault(const LibUtilities::SessionReaderSharedPtr session)
Returns an object for the default FieldIO method.
Definition: FieldIO.cpp:195
Defines a specification for a set of points.
Definition: Points.h:60
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
LibUtilities::SessionReaderSharedPtr m_session
Definition: Filter.h:86
std::map< std::string, std::string > ParamMap
Definition: Filter.h:68
enum MultiRegions::ProjectionType m_projectionType
virtual void v_Finalise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
LibUtilities::FieldIOSharedPtr m_fld
virtual void v_Initialise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
NekDouble L2Error(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, unsigned int field, const NekDouble &time)
virtual void v_Update(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
Array< OneD, MultiRegions::ExpListSharedPtr > m_base
virtual SOLVER_UTILS_EXPORT ~FilterModalEnergy()
void SetUpBaseFields(SpatialDomains::MeshGraphSharedPtr &mesh)
static MeshGraphSharedPtr Read(const LibUtilities::SessionReaderSharedPtr pSession, LibUtilities::DomainRangeShPtr rng=LibUtilities::NullDomainRangeShPtr, bool fillGraph=true)
Definition: MeshGraph.cpp:113
std::shared_ptr< SessionReader > SessionReaderSharedPtr
@ eFourierEvenlySpaced
1D Evenly-spaced points using Fourier Fit
Definition: PointsType.h:65
@ eFourierSingleModeSpaced
1D Non Evenly-spaced points for Single Mode analysis
Definition: PointsType.h:66
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:54
@ eFourierHalfModeRe
Fourier Modified expansions with just the real part of the first mode
Definition: BasisType.h:60
@ eFourier
Fourier Expansion .
Definition: BasisType.h:53
std::shared_ptr< ContField > ContFieldSharedPtr
Definition: ContField.h:292
FilterFactory & GetFilterFactory()
Definition: Filter.cpp:41
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:174
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
double NekDouble
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition: Vmath.cpp:322
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:372