102 #include "libmesh/string_to_enum.h" 105 #include "libmesh/enum_solver_package.h" 108 #include "libmesh/mesh.h" 109 #include "libmesh/mesh_generation.h" 110 #include "libmesh/mesh_modification.h" 113 #include "libmesh/dense_matrix.h" 114 #include "libmesh/sparse_matrix.h" 115 #include "libmesh/dense_vector.h" 116 #include "libmesh/numeric_vector.h" 119 #include "libmesh/fe.h" 120 #include "libmesh/elem.h" 123 #include "libmesh/quadrature_gauss.h" 126 #include "libmesh/dof_map.h" 129 #include "libmesh/equation_systems.h" 130 #include "libmesh/linear_implicit_system.h" 133 #include "libmesh/exact_solution.h" 134 #include "libmesh/enum_norm_type.h" 135 #include "solution_function.h" 138 #include "libmesh/getpot.h" 139 #include "libmesh/exodusII_io.h" 141 #ifdef LIBMESH_HAVE_EIGEN_DENSE 143 #include <Eigen/Dense> 146 using namespace Eigen;
148 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 167 "--enable-petsc, --enable-trilinos, or --enable-eigen");
170 GetPot infile(
"vector_fe_ex7.in");
173 infile.parse_command_line(argc, argv);
176 const unsigned int dimension = infile(
"dim", 2);
177 const unsigned int grid_size = infile(
"grid_size", 15);
180 libmesh_example_requires(dimension <= LIBMESH_DIM, dimension <<
"D support");
189 const std::string elem_str = infile(
"element_type", std::string(
"TRI6"));
191 libmesh_error_msg_if((dimension == 2 && elem_str !=
"TRI6" && elem_str !=
"TRI7" &&
192 elem_str !=
"QUAD8" && elem_str !=
"QUAD9") ||
193 (dimension == 3 && elem_str !=
"TET14" && elem_str !=
"HEX27"),
196 <<
" but this example must be run with TRI6, TRI7, QUAD8, or QUAD9 in 2d" 197 <<
" or with TET14, or HEX27 in 3d.");
201 mesh, grid_size, grid_size, -1., 1., -1., 1., Utility::string_to_enum<ElemType>(elem_str));
202 else if (dimension == 3)
213 Utility::string_to_enum<ElemType>(elem_str));
220 const bool simplicial = (elem_str ==
"TRI6") || (elem_str ==
"TRI7") || (elem_str ==
"TET14");
221 equation_systems.
parameters.
set<
bool>(
"simplicial") = simplicial;
247 equation_systems.
init();
267 std::vector<FunctionBase<Number> *> sols(1, &soln_func);
268 std::vector<FunctionBase<Gradient> *> grads(1, &soln_grad);
273 else if (dimension == 3)
279 std::vector<FunctionBase<Number> *> sols(1, &soln_func);
280 std::vector<FunctionBase<Gradient> *> grads(1, &soln_grad);
287 int extra_error_quadrature = infile(
"extra_error_quadrature", 2);
288 if (extra_error_quadrature)
294 #if !defined(LIBMESH_HAVE_PETSC) || !defined(LIBMESH_USE_REAL_NUMBERS) 305 #if !defined(LIBMESH_HAVE_PETSC) || !defined(LIBMESH_USE_REAL_NUMBERS) 311 #ifdef LIBMESH_HAVE_EXODUS_API 316 #endif // #ifdef LIBMESH_HAVE_EXODUS_API 331 const bool simplicial = es.
parameters.
get<
bool>(
"simplicial");
339 const auto & lambda_dof_map = lambda_system.
get_dof_map();
343 const FEType enriched_scalar_fe_type =
345 const FEType lambda_fe_type =
351 std::unique_ptr<FEBase> enriched_scalar_fe(
FEBase::build(
dim, enriched_scalar_fe_type));
357 vector_fe->attach_quadrature_rule(&qrule);
358 scalar_fe->attach_quadrature_rule(&qrule);
359 enriched_scalar_fe->attach_quadrature_rule(&qrule);
363 std::unique_ptr<FEBase> enriched_scalar_fe_face(
FEBase::build(
dim, enriched_scalar_fe_type));
371 vector_fe_face->attach_quadrature_rule(&qface);
372 enriched_scalar_fe_face->attach_quadrature_rule(&qface);
373 lambda_fe_face->attach_quadrature_rule(&qface);
376 const auto & JxW = vector_fe->get_JxW();
377 const auto & q_point = vector_fe->get_xyz();
378 const auto & vector_phi = vector_fe->get_phi();
379 const auto & scalar_phi = scalar_fe->get_phi();
380 const auto & enriched_scalar_phi = enriched_scalar_fe->get_phi();
381 const auto & div_vector_phi = vector_fe->get_div_phi();
384 const auto & vector_phi_face = vector_fe_face->get_phi();
385 const auto & enriched_scalar_phi_face = enriched_scalar_fe_face->get_phi();
386 const auto & lambda_phi_face = lambda_fe_face->get_phi();
387 const auto & JxW_face = vector_fe_face->get_JxW();
388 const auto & qface_point = vector_fe_face->get_xyz();
389 const auto & normals = vector_fe_face->get_normals();
420 std::vector<Number> lambda_qps;
422 std::vector<Number> scalar_qps;
429 std::vector<dof_id_type> vector_dof_indices;
430 std::vector<dof_id_type> scalar_dof_indices;
431 std::vector<dof_id_type> enriched_scalar_dof_indices;
432 std::vector<dof_id_type> lambda_dof_indices;
433 std::vector<Number> lambda_solution_std_vec;
438 for (
const auto & elem :
mesh.active_local_element_ptr_range())
441 dof_map.dof_indices(elem, vector_dof_indices, system.variable_number(
"u"));
442 dof_map.dof_indices(elem, scalar_dof_indices, system.variable_number(
"p"));
443 lambda_dof_map.dof_indices(elem, lambda_dof_indices, lambda_system.
variable_number(
"lambda"));
445 const auto vector_n_dofs = vector_dof_indices.size();
446 const auto scalar_n_dofs = scalar_dof_indices.size();
447 const auto lambda_n_dofs = lambda_dof_indices.size();
451 scalar_fe->reinit(elem);
453 libmesh_assert_equal_to(vector_n_dofs, vector_phi.size());
454 libmesh_assert_equal_to(scalar_n_dofs, scalar_phi.size());
457 A.setZero(vector_n_dofs, vector_n_dofs);
458 B.setZero(vector_n_dofs, scalar_n_dofs);
459 C.setZero(vector_n_dofs, lambda_n_dofs);
460 G.setZero(vector_n_dofs);
462 Bt.setZero(scalar_n_dofs, vector_n_dofs);
463 F.setZero(scalar_n_dofs);
465 Ct.setZero(lambda_n_dofs, vector_n_dofs);
466 L.setZero(lambda_n_dofs, lambda_n_dofs);
471 for (
const auto i :
make_range(vector_n_dofs))
472 for (
const auto j :
make_range(vector_n_dofs))
473 A(i, j) += JxW[qp] * (vector_phi[i][qp] * vector_phi[j][qp]);
476 for (
const auto i :
make_range(vector_n_dofs))
477 for (
const auto j :
make_range(scalar_n_dofs))
478 B(i, j) -= JxW[qp] * (div_vector_phi[i][qp] * scalar_phi[j][qp]);
481 for (
const auto i :
make_range(scalar_n_dofs))
482 for (
const auto j :
make_range(vector_n_dofs))
483 Bt(i, j) -= JxW[qp] * (scalar_phi[i][qp] * div_vector_phi[j][qp]);
490 const Real x = q_point[qp](0);
491 const Real y = q_point[qp](1);
492 const Real z = q_point[qp](2);
504 for (
const auto i :
make_range(scalar_n_dofs))
505 F(i) -= JxW[qp] * scalar_phi[i][qp] * f;
510 for (
auto side : elem->side_index_range())
513 vector_fe_face->reinit(elem, side);
514 libmesh_assert_equal_to(vector_n_dofs, vector_phi_face.size());
515 lambda_fe_face->reinit(elem, side);
517 if (elem->neighbor_ptr(side) ==
nullptr)
520 const Real xf = qface_point[qp](0);
521 const Real yf = qface_point[qp](1);
522 const Real zf = qface_point[qp](2);
525 Real scalar_value = 0;
532 for (
const auto i :
make_range(vector_n_dofs))
533 G(i) -= JxW_face[qp] * (vector_phi_face[i][qp] * normals[qp]) * scalar_value;
537 for (
const auto i :
make_range(lambda_n_dofs))
538 for (
const auto j :
make_range(lambda_n_dofs))
539 L(i, j) += JxW_face[qp] * lambda_phi_face[i][qp] * lambda_phi_face[j][qp];
545 for (
const auto i :
make_range(vector_n_dofs))
546 for (
const auto j :
make_range(lambda_n_dofs))
548 JxW_face[qp] * (vector_phi_face[i][qp] * normals[qp]) * lambda_phi_face[j][qp];
551 for (
const auto i :
make_range(lambda_n_dofs))
552 for (
const auto j :
make_range(vector_n_dofs))
554 JxW_face[qp] * lambda_phi_face[i][qp] * (vector_phi_face[j][qp] * normals[qp]);
561 Sinv = (Bt * Ainv *
B).inverse();
566 E = Ct * Ainv * (A -
B * Sinv * Bt) * Ainv * C;
568 Hg = Ct * Ainv * (A -
B * Sinv * Bt) * Ainv * G;
569 Hf = Ct * Ainv *
B * Sinv * F;
573 E_libmesh.
resize(E.rows(), E.cols());
574 H_libmesh.
resize(H.size());
580 E_libmesh(i, j) = E(i, j);
587 dof_map.constrain_element_matrix_and_vector(E_libmesh, H_libmesh, lambda_dof_indices);
588 matrix.
add_matrix(E_libmesh, lambda_dof_indices);
589 lambda_system.rhs->
add_vector(H_libmesh, lambda_dof_indices);
599 Lambda.resize(lambda_n_dofs);
601 for (
const auto i :
make_range(lambda_n_dofs))
602 Lambda(i) = lambda_solution_std_vec[i];
603 const auto scalar_soln = Sinv * Bt * Ainv * G - Sinv * F - Sinv * Bt * Ainv * C * Lambda;
604 const auto vector_soln = Ainv * (G -
B * scalar_soln - C * Lambda);
605 for (
const auto i :
make_range(vector_n_dofs))
606 system.solution->set(vector_dof_indices[i], vector_soln(i));
607 for (
const auto i :
make_range(scalar_n_dofs))
608 system.solution->set(scalar_dof_indices[i], scalar_soln(i));
610 #if !defined(LIBMESH_HAVE_PETSC) || !defined(LIBMESH_USE_REAL_NUMBERS) 623 dof_map.dof_indices(elem, enriched_scalar_dof_indices, system.variable_number(
"p_enriched"));
624 const auto enriched_scalar_n_dofs = enriched_scalar_dof_indices.size();
625 const auto m = simplicial ? lambda_n_dofs : lambda_n_dofs + 1;
626 const auto n = enriched_scalar_n_dofs;
628 K_enriched_scalar.
resize(m, n);
629 F_enriched_scalar.
resize(m);
630 U_enriched_scalar.
resize(n);
633 for (
const auto side : elem->side_index_range())
635 vector_fe_face->reinit(elem, side);
636 enriched_scalar_fe_face->reinit(elem, side);
637 lambda_fe_face->reinit(elem, side);
638 if (elem->neighbor_ptr(side) ==
nullptr)
641 const Real xf = qface_point[qp](0);
642 const Real yf = qface_point[qp](1);
643 const Real zf = qface_point[qp](2);
646 Real scalar_value = 0;
652 for (
const auto i :
make_range(lambda_n_dofs))
654 F_enriched_scalar(i) += JxW_face[qp] * lambda_phi_face[i][qp] * scalar_value;
655 for (
const auto j :
make_range(enriched_scalar_n_dofs))
656 K_enriched_scalar(i, j) +=
657 JxW_face[qp] * lambda_phi_face[i][qp] * enriched_scalar_phi_face[j][qp];
664 for (
auto & lambda_qp : lambda_qps)
667 for (
const auto i :
index_range(lambda_solution_std_vec))
668 lambda_qps[qp] += lambda_solution_std_vec[i] * lambda_phi_face[i][qp];
671 for (
const auto i :
make_range(lambda_n_dofs))
673 F_enriched_scalar(i) += JxW_face[qp] * lambda_phi_face[i][qp] * lambda_qps[qp];
674 for (
const auto j :
make_range(enriched_scalar_n_dofs))
675 K_enriched_scalar(i, j) +=
676 JxW_face[qp] * lambda_phi_face[i][qp] * enriched_scalar_phi_face[j][qp];
682 K_enriched_scalar.
lu_solve(F_enriched_scalar, U_enriched_scalar);
691 enriched_scalar_fe->reinit(elem);
696 scalar_qps.resize(qrule.
n_points());
697 for (
auto & scalar_qp : scalar_qps)
700 scalar_qps[qp] += scalar_soln(0) * scalar_phi[0][qp];
703 F_enriched_scalar(n) += JxW[qp] * scalar_phi[0][qp] * scalar_qps[qp];
705 K_enriched_scalar(n, j) += JxW[qp] * scalar_phi[0][qp] * enriched_scalar_phi[j][qp];
708 K_enriched_scalar.
svd_solve(F_enriched_scalar, U_enriched_scalar);
712 system.solution->insert(U_enriched_scalar, enriched_scalar_dof_indices);
718 system.solution->close();
728 libmesh_assert_equal_to(system_name,
"Lambda");
int main(int argc, char **argv)
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Eigen::Matrix< Number, Eigen::Dynamic, Eigen::Dynamic > EigenMatrix
This class handles the computation of the L2 and/or H1 error for the Systems in the EquationSystems o...
This is the EquationSystems class.
Real hdiv_error(std::string_view sys_name, std::string_view unknown_name)
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
void attach_exact_values(const std::vector< FunctionBase< Number > *> &f)
Clone and attach arbitrary functors which compute the exact values of the EquationSystems' solutions ...
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
Eigen::Matrix< Number, Eigen::Dynamic, 1 > EigenVector
void resize(const unsigned int n)
Resize the vector.
void extra_quadrature_order(const int extraorder)
Increases or decreases the order of the quadrature rule used for numerical integration.
NumericVector< Number > & add_vector(std::string_view vec_name, const bool projections=true, const ParallelType type=PARALLEL)
Adds the additional vector vec_name to this system.
virtual void reinit() override
Reinitializes the member data fields associated with the system, so that, e.g., assemble() may be use...
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
The libMesh namespace provides an interface to certain functionality in the library.
void attach_exact_derivs(const std::vector< FunctionBase< Gradient > *> &g)
Clone and attach arbitrary functors which compute the exact gradients of the EquationSystems' solutio...
const T_sys & get_system(std::string_view name) const
This is the MeshBase class.
unsigned int variable_number(std::string_view var) const
SolverPackage default_solver_package()
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols)=0
Add the full matrix dm to the SparseMatrix.
const T & get(std::string_view) const
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.
Manages consistently variables, degrees of freedom, and coefficient vectors.
void compute_error(std::string_view sys_name, std::string_view unknown_name)
Computes and stores the error in the solution value e = u-u_h, the gradient grad(e) = grad(u) - grad(...
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
void fe_assembly(EquationSystems &es, bool global_solve)
unsigned int n_points() const
void attach_assemble_function(void fptr(EquationSystems &es, const std::string &name))
Register a user function to use in assembling the system matrix and RHS.
Real l2_error(std::string_view sys_name, std::string_view unknown_name)
virtual void solve()
Solves the system.
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
Solve the system Ax=b given the input vector b.
const FEType & variable_type(const unsigned int i) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
T & set(const std::string &)
Real forcing(Real x, Real y)
const MeshBase & get_mesh() const
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
This class implements specific orders of Gauss quadrature.
unsigned int mesh_dimension() const
Parameters parameters
Data structure holding arbitrary parameters.
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
virtual void init()
Initialize all the systems.
void assemble_divgrad(EquationSystems &es, const std::string &system_name)
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 Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
const DofMap & get_dof_map() const
void svd_solve(const DenseVector< T > &rhs, DenseVector< T > &x, Real rcond=std::numeric_limits< Real >::epsilon()) const
Solve the system of equations for in the least-squares sense.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Real scalar(Real x, Real y)
Real error_norm(std::string_view sys_name, std::string_view unknown_name, const FEMNormType &norm)