6template <
typename MyTensor,
typename MyVector>
7MyTensor tangential_hessian (
const MyTensor hess,
10 auto full_hess_n = hess*normal;
11 MyTensor tang_hess = hess;
14 for (
unsigned int k=0; k != 3; ++k)
18 const auto Hkn = ek * full_hess_n;
19 const auto Hkn_ek = Hkn*ek;
22 tang_hess += 2.*(Hkn_ek*normal) * n_n;
24 tang_hess -= normal*(full_hess_n) * n_n;
32 CPPUNIT_TEST( testU ); \
33 CPPUNIT_TEST( testGradU ); \
34 CPPUNIT_TEST( testGradUComp ); \
35 CPPUNIT_TEST( testHessU ); \
36 CPPUNIT_TEST( testHessUComp );
38const unsigned int N_x=2;
40template <Order order, FEFamily family, ElemType elem_type>
54 BoundaryInfo & bdy_info = this->
_mesh->get_boundary_info();
55 for (
auto e : this->
_mesh->element_ptr_range())
56 if (!(e->id() % 3) && e->dim() < LIBMESH_DIM)
59 FEType fe_type = this->
_sys->variable_type(0);
60 _fe_side = FEBase::build(this->
_dim, fe_type);
62 _qrule_side = std::make_unique<QGauss>(this->
_dim-1, fe_type.default_quadrature_order());
63 _fe_side->attach_quadrature_rule(this->_qrule_side.get());
77#if LIBMESH_ENABLE_SECOND_DERIVATIVES
107 template <
typename Functor>
114 for (
auto e : this->
_mesh->active_local_element_ptr_range())
120 for (
unsigned int s=0; s != this->
_elem->n_sides(); ++s)
136 auto phi = this->_fe_side->get_phi();
137 CPPUNIT_ASSERT(phi.size());
138 CPPUNIT_ASSERT_EQUAL(phi.size(), this->_dof_indices.size());
140 std::size_t n_qp = phi[0].size();
141 CPPUNIT_ASSERT(n_qp > 0);
143 auto xyz = this->_fe_side->get_xyz();
144 CPPUNIT_ASSERT_EQUAL(n_qp, xyz.size());
146 for (
auto qp : index_range(phi[0]))
149 for (
auto d : index_range(phi))
150 u += phi[d][qp] * (*this->
_sys->current_local_solution)(this->
_dof_indices[d]);
152 const Point p = xyz[qp];
154 y = LIBMESH_DIM > 1 ? p(1) : 0,
155 z = LIBMESH_DIM > 2 ? p(2) : 0;
157 if (family == RATIONAL_BERNSTEIN && order > 1)
158 LIBMESH_ASSERT_NUMBERS_EQUAL
161 LIBMESH_ASSERT_NUMBERS_EQUAL
164 LIBMESH_ASSERT_NUMBERS_EQUAL
167 LIBMESH_ASSERT_NUMBERS_EQUAL
168 (x*x + 0.5*y*y + 0.25*z*z + 0.125*x*y +
169 0.0625*x*z + 0.03125*y*z,
172 LIBMESH_ASSERT_NUMBERS_EQUAL (x + 0.25*y + 0.0625*z, u,
187 auto dphi = this->_fe_side->get_dphi();
188 CPPUNIT_ASSERT(dphi.size() > 0);
189 CPPUNIT_ASSERT_EQUAL(dphi.size(), this->_dof_indices.size());
191 std::size_t n_qp = dphi[0].size();
192 CPPUNIT_ASSERT(n_qp > 0);
194 auto xyz = this->_fe_side->get_xyz();
195 CPPUNIT_ASSERT_EQUAL(n_qp, xyz.size());
197 auto normals = this->_fe_side->get_normals();
198 CPPUNIT_ASSERT_EQUAL(n_qp, normals.size());
200 const Point c = this->
_elem->vertex_average();
202 for (
auto qp : index_range(dphi[0]))
205 for (
auto d : index_range(dphi))
206 grad_u += dphi[d][qp] * (*this->
_sys->current_local_solution)(this->
_dof_indices[d]);
208 const Point p = xyz[qp];
209 const Point n = normals[qp];
212 LIBMESH_ASSERT_FP_EQUAL(Real(n.norm()),
219 CPPUNIT_ASSERT_GREATER(Real(0), (p-c)*n);
228 const Gradient tangential_grad_u = grad_u - ((grad_u * n) * n);
230 if (family == RATIONAL_BERNSTEIN && order > 1)
240 const Gradient true_tangential_grad = true_grad - ((true_grad * n) * n);
242 LIBMESH_ASSERT_NUMBERS_EQUAL(tangential_grad_u(0),
243 true_tangential_grad(0),
246 LIBMESH_ASSERT_NUMBERS_EQUAL(tangential_grad_u(1),
247 true_tangential_grad(1),
250 LIBMESH_ASSERT_NUMBERS_EQUAL(tangential_grad_u(2),
251 true_tangential_grad(2),
266 auto dphidx = this->_fe_side->get_dphidx();
267 CPPUNIT_ASSERT(dphidx.size() > 0);
268 CPPUNIT_ASSERT_EQUAL(dphidx.size(), this->_dof_indices.size());
270 auto dphidy = this->_fe_side->get_dphidy();
271 CPPUNIT_ASSERT_EQUAL(dphidy.size(), this->_dof_indices.size());
274 auto dphidz = this->_fe_side->get_dphidz();
275 CPPUNIT_ASSERT_EQUAL(dphidz.size(), this->_dof_indices.size());
278 std::size_t n_qp = dphidx[0].size();
279 CPPUNIT_ASSERT(n_qp > 0);
281 auto xyz = this->_fe_side->get_xyz();
282 CPPUNIT_ASSERT_EQUAL(n_qp, xyz.size());
284 auto normals = this->_fe_side->get_normals();
285 CPPUNIT_ASSERT_EQUAL(n_qp, normals.size());
287 for (
auto qp : index_range(dphidx[0]))
289 Number grad_u_x = 0, grad_u_y = 0, grad_u_z = 0;
290 for (
auto d : index_range(dphidx))
292 grad_u_x += dphidx[d][qp] * (*this->
_sys->current_local_solution)(this->
_dof_indices[d]);
294 grad_u_y += dphidy[d][qp] * (*this->
_sys->current_local_solution)(this->
_dof_indices[d]);
297 grad_u_z += dphidz[d][qp] * (*this->
_sys->current_local_solution)(this->
_dof_indices[d]);
301 const Point p = xyz[qp];
309 Point n = normals[qp];
311 const Gradient grad_u {grad_u_x, grad_u_y, grad_u_z};
312 const Gradient tangential_grad_u = grad_u - ((grad_u * n) * n);
314 if (family == RATIONAL_BERNSTEIN && order > 1)
324 const Gradient true_tangential_grad = true_grad - ((true_grad * n) * n);
326 LIBMESH_ASSERT_NUMBERS_EQUAL(tangential_grad_u(0),
327 true_tangential_grad(0),
330 LIBMESH_ASSERT_NUMBERS_EQUAL(tangential_grad_u(1),
331 true_tangential_grad(1),
334 LIBMESH_ASSERT_NUMBERS_EQUAL(tangential_grad_u(2),
335 true_tangential_grad(2),
348#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
350 if (family == SZABAB)
356 auto d2phi = this->_fe_side->get_d2phi();
357 CPPUNIT_ASSERT(d2phi.size() > 0);
358 CPPUNIT_ASSERT_EQUAL(d2phi.size(), this->_dof_indices.size());
360 std::size_t n_qp = d2phi[0].size();
361 CPPUNIT_ASSERT(n_qp > 0);
363 auto xyz = this->_fe_side->get_xyz();
364 CPPUNIT_ASSERT_EQUAL(n_qp, xyz.size());
366 auto normals = this->_fe_side->get_normals();
367 CPPUNIT_ASSERT_EQUAL(n_qp, normals.size());
369 for (
auto qp : index_range(d2phi[0]))
372 for (
auto d : index_range(d2phi))
373 hess_u += d2phi[d][qp] * (*this->
_sys->current_local_solution)(this->
_dof_indices[d]);
382 Point n = normals[qp];
383 hess_u = tangential_hessian(hess_u, n);
385 if (family == RATIONAL_BERNSTEIN && order > 1)
391 const Point p = xyz[qp];
395 RealTensor tangential_hess = tangential_hessian(true_hess, n);
397 LIBMESH_ASSERT_NUMBERS_EQUAL(tangential_hess(0,0),
401 LIBMESH_ASSERT_NUMBERS_EQUAL
402 (hess_u(0,1), hess_u(1,0), this->
_hess_tol);
403 LIBMESH_ASSERT_NUMBERS_EQUAL
404 (tangential_hess(0,1), hess_u(0,1), this->
_hess_tol);
405 LIBMESH_ASSERT_NUMBERS_EQUAL
406 (tangential_hess(1,1), hess_u(1,1), this->
_hess_tol);
410 LIBMESH_ASSERT_NUMBERS_EQUAL
411 (hess_u(0,2), hess_u(2,0), this->
_hess_tol);
412 LIBMESH_ASSERT_NUMBERS_EQUAL
413 (hess_u(1,2), hess_u(2,1), this->
_hess_tol);
414 LIBMESH_ASSERT_NUMBERS_EQUAL
415 (tangential_hess(0,2), hess_u(0,2), this->
_hess_tol);
416 LIBMESH_ASSERT_NUMBERS_EQUAL
417 (tangential_hess(1,2), hess_u(1,2), this->
_hess_tol);
418 LIBMESH_ASSERT_NUMBERS_EQUAL
419 (tangential_hess(2,2), hess_u(2,2), this->
_hess_tol);
432#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
434 if (family == SZABAB)
440 auto d2phidx2 = this->_fe_side->get_d2phidx2();
441 CPPUNIT_ASSERT(d2phidx2.size() > 0);
442 CPPUNIT_ASSERT_EQUAL(d2phidx2.size(), this->_dof_indices.size());
444 auto d2phidxdy = this->_fe_side->get_d2phidxdy();
445 CPPUNIT_ASSERT_EQUAL(d2phidxdy.size(), this->_dof_indices.size());
446 auto d2phidy2 = this->_fe_side->get_d2phidy2();
447 CPPUNIT_ASSERT_EQUAL(d2phidy2.size(), this->_dof_indices.size());
450 auto d2phidxdz = this->_fe_side->get_d2phidxdz();
451 CPPUNIT_ASSERT_EQUAL(d2phidxdz.size(), this->_dof_indices.size());
452 auto d2phidydz = this->_fe_side->get_d2phidydz();
453 CPPUNIT_ASSERT_EQUAL(d2phidydz.size(), this->_dof_indices.size());
454 auto d2phidz2 = this->_fe_side->get_d2phidz2();
455 CPPUNIT_ASSERT_EQUAL(d2phidz2.size(), this->_dof_indices.size());
458 std::size_t n_qp = d2phidx2[0].size();
459 CPPUNIT_ASSERT(n_qp > 0);
461 auto xyz = this->_fe_side->get_xyz();
462 CPPUNIT_ASSERT_EQUAL(n_qp, xyz.size());
464 auto normals = this->_fe_side->get_normals();
465 CPPUNIT_ASSERT_EQUAL(n_qp, normals.size());
467 for (
auto qp : index_range(d2phidx2[0]))
470 for (
auto d : index_range(d2phidx2))
472 hess_u(0,0) += d2phidx2[d][qp] * (*this->
_sys->current_local_solution)(this->
_dof_indices[d]);
474 hess_u(0,1) += d2phidxdy[d][qp] * (*this->
_sys->current_local_solution)(this->
_dof_indices[d]);
475 hess_u(1,1) += d2phidy2[d][qp] * (*this->
_sys->current_local_solution)(this->
_dof_indices[d]);
478 hess_u(0,2) += d2phidxdz[d][qp] * (*this->
_sys->current_local_solution)(this->
_dof_indices[d]);
479 hess_u(1,2) += d2phidydz[d][qp] * (*this->
_sys->current_local_solution)(this->
_dof_indices[d]);
480 hess_u(2,2) += d2phidz2[d][qp] * (*this->
_sys->current_local_solution)(this->
_dof_indices[d]);
485 hess_u(1,0) = hess_u(0,1);
488 hess_u(2,0) = hess_u(0,2);
489 hess_u(2,1) = hess_u(1,2);
499 Point n = normals[qp];
500 hess_u = tangential_hessian(hess_u, n);
502 if (family == RATIONAL_BERNSTEIN && order > 1)
505 const Point p = xyz[qp];
509 RealTensor tangential_hess = tangential_hessian(true_hess, n);
511 LIBMESH_ASSERT_NUMBERS_EQUAL
512 (tangential_hess(0,0), hess_u(0,0), this->
_hess_tol);
515 LIBMESH_ASSERT_NUMBERS_EQUAL
516 (tangential_hess(0,1), hess_u(0,1), this->
_hess_tol);
517 LIBMESH_ASSERT_NUMBERS_EQUAL
518 (tangential_hess(1,1), hess_u(1,1), this->
_hess_tol);
522 LIBMESH_ASSERT_NUMBERS_EQUAL
523 (tangential_hess(0,2), hess_u(0,2), this->
_hess_tol);
524 LIBMESH_ASSERT_NUMBERS_EQUAL
525 (tangential_hess(1,2), hess_u(1,2), this->
_hess_tol);
526 LIBMESH_ASSERT_NUMBERS_EQUAL
527 (tangential_hess(2,2), hess_u(2,2), this->
_hess_tol);
552 MeshTools::Generation::build_square(
mesh, 1, 1, 0., 1., 0., 1., QUAD9);
554 auto range =
mesh.active_local_element_ptr_range();
555 if (range.begin() == range.end())
558 const Elem * elem = *range.begin();
559 CPPUNIT_ASSERT_EQUAL(
static_cast<int>(QUAD9),
560 static_cast<int>(elem->type()));
562 const FEType fe_type(CONSTANT, SIDE_HIERARCHIC);
563 const std::vector<Number> elem_soln = {1, 3, 5, 7};
565 std::vector<Number> nodal_soln;
566 FEInterface::nodal_soln(2,
573 CPPUNIT_ASSERT_EQUAL(std::size_t(9), nodal_soln.size());
575 std::vector<Number> expected(nodal_soln.size(), 0);
576 std::vector<unsigned int> expected_count(nodal_soln.size(), 0);
577 for (
const auto side : elem->side_index_range())
578 for (
const auto n : elem->nodes_on_side(side))
580 expected[n] += elem_soln[side];
584 unsigned int n_nodes_without_side_value = 0;
585 for (
const auto n : index_range(expected))
587 if (expected_count[n])
588 expected[n] /= expected_count[n];
590 ++n_nodes_without_side_value;
592 LIBMESH_ASSERT_NUMBERS_EQUAL(expected[n],
594 TOLERANCE * TOLERANCE);
597 CPPUNIT_ASSERT_EQUAL(1u, n_nodes_without_side_value);
605#define INSTANTIATE_FESIDETEST(order, family, elemtype) \
606 class FESideTest_##order##_##family##_##elemtype : public FESideTest<order, family, elemtype> { \
608 FESideTest_##order##_##family##_##elemtype() : \
609 FESideTest<order,family,elemtype>() { \
610 if (unitlog->summarized_logs_enabled()) \
611 this->libmesh_suite_name = "FESideTest"; \
613 this->libmesh_suite_name = "FESideTest_" #order "_" #family "_" #elemtype; \
615 CPPUNIT_TEST_SUITE( FESideTest_##order##_##family##_##elemtype ); \
617 CPPUNIT_TEST_SUITE_END(); \
620 CPPUNIT_TEST_SUITE_REGISTRATION( FESideTest_##order##_##family##_##elemtype );
void testSideLoop(Functor f)
std::unique_ptr< QGauss > _qrule_side
std::unique_ptr< FEBase > _fe_side
std::unique_ptr< Mesh > _mesh
std::vector< dof_id_type > _dof_indices
static RealTensor true_hessian(Point p)
static RealGradient true_gradient(Point p)
LIBMESH_CPPUNIT_TEST_SUITE(SideHierarchicNodalSolnTest)
CPPUNIT_TEST(testConstantQuad9)
Communicator * TestCommWorld
INSTANTIATE_FESIDETEST(CONSTANT, SIDE_HIERARCHIC, EDGE3)
CPPUNIT_TEST_SUITE_REGISTRATION(SideHierarchicNodalSolnTest)
Number fe_cubic_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Number rational_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Number fe_quartic_test(const Point &p, const Parameters &, const std::string &, const std::string &)
TypeTensor< typename CompareTypes< T, T2 >::supertype > outer_product(const TypeVector< T > &a, const TypeVector< T2 > &b)