Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ProcessInterpPoints.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: ProcessInterpPoints.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: Interpolate field to a series of specified points.
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 #include <string>
36 #include <iostream>
37 using namespace std;
38 
39 #include "ProcessInterpPoints.h"
40 
43 #include <boost/math/special_functions/fpclassify.hpp>
44 namespace Nektar
45 {
46 namespace Utilities
47 {
48 ModuleKey ProcessInterpPoints::className =
50  ModuleKey(eProcessModule, "interppoints"),
51  ProcessInterpPoints::create,
52  "Interpolates a set of points to another, requires fromfld and "
53  "fromxml to be defined, a line or plane of points can be "
54  "defined");
55 
56 
57 ProcessInterpPoints::ProcessInterpPoints(FieldSharedPtr f) : ProcessModule(f)
58 {
59 
60  m_config["fromxml"] =
61  ConfigOption(false, "NotSet",
62  "Xml file from which to interpolate field");
63 
64  ASSERTL0(m_config["fromxml"].as<string>().compare("NotSet") != 0,
65  "Need to specify fromxml=file.xml");
66 
67  m_config["fromfld"] =
68  ConfigOption(false,"NotSet",
69  "Fld file from which to interpolate field");
70 
71  ASSERTL0(m_config["fromfld"].as<string>().compare("NotSet") != 0,
72  "Need to specify fromfld=file.fld ");
73 
74  m_config["clamptolowervalue"] =
75  ConfigOption(false, "-10000000",
76  "Lower bound for interpolation value");
77  m_config["clamptouppervalue"] =
78  ConfigOption(false, "10000000",
79  "Upper bound for interpolation value");
80  m_config["defaultvalue"] =
81  ConfigOption(false, "0",
82  "Default value if point is outside domain");
83  m_config["line"] =
84  ConfigOption(false, "NotSet",
85  "Specify a line of N points using "
86  "line=N,x0,y0,z0,z1,y1,z1");
87 
88  m_config["plane"] =
89  ConfigOption(false, "NotSet",
90  "Specify a plane of N1 x N1 points using "
91  "plane=N1,N2,x0,y0,z0,z1,y1,z1,x2,y2,z2,x3,"
92  "y3,z3");
93 }
94 
96 {
97 }
98 
99 void ProcessInterpPoints::Process(po::variables_map &vm)
100 {
101 
102  if(m_f->m_verbose)
103  {
104  cout << "Processing point interpolation" << endl;
105  }
106 
107 
108  // Check for command line point specification if no .pts file specified
109  if(m_f->m_fieldPts == NullFieldPts)
110  {
111  int dim = 0;
112  if(m_config["line"].as<string>().compare("NotSet") != 0)
113  {
114  string help = m_config["line"].as<string>();
115  vector<NekDouble> values;
117  m_config["line"].as<string>().c_str(),values),
118  "Failed to interpret line string");
119 
120  ASSERTL0(values.size() > 3,
121  "line string should contain 2Dim+1 values "
122  "N,x0,y0,z0,x1,y1,z1");
123 
125 
126  dim = m_f->m_fieldPts->m_ptsDim = (values.size()-1)/2;
127 
128  int npts = values[0];
129  m_f->m_fieldPts->m_npts.push_back(values[0]);
130  m_f->m_fieldPts->m_ptype = Utilities::ePtsLine;
131 
132  m_f->m_fieldPts->m_pts = Array<OneD, Array<OneD, NekDouble> > (m_f->m_fieldPts->m_ptsDim);
133 
134  for(int i = 0; i < dim; ++i)
135  {
136  m_f->m_fieldPts->m_pts[i] = Array<OneD,NekDouble>(npts);
137  }
138 
139  for(int i = 0; i < npts; ++i)
140  {
141  m_f->m_fieldPts->m_pts[0][i] = values[1]
142  + i/((NekDouble)(npts-1))*(values[dim+1] - values[1]);
143  if(dim > 1)
144  {
145  m_f->m_fieldPts->m_pts[1][i] = values[2]
146  + i/((NekDouble)(npts-1))*(values[dim+2] - values[2]);
147 
148  if(dim > 2)
149  {
150  m_f->m_fieldPts->m_pts[2][i] = values[3]
151  + i/((NekDouble)(npts-1))*(values[dim+3] - values[3]);
152  }
153  }
154  }
155  }
156  else if(m_config["plane"].as<string>().compare("NotSet") != 0)
157  {
158  string help = m_config["plane"].as<string>();
159  vector<NekDouble> values;
161  m_config["plane"].as<string>().c_str(),values),
162  "Failed to interpret plane string");
163 
164  ASSERTL0(values.size() > 3,
165  "line string should contain 2Dim+1 values "
166  "N,x0,y0,z0,x1,y1,z1");
167 
169 
170  dim = m_f->m_fieldPts->m_ptsDim = (values.size()-1)/4;
171 
172  int npts1 = values[0];
173  int npts2 = values[1];
174  m_f->m_fieldPts->m_npts.push_back(npts1);
175  m_f->m_fieldPts->m_npts.push_back(npts2);
176  m_f->m_fieldPts->m_ptype = Utilities::ePtsPlane;
177 
178  m_f->m_fieldPts->m_pts = Array<OneD, Array<OneD, NekDouble> > (m_f->m_fieldPts->m_ptsDim);
179 
180  for(int i = 0; i < dim; ++i)
181  {
182  m_f->m_fieldPts->m_pts[i] = Array<OneD,NekDouble>(npts1*npts2);
183  }
184 
185  for(int j = 0; j < npts2; ++j)
186  {
187  for(int i = 0; i < npts1; ++i)
188  {
189  m_f->m_fieldPts->m_pts[0][i+j*npts1] =
190  (values[2] + i/((NekDouble)(npts1-1))*(values[dim+2] - values[2]))*(1.0-j/((NekDouble)(npts2-1))) +
191  (values[3*dim+2] + i/((NekDouble)(npts1-1))*(values[2*dim+2] - values[3*dim+2]))*(j/((NekDouble)(npts2-1)));
192  if(dim > 1)
193  {
194  m_f->m_fieldPts->m_pts[1][i+j*npts1] =
195  (values[3] + i/((NekDouble)(npts1-1))*(values[dim+3] - values[3]))*(1.0-j/((NekDouble)(npts2-1))) +
196  (values[3*dim+3] + i/((NekDouble)(npts1-1))*(values[2*dim+3] - values[3*dim+3]))*(j/((NekDouble)(npts2-1)));
197 
198  if(dim > 2)
199  {
200  m_f->m_fieldPts->m_pts[2][i+j*npts1] =
201  (values[4] + i/((NekDouble)(npts1-1))*(values[dim+4] - values[4]))*(1.0-j/((NekDouble)(npts2-1))) +
202  (values[3*dim+4] + i/((NekDouble)(npts1-1))*(values[2*dim+4] - values[3*dim+4]))*(j/((NekDouble)(npts2-1)));
203  }
204  }
205  }
206  }
207  }
208  }
209 
210 
211  m_fromField = boost::shared_ptr<Field>(new Field());
212 
213  std::vector<std::string> files;
214  // set up session file for from field
215  files.push_back(m_config["fromxml"].as<string>());
217  CreateInstance(0, 0, files);
218 
219  // Set up range based on min and max of local parallel partition
221 
222  int coordim = m_f->m_fieldPts->m_ptsDim;
223  int npts = m_f->m_fieldPts->m_pts[0].num_elements();
224  Array<OneD, Array<OneD, NekDouble> > coords = m_f->m_fieldPts->m_pts;
225 
226  rng->m_checkShape = false;
227  switch(coordim)
228  {
229  case 3:
230  rng->m_doZrange = true;
231  rng->m_zmin = Vmath::Vmin(npts,coords[2],1);
232  rng->m_zmax = Vmath::Vmax(npts,coords[2],1);
233  case 2:
234  rng->m_doYrange = true;
235  rng->m_ymin = Vmath::Vmin(npts,coords[1],1);
236  rng->m_ymax = Vmath::Vmax(npts,coords[1],1);
237  case 1:
238  rng->m_doXrange = true;
239  rng->m_xmin = Vmath::Vmin(npts,coords[0],1);
240  rng->m_xmax = Vmath::Vmax(npts,coords[0],1);
241  break;
242  default:
243  ASSERTL0(false,"too many values specfied in range");
244  }
245 
246  // setup rng parameters.
247  m_fromField->m_graph = SpatialDomains::MeshGraph::Read(m_fromField->m_session,rng);
248 
249  // Read in local from field partitions
250  const SpatialDomains::ExpansionMap &expansions = m_fromField->m_graph->GetExpansions();
251 
253  ::AllocateSharedPtr(m_fromField->m_session->GetComm());
254 
255  Array<OneD,int> ElementGIDs(expansions.size());
256  SpatialDomains::ExpansionMap::const_iterator expIt;
257 
258  int i = 0;
259  for (expIt = expansions.begin(); expIt != expansions.end();
260  ++expIt)
261  {
262  ElementGIDs[i++] = expIt->second->m_geomShPtr->GetGlobalID();
263  }
264 
265  string fromfld = m_config["fromfld"].as<string>();
266  m_fromField->m_fld->Import(fromfld,m_fromField->m_fielddef,
267  m_fromField->m_data,
269  ElementGIDs);
270 
271  int NumHomogeneousDir = m_fromField->m_fielddef[0]->m_numHomogeneousDir;
272 
273  //----------------------------------------------
274  // Set up Expansion information to use mode order from field
275  m_fromField->m_graph->SetExpansions(m_fromField->m_fielddef);
276 
277  int nfields = m_fromField->m_fielddef[0]->m_fields.size();
278 
279  m_fromField->m_exp.resize(nfields);
280  m_fromField->m_exp[0] = m_fromField->SetUpFirstExpList(NumHomogeneousDir,true);
281 
282  m_f->m_exp.resize(nfields);
283 
284  // declare auxiliary fields.
285  for(i = 1; i < nfields; ++i)
286  {
287  m_fromField->m_exp[i] = m_fromField->AppendExpList(NumHomogeneousDir);
288  }
289 
290  // load field into expansion in fromfield.
291  for(int j = 0; j < nfields; ++j)
292  {
293  for (i = 0; i < m_fromField->m_fielddef.size(); i++)
294  {
295  m_fromField->m_exp[j]->ExtractDataToCoeffs(
296  m_fromField->m_fielddef[i],
297  m_fromField->m_data[i],
298  m_fromField->m_fielddef[0]->m_fields[j],
299  m_fromField->m_exp[j]->UpdateCoeffs());
300  }
301  m_fromField->m_exp[j]->BwdTrans(m_fromField->m_exp[j]->GetCoeffs(),
302  m_fromField->m_exp[j]->UpdatePhys());
303  m_f->m_fieldPts->m_fields.push_back(m_fromField->m_fielddef[0]->m_fields[j]);
304 
305  }
306 
307  if(m_fromField->m_session->GetComm()->GetRank() == 0)
308  {
309  cout << "Interpolating [" << flush;
310  }
311 
312  NekDouble clamp_low = m_config["clamptolowervalue"].as<NekDouble>();
313  NekDouble clamp_up = m_config["clamptouppervalue"].as<NekDouble>();
314  NekDouble def_value = m_config["defaultvalue"].as<NekDouble>();
315 
316  InterpolateFieldToPts(m_fromField->m_exp, m_f->m_fieldPts->m_pts,
317  clamp_low, clamp_up, def_value);
318 
319  if(m_fromField->m_session->GetComm()->GetRank() == 0)
320  {
321  cout << "]" << endl;
322  }
323 
324 }
325 
327  vector<MultiRegions::ExpListSharedPtr> &field0,
328  Array<OneD, Array<OneD, NekDouble> > &pts,
329  NekDouble clamp_low,
330  NekDouble clamp_up,
331  NekDouble def_value)
332 {
333  int expdim = field0[0]->GetCoordim(0);
334 
335  Array<OneD, NekDouble> coords(expdim), Lcoords(expdim);
336  int nq1 = pts[0].num_elements();
337  int elmtid, offset;
338  int r, f;
339  static int intpts = 0;
340 
341  // resize data field
342  m_f->m_data.resize(field0.size());
343 
344  for (f = 0; f < field0.size(); ++f)
345  {
346  m_f->m_data[f].resize(nq1);
347  }
348 
349  for (r = 0; r < nq1; r++)
350  {
351  coords[0] = pts[0][r];
352  coords[1] = pts[1][r];
353  if (expdim == 3)
354  {
355  coords[2] = pts[2][r];
356  }
357 
358  // Obtain Element and LocalCoordinate to interpolate
359  elmtid = field0[0]->GetExpIndex(coords, Lcoords, 1e-3);
360 
361  if(elmtid >= 0)
362  {
363  offset = field0[0]->GetPhys_Offset(field0[0]->
364  GetOffset_Elmt_Id(elmtid));
365 
366  for (f = 0; f < field0.size(); ++f)
367  {
368  NekDouble value;
369  value = field0[f]->GetExp(elmtid)->
370  StdPhysEvaluate(Lcoords, field0[f]->GetPhys() +offset);
371 
372  if ((boost::math::isnan)(value))
373  {
374  ASSERTL0(false, "new value is not a number");
375  }
376  else
377  {
378  value = (value > clamp_up)? clamp_up :
379  ((value < clamp_low)? clamp_low :
380  value);
381 
382  m_f->m_data[f][r] = value;
383  }
384  }
385  }
386  else
387  {
388  for (f = 0; f < field0.size(); ++f)
389  {
390  m_f->m_data[f][r] = def_value;
391  }
392  }
393 
394  if (intpts%1000 == 0)
395  {
396  cout <<"." << flush;
397  }
398  intpts ++;
399  }
400 }
401 
402 }
403 }
404 
405