1342 lines
37 KiB
C
1342 lines
37 KiB
C
/*---------------------------------------------------------------------------*\
|
|
========= |
|
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
\\ / O peration |
|
|
\\ / A nd | Copyright (C) 1991-2005 OpenCFD Ltd.
|
|
\\/ 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 2 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, write to the Free Software Foundation,
|
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
Description
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
|
|
#include "solidInterface.H"
|
|
#include "fvc.H"
|
|
#include "processorFvPatchFields.H"
|
|
#include "fvMatrices.H"
|
|
#include "skewCorrectionVectors.H"
|
|
#include "leastSquaresGrad.H"
|
|
#include "gaussGrad.H"
|
|
#include "faceSet.H"
|
|
#include "faMesh.H"
|
|
#include "faCFD.H"
|
|
#include "zeroGradientFaPatchFields.H"
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
namespace Foam
|
|
{
|
|
|
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
|
|
|
defineTypeNameAndDebug(solidInterface, 0);
|
|
|
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
|
|
|
void solidInterface::makeSubMesh() const
|
|
{
|
|
if (debug)
|
|
{
|
|
Info<< "void solidInterface::makeSubMesh() const : "
|
|
<< "creating sum-mesh near interface"
|
|
<< endl;
|
|
}
|
|
|
|
// It is an error to attempt to recalculate
|
|
// if the pointer is already set
|
|
if (subMeshPtr_)
|
|
{
|
|
FatalErrorIn("solidInterface::makeSubMesh() const")
|
|
<< "sub-mesh already exist"
|
|
<< abort(FatalError);
|
|
}
|
|
|
|
const volScalarField& materials =
|
|
mesh_.lookupObject<volScalarField>("materials");
|
|
|
|
const scalarField& materialsI = materials.internalField();
|
|
|
|
const unallocLabelList& owner = mesh_.owner();
|
|
const unallocLabelList& neighbour = mesh_.neighbour();
|
|
|
|
labelHashSet interfaceCellSet;
|
|
|
|
forAll(neighbour, faceI)
|
|
{
|
|
if
|
|
(
|
|
mag(materialsI[neighbour[faceI]] - materialsI[owner[faceI]])
|
|
> SMALL
|
|
)
|
|
{
|
|
interfaceCellSet.insert(neighbour[faceI]);
|
|
interfaceCellSet.insert(owner[faceI]);
|
|
}
|
|
}
|
|
|
|
labelList firstRowCells(interfaceCellSet.toc());
|
|
|
|
const labelListList& cellCells = mesh_.cellCells();
|
|
|
|
forAll(firstRowCells, cellI)
|
|
{
|
|
const labelList& curCells = cellCells[firstRowCells[cellI]];
|
|
|
|
forAll(curCells, cellI)
|
|
{
|
|
if(!interfaceCellSet.found(curCells[cellI]))
|
|
{
|
|
interfaceCellSet.insert(curCells[cellI]);
|
|
}
|
|
}
|
|
}
|
|
|
|
subMeshPtr_ = new fvMeshSubset
|
|
(
|
|
IOobject
|
|
(
|
|
"interfaceSubMesh",
|
|
mesh_.time().timeName(),
|
|
mesh_,
|
|
IOobject::NO_READ,
|
|
IOobject::NO_WRITE
|
|
),
|
|
mesh_
|
|
);
|
|
|
|
subMeshPtr_->setLargeCellSubset(interfaceCellSet);
|
|
}
|
|
|
|
|
|
void solidInterface::makeGlobalInterFaces() const
|
|
{
|
|
if (debug)
|
|
{
|
|
Info<< "void solidInterface::makeGlobalInterFaces() const : "
|
|
<< "creating global inter-faces addressing near interface"
|
|
<< endl;
|
|
}
|
|
|
|
// It is an error to attempt to recalculate
|
|
// if the pointer is already set
|
|
if (globalInterFacesPtr_)
|
|
{
|
|
FatalErrorIn("solidInterface::makeGlobalInterFaces() const")
|
|
<< "global inter-faces addressing already exist"
|
|
<< abort(FatalError);
|
|
}
|
|
|
|
if (mesh_.foundObject<volScalarField>("materials"))
|
|
{
|
|
const volScalarField& materials =
|
|
mesh_.lookupObject<volScalarField>("materials");
|
|
|
|
const scalarField& materialsI = materials.internalField();
|
|
|
|
const unallocLabelList& owner = mesh_.owner();
|
|
const unallocLabelList& neighbour = mesh_.neighbour();
|
|
|
|
labelHashSet interFacesSet;
|
|
|
|
forAll(neighbour, faceI)
|
|
{
|
|
if
|
|
(
|
|
mag(materialsI[neighbour[faceI]] - materialsI[owner[faceI]])
|
|
> SMALL
|
|
)
|
|
{
|
|
interFacesSet.insert(faceI);
|
|
}
|
|
}
|
|
|
|
globalInterFacesPtr_ = new labelList(interFacesSet.toc());
|
|
|
|
faceSet faMeshSet(mesh_, "faMeshSet", interFacesSet);
|
|
faMeshSet.write();
|
|
}
|
|
else
|
|
{
|
|
globalInterFacesPtr_ = new labelList(0);
|
|
}
|
|
}
|
|
|
|
|
|
void solidInterface::makeLocalInterFaces() const
|
|
{
|
|
if (debug)
|
|
{
|
|
Info<< "void solidInterface::makeLocalInterFaces() const : "
|
|
<< "creating local inter-faces addressing near interface"
|
|
<< endl;
|
|
}
|
|
|
|
// It is an error to attempt to recalculate
|
|
// if the pointer is already set
|
|
if (localInterFacesPtr_)
|
|
{
|
|
FatalErrorIn("solidInterface::makeLocalInterFaces() const")
|
|
<< "local inter-faces addressing already exist"
|
|
<< abort(FatalError);
|
|
}
|
|
|
|
const volScalarField& materials =
|
|
mesh_.lookupObject<volScalarField>("materials");
|
|
|
|
volScalarField subMaterials = subMesh().interpolate(materials);
|
|
|
|
const scalarField& materialsI = subMaterials.internalField();
|
|
|
|
const fvMesh& sMesh = subMesh().subMesh();
|
|
|
|
const unallocLabelList& owner = sMesh.owner();
|
|
const unallocLabelList& neighbour = sMesh.neighbour();
|
|
|
|
labelHashSet interFacesSet;
|
|
|
|
forAll(neighbour, faceI)
|
|
{
|
|
if
|
|
(
|
|
mag(materialsI[neighbour[faceI]] - materialsI[owner[faceI]])
|
|
> SMALL
|
|
)
|
|
{
|
|
interFacesSet.insert(faceI);
|
|
}
|
|
}
|
|
|
|
localInterFacesPtr_ = new labelList(interFacesSet.toc());
|
|
}
|
|
|
|
|
|
void solidInterface::makeInterfaceDisplacement() const
|
|
{
|
|
if (debug)
|
|
{
|
|
Info<< "void solidInterface::makeInterfaceDisplacement() const : "
|
|
<< "creating interface displacement field"
|
|
<< endl;
|
|
}
|
|
|
|
// It is an error to attempt to recalculate
|
|
// if the pointer is already set
|
|
if (interfaceUPtr_)
|
|
{
|
|
FatalErrorIn("solidInterface::makeInterfaceDisplacement() const")
|
|
<< "interface displacement field already exist"
|
|
<< abort(FatalError);
|
|
}
|
|
|
|
interfaceUPtr_ = new vectorField(globalInterFaces().size(), vector::zero);
|
|
}
|
|
|
|
|
|
void solidInterface::makeProcessorPatches() const
|
|
{
|
|
if (debug)
|
|
{
|
|
Info<< "void solidInterface::makeProcessorPatches() const : "
|
|
<< "creating list of processor patches at the interface"
|
|
<< endl;
|
|
}
|
|
|
|
// It is an error to attempt to recalculate
|
|
// if the pointer is already set
|
|
if (processorPatchesPtr_)
|
|
{
|
|
FatalErrorIn("solidInterface::makeProcessorPatches() const")
|
|
<< "list of processor patches already exist"
|
|
<< abort(FatalError);
|
|
}
|
|
|
|
if (mesh_.foundObject<volScalarField>("materials"))
|
|
{
|
|
const volScalarField& materials =
|
|
mesh_.lookupObject<volScalarField>("materials");
|
|
|
|
labelHashSet processorPatches;
|
|
|
|
forAll(materials.boundaryField(), patchI)
|
|
{
|
|
if (mesh_.boundary()[patchI].type() == processorFvPatch::typeName)
|
|
{
|
|
scalarField ownMat =
|
|
materials.boundaryField()[patchI].patchInternalField();
|
|
|
|
scalarField ngbMat =
|
|
materials.boundaryField()[patchI].patchNeighbourField();
|
|
|
|
forAll(ownMat, faceI)
|
|
{
|
|
if (mag(ownMat[faceI] - ngbMat[faceI]) > SMALL)
|
|
{
|
|
processorPatches.insert(patchI);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
processorPatchesPtr_ = new labelList(processorPatches.toc());
|
|
}
|
|
else
|
|
{
|
|
processorPatchesPtr_ = new labelList(0);
|
|
}
|
|
}
|
|
|
|
|
|
void solidInterface::makeProcessorPatchFaces() const
|
|
{
|
|
if (debug)
|
|
{
|
|
Info<< "void solidInterface::makeProcessorPatchFaces() const : "
|
|
<< "creating list of processor patch faces at the interface"
|
|
<< endl;
|
|
}
|
|
|
|
// It is an error to attempt to recalculate
|
|
// if the pointer is already set
|
|
if (processorPatchFacesPtr_)
|
|
{
|
|
FatalErrorIn("solidInterface::makeProcessorPatchFaces() const")
|
|
<< "list of processor patch faces already exist"
|
|
<< abort(FatalError);
|
|
}
|
|
|
|
const labelList& procPatches = processorPatches();
|
|
|
|
processorPatchFacesPtr_ = new labelListList(procPatches.size());
|
|
labelListList& processorPatchFaces = *processorPatchFacesPtr_;
|
|
|
|
forAll(procPatches, patchI)
|
|
{
|
|
const volScalarField& materials =
|
|
mesh_.lookupObject<volScalarField>("materials");
|
|
|
|
label curProcPatch = procPatches[patchI];
|
|
|
|
scalarField ownMat =
|
|
materials.boundaryField()[curProcPatch].patchInternalField();
|
|
|
|
scalarField ngbMat =
|
|
materials.boundaryField()[curProcPatch].patchNeighbourField();
|
|
|
|
labelHashSet curProcPatchFaces;
|
|
|
|
forAll(ownMat, faceI)
|
|
{
|
|
if (mag(ownMat[faceI] - ngbMat[faceI]) > SMALL)
|
|
{
|
|
curProcPatchFaces.insert(faceI);
|
|
}
|
|
}
|
|
|
|
processorPatchFaces[patchI] = labelList(curProcPatchFaces.toc());
|
|
}
|
|
}
|
|
|
|
|
|
void solidInterface::makeProcessorInterfaceDisplacement() const
|
|
{
|
|
if (debug)
|
|
{
|
|
Info<< "void solidInterface::makeProcessorInterfaceDisplacement() const : "
|
|
<< "creating processor inter-faces displacement"
|
|
<< endl;
|
|
}
|
|
|
|
// It is an error to attempt to recalculate
|
|
// if the pointer is already set
|
|
if (processorInterfaceUPtr_)
|
|
{
|
|
FatalErrorIn("solidInterface::makeProcessorInterfaceDisplacement() const")
|
|
<< "processor interface displacement already exist"
|
|
<< abort(FatalError);
|
|
}
|
|
|
|
processorInterfaceUPtr_ =
|
|
new FieldField<Field, vector>(processorPatches().size());
|
|
FieldField<Field, vector>& processorInterfaceU = *processorInterfaceUPtr_;
|
|
|
|
forAll(processorInterfaceU, patchI)
|
|
{
|
|
processorInterfaceU.set
|
|
(
|
|
patchI,
|
|
new vectorField(processorPatchFaces()[patchI].size(), vector::zero)
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
void solidInterface::makeIndicator() const
|
|
{
|
|
if (debug)
|
|
{
|
|
Info<< "void solidInterface::makeIndicator() const : "
|
|
<< "creating interface indicator"
|
|
<< endl;
|
|
}
|
|
|
|
// It is an error to attempt to recalculate
|
|
// if the pointer is already set
|
|
if (indicatorPtr_)
|
|
{
|
|
FatalErrorIn("solidInterface::makeIndicator() const")
|
|
<< "interface indicator already exist"
|
|
<< abort(FatalError);
|
|
}
|
|
|
|
indicatorPtr_ =
|
|
new List<labelPair>(globalInterFaces().size(), labelPair(0, 0));
|
|
|
|
List<labelPair>& indicator = *indicatorPtr_;
|
|
|
|
const unallocLabelList& owner = mesh_.owner();
|
|
const unallocLabelList& neighbour = mesh_.neighbour();
|
|
|
|
if (mesh_.foundObject<volScalarField>("materials"))
|
|
{
|
|
const volScalarField& materials =
|
|
mesh_.lookupObject<volScalarField>("materials");
|
|
|
|
forAll(globalInterFaces(), faceI)
|
|
{
|
|
label curFace = globalInterFaces()[faceI];
|
|
|
|
labelPair& curPair = indicator[faceI];
|
|
|
|
if (materials[owner[curFace]] < materials[neighbour[curFace]])
|
|
{
|
|
curPair.first() = int(materials[owner[curFace]]);
|
|
curPair.second() = int(materials[neighbour[curFace]]);
|
|
}
|
|
else
|
|
{
|
|
curPair.second() = int(materials[owner[curFace]]);
|
|
curPair.first() = int(materials[neighbour[curFace]]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Info << indicator << endl;
|
|
}
|
|
|
|
|
|
void solidInterface::clearOut()
|
|
{
|
|
deleteDemandDrivenData(subMeshPtr_);
|
|
deleteDemandDrivenData(globalInterFacesPtr_);
|
|
deleteDemandDrivenData(localInterFacesPtr_);
|
|
deleteDemandDrivenData(interfaceUPtr_);
|
|
deleteDemandDrivenData(muPtr_);
|
|
deleteDemandDrivenData(lambdaPtr_);
|
|
deleteDemandDrivenData(processorPatchesPtr_);
|
|
deleteDemandDrivenData(processorPatchFacesPtr_);
|
|
deleteDemandDrivenData(processorInterfaceUPtr_);
|
|
deleteDemandDrivenData(indicatorPtr_);
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
|
|
|
|
solidInterface::solidInterface
|
|
(
|
|
const fvMesh& mesh,
|
|
const rheologyModel& rheology
|
|
)
|
|
:
|
|
mesh_(mesh),
|
|
rheology_(rheology),
|
|
subMeshPtr_(NULL),
|
|
globalInterFacesPtr_(NULL),
|
|
localInterFacesPtr_(NULL),
|
|
interfaceUPtr_(NULL),
|
|
muPtr_(NULL),
|
|
lambdaPtr_(NULL),
|
|
processorPatchesPtr_(NULL),
|
|
processorPatchFacesPtr_(NULL),
|
|
processorInterfaceUPtr_(NULL),
|
|
indicatorPtr_(NULL)
|
|
{
|
|
muPtr_ = new volScalarField(rheology_.mu());
|
|
lambdaPtr_ = new volScalarField(rheology_.lambda());
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * * //
|
|
|
|
solidInterface::~solidInterface()
|
|
{
|
|
clearOut();
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
|
|
|
|
|
const fvMeshSubset& solidInterface::subMesh() const
|
|
{
|
|
if (!subMeshPtr_)
|
|
{
|
|
makeSubMesh();
|
|
}
|
|
|
|
return *subMeshPtr_;
|
|
}
|
|
|
|
|
|
const labelList& solidInterface::globalInterFaces() const
|
|
{
|
|
if (!globalInterFacesPtr_)
|
|
{
|
|
makeGlobalInterFaces();
|
|
}
|
|
|
|
return *globalInterFacesPtr_;
|
|
}
|
|
|
|
|
|
const labelList& solidInterface::localInterFaces() const
|
|
{
|
|
if (!localInterFacesPtr_)
|
|
{
|
|
makeLocalInterFaces();
|
|
}
|
|
|
|
return *localInterFacesPtr_;
|
|
}
|
|
|
|
|
|
vectorField& solidInterface::interfaceDisplacement()
|
|
{
|
|
if (!interfaceUPtr_)
|
|
{
|
|
makeInterfaceDisplacement();
|
|
}
|
|
|
|
return *interfaceUPtr_;
|
|
}
|
|
|
|
|
|
const vectorField& solidInterface::interfaceDisplacement() const
|
|
{
|
|
if (!interfaceUPtr_)
|
|
{
|
|
makeInterfaceDisplacement();
|
|
}
|
|
|
|
return *interfaceUPtr_;
|
|
}
|
|
|
|
|
|
const labelList& solidInterface::processorPatches() const
|
|
{
|
|
if (!processorPatchesPtr_)
|
|
{
|
|
makeProcessorPatches();
|
|
}
|
|
|
|
return *processorPatchesPtr_;
|
|
}
|
|
|
|
|
|
const labelListList& solidInterface::processorPatchFaces() const
|
|
{
|
|
if (!processorPatchFacesPtr_)
|
|
{
|
|
makeProcessorPatchFaces();
|
|
}
|
|
|
|
return *processorPatchFacesPtr_;
|
|
}
|
|
|
|
|
|
const FieldField<Field, vector>& solidInterface
|
|
::processorInterfaceDisplacement() const
|
|
{
|
|
if (!processorInterfaceUPtr_)
|
|
{
|
|
makeProcessorInterfaceDisplacement();
|
|
}
|
|
|
|
return *processorInterfaceUPtr_;
|
|
}
|
|
|
|
|
|
FieldField<Field, vector>& solidInterface::processorInterfaceDisplacement()
|
|
{
|
|
if (!processorInterfaceUPtr_)
|
|
{
|
|
makeProcessorInterfaceDisplacement();
|
|
}
|
|
|
|
return *processorInterfaceUPtr_;
|
|
}
|
|
|
|
|
|
void solidInterface::correct(fvVectorMatrix& UEqn)
|
|
{
|
|
const unallocLabelList& owner = mesh_.owner();
|
|
const unallocLabelList& neighbour = mesh_.neighbour();
|
|
|
|
const volVectorField& U = UEqn.psi();
|
|
const vectorField& UI = U.internalField();
|
|
|
|
const volTensorField& gradU =
|
|
mesh_.lookupObject<volTensorField>("grad(" + U.name() + ')');
|
|
const tensorField& gradUI = gradU.internalField();
|
|
|
|
const volScalarField& mu = *muPtr_;
|
|
const volScalarField& lambda = *lambdaPtr_;
|
|
|
|
const vectorField& SI = mesh_.Sf().internalField();
|
|
const scalarField& magSI = mesh_.magSf().internalField();
|
|
const scalarField& deltaCoeffs = mesh_.deltaCoeffs().internalField();
|
|
const scalarField& w = mesh_.weights().internalField();
|
|
|
|
scalarField& diag = UEqn.diag();
|
|
scalarField& upper = UEqn.upper();
|
|
vectorField& source = UEqn.source();
|
|
FieldField<Field, vector>& boundaryCoeffs = UEqn.boundaryCoeffs();
|
|
|
|
vectorField& interU = interfaceDisplacement();
|
|
|
|
|
|
// // Calc surface gradient using FAM
|
|
// tensorField interSGradU(interU.size(), tensor::zero);
|
|
// {
|
|
// faMesh aMesh(mesh_);
|
|
|
|
// const labelList& faceLabels = aMesh.faceLabels();
|
|
|
|
// wordList patchFieldTypes
|
|
// (
|
|
// aMesh.boundary().size(),
|
|
// zeroGradientFaPatchVectorField::typeName
|
|
// );
|
|
|
|
// areaVectorField Us
|
|
// (
|
|
// IOobject
|
|
// (
|
|
// "Us",
|
|
// mesh_.time().timeName(),
|
|
// mesh_,
|
|
// IOobject::NO_READ,
|
|
// IOobject::AUTO_WRITE
|
|
// ),
|
|
// aMesh,
|
|
// dimensioned<vector>("Us", dimLength, vector::zero),
|
|
// patchFieldTypes
|
|
// );
|
|
|
|
// forAll(globalInterFaces(), faceI)
|
|
// {
|
|
// label curFace = globalInterFaces()[faceI];
|
|
// label index = findIndex(faceLabels, curFace);
|
|
|
|
// Us.internalField()[index] = interU[faceI];
|
|
// }
|
|
// Us.correctBoundaryConditions();
|
|
|
|
// tensorField sGradU = fac::grad(Us)().internalField();
|
|
// forAll(globalInterFaces(), faceI)
|
|
// {
|
|
// label curFace = globalInterFaces()[faceI];
|
|
// label index = findIndex(faceLabels, curFace);
|
|
|
|
// interSGradU[faceI] = sGradU[index];
|
|
// }
|
|
// }
|
|
|
|
// Internal faces
|
|
forAll(globalInterFaces(), faceI)
|
|
{
|
|
label curGlobalFace = globalInterFaces()[faceI];
|
|
|
|
label curOwner = owner[curGlobalFace];
|
|
label curNeighbour = neighbour[curGlobalFace];
|
|
|
|
vector ownN = SI[curGlobalFace]/magSI[curGlobalFace];
|
|
vector ngbN = -ownN;
|
|
|
|
scalar magS = magSI[curGlobalFace];
|
|
|
|
tensor ownSGradU = ((I-ownN*ownN)&gradUI[curOwner]);
|
|
tensor ngbSGradU = ((I-ngbN*ngbN)&gradUI[curNeighbour]);
|
|
|
|
// ownSGradU = interSGradU[faceI];
|
|
// ngbSGradU = interSGradU[faceI];
|
|
|
|
scalar ownTrSGradUt = tr(ownSGradU&(I-ownN*ownN));
|
|
scalar ngbTrSGradUt = tr(ngbSGradU&(I-ownN*ownN));
|
|
|
|
// ownTrSGradUt = 0.5*(ownTrSGradUt + ngbTrSGradUt);
|
|
// ngbTrSGradUt = ownTrSGradUt;
|
|
|
|
vector ownSGradUn = (ownSGradU&ownN);
|
|
vector ngbSGradUn = (ngbSGradU&ownN);
|
|
|
|
// ownSGradUn = 0.5*(ownSGradUn + ngbSGradUn);
|
|
// ngbSGradUn = ownSGradUn;
|
|
|
|
scalar ngbDn = w[curGlobalFace]*(1.0/deltaCoeffs[curGlobalFace]);
|
|
scalar ownDn = (1.0/deltaCoeffs[curGlobalFace]) - ngbDn;
|
|
|
|
scalar ownMu = mu.internalField()[curOwner];
|
|
scalar ngbMu = mu.internalField()[curNeighbour];
|
|
|
|
scalar ownLambda = lambda.internalField()[curOwner];
|
|
scalar ngbLambda = lambda.internalField()[curNeighbour];
|
|
|
|
vector ownUt = ((I-ownN*ownN)&UI[curOwner]);
|
|
vector ngbUt = ((I-ngbN*ngbN)&UI[curNeighbour]);
|
|
|
|
vector ownUn = ownN*(ownN&UI[curOwner]);
|
|
vector ngbUn = ngbN*(ngbN&UI[curNeighbour]);
|
|
|
|
|
|
// Interface displacement
|
|
|
|
vector curInterUt =
|
|
(
|
|
ownMu*ownUt*ngbDn + ngbMu*ngbUt*ownDn
|
|
+ ownDn*ngbDn*(ngbMu*ngbSGradUn - ownMu*ownSGradUn)
|
|
)
|
|
/(ownMu*ngbDn + ngbMu*ownDn);
|
|
|
|
vector curInterUn =
|
|
(
|
|
(2*ownMu + ownLambda)*ownUn*ngbDn
|
|
+ (2*ngbMu + ngbLambda)*ngbUn*ownDn
|
|
+ ownDn*ngbDn
|
|
*(ngbLambda*ngbTrSGradUt - ownLambda*ownTrSGradUt)*ownN
|
|
)
|
|
/((2*ownMu + ownLambda)*ngbDn + (2*ngbMu + ngbLambda)*ownDn);
|
|
|
|
interU[faceI] = curInterUn + curInterUt;
|
|
|
|
|
|
// Implicit coupling
|
|
|
|
scalar wRevLin = 1.0 - w[curGlobalFace];
|
|
|
|
scalar ownK = (2*ownMu + ownLambda);
|
|
scalar ngbK = (2*ngbMu + ngbLambda);
|
|
|
|
scalar Kf = 1.0/(wRevLin/ownK + (1.0-wRevLin)/ngbK);
|
|
scalar muf = 1.0/(wRevLin/ownMu + (1.0-wRevLin)/ngbMu);
|
|
|
|
scalar Dnf = 1.0/deltaCoeffs[curGlobalFace];
|
|
|
|
// Owner
|
|
diag[curOwner] += Kf*magS/Dnf;
|
|
|
|
upper[curGlobalFace] -= Kf*magS/Dnf;
|
|
|
|
source[curOwner] +=
|
|
- (Kf - muf)
|
|
*((UI[curNeighbour] - UI[curOwner])&(I-ownN*ownN))*magS/Dnf;
|
|
|
|
source[curOwner] +=
|
|
(
|
|
ownK*ngbDn*ngbLambda*ngbTrSGradUt
|
|
+ ngbK*ownDn*ownLambda*ownTrSGradUt
|
|
)*ownN*magS
|
|
/(ownK*ngbDn + ngbK*ownDn)
|
|
+ (
|
|
ownMu*ngbMu*ngbDn*ngbSGradUn
|
|
+ ownMu*ngbMu*ownDn*ownSGradUn
|
|
)*magS
|
|
/(ownMu*ngbDn + ngbMu*ownDn);
|
|
|
|
// Neighbour
|
|
diag[curNeighbour] += Kf*magS/Dnf;
|
|
|
|
source[curNeighbour] -=
|
|
- (Kf - muf)
|
|
*((UI[curNeighbour] - UI[curOwner])&(I-ownN*ownN))*magS/Dnf;
|
|
|
|
source[curNeighbour] -=
|
|
(
|
|
ownK*ngbDn*ngbLambda*ngbTrSGradUt
|
|
+ ngbK*ownDn*ownLambda*ownTrSGradUt
|
|
)*ownN*magS
|
|
/(ownK*ngbDn + ngbK*ownDn)
|
|
+ (
|
|
ownMu*ngbMu*ngbDn*ngbSGradUn
|
|
+ ownMu*ngbMu*ownDn*ownSGradUn
|
|
)*magS
|
|
/(ownMu*ngbDn + ngbMu*ownDn);
|
|
}
|
|
|
|
|
|
|
|
// Processor faces
|
|
|
|
forAll(processorPatchFaces(), patchI)
|
|
{
|
|
label curPatch = processorPatches()[patchI];
|
|
|
|
vectorField& curProcInterU =
|
|
processorInterfaceDisplacement()[patchI];
|
|
|
|
const vectorField curProcOwnU =
|
|
U.boundaryField()[curPatch].patchInternalField();
|
|
const vectorField curProcNgbU =
|
|
U.boundaryField()[curPatch].patchNeighbourField();
|
|
|
|
const tensorField curProcOwnGradU =
|
|
gradU.boundaryField()[curPatch].patchInternalField();
|
|
const tensorField curProcNgbGradU =
|
|
gradU.boundaryField()[curPatch].patchNeighbourField();
|
|
|
|
const vectorField& curProcS =
|
|
mesh_.Sf().boundaryField()[curPatch];
|
|
const scalarField& curProcMagS =
|
|
mesh_.magSf().boundaryField()[curPatch];
|
|
const scalarField& curProcDeltaCoeffs =
|
|
mesh_.deltaCoeffs().boundaryField()[curPatch];
|
|
const scalarField& curProcW =
|
|
mesh_.weights().boundaryField()[curPatch];
|
|
|
|
const scalarField curProcOwnMu =
|
|
mu.boundaryField()[curPatch].patchInternalField();
|
|
const scalarField curProcNgbMu =
|
|
mu.boundaryField()[curPatch].patchNeighbourField();
|
|
|
|
const scalarField curProcOwnLambda =
|
|
lambda.boundaryField()[curPatch].patchInternalField();
|
|
const scalarField curProcNgbLambda =
|
|
lambda.boundaryField()[curPatch].patchNeighbourField();
|
|
|
|
const unallocLabelList& curProcFaceCells =
|
|
mesh_.boundary()[curPatch].faceCells();
|
|
|
|
forAll(processorPatchFaces()[patchI], faceI)
|
|
{
|
|
label curFace = processorPatchFaces()[patchI][faceI];
|
|
|
|
scalar ngbDn = curProcW[curFace]*(1.0/curProcDeltaCoeffs[curFace]);
|
|
scalar ownDn = (1.0/curProcDeltaCoeffs[curFace]) - ngbDn;
|
|
|
|
scalar magS = curProcMagS[curFace];
|
|
|
|
scalar ownMu = curProcOwnMu[curFace];
|
|
scalar ngbMu = curProcNgbMu[curFace];
|
|
|
|
scalar ownLambda = curProcOwnLambda[curFace];
|
|
scalar ngbLambda = curProcNgbLambda[curFace];
|
|
|
|
vector ownN = curProcS[curFace]/curProcMagS[curFace];
|
|
vector ngbN = -ownN;
|
|
|
|
vector ownUt = ((I-ownN*ownN)&curProcOwnU[curFace]);
|
|
vector ngbUt = ((I-ngbN*ngbN)&curProcNgbU[curFace]);
|
|
|
|
vector ownUn = ownN*(ownN&curProcOwnU[curFace]);
|
|
vector ngbUn = ngbN*(ngbN&curProcNgbU[curFace]);
|
|
|
|
tensor ownSGradU = ((I-ownN*ownN)&curProcOwnGradU[curFace]);
|
|
tensor ngbSGradU = ((I-ngbN*ngbN)&curProcNgbGradU[curFace]);
|
|
|
|
scalar ownTrSGradUt = tr(ownSGradU&(I-ownN*ownN));
|
|
scalar ngbTrSGradUt = tr(ngbSGradU&(I-ngbN*ngbN));
|
|
|
|
vector ownSGradUn = (ownSGradU&ownN);
|
|
vector ngbSGradUn = (ngbSGradU&ngbN);
|
|
|
|
|
|
// Interface displacement
|
|
|
|
vector curInterUt =
|
|
(
|
|
ownMu*ownUt/ownDn + ngbMu*ngbUt/ngbDn
|
|
- (ngbMu*ngbSGradUn + ownMu*ownSGradUn)
|
|
)
|
|
/(ownMu/ownDn + ngbMu/ngbDn);
|
|
|
|
vector curInterUn =
|
|
(
|
|
(2*ownMu + ownLambda)*ownUn/ownDn
|
|
+ (2*ngbMu + ngbLambda)*ngbUn/ngbDn
|
|
+ (ngbLambda*ngbTrSGradUt - ownLambda*ownTrSGradUt)*ownN
|
|
)
|
|
/((2*ownMu + ownLambda)/ownDn + (2*ngbMu + ngbLambda)/ngbDn);
|
|
|
|
curProcInterU[faceI] = curInterUn + curInterUt;
|
|
|
|
|
|
// Implicit coupling
|
|
|
|
scalar wRevLin = 1.0 - curProcW[curFace];
|
|
|
|
scalar ownK = (2*ownMu + ownLambda);
|
|
scalar ngbK = (2*ngbMu + ngbLambda);
|
|
|
|
scalar Kf = 1.0/(wRevLin/ownK + (1.0-wRevLin)/ngbK);
|
|
scalar muf = 1.0/(wRevLin/ownMu + (1.0-wRevLin)/ngbMu);
|
|
|
|
scalar Dnf = 1.0/curProcDeltaCoeffs[curFace];
|
|
|
|
// Owner
|
|
diag[curProcFaceCells[curFace]] += Kf*magS/Dnf;
|
|
|
|
|
|
boundaryCoeffs[curPatch][curFace] += Kf*magS*vector::one/Dnf;
|
|
// upper[curGlobalFace] -= Kf*magS/Dnf;
|
|
|
|
source[curProcFaceCells[curFace]] +=
|
|
- (Kf - muf)*((ngbUt - ownUt)&(I-ownN*ownN))*magS/Dnf
|
|
+ ownLambda*ownTrSGradUt*ownN*magS
|
|
+ ownMu*ownSGradUn*magS;
|
|
|
|
source[curProcFaceCells[curFace]] +=
|
|
(ownK*ngbDn/(ownK*ngbDn + ngbK*ownDn))
|
|
*(ngbLambda*ngbTrSGradUt - ownLambda*ownTrSGradUt)*ownN*magS
|
|
- (ownMu*ngbDn/(ownMu*ngbDn + ngbMu*ownDn))
|
|
*(ngbMu*ngbSGradUn + ownMu*ownSGradUn)*magS;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void solidInterface::modifyProperties
|
|
(
|
|
surfaceScalarField& muf,
|
|
surfaceScalarField& lambdaf
|
|
) const
|
|
{
|
|
forAll(globalInterFaces(), faceI)
|
|
{
|
|
label curGlobalFace = globalInterFaces()[faceI];
|
|
|
|
muf.internalField()[curGlobalFace] = 0;
|
|
lambdaf.internalField()[curGlobalFace] = 0;
|
|
}
|
|
|
|
forAll(processorPatchFaces(), patchI)
|
|
{
|
|
label curPatch = processorPatches()[patchI];
|
|
|
|
forAll(processorPatchFaces()[patchI], faceI)
|
|
{
|
|
label curFace = processorPatchFaces()[patchI][faceI];
|
|
|
|
muf.boundaryField()[curPatch][curFace] = 0;
|
|
lambdaf.boundaryField()[curPatch][curFace] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
tmp<volTensorField> solidInterface::grad(volVectorField& U) const
|
|
{
|
|
tmp<volTensorField> tGradU
|
|
(
|
|
new volTensorField
|
|
(
|
|
IOobject
|
|
(
|
|
"grad(" + U.name() + ')',
|
|
mesh_.time().timeName(),
|
|
mesh_,
|
|
IOobject::NO_READ,
|
|
IOobject::NO_WRITE
|
|
),
|
|
mesh_,
|
|
dimensionedTensor("zero", dimless, tensor::zero)
|
|
)
|
|
);
|
|
volTensorField& gradU = tGradU();
|
|
|
|
surfaceVectorField Uf = fvc::interpolate(U);
|
|
|
|
|
|
// Skew-correction
|
|
|
|
if (skewCorrectionVectors::New(this->mesh_).skew())
|
|
{
|
|
const skewCorrectionVectors& scv = skewCorrectionVectors::New(mesh_);
|
|
|
|
const volTensorField& gradU =
|
|
mesh_.lookupObject<volTensorField>("grad(" + U.name() + ')');
|
|
|
|
Uf +=
|
|
(
|
|
scv()
|
|
& linear<tensor>(mesh_).interpolate
|
|
(
|
|
gradU
|
|
)
|
|
);
|
|
|
|
// Uf +=
|
|
// (
|
|
// scv()
|
|
// & linear<tensor>(mesh_).interpolate
|
|
// (
|
|
// fv::leastSquaresGrad<vector>(mesh_).grad(U)
|
|
// )
|
|
// );
|
|
}
|
|
|
|
|
|
// Interface correction
|
|
|
|
const vectorField& interU = interfaceDisplacement();
|
|
|
|
forAll(globalInterFaces(), faceI)
|
|
{
|
|
label curGlobalFace = globalInterFaces()[faceI];
|
|
|
|
Uf.internalField()[curGlobalFace] = interU[faceI];
|
|
}
|
|
|
|
forAll(processorPatchFaces(), patchI)
|
|
{
|
|
label curPatch = processorPatches()[patchI];
|
|
|
|
const vectorField& curProcInterU =
|
|
processorInterfaceDisplacement()[patchI];
|
|
|
|
forAll(processorPatchFaces()[patchI], faceI)
|
|
{
|
|
label curFace = processorPatchFaces()[patchI][faceI];
|
|
|
|
Uf.boundaryField()[curPatch][curFace] = curProcInterU[faceI];
|
|
}
|
|
}
|
|
|
|
|
|
// Gradient calculation using Gauss method
|
|
|
|
gradU = fv::gaussGrad<vector>(mesh_).grad(Uf);
|
|
fv::gaussGrad<vector>(mesh_).correctBoundaryConditions(U, gradU);
|
|
|
|
|
|
return tGradU;
|
|
}
|
|
|
|
|
|
tmp<symmTensorField> solidInterface::sigmaA() const
|
|
{
|
|
const unallocLabelList& owner = mesh_.owner();
|
|
const unallocLabelList& neighbour = mesh_.neighbour();
|
|
|
|
const volVectorField& U =
|
|
mesh_.lookupObject<volVectorField>("U");
|
|
const vectorField& UI = U.internalField();
|
|
|
|
const volTensorField& gradU =
|
|
mesh_.lookupObject<volTensorField>("grad(" + U.name() + ')');
|
|
const tensorField& gradUI = gradU.internalField();
|
|
|
|
const volScalarField& mu = *muPtr_;
|
|
const volScalarField& lambda = *lambdaPtr_;
|
|
|
|
const vectorField& interU = interfaceDisplacement();
|
|
|
|
const vectorField& SI = mesh_.Sf().internalField();
|
|
const scalarField& magSI = mesh_.magSf().internalField();
|
|
const scalarField& deltaCoeffs = mesh_.deltaCoeffs().internalField();
|
|
const scalarField& w = mesh_.weights().internalField();
|
|
|
|
tmp<symmTensorField> tSigmaA
|
|
(
|
|
new symmTensorField(globalInterFaces().size(), symmTensor::zero)
|
|
);
|
|
symmTensorField& sigmaA = tSigmaA();
|
|
|
|
if (mesh_.foundObject<volScalarField>("materials"))
|
|
{
|
|
const volScalarField& materials =
|
|
mesh_.lookupObject<volScalarField>("materials");
|
|
|
|
tensorField gradUA(sigmaA.size(), tensor::zero);
|
|
scalarField muA(sigmaA.size(), 0);
|
|
scalarField lambdaA(sigmaA.size(), 0);
|
|
|
|
// // Calc surface gradient using FAM
|
|
// tensorField interSGradU(interU.size(), tensor::zero);
|
|
// {
|
|
// faMesh aMesh(mesh_);
|
|
|
|
// const labelList& faceLabels = aMesh.faceLabels();
|
|
|
|
// wordList patchFieldTypes
|
|
// (
|
|
// aMesh.boundary().size(),
|
|
// zeroGradientFaPatchVectorField::typeName
|
|
// );
|
|
|
|
// areaVectorField Us
|
|
// (
|
|
// IOobject
|
|
// (
|
|
// "Us",
|
|
// mesh_.time().timeName(),
|
|
// mesh_,
|
|
// IOobject::NO_READ,
|
|
// IOobject::AUTO_WRITE
|
|
// ),
|
|
// aMesh,
|
|
// dimensioned<vector>("Us", dimLength, vector::zero),
|
|
// patchFieldTypes
|
|
// );
|
|
|
|
// forAll(globalInterFaces(), faceI)
|
|
// {
|
|
// label curFace = globalInterFaces()[faceI];
|
|
// label index = findIndex(faceLabels, curFace);
|
|
|
|
// Us.internalField()[index] = interU[faceI];
|
|
// }
|
|
// Us.correctBoundaryConditions();
|
|
|
|
// tensorField sGradU = fac::grad(Us)().internalField();
|
|
// forAll(globalInterFaces(), faceI)
|
|
// {
|
|
// label curFace = globalInterFaces()[faceI];
|
|
// label index = findIndex(faceLabels, curFace);
|
|
|
|
// interSGradU[faceI] = sGradU[index];
|
|
// }
|
|
// }
|
|
|
|
forAll(globalInterFaces(), faceI)
|
|
{
|
|
label curFace = globalInterFaces()[faceI];
|
|
|
|
scalar ngbDn = w[curFace]*(1.0/deltaCoeffs[curFace]);
|
|
scalar ownDn = (1.0/deltaCoeffs[curFace]) - ngbDn;
|
|
|
|
label curCell = owner[curFace];
|
|
vector n = SI[curFace]/magSI[curFace];
|
|
scalar dn = ownDn;
|
|
|
|
if (materials[owner[curFace]] < materials[neighbour[curFace]])
|
|
{
|
|
curCell = neighbour[curFace];
|
|
n *= -1;
|
|
dn = ngbDn;
|
|
}
|
|
|
|
muA[faceI] = mu[curCell];
|
|
lambdaA[faceI] = lambda[curCell];
|
|
|
|
gradUA[faceI] = n*(interU[faceI] - UI[curCell])/dn;
|
|
|
|
gradUA[faceI] += ((I-n*n)&gradUI[curCell]);
|
|
// gradUA[faceI] += interSGradU[faceI];
|
|
}
|
|
|
|
sigmaA = 2*muA*symm(gradUA) + lambdaA*(I*tr(gradUA));
|
|
}
|
|
|
|
return tSigmaA;
|
|
}
|
|
|
|
|
|
tmp<symmTensorField> solidInterface::sigmaB() const
|
|
{
|
|
const unallocLabelList& owner = mesh_.owner();
|
|
const unallocLabelList& neighbour = mesh_.neighbour();
|
|
|
|
const volVectorField& U =
|
|
mesh_.lookupObject<volVectorField>("U");
|
|
const vectorField& UI = U.internalField();
|
|
|
|
const volTensorField& gradU =
|
|
mesh_.lookupObject<volTensorField>("grad(" + U.name() + ')');
|
|
const tensorField& gradUI = gradU.internalField();
|
|
|
|
const volScalarField& mu = *muPtr_;
|
|
const volScalarField& lambda = *lambdaPtr_;
|
|
|
|
const vectorField& interU = interfaceDisplacement();
|
|
|
|
const vectorField& SI = mesh_.Sf().internalField();
|
|
const scalarField& magSI = mesh_.magSf().internalField();
|
|
const scalarField& deltaCoeffs = mesh_.deltaCoeffs().internalField();
|
|
const scalarField& w = mesh_.weights().internalField();
|
|
|
|
tmp<symmTensorField> tSigmaB
|
|
(
|
|
new symmTensorField(globalInterFaces().size(), symmTensor::zero)
|
|
);
|
|
symmTensorField& sigmaB = tSigmaB();
|
|
|
|
if (mesh_.foundObject<volScalarField>("materials"))
|
|
{
|
|
const volScalarField& materials =
|
|
mesh_.lookupObject<volScalarField>("materials");
|
|
|
|
tensorField gradUB(sigmaB.size(), tensor::zero);
|
|
scalarField muB(sigmaB.size(), 0);
|
|
scalarField lambdaB(sigmaB.size(), 0);
|
|
|
|
// // Calc surface gradient using FAM
|
|
// tensorField interSGradU(interU.size(), tensor::zero);
|
|
// {
|
|
// faMesh aMesh(mesh_);
|
|
|
|
// const labelList& faceLabels = aMesh.faceLabels();
|
|
|
|
// wordList patchFieldTypes
|
|
// (
|
|
// aMesh.boundary().size(),
|
|
// zeroGradientFaPatchVectorField::typeName
|
|
// );
|
|
|
|
// areaVectorField Us
|
|
// (
|
|
// IOobject
|
|
// (
|
|
// "Us",
|
|
// mesh_.time().timeName(),
|
|
// mesh_,
|
|
// IOobject::NO_READ,
|
|
// IOobject::AUTO_WRITE
|
|
// ),
|
|
// aMesh,
|
|
// dimensioned<vector>("Us", dimLength, vector::zero),
|
|
// patchFieldTypes
|
|
// );
|
|
|
|
// forAll(globalInterFaces(), faceI)
|
|
// {
|
|
// label curFace = globalInterFaces()[faceI];
|
|
// label index = findIndex(faceLabels, curFace);
|
|
|
|
// Us.internalField()[index] = interU[faceI];
|
|
// }
|
|
// Us.correctBoundaryConditions();
|
|
|
|
// tensorField sGradU = fac::grad(Us)().internalField();
|
|
// forAll(globalInterFaces(), faceI)
|
|
// {
|
|
// label curFace = globalInterFaces()[faceI];
|
|
// label index = findIndex(faceLabels, curFace);
|
|
|
|
// interSGradU[faceI] = sGradU[index];
|
|
// }
|
|
// }
|
|
|
|
forAll(globalInterFaces(), faceI)
|
|
{
|
|
label curFace = globalInterFaces()[faceI];
|
|
|
|
scalar ngbDn = w[curFace]*(1.0/deltaCoeffs[curFace]);
|
|
scalar ownDn = (1.0/deltaCoeffs[curFace]) - ngbDn;
|
|
|
|
label curCell = neighbour[curFace];
|
|
vector n = -SI[curFace]/magSI[curFace];
|
|
scalar dn = ngbDn;
|
|
|
|
if (materials[owner[curFace]] < materials[neighbour[curFace]])
|
|
{
|
|
curCell = owner[curFace];
|
|
n *= -1;
|
|
dn = ownDn;
|
|
}
|
|
|
|
muB[faceI] = mu[curCell];
|
|
lambdaB[faceI] = lambda[curCell];
|
|
|
|
gradUB[faceI] = n*(interU[faceI] - UI[curCell])/dn;
|
|
|
|
gradUB[faceI] += ((I-n*n)&gradUI[curCell]);
|
|
// gradUB[faceI] += interSGradU[faceI];
|
|
}
|
|
|
|
sigmaB = 2*muB*symm(gradUB) + lambdaB*(I*tr(gradUB));
|
|
}
|
|
|
|
return tSigmaB;
|
|
}
|
|
|
|
|
|
const List<labelPair>& solidInterface::indicator() const
|
|
{
|
|
if (!indicatorPtr_)
|
|
{
|
|
makeIndicator();
|
|
}
|
|
|
|
return *indicatorPtr_;
|
|
}
|
|
|
|
|
|
void solidInterface::correctGrad
|
|
(
|
|
const volVectorField& U,
|
|
volTensorField& gradU
|
|
) const
|
|
{
|
|
const fvMesh& sMesh = subMesh().subMesh();
|
|
|
|
const unallocLabelList& owner = sMesh.owner();
|
|
const unallocLabelList& neighbour = sMesh.neighbour();
|
|
|
|
volVectorField subU = subMesh().interpolate(U);
|
|
|
|
surfaceVectorField Us = linearInterpolate(subU);
|
|
|
|
const vectorField& interU = interfaceDisplacement();
|
|
|
|
forAll(localInterFaces(), faceI)
|
|
{
|
|
label curFace = localInterFaces()[faceI];
|
|
|
|
Us.internalField()[curFace] = interU[faceI];
|
|
}
|
|
|
|
volTensorField gaussGradU =
|
|
fv::gaussGrad<vector>(sMesh).grad(Us);
|
|
fv::gaussGrad<vector>(sMesh).correctBoundaryConditions
|
|
(
|
|
subU,
|
|
gaussGradU
|
|
);
|
|
|
|
forAll(localInterFaces(), faceI)
|
|
{
|
|
label curFace = localInterFaces()[faceI];
|
|
|
|
gradU.internalField()
|
|
[subMesh().cellMap()[owner[curFace]]] =
|
|
gaussGradU.internalField()[owner[curFace]];
|
|
|
|
gradU.internalField()
|
|
[subMesh().cellMap()[neighbour[curFace]]] =
|
|
gaussGradU.internalField()[neighbour[curFace]];
|
|
}
|
|
|
|
fv::gaussGrad<vector>(mesh_).correctBoundaryConditions(U, gradU);
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
} // End namespace Foam
|
|
|
|
// ************************************************************************* //
|