libMesh
Loading...
Searching...
No Matches
reduced_basis_ex6.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18// rbOOmit: An implementation of the Certified Reduced Basis method.
19// Copyright (C) 2009, 2010 David J. Knezevic
20// This file is part of rbOOmit.
21
22
23
24// <h1>Reduced Basis: Example 6 - Heat transfer on a curved domain in 3D</h1>
25// \author David Knezevic
26// \date 2012
27//
28// In this example we consider heat transfer modeled by a Poisson
29// equation with Robin boundary condition:
30//
31// -kappa \Laplacian u = 1, on \Omega
32// -kappa du\dn = kappa Bi u, on \partial\Omega_Biot,
33// u = 0 on \partial\Omega_Dirichlet,
34//
35// We consider a reference domain \Omega_hat =
36// [-0.2,0.2]x[-0.2,0.2]x[0,3], and the physical domain is then obtain
37// via the parametrized mapping:
38//
39// x = -1/mu + (1/mu+x_hat)*cos(mu*z_hat)
40// y = y_hat
41// z = (1/mu+x_hat)*sin(mu*z_hat)
42//
43// for (x_hat,y_hat,z_hat) \in \Omega_hat. (Here "hats" denotes
44// reference domain.) Also, the "reference Dirichlet boundaries" are
45// [-0.2,0.2]x[-0.2,0.2]x{0} and [-0.2,0.2]x[-0.2,0.2]x{3}, and the
46// remaining boundaries are the "Biot" boundaries.
47//
48// Then, after putting the PDE into weak form and mapping it to the
49// reference domain, we obtain:
50// \kappa \int_\Omega_hat
51// [ (1+mu*x_hat) v_x w_x + (1+mu*x_hat) v_y w_y + 1/(1+mu*x_hat) v_z w_z ]
52// + \kappa Bi \int_\partial\Omega_hat_Biot1 (1-0.2mu) u v
53// + \kappa Bi \int_\partial\Omega_hat_Biot2 (1+mu x_hat) u v
54// + \kappa Bi \int_\partial\Omega_hat_Biot3 (1+0.2mu) u v
55// = \int_\Omega_hat (1+mu x_hat) v
56// where
57// \partial\Omega_hat_Biot1 = [-0.2] x [-0.2,0.2] x [0,3]
58// \partial\Omega_hat_Biot2 = [-0.2,0.2] x {-0.2} x [0,3] \UNION [-0.2,0.2] x {0.2} x [0,3]
59// \partial\Omega_hat_Biot3 = [0.2] x [-0.2,0.2] x [0,3]
60//
61// The term
62// \kappa \int_\Omega_hat 1/(1+mu*x_hat) v_z w_z
63// is "non-affine" (in the Reduced Basis sense), since we can't
64// express it in the form \sum theta_q(kappa,mu) a(v,w). As a result,
65// (as in reduced_basis_ex4) we must employ the Empirical
66// Interpolation Method (EIM) in order to apply the Reduced Basis
67// method here.
68//
69// The approach we use is to construct an EIM approximation, G_EIM, to
70// the vector-valued function G(x_hat,y_hat;mu) = (1 + mu*x_hat, 1 +
71// mu*x_hat, 1/(1+mu*x_hat)) and then we express the "volumetric
72// integral part" of the left-hand side operator as a(v,w;mu) =
73// \int_\hat\Omega G_EIM(x_hat,y_hat;mu) \dot (v_x w_x, v_y w_y, v_z
74// w_z). (We actually only need EIM for the third component of
75// G_EIM, but it's helpful to demonstrate "vector-valued" EIM here.)
76
77// C++ include files that we need
78#include <iostream>
79#include <algorithm>
80#include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
81#include <cmath>
82#include <set>
83
84// Basic include file needed for the mesh functionality.
85#include "libmesh/libmesh.h"
86#include "libmesh/mesh.h"
87#include "libmesh/mesh_generation.h"
88#include "libmesh/exodusII_io.h"
89#include "libmesh/equation_systems.h"
90#include "libmesh/dof_map.h"
91#include "libmesh/getpot.h"
92#include "libmesh/elem.h"
93#include "libmesh/rb_data_serialization.h"
94#include "libmesh/rb_data_deserialization.h"
95#include "libmesh/enum_solver_package.h"
96
97// local includes
98#include "rb_classes.h"
99#include "eim_classes.h"
100#include "assembly.h"
101
102// Bring in everything from the libMesh namespace
103using namespace libMesh;
104
105// Define a function to scale the mesh according to the parameter.
107 Real curvature,
108 const std::string & filename);
109
110// The main program.
111int main (int argc, char ** argv)
112{
113 // Initialize libMesh.
114 LibMeshInit init (argc, argv);
115
116 // This example requires a linear solver package.
117 libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE,
118 "--enable-petsc, --enable-trilinos, or --enable-eigen");
119
120#if !defined(LIBMESH_HAVE_XDR)
121 // We need XDR support to write out reduced bases
122 libmesh_example_requires(false, "--enable-xdr");
123#elif defined(LIBMESH_DEFAULT_SINGLE_PRECISION)
124 // XDR binary support requires double precision
125 libmesh_example_requires(false, "--disable-singleprecision");
126#elif defined(LIBMESH_DEFAULT_TRIPLE_PRECISION)
127 // I have no idea why long double isn't working here... [RHS]
128 libmesh_example_requires(false, "double precision");
129#elif defined(LIBMESH_ENABLE_BLOCKED_STORAGE)
130 // This example dies with "New nonzero at (0,2) caused a malloc"
131 // when blocked storage is enabled.
132 libmesh_example_requires(false, "--disable-blocked-storage");
133#endif
134
135 // This is a 3D example
136 libmesh_example_requires(3 == LIBMESH_DIM, "3D support");
137
138 // This example requires libmesh to be configured with both
139 // DirichletBoundary and Cap'n Proto support.
140#if !defined(LIBMESH_ENABLE_DIRICHLET) || !defined(LIBMESH_HAVE_CAPNPROTO)
141 libmesh_example_requires(false, "--enable-dirichlet --enable-capnp");
142#else
143
144 // Parse the input file using GetPot
145 std::string eim_parameters = "eim.in";
146 std::string rb_parameters = "rb.in";
147 std::string main_parameters = "reduced_basis_ex6.in";
148 GetPot infile(main_parameters);
149
150 unsigned int n_elem_xy = infile("n_elem_xy", 1);
151 unsigned int n_elem_z = infile("n_elem_z", 1);
152
153 // Read the "online_mode" flag from the command line
154 const int online_mode =
155 libMesh::command_line_next("-online_mode", 0);
156
157 // Create a mesh, with dimension to be overridden by build_cube, on
158 // the default MPI communicator. We currently have to create a
159 // ReplicatedMesh here due to a reduced_basis regression with
160 // DistributedMesh
161 ReplicatedMesh mesh(init.comm());
162
164 n_elem_xy, n_elem_xy, n_elem_z,
165 -0.2, 0.2,
166 -0.2, 0.2,
167 0., 3.,
168 HEX8);
169
170 if (!online_mode)
171 {
172 // First run the Offline stage for the EIM approximation.
173 {
174 libMesh::out << "Perform EIM training" << std::endl << std::endl;
175
176 // Initialize the EquationSystems object for this mesh and attach
177 // the EIM and RB Construction objects
178 EquationSystems equation_systems (mesh);
179
180 SimpleEIMConstruction & eim_construction =
181 equation_systems.add_system<SimpleEIMConstruction> ("EIM");
182
183 // Initialize the data structures for the equation system.
184 equation_systems.init ();
185
186 // Print out some information about the "truth" discretization
188 equation_systems.print_info();
189
190 // Initialize the EIM RBEvaluation object
191 SimpleEIMEvaluation eim_rb_eval(mesh.comm());
192
193 // Set the rb_eval objects for the RBConstructions
194 eim_construction.set_rb_eim_evaluation(eim_rb_eval);
195
196 // Read data from input file and print state
197 eim_construction.process_parameters_file(eim_parameters);
198 eim_construction.print_info();
199
200 // Perform the EIM Greedy and write out the data
201 eim_construction.initialize_eim_construction();
202 eim_construction.train_eim_approximation();
203
204 RBDataSerialization::RBEIMEvaluationSerialization rb_eim_eval_writer(eim_rb_eval);
205 rb_eim_eval_writer.write_to_file("rb_eim_eval.bin");
206
207 // Write out the EIM basis functions
208 eim_rb_eval.write_out_basis_functions("eim_data", /*binary=*/false);
209 }
210
211 {
212 libMesh::out << std::endl << "Perform RB training" << std::endl << std::endl;
213
214 // Create an equation systems object.
215 EquationSystems equation_systems (mesh);
216
217 SimpleEIMConstruction & eim_construction =
218 equation_systems.add_system<SimpleEIMConstruction> ("EIM");
219 SimpleRBConstruction & rb_construction =
220 equation_systems.add_system<SimpleRBConstruction> ("RB");
221
222 // Initialize the data structures for the equation system.
223 equation_systems.init ();
224
225 // Print out some information about the "truth" discretization
226 equation_systems.print_info();
228
229 // Initialize the standard RBEvaluation object
230 SimpleRBEvaluation rb_eval(mesh.comm());
231
232 // Initialize the EIM RBEvaluation object
233 SimpleEIMEvaluation eim_rb_eval(mesh.comm());
234
235 // Set the rb_eval objects for the RBConstructions
236 eim_construction.set_rb_eim_evaluation(eim_rb_eval);
237 rb_construction.set_rb_evaluation(rb_eval);
238
239 RBDataDeserialization::RBEIMEvaluationDeserialization rb_eim_eval_reader(eim_rb_eval);
240 rb_eim_eval_reader.read_from_file("rb_eim_eval.bin");
241 eim_rb_eval.read_in_basis_functions(rb_construction, "eim_data", /*binary=*/false);
242
243 // Read data from input file and print state
244 rb_construction.process_parameters_file(rb_parameters);
245
246 // attach the EIM theta objects to the RBEvaluation
247 eim_rb_eval.initialize_eim_theta_objects();
248 rb_eval.get_rb_theta_expansion().attach_multiple_A_theta(eim_rb_eval.get_eim_theta_objects());
249
250 // attach the EIM assembly objects to the RBConstruction
251 eim_construction.initialize_eim_assembly_objects();
252 rb_construction.get_rb_assembly_expansion().attach_multiple_A_assembly(eim_construction.get_eim_assembly_objects());
253
254 // Print out the state of rb_construction now that the EIM objects have been attached
255 rb_construction.print_info();
256
257 // Need to initialize _after_ EIM greedy so that
258 // the system knows how many affine terms there are
259 rb_construction.initialize_rb_construction();
260 rb_construction.train_reduced_basis();
261
262 RBDataSerialization::RBEvaluationSerialization rb_eval_writer(rb_construction.get_rb_evaluation());
263 rb_eval_writer.write_to_file("rb_eval.bin");
264
265 // Write out the basis functions
266 rb_construction.get_rb_evaluation().write_out_basis_functions(rb_construction,
267 "rb_data");
268 }
269 }
270 else
271 {
272 SimpleEIMEvaluation eim_rb_eval(mesh.comm());
273 SimpleRBEvaluation rb_eval(mesh.comm());
274
275 RBDataDeserialization::RBEIMEvaluationDeserialization rb_eim_eval_reader(eim_rb_eval);
276 rb_eim_eval_reader.read_from_file("rb_eim_eval.bin");
277
278 // attach the EIM theta objects to rb_eval objects
279 eim_rb_eval.initialize_eim_theta_objects();
280 rb_eval.get_rb_theta_expansion().attach_multiple_A_theta(eim_rb_eval.get_eim_theta_objects());
281
283 rb_eval_reader.read_from_file("rb_eval.bin", /*read_error_bound_data*/ true);
284
285 // Get the parameters at which we will do a reduced basis solve
286 Real online_curvature = infile("online_curvature", 0.);
287 Real online_Bi = infile("online_Bi", 0.);
288 Real online_kappa = infile("online_kappa", 0.);
289 RBParameters online_mu;
290 online_mu.set_value("curvature", online_curvature);
291 online_mu.set_value("Bi", online_Bi);
292 online_mu.set_value("kappa", online_kappa);
293 rb_eval.set_parameters(online_mu);
294 rb_eval.print_parameters();
295 rb_eval.rb_solve(rb_eval.get_n_basis_functions());
296
297 EquationSystems equation_systems (mesh);
298
299 SimpleRBConstruction & rb_construction =
300 equation_systems.add_system<SimpleRBConstruction> ("RB");
301
302 equation_systems.init ();
303
304 rb_construction.set_rb_evaluation(rb_eval);
305
306 // read in the data from files
307 rb_eval.read_in_basis_functions(rb_construction, "rb_data");
308 rb_construction.load_rb_solution();
309
310 transform_mesh_and_plot(equation_systems, online_curvature, "RB_sol.e");
311 }
312
313#endif // LIBMESH_ENABLE_DIRICHLET
314
315 return 0;
316}
317
318#ifdef LIBMESH_ENABLE_DIRICHLET
319
321 Real curvature,
322 const std::string & filename)
323{
324 // Loop over the mesh nodes and move them!
325 MeshBase & mesh = es.get_mesh();
326
327 for (auto & node : mesh.node_ptr_range())
328 {
329 Real x = (*node)(0);
330 Real z = (*node)(2);
331
332 (*node)(0) = -1./curvature + (1./curvature + x)*cos(curvature*z);
333 (*node)(2) = (1./curvature + x)*sin(curvature*z);
334 }
335
336#ifdef LIBMESH_HAVE_EXODUS_API
338#endif
339
340 // Avoid unused variable warnings in the --disable-exodus case
341 libmesh_ignore(filename, es);
342}
343
344#endif // LIBMESH_ENABLE_DIRICHLET
This is the EquationSystems class.
void print_info(std::ostream &os=libMesh::out) const
Prints information about the equation systems, by default to libMesh::out.
const MeshBase & get_mesh() const
virtual void init()
Initialize all the systems.
virtual System & add_system(std::string_view system_type, std::string_view name)
Add the system of type system_type named name to the systems array.
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition exodusII_io.h:53
virtual void write_equation_systems(const std::string &fname, const EquationSystems &es, const std::set< std::string > *system_names=nullptr) override
Writes out the solution for no specific time or timestep.
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition libmesh.h:92
This is the MeshBase class.
Definition mesh_base.h:81
void print_info(std::ostream &os=libMesh::out, const unsigned int verbosity=0, const bool global=true) const
Prints relevant information about the mesh.
Definition mesh_base.C:1755
const Parallel::Communicator & comm() const
void set_rb_evaluation(RBEvaluation &rb_eval_in)
Set the RBEvaluation object.
virtual void load_rb_solution()
Load the RB solution from the most recent solve with rb_eval into this system's solution vector.
This class de-serializes a RBEIMEvaluation object using the Cap'n Proto library.
void read_from_file(const std::string &path, bool use_packing=false)
Read the Cap'n'Proto buffer from disk.
This class de-serializes an RBEvaluation object using the Cap'n Proto library.
void read_from_file(const std::string &path, bool read_error_bound_data, bool use_packing=false)
Read the Cap'n'Proto buffer from disk.
This class serializes an RBEIMEvaluation object using the Cap'n Proto library.
void write_to_file(const std::string &path, bool use_packing=false)
Write the Cap'n'Proto buffer to disk.
This class serializes an RBEvaluation object using the Cap'n Proto library.
void write_to_file(const std::string &path, bool use_packing=false)
Write the Cap'n'Proto buffer to disk.
void initialize_eim_construction()
Perform initialization of this object to prepare for running train_eim_approximation().
std::vector< std::unique_ptr< ElemAssembly > > & get_eim_assembly_objects()
virtual void initialize_eim_assembly_objects()
Build a vector of ElemAssembly objects that accesses the basis functions stored in this RBEIMConstruc...
void set_rb_eim_evaluation(RBEIMEvaluation &rb_eim_eval_in)
Set the RBEIMEvaluation object.
virtual Real train_eim_approximation()
Generate the EIM approximation for the specified parametrized function using either POD or the Greedy...
virtual void print_info()
Print out info that describes the current setup of this RBConstruction.
virtual void process_parameters_file(const std::string &parameters_filename)
Read parameters in from file and set up this system accordingly.
virtual Real rb_solve(unsigned int N)
Perform online solve with the N RB basis functions, for the set of parameters in current_params,...
virtual unsigned int get_n_basis_functions() const
Get the current number of basis functions.
RBThetaExpansion & get_rb_theta_expansion()
Get a reference to the rb_theta_expansion.
virtual void read_in_basis_functions(System &sys, const std::string &directory_name="offline_data", const bool read_binary_basis_functions=true)
Read in all the basis functions from file.
This class is part of the rbOOmit framework.
void set_value(const std::string &param_name, Real value)
Set the value of the specified parameter.
bool set_parameters(const RBParameters &params)
Set the current parameters to params The parameters are checked for validity; an error is thrown if t...
void print_parameters() const
Print the current parameters.
virtual void attach_multiple_A_theta(std::vector< std::unique_ptr< RBTheta > > &theta_q_a)
Attach a vector of pointers to functor objects that each define one of the theta_q_a terms.
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
MeshBase & mesh
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
The libMesh namespace provides an interface to certain functionality in the library.
void libmesh_ignore(const Args &...)
SolverPackage default_solver_package()
Definition libmesh.C:1064
OStreamProxy out
T command_line_next(std::string name, T default_value)
Use GetPot's search()/next() functions to get following arguments from the command line.
Definition libmesh.C:1025
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void transform_mesh_and_plot(EquationSystems &es, Real curvature, const std::string &filename)
int main()