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
22using namespace libMesh;
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 if (recheck_secondary_nodes.size() > 0 && _patch_update_strategy != Moose::Iteration &&
153 mooseDoOnce(mooseWarning("Warning in PenetrationLocator. Penetration is not "
154 "detected for one or more secondary nodes. This could be because "
155 "those secondary nodes simply do not project to faces on the primary "
156 "surface. However, this could also be because contact should be "
157 "enforced on those nodes, but the faces that they project to "
158 "are outside the contact patch, which will give an erroneous "
159 "result. Use appropriate options for 'patch_size' and "
160 "'patch_update_strategy' in the Mesh block to avoid this issue. "
161 "Setting 'patch_update_strategy=iteration' is recommended because "
162 "it completely avoids this potential issue. Also note that this "
163 "warning is printed only once, so a similar situation could occur "
164 "multiple times during the simulation but this warning is printed "
165 "only at the first occurrence."));
166}
167
168void
170{
171 TIME_SECTION("reinit", 3, "Reinitializing PenetrationLocator");
172
173 // Delete the PenetrationInfo objects we own before clearing the
174 // map, or we have a memory leak.
175 for (auto & it : _penetration_info)
176 delete it.second;
177
178 _penetration_info.clear();
179
180 _has_penetrated.clear();
181
183}
184
185Real
187{
188 PenetrationInfo * info = _penetration_info[node_id];
189
190 if (info)
191 return info->_distance;
192 else
193 return 0;
194}
195
198{
199 std::map<dof_id_type, PenetrationInfo *>::const_iterator found_it =
200 _penetration_info.find(node_id);
201
202 if (found_it != _penetration_info.end())
203 return found_it->second->_normal;
204 else
205 return RealVectorValue(0, 0, 0);
206}
207
208void
213
214void
219
220void
222{
223 _update_location = update;
224}
225
226void
228{
229 _tangential_tolerance = tangential_tolerance;
230}
231
232void
234{
235 _normal_smoothing_distance = normal_smoothing_distance;
238}
239
240void
242{
243 if (nsmString == "edge_based")
245 else if (nsmString == "nodal_normal_based")
247 else
248 mooseError("Invalid normal_smoothing_method: ", nsmString);
250}
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition MooseError.h:345
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
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:2986
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:1236
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:3838
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)
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.
std::unique_ptr< FEGenericBase< Real > > build(const unsigned int dim, const FEType &fet)
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())
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
VectorValue< Real > RealVectorValue
Definition SubProblem.h:34
uint8_t dof_id_type
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
unsigned int n_threads()