fvMeshStitcher: Prevent storage of internal surface fields for mapping

This reduces the memory usage of the stitching operation, and simplifies
its interaction with other mesh changers.

The storage of separate original and non-conformal field parts is now
done within a new "conformal" boundary condition. This condition
internally stores two boundary conditions; one for the original patch
values, and one for the non-conformal part. The conformal condition
replaces the condition applied to the original patch on un-stitch when
the non-conformal boundaries are removed. The data stored in the
conformal condition is then used to restore the previous conditions
during the re-stitch process.

This conformal condition supports mapping of various types. This means
both original and non-conformal boundary data gets mapped automatically
as a result of other mesh changes such as automatic refinement.
This commit is contained in:
Will Bainbridge
2023-08-23 16:14:40 +01:00
parent bc0d74cbc5
commit 2f4ef2abba
19 changed files with 1595 additions and 754 deletions

View File

@ -123,6 +123,9 @@ fvMeshStitchers = fvMesh/fvMeshStitchers
$(fvMeshStitchers)/fvMeshStitcher/fvMeshStitcher.C
$(fvMeshStitchers)/fvMeshStitcher/fvMeshStitcherNew.C
$(fvMeshStitchers)/fvMeshStitcher/fvMeshStitcherTools.C
$(fvMeshStitchers)/fvMeshStitcher/conformedFvsPatchFields.C
#$(fvMeshStitchers)/fvMeshStitcher/conformalisingFvPatchFieldMapper.C
$(fvMeshStitchers)/stationary/fvMeshStitchersStationary.C
functionObjects/fvMeshFunctionObject/fvMeshFunctionObject.C

View File

