https://mooseframework.inl.gov
Loading...
Searching...
No Matches
XFEMCutElem.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 "XFEMCutElem.h"
11
12#include "libmesh/mesh.h"
13#include "libmesh/elem.h"
14#include "libmesh/node.h"
15#include "libmesh/quadrature.h"
16#include "libmesh/fe.h"
17#include "libmesh/enum_fe_family.h"
18
19#include "EFANode.h"
20#include "EFAElement.h"
21
22XFEMCutElem::XFEMCutElem(Elem * elem, unsigned int n_qpoints, unsigned int n_sides)
23 : _n_nodes(elem->n_nodes()),
24 _n_qpoints(n_qpoints),
25 _n_sides(n_sides),
26 _nodes(_n_nodes, nullptr),
27 _elem_side_area(n_sides),
28 _physical_areafrac(n_sides),
29 _have_weights(false),
30 _have_face_weights(n_sides),
31 _new_face_weights(n_sides)
32{
33 for (unsigned int i = 0; i < _n_nodes; ++i)
34 _nodes[i] = elem->node_ptr(i);
35
36 for (unsigned int i = 0; i < _n_sides; ++i)
37 {
38 _have_face_weights[i] = false;
39 _physical_areafrac[i] = 1.0;
40 // TODO: this line does not support RZ/RSpherical geoms
41 _elem_side_area[i] = elem->side_ptr(i)->volume();
42 }
43
44 // TODO: this line does not support RZ/RSpherical geoms
45 _elem_volume = elem->volume();
46}
47
49
50Real
55
56Real
58{
59 return _physical_areafrac[side];
60}
61
62void
64 QBase * qrule,
65 Xfem::XFEM_QRULE xfem_qrule,
66 const MooseArray<Point> & q_points)
67{
68 if (!_have_weights)
69 computeXFEMWeights(qrule, xfem_qrule, q_points);
70
71 weights.resize(_new_weights.size());
72 for (unsigned int qp = 0; qp < _new_weights.size(); ++qp)
73 weights[qp] = _new_weights[qp];
74}
75
76void
78 QBase * qrule,
79 Xfem::XFEM_QRULE xfem_qrule,
80 const MooseArray<Point> & q_points,
81 unsigned int side)
82{
83 if (!_have_face_weights[side])
84 computeXFEMFaceWeights(qrule, xfem_qrule, q_points, side);
85
86 face_weights.resize(_new_face_weights[side].size());
87 for (unsigned int qp = 0; qp < _new_face_weights[side].size(); ++qp)
88 face_weights[qp] = _new_face_weights[side][qp];
89}
90
91void
93 Xfem::XFEM_QRULE /*xfem_qrule*/,
94 const MooseArray<Point> & /*q_points*/,
95 unsigned int side)
96{
98 _new_face_weights[side].resize(qrule->n_points(), 1.0);
99
101 Real surffrac = getPhysicalFaceAreaFraction(side);
102 for (unsigned qp = 0; qp < qrule->n_points(); ++qp)
103 _new_face_weights[side][qp] = surffrac;
104
105 _have_face_weights[side] = true;
106}
107
108void
110 Xfem::XFEM_QRULE xfem_qrule,
111 const MooseArray<Point> & q_points)
112{
113 _new_weights.clear();
114
115 _new_weights.resize(qrule->n_points(), 1.0);
116
117 switch (xfem_qrule)
118 {
119 case Xfem::VOLFRAC:
120 {
123 for (unsigned qp = 0; qp < qrule->n_points(); ++qp)
124 _new_weights[qp] = volfrac;
125 break;
126 }
128 {
129 // These are the coordinates in parametric coordinates
130 _qp_points = qrule->get_points();
131 _qp_weights = qrule->get_weights();
132
134
135 // Blend weights from moment fitting and volume fraction to avoid negative weights
136 Real alpha = 1.0;
137 if (*std::min_element(_new_weights.begin(), _new_weights.end()) < 0.0)
138 {
139 // One or more of the weights computed by moment fitting is negative.
140 // Blend moment and volume fraction weights to keep them nonnegative.
141 // Find the largest value of alpha that will keep all of the weights nonnegative.
142 for (unsigned int i = 0; i < _n_qpoints; ++i)
143 {
144 const Real denominator = _physical_volfrac - _new_weights[i];
145 if (denominator > 0.0) // Negative values would give a negative value for alpha, which
146 // must be between 0 and 1.
147 {
148 const Real alpha_i = _physical_volfrac / denominator;
149 if (alpha_i < alpha)
150 alpha = alpha_i;
151 }
152 }
153 for (unsigned int i = 0; i < _n_qpoints; ++i)
154 {
155 _new_weights[i] = alpha * _new_weights[i] + (1.0 - alpha) * _physical_volfrac;
156 if (_new_weights[i] < 0.0) // We can end up with small (roundoff) negative weights
157 _new_weights[i] = 0.0;
158 }
159 }
160 break;
161 }
162 case Xfem::DIRECT: // remove q-points outside the partial element's physical domain
163 {
164 bool nonzero = false;
165 for (unsigned qp = 0; qp < qrule->n_points(); ++qp)
166 {
167 // q_points contains quadrature point locations in physical coordinates
168 if (isPointPhysical(q_points[qp]))
169 {
170 nonzero = true;
171 _new_weights[qp] = 1.0;
172 }
173 else
174 _new_weights[qp] = 0.0;
175 }
176 if (!nonzero)
177 {
178 // Set the weights to a small value (1e-3) to avoid having DOFs
179 // with zeros on the diagonal, which occurs for nodes that are
180 // connected to no physical material.
181 for (unsigned qp = 0; qp < qrule->n_points(); ++qp)
182 _new_weights[qp] = 1e-3;
183 }
184 break;
185 }
186 default:
187 mooseError("Undefined option for XFEM_QRULE");
188 }
189 _have_weights = true;
190}
191
192bool
194{
195 // determine whether the point is inside the physical domain of a partial element
196 bool physical_flag = true;
197 unsigned int n_cut_planes = numCutPlanes();
198 for (unsigned int plane_id = 0; plane_id < n_cut_planes; ++plane_id)
199 {
200 Point origin = getCutPlaneOrigin(plane_id);
201 Point normal = getCutPlaneNormal(plane_id);
202 Point origin2qp = p - origin;
203 if (origin2qp * normal > 0.0)
204 {
205 physical_flag = false; // Point outside pysical domain
206 break;
207 }
208 }
209 return physical_flag;
210}
const Real p
void mooseError(Args &&... args)
void resize(unsigned int size)
void clear()
std::vector< bool > _have_face_weights
Definition XFEMCutElem.h:53
XFEMCutElem(Elem *elem, unsigned int n_qpoints, unsigned int n_sides)
Constructor initializes XFEMCutElem object.
Definition XFEMCutElem.C:22
virtual void computeMomentFittingWeights()=0
Real _physical_volfrac
Definition XFEMCutElem.h:50
void getWeightMultipliers(MooseArray< Real > &weights, QBase *qrule, Xfem::XFEM_QRULE xfem_qrule, const MooseArray< Point > &q_points)
Definition XFEMCutElem.C:63
virtual Point getCutPlaneNormal(unsigned int plane_id, MeshBase *displaced_mesh=nullptr) const =0
void getFaceWeightMultipliers(MooseArray< Real > &face_weights, QBase *qrule, Xfem::XFEM_QRULE xfem_qrule, const MooseArray< Point > &q_points, unsigned int side)
Definition XFEMCutElem.C:77
Real getPhysicalVolumeFraction() const
Returns the volume fraction of the element fragment.
Definition XFEMCutElem.C:51
unsigned int _n_sides
Definition XFEMCutElem.h:44
std::vector< Real > _qp_weights
Definition XFEMCutElem.h:47
Real getPhysicalFaceAreaFraction(unsigned int side) const
Returns the surface area fraction of the element side.
Definition XFEMCutElem.C:57
void computeXFEMWeights(QBase *qrule, Xfem::XFEM_QRULE xfem_qrule, const MooseArray< Point > &q_points)
Computes integration weights for the cut element.
std::vector< Real > _new_weights
quadrature weights from volume fraction and moment fitting
Definition XFEMCutElem.h:55
virtual void computePhysicalFaceAreaFraction(unsigned int side)=0
Computes the surface area fraction of the element side.
virtual Point getCutPlaneOrigin(unsigned int plane_id, MeshBase *displaced_mesh=nullptr) const =0
unsigned int _n_nodes
Definition XFEMCutElem.h:42
Real _elem_volume
Definition XFEMCutElem.h:48
std::vector< Node * > _nodes
Definition XFEMCutElem.h:45
std::vector< Point > _qp_points
Definition XFEMCutElem.h:46
virtual void computePhysicalVolumeFraction()=0
Computes the volume fraction of the element fragment.
bool isPointPhysical(const Point &p) const
void computeXFEMFaceWeights(QBase *qrule, Xfem::XFEM_QRULE xfem_qrule, const MooseArray< Point > &q_points, unsigned int side)
Computes face integration weights for the cut element side.
Definition XFEMCutElem.C:92
std::vector< std::vector< Real > > _new_face_weights
face quadrature weights from surface area fraction
Definition XFEMCutElem.h:57
bool _have_weights
Definition XFEMCutElem.h:52
std::vector< Real > _physical_areafrac
Definition XFEMCutElem.h:51
unsigned int _n_qpoints
Definition XFEMCutElem.h:43
virtual ~XFEMCutElem()
Definition XFEMCutElem.C:48
virtual unsigned int numCutPlanes() const =0
std::vector< Real > _elem_side_area
Definition XFEMCutElem.h:49
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0
const Node * node_ptr(const unsigned int i) const
virtual Real volume() const
const std::vector< Point > & get_points() const
unsigned int n_points() const
const std::vector< Real > & get_weights() const
XFEM_QRULE
Definition XFEM.h:38
@ DIRECT
Definition XFEM.h:41
@ VOLFRAC
Definition XFEM.h:39
@ MOMENT_FITTING
Definition XFEM.h:40
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const dof_id_type n_nodes