Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
FilterFieldConvert.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File FilterFieldConvert.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: Base clase for filters performing operations on samples
33 // of the field.
34 //
35 ///////////////////////////////////////////////////////////////////////////////
36 
38 #include <boost/program_options.hpp>
39 
40 namespace Nektar
41 {
42 namespace SolverUtils
43 {
46  "FieldConvert", FilterFieldConvert::create);
47 
50  const ParamMap &pParams)
51  : Filter(pSession)
52 {
53  ParamMap::const_iterator it;
54 
55  // OutputFile
56  it = pParams.find("OutputFile");
57  if (it == pParams.end())
58  {
59  std::stringstream outname;
60  outname << m_session->GetSessionName() << ".fld";
61  m_outputFile = outname.str();
62  }
63  else
64  {
65  ASSERTL0(it->second.length() > 0, "Missing parameter 'OutputFile'.");
66  if ( it->second.find_last_of('.') != string::npos)
67  {
68  m_outputFile = it->second;
69  }
70  else
71  {
72  std::stringstream outname;
73  outname << it->second << ".fld";
74  m_outputFile = outname.str();
75  }
76  }
77 
78  // Restart file
79  it = pParams.find("RestartFile");
80  if (it == pParams.end())
81  {
82  m_restartFile = "";
83  }
84  else
85  {
86  ASSERTL0(it->second.length() > 0, "Missing parameter 'RestartFile'.");
87  if ( it->second.find_last_of('.') != string::npos)
88  {
89  m_restartFile = it->second;
90  }
91  else
92  {
93  std::stringstream outname;
94  outname << it->second << ".fld";
95  m_restartFile = outname.str();
96  }
97  }
98 
99  // SampleFrequency
100  it = pParams.find("SampleFrequency");
101  if (it == pParams.end())
102  {
103  m_sampleFrequency = 1;
104  }
105  else
106  {
107  LibUtilities::Equation equ(m_session, it->second);
108  m_sampleFrequency = floor(equ.Evaluate());
109  }
110 
111  // OutputFrequency
112  it = pParams.find("OutputFrequency");
113  if (it == pParams.end())
114  {
115  m_outputFrequency = m_session->GetParameter("NumSteps");
116  }
117  else
118  {
119  LibUtilities::Equation equ(m_session, it->second);
120  m_outputFrequency = floor(equ.Evaluate());
121  }
122 
123  m_numSamples = 0;
124  m_index = 0;
125  m_outputIndex = 0;
126 
127  //
128  // FieldConvert modules
129  //
130  m_f = boost::shared_ptr<Field>(new Field());
131  vector<string> modcmds;
132  // Process modules
133  std::stringstream moduleStream;
134  it = pParams.find("Modules");
135  if (it != pParams.end())
136  {
137  moduleStream.str(it->second);
138  }
139  while (!moduleStream.fail())
140  {
141  std::string sMod;
142  moduleStream >> sMod;
143  if (!moduleStream.fail())
144  {
145  modcmds.push_back(sMod);
146  }
147  }
148  // Output module
149  modcmds.push_back(m_outputFile);
150  // Create modules
151  CreateModules(modcmds);
152 }
153 
155 {
156 }
157 
160  const NekDouble &time)
161 {
162  v_FillVariablesName(pFields);
163 
164  int ncoeff = pFields[0]->GetNcoeffs();
165  // m_variables need to be filled by a derived class
166  m_outFields.resize(m_variables.size());
167 
168  for (int n = 0; n < m_variables.size(); ++n)
169  {
170  m_outFields[n] = Array<OneD, NekDouble>(ncoeff, 0.0);
171  }
172 
173  m_fieldMetaData["InitialTime"] = boost::lexical_cast<std::string>(time);
174 
175  // Fill some parameters of m_f
176  m_f->m_session = m_session;
177  m_f->m_graph = pFields[0]->GetGraph();
178  m_f->m_comm = m_f->m_session->GetComm();
179 
180  // Load restart file if necessary
181  if (m_restartFile != "")
182  {
183  // Load file
184  std::vector<LibUtilities::FieldDefinitionsSharedPtr> fieldDef;
185  std::vector<std::vector<NekDouble> > fieldData;
186  LibUtilities::FieldMetaDataMap fieldMetaData;
189  fld->Import(m_restartFile, fieldDef, fieldData, fieldMetaData);
190 
191  // Extract fields to output
192  for (int j = 0; j < m_variables.size(); ++j)
193  {
194  for (int i = 0; i < fieldData.size(); ++i)
195  {
196  pFields[0]->ExtractDataToCoeffs(
197  fieldDef[i],
198  fieldData[i],
199  m_variables[j],
200  m_outFields[j]);
201  }
202  }
203 
204  // Load information for numSamples
205  if (fieldMetaData.count("NumberOfFieldDumps"))
206  {
207  m_numSamples = atoi(fieldMetaData["NumberOfFieldDumps"].c_str());
208  }
209  else
210  {
211  m_numSamples = 1;
212  }
213 
214  // Divide by scale
215  NekDouble scale = v_GetScale();
216  for (int n = 0; n < m_outFields.size(); ++n)
217  {
218  Vmath::Smul(m_outFields[n].num_elements(),
219  1.0/scale,
220  m_outFields[n],
221  1,
222  m_outFields[n],
223  1);
224  }
225  }
226 }
227 
230 {
231  int nfield = pFields.num_elements();
232  m_variables.resize(pFields.num_elements());
233  for (int n = 0; n < nfield; ++n)
234  {
235  m_variables[n] = pFields[n]->GetSession()->GetVariable(n);
236  }
237 }
238 
241  const NekDouble &time)
242 {
243  m_index++;
244  if (m_index % m_sampleFrequency > 0)
245  {
246  return;
247  }
248 
249  m_numSamples++;
250  v_ProcessSample(pFields, time);
251 
252  if (m_index % m_outputFrequency == 0)
253  {
254  m_fieldMetaData["FinalTime"] = boost::lexical_cast<std::string>(time);
255  v_PrepareOutput(pFields, time);
256  OutputField(pFields, ++m_outputIndex);
257  }
258 }
259 
262  const NekDouble &time)
263 {
264  m_fieldMetaData["FinalTime"] = boost::lexical_cast<std::string>(time);
265  v_PrepareOutput(pFields, time);
266  OutputField(pFields);
267 }
268 
271  const NekDouble &time)
272 {
273  for(int n = 0; n < pFields.num_elements(); ++n)
274  {
275  Vmath::Vcopy(m_outFields[n].num_elements(),
276  pFields[n]->GetCoeffs(),
277  1,
278  m_outFields[n],
279  1);
280  }
281 }
282 
284  const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields, int dump)
285 {
286  NekDouble scale = v_GetScale();
287  for (int n = 0; n < m_outFields.size(); ++n)
288  {
289  Vmath::Smul(m_outFields[n].num_elements(),
290  scale,
291  m_outFields[n],
292  1,
293  m_outFields[n],
294  1);
295  }
296 
297  CreateFields(pFields);
298 
299  // Determine new file name
300  std::stringstream outname;
301  int dot = m_outputFile.find_last_of('.');
302  string name = m_outputFile.substr(0, dot);
303  string ext = m_outputFile.substr(dot, m_outputFile.length() - dot);
304  std::string suffix = v_GetFileSuffix();
305  if (dump == -1) // final dump
306  {
307  outname << name << suffix << ext;
308  }
309  else
310  {
311  outname << name << "_" << dump << suffix << ext;
312  }
313  m_modules[m_modules.size()-1]->RegisterConfig("outfile", outname.str());
314 
315  // Prevent checking before overwritting
316  po::options_description desc("Available options");
317  desc.add_options()
318  ("forceoutput,f",
319  "Force the output to be written without any checks");
320  po::variables_map vm;
321  vm.insert(std::make_pair("forceoutput", po::variable_value()));
322  // Run field process.
323  for (int i = 0; i < m_modules.size(); ++i)
324  {
325  m_modules[i]->Process(vm);
326  cout.flush();
327  }
328 
329  // Empty m_f to save memory
330  ClearFields();
331 
332  if (dump != -1) // not final dump so rescale
333  {
334  for (int n = 0; n < m_outFields.size(); ++n)
335  {
336  Vmath::Smul(m_outFields[n].num_elements(),
337  1.0 / scale,
338  m_outFields[n],
339  1,
340  m_outFields[n],
341  1);
342  }
343  }
344 }
345 
347 {
348  return true;
349 }
350 
351 void FilterFieldConvert::CreateModules( vector<string> &modcmds)
352 {
353  for (int i = 0; i < modcmds.size(); ++i)
354  {
355  // First split each command by the colon separator.
356  vector<string> tmp1;
357  ModuleKey module;
358  int offset = 1;
359 
360  boost::split(tmp1, modcmds[i], boost::is_any_of(":"));
361 
362  if (i == modcmds.size() - 1)
363  {
364  module.first = eOutputModule;
365 
366  // If no colon detected, automatically detect mesh type from
367  // file extension. Otherwise override and use tmp1[1] as the
368  // module to load. This also allows us to pass options to
369  // input/output modules. So, for example, to override
370  // filename.xml to be read as vtk, you use:
371  //
372  // filename.xml:vtk:opt1=arg1:opt2=arg2
373  if (tmp1.size() == 1)
374  {
375  int dot = tmp1[0].find_last_of('.') + 1;
376  string ext = tmp1[0].substr(dot, tmp1[0].length() - dot);
377 
378  module.second = ext;
379  tmp1.push_back(string("outfile=") + tmp1[0]);
380  }
381  else
382  {
383  module.second = tmp1[1];
384  tmp1.push_back(string("outfile=") + tmp1[0]);
385  offset++;
386  }
387  }
388  else
389  {
390  module.first = eProcessModule;
391  module.second = tmp1[0];
392  }
393 
394  // Create modules
395  ModuleSharedPtr mod;
396  mod = GetModuleFactory().CreateInstance(module, m_f);
397  m_modules.push_back(mod);
398 
399  // Set options for this module.
400  for (int j = offset; j < tmp1.size(); ++j)
401  {
402  vector<string> tmp2;
403  boost::split(tmp2, tmp1[j], boost::is_any_of("="));
404 
405  if (tmp2.size() == 1)
406  {
407  mod->RegisterConfig(tmp2[0], "1");
408  }
409  else if (tmp2.size() == 2)
410  {
411  mod->RegisterConfig(tmp2[0], tmp2[1]);
412  }
413  else
414  {
415  cerr << "ERROR: Invalid module configuration: format is "
416  << "either :arg or :arg=val" << endl;
417  abort();
418  }
419  }
420 
421  // Ensure configuration options have been set.
422  mod->SetDefaults();
423  }
424 
425  bool RequiresEquiSpaced = false;
426  for (int i = 0; i < m_modules.size(); ++i)
427  {
428  if(m_modules[i]->GetRequireEquiSpaced())
429  {
430  RequiresEquiSpaced = true;
431  }
432  }
433  if (RequiresEquiSpaced)
434  {
435  for (int i = 0; i < m_modules.size(); ++i)
436  {
437  m_modules[i]->SetRequireEquiSpaced(true);
438  }
439  }
440 }
441 
444 {
445  m_f->m_fieldMetaDataMap = m_fieldMetaData;
446  m_f->m_fieldPts = LibUtilities::NullPtsField;
447  // Create m_f->m_exp
448  int NumHomogeneousDir = 0;
449  if (pFields[0]->GetExpType() == MultiRegions::e3DH1D)
450  {
451  NumHomogeneousDir = 1;
452  }
453  else if (pFields[0]->GetExpType() == MultiRegions::e3DH2D)
454  {
455  NumHomogeneousDir = 2;
456  }
457 
458  m_f->m_exp.resize(m_variables.size());
459  m_f->m_exp[0] = pFields[0];
460  for (int n = 0; n < m_variables.size(); ++n)
461  {
462  m_f->m_exp[n] = m_f->AppendExpList(
463  NumHomogeneousDir, m_variables[0]);
464  m_f->m_exp[n]->SetWaveSpace(false);
465  Vmath::Vcopy( m_outFields[n].num_elements(),
466  m_outFields[n], 1,
467  m_f->m_exp[n]->UpdateCoeffs(), 1);
468  m_f->m_exp[n]->BwdTrans( m_f->m_exp[n]->GetCoeffs(),
469  m_f->m_exp[n]->UpdatePhys());
470  }
471  std::vector<LibUtilities::FieldDefinitionsSharedPtr> FieldDef =
472  pFields[0]->GetFieldDefinitions();
473  std::vector<std::vector<NekDouble> > FieldData(FieldDef.size());
474  for (int n = 0; n < m_outFields.size(); ++n)
475  {
476  for (int i = 0; i < FieldDef.size(); ++i)
477  {
478  FieldDef[i]->m_fields.push_back(m_variables[n]);
479  m_f->m_exp[n]->AppendFieldData(FieldDef[i], FieldData[i]);
480  }
481  }
482  m_f->m_fielddef = FieldDef;
483  m_f->m_data = FieldData;
484 }
485 
487 {
488  m_f->m_fieldPts = LibUtilities::NullPtsField;
489  m_f->m_exp.clear();
490  m_f->m_fielddef = std::vector<LibUtilities::FieldDefinitionsSharedPtr>();
491  m_f->m_data = std::vector<std::vector<NekDouble> > ();
492 }
493 
494 }
495 }
void OutputField(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, int dump=-1)
LibUtilities::FieldMetaDataMap m_fieldMetaData
virtual SOLVER_UTILS_EXPORT ~FilterFieldConvert()
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:198
tBaseSharedPtr CreateInstance(tKey idKey BOOST_PP_COMMA_IF(MAX_PARAM) BOOST_PP_ENUM_BINARY_PARAMS(MAX_PARAM, tParam, x))
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:162
static std::string className
Name of the class.
SOLVER_UTILS_EXPORT FilterFieldConvert(const LibUtilities::SessionReaderSharedPtr &pSession, const ParamMap &pParams)
void CreateFields(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields)
pair< ModuleType, string > ModuleKey
std::vector< Array< OneD, NekDouble > > m_outFields
virtual SOLVER_UTILS_EXPORT void v_Initialise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
boost::shared_ptr< SessionReader > SessionReaderSharedPtr
Definition: MeshPartition.h:51
std::map< std::string, std::string > FieldMetaDataMap
Definition: FieldIO.h:54
virtual SOLVER_UTILS_EXPORT void v_PrepareOutput(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
boost::shared_ptr< Module > ModuleSharedPtr
virtual SOLVER_UTILS_EXPORT void v_FillVariablesName(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields)
virtual SOLVER_UTILS_EXPORT std::string v_GetFileSuffix()
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*y.
Definition: Vmath.cpp:213
NekDouble Evaluate() const
Definition: Equation.h:102
static FilterSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const std::map< std::string, std::string > &pParams)
Creates an instance of this class.
virtual SOLVER_UTILS_EXPORT NekDouble v_GetScale()
void CreateModules(vector< string > &modcmds)
boost::shared_ptr< FieldIO > FieldIOSharedPtr
Definition: FieldIO.h:309
double NekDouble
std::map< std::string, std::string > ParamMap
Definition: Filter.h:67
LibUtilities::SessionReaderSharedPtr m_session
Definition: Filter.h:84
virtual SOLVER_UTILS_EXPORT void v_ProcessSample(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
virtual SOLVER_UTILS_EXPORT void v_Update(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
static PtsFieldSharedPtr NullPtsField
Definition: PtsField.h:179
static boost::shared_ptr< FieldIO > CreateForFile(const LibUtilities::SessionReaderSharedPtr session, const std::string &filename)
Construct a FieldIO object for a given input filename.
Definition: FieldIO.cpp:212
FilterFactory & GetFilterFactory()
Definition: Filter.cpp:42
virtual SOLVER_UTILS_EXPORT void v_Finalise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
virtual SOLVER_UTILS_EXPORT bool v_IsTimeDependent()
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1061
ModuleFactory & GetModuleFactory()
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:215