@ -0,0 +1,299 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2023 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 "conformedFvsPatchField.H"
#include "fvMeshStitcherTools.H"
#include "nonConformalBoundary.H"
#include "nonConformalFvPatch.H"
#include "nonConformalErrorFvPatch.H"
#include "surfaceFields.H"
// * * * * * * * * * * * * * Private Constructors * * * * * * * * * * * * * //
template<class Type>
Foam::conformedFvsPatchField<Type>::conformedFvsPatchField
(
const fvPatch& p,
const DimensionedField<Type, surfaceMesh>& iF,
autoPtr<fvsPatchField<Type>>&& origFieldPtr,
autoPtr<calculatedFvsPatchField<Type>>&& ncFieldPtr
)
:
fvsPatchField<Type>(p, iF),
origFieldPtr_(origFieldPtr),
ncFieldPtr_(ncFieldPtr)
{}
// * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
template<class Type>
void Foam::conformedFvsPatchField<Type>::conform
(
typename SurfaceField<Type>::Boundary& bF
)
{
const DimensionedField<Type, surfaceMesh>& iF = bF[0].internalField();
const fvBoundaryMesh& fvbm = iF.mesh().boundary();
const labelList origPatchIDs =
nonConformalBoundary::New(iF.mesh()).allOrigPatchIDs();
// Evaluate the conformed orig and non-conformal boundary fields
const typename SurfaceField<Type>::Boundary origBf
(
SurfaceField<Type>::Internal::null(),
fvMeshStitcherTools::conformedOrigBoundaryField(bF)
);
const typename SurfaceField<Type>::Boundary ncBf
(
SurfaceField<Type>::Internal::null(),
fvMeshStitcherTools::conformedNcBoundaryField(bF)
);
// Replace every original patch field with a conformed patch field
// containing the conformed orig and non-conformal fields
forAll(origPatchIDs, i)
{
const label origPatchi = origPatchIDs[i];
const fvPatch& origFvp = fvbm[origPatchi];
autoPtr<conformedFvsPatchField<Type>> pF
(
new conformedFvsPatchField<Type>
(
origFvp,
iF,
bF.set(origPatchi, nullptr),
autoPtr<calculatedFvsPatchField<Type>>
(
new calculatedFvsPatchField<Type>(origFvp, iF)
)
)
);
pF->origFieldPtr_() == origBf[origPatchi];
pF->ncFieldPtr_() == ncBf[origPatchi];
bF.set(origPatchi, pF.ptr());
}
}
template<class Type>
void Foam::conformedFvsPatchField<Type>::unconform
(
typename SurfaceField<Type>::Boundary& bF
)
{
const DimensionedField<Type, surfaceMesh>& iF = bF[0].internalField();
const fvBoundaryMesh& fvbm = iF.mesh().boundary();
const labelList origPatchIDs =
nonConformalBoundary::New(iF.mesh()).allOrigPatchIDs();
// Extract the conformalalised orig and non-conformal boundary fields from
// the stored conformed patch fields
PtrList<fvsPatchField<Type>> origPFs(fvbm.size());
PtrList<fvsPatchField<Type>> ncPFs(fvbm.size());
forAll(origPatchIDs, i)
{
const label origPatchi = origPatchIDs[i];
conformedFvsPatchField<Type>& cpF =
refCast<conformedFvsPatchField<Type>>(bF[origPatchi]);
origPFs.set(origPatchi, cpF.origFieldPtr_.ptr());
ncPFs.set(origPatchi, cpF.ncFieldPtr_.ptr());
}
forAll(origPFs, patchi)
{
if (origPFs.set(patchi)) continue;
origPFs.set(patchi, bF.set(patchi, nullptr));
ncPFs.set
(
patchi,
fvsPatchField<Type>::New
(
calculatedFvsPatchField<Type>::typeName,
fvbm[patchi],
iF
)
);
}
typename SurfaceField<Type>::Boundary origBf(fvbm, iF, origPFs);
typename SurfaceField<Type>::Boundary ncBf(fvbm, iF, ncPFs);
// Combine the conformed boundary fields to create the non-conformal
// boundary field
typename SurfaceField<Type>::Boundary result
(
iF,
fvMeshStitcherTools::unconformedBoundaryField(ncBf, origBf)
);
bF.transfer(result);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
Foam::conformedFvsPatchField<Type>::conformedFvsPatchField
(
const fvPatch& p,
const DimensionedField<Type, surfaceMesh>& iF
)
:
fvsPatchField<Type>(p, iF)
{
NotImplemented;
}
template<class Type>
Foam::conformedFvsPatchField<Type>::conformedFvsPatchField
(
const fvPatch& p,
const DimensionedField<Type, surfaceMesh>& iF,
const dictionary& dict
)
:
fvsPatchField<Type>(p, iF, dict, false),
origFieldPtr_
(
fvsPatchField<Type>::New(p, iF, dict.subDict("origField")).ptr()
),
ncFieldPtr_
(
new calculatedFvsPatchField<Type>(p, iF, dict.subDict("ncField"))
)
{}
template<class Type>
Foam::conformedFvsPatchField<Type>::conformedFvsPatchField
(
const conformedFvsPatchField<Type>& ptf,
const fvPatch& p,
const DimensionedField<Type, surfaceMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
fvsPatchField<Type>(ptf, p, iF, mapper, false),
origFieldPtr_
(
fvsPatchField<Type>::New(ptf.origFieldPtr_(), p, iF, mapper).ptr()
),
ncFieldPtr_
(
new calculatedFvsPatchField<Type>
(
ptf.ncFieldPtr_(),
p,
iF,
mapper
)
)
{}
template<class Type>
Foam::conformedFvsPatchField<Type>::conformedFvsPatchField
(
const conformedFvsPatchField<Type>& ptf,
const DimensionedField<Type, surfaceMesh>& iF
)
:
fvsPatchField<Type>(ptf, iF),
origFieldPtr_(ptf.origFieldPtr_->clone(iF).ptr()),
ncFieldPtr_(new calculatedFvsPatchField<Type>(ptf.ncFieldPtr_(), iF))
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
void Foam::conformedFvsPatchField<Type>::map
(
const fvsPatchField<Type>& ptf,
const fvPatchFieldMapper& mapper
)
{
if (isA<conformedFvsPatchField<Type>>(ptf))
{
const conformedFvsPatchField<Type>& cptf =
refCast<const conformedFvsPatchField<Type>>(ptf);
origFieldPtr_->map(cptf.origFieldPtr_(), mapper);
ncFieldPtr_->map(cptf.ncFieldPtr_(), mapper);
}
else
{
origFieldPtr_->reset(ptf);
ncFieldPtr_() == origFieldPtr_();
}
}
template<class Type>
void Foam::conformedFvsPatchField<Type>::reset(const fvsPatchField<Type>& ptf)
{
if (isA<conformedFvsPatchField<Type>>(ptf))
{
const conformedFvsPatchField<Type>& cptf =
refCast<const conformedFvsPatchField<Type>>(ptf);
origFieldPtr_->reset(cptf.origFieldPtr_());
ncFieldPtr_->reset(cptf.ncFieldPtr_());
}
else
{
origFieldPtr_->reset(ptf);
ncFieldPtr_() == origFieldPtr_();
}
}
template<class Type>
void Foam::conformedFvsPatchField<Type>::write(Ostream& os) const
{
fvsPatchField<Type>::write(os);
writeKeyword(os, "origField") << nl;
os << indent << token::BEGIN_BLOCK << incrIndent << nl;
origFieldPtr_->write(os);
os << decrIndent << indent << token::END_BLOCK << nl;
writeKeyword(os, "ncField") << nl;
os << indent << token::BEGIN_BLOCK << incrIndent << nl;
ncFieldPtr_->write(os);
os << decrIndent << indent << token::END_BLOCK << nl;
}
// ************************************************************************* //

View File

@ -0,0 +1,182 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2023 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/>.
Class
Foam::conformedFvsPatchField
Description
This surface field boundary condition holds data from both the original
faces and any associated non-conformal faces, with the latter mapped to the
conformal faces in the original patch. It is used during mesh change
(between the un-stitch and stitch steps) to ensure that fields relating to
both the original and the non-conformal patches are retained and mapped.
SourceFiles
conformedFvsPatchField.C
\*---------------------------------------------------------------------------*/
#ifndef conformedFvsPatchField_H
#define conformedFvsPatchField_H
#include "fvsPatchField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class conformedFvsPatch Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
class conformedFvsPatchField
:
public fvsPatchField<Type>
{
// Private Data
//- The original patch field
autoPtr<fvsPatchField<Type>> origFieldPtr_;
//- The associated non-conformal patch field
autoPtr<calculatedFvsPatchField<Type>> ncFieldPtr_;
// Private Constructors
//- Construct from components
conformedFvsPatchField
(
const fvPatch&,
const DimensionedField<Type, surfaceMesh>&,
autoPtr<fvsPatchField<Type>>&& origFieldPtr,
autoPtr<calculatedFvsPatchField<Type>>&& ncFieldPtr
);
public:
//- Runtime type information
TypeName("conformed");
// Static Member Functions
//- Conform the given boundary field
static void conform(typename SurfaceField<Type>::Boundary& bF);
//- Un-conform the given boundary field
static void unconform(typename SurfaceField<Type>::Boundary& bF);
// Constructors
//- Construct from patch and internal field
conformedFvsPatchField
(
const fvPatch&,
const DimensionedField<Type, surfaceMesh>&
);
//- Construct from patch, internal field and dictionary
conformedFvsPatchField
(
const fvPatch&,
const DimensionedField<Type, surfaceMesh>&,
const dictionary&
);
//- Construct by mapping the given conformedFvsPatchField<Type>
// onto a new patch
conformedFvsPatchField
(
const conformedFvsPatchField<Type>&,
const fvPatch&,
const DimensionedField<Type, surfaceMesh>&,
const fvPatchFieldMapper&
);
//- Disallow copy without setting internal field reference
conformedFvsPatchField
(
const conformedFvsPatchField<Type>&
) = delete;
//- Copy constructor setting internal field reference
conformedFvsPatchField
(
const conformedFvsPatchField<Type>&,
const DimensionedField<Type, surfaceMesh>&
);
//- Construct and return a clone setting internal field reference
virtual tmp<fvsPatchField<Type>> clone
(
const DimensionedField<Type, surfaceMesh>& iF
) const
{
return tmp<fvsPatchField<Type>>
(
new conformedFvsPatchField<Type>(*this, iF)
);
}
// Member Functions
// Mapping functions
//- Map the given fvsPatchField onto this fvsPatchField
virtual void map
(
const fvsPatchField<Type>&,
const fvPatchFieldMapper&
);
//- Reset the fvsPatchField to the given fvsPatchField
// Used for mesh to mesh mapping
virtual void reset(const fvsPatchField<Type>&);
//- Write
virtual void write(Ostream&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "conformedFvsPatchField.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,43 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2023 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 "conformedFvsPatchFields.H"
#include "surfaceFields.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
makeFvsPatchFields(conformed);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,49 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2023 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/>.
\*---------------------------------------------------------------------------*/
#ifndef conformedFvsPatchFields_H
#define conformedFvsPatchFields_H
#include "conformedFvsPatchField.H"
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makeFvsPatchTypeFieldTypedefs(conformed);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2023 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/>.
\*---------------------------------------------------------------------------*/
#ifndef conformedFvsPatchFieldsFwd_H
#define conformedFvsPatchFieldsFwd_H
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type> class conformedFvsPatchField;
makeFvsPatchTypeFieldTypedefs(conformed);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -26,8 +26,11 @@ License
#include "fvMeshStitcher.H"
#include "globalIndex.H"
#include "fvcSurfaceIntegrate.H"
#include "fvMeshToFvMesh.H"
#include "meshObjects.H"
#include "polyTopoChangeMap.H"
#include "polyMeshMap.H"
#include "polyDistributionMap.H"
#include "syncTools.H"
#include "surfaceToVolVelocity.H"
@ -62,10 +65,6 @@ namespace Foam
}
const Foam::word Foam::fvMeshStitcher::nccFieldPrefix_ =
fvMeshStitcher::typeName + ":";
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::fvMeshStitcher::intersectNonConformalCyclic
@ -1084,6 +1083,58 @@ inline void Foam::fvMeshStitcher::createNonConformalStabilisationGeometry
}
void Foam::fvMeshStitcher::preConformSurfaceFields()
{
#define PreConformSurfaceFields(Type, nullArg) \
preConformSurfaceFields<Type>();
FOR_ALL_FIELD_TYPES(PreConformSurfaceFields);
#undef PreConformSurfaceFields
}
void Foam::fvMeshStitcher::postNonConformSurfaceFields()
{
#define PostNonConformSurfaceFields(Type, nullArg) \
postNonConformSurfaceFields<Type>();
FOR_ALL_FIELD_TYPES(PostNonConformSurfaceFields);
#undef PostNonConformSurfaceFields
}
void Foam::fvMeshStitcher::evaluateVolFields()
{
#define EvaluateVolFields(Type, nullArg) \
evaluateVolFields<Type>();
FOR_ALL_FIELD_TYPES(EvaluateVolFields);
#undef EvaluateVolFields
}
void Foam::fvMeshStitcher::postNonConformSurfaceVelocities()
{
UPtrList<surfaceVectorField> Ufs(mesh_.fields<surfaceVectorField>());
forAll(Ufs, i)
{
surfaceVectorField& Uf = Ufs[i];
const volVectorField& U = surfaceToVolVelocity(Uf);
if (!isNull(U))
{
forAll(Uf.boundaryField(), patchi)
{
if (isA<nonConformalFvPatch>(mesh_.boundary()[patchi]))
{
boundaryFieldRefNoUpdate(Uf)[patchi] ==
U.boundaryField()[patchi];
}
}
}
}
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
bool Foam::fvMeshStitcher::geometric() const
@ -1605,7 +1656,7 @@ void Foam::fvMeshStitcher::topoChange(const polyTopoChangeMap&)
{}
void Foam::fvMeshStitcher::mapMesh(const polyMeshMap&)
void Foam::fvMeshStitcher::mapMesh(const polyMeshMap& map)
{}

View File

@ -38,6 +38,7 @@ SourceFiles
#define fvMeshStitcher_H
#include "fvMesh.H"
#include "HashPtrTable.H"
#include "intersectionPatchToPatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -72,18 +73,73 @@ protected:
private:
// Private Static Data
//- Prefix applied to the names of non-conformal fields which are
// stored for mapping purposes
static const word nccFieldPrefix_;
// Private Data
//- Non-const fvMesh reference to allow update
fvMesh& mesh_;
//- Cache of the surface boundary fields with non-conformal parts
// averaged/summed (as appropriate) into the corresponding conformal
// faces. Maintained between disconnect and connect so that
// non-conformal fields can be reconstructed again at the new time.
class
:
#define PrivateTypeTable(Type, nullArg) \
private HashPtrTable<SurfaceFieldBoundary<Type>>,
FOR_ALL_FIELD_TYPES(PrivateTypeTable)
#undef PrivateTypeTable
private nil
{
private:
template<class Type>
using Base = HashPtrTable<SurfaceFieldBoundary<Type>>;
public:
template<class Type>
const HashPtrTable<SurfaceFieldBoundary<Type>>& table() const
{
return *this;
}
template<class Type>
HashPtrTable<SurfaceFieldBoundary<Type>>& table()
{
return *this;
}
template<class Type>
bool insert
(
const word& name,
SurfaceFieldBoundary<Type>* fieldPtr
)
{
return Base<Type>::insert(name, fieldPtr);
}
template<class Type>
bool found(const word& name) const
{
return Base<Type>::found(name);
}
template<class Type>
tmp<SurfaceFieldBoundary<Type>> remove(const word& name)
{
typename Base<Type>::iterator iter = Base<Type>::find(name);
return
tmp<SurfaceFieldBoundary<Type>>
(
Base<Type>::remove(iter)
);
}
} conformalNccBoundaryFields_;
// Private Member Functions
@ -178,21 +234,12 @@ private:
// Field Mapping
//- Return the boundary field reference for the given field,
// without updating the time index, storing old time fields,
// etc...
template<class GeoField>
static typename GeoField::Boundary& boundaryFieldRefNoUpdate
(
GeoField& fld
);
//- Resize the patch fields of a given type and class to match the
// mesh
// sizes of the patches in the mesh
template<class Type, template<class> class GeoField>
void resizePatchFields();
//- Resize the patch fields of a given class to match the mesh
//- As above, for all types
template<template<class> class GeoField>
void resizePatchFields();
@ -202,10 +249,8 @@ private:
template<class Type>
void preConformSurfaceFields();
//- Pre-conform surface fields by separating NCC and original
// parts of non-conformal couplings and storing them in the
// database as separate fields
inline void preConformSurfaceFields();
//- As above, for all types
void preConformSurfaceFields();
//- Post-non-conform surface fields of a given type by looking up
// NCC and original parts of non-conformal couplings and combining
@ -213,110 +258,31 @@ private:
template<class Type>
void postNonConformSurfaceFields();
//- Post-non-conform surface fields by looking up NCC and
// original parts of non-conformal couplings and combining them
// into a single non-conformal boundary field
inline void postNonConformSurfaceFields();
//- As above, for all types
void postNonConformSurfaceFields();
//- Evaluate all non-conformal vol patch fields of a given type
template<class Type>
void evaluateVolFields();
//- Evaluate all non-conformal vol patch fields
inline void evaluateVolFields();
//- As above, for all types
void evaluateVolFields();
//- Special post-non-conform for surface velocities
inline void postNonConformSurfaceVelocities();
void postNonConformSurfaceVelocities();
protected:
// Protected Member Functions
// Field Mapping
//- Resize the patch field of a given field to match the mesh
template<class GeoBoundaryField>
void resizeBoundaryFieldPatchFields
(
const SurfaceFieldBoundary<label>& polyFacesBf,
GeoBoundaryField& fieldBf
);
//- Resize the patch field of a given field to match the mesh
template<class GeoField>
void resizeFieldPatchFields
(
const SurfaceFieldBoundary<label>& polyFacesBf,
GeoField& field
);
//- Reverse-map sum the values of a field
template<class Type>
static tmp<Field<Type>> fieldRMapSum
(
const Field<Type>& f,
const label size,
const labelUList& addr
);
//- Reverse-map sum the values of a field
template<class Type>
static tmp<Field<Type>> fieldRMapSum
(
const tmp<Field<Type>>& f,
const label size,
const labelUList& addr
);
//- Return the total non-conformal area associated with each
// original face
inline tmp<SurfaceFieldBoundary<scalar>> getOrigNccMagSfb() const;
//- Extract the non-conformal-coupled parts of the boundary field
// and store it on the conformal faces
template<class Type>
tmp<SurfaceFieldBoundary<Type>> conformalNccBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb
) const;
//- Extract the original parts of the boundary field and store it
// on the conformal faces
template<class Type>
tmp<SurfaceFieldBoundary<Type>> conformalOrigBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb
) const;
//- Combine non-conformal-coupled and original parts of the
// boundary field from the conformal faces to construct the
// complete non-conformal boundary field
template<class Type>
tmp<SurfaceFieldBoundary<Type>> nonConformalBoundaryField
(
const SurfaceFieldBoundary<Type>& nccFieldb,
const SurfaceFieldBoundary<Type>& origFieldb
) const;
//- Synchronise the boundary field by combining corresponding
// values across couplings with the given weightings
template<class Type>
tmp<SurfaceFieldBoundary<Type>> synchronisedBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb,
const bool flip,
const scalar ownerWeight,
const scalar neighbourWeight
) const;
//- Synchronise the boundary field by combining corresponding
// values across couplings with equal weightings
template<class Type>
tmp<SurfaceFieldBoundary<Type>> synchronisedBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb
) const;
//- Access the boundary field reference of a field, without updating
// the time index, storing old time fields, etc...
template<class GeoField>
static typename GeoField::Boundary& boundaryFieldRefNoUpdate
(
GeoField& fld
);
// Checking

