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