G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsApproxC1Vertex.h
Go to the documentation of this file.
1 
14 #pragma once
15 
17 
20 #include <gsUnstructuredSplines/src/gsApproxC1GluingData.h>
21 
22 
23 namespace gismo {
24 template<short_t d, class T>
25 class gsApproxC1Vertex
26 {
27 
28 private:
29  typedef gsContainerBasis<d, T> Basis;
30  typedef typename std::vector<Basis> BasisContainer;
31  typedef typename std::vector<gsPatchReparameterized<d,T>> C1AuxPatchContainer;
32 
34  typedef memory::shared_ptr<gsApproxC1Vertex> Ptr;
35 
37  typedef memory::unique_ptr<gsApproxC1Vertex> uPtr;
38 
39 
40 public:
42  ~gsApproxC1Vertex() { }
43 
44 
45  gsApproxC1Vertex(gsMultiPatch<T> & mp,
46  BasisContainer & bases,
47  const std::vector<size_t> & patchesAroundVertex,
48  const std::vector<size_t> & vertexIndices,
49  const index_t & numVer,
50  const gsOptionList & optionList)
51  : m_mp(mp), m_bases(bases), m_patchesAroundVertex(patchesAroundVertex),
52  m_vertexIndices(vertexIndices), m_optionList(optionList)
53  {
54  m_auxPatches.clear();
55  basisVertexResult.clear();
56 
57  for(size_t i = 0; i < m_patchesAroundVertex.size(); i++)
58  {
59  index_t patch_1 = m_patchesAroundVertex[i];
60 
61  m_auxPatches.push_back(gsPatchReparameterized<d,T>(m_mp.patch(patch_1), m_bases[patch_1]));
62  }
63 
64  reparametrizeVertexPatches();
65 
66  // Compute Sigma
67  T sigma = computeSigma(m_vertexIndices);
68  gsMatrix<T> Phi(6, 6);
69  Phi.setIdentity();
70 
71  Phi.col(1) *= sigma;
72  Phi.col(2) *= sigma;
73  Phi.col(3) *= sigma * sigma;
74  Phi.col(4) *= sigma * sigma;
75  Phi.col(5) *= sigma * sigma;
76 
77  gsMultiPatch<T> rotPatch;
78  if (m_auxPatches[0].getPatchRotated().parDim() + 1 == m_auxPatches[0].getPatchRotated().targetDim()) // Surface
79  {
80  gsMatrix<T> zero;
81  zero.setZero(2, 1);
82  gsMatrix<T> Jk = m_auxPatches[0].getPatchRotated().jacobian(zero);
83  gsMatrix<T> G = Jk.transpose() * Jk; // Symmetric
84  gsMatrix<T> G_inv = G.cramerInverse(); // Symmetric
85 
86  gsMatrix<T> geoMapDeriv1 = m_auxPatches[0].getPatchRotated()
87  .deriv(zero); // First derivative of the geometric mapping with respect to the parameter coordinates
88  gsMatrix<T> geoMapDeriv2 = m_auxPatches[0].getPatchRotated()
89  .deriv2(zero); // Second derivative of the geometric mapping with respect to the parameter coordinates
90 
91  //Computing the normal vector to the tangent plane along the boundary curve
92  gsVector<T> n(3);
93  n.setZero();
94  n(0) = Jk(1,0)*Jk(2,1)-Jk(2,0)*Jk(1,1);
95  n(1) = Jk(2,0)*Jk(0,1)-Jk(0,0)*Jk(2,1);
96  n(2) = Jk(0,0)*Jk(1,1)-Jk(1,0)*Jk(0,1);
97 
98  gsVector<T> z(3);
99  z.setZero();
100  z(2) = 1.0;
101 
102  gsVector<T> rotVec(3);
103  rotVec.setZero(3);
104  rotVec(0) = n(1,0)*z(2,0)-n(2,0)*z(1,0);
105  rotVec(1) = n(2,0)*z(0,0)-n(0,0)*z(2,0);
106  rotVec(2) = n(0,0)*z(1,0)-n(1,0)*z(0,0);
107 
108  T cos_t = (n.dot(z))/ (n.norm() * z.norm());
109  T sin_t = rotVec.norm() / (n.norm() * z.norm());
110 
111 // Rotation matrix
112  gsMatrix<T> R(3, 3);
113  R.setZero();
114 // Row 0
115  R(0, 0) = cos_t + rotVec.x() * rotVec.x() * (1 - cos_t);
116  R(0, 1) = rotVec.x() * rotVec.y() * (1 - cos_t) - rotVec.z() * sin_t;
117  R(0, 2) = rotVec.x() * rotVec.z() * (1 - cos_t) + rotVec.y() * sin_t;
118 // Row 1
119  R(1, 0) = rotVec.x() * rotVec.y() * (1 - cos_t) + rotVec.z() * sin_t;
120  R(1, 1) = cos_t + rotVec.y() * rotVec.y() * (1 - cos_t);
121  R(1, 2) = rotVec.y() * rotVec.z() * (1 - cos_t) - rotVec.x() * sin_t;
122 // Row 2
123  R(2, 0) = rotVec.x() * rotVec.z() * (1 - cos_t) - rotVec.y() * sin_t;
124  R(2, 1) = rotVec.y() * rotVec.z() * (1 - cos_t) + rotVec.x() * sin_t;
125  R(2, 2) = cos_t + rotVec.z() * rotVec.z() * (1 - cos_t);
126 
127  for (size_t np = 0; np < m_auxPatches.size(); np++)
128  {
129  gsMatrix<T> coeffPatch = m_auxPatches[np].getPatchRotated().coefs();
130 
131  for (index_t i = 0; i < coeffPatch.rows(); i++)
132  {
133  coeffPatch.row(i) =
134  (coeffPatch.row(i) - coeffPatch.row(0)) * R.transpose() + coeffPatch.row(0);
135  }
136 
137  rotPatch.addPatch(m_auxPatches[np].getPatchRotated());
138  rotPatch.patch(np).setCoefs(coeffPatch);
139  }
140 
141  Phi.resize(13, 6);
142  Phi.setZero();
143  Phi(0, 0) = 1;
144  Phi(1, 1) = sigma;
145  Phi(2, 2) = sigma;
146  Phi(4, 3) = sigma * sigma;
147  Phi(5, 4) = sigma * sigma;
148  Phi(7, 4) = sigma * sigma;
149  Phi(8, 5) = sigma * sigma;
150  }
151  else
152  {
153  for (size_t np = 0; np < m_auxPatches.size(); np++)
154  rotPatch.addPatch(m_auxPatches[np].getPatchRotated());
155  }
156 
157  // TODO fix the gluing Data stuff
158  for(size_t i = 0; i < m_patchesAroundVertex.size(); i++)
159  {
160  C1AuxPatchContainer auxPatchSingle;
161  auxPatchSingle.push_back(m_auxPatches[i]);
162 
163  std::vector<patchSide> containingSides; // global sides plus index
164  patchCorner pC(m_patchesAroundVertex[i], m_vertexIndices[i]);
165  pC.getContainingSides(d, containingSides);
166 
167 // std::vector<bool> isInterface(2);
168 // isInterface[0] = m_mp.isInterface(patchSide(m_patchesAroundVertex[i], containingSides.at(0).side()));
169 // isInterface[1] = m_mp.isInterface(patchSide(m_patchesAroundVertex[i], containingSides.at(1).side()));
170 
171  if (containingSides.at(0).side() < 3) // If isInterface_1 == v, then switch
172  {
173  patchSide side_temp = containingSides[0];
174  containingSides[0] = containingSides[1];
175  containingSides[1] = side_temp;
176 
177 // bool isInterface_tmp = isInterface[0];
178 // isInterface[0] = isInterface[1];
179 // isInterface[1] = isInterface_tmp;
180  }
181 
182  std::vector<bool> isInterface(2);
183  isInterface[0] = m_mp.isInterface(patchSide(m_patchesAroundVertex[i], containingSides.at(0).side())); // global interface at u
184  isInterface[1] = m_mp.isInterface(patchSide(m_patchesAroundVertex[i], containingSides.at(1).side())); // global interface at v
185 
186  //Problem setup
187  std::vector<gsBSpline<T>> alpha, beta;
188  std::vector<gsBSplineBasis<T>> basis_plus, basis_minus;
189 
190  std::vector<bool> kindOfEdge;
191 
192  alpha.resize(2); beta.resize(2); basis_plus.resize(2); basis_minus.resize(2);
193  kindOfEdge.resize(2);
194 
195  gsTensorBSplineBasis<d, T> basis = dynamic_cast<const gsTensorBSplineBasis<d, T> &>(auxPatchSingle[0].getBasisRotated().piece(0));
196  gsTensorBSplineBasis<d, T> basis_pm = dynamic_cast<const gsTensorBSplineBasis<d, T> &>(auxPatchSingle[0].getBasisRotated().piece(0));
197  for (size_t dir = 0; dir < containingSides.size(); ++dir)
198  {
199  //index_t localdir = auxPatchSingle[0].getMapIndex(containingSides[dir].index()) < 3 ? 1 : 0;
200  if (isInterface[dir])
201  {
202  patchSide result;
203  m_mp.getNeighbour(containingSides[dir], result);
204 
205  index_t patch2 = -1;
206  for (size_t i_tmp = 0; i_tmp < m_patchesAroundVertex.size(); i_tmp++)
207  if (m_patchesAroundVertex[i_tmp] == size_t(result.patch))
208  patch2 = i_tmp;
209 
210  GISMO_ASSERT(patch2 > -1, "Something went wrong");
211 
212  gsTensorBSplineBasis<d, T> basis2 = dynamic_cast<const gsTensorBSplineBasis<d, T> &>(m_auxPatches[patch2].getBasisRotated().piece(
213  0));
214  index_t dir_1 = auxPatchSingle[0].getMapIndex(containingSides[dir].side()) < 3 ? 1 : 0;
215  index_t dir_2 = m_auxPatches[patch2].getMapIndex(result.side().index()) < 3 ? 1 : 0;
216  if (basis.component(dir_1).numElements() > basis2.component(dir_2).numElements())
217  basis_pm.component(dir_1) = basis2.component(dir_2);
218 
219  }
220  }
221 
222  // Compute Gluing data
223  // Stored locally
224  gsApproxC1GluingData<d, T> approxGluingData(auxPatchSingle, m_optionList, containingSides, isInterface, basis_pm);
225 
226  //gsGeometry<T> & geo = auxPatchSingle[0].getPatchRotated();
227  gsGeometry<T> & geo = rotPatch.patch(i);
228  gsMultiBasis<T> initSpace(auxPatchSingle[0].getBasisRotated().piece(0));
229  for (size_t dir = 0; dir < containingSides.size(); ++dir)
230  {
231  index_t localdir = auxPatchSingle[0].getMapIndex(containingSides[dir].index()) < 3 ? 1 : 0;
232 
233  if (isInterface[dir])
234  {
235  alpha[localdir] = approxGluingData.alphaS(localdir);
236  beta[localdir] = approxGluingData.betaS(localdir);
237  }
238  // Store the isInterface locally
239  kindOfEdge[localdir] = isInterface[dir];
240 
241  gsBSplineBasis<T> b_plus, b_minus;
242  if (isInterface[dir])
243  {
244  // TODO FIX
245  createPlusSpace(geo, basis_pm, localdir, b_plus);
246  createMinusSpace(geo, basis_pm, localdir, b_minus);
247  //createPlusSpace(geo, initSpace.basis(0), dir, b_plus);
248  //createMinusSpace(geo, initSpace.basis(0), dir, b_minus);
249  }
250  else
251  {
252  createPlusSpace(geo, initSpace.basis(0), localdir, b_plus);
253  createMinusSpace(geo, initSpace.basis(0), localdir, b_minus);
254  }
255 
256 // gsDebugVar(b_plus);
257 // gsDebugVar(b_minus);
258 // gsDebugVar(dir);
259 // gsDebugVar(isInterface[localdir]);
260  basis_plus[localdir] = b_plus;
261  basis_minus[localdir] = b_minus;
262  }
263 
264  typename gsSparseSolver<T>::SimplicialLDLT solver;
265  gsExprAssembler<T> A(1, 1);
266 
267  // Elements used for numerical integration
268  gsMultiBasis<T> vertexSpace(auxPatchSingle[0].getBasisRotated().piece(m_vertexIndices[i] + 4));
269  A.setIntegrationElements(vertexSpace);
270  gsExprEvaluator<T> ev(A);
271 
272  // Set the discretization space
273  auto u = A.getSpace(vertexSpace);
274 
275  // Create Mapper
276  gsDofMapper map(vertexSpace);
277  if (!m_optionList.getSwitch("interpolation"))
278  {
279  gsMatrix<index_t> act;
280  for (index_t dir = 0; dir < vertexSpace.basis(0).domainDim(); dir++)
281  for (index_t i = 3 * vertexSpace.basis(0).degree(dir) + 1; i < vertexSpace.basis(0).component(
282  1 - dir).size(); i++) // only the first two u/v-columns are Dofs (0/1)
283  {
284  act = vertexSpace.basis(0).boundaryOffset(dir == 0 ? 3 : 1, i); // WEST
285  //map.markBoundary(0, act); // Patch 0
286  }
287  map.finalize();
288 
289  u.setupMapper(map);
290 
291  gsMatrix<T> &fixedDofs = const_cast<expr::gsFeSpace<T> &>(u).fixedPart();
292  fixedDofs.setZero(u.mapper().boundarySize(), 1);
293 
294  A.initSystem();
295  A.assemble(u * u.tr());
296  solver.compute(A.matrix());
297  }
298 
299  // Create Basis functions
300  gsMultiPatch<T> result_1;
301  for (index_t bfID = 0; bfID < 6; bfID++)
302  {
303  gsVertexBasis<T> vertexBasis(geo, basis_pm, alpha, beta, basis_plus, basis_minus, Phi,
304  kindOfEdge, bfID);
305  if (m_optionList.getSwitch("interpolation"))
306  {
307  //gsQuasiInterpolate<T>::Schoenberg(edgeSpace.basis(0), traceBasis, sol);
308  //result.addPatch(edgeSpace.basis(0).interpolateAtAnchors(give(values)));
309  gsMatrix<T> anchors = vertexSpace.basis(0).anchors();
310  gsMatrix<T> values = vertexBasis.eval(anchors);
311  result_1.addPatch(vertexSpace.basis(0).interpolateAtAnchors(give(values)));
312  }
313  else
314  {
315  A.initVector();
316 
317  auto aa = A.getCoeff(vertexBasis);
318  A.assemble(u * aa);
319 
320  gsMatrix<T> solVector = solver.solve(A.rhs());
321 
322  auto u_sol = A.getSolution(u, solVector);
323  gsMatrix<T> sol;
324  u_sol.extract(sol);
325 
326  result_1.addPatch(vertexSpace.basis(0).makeGeometry(give(sol)));
327  }
328  }
329  //Problem setup end
330 
331  // Store temporary
332  basisVertexResult.push_back(result_1);
333  }
334 
335  gsMultiPatch<T> temp_mp;
336  for (size_t j = 0; j < m_patchesAroundVertex.size(); j++)
337  temp_mp.addPatch(m_mp.patch(m_patchesAroundVertex[j]));
338  temp_mp.computeTopology();
339 
340  if (m_patchesAroundVertex.size() != temp_mp.interfaces().size()) // No internal vertex
341  {
342  computeKernel();
343 
344  for(size_t i = 0; i < m_patchesAroundVertex.size(); i++)
345  m_auxPatches[i].parametrizeBasisBack(basisVertexResult[i]); // parametrizeBasisBack
346  }
347  else // Internal vertex
348  {
349  for(size_t i = 0; i < m_patchesAroundVertex.size(); i++)
350  m_auxPatches[i].parametrizeBasisBack(basisVertexResult[i]); // parametrizeBasisBack
351  }
352 /*
353  if (m_optionList.getSwitch("plot"))
354  {
355  std::string fileName;
356  std::string basename = "VerticesBasisFunctions" + util::to_string(numVer);
357  gsParaviewCollection collection(basename);
358 
359  for (size_t np = 0; np < m_patchesAroundVertex.size(); ++np)
360  {
361  if (basisVertexResult.size() != 0)
362  for (size_t i = 0; i < basisVertexResult[np].nPatches(); ++i)
363  {
364  fileName = basename + "_" + util::to_string(np) + "_" + util::to_string(i);
365  gsField<T> temp_field(m_mp.patch(m_patchesAroundVertex[np]), basisVertexResult[np].patch(i));
366  gsWriteParaview(temp_field, fileName, 5000);
367  collection.addTimestep(fileName, i, "0.vts");
368 
369  }
370  }
371  collection.save();
372  //if (m_patchesAroundVertex.size() == 2)
373  // gsWriteParaview(basisVertexResult[0], "vertex_basis", 20000);
374  }
375 */
376  }
377 
378  void reparametrizeVertexPatches();
379 
380  void checkOrientation(size_t i);
381 
382  T computeSigma(const std::vector<size_t> & vertexIndices);
383 
384  void computeKernel();
385 
386  std::vector<gsMultiPatch<T>> getVertexBasis() { return basisVertexResult; }
387 
388 
389 protected:
390 
391  // Input
392  gsMultiPatch<T> & m_mp;
393  BasisContainer & m_bases;
394 
395  const std::vector<size_t> & m_patchesAroundVertex;
396  const std::vector<size_t> & m_vertexIndices;
397 
398  const gsOptionList & m_optionList;
399 
400  // Need for rotation, etc.
401  C1AuxPatchContainer m_auxPatches;
402 
403  // Store temp solution
404  std::vector<gsMultiPatch<T>> basisVertexResult;
405 
406 }; // gsApproxC1Vertex
407 
408 } // namespace gismo
409 
410 #ifndef GISMO_BUILD_LIB
411 #include GISMO_HPP_HEADER(gsApproxC1Vertex.hpp)
412 #endif
index_t addPatch(typename gsGeometry< T >::uPtr g)
Add a patch from a gsGeometry&lt;T&gt;::uPtr.
Definition: gsMultiPatch.hpp:210
Abstract base class representing a geometry map.
Definition: gsGeometry.h:92
Definition: gsExprAssembler.h:30
Struct which represents a certain side of a patch.
Definition: gsBoundary.h:231
Provides declaration of Basis abstract interface.
S give(S &x)
Definition: gsMemory.h:266
#define index_t
Definition: gsConfig.h:32
Reparametrize one Patch.
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
A univariate B-spline basis.
Definition: gsBSplineBasis.h:694
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
Provides declaration of Basis abstract interface. Similar to gsMultiBasis, but without topology...
Definition: gsDirichletValues.h:23
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition: gsMultiPatch.h:33
Generic evaluator of isogeometric expressions.
Definition: gsExprEvaluator.h:38
short_t index() const
Returns the index (as specified in boundary::side) of the box side.
Definition: gsBoundary.h:140
Class which holds a list of parameters/options, and provides easy access to them. ...
Definition: gsOptionList.h:32
const ifContainer & interfaces() const
Return the vector of interfaces.
Definition: gsBoxTopology.h:252
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
virtual const gsBasis< T > & basis() const =0
Returns a const reference to the basis of the geometry.
index_t patch
The index of the patch.
Definition: gsBoundary.h:234
bool computeTopology(T tol=1e-4, bool cornersOnly=false, bool tjunctions=false)
Attempt to compute interfaces and boundaries automatically.
Definition: gsMultiPatch.hpp:366