View File

@ -28,6 +28,7 @@ Description
#include "volFields.H"
#include "surfaceFields.H"
#include "conformedFvsPatchField.H"
#include "fvPatchFieldMapper.H"
#include "fvMeshStitcher.H"
#include "setSizeFvPatchFieldMapper.H"
@ -41,16 +42,6 @@ Description
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class GeoField>
typename GeoField::Boundary& Foam::fvMeshStitcher::boundaryFieldRefNoUpdate
(
GeoField& fld
)
{
return const_cast<typename GeoField::Boundary&>(fld.boundaryField());
}
template<class Type, template<class> class GeoField>
void Foam::fvMeshStitcher::resizePatchFields()
{
@ -86,134 +77,44 @@ void Foam::fvMeshStitcher::preConformSurfaceFields()
{
UPtrList<SurfaceField<Type>> fields(mesh_.curFields<SurfaceField<Type>>());
const labelList origPatchIDs =
nonConformalBoundary::New(mesh_).allOrigPatchIDs();
forAll(fields, i)
{
SurfaceField<Type>& field = fields[i];
autoPtr<SurfaceField<Type>> nccFieldPtr
(
new SurfaceField<Type>
(
IOobject
(
nccFieldPrefix_ + field.name(),
mesh_.time().name(),
mesh_
),
field
)
);
for (label ti=0; ti<=field.nOldTimes(false); ti++)
{
SurfaceField<Type>& field0 = field.oldTime(ti);
boundaryFieldRefNoUpdate(nccFieldPtr->oldTime(ti)) =
conformalNccBoundaryField<Type>(field0.boundaryField());
boundaryFieldRefNoUpdate(field0) =
conformalOrigBoundaryField<Type>(field0.boundaryField());
conformedFvsPatchField<Type>::conform
(
boundaryFieldRefNoUpdate(field.oldTime(ti))
);
}
nccFieldPtr.ptr()->store();
}
}
inline void Foam::fvMeshStitcher::preConformSurfaceFields()
{
#define PreConformSurfaceFields(Type, nullArg) \
preConformSurfaceFields<Type>();
FOR_ALL_FIELD_TYPES(PreConformSurfaceFields);
#undef PreConformSurfaceFields
}
template<class Type>
void Foam::fvMeshStitcher::postNonConformSurfaceFields()
{
UPtrList<SurfaceField<Type>> fields(mesh_.curFields<SurfaceField<Type>>());
if (!mesh_.topoChanged())
{
forAll(fields, i)
{
if (fields[i].name()(nccFieldPrefix_.size()) == nccFieldPrefix_)
continue;
const labelList origPatchIDs =
nonConformalBoundary::New(mesh_).allOrigPatchIDs();
SurfaceField<Type>& field = fields[i];
const word nccFieldName = nccFieldPrefix_ + field.name();
const SurfaceField<Type>& nccField =
mesh_.lookupObject<SurfaceField<Type>>(nccFieldName);
for (label ti=0; ti<=field.nOldTimes(false); ti++)
{
SurfaceField<Type>& field0 = field.oldTime(ti);
boundaryFieldRefNoUpdate(field0) =
nonConformalBoundaryField<Type>
(
nccField.oldTime(ti).boundaryField(),
field0.boundaryField()
);
boundaryFieldRefNoUpdate(field0) =
synchronisedBoundaryField<Type>(field0.boundaryField());
}
}
}
// Remove NCC fields after all fields have been mapped. This is so that
// old-time fields aren't removed by current-time fields in advance of the
// old-time field being mapped.
// Cache the nccField pointers
DynamicList<SurfaceField<Type>*> nccFields;
forAll(fields, i)
{
if (fields[i].name()(nccFieldPrefix_.size()) == nccFieldPrefix_)
continue;
SurfaceField<Type>& field = fields[i];
const word nccFieldName = nccFieldPrefix_ + field.name();
SurfaceField<Type>& nccField =
mesh_.lookupObjectRef<SurfaceField<Type>>(nccFieldName);
nccFields.append(&nccField);
for (label ti=0; ti<=field.nOldTimes(false); ti++)
{
conformedFvsPatchField<Type>::unconform
(
boundaryFieldRefNoUpdate(field.oldTime(ti))
);
}
}
// Checkout the nccFields after the loop over fields
// to avoid deleting a subsequent field in the list
forAll(nccFields, i)
{
nccFields[i]->checkOut();
}
// Check there are no NCC fields left over
fields = mesh_.curFields<SurfaceField<Type>>();
forAll(fields, i)
{
if (fields[i].name()(nccFieldPrefix_.size()) != nccFieldPrefix_)
continue;
FatalErrorInFunction
<< "Stitching mapping field \"" << fields[i].name()
<< "\" found, but the field it corresponds to no longer exists"
<< exit(FatalError);
}
}
inline void Foam::fvMeshStitcher::postNonConformSurfaceFields()
{
#define PostNonConformSurfaceFields(Type, nullArg) \
postNonConformSurfaceFields<Type>();
FOR_ALL_FIELD_TYPES(PostNonConformSurfaceFields);
#undef PostNonConformSurfaceFields
}
@ -259,517 +160,15 @@ void Foam::fvMeshStitcher::evaluateVolFields()
}
inline void Foam::fvMeshStitcher::evaluateVolFields()
{
#define EvaluateVolFields(Type, nullArg) \
evaluateVolFields<Type>();
FOR_ALL_FIELD_TYPES(EvaluateVolFields);
#undef EvaluateVolFields
}
inline void Foam::fvMeshStitcher::postNonConformSurfaceVelocities()
{
if (mesh_.topoChanged())
{
UPtrList<surfaceVectorField> Ufs(mesh_.fields<surfaceVectorField>());
forAll(Ufs, i)
{
surfaceVectorField& Uf = Ufs[i];
const volVectorField& U = surfaceToVolVelocity(Uf);
if (!isNull(U))
{
forAll(Uf.boundaryField(), patchi)
{
if (isA<nonConformalFvPatch>(mesh_.boundary()[patchi]))
{
boundaryFieldRefNoUpdate(Uf)[patchi] ==
U.boundaryField()[patchi];
}
}
}
}
}
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class GeoBoundaryField>
void Foam::fvMeshStitcher::resizeBoundaryFieldPatchFields
(
const SurfaceFieldBoundary<label>& polyFacesBf,
GeoBoundaryField& fieldBf
)
{
forAll(polyFacesBf, nccPatchi)
{
if (isA<nonConformalFvPatch>(polyFacesBf[nccPatchi].patch()))
{
fieldBf[nccPatchi].map
(
fieldBf[nccPatchi],
setSizeFvPatchFieldMapper(polyFacesBf[nccPatchi].size())
);
}
}
}
template<class GeoField>
void Foam::fvMeshStitcher::resizeFieldPatchFields
typename GeoField::Boundary& Foam::fvMeshStitcher::boundaryFieldRefNoUpdate
(
const SurfaceFieldBoundary<label>& polyFacesBf,
GeoField& field
GeoField& fld
)
{
for (label ti=0; ti<=field.nOldTimes(false); ti++)
{
resizeBoundaryFieldPatchFields
(
polyFacesBf,
boundaryFieldRefNoUpdate(field.oldTime(ti))
);
}
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::fvMeshStitcher::fieldRMapSum
(
const Field<Type>& f,
const label size,
const labelUList& addr
)
{
tmp<Field<Type>> tresult(new Field<Type>(size, Zero));
forAll(addr, i)
{
tresult.ref()[addr[i]] += f[i];
}
return tresult;
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::fvMeshStitcher::fieldRMapSum
(
const tmp<Field<Type>>& f,
const label size,
const labelUList& addr
)
{
tmp<Field<Type>> tresult = fieldRMapSum(f(), size, addr);
f.clear();
return tresult;
}
inline Foam::tmp<Foam::surfaceScalarField::Boundary>
Foam::fvMeshStitcher::getOrigNccMagSfb() const
{
const fvBoundaryMesh& fvbm = mesh_.boundary();
const surfaceScalarField::Boundary& magSfb =
fvbm.mesh().magSf().boundaryField();
tmp<surfaceScalarField::Boundary> tOrigNccMagSfb
(
new surfaceScalarField::Boundary
(
fvbm,
surfaceScalarField::Internal::null(),
calculatedFvPatchField<scalar>::typeName
)
);
surfaceScalarField::Boundary& origNccMagSfb = tOrigNccMagSfb.ref();
origNccMagSfb == 0;
forAll(fvbm, nccPatchi)
{
const fvPatch& fvp = fvbm[nccPatchi];
if (isA<nonConformalCoupledFvPatch>(fvp))
{
const nonConformalCoupledFvPatch& nccFvp =
refCast<const nonConformalCoupledFvPatch>(fvp);
const label origPatchi = nccFvp.origPatchID();
const fvPatch& origFvp = nccFvp.origPatch();
const labelList nccOrigPatchFace =
nccFvp.polyFaces() - origFvp.start();
origNccMagSfb[origPatchi] +=
fieldRMapSum
(
magSfb[nccPatchi],
origFvp.size(),
nccOrigPatchFace
);
}
}
return tOrigNccMagSfb;
}
template<class Type>
Foam::tmp<Foam::fvMeshStitcher::SurfaceFieldBoundary<Type>>
Foam::fvMeshStitcher::conformalNccBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb
) const
{
const bool isFluxField = isFlux(fieldb[0].internalField());
const fvBoundaryMesh& fvbm = fieldb[0].patch().boundaryMesh();
const surfaceScalarField::Boundary& magSfb =
fvbm.mesh().magSf().boundaryField();
tmp<SurfaceFieldBoundary<Type>> tnccFieldb
(
new SurfaceFieldBoundary<Type>
(
SurfaceField<Type>::Internal::null(),
fieldb
)
);
SurfaceFieldBoundary<Type>& nccFieldb = tnccFieldb.ref();
nccFieldb == pTraits<Type>::zero;
const surfaceScalarField::Boundary origNccMagSfb
(
surfaceScalarField::Internal::null(),
getOrigNccMagSfb()
);
// Accumulate the non-conformal parts of the field into the original faces
forAll(fvbm, nccPatchi)
{
const fvPatch& fvp = fvbm[nccPatchi];
if (isA<nonConformalCoupledFvPatch>(fvp))
{
const nonConformalCoupledFvPatch& nccFvp =
refCast<const nonConformalCoupledFvPatch>(fvbm[nccPatchi]);
const label origPatchi = nccFvp.origPatchID();
const fvPatch& origFvp = nccFvp.origPatch();
const labelList nccOrigPatchFace =
nccFvp.polyFaces() - origFvp.start();
// If this is a flux then sum
if (isFluxField)
{
nccFieldb[origPatchi] +=
fieldRMapSum
(
fieldb[nccPatchi],
origFvp.size(),
nccOrigPatchFace
);
}
// If not a flux then do an area-weighted sum
else
{
nccFieldb[origPatchi] +=
fieldRMapSum
(
fieldb[nccPatchi]*magSfb[nccPatchi],
origFvp.size(),
nccOrigPatchFace
);
}
}
}
const labelList origPatchIDs =
nonConformalBoundary::New(mesh_).allOrigPatchIDs();
// Scale or average as appropriate
forAll(origPatchIDs, i)
{
const label origPatchi = origPatchIDs[i];
// If this is a flux then scale to the total size of the face
if (isFluxField)
{
const scalarField origSumMagSf
(
magSfb[origPatchi] + origNccMagSfb[origPatchi]
);
nccFieldb[origPatchi] *=
origSumMagSf
/max(origNccMagSfb[origPatchi], small*origSumMagSf);
}
// If this is not a flux then convert to an area-weighted average
else
{
nccFieldb[origPatchi] /=
max(origNccMagSfb[origPatchi], vSmall);
}
}
return tnccFieldb;
}
template<class Type>
Foam::tmp<Foam::fvMeshStitcher::SurfaceFieldBoundary<Type>>
Foam::fvMeshStitcher::conformalOrigBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb
) const
{
const bool isFluxField = isFlux(fieldb[0].internalField());
const fvBoundaryMesh& fvbm = fieldb[0].patch().boundaryMesh();
const surfaceScalarField::Boundary& magSfb =
fvbm.mesh().magSf().boundaryField();
tmp<SurfaceFieldBoundary<Type>> torigFieldb
(
new SurfaceFieldBoundary<Type>
(
SurfaceField<Type>::Internal::null(),
fieldb
)
);
// If this is a flux then scale up to the total face areas
if (isFluxField)
{
const surfaceScalarField::Boundary origNccMagSfb
(
surfaceScalarField::Internal::null(),
getOrigNccMagSfb()
);
SurfaceFieldBoundary<Type>& origFieldb = torigFieldb.ref();
const labelList origPatchIDs =
nonConformalBoundary::New(mesh_).allOrigPatchIDs();
forAll(origPatchIDs, i)
{
const label origPatchi = origPatchIDs[i];
const scalarField origSumMagSf
(
magSfb[origPatchi] + origNccMagSfb[origPatchi]
);
origFieldb[origPatchi] *=
origSumMagSf
/max(magSfb[origPatchi], small*origSumMagSf);
}
}
return torigFieldb;
}
template<class Type>
Foam::tmp<Foam::fvMeshStitcher::SurfaceFieldBoundary<Type>>
Foam::fvMeshStitcher::nonConformalBoundaryField
(
const SurfaceFieldBoundary<Type>& nccFieldb,
const SurfaceFieldBoundary<Type>& origFieldb
) const
{
const bool isFluxField = isFlux(origFieldb[0].internalField());
const fvBoundaryMesh& fvbm = origFieldb[0].patch().boundaryMesh();
const surfaceScalarField::Boundary& magSfb =
fvbm.mesh().magSf().boundaryField();
tmp<SurfaceFieldBoundary<Type>> tfieldb
(
new SurfaceFieldBoundary<Type>
(
SurfaceField<Type>::Internal::null(),
origFieldb
)
);
SurfaceFieldBoundary<Type>& fieldb = tfieldb.ref();
// Set the coupled values
forAll(fvbm, nccPatchi)
{
const fvPatch& fvp = fvbm[nccPatchi];
if (isA<nonConformalCoupledFvPatch>(fvp))
{
const nonConformalCoupledFvPatch& nccFvp =
refCast<const nonConformalCoupledFvPatch>(fvp);
const label origPatchi = nccFvp.origPatchID();
const fvPatch& origFvp = nccFvp.origPatch();
const labelList nccOrigPatchFace =
nccFvp.polyFaces() - origFvp.start();
// Set the cyclic values
fieldb[nccPatchi] =
Field<Type>(nccFieldb[origPatchi], nccOrigPatchFace);
}
}
// If a flux then scale down to the part face area
if (isFluxField)
{
const surfaceScalarField::Boundary origNccMagSfb
(
surfaceScalarField::Internal::null(),
getOrigNccMagSfb()
);
forAll(fvbm, nccPatchi)
{
const fvPatch& fvp = fvbm[nccPatchi];
if (isA<nonConformalCoupledFvPatch>(fvp))
{
const nonConformalCoupledFvPatch& nccFvp =
refCast<const nonConformalCoupledFvPatch>(fvp);
const label origPatchi = nccFvp.origPatchID();
const fvPatch& origFvp = nccFvp.origPatch();
const labelList nccOrigPatchFace =
nccFvp.polyFaces() - origFvp.start();
const scalarField origSumMagSf
(
magSfb[origPatchi] + origNccMagSfb[origPatchi]
);
const scalarField nccSumMagSf(origSumMagSf, nccOrigPatchFace);
fieldb[nccPatchi] *= magSfb[nccPatchi]/nccSumMagSf;
if (!isA<processorFvPatch>(fvp))
{
fieldb[origPatchi] *= magSfb[origPatchi]/origSumMagSf;
}
}
}
}
// Set error values
forAll(fvbm, patchi)
{
const fvPatch& fvp = fvbm[patchi];
if (isA<nonConformalErrorFvPatch>(fvp))
{
const label errorPatchi = patchi;
const nonConformalErrorFvPatch& errorFvp =
refCast<const nonConformalErrorFvPatch>(fvp);
const label origPatchi = errorFvp.origPatchID();
const fvPatch& origFvp = errorFvp.origPatch();
const labelList errorOrigPatchFace =
errorFvp.polyFaces() - origFvp.start();
if (isFluxField)
{
fieldb[errorPatchi] = Zero;
}
else
{
fieldb[errorPatchi] =
Field<Type>(origFieldb[origPatchi], errorOrigPatchFace);
}
}
}
return tfieldb;
}
template<class Type>
Foam::tmp<Foam::fvMeshStitcher::SurfaceFieldBoundary<Type>>
Foam::fvMeshStitcher::synchronisedBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb,
const bool flip,
const scalar ownerWeight,
const scalar neighbourWeight
) const
{
const fvBoundaryMesh& fvbm = fieldb[0].patch().boundaryMesh();
tmp<SurfaceFieldBoundary<Type>> tsyncFieldb
(
new SurfaceFieldBoundary<Type>
(
SurfaceField<Type>::Internal::null(),
fieldb
)
);
SurfaceFieldBoundary<Type>& syncFieldb = tsyncFieldb.ref();
SurfaceFieldBoundary<Type> fieldbNbr
(
SurfaceField<Type>::Internal::null(),
fieldb.boundaryNeighbourField()
);
forAll(fvbm, patchi)
{
const fvPatch& fvp = fvbm[patchi];
if (fvp.coupled())
{
const coupledFvPatch& cfvp = refCast<const coupledFvPatch>(fvp);
const scalar w = cfvp.owner() ? ownerWeight : neighbourWeight;
const scalar v = cfvp.owner() ? neighbourWeight : ownerWeight;
syncFieldb[patchi] =
w*syncFieldb[patchi] + (flip ? -v : +v)*fieldbNbr[patchi];
}
}
return tsyncFieldb;
}
template<class Type>
Foam::tmp<Foam::fvMeshStitcher::SurfaceFieldBoundary<Type>>
Foam::fvMeshStitcher::synchronisedBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb
) const
{
const bool isFluxField = isFlux(fieldb[0].internalField());
return synchronisedBoundaryField<Type>
(
fieldb,
isFluxField,
0.5,
0.5
);
return const_cast<typename GeoField::Boundary&>(fld.boundaryField());
}

