https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PenetrationLocator.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 "PenetrationLocator.h"
11
12#include "ArbitraryQuadrature.h"
13#include "Conversion.h"
14#include "GeometricSearchData.h"
15#include "LineSegment.h"
16#include "MooseMesh.h"
17#include "NearestNodeLocator.h"
18#include "PenetrationThread.h"
19#include "SubProblem.h"
20#include "MooseApp.h"
21
22#include <sstream>
23
25 GeometricSearchData & /*geom_search_data*/,
26 MooseMesh & mesh,
27 const unsigned int primary_id,
28 const unsigned int secondary_id,
29 Order order,
30 NearestNodeLocator & nearest_node)
31 : Restartable(subproblem.getMooseApp(),
32 Moose::stringify(primary_id) + "to" + Moose::stringify(secondary_id),
33 "PenetrationLocator",
34 0),
35 PerfGraphInterface(subproblem.getMooseApp().perfGraph(),
36 "PenetrationLocator_" + Moose::stringify(primary_id) + "_" +
37 Moose::stringify(secondary_id)),
38 _subproblem(subproblem),
39 _mesh(mesh),
40 _primary_boundary(primary_id),
41 _secondary_boundary(secondary_id),
42 _fe_type(order),
43 _nearest_node(nearest_node),
44 _penetration_info(declareRestartableDataWithContext<std::map<dof_id_type, PenetrationInfo *>>(
45 "penetration_info", &_mesh)),
46 _has_penetrated(declareRestartableData<std::set<dof_id_type>>("has_penetrated")),
47 _check_whether_reasonable(true),
48 _update_location(declareRestartableData<bool>("update_location", true)),
49 _tangential_tolerance(0.0),
50 _do_normal_smoothing(false),
51 _normal_smoothing_distance(0.0),
52 _normal_smoothing_method(NSM_EDGE_BASED),
53 _use_point_locator(false),
54 _patch_update_strategy(_mesh.getPatchUpdateStrategy())
55{
56 // Preconstruct an FE object for each thread we're going to use and for each lower-dimensional
57 // element
58 // This is a time savings so that the thread objects don't do this themselves multiple times
59 _fe.resize(libMesh::n_threads());
60 for (unsigned int i = 0; i < libMesh::n_threads(); i++)
61 {
62 unsigned int n_dims = _mesh.dimension();
63 _fe[i].resize(n_dims + 1);
64 for (unsigned int dim = 0; dim <= n_dims; ++dim)
65 {
66 _fe[i][dim] = FEBase::build(dim, _fe_type).release();
67 _fe[i][dim]->get_xyz();
68 _fe[i][dim]->get_phi();
69 _fe[i][dim]->get_dphi();
70 _fe[i][dim]->get_dxyzdxi();
71 _fe[i][dim]->get_d2xyzdxi2();
72 _fe[i][dim]->get_d2xyzdxideta();
73 _fe[i][dim]->get_dxyzdeta();
74 _fe[i][dim]->get_d2xyzdeta2();
75 _fe[i][dim]->get_d2xyzdxideta();
76 }
77 }
78
80 {
81 if (!((_subproblem.hasVariable("nodal_normal_x")) &&
82 (_subproblem.hasVariable("nodal_normal_y")) &&
83 (_subproblem.hasVariable("nodal_normal_z"))))
84 {
86 "To use nodal-normal-based smoothing, the nodal_normal_x, nodal_normal_y, and "
87 "nodal_normal_z variables must exist. Are you missing the \\[NodalNormals\\] block?");
88 }
89 }
90}
91
93{
94 for (unsigned int i = 0; i < libMesh::n_threads(); i++)
95 for (unsigned int dim = 0; dim < _fe[i].size(); dim++)
96 delete _fe[i][dim];
97
98 for (auto & it : _penetration_info)
99 delete it.second;
100}
101
102void
104{
105 TIME_SECTION("detectPenetration", 3, "Detecting Penetration");
106
107 // Grab the secondary nodes we need to worry about from the NearestNodeLocator
108 NodeIdRange & secondary_node_range = _nearest_node.secondaryNodeRange();
109
110 // Make sure a master point locator has been built if we'll need one
113
115 _mesh,
126 _fe,
127 _fe_type,
130
131 Threads::parallel_reduce(secondary_node_range, pt);
132
133 std::vector<dof_id_type> recheck_secondary_nodes = pt._recheck_secondary_nodes;
134
135 // Update the patch for the secondary nodes in recheck_secondary_nodes and re-run penetration
136 // thread on these nodes at every nonlinear iteration if patch update strategy is set to
137 // "iteration".
138 if (recheck_secondary_nodes.size() > 0 && _patch_update_strategy == Moose::Iteration &&
140 {
141 // Update the patch for this subset of secondary nodes and calculate the nearest neighbor_nodes
142 _nearest_node.updatePatch(recheck_secondary_nodes);
143
144 // Re-run the penetration thread to see if these nodes are in contact with the updated patch
145 NodeIdRange recheck_secondary_node_range(
146 recheck_secondary_nodes.begin(), recheck_secondary_nodes.end(), 1);
147
148 Threads::parallel_reduce(recheck_secondary_node_range, pt);
149 }
150}
151
152void
154{
155 TIME_SECTION("reinit", 3, "Reinitializing PenetrationLocator");
156
157 // Delete the PenetrationInfo objects we own before clearing the
158 // map, or we have a memory leak.
159 for (auto & it : _penetration_info)
160 delete it.second;
161
162 _penetration_info.clear();
163
164 _has_penetrated.clear();
165
167}
168
169std::string
171{
172 std::ostringstream stream;
176 return stream.str();
177}
178
179void
180PenetrationLocator::restore(const std::string & data)
181{
182 // Delete the PenetrationInfo objects we own before dataLoad clears the map, or we have a
183 // memory leak: the generic std::map dataLoad clears without deleting owned pointers.
184 for (auto & it : _penetration_info)
185 delete it.second;
186 _penetration_info.clear();
187
188 std::istringstream stream(data);
190 dataLoad(stream, _has_penetrated, &_mesh);
192}
193
194Real
196{
197 PenetrationInfo * info = _penetration_info[node_id];
198
199 if (info)
200 return info->_distance;
201 else
202 return 0;
203}
204
205RealVectorValue
207{
208 std::map<dof_id_type, PenetrationInfo *>::const_iterator found_it =
209 _penetration_info.find(node_id);
210
211 if (found_it != _penetration_info.end())
212 return found_it->second->_normal;
213 else
214 return RealVectorValue(0, 0, 0);
215}
216
217void
222
223void
228
229void
231{
232 _update_location = update;
233}
234
235void
237{
238 _tangential_tolerance = tangential_tolerance;
239}
240
241void
243{
244 _normal_smoothing_distance = normal_smoothing_distance;
247}
248
249void
251{
252 if (nsmString == "edge_based")
254 else if (nsmString == "nodal_normal_based")
256 else
257 mooseError("Invalid normal_smoothing_method: ", nsmString);
259}
void dataStore(std::ostream &stream, LineSegment &l, void *context)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
void dataLoad(std::istream &stream, std::map< dof_id_type, PenetrationInfo * > &m, void *context)
We have to have a specialization for this map because the PenetrationInfo objects MUST get deleted be...
unsigned int dim
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition MooseMesh.h:95
virtual unsigned int dimension() const
Returns MeshBase::mesh_dimension(), (not MeshBase::spatial_dimension()!) of the underlying libMesh me...
Definition MooseMesh.C:2949
const std::unordered_map< dof_id_type, std::vector< dof_id_type > > & nodeToElemMap()
If not already created, creates a map from every node to all elements to which they are connected.
Definition MooseMesh.C:1241
virtual std::unique_ptr< libMesh::PointLocatorBase > getPointLocator() const
Proxy function to get a (sub)PointLocator from either the underlying libMesh mesh (default),...
Definition MooseMesh.C:3801
Finds the nearest node to each node in boundary1 to each node in boundary2 and the other way around.
NodeIdRange & secondaryNodeRange()
Returns the NodeIdRange of secondary nodes to be used for calling threaded functions operating on the...
void updatePatch(std::vector< dof_id_type > &secondary_nodes)
Reconstructs the KDtree, updates the patch for the nodes in secondary_nodes, and updates the closest ...
Data structure used to hold penetration information.
NORMAL_SMOOTHING_METHOD _normal_smoothing_method
bool _check_whether_reasonable
Check whether found candidates are reasonable.
void setNormalSmoothingMethod(std::string nsmString)
RealVectorValue penetrationNormal(dof_id_type node_id)
void setUsePointLocator(bool state)
void setUpdate(bool update)
void reinit()
Completely redo the search from scratch.
void setTangentialTolerance(Real tangential_tolerance)
PenetrationLocator(SubProblem &subproblem, GeometricSearchData &geom_search_data, MooseMesh &mesh, const unsigned int primary_id, const unsigned int secondary_id, Order order, NearestNodeLocator &nearest_node)
libMesh::FEType _fe_type
void setCheckWhetherReasonable(bool state)
void setNormalSmoothingDistance(Real normal_smoothing_distance)
std::vector< std::vector< libMesh::FEBase * > > _fe
std::map< dof_id_type, PenetrationInfo * > & _penetration_info
Data structure of nodes and their associated penetration information.
std::set< dof_id_type > & _has_penetrated
Real penetrationDistance(dof_id_type node_id)
void restore(const std::string &data)
Restores penetration state previously captured by backup().
std::string backup()
Serializes this locator's restartable penetration state (the same state used for restart/recover) int...
const Moose::PatchUpdateType _patch_update_strategy
NearestNodeLocator & _nearest_node
std::vector< dof_id_type > _recheck_secondary_nodes
List of secondary nodes for which penetration was not detected in the current patch and for which pat...
Interface for objects interacting with the PerfGraph.
A class for creating restricted objects.
Definition Restartable.h:29
Generic class for solving transient nonlinear problems.
Definition SubProblem.h:79
const bool & currentlyComputingJacobian() const
Returns true if the problem is in the process of computing the Jacobian.
Definition SubProblem.h:692
virtual bool hasVariable(const std::string &var_name) const =0
Whether or not this problem has the variable.
MeshBase & mesh
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
@ Iteration
void parallel_reduce(const Range &range, Body &body, unsigned int n_threads=libMesh::n_threads())
unsigned int n_threads()