G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsMPBESMapTensor.h
Go to the documentation of this file.
1
14// This class gsMPBESMapTensor has the sole purpose of creating a mapping of the type gsWeightMapper
15
16#pragma once
17
18#include <gsNurbs/gsBoehm.h>
20
21namespace gismo
22{
31template<short_t d,class T>
33{
34private:
35
36 typedef T weightType;
37 typedef index_t indexType; //indizes of gsMatrix
38 typedef std::vector<std::pair<index_t,index_t> >::iterator step_iter;
39 typedef gsBasis<T> BasisType;
40 typedef typename std::vector<BasisType *>::const_iterator ConstBasisIter;
41 typedef typename std::vector<BasisType *>::iterator BasisIter;
42 typedef typename std::vector<gsMatrix<T> *>::const_iterator ConstMatrixPtrIter;
44 typedef std::vector<indexType> IndexContainer;
45 typedef std::vector<indexType>::const_iterator ConstIndexIter;
46 //index_t m_dim = 2;
47
48public:
49 gsMPBESMapTensor(index_t incrSmoothnessDegree, gsBoxTopology * topol, gsMPBESBasis<d,T> * basis) :
50 m_incrSmoothnessDegree(incrSmoothnessDegree), m_topol(topol), m_basis(basis), m_global(0)
51 {
52 m_mapper=NULL;
53 }
54
55 virtual ~gsMPBESMapTensor() { }
56
58 // Virtual member functions required by the base class
60
61 gsWeightMapper<T> * makeMapper() const
62 {
63 index_t locals = _getNrOfLocalBasisFunktions();
64 index_t size = m_basis->nPatches();
65 std::vector<index_t> offsets;
66 for(index_t i = 0;i<size;i++)
67 offsets.push_back(_getFirstLocalIndex(i));
68 m_mapper = new gsWeightMapper<T>(locals,locals);
69 for(index_t i = 0;i<size;i++)
70 _setMappingOfPatch(i);
71 _finalize();
72 gsWeightMapper<T> * mapper = m_mapper;
73 m_mapper = NULL;
74 return mapper;
75 }
76
77protected:
79 // general help functions for checking, finalizing and building of the mapping
81
82 virtual bool _checkMapping() const = 0;
83
84 virtual void _finalize() const = 0;
85
86 virtual void _setMappingOfPatch(index_t const patch) const = 0;
87
88 index_t _getNrOfLocalBasisFunktions() const
89 {
90 index_t size = 0;
91 for (size_t i = 0; i < m_basis->nPatches(); ++i)
92 size += m_basis->getBase(i).size();
93 return size;
94 }
95
96protected:
98 // function to construct a mapping of a tensorstructured patch
100
101 virtual index_t getDistanceOfVertex(const patchCorner& pc,const patchSide& ps) const = 0;
102
103 void _setTensorMappingOfPatch(index_t const patch) const
104 {
105 const gsBasis<T> & base = m_basis->getBase(patch);
106 index_t degree_u = std::min(base.degree(0),(short_t)(m_incrSmoothnessDegree+1));
107 index_t degree_v = std::min(base.degree(1),(short_t)(m_incrSmoothnessDegree+1));
108 index_t u_amount =_getParMax(patch,0)+1, v_amount=_getParMax(patch,1)+1;
109 patchSide ps_north(patch,boundary::north);
110 patchSide ps_south(patch,boundary::south);
111 patchSide ps_east(patch,boundary::east);
112 patchSide ps_west(patch,boundary::west);
113 bool north = m_topol->isInterface(ps_north);
114 bool south = m_topol->isInterface(ps_south);
115 bool east = m_topol->isInterface(ps_east);
116 bool west = m_topol->isInterface(ps_west);
117 patchCorner pc_northeast(patch,boundary::northeast);
118 patchCorner pc_northwest(patch,boundary::northwest);
119 patchCorner pc_southeast(patch,boundary::southeast);
120 patchCorner pc_southwest(patch,boundary::southwest);
121 bool northeast = m_basis->isSpecialVertex(pc_northeast);
122 bool northwest = m_basis->isSpecialVertex(pc_northwest);
123 bool southeast = m_basis->isSpecialVertex(pc_southeast);
124 bool southwest = m_basis->isSpecialVertex(pc_southwest);
125
126 index_t ne_l_u = getDistanceOfVertex(pc_northeast,ps_north);
127 index_t nw_l_u = getDistanceOfVertex(pc_northwest,ps_north);
128 index_t se_l_u = getDistanceOfVertex(pc_southeast,ps_south);
129 index_t sw_l_u = getDistanceOfVertex(pc_southwest,ps_south);
130 index_t se_l_v = getDistanceOfVertex(pc_southeast,ps_east);
131 index_t ne_l_v = getDistanceOfVertex(pc_northeast,ps_east);
132 index_t sw_l_v = getDistanceOfVertex(pc_southwest,ps_west);
133 index_t nw_l_v = getDistanceOfVertex(pc_northwest,ps_west);
134
135 if(ne_l_u+nw_l_u>u_amount)
136 {
137 ne_l_u=u_amount/2;
138 nw_l_u=u_amount-ne_l_u;
139 }
140 if(se_l_u+sw_l_u>u_amount)
141 {
142 se_l_u=u_amount/2;
143 sw_l_u=u_amount-se_l_u;
144 }
145 if(se_l_v+ne_l_v>v_amount)
146 {
147 se_l_v=v_amount/2;
148 ne_l_v=v_amount-se_l_v;
149 }
150 if(sw_l_v+nw_l_v>v_amount)
151 {
152 sw_l_v=v_amount/2;
153 nw_l_v=v_amount-sw_l_v;
154 }
155
156 index_t n_l_v = north ? degree_v : 0;
157 index_t s_l_v = south ? degree_v : 0;
158 index_t e_l_u = east ? degree_u : 0;
159 index_t w_l_u = west ? degree_u : 0;
160 // added for one-patch gluing
161 bool north_same=false;
162 bool east_same=false;
163 if(1==m_basis->nPatches())
164 {
165 north_same = south;
166 east_same = east;
167 }
168
169 index_t localIndex;
170 // south-west
171 for(index_t j = 0;j<sw_l_v ;j++)
172 for(index_t i = 0;i<sw_l_u ;i++)
173 {
174 if(!_getLocalIndex_into(patch,i,j,localIndex))
175 continue;
176 if(i>=degree_u&&j>=degree_v)
177 ;
178 else if((southwest||degree_u==1||degree_v==1) && i == 0 && j==0)
179 _addSingularCornerToMap(localIndex);
180 else if(southwest && west && i==0)
181 _addCombinedLineToMap(ps_west,localIndex,1,0);
182 else if(southwest && south && j==0)
183 _addCombinedLineToMap(ps_south,localIndex,1,0);
184 else if(!southwest && south && west)
185 _addCombinedBlockToMap(ps_south,ps_west,localIndex,degree_u,degree_v,j,i);
186 else if(!southwest && south && !west)
187 _addCombinedLineToMap(ps_south,localIndex,degree_v,j);
188 else if(!southwest && !south && west)
189 _addCombinedLineToMap(ps_west,localIndex,degree_u,i);
190 else
191 _addFreeToMap(localIndex);
192 }
193 // south-middle
194 for(index_t j=0;j<s_l_v;j++)
195 for(index_t i=sw_l_u;i<u_amount-se_l_u;i++)
196 {
197 if(!_getLocalIndex_into(patch,i,j,localIndex))
198 continue;
199 if(south)
200 _addCombinedLineToMap(ps_south,localIndex,degree_v,j);
201 else
202 _addFreeToMap(localIndex);
203 }
204 // south-east
205 for(index_t j = 0;j<se_l_v ;j++)
206 for(index_t i = u_amount-se_l_u; i<u_amount ;i++)
207 {
208 if(!_getLocalIndex_into(patch,i,j,localIndex))
209 continue;
210 if(i<u_amount-degree_u&&j>=degree_v)
211 continue;
212 else if(!southeast&&east_same)
213 continue;
214 else if((southeast||degree_u==1||degree_v==1) && i == u_amount-1 && j==0)
215 _addSingularCornerToMap(localIndex);
216 else if(southeast && east && i==u_amount-1)
217 _addCombinedLineToMap(ps_east,localIndex,1,0);
218 else if(southeast && south && j==0)
219 _addCombinedLineToMap(ps_south,localIndex,1,0);
220 else if(!southeast && south && east)
221 _addCombinedBlockToMap(ps_south,ps_east,localIndex,degree_u,degree_v,j,u_amount-1-i);
222 else if(!southeast && south && !east)
223 _addCombinedLineToMap(ps_south,localIndex,degree_v,j);
224 else if(!southeast && !south && east)
225 _addCombinedLineToMap(ps_east,localIndex,degree_u,u_amount-1-i);
226 else
227 _addFreeToMap(localIndex);
228 }
229 // west-middle
230 for(index_t j=sw_l_v;j<v_amount-nw_l_v;j++)
231 for(index_t i=0;i<w_l_u;i++)
232 {
233 if(!_getLocalIndex_into(patch,i,j,localIndex))
234 continue;
235 if(west)
236 _addCombinedLineToMap(ps_west,localIndex,degree_u,i);
237 else
238 _addFreeToMap(localIndex);
239 }
240 // middle-middle
241 for(index_t j=s_l_v;j<v_amount-n_l_v;j++)
242 for(index_t i=w_l_u;i<u_amount-e_l_u;i++)
243 {
244 if(j<sw_l_v&&j<degree_v&&i<sw_l_u&&i<degree_u)
245 continue;
246 if(j<se_l_v&&j<degree_v&&i>=u_amount-se_l_u&&i>=u_amount-degree_u)
247 continue;
248 if(j>=v_amount-ne_l_v&&j>=v_amount-degree_v&&i>=u_amount-ne_l_u&&i>=u_amount-degree_u)
249 continue;
250 if(j>=v_amount-nw_l_v&&j>=v_amount-degree_v&&i<nw_l_u&&i<degree_u)
251 continue;
252 if(!_getLocalIndex_into(patch,i,j,localIndex))
253 continue;
254 _addFreeToMap(localIndex);
255 }
256 // east-middle
257 for(index_t j=se_l_v;j<v_amount-ne_l_v;j++)
258 for(index_t i=u_amount-e_l_u;i<u_amount;i++)
259 {
260 if(!_getLocalIndex_into(patch,i,j,localIndex))
261 continue;
262 if(east&&east_same)
263 continue;
264 if(east)
265 _addCombinedLineToMap(ps_east,localIndex,degree_u,u_amount-1-i);
266 else
267 _addFreeToMap(localIndex);
268 }
269 // north-west
270 for(index_t j = v_amount-nw_l_v;j<v_amount ;j++)
271 for(index_t i = 0; i<nw_l_u ;i++)
272 {
273 if(!_getLocalIndex_into(patch,i,j,localIndex))
274 continue;
275 if(i>=degree_u&&j<v_amount-degree_v)
276 continue;
277 else if(!northwest&&north_same)
278 continue;
279 else if((northwest||degree_u==1||degree_v==1) && i == 0 && j==v_amount-1)
280 _addSingularCornerToMap(localIndex);
281 else if(northwest && west && i==0)
282 _addCombinedLineToMap(ps_west,localIndex,1,0);
283 else if(northwest && north && j==v_amount-1)
284 _addCombinedLineToMap(ps_north,localIndex,1,0);
285 else if(!northwest && north && west)
286 _addCombinedBlockToMap(ps_north,ps_west,localIndex,degree_u,degree_v,v_amount-1-j,i);
287 else if(!northwest && north && !west)
288 _addCombinedLineToMap(ps_north,localIndex,degree_v,v_amount-1-j);
289 else if(!northwest && !north && west)
290 _addCombinedLineToMap(ps_west,localIndex,degree_u,i);
291 else
292 _addFreeToMap(localIndex);
293 }
294 // north-middle
295 for(index_t j=v_amount-n_l_v;j<v_amount;j++)
296 for(index_t i=nw_l_u;i<u_amount-ne_l_u;i++)
297 {
298 if(!_getLocalIndex_into(patch,i,j,localIndex))
299 continue;
300 if(north&&north_same)
301 continue;
302 if(north)
303 _addCombinedLineToMap(ps_north,localIndex,degree_v,v_amount-1-j);
304 else
305 _addFreeToMap(localIndex);
306 }
307 // north-east
308 for(index_t j = v_amount-ne_l_v;j<v_amount ;j++)
309 for(index_t i = u_amount-ne_l_u; i<u_amount ;i++)
310 {
311 if(!_getLocalIndex_into(patch,i,j,localIndex))
312 continue;
313 if(i<u_amount-degree_u&&j<v_amount-degree_v)
314 continue;
315 else if(!northeast&&(north_same||east_same))
316 continue;
317 else if((northeast||degree_u==1||degree_v==1) && i == u_amount-1 && j==v_amount-1)
318 _addSingularCornerToMap(localIndex);
319 else if(northeast && east && i==u_amount-1)
320 _addCombinedLineToMap(ps_east,localIndex,1,0);
321 else if(northeast && north && j==v_amount-1)
322 _addCombinedLineToMap(ps_north,localIndex,1,0);
323 else if(!northeast && north && east)
324 _addCombinedBlockToMap(ps_north,ps_east,localIndex,degree_u,degree_v,v_amount-1-j,u_amount-1-i);
325 else if(!northeast && north && !east)
326 _addCombinedLineToMap(ps_north,localIndex,degree_v,v_amount-1-j);
327 else if(!northeast && !north && east)
328 _addCombinedLineToMap(ps_east,localIndex,degree_u,u_amount-1-i);
329 else
330 _addFreeToMap(localIndex);
331 }
332// gsVector<index_t> point(m_dim);
333// std::vector<index_t> lengths(m_dim);
334// lengths.push_back(degree_u);
335// lengths.push_back(degree_v);
336// std::vector<index_t> maxima(m_dim);
337// maxima.push_back(u_amount);
338// maxima.push_back(v_amount);
339// std::vector<index_t> distances(m_dim);
340// point.setZero();
341// do
342// {
343// if(!_getLocalIndex_into(patch,point[0],point[1],localIndex))
344// continue;
345// if(_isInMiddle(point,lengths,maxima))
346// addFreeToMap();
347// _getDistancesToBoundary(point,distances);
348// for(index_t i = 0;i<point.rows();++i)
349// {
350
351// //dists
352// //sides
353// }
354// _addBlockToMap(localIndex, sides, lengths, dists);
355
356// if(m_topol->getDistancesToBoundary(patch,point,lengths,distances))
357// addFreeToMap();
358// else if(m_topol->pointIsNearCp(patch,point))
359// addCombinedLineToMap();
360// else if(m_topol->pointIsNextToSmoothCorner(patch,point))
361// addCombinedBlockToMap();
362// else
363// addFreeToMap();
364// }while(_nextPoint(lengths,point));
365 }
366
367// bool _isInMiddle(const gsVector<index_t>& point,const std::vector<index_t>& lengths,
368// const std::vector<index_t>& maxima)
369// {
370// for(index_t i = 0;i<point.rows();++i)
371// {
372// if(point(i)<lengths[i]||maxima[i]-lengths[i]<point(i))
373// return false;
374// }
375// return true;
376// }
377
378// void _getDistancesToBoundary(const gsVector<index_t>& point, std::vector<index_t>& dists)
379// {
380// for(index_t i = 0;i<point.rows();++i)
381// {
382// dists.push_back(point((i+1)%point.rows()));
383// }
384// }
385private:
387 // functions calculating the weights for the mapping
389
390 void _getBoehmCoefs(gsKnotVector<T> kv0i,bool dir0,T weight0,gsKnotVector<T> kv1i,bool dir1,T weight1,index_t degree,index_t knot_index,std::vector<T> & result) const
391 {
392 result.clear();
393 if(degree==1)
394 {
395 result.push_back(1.0);
396 result.push_back(1.0);
397 return;
398 }
399 typedef typename std::vector<T>::iterator tIter;
400 std::vector<T> temp0 = kv0i.get();
401 std::vector<T> temp1 = kv1i.get();
402 for(tIter it = temp0.begin();it!=temp0.end();++it)
403 (*it)*=weight0;
404 for(tIter it = temp1.begin();it!=temp1.end();++it)
405 (*it)*=weight1;
406 gsKnotVector<T> kv0(give(temp0), kv0i.degree());
407 gsKnotVector<T> kv1(give(temp1), kv1i.degree());
408
409 index_t l0 = kv0.size();
410 if (!dir0)
411 kv0.reverse();
412 if (dir1)
413 kv1.reverse();
414 kv1.addConstant(kv0.last());
415 T inserted = kv0.last();
416 kv0.remove(kv0.last(),degree);
417 kv1.remove(kv1.first(),kv1.degree()+1);
418 kv0.append(kv1.begin(),kv1.end());
419 gsMatrix<T> boem_mat;
420 boem_mat.setZero(kv0.size()-kv0.degree()-1,1);
421 boem_mat.coeffRef(l0-(kv1.degree()+2)-knot_index)=1;
422 gsBoehm<T,gsKnotVector<T>,gsMatrix<T> >(kv0,boem_mat,inserted,degree-1,false);
423 for(index_t i = 0;i<degree;i++)
424 {
425 //index_t ind=dir0 ? boem_mat.rows()-1-i : i;
426 result.push_back(boem_mat.coeff(i+l0-(kv0.degree()+2)-knot_index,0));
427 if(i==knot_index)
428 result.push_back(boem_mat.coeff(i+l0-(kv0.degree()+2)-knot_index,0));
429 }
430 }
431
432protected:
433 virtual gsKnotVector<T> _getKnotVector(index_t const patch,index_t const par) const = 0;
434
435 virtual index_t _getParMax(index_t patch,bool par) const = 0;
436
437private:
439 // functions to look for one vertex in all the patches
441
442 bool _alreadyHandled(patchSide const & ps,bool flag) const
443 {
444 std::vector<indexType> vertices = _findVertexInPatches(ps,flag);
445 for(size_t i = 0;i<vertices.size();i++)
446 if(_getPatch(vertices[i]) < ps.patch )
447 return true;
448 return false;
449 }
450
451 bool _alreadyHandled(std::vector<index_t> local_BFs,index_t startPatch) const
452 {
453 for(size_t i = 0;i<local_BFs.size();i++)
454 if((index_t)startPatch>_getPatch(local_BFs[i]))
455 return true;
456 return false;
457 }
458
459 std::vector<indexType> _findVertexInPatches(patchSide ps, bool flag) const
460 {
461 gsVector<bool> v(2);
462 v(ps.direction())=ps.parameter();
463 v(1-ps.direction())=flag;
464 patchCorner start(ps.patch,boxCorner(v));
465 std::vector<patchCorner> cornerList;
466 m_topol->getCornerList(start,cornerList);
467 std::vector<indexType> vertices;
468 for(size_t i = 0;i<cornerList.size();++i)
469 vertices.push_back(_getLocalIndex(cornerList[i]));
470 return vertices;
471 }
472
473 void _flipOverCorner(patchSide & ps,bool & flag) const
474 {
475 index_t patch = ps.patch;
476 switch(ps.side())
477 {
478 case boundary::north : ps = patchSide(patch,flag ? boundary::east : boundary::west);
479 flag = 1;
480 break;
481 case boundary::south : ps = patchSide(patch,flag ? boundary::east : boundary::west);
482 flag = 0;
483 break;
484 case boundary::west : ps = patchSide(patch,flag ? boundary::north : boundary::south);
485 flag = 0;
486 break;
487 case boundary::east : ps = patchSide(patch,flag ? boundary::north : boundary::south);
488 flag = 1;
489 break;
490 default :
491 GISMO_ERROR("patchSide has no valid side.");
492 }
493 }
494
495private:
497 // functions for adding new map entries
499
500
501 void _addToMap(std::vector<indexType> indices,std::vector<weightType> weights) const
502 {
503 for(size_t i = 0;i<indices.size();++i)
504 m_mapper->setEntry(indices[i],m_global,weights[i]);
505 m_global++;
506 }
507
508 void _addFreeToMap(index_t localIndex) const
509 {
510 std::vector<indexType> indices;
511 indices.push_back(localIndex);
512 std::vector<weightType> weights;
513 weights.push_back(1);
514 _addToMap(indices,weights);
515 }
516
517 void _addSingularCornerToMap(index_t localIndex) const
518 {
519 index_t u=_getPar(localIndex,0), v=_getPar(localIndex,1), patch=_getPatch(localIndex);
520 bool flag=0;
521 patchSide ps;
522 if(u==0&&v==0)
523 ps=patchSide(patch,boundary::south);
524 else if(u==0)
525 ps=patchSide(patch,boundary::north);
526 else if(v==0)
527 ps=patchSide(patch,boundary::east);
528 else
529 {
530 ps=patchSide(patch,boundary::north);
531 flag=1;
532 }
533 if(_alreadyHandled(ps,flag))
534 return;
535 std::vector<indexType> vertices = _findVertexInPatches(ps,flag);
536 std::vector<indexType> locals;
537 std::vector<weightType> weights;
538 for(size_t i = 0;i<vertices.size();i++)
539 {
540 locals.push_back(vertices[i]);
541 weights.push_back(static_cast<weightType>(1));
542 }
543 _addToMap(locals,weights);
544 }
545
546 void _addCombinedLineToMap(patchSide & ps,index_t localStartIndex,index_t length,index_t distToPs) const
547 {
548 std::vector<patchSide> sides;
549 std::vector<index_t> lengths;
550 std::vector<index_t> dists;
551 sides.push_back(ps);
552 lengths.push_back(length);
553 dists.push_back(distToPs);
554 _addBlockToMap(localStartIndex,sides,lengths,dists);
555 }
556
557 void _addCombinedBlockToMap(patchSide & ps_u,patchSide & ps_v,index_t localStartIndex,index_t length_u,index_t length_v,index_t distToPs_u, index_t distToPs_v) const
558 {
559 std::vector<patchSide> sides;
560 std::vector<index_t> lengths;
561 std::vector<index_t> dists;
562 sides.push_back(ps_u);
563 sides.push_back(ps_v);
564 lengths.push_back(length_u);
565 lengths.push_back(length_v);
566 dists.push_back(distToPs_u);
567 dists.push_back(distToPs_v);
568 _addBlockToMap(localStartIndex,sides,lengths,dists);
569 }
570
571 void _addBlockToMap(index_t localStartIndex, std::vector<patchSide> const & sides, std::vector<index_t> const & lengths, std::vector<index_t> const & dists) const
572 {
573 patchSide ps,ps_neighbour;
574 bool par,par_neigh;
575 index_t dir,dir_neigh;
576 gsKnotVector<T> kv_neigh,kv_this;
577 std::vector<std::vector<T> > weights1D;
578 std::vector<bool> minus_dir;
579 std::vector<index_t> dirs;
580 std::vector<weightType> weight;
581 T w0,w1;
582 for(size_t i = 0; i<sides.size();++i)
583 {
584 ps=sides[i];
585 if(!m_topol->getNeighbour(ps,ps_neighbour))
586 GISMO_ERROR("no neighbour found on this side.");
587 par = ps.parameter();
588 dir = ps.direction();
589 minus_dir.push_back(!par);
590 dirs.push_back(dir);
591 kv_this=_getKnotVector(ps.patch,dir);
592 par_neigh = ps_neighbour.parameter();
593 dir_neigh = ps_neighbour.direction();
594 kv_neigh=_getKnotVector(ps_neighbour.patch,dir_neigh);
595 w0 = m_basis->getWeight(ps);
596 w1 = m_basis->getWeight(ps_neighbour);
597 weight.clear();
598 _getBoehmCoefs(kv_this,par,w0,kv_neigh,par_neigh,w1,lengths[i],dists[i],weight);
599 weights1D.push_back(weight);
600 }
601 std::vector<indexType> locals;
602 std::vector<weightType> weights;
603 std::vector<std::pair<index_t,index_t> >steps;
604 gsVector<index_t> distances(sides.size());
605 distances.setZero();
606 do
607 {
608 steps.clear();
609 weightType weight2 = 1.0;
610 for(size_t i=0;i<sides.size();++i)
611 {
612 steps.push_back(std::make_pair(minus_dir[i] ? -distances(i) : distances(i),dirs[i]));
613 weight2 *= weights1D[i][distances(i)];
614 }
615 index_t localIndexTravelled = _travelUVSteps(localStartIndex,steps);
616 locals.push_back(localIndexTravelled);
617 weights.push_back(weight2);
618 }while(_nextPoint(lengths,distances));
619 if(_alreadyHandled(locals,_getPatch(localStartIndex)))
620 return;
621 _addToMap(locals,weights);
622 }
623
624 bool _nextPoint(std::vector<index_t> const & lengths, gsVector<index_t> & point) const
625 {
626 for(size_t i = 0; i<lengths.size(); ++i)
627 {
628 if(++point(i)<=lengths[i])
629 {
630 return true;
631 }
632 else
633 point(i)=0;
634 }
635 return false;
636 }
637
638private:
640 // functions for travelling through the basis-function indizes of patches
642
643 index_t _transformToNeighbour(index_t localIndex,step_iter current,step_iter end) const
644 {
645 index_t patch = _getPatch(localIndex);
646 index_t u = _getPar(localIndex,0);
647 index_t v = _getPar(localIndex,1);
648 patchSide ps,ps_neighbour;
649 if(current->second==0)
650 ps = patchSide(patch,current->first>0 ? 2 : 1);
651 else
652 ps = patchSide(patch,current->first>0 ? 4 : 3);
654 if(!m_topol->getNeighbour(ps,ps_neighbour)||!m_topol->getInterface(ps,bf))
655 GISMO_ERROR("ps no interface");
656 GISMO_ASSERT((ps.side()==1&&u==0)||(ps.side()==2&&u==_getParMax(patch,0))||
657 (ps.side()==3&&v==0)||(ps.side()==4&&v==_getParMax(patch,1)),
658 "steps does not fit to point");
659 GISMO_ASSERT(current->first!=0,"stepsize is zero, which is not allowed in this position.");
660 bool orient = bf.dirOrientation(ps,1-ps.direction());
661 index_t non_fixed = current->second==1 ? u : v;
662 current->first>0 ? current->first-- : current->first++;
663 _transformStepsToNeighbour(current,end,ps,ps_neighbour,orient);
664 localIndex=_transformIndexToNeighbour(localIndex,ps_neighbour,orient,non_fixed);
665 return localIndex;
666 }
667
668 index_t _transformIndexToNeighbour(index_t localIndex,patchSide const & ps_neighbour,bool orient, index_t non_fixed) const
669 {
670 index_t patch = ps_neighbour.patch;
671 index_t u_max = _getParMax(patch,0);
672 index_t v_max = _getParMax(patch,1);
673 if((ps_neighbour.direction()))
674 localIndex = _getLocalIndex(patch,orient ? non_fixed : u_max-non_fixed,ps_neighbour.parameter() ? v_max : 0);
675 else
676 localIndex = _getLocalIndex(patch,(ps_neighbour.parameter()) ? u_max : 0,orient ? non_fixed : v_max-non_fixed);
677 return localIndex;
678 }
679 void _transformStepsToNeighbour(step_iter current,step_iter end,patchSide const & ps,patchSide const & ps_neighbour,bool orient) const
680 {
681 boxSide s1=ps.side(),s2=ps_neighbour.side();
682 if(s1==s2)
683 for(step_iter it = current;it!=end;++it)
684 {
685 if(it->second==s1.direction())
686 it->first *= -1;
687 else
688 if(!orient)
689 it->first *= -1;
690 }
691 else if((s1==1&&s2==3)||(s1==2&&s2==4)||(s1==3&&s2==1)||(s1==4&&s2==2))
692 for(step_iter it = current;it!=end;++it)
693 {
694 if(it->second==s1.direction())
695 it->first *= -1;
696 else
697 if(!orient)
698 it->first *= -1;
699 it->second=(1-it->second);
700 }
701 else if((s1==1&&s2==4)||(s1==2&&s2==3)||(s1==3&&s2==2)||(s1==4&&s2==1))
702 for(step_iter it = current;it!=end;++it)
703 {
704 if(!(it->second==s1.direction()))
705 if(!orient)
706 it->first *= -1;
707 it->second=(1-it->second);
708 }
709 }
710
711 index_t _travelInsidePatch(index_t localIndex,bool dir,step_iter current) const
712 {
713 index_t patch = _getPatch(localIndex);
714 index_t par = _getPar(localIndex,dir);
715 index_t par_max = _getParMax(patch,dir);
716 index_t fixed_par = _getPar(localIndex,!dir);
717 if(0<=par+current->first&&par+current->first<=par_max)
718 {
719 par+=current->first;
720 current->first=0;
721 }
722 else if(current->first>0)
723 {
724 current->first-=par_max-par;
725 par=par_max;
726 }
727 else
728 {
729 current->first+=par;
730 par=0;
731 }
732 localIndex = _getLocalIndex(patch,dir ? fixed_par : par,dir ? par : fixed_par);
733 return localIndex;
734 }
735
736 index_t _travelUVSteps(index_t localIndex,std::vector<std::pair<index_t, index_t> > steps) const
737 {
738 step_iter current = steps.begin();
739 step_iter end = steps.end();
740 while(current!=end)
741 {
742 GISMO_ASSERT(current->second==0||current->second==1,"only 0 and 1 direction possible");
743 localIndex=_travelInsidePatch(localIndex, current->second != 0, current);
744 if(current->first==0)
745 ++current;
746 else
747 localIndex=_transformToNeighbour(localIndex,current,end);
748 }
749 return localIndex;
750 }
751
752protected:
754 // functions for working with Indexes
756
757 //localIndex: this is the index going over all local basis functions of all patches
758 virtual bool _getLocalIndex_into(index_t const patch,index_t const u,index_t const v,index_t & localIndex) const=0;
759
760 index_t _getLocalIndex(index_t const patch,index_t const patchIndex) const
761 {
762 return _getFirstLocalIndex(patch)+patchIndex;
763 }
764
765 index_t _getLocalIndex(patchCorner const & pc) const
766 {
767 gsVector<bool> param = pc.parameters(d);
768 patchSide ps = param(1) ? patchSide(pc.patch,boxSide(4)) : patchSide(pc.patch,boxSide(3));
769 return _getLocalIndex(ps,param(0));
770 }
771
772 index_t _getLocalIndex(patchSide const & ps,bool const flag) const
773 {
774 return _getLocalIndex(ps.patch,ps.side(),flag);
775 }
776
777 index_t _getLocalIndex(index_t const patch,boxSide const side,bool const flag) const
778 {
779 return _getLocalIndex(patch,_getPatchIndex(patch,side,flag));
780 }
781
782 virtual index_t _getLocalIndex(index_t const patch,index_t u,index_t v) const = 0;
783
784 index_t _getFirstLocalIndex(index_t const patch) const
785 {
786 index_t index=0;
787 for(index_t i=0;i<patch;i++)
788 {
789 index+=m_basis->localSize(i);
790 }
791 return index;
792 }
793
794 index_t _getLastLocalIndex(index_t const patch) const
795 {
796 return _getFirstLocalIndex(patch)+m_basis->localSize(patch)-1;
797 }
798
799 //patchIndex: this is the index going over all local basis functions of one patch
800 virtual index_t _getPatchIndex(index_t const patch,boxSide const side,bool const flag) const = 0;
801
802 index_t _getPatchIndex(index_t localIndex) const
803 {
804 index_t patchIndex=localIndex;
805 for(index_t i = 0;i<_getPatch(localIndex);i++)
806 {
807 patchIndex-=m_basis->localSize(i);
808 }
809 return patchIndex;
810 }
811
812 index_t _getPatch(index_t localIndex) const
813 {
814 size_t patch;
815 for (patch = 0; patch < m_basis->nPatches(); patch++)
816 {
817 if (localIndex >= m_basis->localSize(patch))
818 localIndex -= m_basis->localSize(patch);
819 else
820 break;
821 }
822 return patch;
823 }
824
825 virtual index_t _getPar(index_t localIndex,bool par) const = 0;
826
827protected:
828
829 short_t const m_incrSmoothnessDegree;
830 gsBoxTopology const *m_topol;
831 gsMPBESBasis<d,T> const *m_basis;
832 mutable gsWeightMapper<T> *m_mapper;
833 mutable index_t m_global;
834};// class gsMPBESMapTensor
835
836}
Struct which represents a certain side of a box.
Definition gsBoundary.h:85
bool parameter() const
Returns the parameter value (false=0=start, true=1=end) that corresponds to this side.
Definition gsBoundary.h:128
short_t direction() const
Returns the parametric direction orthogonal to this side.
Definition gsBoundary.h:113
A basis represents a family of scalar basis functions defined over a common parameter domain.
Definition gsBasis.h:79
virtual short_t degree(short_t i) const
Degree with respect to the i-th variable. If the basis is a tensor product of (piecewise) polynomial ...
Definition gsBasis.hpp:699
Defines a topological arrangement of a collection of "boxes" (e.g., parameter domains that map to phy...
Definition gsBoxTopology.h:39
bool getCornerList(const patchCorner &start, std::vector< patchCorner > &cornerList) const
Definition gsBoxTopology.cpp:187
bool getNeighbour(const patchSide &ps, patchSide &result, int &ii) const
Definition gsBoxTopology.cpp:137
bool isInterface(const patchSide &ps) const
Is the given patch side ps set to an interface?
Definition gsBoxTopology.cpp:103
bool getInterface(const patchSide &ps, boundaryInterface &result) const
Definition gsBoxTopology.h:290
Class for representing a knot vector.
Definition gsKnotVector.h:80
size_t size() const
Number of knots (including repetitions).
Definition gsKnotVector.h:242
iterator begin() const
Returns iterator pointing to the beginning of the repeated knots.
Definition gsKnotVector.hpp:117
void reverse()
Better directly use affineTransformTo.
Definition gsKnotVector.hpp:468
void append(iterType begin, iterType end)
Adds the knots between begin and end to the knot vector.
Definition gsKnotVector.h:802
T first() const
Get the first knot.
Definition gsKnotVector.h:721
void remove(uiterator uit, mult_t mult=1)
Definition gsKnotVector.hpp:347
const knotContainer & get() const
Get a reference to the underlying std::vector of knots.
Definition gsKnotVector.h:810
int degree() const
Returns the degree of the knot vector.
Definition gsKnotVector.hpp:700
T last() const
Get the last knot.
Definition gsKnotVector.h:728
void addConstant(T amount)
Adds amount to all the knots.
Definition gsKnotVector.hpp:839
iterator end() const
Returns iterator pointing past the end of the repeated knots.
Definition gsKnotVector.hpp:124
Purely abstract class gsMappedBasis, which gives means of combining basis functions to new,...
Definition gsMPBESBasis.h:47
A univariate Lagrange basis.
Definition gsMPBESMapTensor.h:33
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 vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
Boehm's algorithm for knot insertion.
Provides declaration of the BoxTopology class.
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
#define GISMO_ERROR(message)
Definition gsDebug.h:118
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
The G+Smo namespace, containing all definitions for the library.
S give(S &x)
Definition gsMemory.h:266
Struct which represents an interface between two patches.
Definition gsBoundary.h:650
Struct which represents a certain corner of a hyper-cube.
Definition gsBoundary.h:292
Struct which represents a certain corner of a patch.
Definition gsBoundary.h:393
Struct which represents a certain side of a patch.
Definition gsBoundary.h:232
index_t patch
The index of the patch.
Definition gsBoundary.h:234