View File

@ -0,0 +1,81 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2023 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 "fvMeshStitcherTools.H"
#include "surfaceFields.H"
#include "calculatedFvsPatchField.H"
#include "nonConformalFvPatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Foam::tmp<Foam::surfaceScalarField::Boundary>
Foam::fvMeshStitcherTools::origNcMagSfb(const fvMesh& mesh)
{
const fvBoundaryMesh& fvbm = mesh.boundary();
const surfaceScalarField::Boundary& magSfb =
fvbm.mesh().magSf().boundaryField();
tmp<surfaceScalarField::Boundary> tresult
(
new surfaceScalarField::Boundary
(
fvbm,
surfaceScalarField::Internal::null(),
calculatedFvsPatchField<scalar>::typeName
)
);
surfaceScalarField::Boundary& result = tresult.ref();
result == 0;
forAll(fvbm, ncPatchi)
{
const fvPatch& fvp = fvbm[ncPatchi];
if (!isA<nonConformalFvPatch>(fvp)) continue;
const nonConformalFvPatch& ncFvp =
refCast<const nonConformalFvPatch>(fvp);
const label origPatchi = ncFvp.origPatchID();
const fvPatch& origFvp = ncFvp.origPatch();
result[origPatchi] +=
fieldRMapSum
(
magSfb[ncPatchi],
origFvp.size(),
ncFvp.polyFaces(),
origFvp.start()
);
}
return tresult;
}
// ************************************************************************* //

