Loading...
Searching...
No Matches
abaqusMeshSet.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2023 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28#include "abaqusMeshSet.H"
29#include "stringOps.H"
30#include "Fstream.H"
31#include "SpanStream.H"
32#include "meshSearch.H"
34
35// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36
37namespace Foam
38{
41}
42
43
44// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
45
46bool Foam::abaqusMeshSet::readCoord(ISstream& is, vector& coord) const
47{
48 string buffer;
49
50 do
51 {
52 //buffer.clear();
53
54 is.getLine(buffer);
55
56 const auto elems = buffer.find("*ELEMENT");
57
58 if (elems != std::string::npos)
59 {
60 buffer.clear();
61 break;
62 }
63
64 // Trim out any '*' comments
65 const auto pos = buffer.find('*');
66 if (pos != std::string::npos)
67 {
68 buffer.erase(pos);
69 }
71 }
72 while (buffer.empty() && is.good());
73
74 if (buffer.empty())
75 {
76 return false;
77 }
78
79 const auto strings = stringOps::split(buffer, ',');
80
81 if (strings.size() != 4)
82 {
84 << "Read error: expected format int, float, float, float"
85 << " but read buffer " << buffer
86 << exit(FatalError);
87 }
88
89 for (int i = 0; i <= 2; ++i)
90 {
91 // Swallow i=0 for node label
92 const auto& s = strings[i+1].str();
93 ISpanStream buf(s.data(), s.length());
94 buf >> coord[i];
95 }
96
97 coord *= scale_;
98
99 return true;
100}
101
102
103// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
104
105void Foam::abaqusMeshSet::calcSamples
106(
107 DynamicList<point>& samplingPts,
108 DynamicList<label>& samplingCells,
109 DynamicList<label>& samplingFaces,
110 DynamicList<label>& samplingSegments,
111 DynamicList<scalar>& samplingCurveDist
112) const
113{
115 << "abaqusMeshSet : sampling " << sampleCoords_.size() << " points"
116 << endl;
117
118 List<bool> found(sampleCoords_.size(), false);
119
120 forAll(sampleCoords_, samplei)
121 {
122 const vector& pt = sampleCoords_[samplei];
123
124 label celli = searchEngine().findCell(pt);
125 if (celli != -1)
126 {
127 found[samplei] = true;
128
129 samplingPts.append(pt);
130 samplingCells.append(celli);
131 samplingFaces.append(-1);
132 samplingSegments.append(0);
133 samplingCurveDist.append(1.0*samplei);
134 }
135 }
136
138
140 forAll(found, samplei)
141 {
142 if (!found[samplei]) lost.append(samplei);
143 }
144
145 const label nFound = sampleCoords_.size() - lost.size();
146 label nOutOfBounds = 0;
147
148 if (Pstream::parRun())
149 {
150 typedef Tuple2<label, Tuple2<label, scalar>> procCellDist;
151 List<procCellDist> pcd(lost.size(), procCellDist(-1, {-1, GREAT}));
152 forAll(pcd, i)
153 {
154 const label samplei = lost[i];
155 const vector& pt0 = sampleCoords_[samplei];
156 const label celli = searchEngine().findNearestCell(pt0);
157 const vector& pt1 = mesh().cellCentres()[celli];
158 const scalar distSqr = magSqr(pt1 - pt0);
159 pcd[i] = procCellDist(Pstream::myProcNo(), {celli, distSqr});
160 }
161
163 (
164 pcd,
165 [](procCellDist& x, const procCellDist& y)
166 {
167 // Select item with smallest distance
168 if (y.second().second() < x.second().second())
169 {
170 x = y;
171 }
172 }
173 );
174
175 forAll(pcd, i)
176 {
177 const label samplei = lost[i];
178
179 if (pcd[i].second().second() < maxDistSqr_)
180 {
181 if (pcd[i].first() == Pstream::myProcNo())
182 {
183 const label celli = pcd[i].second().first();
184 const vector& pt1 = mesh().cellCentres()[celli];
185
186 samplingPts.append(pt1);
187 samplingCells.append(celli);
188 samplingFaces.append(-1);
189 samplingSegments.append(0);
190 samplingCurveDist.append(1.0*samplei);
191 }
192 }
193 else
194 {
195 // Insert points that have not been found as null points
196 if (Pstream::master())
197 {
198 samplingPts.append(sampleCoords_[samplei]);
199 samplingCells.append(-1);
200 samplingFaces.append(-1);
201 samplingSegments.append(0);
202 samplingCurveDist.append(1.0*samplei);
203 ++nOutOfBounds;
204 }
205 }
206 }
207 }
208 else
209 {
210 // Serial running
211
212 forAll(lost, i)
213 {
214 const label samplei = lost[i];
215 const vector& pt0 = sampleCoords_[samplei];
216 const label celli = searchEngine().findNearestCell(pt0);
217 const vector& pt1 = mesh().cellCentres()[celli];
218 const scalar distSqr = magSqr(pt1 - pt0);
219
220 if (distSqr < maxDistSqr_)
221 {
222 samplingPts.append(pt1);
223 samplingCells.append(celli);
224 samplingFaces.append(-1);
225 samplingSegments.append(0);
226 samplingCurveDist.append(1.0*samplei);
227 }
228 else
229 {
230 // Insert points that have not been found as null points
231 samplingPts.append(sampleCoords_[samplei]);
232 samplingCells.append(-1);
233 samplingFaces.append(-1);
234 samplingSegments.append(0);
235 samplingCurveDist.append(1.0*samplei);
236 ++nOutOfBounds;
237 }
238 }
239 }
240
242 << "Sample size : " << sampleCoords_.size() << nl
243 << "Lost samples : " << nOutOfBounds << nl
244 << "Recovered samples : "
245 << (sampleCoords_.size() - nOutOfBounds - nFound) << nl
246 << endl;
247
248
249 if (nOutOfBounds)
250 {
252 << "Identified " << nOutOfBounds << " out-of-bounds points"
253 << endl;
254 }
255}
256
257
258void Foam::abaqusMeshSet::genSamples()
259{
260 // Storage for sample points
261 DynamicList<point> samplingPts;
262 DynamicList<label> samplingCells;
263 DynamicList<label> samplingFaces;
264 DynamicList<label> samplingSegments;
265 DynamicList<scalar> samplingCurveDist;
266
267 calcSamples
268 (
269 samplingPts,
270 samplingCells,
271 samplingFaces,
272 samplingSegments,
273 samplingCurveDist
274 );
275
276 samplingPts.shrink();
277 samplingCells.shrink();
278 samplingFaces.shrink();
279 samplingSegments.shrink();
280 samplingCurveDist.shrink();
281
282 setSamples
283 (
284 std::move(samplingPts),
285 std::move(samplingCells),
286 std::move(samplingFaces),
287 std::move(samplingSegments),
288 std::move(samplingCurveDist)
289 );
290
291 if (debug > 1)
292 {
294 }
295}
296
297
298// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
299
301(
302 const word& name,
303 const polyMesh& mesh,
304 const meshSearch& searchEngine,
305 const dictionary& dict
306)
307:
308 sampledSet(name, mesh, searchEngine, dict),
309 scale_(dict.getOrDefault<scalar>("scale", 1)),
310 sampleCoords_(),
311 maxDistSqr_(sqr(dict.getOrDefault<scalar>("maxDist", 0)))
312{
313 if (Pstream::master())
314 {
315 const fileName inputFile(dict.get<fileName>("file").expand());
316 IFstream pointsFile(inputFile);
317
318 if (!pointsFile.good())
319 {
321 << "Unable to find file " << pointsFile.name()
323 }
324
325 // Read the points file
326 DynamicList<point> coords;
327 vector c;
328 while (readCoord(pointsFile, c))
329 {
330 coords.append(c);
331 }
332
333 sampleCoords_.transfer(coords);
334 }
335
336 Pstream::broadcast(sampleCoords_);
337
339 << "Number of sample points: " << sampleCoords_.size() << nl
340 << "Sample points bounds: " << boundBox(sampleCoords_) << endl;
341
342 genSamples();
343}
344
345
346// ************************************************************************* //
scalar y
Input/output streams with (internal or external) character storage.
bool found
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void append(const T &val)
Copy append an element to the end of this list.
Input from file stream as an ISstream, normally using std::ifstream for the actual input.
Definition IFstream.H:55
virtual const fileName & name() const override
Read/write access to the name of the stream.
Definition ISstream.H:147
bool good() const noexcept
True if next operation might succeed.
Definition IOstream.H:281
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void append(const T &val)
Append an element at the end of the list.
Definition List.H:497
static void listCombineAllGather(UList< T > &values, CombineOp cop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Same as Pstream::listCombineReduce.
Definition Pstream.H:394
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition Tuple2.H:51
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition UPstream.H:1706
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
Definition UPstream.H:1669
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
@ broadcast
broadcast [MPI]
Definition UPstream.H:189
Generates sample positions from points specified in a file as Abaqus mesh points.
abaqusMeshSet(const word &name, const polyMesh &mesh, const meshSearch &searchEngine, const dictionary &dict)
Construct from dictionary.
A bounding box defined in terms of min/max extrema points.
Definition boundBox.H:71
const word & name() const noexcept
The coord-set name.
Definition coordSet.H:152
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
A class for handling file names.
Definition fileName.H:75
Various (local, not parallel) searches on polyMesh; uses (demand driven) octree to search.
Definition meshSearch.H:57
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
const vectorField & cellCentres() const
Holds list of sampling points which is filled at construction time. Various implementations of this b...
Definition sampledSet.H:82
const meshSearch & searchEngine() const noexcept
Definition sampledSet.H:378
sampledSet(const word &name, const polyMesh &mesh, const meshSearch &searchEngine, const coordSet::coordFormat axisType)
Construct from components.
Definition sampledSet.C:405
const polyMesh & mesh() const noexcept
Definition sampledSet.H:373
string & expand(const bool allowEmpty=false)
Inplace expand initial tags, tildes, and all occurrences of environment variables as per stringOps::e...
Definition string.C:166
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
A class for handling words, derived from Foam::string.
Definition word.H:66
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
dynamicFvMesh & mesh
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
auto & name
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
#define DebugInfo
Report an information message using Foam::Info.
#define WarningInFunction
Report a warning using Foam::Warning.
#define DebugInFunction
Report an information message using Foam::Info.
const dimensionedScalar c
Speed of light in a vacuum.
Namespace for handling debugging switches.
Definition debug.C:45
Foam::SubStrings split(const std::string &str, const char delim, std::string::size_type pos=0, const bool keepEmpty=false)
Split string into sub-strings at the delimiter character.
void inplaceTrimRight(std::string &s)
Trim trailing whitespace inplace.
Namespace for OpenFOAM.
dimensionedScalar pos(const dimensionedScalar &ds)
dimensionedSymmTensor sqr(const dimensionedVector &dv)
messageStream Info
Information stream (stdout output on master, null elsewhere).
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
errorManip< error > abort(error &err)
Definition errorManip.H:139
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
Vector< scalar > vector
Definition vector.H:57
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
runTime write()
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299