ENH: directMapped: allow offset specification; allow fieldName specification; allow non-constant interpolation

This commit is contained in:
mattijs
2010-11-25 13:33:27 +00:00
parent 191cc9a814
commit 938084438e
5 changed files with 389 additions and 103 deletions

View File

@ -26,6 +26,7 @@ License
#include "directMappedFixedValueFvPatchField.H" #include "directMappedFixedValueFvPatchField.H"
#include "directMappedPatchBase.H" #include "directMappedPatchBase.H"
#include "volFields.H" #include "volFields.H"
#include "interpolationCell.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -42,8 +43,10 @@ directMappedFixedValueFvPatchField<Type>::directMappedFixedValueFvPatchField
) )
: :
fixedValueFvPatchField<Type>(p, iF), fixedValueFvPatchField<Type>(p, iF),
fieldName_(iF.name()),
setAverage_(false), setAverage_(false),
average_(pTraits<Type>::zero) average_(pTraits<Type>::zero),
interpolationScheme_(interpolationCell<Type>::typeName)
{} {}
@ -57,8 +60,10 @@ directMappedFixedValueFvPatchField<Type>::directMappedFixedValueFvPatchField
) )
: :
fixedValueFvPatchField<Type>(ptf, p, iF, mapper), fixedValueFvPatchField<Type>(ptf, p, iF, mapper),
fieldName_(ptf.fieldName_),
setAverage_(ptf.setAverage_), setAverage_(ptf.setAverage_),
average_(ptf.average_) average_(ptf.average_),
interpolationScheme_(ptf.interpolationScheme_)
{ {
if (!isA<directMappedPatchBase>(this->patch().patch())) if (!isA<directMappedPatchBase>(this->patch().patch()))
{ {
@ -91,8 +96,10 @@ directMappedFixedValueFvPatchField<Type>::directMappedFixedValueFvPatchField
) )
: :
fixedValueFvPatchField<Type>(p, iF, dict), fixedValueFvPatchField<Type>(p, iF, dict),
fieldName_(dict.lookupOrDefault<word>("fieldName", iF.name())),
setAverage_(readBool(dict.lookup("setAverage"))), setAverage_(readBool(dict.lookup("setAverage"))),
average_(pTraits<Type>(dict.lookup("average"))) average_(pTraits<Type>(dict.lookup("average"))),
interpolationScheme_(interpolationCell<Type>::typeName)
{ {
if (!isA<directMappedPatchBase>(this->patch().patch())) if (!isA<directMappedPatchBase>(this->patch().patch()))
{ {
@ -112,6 +119,15 @@ directMappedFixedValueFvPatchField<Type>::directMappedFixedValueFvPatchField
<< " in file " << this->dimensionedInternalField().objectPath() << " in file " << this->dimensionedInternalField().objectPath()
<< exit(FatalError); << exit(FatalError);
} }
const directMappedPatchBase& mpp = refCast<const directMappedPatchBase>
(
directMappedFixedValueFvPatchField<Type>::patch().patch()
);
if (mpp.mode() == directMappedPatchBase::NEARESTCELL)
{
dict.lookup("interpolationScheme") >> interpolationScheme_;
}
} }
@ -122,8 +138,10 @@ directMappedFixedValueFvPatchField<Type>::directMappedFixedValueFvPatchField
) )
: :
fixedValueFvPatchField<Type>(ptf), fixedValueFvPatchField<Type>(ptf),
fieldName_(ptf.fieldName_),
setAverage_(ptf.setAverage_), setAverage_(ptf.setAverage_),
average_(ptf.average_) average_(ptf.average_),
interpolationScheme_(ptf.interpolationScheme_)
{} {}
@ -135,13 +153,67 @@ directMappedFixedValueFvPatchField<Type>::directMappedFixedValueFvPatchField
) )
: :
fixedValueFvPatchField<Type>(ptf, iF), fixedValueFvPatchField<Type>(ptf, iF),
fieldName_(ptf.fieldName_),
setAverage_(ptf.setAverage_), setAverage_(ptf.setAverage_),
average_(ptf.average_) average_(ptf.average_),
interpolationScheme_(ptf.interpolationScheme_)
{} {}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
const GeometricField<Type, fvPatchField, volMesh>&
directMappedFixedValueFvPatchField<Type>::sampleField() const
{
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
const directMappedPatchBase& mpp = refCast<const directMappedPatchBase>
(
directMappedFixedValueFvPatchField<Type>::patch().patch()
);
const fvMesh& nbrMesh = refCast<const fvMesh>(mpp.sampleMesh());
if (mpp.sameRegion())
{
if (fieldName_ == this->dimensionedInternalField().name())
{
// Optimisation: bypass field lookup
return
dynamic_cast<const fieldType&>
(
this->dimensionedInternalField()
);
}
else
{
const fvMesh& thisMesh = this->patch().boundaryMesh().mesh();
return thisMesh.lookupObject<fieldType>(fieldName_);
}
}
else
{
return nbrMesh.lookupObject<fieldType>(fieldName_);
}
}
template<class Type>
const interpolation<Type>&
directMappedFixedValueFvPatchField<Type>::interpolator() const
{
if (!interpolator_.valid())
{
interpolator_ = interpolation<Type>::New
(
interpolationScheme_,
sampleField()
);
}
return interpolator_();
}
template<class Type> template<class Type>
void directMappedFixedValueFvPatchField<Type>::updateCoeffs() void directMappedFixedValueFvPatchField<Type>::updateCoeffs()
{ {
@ -159,11 +231,8 @@ void directMappedFixedValueFvPatchField<Type>::updateCoeffs()
); );
const mapDistribute& distMap = mpp.map(); const mapDistribute& distMap = mpp.map();
// Force recalculation of schedule const fvMesh& thisMesh = this->patch().boundaryMesh().mesh();
(void)distMap.schedule();
const fvMesh& nbrMesh = refCast<const fvMesh>(mpp.sampleMesh()); const fvMesh& nbrMesh = refCast<const fvMesh>(mpp.sampleMesh());
const word& fldName = this->dimensionedInternalField().name();
// Result of obtaining remote values // Result of obtaining remote values
Field<Type> newValues; Field<Type> newValues;
@ -172,17 +241,37 @@ void directMappedFixedValueFvPatchField<Type>::updateCoeffs()
{ {
case directMappedPatchBase::NEARESTCELL: case directMappedPatchBase::NEARESTCELL:
{ {
if (mpp.sameRegion()) if (interpolationScheme_ != interpolationCell<Type>::typeName)
{ {
newValues = this->internalField(); // Send back sample points to the processor that holds the cell
vectorField samples(mpp.samplePoints());
distMap.reverseDistribute
(
(mpp.sameRegion() ? thisMesh.nCells() : nbrMesh.nCells()),
point::max,
samples
);
const interpolation<Type>& interp = interpolator();
newValues.setSize(samples.size(), pTraits<Type>::max);
forAll(samples, cellI)
{
if (samples[cellI] != point::max)
{
newValues[cellI] = interp.interpolate
(
samples[cellI],
cellI
);
}
}
} }
else else
{ {
newValues = nbrMesh.lookupObject<fieldType> newValues = sampleField();
(
fldName
).internalField();
} }
mapDistribute::distribute mapDistribute::distribute
( (
Pstream::defaultCommsType, Pstream::defaultCommsType,
@ -213,10 +302,8 @@ void directMappedFixedValueFvPatchField<Type>::updateCoeffs()
<< abort(FatalError); << abort(FatalError);
} }
const fieldType& nbrField = nbrMesh.lookupObject<fieldType> const fieldType& nbrField = sampleField();
(
fldName
);
newValues = nbrField.boundaryField()[nbrPatchID]; newValues = nbrField.boundaryField()[nbrPatchID];
mapDistribute::distribute mapDistribute::distribute
( (
@ -234,10 +321,8 @@ void directMappedFixedValueFvPatchField<Type>::updateCoeffs()
{ {
Field<Type> allValues(nbrMesh.nFaces(), pTraits<Type>::zero); Field<Type> allValues(nbrMesh.nFaces(), pTraits<Type>::zero);
const fieldType& nbrField = nbrMesh.lookupObject<fieldType> const fieldType& nbrField = sampleField();
(
fldName
);
forAll(nbrField.boundaryField(), patchI) forAll(nbrField.boundaryField(), patchI)
{ {
const fvPatchField<Type>& pf = const fvPatchField<Type>& pf =
@ -294,7 +379,8 @@ void directMappedFixedValueFvPatchField<Type>::updateCoeffs()
if (debug) if (debug)
{ {
Info<< "directMapped on field:" << fldName Info<< "directMapped on field:"
<< this->dimensionedInternalField().name()
<< " patch:" << this->patch().name() << " patch:" << this->patch().name()
<< " avg:" << gAverage(*this) << " avg:" << gAverage(*this)
<< " min:" << gMin(*this) << " min:" << gMin(*this)
@ -310,8 +396,11 @@ template<class Type>
void directMappedFixedValueFvPatchField<Type>::write(Ostream& os) const void directMappedFixedValueFvPatchField<Type>::write(Ostream& os) const
{ {
fvPatchField<Type>::write(os); fvPatchField<Type>::write(os);
os.writeKeyword("fieldName") << fieldName_ << token::END_STATEMENT << nl;
os.writeKeyword("setAverage") << setAverage_ << token::END_STATEMENT << nl; os.writeKeyword("setAverage") << setAverage_ << token::END_STATEMENT << nl;
os.writeKeyword("average") << average_ << token::END_STATEMENT << nl; os.writeKeyword("average") << average_ << token::END_STATEMENT << nl;
os.writeKeyword("interpolationScheme") << interpolationScheme_
<< token::END_STATEMENT << nl;
this->writeEntry("value", os); this->writeEntry("value", os);
} }

View File

@ -33,6 +33,17 @@ Description
mode = NEARESTFACE : sample nearest face on any patch. Note: does not mode = NEARESTFACE : sample nearest face on any patch. Note: does not
warn if nearest actually is on internal face! warn if nearest actually is on internal face!
For NEARESTCELL you have to provide an 'interpolationScheme' entry
which can be any one of the interpolation schemes (cell, cellPoint, etc.)
In case of interpolation (so scheme != cell) the limitation is that
there is only one value per cell. So e.g. if you have a cell with two
boundary faces and both faces sample into the cell both faces will get
the same value.
See directMappedPatchBase for options on sampling.
Optional 'fieldName' entry to supply a different filename
SourceFiles SourceFiles
directMappedFixedValueFvPatchField.C directMappedFixedValueFvPatchField.C
@ -43,6 +54,7 @@ SourceFiles
#include "fixedValueFvPatchFields.H" #include "fixedValueFvPatchFields.H"
#include "directMappedFvPatch.H" #include "directMappedFvPatch.H"
#include "interpolation.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -60,12 +72,29 @@ class directMappedFixedValueFvPatchField
{ {
// Private data // Private data
//- Name of field to sample - defaults to field associated with this
// patchField if not specified
word fieldName_;
//- If true adjust the mapped field to maintain average value average_ //- If true adjust the mapped field to maintain average value average_
bool setAverage_; const bool setAverage_;
//- Average value the mapped field is adjusted to maintain if //- Average value the mapped field is adjusted to maintain if
// setAverage_ is set true // setAverage_ is set true
Type average_; const Type average_;
//- Interpolation scheme to use for nearestcell mode
word interpolationScheme_;
mutable autoPtr<interpolation<Type> > interpolator_;
// Private Member Functions
//- Field to sample. Either on my or nbr mesh
const GeometricField<Type, fvPatchField, volMesh>& sampleField() const;
//- Access the interpolation method
const interpolation<Type>& interpolator() const;
public: public:

View File

@ -112,6 +112,29 @@ directMappedVelocityFluxFixedValueFvPatchField
<< " in file " << dimensionedInternalField().objectPath() << " in file " << dimensionedInternalField().objectPath()
<< exit(FatalError); << exit(FatalError);
} }
const directMappedPatchBase& mpp = refCast<const directMappedPatchBase>
(
this->patch().patch()
);
if (mpp.mode() == directMappedPolyPatch::NEARESTCELL)
{
FatalErrorIn
(
"directMappedVelocityFluxFixedValueFvPatchField::"
"directMappedVelocityFluxFixedValueFvPatchField"
"("
"const fvPatch&, "
"const DimensionedField<vector, volMesh>&, "
"const dictionary&"
")"
) << "Patch " << p.name()
<< " of type '" << p.type()
<< "' can not be used in 'nearestCell' mode"
<< " of field " << dimensionedInternalField().name()
<< " in file " << dimensionedInternalField().objectPath()
<< exit(FatalError);
}
} }

View File

@ -54,6 +54,18 @@ namespace Foam
directMappedPatchBase::sampleModeNames_; directMappedPatchBase::sampleModeNames_;
template<>
const char* NamedEnum<directMappedPatchBase::offsetMode, 3>::names[] =
{
"uniform",
"nonuniform",
"normal"
};
const NamedEnum<directMappedPatchBase::offsetMode, 3>
directMappedPatchBase::offsetModeNames_;
//- Private class for finding nearest //- Private class for finding nearest
// - point+local index // - point+local index
// - sqr(distance) // - sqr(distance)
@ -100,7 +112,7 @@ void Foam::directMappedPatchBase::collectSamples
labelListList globalFaces(Pstream::nProcs()); labelListList globalFaces(Pstream::nProcs());
globalFc[Pstream::myProcNo()] = patch_.faceCentres(); globalFc[Pstream::myProcNo()] = patch_.faceCentres();
globalSamples[Pstream::myProcNo()] = globalFc[Pstream::myProcNo()]+offsets_; globalSamples[Pstream::myProcNo()] = samplePoints();
globalFaces[Pstream::myProcNo()] = identity(patch_.size()); globalFaces[Pstream::myProcNo()] = identity(patch_.size());
// Distribute to all processors // Distribute to all processors
@ -393,19 +405,34 @@ void Foam::directMappedPatchBase::calcMapping() const
<< "Mapping already calculated" << exit(FatalError); << "Mapping already calculated" << exit(FatalError);
} }
if // Do a sanity check
// Am I sampling my own patch? This only makes sense for a non-zero
// offset.
bool sampleMyself =
( (
gAverage(mag(offsets_)) <= ROOTVSMALL mode_ == NEARESTPATCHFACE
&& mode_ == NEARESTPATCHFACE
&& sampleRegion_ == patch_.boundaryMesh().mesh().name() && sampleRegion_ == patch_.boundaryMesh().mesh().name()
&& samplePatch_ == patch_.name() && samplePatch_ == patch_.name()
) );
// Check offset
vectorField d(samplePoints()-patch_.faceCentres());
if (sampleMyself && gAverage(mag(d)) <= ROOTVSMALL)
{ {
WarningIn("directMappedPatchBase::calcMapping() const") WarningIn
<< "Invalid offset " << offsets_ << endl (
"directMappedPatchBase::directMappedPatchBase\n"
"(\n"
" const polyPatch& pp,\n"
" const word& sampleRegion,\n"
" const sampleMode mode,\n"
" const word& samplePatch,\n"
" const vector& offset\n"
")\n"
) << "Invalid offset " << d << endl
<< "Offset is the vector added to the patch face centres to" << "Offset is the vector added to the patch face centres to"
<< " find the patch face supplying the data." << endl << " find the patch face supplying the data." << endl
<< "Setting it to " << offsets_ << "Setting it to " << d
<< " on the same patch, on the same region" << " on the same patch, on the same region"
<< " will find the faces themselves which does not make sense" << " will find the faces themselves which does not make sense"
<< " for anything but testing." << endl << " for anything but testing." << endl
@ -413,10 +440,11 @@ void Foam::directMappedPatchBase::calcMapping() const
<< "sampleRegion_:" << sampleRegion_ << endl << "sampleRegion_:" << sampleRegion_ << endl
<< "mode_:" << sampleModeNames_[mode_] << endl << "mode_:" << sampleModeNames_[mode_] << endl
<< "samplePatch_:" << samplePatch_ << endl << "samplePatch_:" << samplePatch_ << endl
<< "offsets_:" << offsets_ << endl; << "offsetMode_:" << offsetModeNames_[offsetMode_] << endl;
} }
// Get global list of all samples and the processor and face they come from. // Get global list of all samples and the processor and face they come from.
pointField samples; pointField samples;
labelList patchFaceProcs; labelList patchFaceProcs;
@ -477,40 +505,6 @@ void Foam::directMappedPatchBase::calcMapping() const
} }
//// Check that actual offset vector (sampleLocations - patchFc) is more or
//// less constant.
//if (Pstream::master())
//{
// const scalarField magOffset(mag(sampleLocations - patchFc));
// const scalar avgOffset(average(magOffset));
//
// forAll(magOffset, sampleI)
// {
// if
// (
// mag(magOffset[sampleI]-avgOffset)
// > max(SMALL, 0.001*avgOffset)
// )
// {
// WarningIn("directMappedPatchBase::calcMapping() const")
// << "The actual cell/face centres picked up using offset "
// << offsets_ << " are not" << endl
// << " on a single plane."
// << " This might give numerical problems." << endl
// << " At patchface " << patchFc[sampleI]
// << " the sampled cell/face " << sampleLocations[sampleI]
// << endl
// << " is not on a plane " << avgOffset
// << " offset from the patch." << endl
// << " You might want to shift your plane offset."
// << " Set the debug flag to get a dump of sampled cells."
// << endl;
// break;
// }
// }
//}
// Determine schedule. // Determine schedule.
mapPtr_.reset(new mapDistribute(sampleProcs, patchFaceProcs)); mapPtr_.reset(new mapDistribute(sampleProcs, patchFaceProcs));
@ -597,9 +591,10 @@ Foam::directMappedPatchBase::directMappedPatchBase
sampleRegion_(patch_.boundaryMesh().mesh().name()), sampleRegion_(patch_.boundaryMesh().mesh().name()),
mode_(NEARESTPATCHFACE), mode_(NEARESTPATCHFACE),
samplePatch_("none"), samplePatch_("none"),
uniformOffset_(true), offsetMode_(UNIFORM),
offset_(vector::zero), offset_(vector::zero),
offsets_(pp.size(), offset_), offsets_(pp.size(), offset_),
distance_(0),
sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()), sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
mapPtr_(NULL) mapPtr_(NULL)
{} {}
@ -618,8 +613,10 @@ Foam::directMappedPatchBase::directMappedPatchBase
sampleRegion_(sampleRegion), sampleRegion_(sampleRegion),
mode_(mode), mode_(mode),
samplePatch_(samplePatch), samplePatch_(samplePatch),
uniformOffset_(false), offsetMode_(NONUNIFORM),
offset_(vector::zero),
offsets_(offsets), offsets_(offsets),
distance_(0),
sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()), sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
mapPtr_(NULL) mapPtr_(NULL)
{} {}
@ -638,9 +635,10 @@ Foam::directMappedPatchBase::directMappedPatchBase
sampleRegion_(sampleRegion), sampleRegion_(sampleRegion),
mode_(mode), mode_(mode),
samplePatch_(samplePatch), samplePatch_(samplePatch),
uniformOffset_(true), offsetMode_(UNIFORM),
offset_(offset), offset_(offset),
offsets_(pp.size(), offset_), offsets_(0),
distance_(0),
sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()), sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
mapPtr_(NULL) mapPtr_(NULL)
{} {}
@ -663,22 +661,62 @@ Foam::directMappedPatchBase::directMappedPatchBase
), ),
mode_(sampleModeNames_.read(dict.lookup("sampleMode"))), mode_(sampleModeNames_.read(dict.lookup("sampleMode"))),
samplePatch_(dict.lookup("samplePatch")), samplePatch_(dict.lookup("samplePatch")),
uniformOffset_(dict.found("offset")), offsetMode_(UNIFORM),
offset_ offset_(vector::zero),
( offsets_(0),
uniformOffset_ distance_(0.0),
? point(dict.lookup("offset"))
: vector::zero
),
offsets_
(
uniformOffset_
? pointField(pp.size(), offset_)
: dict.lookup("offsets")
),
sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()), sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
mapPtr_(NULL) mapPtr_(NULL)
{} {
if (dict.found("offsetMode"))
{
offsetMode_ = offsetModeNames_.read(dict.lookup("offsetMode"));
switch(offsetMode_)
{
case UNIFORM:
{
offset_ = point(dict.lookup("offset"));
}
break;
case NONUNIFORM:
{
offsets_ = pointField(dict.lookup("offsets"));
}
break;
case NORMAL:
{
distance_ = readScalar(dict.lookup("distance"));
}
break;
}
}
else if (dict.found("offset"))
{
offsetMode_ = UNIFORM;
offset_ = point(dict.lookup("offset"));
}
else if (dict.found("offsets"))
{
offsetMode_ = NONUNIFORM;
offsets_ = pointField(dict.lookup("offsets"));
}
else
{
FatalErrorIn
(
"directMappedPatchBase::directMappedPatchBase\n"
"(\n"
" const polyPatch& pp,\n"
" const dictionary& dict\n"
")\n"
) << "Please supply the offsetMode as one of "
<< NamedEnum<offsetMode, 3>::words()
<< exit(FatalError);
}
}
Foam::directMappedPatchBase::directMappedPatchBase Foam::directMappedPatchBase::directMappedPatchBase
@ -691,9 +729,10 @@ Foam::directMappedPatchBase::directMappedPatchBase
sampleRegion_(dmp.sampleRegion_), sampleRegion_(dmp.sampleRegion_),
mode_(dmp.mode_), mode_(dmp.mode_),
samplePatch_(dmp.samplePatch_), samplePatch_(dmp.samplePatch_),
uniformOffset_(dmp.uniformOffset_), offsetMode_(dmp.offsetMode_),
offset_(dmp.offset_), offset_(dmp.offset_),
offsets_(dmp.offsets_), offsets_(dmp.offsets_),
distance_(dmp.distance_),
sameRegion_(dmp.sameRegion_), sameRegion_(dmp.sameRegion_),
mapPtr_(NULL) mapPtr_(NULL)
{} {}
@ -710,9 +749,10 @@ Foam::directMappedPatchBase::directMappedPatchBase
sampleRegion_(dmp.sampleRegion_), sampleRegion_(dmp.sampleRegion_),
mode_(dmp.mode_), mode_(dmp.mode_),
samplePatch_(dmp.samplePatch_), samplePatch_(dmp.samplePatch_),
uniformOffset_(dmp.uniformOffset_), offsetMode_(dmp.offsetMode_),
offset_(dmp.offset_), offset_(dmp.offset_),
offsets_(dmp.offsets_, mapAddressing), offsets_(dmp.offsets_, mapAddressing),
distance_(dmp.distance_),
sameRegion_(dmp.sameRegion_), sameRegion_(dmp.sameRegion_),
mapPtr_(NULL) mapPtr_(NULL)
{} {}
@ -762,6 +802,40 @@ const Foam::polyPatch& Foam::directMappedPatchBase::samplePolyPatch() const
} }
Foam::tmp<Foam::pointField> Foam::directMappedPatchBase::samplePoints() const
{
tmp<pointField> tfld(new pointField(patch_.faceCentres()));
pointField& fld = tfld();
switch(offsetMode_)
{
case UNIFORM:
{
fld += offset_;
}
break;
case NONUNIFORM:
{
fld += offsets_;
}
break;
case NORMAL:
{
// Get outwards pointing normal
vectorField n(patch_.faceAreas());
n /= mag(n);
fld += distance_*n;
}
break;
}
return tfld;
}
void Foam::directMappedPatchBase::write(Ostream& os) const void Foam::directMappedPatchBase::write(Ostream& os) const
{ {
os.writeKeyword("sampleMode") << sampleModeNames_[mode_] os.writeKeyword("sampleMode") << sampleModeNames_[mode_]
@ -770,13 +844,31 @@ void Foam::directMappedPatchBase::write(Ostream& os) const
<< token::END_STATEMENT << nl; << token::END_STATEMENT << nl;
os.writeKeyword("samplePatch") << samplePatch_ os.writeKeyword("samplePatch") << samplePatch_
<< token::END_STATEMENT << nl; << token::END_STATEMENT << nl;
if (uniformOffset_)
os.writeKeyword("offsetMode") << offsetModeNames_[offsetMode_]
<< token::END_STATEMENT << nl;
switch(offsetMode_)
{ {
os.writeKeyword("offset") << offset_ << token::END_STATEMENT << nl; case UNIFORM:
} {
else os.writeKeyword("offset") << offset_ << token::END_STATEMENT << nl;
{ }
os.writeKeyword("offsets") << offsets_ << token::END_STATEMENT << nl; break;
case NONUNIFORM:
{
os.writeKeyword("offsets") << offsets_ << token::END_STATEMENT
<< nl;
}
break;
case NORMAL:
{
os.writeKeyword("distance") << distance_ << token::END_STATEMENT
<< nl;
}
break;
} }
} }

