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_geometry.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_GEOMETRY_H_INCLUDED )
16 #define KRATOS_NURBS_SURFACE_GEOMETRY_H_INCLUDED
17 
18 // System includes
19 
20 // External includes
21 
22 // Project includes
23 #include "geometries/geometry.h"
24 
28 
31 
33 
34 namespace Kratos {
35 
36 template <int TWorkingSpaceDimension, class TContainerPointType>
37 class NurbsSurfaceGeometry : public Geometry<typename TContainerPointType::value_type>
38 {
39 public:
42 
43  typedef typename TContainerPointType::value_type NodeType;
44 
46 
47  typedef typename BaseType::IndexType IndexType;
48  typedef typename BaseType::SizeType SizeType;
49 
54 
55  // using base class functionalities.
57  using BaseType::pGetPoint;
58  using BaseType::GetPoint;
59 
62 
66 
69  const PointsArrayType& rThisPoints,
72  const Vector& rKnotsU,
73  const Vector& rKnotsV)
74  : BaseType(rThisPoints, &msGeometryData)
75  , mPolynomialDegreeU(PolynomialDegreeU)
76  , mPolynomialDegreeV(PolynomialDegreeV)
77  , mKnotsU(rKnotsU)
78  , mKnotsV(rKnotsV)
79  {
80  CheckAndFitKnotVectors();
81  }
82 
85  const PointsArrayType& rThisPoints,
88  const Vector& rKnotsU,
89  const Vector& rKnotsV,
90  const Vector& rWeights)
91  : BaseType(rThisPoints, &msGeometryData)
92  , mPolynomialDegreeU(PolynomialDegreeU)
93  , mPolynomialDegreeV(PolynomialDegreeV)
94  , mKnotsU(rKnotsU)
95  , mKnotsV(rKnotsV)
96  , mWeights(rWeights)
97  {
98  CheckAndFitKnotVectors();
99 
100  KRATOS_ERROR_IF(rWeights.size() != rThisPoints.size())
101  << "Number of control points and weights do not match!" << std::endl;
102  }
103 
104  explicit NurbsSurfaceGeometry(const PointsArrayType& ThisPoints)
105  : BaseType(ThisPoints, &msGeometryData)
106  {
107  }
108 
111  : BaseType(rOther)
112  , mPolynomialDegreeU(rOther.mPolynomialDegreeU)
113  , mPolynomialDegreeV(rOther.mPolynomialDegreeV)
114  , mKnotsU(rOther.mKnotsU)
115  , mKnotsV(rOther.mKnotsV)
116  , mWeights(rOther.mWeights)
117  , mpGeometryParent(rOther.mpGeometryParent)
118  {
119  }
120 
122  template<class TOtherContainerPointType> NurbsSurfaceGeometry(
124  : BaseType(rOther, &msGeometryData)
125  , mPolynomialDegreeU(rOther.mPolynomialDegreeU)
126  , mPolynomialDegreeV(rOther.mPolynomialDegreeV)
127  , mKnotsU(rOther.mKnotsU)
128  , mKnotsV(rOther.mKnotsV)
129  , mWeights(rOther.mWeights)
130  , mpGeometryParent(rOther.mpGeometryParent)
131  {
132  }
133 
135  ~NurbsSurfaceGeometry() override = default;
136 
140 
143  {
144  BaseType::operator=(rOther);
145  mPolynomialDegreeU = rOther.mPolynomialDegreeU;
146  mPolynomialDegreeV = rOther.mPolynomialDegreeV;
147  mKnotsU = rOther.mKnotsU;
148  mKnotsV = rOther.mKnotsV;
149  mWeights = rOther.mWeights;
150  mpGeometryParent = rOther.mpGeometryParent;
151  return *this;
152  }
153 
155  template<class TOtherContainerPointType>
158  {
159  BaseType::operator=(rOther);
160  mPolynomialDegreeU = rOther.mPolynomialDegreeU;
161  mPolynomialDegreeV = rOther.mPolynomialDegreeV;
162  mKnotsU = rOther.mKnotsU;
163  mKnotsV = rOther.mKnotsV;
164  mWeights = rOther.mWeights;
165  mpGeometryParent = rOther.mpGeometryParent;
166  return *this;
167  }
168 
172 
173  typename BaseType::Pointer Create(
174  PointsArrayType const& ThisPoints) const override
175  {
176  return Kratos::make_shared<NurbsSurfaceGeometry>(ThisPoints);
177  }
178 
182 
184  {
185  return *mpGeometryParent;
186  }
187 
188  void SetGeometryParent(BaseType* pGeometryParent) override
189  {
190  mpGeometryParent = pGeometryParent;
191  }
192 
196 
198  SizeType PointsNumberInDirection(IndexType LocalDirectionIndex) const override
199  {
200  if (LocalDirectionIndex == 0) {
201  return this->NumberOfControlPointsU();
202  }
203  else if (LocalDirectionIndex == 1) {
204  return this->NumberOfControlPointsV();
205  }
206  KRATOS_ERROR << "Possible direction index in NurbsSurfaceGeometry reaches from 0-1. Given direction index: "
207  << LocalDirectionIndex << std::endl;
208  }
209 
213 
215  SizeType PolynomialDegree(IndexType LocalDirectionIndex) const override
216  {
217  KRATOS_DEBUG_ERROR_IF(LocalDirectionIndex > 1)
218  << "Trying to access polynomial degree in direction " << LocalDirectionIndex
219  << " from NurbsSurfaceGeometry #" << this->Id() << ". Nurbs surfaces have only two directions."
220  << std::endl;
221 
222  if (LocalDirectionIndex == 0) {
223  return mPolynomialDegreeU;
224  }
225  else {
226  return mPolynomialDegreeV;
227  }
228  }
229 
233 
235  void Calculate(
236  const Variable<array_1d<double, 3>>& rVariable,
237  array_1d<double, 3>& rOutput) const override
238  {
239  if (rVariable == CHARACTERISTIC_GEOMETRY_LENGTH)
240  {
241  const CoordinatesArrayType local_coordinates = rOutput;
242  CalculateEstimatedKnotLengthness(rOutput, local_coordinates);
243  }
244  }
245 
249 
251  const PointsArrayType& rThisPoints,
254  const Vector& rKnotsU,
255  const Vector& rKnotsV,
256  const Vector& rWeights)
257  {
258  this->Points() = rThisPoints;
259  mPolynomialDegreeU = PolynomialDegreeU;
260  mPolynomialDegreeV = PolynomialDegreeV;
261  mKnotsU = rKnotsU;
262  mKnotsV = rKnotsV;
263  mWeights = rWeights;
264 
265  CheckAndFitKnotVectors();
266 
267  KRATOS_ERROR_IF(rWeights.size() != rThisPoints.size())
268  << "Number of control points and weights do not match!" << std::endl;
269  }
270 
273  {
274  return mPolynomialDegreeU;
275  }
276 
279  {
280  return mPolynomialDegreeV;
281  }
282 
283  /* Get Knot vector in u-direction. This vector is defined to have
284  a multiplicity of p at the beginning and end (NOT: p + 1).
285  @return knot vector. */
286  const Vector& KnotsU() const
287  {
288  return mKnotsU;
289  }
290 
291  /* Get Knot vector in v-direction. This vector is defined to have
292  a multiplicity of p at the beginning and end (NOT: p + 1).
293  @return knot vector. */
294  const Vector& KnotsV() const
295  {
296  return mKnotsV;
297  }
298 
301  {
302  return mKnotsU.size();
303  }
304 
307  {
308  return mKnotsV.size();
309  }
310 
311  /* Checks if shape functions are rational or not.
312  * @return true if NURBS, false if B-Splines only (all weights are considered as 1) */
313  bool IsRational() const
314  {
315  if (mWeights.size() == 0)
316  return false;
317  else {
318  for (IndexType i = 0; i < mWeights.size(); ++i) {
319  if (std::abs(mWeights[i] - 1.0) > 1e-8) {
320  return true;
321  }
322  }
323  return false;
324  }
325  }
326 
327  /* Get Weights vector. All values are 1.0 for B-Splines, for NURBS those can be unequal 1.0.
328  * @return weights vector.
329  */
330  const Vector& Weights() const
331  {
332  return mWeights;
333  }
334 
336  {
337  return NumberOfKnotsU() - PolynomialDegreeU() + 1;
338  }
339 
341  {
342  return NumberOfKnotsV() - PolynomialDegreeV() + 1;
343  }
344 
346  SizeType NumberOfKnotSpans(IndexType DirectionIndex) const
347  {
348  SizeType knot_span_counter = 0;
349  if (DirectionIndex == 0) {
350  for (IndexType i = 0; i < mKnotsU.size() - 1; i++) {
351  if (std::abs(mKnotsU[i] - mKnotsU[i + 1]) > 1e-6) {
352  knot_span_counter++;
353  }
354  }
355  }
356  else if (DirectionIndex == 1) {
357  for (IndexType i = 0; i < mKnotsV.size() - 1; i++) {
358  if (std::abs(mKnotsV[i] - mKnotsV[i + 1]) > 1e-6) {
359  knot_span_counter++;
360  }
361  }
362  } else {
363  KRATOS_ERROR << "NurbsSurfaceGeometry::NumberOfKnotSpans: Direction index: "
364  << DirectionIndex << " not available. Options are: 0 and 1." << std::endl;
365  }
366  return knot_span_counter;
367  }
368 
369  /* @brief Provides all knot spans within direction u.
370  * @param return vector of span intervals.
371  * @param index of direction: 0: U; 1: V.
372  */
373  void SpansLocalSpace(std::vector<double>& rSpans, IndexType DirectionIndex) const override
374  {
375  rSpans.resize(this->NumberOfKnotSpans(DirectionIndex) + 1);
376 
377  if (DirectionIndex == 0) {
378  rSpans[0] = mKnotsU[0];
379 
380  IndexType counter = 1;
381  for (IndexType i = 0; i < mKnotsU.size() - 1; i++) {
382  if (std::abs(mKnotsU[i] - mKnotsU[i + 1]) > 1e-6) {
383  rSpans[counter] = mKnotsU[i + 1];
384  counter++;
385  }
386  }
387  }
388  else if (DirectionIndex == 1) {
389  rSpans[0] = mKnotsV[0];
390 
391  IndexType counter = 1;
392  for (IndexType i = 0; i < mKnotsV.size() - 1; i++) {
393  if (std::abs(mKnotsV[i] - mKnotsV[i + 1]) > 1e-6) {
394  rSpans[counter] = mKnotsV[i + 1];
395  counter++;
396  }
397  }
398  } else {
399  KRATOS_ERROR << "NurbsSurfaceGeometry::Spans: Direction index: "
400  << DirectionIndex << " not available. Options are: 0 and 1." << std::endl;
401  }
402  }
403 
404  /* Provides the natural boundaries of the NURBS/B-Spline surface.
405  * @return domain interval.
406  */
408  {
409  return NurbsInterval(
410  mKnotsU[mPolynomialDegreeU - 1],
411  mKnotsU[NumberOfKnotsU() - mPolynomialDegreeU]);
412  }
413 
414  /* Provides the natural boundaries of the NURBS/B-Spline surface.
415  * @return domain interval.
416  */
418  {
419  return NurbsInterval(
420  mKnotsV[mPolynomialDegreeV - 1],
421  mKnotsV[NumberOfKnotsV() - mPolynomialDegreeV]);
422  }
423 
424  /* Provides all knot span intervals of the surface in u-direction.
425  * @return vector of knot span intervals.
426  */
427  std::vector<NurbsInterval> KnotSpanIntervalsU() const
428  {
429  const SizeType first_span = mPolynomialDegreeU - 1;
430  const SizeType last_span = NumberOfKnotsU() - mPolynomialDegreeU - 1;
431 
432  const SizeType number_of_spans = last_span - first_span + 1;
433 
434  std::vector<NurbsInterval> result(number_of_spans);
435 
436  for (IndexType i = 0; i < number_of_spans; i++) {
437  const double t0 = mKnotsU[first_span + i];
438  const double t1 = mKnotsU[first_span + i + 1];
439 
440  result[i] = NurbsInterval(t0, t1);
441  }
442 
443  return result;
444  }
445 
446  /* Provides all knot span intervals of the surface in u-direction.
447  * @return vector of knot span intervals.
448  */
449  std::vector<NurbsInterval> KnotSpanIntervalsV() const
450  {
451  const SizeType first_span = mPolynomialDegreeV - 1;
452  const SizeType last_span = NumberOfKnotsV() - mPolynomialDegreeV - 1;
453 
454  const SizeType number_of_spans = last_span - first_span + 1;
455 
456  std::vector<NurbsInterval> result(number_of_spans);
457 
458  for (IndexType i = 0; i < number_of_spans; i++) {
459  const double t0 = mKnotsV[first_span + i];
460  const double t1 = mKnotsV[first_span + i + 1];
461 
462  result[i] = NurbsInterval(t0, t1);
463  }
464 
465  return result;
466  }
467 
469  CoordinatesArrayType& rKnotLengthness,
470  const CoordinatesArrayType& rLocalCoordinates) const
471  {
472  const IndexType SpanU = NurbsUtilities::GetLowerSpan(PolynomialDegreeU(), KnotsU(), rLocalCoordinates[0]);
473  const IndexType SpanV = NurbsUtilities::GetLowerSpan(PolynomialDegreeV(), KnotsV(), rLocalCoordinates[1]);
474 
475  CoordinatesArrayType p1, p2, p3, p4;
476  CoordinatesArrayType gp1, gp2, gp3, gp4;
477  p1[0] = mKnotsU[SpanU];
478  p1[1] = mKnotsV[SpanV];
479  p1[2] = 0;
480 
481  p2[0] = mKnotsU[SpanU + 1];
482  p2[1] = mKnotsV[SpanV];
483  p2[2] = 0;
484 
485  p3[0] = mKnotsU[SpanU + 1];
486  p3[1] = mKnotsV[SpanV + 1];
487  p3[2] = 0;
488 
489  p4[0] = mKnotsU[SpanU];
490  p4[1] = mKnotsV[SpanV + 1];
491  p4[2] = 0;
492 
493  GlobalCoordinates(gp1, p1);
494  GlobalCoordinates(gp2, p2);
495  GlobalCoordinates(gp3, p3);
496  GlobalCoordinates(gp4, p4);
497 
498  rKnotLengthness[0] = (norm_2(gp1 - gp2) + norm_2(gp3 - gp4)) / 2;
499  rKnotLengthness[1] = (norm_2(gp1 - gp4) + norm_2(gp2 - gp3)) / 2;
500  rKnotLengthness[2] = 0;
501  }
502 
506 
509  {
510  return IntegrationInfo(
511  { PolynomialDegreeU() + 1, PolynomialDegreeV() + 1 },
513  }
514 
518 
519  /* Creates integration points according to the polynomial degrees.
520  * @param return integration points.
521  */
523  IntegrationPointsArrayType& rIntegrationPoints,
524  IntegrationInfo& rIntegrationInfo) const override
525  {
526  const SizeType points_in_u = PolynomialDegreeU() + 1;
527  const SizeType points_in_v = PolynomialDegreeV() + 1;
528 
530  rIntegrationPoints, points_in_u, points_in_v);
531  }
532 
533  /* Creates integration points according to the input parameter.
534  * @param return integration points.
535  * @param points in u direction per span.
536  * @param points in v direction per span.
537  */
539  IntegrationPointsArrayType& rIntegrationPoints,
540  SizeType NumPointsPerSpanU,
541  SizeType NumPointsPerSpanV) const
542  {
543  auto knot_span_intervals_u = KnotSpanIntervalsU();
544  auto knot_span_intervals_v = KnotSpanIntervalsV();
545 
546  const SizeType number_of_integration_points =
547  knot_span_intervals_u.size() * knot_span_intervals_v.size()
548  * NumPointsPerSpanU * NumPointsPerSpanV;
549 
550  if (rIntegrationPoints.size() != number_of_integration_points) {
551  rIntegrationPoints.resize(number_of_integration_points);
552  }
553 
554  typename IntegrationPointsArrayType::iterator integration_point_iterator = rIntegrationPoints.begin();
555 
556  for (IndexType i = 0; i < knot_span_intervals_u.size(); ++i) {
557  for (IndexType j = 0; j < knot_span_intervals_v.size(); ++j) {
559  integration_point_iterator,
560  NumPointsPerSpanU, NumPointsPerSpanV,
561  knot_span_intervals_u[i].GetT0(), knot_span_intervals_u[i].GetT1(),
562  knot_span_intervals_v[j].GetT0(), knot_span_intervals_v[j].GetT1());
563  }
564  }
565  }
566 
570 
571  /* @brief creates a list of quadrature point geometries
572  * from a list of integration points.
573  *
574  * @param rResultGeometries list of quadrature point geometries.
575  * @param rIntegrationPoints list of provided integration points.
576  * @param NumberOfShapeFunctionDerivatives the number of evaluated
577  * derivatives of shape functions at the quadrature point geometries.
578  *
579  * @see quadrature_point_geometry.h
580  */
582  GeometriesArrayType& rResultGeometries,
583  IndexType NumberOfShapeFunctionDerivatives,
584  const IntegrationPointsArrayType& rIntegrationPoints,
585  IntegrationInfo& rIntegrationInfo) override
586  {
587  // shape function container.
588  NurbsSurfaceShapeFunction shape_function_container(
589  mPolynomialDegreeU, mPolynomialDegreeV, NumberOfShapeFunctionDerivatives);
590 
591  // Resize containers.
592  if (rResultGeometries.size() != rIntegrationPoints.size())
593  rResultGeometries.resize(rIntegrationPoints.size());
594 
595  auto default_method = this->GetDefaultIntegrationMethod();
596  SizeType num_nonzero_cps = shape_function_container.NumberOfNonzeroControlPoints();
597 
598  Matrix N(1, num_nonzero_cps);
599  DenseVector<Matrix> shape_function_derivatives(NumberOfShapeFunctionDerivatives - 1);
600  for (IndexType i = 0; i < NumberOfShapeFunctionDerivatives - 1; i++) {
601  shape_function_derivatives[i].resize(num_nonzero_cps, i + 2);
602  }
603 
604  for (IndexType i = 0; i < rIntegrationPoints.size(); ++i)
605  {
606  if (IsRational()) {
607  shape_function_container.ComputeNurbsShapeFunctionValues(
608  mKnotsU, mKnotsV, mWeights, rIntegrationPoints[i][0], rIntegrationPoints[i][1]);
609  }
610  else {
611  shape_function_container.ComputeBSplineShapeFunctionValues(
612  mKnotsU, mKnotsV, rIntegrationPoints[i][0], rIntegrationPoints[i][1]);
613  }
614 
616  PointsArrayType nonzero_control_points(num_nonzero_cps);
617  auto cp_indices = shape_function_container.ControlPointIndices(
619  for (IndexType j = 0; j < num_nonzero_cps; j++) {
620  nonzero_control_points(j) = pGetPoint(cp_indices[j]);
621  }
623  for (IndexType j = 0; j < num_nonzero_cps; j++) {
624  N(0, j) = shape_function_container(j, 0);
625  }
626 
628  if (NumberOfShapeFunctionDerivatives > 0) {
629  IndexType shape_derivative_index = 1;
630  for (IndexType n = 0; n < NumberOfShapeFunctionDerivatives - 1; n++) {
631  for (IndexType k = 0; k < n + 2; k++) {
632  for (IndexType j = 0; j < num_nonzero_cps; j++) {
633  shape_function_derivatives[n](j, k) = shape_function_container(j, shape_derivative_index + k);
634  }
635  }
636  shape_derivative_index += n + 2;
637  }
638  }
639 
641  default_method, rIntegrationPoints[i],
642  N, shape_function_derivatives);
643 
645  this->WorkingSpaceDimension(), 2, data_container, nonzero_control_points, this);
646  }
647  }
648 
652 
681  const CoordinatesArrayType& rPointGlobalCoordinates,
682  CoordinatesArrayType& rProjectedPointLocalCoordinates,
683  const double Tolerance = std::numeric_limits<double>::epsilon()
684  ) const override
685  {
686  CoordinatesArrayType point_global_coordinates;
687 
689  rProjectedPointLocalCoordinates,
690  rPointGlobalCoordinates,
691  point_global_coordinates,
692  *this,
693  20, Tolerance);
694  }
695 
704  CoordinatesArrayType& rResult,
705  const CoordinatesArrayType& rLocalCoordinates
706  ) const override
707  {
708  NurbsSurfaceShapeFunction shape_function_container(mPolynomialDegreeU, mPolynomialDegreeV, 0);
709 
710  if (IsRational()) {
711  shape_function_container.ComputeNurbsShapeFunctionValues(
712  mKnotsU, mKnotsV, mWeights, rLocalCoordinates[0], rLocalCoordinates[1]);
713  }
714  else {
715  shape_function_container.ComputeBSplineShapeFunctionValues(
716  mKnotsU, mKnotsV, rLocalCoordinates[0], rLocalCoordinates[1]);
717  }
718 
719  noalias(rResult) = ZeroVector(3);
720  for (IndexType u = 0; u <= PolynomialDegreeU(); u++) {
721  for (IndexType v = 0; v <= PolynomialDegreeV(); v++) {
722  IndexType cp_index_u = shape_function_container.GetFirstNonzeroControlPointU() + u;
723  IndexType cp_index_v = shape_function_container.GetFirstNonzeroControlPointV() + v;
724 
726  NumberOfControlPointsU(), NumberOfControlPointsV(), cp_index_u, cp_index_v);
727 
728  rResult += (*this)[index] * shape_function_container(u, v, 0);
729  }
730  }
731 
732  return rResult;
733  }
734 
743  std::vector<CoordinatesArrayType>& rGlobalSpaceDerivatives,
744  const CoordinatesArrayType& rLocalCoordinates,
745  const SizeType DerivativeOrder) const override
746  {
747  NurbsSurfaceShapeFunction shape_function_container(mPolynomialDegreeU, mPolynomialDegreeV, DerivativeOrder);
748 
749  if (IsRational()) {
750  shape_function_container.ComputeNurbsShapeFunctionValues(
751  mKnotsU, mKnotsV, mWeights, rLocalCoordinates[0], rLocalCoordinates[1]);
752  }
753  else {
754  shape_function_container.ComputeBSplineShapeFunctionValues(
755  mKnotsU, mKnotsV, rLocalCoordinates[0], rLocalCoordinates[1]);
756  }
757 
758  if (rGlobalSpaceDerivatives.size() != shape_function_container.NumberOfShapeFunctionRows()) {
759  rGlobalSpaceDerivatives.resize(shape_function_container.NumberOfShapeFunctionRows());
760  }
761 
762  for (IndexType shape_function_row_i = 0;
763  shape_function_row_i < shape_function_container.NumberOfShapeFunctionRows();
764  shape_function_row_i++) {
765  for (IndexType u = 0; u <= PolynomialDegreeU(); u++) {
766  for (IndexType v = 0; v <= PolynomialDegreeV(); v++) {
767  IndexType cp_index_u = shape_function_container.GetFirstNonzeroControlPointU() + u;
768  IndexType cp_index_v = shape_function_container.GetFirstNonzeroControlPointV() + v;
769 
771  NumberOfControlPointsU(), NumberOfControlPointsV(), cp_index_u, cp_index_v);
772 
773  if (u == 0 && v==0)
774  rGlobalSpaceDerivatives[shape_function_row_i] =
775  (*this)[index] * shape_function_container(u, v, shape_function_row_i);
776  else
777  rGlobalSpaceDerivatives[shape_function_row_i] +=
778  (*this)[index] * shape_function_container(u, v, shape_function_row_i);
779  }
780  }
781  }
782  }
783 
787 
789  Vector &rResult,
790  const CoordinatesArrayType& rCoordinates) const override
791  {
792  NurbsSurfaceShapeFunction shape_function_container(mPolynomialDegreeU, mPolynomialDegreeV, 0);
793 
794  if (IsRational()) {
795  shape_function_container.ComputeNurbsShapeFunctionValues(mKnotsU, mKnotsV, mWeights, rCoordinates[0], rCoordinates[1]);
796  }
797  else {
798  shape_function_container.ComputeBSplineShapeFunctionValues(mKnotsU, mKnotsV, rCoordinates[0], rCoordinates[1]);
799  }
800 
801  if (rResult.size() != shape_function_container.NumberOfNonzeroControlPoints())
802  rResult.resize(shape_function_container.NumberOfNonzeroControlPoints());
803 
804  for (IndexType i = 0; i < shape_function_container.NumberOfNonzeroControlPoints(); i++) {
805  rResult[i] = shape_function_container(i, 0);
806  }
807 
808  return rResult;
809  }
810 
812  Matrix& rResult,
813  const CoordinatesArrayType& rCoordinates) const override
814  {
815  NurbsSurfaceShapeFunction shape_function_container(mPolynomialDegreeU, mPolynomialDegreeV, 0);
816 
817  if (IsRational()) {
818  shape_function_container.ComputeNurbsShapeFunctionValues(mKnotsU, mKnotsV, mWeights, rCoordinates[0], rCoordinates[1]);
819  }
820  else {
821  shape_function_container.ComputeBSplineShapeFunctionValues(mKnotsU, mKnotsV, rCoordinates[0], rCoordinates[1]);
822  }
823 
824  if (rResult.size1() != 2
825  && rResult.size2() != shape_function_container.NumberOfNonzeroControlPoints())
826  rResult.resize(2, shape_function_container.NumberOfNonzeroControlPoints());
827 
828  for (IndexType i = 0; i < shape_function_container.NumberOfNonzeroControlPoints(); i++) {
829  rResult(0, i) = shape_function_container(i, 1);
830  rResult(1, i) = shape_function_container(i, 2);
831  }
832 
833  return rResult;
834  }
835 
839 
841  {
843  }
844 
846  {
848  }
849 
853  std::string Info() const override
854  {
855  return std::to_string(TWorkingSpaceDimension) + " dimensional nurbs surface.";
856  }
857 
858  void PrintInfo(std::ostream& rOStream) const override
859  {
860  rOStream << TWorkingSpaceDimension << " dimensional nurbs surface.";
861  }
862 
863  void PrintData(std::ostream& rOStream) const override
864  {
865  }
867 
868 private:
871 
872  static const GeometryData msGeometryData;
873 
874  static const GeometryDimension msGeometryDimension;
875 
879 
880  SizeType mPolynomialDegreeU;
881  SizeType mPolynomialDegreeV;
882  Vector mKnotsU;
883  Vector mKnotsV;
884  Vector mWeights;
885 
887  BaseType* mpGeometryParent = nullptr;
888 
892 
893  /*
894  * @brief Checks if the knot vector is coinciding with the number of
895  * control points and the polynomial degree. If the knot vectors
896  * have a multiplicity of p+1 in the beginning, it is reduced to p.
897  */
898  void CheckAndFitKnotVectors()
899  {
900  SizeType num_control_points = this->size();
901 
902  if (num_control_points !=
903  (NurbsUtilities::GetNumberOfControlPoints(mPolynomialDegreeU, mKnotsU.size())
904  * NurbsUtilities::GetNumberOfControlPoints(mPolynomialDegreeV, mKnotsV.size()))) {
905  if (num_control_points ==
906  (NurbsUtilities::GetNumberOfControlPoints(mPolynomialDegreeU, mKnotsU.size() - 2)
907  * NurbsUtilities::GetNumberOfControlPoints(mPolynomialDegreeV, mKnotsV.size() - 2))) {
908  Vector KnotsU = ZeroVector(mKnotsU.size() - 2);
909  for (SizeType i = 0; i < mKnotsU.size() - 2; ++i) {
910  KnotsU[i] = mKnotsU[i + 1];
911  }
912  mKnotsU = KnotsU;
913 
914  Vector KnotsV = ZeroVector(mKnotsV.size() - 2);
915  for (SizeType i = 0; i < mKnotsV.size() - 2; ++i) {
916  KnotsV[i] = mKnotsV[i + 1];
917  }
918  mKnotsV = KnotsV;
919  } else {
921  << "Number of controls points and polynomial degrees and number of knots do not match! " << std::endl
922  << " P: " << mPolynomialDegreeU << ", Q: " << mPolynomialDegreeV
923  << ", number of knots u: " << mKnotsU.size() << ", number of knots v: " << mKnotsV.size()
924  << ", number of control points: " << num_control_points << std::endl
925  << "Following condition must be achieved: ControlPoints.size() = (KnotsU.size() - P + 1) * (KnotsV.size() - Q + 1)"
926  << std::endl;
927  }
928  }
929  }
930 
934 
935  friend class Serializer;
936 
937  void save(Serializer& rSerializer) const override
938  {
940  rSerializer.save("PolynomialDegreeU", mPolynomialDegreeU);
941  rSerializer.save("PolynomialDegreeV", mPolynomialDegreeV);
942  rSerializer.save("KnotsU", mKnotsU);
943  rSerializer.save("KnotsV", mKnotsV);
944  rSerializer.save("Weights", mWeights);
945  rSerializer.save("pGeometryParent", mpGeometryParent);
946  }
947 
948  void load(Serializer& rSerializer) override
949  {
951  rSerializer.load("PolynomialDegreeU", mPolynomialDegreeU);
952  rSerializer.load("PolynomialDegreeV", mPolynomialDegreeV);
953  rSerializer.load("KnotsU", mKnotsU);
954  rSerializer.load("KnotsV", mKnotsV);
955  rSerializer.load("Weights", mWeights);
956  rSerializer.load("pGeometryParent", mpGeometryParent);
957  }
958 
959  NurbsSurfaceGeometry() : BaseType(PointsArrayType(), &msGeometryData) {};
960 
962 
963 }; // class NurbsSurfaceGeometry
964 
965 template<int TWorkingSpaceDimension, class TPointType>
966 const GeometryData NurbsSurfaceGeometry<TWorkingSpaceDimension, TPointType>::msGeometryData(
969  {}, {}, {});
970 
971 template<int TWorkingSpaceDimension, class TPointType>
972 const GeometryDimension NurbsSurfaceGeometry<TWorkingSpaceDimension, TPointType>::msGeometryDimension(TWorkingSpaceDimension, 2);
973 
974 } // namespace Kratos
975 
976 #endif // KRATOS_NURBS_SURFACE_GEOMETRY_H_INCLUDED defined
static GeometryPointerType CreateQuadraturePoint(SizeType WorkingSpaceDimension, SizeType LocalSpaceDimension, GeometryShapeFunctionContainer< GeometryData::IntegrationMethod > &rShapeFunctionContainer, PointsArrayType rPoints, GeometryType *pGeometryParent)
Definition: quadrature_points_utility.h:159
Definition: geometry_data.h:60
KratosGeometryType
Definition: geometry_data.h:110
KratosGeometryFamily
Definition: geometry_data.h:91
Definition: geometry_dimension.h:42
Geometry base class.
Definition: geometry.h:71
SizeType size() const
Definition: geometry.h:518
Geometry & operator=(const Geometry &rOther)
Definition: geometry.h:400
std::vector< IntegrationPointType > IntegrationPointsArrayType
Definition: geometry.h:161
std::size_t SizeType
Definition: geometry.h:144
const TPointType::Pointer pGetPoint(const int Index) const
Definition: geometry.h:1790
std::size_t IndexType
Definition: geometry.h:137
IndexType const & Id() const
Id of this Geometry.
Definition: geometry.h:964
virtual void CreateQuadraturePointGeometries(GeometriesArrayType &rResultGeometries, IndexType NumberOfShapeFunctionDerivatives, const IntegrationPointsArrayType &rIntegrationPoints, IntegrationInfo &rIntegrationInfo)
Definition: geometry.h:2331
const PointsArrayType & Points() const
Definition: geometry.h:1768
IntegrationMethod GetDefaultIntegrationMethod() const
Definition: geometry.h:2004
SizeType WorkingSpaceDimension() const
Definition: geometry.h:1287
TPointType const & GetPoint(const int Index) const
Definition: geometry.h:1816
Definition: geometry_shape_function_container.h:60
Integration information for the creation of integration points.
Definition: integration_info.h:35
static void IntegrationPoints2D(typename IntegrationPointsArrayType::iterator &rIntegrationPointsBegin, SizeType PointsInU, SizeType PointsInV, double U0, double U1, double V0, double V1)
Definition: integration_point_utilities.cpp:125
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
Class for optimized use of intervals.
Definition: nurbs_interval.h:36
Definition: nurbs_surface_geometry.h:38
SizeType NumberOfControlPointsU() const
Definition: nurbs_surface_geometry.h:335
void CreateIntegrationPoints(IntegrationPointsArrayType &rIntegrationPoints, SizeType NumPointsPerSpanU, SizeType NumPointsPerSpanV) const
Definition: nurbs_surface_geometry.h:538
void Calculate(const Variable< array_1d< double, 3 >> &rVariable, array_1d< double, 3 > &rOutput) const override
Calculate with array_1d<double, 3>
Definition: nurbs_surface_geometry.h:235
void SetInternals(const PointsArrayType &rThisPoints, const SizeType PolynomialDegreeU, const SizeType PolynomialDegreeV, const Vector &rKnotsU, const Vector &rKnotsV, const Vector &rWeights)
Definition: nurbs_surface_geometry.h:250
bool IsRational() const
Definition: nurbs_surface_geometry.h:313
GeometryData::KratosGeometryType GetGeometryType() const override
Definition: nurbs_surface_geometry.h:845
NurbsSurfaceGeometry(NurbsSurfaceGeometry< TWorkingSpaceDimension, TOtherContainerPointType > const &rOther)
Copy constructor from a geometry with different point type.
Definition: nurbs_surface_geometry.h:122
Vector & ShapeFunctionsValues(Vector &rResult, const CoordinatesArrayType &rCoordinates) const override
Definition: nurbs_surface_geometry.h:788
SizeType PolynomialDegreeV() const
Definition: nurbs_surface_geometry.h:278
void SetGeometryParent(BaseType *pGeometryParent) override
Definition: nurbs_surface_geometry.h:188
std::string Info() const override
Return geometry information as a string.
Definition: nurbs_surface_geometry.h:853
int ProjectionPointGlobalToLocalSpace(const CoordinatesArrayType &rPointGlobalCoordinates, CoordinatesArrayType &rProjectedPointLocalCoordinates, const double Tolerance=std::numeric_limits< double >::epsilon()) const override
Projects a certain point on the geometry, or finds the closest point, depending on the provided initi...
Definition: nurbs_surface_geometry.h:680
SizeType NumberOfKnotsV() const
Definition: nurbs_surface_geometry.h:306
BaseType::IntegrationPointsArrayType IntegrationPointsArrayType
Definition: nurbs_surface_geometry.h:53
SizeType PolynomialDegree(IndexType LocalDirectionIndex) const override
Return polynomial degree of the surface in direction 0 or 1.
Definition: nurbs_surface_geometry.h:215
SizeType NumberOfKnotsU() const
Definition: nurbs_surface_geometry.h:300
NurbsSurfaceGeometry & operator=(NurbsSurfaceGeometry< TWorkingSpaceDimension, TOtherContainerPointType > const &rOther)
Assignment operator for geometries with different point type.
Definition: nurbs_surface_geometry.h:156
BaseType::Pointer Create(PointsArrayType const &ThisPoints) const override
Definition: nurbs_surface_geometry.h:173
BaseType::CoordinatesArrayType CoordinatesArrayType
Definition: nurbs_surface_geometry.h:50
NurbsSurfaceGeometry & operator=(const NurbsSurfaceGeometry &rOther)
Assignment operator.
Definition: nurbs_surface_geometry.h:142
const Vector & KnotsU() const
Definition: nurbs_surface_geometry.h:286
void SpansLocalSpace(std::vector< double > &rSpans, IndexType DirectionIndex) const override
Definition: nurbs_surface_geometry.h:373
const TPointType::Pointer pGetPoint(const int Index) const
Definition: geometry.h:1790
std::vector< NurbsInterval > KnotSpanIntervalsU() const
Definition: nurbs_surface_geometry.h:427
IntegrationInfo GetDefaultIntegrationInfo() const override
Provides the default integration dependent on the polynomial degree of the underlying surface.
Definition: nurbs_surface_geometry.h:508
SizeType NumberOfControlPointsV() const
Definition: nurbs_surface_geometry.h:340
CoordinatesArrayType & GlobalCoordinates(CoordinatesArrayType &rResult, const CoordinatesArrayType &rLocalCoordinates) const override
Definition: nurbs_surface_geometry.h:703
KRATOS_CLASS_POINTER_DEFINITION(NurbsSurfaceGeometry)
Counted pointer of NurbsSurfaceGeometry.
const Vector & Weights() const
Definition: nurbs_surface_geometry.h:330
SizeType NumberOfKnotSpans(IndexType DirectionIndex) const
Returns the number of spans in DirectionIndex=0:U and DirectionIndex=1:V (which are larger than 0).
Definition: nurbs_surface_geometry.h:346
void CalculateEstimatedKnotLengthness(CoordinatesArrayType &rKnotLengthness, const CoordinatesArrayType &rLocalCoordinates) const
Definition: nurbs_surface_geometry.h:468
GeometryData::KratosGeometryFamily GetGeometryFamily() const override
Definition: nurbs_surface_geometry.h:840
const Vector & KnotsV() const
Definition: nurbs_surface_geometry.h:294
BaseType::GeometriesArrayType GeometriesArrayType
Definition: nurbs_surface_geometry.h:52
BaseType::IndexType IndexType
Definition: nurbs_surface_geometry.h:47
TContainerPointType::value_type NodeType
Definition: nurbs_surface_geometry.h:43
std::vector< NurbsInterval > KnotSpanIntervalsV() const
Definition: nurbs_surface_geometry.h:449
NurbsSurfaceGeometry(NurbsSurfaceGeometry< TWorkingSpaceDimension, TContainerPointType > const &rOther)
Copy constructor.
Definition: nurbs_surface_geometry.h:110
~NurbsSurfaceGeometry() override=default
Destructor.
NurbsSurfaceGeometry(const PointsArrayType &rThisPoints, const SizeType PolynomialDegreeU, const SizeType PolynomialDegreeV, const Vector &rKnotsU, const Vector &rKnotsV, const Vector &rWeights)
Conctructor for NURBS surfaces.
Definition: nurbs_surface_geometry.h:84
void CreateQuadraturePointGeometries(GeometriesArrayType &rResultGeometries, IndexType NumberOfShapeFunctionDerivatives, const IntegrationPointsArrayType &rIntegrationPoints, IntegrationInfo &rIntegrationInfo) override
Definition: nurbs_surface_geometry.h:581
Geometry< NodeType > BaseType
Definition: nurbs_surface_geometry.h:45
Matrix & ShapeFunctionsLocalGradients(Matrix &rResult, const CoordinatesArrayType &rCoordinates) const override
Definition: nurbs_surface_geometry.h:811
NurbsSurfaceGeometry(const PointsArrayType &rThisPoints, const SizeType PolynomialDegreeU, const SizeType PolynomialDegreeV, const Vector &rKnotsU, const Vector &rKnotsV)
Conctructor for B-Spline surfaces.
Definition: nurbs_surface_geometry.h:68
void GlobalSpaceDerivatives(std::vector< CoordinatesArrayType > &rGlobalSpaceDerivatives, const CoordinatesArrayType &rLocalCoordinates, const SizeType DerivativeOrder) const override
Definition: nurbs_surface_geometry.h:742
SizeType PointsNumberInDirection(IndexType LocalDirectionIndex) const override
Returns number of points per direction.
Definition: nurbs_surface_geometry.h:198
void PrintInfo(std::ostream &rOStream) const override
Print information about this object.
Definition: nurbs_surface_geometry.h:858
NurbsInterval DomainIntervalU() const
Definition: nurbs_surface_geometry.h:407
NurbsSurfaceGeometry(const PointsArrayType &ThisPoints)
Definition: nurbs_surface_geometry.h:104
NurbsInterval DomainIntervalV() const
Definition: nurbs_surface_geometry.h:417
BaseType::PointsArrayType PointsArrayType
Definition: nurbs_surface_geometry.h:51
BaseType & GetGeometryParent(IndexType Index) const override
Some geometries require relations to other geometries. This is the case for e.g. quadrature points....
Definition: nurbs_surface_geometry.h:183
BaseType::SizeType SizeType
Definition: nurbs_surface_geometry.h:48
void CreateIntegrationPoints(IntegrationPointsArrayType &rIntegrationPoints, IntegrationInfo &rIntegrationInfo) const override
Definition: nurbs_surface_geometry.h:522
void PrintData(std::ostream &rOStream) const override
Print object's data.
Definition: nurbs_surface_geometry.h:863
SizeType PolynomialDegreeU() const
Definition: nurbs_surface_geometry.h:272
Definition: nurbs_surface_shape_functions.h:31
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
static constexpr SizeType NumberOfShapeFunctionRows(const SizeType DerivativeOrder) noexcept
Definition: nurbs_surface_shape_functions.h:66
IndexType GetFirstNonzeroControlPointU() const
Definition: nurbs_surface_shape_functions.h:229
IndexType GetFirstNonzeroControlPointV() const
Definition: nurbs_surface_shape_functions.h:239
SizeType NumberOfNonzeroControlPoints() const
Definition: nurbs_surface_shape_functions.h:151
void ComputeBSplineShapeFunctionValues(const Vector &rKnotsU, const Vector &rKnotsV, const double ParameterU, const double ParameterV)
Definition: nurbs_surface_shape_functions.h:280
PointerVector is a container like stl vector but using a vector to store pointers to its data.
Definition: pointer_vector.h:72
size_type size() const
Definition: pointer_vector.h:255
void resize(size_type dim)
Definition: pointer_vector.h:314
static bool NewtonRaphsonSurface(CoordinatesArrayType &rProjectedPointLocalCoordinates, const CoordinatesArrayType &rPointGlobalCoordinates, CoordinatesArrayType &rProjectedPointGlobalCoordinates, const NurbsSurfaceGeometry< TDimension, TPointType > &rNurbsSurface, const int MaxIterations=20, const double Accuracy=1e-6)
Definition: projection_nurbs_geometry_utilities.h:129
The serialization consists in storing the state of an object into a storage format like data file or ...
Definition: serializer.h:123
void load(std::string const &rTag, TDataType &rObject)
Definition: serializer.h:207
void save(std::string const &rTag, std::array< TDataType, TDataSize > const &rObject)
Definition: serializer.h:545
Variable class contains all information needed to store and retrive data from a data container.
Definition: variable.h:63
Short class definition.
Definition: array_1d.h:61
#define KRATOS_SERIALIZE_SAVE_BASE_CLASS(Serializer, BaseType)
Definition: define.h:812
#define KRATOS_SERIALIZE_LOAD_BASE_CLASS(Serializer, BaseType)
Definition: define.h:815
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
#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 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
TExpressionType::data_type norm_2(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression)
Definition: amatrix_interface.h:625
Internals::Matrix< double, AMatrix::dynamic, 1 > Vector
Definition: amatrix_interface.h:472
std::size_t SizeType
The definition of the size type.
Definition: mortar_classes.h:43
const GeometryData BrepCurve< TContainerPointType, TContainerPointEmbeddedType >::msGeometryData & msGeometryDimension
Definition: brep_curve.h:483
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
v
Definition: generate_convection_diffusion_explicit_element.py:114
u
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:30
def Index()
Definition: hdf5_io_tools.py:38
string t0
Definition: kernel_approximation_error.py:61
def load(f)
Definition: ode_solve.py:307
int n
manufactured solution and derivatives (u=0 at z=0 dudz=0 at z=domain_height)
Definition: ode_solve.py:402
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
int counter
Definition: script_THERMAL_CORRECT.py:218
N
Definition: sensitivityMatrix.py:29
integer i
Definition: TensorModule.f:17
e
Definition: run_cpp_mpi_tests.py:31