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 =
349 std::unique_ptr<FEVectorBase> vector_fe(FEVectorBase::build(
dim, vector_fe_type));
350 std::unique_ptr<FEBase> scalar_fe(FEBase::build(
dim, scalar_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);
362 std::unique_ptr<FEVectorBase> vector_fe_face(FEVectorBase::build(
dim, vector_fe_type));
363 std::unique_ptr<FEBase> enriched_scalar_fe_face(FEBase::build(
dim, enriched_scalar_fe_type));
364 std::unique_ptr<FEBase> lambda_fe_face(FEBase::build(
dim, lambda_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);
468 for (
const auto qp :
make_range(qrule.n_points()))
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)
518 for (
const auto qp :
make_range(qface.n_points()))
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];
542 for (
const auto qp :
make_range(qface.n_points()))
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)
639 for (
const auto qp :
make_range(qface.n_points()))
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];
663 lambda_qps.
resize(qface.n_points());
664 for (
auto & lambda_qp : lambda_qps)
666 for (
const auto qp :
make_range(qface.n_points()))
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];
670 for (
const auto qp :
make_range(qface.n_points()))
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)
699 for (
const auto qp :
make_range(qrule.n_points()))
700 scalar_qps[qp] += scalar_soln(0) * scalar_phi[0][qp];
701 for (
const auto qp :
make_range(qrule.n_points()))
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();
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
void resize(const unsigned int n)
Resize the vector.
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...
const T_sys & get_system(std::string_view name) const
This is the MeshBase class.
unsigned int variable_number(std::string_view var) const
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
Manages consistently variables, degrees of freedom, and coefficient vectors.
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
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.
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)