48 for (
int i = 0; i <
nsd; i++ ) {
64 double *knotVec, knotVal;
92 for (
int i = 0; i <
nsd; i++ ) {
96 for (
int n = 0; n <
nsd; n++ ) {
100 OOFEM_WARNING(
"invalid size of knot vector %s", IFT_knotVector [ n ]);
106 for (
int i = 1; i < size; i++ ) {
107 if (
knotValues [ n ].at(i + 1) <= knotVal ) {
108 OOFEM_WARNING(
"knot vector %s is not monotonic", IFT_knotVector [ n ]);
117 for (
int i = 1; i <= size; i++ ) {
126 for (
int i = 1; i < size - 1; i++ ) {
131 OOFEM_WARNING(
"knot multiplicity %s size mismatch", IFT_knotMultiplicity [ n ]);
136 for (
int i = 1; i < size - 1; i++ ) {
138 OOFEM_WARNING(
"knot multiplicity %s out of range - value %d",
146 OOFEM_LOG_RELEVANT(
"Multiplicity of the first knot in knot vector %s changed to %d\n", IFT_knotVector [ n ],
degree [ n ] + 1);
150 OOFEM_LOG_RELEVANT(
"Multiplicity of the last knot in knot vector %s changed to %d\n", IFT_knotVector [ n ],
degree [ n ] + 1);
159 for (
int i = 0; i < size; i++ ) {
163 knotVec =
knotVector [ n ] =
new double [ sum ];
167 for (
int i = 0; i < size; i++ ) {
186 std :: vector< FloatArray >
N(
nsd);
192 for (
int i = 0; i <
nsd; i++ ) {
197 for (
int i = 0; i <
nsd; i++ ) {
205 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
206 answer.
at(c++) = N [ 0 ](k);
208 }
else if ( nsd == 2 ) {
209 for (
int l = 0; l <=
degree [ 1 ]; l++ ) {
210 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
211 answer.
at(c++) = N [ 0 ](k) * N [ 1 ](l);
214 }
else if ( nsd == 3 ) {
215 for (
int m = 0; m <=
degree [ 2 ]; m++ ) {
216 for (
int l = 0; l <=
degree [ 1 ]; l++ ) {
217 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
218 answer.
at(c++) = N [ 0 ](k) * N [ 1 ](l) * N [ 2 ](m);
223 OOFEM_ERROR(
"evalN not implemented for nsd = %d", nsd);
235 int count, cnt, ind, indx, uind, vind, tind;
236 std :: vector< FloatMatrix > ders(
nsd);
243 for (
int i = 0; i <
nsd; i++ ) {
248 for (
int i = 0; i <
nsd; i++ ) {
253 answer.
resize(count, nsd);
257 uind = span(0) -
degree [ 0 ];
259 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
261 jacobian(0, 0) += ders [ 0 ](1, k) * vertexCoordsPtr->
at(1);
266 if ( fabs(Jacob) < 1.0e-10 ) {
271 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
272 answer(cnt, 0) = ders [ 0 ](1, k) / Jacob;
275 }
else if ( nsd == 2 ) {
278 uind = span(0) -
degree [ 0 ];
279 vind = span(1) -
degree [ 1 ];
281 for (
int l = 0; l <=
degree [ 1 ]; l++ ) {
284 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
287 tmp1(0) += ders [ 0 ](1, k) * vertexCoordsPtr->
at(1);
288 tmp1(1) += ders [ 0 ](1, k) * vertexCoordsPtr->
at(2);
290 tmp2(0) += ders [ 0 ](0, k) * vertexCoordsPtr->
at(1);
291 tmp2(1) += ders [ 0 ](0, k) * vertexCoordsPtr->
at(2);
296 jacobian(0, 0) += ders [ 1 ](0, l) * tmp1(0);
297 jacobian(0, 1) += ders [ 1 ](0, l) * tmp1(1);
299 jacobian(1, 0) += ders [ 1 ](1, l) * tmp2(0);
300 jacobian(1, 1) += ders [ 1 ](1, l) * tmp2(1);
305 if ( fabs(Jacob) < 1.0e-10 ) {
310 for (
int l = 0; l <=
degree [ 1 ]; l++ ) {
311 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
312 tmp1(0) = ders [ 0 ](1, k) * ders [ 1 ](0, l);
313 tmp1(1) = ders [ 0 ](0, k) * ders [ 1 ](1, l);
314 answer(cnt, 0) = ( +jacobian(1, 1) * tmp1(0) - jacobian(0, 1) * tmp1(1) ) / Jacob;
315 answer(cnt, 1) = ( -jacobian(1, 0) * tmp1(0) + jacobian(0, 0) * tmp1(1) ) / Jacob;
319 }
else if ( nsd == 3 ) {
321 FloatArray temp1(nsd), temp2(nsd), temp3(nsd);
323 uind = span(0) -
degree [ 0 ];
324 vind = span(1) -
degree [ 1 ];
325 tind = span(2) -
degree [ 2 ];
327 for (
int m = 0; m <=
degree [ 2 ]; m++ ) {
332 for (
int l = 0; l <=
degree [ 1 ]; l++ ) {
335 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
338 tmp1(0) += ders [ 0 ](1, k) * vertexCoordsPtr->
at(1);
339 tmp1(1) += ders [ 0 ](1, k) * vertexCoordsPtr->
at(2);
340 tmp1(2) += ders [ 0 ](1, k) * vertexCoordsPtr->
at(3);
342 tmp2(0) += ders [ 0 ](0, k) * vertexCoordsPtr->
at(1);
343 tmp2(1) += ders [ 0 ](0, k) * vertexCoordsPtr->
at(2);
344 tmp2(2) += ders [ 0 ](0, k) * vertexCoordsPtr->
at(3);
349 temp1(0) += ders [ 1 ](0, l) * tmp1(0);
350 temp1(1) += ders [ 1 ](0, l) * tmp1(1);
351 temp1(2) += ders [ 1 ](0, l) * tmp1(2);
353 temp2(0) += ders [ 1 ](1, l) * tmp2(0);
354 temp2(1) += ders [ 1 ](1, l) * tmp2(1);
355 temp2(2) += ders [ 1 ](1, l) * tmp2(1);
357 temp3(0) += ders [ 1 ](0, l) * tmp2(0);
358 temp3(1) += ders [ 1 ](0, l) * tmp2(1);
359 temp3(2) += ders [ 1 ](0, l) * tmp2(1);
364 jacobian(0, 0) += ders [ 2 ](0, m) * temp1(0);
365 jacobian(0, 1) += ders [ 2 ](0, m) * temp1(1);
366 jacobian(0, 2) += ders [ 2 ](0, m) * temp1(2);
368 jacobian(1, 0) += ders [ 2 ](0, m) * temp2(0);
369 jacobian(1, 1) += ders [ 2 ](0, m) * temp2(1);
370 jacobian(1, 2) += ders [ 2 ](0, m) * temp2(2);
372 jacobian(2, 0) += ders [ 2 ](1, m) * temp3(0);
373 jacobian(2, 1) += ders [ 2 ](1, m) * temp3(1);
374 jacobian(2, 2) += ders [ 2 ](1, m) * temp3(2);
379 if ( fabs(Jacob) < 1.0e-10 ) {
384 for (
int m = 0; m <=
degree [ 2 ]; m++ ) {
385 for (
int l = 0; l <=
degree [ 1 ]; l++ ) {
386 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
387 tmp1(0) = ders [ 0 ](1, k) * ders [ 1 ](0, l) * ders [ 2 ](0, m);
388 tmp1(1) = ders [ 0 ](0, k) * ders [ 1 ](1, l) * ders [ 2 ](0, m);
389 tmp1(2) = ders [ 0 ](0, k) * ders [ 1 ](0, l) * ders [ 2 ](1, m);
390 answer(cnt, 0) = ( ( jacobian(1, 1) * jacobian(2, 2) - jacobian(1, 2) * jacobian(2, 1) ) * tmp1(0) +
391 ( jacobian(0, 2) * jacobian(2, 1) - jacobian(0, 1) * jacobian(2, 2) ) * tmp1(1) +
392 ( jacobian(0, 1) * jacobian(1, 2) - jacobian(0, 2) * jacobian(1, 1) ) * tmp1(2) ) / Jacob;
393 answer(cnt, 1) = ( ( jacobian(1, 2) * jacobian(2, 0) - jacobian(1, 0) * jacobian(2, 2) ) * tmp1(0) +
394 ( jacobian(0, 0) * jacobian(2, 2) - jacobian(0, 2) * jacobian(2, 0) ) * tmp1(1) +
395 ( jacobian(0, 2) * jacobian(1, 0) - jacobian(0, 0) * jacobian(1, 2) ) * tmp1(2) ) / Jacob;
396 answer(cnt, 2) = ( ( jacobian(1, 0) * jacobian(2, 1) - jacobian(1, 1) * jacobian(2, 0) ) * tmp1(0) +
397 ( jacobian(0, 1) * jacobian(2, 0) - jacobian(0, 0) * jacobian(2, 1) ) * tmp1(1) +
398 ( jacobian(0, 0) * jacobian(1, 1) - jacobian(0, 1) * jacobian(1, 0) ) * tmp1(2) ) / Jacob;
404 OOFEM_ERROR(
"evaldNdx not implemented for nsd = %d", nsd);
417 int ind, indx, uind, vind, tind;
418 std :: vector< FloatArray >
N(
nsd);
424 for (
int i = 0; i <
nsd; i++ ) {
429 for (
int i = 0; i <
nsd; i++ ) {
437 uind = span(0) -
degree [ 0 ];
439 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
441 answer(0) += N [ 0 ](k) * vertexCoordsPtr->
at(1);
443 }
else if ( nsd == 2 ) {
446 uind = span(0) -
degree [ 0 ];
447 vind = span(1) -
degree [ 1 ];
449 for (
int l = 0; l <=
degree [ 1 ]; l++ ) {
451 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
454 tmp(0) += N [ 0 ](k) * vertexCoordsPtr->
at(1);
455 tmp(1) += N [ 0 ](k) * vertexCoordsPtr->
at(2);
460 answer(0) += N [ 1 ](l) * tmp(0);
461 answer(1) += N [ 1 ](l) * tmp(1);
463 }
else if ( nsd == 3 ) {
466 uind = span(0) -
degree [ 0 ];
467 vind = span(1) -
degree [ 1 ];
468 tind = span(2) -
degree [ 2 ];
470 for (
int m = 0; m <=
degree [ 2 ]; m++ ) {
473 for (
int l = 0; l <=
degree [ 1 ]; l++ ) {
475 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
477 tmp.
add(N [ 0 ](k), *vertexCoordsPtr);
482 temp.
add(N [ 1 ](l), tmp);
487 answer.
add(N [ 2 ](m), temp);
490 OOFEM_ERROR(
"local2global not implemented for nsd = %d", nsd);
500 int indx, ind, uind, vind, tind;
501 std :: vector< FloatMatrix > ders(
nsd);
507 for (
int i = 0; i <
nsd; i++ ) {
512 for (
int i = 0; i <
nsd; i++ ) {
519 uind = span(0) -
degree [ 0 ];
521 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
523 jacobian(0, 0) += ders [ 0 ](1, k) * vertexCoordsPtr->
at(1);
525 }
else if ( nsd == 2 ) {
528 uind = span(0) -
degree [ 0 ];
529 vind = span(1) -
degree [ 1 ];
531 for (
int l = 0; l <=
degree [ 1 ]; l++ ) {
534 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
537 tmp1(0) += ders [ 0 ](1, k) * vertexCoordsPtr->
at(1);
538 tmp1(1) += ders [ 0 ](1, k) * vertexCoordsPtr->
at(2);
540 tmp2(0) += ders [ 0 ](0, k) * vertexCoordsPtr->
at(1);
541 tmp2(1) += ders [ 0 ](0, k) * vertexCoordsPtr->
at(2);
546 jacobian(0, 0) += ders [ 1 ](0, l) * tmp1(0);
547 jacobian(0, 1) += ders [ 1 ](0, l) * tmp1(1);
549 jacobian(1, 0) += ders [ 1 ](1, l) * tmp2(0);
550 jacobian(1, 1) += ders [ 1 ](1, l) * tmp2(1);
552 }
else if ( nsd == 3 ) {
554 FloatArray temp1(nsd), temp2(nsd), temp3(nsd);
556 uind = span(0) -
degree [ 0 ];
557 vind = span(1) -
degree [ 1 ];
558 tind = span(2) -
degree [ 2 ];
560 for (
int m = 0; m <=
degree [ 2 ]; m++ ) {
565 for (
int l = 0; l <=
degree [ 1 ]; l++ ) {
568 for (
int k = 0; k <=
degree [ 0 ]; k++ ) {
571 tmp1.
add(ders [ 0 ](1, k), *vertexCoordsPtr);
572 tmp2.
add(ders [ 0 ](0, k), *vertexCoordsPtr);
577 temp1.add(ders [ 1 ](0, l), tmp1);
578 temp2.add(ders [ 1 ](1, l), tmp2);
579 temp3.
add(ders [ 1 ](0, l), tmp2);
584 jacobian(0, 0) += ders [ 2 ](0, m) * temp1(0);
585 jacobian(0, 1) += ders [ 2 ](0, m) * temp1(1);
586 jacobian(0, 2) += ders [ 2 ](0, m) * temp1(2);
588 jacobian(1, 0) += ders [ 2 ](0, m) * temp2(0);
589 jacobian(1, 1) += ders [ 2 ](0, m) * temp2(1);
590 jacobian(1, 2) += ders [ 2 ](0, m) * temp2(2);
592 jacobian(2, 0) += ders [ 2 ](1, m) * temp3(0);
593 jacobian(2, 1) += ders [ 2 ](1, m) * temp3(1);
594 jacobian(2, 2) += ders [ 2 ](1, m) * temp3(2);
597 OOFEM_ERROR(
"giveTransformationJacobian not implemented for nsd = %d", nsd);
604 int size, c = 1, iindx, jindx, kindx;
610 for (
int i = 0; i <=
degree [ 0 ]; i++ ) {
611 iindx = ( i + knotSpan(0) -
degree [ 0 ] );
612 mask.
at(c++) = iindx + 1;
614 }
else if (
nsd == 2 ) {
615 for (
int j = 0; j <=
degree [ 1 ]; j++ ) {
616 jindx = ( j + knotSpan(1) -
degree [ 1 ] );
617 for (
int i = 0; i <=
degree [ 0 ]; i++ ) {
618 iindx = ( i + knotSpan(0) -
degree [ 0 ] );
622 }
else if (
nsd == 3 ) {
623 for (
int k = 0; k <=
degree [ 2 ]; k++ ) {
624 kindx = ( k + knotSpan(2) -
degree [ 2 ] );
625 for (
int j = 0; j <=
degree [ 1 ]; j++ ) {
626 jindx = ( j + knotSpan(1) -
degree [ 1 ] );
627 for (
int i = 0; i <=
degree [ 0 ]; i++ ) {
628 iindx = ( i + knotSpan(0) -
degree [ 0 ] );
646 for (
int i = 0; i <
nsd; i++ ) {
647 answer *= (
degree [ i ] + 1 );
671 for (
int j = 1; j <= p; j++ ) {
672 left(j) = u - U [ span + 1 - j ];
673 right(j) = U [ span + j ] - u;
675 for (
int r = 0; r < j; r++ ) {
676 temp =
N(r) / ( right(r + 1) + left(j - r) );
677 N(r) = saved + right(r + 1) * temp;
678 saved = left(j - r) * temp;
702 ders.
resize(n + 1, p + 1);
705 for (
int j = 1; j <= p; j++ ) {
706 left(j) = u - U [ span + 1 - j ];
707 right(j) = U [ span + j ] - u;
710 for (
int r = 0; r < j; r++ ) {
712 ndu(j, r) = right(r + 1) + left(j - r);
713 temp = ndu(r, j - 1) / ndu(j, r);
715 ndu(r, j) = saved + right(r + 1) * temp;
716 saved = left(j - r) * temp;
722 for (
int j = 0; j <= p; j++ ) {
723 ders(0, j) = ndu(j, p);
728 for (
int r = 0; r <= p; r++ ) {
734 for (
int k = 1; k <= n; k++ ) {
742 a(s2, 0) = a(s1, 0) / ndu(pk + 1, rk);
743 d = a(s2, 0) * ndu(rk, pk);
758 for (
int j = j1; j <= j2; j++ ) {
759 a(s2, j) = ( a(s1, j) - a(s1, j - 1) ) / ndu(pk + 1, rk + j);
760 d += a(s2, j) * ndu(rk + j, pk);
764 a(s2, k) = -a(s1, k - 1) / ndu(pk + 1, r);
765 d += a(s2, k) * ndu(r, pk);
775 for (
int k = 1; k <= n; k++ ) {
776 for (
int j = 0; j <= p; j++ ) {
794 if ( u == U [ n + 1 ] ) {
800 int mid = ( low + high ) / 2;
802 while ( u < U [ mid ] || u >= U [ mid + 1 ] ) {
803 if ( u < U [ mid ] ) {
809 mid = ( low + high ) / 2;
double giveDeterminant() const
Returns the trace (sum of diagonal components) of the receiver.
IntArray * knotMultiplicity
Knot multiplicity [nsd].
const IntArray * knotSpan
#define _IFT_BSplineInterpolation_knotVectorV
int * numberOfKnotSpans
Nonzero spans in each directions [nsd].
virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
Evaluates the array of interpolation functions (shape functions) at given point.
virtual int giveKnotSpanBasisFuncMask(const IntArray &knotSpan, IntArray &mask)
Returns indices (zero based) of nonzero basis functions for given knot span.
double & at(int i)
Coefficient access function.
virtual const FloatArray * giveVertexCoordinates(int i) const =0
int findSpan(int n, int p, double u, const double *U) const
Determines the knot span index (Algorithm A2.1 from the NURBS book)
int * degree
Degree in each direction.
Class representing a general abstraction for cell geometry.
virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
Evaluates global coordinates from given local ones.
const char * InputFieldType
Identifier of fields in input records.
Class implementing an array of integers.
int & at(int i)
Coefficient access function.
#define OOFEM_LOG_RELEVANT(...)
#define _IFT_BSplineInterpolation_knotMultiplicityW
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes receiver according to object description stored in input record.
double ** knotVector
Knot vectors [nsd][knot_vector_size].
FloatArray * knotValues
Knot values [nsd].
void resize(int n)
Checks size of receiver towards requested bounds.
#define _IFT_BSplineInterpolation_knotVectorU
#define _IFT_BSplineInterpolation_knotVectorW
Class representing vector of real numbers.
virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
Gives the jacobian matrix at the local coordinates.
Implementation of matrix containing floating point numbers.
IRResultType
Type defining the return values of InputRecord reading operations.
virtual int giveNumberOfKnotSpanBasisFunctions(const IntArray &knotSpan)
Returns the number of nonzero basis functions at individual knot span,.
void dersBasisFuns(int n, double u, int span, int p, double *const U, FloatMatrix &ders)
Computes nonzero basis functions and their derivatives at u.
void resize(int rows, int cols)
Checks size of receiver towards requested bounds.
virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
Evaluates the matrix of derivatives of interpolation functions (shape functions) at given point...
void zero()
Zeroes all coefficients of receiver.
#define _IFT_BSplineInterpolation_degree
#define _IFT_BSplineInterpolation_knotMultiplicityV
void zero()
Zeroes all coefficient of receiver.
#define _IFT_BSplineInterpolation_knotMultiplicityU
Geometry wrapper for IGA elements.
int * numberOfControlPoints
numberOfControlPoints[nsd]
int giveSize() const
Returns the size of receiver.
the oofem namespace is to define a context or scope in which all oofem names are defined.
void basisFuns(FloatArray &N, int span, double u, int p, const double *U)
Evaluates the nonvanishing basis functions of 1d BSpline (algorithm A2.2 from NURBS book) ...
int nsd
Number of spatial directions.
#define OOFEM_WARNING(...)
void add(const FloatArray &src)
Adds array src to receiver.
virtual ~BSplineInterpolation()
void resize(int s)
Resizes receiver towards requested size.