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  switch(coordim)
227  {
228  case 3:
229  rng->doZrange = true;
230  rng->zmin = Vmath::Vmin(npts,coords[2],1);
231  rng->zmax = Vmath::Vmax(npts,coords[2],1);
232  case 2:
233  rng->doYrange = true;
234  rng->ymin = Vmath::Vmin(npts,coords[1],1);
235  rng->ymax = Vmath::Vmax(npts,coords[1],1);
236  case 1:
237  rng->doXrange = true;
238  rng->xmin = Vmath::Vmin(npts,coords[0],1);
239  rng->xmax = Vmath::Vmax(npts,coords[0],1);
240  break;
241  default:
242  ASSERTL0(false,"too many values specfied in range");
243  }
244 
245  // setup rng parameters.
246  m_fromField->m_graph = SpatialDomains::MeshGraph::Read(m_fromField->m_session,rng);
247 
248  // Read in local from field partitions
249  const SpatialDomains::ExpansionMap &expansions = m_fromField->m_graph->GetExpansions();
250 
252  ::AllocateSharedPtr(m_fromField->m_session->GetComm());
253 
254  Array<OneD,int> ElementGIDs(expansions.size());
255  SpatialDomains::ExpansionMap::const_iterator expIt;
256 
257  int i = 0;
258  for (expIt = expansions.begin(); expIt != expansions.end();
259  ++expIt)
260  {
261  ElementGIDs[i++] = expIt->second->m_geomShPtr->GetGlobalID();
262  }
263 
264  string fromfld = m_config["fromfld"].as<string>();
265  m_fromField->m_fld->Import(fromfld,m_fromField->m_fielddef,
266  m_fromField->m_data,
268  ElementGIDs);
269 
270  int NumHomogeneousDir = m_fromField->m_fielddef[0]->m_numHomogeneousDir;
271 
272  //----------------------------------------------
273  // Set up Expansion information to use mode order from field
274  m_fromField->m_graph->SetExpansions(m_fromField->m_fielddef);
275 
276  int nfields = m_fromField->m_fielddef[0]->m_fields.size();
277 
278  m_fromField->m_exp.resize(nfields);
279  m_fromField->m_exp[0] = m_fromField->SetUpFirstExpList(NumHomogeneousDir,true);
280 
281  m_f->m_exp.resize(nfields);
282 
283  // declare auxiliary fields.
284  for(i = 1; i < nfields; ++i)
285  {
286  m_fromField->m_exp[i] = m_fromField->AppendExpList(NumHomogeneousDir);
287  }
288 
289  // load field into expansion in fromfield.
290  for(int j = 0; j < nfields; ++j)
291  {
292  for (i = 0; i < m_fromField->m_fielddef.size(); i++)
293  {
294  m_fromField->m_exp[j]->ExtractDataToCoeffs(
295  m_fromField->m_fielddef[i],
296  m_fromField->m_data[i],
297  m_fromField->m_fielddef[0]->m_fields[j],
298  m_fromField->m_exp[j]->UpdateCoeffs());
299  }
300  m_fromField->m_exp[j]->BwdTrans(m_fromField->m_exp[j]->GetCoeffs(),
301  m_fromField->m_exp[j]->UpdatePhys());
302  m_f->m_fieldPts->m_fields.push_back(m_fromField->m_fielddef[0]->m_fields[j]);
303 
304  }
305 
306  if(m_fromField->m_session->GetComm()->GetRank() == 0)
307  {
308  cout << "Interpolating [" << flush;
309  }
310 
311  NekDouble clamp_low = m_config["clamptolowervalue"].as<NekDouble>();
312  NekDouble clamp_up = m_config["clamptouppervalue"].as<NekDouble>();
313  NekDouble def_value = m_config["defaultvalue"].as<NekDouble>();
314 
315  InterpolateFieldToPts(m_fromField->m_exp, m_f->m_fieldPts->m_pts,
316  clamp_low, clamp_up, def_value);
317 
318  if(m_fromField->m_session->GetComm()->GetRank() == 0)
319  {
320  cout << "]" << endl;
321  }
322 
323 }
324 
326  vector<MultiRegions::ExpListSharedPtr> &field0,
327  Array<OneD, Array<OneD, NekDouble> > &pts,
328  NekDouble clamp_low,
329  NekDouble clamp_up,
330  NekDouble def_value)
331 {
332  int expdim = field0[0]->GetCoordim(0);
333 
334  Array<OneD, NekDouble> coords(expdim), Lcoords(expdim);
335  int nq1 = pts[0].num_elements();
336  int elmtid, offset;
337  int r, f;
338  static int intpts = 0;
339 
340  // resize data field
341  m_f->m_data.resize(field0.size());
342 
343  for (f = 0; f < field0.size(); ++f)
344  {
345  m_f->m_data[f].resize(nq1);
346  }
347 
348  for (r = 0; r < nq1; r++)
349  {
350  coords[0] = pts[0][r];
351  coords[1] = pts[1][r];
352  if (expdim == 3)
353  {
354  coords[2] = pts[2][r];
355  }
356 
357  // Obtain Element and LocalCoordinate to interpolate
358  elmtid = field0[0]->GetExpIndex(coords, Lcoords, 1e-3);
359 
360  if(elmtid >= 0)
361  {
362  offset = field0[0]->GetPhys_Offset(field0[0]->
363  GetOffset_Elmt_Id(elmtid));
364 
365  for (f = 0; f < field0.size(); ++f)
366  {
367  NekDouble value;
368  value = field0[f]->GetExp(elmtid)->
369  StdPhysEvaluate(Lcoords, field0[f]->GetPhys() +offset);
370 
371  if ((boost::math::isnan)(value))
372  {
373  ASSERTL0(false, "new value is not a number");
374  }
375  else
376  {
377  value = (value > clamp_up)? clamp_up :
378  ((value < clamp_low)? clamp_low :
379  value);
380 
381  m_f->m_data[f][r] = value;
382  }
383  }
384  }
385  else
386  {
387  for (f = 0; f < field0.size(); ++f)
388  {
389  m_f->m_data[f][r] = def_value;
390  }
391  }
392 
393  if (intpts%1000 == 0)
394  {
395  cout <<"." << flush;
396  }
397  intpts ++;
398  }
399 }
400 
401 }
402 }
403 
404