MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
ds-common.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#include "ds-common.hpp"
13
14using namespace std;
15using namespace mfem;
16
17namespace ds_common
18{
19
21int MG_MAX_ITER = 10;
22real_t MG_REL_TOL = std::sqrt(1e-10);
23
24int dim = 0;
25int space_dim = 0;
28
29// Custom monitor that prints a csv-formatted file
30DataMonitor::DataMonitor(string file_name, int ndigits)
31 : os(file_name),
32 precision(ndigits)
33{
34 if (Mpi::Root())
35 {
36 mfem::out << "Saving iterations into: " << file_name << endl;
37 }
38 os << "it,res,sol" << endl;
39 os << fixed << setprecision(precision);
40}
41
43 bool final)
44{
45 os << it << "," << norm << ",";
46}
47
49 bool final)
50{
51 os << norm << endl;
52}
53
54
55// Abs-L(1) general geometric multigrid method, derived from GeometricMultigrid
57 ParFiniteElementSpaceHierarchy& fes_hierarchy,
58 Array<int>& ess_bdr,
60 SolverType st,
62 : GeometricMultigrid(fes_hierarchy, ess_bdr),
63 integrator_type(it),
64 solver_type(st),
65 assembly_level(al),
66 coarse_pc(nullptr),
67 one(1.0)
68{
69 // BilinearForm::FormSystemMatrix does not handle the ownership of A_l.
70 // GeometricMultigrid owns the forms, and deletes them.
71 mg_owned = !(AssemblyLevel::LEGACY == assembly_level);
72
73 ConstructCoarseOperatorAndSolver(fes_hierarchy.GetFESpaceAtLevel(0));
74 for (int l = 1; l < fes_hierarchy.GetNumLevels(); ++l)
75 {
76 ConstructOperatorAndSmoother(fes_hierarchy.GetFESpaceAtLevel(l), l);
77 }
78}
79
80void AbsL1GeometricMultigrid::ConstructCoarseOperatorAndSolver(
81 ParFiniteElementSpace& coarse_fespace)
82{
83 ConstructBilinearForm(coarse_fespace);
84
85 OperatorPtr coarse_mat;
86 coarse_mat.SetType(Operator::ANY_TYPE);
87 bfs[0]->FormSystemMatrix(*essentialTrueDofs[0], coarse_mat);
88 coarse_mat.SetOperatorOwner(false);
89
90 // Create smoother
91 Vector local_ones(coarse_mat->Height());
92 Vector result(coarse_mat->Height());
93
94 local_ones = 1.0;
95 coarse_mat->AbsMult(local_ones, result);
96
97 coarse_pc = new OperatorJacobiSmoother(result, *essentialTrueDofs[0]);
98
99 Solver* coarse_solver = nullptr;
100 switch (solver_type)
101 {
102 case sli:
103 coarse_solver = new SLISolver(MPI_COMM_WORLD);
104 break;
105 case cg:
106 coarse_solver = new CGSolver(MPI_COMM_WORLD);
107 break;
108 default:
109 mfem_error("Invalid solver type!");
110 }
111 coarse_solver->SetOperator(*coarse_mat);
112
113 IterativeSolver *it_solver = dynamic_cast<IterativeSolver*>(coarse_solver);
114 if (it_solver)
115 {
116 it_solver->SetRelTol(MG_REL_TOL);
117 it_solver->SetMaxIter(MG_MAX_ITER);
118 it_solver->SetPrintLevel(-1);
119 it_solver->SetPreconditioner(*coarse_pc);
120 }
121
122 AddLevel(coarse_mat.Ptr(), coarse_solver, mg_owned, true);
123}
124
125void AbsL1GeometricMultigrid::ConstructOperatorAndSmoother(
126 ParFiniteElementSpace& fespace, int level)
127{
129 ConstructBilinearForm(fespace);
130
131 OperatorPtr level_mat;
132 level_mat.SetType(Operator::ANY_TYPE);
133 bfs.Last()->FormSystemMatrix(ess_tdof_list, level_mat);
134 level_mat.SetOperatorOwner(false);
135
136 // Create smoother
137 Vector local_ones(level_mat->Height());
138 Vector result(level_mat->Height());
139
140 local_ones = 1.0;
141 level_mat->AbsMult(local_ones, result);
142
143 Solver* smoother = new OperatorJacobiSmoother(result, ess_tdof_list);
144
145 AddLevel(level_mat.Ptr(), smoother, mg_owned, true);
146}
147
148void AbsL1GeometricMultigrid::ConstructBilinearForm(
149 ParFiniteElementSpace &fespace)
150{
151 ParBilinearForm* form = new ParBilinearForm(&fespace);
152 form->SetAssemblyLevel(assembly_level);
153 switch (integrator_type)
154 {
155 case mass:
156 form->AddDomainIntegrator(new MassIntegrator(one));
157 break;
158 case diffusion:
160 break;
161 case maxwell:
164 break;
165 default:
166 mfem_error("Invalid integrator type! Check ParBilinearForm");
167 }
168 form->Assemble();
169 bfs.Append(form);
170}
171
172
174 Vector& diag)
175{
176 ParBilinearForm temp_form(form.ParFESpace());
177 temp_form.AllocateMatrix();
178 for (int i = 0; i < form.ParFESpace()->GetNE(); ++i)
179 {
180 DenseMatrix emat_i;
181 form.ComputeElementMatrix(i, emat_i);
182 Vector right(emat_i.Height());
183 Vector temp(emat_i.Height());
184 Vector left(emat_i.Height());
185
186 DenseMatrix temp_emat_i = emat_i;
187 for (int j = 0; j < emat_i.Height(); ++j)
188 {
189 for (int k = 0; k < emat_i.Width(); ++k)
190 {
191 temp_emat_i(j, k) = std::pow(std::abs(emat_i(j, k)), p);
192 }
193 }
194
195 if (q!=0.0)
196 {
197 emat_i.GetDiag(right);
198 right.Abs();
199 right.Pow(q);
200 }
201 else
202 {
203 right = 1.0;
204 }
205
206 temp_emat_i.Mult(right, temp);
207
208 if (1.0 + q - p!= 0.0)
209 {
210 emat_i.GetDiag(left);
211 left.Abs();
212 left.Pow(1.0 + q - p);
213 left *= temp;
214 }
215 else
216 {
217 left = temp;
218 }
219
220 temp_emat_i.Clear();
221 temp_emat_i.Diag(left.GetData(), left.Size());
222 temp_form.AssembleElementMatrix(i, temp_emat_i, 1);
223 }
224 temp_form.Finalize();
225 auto mat = temp_form.ParallelAssemble();
226 mat->AssembleDiagonal(diag);
227 delete mat;
228}
229
231{
232 if (dim == 3)
233 {
234 return sin(kappa * x(0)) * sin(kappa * x(1)) * sin(kappa * x(2)) + 1.0;
235 }
236 else
237 {
238 return sin(kappa * x(0)) * sin(kappa * x(1)) + 1.0;
239 }
240}
241
243{
244 if (dim == 3)
245 {
246 return dim * kappa * kappa * sin(kappa * x(0)) * sin(kappa * x(1)) *
247 sin(kappa * x(2));
248 }
249 else
250 {
251 return dim * kappa * kappa * sin(kappa * x(0)) * sin(kappa * x(1));
252 }
253}
254
256{
257 if (dim == 3)
258 {
259 u(0) = sin(kappa * x(1));
260 u(1) = sin(kappa * x(2));
261 u(2) = sin(kappa * x(0));
262 }
263 else
264 {
265 u(0) = sin(kappa * x(1));
266 u(1) = sin(kappa * x(0));
267 if (x.Size() == 3) { u(2) = 0.0; }
268 }
269}
270
272{
273 if (dim == 3)
274 {
275 f(0) = (1. + kappa * kappa) * sin(kappa * x(1));
276 f(1) = (1. + kappa * kappa) * sin(kappa * x(2));
277 f(2) = (1. + kappa * kappa) * sin(kappa * x(0));
278 }
279 else
280 {
281 f(0) = (1. + kappa * kappa) * sin(kappa * x(1));
282 f(1) = (1. + kappa * kappa) * sin(kappa * x(0));
283 if (x.Size() == 3) { f(2) = 0.0; }
284 }
285}
286
287} // end namespace ds_common
AbsL1GeometricMultigrid(ParFiniteElementSpaceHierarchy &fes_hierarchy, Array< int > &ess_bdr, IntegratorType it, SolverType st, AssemblyLevel al)
Definition ds-common.cpp:56
void MonitorResidual(int it, real_t norm, const Vector &x, bool final)
Monitor the residual vector r.
Definition ds-common.cpp:42
DataMonitor(string file_name, int ndigits)
Definition ds-common.cpp:30
void MonitorSolution(int it, real_t norm, const Vector &x, bool final)
Monitor the solution vector x.
Definition ds-common.cpp:48
void SetAssemblyLevel(AssemblyLevel assembly_level)
Set the desired assembly level.
void AllocateMatrix()
Pre-allocate the internal SparseMatrix before assembly. If the internal flag precompute_sparsity is s...
void AddDomainIntegrator(BilinearFormIntegrator *bfi)
Adds new Domain Integrator. Assumes ownership of bfi.
void Finalize(int skip_zeros=1) override
Finalizes the matrix initialization if the AssemblyLevel is AssemblyLevel::LEGACY....
void AssembleElementMatrix(int i, const DenseMatrix &elmat, int skip_zeros=1)
Assemble the given element matrix.
void ComputeElementMatrix(int i, DenseMatrix &elmat) const
Compute the element matrix of the given element.
Conjugate gradient method.
Definition solvers.hpp:627
Integrator for for Nedelec elements.
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
void GetDiag(Vector &d) const
Returns the diagonal of the matrix.
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication.
Definition densemat.cpp:108
void Diag(real_t c, int n)
Creates n x n diagonal matrix with diagonal elements c.
void Clear()
Delete the matrix data array (if owned) and reset the matrix state.
Definition densemat.hpp:115
int GetNumLevels() const
Returns the number of levels in the hierarchy.
Geometric multigrid associated with a hierarchy of finite element spaces.
Array< Array< int > * > essentialTrueDofs
Array< BilinearForm * > bfs
void AssembleDiagonal(Vector &diag) const override
Return the diagonal of the matrix (Operator interface).
Definition hypre.hpp:680
Abstract base class for iterative solver.
Definition solvers.hpp:91
void SetRelTol(real_t rtol)
Definition solvers.hpp:238
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Definition solvers.cpp:178
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Definition solvers.cpp:76
void SetMaxIter(int max_it)
Definition solvers.hpp:240
static bool Root()
Return true if the rank in MPI_COMM_WORLD is zero.
void AddLevel(Operator *op, Solver *smoother, bool ownOperator, bool ownSmoother)
Adds a level to the multigrid operator hierarchy.
Definition multigrid.cpp:87
Pointer to an Operator of a specified type.
Definition handle.hpp:34
void SetOperatorOwner(bool own=true)
Set the ownership flag for the held Operator.
Definition handle.hpp:120
void SetType(Operator::Type tid)
Invoke Clear() and set a new type id.
Definition handle.hpp:132
Operator * Ptr() const
Access the underlying Operator pointer.
Definition handle.hpp:87
Jacobi smoothing for a given bilinear form (no matrix necessary).
Definition solvers.hpp:422
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:68
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition operator.hpp:74
@ ANY_TYPE
ID for the base class Operator, i.e. any type.
Definition operator.hpp:320
virtual void AbsMult(const Vector &x, Vector &y) const
Action of the absolute-value operator: y=|A|(x). The default behavior in class Operator is to generat...
Definition operator.hpp:97
Class for parallel bilinear form.
HypreParMatrix * ParallelAssemble()
Returns the matrix assembled on the true dofs, i.e. P^t A P.
void Assemble(int skip_zeros=1)
Assemble the local matrix.
ParFiniteElementSpace * ParFESpace() const
Return the parallel FE space associated with the ParBilinearForm.
const ParFiniteElementSpace & GetFESpaceAtLevel(int level) const override
Returns the finite element space at the given level.
Abstract parallel finite element space.
Definition pfespace.hpp:31
Stationary linear iteration: x <- x + B (b - A x)
Definition solvers.hpp:591
Base class for solvers.
Definition operator.hpp:855
virtual void SetOperator(const Operator &op)=0
Set/update the solver for the given operator.
Vector data type.
Definition vector.hpp:82
void Pow(const real_t p)
(*this)(i) = pow((*this)(i), p)
Definition vector.cpp:403
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
void Abs()
(*this)(i) = abs((*this)(i))
Definition vector.cpp:392
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:243
const int * ess_tdof_list
real_t f(const Vector &p)
real_t MG_REL_TOL
Definition ds-common.cpp:22
real_t diffusion_source(const Vector &x)
int space_dim
Definition ds-common.cpp:25
void maxwell_source(const Vector &x, Vector &f)
void maxwell_solution(const Vector &x, Vector &u)
int MG_MAX_ITER
Definition ds-common.cpp:21
void AssembleElementLpqJacobiDiag(ParBilinearForm &form, real_t p, real_t q, Vector &diag)
int MONITOR_DIGITS
Definition ds-common.cpp:20
real_t kappa
Definition ds-common.cpp:27
real_t diffusion_solution(const Vector &x)
real_t freq
Definition ds-common.cpp:26
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
void mfem_error(const char *msg)
Definition error.cpp:154
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition globals.hpp:66
AssemblyLevel
Enumeration defining the assembly level for bilinear and nonlinear form classes derived from Operator...
float real_t
Definition config.hpp:46
STL namespace.
real_t p(const Vector &x, real_t t)
MFEM_HOST_DEVICE real_t norm(const Complex &z)