View File

@ -0,0 +1,153 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2023 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/>.
Namespace
Foam::fvMeshStitcherTools
Description
Collection of free functions utilised by the stitching process
SourceFiles
fvMeshStitcherTools.C
fvMeshStitcherToolsTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef fvMeshStitcherTools_H
#define fvMeshStitcherTools_H
#include "fvMesh.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fvMeshStitcherTools
{
//- Map a field with an (optional) addressing offset
template<class Type>
tmp<Field<Type>> fieldMap
(
const Field<Type>& f,
const labelUList& addr,
const label addr0 = 0
);
//- Tmp variant of above
template<class Type>
tmp<Field<Type>> fieldMap
(
const tmp<Field<Type>>& f,
const labelUList& addr,
const label addr0 = 0
);
//- Reverse map a field with an (optional) addressing offset, initialising the
// value to zero and summing repeated indices
template<class Type>
tmp<Field<Type>> fieldRMapSum
(
const Field<Type>& f,
const label size,
const labelUList& addr,
const label addr0 = 0
);
//- Tmp variant of above
template<class Type>
tmp<Field<Type>> fieldRMapSum
(
const tmp<Field<Type>>& f,
const label size,
const labelUList& addr,
const label addr0 = 0
);
//- Alias for surface boundary fields to reduce verbosity of method
// definitions below
template<class Type>
using SurfaceFieldBoundary =
GeometricBoundaryField<Type, fvsPatchField, surfaceMesh>;
//- Return the total non-conformal area associated with each original face
tmp<SurfaceFieldBoundary<scalar>> origNcMagSfb(const fvMesh& mesh);
//- Extract the non-conformal parts of the boundary field and store it on the
// conformal faces
template<class Type>
tmp<SurfaceFieldBoundary<Type>> conformedNcBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb
);
//- Extract the original parts of the boundary field and store it
// on the conformal faces
template<class Type>
tmp<SurfaceFieldBoundary<Type>> conformedOrigBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb
);
//- Combine non-conformal and original parts of the boundary field from the
// conformal faces to construct the complete non-conformal boundary field
template<class Type>
tmp<SurfaceFieldBoundary<Type>> unconformedBoundaryField
(
const SurfaceFieldBoundary<Type>& ncFieldb,
const SurfaceFieldBoundary<Type>& origFieldb
);
//- Synchronise the boundary field by combining corresponding
// values across couplings with the given weightings
template<class Type>
tmp<SurfaceFieldBoundary<Type>> synchronisedBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb,
const bool flip,
const scalar ownerWeight,
const scalar neighbourWeight
);
//- Synchronise the boundary field by combining corresponding
// values across couplings with equal weightings
template<class Type>
tmp<SurfaceFieldBoundary<Type>> synchronisedBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb
);
} // End namespace patchToPatchTools
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "fvMeshStitcherToolsTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,444 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2023 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 "fvMeshStitcherTools.H"
#include "surfaceFields.H"
#include "coupledFvPatch.H"
#include "nonConformalBoundary.H"
#include "nonConformalFvPatch.H"
#include "nonConformalErrorFvPatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::fvMeshStitcherTools::fieldMap
(
const Field<Type>& f,
const labelUList& addr,
const label addr0
)
{
tmp<Field<Type>> tresult(new Field<Type>(addr.size()));
forAll(addr, i)
{
tresult.ref()[i] = f[addr[i] - addr0];
}
return tresult;
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::fvMeshStitcherTools::fieldMap
(
const tmp<Field<Type>>& f,
const labelUList& addr,
const label addr0
)
{
tmp<Field<Type>> tresult = fieldMap(f(), addr, addr0);
f.clear();
return tresult;
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::fvMeshStitcherTools::fieldRMapSum
(
const Field<Type>& f,
const label size,
const labelUList& addr,
const label addr0
)
{
tmp<Field<Type>> tresult(new Field<Type>(size, Zero));
forAll(addr, i)
{
tresult.ref()[addr[i] - addr0] += f[i];
}
return tresult;
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::fvMeshStitcherTools::fieldRMapSum
(
const tmp<Field<Type>>& f,
const label size,
const labelUList& addr,
const label addr0
)
{
tmp<Field<Type>> tresult = fieldRMapSum(f(), size, addr, addr0);
f.clear();
return tresult;
}
template<class Type>
Foam::tmp<Foam::fvMeshStitcherTools::SurfaceFieldBoundary<Type>>
Foam::fvMeshStitcherTools::conformedNcBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb
)
{
const bool isFluxField = isFlux(fieldb[0].internalField());
const fvBoundaryMesh& fvbm = fieldb[0].patch().boundaryMesh();
tmp<SurfaceFieldBoundary<Type>> tncFieldb
(
new SurfaceFieldBoundary<Type>
(
SurfaceField<Type>::Internal::null(),
fieldb
)
);
SurfaceFieldBoundary<Type>& ncFieldb = tncFieldb.ref();
ncFieldb == pTraits<Type>::zero;
const surfaceScalarField::Boundary origNcMagSfb
(
surfaceScalarField::Internal::null(),
fvMeshStitcherTools::origNcMagSfb(fvbm.mesh())
);
const labelList origPatchIDs =
nonConformalBoundary::New(fvbm.mesh()).allOrigPatchIDs();
// Accumulate the non-conformal parts of the field into the original faces
forAll(fvbm, ncPatchi)
{
const fvPatch& fvp = fvbm[ncPatchi];
if (!isA<nonConformalFvPatch>(fvp)) continue;
const nonConformalFvPatch& ncFvp =
refCast<const nonConformalFvPatch>(fvbm[ncPatchi]);
const label origPatchi = ncFvp.origPatchID();
const fvPatch& origFvp = ncFvp.origPatch();
const scalarField& ncNcMagSf = ncFvp.patch().magSf();
// Sum properties with an area-weight, unless this is a flux. Fluxes
// already scale with the area.
ncFieldb[origPatchi] +=
fvMeshStitcherTools::fieldRMapSum
(
isFluxField ? fieldb[ncPatchi] : ncNcMagSf*fieldb[ncPatchi],
origFvp.size(),
ncFvp.polyFaces(),
origFvp.start()
);
}
// Scale or average as appropriate
forAll(origPatchIDs, i)
{
const label origPatchi = origPatchIDs[i];
const fvPatch& origFvp = fvbm[origPatchi];
// If this is a flux then scale to the total size of the face
if (isFluxField)
{
const scalarField origTotalMagSf
(
origFvp.magSf() + origNcMagSfb[origPatchi]
);
ncFieldb[origPatchi] *=
origTotalMagSf
/max(origNcMagSfb[origPatchi], small*origTotalMagSf);
}
// If this is not a flux then divide by the area to create an
// area-weighted average
else
{
ncFieldb[origPatchi] /=
max(origNcMagSfb[origPatchi], vSmall);
}
}
return tncFieldb;
}
template<class Type>
Foam::tmp<Foam::fvMeshStitcherTools::SurfaceFieldBoundary<Type>>
Foam::fvMeshStitcherTools::conformedOrigBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb
)
{
const bool isFluxField = isFlux(fieldb[0].internalField());
const fvBoundaryMesh& fvbm = fieldb[0].patch().boundaryMesh();
tmp<SurfaceFieldBoundary<Type>> torigFieldb
(
new SurfaceFieldBoundary<Type>
(
SurfaceField<Type>::Internal::null(),
fieldb
)
);
SurfaceFieldBoundary<Type>& origFieldb = torigFieldb.ref();
const surfaceScalarField::Boundary origNcMagSfb
(
surfaceScalarField::Internal::null(),
fvMeshStitcherTools::origNcMagSfb(fvbm.mesh())
);
const labelList origPatchIDs =
nonConformalBoundary::New(fvbm.mesh()).allOrigPatchIDs();
// Scale or average as appropriate
forAll(origPatchIDs, i)
{
const label origPatchi = origPatchIDs[i];
const fvPatch& origFvp = fvbm[origPatchi];
// If this is a flux then scale to the total size of the face
if (isFluxField)
{
const scalarField origTotalMagSf
(
origFvp.magSf() + origNcMagSfb[origPatchi]
);
origFieldb[origPatchi] *=
origTotalMagSf
/max(origFvp.magSf(), small*origTotalMagSf);
}
}
return torigFieldb;
}
template<class Type>
Foam::tmp<Foam::fvMeshStitcherTools::SurfaceFieldBoundary<Type>>
Foam::fvMeshStitcherTools::unconformedBoundaryField
(
const SurfaceFieldBoundary<Type>& ncFieldb,
const SurfaceFieldBoundary<Type>& origFieldb
)
{
const bool isFluxField = isFlux(origFieldb[0].internalField());
const fvBoundaryMesh& fvbm = origFieldb[0].patch().boundaryMesh();
const surfaceScalarField::Boundary& magSfb =
fvbm.mesh().magSf().boundaryField();
// Initialise the result and copy the original fields
tmp<SurfaceFieldBoundary<Type>> tfieldb
(
new SurfaceFieldBoundary<Type>
(
SurfaceField<Type>::Internal::null(),
origFieldb
)
);
SurfaceFieldBoundary<Type>& fieldb = tfieldb.ref();
// Map the conformed non-conformal values into the non-conformal patch
// fields
forAll(fvbm, ncPatchi)
{
const fvPatch& fvp = fvbm[ncPatchi];
if (!isA<nonConformalFvPatch>(fvp)) continue;
const nonConformalFvPatch& ncFvp =
refCast<const nonConformalFvPatch>(fvp);
const label origPatchi = ncFvp.origPatchID();
const fvPatch& origFvp = ncFvp.origPatch();
fieldb[ncPatchi] =
fvMeshStitcherTools::fieldMap
(
ncFieldb[origPatchi],
ncFvp.polyFaces(),
origFvp.start()
);
}
const labelList origPatchIDs =
nonConformalBoundary::New(fvbm.mesh()).allOrigPatchIDs();
// If a flux then scale down to the part face area
if (isFluxField)
{
const surfaceScalarField::Boundary origNcMagSfb
(
surfaceScalarField::Internal::null(),
fvMeshStitcherTools::origNcMagSfb(fvbm.mesh())
);
// Scale the original patch fields
forAll(origPatchIDs, i)
{
const label origPatchi = origPatchIDs[i];
const scalarField origTotalMagSf
(
magSfb[origPatchi] + origNcMagSfb[origPatchi]
);
fieldb[origPatchi] *= magSfb[origPatchi]/origTotalMagSf;
}
// Scale the non-conformal patch fields
forAll(fvbm, ncPatchi)
{
const fvPatch& fvp = fvbm[ncPatchi];
if (!isA<nonConformalFvPatch>(fvp)) continue;
const nonConformalFvPatch& ncFvp =
refCast<const nonConformalFvPatch>(fvp);
const label origPatchi = ncFvp.origPatchID();
const fvPatch& origFvp = ncFvp.origPatch();
const scalarField ncTotalMagSf
(
fvMeshStitcherTools::fieldMap
(
magSfb[origPatchi] + origNcMagSfb[origPatchi],
ncFvp.polyFaces(),
origFvp.start()
)
);
fieldb[ncPatchi] *= magSfb[ncPatchi]/ncTotalMagSf;
}
}
// Overwrite error values
forAll(fvbm, errorPatchi)
{
const fvPatch& fvp = fvbm[errorPatchi];
if (!isA<nonConformalErrorFvPatch>(fvp)) continue;
const nonConformalErrorFvPatch& errorFvp =
refCast<const nonConformalErrorFvPatch>(fvp);
const label origPatchi = errorFvp.origPatchID();
const fvPatch& origFvp = errorFvp.origPatch();
if (isFluxField)
{
fieldb[errorPatchi] = Zero;
}
else
{
fieldb[errorPatchi] =
fvMeshStitcherTools::fieldMap
(
origFieldb[origPatchi],
errorFvp.polyFaces(),
origFvp.start()
);
}
}
return tfieldb;
}
template<class Type>
Foam::tmp<Foam::fvMeshStitcherTools::SurfaceFieldBoundary<Type>>
Foam::fvMeshStitcherTools::synchronisedBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb,
const bool flip,
const scalar ownerWeight,
const scalar neighbourWeight
)
{
const fvBoundaryMesh& fvbm = fieldb[0].patch().boundaryMesh();
tmp<SurfaceFieldBoundary<Type>> tsyncFieldb
(
new SurfaceFieldBoundary<Type>
(
SurfaceField<Type>::Internal::null(),
fieldb
)
);
SurfaceFieldBoundary<Type>& syncFieldb = tsyncFieldb.ref();
SurfaceFieldBoundary<Type> fieldbNbr
(
SurfaceField<Type>::Internal::null(),
fieldb.boundaryNeighbourField()
);
forAll(fvbm, patchi)
{
const fvPatch& fvp = fvbm[patchi];
if (!fvp.coupled()) continue;
const coupledFvPatch& cFvp = refCast<const coupledFvPatch>(fvp);
const scalar w = cFvp.owner() ? ownerWeight : neighbourWeight;
const scalar v = cFvp.owner() ? neighbourWeight : ownerWeight;
syncFieldb[patchi] =
w*syncFieldb[patchi] + (flip ? -v : +v)*fieldbNbr[patchi];
}
return tsyncFieldb;
}
template<class Type>
Foam::tmp<Foam::fvMeshStitcherTools::SurfaceFieldBoundary<Type>>
Foam::fvMeshStitcherTools::synchronisedBoundaryField
(
const SurfaceFieldBoundary<Type>& fieldb
)
{
const bool isFluxField = isFlux(fieldb[0].internalField());
return synchronisedBoundaryField<Type>
(
fieldb,
isFluxField,
0.5,
0.5
);
}
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2021-2022 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2021-2023 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -55,6 +55,12 @@ Foam::nonConformalFvPatch::~nonConformalFvPatch()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::fvPatch& Foam::nonConformalFvPatch::patch() const
{
return patch_;
}
const Foam::nonConformalPolyPatch&
Foam::nonConformalFvPatch::nonConformalPatch() const
{

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2021-2022 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2021-2023 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -88,7 +88,10 @@ public:
// Access
//- Return the reference to the polyPatch
//- Reference to the fvPatch
const fvPatch& patch() const;
//- Reference to the polyPatch
const nonConformalPolyPatch& nonConformalPatch() const;
//- Original patch name

View File

@ -36,6 +36,7 @@ SourceFiles
#include "meshToMesh.H"
#include "volFields.H"
#include "surfaceFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -52,6 +53,15 @@ class fvMeshToFvMesh
{
private:
// Private Typedefs
//- Alias for surface boundary fields to reduce verbosity of method
// definitions below
template<class Type>
using SurfaceFieldBoundary =
GeometricBoundaryField<Type, fvsPatchField, surfaceMesh>;
// Private Member Functions
//- Evaluate constraint types for the given vol field
@ -118,6 +128,13 @@ public:
const VolInternalField<Type>& srcFld,
const VolInternalField<Type>& leftOverTgtFld
) const;
//- ...
template<class Type>
tmp<SurfaceFieldBoundary<Type>> srcToTgt
(
const SurfaceFieldBoundary<Type>& srcFld
) const;
};

