7#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_BSPLINEBASIS_HH
8#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_BSPLINEBASIS_HH
18#include <dune/common/dynmatrix.hh>
20#include <dune/localfunctions/common/localbasis.hh>
21#include <dune/common/diagonalmatrix.hh>
22#include <dune/localfunctions/common/localkey.hh>
23#include <dune/localfunctions/common/localfiniteelementtraits.hh>
24#include <dune/geometry/type.hh>
25#include <dune/functions/functionspacebases/nodes.hh>
26#include <dune/functions/functionspacebases/defaultglobalbasis.hh>
27#include <dune/functions/functionspacebases/leafprebasismixin.hh>
34template<
typename GV,
typename R>
35class BSplineLocalFiniteElement;
49template<
class GV,
class R>
54 typedef typename GV::ctype D;
55 enum {dim = GV::dimension};
59 typedef LocalBasisTraits<D,dim,FieldVector<D,dim>,R,1,FieldVector<R,1>,
68 : preBasis_(preBasis),
77 std::vector<FieldVector<R,1> >& out)
const
79 FieldVector<D,dim> globalIn = offset_;
80 scaling_.umv(in,globalIn);
82 preBasis_.evaluateFunction(globalIn, out, lFE_.currentKnotSpan_);
90 std::vector<FieldMatrix<D,1,dim> >& out)
const
92 FieldVector<D,dim> globalIn = offset_;
93 scaling_.umv(in,globalIn);
95 preBasis_.evaluateJacobian(globalIn, out, lFE_.currentKnotSpan_);
97 for (
size_t i=0; i<out.size(); i++)
98 for (
int j=0; j<dim; j++)
99 out[i][0][j] *= scaling_[j][j];
104 inline void evaluate (
const typename std::array<int,k>& directions,
105 const typename Traits::DomainType& in,
106 std::vector<typename Traits::RangeType>& out)
const
115 FieldVector<D,dim> globalIn = offset_;
116 scaling_.umv(in,globalIn);
118 preBasis_.evaluate(directions, globalIn, out, lFE_.currentKnotSpan_);
120 for (
size_t i=0; i<out.size(); i++)
121 out[i][0] *= scaling_[directions[0]][directions[0]];
126 FieldVector<D,dim> globalIn = offset_;
127 scaling_.umv(in,globalIn);
129 preBasis_.evaluate(directions, globalIn, out, lFE_.currentKnotSpan_);
131 for (
size_t i=0; i<out.size(); i++)
132 out[i][0] *= scaling_[directions[0]][directions[0]]*scaling_[directions[1]][directions[1]];
136 DUNE_THROW(NotImplemented,
"B-Spline derivatives of order " << k <<
" not implemented yet!");
149 return *std::max_element(preBasis_.order_.begin(), preBasis_.order_.end());
166 FieldVector<D,dim> offset_;
167 DiagonalMatrix<D,dim> scaling_;
187 std::array<unsigned int,dim> multiindex (
unsigned int i)
const
189 std::array<unsigned int,dim> alpha;
190 for (
int j=0; j<dim; j++)
192 alpha[j] = i % sizes_[j];
199 void setup1d(std::vector<unsigned int>& subEntity)
210 unsigned lastIndex=0;
211 subEntity[lastIndex++] = 0;
212 for (
unsigned i = 0; i < sizes_[0] - 2; ++i)
213 subEntity[lastIndex++] = 0;
215 subEntity[lastIndex++] = 1;
217 assert(
size()==lastIndex);
220 void setup2d(std::vector<unsigned int>& subEntity)
222 unsigned lastIndex=0;
236 subEntity[lastIndex++] = 0;
237 for (
unsigned i = 0; i < sizes_[0]-2; ++i)
238 subEntity[lastIndex++] = 2;
240 subEntity[lastIndex++] = 1;
243 for (
unsigned e = 0; e < sizes_[1]-2; ++e)
245 subEntity[lastIndex++] = 0;
246 for (
unsigned i = 0; i < sizes_[0]-2; ++i)
247 subEntity[lastIndex++] = 0;
248 subEntity[lastIndex++] = 1;
252 subEntity[lastIndex++] = 2;
253 for (
unsigned i = 0; i < sizes_[0]-2; ++i)
254 subEntity[lastIndex++] = 3;
256 subEntity[lastIndex++] = 3;
258 assert(
size()==lastIndex);
263 void init(
const std::array<unsigned,dim>& sizes)
270 std::vector<unsigned int> codim(li_.size());
272 for (std::size_t i=0; i<codim.size(); i++)
277 std::array<unsigned int,dim> mIdx = multiindex(i);
278 for (
int j=0; j<dim; j++)
279 if (mIdx[j]==0 or mIdx[j]==sizes[j]-1)
288 std::vector<unsigned int> index(
size());
290 for (std::size_t i=0; i<index.size(); i++)
294 std::array<unsigned int,dim> mIdx = multiindex(i);
296 for (
int j=dim-1; j>=0; j--)
297 if (mIdx[j]>0 and mIdx[j]<sizes[j]-1)
298 index[i] = (sizes[j]-1)*index[i] + (mIdx[j]-1);
302 std::vector<unsigned int> subEntity(li_.size());
304 if (subEntity.size() > 0)
310 }
else if (dim==2 and sizes_[0]>1 and sizes_[1]>1) {
317 for (
size_t i=0; i<li_.size(); i++)
318 li_[i] = LocalKey(subEntity[i], codim[i], index[i]);
324 return std::accumulate(sizes_.begin(), sizes_.end(), 1, std::multiplies<unsigned int>());
336 std::array<unsigned, dim> sizes_;
338 std::vector<LocalKey> li_;
345template<
int dim,
class LB>
350 template<
typename F,
typename C>
353 DUNE_THROW(NotImplemented,
"BSplineLocalInterpolation::interpolate");
367template<
class GV,
class R>
370 typedef typename GV::ctype D;
371 enum {dim = GV::dimension};
377 typedef LocalFiniteElementTraits<BSplineLocalBasis<GV,R>,
384 : preBasis_(preBasis),
385 localBasis_(preBasis,*this)
391 : preBasis_(other.preBasis_),
392 localBasis_(preBasis_,*this)
401 void bind(
const std::array<unsigned,dim>& elementIdx)
404 for (
size_t i=0; i<elementIdx.size(); i++)
406 currentKnotSpan_[i] = 0;
409 while (preBasis_.knotVectors_[i][currentKnotSpan_[i]+1] < preBasis_.knotVectors_[i][currentKnotSpan_[i]]+1e-8)
410 currentKnotSpan_[i]++;
412 for (
size_t j=0; j<elementIdx[i]; j++)
414 currentKnotSpan_[i]++;
417 while (preBasis_.knotVectors_[i][currentKnotSpan_[i]+1] < preBasis_.knotVectors_[i][currentKnotSpan_[i]]+1e-8)
418 currentKnotSpan_[i]++;
422 localBasis_.offset_[i] = preBasis_.knotVectors_[i][currentKnotSpan_[i]];
423 localBasis_.scaling_[i][i] = preBasis_.knotVectors_[i][currentKnotSpan_[i]+1] - preBasis_.knotVectors_[i][currentKnotSpan_[i]];
427 std::array<unsigned int, dim> sizes;
428 for (
size_t i=0; i<dim; i++)
430 localCoefficients_.init(sizes);
442 return localCoefficients_;
448 return localInterpolation_;
455 for (
int i=0; i<dim; i++)
464 return GeometryTypes::cube(dim);
472 const auto& order = preBasis_.order_;
473 unsigned int r = order[i]+1;
474 if (currentKnotSpan_[i]<order[i])
475 r -= (order[i] - currentKnotSpan_[i]);
476 if ( order[i] > (preBasis_.knotVectors_[i].size() - currentKnotSpan_[i] - 2) )
477 r -= order[i] - (preBasis_.knotVectors_[i].size() - currentKnotSpan_[i] - 2);
488 std::array<unsigned,dim> currentKnotSpan_;
510 static const int dim = GV::dimension;
513 class MultiDigitCounter
520 MultiDigitCounter(
const std::array<unsigned int,dim>& limits)
523 std::fill(counter_.begin(), counter_.end(), 0);
527 MultiDigitCounter& operator++()
529 for (
int i=0; i<dim; i++)
534 if (counter_[i] < limits_[i])
543 const unsigned int& operator[](
int i)
const
549 unsigned int cycle()
const
552 for (
int i=0; i<dim; i++)
560 const std::array<unsigned int,dim> limits_;
563 std::array<unsigned int,dim> counter_;
571 using size_type = std::size_t;
573 using Node = BSplineNode<GV>;
598 const std::vector<double>& knotVector,
600 bool makeOpen =
true)
608 assert( std::accumulate(
elements_.begin(),
elements_.end(), 1, std::multiplies<unsigned>()) == gridView_.size(0) );
610 for (
int i=0; i<dim; i++)
615 for (
unsigned int j=0; j<order; j++)
621 for (
unsigned int j=0; j<order; j++)
650 const FieldVector<double,dim>& lowerLeft,
651 const FieldVector<double,dim>& upperRight,
652 const std::array<unsigned int,dim>&
elements,
654 bool makeOpen =
true)
660 assert( std::accumulate(
elements_.begin(),
elements_.end(), 1, std::multiplies<unsigned>()) == gridView_.size(0) );
662 for (
int i=0; i<dim; i++)
667 for (
unsigned int j=0; j<order; j++)
671 for (
size_t j=0; j<
elements[i]+1; j++)
675 for (
unsigned int j=0; j<order; j++)
709 size_type result = 1;
710 for (
int i=0; i<dim; i++)
716 template<
typename It>
721 std::array<unsigned int, dim> localSizes;
722 for (
int i=0; i<dim; i++)
723 localSizes[i] = node.finiteElement().size(i);
724 for (size_type i = 0, end = node.size() ; i < end ; ++i, ++it)
726 std::array<unsigned int,dim> localIJK =
getIJK(i, localSizes);
728 const auto currentKnotSpan = node.finiteElement().currentKnotSpan_;
729 const auto order =
order_;
731 std::array<unsigned int,dim> globalIJK;
732 for (
int i=0; i<dim; i++)
733 globalIJK[i] = std::max((
int)currentKnotSpan[i] - (
int)order[i], 0) + localIJK[i];
736 size_type globalIdx = globalIJK[dim-1];
738 for (
int i=dim-2; i>=0; i--)
739 globalIdx = globalIdx *
size(i) + globalIJK[i];
749 unsigned int result = 1;
750 for (
size_t i=0; i<dim; i++)
756 unsigned int size (
size_t d)
const
766 std::vector<FieldVector<R,1> >& out,
767 const std::array<unsigned,dim>& currentKnotSpan)
const
770 std::array<std::vector<R>, dim> oneDValues;
772 for (
size_t i=0; i<dim; i++)
775 std::array<unsigned int, dim> limits;
776 for (
int i=0; i<dim; i++)
777 limits[i] = oneDValues[i].
size();
779 MultiDigitCounter ijkCounter(limits);
781 out.resize(ijkCounter.cycle());
783 for (
size_t i=0; i<out.size(); i++, ++ijkCounter)
786 for (
size_t j=0; j<dim; j++)
787 out[i] *= oneDValues[j][ijkCounter[j]];
797 std::vector<FieldMatrix<R,1,dim> >& out,
798 const std::array<unsigned,dim>& currentKnotSpan)
const
801 std::array<unsigned int, dim> limits;
802 for (
int i=0; i<dim; i++)
805 if (currentKnotSpan[i]<
order_[i])
806 limits[i] -= (
order_[i] - currentKnotSpan[i]);
812 std::array<unsigned int, dim> offset;
813 for (
int i=0; i<dim; i++)
814 offset[i] = std::max((
int)(currentKnotSpan[i] -
order_[i]),0);
817 std::array<std::vector<R>, dim> oneDValues;
820 std::array<std::vector<R>, dim> lowOrderOneDValues;
822 std::array<DynamicMatrix<R>, dim> values;
824 for (
size_t i=0; i<dim; i++)
828 for (
size_t j=0; j<oneDValues[i].size(); j++)
829 oneDValues[i][j] = values[i][
order_[i]][j];
834 for (
size_t j=0; j<lowOrderOneDValues[i].size(); j++)
835 lowOrderOneDValues[i][j] = values[i][
order_[i]-1][j];
841 std::array<std::vector<R>, dim> oneDDerivatives;
842 for (
size_t i=0; i<dim; i++)
844 oneDDerivatives[i].resize(limits[i]);
847 std::fill(oneDDerivatives[i].begin(), oneDDerivatives[i].end(), R(0.0));
850 for (
size_t j=offset[i]; j<offset[i]+limits[i]; j++)
855 if (std::isnan(derivativeAddend1))
856 derivativeAddend1 = 0;
857 if (std::isnan(derivativeAddend2))
858 derivativeAddend2 = 0;
859 oneDDerivatives[i][j-offset[i]] =
order_[i] * ( derivativeAddend1 - derivativeAddend2 );
866 std::array<std::vector<R>, dim> oneDValuesShort;
868 for (
int i=0; i<dim; i++)
870 oneDValuesShort[i].resize(limits[i]);
872 for (
size_t j=0; j<limits[i]; j++)
873 oneDValuesShort[i][j] = oneDValues[i][offset[i] + j];
879 MultiDigitCounter ijkCounter(limits);
881 out.resize(ijkCounter.cycle());
884 for (
size_t i=0; i<out.size(); i++, ++ijkCounter)
885 for (
int j=0; j<dim; j++)
888 for (
int k=0; k<dim; k++)
889 out[i][0][j] *= (j==k) ? oneDDerivatives[k][ijkCounter[k]]
890 : oneDValuesShort[k][ijkCounter[k]];
896 template <
size_type k>
897 void evaluate(
const typename std::array<int,k>& directions,
898 const FieldVector<typename GV::ctype,dim>& in,
899 std::vector<FieldVector<R,1> >& out,
900 const std::array<unsigned,dim>& currentKnotSpan)
const
902 if (k != 1 && k != 2)
903 DUNE_THROW(RangeError,
"Differentiation order greater than 2 is not supported!");
906 std::array<std::vector<R>, dim> oneDValues;
907 std::array<std::vector<R>, dim> oneDDerivatives;
908 std::array<std::vector<R>, dim> oneDSecondDerivatives;
912 for (
size_t i=0; i<dim; i++)
913 evaluateAll(in[i], oneDValues[i],
true, oneDDerivatives[i],
false, oneDSecondDerivatives[i],
knotVectors_[i],
order_[i], currentKnotSpan[i]);
915 for (
size_t i=0; i<dim; i++)
919 std::array<unsigned int, dim> offset;
920 for (
int i=0; i<dim; i++)
921 offset[i] = std::max((
int)(currentKnotSpan[i] -
order_[i]),0);
924 std::array<unsigned int, dim> limits;
925 for (
int i=0; i<dim; i++)
930 if (currentKnotSpan[i]<
order_[i])
931 limits[i] -= (
order_[i] - currentKnotSpan[i]);
938 std::array<std::vector<R>, dim> oneDValuesShort;
940 for (
int i=0; i<dim; i++)
942 oneDValuesShort[i].resize(limits[i]);
944 for (
size_t j=0; j<limits[i]; j++)
945 oneDValuesShort[i][j] = oneDValues[i][offset[i] + j];
949 MultiDigitCounter ijkCounter(limits);
951 out.resize(ijkCounter.cycle());
956 for (
size_t i=0; i<out.size(); i++, ++ijkCounter)
959 for (
int l=0; l<dim; l++)
960 out[i][0] *= (directions[0]==l) ? oneDDerivatives[l][ijkCounter[l]]
961 : oneDValuesShort[l][ijkCounter[l]];
968 for (
size_t i=0; i<out.size(); i++, ++ijkCounter)
971 for (
int j=0; j<dim; j++)
973 if (directions[0] != directions[1])
974 if (directions[0] == j || directions[1] == j)
975 out[i][0] *= oneDDerivatives[j][ijkCounter[j]];
977 out[i][0] *= oneDValuesShort[j][ijkCounter[j]];
979 if (directions[0] == j)
980 out[i][0] *= oneDSecondDerivatives[j][ijkCounter[j]];
982 out[i][0] *= oneDValuesShort[j][ijkCounter[j]];
993 static std::array<unsigned int,dim>
getIJK(
typename GridView::IndexSet::IndexType idx, std::array<unsigned int,dim>
elements)
995 std::array<unsigned,dim> result;
996 for (
int i=0; i<dim; i++)
1013 const std::vector<R>& knotVector,
1015 unsigned int currentKnotSpan)
1017 std::size_t outSize = order+1;
1018 if (currentKnotSpan<order)
1019 outSize -= (order - currentKnotSpan);
1020 if ( order > (knotVector.size() - currentKnotSpan - 2) )
1021 outSize -= order - (knotVector.size() - currentKnotSpan - 2);
1022 out.resize(outSize);
1025 DynamicMatrix<R> N(order+1, knotVector.size()-1);
1033 for (
size_t i=0; i<knotVector.size()-1; i++)
1034 N[0][i] = (i == currentKnotSpan);
1036 for (
size_t r=1; r<=order; r++)
1037 for (
size_t i=0; i<knotVector.size()-r-1; i++)
1039 R factor1 = ((knotVector[i+r] - knotVector[i]) > 1e-10)
1040 ? (in - knotVector[i]) / (knotVector[i+r] - knotVector[i])
1042 R factor2 = ((knotVector[i+r+1] - knotVector[i+1]) > 1e-10)
1043 ? (knotVector[i+r+1] - in) / (knotVector[i+r+1] - knotVector[i+1])
1045 N[r][i] = factor1 * N[r-1][i] + factor2 * N[r-1][i+1];
1052 for (
size_t i=0; i<out.size(); i++) {
1053 out[i] = N[order][std::max((
int)(currentKnotSpan - order),0) + i];
1070 DynamicMatrix<R>& out,
1071 const std::vector<R>& knotVector,
1073 unsigned int currentKnotSpan)
1076 DynamicMatrix<R>& N = out;
1078 N.resize(order+1, knotVector.size()-1);
1086 for (
size_t i=0; i<knotVector.size()-1; i++)
1087 N[0][i] = (i == currentKnotSpan);
1089 for (
size_t r=1; r<=order; r++)
1090 for (
size_t i=0; i<knotVector.size()-r-1; i++)
1092 R factor1 = ((knotVector[i+r] - knotVector[i]) > 1e-10)
1093 ? (in - knotVector[i]) / (knotVector[i+r] - knotVector[i])
1095 R factor2 = ((knotVector[i+r+1] - knotVector[i+1]) > 1e-10)
1096 ? (knotVector[i+r+1] - in) / (knotVector[i+r+1] - knotVector[i+1])
1098 N[r][i] = factor1 * N[r-1][i] + factor2 * N[r-1][i+1];
1112 std::vector<R>& out,
1114 bool evaluateHessian, std::vector<R>& outHess,
1115 const std::vector<R>& knotVector,
1117 unsigned int currentKnotSpan)
1122 if (currentKnotSpan<order)
1123 limit -= (order - currentKnotSpan);
1124 if ( order > (knotVector.size() - currentKnotSpan - 2) )
1125 limit -= order - (knotVector.size() - currentKnotSpan - 2);
1128 unsigned int offset;
1129 offset = std::max((
int)(currentKnotSpan - order),0);
1132 DynamicMatrix<R> values;
1136 out.resize(knotVector.size()-order-1);
1137 for (
size_t j=0; j<out.size(); j++)
1138 out[j] = values[order][j];
1141 std::vector<R> lowOrderOneDValues;
1145 lowOrderOneDValues.resize(knotVector.size()-(order-1)-1);
1146 for (
size_t j=0; j<lowOrderOneDValues.size(); j++)
1147 lowOrderOneDValues[j] = values[order-1][j];
1151 std::vector<R> lowOrderTwoDValues;
1153 if (order>1 && evaluateHessian)
1155 lowOrderTwoDValues.resize(knotVector.size()-(order-2)-1);
1156 for (
size_t j=0; j<lowOrderTwoDValues.size(); j++)
1157 lowOrderTwoDValues[j] = values[order-2][j];
1163 outJac.resize(limit);
1166 std::fill(outJac.begin(), outJac.end(), R(0.0));
1169 for (
size_t j=offset; j<offset+limit; j++)
1171 R derivativeAddend1 = lowOrderOneDValues[j] / (knotVector[j+order]-knotVector[j]);
1172 R derivativeAddend2 = lowOrderOneDValues[j+1] / (knotVector[j+order+1]-knotVector[j+1]);
1174 if (std::isnan(derivativeAddend1))
1175 derivativeAddend1 = 0;
1176 if (std::isnan(derivativeAddend2))
1177 derivativeAddend2 = 0;
1178 outJac[j-offset] = order * ( derivativeAddend1 - derivativeAddend2 );
1184 if (evaluateHessian)
1186 outHess.resize(limit);
1189 std::fill(outHess.begin(), outHess.end(), R(0.0));
1192 for (
size_t j=offset; j<offset+limit; j++)
1194 assert(j+2 < lowOrderTwoDValues.size());
1195 R derivativeAddend1 = lowOrderTwoDValues[j] / (knotVector[j+order]-knotVector[j]) / (knotVector[j+order-1]-knotVector[j]);
1196 R derivativeAddend2 = lowOrderTwoDValues[j+1] / (knotVector[j+order]-knotVector[j]) / (knotVector[j+order]-knotVector[j+1]);
1197 R derivativeAddend3 = lowOrderTwoDValues[j+1] / (knotVector[j+order+1]-knotVector[j+1]) / (knotVector[j+order]-knotVector[j+1]);
1198 R derivativeAddend4 = lowOrderTwoDValues[j+2] / (knotVector[j+order+1]-knotVector[j+1]) / (knotVector[j+1+order]-knotVector[j+2]);
1201 if (std::isnan(derivativeAddend1))
1202 derivativeAddend1 = 0;
1203 if (std::isnan(derivativeAddend2))
1204 derivativeAddend2 = 0;
1205 if (std::isnan(derivativeAddend3))
1206 derivativeAddend3 = 0;
1207 if (std::isnan(derivativeAddend4))
1208 derivativeAddend4 = 0;
1209 outHess[j-offset] = order * (order-1) * ( derivativeAddend1 - derivativeAddend2 -derivativeAddend3 + derivativeAddend4 );
1230template<
typename GV>
1232 public LeafBasisNode
1234 static const int dim = GV::dimension;
1238 using size_type = std::size_t;
1239 using Element =
typename GV::template Codim<0>::Entity;
1243 preBasis_(preBasis),
1244 finiteElement_(*preBasis)
1248 const Element& element()
const
1257 const FiniteElement& finiteElement()
const
1259 return finiteElement_;
1263 void bind(
const Element& e)
1266 auto elementIndex = preBasis_->gridView().indexSet().index(e);
1267 finiteElement_.bind(preBasis_->getIJK(elementIndex,preBasis_->elements_));
1268 this->setSize(finiteElement_.size());
1273 const BSplinePreBasis<GV>* preBasis_;
1275 FiniteElement finiteElement_;
1281namespace BasisFactory {
1289inline auto bSpline(
const std::vector<double>& knotVector,
1291 bool makeOpen =
true)
1293 return [&knotVector, order, makeOpen](
const auto& gridView) {
1294 return BSplinePreBasis<std::decay_t<
decltype(gridView)>>(gridView, knotVector, order, makeOpen);
1310template<
typename GV>
LocalBasis class in the sense of dune-localfunctions, presenting the restriction of a B-spline patch ...
Definition: bsplinebasis.hh:51
LocalBasisTraits< D, dim, FieldVector< D, dim >, R, 1, FieldVector< R, 1 >, FieldMatrix< R, 1, dim > > Traits
export type traits for function signature
Definition: bsplinebasis.hh:60
unsigned int order() const
Polynomial order of the shape functions.
Definition: bsplinebasis.hh:147
std::size_t size() const
Return the number of basis functions on the current knot span.
Definition: bsplinebasis.hh:154
void evaluate(const typename std::array< int, k > &directions, const typename Traits::DomainType &in, std::vector< typename Traits::RangeType > &out) const
Evaluate all shape functions and derivatives of any order.
Definition: bsplinebasis.hh:104
void evaluateFunction(const FieldVector< D, dim > &in, std::vector< FieldVector< R, 1 > > &out) const
Evaluate all shape functions.
Definition: bsplinebasis.hh:76
void evaluateJacobian(const FieldVector< D, dim > &in, std::vector< FieldMatrix< D, 1, dim > > &out) const
Evaluate Jacobian of all shape functions.
Definition: bsplinebasis.hh:89
BSplineLocalBasis(const BSplinePreBasis< GV > &preBasis, const BSplineLocalFiniteElement< GV, R > &lFE)
Constructor with a given B-spline patch.
Definition: bsplinebasis.hh:66
Attaches a shape function to an entity.
Definition: bsplinebasis.hh:185
const LocalKey & localKey(std::size_t i) const
get i'th index
Definition: bsplinebasis.hh:328
std::size_t size() const
number of coefficients
Definition: bsplinebasis.hh:322
LocalFiniteElement in the sense of dune-localfunctions, for the B-spline basis on tensor-product grid...
Definition: bsplinebasis.hh:369
BSplineLocalFiniteElement(const BSplineLocalFiniteElement &other)
Copy constructor.
Definition: bsplinebasis.hh:390
const BSplineLocalInterpolation< dim, BSplineLocalBasis< GV, R > > & localInterpolation() const
Hand out a LocalInterpolation object.
Definition: bsplinebasis.hh:446
LocalFiniteElementTraits< BSplineLocalBasis< GV, R >, BSplineLocalCoefficients< dim >, BSplineLocalInterpolation< dim, BSplineLocalBasis< GV, R > > > Traits
Export various types related to this LocalFiniteElement.
Definition: bsplinebasis.hh:379
BSplineLocalFiniteElement(const BSplinePreBasis< GV > &preBasis)
Constructor with a given B-spline basis.
Definition: bsplinebasis.hh:383
const BSplineLocalCoefficients< dim > & localCoefficients() const
Hand out a LocalCoefficients object.
Definition: bsplinebasis.hh:440
void bind(const std::array< unsigned, dim > &elementIdx)
Bind LocalFiniteElement to a specific knot span of the spline patch.
Definition: bsplinebasis.hh:401
GeometryType type() const
Return the reference element that the local finite element is defined on (here, a hypercube)
Definition: bsplinebasis.hh:462
unsigned size() const
Number of shape functions in this finite element.
Definition: bsplinebasis.hh:452
unsigned int size(int i) const
Number of degrees of freedom for one coordinate direction.
Definition: bsplinebasis.hh:470
const BSplineLocalBasis< GV, R > & localBasis() const
Hand out a LocalBasis object.
Definition: bsplinebasis.hh:434
Local interpolation in the sense of dune-localfunctions, for the B-spline basis on tensor-product gri...
Definition: bsplinebasis.hh:347
void interpolate(const F &f, std::vector< C > &out) const
Local interpolation of a function.
Definition: bsplinebasis.hh:351
Pre-basis for B-spline basis.
Definition: bsplinebasis.hh:507
std::array< unsigned, dim > elements_
Number of grid elements in the different coordinate directions.
Definition: bsplinebasis.hh:1223
static void evaluateFunctionFull(const typename GV::ctype &in, DynamicMatrix< R > &out, const std::vector< R > &knotVector, unsigned int order, unsigned int currentKnotSpan)
Evaluate all one-dimensional B-spline functions for a given coordinate direction.
Definition: bsplinebasis.hh:1069
void evaluateFunction(const FieldVector< typename GV::ctype, dim > &in, std::vector< FieldVector< R, 1 > > &out, const std::array< unsigned, dim > ¤tKnotSpan) const
Evaluate all B-spline basis functions at a given point.
Definition: bsplinebasis.hh:765
std::array< unsigned int, dim > order_
Order of the B-spline for each space dimension.
Definition: bsplinebasis.hh:1217
static void evaluateAll(const typename GV::ctype &in, std::vector< R > &out, bool evaluateJacobian, std::vector< R > &outJac, bool evaluateHessian, std::vector< R > &outHess, const std::vector< R > &knotVector, unsigned int order, unsigned int currentKnotSpan)
Evaluate the second derivatives of all one-dimensional B-spline functions for a given coordinate dire...
Definition: bsplinebasis.hh:1111
static void evaluateFunction(const typename GV::ctype &in, std::vector< R > &out, const std::vector< R > &knotVector, unsigned int order, unsigned int currentKnotSpan)
Evaluate all one-dimensional B-spline functions for a given coordinate direction.
Definition: bsplinebasis.hh:1012
unsigned int size(size_t d) const
Number of shape functions in one direction.
Definition: bsplinebasis.hh:756
GV GridView
The grid view that the FE space is defined on.
Definition: bsplinebasis.hh:570
It indices(const Node &node, It it) const
Maps from subtree index set [0..size-1] to a globally unique multi index in global basis.
Definition: bsplinebasis.hh:717
void evaluate(const typename std::array< int, k > &directions, const FieldVector< typename GV::ctype, dim > &in, std::vector< FieldVector< R, 1 > > &out, const std::array< unsigned, dim > ¤tKnotSpan) const
Evaluate Derivatives of all B-spline basis functions.
Definition: bsplinebasis.hh:897
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: bsplinebasis.hh:693
unsigned int dimension() const
Total number of B-spline basis functions.
Definition: bsplinebasis.hh:747
void initializeIndices()
Initialize the global indices.
Definition: bsplinebasis.hh:683
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: bsplinebasis.hh:687
static std::array< unsigned int, dim > getIJK(typename GridView::IndexSet::IndexType idx, std::array< unsigned int, dim > elements)
Compute integer element coordinates from the element index.
Definition: bsplinebasis.hh:993
Node makeNode() const
Create tree node.
Definition: bsplinebasis.hh:701
BSplinePreBasis(const GridView &gridView, const std::vector< double > &knotVector, unsigned int order, bool makeOpen=true)
Construct a B-spline basis for a given grid view and set of knot vectors.
Definition: bsplinebasis.hh:597
void evaluateJacobian(const FieldVector< typename GV::ctype, dim > &in, std::vector< FieldMatrix< R, 1, dim > > &out, const std::array< unsigned, dim > ¤tKnotSpan) const
Evaluate Jacobian of all B-spline basis functions.
Definition: bsplinebasis.hh:796
std::array< std::vector< double >, dim > knotVectors_
The knot vectors, one for each space dimension.
Definition: bsplinebasis.hh:1220
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: bsplinebasis.hh:707
BSplinePreBasis(const GridView &gridView, const FieldVector< double, dim > &lowerLeft, const FieldVector< double, dim > &upperRight, const std::array< unsigned int, dim > &elements, unsigned int order, bool makeOpen=true)
Construct a B-spline basis for a given grid view with uniform knot vectors.
Definition: bsplinebasis.hh:649
Global basis for given pre-basis.
Definition: defaultglobalbasis.hh:53
A generic MixIn class for PreBasis.
Definition: leafprebasismixin.hh:36
size_type size() const
Get the total dimension of the space spanned by this basis.
Definition: leafprebasismixin.hh:60
auto bSpline(const std::vector< double > &knotVector, unsigned int order, bool makeOpen=true)
Create a pre-basis factory that can create a B-spline pre-basis.
Definition: bsplinebasis.hh:1289
auto elements(const SubDomainGridView< HostGridView > &subDomainGridView)
ADL findable access to element range for a SubDomainGridView.
Definition: subdomain.hh:487
Definition: monomialset.hh:19