G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsC1SurfBasisEdge.h
1 
14 #pragma once
15 
16 #include <gsUnstructuredSplines/src/gsC1SurfGluingData.h>
17 #include <gsUnstructuredSplines/src/gsC1SurfVisitorBasisEdge.h>
18 
19 namespace gismo
20 {
21  template<class T, class bhVisitor = gsC1SurfVisitorBasisEdge<T>>
22  class gsC1SurfBasisEdge : public gsAssembler<T>
23  {
24  public:
25  typedef gsAssembler<T> Base;
26 
27  public:
28  gsC1SurfBasisEdge(const gsMultiPatch<T> & mp, // single patch
29  const gsMultiBasis<T> & basis, // single basis
30  index_t uv, // !!! 0 == u; 1 == v !!!
31  bool isBoundary,
32  gsC1SurfGluingData<T> gluingD)
33  : m_mp(mp), m_basis(basis), m_uv(uv), m_isBoundary(isBoundary), m_gD(gluingD)
34  {
35 
36  // Computing the G1 - basis function at the edge
37  gsBSplineBasis<T> basis_edge = dynamic_cast<gsBSplineBasis<T> &>(m_basis.basis(0).component(m_uv)); // 0 -> v, 1 -> u
38 
39  gsBSplineBasis<T> basis_plus(basis_edge);
40  basis_plus.elevateContinuity(1);
41  m_basis_plus = basis_plus;
42  //gsDebugVar(basis_plus.knots().asMatrix());
43 
44 
45  gsBSplineBasis<T> basis_minus(basis_edge);
46  basis_minus.degreeReduce(1);
47  m_basis_minus = basis_minus;
48  //gsDebugVar(basis_minus.knots().asMatrix());
49 
50  // Basis for the G1 basis
51  m_basis_g1 = m_basis.basis(0);
52 
53 // gsTensorBSplineBasis<2, T> basis_edge_ab = dynamic_cast<gsTensorBSplineBasis<2, T> &>(m_basis_g1.basis(0));
54 // gsInfo << "Basis edge 0: " << basis_edge_ab.component(0).knots().asMatrix() << "\n";
55 // gsInfo << "Basis edge 1: " << basis_edge_ab.component(1).knots().asMatrix() << "\n";
56  }
57 
58  // Computed the gluing data globally
59  void setG1BasisEdge(gsMultiPatch<T> & result);
60 
61  void refresh();
62  void assemble(index_t i, std::string typeBf); // i == number of bf
63  inline void apply(bhVisitor & visitor, index_t i, std::string typeBf); // i == number of bf
64  void solve();
65 
66  void constructSolution(const gsMatrix<T> & solVector,
67  gsMultiPatch<T> & result, short_t unk = 0) const;
68 
69  private:
70  // Avoid hidden overloads w.r.t. gsAssembler
71  void assemble()
73 
74  void assemble(const gsMultiPatch<T> & curSolution)
76 
77  protected:
78 
79  // Input
80  gsMultiPatch<T> m_mp;
81  gsMultiBasis<T> m_basis;
82  index_t m_uv;
83  bool m_isBoundary;
84 
85  // Gluing data
86  gsC1SurfGluingData<T> m_gD;
87 
88  // Basis for getting the G1 Basis
89  gsBSplineBasis<T> m_basis_plus;
90  gsBSplineBasis<T> m_basis_minus;
91 
92  // Basis for the G1 Basis
93  gsMultiBasis<T> m_basis_g1;
94 
95  // Basis for Integration
96  gsMultiBasis<T> m_geo;
97 
98  // For Dirichlet boundary
99  using Base::m_ddof;
100  using Base::m_system;
101 
102 
103  }; // class gsG1BasisEdge
104 
105  template <class T, class bhVisitor>
106  void gsC1SurfBasisEdge<T,bhVisitor>::setG1BasisEdge(gsMultiPatch<T> & result)
107  {
108  result.clear();
109 
110  index_t n_plus = m_basis_plus.size();
111  index_t n_minus = m_basis_minus.size();
112 
113  gsMultiPatch<T> g1EdgeBasis;
114  index_t bfID_init = 3;
115 
116  for (index_t bfID = bfID_init; bfID < n_plus - bfID_init; bfID++) // first 3 and last 3 bf are eliminated
117  {
118  m_geo = m_basis_g1; // Basis for Integration
119 
120  refresh();
121 
122  assemble(bfID,"plus"); // i == number of bf
123 
124  typename gsSparseSolver<T>::SimplicialLDLT solver;
125 // typename gsSparseSolver<T>::LU solver;
126  gsMatrix<T> sol;
127  solver.compute(m_system.matrix());
128  sol = solver.solve(m_system.rhs());
129 
130  constructSolution(sol,g1EdgeBasis);
131  }
132  bfID_init = 2;
133  for (index_t bfID = bfID_init; bfID < n_minus-bfID_init; bfID++) // first 2 and last 2 bf are eliminated
134  {
135 
136 
137  m_geo = m_basis_g1; // Basis for Integration
138 
139  refresh();
140 
141  assemble(bfID,"minus"); // i == number of bf
142 
143  typename gsSparseSolver<T>::SimplicialLDLT solver;
144 // typename gsSparseSolver<T>::LU solver;
145  gsMatrix<T> sol;
146  solver.compute(m_system.matrix());
147  sol = solver.solve(m_system.rhs());
148 
149  constructSolution(sol,g1EdgeBasis);
150  }
151 
152  result = g1EdgeBasis;
153  } // setG1BasisEdge
154 
155  template <class T, class bhVisitor>
156  void gsC1SurfBasisEdge<T,bhVisitor>::constructSolution(const gsMatrix<T> & solVector, gsMultiPatch<T> & result, short_t unk) const
157  {
158  GISMO_UNUSED(unk);
159 
160  // Dim is the same for all basis functions
161  const index_t dim = ( 0!=solVector.cols() ? solVector.cols() : m_ddof[0].cols() );
162 
163  gsMatrix<T> coeffs;
164  const gsDofMapper & mapper = m_system.colMapper(0); // unknown = 0
165 
166  // Reconstruct solution coefficients on patch p
167  index_t sz;
168  sz = m_basis.basis(0).size();
169 
170  coeffs.resize(sz, dim);
171 
172  for (index_t i = 0; i < sz; ++i)
173  {
174  if (mapper.is_free(i, 0)) // DoF value is in the solVector // 0 = unitPatch
175  {
176  coeffs.row(i) = solVector.row(mapper.index(i, 0));
177  }
178  else // eliminated DoF: fill with Dirichlet data
179  {
180  //gsInfo << "mapper index dirichlet: " << m_ddof[unk].row( mapper.bindex(i, p) ).head(dim) << "\n";
181  coeffs.row(i) = m_ddof[0].row( mapper.bindex(i, 0) ).head(dim); // = 0
182  }
183  }
184  result.addPatch(m_basis_g1.basis(0).makeGeometry(give(coeffs)));
185 
186  }
187 
188  template <class T, class bhVisitor>
189  void gsC1SurfBasisEdge<T,bhVisitor>::refresh()
190  {
191  // 1. Obtain a map from basis functions to matrix columns and rows
192  gsDofMapper map(m_basis.basis(0));
193 
194  gsMatrix<index_t> act;
195 
196  for (index_t i = 2; i < m_basis.basis(0).component(1-m_uv).size(); i++) // only the first two u/v-columns are Dofs (0/1)
197  {
198  act = m_basis.basis(0).boundaryOffset(m_uv == 0 ? 3 : 1, i); // WEST
199  map.markBoundary(0, act); // Patch 0
200  }
201 
202  map.finalize();
203 
204  // 2. Create the sparse system
205  m_system = gsSparseSystem<T>(map);
206 
207  } // refresh()
208 
209  template <class T, class bhVisitor>
210  void gsC1SurfBasisEdge<T,bhVisitor>::assemble(index_t bfID, std::string typeBf)
211  {
212  // Reserve sparse system
213  const index_t nz = gsAssemblerOptions::numColNz(m_basis[0],2,1,0.333333);
214  m_system.reserve(nz, 1);
215 
216  if(m_ddof.size()==0)
217  m_ddof.resize(1); // 0,1
218 
219  const gsDofMapper & map = m_system.colMapper(0); // Map same for every functions
220 
221  m_ddof[0].setZero(map.boundarySize(), 1 );
222 
223  // Assemble volume integrals
224  bhVisitor visitor;
225  apply(visitor, bfID, typeBf); // basis function i
226 
227  m_system.matrix().makeCompressed();
228 
229  } // assemble()
230 
231  template <class T, class bhVisitor>
232  void gsC1SurfBasisEdge<T,bhVisitor>::apply(bhVisitor & visitor, index_t bf_index, std::string typeBf)
233  {
234 #pragma omp parallel
235  {
236 
237  gsQuadRule<T> quRule ; // Quadrature rule
238  gsMatrix<T> quNodes ; // Temp variable for mapped nodes
239  gsVector<T> quWeights; // Temp variable for mapped weights
240 
241  bhVisitor
242 #ifdef _OPENMP
243  // Create thread-private visitor
244  visitor_(visitor);
245  const int tid = omp_get_thread_num();
246  const int nt = omp_get_num_threads();
247 #else
248  &visitor_ = visitor;
249 #endif
250 
251  gsBasis<T> & basis_g1 = m_basis_g1.basis(0); // basis for construction
252 
253  // Same for all patches
254  gsBasis<T> & basis_geo = m_basis.basis(0).component(1-m_uv);
255  gsBasis<T> & basis_plus = m_basis_plus;
256  gsBasis<T> & basis_minus = m_basis_minus;
257 
258  // Initialize reference quadrature rule and visitor data
259  visitor_.initialize(basis_g1, quRule);
260 
261  const gsGeometry<T> & patch = m_mp.patch(0);
262 
263  // Initialize domain element iterator
264  typename gsBasis<T>::domainIter domIt = m_geo.basis(0).makeDomainIterator(boundary::none);
265 
266 #ifdef _OPENMP
267  for ( domIt->next(tid); domIt->good(); domIt->next(nt) )
268 #else
269  for (; domIt->good(); domIt->next() )
270 #endif
271  {
272  // Map the Quadrature rule to the element
273  quRule.mapTo( domIt->lowerCorner(), domIt->upperCorner(), quNodes, quWeights );
274 
275  // Perform required evaluations on the quadrature nodes
276  visitor_.evaluate(bf_index, typeBf, basis_g1, basis_geo, basis_plus, basis_minus, patch, quNodes, m_uv, m_gD, m_isBoundary);
277 
278  // Assemble on element
279  visitor_.assemble(*domIt, quWeights);
280 
281  // Push to global matrix and right-hand side vector
282 #pragma omp critical(localToGlobal)
283  visitor_.localToGlobal(0, m_ddof, m_system); // omp_locks inside // patchIndex == 0
284  }
285  }//omp parallel
286  } // apply
287 
288 } // namespace gismo
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
Class representing a reference quadrature rule.
Definition: gsQuadRule.h:28
void clear()
Clear (delete) all patches.
Definition: gsMultiPatch.h:319
index_t boundarySize() const
Returns the number of eliminated dofs.
Definition: gsDofMapper.h:457
#define GISMO_NO_IMPLEMENTATION
Definition: gsDebug.h:129
#define short_t
Definition: gsConfig.h:35
bool is_free(index_t i, index_t k=0, index_t c=0) const
Returns true if local dof i of patch k is not eliminated.
Definition: gsDofMapper.h:382
S give(S &x)
Definition: gsMemory.h:266
#define index_t
Definition: gsConfig.h:32
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
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
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
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition: gsMultiPatch.h:33
index_t bindex(index_t i, index_t k=0, index_t c=0) const
Returns the boundary index of local dof i of patch k.
Definition: gsDofMapper.h:334
gsSparseSystem< T > m_system
Global sparse linear system.
Definition: gsAssembler.h:290
virtual void mapTo(const gsVector< T > &lower, const gsVector< T > &upper, gsMatrix< T > &nodes, gsVector< T > &weights) const
Maps quadrature rule (i.e., points and weights) from the reference domain to an element.
Definition: gsQuadRule.h:177
std::vector< gsMatrix< T > > m_ddof
Definition: gsAssembler.h:295
#define GISMO_UNUSED(x)
Definition: gsDebug.h:112
The assembler class provides generic routines for volume and boundary integrals that are used for for...
Definition: gsAssembler.h:265
virtual void constructSolution(const gsMatrix< T > &solVector, gsMultiPatch< T > &result, const gsVector< index_t > &unknowns) const
Construct solution from computed solution vector for a set of unknowns. The result is a vectorfield...
Definition: gsAssembler.hpp:584
A basis represents a family of scalar basis functions defined over a common parameter domain...
Definition: gsBasis.h:78
void apply(ElementVisitor &visitor, size_t patchIndex=0, boxSide side=boundary::none)
Generic assembly routine for volume or boundary integrals.
Definition: gsAssembler.h:668