1 #include "libmesh/nonlinear_implicit_system.h" 2 #include "libmesh/mesh_base.h" 3 #include "libmesh/dof_map.h" 4 #include "libmesh/numeric_vector.h" 5 #include "libmesh/sparse_matrix.h" 6 #include "libmesh/fe_type.h" 7 #include "libmesh/quadrature_gauss.h" 8 #include "libmesh/fe.h" 9 #include "libmesh/tensor_value.h" 10 #include "libmesh/equation_systems.h" 11 #include "libmesh/parameters.h" 12 #include "libmesh/elem.h" 13 #include "libmesh/fe_interface.h" 14 #include "libmesh/elem_side_builder.h" 33 libmesh_assert_equal_to(system.
name(),
"Poisson");
38 const auto epsilon = es.parameters.get<
Real>(
"epsilon");
65 fe->attach_quadrature_rule(&qrule);
79 fe_face->attach_quadrature_rule(&qface);
80 fe_neighbor_face->attach_quadrature_rule(&qface);
86 const auto & JxW = fe->get_JxW();
89 const auto & xyz = fe->get_xyz();
92 const auto & phi = fe->get_phi();
95 const auto & dphi = fe->get_dphi();
98 const auto & face_xyz = fe_face->get_xyz();
101 const auto & phi_face = fe_face->get_phi();
104 const auto & dphi_face = fe_face->get_dphi();
107 const auto & phi_neighbor = fe_neighbor_face->get_phi();
110 const auto & dphi_neighbor = fe_neighbor_face->get_dphi();
113 const auto & normals = fe_face->get_normals();
116 const auto & JxW_face = fe_face->get_JxW();
124 std::vector<dof_id_type> dof_indices;
125 std::vector<dof_id_type> dof_indices_neighbor;
128 std::vector<Number> dof_u;
129 std::vector<Number> dof_u_neighbor;
132 std::vector<VectorValue<Number>> u;
133 std::vector<TensorValue<Number>> grad_u;
134 std::vector<VectorValue<Number>> u_neighbor;
135 std::vector<TensorValue<Number>> grad_u_neighbor;
149 for (
const auto & elem :
mesh.active_local_element_ptr_range())
163 libmesh_assert_msg(dphi.size() == dof_indices.size(),
164 "dphi size doesn't match dof_indices size");
167 Fe.
resize(dof_indices.size());
170 X.
get(dof_indices, dof_u);
173 grad_u.resize(qrule.n_points());
174 for (
unsigned int qp = 0; qp < qrule.n_points(); qp++)
177 for (std::size_t i = 0; i < dof_indices.size(); i++)
178 grad_u[qp] += dof_u[i] * dphi[i][qp];
181 for (
unsigned int qp = 0; qp < qrule.n_points(); qp++)
186 for (std::size_t i = 0; i < dof_indices.size(); i++)
189 Fe(i) += JxW[qp] * dphi[i][qp].contract(grad_u[qp]);
192 Fe(i) += JxW[qp] * phi[i][qp] * forcing_func;
200 for (
auto side : elem->side_index_range())
203 const auto side_volume = side_builder(*elem, side).volume();
204 fe_face->reinit(elem, side);
205 const auto elem_b_order =
static_cast<unsigned int>(fe_face->get_order());
206 const auto h_elem = elem->volume() / side_volume /
std::pow(elem_b_order, 2);
209 u.resize(qface.n_points());
210 grad_u.resize(qface.n_points());
211 for (
unsigned int qp = 0; qp < qface.n_points(); qp++)
215 for (std::size_t i = 0; i < dof_indices.size(); i++)
217 u[qp] += dof_u[i] * phi_face[i][qp];
218 grad_u[qp] += dof_u[i] * dphi_face[i][qp];
223 if (!elem->neighbor_ptr(side))
225 for (
unsigned int qp = 0; qp < qface.n_points(); qp++)
230 for (std::size_t i = 0; i < dof_indices.size(); i++)
232 Fe(i) -= grad_u[qp] * normals[qp] * phi_face[i][qp] * JxW_face[qp];
233 Fe(i) += epsilon * (u[qp] - fn) * dphi_face[i][qp] * normals[qp] * JxW_face[qp];
234 Fe(i) += sigma / h_elem * (u[qp] - fn) * phi_face[i][qp] * JxW_face[qp];
242 const auto elem_id = elem->
id();
243 const auto neighbor_id = neighbor->
id();
246 if ((neighbor->
active() && (neighbor->
level() == elem->level()) &&
247 (elem_id < neighbor_id)) ||
248 (neighbor->
level() < elem->level()))
250 dof_map.
dof_indices(neighbor, dof_indices_neighbor);
253 std::vector<Point> neighbor_xyz;
257 fe_neighbor_face->reinit(neighbor, &neighbor_xyz);
259 libmesh_assert_msg(dphi_neighbor.size() == dof_indices_neighbor.size(),
260 "dphi_neighbor size doesn't match dof_indices_neighbor size");
262 Fn.
resize(dof_indices_neighbor.size());
263 X.
get(dof_indices_neighbor, dof_u_neighbor);
266 u_neighbor.resize(qface.n_points());
267 grad_u_neighbor.resize(qface.n_points());
268 for (
unsigned int qp = 0; qp < qface.n_points(); qp++)
271 grad_u_neighbor[qp] = 0;
272 for (std::size_t i = 0; i < dof_indices_neighbor.size(); i++)
274 u_neighbor[qp] += dof_u_neighbor[i] * phi_neighbor[i][qp];
275 grad_u_neighbor[qp] += dof_u_neighbor[i] * dphi_neighbor[i][qp];
280 for (
unsigned int qp = 0; qp < qface.n_points(); qp++)
283 for (std::size_t i = 0; i < dof_indices.size(); i++)
285 Fe(i) -= 0.5 * (grad_u[qp] * normals[qp] + grad_u_neighbor[qp] * normals[qp]) *
286 phi_face[i][qp] * JxW_face[qp];
287 Fe(i) += epsilon * 0.5 * (u[qp] - u_neighbor[qp]) * dphi_face[i][qp] * normals[qp] *
289 Fe(i) += sigma / h_elem * (u[qp] - u_neighbor[qp]) * phi_face[i][qp] * JxW_face[qp];
292 for (std::size_t i = 0; i < dof_indices_neighbor.size(); i++)
294 Fn(i) += 0.5 * (grad_u[qp] * normals[qp] + grad_u_neighbor[qp] * normals[qp]) *
295 phi_neighbor[i][qp] * JxW_face[qp];
296 Fn(i) -= epsilon * 0.5 * (u[qp] - u_neighbor[qp]) * dphi_neighbor[i][qp] *
297 normals[qp] * JxW_face[qp];
299 sigma / h_elem * (u[qp] - u_neighbor[qp]) * phi_neighbor[i][qp] * JxW_face[qp];
321 libmesh_assert_equal_to(system.
name(),
"Poisson");
326 const auto epsilon = es.parameters.get<
Real>(
"epsilon");
353 fe->attach_quadrature_rule(&qrule);
367 fe_face->attach_quadrature_rule(&qface);
368 fe_neighbor_face->attach_quadrature_rule(&qface);
374 const auto & JxW = fe->get_JxW();
377 const auto & dphi = fe->get_dphi();
380 const auto & face_xyz = fe_face->get_xyz();
383 const auto & phi_face = fe_face->get_phi();
386 const auto & dphi_face = fe_face->get_dphi();
389 const auto & phi_neighbor = fe_neighbor_face->get_phi();
392 const auto & dphi_neighbor = fe_neighbor_face->get_dphi();
395 const auto & normals = fe_face->get_normals();
398 const auto & JxW_face = fe_face->get_JxW();
408 std::vector<dof_id_type> dof_indices;
409 std::vector<dof_id_type> dof_indices_neighbor;
426 for (
const auto & elem :
mesh.active_local_element_ptr_range())
440 libmesh_assert_msg(dphi.size() == dof_indices.size(),
441 "dphi size doesn't match dof_indices size");
444 Kee.
resize(dof_indices.size(), dof_indices.size());
447 for (
unsigned int qp = 0; qp < qrule.n_points(); qp++)
448 for (std::size_t i = 0; i < dof_indices.size(); i++)
449 for (std::size_t j = 0; j < dof_indices.size(); j++)
450 Kee(i, j) += JxW[qp] * dphi[i][qp].contract(dphi[j][qp]);
453 for (
auto side : elem->side_index_range())
456 const auto side_volume = side_builder(*elem, side).volume();
457 fe_face->reinit(elem, side);
458 const auto elem_b_order =
static_cast<unsigned int>(fe_face->get_order());
459 const auto h_elem = elem->volume() / side_volume /
std::pow(elem_b_order, 2);
462 if (!elem->neighbor_ptr(side))
464 for (
unsigned int qp = 0; qp < qface.n_points(); qp++)
465 for (std::size_t i = 0; i < dof_indices.size(); i++)
466 for (std::size_t j = 0; j < dof_indices.size(); j++)
469 Kee(i, j) -= dphi_face[j][qp] * normals[qp] * phi_face[i][qp] * JxW_face[qp];
471 epsilon * phi_face[j][qp] * dphi_face[i][qp] * normals[qp] * JxW_face[qp];
472 Kee(i, j) += sigma / h_elem * phi_face[j][qp] * phi_face[i][qp] * JxW_face[qp];
479 const auto elem_id = elem->
id();
480 const auto neighbor_id = neighbor->
id();
483 if ((neighbor->
active() && (neighbor->
level() == elem->level()) &&
484 (elem_id < neighbor_id)) ||
485 (neighbor->
level() < elem->level()))
487 dof_map.
dof_indices(neighbor, dof_indices_neighbor);
490 std::vector<Point> neighbor_xyz;
494 fe_neighbor_face->reinit(neighbor, &neighbor_xyz);
496 libmesh_assert_msg(dphi_neighbor.size() == dof_indices_neighbor.size(),
497 "dphi_neighbor size doesn't match dof_indices_neighbor size");
499 Ken.
resize(dof_indices.size(), dof_indices_neighbor.size());
500 Kne.
resize(dof_indices_neighbor.size(), dof_indices.size());
501 Knn.
resize(dof_indices_neighbor.size(), dof_indices_neighbor.size());
504 for (
unsigned int qp = 0; qp < qface.n_points(); qp++)
507 for (std::size_t i = 0; i < dof_indices.size(); i++)
508 for (std::size_t j = 0; j < dof_indices.size(); j++)
510 Kee(i, j) -= 0.5 * dphi_face[j][qp] * normals[qp] * phi_face[i][qp] * JxW_face[qp];
512 epsilon * 0.5 * phi_face[j][qp] * dphi_face[i][qp] * normals[qp] * JxW_face[qp];
513 Kee(i, j) += sigma / h_elem * phi_face[j][qp] * phi_face[i][qp] * JxW_face[qp];
516 for (std::size_t i = 0; i < dof_indices.size(); i++)
517 for (std::size_t j = 0; j < dof_indices_neighbor.size(); j++)
520 0.5 * dphi_neighbor[j][qp] * normals[qp] * phi_face[i][qp] * JxW_face[qp];
521 Ken(i, j) += epsilon * 0.5 * -phi_neighbor[j][qp] * dphi_face[i][qp] * normals[qp] *
523 Ken(i, j) += sigma / h_elem * -phi_neighbor[j][qp] * phi_face[i][qp] * JxW_face[qp];
526 for (std::size_t i = 0; i < dof_indices_neighbor.size(); i++)
527 for (std::size_t j = 0; j < dof_indices_neighbor.size(); j++)
530 0.5 * dphi_face[j][qp] * normals[qp] * phi_neighbor[i][qp] * JxW_face[qp];
531 Kne(i, j) -= epsilon * 0.5 * phi_face[j][qp] * dphi_neighbor[i][qp] * normals[qp] *
533 Kne(i, j) -= sigma / h_elem * phi_face[j][qp] * phi_neighbor[i][qp] * JxW_face[qp];
536 for (std::size_t i = 0; i < dof_indices_neighbor.size(); i++)
537 for (std::size_t j = 0; j < dof_indices_neighbor.size(); j++)
540 0.5 * dphi_neighbor[j][qp] * normals[qp] * phi_neighbor[i][qp] * JxW_face[qp];
541 Knn(i, j) -= epsilon * 0.5 * -phi_neighbor[j][qp] * dphi_neighbor[i][qp] *
542 normals[qp] * JxW_face[qp];
544 sigma / h_elem * -phi_neighbor[j][qp] * phi_neighbor[i][qp] * JxW_face[qp];
548 J.
add_matrix(Ken, dof_indices, dof_indices_neighbor);
549 J.
add_matrix(Kne, dof_indices_neighbor, dof_indices);
550 J.
add_matrix(Knn, dof_indices_neighbor, dof_indices_neighbor);
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Real exact_solution(const int component, const Real x, const Real y, const Real z=0.)
This is the exact solution that we are trying to obtain.
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
Access multiple components at once.
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
void resize(const unsigned int n)
Resize the vector.
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
Computes , where v is a pointer and each dof_indices[i] specifies where to add value v[i]...
const FEType & variable_type(const unsigned int c) const
const EquationSystems & get_equation_systems() const
This is the base class from which all geometric element types are derived.
Provides a uniform interface to vector storage schemes for different linear algebra libraries...
Order default_quadrature_order() const
Real forcing_function(const int component, const Real x, const Real y, const Real z=0.)
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
The libMesh namespace provides an interface to certain functionality in the library.
const MeshBase & get_mesh() const
void compute_jacobian(const NumericVector< Number > &, SparseMatrix< Number > &J, NonlinearImplicitSystem &system)
This is the MeshBase class.
This class handles the numbering of degrees of freedom on a mesh.
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
void compute_residual(const NumericVector< Number > &X, NumericVector< Number > &R, NonlinearImplicitSystem &system)
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
Helper for building element sides that minimizes the construction of new elements.
const Elem * neighbor_ptr(unsigned int i) const
unsigned int level() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
This class implements specific orders of Gauss quadrature.
unsigned int mesh_dimension() const
Parameters parameters
Data structure holding arbitrary parameters.
const std::string & name() const
const DofMap & get_dof_map() const