View File

@ -311,4 +311,71 @@ Foam::tmp<Foam::VolInternalField<Type>> Foam::fvMeshToFvMesh::srcToTgt
}
template<class Type>
Foam::tmp<Foam::fvMeshToFvMesh::SurfaceFieldBoundary<Type>>
Foam::fvMeshToFvMesh::srcToTgt
(
const SurfaceFieldBoundary<Type>& srcBfld
) const
{
const fvMesh& tgtMesh = static_cast<const fvMesh&>(meshToMesh::tgtMesh());
// Map all patch fields
PtrList<fvsPatchField<Type>> tgtPatchFields(tgtMesh.boundary().size());
forAll(patchIDs(), i)
{
const label srcPatchi = patchIDs()[i].first();
const label tgtPatchi = patchIDs()[i].second();
if (!tgtPatchFields.set(tgtPatchi))
{
tgtPatchFields.set
(
tgtPatchi,
fvsPatchField<Type>::New
(
srcBfld[srcPatchi],
tgtMesh.boundary()[tgtPatchi],
DimensionedField<Type, surfaceMesh>::null(),
patchToPatchNormalisedFvPatchFieldMapper
(
patchInterpolation(i),
tgtPatchStabilisation(i)
)
)
);
}
}
// Create any patch fields not explicitly mapped; e.g., constraints
forAll(tgtPatchFields, tgtPatchi)
{
if (!tgtPatchFields.set(tgtPatchi))
{
tgtPatchFields.set
(
tgtPatchi,
fvsPatchField<Type>::New
(
calculatedFvPatchField<Type>::typeName,
tgtMesh.boundary()[tgtPatchi],
DimensionedField<Type, surfaceMesh>::null()
)
);
}
}
return
tmp<SurfaceFieldBoundary<Type>>
(
new SurfaceFieldBoundary<Type>
(
tgtMesh.boundary(),
DimensionedField<Type, surfaceMesh>::null(),
tgtPatchFields
)
);
}
// ************************************************************************* //

