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);
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);
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);