MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
diffusion.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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// MFEM Ultraweak DPG example for diffusion
13//
14// Compile with: make diffusion
15//
16// sample runs
17// diffusion -m ../../data/star.mesh -o 3 -ref 1 -do 1 -prob 1 -sc
18// diffusion -m ../../data/inline-tri.mesh -o 2 -ref 2 -do 1 -prob 0
19// diffusion -m ../../data/inline-quad.mesh -o 4 -ref 1 -do 2 -prob 0 -sc
20// diffusion -m ../../data/inline-tet.mesh -o 3 -ref 0 -do 1 -prob 1 -sc
21
22// Description:
23// This example code demonstrates the use of MFEM to define and solve
24// the "ultraweak" (UW) DPG formulation for the Poisson problem
25
26// - Δ u = f, in Ω
27// u = u₀, on ∂Ω
28
29// It solves two kinds of problems
30// a) f = 1 and u₀ = 0 (like ex1)
31// b) A manufactured solution problem where u_exact = sin(π * (x + y + z)).
32// This example computes and prints out convergence rates for the L2 error.
33
34// The DPG UW deals with the First Order System
35// ∇ u - σ = 0, in Ω
36// - ∇⋅σ = f, in Ω
37// u = u₀, in ∂Ω
38
39// Ultraweak-DPG is obtained by integration by parts of both equations and the
40// introduction of trace unknowns on the mesh skeleton
41//
42// u ∈ L²(Ω), σ ∈ (L²(Ω))ᵈⁱᵐ
43// û ∈ H^1/2(Γₕ), σ̂ ∈ H^-1/2(Γₕ)
44// -(u , ∇⋅τ) - (σ , τ) + < û, τ⋅n> = 0, ∀ τ ∈ H(div,Ω)
45// (σ , ∇ v) + < σ̂, v > = (f,v) ∀ v ∈ H¹(Ω)
46// û = u₀ on ∂Ω
47
48// Note:
49// û := u and σ̂ := -σ on the mesh skeleton
50//
51// -------------------------------------------------------------
52// | | u | σ | û | σ̂ | RHS |
53// -------------------------------------------------------------
54// | τ | -(u,∇⋅τ) | -(σ,τ) | < û, τ⋅n> | | 0 |
55// | | | | | | |
56// | v | | (σ,∇ v) | | <σ̂,v> | (f,v) |
57
58// where (τ,v) ∈ H(div,Ω) × H^1(Ω)
59
60// Here we use the "space-induced" test norm i.e.,
61//
62// ||(t,v)||²_H(div)×H¹ := ||t||² + ||∇⋅t||² + ||v||² + ||∇v||²
63
64// For more information see https://doi.org/10.1007/978-3-319-01818-8_6
65
66#include "mfem.hpp"
67#include "util/weakform.hpp"
69#include <fstream>
70#include <iostream>
71
72using namespace std;
73using namespace mfem;
74using namespace mfem::common;
75
81
83
84real_t exact_u(const Vector & X);
85void exact_gradu(const Vector & X, Vector &gradu);
87void exact_sigma(const Vector & X, Vector & sigma);
88real_t exact_hatu(const Vector & X);
89void exact_hatsigma(const Vector & X, Vector & hatsigma);
90real_t f_exact(const Vector & X);
91
92int main(int argc, char *argv[])
93{
94 // 1. Parse command-line options.
95 const char *mesh_file = "../../data/inline-quad.mesh";
96 int order = 1;
97 int delta_order = 1;
98 int ref = 0;
99 bool visualization = true;
100 int iprob = 1;
101 int visport = 19916;
102 bool static_cond = false;
103
104 OptionsParser args(argc, argv);
105 args.AddOption(&mesh_file, "-m", "--mesh",
106 "Mesh file to use.");
107 args.AddOption(&order, "-o", "--order",
108 "Finite element order (polynomial degree).");
109 args.AddOption(&delta_order, "-do", "--delta_order",
110 "Order enrichment for DPG test space.");
111 args.AddOption(&ref, "-ref", "--num_refinements",
112 "Number of uniform refinements");
113 args.AddOption(&iprob, "-prob", "--problem", "Problem case"
114 " 0: manufactured, 1: general");
115 args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
116 "--no-static-condensation", "Enable static condensation.");
117 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
118 "--no-visualization",
119 "Enable or disable GLVis visualization.");
120 args.AddOption(&visport, "-p", "--send-port", "Socket for GLVis.");
121 args.Parse();
122 if (!args.Good())
123 {
124 args.PrintUsage(cout);
125 return 1;
126 }
127 args.PrintOptions(cout);
128
129 if (iprob > 1) { iprob = 1; }
130 prob = (prob_type)iprob;
131
132 Mesh mesh(mesh_file, 1, 1);
133 int dim = mesh.Dimension();
134 MFEM_VERIFY(dim > 1, "Dimension = 1 is not supported in this example");
135
136 // Define spaces
137 enum TrialSpace
138 {
139 u_space = 0,
140 sigma_space = 1,
141 hatu_space = 2,
142 hatsigma_space = 3
143 };
144 enum TestSpace
145 {
146 tau_space = 0,
147 v_space = 1
148 };
149 // L2 space for u
150 FiniteElementCollection *u_fec = new L2_FECollection(order-1,dim);
151 FiniteElementSpace *u_fes = new FiniteElementSpace(&mesh,u_fec);
152
153 // Vector L2 space for σ
154 FiniteElementCollection *sigma_fec = new L2_FECollection(order-1,dim);
155 FiniteElementSpace *sigma_fes = new FiniteElementSpace(&mesh,sigma_fec, dim);
156
157 // H^1/2 space for û
158 FiniteElementCollection * hatu_fec = new H1_Trace_FECollection(order,dim);
159 FiniteElementSpace *hatu_fes = new FiniteElementSpace(&mesh,hatu_fec);
160
161 // H^-1/2 space for σ̂
162 FiniteElementCollection * hatsigma_fec = new RT_Trace_FECollection(order-1,dim);
163 FiniteElementSpace *hatsigma_fes = new FiniteElementSpace(&mesh,hatsigma_fec);
164
165 // test space fe collections
166 int test_order = order+delta_order;
167 FiniteElementCollection * tau_fec = new RT_FECollection(test_order-1, dim);
168 FiniteElementCollection * v_fec = new H1_FECollection(test_order, dim);
169
172
173 trial_fes.Append(u_fes);
174 trial_fes.Append(sigma_fes);
175 trial_fes.Append(hatu_fes);
176 trial_fes.Append(hatsigma_fes);
177 test_fec.Append(tau_fec);
178 test_fec.Append(v_fec);
179
180 // Required coefficients for the weak formulation
181 ConstantCoefficient one(1.0);
182 ConstantCoefficient negone(-1.0);
183 FunctionCoefficient f(f_exact); // rhs for the manufactured solution problem
184
185 // Required coefficients for the exact solution case
189
190 // Define the DPG weak formulation
191 DPGWeakForm * a = new DPGWeakForm(trial_fes,test_fec);
192
193 // -(u,∇⋅τ)
194 a->AddTrialIntegrator(new MixedScalarWeakGradientIntegrator(one),
195 TrialSpace::u_space,TestSpace::tau_space);
196
197 // -(σ,τ)
198 a->AddTrialIntegrator(new TransposeIntegrator(new VectorFEMassIntegrator(
199 negone)), TrialSpace::sigma_space, TestSpace::tau_space);
200
201 // (σ,∇ v)
202 a->AddTrialIntegrator(new TransposeIntegrator(new GradientIntegrator(one)),
203 TrialSpace::sigma_space,TestSpace::v_space);
204
205 // <û,τ⋅n>
206 a->AddTrialIntegrator(new NormalTraceIntegrator,
207 TrialSpace::hatu_space,TestSpace::tau_space);
208
209 // -<σ̂,v> (sign is included in σ̂)
210 a->AddTrialIntegrator(new TraceIntegrator,
211 TrialSpace::hatsigma_space, TestSpace::v_space);
212
213 // test integrators (space-induced norm for H(div) × H1)
214 // (∇⋅τ,∇⋅δτ)
215 a->AddTestIntegrator(new DivDivIntegrator(one),
216 TestSpace::tau_space, TestSpace::tau_space);
217 // (τ,δτ)
218 a->AddTestIntegrator(new VectorFEMassIntegrator(one),
219 TestSpace::tau_space, TestSpace::tau_space);
220 // (∇v,∇δv)
221 a->AddTestIntegrator(new DiffusionIntegrator(one),
222 TestSpace::v_space, TestSpace::v_space);
223 // (v,δv)
224 a->AddTestIntegrator(new MassIntegrator(one),
225 TestSpace::v_space, TestSpace::v_space);
226
227 // RHS
228 if (prob == prob_type::manufactured)
229 {
230 a->AddDomainLFIntegrator(new DomainLFIntegrator(f),TestSpace::v_space);
231 }
232 else
233 {
234 a->AddDomainLFIntegrator(new DomainLFIntegrator(one),TestSpace::v_space);
235 }
236
237 // GridFunction for Dirichlet bdr data
238 GridFunction hatu_gf;
239
240 // Visualization streams
241 socketstream u_out;
242 socketstream sigma_out;
243
244 if (prob == prob_type::manufactured)
245 {
246 std::cout << "\n Ref |"
247 << " Dofs |"
248 << " L2 Error |"
249 << " Rate |"
250 << " PCG it |" << endl;
251 std::cout << std::string(50,'-')
252 << endl;
253 }
254
255 real_t err0 = 0.;
256 int dof0=0.;
257 if (static_cond) { a->EnableStaticCondensation(); }
258 for (int it = 0; it<=ref; it++)
259 {
260 a->Assemble();
261
262 Array<int> ess_tdof_list;
263 Array<int> ess_bdr;
264 if (mesh.bdr_attributes.Size())
265 {
266 ess_bdr.SetSize(mesh.bdr_attributes.Max());
267 ess_bdr = 1;
268 hatu_fes->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
269 }
270
271 // shift the ess_tdofs
272 for (int i = 0; i < ess_tdof_list.Size(); i++)
273 {
274 ess_tdof_list[i] += u_fes->GetTrueVSize() + sigma_fes->GetTrueVSize();
275 }
276
277 Array<int> offsets(5);
278 offsets[0] = 0;
279 offsets[1] = u_fes->GetVSize();
280 offsets[2] = sigma_fes->GetVSize();
281 offsets[3] = hatu_fes->GetVSize();
282 offsets[4] = hatsigma_fes->GetVSize();
283 offsets.PartialSum();
284
285 BlockVector x(offsets);
286 x = 0.0;
287 if (prob == prob_type::manufactured)
288 {
289 hatu_gf.MakeRef(hatu_fes,x.GetBlock(2),0);
290 hatu_gf.ProjectBdrCoefficient(hatuex,ess_bdr);
291 }
292
293 OperatorPtr Ah;
294 Vector X,B;
295 a->FormLinearSystem(ess_tdof_list,x,Ah,X,B);
296
297 BlockMatrix * A = Ah.As<BlockMatrix>();
298
300 M.owns_blocks = 1;
301 for (int i=0; i<A->NumRowBlocks(); i++)
302 {
303 M.SetDiagonalBlock(i,new GSSmoother(A->GetBlock(i,i)));
304 }
305
306 CGSolver cg;
307 cg.SetRelTol(1e-10);
308 cg.SetMaxIter(2000);
309 cg.SetPrintLevel(prob== prob_type::general ? 3 : 0);
310 cg.SetPreconditioner(M);
311 cg.SetOperator(*A);
312 cg.Mult(B, X);
313
314 a->RecoverFEMSolution(X,x);
315
316 GridFunction u_gf, sigma_gf;
317 u_gf.MakeRef(u_fes,x.GetBlock(0),0);
318 sigma_gf.MakeRef(sigma_fes,x.GetBlock(1),0);
319
320 if (prob == prob_type::manufactured)
321 {
322 int l2dofs = u_fes->GetVSize() + sigma_fes->GetVSize();
323 real_t u_err = u_gf.ComputeL2Error(uex);
324 real_t sigma_err = sigma_gf.ComputeL2Error(sigmaex);
325 real_t L2Error = sqrt(u_err*u_err + sigma_err*sigma_err);
326 real_t rate_err = (it) ? dim*log(err0/L2Error)/log((real_t)dof0/l2dofs) : 0.0;
327 err0 = L2Error;
328 dof0 = l2dofs;
329
330 std::ios oldState(nullptr);
331 oldState.copyfmt(std::cout);
332 std::cout << std::right << std::setw(5) << it << " | "
333 << std::setw(10) << dof0 << " | "
334 << std::setprecision(3)
335 << std::setw(10) << std::scientific << err0 << " | "
336 << std::setprecision(2)
337 << std::setw(6) << std::fixed << rate_err << " | "
338 << std::setw(6) << std::fixed << cg.GetNumIterations() << " | "
339 << std::endl;
340 std::cout.copyfmt(oldState);
341 }
342
343 if (visualization)
344 {
345 const char * keys = (it == 0 && dim == 2) ? "jRcm\n" : nullptr;
346 char vishost[] = "localhost";
347 VisualizeField(u_out,vishost, visport, u_gf,
348 "Numerical u", 0,0, 500, 500, keys);
349 VisualizeField(sigma_out,vishost, visport, sigma_gf,
350 "Numerical flux", 500,0,500, 500, keys);
351 }
352
353 if (it == ref) { break; }
354
355 mesh.UniformRefinement();
356 for (int i =0; i<trial_fes.Size(); i++)
357 {
358 trial_fes[i]->Update(false);
359 }
360 a->Update();
361 }
362
363 delete a;
364 delete tau_fec;
365 delete v_fec;
366 delete hatsigma_fes;
367 delete hatsigma_fec;
368 delete hatu_fes;
369 delete hatu_fec;
370 delete sigma_fec;
371 delete sigma_fes;
372 delete u_fec;
373 delete u_fes;
374
375 return 0;
376}
377
379{
380 real_t alpha = M_PI * (X.Sum());
381 return sin(alpha);
382}
383
384void exact_gradu(const Vector & X, Vector & du)
385{
386 du.SetSize(X.Size());
387 real_t alpha = M_PI * (X.Sum());
388 du.SetSize(X.Size());
389 for (int i = 0; i<du.Size(); i++)
390 {
391 du[i] = M_PI * cos(alpha);
392 }
393}
394
396{
397 real_t alpha = M_PI * (X.Sum());
398 real_t u = sin(alpha);
399 return - M_PI*M_PI * u * X.Size();
400}
401
402void exact_sigma(const Vector & X, Vector & sigma)
403{
404 // σ = ∇ u
406}
407
409{
410 return exact_u(X);
411}
412
413void exact_hatsigma(const Vector & X, Vector & hatsigma)
414{
415 exact_sigma(X,hatsigma);
416 hatsigma *= -1.;
417}
418
420{
421 return -exact_laplacian_u(X);
422}
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:68
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:758
int Size() const
Return the logical size of the array.
Definition array.hpp:147
void PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
Definition array.cpp:103
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:830
A class to handle Block diagonal preconditioners in a matrix-free implementation.
SparseMatrix & GetBlock(int i, int j)
Return a reference to block (i,j). Reference may be invalid if Aij(i,j) == NULL.
Array< int > & RowOffsets()
Return the row offsets for block starts.
int NumRowBlocks() const
Return the number of row blocks.
A class to handle Vectors in a block fashion.
Vector & GetBlock(int i)
Get the i-th vector in the block.
Conjugate gradient method.
Definition solvers.hpp:538
void Mult(const Vector &b, Vector &x) const override
Iterative solution of the linear system using the Conjugate Gradient method.
Definition solvers.cpp:751
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
Definition solvers.hpp:551
A coefficient that is constant across space and time.
Class representing the DPG weak formulation. Given the variational formulation a(u,...
Definition weakform.hpp:34
for Raviart-Thomas elements
Class for domain integration .
Definition lininteg.hpp:106
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:244
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
Definition fespace.hpp:851
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:658
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition fespace.hpp:848
A general function coefficient.
Data type for Gauss-Seidel smoother of sparse matrix.
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
virtual void MakeRef(FiniteElementSpace *f, real_t *v)
Make the GridFunction reference external data on a new FiniteElementSpace.
Definition gridfunc.cpp:233
virtual real_t ComputeL2Error(Coefficient *exsol[], const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const
Returns ||exsol - u_h||_L2 for scalar or vector H1 or L2 elements.
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:481
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:275
Arbitrary order "H^{1/2}-conforming" trace finite elements defined on the interface between mesh elem...
Definition fe_coll.hpp:338
void SetRelTol(real_t rtol)
Definition solvers.hpp:229
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Definition solvers.cpp:174
int GetNumIterations() const
Returns the number of iterations taken during the last call to Mult()
Definition solvers.hpp:280
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Definition solvers.cpp:72
void SetMaxIter(int max_it)
Definition solvers.hpp:231
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:346
Mesh data type.
Definition mesh.hpp:64
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:290
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11295
Pointer to an Operator of a specified type.
Definition handle.hpp:34
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get().
Definition handle.hpp:104
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
void PrintUsage(std::ostream &out) const
Print the usage message.
void PrintOptions(std::ostream &out) const
Print the options.
void AddOption(bool *var, const char *enable_short_name, const char *enable_long_name, const char *disable_short_name, const char *disable_long_name, const char *description, bool required=false)
Add a boolean option and set 'var' to receive the value. Enable/disable tags are used to set the bool...
Definition optparser.hpp:82
bool Good() const
Return true if the command line options were parsed successfully.
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Definition fe_coll.hpp:403
Arbitrary order "H^{-1/2}-conforming" face finite elements defined on the interface between mesh elem...
Definition fe_coll.hpp:462
A general vector function coefficient.
Vector data type.
Definition vector.hpp:82
int Size() const
Returns the size of the vector.
Definition vector.hpp:226
real_t Sum() const
Return the sum of the vector entries.
Definition vector.cpp:1204
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:558
real_t sigma(const Vector &x)
Definition maxwell.cpp:102
const real_t alpha
Definition ex15.cpp:369
int dim
Definition ex24.cpp:53
prob_type
Definition ex25.cpp:149
int main()
real_t a
Definition lissajous.cpp:41
void exact_gradu(const Vector &X, Vector &gradu)
real_t exact_hatu(const Vector &X)
real_t exact_laplacian_u(const Vector &X)
real_t exact_u(const Vector &X)
void exact_sigma(const Vector &X, Vector &sigma)
void exact_hatsigma(const Vector &X, Vector &hatsigma)
prob_type prob
Definition diffusion.cpp:82
prob_type
Definition diffusion.cpp:77
@ general
Definition diffusion.cpp:79
@ manufactured
Definition diffusion.cpp:78
real_t f_exact(const Vector &X)
void VisualizeField(socketstream &sock, const char *vishost, int visport, GridFunction &gf, const char *title, int x, int y, int w, int h, const char *keys, bool vec)
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
float real_t
Definition config.hpp:43
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
const char vishost[]