Loading...
Searching...
No Matches
MappedFileFilterField.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) 2022 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
29#include "oneField.H"
30#include "MeshedSurfaces.H"
31#include "MinMax.H"
32#include "indexedOctree.H"
33#include "treeDataPoint.H"
35// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36
37namespace Foam
38{
39namespace PatchFunction1Types
40{
42}
43}
44
45
46const Foam::Enum
47<
49>
50Foam::PatchFunction1Types::FilterField::RBF_typeNames_
51{
52 { RBF_type::RBF_linear, "linear" },
53 { RBF_type::RBF_quadratic, "quadratic" },
54 { RBF_type::RBF_linear, "default" },
55};
56
57
58// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
60namespace Foam
61{
62
63//- Linear basis function: 1 - (r/r0)
64static inline scalar linearWeight
65(
66 const point& p,
67 const point& p0,
68 const scalar radiusSqr
69)
70{
71 return (1 - ::sqrt(p.distSqr(p0) / radiusSqr));
72}
74
75//- Quadratic basis function: 1 - (r/r0)^2
76static inline scalar quadraticWeight
77(
78 const point& p,
79 const point& p0,
80 const scalar radiusSqr
81)
82{
83 return (1 - p.distSqr(p0) / radiusSqr);
84}
85
86
87//- Construct search tree for points
90{
91 // Avoid bounding box error in case of 2D cases
93 bb.grow(1e-4);
94
95 const int debug = PatchFunction1Types::FilterField::debug;
96
97 const int oldDebug = indexedOctreeBase::debug;
98
99 if (debug & 2)
100 {
101 indexedOctreeBase::debug = 1;
102 }
103
105 (
107 bb, // overall search domain
108 points.size(), // maxLevel
109 16, // leafsize
110 1.0 // duplicity
111 );
112
113 indexedOctreeBase::debug = oldDebug;
114
115 if (debug & 2)
116 {
117 const auto& tree = treePtr();
118
119 OFstream os("indexedOctree.obj");
120 tree.writeOBJ(os);
121 Info<< "=================" << endl;
122 Info<< "have " << tree.nodes().size() << " nodes" << nl;
123 Info<< "=================" << endl;
124 }
125
126 return treePtr;
127}
128
129} // End namespace Foam
130
131
132// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
133
134template
135<
136 class TreeType,
137 class RadiusSqrOp,
138 class BasisFunctionOp,
139 class PointWeightFieldType
140>
141void Foam::PatchFunction1Types::FilterField::buildWeightsImpl
142(
143 const TreeType& tree,
144 const RadiusSqrOp& radiusSqrOp,
145 const BasisFunctionOp& basisFuncOp,
146 const PointWeightFieldType& pointWeightFld
147)
148{
149 tmp<pointField> tpoints = tree.shapes().centres();
150
151 const auto& points = tpoints();
152
153 const label nPoints = points.size();
154
155 weights_.clear();
156 addressing_.clear();
157
158 weights_.resize(nPoints);
159 addressing_.resize(nPoints);
160
161 labelHashSet neighbours(2*128);
162
163 // Catch degenerate case where weight/addressing not actually needed
164 bool usesNeighbours = false;
165
166 for (label pointi = 0; pointi < nPoints; ++pointi)
167 {
168 const point& p0 = points[pointi];
169 auto& currAddr = addressing_[pointi];
170 auto& currWeight = weights_[pointi];
171
172 // Search with local sphere
173 const scalar radiusSqr = radiusSqrOp(pointi);
174
175 tree.findSphere(p0, radiusSqr, neighbours);
176
177 // Paranoid, enforce identity weighting as a minimum
178 if (neighbours.size() < 2)
179 {
180 currAddr.resize(1, pointi);
181 currWeight.resize(1, scalar(1));
182 continue;
183 }
184
185 usesNeighbours = true;
186
187 currAddr = neighbours.sortedToc();
188 currWeight.resize_nocopy(currAddr.size());
189
190 scalar sumWeight = 0;
191
192 forAll(currAddr, i)
193 {
194 const point& p = points[currAddr[i]];
195
196 currWeight[i] = basisFuncOp(p, p0, radiusSqr);
197
198 // Eg, face area weighting.
199 // - cast required for oneField()
200 currWeight[i] *= static_cast<scalar>(pointWeightFld[i]);
201 sumWeight += currWeight[i];
202 }
203
204 for (auto& w : currWeight)
205 {
206 w /= sumWeight;
207 }
208 }
209
210 if (!usesNeighbours)
211 {
212 // No addressing/weighting required
213 reset();
214 }
215
216 if (debug && !addressing_.empty())
217 {
218 labelMinMax limits(addressing_[0].size());
219
220 label total = 0;
221
222 for (const labelList& addr : addressing_)
223 {
224 const label n = addr.size();
225
226 limits.add(n);
227 total += n;
228 }
229
230 Pout<< "Weight neighbours: min=" << limits.min()
231 << " avg=" << (total / addressing_.size())
232 << " max=" << limits.max() << endl;
233 }
234}
235
236
237// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
240(
241 const pointField& points,
242 const scalar radius,
243 const RBF_type interp
244)
245{
246 reset(points, radius, interp);
247}
248
251(
252 const meshedSurface& geom,
253 const scalar radius,
254 const bool relative,
255 const RBF_type interp
256)
257{
258 reset(geom, radius, relative, interp);
259}
260
261
262// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
265{
266 addressing_.clear();
267 weights_.clear();
268}
269
272(
273 const pointField& points,
274 const scalar radius,
275 const RBF_type interp
276)
277{
278 scalarField dummyWeights;
279
280 if (debug)
281 {
282 Pout<< "Apply " << RBF_typeNames_[interp] << " filter,"
283 << " radius=" << radius << nl
284 << "Create tree..." << endl;
285 }
286
289
290 const scalar radiusSqr = sqr(radius);
291
292 auto weightFunc = linearWeight;
293
294 if (interp == RBF_type::RBF_quadratic)
295 {
296 weightFunc = quadraticWeight;
297 }
298
299
300 // Use (constant) absolute size
301 buildWeightsImpl
302 (
303 treePtr(),
304 [=](label index) -> scalar { return radiusSqr; },
305 weightFunc,
306 oneField()
307 );
308}
309
312(
313 const meshedSurface& geom,
314 const scalar radius,
315 const bool relative,
316 const RBF_type interp
317)
318{
319 if (!geom.nFaces())
320 {
321 // Received geometry without any faces eg, boundaryData
322 reset(geom.points(), radius, interp);
323 return;
324 }
325
326 if (debug)
327 {
328 Pout<< "Apply " << RBF_typeNames_[interp] << " filter,"
329 << (relative ? " relative" : "") << " radius=" << radius << nl
330 << "Create tree..." << endl;
331 }
332
334 = createTree(geom.faceCentres());
335
336 const scalar radiusSqr = sqr(radius);
337
338 auto weightFunc = linearWeight;
339
340 if (interp == RBF_type::RBF_quadratic)
341 {
342 weightFunc = quadraticWeight;
343 }
344
345
346 if (relative)
347 {
348 // Use relative size
349 buildWeightsImpl
350 (
351 treePtr(),
352 [&](label index) -> scalar
353 {
354 return (radiusSqr * geom.sphere(index));
355 },
356 weightFunc,
357 geom.magSf()
358 );
359 }
360 else
361 {
362 // Use (constant) absolute size
363 buildWeightsImpl
364 (
365 treePtr(),
366 [=](label index) -> scalar { return radiusSqr; },
367 weightFunc,
368 geom.magSf()
369 );
370 }
371}
372
373
374// ************************************************************************* //
label n
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition Enum.H:57
const scalarField & magSf() const
Face area magnitudes.
Output to file stream as an OSstream, normally using std::ofstream for the actual output.
Definition OFstream.H:75
The FilterField helper class provides a multi-sweep median filter for a Field of data associated with...
FilterField() noexcept=default
Default construct.
void reset()
Reset to unweighted (pass-through).
label nFaces() const noexcept
Number of faces in the patch.
const Field< point_type > & points() const noexcept
Return reference to global points.
scalar sphere(const label facei) const
The enclosing (bounding) sphere radius^2 for specified face.
const Field< point_type > & faceCentres() const
Return face centres for patch.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
void grow(const scalar delta)
Expand box by adjusting min/max by specified amount in each dimension.
Definition boundBoxI.H:367
A class representing the concept of a field of 1 used to avoid unnecessary manipulations for objects ...
Definition oneField.H:50
Standard boundBox with extra functionality for use in octree.
Holds (reference to) pointField. Encapsulation of data needed for octree searches....
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
volScalarField & p
auto limits
Definition setRDeltaT.H:186
limits reset(1/(limits.max()+VSMALL), 1/(limits.min()+VSMALL))
const volScalarField & p0
Definition EEqn.H:36
OBJstream os(runTime.globalPath()/outputName)
const pointField & points
label nPoints
Namespace for handling debugging switches.
Definition debug.C:45
Namespace for OpenFOAM.
static scalar linearWeight(const point &p, const point &p0, const scalar radiusSqr)
Linear basis function: 1 - (r/r0).
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
List< label > labelList
A List of labels.
Definition List.H:62
dimensionedSymmTensor sqr(const dimensionedVector &dv)
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition HashSet.H:85
static autoPtr< indexedOctree< treeDataPoint > > createTree(const pointField &points)
Construct search tree for points.
messageStream Info
Information stream (stdout output on master, null elsewhere).
MinMax< label > labelMinMax
A label min/max range.
Definition MinMax.H:96
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
dimensionedScalar sqrt(const dimensionedScalar &ds)
static scalar quadraticWeight(const point &p, const point &p0, const scalar radiusSqr)
Quadratic basis function: 1 - (r/r0)^2.
MeshedSurface< face > meshedSurface
vector point
Point is a vector.
Definition point.H:37
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
vectorField pointField
pointField is a vectorField.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
Tree tree(triangles.begin(), triangles.end())
volScalarField & e
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299