MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
ex37.hpp
Go to the documentation of this file.
1// MFEM Example 37 - Serial/Parallel Shared Code
2
3#include "mfem.hpp"
4#include <fstream>
5#include <iostream>
6#include <functional>
7
8namespace mfem
9{
10
11/// @brief Inverse sigmoid function
13{
14 real_t tol = 1e-12;
15 x = std::min(std::max(tol,x), real_t(1.0)-tol);
16 return std::log(x/(1.0-x));
17}
18
19/// @brief Sigmoid function
21{
22 if (x >= 0)
23 {
24 return 1.0/(1.0+std::exp(-x));
25 }
26 else
27 {
28 return std::exp(x)/(1.0+std::exp(x));
29 }
30}
31
32/// @brief Derivative of sigmoid function
34{
35 real_t tmp = sigmoid(-x);
36 return tmp - std::pow(tmp,2);
37}
38
39/// @brief Returns f(u(x)) where u is a scalar GridFunction and f:R → R
41{
42protected:
43 std::function<real_t(const real_t)> fun; // f:R → R
44public:
49 std::function<real_t(const real_t)> fun_,
50 int comp=1)
51 :GridFunctionCoefficient(gf, comp),
52 fun(fun_) {}
53
54
56 const IntegrationPoint &ip) override
57 {
59 }
60 void SetFunction(std::function<real_t(const real_t)> fun_) { fun = fun_; }
61};
62
63
64/// @brief Returns f(u(x)) - f(v(x)) where u, v are scalar GridFunctions and f:R → R
66{
67protected:
70 std::function<real_t(const real_t)> fun; // f:R → R
71public:
78 const GridFunction *other_gf,
79 std::function<real_t(const real_t)> fun_,
80 int comp=1)
81 :GridFunctionCoefficient(gf, comp),
82 OtherGridF(other_gf),
84 fun(fun_) {}
85
87 const IntegrationPoint &ip) override
88 {
89 const real_t value1 = fun(GridFunctionCoefficient::Eval(T, ip));
90 const real_t value2 = fun(OtherGridF_cf.Eval(T, ip));
91 return value1 - value2;
92 }
93 void SetFunction(std::function<real_t(const real_t)> fun_) { fun = fun_; }
94};
95
96/// @brief Solid isotropic material penalization (SIMP) coefficient
98{
99protected:
104
105public:
107 real_t max_val_ = 1.0, real_t exponent_ = 3)
108 : rho_filter(rho_filter_), min_val(min_val_), max_val(max_val_),
109 exponent(exponent_) { }
110
112 {
113 real_t val = rho_filter->GetValue(T, ip);
114 real_t coeff = min_val + pow(val,exponent)*(max_val-min_val);
115 return coeff;
116 }
117};
118
119
120/// @brief Strain energy density coefficient
122{
123protected:
125 Coefficient * mu=nullptr;
126 GridFunction *u = nullptr; // displacement
127 GridFunction *rho_filter = nullptr; // filter density
128 DenseMatrix grad; // auxiliary matrix, used in Eval
131
132public:
134 GridFunction * u_, GridFunction * rho_filter_, real_t rho_min_=1e-6,
135 real_t exponent_ = 3.0)
136 : lambda(lambda_), mu(mu_), u(u_), rho_filter(rho_filter_),
137 exponent(exponent_), rho_min(rho_min_)
138 {
139 MFEM_ASSERT(rho_min_ >= 0.0, "rho_min must be >= 0");
140 MFEM_ASSERT(rho_min_ < 1.0, "rho_min must be < 1");
141 MFEM_ASSERT(u, "displacement field is not set");
142 MFEM_ASSERT(rho_filter, "density field is not set");
143 }
144
146 {
147 real_t L = lambda->Eval(T, ip);
148 real_t M = mu->Eval(T, ip);
150 real_t div_u = grad.Trace();
151 real_t density = L*div_u*div_u;
152 int dim = T.GetSpaceDim();
153 for (int i=0; i<dim; i++)
154 {
155 for (int j=0; j<dim; j++)
156 {
157 density += M*grad(i,j)*(grad(i,j)+grad(j,i));
158 }
159 }
160 real_t val = rho_filter->GetValue(T,ip);
161
162 return -exponent * pow(val, exponent-1.0) * (1-rho_min) * density;
163 }
164};
165
166/// @brief Volumetric force for linear elasticity
168{
169private:
170 real_t r;
171 Vector center;
172 Vector force;
173public:
174 VolumeForceCoefficient(real_t r_,Vector & center_, Vector & force_) :
175 VectorCoefficient(center_.Size()), r(r_), center(center_), force(force_) { }
176
178
180 const IntegrationPoint &ip) override
181 {
182 Vector xx; xx.SetSize(T.GetDimension());
183 T.Transform(ip,xx);
184 for (int i=0; i<xx.Size(); i++)
185 {
186 xx[i]=xx[i]-center[i];
187 }
188
189 real_t cr=xx.Norml2();
190 V.SetSize(T.GetDimension());
191 if (cr <= r)
192 {
193 V = force;
194 }
195 else
196 {
197 V = 0.0;
198 }
199 }
200
201 void Set(real_t r_,Vector & center_, Vector & force_)
202 {
203 r=r_;
204 center = center_;
205 force = force_;
206 }
207};
208
209/**
210 * @brief Class for solving Poisson's equation:
211 *
212 * - ∇ ⋅(κ ∇ u) = f in Ω
213 *
214 */
216{
217private:
218 Mesh * mesh = nullptr;
219 int order = 1;
220 // diffusion coefficient
221 Coefficient * diffcf = nullptr;
222 // mass coefficient
223 Coefficient * masscf = nullptr;
224 Coefficient * rhscf = nullptr;
225 Coefficient * essbdr_cf = nullptr;
226 Coefficient * neumann_cf = nullptr;
227 VectorCoefficient * gradient_cf = nullptr;
228
229 // FEM solver
230 int dim;
231 FiniteElementCollection * fec = nullptr;
232 FiniteElementSpace * fes = nullptr;
233 Array<int> ess_bdr;
234 Array<int> ess_tdof_list;
235 Array<int> neumann_bdr;
236 GridFunction * u = nullptr;
237 LinearForm * b = nullptr;
238 BilinearForm * a = nullptr;
239 OperatorPtr A;
240 bool parallel;
241#ifdef MFEM_USE_MPI
242 ParMesh * pmesh = nullptr;
243 ParFiniteElementSpace * pfes = nullptr;
244#endif
245
246public:
248 DiffusionSolver(Mesh * mesh_, int order_, Coefficient * diffcf_,
249 Coefficient * cf_);
250
251 void SetMesh(Mesh * mesh_)
252 {
253 mesh = mesh_;
254 parallel = false;
255#ifdef MFEM_USE_MPI
256 pmesh = dynamic_cast<ParMesh *>(mesh);
257 if (pmesh) { parallel = true; }
258#endif
259 }
260 void SetOrder(int order_) { order = order_ ; }
261 void SetDiffusionCoefficient(Coefficient * diffcf_) { diffcf = diffcf_; }
262 void SetMassCoefficient(Coefficient * masscf_) { masscf = masscf_; }
263 void SetRHSCoefficient(Coefficient * rhscf_) { rhscf = rhscf_; }
264 void SetEssentialBoundary(const Array<int> & ess_bdr_) { ess_bdr = ess_bdr_; }
265 void SetNeumannBoundary(const Array<int> & neumann_bdr_) { neumann_bdr = neumann_bdr_; }
266 void SetNeumannData(Coefficient * neumann_cf_) {neumann_cf = neumann_cf_;}
267 void SetEssBdrData(Coefficient * essbdr_cf_) {essbdr_cf = essbdr_cf_;}
268 void SetGradientData(VectorCoefficient * gradient_cf_) {gradient_cf = gradient_cf_;}
269
270 void ResetFEM();
271 void SetupFEM();
272
274 void AssembleDiffusionBilinear(bool update_ess_tdofs=true);
275 void Solve();
278#ifdef MFEM_USE_MPI
281 {
282 if (parallel)
283 {
284 return dynamic_cast<ParLinearForm *>(b);
285 }
286 else
287 {
288 MFEM_ABORT("Wrong code path. Call GetLinearForm");
289 return nullptr;
290 }
291 }
292#endif
293
295
296};
297
298/**
299 * @brief Class for solving linear elasticity:
300 *
301 * -∇ ⋅ σ(u) = f in Ω + BCs
302 *
303 * where
304 *
305 * σ(u) = λ ∇⋅u I + μ (∇ u + ∇uᵀ)
306 *
307 */
309{
310private:
311 Mesh * mesh = nullptr;
312 int order = 1;
313 Coefficient * lambda_cf = nullptr;
314 Coefficient * mu_cf = nullptr;
315 VectorCoefficient * essbdr_cf = nullptr;
316 VectorCoefficient * rhs_cf = nullptr;
317
318 // FEM solver
319 int dim;
320 FiniteElementCollection * fec = nullptr;
321 FiniteElementSpace * fes = nullptr;
322 Array<int> ess_bdr;
323 Array<int> neumann_bdr;
324 GridFunction * u = nullptr;
325 LinearForm * b = nullptr;
326 bool parallel;
327#ifdef MFEM_USE_MPI
328 ParMesh * pmesh = nullptr;
329 ParFiniteElementSpace * pfes = nullptr;
330#endif
331
332public:
334 LinearElasticitySolver(Mesh * mesh_, int order_,
335 Coefficient * lambda_cf_, Coefficient * mu_cf_);
336
337 void SetMesh(Mesh * mesh_)
338 {
339 mesh = mesh_;
340 parallel = false;
341#ifdef MFEM_USE_MPI
342 pmesh = dynamic_cast<ParMesh *>(mesh);
343 if (pmesh) { parallel = true; }
344#endif
345 }
346 void SetOrder(int order_) { order = order_ ; }
347 void SetLameCoefficients(Coefficient * lambda_cf_, Coefficient * mu_cf_) { lambda_cf = lambda_cf_; mu_cf = mu_cf_; }
348 void SetRHSCoefficient(VectorCoefficient * rhs_cf_) { rhs_cf = rhs_cf_; }
349 void SetEssentialBoundary(const Array<int> & ess_bdr_) { ess_bdr = ess_bdr_; }
350 void SetNeumannBoundary(const Array<int> & neumann_bdr_) { neumann_bdr = neumann_bdr_; }
351 void SetEssBdrData(VectorCoefficient * essbdr_cf_) {essbdr_cf = essbdr_cf_;}
352
353 void ResetFEM();
354 void SetupFEM();
355
356 void Solve();
359#ifdef MFEM_USE_MPI
362 {
363 if (parallel)
364 {
365 return dynamic_cast<ParLinearForm *>(b);
366 }
367 else
368 {
369 MFEM_ABORT("Wrong code path. Call GetLinearForm");
370 return nullptr;
371 }
372 }
373#endif
374
376
377};
378
379/**
380 * @brief Bregman projection of ρ = sigmoid(ψ) onto the subspace
381 * ∫_Ω ρ dx = θ vol(Ω) as follows:
382 *
383 * 1. Compute the root of the R → R function
384 * f(c) = ∫_Ω sigmoid(ψ + c) dx - θ vol(Ω)
385 * using the Illinois method
386 * 2. Set ψ ← ψ + c.
387 *
388 * @param psi a GridFunction to be updated
389 * @param alpha_grad alpha multiplied by gradient
390 * @param target_volume θ vol(Ω)
391 * @param tol Illinois iteration tolerance
392 * @param max_its Illinois maximum iteration number
393 * @return real_t Final volume (∫_Ω sigmoid(ψ) dx)
394 */
395real_t proj(GridFunction &psi, GridFunction &alpha_grad, real_t target_volume,
396 real_t tol = 1e-12, int max_its = 100)
397{
398#ifdef MFEM_USE_MPI
399 FiniteElementSpace *fes = psi.FESpace();
400 ParFiniteElementSpace *pfes = dynamic_cast<ParFiniteElementSpace*>(fes);
401#endif
402 ConstantCoefficient zero_cf(0.0);
403 real_t a = -alpha_grad.ComputeMaxError(zero_cf);
404 real_t b = -a;
405 real_t y = 0.0;
406
408 &psi, [&y](const real_t x) { return sigmoid(x + y); });
409 std::unique_ptr<LinearForm> int_sigmoid_psi;
410#ifdef MFEM_USE_MPI
411 ParGridFunction *par_psi = dynamic_cast<ParGridFunction *>(&psi);
412 if (par_psi)
413 {
414 int_sigmoid_psi.reset(new ParLinearForm(par_psi->ParFESpace()));
415 }
416 else
417 {
418 int_sigmoid_psi.reset(new LinearForm(psi.FESpace()));
419 }
420#else
421 int_sigmoid_psi.reset(new LinearForm(psi.FESpace()));
422#endif
423 int_sigmoid_psi->AddDomainIntegrator(new DomainLFIntegrator(sigmoid_psi));
424
425 y = a;
426 int_sigmoid_psi->Assemble();
427 real_t f_a = int_sigmoid_psi->Sum(); // f_a := f(a) + θ vol(Ω)
428
429 y = b;
430 int_sigmoid_psi->Assemble();
431 real_t f_b = int_sigmoid_psi->Sum(); // f_b := f(b) + θ vol(Ω)
432#ifdef MFEM_USE_MPI
433 if (pfes)
434 {
435 MPI_Allreduce(MPI_IN_PLACE, &f_a, 1, MPITypeMap<real_t>::mpi_type,
436 MPI_SUM, MPI_COMM_WORLD);
437 MPI_Allreduce(MPI_IN_PLACE, &f_b, 1, MPITypeMap<real_t>::mpi_type,
438 MPI_SUM, MPI_COMM_WORLD);
439 }
440#endif
441 f_a -= target_volume; // f_a := f(a)
442 f_b -= target_volume; // f_b := f(b)
443 real_t c = 0.0;
444 real_t f_c = 0.0;
445 int side = 0;
446
447 bool done = false;
448 for (int k=0; k < max_its; k++)
449 {
450 c = (f_a * b - f_b * a) / (f_a - f_b);
451
452 if (std::fabs(b - a) < tol * std::fabs(b + a)) { done = true; break; }
453
454 y = c;
455 int_sigmoid_psi->Assemble();
456 f_c = int_sigmoid_psi->Sum(); // f_c := f(c) + θ vol(Ω)
457#ifdef MFEM_USE_MPI
458 if (pfes)
459 {
460 MPI_Allreduce(MPI_IN_PLACE, &f_c, 1, MPITypeMap<real_t>::mpi_type,
461 MPI_SUM, MPI_COMM_WORLD);
462 }
463#endif
464 f_c -= target_volume; // f_c := f(c)
465
466 if (f_c * f_b > 0)
467 {
468 b = c;
469 f_b = f_c;
470 if (side == -1) { f_a /= 2.0; }
471 side = -1;
472 }
473 else if (f_c * f_a > 0)
474 {
475 a = c;
476 f_a = f_c;
477 if (side == 1) { f_b /= 2.0; }
478 side = 1;
479 }
480 else
481 {
482 done = true; break;
483 }
484 }
485 if (!done)
486 {
487 mfem_warning("Projection reached maximum iteration without converging. "
488 "Result may not be accurate.");
489 }
490 y = 0.0;
491 psi += c;
492 int_sigmoid_psi->Assemble();
493 real_t material_volume = int_sigmoid_psi->Sum();
494#ifdef MFEM_USE_MPI
495 if (pfes)
496 {
497 MPI_Allreduce(MPI_IN_PLACE, &material_volume, 1,
498 MPITypeMap<real_t>::mpi_type, MPI_SUM, MPI_COMM_WORLD);
499 }
500#endif
501 return material_volume;
502}
503
504// Poisson solver
505
507 Coefficient * diffcf_, Coefficient * rhscf_)
508 : mesh(mesh_), order(order_), diffcf(diffcf_), rhscf(rhscf_)
509{
510
511#ifdef MFEM_USE_MPI
512 pmesh = dynamic_cast<ParMesh *>(mesh);
513 if (pmesh) { parallel = true; }
514#endif
515
516 SetupFEM();
517}
518
520{
521 dim = mesh->Dimension();
522 fec = new H1_FECollection(order, dim);
523
524#ifdef MFEM_USE_MPI
525 if (parallel)
526 {
527 pfes = new ParFiniteElementSpace(pmesh, fec);
528 u = new ParGridFunction(pfes);
529 b = new ParLinearForm(pfes);
530 }
531 else
532 {
533 fes = new FiniteElementSpace(mesh, fec);
534 u = new GridFunction(fes);
535 b = new LinearForm(fes);
536 }
537#else
538 fes = new FiniteElementSpace(mesh, fec);
539 u = new GridFunction(fes);
540 b = new LinearForm(fes);
541#endif
542 *u=0.0;
543
544 if (!ess_bdr.Size())
545 {
546 if (mesh->bdr_attributes.Size())
547 {
548 ess_bdr.SetSize(mesh->bdr_attributes.Max());
549 ess_bdr = 1;
550 }
551 }
552}
553
555{
556#ifdef MFEM_USE_MPI
557 if (parallel)
558 {
559 pfes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
560 }
561 else
562 {
563 fes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
564 }
565#else
566 fes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
567#endif
568}
569
571{
572 if (update_ess_tdofs)
573 {
575 }
576#ifdef MFEM_USE_MPI
577 if (parallel)
578 {
579 a = new ParBilinearForm(pfes);
580 }
581 else
582 {
583 a = new BilinearForm(fes);
584 }
585#else
586 a = new BilinearForm(fes);
587#endif
589 if (masscf)
590 {
591 a->AddDomainIntegrator(new MassIntegrator(*masscf));
592 }
593 a->Assemble();
594 a->FormSystemMatrix(ess_tdof_list, A);
595}
596
598{
599 Vector B, X;
600
601 if (b)
602 {
603 delete b;
604#ifdef MFEM_USE_MPI
605 if (parallel)
606 {
607 b = new ParLinearForm(pfes);
608 }
609 else
610 {
611 b = new LinearForm(fes);
612 }
613#else
614 b = new LinearForm(fes);
615#endif
616 }
617 if (rhscf)
618 {
620 }
621 if (neumann_cf)
622 {
623 MFEM_VERIFY(neumann_bdr.Size(), "neumann_bdr attributes not provided");
624 b->AddBoundaryIntegrator(new BoundaryLFIntegrator(*neumann_cf),neumann_bdr);
625 }
626 else if (gradient_cf)
627 {
628 MFEM_VERIFY(neumann_bdr.Size(), "neumann_bdr attributes not provided");
630 neumann_bdr);
631 }
632
633 b->Assemble();
634
635 *u=0.0;
636 if (essbdr_cf)
637 {
638 u->ProjectBdrCoefficient(*essbdr_cf,ess_bdr);
639 }
640
641#ifdef MFEM_USE_MPI
642 if (parallel)
643 {
644 X.SetSize(pfes->TrueVSize());
645 B.SetSize(pfes->TrueVSize());
646 dynamic_cast<ParGridFunction*>(u)->ParallelAssemble(X);
647 dynamic_cast<ParLinearForm*>(b)->ParallelAssemble(B);
648 dynamic_cast<ParBilinearForm*>(a)->ParallelEliminateTDofsInRHS(
649 ess_tdof_list, X, B);
650 }
651 else
652 {
653 X.NewDataAndSize(u->GetData(), u->Size());
654 B.NewDataAndSize(b->GetData(), b->Size());
655 a->EliminateVDofsInRHS(ess_tdof_list, X, B);
656 }
657#else
658 X.NewDataAndSize(u->GetData(), u->Size());
659 B.NewDataAndSize(b->GetData(), b->Size());
660 a->EliminateVDofsInRHS(ess_tdof_list, X, B);
661#endif
662
663 CGSolver * cg = nullptr;
664 Solver * M = nullptr;
665#ifdef MFEM_USE_MPI
666 if (parallel)
667 {
668 M = new HypreBoomerAMG;
669 dynamic_cast<HypreBoomerAMG*>(M)->SetPrintLevel(0);
670 cg = new CGSolver(pmesh->GetComm());
671 }
672 else
673 {
674 M = new GSSmoother((SparseMatrix&)(*A));
675 cg = new CGSolver;
676 }
677#else
678 M = new GSSmoother((SparseMatrix&)(*A));
679 cg = new CGSolver;
680#endif
681 cg->SetRelTol(1e-12);
682 cg->SetMaxIter(10000);
683 cg->SetPrintLevel(0);
684 cg->SetPreconditioner(*M);
685 cg->SetOperator(*A);
686 cg->Mult(B, X);
687 delete M;
688 delete cg;
689 a->RecoverFEMSolution(X, *b, *u);
690}
691
696
697#ifdef MFEM_USE_MPI
699{
700 if (parallel)
701 {
702 return dynamic_cast<ParGridFunction*>(u);
703 }
704 else
705 {
706 MFEM_ABORT("Wrong code path. Call GetFEMSolution");
707 return nullptr;
708 }
709}
710#endif
711
713{
714 delete u; u = nullptr;
715 delete fes; fes = nullptr;
716#ifdef MFEM_USE_MPI
717 delete pfes; pfes=nullptr;
718#endif
719 delete fec; fec = nullptr;
720 delete b;
721 A.Clear();
722 delete a;
723}
724
725
726// Elasticity solver
727
729 Coefficient * lambda_cf_, Coefficient * mu_cf_)
730 : mesh(mesh_), order(order_), lambda_cf(lambda_cf_), mu_cf(mu_cf_)
731{
732#ifdef MFEM_USE_MPI
733 pmesh = dynamic_cast<ParMesh *>(mesh);
734 if (pmesh) { parallel = true; }
735#endif
736 SetupFEM();
737}
738
740{
741 dim = mesh->Dimension();
742 fec = new H1_FECollection(order, dim,BasisType::Positive);
743
744#ifdef MFEM_USE_MPI
745 if (parallel)
746 {
747 pfes = new ParFiniteElementSpace(pmesh, fec, dim);
748 u = new ParGridFunction(pfes);
749 b = new ParLinearForm(pfes);
750 }
751 else
752 {
753 fes = new FiniteElementSpace(mesh, fec,dim);
754 u = new GridFunction(fes);
755 b = new LinearForm(fes);
756 }
757#else
758 fes = new FiniteElementSpace(mesh, fec, dim);
759 u = new GridFunction(fes);
760 b = new LinearForm(fes);
761#endif
762 *u=0.0;
763
764 if (!ess_bdr.Size())
765 {
766 if (mesh->bdr_attributes.Size())
767 {
768 ess_bdr.SetSize(mesh->bdr_attributes.Max());
769 ess_bdr = 1;
770 }
771 }
772}
773
775{
776 GridFunction * x = nullptr;
777 OperatorPtr A;
778 Vector B, X;
780
781#ifdef MFEM_USE_MPI
782 if (parallel)
783 {
784 x = new ParGridFunction(pfes);
785 pfes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
786 }
787 else
788 {
789 x = new GridFunction(fes);
791 }
792#else
793 x = new GridFunction(fes);
795#endif
796 *u=0.0;
797 if (b)
798 {
799 delete b;
800#ifdef MFEM_USE_MPI
801 if (parallel)
802 {
803 b = new ParLinearForm(pfes);
804 }
805 else
806 {
807 b = new LinearForm(fes);
808 }
809#else
810 b = new LinearForm(fes);
811#endif
812 }
813 if (rhs_cf)
814 {
816 }
817
818 b->Assemble();
819
820 *x = 0.0;
821
822 BilinearForm * a = nullptr;
823
824#ifdef MFEM_USE_MPI
825 if (parallel)
826 {
827 a = new ParBilinearForm(pfes);
828 }
829 else
830 {
831 a = new BilinearForm(fes);
832 }
833#else
834 a = new BilinearForm(fes);
835#endif
836 a->AddDomainIntegrator(new ElasticityIntegrator(*lambda_cf, *mu_cf));
837 a->Assemble();
838 if (essbdr_cf)
839 {
840 u->ProjectBdrCoefficient(*essbdr_cf,ess_bdr);
841 }
842 a->FormLinearSystem(ess_tdof_list, *x, *b, A, X, B);
843
844 CGSolver * cg = nullptr;
845 Solver * M = nullptr;
846#ifdef MFEM_USE_MPI
847 if (parallel)
848 {
849 M = new HypreBoomerAMG;
850 dynamic_cast<HypreBoomerAMG*>(M)->SetPrintLevel(0);
851 cg = new CGSolver(pmesh->GetComm());
852 }
853 else
854 {
855 M = new GSSmoother((SparseMatrix&)(*A));
856 cg = new CGSolver;
857 }
858#else
859 M = new GSSmoother((SparseMatrix&)(*A));
860 cg = new CGSolver;
861#endif
862 cg->SetRelTol(1e-10);
863 cg->SetMaxIter(10000);
864 cg->SetPrintLevel(0);
865 cg->SetPreconditioner(*M);
866 cg->SetOperator(*A);
867 cg->Mult(B, X);
868 delete M;
869 delete cg;
870 a->RecoverFEMSolution(X, *b, *x);
871 *u+=*x;
872 delete a;
873 delete x;
874}
875
880
881#ifdef MFEM_USE_MPI
883{
884 if (parallel)
885 {
886 return dynamic_cast<ParGridFunction*>(u);
887 }
888 else
889 {
890 MFEM_ABORT("Wrong code path. Call GetFEMSolution");
891 return nullptr;
892 }
893}
894#endif
895
897{
898 delete u; u = nullptr;
899 delete fes; fes = nullptr;
900#ifdef MFEM_USE_MPI
901 delete pfes; pfes=nullptr;
902#endif
903 delete fec; fec = nullptr;
904 delete b;
905}
906
907} // namespace mfem
908
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:69
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:869
int Size() const
Return the logical size of the array.
Definition array.hpp:192
@ Positive
Bernstein polynomials.
Definition fe_base.hpp:37
A "square matrix" operator for the associated FE space and BLFIntegrators The sum of all the BLFInteg...
void EliminateVDofsInRHS(const Array< int > &vdofs, const Vector &x, Vector &b)
Use the stored eliminated part of the matrix (see EliminateVDofs(const Array<int> &,...
void AddDomainIntegrator(BilinearFormIntegrator *bfi)
Adds new Domain Integrator. Assumes ownership of bfi.
void Assemble(int skip_zeros=1)
Assembles the form i.e. sums over all domain/bdr integrators.
void RecoverFEMSolution(const Vector &X, const Vector &b, Vector &x) override
Recover the solution of a linear system formed with FormLinearSystem().
virtual void FormSystemMatrix(const Array< int > &ess_tdof_list, OperatorHandle &A)
Form the linear system matrix A, see FormLinearSystem() for details.
Class for boundary integration .
Definition lininteg.hpp:193
Class for boundary integration .
Definition lininteg.hpp:224
Conjugate gradient method.
Definition solvers.hpp:627
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the coefficient in the element described by T at the point ip.
A coefficient that is constant across space and time.
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
real_t Trace() const
Trace of a square matrix.
Definition densemat.cpp:409
Returns f(u(x)) - f(v(x)) where u, v are scalar GridFunctions and f:R → R.
Definition ex37.hpp:66
GridFunctionCoefficient OtherGridF_cf
Definition ex37.hpp:69
void SetFunction(std::function< real_t(const real_t)> fun_)
Definition ex37.hpp:93
DiffMappedGridFunctionCoefficient(const GridFunction *gf, const GridFunction *other_gf, std::function< real_t(const real_t)> fun_, int comp=1)
Definition ex37.hpp:77
real_t Eval(ElementTransformation &T, const IntegrationPoint &ip) override
Evaluate the coefficient in the element described by T at the point ip.
Definition ex37.hpp:86
const GridFunction * OtherGridF
Definition ex37.hpp:68
std::function< real_t(const real_t)> fun
Definition ex37.hpp:70
Class for solving Poisson's equation:
Definition ex37.hpp:216
ParGridFunction * GetParFEMSolution()
Definition ex37.hpp:698
void SetNeumannData(Coefficient *neumann_cf_)
Definition ex37.hpp:266
LinearForm * GetLinearForm()
Definition ex37.hpp:277
void AssembleDiffusionBilinear(bool update_ess_tdofs=true)
Definition ex37.hpp:570
ParLinearForm * GetParLinearForm()
Definition ex37.hpp:280
void SetDiffusionCoefficient(Coefficient *diffcf_)
Definition ex37.hpp:261
void SetGradientData(VectorCoefficient *gradient_cf_)
Definition ex37.hpp:268
void SetRHSCoefficient(Coefficient *rhscf_)
Definition ex37.hpp:263
void SetNeumannBoundary(const Array< int > &neumann_bdr_)
Definition ex37.hpp:265
void SetOrder(int order_)
Definition ex37.hpp:260
void SetEssBdrData(Coefficient *essbdr_cf_)
Definition ex37.hpp:267
void SetMesh(Mesh *mesh_)
Definition ex37.hpp:251
void UpdateEssentialTDofs()
Definition ex37.hpp:554
void SetMassCoefficient(Coefficient *masscf_)
Definition ex37.hpp:262
GridFunction * GetFEMSolution()
Definition ex37.hpp:692
void SetEssentialBoundary(const Array< int > &ess_bdr_)
Definition ex37.hpp:264
Class for domain integration .
Definition lininteg.hpp:108
virtual int GetSpaceDim() const =0
Get the dimension of the target (physical) space.
int GetDimension() const
Return the topological dimension of the reference element.
Definition eltrans.hpp:178
virtual void Transform(const IntegrationPoint &, Vector &)=0
Transform integration point from reference coordinates to physical coordinates and store them in the ...
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition fe_coll.hpp:27
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:210
virtual void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const
Get a list of essential true dofs, ess_tdof_list, corresponding to the boundary attributes marked in ...
Definition fespace.cpp:624
Gauss-Seidel smoother of a sparse matrix.
Coefficient defined by a GridFunction. This coefficient is mesh dependent.
real_t Eval(ElementTransformation &T, const IntegrationPoint &ip) override
Evaluate the coefficient at ip.
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:53
virtual real_t GetValue(int i, const IntegrationPoint &ip, int vdim=1) const
Definition gridfunc.cpp:429
void GetVectorGradient(ElementTransformation &tr, DenseMatrix &grad) const
Compute the vector gradient with respect to the physical element variable.
virtual real_t ComputeMaxError(Coefficient &exsol, const IntegrationRule *irs[]=NULL) const
Returns Max|u_ex - u_h| error for H1 or L2 elements.
FiniteElementSpace * FESpace()
void ProjectBdrCoefficient(Coefficient &coeff, const Array< int > &attr)
Project a Coefficient on the GridFunction, modifying only DOFs on the boundary associated with the bo...
Definition gridfunc.hpp:672
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:291
The BoomerAMG solver in hypre.
Definition hypre.hpp:1829
Class for integration point with weight.
Definition intrules.hpp:35
Class for solving linear elasticity:
Definition ex37.hpp:309
void SetEssBdrData(VectorCoefficient *essbdr_cf_)
Definition ex37.hpp:351
ParLinearForm * GetParLinearForm()
Definition ex37.hpp:361
GridFunction * GetFEMSolution()
Definition ex37.hpp:876
void SetEssentialBoundary(const Array< int > &ess_bdr_)
Definition ex37.hpp:349
void SetRHSCoefficient(VectorCoefficient *rhs_cf_)
Definition ex37.hpp:348
void SetMesh(Mesh *mesh_)
Definition ex37.hpp:337
LinearForm * GetLinearForm()
Definition ex37.hpp:358
void SetOrder(int order_)
Definition ex37.hpp:346
ParGridFunction * GetParFEMSolution()
Definition ex37.hpp:882
void SetNeumannBoundary(const Array< int > &neumann_bdr_)
Definition ex37.hpp:350
void SetLameCoefficients(Coefficient *lambda_cf_, Coefficient *mu_cf_)
Definition ex37.hpp:347
Vector with associated FE space and LinearFormIntegrators.
void AddDomainIntegrator(LinearFormIntegrator *lfi)
Adds new Domain Integrator. Assumes ownership of lfi.
void AddBoundaryIntegrator(LinearFormIntegrator *lfi)
Adds new Boundary Integrator. Assumes ownership of lfi.
void Assemble()
Assembles the linear form i.e. sums over all domain/bdr integrators.
Returns f(u(x)) where u is a scalar GridFunction and f:R → R.
Definition ex37.hpp:41
real_t Eval(ElementTransformation &T, const IntegrationPoint &ip) override
Evaluate the coefficient at ip.
Definition ex37.hpp:55
void SetFunction(std::function< real_t(const real_t)> fun_)
Definition ex37.hpp:60
std::function< real_t(const real_t)> fun
Definition ex37.hpp:43
MappedGridFunctionCoefficient(const GridFunction *gf, std::function< real_t(const real_t)> fun_, int comp=1)
Definition ex37.hpp:48
Mesh data type.
Definition mesh.hpp:67
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:309
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1314
Pointer to an Operator of a specified type.
Definition handle.hpp:34
void Clear()
Clear the OperatorHandle, deleting the held Operator (if owned), while leaving the type id unchanged.
Definition handle.hpp:124
Class for parallel bilinear form.
Abstract parallel finite element space.
Definition pfespace.hpp:31
void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const override
int TrueVSize() const
Obsolete, kept for backward compatibility.
Definition pfespace.hpp:577
Class for parallel grid function.
Definition pgridfunc.hpp:50
ParFiniteElementSpace * ParFESpace() const
Class for parallel linear form.
Class for parallel meshes.
Definition pmesh.hpp:35
MPI_Comm GetComm() const
Definition pmesh.hpp:403
Solid isotropic material penalization (SIMP) coefficient.
Definition ex37.hpp:98
real_t Eval(ElementTransformation &T, const IntegrationPoint &ip) override
Evaluate the coefficient in the element described by T at the point ip.
Definition ex37.hpp:111
SIMPInterpolationCoefficient(GridFunction *rho_filter_, real_t min_val_=1e-6, real_t max_val_=1.0, real_t exponent_=3)
Definition ex37.hpp:106
Base class for solvers.
Definition operator.hpp:855
Data type sparse matrix.
Definition sparsemat.hpp:51
Strain energy density coefficient.
Definition ex37.hpp:122
real_t Eval(ElementTransformation &T, const IntegrationPoint &ip) override
Evaluate the coefficient in the element described by T at the point ip.
Definition ex37.hpp:145
StrainEnergyDensityCoefficient(Coefficient *lambda_, Coefficient *mu_, GridFunction *u_, GridFunction *rho_filter_, real_t rho_min_=1e-6, real_t exponent_=3.0)
Definition ex37.hpp:133
Base class for vector Coefficients that optionally depend on time and space.
virtual void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the vector coefficient in the element described by T at the point ip, storing the result in ...
Vector data type.
Definition vector.hpp:82
real_t Norml2() const
Returns the l2 norm of the vector.
Definition vector.cpp:968
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
real_t Sum() const
Return the sum of the vector entries.
Definition vector.cpp:1246
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:633
void NewDataAndSize(real_t *d, int s)
Set the Vector data and size, deleting the old data, if owned.
Definition vector.hpp:197
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:243
Volumetric force for linear elasticity.
Definition ex37.hpp:168
VolumeForceCoefficient(real_t r_, Vector &center_, Vector &force_)
Definition ex37.hpp:174
void Set(real_t r_, Vector &center_, Vector &force_)
Definition ex37.hpp:201
void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip) override
Evaluate the vector coefficient in the element described by T at the point ip, storing the result in ...
Definition ex37.hpp:179
const int * ess_tdof_list
int dim
Definition ex24.cpp:53
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
real_t sigmoid(real_t x)
Sigmoid function.
Definition ex37.hpp:20
real_t proj(GridFunction &psi, GridFunction &alpha_grad, real_t target_volume, real_t tol=1e-12, int max_its=100)
Bregman projection of ρ = sigmoid(ψ) onto the subspace ∫_Ω ρ dx = θ vol(Ω) as follows:
Definition ex37.hpp:395
void mfem_warning(const char *msg)
Definition error.cpp:187
real_t inv_sigmoid(real_t x)
Inverse sigmoid function.
Definition ex37.hpp:12
float real_t
Definition config.hpp:46
real_t der_sigmoid(real_t x)
Derivative of sigmoid function.
Definition ex37.hpp:33
Helper struct to convert a C++ type to an MPI type.