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