G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsBiharmonicAssembler2.h
Go to the documentation of this file.
1 
14 #pragma once
15 
17 
18 namespace gismo
19 {
20 
21 template <class T>
22  class gsBiharmonicAssembler2
23  {
24  public:
25 
27  gsBiharmonicAssembler2() { };
28 
29  gsBiharmonicAssembler2(gsMultiPatch<T> & mp,
30  gsMultiBasis<T> & mb,
31  bool & second = false)
32  : m_mp(mp), m_mb(mb)
33  {
34  gsFunctionExpr<>source("1*pi*pi*pi*pi*(4*cos(1*pi*x)*cos(1*pi*y) - cos(1*pi*x) - cos(1*pi*y))",2);
35  m_f.swap(source);
36  gsInfo << "Source function " << m_f << "\n";
37 
38  gsFunctionExpr<> solution("(cos(1*pi*x) - 1) * (cos(1*pi*y) - 1)",2);
39  m_ms.swap(solution);
40  gsInfo << "Exact function " << m_ms << "\n";
41 
42  gsBoundaryConditions<> bc;
43  for (gsMultiPatch<>::const_biterator bit = mp.bBegin(); bit != mp.bEnd(); ++bit)
44  {
45  // Laplace
46  gsFunctionExpr<> laplace ("-1*pi*pi*(2*cos(1*pi*x)*cos(1*pi*y) - cos(1*pi*x) - cos(1*pi*y))",2);
47 
48  // Neumann
49  gsFunctionExpr<> sol1der( "-1*pi*(cos(1*pi*y) - 1)*sin(1*pi*x)",
50  "-1*pi*(cos(1*pi*x) - 1)*sin(1*pi*y)", 2);
51 
52  bc.addCondition(*bit, condition_type::dirichlet, m_ms);
53  if (second)
54  bc.addCondition(*bit, condition_type::laplace, laplace);
55  else
56  bc.addCondition(*bit, condition_type::neumann, sol1der);
57  }
58  bc.setGeoMap(mp);
59  m_bc.swap(bc);
60  gsInfo << "Boundary conditions:\n" << m_bc << "\n";
61  };
62 
63  gsBiharmonicAssembler2(gsMultiPatch<T> & mp,
64  gsMultiBasis<T> & mb,
65  const gsBoundaryConditions<T> & bc,
66  const gsFunctionExpr<T> & f,
67  const gsFunctionExpr<T> & ms)
68  : m_mp(mp), m_mb(mb), m_bc(bc), m_f(f), m_ms(ms)
69  {
70 
71  };
72 
73 
74  public:
75 
76  void initialize()
77  {
78  // Expression Assembler (1x1 Block Matrix)
79  m_A = gsExprAssembler<real_t>(1,1);
80 
81  // Elements used for numerical integration
82  m_A.setIntegrationElements(m_mb);
83  m_ev = gsExprEvaluator<real_t>(m_A);
84  };
85 
86  void assemble(gsMappedBasis<2,T> & bb2)
87  {
88  // Set the geometry map
89  auto G = m_A.getMap(m_mp);
90 
91  // Set the source term
92  auto ff = m_A.getCoeff(m_f, G); // Laplace example
93 
94  // Set the discretization space
95  auto u = m_A.getSpace(bb2);
96 
97  // Solution vector and solution variable
98  gsMatrix<real_t> solVector;
99  auto u_sol = m_A.getSolution(u, solVector);
100 
101  // Setup the mapper
102  gsDofMapper map;
103  setMapperForBiharmonic(m_bc, bb2, map);
104 
105  // Setup the system
106  u.setupMapper(map);
107  gsDirichletNeumannValuesL2Projection(m_mp, m_mb, m_bc, bb2, u);
108 
109  // Initialize the system
110  m_A.initSystem();
111 
112  // Compute the system matrix and right-hand side
113  m_A.assemble(ilapl(u, G) * ilapl(u, G).tr() * meas(G),u * ff * meas(G));
114 
115  // Enforce Laplace conditions to right-hand side
116  auto g_L = m_A.getBdrFunction(G); // Set the laplace bdy value
117  //auto g_L = A.getCoeff(laplace, G);
118  m_A.assembleBdr(m_bc.get("Laplace"), (igrad(u, G) * nv(G)) * g_L.tr() );
119  };
120 
121  void solve()
122  {
123  gsSparseSolver<real_t>::SimplicialLDLT solver;
124  solver.compute( m_A.matrix() );
125  m_solVector = solver.solve(m_A.rhs());
126  };
127 
128  void computeError(gsMappedBasis<2,T> & bb2,
129  T & l2err,
130  T & h1err,
131  T & h2err)
132  {
133  // Set the geometry map
134  auto G = m_A.getMap(m_mp);
135 
136  auto u = m_A.getSpace(bb2);
137  auto u_sol = m_A.getSolution(u, m_solVector);
138 
139  // Recover manufactured solution
140  auto u_ex = m_ev.getVariable(m_ms, G);
141 
142  l2err = math::sqrt( m_ev.integral( (u_ex - u_sol).sqNorm() * meas(G) ) );
143  h1err = l2err + math::sqrt(m_ev.integral( ( igrad(u_ex) - igrad(u_sol,G) ).sqNorm() * meas(G) ));
144  h2err = h1err + math::sqrt(m_ev.integral( ( ihess(u_ex) - ihess(u_sol,G) ).sqNorm() * meas(G) ));
145  };
146 
147  T numDofs() { return m_A.numDofs(); };
148 
149  private:
150 
151  void setMapperForBiharmonic(gsBoundaryConditions<> & bc, gsMappedBasis<2,real_t> & bb2, gsDofMapper & mapper)
152  {
153  mapper.setIdentity(bb2.nPatches(), bb2.size(), 1);
154 
155  gsMatrix<index_t> bnd;
156  for (typename gsBoundaryConditions<real_t>::const_iterator
157  it = bc.begin("Dirichlet"); it != bc.end("Dirichlet"); ++it)
158  {
159  bnd = bb2.basis(it->ps.patch).boundary(it->ps.side());
160  mapper.markBoundary(it->ps.patch, bnd, 0);
161  }
162 
163  for (typename gsBoundaryConditions<real_t>::const_iterator
164  it = bc.begin("Neumann"); it != bc.end("Neumann"); ++it)
165  {
166  bnd = bb2.basis(it->ps.patch).boundaryOffset(it->ps.side(),1);
167  mapper.markBoundary(it->ps.patch, bnd, 0);
168  }
169  mapper.finalize();
170  };
171 
172  void gsDirichletNeumannValuesL2Projection(gsMultiPatch<> & mp,
173  gsMultiBasis<> & dbasis,
174  gsBoundaryConditions<> & bc,
175  gsMappedBasis<2,real_t> & bb2,
176  const expr::gsFeSpace<real_t> & u)
177  {
178  const gsDofMapper & mapper = u.mapper();
179 
180  gsMatrix<index_t> bnd = mapper.findFree(mapper.numPatches()-1);
181  gsDofMapper mapperBdy;
182  mapperBdy.setIdentity(bb2.nPatches(), bb2.size(), 1); // bb2.nPatches() == 1
183  mapperBdy.markBoundary(0, bnd, 0);
184  mapperBdy.finalize();
185 
186  gsExprAssembler<real_t> A(1,1);
187  A.setIntegrationElements(dbasis);
188 
189  auto G = A.getMap(mp);
190  auto uu = A.getSpace(bb2);
191  auto g_bdy = A.getBdrFunction(G);
192 
193  uu.setupMapper(mapperBdy);
194  gsMatrix<real_t> & fixedDofs_A = const_cast<expr::gsFeSpace<real_t>&>(uu).fixedPart();
195  fixedDofs_A.setZero( uu.mapper().boundarySize(), 1 );
196 
197  real_t lambda = 1e-5;
198 
199  A.initSystem();
200  A.assembleBdr(bc.get("Dirichlet"), uu * uu.tr() * meas(G));
201  A.assembleBdr(bc.get("Dirichlet"), uu * g_bdy * meas(G));
202  A.assembleBdr(bc.get("Neumann"),
203  lambda * (igrad(uu, G) * nv(G).normalized()) *
204  (igrad(uu, G) * nv(G).normalized()).tr() * meas(G));
205  A.assembleBdr(bc.get("Neumann"),
206  lambda * (igrad(uu, G) * nv(G).normalized()) * (g_bdy.tr() * nv(G).normalized()) * meas(G));
207 
208  gsSparseSolver<real_t>::SimplicialLDLT solver;
209  solver.compute( A.matrix() );
210  gsMatrix<real_t> & fixedDofs = const_cast<expr::gsFeSpace<real_t>& >(u).fixedPart();
211  fixedDofs = solver.solve(A.rhs());
212  };
213 
214  protected:
215 
216  gsMultiPatch<T> & m_mp;
217  gsMultiBasis<T> & m_mb;
218 
219  gsBoundaryConditions<T> m_bc;
220  gsFunctionExpr<T> m_f;
221  gsFunctionExpr<T> m_ms;
222 
223  gsExprAssembler<T> m_A;
224  gsExprEvaluator<T> m_ev;
225 
226  gsMatrix<T> m_solVector;
227 
228  }; // class gsBiharmonicAssembler2
229 } // namespace gismo
Neumann type.
Definition: gsBoundaryConditions.h:33
Laplace type, e.g. u = g.
Definition: gsBoundaryConditions.h:38
Dirichlet type.
Definition: gsBoundaryConditions.h:31
Generic expressions helper.
EIGEN_STRONG_INLINE onormal_expr< T > nv(const gsGeometryMap< T > &u)
The (outer pointing) boundary normal of a geometry map.
Definition: gsExpressions.h:4506
#define gsInfo
Definition: gsDebug.h:43
EIGEN_STRONG_INLINE meas_expr< T > meas(const gsGeometryMap< T > &G)
The measure of a geometry map.
Definition: gsExpressions.h:4555