MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
lor-transfer.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// --------------------------------------------------------------
13// LOR Transfer Miniapp: Map functions between HO and LOR spaces
14// --------------------------------------------------------------
15//
16// This miniapp visualizes the maps between a high-order (HO) finite element
17// space, typically using high-order functions on a high-order mesh, and a
18// low-order refined (LOR) finite element space, typically defined by 0th or 1st
19// order functions on a low-order refinement of the HO mesh.
20//
21// The grid transfer operators are represented using either
22// InterpolationGridTransfer or L2ProjectionGridTransfer (depending on the
23// options requested by the user). The two transfer operators are then:
24//
25// 1. R: HO -> LOR, defined by GridTransfer::ForwardOperator
26// 2. P: LOR -> HO, defined by GridTransfer::BackwardOperator
27//
28// While defined generally, these operators have some nice properties for
29// particular finite element spaces. For example they satisfy PR=I, plus mass
30// conservation in both directions for L2 fields.
31//
32// Compile with: make lor-transfer
33//
34// Sample runs: lor-transfer
35// lor-transfer -h1
36// lor-transfer -t
37// lor-transfer -m ../../data/star-q2.mesh -lref 5 -p 4
38// lor-transfer -m ../../data/star-mixed.mesh -lref 3 -p 2
39// lor-transfer -lref 4 -o 4 -lo 0 -p 1
40// lor-transfer -lref 5 -o 4 -lo 0 -p 1
41// lor-transfer -lref 5 -o 4 -lo 3 -p 2
42// lor-transfer -lref 5 -o 4 -lo 0 -p 3
43
44#include "mfem.hpp"
45#include <fstream>
46#include <iostream>
47
48using namespace std;
49using namespace mfem;
50
51int problem = 1; // problem type
52
53int Wx = 0, Wy = 0; // window position
54int Ww = 350, Wh = 350; // window size
55int offx = Ww+5, offy = Wh+25; // window offsets
56
57string space;
58string direction;
59
60// Exact functions to project
61real_t RHO_exact(const Vector &x);
62
63// Helper functions
64void visualize(VisItDataCollection &, string, int, int, int visport = 19916);
66 string);
67
68int main(int argc, char *argv[])
69{
70 // Parse command-line options.
71 const char *mesh_file = "../../data/star.mesh";
72 int order = 3;
73 int lref = order+1;
74 int lorder = 0;
75 bool vis = true;
76 bool useH1 = false;
77 int visport = 19916;
78 bool use_pointwise_transfer = false;
79 const char *device_config = "cpu";
80 bool use_ea = false;
81
82 OptionsParser args(argc, argv);
83 args.AddOption(&mesh_file, "-m", "--mesh",
84 "Mesh file to use.");
85 args.AddOption(&problem, "-p", "--problem",
86 "Problem type (see the RHO_exact function).");
87 args.AddOption(&order, "-o", "--order",
88 "Finite element order (polynomial degree) or -1 for"
89 " isoparametric space.");
90 args.AddOption(&lref, "-lref", "--lor-ref-level", "LOR refinement level.");
91 args.AddOption(&lorder, "-lo", "--lor-order",
92 "LOR space order (polynomial degree, zero by default).");
93 args.AddOption(&vis, "-vis", "--visualization", "-no-vis",
94 "--no-visualization",
95 "Enable or disable GLVis visualization.");
96 args.AddOption(&useH1, "-h1", "--use-h1", "-l2", "--use-l2",
97 "Use H1 spaces instead of L2.");
98 args.AddOption(&use_pointwise_transfer, "-t", "--use-pointwise-transfer",
99 "-no-t", "--dont-use-pointwise-transfer",
100 "Use pointwise transfer operators instead of L2 projection.");
101 args.AddOption(&device_config, "-d", "--device",
102 "Device configuration string, see Device::Configure().");
103 args.AddOption(&use_ea, "-ea", "--ea-version", "-no-ea",
104 "--no-ea-version", "Use element assembly version.");
105 args.ParseCheck();
106
107 // Configure device
108 Device device(device_config);
109
110 // Read the mesh from the given mesh file.
111 Mesh mesh(mesh_file, 1, 1);
112 int dim = mesh.Dimension();
113
114 // Create the low-order refined mesh
115 int basis_lor = BasisType::GaussLobatto; // BasisType::ClosedUniform;
116 Mesh mesh_lor = Mesh::MakeRefined(mesh, lref, basis_lor);
117
118 // Create spaces
119 FiniteElementCollection *fec, *fec_lor;
120 if (useH1)
121 {
122 space = "H1";
123 if (lorder == 0)
124 {
125 lorder = 1;
126 cerr << "Switching the H1 LOR space order from 0 to 1\n";
127 }
128 fec = new H1_FECollection(order, dim);
129 fec_lor = new H1_FECollection(lorder, dim);
130 }
131 else
132 {
133 space = "L2";
134 fec = new L2_FECollection(order, dim);
135 fec_lor = new L2_FECollection(lorder, dim);
136 }
137
138 FiniteElementSpace fespace(&mesh, fec);
139 FiniteElementSpace fespace_lor(&mesh_lor, fec_lor);
140
141 GridFunction rho(&fespace);
142 GridFunction rho_lor(&fespace_lor);
143
144 // Data collections for vis/analysis
145 VisItDataCollection HO_dc("HO", &mesh);
146 HO_dc.RegisterField("density", &rho);
147 VisItDataCollection LOR_dc("LOR", &mesh_lor);
148 LOR_dc.RegisterField("density", &rho_lor);
149
150 BilinearForm M_ho(&fespace);
152 M_ho.Assemble();
153 M_ho.Finalize();
154
155 BilinearForm M_lor(&fespace_lor);
157 M_lor.Assemble();
158 M_lor.Finalize();
159
160 // HO projections
161 direction = "HO -> LOR @ HO";
163 rho.ProjectCoefficient(RHO);
164 // Make sure AMR constraints are satisfied
165 rho.SetTrueVector();
166 rho.SetFromTrueVector();
167
168 real_t ho_mass = compute_mass(&fespace, -1.0, HO_dc, "HO ");
169 if (vis) { visualize(HO_dc, "HO", Wx, Wy, visport); Wx += offx; }
170
171 GridTransfer *gt;
172 if (use_pointwise_transfer)
173 {
174 gt = new InterpolationGridTransfer(fespace, fespace_lor);
175 }
176 else
177 {
178 gt = new L2ProjectionGridTransfer(fespace, fespace_lor);
179 }
180
181 // Configure element assembly for device acceleration
182 gt->UseEA(use_ea);
183
184 const Operator &R = gt->ForwardOperator();
185
186 // HO->LOR restriction
187 direction = "HO -> LOR @ LOR";
188 R.Mult(rho, rho_lor);
189 compute_mass(&fespace_lor, ho_mass, LOR_dc, "R(HO) ");
190 if (vis) { visualize(LOR_dc, "R(HO)", Wx, Wy, visport); Wx += offx; }
191
193 {
194 const Operator &P = gt->BackwardOperator();
195 // LOR->HO prolongation
196 direction = "HO -> LOR @ HO";
197 GridFunction rho_prev = rho;
198 P.Mult(rho_lor, rho);
199 compute_mass(&fespace, ho_mass, HO_dc, "P(R(HO)) ");
200 if (vis) { visualize(HO_dc, "P(R(HO))", Wx, Wy, visport); Wx = 0; Wy += offy; }
201
202 rho_prev -= rho;
203 cout.precision(12);
204 cout << "|HO - P(R(HO))|_∞ = " << rho_prev.Normlinf() << endl;
205 }
206
207 // HO* to LOR* dual fields
208 LinearForm M_rho(&fespace), M_rho_lor(&fespace_lor);
209 if (!use_pointwise_transfer && gt->SupportsBackwardsOperator())
210 {
211 const Operator &P = gt->BackwardOperator();
212 M_ho.Mult(rho, M_rho);
213 P.MultTranspose(M_rho, M_rho_lor);
214 cout << "HO -> LOR dual field: " << abs(M_rho.Sum()-M_rho_lor.Sum()) << "\n\n";
215 }
216
217 // LOR projections
218 direction = "LOR -> HO @ LOR";
219 rho_lor.ProjectCoefficient(RHO);
220 GridFunction rho_lor_prev = rho_lor;
221 real_t lor_mass = compute_mass(&fespace_lor, -1.0, LOR_dc, "LOR ");
222 if (vis) { visualize(LOR_dc, "LOR", Wx, Wy, visport); Wx += offx; }
223
225 {
226 const Operator &P = gt->BackwardOperator();
227 // Prolongate to HO space
228 direction = "LOR -> HO @ HO";
229 P.Mult(rho_lor, rho);
230 compute_mass(&fespace, lor_mass, HO_dc, "P(LOR) ");
231 if (vis) { visualize(HO_dc, "P(LOR)", Wx, Wy, visport); Wx += offx; }
232
233 // Restrict back to LOR space. This won't give the original function because
234 // the rho_lor doesn't necessarily live in the range of R.
235 direction = "LOR -> HO @ LOR";
236 R.Mult(rho, rho_lor);
237 compute_mass(&fespace_lor, lor_mass, LOR_dc, "R(P(LOR))");
238 if (vis) { visualize(LOR_dc, "R(P(LOR))", Wx, Wy, visport); }
239
240 rho_lor_prev -= rho_lor;
241 cout.precision(12);
242 cout << "|LOR - R(P(LOR))|_∞ = " << rho_lor_prev.Normlinf() << endl;
243 }
244
245 // LOR* to HO* dual fields
246 if (!use_pointwise_transfer)
247 {
248 M_lor.Mult(rho_lor, M_rho_lor);
249 R.MultTranspose(M_rho_lor, M_rho);
250 cout << "LOR -> HO dual field: " << abs(M_rho.Sum() - M_rho_lor.Sum()) << '\n';
251 }
252
253 delete gt;
254 delete fec;
255 delete fec_lor;
256
257 return 0;
258}
259
260
262{
263 switch (problem)
264 {
265 case 1: // smooth field
266 return x(1)+0.25*cos(2*M_PI*x.Norml2());
267 case 2: // cubic function
268 return x(1)*x(1)*x(1) + 2*x(0)*x(1) + x(0);
269 case 3: // sharp gradient
270 return M_PI/2-atan(5*(2*x.Norml2()-1));
271 case 4: // basis function
272 return (x.Norml2() < 0.1) ? 1 : 0;
273 default:
274 return 1.0;
275 }
276}
277
278
279void visualize(VisItDataCollection &dc, string prefix, int x, int y,
280 int visport)
281{
282 int w = Ww, h = Wh;
283
284 char vishost[] = "localhost";
285
286 socketstream sol_sockL2(vishost, visport);
287 sol_sockL2.precision(8);
288 sol_sockL2 << "solution\n" << *dc.GetMesh() << *dc.GetField("density")
289 << "window_geometry " << x << " " << y << " " << w << " " << h
290 << "plot_caption '" << space << " " << prefix << " Density'"
291 << "window_title '" << direction << "'" << flush;
292}
293
294
296 VisItDataCollection &dc, string prefix)
297{
298 ConstantCoefficient one(1.0);
299 LinearForm lf(L2);
301 lf.Assemble();
302
303 real_t newmass = lf(*dc.GetField("density"));
304 cout.precision(18);
305 cout << space << " " << prefix << " mass = " << newmass;
306 if (massL2 >= 0)
307 {
308 cout.precision(4);
309 cout << " (" << fabs(newmass-massL2)*100/massL2 << "%)";
310 }
311 cout << endl;
312 return newmass;
313}
@ GaussLobatto
Closed type.
Definition fe_base.hpp:36
A "square matrix" operator for the associated FE space and BLFIntegrators The sum of all the BLFInteg...
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 Assemble(int skip_zeros=1)
Assembles the form i.e. sums over all domain/bdr integrators.
void Mult(const Vector &x, Vector &y) const override
Matrix vector multiplication: .
A coefficient that is constant across space and time.
GridFunction * GetField(const std::string &field_name)
Get a pointer to a grid function in the collection.
Mesh * GetMesh()
Get a pointer to the mesh in the collection.
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
Definition device.hpp:123
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
A general function coefficient.
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
void SetTrueVector()
Shortcut for calling GetTrueDofs() with GetTrueVector() as argument.
Definition gridfunc.hpp:147
void SetFromTrueVector()
Shortcut for calling SetFromTrueDofs() with GetTrueVector() as argument.
Definition gridfunc.hpp:153
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
Base class for transfer algorithms that construct transfer Operators between two finite element (FE) ...
Definition transfer.hpp:30
void UseEA(bool use_ea_)
Definition transfer.hpp:76
virtual bool SupportsBackwardsOperator() const
Definition transfer.hpp:115
virtual const Operator & ForwardOperator()=0
Return an Operator that transfers GridFunctions from the domain FE space to GridFunctions in the rang...
virtual const Operator & BackwardOperator()=0
Return an Operator that transfers GridFunctions from the range FE space back to GridFunctions in the ...
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:275
Transfer data between a coarse mesh and an embedded refined mesh using interpolation.
Definition transfer.hpp:137
Transfer data in L2 and H1 finite element spaces between a coarse mesh and an embedded refined mesh u...
Definition transfer.hpp:184
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:346
Vector with associated FE space and LinearFormIntegrators.
void AddDomainIntegrator(LinearFormIntegrator *lfi)
Adds new Domain Integrator. Assumes ownership of lfi.
void Assemble()
Assembles the linear form i.e. sums over all domain/bdr integrators.
Mesh data type.
Definition mesh.hpp:64
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
static Mesh MakeRefined(Mesh &orig_mesh, int ref_factor, int ref_type)
Create a refined (by any factor) version of orig_mesh.
Definition mesh.cpp:4518
Abstract operator.
Definition operator.hpp:25
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
Definition operator.hpp:93
void ParseCheck(std::ostream &out=mfem::out)
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
Vector data type.
Definition vector.hpp:82
real_t Normlinf() const
Returns the l_infinity norm of the vector.
Definition vector.cpp:972
real_t Norml2() const
Returns the l2 norm of the vector.
Definition vector.cpp:931
real_t Sum() const
Return the sum of the vector entries.
Definition vector.cpp:1204
Data collection with VisIt I/O routines.
void RegisterField(const std::string &field_name, GridFunction *gf) override
Add a grid function to the collection and update the root file.
int dim
Definition ex24.cpp:53
int main()
int Ww
void visualize(VisItDataCollection &, string, int, int, int visport=19916)
int Wy
int Wx
int problem
int offx
int Wh
string direction
real_t RHO_exact(const Vector &x)
string space
int offy
real_t compute_mass(FiniteElementSpace *, real_t, VisItDataCollection &, string)
float real_t
Definition config.hpp:43
const char vishost[]