Community contribution from Johan Roenby, DHI IsoAdvector is a geometric Volume-of-Fluid method for advection of a sharp interface between two incompressible fluids. It works on both structured and unstructured meshes with no requirements on cell shapes. IsoAdvector is as an alternative choice for the interface compression treatment with the MULES limiter implemented in the interFoam family of solvers. The isoAdvector concept and code was developed at DHI and was funded by a Sapere Aude postdoc grant to Johan Roenby from The Danish Council for Independent Research | Technology and Production Sciences (Grant-ID: DFF - 1337-00118B - FTP). Co-funding is also provided by the GTS grant to DHI from the Danish Agency for Science, Technology and Innovation. The ideas behind and performance of the isoAdvector scheme is documented in: Roenby J, Bredmose H, Jasak H. 2016 A computational method for sharp interface advection. R. Soc. open sci. 3: 160405. [http://dx.doi.org/10.1098/rsos.160405](http://dx.doi.org/10.1098/rsos.160405) Videos showing isoAdvector's performance with a number of standard test cases can be found in this youtube channel: https://www.youtube.com/channel/UCt6Idpv4C8TTgz1iUX0prAA Project contributors: * Johan Roenby <jro@dhigroup.com> (Inventor and main developer) * Hrvoje Jasak <hrvoje.jasak@fsb.hr> (Consistent treatment of boundary faces including processor boundaries, parallelisation, code clean up * Henrik Bredmose <hbre@dtu.dk> (Assisted in the conceptual development) * Vuko Vukcevic <vuko.vukcevic@fsb.hr> (Code review, profiling, porting to foam-extend, bug fixing, testing) * Tomislav Maric <tomislav@sourceflux.de> (Source file rearrangement) * Andy Heather <a.heather@opencfd.co.uk> (Integration into OpenFOAM for v1706 release) See the integration repository below to see the full set of changes implemented for release into OpenFOAM v1706 https://develop.openfoam.com/Community/Integration-isoAdvector
192 lines
5.4 KiB
C
192 lines
5.4 KiB
C
/*---------------------------------------------------------------------------*\
|
|
========= |
|
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
\\ / O peration |
|
|
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
|
|
\\/ M anipulation |
|
|
-------------------------------------------------------------------------------
|
|
isoAdvector | Copyright (C) 2016-2017 DHI
|
|
-------------------------------------------------------------------------------
|
|
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/>.
|
|
|
|
Application
|
|
setAlphaField
|
|
|
|
Description
|
|
Uses isoCutCell to create a volume fraction field from either a cylinder,
|
|
a sphere or a plane.
|
|
|
|
Original code supplied by Johan Roenby, DHI (2016)
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
|
|
#include "fvCFD.H"
|
|
#include "isoCutFace.H"
|
|
#include "isoCutCell.H"
|
|
#include "Enum.H"
|
|
#include "mathematicalConstants.H"
|
|
|
|
using namespace Foam::constant;
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
class shapeSelector
|
|
{
|
|
public:
|
|
|
|
enum class shapeType
|
|
{
|
|
PLANE,
|
|
SPHERE,
|
|
CYLINDER,
|
|
SIN
|
|
};
|
|
|
|
static const Foam::Enum<shapeType> shapeTypeNames;
|
|
};
|
|
|
|
const Foam::Enum<shapeSelector::shapeType> shapeSelector::shapeTypeNames
|
|
{
|
|
{ shapeSelector::shapeType::PLANE, "plane" },
|
|
{ shapeSelector::shapeType::SPHERE, "sphere" },
|
|
{ shapeSelector::shapeType::CYLINDER, "cylinder" },
|
|
{ shapeSelector::shapeType::SIN, "sin" },
|
|
};
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
#include "setRootCase.H"
|
|
#include "createTime.H"
|
|
#include "createMesh.H"
|
|
|
|
Info<< "Reading setAlphaFieldDict\n" << endl;
|
|
|
|
IOdictionary dict
|
|
(
|
|
IOobject
|
|
(
|
|
"setAlphaFieldDict",
|
|
runTime.system(),
|
|
mesh,
|
|
IOobject::MUST_READ,
|
|
IOobject::NO_WRITE
|
|
)
|
|
);
|
|
|
|
const shapeSelector::shapeType surfType
|
|
(
|
|
shapeSelector::shapeTypeNames.read(dict.lookup("type"))
|
|
);
|
|
const vector centre(dict.lookup("centre"));
|
|
const word fieldName(dict.lookup("field"));
|
|
|
|
Info<< "Reading field " << fieldName << "\n" << endl;
|
|
volScalarField alpha1
|
|
(
|
|
IOobject
|
|
(
|
|
fieldName,
|
|
runTime.timeName(),
|
|
mesh,
|
|
IOobject::MUST_READ,
|
|
IOobject::AUTO_WRITE
|
|
),
|
|
mesh
|
|
);
|
|
|
|
scalar f0 = 0.0;
|
|
scalarField f(mesh.points().size());
|
|
|
|
Info<< "Processing type '" << shapeSelector::shapeTypeNames[surfType]
|
|
<< "'" << endl;
|
|
|
|
switch (surfType)
|
|
{
|
|
case shapeSelector::shapeType::PLANE:
|
|
{
|
|
const vector direction(dict.lookup("direction"));
|
|
|
|
f = -(mesh.points() - centre) & (direction/mag(direction));
|
|
f0 = 0.0;
|
|
break;
|
|
}
|
|
case shapeSelector::shapeType::SPHERE:
|
|
{
|
|
const scalar radius(readScalar(dict.lookup("radius")));
|
|
|
|
f = -mag(mesh.points() - centre);
|
|
f0 = -radius;
|
|
break;
|
|
}
|
|
case shapeSelector::shapeType::CYLINDER:
|
|
{
|
|
const scalar radius(readScalar(dict.lookup("radius")));
|
|
const vector direction(dict.lookup("direction"));
|
|
|
|
f = -sqrt
|
|
(
|
|
sqr(mag(mesh.points() - centre))
|
|
- sqr(mag((mesh.points() - centre) & direction))
|
|
);
|
|
f0 = -radius;
|
|
break;
|
|
}
|
|
case shapeSelector::shapeType::SIN:
|
|
{
|
|
const scalar period(readScalar(dict.lookup("period")));
|
|
const scalar amplitude(readScalar(dict.lookup("amplitude")));
|
|
const vector up(dict.lookup("up"));
|
|
const vector direction(dict.lookup("direction"));
|
|
|
|
const scalarField xx
|
|
(
|
|
(mesh.points() - centre) & direction/mag(direction)
|
|
);
|
|
const scalarField zz((mesh.points() - centre) & up/mag(up));
|
|
|
|
f = amplitude*Foam::sin(2*mathematical::pi*xx/period) - zz;
|
|
f0 = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// Define function on mesh points and isovalue
|
|
|
|
// Calculating alpha1 volScalarField from f = f0 isosurface
|
|
isoCutCell icc(mesh, f);
|
|
icc.volumeOfFluid(alpha1, f0);
|
|
|
|
// Writing volScalarField alpha1
|
|
ISstream::defaultPrecision(18);
|
|
alpha1.write();
|
|
|
|
Info<< nl << "Phase-1 volume fraction = "
|
|
<< alpha1.weightedAverage(mesh.Vsc()).value()
|
|
<< " Min(" << alpha1.name() << ") = " << min(alpha1).value()
|
|
<< " Max(" << alpha1.name() << ") - 1 = " << max(alpha1).value() - 1
|
|
<< nl << endl;
|
|
|
|
Info<< "End\n" << endl;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
// ************************************************************************* //
|