Nektar++
ProcessCurve.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: ProcessCurve.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 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: create curved edges using a custom expression y = f(x)
32 //
33 ////////////////////////////////////////////////////////////////////////////////
34 
36 
37 #include <LocalRegions/SegExp.h>
38 #include <LocalRegions/QuadExp.h>
39 #include <LocalRegions/TriExp.h>
41 
44 
46 
47 #include "ProcessCurve.h"
48 
49 using namespace std;
50 using namespace Nektar::NekMeshUtils;
51 
52 namespace Nektar
53 {
54 namespace Utilities
55 {
56 
57 ModuleKey ProcessCurve::className = GetModuleFactory().RegisterCreatorFunction(
58  ModuleKey(eProcessModule, "curve"),
59  ProcessCurve::create,
60  "Creates curved edge information using a function y=f(x) (2D only).");
61 
62 /**
63  * @brief Default constructor.
64  */
65 ProcessCurve::ProcessCurve(MeshSharedPtr m) : ProcessCurvedEdges(m)
66 {
67  m_config["function"] = ConfigOption(false, "NotSet",
68  "Expression of the curve: y = f(x).");
69  m_config["file"] = ConfigOption(false, "NotSet",
70  "Pts file containing coordinates (x,y).");
71  m_config["niter"] = ConfigOption(false, "50",
72  "Number of iterations to perform to obtain evenly distribution of points.");
73  m_config["gamma"] = ConfigOption(false, "0.1",
74  "Relaxation parameter.");
75 }
76 
77 /**
78  * @brief Destructor.
79  */
81 {
82 }
83 
84 /**
85  * This function generates curved edge information in 2D, by including
86  * equispaced nodes to an edge following the prescribed function \f$y = f(x)\f$.
87  *
88  * An approximately equispaced node distribution is obtained by initially
89  * considering a uniform distribution in the \f$ x\f$ direction, and then
90  * adjusting the interior nodes using the iteration
91  * \f[ x^{n}_{i+1} = x^{n-1}_{i+1} + \Delta x^{n}_{i+1} \f]
92  * \f[ \Delta x^{n}_{i+1} = \Delta x^{n}_{i} +
93  * \gamma (\overline{\Delta s} - \Delta s^{n}_{i}) sign(\Delta x^{n}_{i}) \f]
94  *
95  * where \f$ x^{n}\f$ is the \f$ x\f$ coordinate of the \f$ n^{th}\f$ node,
96  * \f$ i\f$ is the iteration counter, \f$ \Delta s^{n}\f$ is the Cartesian
97  * distance between nodes \f$ n\f$ and \f$ n-1\f$ and \f$ \overline{\Delta s}\f$
98  * is the average of these distances. The relaxation factor \f$ \gamma\f$ and
99  * the fixed number of iterations \f$ Niter\f$ are parameters of the module.
100  *
101  * In case the correction to \f$ \Delta x\f$ leads to an invalid distribution
102  * (i.e. reversing directions), the relaxation parameter is successively halved
103  * until it leads to a valid distribution.
104  *
105  * @param edge Edge which will be modified
106  */
108 {
109  NodeSharedPtr n1 = edge->m_n1;
110  NodeSharedPtr n2 = edge->m_n2;
111 
112  int nq = m_config["N"].as<int>();
113  int niter = m_config["niter"].as<int>();
114  NekDouble gamma = m_config["gamma"].as<double>();
115 
116  edge->m_edgeNodes.resize(nq - 2);
117 
118  // Read function defining the curve
119  if (m_config["function"].as<string>().compare("NotSet") != 0)
120  {
121  ASSERTL0(m_config["file"].as<string>().compare("NotSet") == 0,
122  "Function and file cannot be defined at the same time.");
123 
124  std::string fstr = m_config["function"].as<string>();
125  m_fExprId = m_fEval.DefineFunction("x y z", fstr);
126  m_fromFile = false;
127  }
128  else
129  {
130  ASSERTL0(m_config["file"].as<string>().compare("NotSet") != 0,
131  "Need to define either function or file.");
132  std::string inFile = m_config["file"].as<string>();
133 
138  ptsIO->Import(inFile, m_fieldPts);
139 
140  m_fromFile = true;
141  }
142 
143  // Coordinates of points
144  Array<OneD, NekDouble> x(nq,0.0);
145  Array<OneD, NekDouble> y(nq,0.0);
146  // Distances between points
147  Array<OneD, NekDouble> dx(nq-1,0.0);
148  Array<OneD, NekDouble> dy(nq-1,0.0);
149  Array<OneD, NekDouble> ds(nq-1,0.0);
150  // Average distance and deviation from average
151  Array<OneD, NekDouble> s_deviation(nq-1,0.0);
152  NekDouble s_average;
153 
154  // Fix start point
155  x[0] = n1->m_x;
156  y[0] = EvaluateCoordinate(x[0]);
157  // Start with uniform distribution along x-axis
158  Vmath::Sadd(nq-1, (n2->m_x - n1->m_x) / (nq-1), dx, 1, dx, 1);
159 
160  // Iterate a few times to make points more evenly distributed
161  for (int s = 0; s < niter; ++s)
162  {
163  s_average = 0.0;
164  for (int k = 1; k < nq; ++k)
165  {
166  x[k] = x[k-1] + dx[k-1] + gamma*s_deviation[k-1];
167  y[k] = EvaluateCoordinate(x[k]);
168 
169  dx[k-1] = x[k] - x[k-1];
170  dy[k-1] = y[k] - y[k-1];
171  ds[k-1] = sqrt(dx[k-1]*dx[k-1] + dy[k-1]*dy[k-1]);
172 
173  s_average = s_average + ds[k-1]/(nq-1);
174  }
175  // Calculate correction for next iteration
176  for (int k = 0; k < nq-1; ++k)
177  {
178  s_deviation[k] = (s_average - ds[k])*
179  ( dx[k]/abs(dx[k]));
180  }
181  // Adjust gama to make sure next partition is valid
182  // (no reversals in dx)
183  bool valid = false;
184  gamma = m_config["gamma"].as<double>();
185  while( !valid)
186  {
187  valid = true;
188  for (int k = 0; k < nq-1; ++k)
189  {
190  if( dx[k]*(dx[k]+gamma*s_deviation[k]) < 0.0)
191  {
192  gamma = gamma/2;
193  valid = false;
194  continue;
195  }
196  }
197  }
198  }
199 
200  // Write interior nodes to edge
201  for (int k = 1; k < nq-1; ++k)
202  {
203  edge->m_edgeNodes[k-1] = NodeSharedPtr(
204  new Node(0, x[k], y[k], n1->m_z));
205  }
206  edge->m_curveType = LibUtilities::ePolyEvenlySpaced;
207 }
208 
210 {
211  if (m_fromFile)
212  {
214  tmp[0] = Array<OneD, NekDouble>(1, xCoord);
215  tmp[1] = Array<OneD, NekDouble>(1, 0.0);
216 
219 
221  interp.Interpolate(m_fieldPts, toPts);
222 
223  return tmp[1][0];
224  }
225  else
226  {
227  return m_fEval.Evaluate(m_fExprId, xCoord, 0.0, 0.0, 0.0);
228  }
229 }
230 
231 }
232 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
int DefineFunction(const std::string &vlist, const std::string &expr)
Defines a function for the purposes of evaluation.
A class that contains algorithms for interpolation between pts fields, expansions and different meshe...
NekDouble Evaluate(const int id)
Evaluate a function which depends only on constants and/or parameters.
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:53
STL namespace.
std::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge.
Definition: Edge.h:136
std::shared_ptr< Mesh > MeshSharedPtr
Shared pointer to a mesh.
Definition: Mesh.h:156
CommFactory & GetCommFactory()
std::shared_ptr< Node > NodeSharedPtr
Definition: CADVert.h:49
1D Evenly-spaced points using Lagrange polynomial
Definition: PointsType.h:64
virtual ~ProcessCurve()
Destructor.
LibUtilities::PtsFieldSharedPtr m_fieldPts
Definition: ProcessCurve.h:69
std::shared_ptr< PtsIO > PtsIOSharedPtr
Definition: PtsIO.h:96
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
void Interpolate(const LibUtilities::PtsFieldSharedPtr ptsInField, LibUtilities::PtsFieldSharedPtr &ptsOutField)
Interpolate from a pts field to a pts field.
std::shared_ptr< PtsField > PtsFieldSharedPtr
Definition: PtsField.h:179
std::pair< ModuleType, std::string > ModuleKey
LibUtilities::Interpreter m_fEval
Definition: ProcessCurve.h:67
Represents a command-line configuration option.
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
double NekDouble
std::map< std::string, ConfigOption > m_config
List of configuration values.
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add vector y = alpha + x.
Definition: Vmath.cpp:318
void v_GenerateEdgeNodes(NekMeshUtils::EdgeSharedPtr edge)
NekDouble EvaluateCoordinate(NekDouble xCoord)
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:199
std::pair< ModuleType, std::string > ModuleKey
ModuleFactory & GetModuleFactory()