KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
nurbs_curve_shape_functions.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ `
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Thomas Oberbichler
11 //
12 // Ported from the ANurbs library (https://github.com/oberbichler/ANurbs)
13 //
14 
15 #if !defined(KRATOS_NURBS_CURVE_SHAPE_FUNCTIONS_H_INCLUDED )
16 #define KRATOS_NURBS_CURVE_SHAPE_FUNCTIONS_H_INCLUDED
17 
18 // System includes
19 
20 // External includes
21 
22 // Project includes
23 #include "nurbs_utilities.h"
24 
25 namespace Kratos {
28 
30 /* Container with memory management for an efficient computation
31 * of NURBS and B-Spline - 1 dimensional curve functions.
32 */
34 {
35 public:
38 
39  typedef typename std::size_t IndexType;
40  typedef typename std::size_t SizeType;
41 
45 
48  {
49  };
50 
51  /*
52  * Constructor using the degree u, degree v and the order of shape functions.
53  * This information is required to make an optimized memory management.
54  */
57  const SizeType DerivativeOrder)
58  {
59  ResizeDataContainers(PolynomialDegree, DerivativeOrder);
60  }
61 
65 
66  double operator()(const IndexType NonzeroControlPointIndex, const IndexType DerivativeRow) const
67  {
68  return ShapeFunctionValue(NonzeroControlPointIndex, DerivativeRow);
69  }
70 
74 
75  /*
76  * @brief Resizes the data containers which are needed to compute the
77  * values of the shape functions.
78  */
81  const SizeType DerivativeOrder)
82  {
83  mDerivativeOrder = DerivativeOrder;
84 
85  mValues.resize((PolynomialDegree + 1) * (mDerivativeOrder + 1));
86  mLeft.resize(PolynomialDegree);
87  mRight.resize(PolynomialDegree);
88  mNdu.resize((PolynomialDegree + 1) * (PolynomialDegree + 1));
89  mA.resize(PolynomialDegree + 1);
90  mB.resize(PolynomialDegree + 1);
91 
92  mPolynomialDegree = PolynomialDegree;
93  }
94 
95  /*
96  * @return provides the polynomial degree of this shape function generator.
97  */
99  {
100  return mPolynomialDegree;
101  }
102 
103  /*
104  * @brief the number of nonzero control points for one point on the curve is
105  * given by polynomial degree + 1.
106  * @return the number of nonzero control points of this shape function generator.
107  */
109  {
110  return PolynomialDegree() + 1;
111  }
112 
113  /*
114  * @return the number of shape function rows. This is the derivative order + 1.
115  * rows are defined as: N | dN/de | dN^2/de^2 | ...
116  */
118  {
119  return mDerivativeOrder + 1;
120  }
121 
122  /*
123  * @brief Provides the shape function value depending to the DerivativeOrder and
124  * the index of the control point.
125  */
127  const IndexType ControlPointIndex,
128  const IndexType DerivativeRow) const
129  {
132  ControlPointIndex, DerivativeRow);
133 
134  return mValues[index];
135  }
136 
137  /*
138  * @brief the first nonzero control point index within the list.
139  * @return the index of the first nonzero control point.
140  */
142  {
143  return mFirstNonzeroControlPoint;
144  }
145 
146  /*
147  * @return the indices of all nonzero control points.
148  */
149  std::vector<IndexType> GetNonzeroControlPointIndices() const
150  {
151  std::vector<IndexType> indices(NumberOfNonzeroControlPoints());
152 
153  for (IndexType i = 0; i < NumberOfNonzeroControlPoints(); i++) {
154  indices[i] = GetFirstNonzeroControlPoint() + i;
155  }
156 
157  return indices;
158  }
159 
163 
164  /*
165  * @brief Computation of B-Spline shape function values, use this function
166  * if span of ParameterT is unknown.
167  * From Piegl and Tiller, The NURBS Book, Algorithm A3.1
168  * @param rKnots, the full knot span.
169  * @param ParameterT, the parameter at which the shape functions
170  * are evaluated.
171  */
172  void ComputeBSplineShapeFunctionValues(const Vector& rKnots, const double ParameterT)
173  {
175  PolynomialDegree(), rKnots, ParameterT);
176 
177  ComputeBSplineShapeFunctionValuesAtSpan(rKnots, span, ParameterT);
178  }
179 
180  /*
181  * @brief Computation of B-Spline shape function values.
182  * From Piegl and Tiller, The NURBS Book, Algorithm A2.2 and A2.3
183  * @param rKnots, the full knot span.
184  * @param Span, the index of the span of interest.
185  * @param ParameterT, the parameter at which the shape functions
186  * are evaluated.
187  */
189  const Vector& rKnots,
190  const IndexType Span,
191  const double ParameterT)
192  {
193  // Use a signed integer for the computations!
194  using Int = std::ptrdiff_t;
195 
196  ClearValues();
197 
198  const Int polynominal_degree = static_cast<Int>(PolynomialDegree());
199  const Int number_of_nonzero_control_points =
200  static_cast<Int>(NumberOfNonzeroControlPoints());
201  const Int number_of_shape_function_rows =
202  static_cast<Int>(NumberOfShapeFunctionRows());
203 
204  mFirstNonzeroControlPoint = Span - polynominal_degree + 1;
205 
206  // compute B-Spline shape
207  Ndu(0, 0) = 1.0;
208 
209  for (Int j = 0; j < polynominal_degree; j++) {
210  mLeft[j] = ParameterT - rKnots[Span - j];
211  mRight[j] = rKnots[Span + j + 1] - ParameterT;
212 
213  double saved = 0.0;
214 
215  for (Int r = 0; r <= j; r++) {
216  Ndu(j + 1, r) = mRight[r] + mLeft[j - r];
217 
218  double temp = Ndu(r, j) / Ndu(j + 1, r);
219 
220  Ndu(r, j + 1) = saved + mRight[r] * temp;
221 
222  saved = mLeft[j - r] * temp;
223  }
224  Ndu(j + 1, j + 1) = saved;
225  }
226 
227  for (Int j = 0; j < number_of_nonzero_control_points; j++) {
228  ShapeFunctionValue(j, 0) = Ndu(j, polynominal_degree);
229  }
230 
231  auto& a = mA;
232  auto& b = mB;
233 
234  for (Int r = 0; r < number_of_nonzero_control_points; r++) {
235  a[0] = 1.0;
236 
237  for (Int k = 1; k < number_of_shape_function_rows; k++) {
238  double& value = ShapeFunctionValue(r, k);
239 
240  Int rk = r - k;
241  Int pk = polynominal_degree - k;
242 
243  if (r >= k) {
244  b[0] = a[0] / Ndu(pk + 1, rk);
245  value = b[0] * Ndu(rk, pk);
246  }
247 
248  Int j1 = r >= k - 1 ? 1 : k - r;
249  Int j2 = r <= pk + 1 ? k : number_of_nonzero_control_points - r;
250 
251  for (Int j = j1; j < j2; j++) {
252  b[j] = (a[j] - a[j - 1]) / Ndu(pk + 1, rk + j);
253  value += b[j] * Ndu(rk + j, pk);
254  }
255 
256  if (r <= pk) {
257  b[k] = -a[k - 1] / Ndu(pk + 1, r);
258  value += b[k] * Ndu(r, pk);
259  }
260 
261  std::swap(a, b);
262  }
263  }
264 
265  Int s = polynominal_degree;
266 
267  for (Int k = 1; k < number_of_shape_function_rows; k++) {
268  for (Int j = 0; j < number_of_nonzero_control_points; j++) {
269  ShapeFunctionValue(j, k) *= s;
270  }
271  s *= polynominal_degree - k;
272  }
273  }
274 
275  /*
276  * @brief Computation of NURBS shape function values, use this function
277  * if span of ParameterT is unknown.
278  * From Piegl and Tiller, The NURBS Book, Algorithm A4.2
279  * @param rKnots, the full knot span.
280  * @param rWeights, the complete weights of the curve.
281  * @param ParameterT, the parameter at which the shape functions
282  * are evaluated.
283  */
285  const Vector& rKnots,
286  const Vector& rWeights,
287  const double ParameterT)
288  {
289  const auto span = NurbsUtilities::GetUpperSpan(
290  PolynomialDegree(), rKnots, ParameterT);
291 
292  ComputeNurbsShapeFunctionValuesAtSpan(rKnots, span, rWeights, ParameterT);
293  }
294 
295  /*
296  * @brief Computation of NURBS shape function values
297  * From Piegl and Tiller, The NURBS Book, Algorithm A4.2
298  * @param rKnots, the full knot span.
299  * @param rWeights, the complete weights of the curve.
300  * @param ParameterT, the parameter at which the shape functions
301  * are evaluated.
302  */
304  const Vector& rKnots,
305  const IndexType Span,
306  const Vector& rWeights,
307  const double ParameterT)
308  {
309  // compute B-Spline shape
310  ComputeBSplineShapeFunctionValuesAtSpan(rKnots, Span, ParameterT);
311 
312  // apply weights
313  std::vector<double> weightedSums(NumberOfShapeFunctionRows());
314 
315  for (IndexType k = 0; k < NumberOfShapeFunctionRows(); k++) {
316  weightedSums[k] = 0;
317 
318  for (IndexType i = 0; i < NumberOfNonzeroControlPoints(); i++) {
319  const IndexType poleIndex = GetFirstNonzeroControlPoint() + i;
320  ShapeFunctionValue(i, k) *= rWeights(poleIndex);
321  weightedSums[k] += ShapeFunctionValue(i, k);
322  }
323  }
324 
325  for (IndexType k = 0; k < NumberOfShapeFunctionRows(); k++) {
326  for (IndexType i = 1; i <= k; i++) {
327  const double a = NurbsUtilities::GetBinomCoefficient(k, i) *
328  weightedSums[i];
329 
330  for (IndexType p = 0; p < NumberOfNonzeroControlPoints(); p++) {
331  ShapeFunctionValue(p, k) -=
332  a * ShapeFunctionValue(p, k - i);
333  }
334  }
335 
336  for (IndexType p = 0; p < NumberOfNonzeroControlPoints(); p++) {
337  ShapeFunctionValue(p, k) /= weightedSums[0];
338  }
339  }
340  }
341 
343 
344 private:
347 
348  /*
349  * @brief Provides the shape function value depending to the derivative row and
350  * the index of the control point.
351  * For curves the indices for derivatives are as following:
352  * 0-> N | 1-> dN/de | 2-> ddN/dde | ...
353  */
354  double& ShapeFunctionValue(const IndexType NonzeroControlPointIndex, const IndexType DerivativeRow)
355  {
358  NonzeroControlPointIndex, DerivativeRow);
359 
360  return mValues[index];
361  }
362 
363  double& Ndu(const IndexType DerivativeRow, const IndexType NonzeroControlPointIndex)
364  {
366  NumberOfNonzeroControlPoints(), NumberOfShapeFunctionRows(), NonzeroControlPointIndex, DerivativeRow);
367 
368  return mNdu[index];
369  }
370 
371  /*
372  * @brief resets the shape function container.
373  */
374  void ClearValues()
375  {
376  const SizeType number_of_values = NumberOfNonzeroControlPoints() * NumberOfShapeFunctionRows();
377 
378  mValues = ZeroVector(number_of_values);
379  }
380 
384 
385  SizeType mPolynomialDegree;
386  SizeType mDerivativeOrder;
387  Vector mValues;
388  Vector mLeft;
389  Vector mRight;
390  Vector mNdu;
391  Vector mA;
392  Vector mB;
393  IndexType mFirstNonzeroControlPoint;
394 
396 
397 };
399 
400 } // namespace Kratos
401 
402 #endif // KRATOS_NURBS_CURVE_SHAPE_FUNCTIONS_H_INCLUDED defined
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
NurbsCurveShapeFunction.
Definition: nurbs_curve_shape_functions.h:34
void ComputeNurbsShapeFunctionValuesAtSpan(const Vector &rKnots, const IndexType Span, const Vector &rWeights, const double ParameterT)
Definition: nurbs_curve_shape_functions.h:303
IndexType GetFirstNonzeroControlPoint() const
Definition: nurbs_curve_shape_functions.h:141
std::size_t SizeType
Definition: nurbs_curve_shape_functions.h:40
void ResizeDataContainers(const SizeType PolynomialDegree, const SizeType DerivativeOrder)
Definition: nurbs_curve_shape_functions.h:79
void ComputeBSplineShapeFunctionValuesAtSpan(const Vector &rKnots, const IndexType Span, const double ParameterT)
Definition: nurbs_curve_shape_functions.h:188
SizeType NumberOfNonzeroControlPoints() const
Definition: nurbs_curve_shape_functions.h:108
SizeType NumberOfShapeFunctionRows() const
Definition: nurbs_curve_shape_functions.h:117
NurbsCurveShapeFunction()
Default constructor.
Definition: nurbs_curve_shape_functions.h:47
SizeType PolynomialDegree() const
Definition: nurbs_curve_shape_functions.h:98
double ShapeFunctionValue(const IndexType ControlPointIndex, const IndexType DerivativeRow) const
Definition: nurbs_curve_shape_functions.h:126
void ComputeNurbsShapeFunctionValues(const Vector &rKnots, const Vector &rWeights, const double ParameterT)
Definition: nurbs_curve_shape_functions.h:284
std::size_t IndexType
Definition: nurbs_curve_shape_functions.h:39
void ComputeBSplineShapeFunctionValues(const Vector &rKnots, const double ParameterT)
Definition: nurbs_curve_shape_functions.h:172
std::vector< IndexType > GetNonzeroControlPointIndices() const
Definition: nurbs_curve_shape_functions.h:149
NurbsCurveShapeFunction(const SizeType PolynomialDegree, const SizeType DerivativeOrder)
Definition: nurbs_curve_shape_functions.h:55
double operator()(const IndexType NonzeroControlPointIndex, const IndexType DerivativeRow) const
Definition: nurbs_curve_shape_functions.h:66
std::size_t IndexType
The definition of the index type.
Definition: key_hash.h:35
static constexpr SizeType GetBinomCoefficient(const SizeType N, const SizeType K) noexcept
Definition: nurbs_utilities.h:117
IndexType GetUpperSpan(const SizeType PolynomialDegree, const Vector &rKnots, const double ParameterT)
Definition: nurbs_utilities.h:50
static constexpr IndexType GetVectorIndexFromMatrixIndices(const SizeType NumberPerRow, const SizeType NumberPerColumn, const IndexType RowIndex, const IndexType ColumnIndex) noexcept
Definition: nurbs_utilities.h:133
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
Internals::Matrix< double, AMatrix::dynamic, 1 > Vector
Definition: amatrix_interface.h:472
float span
Definition: angle_finder.py:9
a
Definition: generate_stokes_twofluid_element.py:77
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
float temp
Definition: rotating_cone.py:85
p
Definition: sensitivityMatrix.py:52
integer i
Definition: TensorModule.f:17