https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ActiveElementFractionTest.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#include "gtest/gtest.h"
11
12#include "SBMUtils.h"
13
14#include "libmesh/serial_mesh.h"
15#include "libmesh/face_quad4.h"
16#include "libmesh/enum_order.h"
17
18// activeElementFraction integrates a predicate over the element with quadrature and returns the
19// active fraction of the total measure. On the unit square, a symmetric Gauss rule splits an
20// x < 0.5 half-space predicate exactly in two, and the all/none predicates give the exact
21// endpoints one/zero.
22TEST(ActiveElementFractionTest, UnitSquare)
23{
24 Parallel::Communicator comm(MPI_COMM_SELF);
25 auto mesh = std::make_unique<libMesh::SerialMesh>(comm);
26
27 Node * n0 = mesh->add_point(Point(0.0, 0.0, 0.0), 0);
28 Node * n1 = mesh->add_point(Point(1.0, 0.0, 0.0), 1);
29 Node * n2 = mesh->add_point(Point(1.0, 1.0, 0.0), 2);
30 Node * n3 = mesh->add_point(Point(0.0, 1.0, 0.0), 3);
31
32 auto quad = new Quad4();
33 quad->set_node(0, n0);
34 quad->set_node(1, n1);
35 quad->set_node(2, n2);
36 quad->set_node(3, n3);
37 const Elem * elem = mesh->add_elem(quad);
38
39 mesh->prepare_for_use();
40
41 const auto all_active = [](const Point &) { return true; };
42 const auto none_active = [](const Point &) { return false; };
43 const auto left_half = [](const Point & p) { return p(0) < 0.5; };
44
45 // SECOND-order Gauss has 2 points per dimension, symmetric about the centre with none on it.
46 EXPECT_NEAR(SBMUtils::activeElementFraction(*elem, SECOND, all_active), 1.0, 1e-12);
47 EXPECT_NEAR(SBMUtils::activeElementFraction(*elem, SECOND, none_active), 0.0, 1e-12);
48 EXPECT_NEAR(SBMUtils::activeElementFraction(*elem, SECOND, left_half), 0.5, 1e-12);
49
50 const auto fully_occupied = SBMUtils::elementDomainOccupancy(*elem, SECOND, all_active);
51 EXPECT_TRUE(fully_occupied.all_nodes_in_domain);
52 EXPECT_FALSE(fully_occupied.all_nodes_outside_domain);
53 EXPECT_NEAR(fully_occupied.fraction_of_element_in_domain, 1.0, 1e-12);
54
55 const auto unoccupied = SBMUtils::elementDomainOccupancy(*elem, SECOND, none_active);
56 EXPECT_FALSE(unoccupied.all_nodes_in_domain);
57 EXPECT_TRUE(unoccupied.all_nodes_outside_domain);
58 EXPECT_NEAR(unoccupied.fraction_of_element_in_domain, 0.0, 1e-12);
59
60 const auto partially_occupied = SBMUtils::elementDomainOccupancy(*elem, SECOND, left_half);
61 EXPECT_FALSE(partially_occupied.all_nodes_in_domain);
62 EXPECT_FALSE(partially_occupied.all_nodes_outside_domain);
63 EXPECT_NEAR(partially_occupied.fraction_of_element_in_domain, 0.5, 1e-12);
64}
65
66// Nodal and quadrature occupancy are independent measurements. This predicate excludes every
67// corner of the unit square while including every SECOND-order quadrature point.
68TEST(ElementDomainOccupancyTest, DomainEnclosedWithinElement)
69{
70 Parallel::Communicator comm(MPI_COMM_SELF);
71 auto mesh = std::make_unique<libMesh::SerialMesh>(comm);
72
73 Node * n0 = mesh->add_point(Point(0.0, 0.0, 0.0), 0);
74 Node * n1 = mesh->add_point(Point(1.0, 0.0, 0.0), 1);
75 Node * n2 = mesh->add_point(Point(1.0, 1.0, 0.0), 2);
76 Node * n3 = mesh->add_point(Point(0.0, 1.0, 0.0), 3);
77
78 auto quad = new Quad4();
79 quad->set_node(0, n0);
80 quad->set_node(1, n1);
81 quad->set_node(2, n2);
82 quad->set_node(3, n3);
83 const Elem * elem = mesh->add_elem(quad);
84 mesh->prepare_for_use();
85
86 const auto centered_domain = [](const Point & p)
87 {
88 const Real x = p(0) - 0.5;
89 const Real y = p(1) - 0.5;
90 return x * x + y * y < 0.45 * 0.45;
91 };
92
93 const auto occupancy = SBMUtils::elementDomainOccupancy(*elem, SECOND, centered_domain);
94 EXPECT_FALSE(occupancy.all_nodes_in_domain);
95 EXPECT_TRUE(occupancy.all_nodes_outside_domain);
96 EXPECT_NEAR(occupancy.fraction_of_element_in_domain, 1.0, 1e-12);
97
98 const auto signed_value = [](const Point & p)
99 { return p(0) * (1.0 - p(0)) * p(1) * (1.0 - p(1)); };
100 const auto is_in_domain = [&signed_value](const Point & p) { return signed_value(p) > 0.0; };
101 const auto is_outside_domain = [&signed_value](const Point & p) { return signed_value(p) < 0.0; };
102
103 const auto boundary_occupancy =
104 SBMUtils::elementDomainOccupancy(*elem, SECOND, is_in_domain, is_outside_domain);
105 EXPECT_FALSE(boundary_occupancy.all_nodes_in_domain);
106 EXPECT_FALSE(boundary_occupancy.all_nodes_outside_domain);
107 EXPECT_NEAR(boundary_occupancy.fraction_of_element_in_domain, 1.0, 1e-12);
108}
TEST(ActiveElementFractionTest, UnitSquare)
const std::vector< double > y
const std::vector< double > x
const Real p
MeshBase & mesh
ElementDomainOccupancy elementDomainOccupancy(const Elem &elem, Order qrule_order, const std::function< bool(const libMesh::Point &)> &is_in_domain)
Test an element against the domain defined by is_in_domain.
Definition SBMUtils.C:51
Real activeElementFraction(const Elem &elem, Order qrule_order, const std::function< bool(const libMesh::Point &)> &is_active)
Compute the fraction of an element's quadrature-weighted measure satisfying a predicate.
Definition SBMUtils.C:26