G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsC1SurfSpline.hpp
Go to the documentation of this file.
1 
14 #pragma once
17 
18 
19 namespace gismo
20 {
21  template<short_t d,class T>
22  void gsC1SurfSpline<d,T>::defaultOptions()
23  {
24  /*
25  to do: general
26  m_options.addInt("gluingDataDegree","Polynomial degree of the gluing data space", p-1 );
27  m_options.addInt("gluingDataSmoothness","Regularity of the gluing data space", p-2 );
28  m_options.addSwitch("info","Print debug information", false );
29  m_options.addSwitch("plot","Print debug information", false );
30  */
31  }
32 
33  template<short_t d,class T>
34  void gsC1SurfSpline<d,T>::init()
35  {
36  // Check requirements
37  for (size_t p=0; p!=m_multiBasis.nBases(); p++)
38  {
39  gsTensorBSplineBasis<d, T> * basis_patch = dynamic_cast<gsTensorBSplineBasis<d, T> *>(&m_patches.basis(p));
40  index_t degree;
41  for (short_t dd = 0; dd!=d; dd++)
42  {
43  degree = basis_patch->component(dd).knots().degree();
44  GISMO_ENSURE((index_t)(basis_patch->component(dd).knots().size()-2*(degree+1))>=(index_t)(5-degree),"For a degree="<<degree<<" basis, the knot vector should at least have "<<5-degree<<" inner knots, but now it has "<<basis_patch->component(dd).knots().size()-2*(degree+1)<<" inner knots.");
45  }
46 
47  // regularity check (r=p-2)
48  // check for AS??
49  }
50 
51  // Fix orientation of each patch
52  m_patches.fixOrientation();
53 
54  m_bases.clear();
55  m_bases.reserve(m_patches.nPatches()); // For each Patch
56  for (size_t np = 0; np < m_patches.nPatches(); np++)
57  {
58  // gsContainerBasisBase
59  gsContainerBasis<d,T> containerBasis(1); // for 9 subspaces and 4 helper Basis
60  m_bases.push_back(containerBasis);
61  }
62 
63 
64  // Create interior spline space
65  for (size_t np = 0; np < m_patches.nPatches(); np++)
66  {
67  gsTensorBSplineBasis<d, T> basis_patch = dynamic_cast<gsTensorBSplineBasis<d, T> &>(m_multiBasis.basis(np));
68  //gsInfo << "Basis Patch: " << basis_patch.component(0).knots().asMatrix() << "\n";
69  m_bases[np].setBasis(0, basis_patch); // Inner
70  }
71 
72  index_t row_dofs = 0;
73  // Inner basis
74  for (size_t np = 0; np < m_patches.nPatches(); np++)
75  {
76  index_t dim_u = m_bases[np].piece(0).component(0).size();
77  index_t dim_v = m_bases[np].piece(0).component(1).size();
78  row_dofs += (dim_u - 4) * (dim_v - 4);
79  }
80 
81  // Interfaces
82  for (size_t numInt = 0; numInt < m_patches.interfaces().size(); numInt++)
83  {
84  index_t dir = m_patches.interfaces()[numInt].first().m_index < 3 ? 1 : 0;
85  gsBSplineBasis<T> basis_edge = dynamic_cast<gsBSplineBasis<T> &>(m_multiBasis.basis(m_patches.interfaces()[numInt].first().patch).component(dir)); // If the interface matches!!!
86 
87  gsBSplineBasis<T> basis_plus(basis_edge);
88  basis_plus.elevateContinuity(1);
89 
90  gsBSplineBasis<T> basis_minus(basis_edge);
91  basis_minus.degreeReduce(1);
92 
93  index_t numDofs = basis_plus.size() + basis_minus.size() - 10;
94  row_dofs += numDofs;
95  }
96 
97  // Boundary Edges
98  for (size_t numBdy = 0; numBdy < m_patches.boundaries().size(); numBdy++)
99  {
100  const patchSide &bit = m_patches.boundaries()[numBdy];
101 
102  index_t patch_1 = bit.patch;
103  index_t side_1 = bit.side().index();
104 
105  index_t dir = side_1 < 3 ? 1 : 0;
106  gsBSplineBasis<T> basis_edge = dynamic_cast<gsBSplineBasis<T> &>(m_multiBasis.basis(patch_1).component(dir)); // If the interface matches!!!
107 
108  gsBSplineBasis<T> basis_plus(basis_edge);
109  basis_plus.elevateContinuity(1);
110 
111  gsBSplineBasis<T> basis_minus(basis_edge);
112  basis_minus.degreeReduce(1);
113 
114  index_t numDofs = basis_plus.size() + basis_minus.size() - 10;
115  row_dofs += numDofs;
116  }
117 
118  // Vertices
119  for (size_t numVer = 0; numVer < m_patches.vertices().size(); numVer++)
120  {
121  row_dofs += 6;
122  }
123 
124 
125  m_matrix.clear();
126  index_t dim_col = 0;
127  for (size_t i = 0; i < m_bases.size(); i++)
128  {
129  dim_col += m_bases[i].size();
130  }
131 
132  m_matrix.resize(row_dofs, dim_col);
133  const index_t nz = 7*row_dofs; // TODO
134  m_matrix.reserve(nz);
135 
136 // gsInfo << m_multiBasis << "\n";
137 // for (index_t np = 0; np < m_patches.nPatches(); np++)
138 // gsInfo << "Basis " << np << " Size: " << m_multiBasis.basis(np).size() << "\n";
139 // gsInfo << "Mat dim: (" << row_dofs << " : " << dim_col << ")\n";
140  }
141 
142 
143  template<short_t d,class T>
144  void gsC1SurfSpline<d,T>::compute()
145  {
146  std::vector<gsEigen::Triplet<T,index_t>> tripletList;
147  // Compute Inner Basis functions
148  index_t shift_row = 0, shift_col = 0;
149  for(size_t np = 0; np < m_patches.nPatches(); ++np)
150  {
151  index_t dim_u = m_bases[np].piece(0).component(0).size();
152  index_t dim_v = m_bases[np].piece(0).component(1).size();
153 
154  index_t row_i = 0;
155  for (index_t j = 2; j < dim_v-2; ++j)
156  for (index_t i = 2; i < dim_u-2; ++i)
157  {
158  tripletList.push_back(gsEigen::Triplet<T,index_t>(shift_row + row_i, shift_col + j*dim_u+i,1));
159  ++row_i;
160  }
161  shift_row += row_i;
162  shift_col += m_bases[np].size();
163  }
164 
165  // Interfaces
166  for (size_t numInt = 0; numInt < m_patches.interfaces().size(); numInt++)
167  {
168  gsC1SurfEdge<d,T> smoothC1Edge(m_patches,m_patches.interfaces()[numInt]);
169  smoothC1Edge.computeG1InterfaceBasis();
170  std::vector<gsMultiPatch<T>> basisEdge = smoothC1Edge.getBasis();
171 
172  //gsWriteParaview(basisEdge[0].patch(0),"test_1",2000);
173 
174  const boundaryInterface & item = m_patches.interfaces()[numInt];
175 
176  index_t patch_1 = item.first().patch;
177  index_t patch_2 = item.second().patch;
178 
179  index_t begin_col = 0, end_col = 0, shift_col = 0;
180  for (index_t np = 0; np < patch_1; ++np)
181  shift_col += m_bases[np].size();
182 
183  end_col += m_bases[patch_1].piece(0).size();
184  for (size_t ii = 0; ii < basisEdge[0].nPatches(); ++ii)
185  {
186  index_t jj = 0;
187  for (index_t j = begin_col; j < end_col; ++j, ++jj)
188  if (basisEdge[0].patch(ii).coef(jj, 0) * basisEdge[0].patch(ii).coef(jj, 0) > 1e-25)
189  tripletList.push_back(gsEigen::Triplet<T,index_t>(shift_row + ii, shift_col + j,basisEdge[0].patch(ii).coef(jj, 0)));
190  }
191 
192  begin_col = 0, end_col = 0, shift_col = 0;
193  for (index_t np = 0; np < patch_2; ++np)
194  shift_col += m_bases[np].size();
195 
196  end_col += m_bases[patch_2].piece(0).size();
197 
198  for (size_t ii = 0; ii < basisEdge[1].nPatches(); ++ii)
199  {
200  index_t jj = 0;
201  for (index_t j = begin_col; j < end_col; ++j, ++jj)
202  if (basisEdge[1].patch(ii).coef(jj, 0) * basisEdge[1].patch(ii).coef(jj, 0) > 1e-25)
203  tripletList.push_back(gsEigen::Triplet<T,index_t>(shift_row + ii, shift_col + j,basisEdge[1].patch(ii).coef(jj, 0)));
204  }
205 
206  shift_row += basisEdge[0].nPatches();
207 
208  }
209  // Compute Edge Basis functions
210  for (size_t numBdy = 0; numBdy < m_patches.boundaries().size(); numBdy++)
211  {
212 
213  const patchSide & bit = m_patches.boundaries()[numBdy];
214 
215  index_t patch_1 = bit.patch;
216  index_t side_1 = bit.side().index();
217 
218  gsC1SurfEdge<d,T> smoothC1Edge(m_patches,bit);
219  smoothC1Edge.computeG1BoundaryBasis(side_1);
220  std::vector<gsMultiPatch<T>> basisEdge = smoothC1Edge.getBasis();
221 
222  index_t begin_col = 0, end_col = 0, shift_col = 0;
223  for (index_t np = 0; np < patch_1; ++np)
224  shift_col += m_bases[np].size();
225 
226  end_col += m_bases[patch_1].piece(0).size();
227  for (size_t ii = 0; ii < basisEdge[0].nPatches(); ++ii)
228  {
229  index_t jj = 0;
230  for (index_t j = begin_col; j < end_col; ++j, ++jj)
231  if (basisEdge[0].patch(ii).coef(jj, 0) * basisEdge[0].patch(ii).coef(jj, 0) > 1e-25)
232  tripletList.push_back(gsEigen::Triplet<T,index_t>(shift_row + ii, shift_col + j,basisEdge[0].patch(ii).coef(jj, 0)));
233  }
234 
235  shift_row += basisEdge[0].nPatches();
236  }
237  // Compute Vertex Basis functions
238  for (size_t numVer = 0; numVer < m_patches.vertices().size(); numVer++)
239  {
240  std::vector<patchCorner> allcornerLists = m_patches.vertices()[numVer];
241  std::vector<index_t> patchIndex;
242  std::vector<index_t> vertIndex;
243  for (size_t j = 0; j < allcornerLists.size(); j++)
244  {
245  patchIndex.push_back(allcornerLists[j].patch);
246  vertIndex.push_back(allcornerLists[j].m_index);
247  }
248 
249  gsC1SurfVertex<d,T> smoothC1Vertex(m_patches, patchIndex, vertIndex);
250  smoothC1Vertex.computeG1InternalVertexBasis();
251  std::vector<gsMultiPatch<T>> basisVertex = smoothC1Vertex.getBasis();
252 
253  for(size_t pInd=0; pInd < patchIndex.size(); pInd++)
254  {
255  index_t begin_col = 0, end_col = 0, shift_col = 0;
256  for (index_t np = 0; np < patchIndex[pInd]; ++np)
257  shift_col += m_bases[np].size();
258 
259  end_col += m_bases[patchIndex[pInd]].piece(0).size();
260  for (size_t ii = 0; ii < basisVertex[pInd].nPatches(); ++ii)
261  {
262  index_t jj = 0;
263  for (index_t j = begin_col; j < end_col; ++j, ++jj)
264  if (basisVertex[pInd].patch(ii).coef(jj, 0) * basisVertex[pInd].patch(ii).coef(jj, 0) > 1e-25)
265  tripletList.push_back(gsEigen::Triplet<T,index_t>(shift_row + ii, shift_col + j,basisVertex[pInd].patch(ii).coef(jj, 0)));
266  }
267  }
268  shift_row += 6;
269  }
270  m_matrix.setFromTriplets(tripletList.begin(),tripletList.end());
271  m_matrix.makeCompressed();
272  }
273 
274 
275 } // namespace gismo
Struct which represents a certain side of a patch.
Definition: gsBoundary.h:231
#define short_t
Definition: gsConfig.h:35
#define index_t
Definition: gsConfig.h:32
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
A tensor product B-spline basis.
Definition: gsTensorBSplineBasis.h:36
A univariate B-spline basis.
Definition: gsBSplineBasis.h:694
patchSide & second()
second, returns the second patchSide of this interface
Definition: gsBoundary.h:782
Struct which represents an interface between two patches.
Definition: gsBoundary.h:649
short_t index() const
Returns the index (as specified in boundary::side) of the box side.
Definition: gsBoundary.h:140
const Basis_t & component(short_t dir) const
For a tensor product basis, return the (const) 1-d basis for the i-th parameter component.
Definition: gsTensorBSplineBasis.h:202
index_t patch
The index of the patch.
Definition: gsBoundary.h:234
Creates the (approx) C1 Edge space.
patchSide & first()
first, returns the first patchSide of this interface
Definition: gsBoundary.h:776
Creates the (approx.) C1 Vertex space.