G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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>
19 #include <gsCore/gsBoxTopology.h>
20 
21 namespace gismo
22 {
31 template<short_t d,class T>
33 {
34 private:
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 
48 public:
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 
77 protected:
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 
96 protected:
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 // }
385 private:
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 
432 protected:
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 
437 private:
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 
495 private:
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 
638 private:
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 
752 protected:
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 
827 protected:
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 patch.
Definition: gsBoundary.h:231
Provides declaration of the BoxTopology class.
#define short_t
Definition: gsConfig.h:35
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:650
bool parameter() const
Returns the parameter value (false=0=start, true=1=end) that corresponds to this side.
Definition: gsBoundary.h:128
Boehm&#39;s algorithm for knot insertion.
bool getCornerList(const patchCorner &start, std::vector< patchCorner > &cornerList) const
Definition: gsBoxTopology.cpp:187
A univariate Lagrange basis.
Definition: gsMPBESMapTensor.h:32
S give(S &x)
Definition: gsMemory.h:266
#define index_t
Definition: gsConfig.h:32
Struct which represents a certain corner of a patch.
Definition: gsBoundary.h:392
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
Sparse matrix class, based on gsEigen::SparseMatrix.
Definition: gsSparseMatrix.h:140
bool getInterface(const patchSide &ps, boundaryInterface &result) const
Definition: gsBoxTopology.h:290
const knotContainer & get() const
Get a reference to the underlying std::vector of knots.
Definition: gsKnotVector.h:810
bool getNeighbour(const patchSide &ps, patchSide &result, int &ii) const
Definition: gsBoxTopology.cpp:137
Purely abstract class gsMappedBasis, which gives means of combining basis functions to new...
Definition: gsMPBESBasis.h:46
Struct which represents a certain side of a box.
Definition: gsBoundary.h:84
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
Class for representing a knot vector.
Definition: gsKnotVector.h:79
Struct which represents an interface between two patches.
Definition: gsBoundary.h:649
Defines a topological arrangement of a collection of &quot;boxes&quot; (e.g., parameter domains that map to phy...
Definition: gsBoxTopology.h:38
int degree() const
Returns the degree of the knot vector.
Definition: gsKnotVector.hpp:700
index_t patch
The index of the patch.
Definition: gsBoundary.h:234
Struct which represents a certain corner of a hyper-cube.
Definition: gsBoundary.h:291
short_t direction() const
Returns the parametric direction orthogonal to this side.
Definition: gsBoundary.h:113
bool isInterface(const patchSide &ps) const
Is the given patch side ps set to an interface?
Definition: gsBoxTopology.cpp:103
A basis represents a family of scalar basis functions defined over a common parameter domain...
Definition: gsBasis.h:78