Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
OutputFld.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: OutputFld.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: FLD file format output.
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
36 #include <set>
37 #include <string>
38 using namespace std;
39 
40 #include "OutputFld.h"
42 
43 namespace Nektar
44 {
45 namespace FieldUtils
46 {
47 
48 ModuleKey OutputFld::m_className[2] = {
50  OutputFld::create,
51  "Writes a Fld file."),
53  OutputFld::create,
54  "Writes a Fld file."),
55 };
56 
57 OutputFld::OutputFld(FieldSharedPtr f) : OutputModule(f)
58 {
59  m_config["format"] = ConfigOption(
60  false, "Xml", "Output format of field file");
61 }
62 
64 {
65 }
66 
67 void OutputFld::Process(po::variables_map &vm)
68 {
69  // Extract the output filename and extension
70  string filename = m_config["outfile"].as<string>();
71 
72  // Set up communicator and FieldIO object.
73  LibUtilities::CommSharedPtr c = m_f->m_session ? m_f->m_session->GetComm() :
77  m_config["format"].as<string>(), c, true);
78 
79  if (m_f->m_writeBndFld)
80  {
81  ModuleKey module;
82 
83  if (m_f->m_verbose)
84  {
85  if (m_f->m_comm->TreatAsRankZero())
86  {
87  cout << "OutputFld: Writing boundary file(s): ";
88  for (int i = 0; i < m_f->m_bndRegionsToWrite.size(); ++i)
89  {
90  cout << m_f->m_bndRegionsToWrite[i];
91  if (i < m_f->m_bndRegionsToWrite.size() - 1)
92  {
93  cout << ",";
94  }
95  }
96  cout << endl;
97  }
98  }
99 
100  // Extract data to boundaryconditions
101  if (m_f->m_fldToBnd)
102  {
103  for (int i = 0; i < m_f->m_exp.size(); ++i)
104  {
105  m_f->m_exp[i]->FillBndCondFromField();
106  }
107  }
108 
109  int nfields = m_f->m_exp.size();
111  nfields);
112  for (int i = 0; i < nfields; ++i)
113  {
114  BndExp[i] = m_f->m_exp[i]->GetBndCondExpansions();
115  }
116 
117  // get hold of partition boundary regions so we can match it to desired
118  // region extraction
120  m_f->m_exp[0]->GetGraph());
122  bcs.GetBoundaryRegions();
123  SpatialDomains::BoundaryRegionCollection::const_iterator breg_it;
124  map<int, int> BndRegionMap;
125  int cnt = 0;
126  for (breg_it = bregions.begin(); breg_it != bregions.end();
127  ++breg_it, ++cnt)
128  {
129  BndRegionMap[breg_it->first] = cnt;
130  }
131 
132  // find ending of output file and insert _b1, _b2
133  int dot = filename.find_last_of('.') + 1;
134  string ext = filename.substr(dot, filename.length() - dot);
135  string name = filename.substr(0, dot - 1);
136 
137  for (int i = 0; i < m_f->m_bndRegionsToWrite.size(); ++i)
138  {
139  string outname =
140  name + "_b" +
141  boost::lexical_cast<string>(m_f->m_bndRegionsToWrite[i]) + "." +
142  ext;
143 
144  std::vector<LibUtilities::FieldDefinitionsSharedPtr> FieldDef;
145  std::vector<std::vector<NekDouble> > FieldData;
146 
147  if (BndRegionMap.count(m_f->m_bndRegionsToWrite[i]) == 1)
148  {
149  int Border = BndRegionMap[m_f->m_bndRegionsToWrite[i]];
150 
151  FieldDef = BndExp[0][Border]->GetFieldDefinitions();
152  FieldData.resize(FieldDef.size());
153 
154  for (int j = 0; j < nfields; ++j)
155  {
156  for (int k = 0; k < FieldDef.size(); ++k)
157  {
158  BndExp[j][Border]->AppendFieldData(FieldDef[k],
159  FieldData[k]);
160 
161  if (m_f->m_fielddef.size() > 0)
162  {
163  FieldDef[k]->m_fields.push_back(
164  m_f->m_fielddef[0]->m_fields[j]);
165  }
166  else
167  {
168  FieldDef[k]->m_fields.push_back(
169  m_f->m_session->GetVariable(j));
170  }
171  }
172  }
173 
174  if (m_f->m_addNormals)
175  {
176  int normdim = m_f->m_graph->GetMeshDimension();
177  string normstr[3] = {"Norm_x", "Norm_y", "Norm_z"};
178 
179  // Get normals
181  m_f->m_exp[0]->GetBoundaryNormals(Border, NormPhys);
182 
183  // add normal coefficients to list to be dumped
184  for (int j = 0; j < normdim; ++j)
185  {
186  BndExp[0][Border]->FwdTrans(
187  NormPhys[j], BndExp[0][Border]->UpdateCoeffs());
188 
189  for (int k = 0; k < FieldDef.size(); ++k)
190  {
191  BndExp[0][Border]->AppendFieldData(FieldDef[k],
192  FieldData[k]);
193  FieldDef[k]->m_fields.push_back(normstr[j]);
194  }
195  }
196  }
197 
198  // output error for regression checking.
199  if (vm.count("error"))
200  {
201  int rank = m_f->m_session->GetComm()->GetRank();
202 
203  for (int j = 0; j < nfields; ++j)
204  {
205  BndExp[j][Border]->BwdTrans(
206  BndExp[j][Border]->GetCoeffs(),
207  BndExp[j][Border]->UpdatePhys());
208 
209  // Note currently these calls will
210  // hange since not all partitions will
211  // call error.
212  NekDouble l2err =
213  BndExp[j][Border]->L2(BndExp[j][Border]->GetPhys());
214 
215  NekDouble linferr = BndExp[j][Border]->Linf(
216  BndExp[j][Border]->GetPhys());
217 
218  if (rank == 0)
219  {
220  cout << "L 2 error (variable "
221  << FieldDef[0]->m_fields[j] << ") : " << l2err
222  << endl;
223 
224  cout << "L inf error (variable "
225  << FieldDef[0]->m_fields[j]
226  << ") : " << linferr << endl;
227  }
228  }
229  }
230  }
231 
232  fld->Write(outname, FieldDef, FieldData, m_f->m_fieldMetaDataMap);
233  }
234  }
235  else
236  {
237  if (m_f->m_verbose)
238  {
239  if (m_f->m_comm->TreatAsRankZero())
240  {
241  cout << "OutputFld: Writing file..." << endl;
242  }
243  }
244 
245  fs::path writefile(filename);
246  int writefld = 1;
247  if (fs::exists(writefile) && (vm.count("forceoutput") == 0))
248  {
249  int rank = 0;
251 
252  if (m_f->m_session)
253  {
254  comm = m_f->m_session->GetComm();
255  rank = comm->GetRank();
256  }
257  else
258  {
260  "Serial", 0, 0);
261  }
262 
263  writefld = 0; // set to zero for reduce all to be correct.
264 
265  if (rank == 0)
266  {
267  string answer;
268  cout << "Did you wish to overwrite " << filename << " (y/n)? ";
269  getline(cin, answer);
270  if (answer.compare("y") == 0)
271  {
272  writefld = 1;
273  }
274  else
275  {
276  cout << "Not writing file " << filename
277  << " because it already exists" << endl;
278  }
279  }
280 
281  comm->AllReduce(writefld, LibUtilities::ReduceSum);
282  }
283 
284  if (writefld)
285  {
286  fld->Write(filename, m_f->m_fielddef, m_f->m_data,
287  m_f->m_fieldMetaDataMap);
288  }
289 
290  // output error for regression checking.
291  if (vm.count("error"))
292  {
293  int rank = m_f->m_session->GetComm()->GetRank();
294 
295  for (int j = 0; j < m_f->m_exp.size(); ++j)
296  {
297  if (m_f->m_exp[j]->GetPhysState() == false)
298  {
299  m_f->m_exp[j]->BwdTrans(m_f->m_exp[j]->GetCoeffs(),
300  m_f->m_exp[j]->UpdatePhys());
301  }
302 
303  NekDouble l2err = m_f->m_exp[j]->L2(m_f->m_exp[j]->GetPhys());
304 
305  NekDouble linferr =
306  m_f->m_exp[j]->Linf(m_f->m_exp[j]->GetPhys());
307  if (rank == 0)
308  {
309  cout << "L 2 error (variable "
310  << m_f->m_fielddef[0]->m_fields[j] << ") : " << l2err
311  << endl;
312 
313  cout << "L inf error (variable "
314  << m_f->m_fielddef[0]->m_fields[j] << ") : " << linferr
315  << endl;
316  }
317  }
318  }
319  }
320 }
321 }
322 }
map< string, ConfigOption > m_config
List of configuration values.
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
Represents a command-line configuration option.
STL namespace.
pair< ModuleType, string > ModuleKey
virtual void Process(po::variables_map &vm)
Write fld to output file.
Definition: OutputFld.cpp:67
FieldIOFactory & GetFieldIOFactory()
Returns the FieldIO factory.
Definition: FieldIO.cpp:74
CommFactory & GetCommFactory()
Definition: Comm.cpp:61
boost::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:55
boost::shared_ptr< Field > FieldSharedPtr
Definition: Field.hpp:740
std::map< int, BoundaryRegionShPtr > BoundaryRegionCollection
Definition: Conditions.h:217
boost::shared_ptr< FieldIO > FieldIOSharedPtr
Definition: FieldIO.h:309
double NekDouble
const BoundaryRegionCollection & GetBoundaryRegions(void) const
Definition: Conditions.h:238
Abstract base class for output modules.
ModuleFactory & GetModuleFactory()
FieldSharedPtr m_f
Field object.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:215