G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsBiharmonicExprAssembler.hpp
1 
16 #pragma once
17 
22 #include <gsCore/gsFunctionExpr.h>
23 #include <gsCore/gsBasis.h>
25 
26 #ifdef gsSpectra_ENABLED
27 #include <gsSpectra/gsSpectra.h>
28 #endif
29 
30 namespace gismo
31 {
32 
33 template <class T>
34 gsBiharmonicExprAssembler<T>::gsBiharmonicExprAssembler(const gsMultiPatch<T> & mp,
35  const gsMultiBasis<T> & mb,
36  const gsFunctionSet<T> & force,
37  const gsBoundaryConditions<T> & bcs
38  )
39 :
40 m_patches(mp),
41 m_basis(mb),
42 m_spaceBasis(&mb),
43 m_force(&force),
44 m_bcs(bcs)
45 {
46  this->_defaultOptions();
47  this->_getOptions();
48  this->_initialize();
49 };
50 
51 template <class T>
52 gsBiharmonicExprAssembler<T>& gsBiharmonicExprAssembler<T>::operator=( const gsBiharmonicExprAssembler& other )
53 {
54  if (this!=&other)
55  {
56  m_penalty=other.m_penalty;
57  m_lambda=other.m_lambda;
58  m_second=other.m_second;
59  m_continuity=other.m_continuity;
60 
61  m_patches=other.m_patches;
62  m_basis=other.m_basis;
63  m_spaceBasis=other.m_spaceBasis;
64  m_bcs=other.m_bcs;
65  m_force=other.m_force;
66 
67  m_options=other.m_options;
68 
69  // To do: make copy constructor for the gsExprAssembler
70  m_assembler.setIntegrationElements(m_basis);
71  m_assembler.setOptions(m_options);
72  }
73  return *this;
74 }
75 
76 template <class T>
77 gsBiharmonicExprAssembler<T>& gsBiharmonicExprAssembler<T>::operator=( gsBiharmonicExprAssembler&& other )
78 {
79  m_penalty=give(other.m_penalty);
80  m_lambda=give(other.m_lambda);
81  m_second=give(other.m_second);
82  m_continuity=give(other.m_continuity);
83 
84  m_patches=give(other.m_patches);
85  m_basis=give(other.m_basis);
86  m_spaceBasis=give(other.m_spaceBasis);
87  m_bcs=give(other.m_bcs);
88  m_force=give(other.m_force);
89 
90  m_options=give(other.m_options);
91 
92  // To do: make copy constructor for the gsExprAssembler
93  m_assembler.setIntegrationElements(m_basis);
94  m_assembler.setOptions(m_options);
95  return *this;
96 }
97 
98 template <class T>
99 void gsBiharmonicExprAssembler<T>::_defaultOptions()
100 {
101  m_options.addReal("PenaltyIfc","Parameter Nitsche's method",-1);
102  m_options.addReal("Lambda","Parameter for BC projection",1e-5);
103  m_options.addSwitch("Second","Assemble the second biharmonic equation",false);
104  m_options.addInt("Continuity","Set the continuity for the space",-1);
105  // Assembler options
106  gsOptionList assemblerOptions = m_assembler.defaultOptions().wrapIntoGroup("ExprAssembler");
107  m_options.update(assemblerOptions,gsOptionList::addIfUnknown);
108 }
109 
110 template <class T>
111 void gsBiharmonicExprAssembler<T>::_getOptions()
112 {
113  m_penalty = m_options.getReal("PenaltyIfc");
114  m_lambda = m_options.getReal("Lambda");
115  m_second = m_options.getSwitch("Second");
116  m_continuity = m_options.getInt("Continuity");
117 
118  GISMO_ENSURE(m_options.hasGroup("ExprAssembler"),"The option list does not contain options with the label 'ExprAssembler'!");
119  m_assembler.setOptions(m_options.getGroup("ExprAssembler"));
120 }
121 
122 template<class T>
123 void gsBiharmonicExprAssembler<T>::setOptions(gsOptionList & options)
124 {
125  m_options.update(options,gsOptionList::ignoreIfUnknown);
126  this->_getOptions();
127  this->_initialize();
128 }
129 
130 template <class T>
131 void gsBiharmonicExprAssembler<T>::_initialize()
132 {
133  // Elements used for numerical integration
134  m_assembler.setIntegrationElements(m_basis);
135  m_assembler.setOptions(m_options.getGroup("ExprAssembler"));
136 
137  GISMO_ASSERT(m_bcs.hasGeoMap(),"No geometry map was assigned to the boundary conditions. Use bc.setGeoMap to assign one!");
138 
139  m_assembler.getSpace(*m_spaceBasis, 1, 0); // last argument is the space ID
140 }
141 
142 template <class T>
143 void gsBiharmonicExprAssembler<T>::_setup(const expr::gsFeSpace<T> & u)
144 {
145  // Setup the mapper
146  gsDofMapper map;
147  _setMapperForBiharmonic(m_bcs, *m_spaceBasis, map);
148 
149  // Setup the system
150  u.setupMapper(map);
151  _getDirichletNeumannValuesL2Projection(m_patches, m_basis, m_bcs, *m_spaceBasis, u);
152 }
153 
154 template <class T>
155 void gsBiharmonicExprAssembler<T>::assembleMass()
156 {
157  m_assembler.cleanUp();
158  this->_getOptions();
159  this->_initialize();
160 
161  // Set the geometry map
162  geometryMap G = m_assembler.getMap(m_patches);
163 
164  // Set the discretization space
165  auto u = m_assembler.trialSpace(0);
166 
167  // Setup the mapper
168  this->_setup(u);
169 
170  // Initialize the system
171  m_assembler.initSystem();
172 
173  // Compute the system matrix and right-hand side
174  m_assembler.assemble(u * u.tr() * meas(G));
175 }
176 
177 template <class T>
178 void gsBiharmonicExprAssembler<T>::assemble()
179 {
180  m_assembler.cleanUp();
181  this->_getOptions();
182  this->_initialize();
183 
184  // Set the geometry map
185  geometryMap G = m_assembler.getMap(m_patches);
186 
187  // Set the source term
188  auto ff = m_assembler.getCoeff(*m_force, G);
189 
190  // Set the discretization space
191  auto u = m_assembler.trialSpace(0);
192 
193  // Setup the mapper
194  this->_setup(u);
195 
196  // Initialize the system
197  m_assembler.initSystem();
198 
199  // Compute the system matrix and right-hand side
200  m_assembler.assemble(ilapl(u, G) * ilapl(u, G).tr() * meas(G),u * ff * meas(G));
201 
202  // Enforce Laplace conditions to right-hand side
203  auto g_L = m_assembler.getBdrFunction(G); // Set the laplace bdy value
204  //auto g_L = A.getCoeff(laplace, G);
205  m_assembler.assembleBdr(m_bcs.get("Laplace"), (igrad(u, G) * nv(G)) * g_L.tr() );
206 
207  // Optionally, assemble Nitsche
208  if (m_continuity>0)
209  {
210  gsMatrix<T> mu_interfaces;
211  if (m_penalty == -1)
212  _computeStabilityParameter(m_patches, m_basis, mu_interfaces);
213 
214  index_t i = 0;
215  for ( typename gsMultiPatch<T>::const_iiterator it = m_patches.iBegin(); it != m_patches.iEnd(); ++it, ++i)
216  {
217  T stab = 4 * ( m_basis.maxCwiseDegree() + m_basis.dim() ) * ( m_basis.maxCwiseDegree() + 1 );
218  T m_h = m_basis.basis(0).getMinCellLength(); // m_basis.basis(0).getMinCellLength();
219  T mu = 2 * stab / m_h;
220  T alpha = 1;
221 
222  //mu = penalty_init == -1.0 ? mu : penalty_init / m_h;
223  if (m_penalty == -1)
224  mu = mu_interfaces(i,0) / m_h;
225  else
226  mu = m_penalty / m_h;
227 
228  std::vector<boundaryInterface> iFace;
229  iFace.push_back(*it);
230  m_assembler.assembleIfc(iFace,
231  //B11
232  -alpha * 0.5 * igrad(u.left(), G) * nv(G.left()).normalized() *
233  (ilapl(u.left(), G)).tr() * nv(G.left()).norm(),
234  -alpha * 0.5 *
235  (igrad(u.left(), G) * nv(G.left()).normalized() * (ilapl(u.left(), G)).tr()).tr() *
236  nv(G.left()).norm(),
237  //B12
238  -alpha * 0.5 * igrad(u.left(), G.left()) * nv(G.left()).normalized() *
239  (ilapl(u.right(), G.right())).tr() * nv(G.left()).norm(),
240  -alpha * 0.5 * (igrad(u.left(), G.left()) * nv(G.left()).normalized() *
241  (ilapl(u.right(), G.right())).tr()).tr() * nv(G.left()).norm(),
242  //B21
243  alpha * 0.5 * igrad(u.right(), G.right()) * nv(G.left()).normalized() *
244  (ilapl(u.left(), G.left())).tr() * nv(G.left()).norm(),
245  alpha * 0.5 * (igrad(u.right(), G.right()) * nv(G.left()).normalized() *
246  (ilapl(u.left(), G.left())).tr()).tr() * nv(G.left()).norm(),
247  //B22
248  alpha * 0.5 * igrad(u.right(), G.right()) * nv(G.left()).normalized() *
249  (ilapl(u.right(), G.right())).tr() * nv(G.left()).norm(),
250  alpha * 0.5 * (igrad(u.right(), G.right()) * nv(G.left()).normalized() *
251  (ilapl(u.right(), G.right())).tr()).tr() * nv(G.left()).norm(),
252 
253  // E11
254  mu * igrad(u.left(), G.left()) * nv(G.left()).normalized() *
255  (igrad(u.left(), G.left()) * nv(G.left()).normalized()).tr() * nv(G.left()).norm(),
256  //-E12
257  -mu * (igrad(u.left(), G.left()) * nv(G.left()).normalized()) *
258  (igrad(u.right(), G.right()) * nv(G.left()).normalized()).tr() * nv(G.left()).norm(),
259  //-E21
260  -mu * (igrad(u.right(), G.right()) * nv(G.left()).normalized()) *
261  (igrad(u.left(), G.left()) * nv(G.left()).normalized()).tr() * nv(G.left()).norm(),
262  // E22
263  mu * igrad(u.right(), G.right()) * nv(G.left()).normalized() *
264  (igrad(u.right(), G.right()) * nv(G.left()).normalized()).tr() * nv(G.left()).norm()
265  );
266 
267  if (m_continuity>1)
268  gsDebug<<"Put here the terms for continuity 1\n";
269  }
270  }
271 }
272 
273 
274 template <class T>
275 void gsBiharmonicExprAssembler<T>::assembleRHS()
276 {
277  m_assembler.cleanUp();
278  this->_getOptions();
279  this->_initialize();
280 
281  // Set the geometry map
282  geometryMap G = m_assembler.getMap(m_patches);
283 
284  // Set the source term
285  auto ff = m_assembler.getCoeff(*m_force, G);
286 
287  // Set the discretization space
288  auto u = m_assembler.trialSpace(0);
289 
290  // Setup the mapper
291  this->_setup(u);
292 
293  // Initialize the system
294  m_assembler.initVector(1);
295 
296  // Compute the system matrix and right-hand side
297  m_assembler.assemble(u * ff * meas(G));
298 
299  // Enforce Laplace conditions to right-hand side
300  auto g_L = m_assembler.getBdrFunction(G); // Set the laplace bdy value
301  //auto g_L = A.getCoeff(laplace, G);
302  m_assembler.assembleBdr(m_bcs.get("Laplace"), (igrad(u, G) * nv(G)) * g_L.tr() );
303 }
304 
305 template <class T>
306 void gsBiharmonicExprAssembler<T>::assembleLHS()
307 {
308  m_assembler.cleanUp();
309  this->_getOptions();
310  this->_initialize();
311 
312  // Set the geometry map
313  geometryMap G = m_assembler.getMap(m_patches);
314 
315  // Set the discretization space
316  auto u = m_assembler.trialSpace(0);
317 
318  // Setup the mapper
319  this->_setup(u);
320 
321  // Initialize the system
322  m_assembler.initMatrix();
323 
324  // Compute the system matrix and right-hand side
325  m_assembler.assemble(ilapl(u, G) * ilapl(u, G).tr() * meas(G));
326 
327  // Optionally, assemble Nitsche
328  if (m_continuity>0)
329  {
330  gsMatrix<T> mu_interfaces;
331  if (m_penalty == -1)
332  _computeStabilityParameter(m_patches, m_basis, mu_interfaces);
333 
334  index_t i = 0;
335  for ( typename gsMultiPatch<T>::const_iiterator it = m_patches.iBegin(); it != m_patches.iEnd(); ++it, ++i)
336  {
337  T stab = 4 * ( m_basis.maxCwiseDegree() + m_basis.dim() ) * ( m_basis.maxCwiseDegree() + 1 );
338  T m_h = m_basis.basis(0).getMinCellLength(); // m_basis.basis(0).getMinCellLength();
339  T mu = 2 * stab / m_h;
340  T alpha = 1;
341 
342  //mu = penalty_init == -1.0 ? mu : penalty_init / m_h;
343  if (m_penalty == -1)
344  mu = mu_interfaces(i,0) / m_h;
345  else
346  mu = m_penalty / m_h;
347 
348  std::vector<boundaryInterface> iFace;
349  iFace.push_back(*it);
350  m_assembler.assembleIfc(iFace,
351  //B11
352  -alpha * 0.5 * igrad(u.left(), G) * nv(G.left()).normalized() *
353  (ilapl(u.left(), G)).tr() * nv(G.left()).norm(),
354  -alpha * 0.5 *
355  (igrad(u.left(), G) * nv(G.left()).normalized() * (ilapl(u.left(), G)).tr()).tr() *
356  nv(G.left()).norm(),
357  //B12
358  -alpha * 0.5 * igrad(u.left(), G.left()) * nv(G.left()).normalized() *
359  (ilapl(u.right(), G.right())).tr() * nv(G.left()).norm(),
360  -alpha * 0.5 * (igrad(u.left(), G.left()) * nv(G.left()).normalized() *
361  (ilapl(u.right(), G.right())).tr()).tr() * nv(G.left()).norm(),
362  //B21
363  alpha * 0.5 * igrad(u.right(), G.right()) * nv(G.left()).normalized() *
364  (ilapl(u.left(), G.left())).tr() * nv(G.left()).norm(),
365  alpha * 0.5 * (igrad(u.right(), G.right()) * nv(G.left()).normalized() *
366  (ilapl(u.left(), G.left())).tr()).tr() * nv(G.left()).norm(),
367  //B22
368  alpha * 0.5 * igrad(u.right(), G.right()) * nv(G.left()).normalized() *
369  (ilapl(u.right(), G.right())).tr() * nv(G.left()).norm(),
370  alpha * 0.5 * (igrad(u.right(), G.right()) * nv(G.left()).normalized() *
371  (ilapl(u.right(), G.right())).tr()).tr() * nv(G.left()).norm(),
372 
373  // E11
374  mu * igrad(u.left(), G.left()) * nv(G.left()).normalized() *
375  (igrad(u.left(), G.left()) * nv(G.left()).normalized()).tr() * nv(G.left()).norm(),
376  //-E12
377  -mu * (igrad(u.left(), G.left()) * nv(G.left()).normalized()) *
378  (igrad(u.right(), G.right()) * nv(G.left()).normalized()).tr() * nv(G.left()).norm(),
379  //-E21
380  -mu * (igrad(u.right(), G.right()) * nv(G.left()).normalized()) *
381  (igrad(u.left(), G.left()) * nv(G.left()).normalized()).tr() * nv(G.left()).norm(),
382  // E22
383  mu * igrad(u.right(), G.right()) * nv(G.left()).normalized() *
384  (igrad(u.right(), G.right()) * nv(G.left()).normalized()).tr() * nv(G.left()).norm()
385  );
386 
387  if (m_continuity>1)
388  gsDebug<<"Put here the terms for continuity 1\n";
389  }
390  }
391 }
392 
393 template <class T>
394 void gsBiharmonicExprAssembler<T>::constructSolution(gsMatrix<T> & solVector)
395 {
396  auto u = m_assembler.trialSpace(0);
397  auto u_sol = m_assembler.getSolution(u, solVector);
398 
399  if (const gsMappedBasis<2,T> * bb2 = dynamic_cast<const gsMappedBasis<2,T> *>(m_spaceBasis))
400  {
401  u_sol.extract(m_mspline);
402  }
403  else
404  {
405  u_sol.extract(m_sol);
406  }
407 
408 }
409 
410 template <class T>
411 typename gsFunctionSet<T>::Ptr gsBiharmonicExprAssembler<T>::getSolution() const
412 {
413  if (const gsMappedBasis<2,T> * bb2 = dynamic_cast<const gsMappedBasis<2,T> *>(m_spaceBasis))
414  {
415  return memory::make_shared_not_owned(static_cast<gsFunctionSet<T>*>(&m_mspline));
416  }
417  else
418  {
419  return memory::make_shared_not_owned(static_cast<gsFunctionSet<T>*>(&m_sol));
420  }
421 }
422 
423 template <class T>
424 T gsBiharmonicExprAssembler<T>::l2error(gsMatrix<T> & solVector, const gsFunctionSet<T> & exact)
425 {
426  auto u = m_assembler.trialSpace(0);
427  auto u_sol = m_assembler.getSolution(u, solVector);
428  geometryMap G = m_assembler.getMap(m_patches);
429 
430  gsExprEvaluator<T> ev(m_assembler);
431  auto u_ex = ev.getVariable(exact, G);
432 
433  T l2err= math::sqrt( ev.integral( (u_ex - u_sol).sqNorm() * meas(G) ) );
434  return l2err;
435 }
436 
437 template <class T>
438 T gsBiharmonicExprAssembler<T>::h1error(gsMatrix<T> & solVector, const gsFunctionSet<T> & exact)
439 {
440  geometryMap G = m_assembler.getMap(m_patches);
441  auto u = m_assembler.trialSpace(0);
442  auto u_sol = m_assembler.getSolution(u, solVector);
443 
444  gsExprEvaluator<T> ev(m_assembler);
445  auto u_ex = ev.getVariable(exact, G);
446 
447  T l2err = math::sqrt( ev.integral( (u_ex - u_sol).sqNorm() * meas(G) ) ); // / ev.integral(f.sqNorm()*meas(G)) );
448  T h1err = l2err +
449  math::sqrt(ev.integral( ( igrad(u_ex) - igrad(u_sol,G) ).sqNorm() * meas(G) ));
450  return h1err;
451 }
452 
453 template <class T>
454 T gsBiharmonicExprAssembler<T>::h2error(gsMatrix<T> & solVector, const gsFunctionSet<T> & exact)
455 {
456  geometryMap G = m_assembler.getMap(m_patches);
457  auto u = m_assembler.trialSpace(0);
458  auto u_sol = m_assembler.getSolution(u, solVector);
459 
460  gsExprEvaluator<T> ev(m_assembler);
461  auto u_ex = ev.getVariable(exact, G);
462 
463  T l2err = math::sqrt( ev.integral( (u_ex - u_sol).sqNorm() * meas(G) ) ); // / ev.integral(f.sqNorm()*meas(G)) );
464  T h1err = l2err +
465  math::sqrt(ev.integral( ( igrad(u_ex) - igrad(u_sol,G) ).sqNorm() * meas(G) ));
466  T h2err = h1err +
467  math::sqrt(ev.integral( ( ihess(u_ex) - ihess(u_sol,G) ).sqNorm() * meas(G) )); // /ev.integral( ihess(f).sqNorm()*meas(G) )
468  return h2err;
469 }
470 
471 
472 template <class T>
473 std::tuple<T,T,T> gsBiharmonicExprAssembler<T>::errors(gsMatrix<T> & solVector, const gsFunctionSet<T> & exact)
474 {
475  geometryMap G = m_assembler.getMap(m_patches);
476  auto u = m_assembler.trialSpace(0);
477  auto u_sol = m_assembler.getSolution(u, solVector);
478 
479  gsExprEvaluator<T> ev(m_assembler);
480  auto u_ex = ev.getVariable(exact, G);
481 
482  T l2err = math::sqrt( ev.integral( (u_ex - u_sol).sqNorm() * meas(G) ) ); // / ev.integral(f.sqNorm()*meas(G)) );
483  T h1err = l2err +
484  math::sqrt(ev.integral( ( igrad(u_ex) - igrad(u_sol,G) ).sqNorm() * meas(G) ));
485  T h2err = h1err +
486  math::sqrt(ev.integral( ( ihess(u_ex) - ihess(u_sol,G) ).sqNorm() * meas(G) )); // /ev.integral( ihess(f).sqNorm()*meas(G) )
487  return std::make_tuple(l2err,h1err,h2err);
488 }
489 
490 template <class T>
491 T gsBiharmonicExprAssembler<T>::interfaceError(gsMatrix<T> & solVector, const gsFunctionSet<T> & exact)
492 {
493  GISMO_UNUSED(exact);
494  if (const gsMappedBasis<2,T> * bb2 = dynamic_cast<const gsMappedBasis<2,T> *>(m_spaceBasis))
495  {
496  geometryMap G = m_assembler.getMap(m_patches);
497  auto u = m_assembler.trialSpace(0);
498  auto u_sol = m_assembler.getSolution(u, solVector);
499 
500  gsMatrix<T> solFull;
501  u_sol.extractFull(solFull);
502  gsMappedSpline<2, T> mappedSpline(*bb2, solFull);
503 
504  auto ms_sol = m_assembler.getCoeff(mappedSpline);
505 
506  gsExprEvaluator<T> ev(m_assembler);
507  T IFaceErr = math::sqrt(ev.integralInterface(((igrad(ms_sol.left(), G.left()) -
508  igrad(ms_sol.right(), G.right())) *
509  nv(G).normalized()).sqNorm() * meas(G)));
510 
511  return IFaceErr;
512  }
513  else
514  {
515  geometryMap G = m_assembler.getMap(m_patches);
516  auto u = m_assembler.trialSpace(0);
517  auto u_sol = m_assembler.getSolution(u, solVector);
518 
519  gsMultiPatch<T> sol;
520  u_sol.extract(sol);
521 
522  auto ms_sol = m_assembler.getCoeff(sol);
523 
524  gsExprEvaluator<T> ev(m_assembler);
525  T IFaceErr = math::sqrt(ev.integralInterface(((igrad(ms_sol.left(), G.left()) -
526  igrad(ms_sol.right(), G.right())) *
527  nv(G).normalized()).sqNorm() * meas(G)));
528 
529  return IFaceErr;
530  }
531 }
532 
533 template <class T>
534 void gsBiharmonicExprAssembler<T>::setSpaceBasis(const gsFunctionSet<T> & spaceBasis)
535 {
536  m_spaceBasis = &spaceBasis;
537  this->_getOptions();
538  this->_initialize();
539 }
540 
541 template <class T>
542 void gsBiharmonicExprAssembler<T>::_setMapperForBiharmonic( const gsBoundaryConditions<T> & bc,
543  const gsFunctionSet<T> & spaceBasis,
544  gsDofMapper & mapper)
545 {
546  if (const gsMappedBasis<2,T> * bb2 = dynamic_cast<const gsMappedBasis<2,T> *>(&spaceBasis))
547  {
548  mapper.setIdentity(bb2->nPatches(), bb2->size(), 1);
549 
550  gsMatrix<index_t> bnd;
551  for (typename gsBoundaryConditions<T>::const_iterator it = bc.begin("Dirichlet"); it != bc.end("Dirichlet"); ++it)
552  {
553  bnd = bb2->basis(it->ps.patch).boundary(it->ps.side());
554  mapper.markBoundary(it->ps.patch, bnd, 0);
555  }
556 
557  for (typename gsBoundaryConditions<T>::const_iterator it = bc.begin("Neumann"); it != bc.end("Neumann"); ++it)
558  {
559  bnd = bb2->basis(it->ps.patch).boundaryOffset(it->ps.side(),1);
560  mapper.markBoundary(it->ps.patch, bnd, 0);
561  }
562  mapper.finalize();
563  }
564  else if (const gsMultiBasis<T> * dbasis = dynamic_cast<const gsMultiBasis<T> *>(&spaceBasis))
565  {
566  mapper.init(*dbasis);
567 
568  for (gsBoxTopology::const_iiterator it = dbasis->topology().iBegin();
569  it != dbasis->topology().iEnd(); ++it) // C^0 at the interface
570  {
571  dbasis->matchInterface(*it, mapper);
572  }
573 
574  gsMatrix<index_t> bnd;
575  for (typename gsBoundaryConditions<T>::const_iterator
576  it = bc.begin("Dirichlet"); it != bc.end("Dirichlet"); ++it)
577  {
578  bnd = dbasis->basis(it->ps.patch).boundary(it->ps.side());
579  mapper.markBoundary(it->ps.patch, bnd, 0);
580  }
581 
582  for (typename gsBoundaryConditions<T>::const_iterator
583  it = bc.begin("Neumann"); it != bc.end("Neumann"); ++it)
584  {
585  bnd = dbasis->basis(it->ps.patch).boundaryOffset(it->ps.side(),1);
586  mapper.markBoundary(it->ps.patch, bnd, 0);
587  }
588  mapper.finalize();
589  }
590  else
591  {
592  GISMO_ERROR("bb2 is not a gsMappedBasis");
593  }
594 };
595 
596 
597 template <class T>
598 void gsBiharmonicExprAssembler<T>::_getDirichletNeumannValuesL2Projection(
599  const gsMultiPatch<T> & mp,
600  const gsMultiBasis<T> & dbasis,
601  const gsBoundaryConditions<T> & bc,
602  const gsFunctionSet<T> & spaceBasis,
603  const expr::gsFeSpace<T> & u
604  )
605 {
606  gsDebugVar(bc.dirichletSides().size());
607  gsDebugVar(bc.neumannSides().size());
608 
609  if (bc.dirichletSides().size()==0 && bc.neumannSides().size()==0)
610  return;
611  if (const gsMappedBasis<2,T> * bb2 = dynamic_cast<const gsMappedBasis<2,T> *>(&spaceBasis))
612  {
613  const gsDofMapper & mapper = u.mapper();
614 
615  gsMatrix<index_t> bnd = mapper.findFree(mapper.numPatches()-1);
616  gsDofMapper mapperBdy;
617  mapperBdy.setIdentity(bb2->nPatches(), bb2->size(), 1); // bb2->nPatches() == 1
618  mapperBdy.markBoundary(0, bnd, 0);
619  mapperBdy.finalize();
620 
621  gsExprAssembler<T> A(1,1);
622  A.setIntegrationElements(dbasis);
623 
624  auto G = A.getMap(mp);
625  auto uu = A.getSpace(*bb2);
626  auto g_bdy = A.getBdrFunction(G);
627 
628  uu.setupMapper(mapperBdy);
629  gsMatrix<T> & fixedDofs_A = const_cast<expr::gsFeSpace<T>&>(uu).fixedPart();
630  fixedDofs_A.setZero( uu.mapper().boundarySize(), 1 );
631 
632  A.initSystem();
633  A.assembleBdr(bc.get("Dirichlet"), uu * uu.tr() * meas(G));
634  A.assembleBdr(bc.get("Dirichlet"), uu * g_bdy * meas(G));
635  A.assembleBdr(bc.get("Neumann"),m_lambda * (igrad(uu, G) * nv(G).normalized()) * (igrad(uu, G) * nv(G).normalized()).tr() * meas(G));
636  A.assembleBdr(bc.get("Neumann"),m_lambda * (igrad(uu, G) * nv(G).normalized()) * (g_bdy.tr() * nv(G).normalized()) * meas(G));
637 
638  typename gsSparseSolver<T>::SimplicialLDLT solver;
639  solver.compute( A.matrix() );
640  gsMatrix<T> & fixedDofs = const_cast<expr::gsFeSpace<T>& >(u).fixedPart();
641  fixedDofs = solver.solve(A.rhs());
642  }
643  else if (dynamic_cast<const gsMultiBasis<T> *>(&spaceBasis)) // assumes spacebasis==dbasis
644  {
645  gsDofMapper mapper = u.mapper();
646  gsDofMapper mapperBdy(dbasis, u.dim());
647  for (gsBoxTopology::const_iiterator it = dbasis.topology().iBegin();
648  it != dbasis.topology().iEnd(); ++it) // C^0 at the interface
649  {
650  dbasis.matchInterface(*it, mapperBdy);
651  }
652  for (index_t np = 0; np < mp.nPieces(); np++)
653  {
654  gsMatrix<index_t> bnd = mapper.findFree(np);
655  mapperBdy.markBoundary(np, bnd, 0);
656  }
657  mapperBdy.finalize();
658 
659  gsExprAssembler<T> A(1,1);
660  A.setIntegrationElements(dbasis);
661 
662  auto G = A.getMap(mp);
663  auto uu = A.getSpace(dbasis);
664  auto g_bdy = A.getBdrFunction(G);
665 
666  uu.setupMapper(mapperBdy);
667  gsMatrix<T> & fixedDofs_A = const_cast<expr::gsFeSpace<T>&>(uu).fixedPart();
668  fixedDofs_A.setZero( uu.mapper().boundarySize(), 1 );
669 
670  A.initSystem();
671  A.assembleBdr(bc.get("Dirichlet"), uu * uu.tr() * meas(G));
672  A.assembleBdr(bc.get("Dirichlet"), uu * g_bdy * meas(G));
673  A.assembleBdr(bc.get("Neumann"),
674  m_lambda * (igrad(uu, G) * nv(G).normalized()) * (igrad(uu, G) * nv(G).normalized()).tr() * meas(G));
675  A.assembleBdr(bc.get("Neumann"),
676  m_lambda * (igrad(uu, G) * nv(G).normalized()) * (g_bdy.tr() * nv(G).normalized()) * meas(G));
677 
678  typename gsSparseSolver<T>::SimplicialLDLT solver;
679  solver.compute( A.matrix() );
680  gsMatrix<T> & fixedDofs = const_cast<expr::gsFeSpace<T>& >(u).fixedPart();
681  gsMatrix<T> fixedDofs_temp = solver.solve(A.rhs());
682 
683  // Reordering the dofs of the boundary
684  fixedDofs.setZero(mapper.boundarySize(),1);
685  index_t sz = 0;
686  for (index_t np = 0; np < mp.nPieces(); np++)
687  {
688  gsMatrix<index_t> bnd = mapperBdy.findFree(np);
689  bnd.array() += sz;
690  for (index_t i = 0; i < bnd.rows(); i++)
691  {
692  index_t ii = mapperBdy.asVector()(bnd(i,0));
693  fixedDofs(mapper.global_to_bindex(mapper.asVector()(bnd(i,0))),0) = fixedDofs_temp(ii,0);
694  }
695  sz += mapperBdy.patchSize(np,0);
696  }
697  }
698  else
699  {
700  GISMO_ERROR("bb2 is not a gsMappedBasis");
701  }
702 };
703 
704 template <class T>
705 void gsBiharmonicExprAssembler<T>::_computeStabilityParameter(
706  const gsMultiPatch<T> & mp,
707  const gsMultiBasis<T> & dbasis,
708  gsMatrix<T> & mu_interfaces)
709 {
710  mu_interfaces.setZero(mp.nInterfaces(),1);
711 
712  index_t i = 0;
713  for ( typename gsMultiPatch<T>::const_iiterator it = mp.iBegin(); it != mp.iEnd(); ++it, ++i)
714  {
715  gsMultiPatch<T> mp_temp;
716  mp_temp.addPatch(mp.patch(it->first().patch));
717  mp_temp.addPatch(mp.patch(it->second().patch));
718  mp_temp.computeTopology();
719 
720  gsMultiBasis<T> dbasis_temp;
721  dbasis_temp.addBasis(dbasis.basis(it->first().patch).clone().release());
722  dbasis_temp.addBasis(dbasis.basis(it->second().patch).clone().release());
723 
724  gsBoundaryConditions<T> bc;
725 
726 // patchSide pS1 = mp_temp.interfaces()[0].first();
727 // patchSide pS2 = mp_temp.interfaces()[0].second();
728 //
729 //
730 // index_t side = pS1.index() < 3 ? (pS1.index() == 1 ? 2 : 1) : (pS1.index() == 3 ? 4 : 3);
731 // bc.addCondition(patchSide(pS1.patchIndex(), side), condition_type::dirichlet, 0);
732 //
733 // side = pS2.index() < 3 ? (pS2.index() == 1 ? 2 : 1) : (pS2.index() == 3 ? 4 : 3);
734 // bc.addCondition(patchSide(pS2.patchIndex(), side), condition_type::dirichlet, 0);
735 
736  // Make the Eigenvalue problem to a homogeneous one
737  for (typename gsMultiPatch<T>::const_biterator bit = mp_temp.bBegin(); bit != mp_temp.bEnd(); ++bit)
738  bc.addCondition(*bit, condition_type::dirichlet, 0);
739 
740  gsExprAssembler<T> A2(1, 1), B2(1, 1);
741 
742  // Elements used for numerical integration
743  A2.setIntegrationElements(dbasis_temp);
744  B2.setIntegrationElements(dbasis_temp);
745 
746  // Set the geometry map
747  auto GA = A2.getMap(mp_temp);
748  auto GB = B2.getMap(mp_temp);
749 
750  // Set the discretization space
751  auto uA = A2.getSpace(dbasis_temp);
752  auto uB = B2.getSpace(dbasis_temp);
753 
754  uA.setup(bc, dirichlet::homogeneous, 0);
755  uB.setup(bc, dirichlet::homogeneous,0);
756  //uA.setup(0);
757  //uB.setup(0);
758 
759  A2.initSystem();
760  B2.initSystem();
761 
762  T c = 0.25;
763  A2.assembleIfc(mp_temp.interfaces(),
764  c * ilapl(uA.left(), GA.left()) * ilapl(uA.left(), GA.left()).tr() * nv(GA.left()).norm(),
765  c * ilapl(uA.left(), GA.left()) * ilapl(uA.right(), GA.right()).tr() * nv(GA.left()).norm(),
766  c * ilapl(uA.right(), GA.right()) * ilapl(uA.left(), GA.left()).tr() * nv(GA.left()).norm(),
767  c * ilapl(uA.right(), GA.right()) * ilapl(uA.right(), GA.right()).tr() * nv(GA.left()).norm());
768 
769  B2.assemble(ilapl(uB, GB) * ilapl(uB, GB).tr() * meas(GB));
770 
771  // TODO INSTABLE && SLOW
772  gsMatrix<T> AA = A2.matrix().toDense();
773  gsMatrix<T> BB = B2.matrix().toDense();
774 
775 #ifdef gsSpectra_ENABLED
776  gsSpectraGenSymSolver<gsSparseMatrix<T>,Spectra::GEigsMode::Cholesky> ges(A2.matrix(),B2.matrix(),1,10);
777  ges.compute(Spectra::SortRule::LargestMagn,1000,1e-6,Spectra::SortRule::LargestMagn);
778  T maxEV = ges.eigenvalues()(0,0);
779 #else
780  gsEigen::GeneralizedSelfAdjointEigenSolver<typename gsMatrix<T>::Base > ges(AA, BB);
781  T maxEV = ges.eigenvalues().array().maxCoeff();
782 #endif
783  T m_h = dbasis_temp.basis(0).getMinCellLength(); // dbasis.basis(0).getMinCellLength();
784  mu_interfaces(i,0) = 16.0 * m_h * maxEV;
785 /*
786  gsSparseSolver<T>::SimplicialLDLT sol;
787  sol.compute(B2.matrix());
788  gsSparseMatrix<T> R = sol.matrixU();
789  gsSparseMatrix<T> RT = sol.matrixL();
790  gsMatrix<T> AAA = RT.toDense().inverse() * AA * R.toDense().inverse();
791 
792  gsConjugateGradient<T> cg(AAA);
793 
794  cg.setCalcEigenvalues(true);
795  cg.setTolerance(1e-15);
796  cg.setMaxIterations(100000);
797 
798  gsMatrix<T> rhs, result;
799  rhs.setRandom( AAA.rows(), 1 );
800  result.setRandom( AAA.rows(), 1 );
801 
802  cg.solve(rhs,result);
803 
804  gsInfo << "Tol: " << cg.error() << "\n";
805  gsInfo << "Max it: " << cg.iterations() << "\n";
806 
807  gsMatrix<T> eigenvalues;
808  cg.getEigenvalues(eigenvalues);
809 
810  gsInfo << "Cond Number: " << eigenvalues.bottomRows(1)(0,0) << "\n";
811 */
812  }
813 }
814 
815 
816 }// namespace gismo
shared_ptr< T > make_shared_not_owned(const T *x)
Creates a shared pointer which does not eventually delete the underlying raw pointer. Usefull to refer to objects which should not be destroyed.
Definition: gsMemory.h:189
Provides declaration of FunctionExpr class.
Dirichlet type.
Definition: gsBoundaryConditions.h:31
#define gsDebug
Definition: gsDebug.h:61
Provides declaration of Basis abstract interface.
S give(S &x)
Definition: gsMemory.h:266
#define index_t
Definition: gsConfig.h:32
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
Provides declaration of Basis abstract interface.
EIGEN_STRONG_INLINE onormal_expr< T > nv(const gsGeometryMap< T > &u)
The (outer pointing) boundary normal of a geometry map.
Definition: gsExpressions.h:4508
Provides declaration of a gsPiecewiseFunction class.
Provides declaration of Basis abstract interface.
Provides assembler for a (planar) Biharmonic equation.
Header file for using Spectra extension.
#define GISMO_UNUSED(x)
Definition: gsDebug.h:112
Provides gsBoundaryConditions class.
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
EIGEN_STRONG_INLINE meas_expr< T > meas(const gsGeometryMap< T > &G)
The measure of a geometry map.
Definition: gsExpressions.h:4557