Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Output values of the modal energy
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #include <iomanip>
37 
40 
41 using namespace std;
42 
43 namespace Nektar
44 {
45 namespace SolverUtils
46 {
47 std::string FilterModalEnergy::className = GetFilterFactory().
48  RegisterCreatorFunction("ModalEnergy", FilterModalEnergy::create);
49 
50 /**
51  * Constructor.
52  */
53 FilterModalEnergy::FilterModalEnergy(
55  const ParamMap &pParams) :
56  Filter(pSession)
57 {
58  ParamMap::const_iterator it;
59 
60  // OutputFile
61  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  {
85  LibUtilities::Equation equ(m_session, it->second);
86  m_outputFrequency = round(equ.Evaluate());
87  }
88 
89 
90  m_session->MatchSolverInfo("Homogeneous", "1D", m_isHomogeneous1D, false);
91  m_session->MatchSolverInfo("Homogeneous", "2D", m_isHomogeneous2D, false);
92  m_session->MatchSolverInfo("CalculatePerturbationEnergy", "True",
93  m_PertEnergy, false);
94  m_session->LoadParameter ("NumQuadPointsError", m_NumQuadPointsError, 0);
95  m_EqTypeStr = m_session->GetSolverInfo("EQTYPE");
96 
97  // OutputPlane
99  {
100  m_session->LoadParameter("LZ", m_LhomZ);
101 
102  it = pParams.find("OutputPlane");
103  if (it == pParams.end())
104  {
105  m_outputPlane = 0;
106  }
107  else
108  {
109  LibUtilities::Equation equ(m_session, it->second);
110  m_outputPlane = round(equ.Evaluate());
111  }
112  }
113 
115 }
116 
117 /**
118  * Destructor.
119  */
121 {
122 
123 }
124 
125 /**
126  * Initialize the parallel communication and the output stream.
127  */
130  const NekDouble &time)
131 {
132  LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
133 
134  if (vComm->GetRank() == 0)
135  {
136  // Open output stream
137  bool adaptive;
138  m_session->MatchSolverInfo("Driver", "Adaptive",
139  adaptive, false);
140  if (adaptive)
141  {
142  m_outputStream.open(m_outputFile.c_str(), ofstream::app);
143  }
144  else
145  {
146  m_outputStream.open(m_outputFile.c_str());
147  }
149  {
150  m_outputStream << "# Time, Fourier Mode, Energy ";
151  m_outputStream << endl;
152  }
153  else
154  {
155  m_outputStream << "# Time, Energy ";
156  m_outputStream << endl;
157  }
158 
159  }
160 
161  m_index = 0;
162  v_Update(pFields, time);
163 }
164 
165 
166 /**
167  * Update the modal energy every m_outputFrequency.
168  */
171  const NekDouble &time)
172 {
173  // Only output every m_outputFrequency
174  if ((m_index++) % m_outputFrequency)
175  {
176  return;
177  }
178 
179  LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
180 
181  // Homogeneous 1D implementation
182  if (m_isHomogeneous1D)
183  {
184  int colrank = vComm->GetColumnComm()->GetRank();
185  int nproc = vComm->GetColumnComm()->GetSize();
186  m_npointsZ = (m_session->GetParameter("HomModesZ"));
187  int locsize = m_npointsZ/nproc/2;
188 
189  Array<OneD, NekDouble> energy (locsize, 0.0);
190  Array<OneD, NekDouble> energy_tmp(locsize, 0.0);
192 
193  // Calculate the energy of the perturbation for stability
194  // analysis
195  if (m_PertEnergy)
196  {
197  // Compressible Flow Solver
198  if (m_EqTypeStr=="EulerCFE" ||
199  m_EqTypeStr=="EulerADCFE" ||
200  m_EqTypeStr=="NavierStokesCFE")
201  {
202  ASSERTL0(false, "Stability analysis module not "
203  "implemented for the Compressible Flow "
204  "Solver. Please remove the function BaseFlow "
205  "from your .xml file");
206  }
207  // Incompressible Navier-Stokes Solver
208  else
209  {
212  SetUpBaseFields(graphShrPtr);
213  string file = m_session->
214  GetFunctionFilename("BaseFlow", 0);
215  ImportFldBase(file, graphShrPtr);
216 
217  for (int i = 0; i < pFields.num_elements()-1; ++i)
218  {
219  Vmath::Vsub(pFields[i]->GetNcoeffs(),
220  pFields[i]->GetCoeffs(), 1,
221  m_base [i]->GetCoeffs(), 1,
222  pFields[i]->UpdateCoeffs(), 1);
223 
224  energy_tmp = pFields[i]->HomogeneousEnergy();
225  Vmath::Vadd(locsize, energy_tmp, 1,
226  energy, 1, energy, 1);
227 
228  Vmath::Vadd(pFields[i]->GetNcoeffs(),
229  pFields[i]->GetCoeffs(), 1,
230  m_base[i]->GetCoeffs(), 1,
231  pFields[i]->UpdateCoeffs(), 1);
232  }
233  }
234  }
235  // Calculate the modal energy for general simulation
236  else
237  {
238  // Compressible Flow Solver
239  if (m_EqTypeStr=="EulerCFE" ||
240  m_EqTypeStr=="EulerADCFE" ||
241  m_EqTypeStr=="NavierStokesCFE")
242  {
243  // Extracting kinetic energy
244  for (int i = 1; i < pFields.num_elements()-1; ++i)
245  {
246  energy_tmp = pFields[i]->HomogeneousEnergy();
247  Vmath::Vadd(locsize, energy_tmp, 1,
248  energy, 1, energy, 1);
249  }
250  }
251  // Incompressible Navier-Stokes Solver
252  else
253  {
254  // Extracting kinetic energy
255  for (int i = 0; i < pFields.num_elements()-1; ++i)
256  {
257  energy_tmp = pFields[i]->HomogeneousEnergy();
258  Vmath::Vadd(locsize, energy_tmp, 1,
259  energy, 1, energy, 1);
260  }
261  }
262  }
263 
264  // Send to root process
265  if (colrank == 0)
266  {
267  int j, m = 0;
268 
269  for (j = 0; j < energy.num_elements(); ++j, ++m)
270  {
271  m_outputStream << setw(10) << time
272  << setw(5) << m
273  << setw(18) << energy[j] << endl;
274  }
275 
276  for (int i = 1; i < nproc; ++i)
277  {
278  vComm->GetColumnComm()->Recv(i, energy);
279 
280  for (j = 0; j < energy.num_elements(); ++j, ++m)
281  {
282  m_outputStream << setw(10) << time
283  << setw(5) << m
284  << setw(18) << energy[j] << endl;
285  }
286  }
287  }
288  else
289  {
290  vComm->GetColumnComm()->Send(0, energy);
291  }
292  }
293  // Homogeneous 2D implementation
294  else if (m_isHomogeneous2D)
295  {
296  ASSERTL0(false, "3D Homogeneous 2D energy "
297  "dumping not implemented yet");
298  }
299  // General implementation
300  else
301  {
302  // Compressible Flow Solver
303  if (m_EqTypeStr=="EulerCFE" ||
304  m_EqTypeStr=="EulerADCFE" ||
305  m_EqTypeStr=="NavierStokesCFE")
306  {
307  // Total energy
308  NekDouble energy = 0.0;
309  for (int i = 1; i < pFields.num_elements()-1; ++i)
310  {
311  pFields[i]->SetPhysState(true);
312  NekDouble norm = L2Error(pFields, i, time);
313  energy += norm * norm;
314  }
315 
316  m_outputStream << setprecision(6) << time;
317  m_outputStream.width(25);
318  m_outputStream << setprecision(8) << 0.5*energy;
319  m_outputStream << endl;
320  }
321  // Incompressible Navier-Stokes Solver
322  else
323  {
324  // Kinetic energy
325  NekDouble energy = 0.0;
326  for (int i = 0; i < pFields.num_elements()-1; ++i)
327  {
328  pFields[i]->SetPhysState(true);
329  NekDouble norm = L2Error(pFields, i, time);
330  energy += norm * norm;
331  }
332  m_outputStream << setprecision(6) << time;
333  m_outputStream.width(25);
334  m_outputStream << setprecision(8) << 0.5*energy;
335  m_outputStream << endl;
336  }
337  }
338 }
339 
340 /**
341  * Close the output stream.
342  */
345  const NekDouble &time)
346 {
347  if (pFields[0]->GetComm()->GetRank() == 0)
348  {
349  m_outputStream.close();
350  }
351 }
352 
353 /**
354  * Calculate the L2 norm of a given field for calculating the
355  * modal energy.
356  */
359  unsigned int field,
360  const NekDouble &time)
361 {
362  NekDouble L2error = -1.0;
363  LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
364 
365  if (m_NumQuadPointsError == 0)
366  {
367  if (pFields[field]->GetPhysState() == false)
368  {
369  pFields[field]->BwdTrans(pFields[field]->GetCoeffs(),
370  pFields[field]->UpdatePhys());
371  }
372  }
373 
374  L2error = pFields[field]->L2(pFields[field]->GetPhys());
375  return L2error;
376 }
377 
378 /**
379  * Setup the base fields in case of stability analyses.
380  */
383 {
384  int i;
385  int m_expdim = graphShrPtr->GetMeshDimension();
386 
387  //definition of the projection tipe:
388  if(m_session->DefinesSolverInfo("PROJECTION"))
389  {
390  std::string ProjectStr = m_session->GetSolverInfo("PROJECTION");
391 
392  if ((ProjectStr == "Continuous") ||
393  (ProjectStr == "Galerkin") ||
394  (ProjectStr == "CONTINUOUS") ||
395  (ProjectStr == "GALERKIN"))
396  {
398  }
399  else if ((ProjectStr == "MixedCGDG") ||
400  (ProjectStr == "Mixed_CG_Discontinuous"))
401  {
403  }
404  else if(ProjectStr == "DisContinuous")
405  {
407  }
408  else
409  {
410  ASSERTL0(false, "PROJECTION value not recognised");
411  }
412  }
413  else
414  {
415  cerr << "Projection type not specified in SOLVERINFO,"
416  "defaulting to continuous Galerkin" << endl;
418  }
419 
420  if (m_session->DefinesSolverInfo("ModeType"))
421  {
422  m_session->MatchSolverInfo("ModeType", "SingleMode",
423  m_SingleMode, false);
424  m_session->MatchSolverInfo("ModeType", "HalfMode",
425  m_HalfMode, false);
426  m_session->MatchSolverInfo("ModeType", "MultipleModes",
427  m_MultipleModes, false);
428  }
429 
430  m_session->MatchSolverInfo("USEFFT","FFTW", m_useFFT, false);
431  m_session->MatchSolverInfo("DEALIASING", "True",
432  m_homogen_dealiasing, false);
433 
434  if (m_homogen_dealiasing == false)
435  {
436  m_session->MatchSolverInfo("DEALIASING", "On",
437  m_homogen_dealiasing, false);
438  }
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.num_elements(); 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.num_elements(); i++)
494  {
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.num_elements(); i++)
517  {
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.num_elements(); i++)
538  {
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.num_elements(); i++)
563  {
564  m_base[i] = MemoryManager<MultiRegions::
565  ContField2D>::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.num_elements(); i++)
580  {
581  m_base[i] = MemoryManager<MultiRegions::
582  ContField3D>::AllocateSharedPtr(
583  *firstbase, graphShrPtr,
584  m_session->GetVariable(0));
585  }
586  }
587  break;
588  default:
589  ASSERTL0(false, "Expansion dimension not recognised");
590  break;
591  }
592  }
593  else
594  {
595  switch (m_expdim)
596  {
597  case 1:
598  {
599  // need to use zero for variable as may be more base
600  // flows than variables
601  for (i = 0 ; i < m_base.num_elements(); i++)
602  {
604  DisContField1D>::AllocateSharedPtr(
605  m_session, graphShrPtr,
606  m_session->GetVariable(0));
607  }
608  break;
609  }
610  case 2:
611  {
612  for (i = 0 ; i < m_base.num_elements(); i++)
613  {
615  DisContField2D>::AllocateSharedPtr(
616  m_session, graphShrPtr,
617  m_session->GetVariable(0));
618  }
619  break;
620  }
621  case 3:
622  ASSERTL0(false, "3D not set up");
623  default:
624  ASSERTL0(false, "Expansion dimension not recognised");
625  break;
626  }
627  }
628 }
629 
630 /**
631  * Import the base flow fld file.
632  */
634  std::string pInfile,
636 {
637  std::vector<LibUtilities::FieldDefinitionsSharedPtr> FieldDef;
638  std::vector<std::vector<NekDouble> > FieldData;
639 
640  // Get Homogeneous
641  m_fld->Import(pInfile,FieldDef,FieldData);
642 
643  int nvar = m_session->GetVariables().size();
644  if(m_session->DefinesSolverInfo("HOMOGENEOUS"))
645  {
646  std::string HomoStr = m_session->GetSolverInfo("HOMOGENEOUS");
647  }
648  // Copy FieldData into m_fields
649  for (int j = 0; j < nvar; ++j)
650  {
651  for (int i = 0; i < FieldDef.size(); ++i)
652  {
653  bool flag =
654  FieldDef[i]->m_fields[j] == m_session->GetVariable(j);
655 
656  ASSERTL0(flag, (std::string("Order of ") + pInfile
657  + std::string(" data and that defined in "
658  "m_boundaryconditions differs")).c_str());
659 
660  m_base[j]->ExtractDataToCoeffs(FieldDef[i], FieldData[i],
661  FieldDef[i]->m_fields[j],
662  m_base[j]->UpdateCoeffs());
663  }
664  }
665 }
666 
667 /**
668  * Flag for time-dependent flows.
669  */
671 {
672  return true;
673 }
674 }
675 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:198
enum MultiRegions::ProjectionType m_projectionType
static boost::shared_ptr< MeshGraph > Read(const LibUtilities::SessionReaderSharedPtr &pSession, DomainRangeShPtr &rng=NullDomainRangeShPtr)
Definition: MeshGraph.cpp:124
static boost::shared_ptr< DataType > AllocateSharedPtr()
Allocate a shared pointer from the memory pool.
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
virtual void v_Initialise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
virtual void v_Finalise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
STL namespace.
boost::shared_ptr< ContField2D > ContField2DSharedPtr
Definition: ContField2D.h:289
Array< OneD, MultiRegions::ExpListSharedPtr > m_base
Fourier Expansion .
Definition: BasisType.h:52
boost::shared_ptr< SessionReader > SessionReaderSharedPtr
Definition: MeshPartition.h:51
LibUtilities::FieldIOSharedPtr m_fld
boost::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:55
1D Evenly-spaced points using Fourier Fit
Definition: PointsType.h:66
Fourier Modified expansions with just the real part of the first mode .
Definition: BasisType.h:59
This class is the abstraction of a global continuous two- dimensional spectral/hp element expansion w...
Definition: ContField2D.h:56
void SetUpBaseFields(SpatialDomains::MeshGraphSharedPtr &mesh)
NekDouble Evaluate() const
Definition: Equation.h:102
This class is the abstraction of a global discontinuous two- dimensional spectral/hp element expansio...
Defines a specification for a set of points.
Definition: Points.h:58
double NekDouble
void ImportFldBase(std::string pInfile, SpatialDomains::MeshGraphSharedPtr pGraph)
std::map< std::string, std::string > ParamMap
Definition: Filter.h:67
LibUtilities::SessionReaderSharedPtr m_session
Definition: Filter.h:84
NekDouble L2Error(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, unsigned int field, const NekDouble &time)
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:343
static boost::shared_ptr< FieldIO > CreateDefault(const LibUtilities::SessionReaderSharedPtr session)
Returns an object for the default FieldIO method.
Definition: FieldIO.cpp:181
virtual void v_Update(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
1D Non Evenly-spaced points for Single Mode analysis
Definition: PointsType.h:67
FilterFactory & GetFilterFactory()
Definition: Filter.cpp:42
virtual SOLVER_UTILS_EXPORT ~FilterModalEnergy()
boost::shared_ptr< ContField3D > ContField3DSharedPtr
Definition: ContField3D.h:208
boost::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:442
Describes the specification for a Basis.
Definition: Basis.h:50
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:299