https://mooseframework.inl.gov
Loading...
Searching...
No Matches
GeometricCutUserObject.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
11
12// MOOSE includes
13#include "MooseError.h"
14#include "XFEM.h"
15#include "DataIO.h"
16#include "EFAElement2D.h"
17#include "EFAElement3D.h"
19#include "DisplacedProblem.h"
20
23{
25 params.addClassDescription("Base UserObject class for XFEM Geometric Cuts");
26 params.addParam<bool>("heal_always", false, "Heal previous cuts at every time step");
27 ExecFlagEnum & exec = params.set<ExecFlagEnum>("execute_on");
29 params.setDocString("execute_on", exec.getDocString());
30 params.set<ExecFlagEnum>("execute_on") = EXEC_XFEM_MARK;
31 params.set<int>("execution_order_group") = 1;
32 return params;
33}
34
36 const bool uses_mesh)
37 : CrackFrontPointsProvider(parameters, uses_mesh), _heal_always(getParam<bool>("heal_always"))
38{
39 _xfem = MooseSharedNamespace::dynamic_pointer_cast<XFEM>(_fe_problem.getXFEM());
40 if (_xfem == nullptr)
41 mooseError("Problem casting to XFEM in GeometricCutUserObject");
42
43 _xfem->addGeometricCut(this);
44
45 auto new_xfem_epl = std::make_shared<XFEMElementPairLocator>(_xfem, _interface_id);
47
48 if (_fe_problem.getDisplacedProblem() != nullptr)
49 {
50 auto new_xfem_epl2 = std::make_shared<XFEMElementPairLocator>(_xfem, _interface_id, true);
51 _fe_problem.getDisplacedProblem()->geomSearchData().addElementPairLocator(_interface_id,
52 new_xfem_epl2);
53 }
54}
55
56void
62
63void
65{
66 if (_current_elem->dim() == 2)
67 {
68 std::vector<Xfem::CutEdge> elem_cut_edges;
69 std::vector<Xfem::CutNode> elem_cut_nodes;
70 std::vector<Xfem::CutEdge> frag_cut_edges;
71 std::vector<std::vector<Point>> frag_edges;
72
73 EFAElement2D * EFAElem = _xfem->getEFAElem2D(_current_elem);
74
75 // Don't cut again if elem has been already cut twice
76 if (!EFAElem->isFinalCut())
77 {
78 // get fragment edges
79 _xfem->getFragmentEdges(_current_elem, EFAElem, frag_edges);
80
81 // mark cut edges for the element and its fragment
82 bool cut = cutElementByGeometry(_current_elem, elem_cut_edges, elem_cut_nodes);
83 if (EFAElem->numFragments() > 0)
84 cut |= cutFragmentByGeometry(frag_edges, frag_cut_edges);
85
86 if (cut)
87 {
89 gmei2d._elem_cut_edges = elem_cut_edges;
90 gmei2d._elem_cut_nodes = elem_cut_nodes;
91 gmei2d._frag_cut_edges = frag_cut_edges;
92 gmei2d._frag_edges = frag_edges;
93 _marked_elems_2d[_current_elem->id()].push_back(gmei2d);
94 }
95 }
96 }
97 else if (_current_elem->dim() == 3)
98 {
99 std::vector<Xfem::CutFace> elem_cut_faces;
100 std::vector<Xfem::CutFace> frag_cut_faces;
101 std::vector<std::vector<Point>> frag_faces;
102
103 EFAElement3D * EFAElem = _xfem->getEFAElem3D(_current_elem);
104
105 // Don't cut again if elem has been already cut twice
106 if (!EFAElem->isFinalCut())
107 {
108 // get fragment edges
109 _xfem->getFragmentFaces(_current_elem, EFAElem, frag_faces);
110
111 // mark cut faces for the element and its fragment
112 bool cut = cutElementByGeometry(_current_elem, elem_cut_faces);
113 // TODO: This would be done for branching, which is not yet supported in 3D
114 // if (EFAElem->numFragments() > 0)
115 // cut |= cutFragmentByGeometry(frag_faces, frag_cut_faces, _t);
116
117 if (cut)
118 {
120 gmei3d._elem_cut_faces = elem_cut_faces;
121 gmei3d._frag_cut_faces = frag_cut_faces;
122 gmei3d._frag_faces = frag_faces;
123 _marked_elems_3d[_current_elem->id()].push_back(gmei3d);
124 }
125 }
126 }
127}
128
129void
131{
132 const auto & gcuo = cast_ref<const GeometricCutUserObject &>(y);
133
134 for (const auto & it : gcuo._marked_elems_2d)
135 {
136 mooseAssert(_marked_elems_2d.find(it.first) == _marked_elems_2d.end(),
137 "Element already inserted in map from a different thread");
138 _marked_elems_2d[it.first] = it.second;
139 }
140 for (const auto & it : gcuo._marked_elems_3d)
141 {
142 mooseAssert(_marked_elems_3d.find(it.first) == _marked_elems_3d.end(),
143 "Element already inserted in map from a different thread");
144 _marked_elems_3d[it.first] = it.second;
145 }
146}
147
148// custom data load and data store methods for geometric cut structs
149template <>
150inline void
151dataStore(std::ostream & stream, Xfem::CutEdge & ce, void * context)
152{
153 dataStore(stream, ce._id1, context);
154 dataStore(stream, ce._id2, context);
155 dataStore(stream, ce._distance, context);
156 dataStore(stream, ce._host_side_id, context);
157}
158
159template <>
160inline void
161dataLoad(std::istream & stream, Xfem::CutEdge & ce, void * context)
162{
163 dataLoad(stream, ce._id1, context);
164 dataLoad(stream, ce._id2, context);
165 dataLoad(stream, ce._distance, context);
166 dataLoad(stream, ce._host_side_id, context);
167}
168
169template <>
170inline void
171dataStore(std::ostream & stream, Xfem::CutNode & cn, void * context)
172{
173 dataStore(stream, cn._id, context);
174 dataStore(stream, cn._host_id, context);
175}
176
177template <>
178inline void
179dataLoad(std::istream & stream, Xfem::CutNode & cn, void * context)
180{
181 dataLoad(stream, cn._id, context);
182 dataLoad(stream, cn._host_id, context);
183}
184
185template <>
186inline void
187dataStore(std::ostream & stream, Xfem::CutFace & cf, void * context)
188{
189 dataStore(stream, cf._face_id, context);
190 dataStore(stream, cf._face_edge, context);
191 dataStore(stream, cf._position, context);
192}
193
194template <>
195inline void
196dataLoad(std::istream & stream, Xfem::CutFace & cf, void * context)
197{
198 dataLoad(stream, cf._face_id, context);
199 dataLoad(stream, cf._face_edge, context);
200 dataLoad(stream, cf._position, context);
201}
202
203template <>
204inline void
205dataStore(std::ostream & stream, Xfem::GeomMarkedElemInfo2D & gmei, void * context)
206{
207 dataStore(stream, gmei._elem_cut_edges, context);
208 dataStore(stream, gmei._elem_cut_nodes, context);
209 dataStore(stream, gmei._frag_cut_edges, context);
210 dataStore(stream, gmei._frag_edges, context);
211}
212
213template <>
214inline void
215dataLoad(std::istream & stream, Xfem::GeomMarkedElemInfo2D & gmei, void * context)
216{
217 dataLoad(stream, gmei._elem_cut_edges, context);
218 dataLoad(stream, gmei._elem_cut_nodes, context);
219 dataLoad(stream, gmei._frag_cut_edges, context);
220 dataLoad(stream, gmei._frag_edges, context);
221}
222
223template <>
224inline void
225dataStore(std::ostream & stream, Xfem::GeomMarkedElemInfo3D & gmei, void * context)
226{
227 dataStore(stream, gmei._elem_cut_faces, context);
228 dataStore(stream, gmei._frag_cut_faces, context);
229 dataStore(stream, gmei._frag_faces, context);
230}
231
232template <>
233inline void
234dataLoad(std::istream & stream, Xfem::GeomMarkedElemInfo3D & gmei, void * context)
235{
236 dataLoad(stream, gmei._elem_cut_faces, context);
237 dataLoad(stream, gmei._frag_cut_faces, context);
238 dataLoad(stream, gmei._frag_faces, context);
239}
240
241void
242GeometricCutUserObject::serialize(std::string & serialized_buffer)
243{
244 // stream for serializing the _marked_elems_2d and _marked_elems_3d data structures to a byte
245 // stream
246 std::ostringstream oss;
247 dataStore(oss, _marked_elems_2d, this);
248 dataStore(oss, _marked_elems_3d, this);
249
250 // Populate the passed in string pointer with the string stream's buffer contents
251 serialized_buffer.assign(oss.str());
252}
253
254void
255GeometricCutUserObject::deserialize(std::vector<std::string> & serialized_buffers)
256{
257 mooseAssert(serialized_buffers.size() == _app.n_processors(),
258 "Unexpected size of serialized_buffers: " << serialized_buffers.size());
259
260 // The input string stream used for deserialization
261 std::istringstream iss;
262
263 // Loop over all datastructures for all processors to perfrom the gather operation
264 for (unsigned int rank = 0; rank < serialized_buffers.size(); ++rank)
265 {
266 // skip the current processor (its data is already in the structures)
267 if (rank == processor_id())
268 continue;
269
270 // populate the stream with a new buffer and reset stream state
271 iss.clear();
272 iss.str(serialized_buffers[rank]);
273
274 // Load the communicated data into temporary structures
275 std::map<unsigned int, std::vector<Xfem::GeomMarkedElemInfo2D>> other_marked_elems_2d;
276 std::map<unsigned int, std::vector<Xfem::GeomMarkedElemInfo3D>> other_marked_elems_3d;
277 dataLoad(iss, other_marked_elems_2d, this);
278 dataLoad(iss, other_marked_elems_3d, this);
279
280 // merge the data in with the current processor's data
281 _marked_elems_2d.insert(other_marked_elems_2d.begin(), other_marked_elems_2d.end());
282 _marked_elems_3d.insert(other_marked_elems_3d.begin(), other_marked_elems_3d.end());
283 }
284}
285
286void
288{
289 // for single processor runs we do not need to do anything here
290 if (_app.n_processors() > 1)
291 {
292 // create send buffer
293 std::string send_buffer;
294
295 // create byte buffers for the streams received from all processors
296 std::vector<std::string> recv_buffers;
297
298 // pack the complex datastructures into the string stream
299 serialize(send_buffer);
300
301 // broadcast serialized data to and receive from all processors
302 _communicator.allgather(send_buffer, recv_buffers);
303
304 // unpack the received data and merge it into the local data structures
305 deserialize(recv_buffers);
306 }
307
308 for (const auto & it : _marked_elems_2d)
309 for (const auto & gmei : it.second)
310 _xfem->addGeomMarkedElem2D(it.first, gmei, _interface_id);
311
312 for (const auto & it : _marked_elems_3d)
313 for (const auto & gmei : it.second)
314 _xfem->addGeomMarkedElem3D(it.first, gmei, _interface_id);
315
316 _marked_elems_2d.clear();
317 _marked_elems_3d.clear();
318}
319
322{
323 return _xfem->getCutSubdomainID(this, elem);
324}
const std::vector< double > y
void dataStore(std::ostream &stream, Xfem::CutEdge &ce, void *context)
void dataLoad(std::istream &stream, Xfem::CutEdge &ce, void *context)
void dataLoad(std::istream &stream, LineSegment &l, void *context)
void dataStore(std::ostream &stream, LineSegment &l, void *context)
const ExecFlagType EXEC_XFEM_MARK
Exec flag used to execute MooseObjects while elements are being marked for cutting by XFEM.
unsigned int CutSubdomainID
Base class for crack front points provider.
static InputParameters validParams()
virtual unsigned int numFragments() const
virtual bool isFinalCut() const
virtual bool isFinalCut() const
const Elem *const & _current_elem
void addAvailableFlags(const ExecFlagType &flag, Args... flags)
std::shared_ptr< XFEMInterface > getXFEM()
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
virtual GeometricSearchData & geomSearchData() override
std::map< unsigned int, std::vector< Xfem::GeomMarkedElemInfo3D > > _marked_elems_3d
virtual void threadJoin(const UserObject &y) override
std::map< unsigned int, std::vector< Xfem::GeomMarkedElemInfo2D > > _marked_elems_2d
Containers with information about all 2D and 3D elements marked for cutting by this object.
static InputParameters validParams()
Factory constructor, takes parameters so that all derived classes can be built using the same constru...
virtual void execute() override
unsigned int _interface_id
Associated interface id.
void serialize(std::string &serialized_buffer)
Methods to pack/unpack the _marked_elems_2d and _marked_elems_3d data into a structure suitable for p...
virtual bool cutFragmentByGeometry(std::vector< std::vector< Point > > &frag_edges, std::vector< Xfem::CutEdge > &cut_edges) const =0
Check to see whether a fragment of a 2D element should be cut based on geometric conditions.
GeometricCutUserObject(const InputParameters &parameters, const bool uses_mesh=false)
void deserialize(std::vector< std::string > &serialized_buffers)
virtual bool cutElementByGeometry(const Elem *elem, std::vector< Xfem::CutEdge > &cut_edges, std::vector< Xfem::CutNode > &cut_nodes) const =0
Check to see whether a specified 2D element should be cut based on geometric conditions.
virtual void initialize() override
virtual CutSubdomainID getCutSubdomainID(const Node *) const
Get CutSubdomainID telling which side the node belongs to relative to the cut.
virtual void finalize() override
std::shared_ptr< XFEM > _xfem
Pointer to the XFEM controller object.
void addElementPairLocator(BoundaryID interface_id, std::shared_ptr< ElementPairLocator > epl)
void setDocString(const std::string &name, const std::string &doc)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
void mooseError(Args &&... args) const
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
FEProblemBase & _fe_problem
const Parallel::Communicator & _communicator
processor_id_type processor_id() const
processor_id_type n_processors() const
Data structure defining a cut on an element edge.
unsigned int _id1
ID of the first node on the edge.
Real _distance
Fractional distance along the edge (from node 1 to 2) where the cut is located.
unsigned int _id2
ID of the second node on the edge.
unsigned int _host_side_id
Local ID of this side in the host element.
Data structure defining a cut through a face.
unsigned int _face_id
ID of the cut face.
std::vector< Real > _position
Fractional distance along the cut edges where the cut is located.
std::vector< unsigned int > _face_edge
IDs of all cut faces.
Data structure defining a cut through a node.
unsigned int _id
ID of the cut node.
unsigned int _host_id
Local ID of this node in the host element.
Data structure describing geometrically described cut through 2D element.
std::vector< CutNode > _elem_cut_nodes
Container for data about all cut nodes in this element.
std::vector< CutEdge > _frag_cut_edges
Container for data about all cut fragments in this element.
std::vector< CutEdge > _elem_cut_edges
Container for data about all cut edges in this element.
std::vector< std::vector< Point > > _frag_edges
Container for data about all cut edges in cut fragments in this element.
Data structure describing geometrically described cut through 3D element.
std::vector< CutFace > _frag_cut_faces
Container for data about all faces this element's fragment.
std::vector< CutFace > _elem_cut_faces
Container for data about all cut faces in this element.
std::vector< std::vector< Point > > _frag_faces
Container for data about all cut faces in cut fragments in this element.