25 template<
short_t d,
class T>
30 _computeSmoothMatrix();
31 GISMO_ASSERT(this->_checkMatrix(m_matrix),
"Mapper does not have column sum equal to 1");
34 GISMO_ASSERT(this->_checkMatrix(m_matrix),
"Mapper does not have column sum equal to 1");
38 template<
short_t d,
class T>
41 m_options.addSwitch(
"SharpCorners",
"Reproduce sharp corners",
true);
42 m_options.addReal(
"SharpCornerTolerance",
"Sharp corner tolerance",1e-2);
43 m_options.addSwitch(
"Verbose",
"Verbose output",
false);
46 template<
short_t d,
class T>
49 std::fill(m_vertCheck.begin(), m_vertCheck.end(),
false);
50 std::vector<bool> result(m_vertCheck.size());
52 if (m_patches.empty())
54 gsWarn<<
"Sharp corners should be detected, but no multi-patch object is assigned to this class\n";
58 std::fill(result.begin(), result.end(),
false);
61 for (
size_t p=0; p<m_Bbases.nBases(); p++)
65 cidx = _vertIndex(p,c);
66 if (m_vertCheck.at(cidx))
71 std::vector<patchCorner> pcorners;
72 m_topology.getCornerList(pcorner,pcorners);
73 std::vector<std::pair<patchCorner,patchSide>> boundaries;
74 for (std::vector<patchCorner>::iterator it=pcorners.begin(); it!=pcorners.end(); it++)
76 std::vector<patchSide> psides;
77 it->getContainingSides(d,psides);
78 for (
size_t s=0; s!=psides.size(); s++)
81 if (!m_topology.isInterface(psides[s]))
83 boundaries.push_back(std::make_pair(*it,psides[s]));
89 m_vertCheck[ _vertIndex(it->patch, it->corner()) ] =
true;
92 if (boundaries.size()==0)
94 else if (boundaries.size()==2)
96 std::vector<gsVector<T>> normals;
97 for (std::vector<std::pair<patchCorner,patchSide>>::iterator it=boundaries.begin(); it!=boundaries.end(); it++)
104 it->first.parameters_into(m_Bbases.domainDim(),pars);
105 gsMatrix<T> supp = m_Bbases.basis(it->first.patch).support();
107 for (
index_t r = 0; r!=supp.rows(); r++)
108 vec(r) = supp(r,pars(r));
111 md.side = it->second;
112 m_patches.patch(it->first.patch).computeMap(md);
114 normals.push_back(md.outNormal(0).normalized());
117 if ( (
std::abs(normals[0].transpose() * normals[1] - 1)) > tol )
118 for (std::vector<patchCorner>::iterator it=pcorners.begin(); it!=pcorners.end(); it++)
119 result[ _vertIndex(it->patch, it->corner()) ] =
true;
122 GISMO_ERROR(
"Size of the stored boundary corners and sides must be 0 or 2, but is "<<boundaries.size());
133 template<
short_t d,
class T>
136 for (
size_t p=0; p!=m_bases.nBases(); p++)
138 gsInfo<<
"----------------------------------\n";
139 gsInfo<<
"patch "<<p<<
"\n";
140 index_t size = m_mapModified.patchSize(p);
141 for (
index_t k=0; k!=size; k++)
143 bool free = m_mapModified.is_free(k,p);
144 std::string str = free ?
"free" :
"eliminated";
145 gsInfo<<
"DoF "<<k<<
" is "<<str<<
"\n";
150 template<
short_t d,
class T>
153 std::pair<index_t,bool> data = this->_vertexData(corner);
154 gsInfo<<
"Patch "<<corner.patch<<
", corner "<<corner<<
" has valence "<<data.first<<
" and is "<<(data.second ?
"an interior vertex" :
"a boundary vertex")<<
"\n";
158 template<
short_t d,
class T>
161 gsInfo<<
"Patch "<<side.
patch<<
", side "<<side<<
" is "<<(m_topology.isBoundary(side) ?
"a boundary side" :
"an interface")<<
"\n";
164 template<
short_t d,
class T>
167 gsInfo<<
"**D-Patch Side info**\n";
168 for(
size_t i = 0;i<m_bases.nBases();++i)
173 template<
short_t d,
class T>
176 gsInfo<<
"**D-Patch Corner info**\n";
177 for(
size_t i = 0;i<m_bases.nBases();++i)
185 template<
short_t d,
class T>
188 GISMO_ASSERT(m_computed,
"The method has not been computed! Call compute().");
193 if (computeCoefs || m_coefs.rows()==0)
195 m_coefs = this->_preCoefficients();
196 m_coefs = m_matrix.transpose() * m_coefs;
201 for (
index_t p=0; p!=patch; p++)
202 offset += m_mapOriginal.patchSize(p);
204 size = m_mapOriginal.patchSize(patch);
205 gsMatrix<T> local = m_coefs.block(offset,0,size,m_coefs.cols());
206 return m_bases[patch].makeGeometry(
give(local) ).release();
226 template<
short_t d,
class T>
245 index = indices1(index1);
247 index = indices1(n-1-index1);
248 else if (side1.side()==2)
250 index = indices1(index1);
252 index = indices1(n-1-index1);
253 else if (side1.side()==3)
255 index = indices1(index1);
257 index = indices1(n-1-index1);
258 else if (side1.side()==4)
260 index = indices1(index1);
262 index = indices1(n-1-index1);
264 GISMO_ERROR(
"Side unknown. index = "<<side1.side());
268 template<
short_t d,
class T>
271 return _indexFromVert(&m_bases.basis(corner.patch),index, corner, side, offset);
274 template<
short_t d,
class T>
277 return _indexFromVert(&bases.
basis(corner.patch),index, corner, side, offset);
280 template<
short_t d,
class T>
283 const gsTensorBSplineBasis<d,T> * tbbasis;
284 const gsTensorNurbsBasis<d,T> * tnbasis;
285 const gsHTensorBasis<d,T> * thbasis;
287 if ((index==0) && (offset==0))
290 index_t idx = basis->functionAtCorner(corner.corner());
295 if ((tbbasis =
dynamic_cast<const gsTensorBSplineBasis<d,T> *
>(basis)))
296 return _indexFromVert_impl(tbbasis,index,corner,side,offset);
297 else if ((tnbasis =
dynamic_cast<const gsTensorNurbsBasis<d,T> *
>(basis)))
298 return _indexFromVert_impl(&tnbasis->source(),index,corner,side,offset);
299 else if ((thbasis =
dynamic_cast<const gsHTensorBasis<d,T> *
>(basis)))
300 return _indexFromVert_impl(thbasis,index,corner,side,offset);
306 template<
short_t d,
class T>
308 typename util::enable_if<util::is_same<U, const gsTensorBSplineBasis<d,T> *>::value,
310 gsDPatchBase<d,T>::_indexFromVert_impl(U basis,
const index_t index,
const patchCorner corner,
const patchSide side,
const index_t offset)
const
319 gsVector<index_t,2> sizes;
320 basis->size_cwise(sizes);
323 GISMO_ASSERT(offset<sizes[0],
"Offset is out of bounds");
325 if (corner.corner()==1)
326 result = basis->index(offset,index);
327 else if (corner.corner()==3)
328 result = basis->index(offset,sizes[1]-1-index);
330 GISMO_ERROR(corner.corner() <<
" is not adjacent to side "<<side.side()<<
"!");
332 else if (side.side()==2)
334 GISMO_ASSERT(offset<sizes[0],
"Offset is out of bounds");
336 if (corner.corner()==2)
337 result = basis->index(sizes[0]-1-offset,index);
338 else if (corner.corner()==4)
339 result = basis->index(sizes[0]-1-offset,sizes[1]-1-index);
341 GISMO_ERROR(corner.corner() <<
" is not adjacent to side "<<side.side()<<
"!");
343 else if (side.side()==3)
345 GISMO_ASSERT(offset<sizes[1],
"Offset is out of bounds");
347 if (corner.corner()==1)
348 result = basis->index(index,offset);
349 else if (corner.corner()==2)
350 result = basis->index(sizes[0]-1-index,offset);
352 GISMO_ERROR(corner.corner() <<
" is not adjacent to side "<<side.side()<<
"!");
354 else if (side.side()==4)
356 GISMO_ASSERT(offset<sizes[1],
"Offset is out of bounds");
358 if (corner.corner()==3)
359 result = basis->index(index,sizes[1]-1-offset);
360 else if (corner.corner()==4)
361 result = basis->index(sizes[0]-1-index,sizes[1]-1-offset);
363 GISMO_ERROR(corner.corner() <<
" is not adjacent to side "<<side.side()<<
"!");
370 template<
short_t d,
class T>
372 typename util::enable_if<util::is_same<U, const gsHTensorBasis<d,T> *>::value,
374 gsDPatchBase<d,T>::_indexFromVert_impl(U basis,
const index_t index,
const patchCorner corner,
const patchSide side,
const index_t offset)
const
382 index_t level = basis->levelAtCorner(corner.corner());
383 gsTensorBSplineBasis<d,T> tbasis;
384 tbasis = basis->tensorLevel(level);
385 result = _indexFromVert(&tbasis,index,corner,side,offset);
386 result = basis->flatTensorIndexToHierachicalIndex(result,level);
387 if (result!=-1)
return result;
389 GISMO_ASSERT(basis->maxLevel()!=0,
"Basis must have more than one level!");
390 GISMO_ASSERT(level!=0,
"The level in the corner should not be 0!");
397 result = _indexFromVert(&tbasis,nActive_f++,corner,side,offset);
398 result = basis->flatTensorIndexToHierachicalIndex(result,level);
407 tbasis = basis->tensorLevel(level);
410 result = _indexFromVert(&tbasis,nInactive_c++,corner,side,offset);
411 result = basis->flatTensorIndexToHierachicalIndex(result,level);
417 index_t tmpIdx = index - nActive_f + nInactive_c;
418 result = _indexFromVert(&tbasis,tmpIdx,corner,side,offset);
419 result = basis->flatTensorIndexToHierachicalIndex(result,level);
424 template<
short_t d,
class T>
427 std::vector<patchCorner> corners;
428 std::pair<index_t,bool> output;
429 output.second = m_topology.getCornerList(corner,corners);
430 output.first = corners.size();
434 template<
short_t d,
class T>
442 std::sort(pcorners.begin(), pcorners.end(),customLess);
447 template<
short_t d,
class T>
450 index_t size = pcorners.size();
451 GISMO_ASSERT(n<=size,
"You cannot remove more corners than there are actually stored in the container. Container size = "<<size<<
" no. corners to be removed = "<<n);
457 std::sort(pcorners.begin(), pcorners.end(),customGreater);
459 pcorners.resize(size-n);
462 template<
short_t d,
class T>
467 bool operator()(std::pair<index_t,index_t> a, std::pair<index_t,index_t> b)
const
472 ((a.first == b.first) &&
473 (a.second < b.second) );
478 std::sort(indices.begin(), indices.end(),customLess);
483 template<
short_t d,
class T>
487 GISMO_ASSERT(n<=size,
"You cannot remove more corners than there are actually stored in the container. Container size = "<<size<<
" no. corners to be removed = "<<n);
490 bool operator()(std::pair<index_t,index_t> a, std::pair<index_t,index_t> b)
const
495 ((a.first == b.first) &&
496 (a.second > b.second) );
501 std::sort(indices.begin(), indices.end(),customGreater);
503 indices.resize(size-n);
507 template<
short_t d,
class T>
510 std::vector<std::pair<index_t,index_t>> result;
511 std::vector<patchSide> csides(d);
515 patch = pcorner.patch;
521 index = basis->functionAtCorner(pcorner);
522 result.push_back(std::make_pair(patch,index));
528 if ( m_topology.isBoundary(csides[i]) )
continue;
529 index = _indexFromVert(mbasis,depth,pcorner,csides[i],0);
530 result.push_back(std::make_pair(patch,index));
537 template<
short_t d,
class T>
538 std::vector<std::pair<index_t,index_t>> gsDPatchBase<d,T>::_getAllInterfaceIndices(patchCorner pcorner,
index_t depth,
const gsMultiBasis<T> & mbasis)
const
540 std::vector<std::pair<index_t,index_t>> result, tmp;
541 std::vector<patchCorner> pcorners;
543 m_topology.getCornerList(pcorner,pcorners);
544 for (std::vector<patchCorner>::const_iterator it=pcorners.begin(); it!=pcorners.end(); it++)
546 tmp = this->_getInterfaceIndices(*it,depth,mbasis);
547 result.insert(result.end(), tmp.begin(), tmp.end());
552 template<
short_t d,
class T>
553 bool gsDPatchBase<d,T>::_checkMatrix(
const gsSparseMatrix<T> & matrix)
const
555 GISMO_ASSERT(matrix.cols()==matrix.outerSize(),
"is the matrix ColMajor?");
556 gsVector<T> colSums(matrix.cols());
558 for (
index_t i = 0; i<matrix.outerSize(); ++i)
559 for (
typename gsSparseMatrix<T>::iterator it = matrix.begin(i); it; ++it)
560 colSums.at(i) += it.value();
563 colSums.array() -= 1;
564 return (colSums.array() < 1e-8).all() && (colSums.array() > -1e-8).all();
791 template<
short_t d,
class T>
796 m_C0s.resize(m_nVerts);
797 if (m_options.getSwitch(
"SharpCorners"))
798 m_C0s = getSharpCorners(m_options.getReal(
"SharpCornerTolerance"));
800 std::fill(m_C0s.begin(), m_C0s.end(),
false);
809 template<
short_t d,
class T>
812 m_topology.checkConsistency();
813 m_nSides = 2*m_topology.nInterfaces() + m_topology.nBoundary();
814 m_nVerts = 4*m_Bbases.nBases();
816 m_sideCheck.resize(m_nSides);
817 std::fill(m_sideCheck.begin(), m_sideCheck.end(),
false);
818 m_vertCheck.resize(m_nVerts);
819 std::fill(m_vertCheck.begin(), m_vertCheck.end(),
false);
822 template<
short_t d,
class T>
826 for (
size_t k=0; k!=m_Bbases.nBases(); ++k)
831 m_bases.addBasis(m_Bbases.basis(k).clone());
833 gsWarn<<
"No THB basis was constructed";
835 m_bases.setTopology(m_topology);
838 template<
short_t d,
class T>
843 template<
short_t d,
class T>
850 template<
short_t d,
class T>
853 m_matrix.resize(m_size,m_bases.totalSize());
856 template<
short_t d,
class T>
859 for (
size_t p=0; p!=m_bases.nBases(); p++)
861 gsInfo<<
"----------------------------------\n";
862 gsInfo<<
"patch "<<p<<
"\n";
863 for (
size_t b=0; b!=m_mapOriginal.patchSize(p); b++)
865 index_t idx = m_mapModified.index(b,p);
866 if (m_mapModified.is_free_index(idx))
867 gsInfo<<
"basis function "<<b<<
" (check="<<m_basisCheck[idx]<<
") on patch "<<p<<
" is "<<(m_basisCheck[idx] ?
"":
"not ")<<
"handled\n";
869 gsInfo<<
"basis function "<<b<<
" on patch "<<p<<
" is "<<
"eliminated\n";
874 template<
short_t d,
class T>
877 bool checkSides = std::all_of(m_sideCheck.begin(), m_sideCheck.end(), [](
bool m_sideCheck) {
return m_sideCheck; });
879 bool checkVerts = std::all_of(m_vertCheck.begin(), m_vertCheck.end(), [](
bool m_vertCheck) {
return m_vertCheck; });
880 GISMO_ENSURE(checkVerts,
"Not all vertices are checked");
885 bool checkBasis = std::all_of(m_basisCheck.begin(), m_basisCheck.end(), [](
bool m_basisCheck) {
return m_basisCheck; });
886 GISMO_ENSURE(checkBasis,
"Not all basis functions are checked");
889 template<
short_t d,
class T>
892 m_sideCheck.resize(m_nSides);
893 std::fill(m_sideCheck.begin(), m_sideCheck.end(),
false);
894 m_vertCheck.resize(m_nVerts);
895 std::fill(m_vertCheck.begin(), m_vertCheck.end(),
false);
900 m_basisCheck.resize(m_size);
901 std::fill(m_basisCheck.begin(), m_basisCheck.end(),
false);
905 template<
short_t d,
class T>
908 std::vector<patchSide> psides;
909 std::vector<patchCorner> corners;
910 sparseEntry_t entries;
920 index_t b11_p1 = _indexFromVert(1,pcorner,psides[0],1);
921 rowIdx = m_mapModified.index(b11_p1,pcorner.patch);
922 colIdx = m_mapOriginal.index(b11_p1,pcorner.patch);
925 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
927 m_topology.getCornerList(pcorner,corners);
932 for (std::vector<patchCorner>::iterator corn = corners.begin(); corn != corners.end(); ++corn)
934 tmpBasis = &m_bases.
basis(corn->patch);
935 index = tmpBasis->functionAtCorner(corn->corner());
936 colIdx = m_mapOriginal.index(index,corn->patch);
938 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
944 for (std::vector<patchSide>::iterator side = psides.begin(); side != psides.end(); ++side)
946 GISMO_ENSURE(m_topology.getInterface(*side,iface),
"Side must be an interface!");
947 m_topology.getNeighbour(*side,otherSide);
948 patchCorner otherCorner = iface.mapCorner(pcorner);
950 index_t b10_p1 = _indexFromVert(1,pcorner,*side,0);
951 index_t b10_p2 = _indexFromVert(1,otherCorner,otherSide,0);
954 colIdx = m_mapOriginal.index(b10_p1,side->patch);
955 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
956 colIdx = m_mapOriginal.index(b10_p2,otherSide.
patch);
957 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
961 #pragma omp critical (handle_interior_vertex)
963 _pushAndCheck(entries);
964 m_vertCheck[ _vertIndex(pcorner.patch, pcorner.corner()) ] =
true;
969 template<
short_t d,
class T>
973 if (m_vertCheck[ _vertIndex(pcorner.patch, pcorner.corner()) ])
979 std::pair<index_t,bool> vdata = _vertexData(pcorner);
981 bool C0 = m_C0s[_vertIndex(pcorner.patch,pcorner.corner())];
985 _handleRegularCorner(pcorner);
986 else if (vdata.first==2 && !C0)
987 _handleRegularBoundaryVertexSmooth(pcorner,vdata.first);
988 else if (vdata.first==2 && C0)
989 _handleRegularBoundaryVertexNonSmooth(pcorner,vdata.first);
990 else if (vdata.first> 2 && !C0)
991 _handleIrregularBoundaryVertexSmooth(pcorner,vdata.first);
992 else if (vdata.first> 2 && C0)
993 _handleIrregularBoundaryVertexNonSmooth(pcorner,vdata.first);
998 _handleInteriorVertex(pcorner,vdata.first);
1001 template<
short_t d,
class T>
1010 std::vector<patchCorner> pcorners;
1012 std::vector<std::vector<index_t>> selectedIndices(2);
1013 std::vector<std::vector<index_t>> selectedOIndices(2);
1015 std::vector<gsBasis<T> *> basis(2);
1016 std::vector<gsMatrix<index_t>> indices(2);
1017 std::vector<gsMatrix<index_t>> oindices(2);
1019 sparseEntry_t entries;
1023 basis[p] = &m_bases.basis(iface[p].patch);
1026 basis[0]->matchWith(iface,*basis[1],indices[0],indices[1],0);
1027 basis[0]->matchWith(iface,*basis[1],oindices[0],oindices[1],1);
1034 iface[p].getContainedCorners(d,pcorners);
1037 selectedIndices[p].push_back(_indexFromVert(0,pcorners[c],iface[p],0));
1038 selectedIndices[p].push_back(_indexFromVert(1,pcorners[c],iface[p],0));
1040 selectedOIndices[p].push_back(_indexFromVert(0,pcorners[c],iface[p],1));
1041 selectedOIndices[p].push_back(_indexFromVert(1,pcorners[c],iface[p],1));
1043 std::vector<index_t> allIndices(indices[p].data(), indices[p].data() + indices[p].rows() * indices[p].cols());
1044 std::vector<index_t> result;
1045 std::copy_if(allIndices.begin(), allIndices.end(), std::back_inserter(result),
1046 [&selectedIndices,&p] (
index_t entry)
1048 std::vector<index_t>::const_iterator res = std::find(selectedIndices[p].begin(), selectedIndices[p].end(), entry);
1049 return (res == selectedIndices[p].end());
1053 std::vector<index_t> allOIndices(oindices[p].data(), oindices[p].data() + oindices[p].rows() * oindices[p].cols());
1055 std::copy_if(allOIndices.begin(), allOIndices.end(), std::back_inserter(result),
1056 [&selectedOIndices,&p] (
index_t entry)
1058 std::vector<index_t>::const_iterator res = std::find(selectedOIndices[p].begin(), selectedOIndices[p].end(), entry);
1059 return (res == selectedOIndices[p].end());
1064 GISMO_ASSERT(indices[0].size()==indices[1].size(),
"Indices do not have the right size, indices[0].size()="<<indices[0].size()<<
",indices[1].size()="<<indices[1].size());
1065 GISMO_ASSERT(oindices[0].size()==oindices[1].size(),
"Offset indices do not have the right size, oindices[0].size()="<<oindices[0].size()<<
",oindices[1].size()="<<oindices[1].size());
1070 for (
index_t p =0; p!= 2; p++)
1073 for (
index_t k=0; k!= indices[p].size(); k++ )
1075 GISMO_ASSERT(m_mapModified.is_free(oindices[p].at(k),iface[p].patch),
"Index "<<oindices[p].at(k)<<
" on patch "<<iface[p].patch<<
" is eliminated. Something went wrong?");
1076 rowIdx = m_mapModified.index(oindices[p].at(k),iface[p].patch);
1078 GISMO_ASSERT(m_mapOriginal.is_free(oindices[p].at(k),iface[p].patch),
"Index is eliminated. Something went wrong?");
1079 colIdx = m_mapOriginal.index(oindices[p].at(k),iface[p].patch);
1082 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1084 GISMO_ASSERT(m_mapOriginal.is_free(indices[p].at(k),iface[p].patch),
"Index is eliminated. Something went wrong?");
1085 colIdx = m_mapOriginal.index(indices[p].at(k),iface[p].patch);
1088 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1090 GISMO_ASSERT(m_mapOriginal.is_free(indices[np].at(k),iface[np].patch),
"Index is eliminated. Something went wrong?");
1091 colIdx = m_mapOriginal.index(indices[np].at(k),iface[np].patch);
1094 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1101 #pragma omp critical (handle_interface)
1103 _pushAndCheck(entries);
1105 for (
index_t p =0; p!= 2; p++)
1106 m_sideCheck[ _sideIndex(iface[p].patch, iface[p].side()) ] =
true;
1111 template<
short_t d,
class T>
1114 std::vector<patchCorner> pcorners;
1115 std::vector<index_t> selectedIndices;
1117 sparseEntry_t entries;
1123 selectedIndices.push_back(_indexFromVert(0,pcorners[c],side,0));
1124 selectedIndices.push_back(_indexFromVert(1,pcorners[c],side,0));
1127 std::sort(selectedIndices.begin(),selectedIndices.end());
1128 std::vector<index_t> allIndices(indices.data(), indices.data() + indices.rows() * indices.cols());
1129 std::vector<index_t> result(allIndices.size());
1130 std::vector<index_t>::iterator it=std::set_difference (allIndices.begin(), allIndices.end(), selectedIndices.begin(), selectedIndices.end(), result.begin());
1131 result.resize(it-result.begin());
1135 for (std::vector<index_t>::iterator it = result.begin(); it!=result.end(); ++it)
1137 rowIdx = m_mapModified.index(*it,side.
patch);
1138 colIdx = m_mapOriginal.index(*it,side.
patch);
1140 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1146 #pragma omp critical (handle_boundary)
1148 _pushAndCheck(entries);
1150 m_sideCheck.at( _sideIndex(side.
patch,side.side()) ) =
true;
1154 template<
short_t d,
class T>
1157 #pragma omp critical (handle_interior)
1160 for(
size_t p=0; p!=m_bases.nBases(); p++)
1161 for (
index_t b=0; b!=m_bases.basis(p).size(); b++)
1163 rowIdx = m_mapModified.index(b,p);
1165 if ( (!m_mapModified.is_free(b,p)) || (m_basisCheck[rowIdx]) )
1168 colIdx = m_mapOriginal.index(b,p);
1169 m_matrix(rowIdx,colIdx) = 1;
1170 m_basisCheck[rowIdx] =
true;
1176 template<
short_t d,
class T>
1179 GISMO_ASSERT((
size_t)m_mapModified.freeSize()==m_size,
"Size does not match predicted size, m_mapModified.freeSize()="<<m_mapModified.freeSize()<<
"; m_size="<<m_size);
1187 for (
size_t p=0; p<m_bases.nBases(); p++)
1192 for(gsBoxTopology::const_iiterator iit = m_topology.iBegin(); iit< m_topology.iEnd(); iit++)
1193 _handleInterface(*iit);
1197 for(gsBoxTopology::const_biterator bit = m_topology.bBegin(); bit< m_topology.bEnd(); bit++)
1198 _handleBoundary(*bit);
1202 if (m_options.getSwitch(
"Verbose")) { _whichHandled(); }
1204 _performChecks(
true);
1205 m_matrix.makeCompressed();
1208 template<
short_t d,
class T>
1212 _resetChecks(
false);
1220 for(gsBoxTopology::const_iiterator iit = m_topology.iBegin(); iit!= m_topology.iEnd(); iit++)
1221 _computeInterfaceMapper(*iit);
1227 for(gsBoxTopology::const_biterator bit = m_topology.bBegin(); bit!= m_topology.bEnd(); bit++)
1228 _computeBoundaryMapper(*bit);
1239 for (
size_t p=0; p!=m_bases.nBases(); p++)
1245 _computeVertexMapper(pcorner);
1248 m_mapModified.finalize();
1249 m_mapOriginal.finalize();
1251 GISMO_ASSERT((
size_t)m_mapModified.freeSize()==m_size,
"Size does not match predicted size, m_mapModified.freeSize()="<<m_mapModified.freeSize()<<
"; m_size="<<m_size);
1252 m_matrix.resize( m_size, m_mapOriginal.freeSize() );
1260 template<
short_t d,
class T>
1264 if (m_sideCheck.at(sidx))
1268 std::pair<index_t,bool> vdata1, vdata2;
1269 std::vector<index_t> patches(2);
1270 std::vector<patchSide> psides(2);
1272 std::vector<patchCorner> pcorners;
1279 for (
index_t p = 0; p != 2; p++)
1281 sidx = _sideIndex( patches[p] ,psides[p] );
1282 if (m_sideCheck.at(sidx))
1302 basis = &m_bases.
basis(patches[p]);
1306 vdata1 = this->_vertexData(pcorners[0]);
1307 vdata2 = this->_vertexData(pcorners[1]);
1310 std::vector<index_t> allIndices(indices.data(), indices.data() + indices.rows() * indices.cols());
1314 std::vector<index_t> selectedIndices;
1318 selectedIndices.push_back(_indexFromVert(0,pcorners[c],psides[p],0));
1319 selectedIndices.push_back(_indexFromVert(1,pcorners[c],psides[p],0));
1322 std::sort(selectedIndices.begin(),selectedIndices.end());
1326 std::vector<index_t> result(allIndices.size());
1327 std::vector<index_t>::iterator it=std::set_difference (allIndices.begin(), allIndices.end(), selectedIndices.begin(), selectedIndices.end(), result.begin());
1328 result.resize(it-result.begin());
1330 gsAsMatrix<index_t> indices(result,result.size(),1);
1332 #pragma omp critical (side_interface)
1334 m_mapModified.markBoundary(patches[p], indices);
1335 m_sideCheck.
at(sidx) =
true;
1340 template<
short_t d,
class T>
1341 void gsDPatchBase<d,T>::_computeBoundaryMapper(patchSide boundary)
1343 index_t sidx = _sideIndex(boundary.patch,boundary.side());
1344 m_sideCheck.at(sidx) =
true;
1347 template<
short_t d,
class T>
1348 void gsDPatchBase<d,T>::_computeVertexMapper(patchCorner pcorner)
1350 index_t cidx = _vertIndex(pcorner.patch,pcorner.corner());
1351 if (m_vertCheck.at(cidx))
1354 bool C0 = m_C0s[cidx];
1358 std::tie(valence,interior) = _vertexData(pcorner);
1359 if (!interior && valence==1)
1360 _computeMapperRegularCorner_v1(pcorner,valence);
1361 else if (!interior && valence==2 && C0)
1362 _computeMapperRegularBoundaryVertexNonSmooth_v2(pcorner,valence);
1363 else if (!interior && valence==2 && !C0)
1364 _computeMapperRegularBoundaryVertexSmooth_v2(pcorner,valence);
1365 else if (!interior && valence >2 && C0)
1366 _computeMapperIrregularBoundaryVertexNonSmooth_v(pcorner,valence);
1367 else if (!interior && valence >2 && !C0)
1368 _computeMapperIrregularBoundaryVertexSmooth_v(pcorner,valence);
1370 _computeMapperInteriorVertex_v(pcorner,valence);
1372 GISMO_ERROR(
"Something went terribly wrong, interior="<<interior<<
"; valence="<<valence);
1375 m_vertCheck[ cidx ] =
true;
1378 template<
short_t d,
class T>
1379 void gsDPatchBase<d,T>::_computeMapperRegularCorner_v1(patchCorner pcorner,
index_t valence)
1385 template<
short_t d,
class T>
1386 void gsDPatchBase<d,T>::_computeMapperRegularBoundaryVertexSmooth_v2(patchCorner pcorner,
index_t valence)
1388 std::vector<patchSide> psides(2);
1418 pcorner.getContainingSides(d,psides);
1419 for (
size_t p=0; p!=psides.size(); p++)
1422 if (m_topology.isInterface(psides[p]))
1425 m_mapModified.eliminateDof(_indexFromVert(k,pcorner,psides[p],0),pcorner.patch);
1442 template<
short_t d,
class T>
1443 void gsDPatchBase<d,T>::_computeMapperRegularBoundaryVertexNonSmooth_v2(patchCorner pcorner,
index_t valence)
1445 std::vector<patchSide> psides(2);
1458 pcorner.getContainingSides(d,psides);
1459 for (
size_t p=0; p!=psides.size(); p++)
1461 if (m_topology.isInterface(psides[p]))
1463 m_mapModified.eliminateDof(this->_indexFromVert(1,pcorner,psides[p],0),pcorner.patch);
1468 template<
short_t d,
class T>
1469 void gsDPatchBase<d,T>::_computeMapperIrregularBoundaryVertexSmooth_v(patchCorner pcorner,
index_t valence)
1488 gsWarn<<
"C0 handling for boundary corners with valence >2 has not yet been implemented. Using the default approach\n";
1489 this->_computeMapperIrregularBoundaryVertexNonSmooth_v(pcorner,valence);
1492 template<
short_t d,
class T>
1493 void gsDPatchBase<d,T>::_computeMapperIrregularBoundaryVertexNonSmooth_v(patchCorner pcorner,
index_t valence)
1497 std::vector<patchSide> psides(2);
1498 pcorner.getContainingSides(d,psides);
1499 for (
size_t p=0; p!=psides.size(); p++)
1502 if (m_topology.isInterface(psides[p]))
1503 m_mapModified.eliminateDof(_indexFromVert(1,pcorner,psides[p],0),pcorner.patch);
1507 template<
short_t d,
class T>
1508 void gsDPatchBase<d,T>::_computeMapperInteriorVertex_v(patchCorner pcorner,
index_t valence)
1510 std::vector<patchSide> psides(2);
1528 pcorner.getContainingSides(d,psides);
1529 for (
size_t p=0; p!=psides.size(); p++)
1531 m_mapModified.eliminateDof(this->_indexFromVert(0,pcorner,psides[p],0),pcorner.patch);
1532 m_mapModified.eliminateDof(this->_indexFromVert(1,pcorner,psides[p],0),pcorner.patch);
1536 template<
short_t d,
class T>
1539 std::vector<patchSide> psides;
1540 std::vector<index_t> indices(4);
1541 sparseEntry_t entries;
1544 indices[0] = _indexFromVert(0,pcorner,psides[0],0);
1545 indices[1] = _indexFromVert(1,pcorner,psides[0],0);
1546 indices[2] = _indexFromVert(1,pcorner,psides[1],0);
1547 indices[3] = _indexFromVert(1,pcorner,psides[1],1);
1551 for (std::vector<index_t>::iterator it = indices.begin(); it!=indices.end(); ++it)
1553 rowIdx = m_mapModified.index(*it,pcorner.patch);
1554 colIdx = m_mapOriginal.index(*it,pcorner.patch);
1555 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1558 #pragma omp critical (handle_boundary_vertex_tt)
1560 _pushAndCheck(entries);
1561 m_vertCheck[ _vertIndex(pcorner.patch, pcorner.corner()) ] =
true;
1567 template<
short_t d,
class T>
1570 std::vector<patchSide> psides;
1571 std::vector<index_t> indices(3);
1573 sparseEntry_t entries;
1583 index_t iindex = m_topology.isInterface(psides[0]) ? 0 : 1;
1585 GISMO_ENSURE(m_topology.getInterface(psides[iindex],iface),
"Must be an interface");
1590 patchCorner otherCorner = iface.mapCorner(pcorner);
1591 for (
index_t k = 0; k!=2; k++)
1593 indices[0] = _indexFromVert(k,pcorner,psides[iindex],1);
1594 indices[1] = _indexFromVert(k,pcorner,psides[iindex],0);
1595 indices[2] = _indexFromVert(k,otherCorner,otherSide,0);
1597 rowIdx = m_mapModified.index(indices[0],pcorner.patch);
1598 colIdx = m_mapOriginal.index(indices[0],pcorner.patch);
1600 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1601 colIdx = m_mapOriginal.index(indices[1],psides[iindex].patch);
1603 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1604 colIdx = m_mapOriginal.index(indices[2],otherSide.patch);
1606 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1609 #pragma omp critical (handle_boundary_vertex_tt)
1611 _pushAndCheck(entries);
1612 m_vertCheck[ _vertIndex(pcorner.patch, pcorner.corner()) ] =
true;
1616 template<
short_t d,
class T>
1617 void gsDPatchBase<d,T>::_handleRegularBoundaryVertexNonSmooth(patchCorner pcorner,
index_t valence)
1619 std::vector<patchSide> psides;
1620 std::vector<index_t> indices(3);
1622 sparseEntry_t entries;
1626 boundaryInterface iface;
1629 pcorner.getContainingSides(d,psides);
1632 index_t iindex = m_topology.isInterface(psides[0]) ? 0 : 1;
1634 GISMO_ENSURE(m_topology.getInterface(psides[iindex],iface),
"Must be an interface");
1638 patchSide otherSide = iface.other(psides[iindex]);
1639 patchCorner otherCorner = iface.mapCorner(pcorner);
1640 for (
index_t k = 1; k!=2; k++)
1642 indices[0] = _indexFromVert(k,pcorner,psides[iindex],1);
1643 indices[1] = _indexFromVert(k,pcorner,psides[iindex],0);
1644 indices[2] = _indexFromVert(k,otherCorner,otherSide,0);
1646 rowIdx = m_mapModified.index(indices[0],pcorner.patch);
1647 colIdx = m_mapOriginal.index(indices[0],pcorner.patch);
1649 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1650 colIdx = m_mapOriginal.index(indices[1],psides[iindex].patch);
1652 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1653 colIdx = m_mapOriginal.index(indices[2],otherSide.patch);
1655 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1658 #pragma omp critical (handle_boundary_vertex_tt)
1660 _pushAndCheck(entries);
1661 m_vertCheck[ _vertIndex(pcorner.patch, pcorner.corner()) ] =
true;
1665 template<
short_t d,
class T>
1666 void gsDPatchBase<d,T>::_handleIrregularBoundaryVertexSmooth(patchCorner pcorner,
index_t valence)
1668 gsWarn<<
"C1 handling for boundary corners with valence >2 has not yet been implemented. Using the default approach\n";
1669 this->_handleIrregularBoundaryVertexNonSmooth(pcorner,valence);
1672 template<
short_t d,
class T>
1673 void gsDPatchBase<d,T>::_handleIrregularBoundaryVertexNonSmooth(patchCorner pcorner,
index_t valence)
1675 std::vector<patchSide> psides;
1676 std::vector<patchCorner> corners;
1677 std::vector<index_t> indices;
1678 sparseEntry_t entries;
1680 boundaryInterface iface;
1681 patchSide otherSide;
1686 pcorner.getContainingSides(d,psides);
1688 std::vector<index_t> rowIndices, colIndices, patchIndices;
1691 m_topology.getCornerList(pcorner,corners);
1695 index_t b11_p1 = _indexFromVert(1,pcorner,psides[0],1);
1696 rowIdx = m_mapModified.index(b11_p1,pcorner.patch);
1697 colIdx = m_mapOriginal.index(b11_p1,pcorner.patch);
1700 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1704 for (
index_t k = 0; k!=2; k++)
1708 if (!m_topology.getInterface(psides[k],iface))
1710 idx = _indexFromVert(1,pcorner,psides[k],0);
1711 rowIdx = m_mapModified.index(idx,pcorner.patch);
1712 colIdx = m_mapOriginal.index(idx,pcorner.patch);
1714 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1720 rowIdx = m_mapModified.index(b11_p1,pcorner.patch);
1722 patchSide otherSide = iface.other(psides[k]);
1723 patchCorner otherCorner = iface.mapCorner(pcorner);
1725 idx = _indexFromVert(1,pcorner,psides[k],0);
1726 colIdx = m_mapOriginal.index(idx,pcorner.patch);
1727 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1729 idx = _indexFromVert(1,otherCorner,otherSide,0);
1730 colIdx = m_mapOriginal.index(idx,otherCorner.patch);
1731 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1736 index_t b00_p1 = _indexFromVert(0,pcorner,psides[0],0);
1737 rowIdx = m_mapModified.index(b00_p1,pcorner.patch);
1738 colIdx = m_mapOriginal.index(b00_p1,pcorner.patch);
1741 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
1743 #pragma omp critical (handle_boundary_vertex_ff)
1745 _pushAndCheck(entries);
1746 m_vertCheck[ _vertIndex(pcorner.patch, pcorner.corner()) ] =
true;
Provides definition of HTensorBasis abstract interface.
Abstract base class representing a geometry map.
Definition: gsGeometry.h:92
Provides generic assembler routines.
virtual void _computeMapper()
Calculates the mapper.
Definition: gsDPatchBase.hpp:1209
virtual gsGeometry< T > * exportPatch(index_t patch, bool computeCoefs=true)
Exports a single modified patch with index patch.
Definition: gsDPatchBase.hpp:186
Struct which represents a certain side of a patch.
Definition: gsBoundary.h:231
virtual void vertexInfo(patchCorner corner) const
Returns information about a vertex.
Definition: gsDPatchBase.hpp:151
Creates a mapped object or data pointer to a matrix without copying data.
Definition: gsLinearAlgebra.h:126
patchSide & other(const patchSide &ps)
Returns the second side if ps is the first side, otherwise returns the second side.
Definition: gsBoundary.h:789
virtual void sideInfo() const
Returns information for all the sides in the topology.
Definition: gsDPatchBase.hpp:165
bool parameter() const
Returns the parameter value (false=0=start, true=1=end) that corresponds to this side.
Definition: gsBoundary.h:128
virtual void _handleInterface(boundaryInterface iface)
Handles an interface in the global matrix.
Definition: gsDPatchBase.hpp:1002
virtual void _handleInterior()
Handles the interior in the global matrix.
Definition: gsDPatchBase.hpp:1155
Outward normal on the boundary.
Definition: gsForwardDeclarations.h:86
void getContainedCorners(short_t dim, std::vector< patchCorner > &corners) const
returns the vector of the corners contained in the side
Definition: gsBoundary.cpp:35
virtual std::vector< bool > getSharpCorners(T tol=1e-2) const
Checks if corners are sharp or not.
Definition: gsDPatchBase.hpp:47
the gsMapData is a cache of pre-computed function (map) values.
Definition: gsFuncData.h:324
virtual void _initMatrix()
Initializes the matrix.
Definition: gsDPatchBase.hpp:851
Provides declaration of THBSplineBasis class.
virtual void _initChecks()
Prepares the THB basis if needed.
Definition: gsDPatchBase.hpp:810
S give(S &x)
Definition: gsMemory.h:266
virtual void compute()
Computes the construction.
Definition: gsDPatchBase.hpp:26
#define index_t
Definition: gsConfig.h:32
Generic expressions helper.
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
void getContainingSides(short_t dim, std::vector< patchSide > &sides) const
returns a vector of patchSides that contain this corner
Definition: gsBoundary.h:416
virtual void _computeSmoothMatrix()
Calculates the smooth matrix.
Definition: gsDPatchBase.hpp:1177
A tensor product B-spline basis.
Definition: gsTensorBSplineBasis.h:36
Struct which represents a certain corner of a patch.
Definition: gsBoundary.h:392
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
Maintains a mapping from patch-local dofs to global dof indices and allows the elimination of individ...
Definition: gsDofMapper.h:68
virtual void _handleBoundary(patchSide side)
Handles a boundary in the global matrix.
Definition: gsDPatchBase.hpp:1112
virtual void mapperInfo() const
Returns for each basis function if it is free or eliminated.
Definition: gsDPatchBase.hpp:134
Generic expressions evaluator.
virtual void _removeLowestCorners(std::vector< patchCorner > &pcorners, index_t n=3) const
From a list of patchCorners pcorners, remove all but the lowest n corners.
Definition: gsDPatchBase.hpp:448
virtual void _handleVertex(patchCorner pcorner)
Handles a vertex in the global matrix.
Definition: gsDPatchBase.hpp:970
Provides declaration of TensorNurbsBasis abstract interface.
virtual void _whichHandled()
Prints which DoFs have been handled and which have been eliminated.
Definition: gsDPatchBase.hpp:857
#define gsWarn
Definition: gsDebug.h:50
Holds a set of patch-wise bases and their topology information.
Definition: gsMultiBasis.h:36
const gsBasis< T > & basis(const index_t k) const
Helper which casts and returns the k-th piece of this function set as a gsBasis.
Definition: gsFunctionSet.hpp:33
virtual void cornerInfo() const
Returns information for all the corners in the topology.
Definition: gsDPatchBase.hpp:174
#define gsInfo
Definition: gsDebug.h:43
Constructs the D-Patch, from which the transformation matrix can be called.
Definition: gsDPatchBase.h:36
T at(index_t i) const
Returns the i-th element of the vector.
Definition: gsVector.h:177
virtual void _initMappers()
Initializes the matrix, the basis and the mappers.
Definition: gsDPatchBase.hpp:844
virtual void _getLowestCorners(std::vector< patchCorner > &pcorners, index_t n=3) const
From a list of patchCorners pcorners, get the lowest n corners.
Definition: gsDPatchBase.hpp:435
virtual void _initialize()
Initializes the class:-.
Definition: gsDPatchBase.hpp:792
virtual void _performChecks(bool basis)
Performs checks on sides, vertices and bases.
Definition: gsDPatchBase.hpp:875
virtual void _initBasis()
Initializes the basis.
Definition: gsDPatchBase.hpp:839
virtual gsMatrix< index_t > boundaryOffset(boxSide const &s, index_t offset) const
Definition: gsBasis.hpp:316
const gsBasis< T > & basis(const size_t i) const
Return the i-th basis block.
Definition: gsMultiBasis.h:267
virtual void _getLowestIndices(std::vector< std::pair< index_t, index_t >> &indices, index_t n=3) const
From a list of tuples (patch,index), get the lowest n tuples.
Definition: gsDPatchBase.hpp:463
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
virtual const index_t _indexFromSides(index_t index1, const patchSide side1, index_t index2, const patchSide side2)
Computes the index of a basis function using sides as reference.
Definition: gsDPatchBase.hpp:227
patchSide & second()
second, returns the second patchSide of this interface
Definition: gsBoundary.h:782
EIGEN_STRONG_INLINE abs_expr< E > abs(const E &u)
Absolute value.
Definition: gsExpressions.h:4486
virtual void _initTHB()
Initializes the matrix, the basis and the mappers.
Definition: gsDPatchBase.hpp:823
virtual void defaultOptions()
Sets the default options.
Definition: gsDPatchBase.hpp:39
gsMatrix< T > points
input (parametric) points
Definition: gsFuncData.h:348
Struct which represents an interface between two patches.
Definition: gsBoundary.h:649
virtual void _removeLowestIndices(std::vector< std::pair< index_t, index_t >> &indices, index_t n=3) const
From a list of tuples (patch,index), remove all but the lowest n tuples.
Definition: gsDPatchBase.hpp:484
Truncated hierarchical B-spline basis.
Definition: gsTHBSplineBasis.h:35
virtual const std::pair< index_t, bool > _vertexData(const patchCorner corner) const
Returns the valence and whether a corner is interior or boundary.
Definition: gsDPatchBase.hpp:425
virtual void _handleRegularCorner(patchCorner pcorner)
Handles a regular corner.
Definition: gsDPatchBase.hpp:1537
virtual const index_t _indexFromVert(const index_t index, const patchCorner corner, const patchSide side, const index_t offsets=0) const
Computes the index of a basis function taking one corner and one side as reference.
Definition: gsDPatchBase.hpp:269
index_t patch
The index of the patch.
Definition: gsBoundary.h:234
short_t direction() const
Returns the parametric direction orthogonal to this side.
Definition: gsBoundary.h:113
virtual void _resetChecks(bool basis)
Resets checks on sides, vertices and bases.
Definition: gsDPatchBase.hpp:890
gsMatrix< index_t > boundary(boxSide const &s) const
Returns the indices of the basis functions that are nonzero at the domain boundary as single-column-m...
Definition: gsBasis.h:520
A basis represents a family of scalar basis functions defined over a common parameter domain...
Definition: gsBasis.h:78
patchSide & first()
first, returns the first patchSide of this interface
Definition: gsBoundary.h:776