https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Positions.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 "Positions.h"
11#include "libmesh/parallel_algebra.h"
12#include "MooseMeshUtils.h"
13
16{
18
19 params.addParam<PositionsName>("initial_positions",
20 "Positions at the beginning of the simulation");
21
22 // This parameter should be set by each derived class depending on whether the generation of
23 // positions is replicated or distributed. We want positions to be replicated across all ranks
24 params.addRequiredParam<bool>("auto_broadcast",
25 "Wether Positions should be broadcasted across all ranks");
26 // This parameter should be set by each derived class depending on whether positions should
27 // be sorted after being communicated. Sorting is usually undesirable, as the user input order
28 // should be respected. It may be only desirable for testing reproducibility
29 params.addRequiredParam<bool>("auto_sort", "Whether Positions should be sorted by coordinates");
30
31 // In general, no need to refresh Positions unless the mesh moved
32 params.set<ExecFlagEnum>("execute_on") = EXEC_NONE;
33
34 params.addParamNamesToGroup("auto_broadcast auto_sort", "Advanced");
35 params.registerBase("Positions");
36 return params;
37}
38
40 : GeneralReporter(parameters),
41 // leverage reporter interface to keep track of consumers
42 _initial_positions(isParamValid("initial_positions")
43 ? &getReporterValueByName<std::vector<Point>>(
44 getParam<PositionsName>("initial_positions") + "/positions_1d")
45 : nullptr),
46 // Positions will be replicated on every rank so transfers may query positions from all ranks
47 _positions(declareValueByName<std::vector<Point>, ReporterVectorContext<Point>>(
48 "positions_1d", REPORTER_MODE_REPLICATED)),
49 _need_broadcast(getParam<bool>("auto_broadcast")),
50 _need_sort(getParam<bool>("auto_sort")),
51 _initialized(false)
52{
53
55 _initial_positions_kd_tree = std::make_unique<KDTree>(*_initial_positions, 1);
56}
57
58const Point &
59Positions::getPosition(unsigned int index, bool initial) const
60{
61 mooseAssert(initialized(initial), "Positions vector has not been initialized.");
62 // Check sizes of inital positions
63 if (initial && _initial_positions && (*_initial_positions).size() < index)
64 mooseError("Initial positions is not sized or initialized appropriately");
65
66 // Check sizes of regular positions
67 if (!initial)
68 {
69 if (_initial_positions && _positions.size() != (*_initial_positions).size())
70 mooseError("Initial positions and current positions array length do not match");
71 else if (_positions.size() < index)
72 mooseError("Positions retrieved with an out-of-bound index: '",
73 index,
74 "' when there are only ",
75 _positions.size(),
76 " positions.");
77 }
78
79 if (initial && _initial_positions)
80 return (*_initial_positions)[index];
81 if (_positions.size())
82 return _positions[index];
83 else
84 mooseError("Positions vector has not been initialized.");
85}
86
87const Point &
88Positions::getNearestPosition(const Point & target, const bool initial) const
89{
90 mooseAssert(initialized(initial), "Positions vector has not been initialized.");
91 const auto & positions = (initial && _initial_positions) ? *_initial_positions : _positions;
92 return positions[getNearestPositionIndex(target, initial)];
93}
94
95unsigned int
96Positions::getNearestPositionIndex(const Point & target, const bool initial) const
97{
98 mooseAssert(initialized(initial), "Positions vector has not been initialized.");
99 std::vector<std::size_t> return_index(1);
100
101 if (initial && _initial_positions)
102 {
103 mooseAssert(_initial_positions_kd_tree, "Should have an initial positions KDTree");
104 _initial_positions_kd_tree->neighborSearch(target, 1, return_index);
105 }
106 else
107 {
108 mooseAssert(_positions_kd_tree, "Should have a positions KDTree");
109 _positions_kd_tree->neighborSearch(target, 1, return_index);
110 }
111
112 return return_index[0];
113}
114
115const std::vector<Point> &
116Positions::getPositions(bool initial) const
117{
118 if (initial && _initial_positions)
119 return *_initial_positions;
120 if (_positions.size())
121 return _positions;
122 else
123 mooseError("Positions vector has not been initialized.");
124}
125
126const std::vector<std::vector<Point>> &
128{
129 if (_positions_2d.size())
130 return _positions_2d;
131 else
132 mooseError("2D positions vectors have not been initialized.");
133}
134
135const std::vector<std::vector<std::vector<Point>>> &
137{
138 if (_positions_3d.size())
139 return _positions_3d;
140 else
141 mooseError("3D positions vectors have not been initialized.");
142}
143
144const std::vector<std::vector<std::vector<std::vector<Point>>>> &
146{
147 if (_positions_4d.size())
148 return _positions_4d;
149 else
150 mooseError("4D positions vectors have not been initialized.");
151}
152
153void
155{
156 _positions.clear();
157 _positions_2d.clear();
158 _positions_3d.clear();
159 _positions_4d.clear();
160}
161
162void
164{
165 // Unroll in every dimension available
166 std::vector<Point> temp_2d_unrolled;
167 std::vector<Point> temp_3d_unrolled;
168 std::vector<Point> temp_4d_unrolled;
169 for (auto vec : _positions_2d)
170 temp_2d_unrolled.insert(temp_2d_unrolled.end(), vec.begin(), vec.end());
171 for (const auto & vec_vec : _positions_3d)
172 for (const auto & vec : vec_vec)
173 temp_3d_unrolled.insert(temp_3d_unrolled.end(), vec.begin(), vec.end());
174 for (const auto & vec_vec_vec : _positions_4d)
175 for (const auto & vec_vec : vec_vec_vec)
176 for (const auto & vec : vec_vec)
177 temp_4d_unrolled.insert(temp_4d_unrolled.end(), vec.begin(), vec.end());
178
179 // for now we wont even tolerate a different ordering
180 // 2D & 1D: check for conflicts
181 if (temp_2d_unrolled.size() && _positions.size() && temp_2d_unrolled != _positions)
182 mooseError("Inconsistency between the 2D and 1D position vectors detected. "
183 "The 2D positions must unroll into the 1D positions");
184
185 // 3D vs 2D & 1D
186 if (temp_3d_unrolled.size() && temp_2d_unrolled.size() && temp_3d_unrolled != temp_3d_unrolled)
187 mooseError("Inconsistency between the 3D and 2D position vectors detected. "
188 "The 3D positions must unroll the same way as the 2D positions");
189 if (temp_3d_unrolled.size() && _positions.size() && temp_3d_unrolled != _positions)
190 mooseError("Inconsistency between the 3D and 1D position vectors detected. "
191 "The 3D positions must unroll into the 1D positions");
192
193 // 4D vs all lower dimensions
194 if (temp_4d_unrolled.size() && temp_3d_unrolled.size() && temp_4d_unrolled != temp_3d_unrolled)
195 mooseError("Inconsistency between the 4D and 3D position vectors detected. "
196 "The 4D positions must unroll the same way as the 3D positions");
197 if (temp_4d_unrolled.size() && temp_2d_unrolled.size() && temp_4d_unrolled != temp_2d_unrolled)
198 mooseError("Inconsistency between the 4D and 2D position vectors detected. "
199 "The 4D positions must unroll the same way as the 2D positions");
200 if (temp_4d_unrolled.size() && _positions.size() && temp_4d_unrolled != _positions)
201 mooseError("Inconsistency between the 4D and 1D position vectors detected. "
202 "The 4D positions must unroll into the 1D positions");
203
204 // Use any of the higher D to set the one D vector
205 if (!_positions.size())
206 {
207 if (temp_2d_unrolled.size())
208 _positions = temp_2d_unrolled;
209 else if (temp_3d_unrolled.size())
210 _positions = temp_3d_unrolled;
211 else if (temp_4d_unrolled.size())
212 _positions = temp_4d_unrolled;
213 else
214 mooseError("Positions::unrollMultiDPositions() may only be called if there is at least one "
215 "non-empty positions vector.");
216 }
217}
218
219void
221{
222 // Gather up the positions vector on all ranks
223 mooseAssert(initialized(false), "Positions vector has not been initialized.");
224 if (_need_broadcast)
225 // The consumer/producer reporter interface can keep track of whether a reduction is needed
226 // (for example if a consumer needs replicated data, but the producer is distributed) however,
227 // we have currently made the decision that positions should ALWAYS be replicated
228 _communicator.allgather(_positions, /* identical buffer lengths = */ false);
229
230 // Sort positions by X then Y then Z
231 if (_need_sort)
232 std::sort(_positions.begin(), _positions.end());
233
234 // Make a KDTree with the positions
235 _positions_kd_tree = std::make_unique<KDTree>(_positions, 1);
236
237 // For now at least, we expect positions to be the same on all ranks
238 mooseAssert(comm().verify(_positions), "Positions should be the same across all MPI processes.");
239}
240
241Real
243{
244 mooseAssert(initialized(false), "Positions vector has not been initialized.");
245 // Dumb nested loops. We can revisit this once we have a KDTree for nearest position searching
246 // These nested loops are still faster than calling getNearestPositions on each position for now
247 Real min_distance_sq = std::numeric_limits<Real>::max();
248 for (const auto i1 : index_range(_positions))
249 for (auto i2 = i1 + 1; i2 < _positions.size(); i2++)
250 min_distance_sq = std::min(min_distance_sq, (_positions[i1] - _positions[i2]).norm_sq());
251 return std::sqrt(min_distance_sq);
252}
253
254bool
256{
257 mooseAssert(initialized(false), "Positions vector has not been initialized.");
259}
260
261bool
262Positions::initialized(bool initial) const
263{
264 if (initial && _initial_positions)
265 // We do not forward the 'initial' status as we are not currently looking
266 // to support two level nesting for initial positions
267 return _fe_problem.getPositionsObject(getParam<PositionsName>("initial_positions"))
268 .initialized(false);
269 else
270 return _initialized;
271}
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
const ExecFlagType EXEC_NONE
Definition Moose.C:29
const ReporterMode REPORTER_MODE_REPLICATED
A MultiMooseEnum object to hold "execute_on" flags.
const Positions & getPositionsObject(const std::string &name) const
Get the Positions object by its name.
Reporter object that has a single execution of the "execute" method for each execute flag.
static InputParameters validParams()
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
void registerBase(const std::string &value)
This method must be called from every base "Moose System" to create linkage with the Action System.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
bool initialized(bool initial) const
Whether the positions object has been initialized.
Definition Positions.C:262
const Point & getPosition(unsigned int index, bool initial) const
Getter for a single position at a known index.
Definition Positions.C:59
std::unique_ptr< KDTree > _positions_kd_tree
Definition Positions.h:105
const bool _need_sort
Whether positions should be sorted.
Definition Positions.h:113
const std::vector< Point > *const _initial_positions
For initialization of the positions, another position reporter may be used.
Definition Positions.h:86
bool arePositionsCoplanar() const
Report if the positions are co-planar or not.
Definition Positions.C:255
std::unique_ptr< KDTree > _initial_positions_kd_tree
KDTree to be able to find the nearest position to a point in a fast and scalable manner.
Definition Positions.h:104
unsigned int getNearestPositionIndex(const Point &target, bool initial) const
Find the nearest Position index for a given point.
Definition Positions.C:96
Real getMinDistanceBetweenPositions() const
Find the minimum distance between positions.
Definition Positions.C:242
bool _need_broadcast
Whether generation of positions is distributed or not (and therefore needs a broadcast)
Definition Positions.h:108
const std::vector< std::vector< std::vector< Point > > > & getPositionsVector3D() const
Definition Positions.C:136
std::vector< std::vector< std::vector< std::vector< Point > > > > _positions_4d
4D storage for all the positions : space & time
Definition Positions.h:101
std::vector< std::vector< Point > > _positions_2d
2D storage for all the positions
Definition Positions.h:95
Positions(const InputParameters &parameters)
Definition Positions.C:39
void clearPositions()
Clear all positions vectors.
Definition Positions.C:154
const std::vector< std::vector< std::vector< std::vector< Point > > > > & getPositionsVector4D() const
Definition Positions.C:145
const std::vector< std::vector< Point > > & getPositionsVector2D() const
Definition Positions.C:127
const Point & getNearestPosition(const Point &target, bool initial) const
Find the nearest Position for a given point.
Definition Positions.C:88
std::vector< Point > & _positions
For now, only the 1D vector will be shared across all ranks.
Definition Positions.h:92
const std::vector< Point > & getPositions(bool initial) const
{ Getters for the positions vector for the desired dimension 1D will be the only one guaranteed to su...
Definition Positions.C:116
void unrollMultiDPositions()
Unrolls the multi-dimensional position vectors.
Definition Positions.C:163
static InputParameters validParams()
Definition Positions.C:15
std::vector< std::vector< std::vector< Point > > > _positions_3d
3D storage for all the positions
Definition Positions.h:98
virtual void finalize() override
In charge of reduction across all ranks & sorting for consistent output.
Definition Positions.C:220
bool _initialized
Whether the positions object has been initialized. This must be set by derived objects.
Definition Positions.h:116
This context is specific for vector types of reporters, mainly for declaring a vector of the type fro...
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
FEProblemBase & _fe_problem
Reference to the FEProblemBase for this user object.
const Parallel::Communicator & _communicator
const Parallel::Communicator & comm() const
bool isCoPlanar(const std::vector< Point > &vec_pts, const Point plane_nvec, const Point fixed_pt)
Decides whether all the Points of a vector of Points are in a plane that is defined by a normal vecto...