G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsTensorBSplineBasis.hpp
Go to the documentation of this file.
1
14#pragma once
15
20#include <gsNurbs/gsBoehm.h>
21
22#include <gsIO/gsXml.h>
24
25
26namespace gismo
27{
28
29template<short_t d, class T>
30gsTensorBSplineBasis<d,T>::gsTensorBSplineBasis(std::vector<typename gsTensorBSplineBasis<d,T>::Basis_t*> & bb )
31: Base( castVectorPtr<gsBasis<T> >(bb).data() )
32{
33 GISMO_ASSERT( checkVectorPtrCast<Basis_t>(bb), "Invalid vector of basis pointers.");
34 GISMO_ENSURE( d == bb.size(), "Wrong d in the constructor of gsTensorBSplineBasis." );
35 bb.clear();
36 setIsPeriodic();
37}
38
39template<short_t d, class T>
40gsTensorBSplineBasis<d,T>::gsTensorBSplineBasis(std::vector<gsBasis<T>*> & bb )
41: Base(bb.data())
42{
43 GISMO_ENSURE( d == bb.size(), "Wrong d in the constructor of gsTensorBSplineBasis." );
44 bb.clear();
45 setIsPeriodic();
46}
47
48template<short_t d, class T>
52 gsVector<index_t,d>& upp ) const
53{
54 for (index_t j = 0; j < u.cols(); ++j)
55 {
56 for (short_t i = 0; i < d; ++i)
57 {
58 low[i] = component(i).firstActive( u(i,j) );
59 upp[i] = low[i] + component(i).degree();
60 }
61 }
62}
63
64template<short_t d, class T>
67 const std::vector< std::vector<T> >& refineKnots)
68{
69 GISMO_ASSERT( refineKnots.size() == d, "refineKnots vector has wrong size" );
71
72 // refine component bases and obtain their transfer matrices
73 for (unsigned i = 0; i < d; ++i)
74 {
75 this->component(i).refine_withTransfer( B[i], refineKnots[i] );
76 }
77
78 tensorCombineTransferMatrices<d, T>( B, transfer );
79}
80
81template<short_t d, class T>
83refine_withCoefs(gsMatrix<T> & coefs,const std::vector< std::vector<T> >& refineKnots)
84{
85 GISMO_ASSERT( refineKnots.size() == d, "refineKnots vector has wrong size" );
86 gsVector<unsigned> strides(d);
87 for (unsigned j = 0; j < d; ++j) //calculate the strides for each direction
88 {
89 strides[j]=this->stride(j);
90 }
91 for (unsigned i = 0; i < d; ++i)
92 {
93 if(refineKnots[i].size()>0)
94 {
95 gsTensorBoehmRefine(this->component(i).knots(), coefs, i, strides,
96 refineKnots[i].begin(), refineKnots[i].end(), true);
97
98 for (index_t j = i+1; j<strides.rows(); ++j)
99 strides[j]=this->stride(j); //new stride for this direction
100 }
101 }
102}
103
104
105template<short_t d, class T>
106std::vector<std::vector<T>> gsTensorBSplineBasis<d,T>::_boxToKnots(gsMatrix<T> const & boxes)
107{
108 std::vector<std::vector<T>> result(d);
109 GISMO_ASSERT( boxes.rows() == this->dim() ,
110 "Number of rows of refinement boxes must equal dimension of parameter space.");
111 GISMO_ASSERT( boxes.cols() % 2 == 0,
112 "Refinement boxes must have even number of columns.");
113
114 const T tol = 0.000000001;
115
116 // for each coordinate direction of the parameter domain:
117 for( short_t di = 0; di < this->dim(); di++)
118 {
119
120 // for simplicity, get the corresponding knot vector.
121 KnotVectorType kold_di = Self_t::component(di).knots();
122
123 // vector of flags for refining knotspans
124 std::vector<bool> flagInsertKt( kold_di.size(), false);
125
126 // This is a very crude and unelegant test, but
127 // conveniently straightforward to implement (and maybe to):
128 // For each knot span, check if its midpoint is
129 // contained in any of the refinement boxes.
130 // If yes, set the corresponding flag to 1.
131 for( size_t i=1; i < kold_di.size(); i++ ) // loop over spans
132 if( kold_di[i]-kold_di[i-1] > tol) // check for empty spans
133 {
134 const T midpt = (kold_di[i] + kold_di[i-1])/(T)(2); // midpoint of knot span
135 for( index_t j=0; j < boxes.cols(); j+=2 ) // loop over all boxes
136 {
137 // if the box contains the midpoint, mark it
138 flagInsertKt[i] = boxes(di,j) < midpt && midpt < boxes(di,j+1);
139 }
140 }
141
142 // now, with the flags set, loop over all knots spans and
143 // insert midpoint in each knot span which is marked for refinement.
144 for( size_t i=1; i < kold_di.size(); i++ )
145 if( flagInsertKt[i] )
146 {
147 T midpt = (kold_di[i] + kold_di[i-1])/(T)(2);
148 result[di].push_back(midpt);
149 // Self_t::component(di).insertKnot( midpt );
150 }
151 } // for( int di )
152 return result;
153}
154
155template<short_t d, class T>
157{
158 // Note: refExt parameter is ignored
159 std::vector<std::vector<T>> knots = this->_boxToKnots(boxes);
160 for( short_t di = 0; di < d; di++)
161 for( size_t i=1; i < knots[di].size(); i++ )
162 Self_t::component(di).insertKnot(knots[di][i]);
163
164} // refine()
165
166
167/*
168 * NB:
169 * This implementation assumes that the component bases implement the firstActive() / numActive() protocol.
170 * In particular, their active basis functions must always be continuous intervals.
171 * This is the case for all current component bases, so we only keep this version for now.
172 * Above, commented out, is the generic version which is quite a bit slower.
173 */
174template<short_t d, class T>
176active_into(const gsMatrix<T> & u, gsMatrix<index_t>& result) const
177{
178 GISMO_ASSERT( u.rows() == static_cast<index_t>(d), "Invalid point dimension: "<<u.rows()<<", expected "<< d);
179
180 unsigned firstAct[d];
181 gsVector<unsigned, d> v, size;
182
183 // count active functions in each tensor direction
184 unsigned numAct = 1;
185 for (unsigned i = 0; i < d; ++i)
186 {
187 size[i] = component(i).numActive();
188 numAct *= size[i];
189 }
190
191 result.resize( numAct, u.cols() );
192
193 // Fill with active bases indices
194 for (index_t j = 0; j < u.cols(); ++j)
195 {
196 // get the active basis indices for the component bases at u(:,j)
197 for (short_t i = 0; i < d; ++i)
198 {
199 firstAct[i] = component(i).firstActive( u(i,j) );
200 }
201
202 // iterate over all tensor product active functions
203 unsigned r = 0;
204 v.setZero();
205 do
206 {
207 index_t gidx = firstAct[d-1] + v(d-1); //compute global index in the tensor product
208 for ( short_t i=d-2; i>=0; --i )
209 gidx = gidx * this->size(i) + firstAct[i] + v(i);
210
211 result(r, j) = gidx;
212 ++r ;
213 } while (nextLexicographic(v, size));
214 }
215}
216
217
218namespace internal
220
222template<short_t d, class T>
223class gsXml< gsTensorBSplineBasis<d,T> >
224{
225private:
226 gsXml() { }
227 typedef gsTensorBSplineBasis<d,T> Object;
228public:
229 GSXML_COMMON_FUNCTIONS(Object);
230 static std::string tag () { return "Basis"; }
231 static std::string type () { return "TensorBSplineBasis"+to_string(d); }
232
233 static Object * get (gsXmlNode * node)
234 {
235 if (d>1)
236 {
237 GISMO_ASSERT( ( !strcmp( node->name(),"Basis") )
238 && ( !strcmp(node->first_attribute("type")->value(),
239 internal::gsXml<Object>::type().c_str() ) ),
240 "Something is wrong with the XML data: There should be a node with a "
241 <<internal::gsXml<Object>::type().c_str()<<" Basis.");
242 }
243 else
244 {
245 GISMO_ASSERT( ( !strcmp( node->name(),"Basis") )
246 && ( !strcmp(node->first_attribute("type")->value(),
247 internal::gsXml<Object>::type().c_str())
248 || !strcmp(node->first_attribute("type")->value(), "BSplineBasis") ),
249 "Something is wrong with the XML data: There should be a node with a "
250 <<internal::gsXml<Object>::type().c_str()<<" Basis.");
251 }
252
253 return getTensorBasisFromXml<Object >( node );
254 }
255
256 static gsXmlNode * put (const Object & obj,
257 gsXmlTree & data )
258 {
259 return putTensorBasisToXml<Object >(obj,data);
260 }
261};
262
263} // internal
264
265} // gismo
266
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
Sparse matrix class, based on gsEigen::SparseMatrix.
Definition gsSparseMatrix.h:139
A tensor product B-spline basis.
Definition gsTensorBSplineBasis.h:37
gsTensorBSplineBasis()
Default constructor.
Definition gsTensorBSplineBasis.h:74
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
void gsTensorBoehmRefine(KnotVectorType &knots, Mat &coefs, int direction, gsVector< unsigned > str, ValIt valBegin, ValIt valEnd, bool update_knots=true)
Definition gsBoehm.hpp:372
bool nextLexicographic(Vec &cur, const Vec &size)
Iterates through a tensor lattice with the given size. Updates cur and returns true if another entry ...
Definition gsCombinatorics.h:196
Boehm's algorithm for knot insertion.
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
#define GISMO_ENSURE(cond, message)
Definition gsDebug.h:102
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Knot vector for B-splines.
Utilities related to template programming.
Provides declaration of TensorBSplineBasis abstract interface.
Utility functions related to tensor-structured objects.
Provides implementation of generic XML functions.
Provides declaration of input/output XML utilities struct.
The G+Smo namespace, containing all definitions for the library.
std::vector< Base * > castVectorPtr(std::vector< Derived * > pVec)
Casts a vector of pointers.
Definition gsMemory.h:344