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_surface_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_SURFACE_SHAPE_FUNCTIONS_H_INCLUDED )
16 #define KRATOS_NURBS_SURFACE_SHAPE_FUNCTIONS_H_INCLUDED
17 
18 // Project includes
21 
22 namespace Kratos
23 {
27 
31 {
32 public:
35 
36  typedef typename std::size_t IndexType;
37  typedef typename std::size_t SizeType;
38 
42 
45  {
46  };
47 
48  // Constructor using the degree u, degree v and the order of shape functions.
49  // This is required to make an optimized memory management.
54  {
56  }
57 
61  /* @brief Returns the number of shape function rows for a given order.
62  @param DerivativesOrder 0 the shape functions N only, 1 N and first derivatives, ...
63  Thus, for DerivativesOrder 0 the return value is 1, for 1 the return value is 3, ...
64  @return NumberOfShapeFunctionRows, shape functions are provided as:
65  N | dN/du, dN/dv | dN^2/du^2, dN^2/dn*dv, dN^2/dv^2 | ... */
66  static constexpr inline SizeType NumberOfShapeFunctionRows(const SizeType DerivativeOrder) noexcept
67  {
68  return (1 + DerivativeOrder) * (2 + DerivativeOrder) / 2;
69  }
70 
71  /* @brief Returns the index of the shape function row for a given derivative index.
72  @param DerivativesOrder 0 the shape functions N only, 1 N and first derivatives, ...
73  Thus, for DerivativesOrder 0 the return value is 1, for 1 the return value is 3, ...
74  @return NumberOfShapeFunctionRows, shape functions are provided as:
75  N | dN/du, dN/dv | dN^2/du^2, dN^2/dn*dv, dN^2/dv^2 | ... */
76  static constexpr inline IndexType IndexOfShapeFunctionRow(
77  const SizeType DerivativeOrderU,
78  const SizeType DerivativeOrderV) noexcept
79  {
80  return DerivativeOrderV + (DerivativeOrderU + DerivativeOrderV) *
81  (1 + DerivativeOrderU + DerivativeOrderV) / 2;
82  }
86 
87  double operator()(
88  const IndexType ControlPointIndex,
89  const IndexType DerivativeRow) const
90  {
91  return ShapeFunctionValue(ControlPointIndex, DerivativeRow);
92  }
93 
94  double operator()(
95  const IndexType ControlPointIndexU,
96  const IndexType ControlPointIndexV,
97  const IndexType DerivativeRow) const
98  {
99  return ShapeFunctionValue(ControlPointIndexU, ControlPointIndexV, DerivativeRow);
100  }
101 
109  {
110  const SizeType number_of_shape_function_rows = this->NumberOfShapeFunctionRows(DerivativeOrder);
111  const SizeType number_of_nonzero_control_points = (PolynomialDegreeU + 1) * (PolynomialDegreeV + 1);
112 
115  mShapeFunctionValues.resize(number_of_nonzero_control_points * number_of_shape_function_rows);
116  mWeightedSums.resize(number_of_shape_function_rows);
117 
118  mDerivativeOrder = DerivativeOrder;
119  }
120 
122  {
123  return mShapeFunctionsU.PolynomialDegree();
124  }
125 
127  {
128  return mShapeFunctionsV.PolynomialDegree();
129  }
130 
132  {
133  return mDerivativeOrder;
134  }
135 
137  {
139  }
140 
142  {
143  return mShapeFunctionsU.NumberOfNonzeroControlPoints();
144  }
145 
147  {
148  return mShapeFunctionsV.NumberOfNonzeroControlPoints();
149  }
150 
152  {
154  }
155 
156  std::vector<std::pair<int, int>> NonzeroControlPointIndices() const
157  {
158  std::vector<std::pair<int, int>> indices(NumberOfNonzeroControlPoints());
159 
160  for (IndexType i = 0; i < NumberOfNonzeroControlPointsU(); i++) {
161  for (IndexType j = 0; j < NumberOfNonzeroControlPointsV(); j++) {
164 
167 
168  indices[poleIndex] = { poleU, poleV };
169  }
170  }
171 
172  return indices;
173  }
174 
175  std::vector<int> ControlPointIndices(
176  SizeType NumberOfControlPointsU, SizeType NumberOfControlPointsV) const
177  {
178  std::vector<int> indices(NumberOfNonzeroControlPoints());
179 
180  for (IndexType i = 0; i < NumberOfNonzeroControlPointsU(); i++) {
181  for (IndexType j = 0; j < NumberOfNonzeroControlPointsV(); j++) {
184 
185  IndexType cp_index_u = GetFirstNonzeroControlPointU() + i;
186  IndexType cp_index_v = GetFirstNonzeroControlPointV() + j;
187 
189  NumberOfControlPointsU, NumberOfControlPointsV, cp_index_u, cp_index_v);
190  }
191  }
192 
193  return indices;
194  }
195 
197  const IndexType ControlPointIndexU,
198  const IndexType ControlPointIndexV,
199  const SizeType DerivativeRow) const
200  {
201  const IndexType index = this->GetIndex(
202  ControlPointIndexU,
203  ControlPointIndexV,
204  DerivativeRow);
205 
206  KRATOS_DEBUG_ERROR_IF(index >= mShapeFunctionValues.size()) << "Index exceeds size of shape function values. Index: "
207  << index << ", mShapeFunctionValues.size(): " << mShapeFunctionValues.size()
208  << ", ControlPointIndexU: " << ControlPointIndexU << ", ControlPointIndexV: " << ControlPointIndexV
209  << ", DerivativeRow: " << DerivativeRow << std::endl;
210 
211  return mShapeFunctionValues[index];
212  }
213 
215  const IndexType ControlPointIndex,
216  const SizeType DerivativeOrder) const
217  {
220  DerivativeOrder, ControlPointIndex);
221 
222  KRATOS_DEBUG_ERROR_IF(index >= mShapeFunctionValues.size()) << "Index exceeds size of shape function values. Index: "
223  << index << ", mShapeFunctionValues.size(): " << mShapeFunctionValues.size()
224  << ", ControlPointIndex: " << ControlPointIndex << ", DerivativeOrder: " << DerivativeOrder << std::endl;
225 
226  return mShapeFunctionValues[index];
227  }
228 
230  {
231  return mFirstNonzeroControlPointU;
232  }
233 
235  {
237  }
238 
240  {
241  return mFirstNonzeroControlPointV;
242  }
243 
245  {
247  }
248 
250  const Vector& rKnotsU,
251  const Vector& rKnotsV,
252  const int SpanU,
253  const int SpanV,
254  const double ParameterU,
255  const double ParameterV)
256  {
257  mShapeFunctionValues = ZeroVector(mShapeFunctionValues.size());
258 
259  mFirstNonzeroControlPointU = SpanU - PolynomialDegreeU() + 1;
260  mFirstNonzeroControlPointV = SpanV - PolynomialDegreeV() + 1;
261 
262  // compute 1D shape functions
263  mShapeFunctionsU.ComputeBSplineShapeFunctionValuesAtSpan(rKnotsU, SpanU, ParameterU);
264  mShapeFunctionsV.ComputeBSplineShapeFunctionValuesAtSpan(rKnotsV, SpanV, ParameterV);
265 
266  // compute 2D shape functions
267  for (IndexType i = 0; i <= DerivativeOrder(); i++) {
268  for (IndexType j = 0; j <= DerivativeOrder() - i; j++) {
269  for (IndexType a = 0; a < NumberOfNonzeroControlPointsU(); a++) {
270  for (IndexType b = 0; b < NumberOfNonzeroControlPointsV(); b++) {
271  const IndexType index = IndexOfShapeFunctionRow(i, j);
272 
273  ShapeFunctionValue(a, b, index) = mShapeFunctionsU(a, i) * mShapeFunctionsV(b, j);
274  }
275  }
276  }
277  }
278  }
279 
281  const Vector& rKnotsU,
282  const Vector& rKnotsV,
283  const double ParameterU,
284  const double ParameterV)
285  {
286  const IndexType SpanU = NurbsUtilities::GetLowerSpan(PolynomialDegreeU(), rKnotsU, ParameterU);
287  const IndexType SpanV = NurbsUtilities::GetLowerSpan(PolynomialDegreeV(), rKnotsV, ParameterV);
288 
290  rKnotsU,
291  rKnotsV,
292  SpanU,
293  SpanV,
294  ParameterU,
295  ParameterV);
296  }
297 
299  const Vector& rKnotsU,
300  const Vector& rKnotsV,
301  const IndexType SpanU,
302  const IndexType SpanV,
303  const Vector& Weights,
304  const double ParameterU,
305  const double ParameterV)
306  {
307  // Check input
308  KRATOS_DEBUG_ERROR_IF(Weights.size() !=
311  << "Number of controls points and polynomial degrees and number of knots do not match!" << std::endl;
312 
313  // compute B-Spline shape functions
315  rKnotsU, rKnotsV, SpanU, SpanV, ParameterU, ParameterV);
316 
317  // apply weights
318  for (IndexType shape_row_index = 0; shape_row_index < NumberOfShapeFunctionRows(); shape_row_index++) {
319  GetWeightedSum(shape_row_index) = double(0);
320 
321  for (IndexType u = 0; u < NumberOfNonzeroControlPointsU(); u++) {
322  for (IndexType v = 0; v < NumberOfNonzeroControlPointsV(); v++) {
323  const IndexType ControlPointIndexU = GetFirstNonzeroControlPointU() + u;
324  const IndexType ControlPointIndexV = GetFirstNonzeroControlPointV() + v;
325 
326  const double weight = Weights(GetControlPointIndex(rKnotsU.size(), rKnotsV.size(), ControlPointIndexU, ControlPointIndexV));
327  ShapeFunctionValue(u, v, shape_row_index) *= weight;
328  GetWeightedSum(shape_row_index) += ShapeFunctionValue(u, v, shape_row_index);
329  }
330  }
331  }
332 
333  for (IndexType k = 0; k <= DerivativeOrder(); k++) {
334  for (IndexType l = 0; l <= DerivativeOrder() - k; l++) {
335  const IndexType shape = IndexOfShapeFunctionRow(k, l);
336 
337  for (IndexType j = 1; j <= l; j++) {
338  const IndexType index = IndexOfShapeFunctionRow(k, l - j);
339 
340  double a = NurbsUtilities::GetBinomCoefficient(l, j) * GetWeightedSum(0, j);
341 
342  for (IndexType p = 0; p < NumberOfNonzeroControlPoints(); p++) {
343  ShapeFunctionValue(p, shape) -= a * ShapeFunctionValue(p, index);
344  }
345  }
346 
347  for (IndexType i = 1; i <= k; i++) {
348  const IndexType index = IndexOfShapeFunctionRow(k - i, l);
349 
350  double a = NurbsUtilities::GetBinomCoefficient(k, i) * GetWeightedSum(i, 0);
351 
352  for (IndexType p = 0; p < NumberOfNonzeroControlPoints(); p++) {
353  ShapeFunctionValue(p, shape) -= a * ShapeFunctionValue(p, index);
354  }
355  }
356 
357  for (IndexType i = 1; i <= k; i++) {
358  const double a = NurbsUtilities::GetBinomCoefficient(k, i);
359 
360  for (IndexType j = 1; j <= l; j++) {
361  const IndexType index = IndexOfShapeFunctionRow(k - i, l - j);
362 
363  const double b = a * NurbsUtilities::GetBinomCoefficient(l, j) *
364  GetWeightedSum(i, j);
365 
366  for (IndexType p = 0; p < NumberOfNonzeroControlPoints(); p++) {
367  ShapeFunctionValue(p, shape) -= b * ShapeFunctionValue(p, index);
368  }
369  }
370  }
371 
372  for (IndexType p = 0; p < NumberOfNonzeroControlPoints(); p++) {
373  ShapeFunctionValue(p, shape) /= GetWeightedSum(0);
374  }
375  }
376  }
377  }
378 
380  const Vector& rKnotsU,
381  const Vector& rKnotsV,
382  const Vector& Weights,
383  const double ParameterU,
384  const double ParameterV)
385  {
386  const IndexType SpanU = NurbsUtilities::GetLowerSpan(PolynomialDegreeU(), rKnotsU, ParameterU);
387  const IndexType SpanV = NurbsUtilities::GetLowerSpan(PolynomialDegreeV(), rKnotsV, ParameterV);
388 
390  rKnotsU, rKnotsV, SpanU, SpanV, Weights, ParameterU, ParameterV);
391  }
393 private:
396  double& GetWeightedSum(const IndexType Index)
397  {
398  return mWeightedSums[Index];
399  }
400 
401  double& GetWeightedSum(const SizeType DerivativeOrderU, const SizeType DerivativeOrderV)
402  {
403  const int index = IndexOfShapeFunctionRow(DerivativeOrderU, DerivativeOrderV);
404 
405  return GetWeightedSum(index);
406  }
407 
408  inline int GetControlPointIndex(
409  const SizeType NumberOfKnotsU,
410  const SizeType NumberOfKnotsV,
411  const IndexType ControlPointIndexU,
412  const IndexType ControlPointIndexV)
413  const
414  {
418  ControlPointIndexU, ControlPointIndexV);
419  }
420 
421  inline int GetNonzeroControlPointIndex(
422  const IndexType ControlPointIndexU,
423  const IndexType ControlPointIndexV)
424  const
425  {
428  ControlPointIndexU, ControlPointIndexV);
429  }
430 
431  inline int GetIndex(
432  const IndexType ControlPointIndexU,
433  const IndexType ControlPointIndexV,
434  const SizeType DerivativeRow)
435  const
436  {
437  const IndexType control_point_index = GetNonzeroControlPointIndex(
438  ControlPointIndexU, ControlPointIndexV);
441  DerivativeRow, control_point_index);
442 
443  return index;
444  }
445 
446  double& ShapeFunctionValue(
447  const IndexType ControlPointIndex,
448  const IndexType DerivativeRow)
449  {
452  DerivativeRow, ControlPointIndex);
453 
454  return mShapeFunctionValues[index];
455  }
456 
457  double& ShapeFunctionValue(
458  const IndexType ControlPointIndexU,
459  const IndexType ControlPointIndexV,
460  const SizeType DerivativeRow)
461  {
462  const IndexType index = this->GetIndex(ControlPointIndexU, ControlPointIndexV, DerivativeRow);
463 
464  return mShapeFunctionValues[index];
465  }
466 
470  int mDerivativeOrder;
471  NurbsCurveShapeFunction mShapeFunctionsU;
472  NurbsCurveShapeFunction mShapeFunctionsV;
473  Vector mWeightedSums;
474  Vector mShapeFunctionValues;
475  IndexType mFirstNonzeroControlPointU;
476  IndexType mFirstNonzeroControlPointV;
478  }; // class NurbsSurfaceShapeFunction
479 
480 } // namespace Kratos
481 
482 #endif // KRATOS_NURBS_SURFACE_SHAPE_FUNCTIONS_H_INCLUDED defined
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
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 PolynomialDegree() const
Definition: nurbs_curve_shape_functions.h:98
Definition: nurbs_surface_shape_functions.h:31
double ShapeFunctionValue(const IndexType ControlPointIndexU, const IndexType ControlPointIndexV, const SizeType DerivativeRow) const
Definition: nurbs_surface_shape_functions.h:196
void ComputeBSplineShapeFunctionValuesAtSpan(const Vector &rKnotsU, const Vector &rKnotsV, const int SpanU, const int SpanV, const double ParameterU, const double ParameterV)
Definition: nurbs_surface_shape_functions.h:249
void ResizeDataContainers(const SizeType PolynomialDegreeU, const SizeType PolynomialDegreeV, const SizeType DerivativeOrder)
Definition: nurbs_surface_shape_functions.h:105
IndexType GetLastNonzeroControlPointV() const
Definition: nurbs_surface_shape_functions.h:244
NurbsSurfaceShapeFunction(const SizeType PolynomialDegreeU, const SizeType PolynomialDegreeV, const SizeType DerivativeOrder)
Definition: nurbs_surface_shape_functions.h:50
void ComputeNurbsShapeFunctionValues(const Vector &rKnotsU, const Vector &rKnotsV, const Vector &Weights, const double ParameterU, const double ParameterV)
Definition: nurbs_surface_shape_functions.h:379
std::vector< int > ControlPointIndices(SizeType NumberOfControlPointsU, SizeType NumberOfControlPointsV) const
Definition: nurbs_surface_shape_functions.h:175
std::vector< std::pair< int, int > > NonzeroControlPointIndices() const
Definition: nurbs_surface_shape_functions.h:156
double operator()(const IndexType ControlPointIndex, const IndexType DerivativeRow) const
Definition: nurbs_surface_shape_functions.h:87
static constexpr SizeType NumberOfShapeFunctionRows(const SizeType DerivativeOrder) noexcept
Definition: nurbs_surface_shape_functions.h:66
double operator()(const IndexType ControlPointIndexU, const IndexType ControlPointIndexV, const IndexType DerivativeRow) const
Definition: nurbs_surface_shape_functions.h:94
SizeType NumberOfNonzeroControlPointsV() const
Definition: nurbs_surface_shape_functions.h:146
NurbsSurfaceShapeFunction()
Default constructor.
Definition: nurbs_surface_shape_functions.h:44
void ComputeNurbsShapeFunctionValuesAtSpan(const Vector &rKnotsU, const Vector &rKnotsV, const IndexType SpanU, const IndexType SpanV, const Vector &Weights, const double ParameterU, const double ParameterV)
Definition: nurbs_surface_shape_functions.h:298
std::size_t IndexType
Definition: nurbs_surface_shape_functions.h:36
SizeType NumberOfNonzeroControlPointsU() const
Definition: nurbs_surface_shape_functions.h:141
IndexType GetFirstNonzeroControlPointU() const
Definition: nurbs_surface_shape_functions.h:229
static constexpr IndexType IndexOfShapeFunctionRow(const SizeType DerivativeOrderU, const SizeType DerivativeOrderV) noexcept
Definition: nurbs_surface_shape_functions.h:76
SizeType PolynomialDegreeV() const
Definition: nurbs_surface_shape_functions.h:126
std::size_t SizeType
Definition: nurbs_surface_shape_functions.h:37
SizeType PolynomialDegreeU() const
Definition: nurbs_surface_shape_functions.h:121
IndexType GetLastNonzeroControlPointU() const
Definition: nurbs_surface_shape_functions.h:234
IndexType GetFirstNonzeroControlPointV() const
Definition: nurbs_surface_shape_functions.h:239
SizeType NumberOfNonzeroControlPoints() const
Definition: nurbs_surface_shape_functions.h:151
SizeType DerivativeOrder() const
Definition: nurbs_surface_shape_functions.h:131
double ShapeFunctionValue(const IndexType ControlPointIndex, const SizeType DerivativeOrder) const
Definition: nurbs_surface_shape_functions.h:214
SizeType NumberOfShapeFunctionRows() const
Definition: nurbs_surface_shape_functions.h:136
void ComputeBSplineShapeFunctionValues(const Vector &rKnotsU, const Vector &rKnotsV, const double ParameterU, const double ParameterV)
Definition: nurbs_surface_shape_functions.h:280
std::size_t IndexType
The definition of the index type.
Definition: key_hash.h:35
#define KRATOS_DEBUG_ERROR_IF(conditional)
Definition: exception.h:171
IndexType GetLowerSpan(const SizeType PolynomialDegree, const Vector &rKnots, const double ParameterT)
Definition: nurbs_utilities.h:64
SizeType GetNumberOfControlPoints(const SizeType PolynomialDegree, const SizeType NumberOfKnots)
Definition: nurbs_utilities.h:99
static constexpr SizeType GetBinomCoefficient(const SizeType N, const SizeType K) noexcept
Definition: nurbs_utilities.h:117
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
TABLE_NUMBER_ANGULAR_VELOCITY TABLE_NUMBER_MOMENT I33 BEAM_INERTIA_ROT_UNIT_LENGHT_Y KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, BEAM_INERTIA_ROT_UNIT_LENGHT_Z) typedef std double
Definition: DEM_application_variables.h:182
v
Definition: generate_convection_diffusion_explicit_element.py:114
a
Definition: generate_stokes_twofluid_element.py:77
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
u
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:30
def Index()
Definition: hdf5_io_tools.py:38
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
p
Definition: sensitivityMatrix.py:52
integer i
Definition: TensorModule.f:17
integer l
Definition: TensorModule.f:17