View File

@ -144,17 +144,15 @@ void Foam::fvMeshStitchers::moving::conformCorrectMeshPhi
const label origPatchi = ncFvp.origPatchID();
const fvPatch& origFvp = ncFvp.origPatch();
const labelList nccOrigPatchFace =
ncFvp.polyFaces() - origFvp.start();
for (label i = 0; i <= phi.nOldTimes(false); ++ i)
{
phi.oldTime(i).boundaryFieldRef()[origPatchi] +=
fieldRMapSum
fvMeshStitcherTools::fieldRMapSum
(
phi.oldTime(i).boundaryField()[nccPatchi],
origFvp.size(),
nccOrigPatchFace
ncFvp.polyFaces(),
origFvp.start()
);
phi.oldTime(i).boundaryFieldRef()[nccPatchi].clear();
@ -388,7 +386,7 @@ void Foam::fvMeshStitchers::moving::unconformInternalFaceCorrectMeshPhi
surfaceScalarField::Boundary syncPhiBf
(
surfaceScalarField::Internal::null(),
synchronisedBoundaryField<scalar>(phiBf, true, 0, 1)
fvMeshStitcherTools::synchronisedBoundaryField(phiBf, true, 0, 1)
);
// Determine the total mesh flux error and area magnitude for each region
@ -863,7 +861,10 @@ void Foam::fvMeshStitchers::moving::unconformErrorFaceCorrectMeshPhi
for (label i = 0; i <= phi.nOldTimes(false); ++ i)
{
tmp<surfaceScalarField::Boundary> tphib =
synchronisedBoundaryField<scalar>(phi.oldTime(i).boundaryField());
fvMeshStitcherTools::synchronisedBoundaryField
(
phi.oldTime(i).boundaryField()
);
phiErrorbs.set
(
@ -967,7 +968,7 @@ void Foam::fvMeshStitchers::moving::unconformErrorFaceCorrectMeshPhi
surfaceScalarField::Boundary meshMagUfb
(
surfaceScalarField::Internal::null(),
conformalNccBoundaryField<scalar>(tnccMeshMagUfb)
fvMeshStitcherTools::conformedNcBoundaryField(tnccMeshMagUfb)
);
tnccMeshMagUf.clear();
@ -1059,14 +1060,32 @@ void Foam::fvMeshStitchers::moving::unconformCorrectMeshPhi
// and this function would only modify its arguments and leave calling
// fvMesh::unconform to the base class.
mesh().unconform(polyFacesBf, SfSf, CfSf);
resizeFieldPatchFields(polyFacesBf, phi);
// Resize the patched in the flux field
for (label i = 0; i <= phi.nOldTimes(false); ++ i)
{
surfaceScalarField::Boundary& phi0Bf =
boundaryFieldRefNoUpdate(phi.oldTime(i));
forAll(polyFacesBf, ncPatchi)
{
if (!isA<nonConformalFvPatch>(polyFacesBf[ncPatchi].patch()))
{
phi0Bf[ncPatchi].map
(
phi0Bf[ncPatchi],
setSizeFvPatchFieldMapper(polyFacesBf[ncPatchi].size())
);
}
}
}
// Set mesh fluxes on the original and cyclic faces as a proportion of
// the area taken from the old original faces
for (label i = 0; i <= phi.nOldTimes(false); ++ i)
{
phi.oldTime(i).boundaryFieldRef() =
nonConformalBoundaryField<scalar>
fvMeshStitcherTools::unconformedBoundaryField
(
phi.oldTime(i).boundaryField(),
phi.oldTime(i).boundaryField()

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2021-2022 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2021-2023 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -137,6 +137,12 @@ Foam::nonConformalPolyPatch::~nonConformalPolyPatch()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::polyPatch& Foam::nonConformalPolyPatch::patch() const
{
return patch_;
}
const Foam::word& Foam::nonConformalPolyPatch::origPatchName() const
{
return origPatchName_;

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2021-2022 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2021-2023 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -121,6 +121,9 @@ public:
// Member Functions
//- Reference to the polyPatch
const polyPatch& patch() const;
//- Original patch name
const word& origPatchName() const;