diff --git a/applications/solvers/finiteArea/liquidFilmFoam/Make/files b/applications/solvers/finiteArea/liquidFilmFoam/Make/files
new file mode 100755
index 000000000..39ee7f75e
--- /dev/null
+++ b/applications/solvers/finiteArea/liquidFilmFoam/Make/files
@@ -0,0 +1,3 @@
+liquidFilmFoam.C
+
+EXE = $(FOAM_APPBIN)/liquidFilmFoam
diff --git a/applications/solvers/surfaceTracking/surfactantFoam/Make/options b/applications/solvers/finiteArea/liquidFilmFoam/Make/options
old mode 100644
new mode 100755
similarity index 100%
rename from applications/solvers/surfaceTracking/surfactantFoam/Make/options
rename to applications/solvers/finiteArea/liquidFilmFoam/Make/options
diff --git a/applications/solvers/finiteArea/liquidFilmFoam/calcFrictionFactor.H b/applications/solvers/finiteArea/liquidFilmFoam/calcFrictionFactor.H
new file mode 100644
index 000000000..af9454484
--- /dev/null
+++ b/applications/solvers/finiteArea/liquidFilmFoam/calcFrictionFactor.H
@@ -0,0 +1,7 @@
+{
+ // Stabilisation of friction factor calculation
+ // Friction factor is defined with standard gravity
+ frictionFactor.internalField() =
+ mag(2*9.81*sqr(manningField.internalField())/
+ pow(mag(h.internalField()) + 1e-7, 1.0/3.0));
+}
diff --git a/applications/solvers/finiteArea/liquidFilmFoam/capillaryCourantNo.H b/applications/solvers/finiteArea/liquidFilmFoam/capillaryCourantNo.H
new file mode 100644
index 000000000..8e66fd171
--- /dev/null
+++ b/applications/solvers/finiteArea/liquidFilmFoam/capillaryCourantNo.H
@@ -0,0 +1,13 @@
+{
+ scalar CoNumSigma = max
+ (
+ sqrt
+ (
+ 2*M_PI*sigma*sqr(aMesh.edgeInterpolation::deltaCoeffs())
+ *aMesh.edgeInterpolation::deltaCoeffs()
+ /rhol
+ )
+ ).value()*runTime.deltaT().value();
+
+ Info<< "Max Capillary Courant Number = " << CoNumSigma << '\n' << endl;
+}
diff --git a/applications/solvers/finiteArea/liquidFilmFoam/createFaFields.H b/applications/solvers/finiteArea/liquidFilmFoam/createFaFields.H
new file mode 100644
index 000000000..5ade57175
--- /dev/null
+++ b/applications/solvers/finiteArea/liquidFilmFoam/createFaFields.H
@@ -0,0 +1,156 @@
+ Info << "Reading field h" << endl;
+ areaScalarField h
+ (
+ IOobject
+ (
+ "h",
+ runTime.timeName(),
+ mesh,
+ IOobject::MUST_READ,
+ IOobject::AUTO_WRITE
+ ),
+ aMesh
+ );
+
+
+ Info << "Reading field Us" << endl;
+ areaVectorField Us
+ (
+ IOobject
+ (
+ "Us",
+ runTime.timeName(),
+ mesh,
+ IOobject::MUST_READ,
+ IOobject::AUTO_WRITE
+ ),
+ aMesh
+ );
+
+
+ edgeScalarField phis
+ (
+ IOobject
+ (
+ "phis",
+ runTime.timeName(),
+ mesh,
+ IOobject::READ_IF_PRESENT,
+ IOobject::AUTO_WRITE
+ ),
+ fac::interpolate(Us) & aMesh.Le()
+ );
+
+
+ edgeScalarField phi2s
+ (
+ IOobject
+ (
+ "phi2s",
+ runTime.timeName(),
+ mesh,
+ IOobject::READ_IF_PRESENT,
+ IOobject::AUTO_WRITE
+ ),
+ fac::interpolate(h*Us) & aMesh.Le()
+ );
+
+
+ const areaVectorField& Ns = aMesh.faceAreaNormals();
+ areaVectorField Gs = g - Ns*(Ns & g);
+ areaScalarField Gn = mag(g - Gs);
+
+ // Mass source
+ areaScalarField Sm
+ (
+ IOobject
+ (
+ "Sm",
+ runTime.timeName(),
+ mesh,
+ IOobject::NO_READ,
+ IOobject::NO_WRITE
+ ),
+ aMesh,
+ dimensionedScalar("Sm", dimLength/dimTime, 0)
+ );
+
+ // Mass sink
+ areaScalarField Sd
+ (
+ IOobject
+ (
+ "Sd",
+ runTime.timeName(),
+ mesh,
+ IOobject::NO_READ,
+ IOobject::NO_WRITE
+ ),
+ aMesh,
+ dimensionedScalar("Sd", dimLength/dimTime, 0)
+ );
+
+ areaVectorField Ug
+ (
+ IOobject
+ (
+ "Sg",
+ runTime.timeName(),
+ mesh,
+ IOobject::NO_READ,
+ IOobject::NO_WRITE
+ ),
+ aMesh,
+ dimensionedVector("Ug", dimVelocity, vector::zero)
+ );
+
+
+ // Surface pressure
+ areaScalarField ps
+ (
+ IOobject
+ (
+ "ps",
+ runTime.timeName(),
+ mesh,
+ IOobject::NO_READ,
+ IOobject::AUTO_WRITE
+ ),
+ rhol*Gn*h - sigma*fac::laplacian(h)
+ );
+
+ // Friction factor
+ areaScalarField dotProduct
+ (
+ aMesh.faceAreaNormals() & (g/mag(g))
+ );
+
+ Info<< "View factor: min = " << min(dotProduct.internalField())
+ << " max = " << max(dotProduct.internalField()) << endl;
+
+ areaScalarField manningField
+ (
+ IOobject
+ (
+ "manningField",
+ runTime.timeName(),
+ mesh,
+ IOobject::MUST_READ,
+ IOobject::AUTO_WRITE
+ ),
+ aMesh
+ );
+
+ areaScalarField frictionFactor
+ (
+ IOobject
+ (
+ "frictionFactor",
+ runTime.timeName(),
+ mesh,
+ IOobject::NO_READ,
+ IOobject::NO_WRITE
+ ),
+ aMesh,
+ dimensionedScalar("one", dimless, 0.01)
+ );
diff --git a/applications/solvers/finiteArea/liquidFilmFoam/createFvFields.H b/applications/solvers/finiteArea/liquidFilmFoam/createFvFields.H
new file mode 100644
index 000000000..788b15558
--- /dev/null
+++ b/applications/solvers/finiteArea/liquidFilmFoam/createFvFields.H
@@ -0,0 +1,31 @@
+volVectorField U
+(
+ IOobject
+ (
+ "U",
+ runTime.timeName(),
+ mesh,
+ IOobject::NO_READ,
+ IOobject::AUTO_WRITE
+ ),
+ mesh,
+ dimensionedVector("0", dimVelocity, vector::zero)
+);
+
+
+volScalarField H
+(
+ IOobject
+ (
+ "H",
+ runTime.timeName(),
+ mesh,
+ IOobject::NO_READ,
+ IOobject::AUTO_WRITE
+ ),
+ mesh,
+ dimensionedScalar("0", dimLength, 0)
+);
+
+// Create volume-to surface mapping object
+volSurfaceMapping vsm(aMesh);
diff --git a/applications/solvers/finiteArea/liquidFilmFoam/liquidFilmFoam.C b/applications/solvers/finiteArea/liquidFilmFoam/liquidFilmFoam.C
new file mode 100644
index 000000000..03fd98c06
--- /dev/null
+++ b/applications/solvers/finiteArea/liquidFilmFoam/liquidFilmFoam.C
@@ -0,0 +1,152 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | foam-extend: Open Source CFD
+ \\ / O peration |
+ \\ / A nd | For copyright notice see file Copyright
+ \\/ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Application
+ liquidFilmFoam
+
+Description
+ Transient solver for incompressible, laminar flow of Newtonian fluids in
+ liquid film formulation.
+
+Author
+ Zeljko Tukovic, FMENA
+ Hrvoje Jasak, Wikki Ltd. All rights reserved.
+
+\*---------------------------------------------------------------------------*/
+
+#include "fvCFD.H"
+#include "faCFD.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+int main(int argc, char *argv[])
+{
+# include "setRootCase.H"
+# include "createTime.H"
+# include "createMesh.H"
+# include "createFaMesh.H"
+# include "readGravitationalAcceleration.H"
+# include "readTransportProperties.H"
+# include "createFaFields.H"
+# include "createFvFields.H"
+
+ Info << "\nStarting time loop\n" << endl;
+
+ while (runTime.run())
+ {
+# include "readSolutionControls.H"
+# include "readTimeControls.H"
+# include "surfaceCourantNo.H"
+# include "capillaryCourantNo.H"
+# include "setDeltaT.H"
+
+ runTime++;
+
+ Info<< "Time = " << runTime.timeName() << nl << endl;
+
+ for (int iCorr = 0; iCorr < nCorr; iCorr++)
+ {
+ phi2s = fac::interpolate(h)*phis;
+
+# include "calcFrictionFactor.H"
+
+ faVectorMatrix UsEqn
+ (
+ fam::ddt(h, Us)
+ + fam::div(phi2s, Us)
+ + fam::Sp(0.0125*frictionFactor*mag(Us), Us)
+ ==
+ Gs*h
+ - fam::Sp(Sd, Us)
+ );
+
+ UsEqn.relax();
+ solve(UsEqn == - fac::grad(ps*h)/rhol + ps*fac::grad(h)/rhol);
+
+ areaScalarField UsA = UsEqn.A();
+
+ Us = UsEqn.H()/UsA;
+ Us.correctBoundaryConditions();
+
+ phis = (fac::interpolate(Us) & aMesh.Le())
+ - fac::interpolate(1.0/(rhol*UsA))
+ *fac::lnGrad(ps*h)*aMesh.magLe()
+ + fac::interpolate(ps/(rhol*UsA))
+ *fac::lnGrad(h)*aMesh.magLe();
+
+ faScalarMatrix hEqn
+ (
+ fam::ddt(h)
+ + fam::div(phis, h)
+ ==
+ Sm
+ - fam::Sp
+ (
+ Sd/(h + dimensionedScalar("small", dimLength, SMALL)),
+ h
+ )
+ );
+
+ hEqn.relax();
+ hEqn.solve();
+
+ phi2s = hEqn.flux();
+
+ // Bound h
+ h.internalField() = max
+ (
+ max
+ (
+ h.internalField(),
+ fac::average(max(h, h0))().internalField()
+ *pos(h0.value() - h.internalField())
+ ),
+ h0.value()
+ );
+
+ ps = rhol*Gn*h - sigma*fac::laplacian(h);
+ ps.correctBoundaryConditions();
+
+ Us -= (1.0/(rhol*UsA))*fac::grad(ps*h)
+ - (ps/(rhol*UsA))*fac::grad(h);
+ Us.correctBoundaryConditions();
+ }
+
+ if (runTime.outputTime())
+ {
+ vsm.mapToVolume(h, H.boundaryField());
+ vsm.mapToVolume(Us, U.boundaryField());
+
+ runTime.write();
+ }
+
+ Info << "ExecutionTime = "
+ << scalar(runTime.elapsedCpuTime())
+ << " s\n" << endl << endl;
+ }
+
+ return(0);
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/finiteArea/liquidFilmFoam/readSolutionControls.H b/applications/solvers/finiteArea/liquidFilmFoam/readSolutionControls.H
new file mode 100644
index 000000000..00930b2c1
--- /dev/null
+++ b/applications/solvers/finiteArea/liquidFilmFoam/readSolutionControls.H
@@ -0,0 +1,13 @@
+int nCorr = 0;
+
+if (aMesh.solutionDict().found("nOuterCorrectors"))
+{
+ nCorr =
+ readInt(aMesh.solutionDict().lookup("nOuterCorrectors"));
+}
+else
+{
+ FatalErrorIn(args.executable())
+ << "Cannot find number of correctors"
+ << abort(FatalError);
+}
diff --git a/applications/solvers/finiteArea/liquidFilmFoam/readTransportProperties.H b/applications/solvers/finiteArea/liquidFilmFoam/readTransportProperties.H
new file mode 100644
index 000000000..2f2c99ffd
--- /dev/null
+++ b/applications/solvers/finiteArea/liquidFilmFoam/readTransportProperties.H
@@ -0,0 +1,41 @@
+IOdictionary transportProperties
+(
+ IOobject
+ (
+ "transportProperties",
+ runTime.constant(),
+ mesh,
+ IOobject::MUST_READ,
+ IOobject::NO_WRITE
+ )
+);
+
+dimensionedScalar mug
+(
+ transportProperties.lookup("mug")
+);
+
+dimensionedScalar mul
+(
+ transportProperties.lookup("mul")
+);
+
+dimensionedScalar sigma
+(
+ transportProperties.lookup("sigma")
+);
+
+dimensionedScalar rhol
+(
+ transportProperties.lookup("rhol")
+);
+
+dimensionedScalar rhog
+(
+ transportProperties.lookup("rhog")
+);
+
+dimensionedScalar h0
+(
+ transportProperties.lookup("h0")
+);
diff --git a/applications/solvers/finiteArea/liquidFilmFoam/surfaceCourantNo.H b/applications/solvers/finiteArea/liquidFilmFoam/surfaceCourantNo.H
new file mode 100644
index 000000000..160797516
--- /dev/null
+++ b/applications/solvers/finiteArea/liquidFilmFoam/surfaceCourantNo.H
@@ -0,0 +1,59 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright held by original author
+ \\/ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Global
+ surfaceCourantNo
+
+Author
+ Hrvoje Jasak, Wikki Ltd. All rights reserved.
+
+Description
+ Calculates and outputs the mean and maximum Courant Numbers for the
+ Finite Area method.
+
+\*---------------------------------------------------------------------------*/
+
+scalar CoNum = 0.0;
+scalar meanCoNum = 0.0;
+scalar velMag = 0.0;
+
+if (aMesh.nInternalEdges())
+{
+ edgeScalarField SfUfbyDelta =
+ aMesh.edgeInterpolation::deltaCoeffs()*mag(phis);
+
+ CoNum = max(SfUfbyDelta/aMesh.magLe())
+ .value()*runTime.deltaT().value();
+
+ meanCoNum = (sum(SfUfbyDelta)/sum(aMesh.magLe()))
+ .value()*runTime.deltaT().value();
+
+ velMag = max(mag(phis)/aMesh.magLe()).value();
+}
+
+Info<< "Courant Number mean: " << meanCoNum
+ << " max: " << CoNum
+ << " velocity magnitude: " << velMag << endl;
+
+// ************************************************************************* //
diff --git a/applications/solvers/surfaceTracking/surfactantFoam/Make/files b/applications/solvers/finiteArea/surfactantFoam/Make/files
similarity index 100%
rename from applications/solvers/surfaceTracking/surfactantFoam/Make/files
rename to applications/solvers/finiteArea/surfactantFoam/Make/files
diff --git a/tutorials/surfaceTracking/surfactantFoam/sphereTransport/sphereSurfactantFoam/Make/options b/applications/solvers/finiteArea/surfactantFoam/Make/options
similarity index 100%
rename from tutorials/surfaceTracking/surfactantFoam/sphereTransport/sphereSurfactantFoam/Make/options
rename to applications/solvers/finiteArea/surfactantFoam/Make/options
diff --git a/applications/solvers/surfaceTracking/surfactantFoam/createFaFields.H b/applications/solvers/finiteArea/surfactantFoam/createFaFields.H
similarity index 100%
rename from applications/solvers/surfaceTracking/surfactantFoam/createFaFields.H
rename to applications/solvers/finiteArea/surfactantFoam/createFaFields.H
diff --git a/applications/solvers/surfaceTracking/surfactantFoam/createFaMesh.H b/applications/solvers/finiteArea/surfactantFoam/createFaMesh.H
similarity index 100%
rename from applications/solvers/surfaceTracking/surfactantFoam/createFaMesh.H
rename to applications/solvers/finiteArea/surfactantFoam/createFaMesh.H
diff --git a/applications/solvers/surfaceTracking/surfactantFoam/createVolFields.H b/applications/solvers/finiteArea/surfactantFoam/createVolFields.H
similarity index 100%
rename from applications/solvers/surfaceTracking/surfactantFoam/createVolFields.H
rename to applications/solvers/finiteArea/surfactantFoam/createVolFields.H
diff --git a/tutorials/surfaceTracking/surfactantFoam/sphereTransport/sphereSurfactantFoam/surfactantFoam.C b/applications/solvers/finiteArea/surfactantFoam/surfactantFoam.C
similarity index 99%
rename from tutorials/surfaceTracking/surfactantFoam/sphereTransport/sphereSurfactantFoam/surfactantFoam.C
rename to applications/solvers/finiteArea/surfactantFoam/surfactantFoam.C
index 74c31e86b..44ad27420 100644
--- a/tutorials/surfaceTracking/surfactantFoam/sphereTransport/sphereSurfactantFoam/surfactantFoam.C
+++ b/applications/solvers/finiteArea/surfactantFoam/surfactantFoam.C
@@ -22,7 +22,7 @@ License
along with foam-extend. If not, see .
Application
- finiteAreaFoam
+ surfactantFoam
Description
diff --git a/applications/solvers/surfaceTracking/Allwclean b/applications/solvers/surfaceTracking/Allwclean
index db649038c..9f7bf3903 100755
--- a/applications/solvers/surfaceTracking/Allwclean
+++ b/applications/solvers/surfaceTracking/Allwclean
@@ -5,6 +5,5 @@ wclean freeSurface
wclean interTrackFoam
wclean bubbleInterTrackFoam
-wclean surfactantFoam
wclean ./utilities/setFluidIndicator
diff --git a/applications/solvers/surfaceTracking/Allwmake b/applications/solvers/surfaceTracking/Allwmake
index e0fff3202..112bb3bc7 100755
--- a/applications/solvers/surfaceTracking/Allwmake
+++ b/applications/solvers/surfaceTracking/Allwmake
@@ -1,8 +1,6 @@
#!/bin/sh
set -x
-wmake surfactantFoam
-
wmake libso freeSurface
wmake interTrackFoam
diff --git a/applications/utilities/finiteArea/checkFaMesh/Make/files b/applications/utilities/finiteArea/checkFaMesh/Make/files
new file mode 100644
index 000000000..14a2b1639
--- /dev/null
+++ b/applications/utilities/finiteArea/checkFaMesh/Make/files
@@ -0,0 +1,3 @@
+checkFaMesh.C
+
+EXE = $(FOAM_APPBIN)/checkFaMesh
diff --git a/applications/utilities/finiteArea/checkFaMesh/Make/options b/applications/utilities/finiteArea/checkFaMesh/Make/options
new file mode 100644
index 000000000..3b03eb4be
--- /dev/null
+++ b/applications/utilities/finiteArea/checkFaMesh/Make/options
@@ -0,0 +1,7 @@
+EXE_INC = \
+ -I$(LIB_SRC)/finiteVolume/lnInclude \
+ -I$(LIB_SRC)/finiteArea/lnInclude
+
+EXE_LIBS = \
+ -lfiniteVolume \
+ -lfiniteArea
diff --git a/applications/utilities/finiteArea/checkFaMesh/checkFaMesh.C b/applications/utilities/finiteArea/checkFaMesh/checkFaMesh.C
new file mode 100644
index 000000000..37aad4a8e
--- /dev/null
+++ b/applications/utilities/finiteArea/checkFaMesh/checkFaMesh.C
@@ -0,0 +1,73 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright held by original author
+ \\/ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Application
+ Check a Finite Area mesh
+
+\*---------------------------------------------------------------------------*/
+
+#include "fvCFD.H"
+#include "faCFD.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+int main(int argc, char *argv[])
+{
+# include "setRootCase.H"
+# include "createTime.H"
+# include "createMesh.H"
+# include "createFaMesh.H"
+
+ Info<< "Time = " << runTime.timeName() << nl << endl;
+
+ // General mesh statistics
+ Info<< "Number of points: " << aMesh.nPoints() << nl
+ << "Number of internal edges: " << aMesh.nInternalEdges() << nl
+ << "Number of edges: " << aMesh.nEdges() << nl
+ << "Number of faces: " << aMesh.nFaces() << nl
+ << endl;
+
+ // Check geometry
+ Info<< "Face area: min = " << min(aMesh.S().field())
+ << " max = " << max(aMesh.S().field()) << nl
+ << "Internal edge length: min = "
+ << min(aMesh.magLe().internalField()) << nl
+ << " max = " << max(aMesh.magLe().internalField()) << nl
+ << "Edge length: min = "
+ << min(aMesh.magLe()).value() << nl
+ << " max = " << max(aMesh.magLe()).value() << nl
+ << "Face area normals: min = " << min(aMesh.faceAreaNormals().field())
+ << " max = " << max(aMesh.faceAreaNormals().field()) << nl
+ << endl;
+
+
+ return(0);
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/finiteArea/createFaMeshFromStl/Make/files b/applications/utilities/finiteArea/createFaMeshFromStl/Make/files
new file mode 100644
index 000000000..3d70df5f5
--- /dev/null
+++ b/applications/utilities/finiteArea/createFaMeshFromStl/Make/files
@@ -0,0 +1,3 @@
+createFaMeshFromStl.C
+
+EXE = $(FOAM_APPBIN)/createFaMeshFromStl
diff --git a/applications/utilities/finiteArea/createFaMeshFromStl/Make/options b/applications/utilities/finiteArea/createFaMeshFromStl/Make/options
new file mode 100644
index 000000000..e6d06285d
--- /dev/null
+++ b/applications/utilities/finiteArea/createFaMeshFromStl/Make/options
@@ -0,0 +1,8 @@
+EXE_INC = \
+ -I$(LIB_SRC)/triSurface/lnInclude \
+ -I$(LIB_SRC)/finiteArea/lnInclude
+
+EXE_LIBS = \
+ -ltriSurface \
+ -lmeshTools \
+ -lfiniteArea
diff --git a/applications/utilities/finiteArea/createFaMeshFromStl/createFaMeshFromStl.C b/applications/utilities/finiteArea/createFaMeshFromStl/createFaMeshFromStl.C
new file mode 100644
index 000000000..871899861
--- /dev/null
+++ b/applications/utilities/finiteArea/createFaMeshFromStl/createFaMeshFromStl.C
@@ -0,0 +1,93 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright held by original author
+ \\/ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Application
+ Create a Finite Area mesh from an STL file
+
+\*---------------------------------------------------------------------------*/
+
+#include "argList.H"
+#include "triSurface.H"
+#include "Time.H"
+#include "polyMesh.H"
+#include "faCFD.H"
+#include "IFstream.H"
+#include "graph.H"
+#include "Tuple2.H"
+#include "matchPoints.H"
+#include "standAlonePatch.H"
+
+#include "fixedValueFaPatchFields.H"
+#include "zeroGradientFaPatchFields.H"
+#include "inletOutletFaPatchFields.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+int main(int argc, char *argv[])
+{
+ argList::validArgs.append("STL mesh file");
+
+ argList args(argc, argv);
+
+ if (!args.check())
+ {
+ FatalError.exit();
+ }
+
+ fileName prefix(args.additionalArgs()[0]);
+
+# include "createTime.H"
+# include "makePolyMesh.H"
+# include "makeFaMesh.H"
+
+ Info<< " done." << nl << endl;
+
+ Info<< nl << "Write mesh vtk files... ";
+ standAlonePatch::writeVTK
+ (
+ runTime.caseName() + "Mesh",
+ aMesh.patch().localFaces(),
+ aMesh.patch().localPoints()
+ );
+
+ standAlonePatch::writeVTKNormals
+ (
+ runTime.caseName() + "Normals",
+ aMesh.patch().localFaces(),
+ aMesh.patch().localPoints()
+ );
+
+ Info<< " done." << nl << endl;
+
+ Info<< "End\n" << endl;
+
+ return(0);
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/finiteArea/createFaMeshFromStl/makeFaMesh.H b/applications/utilities/finiteArea/createFaMeshFromStl/makeFaMesh.H
new file mode 100644
index 000000000..7b8a797f7
--- /dev/null
+++ b/applications/utilities/finiteArea/createFaMeshFromStl/makeFaMesh.H
@@ -0,0 +1 @@
+faMesh aMesh(mesh, faceLabels);
diff --git a/applications/utilities/finiteArea/createFaMeshFromStl/makePolyMesh.H b/applications/utilities/finiteArea/createFaMeshFromStl/makePolyMesh.H
new file mode 100644
index 000000000..13872316c
--- /dev/null
+++ b/applications/utilities/finiteArea/createFaMeshFromStl/makePolyMesh.H
@@ -0,0 +1,58 @@
+ triSurface patch(prefix + ".stl");
+
+ // Read patches
+ List > patchNames(patch.patches().size());
+
+ forAll (patch.patches(), patchI)
+ {
+ patchNames[patchI] =
+ Tuple2(patch.patches()[patchI].name(), patchI);
+ }
+
+ Info << "Patches: " << patchNames << endl;
+
+ // Create polyMesh
+ faceList faces(patch.size());
+ labelList faceLabels(patch.size());
+ labelList faceRegion(patch.size());
+
+ forAll (patch, faceI)
+ {
+ faces[faceI] = face(patch[faceI]);
+ faceLabels[faceI] = faceI;
+ faceRegion[faceI] = patch[faceI].region();
+ }
+
+ polyMesh mesh
+ (
+ IOobject
+ (
+ polyMesh::defaultRegion,
+ runTime.constant(),
+ runTime
+ ),
+ xferCopy(patch.points()),
+ xferCopy(faces),
+ xferCopy(labelList(0)),
+ xferCopy(labelList(0)),
+ false
+ );
+
+{
+ // Add zones
+ List pz(0);
+ List fz(1);
+ List cz(0);
+
+ fz[0] = new faceZone
+ (
+ "roof",
+ faceLabels,
+ boolList(patch.size(), false),
+ 0,
+ mesh.faceZones()
+ );
+
+ mesh.addPatches(List(0), true);
+ mesh.addZones(pz, fz, cz);
+}
diff --git a/applications/utilities/finiteArea/makeFaMesh/Make/files b/applications/utilities/finiteArea/makeFaMesh/Make/files
new file mode 100644
index 000000000..fbd0f40cd
--- /dev/null
+++ b/applications/utilities/finiteArea/makeFaMesh/Make/files
@@ -0,0 +1,3 @@
+makeFaMesh.C
+
+EXE = $(FOAM_APPBIN)/makeFaMesh
diff --git a/applications/utilities/finiteArea/makeFaMesh/Make/options b/applications/utilities/finiteArea/makeFaMesh/Make/options
new file mode 100644
index 000000000..98ba4f722
--- /dev/null
+++ b/applications/utilities/finiteArea/makeFaMesh/Make/options
@@ -0,0 +1,8 @@
+EXE_INC = \
+ -I$(LIB_SRC)/finiteArea/lnInclude \
+ -I$(LIB_SRC)/finiteVolume/lnInclude \
+ -I$(LIB_SRC)/cfdTools/general/lnInclude
+
+EXE_LIBS = \
+ -lfiniteArea \
+ -lfiniteVolume
diff --git a/applications/utilities/finiteArea/makeFaMesh/makeFaMesh.C b/applications/utilities/finiteArea/makeFaMesh/makeFaMesh.C
new file mode 100644
index 000000000..010c647f2
--- /dev/null
+++ b/applications/utilities/finiteArea/makeFaMesh/makeFaMesh.C
@@ -0,0 +1,328 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | foam-extend: Open Source CFD
+ \\ / O peration |
+ \\ / A nd | For copyright notice see file Copyright
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of foam-extend.
+
+ foam-extend 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.
+
+ foam-extend 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 foam-extend. If not, see .
+
+Application
+ makeFaMesh
+
+Description
+ A mesh generator for finite area mesh.
+
+\*---------------------------------------------------------------------------*/
+
+#include "objectRegistry.H"
+#include "Time.H"
+#include "argList.H"
+#include "OSspecific.H"
+#include "faMesh.H"
+#include "fvMesh.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+class faPatchData
+{
+public:
+ word name_;
+ word type_;
+ dictionary dict_;
+ label ownPolyPatchID_;
+ label ngbPolyPatchID_;
+ labelList edgeLabels_;
+ faPatchData()
+ :
+ name_(word::null),
+ type_(word::null),
+ ownPolyPatchID_(-1),
+ ngbPolyPatchID_(-1)
+ {}
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+int main(int argc, char *argv[])
+{
+# include "setRootCase.H"
+# include "createTime.H"
+# include "createMesh.H"
+
+ // Reading faMeshDefinition dictionary
+ IOdictionary faMeshDefinition
+ (
+ IOobject
+ (
+ "faMeshDefinition",
+ runTime.constant(),
+ "faMesh",
+ mesh,
+ IOobject::MUST_READ,
+ IOobject::NO_WRITE
+ )
+ );
+
+ wordList polyMeshPatches
+ (
+ faMeshDefinition.lookup("polyMeshPatches")
+ );
+
+ dictionary bndDict = faMeshDefinition.subDict("boundary");
+
+ wordList faPatchNames = bndDict.toc();
+
+ List faPatches(faPatchNames.size()+1);
+
+ forAll (faPatchNames, patchI)
+ {
+ dictionary curPatchDict =
+ bndDict.subDict(faPatchNames[patchI]);
+
+ faPatches[patchI].name_ = faPatchNames[patchI];
+
+ faPatches[patchI].type_ =
+ word(curPatchDict.lookup("type"));
+
+ word ownName = curPatchDict.lookup("ownerPolyPatch");
+
+ faPatches[patchI].ownPolyPatchID_ =
+ mesh.boundaryMesh().findPatchID(ownName);
+
+ if ( faPatches[patchI].ownPolyPatchID_ < 0 )
+ {
+ FatalErrorIn("makeFaMesh:")
+ << "neighbourPolyPatch " << ownName << " does not exist"
+ << exit(FatalError);
+ }
+
+ word neiName = curPatchDict.lookup("neighbourPolyPatch");
+
+ faPatches[patchI].ngbPolyPatchID_ =
+ mesh.boundaryMesh().findPatchID(neiName);
+
+ if ( faPatches[patchI].ngbPolyPatchID_ < 0 )
+ {
+ FatalErrorIn("makeFaMesh:")
+ << "neighbourPolyPatch " << neiName << " does not exist"
+ << exit(FatalError);
+ }
+ }
+
+ // Setting faceLabels list size
+ label size = 0;
+
+ labelList patchIDs(polyMeshPatches.size(), -1);
+
+ forAll (polyMeshPatches, patchI)
+ {
+ patchIDs[patchI] =
+ mesh.boundaryMesh().findPatchID(polyMeshPatches[patchI]);
+
+ if ( patchIDs[patchI] < 0 )
+ {
+ FatalErrorIn("makeFaMesh:")
+ << "Patch " << polyMeshPatches[patchI] << " does not exist"
+ << exit(FatalError);
+ }
+
+ size += mesh.boundaryMesh()[patchIDs[patchI]].size();
+ }
+
+ labelList faceLabels(size, -1);
+
+ sort(patchIDs);
+
+
+ // Filling of faceLabels list
+ label faceI = -1;
+
+ forAll (polyMeshPatches, patchI)
+ {
+ label start = mesh.boundaryMesh()[patchIDs[patchI]].start();
+
+ label size = mesh.boundaryMesh()[patchIDs[patchI]].size();
+
+ for(label i = 0; i < size; i++)
+ {
+ faceLabels[++faceI] = start + i;
+ }
+ }
+
+ // Creating faMesh
+ Info << "Create faMesh ... ";
+
+ faMesh areaMesh
+ (
+ mesh,
+ faceLabels
+ );
+ Info << "Done" << endl;
+
+
+ // Determination of faPatch ID for each boundary edge.
+ // Result is in the bndEdgeFaPatchIDs list
+ const indirectPrimitivePatch& patch = areaMesh.patch();
+
+ labelList faceCells(faceLabels.size(), -1);
+
+ forAll (faceCells, faceI)
+ {
+ label faceID = faceLabels[faceI];
+
+ faceCells[faceI] = mesh.faceOwner()[faceID];
+ }
+
+ labelList meshEdges =
+ patch.meshEdges
+ (
+ mesh.edges(),
+ mesh.cellEdges(),
+ faceCells
+ );
+
+ const labelListList& edgeFaces = mesh.edgeFaces();
+
+ const label nTotalEdges = patch.nEdges();
+ const label nInternalEdges = patch.nInternalEdges();
+
+ labelList bndEdgeFaPatchIDs(nTotalEdges - nInternalEdges, -1);
+
+ for (label edgeI = nInternalEdges; edgeI < nTotalEdges; edgeI++)
+ {
+ label curMeshEdge = meshEdges[edgeI];
+
+ labelList curEdgePatchIDs(2, -1);
+
+ label patchI = -1;
+
+ forAll (edgeFaces[curMeshEdge], faceI)
+ {
+ label curFace = edgeFaces[curMeshEdge][faceI];
+
+ label curPatchID = mesh.boundaryMesh().whichPatch(curFace);
+
+ if (curPatchID != -1)
+ {
+ curEdgePatchIDs[++patchI] = curPatchID;
+ }
+ }
+
+ for(label pI = 0; pI < faPatches.size() - 1; pI++)
+ {
+ if
+ (
+ (
+ curEdgePatchIDs[0] == faPatches[pI].ownPolyPatchID_
+ && curEdgePatchIDs[1] == faPatches[pI].ngbPolyPatchID_
+ )
+ ||
+ (
+ curEdgePatchIDs[1] == faPatches[pI].ownPolyPatchID_
+ && curEdgePatchIDs[0] == faPatches[pI].ngbPolyPatchID_
+ )
+ )
+ {
+ bndEdgeFaPatchIDs[edgeI - nInternalEdges] = pI;
+ break;
+ }
+ }
+ }
+
+
+ // Set edgeLabels for each faPatch
+ for(label pI=0; pI<(faPatches.size()-1); pI++)
+ {
+ SLList