6 #include <eigen3/Eigen/Dense> 17 template <
int TDimParameter>
29 Nurbs(
const std::array<std::vector<double>, TDimParameter>& knots,
34 const std::vector<std::vector<NodeSimple*>>& controlPoints,
const std::vector<std::vector<double>>& weights,
35 const std::array<int, TDimParameter>& degree)
37 , mControlPoints(controlPoints)
49 return mControlPoints[0][0]->GetNumValues();
56 assert(dir <= TDimParameter && dir >= 0);
57 return mDegree[dir] + 1;
65 for (
int degree : mDegree)
73 std::array<Eigen::Vector2d, TDimParameter>
GetKnotVectorElement(std::array<int, TDimParameter> knotIDs)
const 75 std::array<Eigen::Vector2d, TDimParameter> knots;
76 Eigen::Vector2d knotCoordinates;
77 for (
int i = 0; i < TDimParameter; i++)
79 knotCoordinates(0) = mKnots[i][knotIDs[i]];
80 knotCoordinates(1) = mKnots[i][knotIDs[i] + 1];
81 knots[i] = knotCoordinates;
91 const std::array<int, TDimParameter> spanIdx =
FindSpan(parameter);
101 assert(numCPs == shapeFunctions.rows());
105 for (
int i = 0; i <
dim; i++)
106 for (
int j = 0; j < numCPs; j++)
107 coordinates(i) += shapeFunctions(j, 0) * cpCoords(dim * j + i);
114 static int FindSpan(
double parameter,
int degree,
const std::vector<double>& knots)
116 int size = knots.size();
119 if (parameter < knots[0] || parameter > knots[size - 1])
120 throw NuTo::Exception(__PRETTY_FUNCTION__,
"The parameter is out of the range of the knot vector.");
122 int numBasisFuns = size - degree - 1;
123 if (parameter == knots[numBasisFuns])
124 return numBasisFuns - 1;
127 int high = numBasisFuns;
128 int mid = (low + high) / 2;
130 while (parameter < knots[mid] || parameter >= knots[mid + 1])
132 if (parameter < knots[mid])
137 mid = (low + high) / 2;
139 if (iterations > size)
141 "The maximum number of iterations for finding the span exceeded.");
155 const std::vector<double>& knots)
158 Eigen::MatrixXd ndu(degree + 1, degree + 1);
162 Eigen::VectorXd left(degree + 1);
163 Eigen::VectorXd right(degree + 1);
165 for (
int j = 1; j <= degree; j++)
167 left[j] = parameter - knots[spanIdx + 1 - j];
168 right[j] = knots[spanIdx + j] - parameter;
170 for (
int r = 0; r < j; r++)
172 ndu(j, r) = right[r + 1] + left[j - r];
173 double temp = ndu(r, j - 1) / ndu(j, r);
174 ndu(r, j) = saved + right[r + 1] * temp;
175 saved = left[j - r] * temp;
180 Eigen::MatrixXd basisFctsDerivatives(derivativeOrder + 1, degree + 1);
182 for (
int j = 0; j <= degree; j++)
183 basisFctsDerivatives(0, j) = ndu(j, degree);
186 Eigen::MatrixXd a(2, degree + 1);
187 for (
int r = 0; r <= degree; r++)
195 for (
int k = 1; k <= derivativeOrder; k++)
202 a(s2, 0) = a(s1, 0) / ndu(pk + 1, rk);
203 d = a(s2, 0) * ndu(rk, pk);
217 for (j = j1; j <= j2; j++)
219 a(s2, j) = (a(s1, j) - a(s1, j - 1)) / ndu(pk + 1, rk + j);
220 d += a(s2, j) * ndu(rk + j, pk);
225 a(s2, k) = -a(s1, k - 1) / ndu(pk + 1, r);
226 d += a(s2, k) * ndu(r, pk);
229 basisFctsDerivatives(k, r) =
d;
237 for (
int k = 1; k <= derivativeOrder; k++)
239 for (
int j = 0; j <= degree; j++)
240 basisFctsDerivatives(k, j) *= r;
244 return basisFctsDerivatives;
256 int degree,
const std::vector<double>& knots,
257 const std::vector<double>& weights)
259 assert(derivativeOrder >= 0 && derivativeOrder <= 2);
264 Eigen::VectorXd sum(derivativeOrder + 1);
265 sum.setZero(derivativeOrder + 1);
267 for (
int i = 0; i <= degree; i++)
269 double weight = weights[spanIdx - degree + i];
270 if (derivativeOrder == 0)
271 sum(0) += ders(0, i) * weight;
272 else if (derivativeOrder == 1)
274 sum(0) += ders(0, i) * weight;
275 sum(1) += ders(1, i) * weight;
279 sum(0) += ders(0, i) * weight;
280 sum(1) += ders(1, i) * weight;
281 sum(2) += ders(2, i) * weight;
285 Eigen::VectorXd basisFctsDerivativesRational(degree + 1);
286 basisFctsDerivativesRational.setZero(degree + 1);
288 for (
int i = 0; i <= degree; i++)
290 double weight = weights[spanIdx - degree + i];
291 if (derivativeOrder == 0)
292 basisFctsDerivativesRational(i) = ders(0, i) * weight / sum(0);
293 else if (derivativeOrder == 1)
294 basisFctsDerivativesRational(i) =
295 (ders(1, i) * sum(0) - ders(0, i) * sum(1)) * weight / (sum(0) * sum(0));
298 double sum2 = sum(0) * sum(0);
299 basisFctsDerivativesRational(i) =
300 weight * (ders(2, i) / sum(0) - 2 * ders(1, i) * sum(1) / (sum2)-ders(0, i) * sum(2) / (sum2) +
301 2 * ders(0, i) * sum(1) * sum(1) / (sum2 * sum(0)));
305 return basisFctsDerivativesRational;
313 std::array<int, TDimParameter> parameterIDs;
314 for (
int i = 0; i < parameter.rows(); i++)
316 parameterIDs[i] =
FindSpan(parameter[i], mDegree[i], mKnots[i]);
327 std::array<std::vector<double>, TDimParameter> mKnots;
330 std::vector<std::vector<NodeSimple*>> mControlPoints;
333 std::vector<std::vector<double>> mWeights;
336 std::array<int, TDimParameter> mDegree;
342 assert(knotID[0] >= mDegree[0]);
347 Eigen::VectorXd nodeValues(numCPs * dim);
349 for (
int i = 0; i < numCPs; i++)
350 nodeValues.segment(dim * i, dim) = mControlPoints[0][knotID[0] - mDegree[0] + i]->GetValues(instance);
358 assert(knotID[0] >= mDegree[0] && knotID[1] >= mDegree[1]);
363 Eigen::VectorXd nodeValues(numCPs * dim);
366 for (
int i = 0; i <= mDegree[1]; i++)
368 for (
int j = 0; j <= mDegree[0]; j++)
370 nodeValues.segment(count, dim) =
371 mControlPoints[knotID[1] - mDegree[1] + i][knotID[0] - mDegree[0] + j]->GetValues(instance);
379 inline Eigen::MatrixXd
382 assert(der >= 0 && der <= 2);
384 int spanIdx =
FindSpan(parameter)[0];
388 Eigen::VectorXd sum = Eigen::VectorXd::Zero(der + 1);
390 for (
int i = 0; i <= mDegree[0]; i++)
392 double weight = mWeights[0][spanIdx - mDegree[0] + i];
394 sum(0) += ders(0, i) * weight;
397 sum(0) += ders(0, i) * weight;
398 sum(1) += ders(1, i) * weight;
402 sum(0) += ders(0, i) * weight;
403 sum(1) += ders(1, i) * weight;
404 sum(2) += ders(2, i) * weight;
408 Eigen::VectorXd dersRat(mDegree[0] + 1);
409 dersRat.setZero(mDegree[0] + 1);
411 for (
int i = 0; i <= mDegree[0]; i++)
413 double weight = mWeights[0][spanIdx - mDegree[0] + i];
415 dersRat(i) = ders(0, i) * weight / sum(0);
417 dersRat(i) = (ders(1, i) * sum(0) - ders(0, i) * sum(1)) * weight / (sum(0) * sum(0));
420 double sum2 = sum(0) * sum(0);
421 dersRat(i) = weight * (ders(2, i) / sum(0) - 2 * ders(1, i) * sum(1) / (sum2)-ders(0, i) * sum(2) / (sum2) +
422 2 * ders(0, i) * sum(1) * sum(1) / (sum2 * sum(0)));
429 inline Eigen::MatrixXd
432 assert(der >= 0 && der <= 2);
434 const std::array<int, 2> spanIdx =
FindSpan(parameter);
435 std::array<Eigen::MatrixXd, 2> shapeFunctions;
438 for (
int i = 0; i < 2; i++)
441 numDers *= mDegree[i] + 1;
444 Eigen::MatrixXd ders(numDers, der + 1);
445 ders.setZero(numDers, der + 1);
447 int num = ((der + 1) * (der + 1) + (der + 1)) / 2;
448 Eigen::VectorXd sum(num);
451 for (
int i = 0; i <= mDegree[1]; i++)
453 for (
int j = 0; j <= mDegree[0]; j++)
455 double weight = mWeights[spanIdx[1] - mDegree[1] + i][spanIdx[0] - mDegree[0] + j];
459 sum(0) += shapeFunctions[0](0, j) * shapeFunctions[1](0, i) * weight;
463 sum(0) += shapeFunctions[0](0, j) * shapeFunctions[1](0, i) * weight;
464 sum(1) += shapeFunctions[0](1, j) * shapeFunctions[1](0, i) * weight;
465 sum(2) += shapeFunctions[0](0, j) * shapeFunctions[1](1, i) * weight;
469 sum(0) += shapeFunctions[0](0, j) * shapeFunctions[1](0, i) * weight;
470 sum(1) += shapeFunctions[0](1, j) * shapeFunctions[1](0, i) * weight;
471 sum(2) += shapeFunctions[0](2, j) * shapeFunctions[1](0, i) * weight;
473 sum(3) += shapeFunctions[0](0, j) * shapeFunctions[1](1, i) * weight;
474 sum(4) += shapeFunctions[0](0, j) * shapeFunctions[1](2, i) * weight;
476 sum(5) += shapeFunctions[0](1, j) * shapeFunctions[1](1, i) * weight;
482 for (
int i = 0; i <= mDegree[1]; i++)
484 for (
int j = 0; j <= mDegree[0]; j++)
486 double weight = mWeights[spanIdx[1] - mDegree[1] + i][spanIdx[0] - mDegree[0] + j];
490 ders(count, 0) = shapeFunctions[0](0, j) * shapeFunctions[1](0, i) * weight / sum(0);
495 ders(count, 0) = (shapeFunctions[0](1, j) * shapeFunctions[1](0, i) * sum(0) -
496 shapeFunctions[0](0, j) * shapeFunctions[1](0, i) * sum(1)) *
497 weight / (sum(0) * sum(0));
498 ders(count, 1) = (shapeFunctions[0](0, j) * shapeFunctions[1](1, i) * sum(0) -
499 shapeFunctions[0](0, j) * shapeFunctions[1](0, i) * sum(2)) *
500 weight / (sum(0) * sum(0));
505 ders(count, 0) = (shapeFunctions[0](2, j) * shapeFunctions[1](0, i) / sum(0) -
506 2 * shapeFunctions[0](1, j) * shapeFunctions[1](0, i) * sum(1) / (sum(0) * sum(0)) -
507 shapeFunctions[0](0, j) * shapeFunctions[1](0, i) * sum(2) / (sum(0) * sum(0)) +
508 2 * shapeFunctions[0](0, j) * shapeFunctions[1](0, i) * sum(1) * sum(1) /
509 (sum(0) * sum(0) * sum(0))) *
512 ders(count, 1) = (shapeFunctions[0](0, j) * shapeFunctions[1](2, i) / sum(0) -
513 2 * shapeFunctions[0](0, j) * shapeFunctions[1](1, i) * sum(3) / (sum(0) * sum(0)) -
514 shapeFunctions[0](0, j) * shapeFunctions[1](0, i) * sum(4) / (sum(0) * sum(0)) +
515 2 * shapeFunctions[0](0, j) * shapeFunctions[0](0, i) * sum(3) * sum(3) /
516 (sum(0) * sum(0) * sum(0))) *
520 (shapeFunctions[0](1, j) * shapeFunctions[1](1, i) / sum(0) -
521 shapeFunctions[0](1, j) * shapeFunctions[1](0, i) * sum(3) / (sum(0) * sum(0)) -
522 shapeFunctions[0](0, j) * shapeFunctions[1](1, i) * sum(1) / (sum(0) * sum(0)) -
523 shapeFunctions[0](1, j) * shapeFunctions[1](0, i) * sum(5) * sum(5) / (sum(0) * sum(0)) +
524 2 * shapeFunctions[0](0, j) * shapeFunctions[1](0, i) * sum(1) * sum(3) /
525 (sum(0) * sum(0) * sum(0))) *
std::array< Eigen::Vector2d, TDimParameter > GetKnotVectorElement(std::array< int, TDimParameter > knotIDs) const
get the knots to given knot ids
Definition: Nurbs.h:73
coordinates
Definition: DamageBar.py:13
const NuTo::DofType d("...", 1)
int GetNumControlPointsElement() const
get the number of control points for each IGA element (one parametric span)
Definition: Nurbs.h:62
Base class for all exceptions thrown in NuTo.
Definition: Exception.h:9
static Eigen::MatrixXd BasisFunctionsAndDerivatives(int derivativeOrder, double parameter, int spanIdx, int degree, const std::vector< double > &knots)
calculates the basisfunctions and derivatives, see Piegl/Tiller 'NURBS Book' 2nd ed., Page 72
Definition: Nurbs.h:154
Eigen::VectorXd GetControlPointsElement(const std::array< int, TDimParameter > &knotID, int instance=0) const
Class for NURBS curves, with IGA specific functions. NURBS specific algorithms taken from Piegl...
Definition: Nurbs.h:18
Nurbs(const std::array< std::vector< double >, TDimParameter > &knots, const std::vector< std::vector< NodeSimple * >> &controlPoints, const std::vector< std::vector< double >> &weights, const std::array< int, TDimParameter > °ree)
Constructors.
Definition: Nurbs.h:33
const std::array< int, TDimParameter > FindSpan(const Eigen::Matrix< double, TDimParameter, 1 > ¶meter) const
calculates the knot span to given parameters
Definition: Nurbs.h:311
static int FindSpan(double parameter, int degree, const std::vector< double > &knots)
Basis Functions.
Definition: Nurbs.h:114
int GetDimension() const
Getter.
Definition: Nurbs.h:47
int GetNumControlPointsElement(int dir) const
get the number of control points for each IGA element (one parametric span) in a specific direction ...
Definition: Nurbs.h:54
mParametrization
Definition: Nurbs.h:21
Definition: Exception.h:6
Definition: SerializeStreamOut.h:9
static Eigen::VectorXd BasisFunctionsAndDerivativesRational(int derivativeOrder, double parameter, int spanIdx, int degree, const std::vector< double > &knots, const std::vector< double > &weights)
calculates the basisfunctions and derivatives, see Piegl/Tiller 'NURBS Book' 2nd ed., Page 72
Definition: Nurbs.h:255
constexpr int dim
Definition: ConstraintNodeToElement2D.cpp:24
Eigen::VectorXd Evaluate(const Eigen::Matrix< double, TDimParameter, 1 > ¶meter, int derivativeOrder=0) const
Evaluation.
Definition: Nurbs.h:89