Newer
Older
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "faceSource.H"
#include "fvMesh.H"
#include "cyclicPolyPatch.H"
#include "emptyPolyPatch.H"
#include "sampledSurface.H"
#include "mergePoints.H"
#include "indirectPrimitivePatch.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
Henry Weller
committed
namespace functionObjects
{
namespace fieldValues
{
defineTypeNameAndDebug(faceSource, 0);
addToRunTimeSelectionTable(fieldValue, faceSource, dictionary);
addToRunTimeSelectionTable(functionObject, faceSource, dictionary);
Henry Weller
committed
}
}
Henry Weller
committed
template<>
const char* Foam::NamedEnum
<
Foam::functionObjects::fieldValues::faceSource::sourceType,
3
>::names[] =
{
"faceZone",
"patch",
"sampledSurface"
};
Henry Weller
committed
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
template<>
const char* Foam::NamedEnum
<
Foam::functionObjects::fieldValues::faceSource::operationType,
15
>::names[] =
{
"none",
"sum",
"sumMag",
"sumDirection",
"sumDirectionBalance",
"average",
"weightedAverage",
"areaAverage",
"weightedAreaAverage",
"areaIntegrate",
"min",
"max",
"CoV",
"areaNormalAverage",
"areaNormalIntegrate"
};
const Foam::NamedEnum
<
Foam::functionObjects::fieldValues::faceSource::sourceType,
3
> Foam::functionObjects::fieldValues::faceSource::sourceTypeNames_;
const Foam::NamedEnum
<
Foam::functionObjects::fieldValues::faceSource::operationType,
15
> Foam::functionObjects::fieldValues::faceSource::operationTypeNames_;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Henry Weller
committed
void Foam::functionObjects::fieldValues::faceSource::setFaceZoneFaces()
{
label zoneId = mesh().faceZones().findZoneID(sourceName_);
if (zoneId < 0)
{
<< type() << " " << name() << ": "
<< sourceTypeNames_[source_] << "(" << sourceName_ << "):" << nl
<< " Unknown face zone name: " << sourceName_
<< ". Valid face zones are: " << mesh().faceZones().names()
<< nl << exit(FatalError);
}
const faceZone& fZone = mesh().faceZones()[zoneId];
DynamicList<label> faceIds(fZone.size());
DynamicList<label> facePatchIds(fZone.size());
DynamicList<label> faceSigns(fZone.size());
forAll(fZone, i)
{
label facei = fZone[i];
label faceId = -1;
label facePatchId = -1;
if (mesh().isInternalFace(facei))
facePatchId = -1;
}
else
{
facePatchId = mesh().boundaryMesh().whichPatch(facei);
const polyPatch& pp = mesh().boundaryMesh()[facePatchId];
if (refCast<const coupledPolyPatch>(pp).owner())
faceId = pp.whichFace(facei);
}
else
{
faceId = -1;
}
}
else if (!isA<emptyPolyPatch>(pp))
{
faceId = facei - pp.start();
}
else
{
faceId = -1;
facePatchId = -1;
}
}
if (faceId >= 0)
{
if (fZone.flipMap()[i])
{
faceIds.append(faceId);
facePatchIds.append(facePatchId);
faceId_.transfer(faceIds);
facePatchId_.transfer(facePatchIds);
faceSign_.transfer(faceSigns);
nFaces_ = returnReduce(faceId_.size(), sumOp<label>());
Pout<< "Original face zone size = " << fZone.size()
<< ", new size = " << faceId_.size() << endl;
Henry Weller
committed
void Foam::functionObjects::fieldValues::faceSource::setPatchFaces()
const label patchid = mesh().boundaryMesh().findPatchID(sourceName_);
<< type() << " " << name() << ": "
<< sourceTypeNames_[source_] << "(" << sourceName_ << "):" << nl
<< " Unknown patch name: " << sourceName_
<< ". Valid patch names are: "
<< mesh().boundaryMesh().names() << nl
<< exit(FatalError);
}
const polyPatch& pp = mesh().boundaryMesh()[patchid];
label nFaces = pp.size();
if (isA<emptyPolyPatch>(pp))
{
nFaces = 0;
}
faceId_.setSize(nFaces);
facePatchId_.setSize(nFaces);
faceSign_.setSize(nFaces);
nFaces_ = returnReduce(faceId_.size(), sumOp<label>());
forAll(faceId_, facei)
faceId_[facei] = facei;
facePatchId_[facei] = patchid;
faceSign_[facei] = 1;
Henry Weller
committed
void Foam::functionObjects::fieldValues::faceSource::sampledSurfaceFaces
(
const dictionary& dict
)
{
surfacePtr_ = sampledSurface::New
(
name(),
mesh(),
dict.subDict("sampledSurfaceDict")
);
surfacePtr_().update();
nFaces_ = returnReduce(surfacePtr_().faces().size(), sumOp<label>());
}
Henry Weller
committed
void Foam::functionObjects::fieldValues::faceSource::combineMeshGeometry
(
faceList& faces,
pointField& points
) const
{
List<faceList> allFaces(Pstream::nProcs());
List<pointField> allPoints(Pstream::nProcs());
labelList globalFacesIs(faceId_);
forAll(globalFacesIs, i)
{
if (facePatchId_[i] != -1)
{
label patchi = facePatchId_[i];
globalFacesIs[i] += mesh().boundaryMesh()[patchi].start();
}
}
// Add local faces and points to the all* lists
indirectPrimitivePatch pp
(
IndirectList<face>(mesh().faces(), globalFacesIs),
mesh().points()
);
allFaces[Pstream::myProcNo()] = pp.localFaces();
allPoints[Pstream::myProcNo()] = pp.localPoints();
Pstream::gatherList(allFaces);
Pstream::gatherList(allPoints);
// Renumber and flatten
label nFaces = 0;
label nPoints = 0;
forAll(allFaces, proci)
{
nFaces += allFaces[proci].size();
nPoints += allPoints[proci].size();
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
}
faces.setSize(nFaces);
points.setSize(nPoints);
nFaces = 0;
nPoints = 0;
// My own data first
{
const faceList& fcs = allFaces[Pstream::myProcNo()];
forAll(fcs, i)
{
const face& f = fcs[i];
face& newF = faces[nFaces++];
newF.setSize(f.size());
forAll(f, fp)
{
newF[fp] = f[fp] + nPoints;
}
}
const pointField& pts = allPoints[Pstream::myProcNo()];
forAll(pts, i)
{
points[nPoints++] = pts[i];
}
}
// Other proc data follows
forAll(allFaces, proci)
{
if (proci != Pstream::myProcNo())
{
const faceList& fcs = allFaces[proci];
forAll(fcs, i)
{
const face& f = fcs[i];
face& newF = faces[nFaces++];
newF.setSize(f.size());
forAll(f, fp)
{
newF[fp] = f[fp] + nPoints;
}
}
const pointField& pts = allPoints[proci];
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
forAll(pts, i)
{
points[nPoints++] = pts[i];
}
}
}
// Merge
labelList oldToNew;
pointField newPoints;
bool hasMerged = mergePoints
(
points,
SMALL,
false,
oldToNew,
newPoints
);
if (hasMerged)
{
if (debug)
{
Pout<< "Merged from " << points.size()
<< " down to " << newPoints.size() << " points" << endl;
}
points.transfer(newPoints);
forAll(faces, i)
{
inplaceRenumber(oldToNew, faces[i]);
}
}
}
Henry Weller
committed
void Foam::functionObjects::fieldValues::faceSource::combineSurfaceGeometry
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
(
faceList& faces,
pointField& points
) const
{
if (surfacePtr_.valid())
{
const sampledSurface& s = surfacePtr_();
if (Pstream::parRun())
{
// dimension as fraction of mesh bounding box
scalar mergeDim = 1e-10*mesh().bounds().mag();
labelList pointsMap;
PatchTools::gatherAndMerge
(
mergeDim,
primitivePatch
(
SubList<face>(s.faces(), s.faces().size()),
s.points()
),
points,
faces,
pointsMap
);
}
else
{
faces = s.faces();
points = s.points();
}
}
}
Henry Weller
committed
Foam::scalar Foam::functionObjects::fieldValues::faceSource::totalArea() const
Henry
committed
{
scalar totalArea;
if (surfacePtr_.valid())
{
totalArea = gSum(surfacePtr_().magSf());
}
else
{
totalArea = gSum(filterField(mesh().magSf(), false));
}
return totalArea;
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Henry Weller
committed
void Foam::functionObjects::fieldValues::faceSource::initialise
(
const dictionary& dict
)
dict.lookup("sourceName") >> sourceName_;
switch (source_)
{
case stFaceZone:
{
setFaceZoneFaces();
break;
}
case stPatch:
{
setPatchFaces();
break;
}
case stSampledSurface:
{
sampledSurfaceFaces(dict);
break;
}
<< type() << " " << name() << ": "
<< sourceTypeNames_[source_] << "(" << sourceName_ << "):"
<< nl << " Unknown source type. Valid source types are:"
<< sourceTypeNames_.sortedToc() << nl << exit(FatalError);
if (nFaces_ == 0)
{
Henry Weller
committed
FatalErrorInFunction
<< type() << " " << name() << ": "
<< sourceTypeNames_[source_] << "(" << sourceName_ << "):" << nl
Henry Weller
committed
<< " Source has no faces" << exit(FatalError);
if (surfacePtr_.valid())
{
surfacePtr_().update();
}
totalArea_ = totalArea();
Info<< type() << " " << name() << ":" << nl
<< " total faces = " << nFaces_
<< nl
<< " total area = " << totalArea_
if (dict.readIfPresent("weightField", weightFieldName_))
Info<< " weight field = " << weightFieldName_ << nl;
FatalIOErrorInFunction(dict)
<< "Cannot use weightField for a sampledSurface"
<< exit(FatalIOError);
}
}
if (dict.found("orientedWeightField"))
{
if (weightFieldName_ == "none")
{
dict.lookup("orientedWeightField") >> weightFieldName_;
Info<< " weight field = " << weightFieldName_ << nl;
orientWeightField_ = true;
}
else
{
FatalIOErrorInFunction(dict)
<< "Either weightField or orientedWeightField can be supplied, "
<< "but not both"
<< exit(FatalIOError);
}
}
List<word> orientedFields;
if (dict.readIfPresent("orientedFields", orientedFields))
{
orientedFieldsStart_ = fields_.size();
fields_.append(orientedFields);
if (dict.readIfPresent("scaleFactor", scaleFactor_))
{
Info<< " scale factor = " << scaleFactor_ << nl;
{
const word surfaceFormat(dict.lookup("surfaceFormat"));
surfaceWriterPtr_.reset
(
surfaceWriter::New
(
surfaceFormat,
dict.subOrEmptyDict("formatOptions").
subOrEmptyDict(surfaceFormat)
).ptr()
);
}
Henry Weller
committed
void Foam::functionObjects::fieldValues::faceSource::writeFileHeader
(
const label i
)
Henry
committed
writeCommented(file(), "Source : ");
file() << sourceTypeNames_[source_] << " " << sourceName_ << endl;
writeCommented(file(), "Faces : ");
file() << nFaces_ << endl;
writeCommented(file(), "Area : ");
file() << totalArea_ << endl;
Henry
committed
writeCommented(file(), "Time");
if (writeArea_)
Henry
committed
{
file() << tab << "Area";
}
forAll(fields_, i)
{
file()
<< tab << operationTypeNames_[operation_]
<< "(" << fields_[i] << ")";
file() << endl;
Henry Weller
committed
Foam::scalar Foam::functionObjects::fieldValues::faceSource::processValues
(
const Field<scalar>& values,
const vectorField& Sf,
const scalarField& weightField
) const
{
switch (operation_)
{
case opSumDirection:
{
vector n(dict_.lookup("direction"));
return sum(pos(values*(Sf & n))*mag(values));
}
case opSumDirectionBalance:
{
vector n(dict_.lookup("direction"));
const scalarField nv(values*(Sf & n));
return sum(pos(nv)*mag(values) - neg(nv)*mag(values));
}
default:
{
// Fall through to other operations
return processSameTypeValues(values, Sf, weightField);
}
}
}
Henry Weller
committed
Foam::vector Foam::functionObjects::fieldValues::faceSource::processValues
(
const Field<vector>& values,
const vectorField& Sf,
const scalarField& weightField
) const
{
switch (operation_)
{
case opSumDirection:
{
vector n(dict_.lookup("direction"));
n /= mag(n) + ROOTVSMALL;
const scalarField nv(n & values);
return sum(pos(nv)*n*(nv));
}
case opSumDirectionBalance:
{
vector n(dict_.lookup("direction"));
n /= mag(n) + ROOTVSMALL;
const scalarField nv(n & values);
return sum(pos(nv)*n*(nv));
case opAreaNormalAverage:
{
scalar result = sum(values & Sf)/sum(mag(Sf));
return vector(result, 0.0, 0.0);
}
case opAreaNormalIntegrate:
{
scalar result = sum(values & Sf);
return vector(result, 0.0, 0.0);
}
default:
{
// Fall through to other operations
return processSameTypeValues(values, Sf, weightField);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
Foam::functionObjects::fieldValues::faceSource::faceSource
(
const word& name,
const Time& runTime,
const dictionary& dict
)
:
fieldValue(name, runTime, dict, typeName),
surfaceWriterPtr_(NULL),
source_(sourceTypeNames_.read(dict.lookup("source"))),
operation_(operationTypeNames_.read(dict.lookup("operation"))),
weightFieldName_("none"),
orientWeightField_(false),
orientedFieldsStart_(labelMax),
scaleFactor_(1.0),
writeArea_(dict.lookupOrDefault("writeArea", false)),
nFaces_(0),
faceId_(),
facePatchId_(),
faceSign_()
{
if (!isA<fvMesh>(obr_))
{
FatalErrorInFunction
<< "objectRegistry is not an fvMesh" << exit(FatalError);
}
read(dict);
}
Henry Weller
committed
Foam::functionObjects::fieldValues::faceSource::faceSource
(
const word& name,
const objectRegistry& obr,
const dictionary& dict
fieldValue(name, obr, dict, typeName),
surfaceWriterPtr_(NULL),
source_(sourceTypeNames_.read(dict.lookup("source"))),
operation_(operationTypeNames_.read(dict.lookup("operation"))),
weightFieldName_("none"),
orientWeightField_(false),
orientedFieldsStart_(labelMax),
writeArea_(dict.lookupOrDefault("writeArea", false)),
nFaces_(0),
faceId_(),
facePatchId_(),
faceSign_()
if (!isA<fvMesh>(obr_))
{
FatalErrorInFunction
<< "objectRegistry is not an fvMesh" << exit(FatalError);
}
read(dict);
Henry Weller
committed
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Henry Weller
committed
Foam::functionObjects::fieldValues::faceSource::~faceSource()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionObjects::fieldValues::faceSource::read
Henry Weller
committed
(
const dictionary& dict
)
Henry Weller
committed
initialise(dict);
return true;
bool Foam::functionObjects::fieldValues::faceSource::write
(
const bool postProcess
)
Henry Weller
committed
if (surfacePtr_.valid())
Henry Weller
committed
surfacePtr_().update();
}
if (Pstream::master())
{
writeTime(file());
}
Henry
committed
Henry Weller
committed
if (writeArea_)
{
totalArea_ = totalArea();
Henry
committed
if (Pstream::master())
{
Henry Weller
committed
file() << tab << totalArea_;
}
Log << " total area = " << totalArea_ << endl;
Henry Weller
committed
}
Henry Weller
committed
// construct weight field. Note: zero size means weight = 1
scalarField weightField;
if (weightFieldName_ != "none")
{
weightField =
getFieldValues<scalar>
(
weightFieldName_,
true,
orientWeightField_
);
}
Henry Weller
committed
// Combine onto master
combineFields(weightField);
Henry Weller
committed
// process the fields
forAll(fields_, i)
{
const word& fieldName = fields_[i];
bool ok = false;
Henry Weller
committed
bool orient = i >= orientedFieldsStart_;
ok = ok || writeValues<scalar>(fieldName, weightField, orient);
ok = ok || writeValues<vector>(fieldName, weightField, orient);
ok = ok
|| writeValues<sphericalTensor>(fieldName, weightField, orient);
ok = ok || writeValues<symmTensor>(fieldName, weightField, orient);
ok = ok || writeValues<tensor>(fieldName, weightField, orient);
Henry Weller
committed
if (!ok)
Henry Weller
committed
WarningInFunction
<< "Requested field " << fieldName
<< " not found in database and not processed"
<< endl;
Henry Weller
committed
}
Henry Weller
committed
if (Pstream::master())
{
file()<< endl;
Henry Weller
committed
Log << endl;
return true;
}
// ************************************************************************* //