View File

@ -28,6 +28,33 @@ Description
Determines a mapping between patch face centres and mesh cell or face Determines a mapping between patch face centres and mesh cell or face
centres and processors they're on. centres and processors they're on.
If constructed from dictionary:
// Region to sample (default is region0)
sampleRegion region0;
// What to sample:
// - nearestCell : sample nearest cell
// - nearestPatchFace : nearest face on selected patch
// - nearestFace : nearest boundary face on any patch
sampleMode nearestCell;
// If sampleMod is nearestPatchFace : patch to find faces of
samplePatch movingWall;
// How to supply offset (w.r.t. my patch face centres):
// - uniform : single offset vector
// - nonuniform : per-face offset vector
// - normal : using supplied distance and face normal
offsetMode uniform;
// According to offsetMode (see above) supply one of
// offset, offsets or distance
offset (1 0 0);
Note: if offsetMode is 'normal' it uses outwards pointing normals. So
supply a negative distance if sampling inside the domain.
Note Note
Storage is not optimal. It temporary collects all (patch)face centres Storage is not optimal. It temporary collects all (patch)face centres
on all processors to keep the addressing calculation simple. on all processors to keep the addressing calculation simple.
@ -71,12 +98,22 @@ public:
NEARESTFACE // nearest face NEARESTFACE // nearest face
}; };
//- How to project face centres
enum offsetMode
{
UNIFORM, // single offset vector
NONUNIFORM, // per-face offset vector
NORMAL // use face normal + distance
};
private: private:
// Private data // Private data
static const NamedEnum<sampleMode, 3> sampleModeNames_; static const NamedEnum<sampleMode, 3> sampleModeNames_;
static const NamedEnum<offsetMode, 3> offsetModeNames_;
//- Patch to sample //- Patch to sample
const polyPatch& patch_; const polyPatch& patch_;
@ -89,14 +126,17 @@ private:
//- Patch (only if NEARESTPATCHFACE) //- Patch (only if NEARESTPATCHFACE)
const word samplePatch_; const word samplePatch_;
//- For backwards compatibility : reading/writing of uniform offset. //- How to obtain samples
const bool uniformOffset_; offsetMode offsetMode_;
//- Offset vector (uniform) //- Offset vector (uniform)
const vector offset_; vector offset_;
//- Offset vector //- Offset vector (nonuniform)
const vectorField offsets_; vectorField offsets_;
//- Offset distance (normal)
scalar distance_;
//- Same region //- Same region
const bool sameRegion_; const bool sameRegion_;
@ -146,17 +186,17 @@ public:
//- Construct from patch //- Construct from patch
directMappedPatchBase(const polyPatch&); directMappedPatchBase(const polyPatch&);
//- Construct from components //- Construct with offsetMode=non-uniform
directMappedPatchBase directMappedPatchBase
( (
const polyPatch& pp, const polyPatch& pp,
const word& sampleRegion, const word& sampleRegion,
const sampleMode sampleMode, const sampleMode sampleMode,
const word& samplePatch, const word& samplePatch,
const vectorField& offset const vectorField& offsets
); );
//- Construct from components //- Construct from offsetMode=uniform
directMappedPatchBase directMappedPatchBase
( (
const polyPatch& pp, const polyPatch& pp,
@ -166,6 +206,16 @@ public:
const vector& offset const vector& offset
); );
////- Construct from normal and distance
//directMappedPatchBase
//(
// const polyPatch& pp,
// const word& sampleRegion,
// const word& samplePatch,
// const sampleMode sampleMode,
// const vector& offset
//);
//- Construct from dictionary //- Construct from dictionary
directMappedPatchBase(const polyPatch&, const dictionary&); directMappedPatchBase(const polyPatch&, const dictionary&);
@ -241,6 +291,9 @@ public:
//- Get the patch on the region //- Get the patch on the region
const polyPatch& samplePolyPatch() const; const polyPatch& samplePolyPatch() const;
//- Get the sample points
tmp<pointField> samplePoints() const;
//- Write as a dictionary //- Write as a dictionary
virtual void write(Ostream&) const; virtual void write(Ostream&) const;
}; };