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
23 GeometricSearchData & /*geom_search_data*/,
24 MooseMesh & mesh,
25 const unsigned int primary_id,
26 const unsigned int secondary_id,
27 Order order,
28 NearestNodeLocator & nearest_node)
29 : Restartable(subproblem.getMooseApp(),
30 Moose::stringify(primary_id) + "to" + Moose::stringify(secondary_id),
31 "PenetrationLocator",
32 0),
33 PerfGraphInterface(subproblem.getMooseApp().perfGraph(),
34 "PenetrationLocator_" + Moose::stringify(primary_id) + "_" +
35 Moose::stringify(secondary_id)),
36 _subproblem(subproblem),
37 _mesh(mesh),
38 _primary_boundary(primary_id),
39 _secondary_boundary(secondary_id),
40 _fe_type(order),
41 _nearest_node(nearest_node),
42 _penetration_info(declareRestartableDataWithContext<std::map<dof_id_type, PenetrationInfo *>>(
43 "penetration_info", &_mesh)),
44 _has_penetrated(declareRestartableData<std::set<dof_id_type>>("has_penetrated")),
45 _check_whether_reasonable(true),
46 _update_location(declareRestartableData<bool>("update_location", true)),
47 _tangential_tolerance(0.0),
48 _do_normal_smoothing(false),
49 _normal_smoothing_distance(0.0),
50 _normal_smoothing_method(NSM_EDGE_BASED),
51 _use_point_locator(false),
52 _patch_update_strategy(_mesh.getPatchUpdateStrategy())
53{
54 // Preconstruct an FE object for each thread we're going to use and for each lower-dimensional
55 // element
56 // This is a time savings so that the thread objects don't do this themselves multiple times
57 _fe.resize(libMesh::n_threads());
58 for (unsigned int i = 0; i < libMesh::n_threads(); i++)
59 {
60 unsigned int n_dims = _mesh.dimension();
61 _fe[i].resize(n_dims + 1);
62 for (unsigned int dim = 0; dim <= n_dims; ++dim)
63 {
64 _fe[i][dim] = FEBase::build(dim, _fe_type).release();
65 _fe[i][dim]->get_xyz();
66 _fe[i][dim]->get_phi();
67 _fe[i][dim]->get_dphi();
68 _fe[i][dim]->get_dxyzdxi();
69 _fe[i][dim]->get_d2xyzdxi2();
70 _fe[i][dim]->get_d2xyzdxideta();
71 _fe[i][dim]->get_dxyzdeta();
72 _fe[i][dim]->get_d2xyzdeta2();
73 _fe[i][dim]->get_d2xyzdxideta();
74 }
75 }
76
78 {
79 if (!((_subproblem.hasVariable("nodal_normal_x")) &&
80 (_subproblem.hasVariable("nodal_normal_y")) &&
81 (_subproblem.hasVariable("nodal_normal_z"))))
82 {
84 "To use nodal-normal-based smoothing, the nodal_normal_x, nodal_normal_y, and "
85 "nodal_normal_z variables must exist. Are you missing the \\[NodalNormals\\] block?");
86 }
87 }
88}
89
91{
92 for (unsigned int i = 0; i < libMesh::n_threads(); i++)
93 for (unsigned int dim = 0; dim < _fe[i].size(); dim++)
94 delete _fe[i][dim];
95
96 for (auto & it : _penetration_info)
97 delete it.second;
98}
99
100void
102{
103 TIME_SECTION("detectPenetration", 3, "Detecting Penetration");
104
105 // Grab the secondary nodes we need to worry about from the NearestNodeLocator
106 NodeIdRange & secondary_node_range = _nearest_node.secondaryNodeRange();
107
108 // Make sure a master point locator has been built if we'll need one
111
113 _mesh,
124 _fe,
125 _fe_type,
128
129 Threads::parallel_reduce(secondary_node_range, pt);
130
131 std::vector<dof_id_type> recheck_secondary_nodes = pt._recheck_secondary_nodes;
132
133 // Update the patch for the secondary nodes in recheck_secondary_nodes and re-run penetration
134 // thread on these nodes at every nonlinear iteration if patch update strategy is set to
135 // "iteration".
136 if (recheck_secondary_nodes.size() > 0 && _patch_update_strategy == Moose::Iteration &&
138 {
139 // Update the patch for this subset of secondary nodes and calculate the nearest neighbor_nodes
140 _nearest_node.updatePatch(recheck_secondary_nodes);
141
142 // Re-run the penetration thread to see if these nodes are in contact with the updated patch
143 NodeIdRange recheck_secondary_node_range(
144 recheck_secondary_nodes.begin(), recheck_secondary_nodes.end(), 1);
145
146 Threads::parallel_reduce(recheck_secondary_node_range, pt);
147 }
148
149 if (recheck_secondary_nodes.size() > 0 && _patch_update_strategy != Moose::Iteration &&
151 mooseDoOnce(mooseWarning("Warning in PenetrationLocator. Penetration is not "
152 "detected for one or more secondary nodes. This could be because "
153 "those secondary nodes simply do not project to faces on the primary "
154 "surface. However, this could also be because contact should be "
155 "enforced on those nodes, but the faces that they project to "
156 "are outside the contact patch, which will give an erroneous "
157 "result. Use appropriate options for 'patch_size' and "
158 "'patch_update_strategy' in the Mesh block to avoid this issue. "
159 "Setting 'patch_update_strategy=iteration' is recommended because "
160 "it completely avoids this potential issue. Also note that this "
161 "warning is printed only once, so a similar situation could occur "
162 "multiple times during the simulation but this warning is printed "
163 "only at the first occurrence."));
164}
165
166void
168{
169 TIME_SECTION("reinit", 3, "Reinitializing PenetrationLocator");
170
171 // Delete the PenetrationInfo objects we own before clearing the
172 // map, or we have a memory leak.
173 for (auto & it : _penetration_info)
174 delete it.second;
175
176 _penetration_info.clear();
177
178 _has_penetrated.clear();
179
181}
182
183Real
185{
186 PenetrationInfo * info = _penetration_info[node_id];
187
188 if (info)
189 return info->_distance;
190 else
191 return 0;
192}
193
194RealVectorValue
196{
197 std::map<dof_id_type, PenetrationInfo *>::const_iterator found_it =
198 _penetration_info.find(node_id);
199
200 if (found_it != _penetration_info.end())
201 return found_it->second->_normal;
202 else
203 return RealVectorValue(0, 0, 0);
204}
205
206void
211
212void
217
218void
220{
221 _update_location = update;
222}
223
224void
226{
227 _tangential_tolerance = tangential_tolerance;
228}
229
230void
232{
233 _normal_smoothing_distance = normal_smoothing_distance;
236}
237
238void
240{
241 if (nsmString == "edge_based")
243 else if (nsmString == "nodal_normal_based")
245 else
246 mooseError("Invalid normal_smoothing_method: ", nsmString);
248}
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:2994
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:1239
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:3846
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.
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()