25 template<
short_t d,
class T>
32 for (
size_t p=0; p!=m_Bbases.nBases(); p++)
33 for (
short_t dim=0; dim!=d; dim++)
34 GISMO_ENSURE(m_Bbases.basis(p).degree(dim)==2,
"Degree of the basis ( dimension "<<dim<<
" ) of patch "<<p<<
" is "<<m_Bbases.basis(p).degree(dim)<<
", but should be 2!");
37 template<
short_t d,
class T>
60 template<
short_t d,
class T>
61 gsMatrix<T> gsAlmostC1<d,T>::_getNormals(
const std::vector<patchCorner> & corners)
const
63 gsMatrix<T> normals(3,corners.size());
68 gsExprEvaluator<T> ev;
69 typename gsExprEvaluator<T>::geometryMap Gm = ev.getMap(m_RefPatches);
71 for (
typename std::vector<patchCorner>::const_iterator it = corners.begin(); it!=corners.end(); it++, k++)
73 it->corner().parameters_into(m_RefPatches.parDim(),pars);
74 gsMatrix<T> supp = m_RefPatches.basis(it->patch).support();
75 gsVector<T> vec(supp.rows());
76 for (
index_t r = 0; r!=supp.rows(); r++)
77 vec(r) = supp(r,pars(r));
79 normals.col(k) = ev.eval(sn(Gm).normalized(),vec,it->patch);
85 template<
short_t d,
class T>
86 std::tuple<gsMatrix<T>,gsMatrix<T>,gsMatrix<index_t>> gsAlmostC1<d,T>::_makeTriangle(
const patchCorner & corner)
const
88 GISMO_ASSERT(m_RefPatches.nPatches()!=0,
"Are the patches refined?");
90 index_t tdim = m_RefPatches.targetDim();
92 std::vector<patchCorner> corners;
93 m_RefPatches.getCornerList(corner,corners);
98 gsMatrix<T> um(3,1), midpoint;
100 corner.corner().parameters_into(m_RefPatches.parDim(),pars);
101 gsMatrix<T> supp = m_RefPatches.basis(corner.patch).support();
102 gsVector<T> vec(supp.rows());
103 for (
index_t r = 0; r!=supp.rows(); r++)
104 vec(r) = supp(r,pars(r));
106 um.block(0,0,tdim,1) = m_RefPatches.patch(corner.patch).eval(vec);
110 gsMatrix<T> u(3,corners.size()*4);
112 gsMatrix<index_t> uind(1,corners.size()*4);
115 std::vector<patchSide> csides;
117 for (
size_t c = 0; c!=corners.size(); c++)
119 corners[c].getContainingSides(d,csides);
122 for (
index_t j=0; j!=2; j++,k++)
124 idx = _indexFromVert(i,corners[c],csides[0],j);
125 uind(0,4*c+k) = m_mapOriginal.index(idx,corners[c].patch);
126 u.block(0,4*c+k,m_RefPatches.targetDim(),1) = m_RefPatches.patch(corners[c].patch).coefs().row(idx).transpose();
132 for (
index_t k=0; k!=up.cols(); k++)
136 gsMatrix<T,3,3> Rn, Rx;
138 if (m_RefPatches.targetDim()==2)
142 else if(m_RefPatches.targetDim()==3)
145 gsVector<T> avgnormal = _getNormals(corners).rowwise().mean();
147 if (avgnormal.norm()==0) avgnormal = _getNormals(corners).col(0);
151 Rn = _getRotationMatrix(avgnormal.normalized(),ez);
153 for (
index_t k=0; k!=up.cols(); k++)
154 up.col(k).applyOnTheLeft(Rn);
160 GISMO_ERROR(
"Target dimension of the multipatch should be 2 or 3, but is "<<m_RefPatches.targetDim());
165 for (
index_t k = 0; k!=up.cols(); k++)
167 distance = (up.col(k)).norm();
168 if (distance > maxDistance)
179 Rx = _getRotationMatrix(umax.normalized(),ex);
180 for (
index_t k=0; k!=up.cols(); k++)
181 up.col(k).applyOnTheLeft(Rx);
185 T a = 1. / ( 1./6. * std::sqrt(3) ) * r;
186 T rr = 1. / 3. * std::sqrt(3) * a;
190 Cp.col(1)<<-r, 0.5*a;
191 Cp.col(2)<<-r,-0.5*a;
197 A.block(0,0,2,3) = Cp;
200 for (
index_t k = 0; k!=ub.cols(); k++)
202 ub.col(k) = A.colPivHouseholderQr().solve(up.col(k));
203 GISMO_ASSERT((Cp * ub.col(k)-up.col(k).head(2)).norm()<1e-12,
"Something went wrong with the computation of the barycentric coordinates. (Cp * ub.col(k)-up.col(k).head(2)).norm() = "<<(Cp * ub.col(k)-up.col(k).head(2)).norm()<<
"; Cp * ub.col(k) = "<<Cp * ub.col(k)<<
"; up.col(k).head(2) = "<<up.col(k).head(2));
209 Cg.block(0,0,2,3) = Cp;
211 for (
index_t k = 0; k!=Cg.cols(); k++)
213 Cg.col(k).applyOnTheLeft((Rx).transpose());
214 Cg.col(k).applyOnTheLeft((Rn).transpose());
215 Cg.col(k) += midpoint;
218 if (m_RefPatches.targetDim()==2)
219 Cg.conservativeResize(2,gsEigen::NoChange);
221 return std::make_tuple(Cg,ub,uind);
224 template<
short_t d,
class T>
225 gsMatrix<T,3,3> gsAlmostC1<d,T>::_getRotationMatrix(
const gsVector<T,3> & a,
const gsVector<T,3> & b)
const
230 gsVector<T,3> v = a.cross(b);
232 T theta = std::acos( a.dot(b) / ( a.norm() * b.norm() ) );
234 T s = std::sin(theta);
235 T c = std::cos(theta);
236 gsMatrix<T,3,3> R,vx,tmp, I;
240 vx.row(0)<<0,-v.at(2),v.at(1);
241 vx.row(1)<<v.at(2),0,-v.at(0);
242 vx.row(2)<<-v.at(1),v.at(0),0;
247 tmp = (v*v.transpose()) * (1-c);
250 GISMO_ASSERT((R * a - b).norm() < 1e-12,
"Rotation matrix is wrong, R*a = "<<R*a<<
"; b = "<<b);
260 template<
short_t d,
class T>
263 GISMO_ASSERT(m_mapModified.isFinalized(),
"Mapper is not finalized, run XXXX first");
265 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);
266 gsMatrix<T> coefs(m_mapModified.freeSize(),m_patches.geoDim());
269 for (
size_t p=0; p!=m_bases.nBases(); p++)
271 size = m_mapModified.patchSize(p);
272 for (
index_t k=0; k!=size; k++)
274 if (m_mapModified.is_free(k,p))
275 coefs.row(m_mapModified.index(k,p,0)) = m_patches.patch(p).coefs().row(k);
281 template<
short_t d,
class T>
284 GISMO_ASSERT(m_mapModified.isFinalized(),
"Mapper is not finalized, run XXXX first");
289 std::fill(m_vertCheck.begin(), m_vertCheck.end(),
false);
291 std::vector<patchCorner> pcorners;
293 for (
size_t p=0; p!=m_bases.nBases(); p++)
297 cidx = _vertIndex(p,c);
298 if (m_vertCheck.at(cidx))
301 bool C0 = m_C0s[cidx];
303 m_topology.getCornerList(pcorner,pcorners);
304 std::pair<index_t,bool> vdata = _vertexData(pcorner);
305 if (vdata.first > 2 && !(vdata.first==4 && vdata.second))
309 std::tie(Cg,std::ignore,std::ignore) = _makeTriangle(pcorner);
313 std::vector<std::pair<index_t,index_t>> indices = _getAllInterfaceIndices(pcorner,0,m_Bbases);
314 _getLowestIndices(indices,3);
316 std::vector<index_t> rowIndices;
317 for (std::vector<std::pair<index_t,index_t>>::iterator it=indices.begin(); it!=indices.end(); it++)
319 GISMO_ASSERT(m_mapModified.is_free(it->second,it->first),
"This DoF must be free! patch = "<<it->first<<
"; index = "<<it->first);
320 rowIndices.push_back(m_mapModified.index(it->second,it->first));
324 for (
index_t j=0; j!=Cg.cols(); j++)
326 rowIdx = rowIndices[j];
327 coefs.row(rowIdx) = Cg.col(j).transpose();
330 for (
size_t k = 0; k!=pcorners.size(); k++)
331 m_vertCheck[ _vertIndex(pcorners[k].patch, pcorners[k].corner()) ] =
true;
333 else if (vdata.first == 2 && C0)
337 std::tie(Cg,std::ignore,std::ignore) = _makeTriangle(pcorner);
341 std::vector<std::pair<index_t,index_t>> indices0 = _getAllInterfaceIndices(pcorner,0,m_Bbases);
342 std::vector<std::pair<index_t,index_t>> indices1 = _getAllInterfaceIndices(pcorner,1,m_Bbases);
343 _getLowestIndices(indices1,1);
344 indices0.push_back(indices1[0]);
346 std::vector<index_t> rowIndices;
347 for (std::vector<std::pair<index_t,index_t>>::iterator it=indices0.begin(); it!=indices0.end(); it++)
349 GISMO_ASSERT(m_mapModified.is_free(it->second,it->first),
"This DoF must be free! patch = "<<it->first<<
"; index = "<<it->first);
350 rowIndices.push_back(m_mapModified.index(it->second,it->first));
354 for (
index_t j=0; j!=Cg.cols(); j++)
356 rowIdx = rowIndices[j];
357 coefs.row(rowIdx) = Cg.col(j).transpose();
360 for (
size_t k = 0; k!=pcorners.size(); k++)
361 m_vertCheck[ _vertIndex(pcorners[k].patch, pcorners[k].corner()) ] =
true;
365 m_vertCheck[ _vertIndex(pcorner.patch, pcorner.corner()) ] =
true;
373 template<
short_t d,
class T>
376 std::vector<index_t> sizes(mp.
nPatches());
378 for (
size_t p=0; p!=mp.
nPatches(); p++)
380 sizes.at(p) = mp.
patch(p).coefs().rows();
381 totalsize += sizes.at(p);
384 GISMO_ENSURE(totalsize==coefs.rows(),
"Sizes do not agree");
390 for (
size_t p=0; p!=mp.
nPatches(); p++)
391 for (
index_t k=0; k!=sizes.at(p); k++)
392 mp.
patch(p).coefs().row(k) = coefs.row(tmpMap.
index(k,p));
399 template<
short_t d,
class T>
405 template<
short_t d,
class T>
408 m_RefPatches = m_patches;
412 for (
size_t k=0; k!=m_RefPatches.nPatches(); ++k)
417 m_RefPatches.patch(k) = thb;
422 gsWarn<<
"No THB basis was constructed";
427 template <
short_t d,
class T>
431 patchBoxes.resize(m_RefPatches.nPatches());
435 std::vector<index_t> boxes;
439 std::vector<patchCorner> cornerList;
440 std::vector<std::vector<patchCorner> > cornerLists = _getSpecialCornerLists(m_RefPatches);
442 index_t N = cornerLists.size();
446 mask.setConstant(
false);
450 for (
size_t c = 0; c<cornerLists[v].size(); c++)
452 corner = cornerLists[v].at(c);
455 if (mask(corner.patch,corner.corner()-1))
460 for (
short_t dim = 0; dim!=d; dim++)
464 box.row(dim).setConstant(pars(dim)*(KV.
uSize()-1));
465 box(dim,!pars(dim)) += ( 1 - 2*pars(dim) ) * nelements;
473 if ((corner.
m_index==1 && dim==0) || (corner.
m_index==4 && dim==1))
475 else if ((corner.
m_index==1 && dim==1) || (corner.
m_index==4 && dim==0))
477 else if ((corner.
m_index==2 && dim==0) || (corner.
m_index==3 && dim==1))
479 else if ((corner.
m_index==2 && dim==1) || (corner.
m_index==3 && dim==0))
487 m_topology.getCornerList(otherPCorner,cornerList);
488 cornerLists.push_back(cornerList);
495 boxes.insert(boxes.end(), box.data(), box.data()+box.size());
496 patchBoxes.at(corner.patch).insert(patchBoxes.at(corner.patch).end(), boxes.begin(), boxes.end());
498 mask(corner.patch,corner.corner()-1) =
true;
503 template<
short_t d,
class T>
507 std::vector<std::vector<patchCorner> > cornerLists = _getSpecialCornerLists(m_RefPatches);
509 if (cornerLists.size()!=0)
513 coefs = m_matrix.transpose() * coefs;
515 this->setCoefficients(coefs,m_RefPatches);
518 std::vector< std::vector<index_t> > elVec;
519 this->_refBoxes(elVec);
523 std::vector<gsEigen::Triplet<T,index_t>> tripletList;
524 for (
size_t p=0; p!=m_RefPatches.nPatches(); p++)
528 boxMat.row(0).array() += 1;
529 boxMat.block(1,0,boxMat.rows()-1,boxMat.cols()).array() *= 2;
532 std::vector< gsSortedVector< index_t > > xmat = basis->getXmatrix();
534 m_RefPatches.patch(p).refineElements(elVec[p]);
537 for (
index_t i = 0; i<tmp.outerSize(); ++i)
539 tripletList.push_back(gsEigen::Triplet<T,index_t>(it.row()+rows,it.col()+cols,it.value()));
545 m_tMatrix.resize(rows,cols);
546 m_tMatrix.setFromTriplets(tripletList.begin(), tripletList.end());
548 m_tMatrix.makeCompressed();
554 m_mapOriginal.finalize();
559 template<
short_t d,
class T>
562 std::vector<std::vector<patchCorner> > cornerLists;
564 std::vector<patchCorner> cornerList;
567 for(
size_t p = 0;p<patches.
nPatches();++p)
572 cidx = _vertIndex(p,c);
573 bool C0 = m_C0s[cidx];
575 bool alreadyReached =
false;
576 for(
size_t k = 0;k<cornerList.size();++k)
577 if((
size_t)cornerList[k].patch<p)
578 alreadyReached =
true;
584 if(((isCycle&&cornerList.size()!=4)||((!isCycle)&&cornerList.size()>2-(size_t)C0))&&!alreadyReached)
585 cornerLists.push_back(cornerList);
591 template<
short_t d,
class T>
600 std::vector<std::vector<patchCorner> > cornerLists = _getSpecialCornerLists(m_RefPatches);
603 std::fill(m_vertCheck.begin(), m_vertCheck.end(),
false);
604 if (cornerLists.size()!=0)
606 m_matrix = m_matrix * m_tMatrix.transpose();
608 std::vector<patchCorner> pcorners;
615 for (std::vector<std::vector<patchCorner> >::iterator it=cornerLists.begin(); it!=cornerLists.end(); it++)
618 std::vector<patchCorner> pcorners = *it;
620 cidx = _vertIndex(pcorner.patch,pcorner.corner());
621 if (m_vertCheck.at(cidx))
624 std::pair<index_t,bool> vdata = _vertexData(pcorner);
628 std::tie(Cg,ub,uind) = _makeTriangle(pcorner);
633 std::vector<std::pair<index_t,index_t>> indices, tmp;
637 indices = _getAllInterfaceIndices(pcorner,0,m_Bbases);
638 tmp = _getAllInterfaceIndices(pcorner,1,m_Bbases);
639 _getLowestIndices(tmp,1);
640 indices.push_back(tmp[0]);
644 indices = _getAllInterfaceIndices(pcorner,0,m_Bbases);
645 _getLowestIndices(indices,3);
649 std::vector<index_t> rowIndices;
650 rowIndices.reserve(3);
651 for (std::vector<std::pair<index_t,index_t>>::iterator it=indices.begin(); it!=indices.end(); it++)
654 GISMO_ASSERT(m_mapModified.is_free(it->second,it->first),
"This DoF must be free! patch = "<<it->first<<
"; index = "<<it->first);
655 rowIndices.push_back(m_mapModified.index(it->second,it->first));
660 for (
index_t j=0; j!=ub.cols(); j++)
665 {
return j!=colIdx; }
669 for (
index_t i=0; i!=ub.rows(); i++)
670 for (
index_t j=0; j!=ub.cols(); j++)
672 rowIdx = rowIndices[i];
674 m_matrix(rowIdx,colIdx) = ub(i,j);
677 for (
size_t k = 0; k!=pcorners.size(); k++)
678 m_vertCheck[ _vertIndex(pcorners[k].patch, pcorners[k].corner()) ] =
true;
680 m_matrix.makeCompressed();
684 template<
short_t d,
class T>
691 for (
size_t p=0; p!=m_bases.nBases(); p++)
693 tmp += m_bases.basis(p).size();
696 tmp -= m_bases.basis(p).boundaryOffset(
boxSide(1),k).size();
697 tmp -= m_bases.basis(p).boundaryOffset(
boxSide(2),k).size();
698 tmp -= m_bases.basis(p).boundaryOffset(
boxSide(3),k).size()-4;
699 tmp -= m_bases.basis(p).boundaryOffset(
boxSide(4),k).size()-4;
710 for(gsBoxTopology::const_iiterator iit = m_topology.iBegin(); iit!= m_topology.iEnd(); iit++)
712 basis1 = &m_bases.
basis(iit->first().patch);
713 basis2 = &m_bases.
basis(iit->second().patch);
714 tmp += basis1->
boundary(iit->first().side()).size() - 4;
715 tmp += basis2->
boundary(iit->second().side()).size() - 4;
721 for(gsBoxTopology::const_biterator bit = m_topology.bBegin(); bit!= m_topology.bEnd(); bit++)
723 basis1 = &m_bases.
basis(bit->patch);
736 std::vector<bool> passed(m_bases.nBases()*4);
737 std::fill(passed.begin(), passed.end(),
false);
739 std::vector<patchCorner> corners;
740 for (
size_t p=0; p!=m_bases.nBases(); p++)
746 m_topology.getCornerList(
patchCorner(p,c),corners);
747 for (
size_t k=0; k!=corners.size(); k++)
748 passed.at(_vertIndex(corners[k].patch,corners[k])) =
true;
750 std::pair<index_t,bool> vdata = _vertexData(
patchCorner(p,c));
751 bool C0 = m_C0s[idx];
753 if ((!vdata.second) && vdata.first==1)
757 else if ((!vdata.second) && vdata.first==2 && !C0)
761 else if ((!vdata.second) && vdata.first>2 && !C0)
762 tmp += vdata.first+3+2;
765 else if ((!vdata.second) && vdata.first==2 && C0)
766 tmp += 2*vdata.first+2+1;
769 else if ((!vdata.second) && vdata.first>2 && C0)
770 tmp += 2*vdata.first+2;
773 else if (( vdata.second) && vdata.first==4)
778 tmp += vdata.first+3;
786 template<
short_t d,
class T>
789 index_t cidx = _vertIndex(pcorner.patch,pcorner.corner());
790 if (m_vertCheck.at(cidx))
793 bool C0 = m_C0s[cidx];
797 std::tie(valence,interior) = _vertexData(pcorner);
798 if (!interior && valence==1)
799 _computeMapperRegularCorner_v1(pcorner,valence);
800 else if (!interior && valence==2 && C0)
801 _computeMapperRegularBoundaryVertexNonSmooth_v2(pcorner,valence);
802 else if (!interior && valence==2 && !C0)
803 _computeMapperRegularBoundaryVertexSmooth_v2(pcorner,valence);
804 else if (!interior && valence >2 && C0)
805 _computeMapperIrregularBoundaryVertexNonSmooth_v(pcorner,valence);
806 else if (!interior && valence >2 && !C0)
807 _computeMapperIrregularBoundaryVertexSmooth_v(pcorner,valence);
808 else if (interior && valence==4)
809 _computeMapperInteriorVertex_v4(pcorner,valence);
810 else if (interior && (valence==3 || valence> 4) )
811 _computeMapperInteriorVertex_v(pcorner,valence);
813 GISMO_ERROR(
"Something went terribly wrong, interior="<<interior<<
"; valence="<<valence);
816 m_vertCheck[ cidx ] =
true;
819 template<
short_t d,
class T>
820 void gsAlmostC1<d,T>::_computeMapperRegularBoundaryVertexNonSmooth_v2(patchCorner pcorner,
index_t valence)
830 std::vector<std::pair<index_t,index_t>> indices1 = _getAllInterfaceIndices(pcorner,1,m_bases);
832 _removeLowestIndices(indices1,1);
833 for (std::vector<std::pair<index_t,index_t>>::iterator it=indices1.begin(); it!=indices1.end(); it++)
834 m_mapModified.eliminateDof(it->second,it->first);
836 std::vector<patchCorner> pcorners;
837 m_topology.getCornerList(pcorner,pcorners);
838 for (std::vector<patchCorner>::iterator it=pcorners.begin(); it!=pcorners.end(); it++)
841 m_vertCheck[ _vertIndex(it->patch, it->corner()) ] =
true;
846 template<
short_t d,
class T>
847 void gsAlmostC1<d,T>::_computeMapperIrregularBoundaryVertexSmooth_v(patchCorner pcorner,
index_t valence)
849 std::vector<std::pair<index_t,index_t>> indices0 = _getAllInterfaceIndices(pcorner,0,m_bases);
850 std::vector<std::pair<index_t,index_t>> indices1 = _getAllInterfaceIndices(pcorner,1,m_bases);
851 std::vector<patchCorner> pcorners;
852 m_topology.getCornerList(pcorner,pcorners);
853 for (std::vector<patchCorner>::iterator it=pcorners.begin(); it!=pcorners.end(); it++)
856 m_vertCheck[ _vertIndex(it->patch, it->corner()) ] =
true;
860 for (std::vector<std::pair<index_t,index_t>>::iterator it=indices1.begin(); it!=indices1.end(); it++)
861 m_mapModified.eliminateDof(it->second,it->first);
863 _removeLowestIndices(indices0,3);
864 for (std::vector<std::pair<index_t,index_t>>::iterator it=indices0.begin(); it!=indices0.end(); it++)
865 m_mapModified.eliminateDof(it->second,it->first);
869 template<
short_t d,
class T>
870 void gsAlmostC1<d,T>::_computeMapperInteriorVertex_v4(patchCorner pcorner,
index_t valence)
872 this->_computeMapperRegularBoundaryVertexSmooth_v2(pcorner,valence);
876 template<
short_t d,
class T>
877 void gsAlmostC1<d,T>::_computeMapperInteriorVertex_v(patchCorner pcorner,
index_t valence)
879 std::vector<std::pair<index_t,index_t>> indices0 = _getAllInterfaceIndices(pcorner,0,m_bases);
880 std::vector<std::pair<index_t,index_t>> indices1 = _getAllInterfaceIndices(pcorner,1,m_bases);
881 std::vector<patchCorner> pcorners;
882 m_topology.getCornerList(pcorner,pcorners);
883 for (std::vector<patchCorner>::iterator it=pcorners.begin(); it!=pcorners.end(); it++)
886 m_vertCheck[ _vertIndex(it->patch, it->corner()) ] =
true;
890 _removeLowestIndices(indices0,3);
891 for (std::vector<std::pair<index_t,index_t>>::iterator it=indices0.begin(); it!=indices0.end(); it++)
892 m_mapModified.eliminateDof(it->second,it->first);
894 for (std::vector<std::pair<index_t,index_t>>::iterator it=indices1.begin(); it!=indices1.end(); it++)
895 m_mapModified.eliminateDof(it->second,it->first);
898 template<
short_t d,
class T>
901 this->_handleIrregularBoundaryVertexNonSmooth(pcorner,valence);
904 template<
short_t d,
class T>
907 std::vector<patchSide> psides;
908 std::vector<patchCorner> corners;
909 std::vector<index_t> indices;
910 sparseEntry_t entries;
923 std::vector<index_t> rowIndices, colIndices, patchIndices;
926 m_topology.getCornerList(pcorner,corners);
928 index_t b11_p1 = _indexFromVert(1,pcorner,psides[0],1);
929 rowIdx = m_mapModified.index(b11_p1,pcorner.patch);
930 colIdx = m_mapOriginal.index(b11_p1,pcorner.patch);
933 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
935 for (std::vector<patchSide>::iterator side = psides.begin(); side != psides.end(); ++side)
937 if (!m_topology.isInterface(*side))
940 GISMO_ENSURE(m_topology.getInterface(*side,iface),
"Side must be an interface!");
942 m_topology.getNeighbour(*side,otherSide);
943 patchCorner otherCorner = iface.mapCorner(pcorner);
945 index_t b10_p1 = _indexFromVert(1,pcorner,*side,0);
946 index_t b10_p2 = _indexFromVert(1,otherCorner,otherSide,0);
949 colIdx = m_mapOriginal.index(b10_p1,side->patch);
950 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
951 colIdx = m_mapOriginal.index(b10_p2,otherSide.
patch);
952 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
959 for (
typename std::vector<patchCorner>::iterator it = corners.begin(); it!=corners.end(); it++)
961 basis = &m_bases.
basis(it->patch);
962 colIndices.push_back(basis->functionAtCorner(*it));
963 patchIndices.push_back(it->patch);
966 basis = &m_bases.
basis(pcorner.patch);
971 if (!m_topology.getInterface(psides[k],iface))
973 idx = _indexFromVert(1,pcorner,psides[k],0);
974 rowIdx = m_mapModified.index(idx,pcorner.patch);
975 colIdx = m_mapOriginal.index(idx,pcorner.patch);
977 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
978 rowIndices.push_back(rowIdx);
981 GISMO_ASSERT(rowIndices.size()<2,
"Size issue, the boundary vertex is adjacent to two boundaries??" << rowIndices.size());
983 if (rowIndices.size()==1)
985 rowIdx = rowIndices[0];
986 for (
size_t k=0; k!=colIndices.size(); k++)
988 colIdx = m_mapOriginal.index(colIndices.at(k),patchIndices.at(k));
990 entries.push_back(std::make_tuple(rowIdx,colIdx,weight));
994 #pragma omp critical (handle_boundary_vertex_ff)
996 _pushAndCheck(entries);
999 std::vector<std::pair<index_t,index_t>> indices = this->_getInterfaceIndices(pcorner,0,m_bases);
1000 for (std::vector<std::pair<index_t,index_t>>::iterator it=indices.begin(); it!=indices.end(); it++)
1001 if (m_mapModified.is_free(it->second,it->first))
1003 rowIdx = m_mapModified.index(it->second,it->first);
1004 m_basisCheck[rowIdx] =
true;
1007 m_basisCheck[rowIdx] =
true;
1008 m_vertCheck[ _vertIndex(pcorner.patch, pcorner.corner()) ] =
true;
1012 template<
short_t d,
class T>
1013 void gsAlmostC1<d,T>::_handleIrregularBoundaryVertexNonSmooth(patchCorner pcorner,
index_t valence)
1015 Base::_handleIrregularBoundaryVertexNonSmooth(pcorner,valence);
1016 #pragma omp critical (handle_boundary_vertex_ff)
1020 std::vector<std::pair<index_t,index_t>> indices = this->_getInterfaceIndices(pcorner,1,m_bases);
1021 for (std::vector<std::pair<index_t,index_t>>::iterator it=indices.begin(); it!=indices.end(); it++)
1022 if (m_mapModified.is_free(it->second,it->first))
1024 rowIdx = m_mapModified.index(it->second,it->first);
1025 m_basisCheck[rowIdx] =
true;
1030 template<
short_t d,
class T>
1033 Base::_handleInteriorVertex(pcorner,valence);
1034 #pragma omp critical (handle_interior_vertex)
1038 std::vector<std::pair<index_t,index_t>> indices = this->_getInterfaceIndices(pcorner,0,m_bases);
1039 for (std::vector<std::pair<index_t,index_t>>::iterator it=indices.begin(); it!=indices.end(); it++)
1040 if (m_mapModified.is_free(it->second,it->first))
1042 rowIdx = m_mapModified.index(it->second,it->first);
1043 m_basisCheck[rowIdx] =
true;
Provides definition of HTensorBasis abstract interface.
void parameters_into(index_t dim, gsVector< bool > ¶m) const
returns a vector of parameters describing the position of the corner
Definition: gsBoundary.h:322
Constructs the D-Patch, from which the transformation matrix can be called.
Definition: gsAlmostC1.h:33
A truncated hierarchical B-Spline function, in d dimensions.
Definition: gsTHBSpline.h:37
Provides generic assembler routines.
Struct which represents a certain side of a patch.
Definition: gsBoundary.h:231
T distance(gsMatrix< T > const &A, gsMatrix< T > const &B, index_t i=0, index_t j=0, bool cols=false)
compute a distance between the point number in the set and the point number <j> in the set ; by def...
Creates a mapped object or data pointer to a matrix without copying data.
Definition: gsLinearAlgebra.h:126
#define short_t
Definition: gsConfig.h:35
size_t numElements() const
Number of knot intervals inside domain.
Definition: gsKnotVector.h:268
A tensor product of d B-spline functions, with arbitrary target dimension.
Definition: gsTensorBSpline.h:44
void _countDoFs()
Initializes the matrix, the basis and the mappers.
Definition: gsAlmostC1.hpp:685
Provides declaration of THBSplineBasis class.
bool getCornerList(const patchCorner &start, std::vector< patchCorner > &cornerList) const
Definition: gsBoxTopology.cpp:187
#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
Provides declaration of functions writing Paraview files.
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
Generic expressions evaluator.
void _handleInteriorVertex(patchCorner pcorner, index_t valence)
Handles a vertex in the global matrix.
Definition: gsAlmostC1.hpp:1031
void finalize()
Must be called after all boundaries and interfaces have been marked to set up the dof numbering...
Definition: gsDofMapper.cpp:240
index_t index(index_t i, index_t k=0, index_t c=0) const
Returns the global dof index associated to local dof i of patch k.
Definition: gsDofMapper.h:325
Class representing a (scalar) hierarchical tensor basis of functions .
Definition: gsHTensorBasis.h:74
#define gsWarn
Definition: gsDebug.h:50
Holds a set of patch-wise bases and their topology information.
Definition: gsMultiBasis.h:36
gsGeometry< T > & patch(size_t i) const
Return the i-th patch.
Definition: gsMultiPatch.h:226
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
size_t nPatches() const
Number of patches.
Definition: gsMultiPatch.h:208
void setCoefficients(const gsMatrix< T > &coefs, gsMultiPatch< T > &mp) const
Set the coefficients of mp to coefs.
Definition: gsAlmostC1.hpp:374
void _initTHB()
Initializes the matrix, the basis and the mappers.
Definition: gsAlmostC1.hpp:406
gsMatrix< T > freeCoefficients()
Computes the C1 coefficients for pre-multiplication to make the multipatch.
Definition: gsAlmostC1.hpp:261
Constructs the D-Patch, from which the transformation matrix can be called.
Definition: gsDPatchBase.h:36
void freeAll(It begin, It end)
Frees all pointers in the range [begin end)
Definition: gsMemory.h:312
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition: gsMultiPatch.h:33
Struct which represents a certain side of a box.
Definition: gsBoundary.h:84
gsAlmostC1()
Empty constructor.
Definition: gsAlmostC1.h:51
virtual gsMatrix< index_t > boundaryOffset(boxSide const &s, index_t offset) const
Definition: gsBasis.hpp:316
void _computeEVs()
Computes D-Patch smoothing.
Definition: gsAlmostC1.hpp:592
tensorBasis & tensorLevel(index_t i) const
Returns the tensor basis member of level i.
Definition: gsHTensorBasis.h:668
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
Class for representing a knot vector.
Definition: gsKnotVector.h:79
gsMatrix< T > _preCoefficients()
Computes the C1 coefficients for pre-multiplication to make the multipatch.
Definition: gsAlmostC1.hpp:282
EIGEN_STRONG_INLINE abs_expr< E > abs(const E &u)
Absolute value.
Definition: gsExpressions.h:4486
virtual void defaultOptions()
Sets the default options.
Definition: gsDPatchBase.hpp:39
Struct which represents an interface between two patches.
Definition: gsBoundary.h:649
void transfer(const std::vector< gsSortedVector< index_t > > &old, gsSparseMatrix< T > &result)
Returns transfer matrix between the hirarchical spline given by the characteristic matrix "old" and t...
Definition: gsHTensorBasis.hpp:1735
void _initBasis()
Initializes the basis.
Definition: gsAlmostC1.hpp:400
size_t uSize() const
Number of unique knots (i.e., without repetitions).
Definition: gsKnotVector.h:245
void _makeTHB()
Prepares the THB basis if needed.
Definition: gsAlmostC1.hpp:504
index_t patch
The index of the patch.
Definition: gsBoundary.h:234
void _handleRegularBoundaryVertexNonSmooth(patchCorner pcorner, index_t valence)
Handles an interface in the global matrix.
Definition: gsAlmostC1.hpp:899
index_t m_index
Index of the corner.
Definition: gsBoundary.h:298
Struct which represents a certain corner of a hyper-cube.
Definition: gsBoundary.h:291
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