G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsBiharmonicAssembler2.h
Go to the documentation of this file.
1
14#pragma once
15
17
18namespace gismo
19{
20
21template <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
#define gsInfo
Definition gsDebug.h:43
Generic expressions helper.
EIGEN_STRONG_INLINE meas_expr< T > meas(const gsGeometryMap< T > &G)
The measure of a geometry map.
Definition gsExpressions.h:4555
EIGEN_STRONG_INLINE onormal_expr< T > nv(const gsGeometryMap< T > &u)
The (outer pointing) boundary normal of a geometry map.
Definition gsExpressions.h:4506
The G+Smo namespace, containing all definitions for the library.
@ dirichlet
Dirichlet type.
Definition gsBoundaryConditions.h:31
@ neumann
Neumann type.
Definition gsBoundaryConditions.h:33
@ laplace
Laplace type, e.g. \Delta u = g.
Definition gsBoundaryConditions.h:38