diff --git a/applications/solvers/basic/potentialFoam/createControls.H b/applications/solvers/basic/potentialFoam/createControls.H deleted file mode 100644 index 7015cae02e8c7400d4c59a211637015c558d6b63..0000000000000000000000000000000000000000 --- a/applications/solvers/basic/potentialFoam/createControls.H +++ /dev/null @@ -1,9 +0,0 @@ -const dictionary& potentialFlow -( - mesh.solutionDict().subDict("potentialFlow") -); - -const int nNonOrthCorr -( - potentialFlow.lookupOrDefault<int>("nNonOrthogonalCorrectors", 0) -); diff --git a/applications/solvers/basic/potentialFoam/createFields.H b/applications/solvers/basic/potentialFoam/createFields.H index ce912510ecbf992542d9ba8d3206ec4bb199d6f0..36c4dcc08afe5a408899504a0e3168ca0842d8ed 100644 --- a/applications/solvers/basic/potentialFoam/createFields.H +++ b/applications/solvers/basic/potentialFoam/createFields.H @@ -12,6 +12,7 @@ volVectorField U mesh ); +// Initialise the velocity internal field to zero U = dimensionedVector("0", U.dimensions(), vector::zero); surfaceScalarField phi @@ -34,7 +35,9 @@ if (args.optionFound("initialiseUBCs")) } -// Default name for the pressure field +// Construct a pressure field +// If it is available read it otherwise construct from the velocity BCs +// converting fixed-value BCs to zero-gradient and vice versa. word pName("p"); // Update name of the pressure field from the command-line option @@ -55,6 +58,9 @@ forAll(U.boundaryField(), patchi) } } +// Note that registerObject is false for the pressure field. The pressure +// field in this solver doesn't have a physical value during the solution. +// It shouldn't be looked up and used by sub models or boundary conditions. Info<< "Constructing pressure field " << pName << nl << endl; volScalarField p ( @@ -64,13 +70,28 @@ volScalarField p runTime.timeName(), mesh, IOobject::READ_IF_PRESENT, - IOobject::NO_WRITE + IOobject::NO_WRITE, + false ), mesh, dimensionedScalar(pName, sqr(dimVelocity), 0), pBCTypes ); +label pRefCell = 0; +scalar pRefValue = 0.0; +if (args.optionFound("writep")) +{ + setRefCell + ( + p, + potentialFlow.dict(), + pRefCell, + pRefValue + ); +} + + Info<< "Constructing velocity potential field Phi\n" << endl; volScalarField Phi ( diff --git a/applications/solvers/basic/potentialFoam/potentialFoam.C b/applications/solvers/basic/potentialFoam/potentialFoam.C index 5c56133788200eed506481d321c1bf5fd55f84fd..d6dc4b78a55711201c7767804259d4d132e0073d 100644 --- a/applications/solvers/basic/potentialFoam/potentialFoam.C +++ b/applications/solvers/basic/potentialFoam/potentialFoam.C @@ -24,13 +24,64 @@ License Application potentialFoam -Description - Potential flow solver which solves for the velocity potential - from which the flux-field is obtained and velocity field by reconstructing - the flux. +Group + grpBasicSolvers - This application is particularly useful to generate starting fields for - Navier-Stokes codes. +Description + Potential flow solver. + + \heading Solver details + The potential flow solution is typically employed to generate initial fields + for full Navier-Stokes codes. The flow is evolved using the equation: + + \f[ + \laplacian \Phi = \div(\vec{U}) + \f] + + Where: + \vartable + \Phi | Velocity potential [m2/s] + \vec{U} | Velocity [m/s] + \endvartable + + The corresponding pressure field could be calculated from the divergence + of the Euler equation: + + \f[ + \laplacian p + \div(\div(\vec{U}\otimes\vec{U})) = 0 + \f] + + but this generates excessive pressure variation in regions of large + velocity gradient normal to the flow direction. A better option is to + calculate the pressure field corresponding to velocity variation along the + stream-lines: + + \f[ + \laplacian p + \div(\vec{F}\cdot\div(\vec{U}\otimes\vec{U})) = 0 + \f] + where the flow direction tensor \f$\vec{F}\f$ is obtained from + \f[ + \vec{F} = \hat{\vec{U}}\otimes\hat{\vec{U}} + \f] + + \heading Required fields + \plaintable + U | Velocity [m/s] + \endplaintable + + \heading Optional fields + \plaintable + p | Kinematic pressure [m2/s2] + Phi | Velocity potential [m2/s] + | Generated from p (if present) or U if not present + \endplaintable + + \heading Options + \plaintable + -writep | write the Euler pressure + -writePhi | Write the final velocity potential + -initialiseUBCs | Update the velocity boundaries before solving for Phi + \endplaintable \*---------------------------------------------------------------------------*/ @@ -58,19 +109,13 @@ int main(int argc, char *argv[]) argList::addBoolOption ( "writePhi", - "Write the velocity potential field" + "Write the final velocity potential field" ); argList::addBoolOption ( "writep", - "Calculate and write the pressure field" - ); - - argList::addBoolOption - ( - "withFunctionObjects", - "execute functionObjects" + "Calculate and write the Euler pressure field" ); #include "setRootCase.H" @@ -137,7 +182,7 @@ int main(int argc, char *argv[]) Phi.write(); } - // Calculate the pressure field + // Calculate the pressure field from the Euler equation if (args.optionFound("writep")) { Info<< nl << "Calculating approximate pressure field" << endl; diff --git a/applications/utilities/mesh/manipulation/moveDynamicMesh/moveDynamicMesh.C b/applications/utilities/mesh/manipulation/moveDynamicMesh/moveDynamicMesh.C index d2f25bb46f5dc4e39532aeac4e08a37a2aa37b59..2fac9f25c06e80d3101d7eb52b80cf826ae0ad99 100644 --- a/applications/utilities/mesh/manipulation/moveDynamicMesh/moveDynamicMesh.C +++ b/applications/utilities/mesh/manipulation/moveDynamicMesh/moveDynamicMesh.C @@ -32,6 +32,7 @@ Description #include "argList.H" #include "Time.H" #include "dynamicFvMesh.H" +#include "pimpleControl.H" #include "vtkSurfaceWriter.H" #include "cyclicAMIPolyPatch.H" @@ -129,13 +130,23 @@ int main(int argc, char *argv[]) Info<< "Writing VTK files with weights of AMI patches." << nl << endl; } + pimpleControl pimple(mesh); + + bool moveMeshOuterCorrectors + ( + pimple.dict().lookupOrDefault<Switch>("moveMeshOuterCorrectors", false) + ); + while (runTime.loop()) { Info<< "Time = " << runTime.timeName() << endl; - for (int i = 0; i<2; i++) + while (pimple.loop()) { - mesh.update(); + if (pimple.firstIter() || moveMeshOuterCorrectors) + { + mesh.update(); + } } mesh.checkMesh(true); diff --git a/applications/utilities/postProcessing/sampling/sample/sampleDict b/applications/utilities/postProcessing/sampling/sample/sampleDict index 92b1c02e35b983ca4e52f377cdc6bcf2ae5fec76..88c86bf482eda4b44f3d96bca85e4ed6468cebe5 100644 --- a/applications/utilities/postProcessing/sampling/sample/sampleDict +++ b/applications/utilities/postProcessing/sampling/sample/sampleDict @@ -31,18 +31,66 @@ setFormat raw; // dx : DX scalar or vector format // vtk : VTK ascii format // raw : x y z value format for use with e.g. gnuplot 'splot'. +// boundaryData: written in a form that can be used with timeVaryingMapped +// boundary conditions (move to constant/boundaryData) +// starcd : Star-CD format (geometry in .cel/.vrt, data in .usr) +// nastran : Nastran (.nas) format // // Note: -// other formats such as obj, stl, etc can also be written (by proxy) -// but without any values! +// - other formats such as obj, stl, etc can also be written (by proxy) +// but without any values! +// - boundaryData format: typical use: +// - use a surfaces functionObject to sample a patch: +// type surfaces; +// surfaceFormat boundaryData; +// fields ( p ); +// surfaces +// ( +// inlet +// { +// type patch; +// patches (inpletPatch); +// interpolate false; +// } +// ); +// - the boundaryData writer will write postProcessing/surfaces/inlet/ +// - move this to constant/boundaryData/inlet of the destination case +// - use a timeVaryingMappedFixedValue bc to read&interpolate and use +// as fixedValue. +// - boundaryData: 'interpolate false' writes face centres, 'interpolate true' +// writes points. For 2D case the face centres might only be a single column +// so cannot be used in timeVaryingMapped with standard mapping (since +// uses triangulation to do interpolation). + surfaceFormat vtk; -// optionally define extra controls for the output formats +// Optionally define extra controls for the output formats formatOptions { ensight { + // ascii/binary format format ascii; + //collateTimes true; // write single file containing multiple timesteps + // (only for static surfaces) + } + nastran + { + // From OpenFOAM field name to Nastran field name + fields + ( + (U PLOAD4) + (p PLOAD2) + ); + // Optional scale + scale 1.0; + // Optional format + // short/long/free format + // short: scalar field width 8. default. + // long : scalar field width 16 + // free : comma separated, field width according to writePrecision + // setting + format short; // short/long/free } } @@ -143,9 +191,19 @@ sets type patchSeed; axis xyz; patches (".*Wall.*"); - // Number of points to seed. Divided amongst all processors according - // to fraction of patches they hold. + + // Subset patch faces by: + + // 1. Number of points to seed. Divided amongst all processors + // according to fraction of patches they hold. maxPoints 100; + + // 2. Specified set of locations. This selects for every the specified + // point the nearest patch face. (in addition the number of points + // is also truncated by the maxPoints setting) + // The difference with patchCloud is that this selects patch + // face centres, not an arbitrary location on the face. + points ((0.049 0.099 0.005)(0.051 0.054 0.005)); } ); @@ -249,8 +307,10 @@ surfaces isoValue 0.5; interpolate true; - //zone ABC; // Optional: zone only - //exposedPatchName fixedWalls; // Optional: zone only + // zone ABC; // Optional: zone only + // exposedPatchName fixedWalls; // Optional: zone only + + // bounds (1 1 1)(2 2 2); // Optional: limit extent // regularise false; // Optional: do not simplify // mergeTol 1e-10; // Optional: fraction of mesh bounding box @@ -265,6 +325,9 @@ surfaces isoValue 0.5; interpolate false; regularise false; // do not simplify + + // bounds (1 1 1)(2 2 2); // Optional: limit extent + // mergeTol 1e-10; // Optional: fraction of mesh bounding box // to merge points (default=1e-6) } @@ -281,8 +344,10 @@ surfaces } interpolate true; - //zone ABC; // Optional: zone only - //exposedPatchName fixedWalls; // Optional: zone only + // zone ABC; // Optional: zone only + // exposedPatchName fixedWalls; // Optional: zone only + + // bounds (1 1 1)(2 2 2); // Optional: limit extent // regularise false; // Optional: do not simplify // mergeTol 1e-10; // Optional: fraction of mesh bounding box @@ -305,6 +370,8 @@ surfaces // of isoSurfaceCell interpolate false; regularise false; // Optional: do not simplify + // bounds (1 1 1)(2 2 2); // Optional: limit extent + // mergeTol 1e-10; // Optional: fraction of mesh bounding box // to merge points (default=1e-6) } diff --git a/applications/utilities/preProcessing/createExternalCoupledPatchGeometry/addRegionsOption.H b/applications/utilities/preProcessing/createExternalCoupledPatchGeometry/addRegionsOption.H new file mode 100644 index 0000000000000000000000000000000000000000..9f57e35a40ab441841bdb3dddbd5e2a74dc7bd52 --- /dev/null +++ b/applications/utilities/preProcessing/createExternalCoupledPatchGeometry/addRegionsOption.H @@ -0,0 +1,10 @@ +// +// addRegionOption.H +// ~~~~~~~~~~~~~~~~~ + + Foam::argList::addOption + ( + "regions", + "(name1 .. nameN)", + "specify alternative mesh regions" + ); diff --git a/applications/utilities/preProcessing/createExternalCoupledPatchGeometry/createExternalCoupledPatchGeometry.C b/applications/utilities/preProcessing/createExternalCoupledPatchGeometry/createExternalCoupledPatchGeometry.C index 51818b378741ee10d3cf18fa4dac9dc0d0f8a9bf..6a8b78c6837494f75bb4a30a1a419f7fdb26c39b 100644 --- a/applications/utilities/preProcessing/createExternalCoupledPatchGeometry/createExternalCoupledPatchGeometry.C +++ b/applications/utilities/preProcessing/createExternalCoupledPatchGeometry/createExternalCoupledPatchGeometry.C @@ -38,6 +38,11 @@ Usage \param -region \<name\> \n Specify an alternative mesh region. + \param -regions (\<name1\> \<name2\> .. \<namen\>) \n + Specify alternative mesh regions. The region names will be sorted + alphabetically and a single composite name will be created + \<nameX\>_\<nameY\>.._\<nameZ\> + On execution, the combined patch geometry (points and faces) are output to the communications directory. @@ -59,6 +64,7 @@ SeeAlso int main(int argc, char *argv[]) { #include "addRegionOption.H" + #include "addRegionsOption.H" argList::validArgs.append("patchGroup"); argList::addOption ( @@ -68,16 +74,52 @@ int main(int argc, char *argv[]) ); #include "setRootCase.H" #include "createTime.H" - #include "createNamedMesh.H" - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + wordList regionNames(1, fvMesh::defaultRegion); + if (!args.optionReadIfPresent("region", regionNames[0])) + { + args.optionReadIfPresent("regions", regionNames); + } - const wordRe patchGroup(args[1]); + const wordRe patchGroup(args.argRead<wordRe>(1)); fileName commsDir(runTime.path()/"comms"); args.optionReadIfPresent("commsDir", commsDir); - externalCoupledFunctionObject::writeGeometry(mesh, commsDir, patchGroup); + + // Make sure region names are in canonical order + stableSort(regionNames); + + + PtrList<const fvMesh> meshes(regionNames.size()); + forAll(regionNames, i) + { + Info<< "Create mesh " << regionNames[i] << " for time = " + << runTime.timeName() << nl << endl; + + meshes.set + ( + i, + new fvMesh + ( + Foam::IOobject + ( + regionNames[i], + runTime.timeName(), + runTime, + Foam::IOobject::MUST_READ + ) + ) + ); + } + + + externalCoupledFunctionObject::writeGeometry + ( + UPtrList<const fvMesh>(meshes), + commsDir, + patchGroup + ); Info<< "\nEnd\n" << endl; diff --git a/etc/caseDicts/setConstraintTypes b/etc/caseDicts/setConstraintTypes index 6b075c7382577d13a2797aab6fe6f14b0f3dcfd3..95bce1469db47af1ef0c5ae84b1977825c0b50e0 100644 --- a/etc/caseDicts/setConstraintTypes +++ b/etc/caseDicts/setConstraintTypes @@ -39,11 +39,13 @@ nonuniformTransformCyclic processor { type processor; + value $internalField; } processorCyclic { type processorCyclic; + value $internalField; } symmetryPlane diff --git a/src/OpenFOAM/db/error/IOerror.C b/src/OpenFOAM/db/error/IOerror.C index 08f490c0bd8942ede33c5aa85017098f75507596..ee138d80c90e51da8b5bbe27fee24bd0c8304d86 100644 --- a/src/OpenFOAM/db/error/IOerror.C +++ b/src/OpenFOAM/db/error/IOerror.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -174,7 +174,7 @@ void Foam::IOerror::exit(const int) jobInfo.exit(); } - if (abort_) + if (env("FOAM_ABORT")) { abort(); } @@ -215,7 +215,7 @@ void Foam::IOerror::abort() jobInfo.abort(); } - if (abort_) + if (env("FOAM_ABORT")) { Perr<< endl << *this << endl << "\nFOAM aborting (FOAM_ABORT set)\n" << endl; diff --git a/src/OpenFOAM/db/error/error.C b/src/OpenFOAM/db/error/error.C index 91ec556324b285ece7ed8e349c201d69e345402e..f29eafb486d4059c331336e0e18cf4fe4a8416a1 100644 --- a/src/OpenFOAM/db/error/error.C +++ b/src/OpenFOAM/db/error/error.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -40,7 +40,6 @@ Foam::error::error(const string& title) functionName_("unknown"), sourceFileName_("unknown"), sourceFileLineNumber_(0), - abort_(env("FOAM_ABORT")), throwExceptions_(false), messageStreamPtr_(new OStringStream()) { @@ -61,7 +60,6 @@ Foam::error::error(const dictionary& errDict) functionName_(errDict.lookup("functionName")), sourceFileName_(errDict.lookup("sourceFileName")), sourceFileLineNumber_(readLabel(errDict.lookup("sourceFileLineNumber"))), - abort_(env("FOAM_ABORT")), throwExceptions_(false), messageStreamPtr_(new OStringStream()) { @@ -83,7 +81,6 @@ Foam::error::error(const error& err) functionName_(err.functionName_), sourceFileName_(err.sourceFileName_), sourceFileLineNumber_(err.sourceFileLineNumber_), - abort_(err.abort_), throwExceptions_(err.throwExceptions_), messageStreamPtr_(new OStringStream(*err.messageStreamPtr_)) { @@ -173,7 +170,7 @@ void Foam::error::exit(const int errNo) jobInfo.exit(); } - if (abort_) + if (env("FOAM_ABORT")) { abort(); } @@ -214,7 +211,7 @@ void Foam::error::abort() jobInfo.abort(); } - if (abort_) + if (env("FOAM_ABORT")) { Perr<< endl << *this << endl << "\nFOAM aborting (FOAM_ABORT set)\n" << endl; diff --git a/src/OpenFOAM/db/error/error.H b/src/OpenFOAM/db/error/error.H index 97a08b175c612c4f214b1325b6e62296bd4dc014..5626ba4db0d345138ade5481fe48aa0ddbd75f53 100644 --- a/src/OpenFOAM/db/error/error.H +++ b/src/OpenFOAM/db/error/error.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -78,11 +78,10 @@ protected: string sourceFileName_; label sourceFileLineNumber_; - bool abort_; - bool throwExceptions_; OStringStream* messageStreamPtr_; + public: // Constructors diff --git a/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.C b/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.C new file mode 100644 index 0000000000000000000000000000000000000000..8085ccd8f0ca7093040c19ca2e9c3e444fd8c4ad --- /dev/null +++ b/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.C @@ -0,0 +1,242 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2015 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 "triangle.H" +#include "triPoints.H" +#include "plane.H" + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class Point, class PointRef> +template<class AboveOp, class BelowOp> +inline void Foam::triangle<Point, PointRef>::triSliceWithPlane +( + const plane& pl, + const triPoints& tri, + AboveOp& aboveOp, + BelowOp& belowOp +) +{ + // distance to cutting plane + FixedList<scalar, 3> d; + + // determine how many of the points are above the cutting plane + label nPos = 0; + label posI = -1; + label negI = -1; + forAll(tri, i) + { + d[i] = ((tri[i] - pl.refPoint()) & pl.normal()); + + if (d[i] > 0) + { + nPos++; + posI = i; + } + else + { + negI = i; + } + } + + if (nPos == 3) + { + aboveOp(tri); + } + else if (nPos == 2) + { + // point under the plane + label i0 = negI; + + // indices of remaining points + label i1 = d.fcIndex(i0); + label i2 = d.fcIndex(i1); + + // determine the two intersection points + point p01 = planeIntersection(d, tri, i0, i1); + point p02 = planeIntersection(d, tri, i0, i2); + + aboveOp(triPoints(tri[i1], tri[i2], p02)); + aboveOp(triPoints(tri[i1], p02, p01)); + belowOp(triPoints(tri[i0], p01, p02)); + } + else if (nPos == 1) + { + // point above the plane + label i0 = posI; + + // indices of remaining points + label i1 = d.fcIndex(i0); + label i2 = d.fcIndex(i1); + + // determine the two intersection points + point p01 = planeIntersection(d, tri, i0, i1); + point p02 = planeIntersection(d, tri, i0, i2); + + belowOp(triPoints(tri[i1], tri[i2], p02)); + belowOp(triPoints(tri[i1], p02, p01)); + aboveOp(triPoints(tri[i0], p01, p02)); + } + else + { + // All below + belowOp(tri); + } +} + + +template<class Point, class PointRef> +template<class AboveOp, class BelowOp> +inline void Foam::triangle<Point, PointRef>::sliceWithPlane +( + const plane& pl, + AboveOp& aboveOp, + BelowOp& belowOp +) const +{ + triSliceWithPlane(pl, triPoints(a_, b_, c_), aboveOp, belowOp); +} + + +template<class Point, class PointRef> +template<class InsideOp, class OutsideOp> +inline void Foam::triangle<Point, PointRef>::triangleOverlap +( + const vector& n, + const triangle<Point, PointRef>& tgt, + InsideOp& insideOp, + OutsideOp& outsideOp +) const +{ + // There are two possibilities with this algorithm - we either cut + // the outside triangles with all the edges or not (and keep them + // as disconnected triangles). In the first case + // we cannot do any evaluation short cut so we've chosen not to re-cut + // the outside triangles. + + + triIntersectionList insideTrisA; + label nInsideA = 0; + storeOp insideOpA(insideTrisA, nInsideA); + + triIntersectionList outsideTrisA; + label nOutsideA = 0; + storeOp outsideOpA(outsideTrisA, nOutsideA); + + + const triPoints thisTri(a_, b_, c_); + + + // Cut original triangle with tgt edge 0. + // From *this to insideTrisA, outsideTrisA. + { + scalar s = Foam::mag(tgt.b() - tgt.a()); + const plane pl0(tgt.a(), tgt.b(), tgt.b() + s*n); + triSliceWithPlane(pl0, thisTri, insideOpA, outsideOpA); + } + + // Shortcut if nothing cut + + if (insideOpA.nTris_ == 0) + { + outsideOp(thisTri); + return; + } + + if (outsideOpA.nTris_ == 0) + { + insideOp(thisTri); + return; + } + + + // Cut all triangles with edge 1. + // From insideTrisA to insideTrisB, outsideTrisA + + triIntersectionList insideTrisB; + label nInsideB = 0; + storeOp insideOpB(insideTrisB, nInsideB); + + //triIntersectionList outsideTrisB; + //label nOutsideB = 0; + //storeOp outsideOpB(outsideTrisB, nOutsideB); + + { + scalar s = Foam::mag(tgt.c() - tgt.b()); + const plane pl0(tgt.b(), tgt.c(), tgt.c() + s*n); + + for (label i = 0; i < insideOpA.nTris_; i++) + { + const triPoints& tri = insideOpA.tris_[i]; + triSliceWithPlane(pl0, tri, insideOpB, outsideOpA); + } + + //// Recut outside triangles (not necessary if only interested in + //// intersection properties) + //for (label i = 0; i < outsideOpA.nTris_; i++) + //{ + // const triPoints& tri = outsideOpA.tris_[i]; + // triSliceWithPlane(pl0, tri, outsideOpB, outsideOpB); + //} + } + + + // Cut all triangles with edge 2. + // From insideTrisB to insideTrisA, outsideTrisA + { + scalar s = Foam::mag(tgt.a() - tgt.c()); + const plane pl0(tgt.c(), tgt.a(), tgt.a() + s*n); + + insideOpA.nTris_ = 0; + //outsideOpA.nTris_ = 0; + for (label i = 0; i < insideOpB.nTris_; i++) + { + const triPoints& tri = insideOpB.tris_[i]; + triSliceWithPlane(pl0, tri, insideOpA, outsideOpA); + } + + //// Recut outside triangles (not necessary if only interested in + //// intersection properties) + //for (label i = 0; i < outsideOpB.nTris_; i++) + //{ + // const triPoints& tri = outsideOpB.tris_[i]; + // triSliceWithPlane(pl0, tri, outsideOpA, outsideOpA); + //} + } + + // Transfer from A to argument + for (label i = 0; i < insideOpA.nTris_; i++) + { + insideOp(insideOpA.tris_[i]); + } + + for (label i = 0; i < outsideOpA.nTris_; i++) + { + outsideOp(outsideOpA.tris_[i]); + } +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.H b/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.H index 6e8030c797658bb16108b4d32bad9766d3adaf7f..de477d20e05277b6c1f85660643e43d6ecac312a 100644 --- a/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.H +++ b/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -52,6 +52,8 @@ namespace Foam class Istream; class Ostream; +class triPoints; +class plane; // Forward declaration of friend functions and operators @@ -71,6 +73,8 @@ inline Ostream& operator<< const triangle<Point, PointRef>& ); +typedef triangle<point, const point&> triPointRef; + /*---------------------------------------------------------------------------*\ Class triangle Declaration @@ -79,27 +83,98 @@ inline Ostream& operator<< template<class Point, class PointRef> class triangle { +public: + + // Public typedefs + + //- Storage type for triangles originating from intersecting triangle + // with another triangle + typedef FixedList<triPoints, 27> triIntersectionList; + + //- Return types for classify + enum proxType + { + NONE, + POINT, // Close to point + EDGE // Close to edge + }; + + + // Public classes + + // Classes for use in sliceWithPlane. What to do with decomposition + // of triangle. + + //- Dummy + class dummyOp + { + public: + inline void operator()(const triPoints&); + }; + + //- Sum resulting areas + class sumAreaOp + { + public: + scalar area_; + + inline sumAreaOp(); + + inline void operator()(const triPoints&); + }; + + //- Store resulting tris + class storeOp + { + public: + triIntersectionList& tris_; + label& nTris_; + + inline storeOp(triIntersectionList&, label&); + + inline void operator()(const triPoints&); + }; + + +private: + // Private data PointRef a_, b_, c_; -public: + // Private Member Functions - //- Return types for classify - enum proxType - { - NONE, - POINT, // Close to point - EDGE // Close to edge - }; + //- Helper: calculate intersection point + inline static point planeIntersection + ( + const FixedList<scalar, 3>& d, + const triPoints& t, + const label negI, + const label posI + ); + + //- Helper: slice triangle with plane + template<class AboveOp, class BelowOp> + inline static void triSliceWithPlane + ( + const plane& pl, + const triPoints& tri, + AboveOp& aboveOp, + BelowOp& belowOp + ); +public: + // Constructors //- Construct from three points inline triangle(const Point& a, const Point& b, const Point& c); + //- Construct from three points + inline triangle(const FixedList<Point, 3>&); + //- Construct from three points in the list of points // The indices could be from triFace etc. inline triangle @@ -237,6 +312,27 @@ public: pointHit& edgePoint ) const; + //- Decompose triangle into triangles above and below plane + template<class AboveOp, class BelowOp> + inline void sliceWithPlane + ( + const plane& pl, + AboveOp& aboveOp, + BelowOp& belowOp + ) const; + + //- Decompose triangle into triangles inside and outside + // (with respect to user provided normal) other + // triangle. + template<class InsideOp, class OutsideOp> + inline void triangleOverlap + ( + const vector& n, + const triangle<Point, PointRef>& tri, + InsideOp& insideOp, + OutsideOp& outsideOp + ) const; + // IOstream operators @@ -264,6 +360,12 @@ public: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +#ifdef NoRepository +# include "triangle.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + #endif // ************************************************************************* // diff --git a/src/OpenFOAM/meshes/primitiveShapes/triangle/triangleI.H b/src/OpenFOAM/meshes/primitiveShapes/triangle/triangleI.H index fbc5a14286b8d5572dcfadff2d1c0280d4ebcde1..e3f8993e2eac9c4c13515c45defb3c810f6e2eaa 100644 --- a/src/OpenFOAM/meshes/primitiveShapes/triangle/triangleI.H +++ b/src/OpenFOAM/meshes/primitiveShapes/triangle/triangleI.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -25,6 +25,7 @@ License #include "IOstreams.H" #include "pointHit.H" +#include "triPoints.H" #include "mathematicalConstants.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -43,6 +44,18 @@ inline Foam::triangle<Point, PointRef>::triangle {} +template<class Point, class PointRef> +inline Foam::triangle<Point, PointRef>::triangle +( + const FixedList<Point, 3>& tri +) +: + a_(tri[0]), + b_(tri[1]), + c_(tri[2]) +{} + + template<class Point, class PointRef> inline Foam::triangle<Point, PointRef>::triangle ( @@ -804,6 +817,66 @@ inline Foam::pointHit Foam::triangle<Point, PointRef>::nearestPoint } +template<class Point, class PointRef> +inline void Foam::triangle<Point, PointRef>::dummyOp::operator() +( + const triPoints& +) +{} + + +template<class Point, class PointRef> +inline Foam::triangle<Point, PointRef>::sumAreaOp::sumAreaOp() +: + area_(0.0) +{} + + +template<class Point, class PointRef> +inline void Foam::triangle<Point, PointRef>::sumAreaOp::operator() +( + const triPoints& tri +) +{ + area_ += triangle<Point, const Point&>(tri).mag(); +} + + +template<class Point, class PointRef> +inline Foam::triangle<Point, PointRef>::storeOp::storeOp +( + triIntersectionList& tris, + label& nTris +) +: + tris_(tris), + nTris_(nTris) +{} + + +template<class Point, class PointRef> +inline void Foam::triangle<Point, PointRef>::storeOp::operator() +( + const triPoints& tri +) +{ + tris_[nTris_++] = tri; +} + + +template<class Point, class PointRef> +inline Foam::point Foam::triangle<Point, PointRef>::planeIntersection +( + const FixedList<scalar, 3>& d, + const triPoints& t, + const label negI, + const label posI +) +{ + return (d[posI]*t[negI] - d[negI]*t[posI])/(-d[negI] + d[posI]); +} + + // * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * // template<class Point, class PointRef> diff --git a/src/dynamicMesh/motionSmoother/motionSmootherAlgo.C b/src/dynamicMesh/motionSmoother/motionSmootherAlgo.C index d546ff86bb7c5fc347575f8e76220fbf8a45fb99..dbef33a6adfd84465c69fffac763f3c5b64d9765 100644 --- a/src/dynamicMesh/motionSmoother/motionSmootherAlgo.C +++ b/src/dynamicMesh/motionSmoother/motionSmootherAlgo.C @@ -514,12 +514,31 @@ void Foam::motionSmootherAlgo::setDisplacement const labelList& cppMeshPoints = mesh.globalData().coupledPatch().meshPoints(); - forAll(cppMeshPoints, i) + const labelList& ppMeshPoints = pp.meshPoints(); + + // Knock out displacement on points which are not on pp but are coupled + // to them since we want 'proper' values from displacement to take + // precedence. { - displacement[cppMeshPoints[i]] = vector::zero; + PackedBoolList isPatchPoint(mesh.nPoints()); + isPatchPoint.set(ppMeshPoints); + syncTools::syncPointList + ( + mesh, + isPatchPoint, + maxEqOp<unsigned int>(), + 0 + ); + forAll(cppMeshPoints, i) + { + label pointI = cppMeshPoints[i]; + if (isPatchPoint[pointI]) + { + displacement[pointI] = vector::zero; + } + } } - const labelList& ppMeshPoints = pp.meshPoints(); // Set internal point data from displacement on combined patch points. forAll(ppMeshPoints, patchPointI) diff --git a/src/dynamicMesh/motionSmoother/motionSmootherAlgo.H b/src/dynamicMesh/motionSmoother/motionSmootherAlgo.H index 724658012e8cb45e43617c4fdf2b9e8778d12f27..4cc17efdcd2ea67eb1fa064f928ecc0b14e6319a 100644 --- a/src/dynamicMesh/motionSmoother/motionSmootherAlgo.H +++ b/src/dynamicMesh/motionSmoother/motionSmootherAlgo.H @@ -56,7 +56,8 @@ Note and/or edges but no faces of pp). Hence we have to be careful when e.g. synchronising displacements that the value from the processor which has faces of pp get priority. This is currently handled in setDisplacement - by resetting the internal displacement to zero before doing anything + by resetting the internal displacement to zero on coupled points + that are coupled to patch points before doing anything else. The combine operator used will give preference to non-zero values. diff --git a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.C b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.C index a4148b950b5494eb6fa6e48bb12dd12d92d9fc50..b4117c424a6c1adf80dc3960d3570b6cc55bcd0c 100644 --- a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.C +++ b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation + \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -48,12 +48,9 @@ Foam::scalar Foam::layerParameters::layerExpansionRatio return 1.0; } - //scalar totalOverFirst = totalThickness/firstLayerThickess; - - const label maxIters = 10; + const label maxIters = 20; const scalar tol = 1e-8; - if (mag(n-totalOverFirst) < tol) { return 1.0; @@ -74,8 +71,6 @@ Foam::scalar Foam::layerParameters::layerExpansionRatio maxR = totalOverFirst/(n - 1); } - //Info<< "Solution bounds = (" << minR << ", " << maxR << ")" << nl << endl; - // Starting guess scalar r = 0.5*(minR + maxR); @@ -85,14 +80,9 @@ Foam::scalar Foam::layerParameters::layerExpansionRatio const scalar fx = pow(r, n) - totalOverFirst*r - (1 - totalOverFirst); const scalar dfx = n*pow(r, n - 1) - totalOverFirst; - r -= fx/dfx; - const scalar error = mag(r - prevr); - - //Info<< i << " " << r << " Error = " << error << endl; - - if (error < tol) + if (mag(r - prevr) < tol) { break; } @@ -103,7 +93,6 @@ Foam::scalar Foam::layerParameters::layerExpansionRatio // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -// Construct from dictionary Foam::layerParameters::layerParameters ( const dictionary& dict, @@ -417,9 +406,9 @@ Foam::scalar Foam::layerParameters::layerThickness } else { - return firstLayerThickess * - (1.0 - pow(expansionRatio, nLayers)) - / (1.0 - expansionRatio); + return firstLayerThickess + *(1.0 - pow(expansionRatio, nLayers)) + /(1.0 - expansionRatio); } } break; @@ -433,9 +422,9 @@ Foam::scalar Foam::layerParameters::layerThickness else { scalar invExpansion = 1.0 / expansionRatio; - return finalLayerThickess * - (1.0 - pow(invExpansion, nLayers)) - / (1.0 - invExpansion); + return finalLayerThickess + *(1.0 - pow(invExpansion, nLayers)) + /(1.0 - invExpansion); } } break; @@ -484,7 +473,7 @@ Foam::scalar Foam::layerParameters::layerExpansionRatio { return 1.0 - / layerExpansionRatio + /layerExpansionRatio ( nLayers, totalThickness/finalLayerThickess @@ -577,8 +566,8 @@ Foam::scalar Foam::layerParameters::finalLayerThicknessRatio { return pow(expansionRatio, nLayers - 1) - * (1.0 - expansionRatio) - / (1.0 - pow(expansionRatio, nLayers)); + *(1.0 - expansionRatio) + /(1.0 - pow(expansionRatio, nLayers)); } } else diff --git a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.H b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.H index 505fb8b07bd1cd7a0f29e186fb6557ec4546b182..f617916f4739c86bf9969044b581230342486aff 100644 --- a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.H +++ b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/layerParameters/layerParameters.H @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation + \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -333,7 +333,6 @@ public: const label nLayers, const scalar expansionRatio ) const; - }; diff --git a/src/mesh/extrudeModel/planeExtrusion/planeExtrusion.H b/src/mesh/extrudeModel/planeExtrusion/planeExtrusion.H index 9fea06cf2c758c665a84d42c6195b34ab0086265..b832f7e2bede3c8bf524a951b241d3c794f7d049 100644 --- a/src/mesh/extrudeModel/planeExtrusion/planeExtrusion.H +++ b/src/mesh/extrudeModel/planeExtrusion/planeExtrusion.H @@ -33,8 +33,8 @@ SeeAlso \*---------------------------------------------------------------------------*/ -#ifndef plane_H -#define plane_H +#ifndef planeExtrusion_H +#define planeExtrusion_H #include "linearNormal.H" diff --git a/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatch.C b/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatch.C index 7a862ee9dacab94dc75585403ed937b5e0075c80..84028ebef507b440fef255669dbeebc861706000 100644 --- a/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatch.C +++ b/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatch.C @@ -44,7 +44,7 @@ const Foam::scalar Foam::cyclicACMIPolyPatch::tolerance_ = 1e-6; void Foam::cyclicACMIPolyPatch::initPatchFaceAreas() const { - if (!empty() && faceAreas0_.empty()) + if (!empty() && (faceAreas0_.empty() || boundaryMesh().mesh().moving())) { faceAreas0_ = faceAreas(); } @@ -52,9 +52,13 @@ void Foam::cyclicACMIPolyPatch::initPatchFaceAreas() const const cyclicACMIPolyPatch& nbrACMI = refCast<const cyclicACMIPolyPatch>(this->neighbPatch()); - if (!nbrACMI.empty() && nbrACMI.faceAreas0().empty()) + if + ( + !nbrACMI.empty() + && (nbrACMI.faceAreas0().empty() || boundaryMesh().mesh().moving()) + ) { - nbrACMI.initPatchFaceAreas(); + nbrACMI.faceAreas0_ = nbrACMI.faceAreas(); } } @@ -136,11 +140,13 @@ void Foam::cyclicACMIPolyPatch::setNeighbourFaceAreas() const void Foam::cyclicACMIPolyPatch::initGeometry(PstreamBuffers& pBufs) { + // Note: cyclicAMIPolyPatch clears AMI so do first + cyclicAMIPolyPatch::initGeometry(pBufs); + // Initialise the AMI so that base geometry (e.g. cell volumes) are - // correctly evaluated + // correctly evaluated before e.g. any of the processor patches gets + // hit (since uses cell volumes in its initGeometry) resetAMI(); - - cyclicAMIPolyPatch::initGeometry(pBufs); } @@ -156,7 +162,13 @@ void Foam::cyclicACMIPolyPatch::initMovePoints const pointField& p ) { + // Note: cyclicAMIPolyPatch clears AMI so do first cyclicAMIPolyPatch::initMovePoints(pBufs, p); + + // Initialise the AMI so that base geometry (e.g. cell volumes) are + // correctly evaluated before e.g. any of the processor patches gets + // hit (since uses cell volumes in its initGeometry) + resetAMI(); } diff --git a/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatchTemplates.C b/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatchTemplates.C index 231a2e0ba7a2ad673628c5afad7db19bb0b88def..a3a3707e015219e6cb4f59e24ee876660b63dbb9 100644 --- a/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatchTemplates.C +++ b/src/meshTools/AMIInterpolation/patches/cyclicACMI/cyclicACMIPolyPatch/cyclicACMIPolyPatchTemplates.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2013-2014 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -37,7 +37,7 @@ Foam::tmp<Foam::Field<Type> > Foam::cyclicACMIPolyPatch::interpolate if (owner()) { - const scalarField& w = srcMask_; + const scalarField& w = AMI().srcWeightsSum(); tmp<Field<Type> > interpField(AMI().interpolateToSource(fldCouple)); @@ -45,7 +45,7 @@ Foam::tmp<Foam::Field<Type> > Foam::cyclicACMIPolyPatch::interpolate } else { - const scalarField& w = neighbPatch().tgtMask(); + const scalarField& w = neighbPatch().AMI().tgtWeightsSum(); tmp<Field<Type> > interpField ( @@ -82,16 +82,18 @@ void Foam::cyclicACMIPolyPatch::interpolate if (owner()) { - const scalarField& w = srcMask_; + const scalarField& w = AMI().srcWeightsSum(); AMI().interpolateToSource(fldCouple, cop, result); + result = result + (1.0 - w)*fldNonOverlap; } else { - const scalarField& w = neighbPatch().tgtMask(); + const scalarField& w = neighbPatch().AMI().tgtWeightsSum(); neighbPatch().AMI().interpolateToTarget(fldCouple, cop, result); + result = result + (1.0 - w)*fldNonOverlap; } } diff --git a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C index f58e99ce0e01e65646c8275b51513334e48eaef0..b8f9b3b2c0fbc8a24997a07a754a6f27dd737bae 100644 --- a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C +++ b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C @@ -24,9 +24,13 @@ License \*---------------------------------------------------------------------------*/ #include "cyclicAMIPolyPatch.H" +#include "transformField.H" #include "SubField.H" +#include "polyMesh.H" #include "Time.H" #include "addToRunTimeSelectionTable.H" +#include "faceAreaIntersect.H" +#include "ops.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -172,18 +176,19 @@ void Foam::cyclicAMIPolyPatch::calcTransforms scalar errorPos = mag(transformedAreaPos + area0); scalar errorNeg = mag(transformedAreaNeg + area0); - if (errorPos < errorNeg) - { - revT = revTPos; - } - else + scalar scaledErrorPos = errorPos/(mag(area0) + ROOTVSMALL); + scalar scaledErrorNeg = errorNeg/(mag(area0) + ROOTVSMALL); + + // One of the errors should be (close to) zero. If this is + // the reverse transformation flip the rotation angle. + revT = revTPos; + if (errorPos > errorNeg && scaledErrorNeg <= matchTolerance()) { revT = revTNeg; rotationAngle_ *= -1; } - scalar areaError = - min(errorPos, errorNeg)/(mag(area0) + ROOTVSMALL); + scalar areaError = min(scaledErrorPos, scaledErrorNeg); if (areaError > matchTolerance()) { @@ -406,6 +411,9 @@ void Foam::cyclicAMIPolyPatch::resetAMI void Foam::cyclicAMIPolyPatch::initGeometry(PstreamBuffers& pBufs) { + // The AMI is no longer valid. Leave it up to demand-driven calculation + AMIPtr_.clear(); + polyPatch::initGeometry(pBufs); } @@ -431,6 +439,9 @@ void Foam::cyclicAMIPolyPatch::initMovePoints const pointField& p ) { + // The AMI is no longer valid. Leave it up to demand-driven calculation + AMIPtr_.clear(); + polyPatch::initMovePoints(pBufs, p); // See below. Clear out any local geometry @@ -447,19 +458,15 @@ void Foam::cyclicAMIPolyPatch::movePoints polyPatch::movePoints(pBufs, p); calcTransforms(); - - // Note: resetAMI is called whilst in geometry update. So the slave - // side might not have reached 'movePoints'. Is explicitly handled by - // - clearing geometry of neighbour inside initMovePoints - // - not using localPoints() inside resetAMI - resetAMI(); } void Foam::cyclicAMIPolyPatch::initUpdateMesh(PstreamBuffers& pBufs) { - polyPatch::initUpdateMesh(pBufs); + // The AMI is no longer valid. Leave it up to demand-driven calculation AMIPtr_.clear(); + + polyPatch::initUpdateMesh(pBufs); } diff --git a/src/meshTools/regionSplit/regionSplit.C b/src/meshTools/regionSplit/regionSplit.C index 2583c2ddfe8540b730b718c0ea17448301e9b98d..1a8de0fa152526c37959375d28df6f9fcb638c6e 100644 --- a/src/meshTools/regionSplit/regionSplit.C +++ b/src/meshTools/regionSplit/regionSplit.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -28,6 +28,8 @@ License #include "processorPolyPatch.H" #include "globalIndex.H" #include "syncTools.H" +#include "FaceCellWave.H" +#include "minData.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -40,524 +42,243 @@ defineTypeNameAndDebug(regionSplit, 0); // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -// Handle (non-processor) coupled faces. -void Foam::regionSplit::transferCoupledFaceRegion +void Foam::regionSplit::calcNonCompactRegionSplit ( - const label faceI, - const label otherFaceI, + const globalIndex& globalFaces, + const boolList& blockedFace, + const List<labelPair>& explicitConnections, - labelList& faceRegion, - DynamicList<label>& newChangedFaces + labelList& cellRegion ) const { - if (faceRegion[faceI] >= 0) - { - if (faceRegion[otherFaceI] == -1) - { - faceRegion[otherFaceI] = faceRegion[faceI]; - newChangedFaces.append(otherFaceI); - } - else if (faceRegion[otherFaceI] == -2) - { - // otherFaceI blocked but faceI is not. Is illegal for coupled - // faces, not for explicit connections. - } - else if (faceRegion[otherFaceI] != faceRegion[faceI]) - { - FatalErrorIn - ( - "regionSplit::transferCoupledFaceRegion" - "(const label, const label, labelList&, labelList&) const" - ) << "Problem : coupled face " << faceI - << " on patch " << mesh().boundaryMesh().whichPatch(faceI) - << " has region " << faceRegion[faceI] - << " but coupled face " << otherFaceI - << " has region " << faceRegion[otherFaceI] - << endl - << "Is your blocked faces specification" - << " synchronized across coupled boundaries?" - << abort(FatalError); - } - } - else if (faceRegion[faceI] == -1) + // Field on cells and faces. + List<minData> cellData(mesh().nCells()); + List<minData> faceData(mesh().nFaces()); + + // Take over blockedFaces by seeding a negative number + // (so is always less than the decomposition) + label nUnblocked = 0; + forAll(faceData, faceI) { - if (faceRegion[otherFaceI] >= 0) + if (blockedFace.size() && blockedFace[faceI]) { - faceRegion[faceI] = faceRegion[otherFaceI]; - newChangedFaces.append(faceI); + faceData[faceI] = minData(-2); } - else if (faceRegion[otherFaceI] == -2) + else { - // otherFaceI blocked but faceI is not. Is illegal for coupled - // faces, not for explicit connections. + nUnblocked++; } } -} - - -void Foam::regionSplit::fillSeedMask -( - const List<labelPair>& explicitConnections, - labelList& cellRegion, - labelList& faceRegion, - const label seedCellID, - const label markValue -) const -{ - // Do seed cell - cellRegion[seedCellID] = markValue; - - // Collect faces on seed cell - const cell& cFaces = mesh().cells()[seedCellID]; + // Seed unblocked faces + labelList seedFaces(nUnblocked); + List<minData> seedData(nUnblocked); + nUnblocked = 0; - label nFaces = 0; - labelList changedFaces(cFaces.size()); - - forAll(cFaces, i) + forAll(faceData, faceI) { - label faceI = cFaces[i]; - - if (faceRegion[faceI] == -1) + if (blockedFace.empty() || !blockedFace[faceI]) { - faceRegion[faceI] = markValue; - changedFaces[nFaces++] = faceI; + seedFaces[nUnblocked] = faceI; + // Seed face with globally unique number + seedData[nUnblocked] = minData(globalFaces.toGlobal(faceI)); + nUnblocked++; } } - changedFaces.setSize(nFaces); - - // Loop over changed faces. FaceCellWave in small. - while (changedFaces.size()) - { - //if (debug) - //{ - // Pout<< "regionSplit::fillSeedMask : changedFaces:" - // << changedFaces.size() << endl; - //} + // Propagate information inwards + FaceCellWave<minData> deltaCalc + ( + mesh(), + explicitConnections, + false, // disable walking through cyclicAMI for backwards compatibility + seedFaces, + seedData, + faceData, + cellData, + mesh().globalData().nTotalCells()+1 + ); - DynamicList<label> changedCells(changedFaces.size()); - forAll(changedFaces, i) + // And extract + cellRegion.setSize(mesh().nCells()); + forAll(cellRegion, cellI) + { + if (cellData[cellI].valid(deltaCalc.data())) { - label faceI = changedFaces[i]; - - label own = mesh().faceOwner()[faceI]; - - if (cellRegion[own] == -1) - { - cellRegion[own] = markValue; - changedCells.append(own); - } - - if (mesh().isInternalFace(faceI)) - { - label nei = mesh().faceNeighbour()[faceI]; - - if (cellRegion[nei] == -1) - { - cellRegion[nei] = markValue; - changedCells.append(nei); - } - } + cellRegion[cellI] = cellData[cellI].data(); } - - - //if (debug) - //{ - // Pout<< "regionSplit::fillSeedMask : changedCells:" - // << changedCells.size() << endl; - //} - - // Loop over changedCells and collect faces - DynamicList<label> newChangedFaces(changedCells.size()); - - forAll(changedCells, i) + else { - label cellI = changedCells[i]; - + // Unvisited cell -> only possible if surrounded by blocked faces. + // If so make up region from any of the faces const cell& cFaces = mesh().cells()[cellI]; + label faceI = cFaces[0]; - forAll(cFaces, cFaceI) + if (blockedFace.size() && !blockedFace[faceI]) { - label faceI = cFaces[cFaceI]; - - if (faceRegion[faceI] == -1) - { - faceRegion[faceI] = markValue; - newChangedFaces.append(faceI); - } - } - } - - - //if (debug) - //{ - // Pout<< "regionSplit::fillSeedMask : changedFaces before sync:" - // << changedFaces.size() << endl; - //} - - - // Check for changes to any locally coupled face. - // Global connections are done later. - - const polyBoundaryMesh& patches = mesh().boundaryMesh(); - - forAll(patches, patchI) - { - const polyPatch& pp = patches[patchI]; - - if - ( - isA<cyclicPolyPatch>(pp) - && refCast<const cyclicPolyPatch>(pp).owner() - ) - { - // Transfer from neighbourPatch to here or vice versa. - - const cyclicPolyPatch& cycPatch = - refCast<const cyclicPolyPatch>(pp); - - label faceI = cycPatch.start(); - - forAll(cycPatch, i) - { - label otherFaceI = cycPatch.transformGlobalFace(faceI); - - transferCoupledFaceRegion - ( - faceI, - otherFaceI, - faceRegion, - newChangedFaces - ); - - faceI++; - } + FatalErrorIn("regionSplit::calcNonCompactRegionSplit(..)") + << "Problem: unblocked face " << faceI + << " at " << mesh().faceCentres()[faceI] + << " on unassigned cell " << cellI + << mesh().cellCentres()[faceI] + << exit(FatalError); } + cellRegion[cellI] = globalFaces.toGlobal(faceI); } - forAll(explicitConnections, i) - { - transferCoupledFaceRegion - ( - explicitConnections[i][0], - explicitConnections[i][1], - faceRegion, - newChangedFaces - ); - } - - //if (debug) - //{ - // Pout<< "regionSplit::fillSeedMask : changedFaces after sync:" - // << newChangedFaces.size() << endl; - //} - - changedFaces.transfer(newChangedFaces); } } -Foam::label Foam::regionSplit::calcLocalRegionSplit +Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::calcRegionSplit ( + const bool doGlobalRegions, const boolList& blockedFace, const List<labelPair>& explicitConnections, labelList& cellRegion ) const { - if (debug) - { - if (blockedFace.size()) - { - // Check that blockedFace is synced. - boolList syncBlockedFace(blockedFace); - syncTools::swapFaceList(mesh(), syncBlockedFace); - - forAll(syncBlockedFace, faceI) - { - if (syncBlockedFace[faceI] != blockedFace[faceI]) - { - FatalErrorIn - ( - "regionSplit::calcLocalRegionSplit(..)" - ) << "Face " << faceI << " not synchronised. My value:" - << blockedFace[faceI] << " coupled value:" - << syncBlockedFace[faceI] - << abort(FatalError); - } - } - } - } - - // Region per face. - // -1 unassigned - // -2 blocked - labelList faceRegion(mesh().nFaces(), -1); - - if (blockedFace.size()) - { - forAll(blockedFace, faceI) - { - if (blockedFace[faceI]) - { - faceRegion[faceI] = -2; - } - } - } - - - // Assign local regions - // ~~~~~~~~~~~~~~~~~~~~ - - // Start with region 0 - label nLocalRegions = 0; + // See header in regionSplit.H - label unsetCellI = 0; - do + if (!doGlobalRegions) { - // Find first unset cell + // Block all parallel faces to avoid comms across + boolList coupledOrBlockedFace(blockedFace); + const polyBoundaryMesh& pbm = mesh().boundaryMesh(); - for (; unsetCellI < mesh().nCells(); unsetCellI++) + if (coupledOrBlockedFace.size()) { - if (cellRegion[unsetCellI] == -1) + forAll(pbm, patchI) { - break; + const polyPatch& pp = pbm[patchI]; + if (isA<processorPolyPatch>(pp)) + { + label faceI = pp.start(); + forAll(pp, i) + { + coupledOrBlockedFace[faceI++] = true; + } + } } } - if (unsetCellI >= mesh().nCells()) + // Create dummy (local only) globalIndex + labelList offsets(Pstream::nProcs()+1, 0); + for (label i = Pstream::myProcNo()+1; i < offsets.size(); i++) { - break; + offsets[i] = mesh().nFaces(); } + const globalIndex globalRegions(offsets.xfer()); - fillSeedMask + // Minimise regions across connected cells + // Note: still uses global decisions so all processors are running + // in lock-step, i.e. slowest determines overall time. + // To avoid this we could switch off Pstream::parRun. + calcNonCompactRegionSplit ( + globalRegions, + coupledOrBlockedFace, explicitConnections, - cellRegion, - faceRegion, - unsetCellI, - nLocalRegions + cellRegion ); - // Current unsetCell has now been handled. Go to next region. - nLocalRegions++; - unsetCellI++; - } - while (true); - - - if (debug) - { + // Compact + Map<label> globalToCompact(mesh().nCells()/8); forAll(cellRegion, cellI) { - if (cellRegion[cellI] < 0) + label region = cellRegion[cellI]; + + label globalRegion; + + Map<label>::const_iterator fnd = globalToCompact.find(region); + if (fnd == globalToCompact.end()) { - FatalErrorIn("regionSplit::calcLocalRegionSplit(..)") - << "cell:" << cellI << " region:" << cellRegion[cellI] - << abort(FatalError); + globalRegion = globalRegions.toGlobal(globalToCompact.size()); + globalToCompact.insert(region, globalRegion); } + else + { + globalRegion = fnd(); + } + cellRegion[cellI] = globalRegion; } - forAll(faceRegion, faceI) + + // Return globalIndex with size = localSize and all regions local + labelList compactOffsets(Pstream::nProcs()+1, 0); + for (label i = Pstream::myProcNo()+1; i < compactOffsets.size(); i++) { - if (faceRegion[faceI] == -1) - { - FatalErrorIn("regionSplit::calcLocalRegionSplit(..)") - << "face:" << faceI << " region:" << faceRegion[faceI] - << abort(FatalError); - } + compactOffsets[i] = globalToCompact.size(); } + + return autoPtr<globalIndex>(new globalIndex(compactOffsets.xfer())); } - return nLocalRegions; -} -Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::calcRegionSplit -( - const bool doGlobalRegions, - const boolList& blockedFace, - const List<labelPair>& explicitConnections, - - labelList& cellRegion -) const -{ - // See header in regionSplit.H + // Initial global region numbers + const globalIndex globalRegions(mesh().nFaces()); - // 1. Do local analysis - label nLocalRegions = calcLocalRegionSplit + // Minimise regions across connected cells (including parallel) + calcNonCompactRegionSplit ( + globalRegions, blockedFace, explicitConnections, cellRegion ); - if (!doGlobalRegions) - { - return autoPtr<globalIndex>(new globalIndex(nLocalRegions)); - } - - // 2. Assign global regions - // ~~~~~~~~~~~~~~~~~~~~~~~~ - // Offset local regions to create unique global regions. + // Now our cellRegion will have + // - non-local regions (i.e. originating from other processors) + // - non-compact locally originating regions + // so we'll need to compact - globalIndex globalRegions(nLocalRegions); - - - // Convert regions to global ones - forAll(cellRegion, cellI) + // 4a: count per originating processor the number of regions + labelList nOriginating(Pstream::nProcs(), 0); { - cellRegion[cellI] = globalRegions.toGlobal(cellRegion[cellI]); - } - - - // 3. Merge global regions - // ~~~~~~~~~~~~~~~~~~~~~~~ - // Regions across non-blocked proc patches get merged. - // This will set merged global regions to be the min of both. - // (this will create gaps in the global region list so they will get - // merged later on) - - while (true) - { - if (debug) - { - Pout<< nl << "-- Starting Iteration --" << endl; - } - + labelHashSet haveRegion(mesh().nCells()/8); - const polyBoundaryMesh& patches = mesh().boundaryMesh(); - - labelList nbrRegion(mesh().nFaces()-mesh().nInternalFaces(), -1); - forAll(patches, patchI) + forAll(cellRegion, cellI) { - const polyPatch& pp = patches[patchI]; + label region = cellRegion[cellI]; - if (pp.coupled()) + // Count originating processor. Use isLocal as efficiency since + // most cells are locally originating. + if (globalRegions.isLocal(region)) { - const labelList& patchCells = pp.faceCells(); - SubList<label> patchNbrRegion - ( - nbrRegion, - pp.size(), - pp.start()-mesh().nInternalFaces() - ); - - forAll(patchCells, i) + if (haveRegion.insert(region)) { - label faceI = pp.start()+i; - if (!blockedFace.size() || !blockedFace[faceI]) - { - patchNbrRegion[i] = cellRegion[patchCells[i]]; - } + nOriginating[Pstream::myProcNo()]++; } } - } - syncTools::swapBoundaryFaceList(mesh(), nbrRegion); - - Map<label> globalToMerged(mesh().nFaces()-mesh().nInternalFaces()); - - forAll(patches, patchI) - { - const polyPatch& pp = patches[patchI]; - - if (pp.coupled()) + else { - const labelList& patchCells = pp.faceCells(); - SubList<label> patchNbrRegion - ( - nbrRegion, - pp.size(), - pp.start()-mesh().nInternalFaces() - ); - - forAll(patchCells, i) + label procI = globalRegions.whichProcID(region); + if (haveRegion.insert(region)) { - label faceI = pp.start()+i; - - if (!blockedFace.size() || !blockedFace[faceI]) - { - if (patchNbrRegion[i] < cellRegion[patchCells[i]]) - { - //Pout<< "on patch:" << pp.name() - // << " cell:" << patchCells[i] - // << " at:" - // << mesh().cellCentres()[patchCells[i]] - // << " was:" << cellRegion[patchCells[i]] - // << " nbr:" << patchNbrRegion[i] - // << endl; - - globalToMerged.insert - ( - cellRegion[patchCells[i]], - patchNbrRegion[i] - ); - } - } + nOriginating[procI]++; } } } - - - label nMerged = returnReduce(globalToMerged.size(), sumOp<label>()); - - if (debug) - { - Pout<< "nMerged:" << nMerged << endl; - } - - if (nMerged == 0) - { - break; - } - - // Renumber the regions according to the globalToMerged - forAll(cellRegion, cellI) - { - label regionI = cellRegion[cellI]; - Map<label>::const_iterator iter = globalToMerged.find(regionI); - if (iter != globalToMerged.end()) - { - cellRegion[cellI] = iter(); - } - } - } - - - // Now our cellRegion will have non-local elements in it. So compact - // it. - - // 4a: count. Use a labelHashSet to count regions only once. - label nCompact = 0; - { - labelHashSet localRegion(mesh().nFaces()-mesh().nInternalFaces()); - forAll(cellRegion, cellI) - { - if - ( - globalRegions.isLocal(cellRegion[cellI]) - && localRegion.insert(cellRegion[cellI]) - ) - { - nCompact++; - } - } } if (debug) { - Pout<< "Compacted from " << nLocalRegions - << " down to " << nCompact << " local regions." << endl; + Pout<< "Counted " << nOriginating[Pstream::myProcNo()] + << " local regions." << endl; } // Global numbering for compacted local regions - autoPtr<globalIndex> globalCompactPtr(new globalIndex(nCompact)); + autoPtr<globalIndex> globalCompactPtr + ( + new globalIndex(nOriginating[Pstream::myProcNo()]) + ); const globalIndex& globalCompact = globalCompactPtr(); @@ -568,12 +289,15 @@ Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::calcRegionSplit // labelList. // Local compaction map - Map<label> globalToCompact(2*nCompact); + Map<label> globalToCompact(2*nOriginating[Pstream::myProcNo()]); // Remote regions we want the compact number for List<labelHashSet> nonLocal(Pstream::nProcs()); forAll(nonLocal, procI) { - nonLocal[procI].resize((nLocalRegions-nCompact)/Pstream::nProcs()); + if (procI != Pstream::myProcNo()) + { + nonLocal[procI].resize(2*nOriginating[procI]); + } } forAll(cellRegion, cellI) @@ -581,15 +305,12 @@ Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::calcRegionSplit label region = cellRegion[cellI]; if (globalRegions.isLocal(region)) { - Map<label>::const_iterator iter = globalToCompact.find(region); - if (iter == globalToCompact.end()) - { - label compactRegion = globalCompact.toGlobal - ( - globalToCompact.size() - ); - globalToCompact.insert(region, compactRegion); - } + // Insert new compact region (if not yet present) + globalToCompact.insert + ( + region, + globalCompact.toGlobal(globalToCompact.size()) + ); } else { @@ -603,22 +324,17 @@ Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::calcRegionSplit // Convert the nonLocal (labelHashSets) to labelLists. labelListList sendNonLocal(Pstream::nProcs()); - labelList nNonLocal(Pstream::nProcs(), 0); forAll(sendNonLocal, procI) { - sendNonLocal[procI].setSize(nonLocal[procI].size()); - forAllConstIter(labelHashSet, nonLocal[procI], iter) - { - sendNonLocal[procI][nNonLocal[procI]++] = iter.key(); - } + sendNonLocal[procI] = nonLocal[procI].toc(); } if (debug) { - forAll(nNonLocal, procI) + forAll(sendNonLocal, procI) { Pout<< " from processor " << procI - << " want " << nNonLocal[procI] + << " want " << sendNonLocal[procI].size() << " region numbers." << endl; } @@ -627,7 +343,7 @@ Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::calcRegionSplit // Get the wanted region labels into recvNonLocal - labelListList recvNonLocal; + labelListList recvNonLocal(Pstream::nProcs()); labelListList sizes; Pstream::exchange<labelList, label> ( @@ -655,6 +371,7 @@ Foam::autoPtr<Foam::globalIndex> Foam::regionSplit::calcRegionSplit // Send back (into recvNonLocal) recvNonLocal.clear(); + recvNonLocal.setSize(sendWantedLocal.size()); sizes.clear(); Pstream::exchange<labelList, label> ( diff --git a/src/meshTools/regionSplit/regionSplit.H b/src/meshTools/regionSplit/regionSplit.H index 83302529df24349890b4c4425d21fe4a0c5dfdae..543259a10bfeeb6345e4b84ab9138e84676605d0 100644 --- a/src/meshTools/regionSplit/regionSplit.H +++ b/src/meshTools/regionSplit/regionSplit.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -89,6 +89,9 @@ Description Can optionally keep all regions local to the processor. + Note: does not walk across cyclicAMI/cyclicACMI - since not 'coupled()' + at the patch level. + SourceFiles regionSplit.C @@ -126,30 +129,10 @@ class regionSplit // Private Member Functions - //- Transfer faceRegion data from one face to the other (or vice versa) - void transferCoupledFaceRegion - ( - const label faceI, - const label otherFaceI, - - labelList& faceRegion, - DynamicList<label>& newChangedFaces - ) const; - - //- Given a seed cell label, fill cellRegion/faceRegion with markValue - // for contiguous region around it - void fillSeedMask - ( - const List<labelPair>& explicitConnections, - labelList& cellRegion, - labelList& faceRegion, - const label seedCellID, - const label markValue - ) const; - - //- Calculate local region split. Return number of regions. - label calcLocalRegionSplit + //- Calculate region split in non-compact (global) numbering. + void calcNonCompactRegionSplit ( + const globalIndex& globalFaces, const boolList& blockedFace, const List<labelPair>& explicitConnections, labelList& cellRegion diff --git a/src/postProcessing/functionObjects/jobControl/externalCoupled/externalCoupledFunctionObject.C b/src/postProcessing/functionObjects/jobControl/externalCoupled/externalCoupledFunctionObject.C index ca7e2d3951d40e63de4a97b2e1f2c668ce05ed77..ca9905c03717e75df374a93b11b13657af3c7269 100644 --- a/src/postProcessing/functionObjects/jobControl/externalCoupled/externalCoupledFunctionObject.C +++ b/src/postProcessing/functionObjects/jobControl/externalCoupled/externalCoupledFunctionObject.C @@ -31,6 +31,7 @@ License #include "volFields.H" #include "globalIndex.H" #include "fvMesh.H" +#include "DynamicField.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -65,11 +66,16 @@ Foam::fileName Foam::externalCoupledFunctionObject::baseDir() const Foam::fileName Foam::externalCoupledFunctionObject::groupDir ( const fileName& commsDir, - const word& regionName, + const word& regionGroupName, const wordRe& groupName ) { - fileName result(commsDir/regionName/string::validate<fileName>(groupName)); + fileName result + ( + commsDir + /regionGroupName + /string::validate<fileName>(groupName) + ); result.clean(); return result; @@ -126,11 +132,11 @@ void Foam::externalCoupledFunctionObject::removeReadFiles() const if (log_) Info<< type() << ": removing all read files" << endl; - forAll(regionNames_, regionI) + forAll(regionGroupNames_, regionI) { - const word& regionName = regionNames_[regionI]; - const fvMesh& mesh = time_.lookupObject<fvMesh>(regionName); - const labelList& groups = regionToGroups_[regionName]; + const word& compName = regionGroupNames_[regionI]; + + const labelList& groups = regionToGroups_[compName]; forAll(groups, i) { label groupI = groups[i]; @@ -141,7 +147,7 @@ void Foam::externalCoupledFunctionObject::removeReadFiles() const const word& fieldName = groupReadFields_[groupI][fieldI]; rm ( - groupDir(commsDir_, mesh.dbDir(), groupName) + groupDir(commsDir_, compName, groupName) / fieldName + ".in" ); } @@ -159,22 +165,22 @@ void Foam::externalCoupledFunctionObject::removeWriteFiles() const if (log_) Info<< type() << ": removing all write files" << endl; - forAll(regionNames_, regionI) + forAll(regionGroupNames_, regionI) { - const word& regionName = regionNames_[regionI]; - const fvMesh& mesh = time_.lookupObject<fvMesh>(regionName); - const labelList& groups = regionToGroups_[regionName]; + const word& compName = regionGroupNames_[regionI]; + + const labelList& groups = regionToGroups_[compName]; forAll(groups, i) { label groupI = groups[i]; const wordRe& groupName = groupNames_[groupI]; - forAll(groupWriteFields_[groupI], fieldI) + forAll(groupReadFields_[groupI], fieldI) { - const word& fieldName = groupWriteFields_[groupI][fieldI]; + const word& fieldName = groupReadFields_[groupI][fieldI]; rm ( - groupDir(commsDir_, mesh.dbDir(), groupName) + groupDir(commsDir_, compName, groupName) / fieldName + ".out" ); } @@ -376,12 +382,21 @@ void Foam::externalCoupledFunctionObject::readLines void Foam::externalCoupledFunctionObject::writeGeometry ( - const fvMesh& mesh, + const UPtrList<const fvMesh>& meshes, const fileName& commsDir, const wordRe& groupName ) { - fileName dir(groupDir(commsDir, mesh.dbDir(), groupName)); + wordList regionNames(meshes.size()); + forAll(meshes, i) + { + regionNames[i] = meshes[i].dbDir(); + } + + // Make sure meshes are provided in sorted order + checkOrder(regionNames); + + fileName dir(groupDir(commsDir, compositeName(regionNames), groupName)); //if (log_) { @@ -397,99 +412,210 @@ void Foam::externalCoupledFunctionObject::writeGeometry osFacesPtr.reset(new OFstream(dir/"patchFaces")); } - const labelList patchIDs - ( - mesh.boundaryMesh().patchSet - ( - List<wordRe>(1, groupName) - ).sortedToc() - ); - forAll(patchIDs, i) + DynamicList<face> allMeshesFaces; + DynamicField<point> allMeshesPoints; + + forAll(meshes, meshI) { - label patchI = patchIDs[i]; + const fvMesh& mesh = meshes[meshI]; + + const labelList patchIDs + ( + mesh.boundaryMesh().patchSet + ( + List<wordRe>(1, groupName) + ).sortedToc() + ); + + // Count faces + label nFaces = 0; + forAll(patchIDs, i) + { + nFaces += mesh.boundaryMesh()[patchIDs[i]].size(); + } + + // Collect faces + DynamicList<label> allFaceIDs(nFaces); + forAll(patchIDs, i) + { + const polyPatch& p = mesh.boundaryMesh()[patchIDs[i]]; + + forAll(p, pI) + { + allFaceIDs.append(p.start()+pI); + } + } - const polyPatch& p = mesh.boundaryMesh()[patchI]; + // Construct overall patch + indirectPrimitivePatch allPatch + ( + IndirectList<face>(mesh.faces(), allFaceIDs), + mesh.points() + ); labelList pointToGlobal; labelList uniquePointIDs; mesh.globalData().mergePoints ( - p.meshPoints(), - p.meshPointMap(), + allPatch.meshPoints(), + allPatch.meshPointMap(), pointToGlobal, uniquePointIDs ); label procI = Pstream::myProcNo(); - List<pointField> allPoints(Pstream::nProcs()); - allPoints[procI] = pointField(mesh.points(), uniquePointIDs); - Pstream::gatherList(allPoints); + List<pointField> collectedPoints(Pstream::nProcs()); + collectedPoints[procI] = pointField(mesh.points(), uniquePointIDs); + Pstream::gatherList(collectedPoints); - List<faceList> allFaces(Pstream::nProcs()); - faceList& patchFaces = allFaces[procI]; - patchFaces = p.localFaces(); + List<faceList> collectedFaces(Pstream::nProcs()); + faceList& patchFaces = collectedFaces[procI]; + patchFaces = allPatch.localFaces(); forAll(patchFaces, faceI) { inplaceRenumber(pointToGlobal, patchFaces[faceI]); } - Pstream::gatherList(allFaces); + Pstream::gatherList(collectedFaces); if (Pstream::master()) { - pointField pts - ( - ListListOps::combine<pointField> - ( - allPoints, - accessOp<pointField>() - ) - ); + // Append and renumber + label nPoints = allMeshesPoints.size(); - //if (log_) + forAll(collectedPoints, procI) { - Info<< typeName << ": for patch " << p.name() - << " writing " << pts.size() << " points to " - << osPointsPtr().name() << endl; + allMeshesPoints.append(collectedPoints[procI]); + } + face newFace; + forAll(collectedFaces, procI) + { + const faceList& procFaces = collectedFaces[procI]; - // Write points - osPointsPtr() << patchKey.c_str() << p.name() << pts << endl; + forAll(procFaces, faceI) + { + const face& f = procFaces[faceI]; - faceList fcs - ( - ListListOps::combine<faceList>(allFaces, accessOp<faceList>()) - ); + newFace.setSize(f.size()); + forAll(f, fp) + { + newFace[fp] = f[fp]+nPoints; + } + allMeshesFaces.append(newFace); + } - //if (log_) - { - Info<< typeName << ": for patch " << p.name() - << " writing " << fcs.size() << " faces to " - << osFacesPtr().name() << endl; + nPoints += collectedPoints[procI].size(); } + } + + //if (log_) + { + Info<< typeName << ": for mesh " << mesh.name() + << " writing " << allMeshesPoints.size() << " points to " + << osPointsPtr().name() << endl; + Info<< typeName << ": for mesh " << mesh.name() + << " writing " << allMeshesFaces.size() << " faces to " + << osFacesPtr().name() << endl; + } + } + + // Write points + if (osPointsPtr.valid()) + { + osPointsPtr() << allMeshesPoints << endl; + } + + // Write faces + if (osFacesPtr.valid()) + { + osFacesPtr() << allMeshesFaces << endl; + } +} - // Write faces - osFacesPtr() << patchKey.c_str() << p.name() << fcs << endl; + +Foam::word Foam::externalCoupledFunctionObject::compositeName +( + const wordList& regionNames +) +{ + if (regionNames.size() == 0) + { + FatalErrorIn + ( + "externalCoupledFunctionObject::compositeName(const wordList&)" + ) << "Empty regionNames" << abort(FatalError); + return word::null; + } + else if (regionNames.size() == 1) + { + if (regionNames[0] == polyMesh::defaultRegion) + { + // For compatibility with single region cases suppress single + // region name + return word(""); + } + else + { + return regionNames[0]; } } + else + { + // Enforce lexical ordering + checkOrder(regionNames); + + word composite(regionNames[0]); + for (label i = 1; i < regionNames.size(); i++) + { + composite += "_" + regionNames[i]; + } + + return composite; + } +} + + +void Foam::externalCoupledFunctionObject::checkOrder +( + const wordList& regionNames +) +{ + labelList order; + sortedOrder(regionNames, order); + if (order != identity(regionNames.size())) + { + FatalErrorIn + ( + "externalCoupledFunctionObject::checkOrder(const wordList&)" + ) << "regionNames " << regionNames << " not in alphabetical order :" + << order << exit(FatalError); + } } void Foam::externalCoupledFunctionObject::readData() { - forAll(regionNames_, regionI) + forAll(regionGroupNames_, regionI) { - const word& regionName = regionNames_[regionI]; - const labelList& groups = regionToGroups_[regionName]; + const word& compName = regionGroupNames_[regionI]; + const wordList& regionNames = regionGroupRegions_[regionI]; - const fvMesh& mesh = time_.lookupObject<fvMesh>(regionName); + // Get the meshes for the region-group + UPtrList<const fvMesh> meshes(regionNames.size()); + forAll(regionNames, j) + { + const word& regionName = regionNames[j]; + meshes.set(j, &time_.lookupObject<fvMesh>(regionName)); + } + + const labelList& groups = regionToGroups_[compName]; forAll(groups, i) { label groupI = groups[i]; const wordRe& groupName = groupNames_[groupI]; - const labelList& patchIDs = groupPatchIDs_[groupI]; const wordList& fieldNames = groupReadFields_[groupI]; forAll(fieldNames, fieldI) @@ -498,37 +624,32 @@ void Foam::externalCoupledFunctionObject::readData() bool ok = readData<scalar> ( - mesh, + meshes, groupName, - patchIDs, fieldName ); ok = ok || readData<vector> ( - mesh, + meshes, groupName, - patchIDs, fieldName ); ok = ok || readData<sphericalTensor> ( - mesh, + meshes, groupName, - patchIDs, fieldName ); ok = ok || readData<symmTensor> ( - mesh, + meshes, groupName, - patchIDs, fieldName ); ok = ok || readData<tensor> ( - mesh, + meshes, groupName, - patchIDs, fieldName ); @@ -538,7 +659,7 @@ void Foam::externalCoupledFunctionObject::readData() ( "void Foam::externalCoupledFunctionObject::readData()" ) - << "Field " << fieldName << " in region " << mesh.name() + << "Field " << fieldName << " in regions " << compName << " was not found." << endl; } } @@ -549,56 +670,59 @@ void Foam::externalCoupledFunctionObject::readData() void Foam::externalCoupledFunctionObject::writeData() const { - forAll(regionNames_, regionI) + forAll(regionGroupNames_, regionI) { - const word& regionName = regionNames_[regionI]; - const labelList& groups = regionToGroups_[regionName]; + const word& compName = regionGroupNames_[regionI]; + const wordList& regionNames = regionGroupRegions_[regionI]; - const fvMesh& mesh = time_.lookupObject<fvMesh>(regionName); + // Get the meshes for the region-group + UPtrList<const fvMesh> meshes(regionNames.size()); + forAll(regionNames, j) + { + const word& regionName = regionNames[j]; + meshes.set(j, &time_.lookupObject<fvMesh>(regionName)); + } + + const labelList& groups = regionToGroups_[compName]; forAll(groups, i) { label groupI = groups[i]; const wordRe& groupName = groupNames_[groupI]; - const labelList& patchIDs = groupPatchIDs_[groupI]; const wordList& fieldNames = groupWriteFields_[groupI]; forAll(fieldNames, fieldI) { const word& fieldName = fieldNames[fieldI]; + bool ok = writeData<scalar> ( - mesh, + meshes, groupName, - patchIDs, fieldName ); ok = ok || writeData<vector> ( - mesh, + meshes, groupName, - patchIDs, fieldName ); ok = ok || writeData<sphericalTensor> ( - mesh, + meshes, groupName, - patchIDs, fieldName ); ok = ok || writeData<symmTensor> ( - mesh, + meshes, groupName, - patchIDs, fieldName ); ok = ok || writeData<tensor> ( - mesh, + meshes, groupName, - patchIDs, fieldName ); @@ -608,7 +732,7 @@ void Foam::externalCoupledFunctionObject::writeData() const ( "void Foam::externalCoupledFunctionObject::writeData()" ) - << "Field " << fieldName << " in region " << mesh.name() + << "Field " << fieldName << " in regions " << compName << " was not found." << endl; } } @@ -625,12 +749,20 @@ void Foam::externalCoupledFunctionObject::initialise() } // Write the geometry if not already there - forAll(regionNames_, regionI) + forAll(regionGroupRegions_, i) { - const word& regionName = regionNames_[regionI]; - const labelList& groups = regionToGroups_[regionName]; + const word& compName = regionGroupNames_[i]; + const wordList& regionNames = regionGroupRegions_[i]; - const fvMesh& mesh = time_.lookupObject<fvMesh>(regionName); + // Get the meshes for the region-group + UPtrList<const fvMesh> meshes(regionNames.size()); + forAll(regionNames, j) + { + const word& regionName = regionNames[j]; + meshes.set(j, &time_.lookupObject<fvMesh>(regionName)); + } + + const labelList& groups = regionToGroups_[compName]; forAll(groups, i) { @@ -640,14 +772,16 @@ void Foam::externalCoupledFunctionObject::initialise() bool exists = false; if (Pstream::master()) { - fileName dir(groupDir(commsDir_, mesh.dbDir(), groupName)); + fileName dir(groupDir(commsDir_, compName, groupName)); - exists = isFile(dir/"patchPoints") || isFile(dir/"patchFaces"); + exists = + isFile(dir/"patchPoints") + || isFile(dir/"patchFaces"); } if (!returnReduce(exists, orOp<bool>())) { - writeGeometry(mesh, commsDir_, groupName); + writeGeometry(meshes, commsDir_, groupName); } } } @@ -802,6 +936,12 @@ bool Foam::externalCoupledFunctionObject::read(const dictionary& dict) initByExternal_ = readBool(dict.lookup("initByExternal")); log_ = dict.lookupOrDefault("log", false); + + // Get names of all fvMeshes (and derived types) + wordList allRegionNames(time_.lookupClass<fvMesh>().sortedToc()); + + + const dictionary& allRegionsDict = dict.subDict("regions"); forAllConstIter(dictionary, allRegionsDict, iter) @@ -818,9 +958,16 @@ bool Foam::externalCoupledFunctionObject::read(const dictionary& dict) << exit(FatalIOError); } - const word& regionName = iter().keyword(); + const wordRe regionGroupName(iter().keyword()); const dictionary& regionDict = iter().dict(); - regionNames_.append(regionName); + + labelList regionIDs = findStrings(regionGroupName, allRegionNames); + + const wordList regionNames(allRegionNames, regionIDs); + + regionGroupNames_.append(compositeName(regionNames)); + regionGroupRegions_.append(regionNames); + forAllConstIter(dictionary, regionDict, regionIter) { @@ -844,7 +991,7 @@ bool Foam::externalCoupledFunctionObject::read(const dictionary& dict) HashTable<labelList>::iterator fnd = regionToGroups_.find ( - regionName + regionGroupNames_.last() ); if (fnd != regionToGroups_.end()) { @@ -852,21 +999,15 @@ bool Foam::externalCoupledFunctionObject::read(const dictionary& dict) } else { - regionToGroups_.insert(regionName, labelList(1, nGroups)); + regionToGroups_.insert + ( + regionGroupNames_.last(), + labelList(1, nGroups) + ); } groupNames_.append(groupName); groupReadFields_.append(readFields); groupWriteFields_.append(writeFields); - - // Pre-calculate the patchIDs - const fvMesh& mesh = time_.lookupObject<fvMesh>(regionName); - groupPatchIDs_.append - ( - mesh.boundaryMesh().patchSet - ( - List<wordRe>(1, groupName) - ).sortedToc() - ); } } @@ -875,25 +1016,26 @@ bool Foam::externalCoupledFunctionObject::read(const dictionary& dict) if (log_) { Info<< type() << ": Communicating with regions:" << endl; - forAll(regionNames_, regionI) + forAll(regionGroupNames_, rgI) { - const word& regionName = regionNames_[regionI]; - const fvMesh& mesh = time_.lookupObject<fvMesh>(regionName); + //const wordList& regionNames = regionGroupRegions_[rgI]; + const word& compName = regionGroupNames_[rgI]; - Info<< "Region: " << mesh.name() << endl << incrIndent; - const labelList& groups = regionToGroups_[regionName]; + Info<< "Region: " << compName << endl << incrIndent; + const labelList& groups = regionToGroups_[compName]; forAll(groups, i) { label groupI = groups[i]; const wordRe& groupName = groupNames_[groupI]; - const labelList& patchIDs = groupPatchIDs_[groupI]; - Info<< indent << "Group: " << groupName << "\t" - << " patches: " << patchIDs << endl + Info<< indent << "patchGroup: " << groupName << "\t" + << endl << incrIndent - << indent << "Reading fields: " << groupReadFields_[groupI] + << indent << "Reading fields: " + << groupReadFields_[groupI] << endl - << indent << "Writing fields: " << groupWriteFields_[groupI] + << indent << "Writing fields: " + << groupWriteFields_[groupI] << endl << decrIndent; } @@ -907,25 +1049,24 @@ bool Foam::externalCoupledFunctionObject::read(const dictionary& dict) // should already be written - but just make sure if (Pstream::master()) { - forAll(regionNames_, regionI) + forAll(regionGroupNames_, rgI) { - const word& regionName = regionNames_[regionI]; - const fvMesh& mesh = time_.lookupObject<fvMesh>(regionName); - const labelList& groups = regionToGroups_[regionName]; + const word& compName = regionGroupNames_[rgI]; + + const labelList& groups = regionToGroups_[compName]; forAll(groups, i) { label groupI = groups[i]; const wordRe& groupName = groupNames_[groupI]; - fileName dir(groupDir(commsDir_, mesh.dbDir(), groupName)); + fileName dir(groupDir(commsDir_, compName, groupName)); if (!isDir(dir)) { if (log_) { Info<< type() << ": creating communications directory " - << dir << endl; + << dir << endl; } - mkDir(dir); } } diff --git a/src/postProcessing/functionObjects/jobControl/externalCoupled/externalCoupledFunctionObject.H b/src/postProcessing/functionObjects/jobControl/externalCoupled/externalCoupledFunctionObject.H index 7806e64d64aa89bfeef74a957bf6fc55f3244fe6..5985f1f587d6b9ec2dbacf066d498a026d692e1e 100644 --- a/src/postProcessing/functionObjects/jobControl/externalCoupled/externalCoupledFunctionObject.H +++ b/src/postProcessing/functionObjects/jobControl/externalCoupled/externalCoupledFunctionObject.H @@ -48,7 +48,10 @@ Description which gets read/written on the master processor only. In the communications directory the structure will be - <regionName>/<patchGroup>/<fieldName>.[in|out] + <regionsName>/<patchGroup>/<fieldName>.[in|out] + + (where regionsName is either the name of a single region or a composite + of multiple region names) At start-up, the boundary creates a lock file, i.e.. @@ -58,13 +61,13 @@ Description execution the boundary values are written to files (one per region, per patch(group), per field), e.g. - <regionName>/<patchGroup>/<fieldName>.out + <regionsName>/<patchGroup>/<fieldName>.out The lock file is then removed, instructing the external source to take control of the program execution. When ready, the external program should create the return values, e.g. to files - <regionName>/<patchGroup>/<fieldName>.in + <regionsName>/<patchGroup>/<fieldName>.in ... and then re-instate the lock file. The functionObject will then read these values, apply them to the boundary conditions and pass @@ -82,7 +85,7 @@ Description regions { - region0 + "(region1|region0)" // Name of region(s) { TPatchGroup // Name of patch(group) { @@ -95,7 +98,7 @@ Description \endverbatim This reads/writes (on the master processor) the directory: - comms/region0/TPatchGroup/ + comms/region0_region1/TPatchGroup/ with contents: patchPoints (collected points) patchFaces (collected faces) @@ -120,6 +123,7 @@ SourceFiles #include "wordReList.H" #include "scalarField.H" #include "Switch.H" +#include "UPtrList.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -167,18 +171,18 @@ class externalCoupledFunctionObject //- Log flag bool log_; - //- Names of regions - DynamicList<word> regionNames_; + //- Names of (composite) regions + DynamicList<word> regionGroupNames_; + + // Per (composite) region the names of the regions + DynamicList<wordList> regionGroupRegions_; - // Per region the indices of the group information + // Per (composite) region the indices of the group information HashTable<labelList> regionToGroups_; // Per group the names of the patches/patchGroups DynamicList<wordRe> groupNames_; - // Per group the indices of the patches - DynamicList<labelList> groupPatchIDs_; - // Per group the names of the fields to read DynamicList<wordList> groupReadFields_; @@ -195,7 +199,7 @@ class externalCoupledFunctionObject static fileName groupDir ( const fileName& commsDir, - const word& regionName, + const word& regionsName, const wordRe& groupName ); @@ -225,9 +229,8 @@ class externalCoupledFunctionObject template<class Type> bool readData ( - const fvMesh& mesh, + const UPtrList<const fvMesh>& meshes, const wordRe& groupName, - const labelList& patchIDs, const word& fieldName ); //- Read data for all regions, all fields @@ -237,9 +240,8 @@ class externalCoupledFunctionObject template<class Type> bool writeData ( - const fvMesh& mesh, + const UPtrList<const fvMesh>& meshes, const wordRe& groupName, - const labelList& patchIDs, const word& fieldName ) const; @@ -275,6 +277,7 @@ class externalCoupledFunctionObject template<class Type> static tmp<Field<Type> > gatherAndCombine(const Field<Type>& fld); + static void checkOrder(const wordList&); //- Disallow default bitwise copy construc externalCoupledFunctionObject(const externalCoupledFunctionObject&); @@ -356,10 +359,14 @@ public: // Other + //- Create single name by appending words (in sorted order), + // separated by '_' + static word compositeName(const wordList&); + //- Write geometry for the group/patch static void writeGeometry ( - const fvMesh& mesh, + const UPtrList<const fvMesh>& meshes, const fileName& commsDir, const wordRe& groupName ); diff --git a/src/postProcessing/functionObjects/jobControl/externalCoupled/externalCoupledFunctionObjectTemplates.C b/src/postProcessing/functionObjects/jobControl/externalCoupled/externalCoupledFunctionObjectTemplates.C index 88477c5bb64ba253d3f26a24a9d03dfd90cd9def..f483ecb71e10063950838376184e6c4cc74bbbd1 100644 --- a/src/postProcessing/functionObjects/jobControl/externalCoupled/externalCoupledFunctionObjectTemplates.C +++ b/src/postProcessing/functionObjects/jobControl/externalCoupled/externalCoupledFunctionObjectTemplates.C @@ -40,25 +40,20 @@ License template<class Type> bool Foam::externalCoupledFunctionObject::readData ( - const fvMesh& mesh, + const UPtrList<const fvMesh>& meshes, const wordRe& groupName, - const labelList& patchIDs, const word& fieldName ) { typedef GeometricField<Type, fvPatchField, volMesh> volFieldType; typedef externalCoupledMixedFvPatchField<Type> patchFieldType; - if (!mesh.foundObject<volFieldType>(fieldName)) + wordList regionNames(meshes.size()); + forAll(meshes, i) { - return false; + regionNames[i] = meshes[i].dbDir(); } - const volFieldType& cvf = mesh.lookupObject<volFieldType>(fieldName); - const typename volFieldType::GeometricBoundaryField& bf = - cvf.boundaryField(); - - // File only opened on master; contains data for all processors, for all // patchIDs. autoPtr<IFstream> masterFilePtr; @@ -66,7 +61,7 @@ bool Foam::externalCoupledFunctionObject::readData { const fileName transferFile ( - groupDir(commsDir_, mesh.dbDir(), groupName) + groupDir(commsDir_, compositeName(regionNames), groupName) / fieldName + ".in" ); @@ -82,181 +77,234 @@ bool Foam::externalCoupledFunctionObject::readData ( "void externalCoupledFunctionObject::readData" "(" - "const fvMesh&, " + "const UPtrList<const fvMesh>&, " "const wordRe&, " - "const labelList&, " "const word&" ")", masterFilePtr() - ) << "Cannot open file for region " << mesh.name() - << ", field " << fieldName << ", patches " << patchIDs + ) << "Cannot open file for region " << compositeName(regionNames) + << ", field " << fieldName << exit(FatalIOError); } } - // Handle column-wise reading of patch data. Supports most easy types - forAll(patchIDs, i) + + label nFound = 0; + + + forAll(meshes, i) { - label patchI = patchIDs[i]; + const fvMesh& mesh = meshes[i]; - if (isA<patchFieldType>(bf[patchI])) + if (!mesh.foundObject<volFieldType>(fieldName)) { - // Explicit handling of externalCoupledObjectMixed bcs - they have - // specialised reading routines. + continue; + } - patchFieldType& pf = const_cast<patchFieldType&> - ( - refCast<const patchFieldType> - ( - bf[patchI] - ) - ); + nFound++; - // Read from master into local stream - OStringStream os; - readLines - ( - bf[patchI].size(), // number of lines to read - masterFilePtr, - os - ); + const volFieldType& cvf = mesh.lookupObject<volFieldType>(fieldName); + const typename volFieldType::GeometricBoundaryField& bf = + cvf.boundaryField(); - // Pass responsability for all reading over to bc - pf.readData(IStringStream(os.str())()); - // Update the value from the read coefficicient. Bypass any - // additional processing by derived type. - pf.patchFieldType::evaluate(); - } - else if (isA<mixedFvPatchField<Type> >(bf[patchI])) - { - // Read columns from file for - // value, snGrad, refValue, refGrad, valueFraction - List<scalarField> data; - readColumns + // Get the patches + const labelList patchIDs + ( + mesh.boundaryMesh().patchSet ( - bf[patchI].size(), // number of lines to read - 4*pTraits<Type>::nComponents+1, // nColumns: 4*Type + 1*scalar - masterFilePtr, - data - ); + List<wordRe>(1, groupName) + ).sortedToc() + ); - mixedFvPatchField<Type>& pf = const_cast<mixedFvPatchField<Type>&> - ( - refCast<const mixedFvPatchField<Type> > + // Handle column-wise reading of patch data. Supports most easy types + forAll(patchIDs, i) + { + label patchI = patchIDs[i]; + + if (isA<patchFieldType>(bf[patchI])) + { + // Explicit handling of externalCoupledMixed bcs - they + // have specialised reading routines. + + patchFieldType& pf = const_cast<patchFieldType&> ( - bf[patchI] - ) - ); + refCast<const patchFieldType> + ( + bf[patchI] + ) + ); + + // Read from master into local stream + OStringStream os; + readLines + ( + bf[patchI].size(), // number of lines to read + masterFilePtr, + os + ); - // Transfer read data to bc. - // Skip value, snGrad - direction columnI = 2*pTraits<Type>::nComponents; + // Pass responsability for all reading over to bc + pf.readData(IStringStream(os.str())()); - Field<Type>& refValue = pf.refValue(); - for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; cmpt++) - { - refValue.replace(cmpt, data[columnI++]); + // Update the value from the read coefficicient. Bypass any + // additional processing by derived type. + pf.patchFieldType::evaluate(); } - Field<Type>& refGrad = pf.refGrad(); - for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; cmpt++) + else if (isA<mixedFvPatchField<Type> >(bf[patchI])) { - refGrad.replace(cmpt, data[columnI++]); - } - pf.valueFraction() = data[columnI]; - - // Update the value from the read coefficicient. Bypass any - // additional processing by derived type. - pf.mixedFvPatchField<Type>::evaluate(); - } - else if (isA<fixedGradientFvPatchField<Type> >(bf[patchI])) - { - // Read columns for value and gradient - List<scalarField> data; - readColumns - ( - bf[patchI].size(), // number of lines to read - 2*pTraits<Type>::nComponents, // nColumns: Type - masterFilePtr, - data - ); - - fixedGradientFvPatchField<Type>& pf = - const_cast<fixedGradientFvPatchField<Type>&> - ( - refCast<const fixedGradientFvPatchField<Type> > + // Read columns from file for + // value, snGrad, refValue, refGrad, valueFraction + List<scalarField> data; + readColumns ( - bf[patchI] + bf[patchI].size(), // number of lines to read + 4*pTraits<Type>::nComponents+1, // nColumns: 4*Type+1*scalar + masterFilePtr, + data + ); + + mixedFvPatchField<Type>& pf = + const_cast<mixedFvPatchField<Type>&> + ( + refCast<const mixedFvPatchField<Type> > + ( + bf[patchI] + ) + ); + + // Transfer read data to bc. + // Skip value, snGrad + direction columnI = 2*pTraits<Type>::nComponents; + + Field<Type>& refValue = pf.refValue(); + for + ( + direction cmpt = 0; + cmpt < pTraits<Type>::nComponents; + cmpt++ ) - ); + { + refValue.replace(cmpt, data[columnI++]); + } + Field<Type>& refGrad = pf.refGrad(); + for + ( + direction cmpt = 0; + cmpt < pTraits<Type>::nComponents; + cmpt++ + ) + { + refGrad.replace(cmpt, data[columnI++]); + } + pf.valueFraction() = data[columnI]; - // Transfer gradient to bc - Field<Type>& gradient = pf.gradient(); - for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; cmpt++) - { - gradient.replace(cmpt, data[pTraits<Type>::nComponents+cmpt]); + // Update the value from the read coefficicient. Bypass any + // additional processing by derived type. + pf.mixedFvPatchField<Type>::evaluate(); } - - // Update the value from the read coefficicient. Bypass any - // additional processing by derived type. - pf.fixedGradientFvPatchField<Type>::evaluate(); - } - else if (isA<fixedValueFvPatchField<Type> >(bf[patchI])) - { - // Read columns for value only - List<scalarField> data; - readColumns - ( - bf[patchI].size(), // number of lines to read - pTraits<Type>::nComponents, // number of columns to read - masterFilePtr, - data - ); - - // Transfer read value to bc - Field<Type> value(bf[patchI].size()); - for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; cmpt++) + else if (isA<fixedGradientFvPatchField<Type> >(bf[patchI])) { - value.replace(cmpt, data[cmpt]); - } + // Read columns for value and gradient + List<scalarField> data; + readColumns + ( + bf[patchI].size(), // number of lines to read + 2*pTraits<Type>::nComponents, // nColumns: Type + masterFilePtr, + data + ); + + fixedGradientFvPatchField<Type>& pf = + const_cast<fixedGradientFvPatchField<Type>&> + ( + refCast<const fixedGradientFvPatchField<Type> > + ( + bf[patchI] + ) + ); + + // Transfer gradient to bc + Field<Type>& gradient = pf.gradient(); + for + ( + direction cmpt = 0; + cmpt < pTraits<Type>::nComponents; + cmpt++ + ) + { + gradient.replace + ( + cmpt, + data[pTraits<Type>::nComponents+cmpt] + ); + } - fixedValueFvPatchField<Type>& pf = - const_cast<fixedValueFvPatchField<Type>&> - ( - refCast<const fixedValueFvPatchField<Type> > + // Update the value from the read coefficicient. Bypass any + // additional processing by derived type. + pf.fixedGradientFvPatchField<Type>::evaluate(); + } + else if (isA<fixedValueFvPatchField<Type> >(bf[patchI])) + { + // Read columns for value only + List<scalarField> data; + readColumns ( - bf[patchI] + bf[patchI].size(), // number of lines to read + pTraits<Type>::nComponents, // number of columns to read + masterFilePtr, + data + ); + + // Transfer read value to bc + Field<Type> value(bf[patchI].size()); + for + ( + direction cmpt = 0; + cmpt < pTraits<Type>::nComponents; + cmpt++ ) - ); + { + value.replace(cmpt, data[cmpt]); + } - pf == value; + fixedValueFvPatchField<Type>& pf = + const_cast<fixedValueFvPatchField<Type>&> + ( + refCast<const fixedValueFvPatchField<Type> > + ( + bf[patchI] + ) + ); - // Update the value from the read coefficicient. Bypass any - // additional processing by derived type. - pf.fixedValueFvPatchField<Type>::evaluate(); - } - else - { - FatalErrorIn - ( - "void externalCoupledFunctionObject::readData" - "(" - "const fvMesh&, " - "const wordRe&, " - "const labelList&, " - "const word&" - ")" - ) - << "Unsupported boundary condition " << bf[patchI].type() - << " for patch " << bf[patchI].patch().name() - << " in region " << mesh.name() - << exit(FatalError); - } + pf == value; + + // Update the value from the read coefficicient. Bypass any + // additional processing by derived type. + pf.fixedValueFvPatchField<Type>::evaluate(); + } + else + { + FatalErrorIn + ( + "void externalCoupledFunctionObject::readData" + "(" + "const UPtrList<const fvMesh>&, " + "const wordRe&, " + "const word&" + ")" + ) + << "Unsupported boundary condition " << bf[patchI].type() + << " for patch " << bf[patchI].patch().name() + << " in region " << mesh.name() + << exit(FatalError); + } - initialised_ = true; + initialised_ = true; + } } - return true; + return nFound > 0; } @@ -308,25 +356,20 @@ Foam::externalCoupledFunctionObject::gatherAndCombine template<class Type> bool Foam::externalCoupledFunctionObject::writeData ( - const fvMesh& mesh, + const UPtrList<const fvMesh>& meshes, const wordRe& groupName, - const labelList& patchIDs, const word& fieldName ) const { typedef GeometricField<Type, fvPatchField, volMesh> volFieldType; typedef externalCoupledMixedFvPatchField<Type> patchFieldType; - if (!mesh.foundObject<volFieldType>(fieldName)) + wordList regionNames(meshes.size()); + forAll(meshes, i) { - return false; + regionNames[i] = meshes[i].dbDir(); } - const volFieldType& cvf = mesh.lookupObject<volFieldType>(fieldName); - const typename volFieldType::GeometricBoundaryField& bf = - cvf.boundaryField(); - - // File only opened on master; contains data for all processors, for all // patchIDs autoPtr<OFstream> masterFilePtr; @@ -334,7 +377,7 @@ bool Foam::externalCoupledFunctionObject::writeData { const fileName transferFile ( - groupDir(commsDir_, mesh.dbDir(), groupName) + groupDir(commsDir_, compositeName(regionNames), groupName) / fieldName + ".out" ); @@ -350,14 +393,13 @@ bool Foam::externalCoupledFunctionObject::writeData ( "externalCoupledFunctionObject::writeData" "(" - "const fvMesh&, " + "const UPtrList<const fvMesh>&, " "const wordRe&, " - "const labelList&, " "const word&" ") const", masterFilePtr() - ) << "Cannot open file for region " << mesh.name() - << ", field " << fieldName << ", patches " << patchIDs + ) << "Cannot open file for region " << compositeName(regionNames) + << ", field " << fieldName << exit(FatalIOError); } } @@ -365,94 +407,122 @@ bool Foam::externalCoupledFunctionObject::writeData bool headerDone = false; - // Handle column-wise writing of patch data. Supports most easy types - forAll(patchIDs, i) - { - label patchI = patchIDs[i]; + label nFound = 0; - const globalIndex globalFaces(bf[patchI].size()); + forAll(meshes, i) + { + const fvMesh& mesh = meshes[i]; - if (isA<patchFieldType>(bf[patchI])) + if (!mesh.foundObject<volFieldType>(fieldName)) { - // Explicit handling of externalCoupledObjectMixed bcs - they have - // specialised writing routines + continue; + } + + nFound++; + + const volFieldType& cvf = mesh.lookupObject<volFieldType>(fieldName); + const typename volFieldType::GeometricBoundaryField& bf = + cvf.boundaryField(); + - const patchFieldType& pf = refCast<const patchFieldType> + // Get the patches + const labelList patchIDs + ( + mesh.boundaryMesh().patchSet ( - bf[patchI] - ); - OStringStream os; + List<wordRe>(1, groupName) + ).sortedToc() + ); + + // Handle column-wise writing of patch data. Supports most easy types + forAll(patchIDs, i) + { + label patchI = patchIDs[i]; - // Pass responsibility for all writing over to bc - pf.writeData(os); + const globalIndex globalFaces(bf[patchI].size()); - // Collect contributions from all processors and output them on - // master - if (Pstream::master()) + if (isA<patchFieldType>(bf[patchI])) { - // Output master data first - if (!headerDone) + // Explicit handling of externalCoupledMixed bcs - they + // have specialised writing routines + + const patchFieldType& pf = refCast<const patchFieldType> + ( + bf[patchI] + ); + OStringStream os; + + // Pass responsibility for all writing over to bc + pf.writeData(os); + + // Collect contributions from all processors and output them on + // master + if (Pstream::master()) { - pf.writeHeader(masterFilePtr()); - headerDone = true; + // Output master data first + if (!headerDone) + { + pf.writeHeader(masterFilePtr()); + headerDone = true; + } + masterFilePtr() << os.str().c_str(); + + for (label procI = 1; procI < Pstream::nProcs(); procI++) + { + IPstream fromSlave(Pstream::scheduled, procI); + string str(fromSlave); + masterFilePtr() << str.c_str(); + } } - masterFilePtr() << os.str().c_str(); - - for (label procI = 1; procI < Pstream::nProcs(); procI++) + else { - IPstream fromSlave(Pstream::scheduled, procI); - string str(fromSlave); - masterFilePtr() << str.c_str(); + OPstream toMaster(Pstream::scheduled, Pstream::masterNo()); + toMaster << os.str(); } } - else + else if (isA<mixedFvPatchField<Type> >(bf[patchI])) { - OPstream toMaster(Pstream::scheduled, Pstream::masterNo()); - toMaster << os.str(); - } - } - else if (isA<mixedFvPatchField<Type> >(bf[patchI])) - { - const mixedFvPatchField<Type>& pf = - refCast<const mixedFvPatchField<Type> >(bf[patchI]); + const mixedFvPatchField<Type>& pf = + refCast<const mixedFvPatchField<Type> >(bf[patchI]); - Field<Type> value(gatherAndCombine(pf)); - Field<Type> snGrad(gatherAndCombine(pf.snGrad()())); - Field<Type> refValue(gatherAndCombine(pf.refValue())); - Field<Type> refGrad(gatherAndCombine(pf.refGrad())); - scalarField valueFraction(gatherAndCombine(pf.valueFraction())); + Field<Type> value(gatherAndCombine(pf)); + Field<Type> snGrad(gatherAndCombine(pf.snGrad()())); + Field<Type> refValue(gatherAndCombine(pf.refValue())); + Field<Type> refGrad(gatherAndCombine(pf.refGrad())); + scalarField valueFraction(gatherAndCombine(pf.valueFraction())); - if (Pstream::master()) - { - forAll(refValue, faceI) + if (Pstream::master()) { - masterFilePtr() - << value[faceI] << token::SPACE - << snGrad[faceI] << token::SPACE - << refValue[faceI] << token::SPACE - << refGrad[faceI] << token::SPACE - << valueFraction[faceI] << nl; + forAll(refValue, faceI) + { + masterFilePtr() + << value[faceI] << token::SPACE + << snGrad[faceI] << token::SPACE + << refValue[faceI] << token::SPACE + << refGrad[faceI] << token::SPACE + << valueFraction[faceI] << nl; + } } } - } - else - { - // Output the value and snGrad - Field<Type> value(gatherAndCombine(bf[patchI])); - Field<Type> snGrad(gatherAndCombine(bf[patchI].snGrad()())); - if (Pstream::master()) + else { - forAll(value, faceI) + // Output the value and snGrad + Field<Type> value(gatherAndCombine(bf[patchI])); + Field<Type> snGrad(gatherAndCombine(bf[patchI].snGrad()())); + if (Pstream::master()) { - masterFilePtr() - << value[faceI] << token::SPACE - << snGrad[faceI] << nl; + forAll(value, faceI) + { + masterFilePtr() + << value[faceI] << token::SPACE + << snGrad[faceI] << nl; + } } } } } - return true; + return nFound > 0; } diff --git a/src/sampling/sampledSet/face/faceOnlySet.C b/src/sampling/sampledSet/face/faceOnlySet.C index 85fb7bc74b59649889319367c827f5ea5bb5bd01..1257807e2b41f6982c764a60363a014fbf0ff96a 100644 --- a/src/sampling/sampledSet/face/faceOnlySet.C +++ b/src/sampling/sampledSet/face/faceOnlySet.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -169,6 +169,7 @@ void Foam::faceOnlySet::calcSamples // Set points and cell/face labels to empty lists //Info<< "calcSamples : Both start_ and end_ outside domain" // << endl; + const_cast<polyMesh&>(mesh()).moving(oldMoving); return; } diff --git a/src/sampling/sampledSet/patchSeed/patchSeedSet.C b/src/sampling/sampledSet/patchSeed/patchSeedSet.C index 3560fe42046778b9e36d572a8c59bdd432d9ce36..9cdcc7d230c6b8e2e2117a58265fb55be6e7e436 100644 --- a/src/sampling/sampledSet/patchSeed/patchSeedSet.C +++ b/src/sampling/sampledSet/patchSeed/patchSeedSet.C @@ -30,9 +30,8 @@ License #include "treeDataFace.H" #include "Time.H" #include "meshTools.H" -//#include "Random.H" -// For 'facePoint' helper function only #include "mappedPatchBase.H" +#include "indirectPrimitivePatch.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -85,19 +84,145 @@ void Foam::patchSeedSet::calcSamples } - label totalSize = returnReduce(sz, sumOp<label>()); + if (!rndGenPtr_.valid()) + { + rndGenPtr_.reset(new Random(0)); + } + Random& rndGen = rndGenPtr_(); + + + if (selectedLocations_.size()) + { + DynamicList<label> newPatchFaces(patchFaces.size()); + + // Find the nearest patch face + { + // 1. All processors find nearest local patch face for all + // selectedLocations + + // All the info for nearest. Construct to miss + List<mappedPatchBase::nearInfo> nearest(selectedLocations_.size()); + + const indirectPrimitivePatch pp + ( + IndirectList<face>(mesh().faces(), patchFaces), + mesh().points() + ); + + treeBoundBox patchBb + ( + treeBoundBox(pp.points(), pp.meshPoints()).extend + ( + rndGen, + 1e-4 + ) + ); + patchBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL); + patchBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL); + + indexedOctree<treeDataFace> boundaryTree + ( + treeDataFace // all information needed to search faces + ( + false, // do not cache bb + mesh(), + patchFaces // boundary faces only + ), + patchBb, // overall search domain + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity + ); + + // Get some global dimension so all points are equally likely + // to be found + const scalar globalDistSqr + ( + //magSqr + //( + // boundBox + // ( + // pp.points(), + // pp.meshPoints(), + // true + // ).span() + //) + GREAT + ); + + forAll(selectedLocations_, sampleI) + { + const point& sample = selectedLocations_[sampleI]; + + pointIndexHit& nearInfo = nearest[sampleI].first(); + nearInfo = boundaryTree.findNearest + ( + sample, + globalDistSqr + ); + + if (!nearInfo.hit()) + { + nearest[sampleI].second().first() = Foam::sqr(GREAT); + nearest[sampleI].second().second() = + Pstream::myProcNo(); + } + else + { + point fc(pp[nearInfo.index()].centre(pp.points())); + nearInfo.setPoint(fc); + nearest[sampleI].second().first() = magSqr(fc-sample); + nearest[sampleI].second().second() = + Pstream::myProcNo(); + } + } + + + // 2. Reduce on master. Select nearest processor. + + // Find nearest. Combine on master. + Pstream::listCombineGather(nearest, mappedPatchBase::nearestEqOp()); + Pstream::listCombineScatter(nearest); + + + // 3. Pick up my local faces that have won + + forAll(nearest, sampleI) + { + if (nearest[sampleI].first().hit()) + { + label procI = nearest[sampleI].second().second(); + label index = nearest[sampleI].first().index(); + + if (procI == Pstream::myProcNo()) + { + newPatchFaces.append(pp.addressing()[index]); + } + } + } + } + + if (debug) + { + Pout<< "Found " << newPatchFaces.size() + << " out of " << selectedLocations_.size() + << " on local processor" << endl; + } + + patchFaces.transfer(newPatchFaces); + } // Shuffle and truncate if in random mode + label totalSize = returnReduce(patchFaces.size(), sumOp<label>()); + if (maxPoints_ < totalSize) { // Check what fraction of maxPoints_ I need to generate locally. - label myMaxPoints = label(scalar(sz)/totalSize*maxPoints_); + label myMaxPoints = + label(scalar(patchFaces.size())/totalSize*maxPoints_); - rndGenPtr_.reset(new Random(123456)); - Random& rndGen = rndGenPtr_(); - - labelList subset = identity(sz); + labelList subset = identity(patchFaces.size()); for (label iter = 0; iter < 4; iter++) { forAll(subset, i) @@ -115,7 +240,7 @@ void Foam::patchSeedSet::calcSamples if (debug) { Pout<< "In random mode : selected " << patchFaces.size() - << " faces out of " << sz << endl; + << " faces out of " << patchFaces.size() << endl; } } @@ -135,6 +260,9 @@ void Foam::patchSeedSet::calcSamples forAll(patchFaces, i) { label faceI = patchFaces[i]; + + // Slightly shift point in since on warped face face-diagonal + // decomposition might be outside cell for face-centre decomposition! pointIndexHit info = mappedPatchBase::facePoint ( mesh(), @@ -217,9 +345,15 @@ Foam::patchSeedSet::patchSeedSet wordReList(dict.lookup("patches")) ) ), - //searchDist_(readScalar(dict.lookup("maxDistance"))), - //offsetDist_(readScalar(dict.lookup("offsetDist"))), - maxPoints_(readLabel(dict.lookup("maxPoints"))) + maxPoints_(readLabel(dict.lookup("maxPoints"))), + selectedLocations_ + ( + dict.lookupOrDefault<pointField> + ( + "points", + pointField(0) + ) + ) { genSamples(); diff --git a/src/sampling/sampledSet/patchSeed/patchSeedSet.H b/src/sampling/sampledSet/patchSeed/patchSeedSet.H index a6e795ad2be1a9d641efb2cf9418b757792fcfc4..c2143a209852416839b8b6b7b4525dd986601e1f 100644 --- a/src/sampling/sampledSet/patchSeed/patchSeedSet.H +++ b/src/sampling/sampledSet/patchSeed/patchSeedSet.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2012-2014 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -58,18 +58,15 @@ class patchSeedSet //- Patches to sample const labelHashSet patchSet_; -// //- Maximum distance to look for nearest -// const scalar searchDist_; -// -// //- Offset distance -// const scalar offsetDist_; - - //- Maximum number of patch faces to seed + //- Maximum number of patch faces to seed (if in random subset mode) const label maxPoints_; //- Random number generator (if maxPoints < num patch faces) autoPtr<Random> rndGenPtr_; + //- Patch faces to seed selected based on nearness to supplied points + const pointField selectedLocations_; + // Private Member Functions diff --git a/src/sampling/sampledSet/uniform/uniformSet.C b/src/sampling/sampledSet/uniform/uniformSet.C index 9689218ae58c591fde4c69fcad9decabc52c767c..4c2650c443426761a48df748e19aee3f7e6be7df 100644 --- a/src/sampling/sampledSet/uniform/uniformSet.C +++ b/src/sampling/sampledSet/uniform/uniformSet.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -276,6 +276,8 @@ void Foam::uniformSet::calcSamples // (or is along edge) // Set points and cell/face labels to empty lists + const_cast<polyMesh&>(mesh()).moving(oldMoving); + return; } diff --git a/src/sampling/sampledSurface/distanceSurface/distanceSurface.C b/src/sampling/sampledSurface/distanceSurface/distanceSurface.C index 2dafe3e98ad268312e11ca50d68c84a2669b83ec..fd2927ca719e7225fb8e55cfc1c5e72c640745fc 100644 --- a/src/sampling/sampledSurface/distanceSurface/distanceSurface.C +++ b/src/sampling/sampledSurface/distanceSurface/distanceSurface.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -278,7 +278,8 @@ void Foam::distanceSurface::createGeometry() cellDistance, pointDistance_, distance_, - regularise_ + regularise_, + bounds_ ) ); } @@ -291,7 +292,8 @@ void Foam::distanceSurface::createGeometry() cellDistance, pointDistance_, distance_, - regularise_ + regularise_, + bounds_ ) ); } @@ -336,6 +338,7 @@ Foam::distanceSurface::distanceSurface cell_(dict.lookupOrDefault("cell", true)), regularise_(dict.lookupOrDefault("regularise", true)), average_(dict.lookupOrDefault("average", false)), + bounds_(dict.lookupOrDefault("bounds", boundBox::greatBox)), zoneKey_(keyType::null), needsUpdate_(true), isoSurfCellPtr_(NULL), @@ -364,7 +367,8 @@ Foam::distanceSurface::distanceSurface const bool signedDistance, const bool cell, const Switch regularise, - const Switch average + const Switch average, + const boundBox& bounds ) : sampledSurface(name, mesh, interpolate), @@ -390,6 +394,7 @@ Foam::distanceSurface::distanceSurface cell_(cell), regularise_(regularise), average_(average), + bounds_(bounds), zoneKey_(keyType::null), needsUpdate_(true), isoSurfCellPtr_(NULL), diff --git a/src/sampling/sampledSurface/distanceSurface/distanceSurface.H b/src/sampling/sampledSurface/distanceSurface/distanceSurface.H index 73cd555e05e35a04dee8c5854745d8ba36fcbfed..aa3f63251144fa3a46ba4140c416070d87b0f3df 100644 --- a/src/sampling/sampledSurface/distanceSurface/distanceSurface.H +++ b/src/sampling/sampledSurface/distanceSurface/distanceSurface.H @@ -75,6 +75,9 @@ class distanceSurface //- Whether to recalculate cell values as average of point values const Switch average_; + //- Optional bounding box to trim triangles against + const boundBox bounds_; + //- If restricted to zones, name of this zone or a regular expression keyType zoneKey_; @@ -144,7 +147,8 @@ public: const bool signedDistance, const bool cell, const Switch regularise, - const Switch average + const Switch average, + const boundBox& bounds = boundBox::greatBox ); diff --git a/src/sampling/sampledSurface/isoSurface/isoSurface.C b/src/sampling/sampledSurface/isoSurface/isoSurface.C index e3105b35a56410fe8c6c1ee73425ac45874fcb95..9dbe88440d49a2e43bdbcff0f96d2f24e34685bb 100644 --- a/src/sampling/sampledSurface/isoSurface/isoSurface.C +++ b/src/sampling/sampledSurface/isoSurface/isoSurface.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -32,12 +32,36 @@ License #include "surfaceFields.H" #include "OFstream.H" #include "meshTools.H" +#include "triSurfaceSearch.H" +#include "surfaceIntersection.H" +#include "intersectedSurface.H" +#include "searchableBox.H" +#include "triSurfaceMesh.H" +#include "triPoints.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { defineTypeNameAndDebug(isoSurface, 0); + +// Helper class for slicing triangles +class storeOp +{ +public: + DynamicList<triPoints>& tris_; + + inline storeOp(DynamicList<triPoints>& tris) + : + tris_(tris) + {} + + inline void operator()(const triPoints& tri) + { + tris_.append(tri); + } +}; + } @@ -473,43 +497,6 @@ void Foam::isoSurface::calcCutTypes } -// Return the two common points between two triangles -Foam::labelPair Foam::isoSurface::findCommonPoints -( - const labelledTri& tri0, - const labelledTri& tri1 -) -{ - labelPair common(-1, -1); - - label fp0 = 0; - label fp1 = findIndex(tri1, tri0[fp0]); - - if (fp1 == -1) - { - fp0 = 1; - fp1 = findIndex(tri1, tri0[fp0]); - } - - if (fp1 != -1) - { - // So tri0[fp0] is tri1[fp1] - - // Find next common point - label fp0p1 = tri0.fcIndex(fp0); - label fp1p1 = tri1.fcIndex(fp1); - label fp1m1 = tri1.rcIndex(fp1); - - if (tri0[fp0p1] == tri1[fp1p1] || tri0[fp0p1] == tri1[fp1m1]) - { - common[0] = tri0[fp0]; - common[1] = tri0[fp0p1]; - } - } - return common; -} - - // Caculate centre of surface. Foam::point Foam::isoSurface::calcCentre(const triSurface& s) { @@ -523,73 +510,6 @@ Foam::point Foam::isoSurface::calcCentre(const triSurface& s) } -// Replace surface (localPoints, localTris) with single point. Returns -// point. Destructs arguments. -Foam::pointIndexHit Foam::isoSurface::collapseSurface -( - pointField& localPoints, - DynamicList<labelledTri, 64>& localTris -) -{ - pointIndexHit info(false, vector::zero, localTris.size()); - - if (localTris.size() == 1) - { - const labelledTri& tri = localTris[0]; - info.setPoint(tri.centre(localPoints)); - info.setHit(); - } - else if (localTris.size() == 2) - { - // Check if the two triangles share an edge. - const labelledTri& tri0 = localTris[0]; - const labelledTri& tri1 = localTris[0]; - - labelPair shared = findCommonPoints(tri0, tri1); - - if (shared[0] != -1) - { - info.setPoint - ( - 0.5 - * ( - tri0.centre(localPoints) - + tri1.centre(localPoints) - ) - ); - info.setHit(); - } - } - else if (localTris.size()) - { - // Check if single region. Rare situation. - triSurface surf - ( - localTris, - geometricSurfacePatchList(0), - localPoints, - true - ); - localTris.clearStorage(); - - labelList faceZone; - label nZones = surf.markZones - ( - boolList(surf.nEdges(), false), - faceZone - ); - - if (nZones == 1) - { - info.setPoint(calcCentre(surf)); - info.setHit(); - } - } - - return info; -} - - // Determine per cell centre whether all the intersections get collapsed // to a single point void Foam::isoSurface::calcSnappedCc @@ -1133,505 +1053,288 @@ Foam::triSurface Foam::isoSurface::stitchTriPoints } -// Does face use valid vertices? -bool Foam::isoSurface::validTri(const triSurface& surf, const label faceI) +void Foam::isoSurface::trimToPlanes +( + const PtrList<plane>& planes, + const triPointRef& tri, + DynamicList<point>& newTriPoints +) { - // Simple check on indices ok. - - const labelledTri& f = surf[faceI]; + // Buffer for generated triangles + DynamicList<triPoints> insideTrisA; + storeOp insideOpA(insideTrisA); - if - ( - (f[0] < 0) || (f[0] >= surf.points().size()) - || (f[1] < 0) || (f[1] >= surf.points().size()) - || (f[2] < 0) || (f[2] >= surf.points().size()) - ) - { - WarningIn("validTri(const triSurface&, const label)") - << "triangle " << faceI << " vertices " << f - << " uses point indices outside point range 0.." - << surf.points().size()-1 << endl; + // Buffer for generated triangles + DynamicList<triPoints> insideTrisB; + storeOp insideOpB(insideTrisB); - return false; - } + triPointRef::dummyOp dop; - if ((f[0] == f[1]) || (f[0] == f[2]) || (f[1] == f[2])) - { - WarningIn("validTri(const triSurface&, const label)") - << "triangle " << faceI - << " uses non-unique vertices " << f - << endl; - return false; - } + // Store starting triangle in insideTrisA + insideOpA(triPoints(tri.a(), tri.b(), tri.c())); - // duplicate triangle check - const labelList& fFaces = surf.faceFaces()[faceI]; + bool useA = true; - // Check if faceNeighbours use same points as this face. - // Note: discards normal information - sides of baffle are merged. - forAll(fFaces, i) + forAll(planes, faceI) { - label nbrFaceI = fFaces[i]; + const plane& pl = planes[faceI]; - if (nbrFaceI <= faceI) + if (useA) { - // lower numbered faces already checked - continue; + insideOpB.tris_.clear(); + forAll(insideOpA.tris_, i) + { + const triPoints& tri = insideOpA.tris_[i]; + triPointRef(tri).sliceWithPlane(pl, insideOpB, dop); + } + } + else + { + insideOpA.tris_.clear(); + forAll(insideOpB.tris_, i) + { + const triPoints& tri = insideOpB.tris_[i]; + triPointRef(tri).sliceWithPlane(pl, insideOpA, dop); + } } + useA = !useA; + } - const labelledTri& nbrF = surf[nbrFaceI]; - if - ( - ((f[0] == nbrF[0]) || (f[0] == nbrF[1]) || (f[0] == nbrF[2])) - && ((f[1] == nbrF[0]) || (f[1] == nbrF[1]) || (f[1] == nbrF[2])) - && ((f[2] == nbrF[0]) || (f[2] == nbrF[1]) || (f[2] == nbrF[2])) - ) + // Transfer + if (useA) + { + forAll(insideOpA.tris_, i) { - WarningIn("validTri(const triSurface&, const label)") - << "triangle " << faceI << " vertices " << f - << " fc:" << f.centre(surf.points()) - << " has the same vertices as triangle " << nbrFaceI - << " vertices " << nbrF - << " fc:" << nbrF.centre(surf.points()) - << endl; - - return false; + const triPoints& tri = insideOpA.tris_[i]; + newTriPoints.append(tri[0]); + newTriPoints.append(tri[1]); + newTriPoints.append(tri[2]); + } + } + else + { + forAll(insideOpB.tris_, i) + { + const triPoints& tri = insideOpB.tris_[i]; + newTriPoints.append(tri[0]); + newTriPoints.append(tri[1]); + newTriPoints.append(tri[2]); } } - return true; } -void Foam::isoSurface::calcAddressing +void Foam::isoSurface::trimToBox ( - const triSurface& surf, - List<FixedList<label, 3> >& faceEdges, - labelList& edgeFace0, - labelList& edgeFace1, - Map<labelList>& edgeFacesRest -) const + const treeBoundBox& bb, + DynamicList<point>& triPoints, + DynamicList<label>& triMap // trimmed to original tris +) { - const pointField& points = surf.points(); - - pointField edgeCentres(3*surf.size()); - label edgeI = 0; - forAll(surf, triI) - { - const labelledTri& tri = surf[triI]; - edgeCentres[edgeI++] = 0.5*(points[tri[0]]+points[tri[1]]); - edgeCentres[edgeI++] = 0.5*(points[tri[1]]+points[tri[2]]); - edgeCentres[edgeI++] = 0.5*(points[tri[2]]+points[tri[0]]); - } - - pointField mergedCentres; - labelList oldToMerged; - bool hasMerged = mergePoints - ( - edgeCentres, - mergeDistance_, - false, - oldToMerged, - mergedCentres - ); - if (debug) { - Pout<< "isoSurface : detected " - << mergedCentres.size() - << " geometric edges on " << surf.size() << " triangles." << endl; - } - - if (!hasMerged) - { - return; + Pout<< "isoSurface : trimming to " << bb << endl; } - - // Determine faceEdges - faceEdges.setSize(surf.size()); - edgeI = 0; - forAll(surf, triI) + // Generate inwards pointing planes + PtrList<plane> planes(6); + const pointField pts(bb.treeBoundBox::points()); + forAll(treeBoundBox::faces, faceI) { - faceEdges[triI][0] = oldToMerged[edgeI++]; - faceEdges[triI][1] = oldToMerged[edgeI++]; - faceEdges[triI][2] = oldToMerged[edgeI++]; + const face& f = treeBoundBox::faces[faceI]; + const vector& n = treeBoundBox::faceNormals[faceI]; + planes.set(faceI, new plane(pts[f[0]], -n)); } + label nTris = triPoints.size()/3; - // Determine edgeFaces - edgeFace0.setSize(mergedCentres.size()); - edgeFace0 = -1; - edgeFace1.setSize(mergedCentres.size()); - edgeFace1 = -1; - edgeFacesRest.clear(); - - // Overflow edge faces for geometric shared edges that turned - // out to be different anyway. - EdgeMap<labelList> extraEdgeFaces(mergedCentres.size()/100); + DynamicList<point> newTriPoints(triPoints.size()/16); + triMap.setCapacity(nTris/16); - forAll(oldToMerged, oldEdgeI) + label vertI = 0; + for (label triI = 0; triI < nTris; triI++) { - label triI = oldEdgeI / 3; - label edgeI = oldToMerged[oldEdgeI]; + const point& p0 = triPoints[vertI++]; + const point& p1 = triPoints[vertI++]; + const point& p2 = triPoints[vertI++]; + + label oldNPoints = newTriPoints.size(); + trimToPlanes + ( + planes, + triPointRef(p0, p1, p2), + newTriPoints + ); - if (edgeFace0[edgeI] == -1) + label nCells = (newTriPoints.size()-oldNPoints)/3; + for (label i = 0; i < nCells; i++) { - // First triangle for edge - edgeFace0[edgeI] = triI; + triMap.append(triI); } - else - { - //- Check that the two triangles actually topologically - // share an edge - const labelledTri& prevTri = surf[edgeFace0[edgeI]]; - const labelledTri& tri = surf[triI]; + } - label fp = oldEdgeI % 3; + if (debug) + { + Pout<< "isoSurface : trimmed from " << nTris + << " down to " << triMap.size() + << " triangles." << endl; + } - edge e(tri[fp], tri[tri.fcIndex(fp)]); + triPoints.transfer(newTriPoints); +} - label prevTriIndex = -1; - forAll(prevTri, i) - { - if (edge(prevTri[i], prevTri[prevTri.fcIndex(i)]) == e) - { - prevTriIndex = i; - break; - } - } +void Foam::isoSurface::trimToBox +( + const treeBoundBox& bb, + DynamicList<point>& triPoints, // new points + DynamicList<label>& triMap, // map from (new) triangle to original + labelList& triPointMap, // map from (new) point to original + labelList& interpolatedPoints, // labels of newly introduced points + List<FixedList<label, 3> >& interpolatedOldPoints,// and their interpolation + List<FixedList<scalar, 3> >& interpolationWeights +) +{ + const List<point> oldTriPoints(triPoints); - if (prevTriIndex == -1) - { - // Different edge. Store for later. - EdgeMap<labelList>::iterator iter = extraEdgeFaces.find(e); + // Trim triPoints, return map + trimToBox(bb, triPoints, triMap); - if (iter != extraEdgeFaces.end()) - { - labelList& eFaces = iter(); - label sz = eFaces.size(); - eFaces.setSize(sz+1); - eFaces[sz] = triI; - } - else - { - extraEdgeFaces.insert(e, labelList(1, triI)); - } - } - else if (edgeFace1[edgeI] == -1) - { - edgeFace1[edgeI] = triI; - } - else - { - //WarningIn("orientSurface(triSurface&)") - // << "Edge " << edgeI << " with centre " - // << mergedCentres[edgeI] - // << " used by more than two triangles: " - // << edgeFace0[edgeI] << ", " - // << edgeFace1[edgeI] << " and " << triI << endl; - Map<labelList>::iterator iter = edgeFacesRest.find(edgeI); - - if (iter != edgeFacesRest.end()) - { - labelList& eFaces = iter(); - label sz = eFaces.size(); - eFaces.setSize(sz+1); - eFaces[sz] = triI; - } - else - { - edgeFacesRest.insert(edgeI, labelList(1, triI)); - } - } - } - } - // Add extraEdgeFaces - edgeI = edgeFace0.size(); + // Find point correspondence: + // - one-to-one for preserved original points (triPointMap) + // - interpolation for newly introduced points + // (interpolatedOldPoints) + label sz = oldTriPoints.size()/100; + DynamicList<label> dynInterpolatedPoints(sz); + DynamicList<FixedList<label, 3> > dynInterpolatedOldPoints(sz); + DynamicList<FixedList<scalar, 3> > dynInterpolationWeights(sz); - edgeFace0.setSize(edgeI + extraEdgeFaces.size()); - edgeFace1.setSize(edgeI + extraEdgeFaces.size(), -1); - forAllConstIter(EdgeMap<labelList>, extraEdgeFaces, iter) + triPointMap.setSize(triPoints.size()); + forAll(triMap, triI) { - const labelList& eFaces = iter(); + label oldTriI = triMap[triI]; - // The current edge will become edgeI. Replace all occurrences in - // faceEdges - forAll(eFaces, i) + // Find point correspondence. Assumes coordinate is bit-copy. + for (label i = 0; i < 3; i++) { - label triI = eFaces[i]; - const labelledTri& tri = surf[triI]; + label pointI = 3*triI+i; + const point& pt = triPoints[pointI]; - FixedList<label, 3>& fEdges = faceEdges[triI]; - forAll(tri, fp) + // Compare to old-triangle's points + label matchPointI = -1; + for (label j = 0; j < 3; j++) { - edge e(tri[fp], tri[tri.fcIndex(fp)]); - - if (e == iter.key()) + label oldPointI = 3*oldTriI+j; + if (pt == oldTriPoints[oldPointI]) { - fEdges[fp] = edgeI; + matchPointI = oldPointI; break; } } - } - - // Add face to edgeFaces - - edgeFace0[edgeI] = eFaces[0]; - - if (eFaces.size() >= 2) - { - edgeFace1[edgeI] = eFaces[1]; + triPointMap[pointI] = matchPointI; - if (eFaces.size() > 2) + // If new point: calculate and store interpolation + if (matchPointI == -1) { - edgeFacesRest.insert - ( - edgeI, - SubList<label>(eFaces, eFaces.size()-2, 2) - ); + dynInterpolatedPoints.append(pointI); + + FixedList<label, 3> oldPoints; + oldPoints[0] = 3*oldTriI; + oldPoints[1] = 3*oldTriI+1; + oldPoints[2] = 3*oldTriI+2; + dynInterpolatedOldPoints.append(oldPoints); + + triPointRef tri(oldTriPoints, oldPoints); + scalarList bary; + tri.barycentric(pt, bary); + FixedList<scalar, 3> weights; + weights[0] = bary[0]; + weights[1] = bary[1]; + weights[2] = bary[2]; + dynInterpolationWeights.append(weights); } } - - edgeI++; } -} - - -void Foam::isoSurface::walkOrientation -( - const triSurface& surf, - const List<FixedList<label, 3> >& faceEdges, - const labelList& edgeFace0, - const labelList& edgeFace1, - const label seedTriI, - labelList& flipState -) -{ - // Do walk for consistent orientation. - DynamicList<label> changedFaces(surf.size()); - - changedFaces.append(seedTriI); - - while (changedFaces.size()) - { - DynamicList<label> newChangedFaces(changedFaces.size()); - forAll(changedFaces, i) - { - label triI = changedFaces[i]; - const labelledTri& tri = surf[triI]; - const FixedList<label, 3>& fEdges = faceEdges[triI]; - - forAll(fEdges, fp) - { - label edgeI = fEdges[fp]; - - // my points: - label p0 = tri[fp]; - label p1 = tri[tri.fcIndex(fp)]; - - label nbrI = - ( - edgeFace0[edgeI] != triI - ? edgeFace0[edgeI] - : edgeFace1[edgeI] - ); - - if (nbrI != -1 && flipState[nbrI] == -1) - { - const labelledTri& nbrTri = surf[nbrI]; - - // nbr points - label nbrFp = findIndex(nbrTri, p0); - - if (nbrFp == -1) - { - FatalErrorIn("isoSurface::walkOrientation(..)") - << "triI:" << triI - << " tri:" << tri - << " p0:" << p0 - << " p1:" << p1 - << " fEdges:" << fEdges - << " edgeI:" << edgeI - << " edgeFace0:" << edgeFace0[edgeI] - << " edgeFace1:" << edgeFace1[edgeI] - << " nbrI:" << nbrI - << " nbrTri:" << nbrTri - << abort(FatalError); - } - - - label nbrP1 = nbrTri[nbrTri.rcIndex(nbrFp)]; - - bool sameOrientation = (p1 == nbrP1); - - if (flipState[triI] == 0) - { - flipState[nbrI] = (sameOrientation ? 0 : 1); - } - else - { - flipState[nbrI] = (sameOrientation ? 1 : 0); - } - newChangedFaces.append(nbrI); - } - } - } - - changedFaces.transfer(newChangedFaces); - } + interpolatedPoints.transfer(dynInterpolatedPoints); + interpolatedOldPoints.transfer(dynInterpolatedOldPoints); + interpolationWeights.transfer(dynInterpolationWeights); } -void Foam::isoSurface::orientSurface -( - triSurface& surf, - const List<FixedList<label, 3> >& faceEdges, - const labelList& edgeFace0, - const labelList& edgeFace1, - const Map<labelList>& edgeFacesRest -) +// Does face use valid vertices? +bool Foam::isoSurface::validTri(const triSurface& surf, const label faceI) { - // -1 : unvisited - // 0 : leave as is - // 1 : flip - labelList flipState(surf.size(), -1); - - label seedTriI = 0; - - while (true) - { - // Find first unvisited triangle - for - ( - ; - seedTriI < surf.size() && flipState[seedTriI] != -1; - seedTriI++ - ) - {} - - if (seedTriI == surf.size()) - { - break; - } - - // Note: Determine orientation of seedTriI? - // for now assume it is ok - flipState[seedTriI] = 0; + // Simple check on indices ok. - walkOrientation - ( - surf, - faceEdges, - edgeFace0, - edgeFace1, - seedTriI, - flipState - ); - } + const labelledTri& f = surf[faceI]; - // Do actual flipping - surf.clearOut(); - forAll(surf, triI) + if + ( + (f[0] < 0) || (f[0] >= surf.points().size()) + || (f[1] < 0) || (f[1] >= surf.points().size()) + || (f[2] < 0) || (f[2] >= surf.points().size()) + ) { - if (flipState[triI] == 1) - { - labelledTri tri(surf[triI]); - - surf[triI][0] = tri[0]; - surf[triI][1] = tri[2]; - surf[triI][2] = tri[1]; - } - else if (flipState[triI] == -1) - { - FatalErrorIn - ( - "isoSurface::orientSurface(triSurface&, const label)" - ) << "problem" << abort(FatalError); - } - } -} - + WarningIn("validTri(const triSurface&, const label)") + << "triangle " << faceI << " vertices " << f + << " uses point indices outside point range 0.." + << surf.points().size()-1 << endl; -// Checks if triangle is connected through edgeI only. -bool Foam::isoSurface::danglingTriangle -( - const FixedList<label, 3>& fEdges, - const labelList& edgeFace1 -) -{ - label nOpen = 0; - forAll(fEdges, i) - { - if (edgeFace1[fEdges[i]] == -1) - { - nOpen++; - } + return false; } - if (nOpen == 1 || nOpen == 2 || nOpen == 3) - { - return true; - } - else + if ((f[0] == f[1]) || (f[0] == f[2]) || (f[1] == f[2])) { + WarningIn("validTri(const triSurface&, const label)") + << "triangle " << faceI + << " uses non-unique vertices " << f + << endl; return false; } -} + // duplicate triangle check -// Mark triangles to keep. Returns number of dangling triangles. -Foam::label Foam::isoSurface::markDanglingTriangles -( - const List<FixedList<label, 3> >& faceEdges, - const labelList& edgeFace0, - const labelList& edgeFace1, - const Map<labelList>& edgeFacesRest, - boolList& keepTriangles -) -{ - keepTriangles.setSize(faceEdges.size()); - keepTriangles = true; - - label nDangling = 0; + const labelList& fFaces = surf.faceFaces()[faceI]; - // Remove any dangling triangles - forAllConstIter(Map<labelList>, edgeFacesRest, iter) + // Check if faceNeighbours use same points as this face. + // Note: discards normal information - sides of baffle are merged. + forAll(fFaces, i) { - // These are all the non-manifold edges. Filter out all triangles - // with only one connected edge (= this edge) - - label edgeI = iter.key(); - const labelList& otherEdgeFaces = iter(); + label nbrFaceI = fFaces[i]; - // Remove all dangling triangles - if (danglingTriangle(faceEdges[edgeFace0[edgeI]], edgeFace1)) - { - keepTriangles[edgeFace0[edgeI]] = false; - nDangling++; - } - if (danglingTriangle(faceEdges[edgeFace1[edgeI]], edgeFace1)) + if (nbrFaceI <= faceI) { - keepTriangles[edgeFace1[edgeI]] = false; - nDangling++; + // lower numbered faces already checked + continue; } - forAll(otherEdgeFaces, i) + + const labelledTri& nbrF = surf[nbrFaceI]; + + if + ( + ((f[0] == nbrF[0]) || (f[0] == nbrF[1]) || (f[0] == nbrF[2])) + && ((f[1] == nbrF[0]) || (f[1] == nbrF[1]) || (f[1] == nbrF[2])) + && ((f[2] == nbrF[0]) || (f[2] == nbrF[1]) || (f[2] == nbrF[2])) + ) { - label triI = otherEdgeFaces[i]; - if (danglingTriangle(faceEdges[triI], edgeFace1)) - { - keepTriangles[triI] = false; - nDangling++; - } + WarningIn("validTri(const triSurface&, const label)") + << "triangle " << faceI << " vertices " << f + << " fc:" << f.centre(surf.points()) + << " has the same vertices as triangle " << nbrFaceI + << " vertices " << nbrF + << " fc:" << nbrF.centre(surf.points()) + << endl; + + return false; } } - return nDangling; + return true; } @@ -1715,6 +1418,7 @@ Foam::isoSurface::isoSurface const scalarField& pVals, const scalar iso, const bool regularise, + const boundBox& bounds, const scalar mergeTol ) : @@ -1722,6 +1426,7 @@ Foam::isoSurface::isoSurface pVals_(pVals), iso_(iso), regularise_(regularise), + bounds_(bounds), mergeDistance_(mergeTol*mesh_.bounds().mag()) { if (debug) @@ -1957,138 +1662,115 @@ Foam::isoSurface::isoSurface } - - DynamicList<point> triPoints(nCutCells_); - DynamicList<label> triMeshCells(nCutCells_); - - generateTriPoints - ( - cValsPtr_(), - pVals_, - - meshC, - mesh_.points(), - - snappedPoints, - snappedCc, - snappedPoint, - - triPoints, - triMeshCells - ); - - if (debug) { - Pout<< "isoSurface : generated " << triMeshCells.size() - << " unmerged triangles from " << triPoints.size() - << " unmerged points." << endl; - } + DynamicList<point> triPoints(3*nCutCells_); + DynamicList<label> triMeshCells(nCutCells_); - - // Merge points and compact out non-valid triangles - labelList triMap; // merged to unmerged triangle - triSurface::operator= - ( - stitchTriPoints + generateTriPoints ( - true, // check for duplicate tris - triPoints, - triPointMergeMap_, // unmerged to merged point - triMap - ) - ); + cValsPtr_(), + pVals_, - if (debug) - { - Pout<< "isoSurface : generated " << triMap.size() - << " merged triangles." << endl; - } + meshC, + mesh_.points(), - meshCells_.setSize(triMap.size()); - forAll(triMap, i) - { - meshCells_[i] = triMeshCells[triMap[i]]; - } + snappedPoints, + snappedCc, + snappedPoint, - if (debug) - { - Pout<< "isoSurface : checking " << size() - << " triangles for validity." << endl; + triPoints, // 3 points of the triangle + triMeshCells // per triangle the originating cell + ); - forAll(*this, triI) + if (debug) { - // Copied from surfaceCheck - validTri(*this, triI); + Pout<< "isoSurface : generated " << triMeshCells.size() + << " unmerged triangles from " << triPoints.size() + << " unmerged points." << endl; } - } - - - if (false) - { - List<FixedList<label, 3> > faceEdges; - labelList edgeFace0, edgeFace1; - Map<labelList> edgeFacesRest; + label nOldPoints = triPoints.size(); - while (true) + // Trimmed to original triangle + DynamicList<label> trimTriMap; + // Trimmed to original point + labelList trimTriPointMap; + if (bounds_ != boundBox::greatBox) { - // Calculate addressing - calcAddressing + trimToBox ( - *this, - faceEdges, - edgeFace0, - edgeFace1, - edgeFacesRest + treeBoundBox(bounds_), + triPoints, // new points + trimTriMap, // map from (new) triangle to original + trimTriPointMap, // map from (new) point to original + interpolatedPoints_, // labels of newly introduced points + interpolatedOldPoints_, // and their interpolation + interpolationWeights_ ); + triMeshCells = labelField(triMeshCells, trimTriMap); + } - // See if any dangling triangles - boolList keepTriangles; - label nDangling = markDanglingTriangles + + // Merge points and compact out non-valid triangles + labelList triMap; // merged to unmerged triangle + triSurface::operator= + ( + stitchTriPoints ( - faceEdges, - edgeFace0, - edgeFace1, - edgeFacesRest, - keepTriangles - ); + true, // check for duplicate tris + triPoints, + triPointMergeMap_, // unmerged to merged point + triMap + ) + ); - if (debug) - { - Pout<< "isoSurface : detected " << nDangling - << " dangling triangles." << endl; - } + if (debug) + { + Pout<< "isoSurface : generated " << triMap.size() + << " merged triangles." << endl; + } - if (nDangling == 0) - { - break; - } - // Create face map (new to old) - labelList subsetTriMap(findIndices(keepTriangles, true)); + if (bounds_ != boundBox::greatBox) + { + // Adjust interpolatedPoints_ + inplaceRenumber(triPointMergeMap_, interpolatedPoints_); - labelList subsetPointMap; - labelList reversePointMap; - triSurface::operator= - ( - subsetMesh - ( - *this, - subsetTriMap, - reversePointMap, - subsetPointMap - ) - ); - meshCells_ = labelField(meshCells_, subsetTriMap); - inplaceRenumber(reversePointMap, triPointMergeMap_); + // Adjust triPointMergeMap_ + labelList newTriPointMergeMap(nOldPoints, -1); + forAll(trimTriPointMap, trimPointI) + { + label oldPointI = trimTriPointMap[trimPointI]; + if (oldPointI >= 0) + { + label pointI = triPointMergeMap_[trimPointI]; + if (pointI >= 0) + { + newTriPointMergeMap[oldPointI] = pointI; + } + } + } + triPointMergeMap_.transfer(newTriPointMergeMap); } - orientSurface(*this, faceEdges, edgeFace0, edgeFace1, edgeFacesRest); + meshCells_.setSize(triMap.size()); + forAll(triMap, i) + { + meshCells_[i] = triMeshCells[triMap[i]]; + } } - if (debug) { + Pout<< "isoSurface : checking " << size() + << " triangles for validity." << endl; + + forAll(*this, triI) + { + // Copied from surfaceCheck + validTri(*this, triI); + } + fileName stlFile = mesh_.time().path() + ".stl"; Pout<< "Dumping surface to " << stlFile << endl; triSurface::write(stlFile); diff --git a/src/sampling/sampledSurface/isoSurface/isoSurface.H b/src/sampling/sampledSurface/isoSurface/isoSurface.H index 9f6dc7d76e0318abe34e3455c9ffeb9bd0de77b1..c74586a2ce1f4f1ee07aa9f59261582beef3339b 100644 --- a/src/sampling/sampledSurface/isoSurface/isoSurface.H +++ b/src/sampling/sampledSurface/isoSurface/isoSurface.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -76,6 +76,8 @@ namespace Foam { class fvMesh; +class plane; +class treeBoundBox; /*---------------------------------------------------------------------------*\ Class isoSurface Declaration @@ -116,10 +118,12 @@ class isoSurface //- Regularise? const Switch regularise_; + //- Optional bounds + const boundBox bounds_; + //- When to merge points const scalar mergeDistance_; - //- Whether face might be cut List<cellCutType> faceCutType_; @@ -135,6 +139,15 @@ class isoSurface //- For every unmerged triangle point the point in the triSurface labelList triPointMergeMap_; + //- triSurface points that have weighted interpolation + DynamicList<label> interpolatedPoints_; + + //- corresponding original, unmerged points + DynamicList<FixedList<label, 3> > interpolatedOldPoints_; + + //- corresponding weights + DynamicList<FixedList<scalar, 3> > interpolationWeights_; + // Private Member Functions @@ -193,20 +206,8 @@ class isoSurface const scalarField& pVals ); - static labelPair findCommonPoints - ( - const labelledTri&, - const labelledTri& - ); - static point calcCentre(const triSurface&); - static pointIndexHit collapseSurface - ( - pointField& localPoints, - DynamicList<labelledTri, 64>& localTris - ); - //- Determine per cc whether all near cuts can be snapped to single // point. void calcSnappedCc @@ -323,6 +324,17 @@ class isoSurface DynamicList<label>& triMeshCells ) const; + template<class Type> + static tmp<Field<Type> > interpolate + ( + const label nPoints, + const labelList& triPointMergeMap, + const labelList& interpolatedPoints, + const List<FixedList<label, 3> >& interpolatedOldPoints, + const List<FixedList<scalar, 3> >& interpolationWeights, + const DynamicList<Type>& unmergedValues + ); + triSurface stitchTriPoints ( const bool checkDuplicates, @@ -331,56 +343,37 @@ class isoSurface labelList& triMap // merged to unmerged triangle ) const; - //- Check single triangle for (topological) validity - static bool validTri(const triSurface&, const label); - - //- Determine edge-face addressing - void calcAddressing - ( - const triSurface& surf, - List<FixedList<label, 3> >& faceEdges, - labelList& edgeFace0, - labelList& edgeFace1, - Map<labelList>& edgeFacesRest - ) const; - - //- Determine orientation - static void walkOrientation + //- Trim triangle to planes + static void trimToPlanes ( - const triSurface& surf, - const List<FixedList<label, 3> >& faceEdges, - const labelList& edgeFace0, - const labelList& edgeFace1, - const label seedTriI, - labelList& flipState + const PtrList<plane>& planes, + const triPointRef& tri, + DynamicList<point>& newTriPoints ); - //- Orient surface - static void orientSurface + //- Trim all triangles to box + static void trimToBox ( - triSurface&, - const List<FixedList<label, 3> >& faceEdges, - const labelList& edgeFace0, - const labelList& edgeFace1, - const Map<labelList>& edgeFacesRest + const treeBoundBox& bb, + DynamicList<point>& triPoints, + DynamicList<label>& triMeshCells ); - //- Is triangle (given by 3 edges) not fully connected? - static bool danglingTriangle + //- Trim all triangles to box. Determine interpolation + // for existing and new points + static void trimToBox ( - const FixedList<label, 3>& fEdges, - const labelList& edgeFace1 + const treeBoundBox& bb, + DynamicList<point>& triPoints, + DynamicList<label>& triMap, + labelList& triPointMap, + labelList& interpolatedPoints, + List<FixedList<label, 3> >& interpolatedOldPoints, + List<FixedList<scalar, 3> >& interpolationWeights ); - //- Mark all non-fully connected triangles - static label markDanglingTriangles - ( - const List<FixedList<label, 3> >& faceEdges, - const labelList& edgeFace0, - const labelList& edgeFace1, - const Map<labelList>& edgeFacesRest, - boolList& keepTriangles - ); + //- Check single triangle for (topological) validity + static bool validTri(const triSurface&, const label); static triSurface subsetMesh ( @@ -392,6 +385,10 @@ class isoSurface public: + //- Declare friendship with isoSurfaceCell to share some functionality + friend class isoSurfaceCell; + + //- Runtime type information TypeName("isoSurface"); @@ -407,24 +404,19 @@ public: const scalarField& pointIsoVals, const scalar iso, const bool regularise, + const boundBox& bounds = boundBox::greatBox, const scalar mergeTol = 1e-6 // fraction of bounding box ); // Member Functions - //- For every face original cell in mesh + //- For every triangle the original cell in mesh const labelList& meshCells() const { return meshCells_; } - //- For every unmerged triangle point the point in the triSurface - const labelList& triPointMergeMap() const - { - return triPointMergeMap_; - } - //- Interpolates cCoords,pCoords. Uses the references to the original // fields used to create the iso surface. template<class Type> diff --git a/src/sampling/sampledSurface/isoSurface/isoSurfaceCell.C b/src/sampling/sampledSurface/isoSurface/isoSurfaceCell.C index 8123541ebee8bbabcf84c9586a0bc523b5d90c6a..f0f140cfd4a791c96b59b2a6eb6334caf51cfc9e 100644 --- a/src/sampling/sampledSurface/isoSurface/isoSurfaceCell.C +++ b/src/sampling/sampledSurface/isoSurface/isoSurfaceCell.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -30,6 +30,9 @@ License #include "tetMatcher.H" #include "syncTools.H" #include "addToRunTimeSelectionTable.H" +#include "Time.H" +#include "triPoints.H" +#include "isoSurface.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -1222,144 +1225,6 @@ void Foam::isoSurfaceCell::calcAddressing } -//void Foam::isoSurfaceCell::walkOrientation -//( -// const triSurface& surf, -// const List<FixedList<label, 3> >& faceEdges, -// const labelList& edgeFace0, -// const labelList& edgeFace1, -// const label seedTriI, -// labelList& flipState -//) -//{ -// // Do walk for consistent orientation. -// DynamicList<label> changedFaces(surf.size()); -// -// changedFaces.append(seedTriI); -// -// while (changedFaces.size()) -// { -// DynamicList<label> newChangedFaces(changedFaces.size()); -// -// forAll(changedFaces, i) -// { -// label triI = changedFaces[i]; -// const labelledTri& tri = surf[triI]; -// const FixedList<label, 3>& fEdges = faceEdges[triI]; -// -// forAll(fEdges, fp) -// { -// label edgeI = fEdges[fp]; -// -// // my points: -// label p0 = tri[fp]; -// label p1 = tri[tri.fcIndex(fp)]; -// -// label nbrI = -// ( -// edgeFace0[edgeI] != triI -// ? edgeFace0[edgeI] -// : edgeFace1[edgeI] -// ); -// -// if (nbrI != -1 && flipState[nbrI] == -1) -// { -// const labelledTri& nbrTri = surf[nbrI]; -// -// // nbr points -// label nbrFp = findIndex(nbrTri, p0); -// label nbrP1 = nbrTri[nbrTri.rcIndex(nbrFp)]; -// -// bool sameOrientation = (p1 == nbrP1); -// -// if (flipState[triI] == 0) -// { -// flipState[nbrI] = (sameOrientation ? 0 : 1); -// } -// else -// { -// flipState[nbrI] = (sameOrientation ? 1 : 0); -// } -// newChangedFaces.append(nbrI); -// } -// } -// } -// -// changedFaces.transfer(newChangedFaces); -// } -//} -// -// -//void Foam::isoSurfaceCell::orientSurface -//( -// triSurface& surf, -// const List<FixedList<label, 3> >& faceEdges, -// const labelList& edgeFace0, -// const labelList& edgeFace1, -// const Map<labelList>& edgeFacesRest -//) -//{ -// // -1 : unvisited -// // 0 : leave as is -// // 1 : flip -// labelList flipState(surf.size(), -1); -// -// label seedTriI = 0; -// -// while (true) -// { -// // Find first unvisited triangle -// for -// ( -// ; -// seedTriI < surf.size() && flipState[seedTriI] != -1; -// seedTriI++ -// ) -// {} -// -// if (seedTriI == surf.size()) -// { -// break; -// } -// -// // Note: Determine orientation of seedTriI? -// // for now assume it is ok -// flipState[seedTriI] = 0; -// -// walkOrientation -// ( -// surf, -// faceEdges, -// edgeFace0, -// edgeFace1, -// seedTriI, -// flipState -// ); -// } -// -// // Do actual flipping -// surf.clearOut(); -// forAll(surf, triI) -// { -// if (flipState[triI] == 1) -// { -// labelledTri tri(surf[triI]); -// -// surf[triI][0] = tri[0]; -// surf[triI][1] = tri[2]; -// surf[triI][2] = tri[1]; -// } -// else if (flipState[triI] == -1) -// { -// FatalErrorIn -// ( -// "isoSurfaceCell::orientSurface(triSurface&, const label)" -// ) << "problem" << abort(FatalError); -// } -// } -//} - - // Checks if triangle is connected through edgeI only. bool Foam::isoSurfaceCell::danglingTriangle ( @@ -1517,6 +1382,7 @@ Foam::isoSurfaceCell::isoSurfaceCell const scalarField& pVals, const scalar iso, const bool regularise, + const boundBox& bounds, const scalar mergeTol ) : @@ -1524,6 +1390,7 @@ Foam::isoSurfaceCell::isoSurfaceCell cVals_(cVals), pVals_(pVals), iso_(iso), + bounds_(bounds), mergeDistance_(mergeTol*mesh.bounds().mag()) { if (debug) @@ -1607,57 +1474,105 @@ Foam::isoSurfaceCell::isoSurfaceCell } + { + DynamicList<point> triPoints(nCutCells_); + DynamicList<label> triMeshCells(nCutCells_); - DynamicList<point> triPoints(nCutCells_); - DynamicList<label> triMeshCells(nCutCells_); + generateTriPoints + ( + cVals, + pVals, - generateTriPoints - ( - cVals, - pVals, + mesh_.cellCentres(), + mesh_.points(), - mesh_.cellCentres(), - mesh_.points(), + snappedPoints, + snappedCc, + snappedPoint, - snappedPoints, - snappedCc, - snappedPoint, + triPoints, + triMeshCells + ); - triPoints, - triMeshCells - ); + if (debug) + { + Pout<< "isoSurfaceCell : generated " << triMeshCells.size() + << " unmerged triangles." << endl; + } - if (debug) - { - Pout<< "isoSurfaceCell : generated " << triMeshCells.size() - << " unmerged triangles." << endl; - } - // Merge points and compact out non-valid triangles - labelList triMap; // merged to unmerged triangle - triSurface::operator= - ( - stitchTriPoints + label nOldPoints = triPoints.size(); + + // Trimmed to original triangle + DynamicList<label> trimTriMap; + // Trimmed to original point + labelList trimTriPointMap; + if (bounds_ != boundBox::greatBox) + { + isoSurface::trimToBox + ( + treeBoundBox(bounds_), + triPoints, // new points + trimTriMap, // map from (new) triangle to original + trimTriPointMap, // map from (new) point to original + interpolatedPoints_, // labels of newly introduced points + interpolatedOldPoints_, // and their interpolation + interpolationWeights_ + ); + triMeshCells = labelField(triMeshCells, trimTriMap); + } + + + + // Merge points and compact out non-valid triangles + labelList triMap; + triSurface::operator= ( - regularise, // check for duplicate tris - triPoints, - triPointMergeMap_, // unmerged to merged point - triMap - ) - ); + stitchTriPoints + ( + regularise, // check for duplicate tris + triPoints, + triPointMergeMap_, // unmerged to merged point + triMap // merged to unmerged triangle + ) + ); - if (debug) - { - Pout<< "isoSurfaceCell : generated " << triMap.size() - << " merged triangles." << endl; - } + if (debug) + { + Pout<< "isoSurfaceCell : generated " << triMap.size() + << " merged triangles." << endl; + } - meshCells_.setSize(triMap.size()); - forAll(triMap, i) - { - meshCells_[i] = triMeshCells[triMap[i]]; + if (bounds_ != boundBox::greatBox) + { + // Adjust interpolatedPoints_ + inplaceRenumber(triPointMergeMap_, interpolatedPoints_); + + // Adjust triPointMergeMap_ + labelList newTriPointMergeMap(nOldPoints, -1); + forAll(trimTriPointMap, trimPointI) + { + label oldPointI = trimTriPointMap[trimPointI]; + if (oldPointI >= 0) + { + label pointI = triPointMergeMap_[trimPointI]; + if (pointI >= 0) + { + newTriPointMergeMap[oldPointI] = pointI; + } + } + } + triPointMergeMap_.transfer(newTriPointMergeMap); + } + + meshCells_.setSize(triMap.size()); + forAll(triMap, i) + { + meshCells_[i] = triMeshCells[triMap[i]]; + } } + if (debug) { Pout<< "isoSurfaceCell : checking " << size() @@ -1730,8 +1645,6 @@ Foam::isoSurfaceCell::isoSurfaceCell meshCells_ = labelField(meshCells_, subsetTriMap); inplaceRenumber(reversePointMap, triPointMergeMap_); } - - //orientSurface(*this, faceEdges, edgeFace0, edgeFace1, edgeFacesRest); } } diff --git a/src/sampling/sampledSurface/isoSurface/isoSurfaceCell.H b/src/sampling/sampledSurface/isoSurface/isoSurfaceCell.H index 7e12efc7bbead6bdac2d7bc23561734530dfe3ca..910f3fe46ed7bdeef88d173fa1c64cceb705331c 100644 --- a/src/sampling/sampledSurface/isoSurface/isoSurfaceCell.H +++ b/src/sampling/sampledSurface/isoSurface/isoSurfaceCell.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -48,6 +48,7 @@ SourceFiles #include "labelPair.H" #include "pointIndexHit.H" #include "PackedBoolList.H" +#include "boundBox.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -55,6 +56,7 @@ namespace Foam { class polyMesh; +class plane; /*---------------------------------------------------------------------------*\ Class isoSurfaceCell Declaration @@ -91,6 +93,9 @@ class isoSurfaceCell //- isoSurfaceCell value const scalar iso_; + //- Optional bounds + const boundBox bounds_; + //- When to merge points const scalar mergeDistance_; @@ -106,6 +111,15 @@ class isoSurfaceCell //- For every unmerged triangle point the point in the triSurface labelList triPointMergeMap_; + //- triSurface points that have weighted interpolation + DynamicList<label> interpolatedPoints_; + + //- corresponding original, unmerged points + DynamicList<FixedList<label, 3> > interpolatedOldPoints_; + + //- corresponding weights + DynamicList<FixedList<scalar, 3> > interpolationWeights_; + // Private Member Functions @@ -214,19 +228,15 @@ class isoSurfaceCell void generateTriPoints ( const DynamicList<Type>& snapped, - const scalar isoVal0, const scalar s0, const Type& p0, const label p0Index, - const scalar isoVal1, const scalar s1, const Type& p1, const label p1Index, - const scalar isoVal2, const scalar s2, const Type& p2, const label p2Index, - const scalar isoVal3, const scalar s3, const Type& p3, const label p3Index, @@ -271,27 +281,6 @@ class isoSurfaceCell Map<labelList>& edgeFacesRest ) const; - ////- Determine orientation - //static void walkOrientation - //( - // const triSurface& surf, - // const List<FixedList<label, 3> >& faceEdges, - // const labelList& edgeFace0, - // const labelList& edgeFace1, - // const label seedTriI, - // labelList& flipState - //); - - ////- Orient surface - //static void orientSurface - //( - // triSurface&, - // const List<FixedList<label, 3> >& faceEdges, - // const labelList& edgeFace0, - // const labelList& edgeFace1, - // const Map<labelList>& edgeFacesRest - //); - //- Is triangle (given by 3 edges) not fully connected? static bool danglingTriangle ( @@ -317,8 +306,6 @@ class isoSurfaceCell labelList& newToOldPoints ); - //- Combine all triangles inside a cell into a minimal triangulation - void combineCellTriangles(); public: @@ -336,6 +323,7 @@ public: const scalarField& pointValues, const scalar iso, const bool regularise, + const boundBox& bounds = boundBox::greatBox, const scalar mergeTol = 1e-6 // fraction of bounding box ); @@ -348,24 +336,6 @@ public: return meshCells_; } - //- For every unmerged triangle point the point in the triSurface - const labelList triPointMergeMap() const - { - return triPointMergeMap_; - } - - - //- Interpolates cCoords,pCoords. Takes the original fields - // used to create the iso surface. - template<class Type> - tmp<Field<Type> > interpolate - ( - const scalarField& cVals, - const scalarField& pVals, - const Field<Type>& cCoords, - const Field<Type>& pCoords - ) const; - //- Interpolates cCoords,pCoords. template<class Type> tmp<Field<Type> > interpolate diff --git a/src/sampling/sampledSurface/isoSurface/isoSurfaceCellTemplates.C b/src/sampling/sampledSurface/isoSurface/isoSurfaceCellTemplates.C index c78aafeee50525ed763dab6863083546a160084e..8fdee4831b82a2b908addba634e66485077267fe 100644 --- a/src/sampling/sampledSurface/isoSurface/isoSurfaceCellTemplates.C +++ b/src/sampling/sampledSurface/isoSurface/isoSurfaceCellTemplates.C @@ -26,6 +26,7 @@ License #include "isoSurfaceCell.H" #include "polyMesh.H" #include "tetMatcher.H" +#include "isoSurface.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -76,22 +77,18 @@ void Foam::isoSurfaceCell::generateTriPoints ( const DynamicList<Type>& snapped, - const scalar isoVal0, const scalar s0, const Type& p0, const label p0Index, - const scalar isoVal1, const scalar s1, const Type& p1, const label p1Index, - const scalar isoVal2, const scalar s2, const Type& p2, const label p2Index, - const scalar isoVal3, const scalar s3, const Type& p3, const label p3Index, @@ -124,160 +121,196 @@ void Foam::isoSurfaceCell::generateTriPoints case 0x0F: break; - case 0x0E: case 0x01: + case 0x0E: { - // 0 is common point. Orient such that normal points in positive - // gradient direction - if (isoVal0 >= isoVal1) - { - pts.append(generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index)); - pts.append(generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index)); - pts.append(generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index)); - } - else + pts.append + ( + generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index) + ); + pts.append + ( + generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index) + ); + pts.append + ( + generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index) + ); + if (triIndex == 0x0E) { - pts.append(generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index)); - pts.append(generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index)); - pts.append(generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index)); + // Flip normals + label sz = pts.size(); + Swap(pts[sz-2], pts[sz-1]); } } break; - case 0x0D: case 0x02: + case 0x0D: { - // 1 is common point - if (isoVal1 >= isoVal0) - { - pts.append(generatePoint(snapped,s1,p1,p1Index,s0,p0,p0Index)); - pts.append(generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index)); - pts.append(generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index)); - } - else + pts.append + ( + generatePoint(snapped,s1,p1,p1Index,s0,p0,p0Index) + ); + pts.append + ( + generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index) + ); + pts.append + ( + generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index) + ); + + if (triIndex == 0x0D) { - pts.append(generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index)); - pts.append(generatePoint(snapped,s1,p1,p1Index,s0,p0,p0Index)); - pts.append(generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index)); + // Flip normals + label sz = pts.size(); + Swap(pts[sz-2], pts[sz-1]); } } break; - case 0x0C: case 0x03: + case 0x0C: { - Type s02 = generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index); - Type s13 = generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index); - - if (isoVal0 >= isoVal3) - { - pts.append(generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index)); - pts.append(s02); - pts.append(s13); - pts.append(s13); - pts.append(generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index)); - pts.append(s02); - } - else + Type p0p2 = + generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index); + Type p1p3 = + generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index); + + pts.append + ( + generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index) + ); + pts.append(p1p3); + pts.append(p0p2); + + pts.append(p1p3); + pts.append + ( + generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index) + ); + pts.append(p0p2); + + if (triIndex == 0x0C) { - pts.append(s02); - pts.append(generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index)); - pts.append(s13); - pts.append(generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index)); - pts.append(s13); - pts.append(s02); + // Flip normals + label sz = pts.size(); + Swap(pts[sz-5], pts[sz-4]); + Swap(pts[sz-2], pts[sz-1]); } } break; - case 0x0B: case 0x04: + case 0x0B: { - // 2 is common point - if (isoVal2 >= isoVal0) + pts.append + ( + generatePoint(snapped,s2,p2,p2Index,s0,p0,p0Index) + ); + pts.append + ( + generatePoint(snapped,s2,p2,p2Index,s1,p1,p1Index) + ); + pts.append + ( + generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index) + ); + + if (triIndex == 0x0B) { - pts.append(generatePoint(snapped,s2,p2,p2Index,s0,p0,p0Index)); - pts.append(generatePoint(snapped,s2,p2,p2Index,s1,p1,p1Index)); - pts.append(generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index)); - } - else - { - pts.append(generatePoint(snapped,s2,p2,p2Index,s1,p1,p1Index)); - pts.append(generatePoint(snapped,s2,p2,p2Index,s0,p0,p0Index)); - pts.append(generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index)); + // Flip normals + label sz = pts.size(); + Swap(pts[sz-2], pts[sz-1]); } } break; - case 0x0A: case 0x05: + case 0x0A: { - Type s01 = generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index); - Type s23 = generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index); - - if (isoVal3 >= isoVal0) + Type p0p1 = + generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index); + Type p2p3 = + generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index); + + pts.append(p0p1); + pts.append(p2p3); + pts.append + ( + generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index) + ); + + pts.append(p0p1); + pts.append + ( + generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index) + ); + pts.append(p2p3); + + if (triIndex == 0x0A) { - pts.append(s01); - pts.append(s23); - pts.append(generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index)); - pts.append(s01); - pts.append(generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index)); - pts.append(s23); - } - else - { - pts.append(s23); - pts.append(s01); - pts.append(generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index)); - pts.append(generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index)); - pts.append(s01); - pts.append(s23); + // Flip normals + label sz = pts.size(); + Swap(pts[sz-5], pts[sz-4]); + Swap(pts[sz-2], pts[sz-1]); } } break; - case 0x09: case 0x06: + case 0x09: { - Type s01 = generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index); - Type s23 = generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index); - - if (isoVal3 >= isoVal1) + Type p0p1 = + generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index); + Type p2p3 = + generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index); + + pts.append(p0p1); + pts.append + ( + generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index) + ); + pts.append(p2p3); + + pts.append(p0p1); + pts.append(p2p3); + pts.append + ( + generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index) + ); + + if (triIndex == 0x09) { - pts.append(s01); - pts.append(generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index)); - pts.append(s23); - pts.append(s01); - pts.append(generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index)); - pts.append(s23); - } - else - { - pts.append(generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index)); - pts.append(s01); - pts.append(s23); - pts.append(generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index)); - pts.append(s01); - pts.append(s23); + // Flip normals + label sz = pts.size(); + Swap(pts[sz-5], pts[sz-4]); + Swap(pts[sz-2], pts[sz-1]); } } break; - case 0x07: case 0x08: + case 0x07: { - // 3 is common point - if (isoVal3 >= isoVal0) + pts.append + ( + generatePoint(snapped,s3,p3,p3Index,s0,p0,p0Index) + ); + pts.append + ( + generatePoint(snapped,s3,p3,p3Index,s2,p2,p2Index) + ); + pts.append + ( + generatePoint(snapped,s3,p3,p3Index,s1,p1,p1Index) + ); + if (triIndex == 0x07) { - pts.append(generatePoint(snapped,s3,p3,p3Index,s0,p0,p0Index)); - pts.append(generatePoint(snapped,s3,p3,p3Index,s2,p2,p2Index)); - pts.append(generatePoint(snapped,s3,p3,p3Index,s1,p1,p1Index)); - } - else - { - pts.append(generatePoint(snapped,s3,p3,p3Index,s2,p2,p2Index)); - pts.append(generatePoint(snapped,s3,p3,p3Index,s0,p0,p0Index)); - pts.append(generatePoint(snapped,s3,p3,p3Index,s1,p1,p1Index)); + // Flip normals + label sz = pts.size(); + Swap(pts[sz-2], pts[sz-1]); } } break; @@ -341,22 +374,18 @@ void Foam::isoSurfaceCell::generateTriPoints ( snappedPoints, - pVals_[f0[1]], pVals[f0[1]], pCoords[f0[1]], snappedPoint[f0[1]], - pVals_[f0[0]], pVals[f0[0]], pCoords[f0[0]], snappedPoint[f0[0]], - pVals_[f0[2]], pVals[f0[2]], pCoords[f0[2]], snappedPoint[f0[2]], - pVals_[oppositeI], pVals[oppositeI], pCoords[oppositeI], snappedPoint[oppositeI], @@ -370,22 +399,18 @@ void Foam::isoSurfaceCell::generateTriPoints ( snappedPoints, - pVals_[f0[0]], pVals[f0[0]], pCoords[f0[0]], snappedPoint[f0[0]], - pVals_[f0[1]], pVals[f0[1]], pCoords[f0[1]], snappedPoint[f0[1]], - pVals_[f0[2]], pVals[f0[2]], pCoords[f0[2]], snappedPoint[f0[2]], - pVals_[oppositeI], pVals[oppositeI], pCoords[oppositeI], snappedPoint[oppositeI], @@ -411,7 +436,6 @@ void Foam::isoSurfaceCell::generateTriPoints } label fp = f.fcIndex(fp0); - for (label i = 2; i < f.size(); i++) { label nextFp = f.fcIndex(fp); @@ -425,22 +449,18 @@ void Foam::isoSurfaceCell::generateTriPoints ( snappedPoints, - pVals_[tri[1]], pVals[tri[1]], pCoords[tri[1]], snappedPoint[tri[1]], - pVals_[tri[0]], pVals[tri[0]], pCoords[tri[0]], snappedPoint[tri[0]], - pVals_[tri[2]], pVals[tri[2]], pCoords[tri[2]], snappedPoint[tri[2]], - cVals_[cellI], cVals[cellI], cCoords[cellI], snappedCc[cellI], @@ -454,22 +474,18 @@ void Foam::isoSurfaceCell::generateTriPoints ( snappedPoints, - pVals_[tri[0]], pVals[tri[0]], pCoords[tri[0]], snappedPoint[tri[0]], - pVals_[tri[1]], pVals[tri[1]], pCoords[tri[1]], snappedPoint[tri[1]], - pVals_[tri[2]], pVals[tri[2]], pCoords[tri[2]], snappedPoint[tri[2]], - cVals_[cellI], cVals[cellI], cCoords[cellI], snappedCc[cellI], @@ -495,7 +511,7 @@ void Foam::isoSurfaceCell::generateTriPoints if (countNotFoundTets > 0) { - WarningIn("Foam::isoSurfaceCell::generateTriPoints") + WarningIn("Foam::isoSurfaceCell::generateTriPoints(..)") << "Could not find " << countNotFoundTets << " tet base points, which may lead to inverted triangles." << endl; @@ -510,13 +526,11 @@ template<class Type> Foam::tmp<Foam::Field<Type> > Foam::isoSurfaceCell::interpolate ( - const scalarField& cVals, - const scalarField& pVals, const Field<Type>& cCoords, const Field<Type>& pCoords ) const { - DynamicList<Type> triPoints(nCutCells_); + DynamicList<Type> triPoints(3*nCutCells_); DynamicList<label> triMeshCells(nCutCells_); // Dummy snap data @@ -524,59 +538,6 @@ Foam::isoSurfaceCell::interpolate labelList snappedCc(mesh_.nCells(), -1); labelList snappedPoint(mesh_.nPoints(), -1); - - generateTriPoints - ( - cVals, - pVals, - - cCoords, - pCoords, - - snappedPoints, - snappedCc, - snappedPoint, - - triPoints, - triMeshCells - ); - - - // One value per point - tmp<Field<Type> > tvalues(new Field<Type>(points().size())); - Field<Type>& values = tvalues(); - - forAll(triPoints, i) - { - label mergedPointI = triPointMergeMap_[i]; - - if (mergedPointI >= 0) - { - values[mergedPointI] = triPoints[i]; - } - } - - return tvalues; -} - - -template<class Type> -Foam::tmp<Foam::Field<Type> > -Foam::isoSurfaceCell::interpolate -( - const Field<Type>& cCoords, - const Field<Type>& pCoords -) const -{ - DynamicList<Type> triPoints(nCutCells_); - DynamicList<label> triMeshCells(nCutCells_); - - // Dummy snap data - DynamicList<Type> snappedPoints; - labelList snappedCc(mesh_.nCells(), -1); - labelList snappedPoint(mesh_.nPoints(), -1); - - generateTriPoints ( cVals_, @@ -593,22 +554,15 @@ Foam::isoSurfaceCell::interpolate triMeshCells ); - - // One value per point - tmp<Field<Type> > tvalues(new Field<Type>(points().size())); - Field<Type>& values = tvalues(); - - forAll(triPoints, i) - { - label mergedPointI = triPointMergeMap_[i]; - - if (mergedPointI >= 0) - { - values[mergedPointI] = triPoints[i]; - } - } - - return tvalues; + return isoSurface::interpolate + ( + points().size(), + triPointMergeMap_, + interpolatedPoints_, + interpolatedOldPoints_, + interpolationWeights_, + triPoints + ); } diff --git a/src/sampling/sampledSurface/isoSurface/isoSurfaceTemplates.C b/src/sampling/sampledSurface/isoSurface/isoSurfaceTemplates.C index 6f64c9fe541198ea8524f097b69921702d525264..0c4f0f7811d53181d6b56251dc26a8213ac41416 100644 --- a/src/sampling/sampledSurface/isoSurface/isoSurfaceTemplates.C +++ b/src/sampling/sampledSurface/isoSurface/isoSurfaceTemplates.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -120,7 +120,7 @@ Foam::isoSurface::adaptPatchFields { fvPatchField<Type>& pfld = const_cast<fvPatchField<Type>&> ( - fld.boundaryField()[patchI] + sliceFld.boundaryField()[patchI] ); const scalarField& w = mesh.weights().boundaryField()[patchI]; @@ -189,6 +189,8 @@ Type Foam::isoSurface::generatePoint } +// Note: cannot use simpler isoSurfaceCell::generateTriPoints since +// the need here to sometimes pass in remote 'snappedPoints' template<class Type> void Foam::isoSurface::generateTriPoints ( @@ -240,8 +242,8 @@ void Foam::isoSurface::generateTriPoints case 0x0F: break; - case 0x0E: case 0x01: + case 0x0E: points.append ( generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1) @@ -254,10 +256,16 @@ void Foam::isoSurface::generateTriPoints ( generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3) ); + if (triIndex == 0x0E) + { + // Flip normals + label sz = points.size(); + Swap(points[sz-2], points[sz-1]); + } break; - case 0x0D: case 0x02: + case 0x0D: points.append ( generatePoint(s1,p1,hasSnap1,snapP1,s0,p0,hasSnap0,snapP0) @@ -270,97 +278,133 @@ void Foam::isoSurface::generateTriPoints ( generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2) ); + if (triIndex == 0x0D) + { + // Flip normals + label sz = points.size(); + Swap(points[sz-2], points[sz-1]); + } break; - case 0x0C: case 0x03: - { - Type tp1 = - generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2); - Type tp2 = - generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3); + case 0x0C: + { + Type p0p2 = + generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2); + Type p1p3 = + generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3); - points.append - ( - generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3) - ); - points.append(tp1); - points.append(tp2); - points.append(tp2); - points.append - ( - generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2) - ); - points.append(tp1); - } + points.append + ( + generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3) + ); + points.append(p1p3); + points.append(p0p2); + + points.append(p1p3); + points.append + ( + generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2) + ); + points.append(p0p2); + } + if (triIndex == 0x0C) + { + // Flip normals + label sz = points.size(); + Swap(points[sz-5], points[sz-4]); + Swap(points[sz-2], points[sz-1]); + } break; - case 0x0B: case 0x04: - { - points.append - ( - generatePoint(s2,p2,hasSnap2,snapP2,s0,p0,hasSnap0,snapP0) - ); - points.append - ( - generatePoint(s2,p2,hasSnap2,snapP2,s1,p1,hasSnap1,snapP1) - ); - points.append - ( - generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3) - ); - } + case 0x0B: + { + points.append + ( + generatePoint(s2,p2,hasSnap2,snapP2,s0,p0,hasSnap0,snapP0) + ); + points.append + ( + generatePoint(s2,p2,hasSnap2,snapP2,s1,p1,hasSnap1,snapP1) + ); + points.append + ( + generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3) + ); + } + if (triIndex == 0x0B) + { + // Flip normals + label sz = points.size(); + Swap(points[sz-2], points[sz-1]); + } break; - case 0x0A: case 0x05: - { - Type tp0 = - generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1); - Type tp1 = - generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3); + case 0x0A: + { + Type p0p1 = + generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1); + Type p2p3 = + generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3); + + points.append(p0p1); + points.append(p2p3); + points.append + ( + generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3) + ); - points.append(tp0); - points.append(tp1); - points.append - ( - generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3) - ); - points.append(tp0); - points.append - ( - generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2) - ); - points.append(tp1); - } + points.append(p0p1); + points.append + ( + generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2) + ); + points.append(p2p3); + } + if (triIndex == 0x0A) + { + // Flip normals + label sz = points.size(); + Swap(points[sz-5], points[sz-4]); + Swap(points[sz-2], points[sz-1]); + } break; - case 0x09: case 0x06: - { - Type tp0 = - generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1); - Type tp1 = - generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3); + case 0x09: + { + Type p0p1 = + generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1); + Type p2p3 = + generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3); - points.append(tp0); - points.append - ( - generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3) - ); - points.append(tp1); - points.append(tp0); - points.append - ( - generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2) - ); - points.append(tp1); - } + points.append(p0p1); + points.append + ( + generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3) + ); + points.append(p2p3); + + points.append(p0p1); + points.append(p2p3); + points.append + ( + generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2) + ); + } + if (triIndex == 0x09) + { + // Flip normals + label sz = points.size(); + Swap(points[sz-5], points[sz-4]); + Swap(points[sz-2], points[sz-1]); + } break; - case 0x07: case 0x08: + case 0x07: points.append ( generatePoint(s3,p3,hasSnap3,snapP3,s0,p0,hasSnap0,snapP0) @@ -373,6 +417,12 @@ void Foam::isoSurface::generateTriPoints ( generatePoint(s3,p3,hasSnap3,snapP3,s1,p1,hasSnap1,snapP1) ); + if (triIndex == 0x07) + { + // Flip normals + label sz = points.size(); + Swap(points[sz-2], points[sz-1]); + } break; } } @@ -689,6 +739,69 @@ void Foam::isoSurface::generateTriPoints //} +template<class Type> +Foam::tmp<Foam::Field<Type> > +Foam::isoSurface::interpolate +( + const label nPoints, + const labelList& triPointMergeMap, + const labelList& interpolatedPoints, + const List<FixedList<label, 3> >& interpolatedOldPoints, + const List<FixedList<scalar, 3> >& interpolationWeights, + const DynamicList<Type>& unmergedValues +) +{ + // One value per point + tmp<Field<Type> > tvalues(new Field<Type>(nPoints, pTraits<Type>::zero)); + Field<Type>& values = tvalues(); + + + // Pass1: unweighted average of merged point values + { + labelList nValues(values.size(), 0); + + forAll(unmergedValues, i) + { + label mergedPointI = triPointMergeMap[i]; + + if (mergedPointI >= 0) + { + values[mergedPointI] += unmergedValues[i]; + nValues[mergedPointI]++; + } + } + + forAll(values, i) + { + if (nValues[i] > 0) + { + values[i] /= scalar(nValues[i]); + } + } + } + + + // Pass2: weighted average for remaining values (from clipped triangles) + + forAll(interpolatedPoints, i) + { + label pointI = interpolatedPoints[i]; + const FixedList<label, 3>& oldPoints = interpolatedOldPoints[i]; + const FixedList<scalar, 3>& w = interpolationWeights[i]; + + // Note: zeroing should not be necessary if interpolation only done + // for newly introduced points (i.e. not in triPointMergeMap) + values[pointI] = pTraits<Type>::zero; + forAll(oldPoints, j) + { + values[pointI] = w[j]*unmergedValues[oldPoints[j]]; + } + } + + return tvalues; +} + + template<class Type> Foam::tmp<Foam::Field<Type> > Foam::isoSurface::interpolate @@ -707,7 +820,7 @@ Foam::isoSurface::interpolate > > c2(adaptPatchFields(cCoords)); - DynamicList<Type> triPoints(nCutCells_); + DynamicList<Type> triPoints(3*nCutCells_); DynamicList<label> triMeshCells(nCutCells_); // Dummy snap data @@ -731,52 +844,15 @@ Foam::isoSurface::interpolate triMeshCells ); - - // One value per point - tmp<Field<Type> > tvalues + return interpolate ( - new Field<Type>(points().size(), pTraits<Type>::zero) + points().size(), + triPointMergeMap_, + interpolatedPoints_, + interpolatedOldPoints_, + interpolationWeights_, + triPoints ); - Field<Type>& values = tvalues(); - labelList nValues(values.size(), 0); - - forAll(triPoints, i) - { - label mergedPointI = triPointMergeMap_[i]; - - if (mergedPointI >= 0) - { - values[mergedPointI] += triPoints[i]; - nValues[mergedPointI]++; - } - } - - if (debug) - { - Pout<< "nValues:" << values.size() << endl; - label nMult = 0; - forAll(nValues, i) - { - if (nValues[i] == 0) - { - FatalErrorIn("isoSurface::interpolate(..)") - << "point:" << i << " nValues:" << nValues[i] - << abort(FatalError); - } - else if (nValues[i] > 1) - { - nMult++; - } - } - Pout<< "Of which mult:" << nMult << endl; - } - - forAll(values, i) - { - values[i] /= scalar(nValues[i]); - } - - return tvalues; } diff --git a/src/sampling/sampledSurface/isoSurface/sampledIsoSurface.C b/src/sampling/sampledSurface/isoSurface/sampledIsoSurface.C index bb171c2c0e98a814e752dad4fe5865f2118b8f47..0399eeae06e824ce8b4dd8fd7ca0db77c6668fdd 100644 --- a/src/sampling/sampledSurface/isoSurface/sampledIsoSurface.C +++ b/src/sampling/sampledSurface/isoSurface/sampledIsoSurface.C @@ -122,18 +122,52 @@ void Foam::sampledIsoSurface::getIsoFields() const // Get pointField // ~~~~~~~~~~~~~~ + // In case of multiple iso values we don't want to calculate multiple e.g. + // "volPointInterpolate(p)" so register it and re-use it. This is the + // same as the 'cache' functionality from volPointInterpolate but + // unfortunately that one does not guarantee that the field pointer + // remain: e.g. some other + // functionObject might delete the cached version. + // (volPointInterpolation::interpolate with cache=false deletes any + // registered one or if mesh.changing()) + if (!subMeshPtr_.valid()) { - word pointFldName = "volPointInterpolate(" + isoField_ + ')'; + const word pointFldName = + "volPointInterpolate_" + + type() + + "(" + + isoField_ + + ')'; if (fvm.foundObject<pointScalarField>(pointFldName)) { if (debug) { - Info<< "sampledIsoSurface::getIsoFields() : lookup pointField " - << pointFldName << endl; + Info<< "sampledIsoSurface::getIsoFields() :" + << " lookup pointField " << pointFldName << endl; } - pointFieldPtr_ = &fvm.lookupObject<pointScalarField>(pointFldName); + const pointScalarField& pfld = fvm.lookupObject<pointScalarField> + ( + pointFldName + ); + + if (!pfld.upToDate(*volFieldPtr_)) + { + if (debug) + { + Info<< "sampledIsoSurface::getIsoFields() :" + << " updating pointField " << pointFldName << endl; + } + // Update the interpolated value + volPointInterpolation::New(fvm).interpolate + ( + *volFieldPtr_, + const_cast<pointScalarField&>(pfld) + ); + } + + pointFieldPtr_ = &pfld; } else { @@ -141,33 +175,23 @@ void Foam::sampledIsoSurface::getIsoFields() const if (debug) { - Info<< "sampledIsoSurface::getIsoFields() : " - << "checking pointField " << pointFldName - << " for same time " << fvm.time().timeName() - << endl; + Info<< "sampledIsoSurface::getIsoFields() :" + << " creating and storing pointField " + << pointFldName << " for time " + << fvm.time().timeName() << endl; } - if + tmp<pointScalarField> tpfld ( - storedPointFieldPtr_.empty() - || (fvm.time().timeName() != storedPointFieldPtr_().instance()) - ) - { - if (debug) - { - Info<< "sampledIsoSurface::getIsoFields() :" - << " interpolating volField " << volFieldPtr_->name() - << " to get pointField " << pointFldName << endl; - } - - storedPointFieldPtr_.reset + volPointInterpolation::New(fvm).interpolate ( - volPointInterpolation::New(fvm) - .interpolate(*volFieldPtr_).ptr() - ); - storedPointFieldPtr_->checkOut(); - pointFieldPtr_ = storedPointFieldPtr_.operator->(); - } + *volFieldPtr_, + pointFldName, + false + ) + ); + pointFieldPtr_ = tpfld.ptr(); + const_cast<pointScalarField*>(pointFieldPtr_)->store(); } @@ -233,8 +257,10 @@ void Foam::sampledIsoSurface::getIsoFields() const // Pointfield on submesh - word pointFldName = - "volPointInterpolate(" + const word pointFldName = + "volPointInterpolate_" + + type() + + "(" + volSubFieldPtr_->name() + ')'; @@ -245,11 +271,28 @@ void Foam::sampledIsoSurface::getIsoFields() const Info<< "sampledIsoSurface::getIsoFields() :" << " submesh lookup pointField " << pointFldName << endl; } - storedPointSubFieldPtr_.clear(); - pointSubFieldPtr_ = &subFvm.lookupObject<pointScalarField> + const pointScalarField& pfld = subFvm.lookupObject<pointScalarField> ( pointFldName ); + + if (!pfld.upToDate(*volSubFieldPtr_)) + { + if (debug) + { + Info<< "sampledIsoSurface::getIsoFields() :" + << " updating submesh pointField " + << pointFldName << endl; + } + // Update the interpolated value + volPointInterpolation::New(subFvm).interpolate + ( + *volSubFieldPtr_, + const_cast<pointScalarField&>(pfld) + ); + } + + pointFieldPtr_ = &pfld; } else { @@ -260,15 +303,15 @@ void Foam::sampledIsoSurface::getIsoFields() const << volSubFieldPtr_->name() << " to get submesh pointField " << pointFldName << endl; } - storedPointSubFieldPtr_.reset + tmp<pointScalarField> tpfld ( volPointInterpolation::New ( subFvm - ).interpolate(*volSubFieldPtr_).ptr() + ).interpolate(*volSubFieldPtr_) ); - storedPointSubFieldPtr_->checkOut(); - pointSubFieldPtr_ = storedPointSubFieldPtr_.operator->(); + pointSubFieldPtr_ = tpfld.ptr(); + const_cast<pointScalarField*>(pointSubFieldPtr_)->store(); } @@ -349,28 +392,34 @@ bool Foam::sampledIsoSurface::updateGeometry() const if (subMeshPtr_.valid()) { + const volScalarField& vfld = *volSubFieldPtr_; + surfPtr_.reset ( new isoSurface ( - *volSubFieldPtr_, + vfld, *pointSubFieldPtr_, isoVal_, regularise_, + bounds_, mergeTol_ ) ); } else { + const volScalarField& vfld = *volFieldPtr_; + surfPtr_.reset ( new isoSurface ( - *volFieldPtr_, + vfld, *pointFieldPtr_, isoVal_, regularise_, + bounds_, mergeTol_ ) ); @@ -412,6 +461,7 @@ Foam::sampledIsoSurface::sampledIsoSurface sampledSurface(name, mesh, dict), isoField_(dict.lookup("isoField")), isoVal_(readScalar(dict.lookup("isoValue"))), + bounds_(dict.lookupOrDefault("bounds", boundBox::greatBox)), mergeTol_(dict.lookupOrDefault("mergeTol", 1e-6)), regularise_(dict.lookupOrDefault("regularise", true)), average_(dict.lookupOrDefault("average", false)), @@ -422,7 +472,6 @@ Foam::sampledIsoSurface::sampledIsoSurface prevTimeIndex_(-1), storedVolFieldPtr_(NULL), volFieldPtr_(NULL), - storedPointFieldPtr_(NULL), pointFieldPtr_(NULL) { if (!sampledSurface::interpolate()) diff --git a/src/sampling/sampledSurface/isoSurface/sampledIsoSurface.H b/src/sampling/sampledSurface/isoSurface/sampledIsoSurface.H index 8cfd14c3c15cd3b0d26d2e21510d42acc89c96ec..488ba56452544309557a54de64611341025913d8 100644 --- a/src/sampling/sampledSurface/isoSurface/sampledIsoSurface.H +++ b/src/sampling/sampledSurface/isoSurface/sampledIsoSurface.H @@ -63,6 +63,9 @@ class sampledIsoSurface //- Iso value const scalar isoVal_; + //- Optional bounding box to trim triangles against + const boundBox bounds_; + //- Merge tolerance const scalar mergeTol_; @@ -94,7 +97,6 @@ class sampledIsoSurface mutable const volScalarField* volFieldPtr_; //- Cached pointfield - mutable autoPtr<pointScalarField> storedPointFieldPtr_; mutable const pointScalarField* pointFieldPtr_; // And on subsetted mesh @@ -107,7 +109,6 @@ class sampledIsoSurface mutable const volScalarField* volSubFieldPtr_; //- Cached pointfield - mutable autoPtr<pointScalarField> storedPointSubFieldPtr_; mutable const pointScalarField* pointSubFieldPtr_; diff --git a/src/sampling/sampledSurface/isoSurface/sampledIsoSurfaceCell.C b/src/sampling/sampledSurface/isoSurface/sampledIsoSurfaceCell.C index 239217a352c365316da312e91a14992ea8a2fd0c..4c21257ce7b07de49a65b131d687531b03e2d74d 100644 --- a/src/sampling/sampledSurface/isoSurface/sampledIsoSurfaceCell.C +++ b/src/sampling/sampledSurface/isoSurface/sampledIsoSurfaceCell.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -148,7 +148,8 @@ bool Foam::sampledIsoSurfaceCell::updateGeometry() const cellAvg, pointFld().internalField(), isoVal_, - regularise_ + regularise_, + bounds_ ); const_cast<sampledIsoSurfaceCell&> @@ -166,7 +167,8 @@ bool Foam::sampledIsoSurfaceCell::updateGeometry() const cellFld.internalField(), pointFld().internalField(), isoVal_, - regularise_ + regularise_, + bounds_ ); const_cast<sampledIsoSurfaceCell&> @@ -185,6 +187,7 @@ bool Foam::sampledIsoSurfaceCell::updateGeometry() const << " average : " << average_ << nl << " isoField : " << isoField_ << nl << " isoValue : " << isoVal_ << nl + << " bounds : " << bounds_ << nl << " points : " << points().size() << nl << " tris : " << triSurface::size() << nl << " cut cells : " << meshCells_.size() << endl; @@ -206,6 +209,7 @@ Foam::sampledIsoSurfaceCell::sampledIsoSurfaceCell sampledSurface(name, mesh, dict), isoField_(dict.lookup("isoField")), isoVal_(readScalar(dict.lookup("isoValue"))), + bounds_(dict.lookupOrDefault("bounds", boundBox::greatBox)), regularise_(dict.lookupOrDefault("regularise", true)), average_(dict.lookupOrDefault("average", true)), zoneKey_(keyType::null), diff --git a/src/sampling/sampledSurface/isoSurface/sampledIsoSurfaceCell.H b/src/sampling/sampledSurface/isoSurface/sampledIsoSurfaceCell.H index 7021bf0b97e35b941ab743cb83ea1b985a96fb86..0cfa6a7461a9ec02b6b022e989d24c961222f528 100644 --- a/src/sampling/sampledSurface/isoSurface/sampledIsoSurfaceCell.H +++ b/src/sampling/sampledSurface/isoSurface/sampledIsoSurfaceCell.H @@ -62,6 +62,9 @@ class sampledIsoSurfaceCell //- Iso value const scalar isoVal_; + //- Optional bounding box to trim triangles against + const boundBox bounds_; + //- Whether to coarse const Switch regularise_; diff --git a/src/sampling/sampledSurface/sampledCuttingPlane/sampledCuttingPlane.C b/src/sampling/sampledSurface/sampledCuttingPlane/sampledCuttingPlane.C index 7da10d7a57db7ce97e6e7454106c6f444cbe696f..7030b20d5e62a97e4fe824b8ac2ebcc41b2230a2 100644 --- a/src/sampling/sampledSurface/sampledCuttingPlane/sampledCuttingPlane.C +++ b/src/sampling/sampledSurface/sampledCuttingPlane/sampledCuttingPlane.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -230,6 +230,7 @@ void Foam::sampledCuttingPlane::createGeometry() pointDistance_, 0.0, regularise_, + bounds_, mergeTol_ ) //new isoSurfaceCell @@ -262,6 +263,7 @@ Foam::sampledCuttingPlane::sampledCuttingPlane : sampledSurface(name, mesh, dict), plane_(dict), + bounds_(dict.lookupOrDefault("bounds", boundBox::greatBox)), mergeTol_(dict.lookupOrDefault("mergeTol", 1e-6)), regularise_(dict.lookupOrDefault("regularise", true)), average_(dict.lookupOrDefault("average", false)), diff --git a/src/sampling/sampledSurface/sampledCuttingPlane/sampledCuttingPlane.H b/src/sampling/sampledSurface/sampledCuttingPlane/sampledCuttingPlane.H index a8aa477407fe466a140d6f1b695a6ccb4f0e6a33..308bdcd46a01aeb8bb5fa5aad007141ade2fd886 100644 --- a/src/sampling/sampledSurface/sampledCuttingPlane/sampledCuttingPlane.H +++ b/src/sampling/sampledSurface/sampledCuttingPlane/sampledCuttingPlane.H @@ -60,6 +60,9 @@ class sampledCuttingPlane //- Plane const plane plane_; + //- Optional bounding box to trim triangles against + const boundBox bounds_; + //- Merge tolerance const scalar mergeTol_; diff --git a/src/sampling/sampledSurface/sampledPatch/sampledPatch.C b/src/sampling/sampledSurface/sampledPatch/sampledPatch.C index d07a6391f120f7a2a2154d547de6bb01be7f63a8..faeccd69a3f9669228860950d337026f0a25ba4f 100644 --- a/src/sampling/sampledSurface/sampledPatch/sampledPatch.C +++ b/src/sampling/sampledSurface/sampledPatch/sampledPatch.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -84,11 +84,7 @@ const Foam::labelList& Foam::sampledPatch::patchIDs() const { if (patchIDs_.empty()) { - patchIDs_ = mesh().boundaryMesh().patchSet - ( - patchNames_, - false - ).sortedToc(); + patchIDs_ = mesh().boundaryMesh().patchSet(patchNames_).sortedToc(); } return patchIDs_; } diff --git a/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C b/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C index 47a9f9ebbc4d0e0e67bfb7b63e98c683c6eb56de..4e12874c2545f21c1f31f5a2aa4f8d7a4519dfbd 100644 --- a/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C +++ b/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd + \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation + \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -162,19 +162,7 @@ void Foam::sampledSurfaces::write() const label nFields = classifyFields(); - if (Pstream::master()) - { - if (debug) - { - Pout<< "Creating directory " - << outputPath_/obr_.time().timeName() << nl << endl; - - } - - mkDir(outputPath_/obr_.time().timeName()); - } - - // Write geometry first if required, + // write geometry first if required, // or when no fields would otherwise be written if (nFields == 0 || formatter_->separateGeometry()) { diff --git a/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C b/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C index 094ae45cfcb488323910c412de721701d661b8af..654b3d438f23d3a100eee1d8499b6bfd3cc19e45 100644 --- a/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C +++ b/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C @@ -644,8 +644,25 @@ bool Foam::sampledTriSurfaceMesh::update() return false; } + // Calculate surface and mesh overlap bounding box + treeBoundBox bb + ( + surface_.triSurface::points(), + surface_.triSurface::meshPoints() + ); + bb.min() = max(bb.min(), mesh().bounds().min()); + bb.max() = min(bb.max(), mesh().bounds().max()); + + // Extend a bit + const vector span(bb.span()); + + bb.min() -= 0.5*span; + bb.max() += 0.5*span; + + bb.inflate(1e-6); + // Mesh search engine, no triangulation of faces. - meshSearch meshSearcher(mesh(), polyMesh::FACE_PLANES); + meshSearch meshSearcher(mesh(), bb, polyMesh::FACE_PLANES); return update(meshSearcher); } diff --git a/src/triSurface/triSurface/interfaces/NAS/readNAS.C b/src/triSurface/triSurface/interfaces/NAS/readNAS.C index 3e39579d052d01dd70f5fee1ed388396b5a9a602..129ce49610c142abf6da2c081b9f49a45012578a 100644 --- a/src/triSurface/triSurface/interfaces/NAS/readNAS.C +++ b/src/triSurface/triSurface/interfaces/NAS/readNAS.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -26,7 +26,7 @@ Description - Uses the Ansa "$ANSA_NAME" or the Hypermesh "$HMNAME COMP" extensions to obtain patch names. - - Handles Nastran short and long formats, but not free format. + - Handles Nastran short, long, and comma-separated free formats. - Properly handles the Nastran compact floating point notation: \n \verbatim GRID 28 10.20269-.030265-2.358-8 @@ -69,6 +69,32 @@ static scalar parseNASCoord(const string& s) } +// Read a column of a given width from either a fixed-format NAS file, or a +// comma-separated free-format NAS file +static std::string readNASToken +( + const string& line, + const size_t& width, + size_t& index +) +{ + size_t indexStart, indexEnd; + + indexStart = index; + + indexEnd = line.find(',', indexStart); + index = indexEnd + 1; + + if (indexEnd == std::string::npos) + { + indexEnd = indexStart + width; + index = indexEnd; + } + + return line.substr(indexStart, indexEnd - indexStart); +} + + bool triSurface::readNAS(const fileName& fName) { IFstream is(fName); @@ -104,6 +130,7 @@ bool triSurface::readNAS(const fileName& fName) while (is.good()) { + size_t linei = 0; string line; is.getLine(line); @@ -197,17 +224,16 @@ bool triSurface::readNAS(const fileName& fName) } // Read first word - IStringStream lineStream(line); - word cmd; - lineStream >> cmd; + word cmd(IStringStream(readNASToken(line, 8, linei))()); if (cmd == "CTRIA3") { - label groupId = readLabel(IStringStream(line.substr(16,8))()); - label a = readLabel(IStringStream(line.substr(24,8))()); - label b = readLabel(IStringStream(line.substr(32,8))()); - label c = readLabel(IStringStream(line.substr(40,8))()); - + readNASToken(line, 8, linei); + label groupId = + readLabel(IStringStream(readNASToken(line, 8, linei))()); + label a = readLabel(IStringStream(readNASToken(line, 8, linei))()); + label b = readLabel(IStringStream(readNASToken(line, 8, linei))()); + label c = readLabel(IStringStream(readNASToken(line, 8, linei))()); // Convert group into patch Map<label>::const_iterator iter = groupToPatch.find(groupId); @@ -228,11 +254,13 @@ bool triSurface::readNAS(const fileName& fName) } else if (cmd == "CQUAD4") { - label groupId = readLabel(IStringStream(line.substr(16,8))()); - label a = readLabel(IStringStream(line.substr(24,8))()); - label b = readLabel(IStringStream(line.substr(32,8))()); - label c = readLabel(IStringStream(line.substr(40,8))()); - label d = readLabel(IStringStream(line.substr(48,8))()); + readNASToken(line, 8, linei); + label groupId = + readLabel(IStringStream(readNASToken(line, 8, linei))()); + label a = readLabel(IStringStream(readNASToken(line, 8, linei))()); + label b = readLabel(IStringStream(readNASToken(line, 8, linei))()); + label c = readLabel(IStringStream(readNASToken(line, 8, linei))()); + label d = readLabel(IStringStream(readNASToken(line, 8, linei))()); // Convert group into patch Map<label>::const_iterator iter = groupToPatch.find(groupId); @@ -255,7 +283,8 @@ bool triSurface::readNAS(const fileName& fName) else if (cmd == "PSHELL") { // Read shell type since group gives patchnames - label groupId = readLabel(IStringStream(line.substr(8,8))()); + label groupId = + readLabel(IStringStream(readNASToken(line, 8, linei))()); if (groupId == ansaId && ansaType == "PSHELL") { groupToName.insert(groupId, string::validate<word>(ansaName)); @@ -264,10 +293,12 @@ bool triSurface::readNAS(const fileName& fName) } else if (cmd == "GRID") { - label index = readLabel(IStringStream(line.substr(8,8))()); - scalar x = parseNASCoord(line.substr(24, 8)); - scalar y = parseNASCoord(line.substr(32, 8)); - scalar z = parseNASCoord(line.substr(40, 8)); + label index = + readLabel(IStringStream(readNASToken(line, 8, linei))()); + readNASToken(line, 8, linei); + scalar x = parseNASCoord(readNASToken(line, 8, linei)); + scalar y = parseNASCoord(readNASToken(line, 8, linei)); + scalar z = parseNASCoord(readNASToken(line, 8, linei)); indices.append(index); points.append(point(x, y, z)); @@ -279,11 +310,13 @@ bool triSurface::readNAS(const fileName& fName) // Typical line (spaces compacted) // GRID* 126 0 -5.55999875E+02 -5.68730474E+02 // * 2.14897901E+02 + label index = + readLabel(IStringStream(readNASToken(line, 8, linei))()); + readNASToken(line, 8, linei); + scalar x = parseNASCoord(readNASToken(line, 16, linei)); + scalar y = parseNASCoord(readNASToken(line, 16, linei)); - label index = readLabel(IStringStream(line.substr(8,16))()); - scalar x = parseNASCoord(line.substr(40, 16)); - scalar y = parseNASCoord(line.substr(56, 16)); - + linei = 0; is.getLine(line); if (line[0] != '*') { @@ -295,7 +328,8 @@ bool triSurface::readNAS(const fileName& fName) << " line:" << is.lineNumber() << exit(FatalError); } - scalar z = parseNASCoord(line.substr(8, 16)); + readNASToken(line, 8, linei); + scalar z = parseNASCoord(readNASToken(line, 16, linei)); indices.append(index); points.append(point(x, y, z)); diff --git a/src/triSurface/triSurface/interfaces/OBJ/readOBJ.C b/src/triSurface/triSurface/interfaces/OBJ/readOBJ.C index 004661ab3cf36831c3bed3a63ee79d5797fe8e48..dd57ffb94f6549e4777d8b5824b738d828810478 100644 --- a/src/triSurface/triSurface/interfaces/OBJ/readOBJ.C +++ b/src/triSurface/triSurface/interfaces/OBJ/readOBJ.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -53,105 +53,112 @@ bool Foam::triSurface::readOBJ(const fileName& OBJfileName) label sz = line.size(); - if (sz && line[sz-1] == '\\') + if (sz) { - line.substr(0, sz-1); - line += getLineNoComment(OBJfile); - } - - // Read first word - IStringStream lineStream(line); - word cmd; - lineStream >> cmd; - - if (cmd == "v") - { - scalar x, y, z; - - lineStream >> x >> y >> z; - - points.append(point(x, y, z)); - } - else if (cmd == "g") - { - word group; - - lineStream >> group; - - HashTable<label>::const_iterator findGroup = - groupToPatch.find(group); - - if (findGroup != groupToPatch.end()) + if (line[sz-1] == '\\') { - groupID = findGroup(); + line.substr(0, sz-1); + line += getLineNoComment(OBJfile); } - else - { - groupID = maxGroupID; - groupToPatch.insert(group, groupID); + // Read first word + IStringStream lineStream(line); + word cmd; + lineStream >> cmd; - maxGroupID++; - } - } - else if (cmd == "f") - { - DynamicList<label> verts; + if (cmd == "v") + { + scalar x, y, z; - // Assume 'f' is followed by space. - string::size_type endNum = 1; + lineStream >> x >> y >> z; - while (true) + points.append(point(x, y, z)); + } + else if (cmd == "g") { - string::size_type startNum = - line.find_first_not_of(" \r", endNum); + word group; - if (startNum == string::npos) - { - break; - } + lineStream >> group; - endNum = line.find(' ', startNum); + HashTable<label>::const_iterator findGroup = + groupToPatch.find(group); - string vertexSpec; - if (endNum != string::npos) + if (findGroup != groupToPatch.end()) { - vertexSpec = line.substr(startNum, endNum-startNum); + groupID = findGroup(); } else { - vertexSpec = line.substr(startNum, line.size() - startNum); - } + groupID = maxGroupID; - string::size_type slashPos = vertexSpec.find('/'); + groupToPatch.insert(group, groupID); - label vertI = 0; - if (slashPos != string::npos) - { - IStringStream intStream(vertexSpec.substr(0, slashPos)); - - intStream >> vertI; + maxGroupID++; } - else - { - IStringStream intStream(vertexSpec); + } + else if (cmd == "f") + { + DynamicList<label> verts; - intStream >> vertI; + // Assume 'f' is followed by space. + string::size_type endNum = 1; + + while (true) + { + string::size_type startNum = + line.find_first_not_of(" \r", endNum); + + if (startNum == string::npos) + { + break; + } + + endNum = line.find(' ', startNum); + + string vertexSpec; + if (endNum != string::npos) + { + vertexSpec = line.substr(startNum, endNum-startNum); + } + else + { + vertexSpec = line.substr + ( + startNum, + line.size() - startNum + ); + } + + string::size_type slashPos = vertexSpec.find('/'); + + label vertI = 0; + if (slashPos != string::npos) + { + IStringStream intStream(vertexSpec.substr(0, slashPos)); + + intStream >> vertI; + } + else + { + IStringStream intStream(vertexSpec); + + intStream >> vertI; + } + verts.append(vertI - 1); } - verts.append(vertI - 1); - } - verts.shrink(); + verts.shrink(); - // Do simple face triangulation around f[0]. - // Cannot use face::triangulation since no complete points yet. - for (label fp = 1; fp < verts.size() - 1; fp++) - { - label fp1 = verts.fcIndex(fp); + // Do simple face triangulation around f[0]. + // Cannot use face::triangulation since no complete points yet. + for (label fp = 1; fp < verts.size() - 1; fp++) + { + label fp1 = verts.fcIndex(fp); - labelledTri tri(verts[0], verts[fp], verts[fp1], groupID); + labelledTri tri(verts[0], verts[fp], verts[fp1], groupID); - faces.append(tri); + faces.append(tri); + } } } } diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/T b/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/T deleted file mode 100644 index 3bf09662bb0a143ba6281b3e9f135607ea59eefe..0000000000000000000000000000000000000000 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/T +++ /dev/null @@ -1,56 +0,0 @@ -/*--------------------------------*- C++ -*----------------------------------*\ -| ========= | | -| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | -| \\ / O peration | Version: dev | -| \\ / A nd | Web: www.OpenFOAM.org | -| \\/ M anipulation | | -\*---------------------------------------------------------------------------*/ -FoamFile -{ - version 2.0; - format ascii; - class volScalarField; - location "0"; - object T; -} -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -dimensions [0 0 0 1 0 0 0]; - -internalField uniform 293; - -boundaryField -{ - frontAndBack - { - type zeroGradient; - } - - topAndBottom - { - type zeroGradient; - } - - hot - { - type externalCoupledTemperature; - commsDir "${FOAM_CASE}/comms"; - fileName "data"; - initByExternal yes; - log true; - value uniform 307.75; // 34.6 degC - } - - cold - { - type externalCoupledTemperature; - commsDir "${FOAM_CASE}/comms"; - fileName "data"; - initByExternal yes; - log true; - value uniform 288.15; // 15 degC - } -} - - -// ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/alphat b/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/alphat deleted file mode 100644 index 9e486ba21571232468addb9c24008bcaebb3be18..0000000000000000000000000000000000000000 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/alphat +++ /dev/null @@ -1,51 +0,0 @@ -/*--------------------------------*- C++ -*----------------------------------*\ -| ========= | | -| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | -| \\ / O peration | Version: dev | -| \\ / A nd | Web: www.OpenFOAM.org | -| \\/ M anipulation | | -\*---------------------------------------------------------------------------*/ -FoamFile -{ - version 2.0; - format ascii; - class volScalarField; - location "0"; - object alphat; -} -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -dimensions [1 -1 -1 0 0 0 0]; - -internalField uniform 0; - -boundaryField -{ - frontAndBack - { - type compressible::alphatWallFunction; - Prt 0.85; - value uniform 0; - } - topAndBottom - { - type compressible::alphatWallFunction; - Prt 0.85; - value uniform 0; - } - hot - { - type compressible::alphatWallFunction; - Prt 0.85; - value uniform 0; - } - cold - { - type compressible::alphatWallFunction; - Prt 0.85; - value uniform 0; - } -} - - -// ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/epsilon b/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/epsilon deleted file mode 100644 index f1ac119104a47031603714d652d9ccd9ec7feb4b..0000000000000000000000000000000000000000 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/epsilon +++ /dev/null @@ -1,47 +0,0 @@ -/*--------------------------------*- C++ -*----------------------------------*\ -| ========= | | -| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | -| \\ / O peration | Version: dev | -| \\ / A nd | Web: www.OpenFOAM.org | -| \\/ M anipulation | | -\*---------------------------------------------------------------------------*/ -FoamFile -{ - version 2.0; - format ascii; - class volScalarField; - location "0"; - object epsilon; -} -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -dimensions [0 2 -3 0 0 0 0]; - -internalField uniform 4e-06; - -boundaryField -{ - frontAndBack - { - type epsilonWallFunction; - value uniform 4e-06; - } - topAndBottom - { - type epsilonWallFunction; - value uniform 4e-06; - } - hot - { - type epsilonWallFunction; - value uniform 4e-06; - } - cold - { - type epsilonWallFunction; - value uniform 4e-06; - } -} - - -// ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/omega b/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/omega deleted file mode 100644 index 481f4e64d7c72aa3ac16b1b9632ba05ff72aae89..0000000000000000000000000000000000000000 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/omega +++ /dev/null @@ -1,47 +0,0 @@ -/*--------------------------------*- C++ -*----------------------------------*\ -| ========= | | -| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | -| \\ / O peration | Version: dev | -| \\ / A nd | Web: www.OpenFOAM.org | -| \\/ M anipulation | | -\*---------------------------------------------------------------------------*/ -FoamFile -{ - version 2.0; - format ascii; - class volScalarField; - location "0"; - object omega; -} -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -dimensions [0 0 -1 0 0 0 0]; - -internalField uniform 0.12; - -boundaryField -{ - frontAndBack - { - type omegaWallFunction; - value uniform 0.12; - } - topAndBottom - { - type omegaWallFunction; - value uniform 0.12; - } - hot - { - type omegaWallFunction; - value uniform 0.12; - } - cold - { - type omegaWallFunction; - value uniform 0.12; - } -} - - -// ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/Allclean b/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/Allclean deleted file mode 100755 index 871192082a8ae8f3c7c91f2d81728f29d5ac3c10..0000000000000000000000000000000000000000 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/Allclean +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -cd ${0%/*} || exit 1 # Run from this directory - -# Source tutorial run functions -. $WM_PROJECT_DIR/bin/tools/CleanFunctions - -cleanCase - -rm -rf comms - -killall externalSolver > /dev/null 2>&1 - - -# ----------------------------------------------------------------- end-of-file diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/Allrun b/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/Allrun deleted file mode 100755 index ba2d9335431a8d22f2a5ed77da9e0160052107f7..0000000000000000000000000000000000000000 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/Allrun +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -cd ${0%/*} || exit 1 # Run from this directory - -# Source tutorial run functions -. $WM_PROJECT_DIR/bin/tools/RunFunctions - -./Allrun.pre - -runApplication $(getApplication) & - -./externalSolver - - -# ----------------------------------------------------------------- end-of-file diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/Allrun-parallel b/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/Allrun-parallel deleted file mode 100755 index 8c451a124e8a65ec7b1e334b290719869bac9313..0000000000000000000000000000000000000000 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/Allrun-parallel +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -cd ${0%/*} || exit 1 # Run from this directory - -# Source tutorial run functions -. $WM_PROJECT_DIR/bin/tools/RunFunctions - -./Allrun.pre - -runApplication decomposePar - -runParallel $(getApplication) 4 & - -./externalSolver - - -# ----------------------------------------------------------------- end-of-file diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/Allrun.pre b/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/Allrun.pre deleted file mode 100755 index 0fca0f1d7929120427ba55273c3be8c711bc91d1..0000000000000000000000000000000000000000 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/Allrun.pre +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -cd ${0%/*} || exit 1 # Run from this directory - -# Source tutorial run functions -. $WM_PROJECT_DIR/bin/tools/RunFunctions - -runApplication blockMesh -runApplication createExternalCoupledPatchGeometry T - - -# ----------------------------------------------------------------- end-of-file diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/README b/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/README deleted file mode 100644 index 10d7392eb4814034795d02d08115ce261ce9875a..0000000000000000000000000000000000000000 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/README +++ /dev/null @@ -1,5 +0,0 @@ -Example of an explicit coupling between OpenFOAM and an external application -using the externalCoupled boundary conditions. - -The case is based on the buoyantCavity tutorial case, whereby on each iteration -the 'hot' and 'cold' patch temperatures are incremented by 1K. diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/T b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/T new file mode 100644 index 0000000000000000000000000000000000000000..a2e5fd849a6b1abd36df18241cf49c3c9a64c887 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/T @@ -0,0 +1,30 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 300; + +boundaryField +{ + ".*" + { + type calculated; + value uniform 300; + } +} + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/U b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/U similarity index 66% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/U rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/U index 2d917d036faaa2d227ec7ef69f7338d00b670f22..5c6a42bb1dfd4ab33a7e076968ad74745d385dea 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/U +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/U @@ -10,41 +10,21 @@ FoamFile version 2.0; format ascii; class volVectorField; - location "0"; object U; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // dimensions [0 1 -1 0 0 0 0]; -internalField uniform (0 0 0); +internalField uniform (0.01 0 0); boundaryField { - frontAndBack + ".*" { - type fixedValue; - value uniform (0 0 0); - } - - topAndBottom - { - type fixedValue; - value uniform (0 0 0); - } - - hot - { - type fixedValue; - value uniform (0 0 0); - } - - cold - { - type fixedValue; - value uniform (0 0 0); + type calculated; + value uniform (0.01 0 0); } } - // ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/epsilon b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/epsilon new file mode 100644 index 0000000000000000000000000000000000000000..e20d66145159d55a94d78f8d89ee8f1b1b3543e4 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/epsilon @@ -0,0 +1,31 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object epsilon; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -3 0 0 0 0]; + +internalField uniform 0.01; + +boundaryField +{ + ".*" + { + type calculated; + value uniform 0.01; + } +} + + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/k b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/k new file mode 100644 index 0000000000000000000000000000000000000000..351dfc5606e8f86e5bad5cde8f6dd139c2b366b7 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/k @@ -0,0 +1,31 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object k; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +internalField uniform 0.1; + +boundaryField +{ + ".*" + { + type calculated; + value uniform 0.1; + } +} + + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/p b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/p similarity index 71% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/p rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/p index 9b1e74247bf9946eae6d063aa536d141bee454ad..3e972159635b2a34e38825adaf8a2d6e7c5d77c3 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/p +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/p @@ -10,7 +10,6 @@ FoamFile version 2.0; format ascii; class volScalarField; - location "0"; object p; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -21,30 +20,11 @@ internalField uniform 1e5; boundaryField { - frontAndBack + ".*" { type calculated; - value $internalField; - } - - topAndBottom - { - type calculated; - value $internalField; - } - - hot - { - type calculated; - value $internalField; - } - - cold - { - type calculated; - value $internalField; + value uniform 1e5; } } - // ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/p_rgh b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/p_rgh similarity index 70% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/p_rgh rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/p_rgh index 15979d020e33ed2769512df863c4ccb772b6eeca..8673f6e9bc3a086eabb702e918ae5a5d0f5311fc 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/p_rgh +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/0/p_rgh @@ -10,7 +10,6 @@ FoamFile version 2.0; format ascii; class volScalarField; - location "0"; object p_rgh; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -21,30 +20,11 @@ internalField uniform 1e5; boundaryField { - frontAndBack + ".*" { - type fixedFluxPressure; - value uniform 1e5; - } - - topAndBottom - { - type fixedFluxPressure; - value uniform 1e5; - } - - hot - { - type fixedFluxPressure; - value uniform 1e5; - } - - cold - { - type fixedFluxPressure; + type calculated; value uniform 1e5; } } - // ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/Allclean b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/Allclean new file mode 100755 index 0000000000000000000000000000000000000000..82e538bb437c74bcb9fb9647866fc714de04586c --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/Allclean @@ -0,0 +1,23 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +# Source tutorial clean functions +. $WM_PROJECT_DIR/bin/tools/CleanFunctions + +cleanCase +rm -rf comms +rm -rf VTK +rm -rf constant/cellToRegion constant/polyMesh/sets +rm -rf 0/bottomWater +rm -rf 0/topAir +rm -rf 0/heater +rm -rf 0/leftSolid +rm -rf 0/rightSolid +rm -f 0/cellToRegion +rm -rf constant/bottomWater/polyMesh +rm -rf constant/topAir/polyMesh +rm -rf constant/heater/polyMesh +rm -rf constant/leftSolid/polyMesh +rm -rf constant/rightSolid/polyMesh + +# ----------------------------------------------------------------- end-of-file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/Allrun b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/Allrun new file mode 100755 index 0000000000000000000000000000000000000000..bfb99ee4d13156c295080e7ab823d786351661c3 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/Allrun @@ -0,0 +1,28 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + + +# Source tutorial run functions +. $WM_PROJECT_DIR/bin/tools/RunFunctions + +./Allrun.pre + +#-- Run on single processor +#runApplication `getApplication` & +# Simulated external solver +#runApplication ./externalSolver + +# Decompose +runApplication decomposePar -allRegions + +# Run OpenFOAM +runParallel `getApplication` 4 & + +# Simulated external solver +runApplication ./externalSolver + +# Reconstruct +runApplication reconstructPar -allRegions + + +# ----------------------------------------------------------------- end-of-file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/Allrun.pre b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/Allrun.pre new file mode 100755 index 0000000000000000000000000000000000000000..d841e3cfe0bede051684a1ef20052e0a18d788a1 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/Allrun.pre @@ -0,0 +1,33 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + + +# Source tutorial run functions +. $WM_PROJECT_DIR/bin/tools/RunFunctions + +runApplication blockMesh +runApplication topoSet +runApplication splitMeshRegions -cellZones -overwrite + +# remove fluid fields from solid regions (important for post-processing) +for i in heater leftSolid rightSolid +do + rm -f 0*/$i/{nut,alphat,epsilon,k,U,p_rgh} +done + + +for i in bottomWater topAir heater leftSolid rightSolid +do + changeDictionary -region $i > log.changeDictionary.$i 2>&1 +done + +# Create coupling geometry +runApplication createExternalCoupledPatchGeometry \ + -regions '(topAir heater)' coupleGroup + +echo +echo "creating files for paraview post-processing" +echo +paraFoam -touchAll + +# ----------------------------------------------------------------- end-of-file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/README.txt b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..b0ca34a87367b7e25321f9cba9cadf2ce5cd54f7 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/README.txt @@ -0,0 +1,3 @@ +Modification of the heatTransfer chtMultiRegionFoam tutorial that demonstrates +the externalCoupled functionObject in combination with the ./externalSolver +script to simulate coupling to an external code. diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/constant/g b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/bottomWater/g similarity index 96% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/constant/g rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/bottomWater/g index 0cc222ca3457ed24bf9753d0926fbee84359e624..6f32e338356b14a2d7ff55d2d3f7e948dd1e8479 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/constant/g +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/bottomWater/g @@ -10,7 +10,6 @@ FoamFile version 2.0; format ascii; class uniformDimensionedVectorField; - location "constant"; object g; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -18,5 +17,4 @@ FoamFile dimensions [0 1 -2 0 0 0 0]; value (0 -9.81 0); - // ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/bottomWater/radiationProperties b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/bottomWater/radiationProperties new file mode 100644 index 0000000000000000000000000000000000000000..42defceaf42b8ef9bbd7b9f1b61ecf353e66635c --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/bottomWater/radiationProperties @@ -0,0 +1,22 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object radiationProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +radiation off; + +radiationModel none; + + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/k b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/bottomWater/thermophysicalProperties similarity index 59% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/k rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/bottomWater/thermophysicalProperties index ccdab2054e56a89c2890e16cd16428d7ae6fbebb..828c78d2084416702bd61ec950547004da8d3a45 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/k +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/bottomWater/thermophysicalProperties @@ -9,39 +9,43 @@ FoamFile { version 2.0; format ascii; - class volScalarField; - location "0"; - object k; + class dictionary; + object thermophysicalProperties; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -dimensions [0 2 -2 0 0 0 0]; - -internalField uniform 3.75e-04; +thermoType +{ + type heRhoThermo; + mixture pureMixture; + transport const; + thermo hConst; + equationOfState rhoConst; + specie specie; + energy sensibleEnthalpy; +} -boundaryField +mixture { - frontAndBack + specie { - type kqRWallFunction; - value uniform 3.75e-04; + nMoles 1; + molWeight 18; } - topAndBottom + equationOfState { - type kqRWallFunction; - value uniform 3.75e-04; + rho 1000; } - hot + thermodynamics { - type kqRWallFunction; - value uniform 3.75e-04; + Cp 4181; + Hf 0; } - cold + transport { - type kqRWallFunction; - value uniform 3.75e-04; + mu 959e-6; + Pr 6.62; } } - // ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/bottomWater/turbulenceProperties b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/bottomWater/turbulenceProperties new file mode 100644 index 0000000000000000000000000000000000000000..e63bbc50815e89dfc7ef93352a3228a18620220d --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/bottomWater/turbulenceProperties @@ -0,0 +1,19 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +simulationType laminar; + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/heater/radiationProperties b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/heater/radiationProperties new file mode 100644 index 0000000000000000000000000000000000000000..ef3aba9e4ba8e3a8834c6e4f4e57e2a47ee3ed9d --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/heater/radiationProperties @@ -0,0 +1,23 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ + +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object radiationProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +radiation off; + +radiationModel none; + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/nut b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/heater/thermophysicalProperties similarity index 62% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/nut rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/heater/thermophysicalProperties index bc7b9104086a9c7ae35d1d1f7104faa1d56c2d0a..edb01db8b83370ec9908df5569abd2420aff451e 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/0/nut +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/heater/thermophysicalProperties @@ -9,39 +9,45 @@ FoamFile { version 2.0; format ascii; - class volScalarField; - location "0"; - object nut; + class dictionary; + object thermophysicalProperties; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -dimensions [0 2 -1 0 0 0 0]; - -internalField uniform 0; +thermoType +{ + type heSolidThermo; + mixture pureMixture; + transport constIso; + thermo hConst; + equationOfState rhoConst; + specie specie; + energy sensibleEnthalpy; +} -boundaryField +mixture { - frontAndBack + specie { - type nutUWallFunction; - value uniform 0; + nMoles 1; + molWeight 50; } - topAndBottom + + transport { - type nutUWallFunction; - value uniform 0; + kappa 80; } - hot + + thermodynamics { - type nutUWallFunction; - value uniform 0; + Hf 0; + Cp 450; } - cold + + equationOfState { - type nutUWallFunction; - value uniform 0; + rho 8000; } } - // ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/leftSolid/radiationProperties b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/leftSolid/radiationProperties new file mode 120000 index 0000000000000000000000000000000000000000..08087c37b4d0f37d8df26e11ea195b102f43e32d --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/leftSolid/radiationProperties @@ -0,0 +1 @@ +../heater/radiationProperties \ No newline at end of file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/leftSolid/thermophysicalProperties b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/leftSolid/thermophysicalProperties new file mode 120000 index 0000000000000000000000000000000000000000..dc4d3a18ee4b034d4fdd38eef0466567d0d331bb --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/leftSolid/thermophysicalProperties @@ -0,0 +1 @@ +../heater/thermophysicalProperties \ No newline at end of file diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/blockMeshDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/polyMesh/blockMeshDict similarity index 63% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/blockMeshDict rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/polyMesh/blockMeshDict index 5f2f1e8fd2b5032b4ee3d38fcb0a2d432d1e3077..2a69ccd09ce696a8bb4cfd07ae6973f062207a89 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/blockMeshDict +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/polyMesh/blockMeshDict @@ -14,66 +14,77 @@ FoamFile } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -convertToMeters 0.001; +convertToMeters 1; vertices ( - ( 0 0 -260) - (76 0 -260) - (76 2180 -260) - ( 0 2180 -260) - ( 0 0 260) - (76 0 260) - (76 2180 260) - ( 0 2180 260) + (-0.1 -0.04 -0.05) + ( 0.1 -0.04 -0.05) + ( 0.1 0.04 -0.05) + (-0.1 0.04 -0.05) + (-0.1 -0.04 0.05) + ( 0.1 -0.04 0.05) + ( 0.1 0.04 0.05) + (-0.1 0.04 0.05) ); -edges +blocks ( + hex (0 1 2 3 4 5 6 7) (30 10 10) simpleGrading (1 1 1) ); -blocks +edges ( - hex (0 1 2 3 4 5 6 7) (35 150 15) simpleGrading (1 1 1) ); boundary ( - frontAndBack + maxY { type wall; faces ( - (0 1 5 4) - (2 3 7 6) + (3 7 6 2) ); } - - topAndBottom + minX + { + type patch; + faces + ( + (0 4 7 3) + ); + } + maxX + { + type patch; + faces + ( + (2 6 5 1) + ); + } + minY { type wall; faces ( - (4 5 6 7) - (3 2 1 0) + (1 5 4 0) ); } - - hot + minZ { type wall; faces ( - (6 5 1 2) + (0 3 2 1) ); } - - cold + maxZ { type wall; faces ( - (4 7 3 0) + (4 5 6 7) ); } ); @@ -81,3 +92,5 @@ boundary mergePatchPairs ( ); + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/constant/polyMesh/boundary b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/polyMesh/boundary similarity index 65% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/constant/polyMesh/boundary rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/polyMesh/boundary index 0e07c61c65872cf66a11baf8acc7834ae1654727..b692f177a0815940d999a0be9244af1912ff6c23 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/constant/polyMesh/boundary +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/polyMesh/boundary @@ -1,7 +1,7 @@ /*--------------------------------*- C++ -*----------------------------------*\ | ========= | | | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | -| \\ / O peration | Version: dev | +| \\ / O peration | Version: dev-OpenCFD.feature-externalCoupled | | \\ / A nd | Web: www.OpenFOAM.org | | \\/ M anipulation | | \*---------------------------------------------------------------------------*/ @@ -15,35 +15,47 @@ FoamFile } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -4 +6 ( - frontAndBack + maxY { type wall; inGroups 1(wall); - nFaces 1050; - startFace 228225; + nFaces 300; + startFace 8300; } - topAndBottom + minX + { + type patch; + nFaces 100; + startFace 8600; + } + maxX + { + type patch; + nFaces 100; + startFace 8700; + } + minY { type wall; inGroups 1(wall); - nFaces 10500; - startFace 229275; + nFaces 300; + startFace 8800; } - hot + minZ { type wall; inGroups 1(wall); - nFaces 2250; - startFace 239775; + nFaces 300; + startFace 9100; } - cold + maxZ { type wall; inGroups 1(wall); - nFaces 2250; - startFace 242025; + nFaces 300; + startFace 9400; } ) diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/regionProperties b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/regionProperties new file mode 100644 index 0000000000000000000000000000000000000000..0666069c2c9fcdc92b408fcc62dd424156d08d8d --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/regionProperties @@ -0,0 +1,24 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object regionProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +regions +( + fluid (bottomWater topAir) + solid (heater leftSolid rightSolid) +); + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/rightSolid/radiationProperties b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/rightSolid/radiationProperties new file mode 120000 index 0000000000000000000000000000000000000000..08087c37b4d0f37d8df26e11ea195b102f43e32d --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/rightSolid/radiationProperties @@ -0,0 +1 @@ +../heater/radiationProperties \ No newline at end of file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/rightSolid/thermophysicalProperties b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/rightSolid/thermophysicalProperties new file mode 120000 index 0000000000000000000000000000000000000000..dc4d3a18ee4b034d4fdd38eef0466567d0d331bb --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/rightSolid/thermophysicalProperties @@ -0,0 +1 @@ +../heater/thermophysicalProperties \ No newline at end of file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/topAir/g b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/topAir/g new file mode 120000 index 0000000000000000000000000000000000000000..fea37570067f9f5dbf14e5011717bb654a2f9899 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/topAir/g @@ -0,0 +1 @@ +../bottomWater/g \ No newline at end of file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/topAir/radiationProperties b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/topAir/radiationProperties new file mode 120000 index 0000000000000000000000000000000000000000..583b06cb0b1ff1d19e180d6045ab4f2202a6503a --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/topAir/radiationProperties @@ -0,0 +1 @@ +../bottomWater/radiationProperties \ No newline at end of file diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/constant/thermophysicalProperties b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/topAir/thermophysicalProperties similarity index 88% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/constant/thermophysicalProperties rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/topAir/thermophysicalProperties index 95579e34cb51bd580ceb7debb125ff47a8c7a6aa..551767d5749bf486ad4784a6f56e86798e8bc322 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/constant/thermophysicalProperties +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/topAir/thermophysicalProperties @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - location "constant"; + location "constant/bottomWater"; object thermophysicalProperties; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -31,17 +31,17 @@ mixture specie { nMoles 1; - molWeight 28.96; + molWeight 28.9; } thermodynamics { - Cp 1004.4; + Cp 1000; Hf 0; } transport { - mu 1.831e-05; - Pr 0.705; + mu 1.8e-05; + Pr 0.7; } } diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/topAir/turbulenceProperties b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/topAir/turbulenceProperties new file mode 120000 index 0000000000000000000000000000000000000000..ec52cbd5927f5085eeac5ce87f82bd0b9641eeb2 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/constant/topAir/turbulenceProperties @@ -0,0 +1 @@ +../bottomWater/turbulenceProperties \ No newline at end of file diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/externalSolver b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/externalSolver similarity index 53% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/externalSolver rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/externalSolver index 03c25c644abcccc7d05074160e42835086e3d767..cf8caf9c6b75fbdc6ddfc610887baac9f71ee005 100755 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/externalSolver +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/externalSolver @@ -1,20 +1,29 @@ #!/bin/sh # # Dummy external solver to communicate with OpenFOAM via externalCoupled -# boundary conditions +# functionObject # # Functionality is hard-coded for this particular test case # - patch temperatures increased by 1K on each step # -cd ${0%/*} || exit 1 # run from this directory +cd ${0%/*} || exit 1 # Run from this directory + +# Check for unassigned variables +set -u echo "Executing dummy external solver" commsDir="comms" +regionGroupName="heater_topAir" +patchGroupName="coupleGroup" +fieldName="T" + lockFile="${commsDir}/OpenFOAM.lock" -dataFile="${commsDir}/data" +dataFile="${commsDir}/${regionGroupName}/${patchGroupName}/${fieldName}" waitSec=1 timeOut=10 +nSteps=200 # maximum number of time steps. Note: should be more than + # number of iterations on the OpenFOAM side refGrad=0 valueFraction=1 @@ -27,16 +36,21 @@ init() { log "initialisation: creating ${dataFile}.in" - # Hard-coded for 2 patches of size 2250 - n=2250 - refCold=283 - refHot=303 + # Hard-coded for patch of size 8 (heater/minY) + n1=8 + refValue1=500 touch "${dataFile}.in" - for i in $(seq 1 $n); do - echo "$refHot $refGrad $valueFraction" >> "${dataFile}.in" + log "initialisation: adding $n1 data elements with refValue $refValue1" + for i in $(seq 1 $n1); do + echo "$refValue1 $refGrad $valueFraction" >> "${dataFile}.in" done - for i in $(seq 1 $n); do - echo "$refCold $refGrad $valueFraction" >> "${dataFile}.in" + + # Hard-coded for patch of size 40 (topAir/minX) + n2=40 + refValue2=300 + log "initialisation: adding $n2 data elements with refValue $refValue2" + for i in $(seq 1 $n2); do + echo "$refValue2 $refGrad $valueFraction" >> "${dataFile}.in" done # create lock file to pass control to OF @@ -44,6 +58,10 @@ init() } +# create the comms directory +mkdir -p ${commsDir}/${regionGroupName}/${patchGroupName} + + # tutorial case employs the 'initByExternalOption', so we need to provide # the initial values init @@ -51,7 +69,7 @@ init totalWait=0 step=0 -while [ 1 ]; do +while [ $step -lt $nSteps ]; do if [ -f $lockFile ]; then log "found lock file ${lockFile} - waiting" totalWait=$(expr $totalWait + $waitSec) @@ -70,9 +88,10 @@ while [ 1 ]; do log "sleeping for $waitSec secs to simulate external process" sleep $waitSec - log "creating ${dataFile}.in" + log "updating ${dataFile}.in from ${dataFile}.out" - awk '{if( $1 != "#" ){print $2+1 " 0 1"}}' ${dataFile}.out > ${dataFile}.in + awk '{if( $1 != "#" ){print $1+1 " 0 1"}}' \ + ${dataFile}.out | tee ${dataFile}.in log "creating lock file ${lockFile}" touch ${lockFile} diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/README b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/README new file mode 100644 index 0000000000000000000000000000000000000000..5a81b9a5708b0346c6cdd4bd2f6835feb3700bc1 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/README @@ -0,0 +1,3 @@ +fvSolution is used for outer correctors specification. +fvSchemes is only so that pre-processing activities can proceed + diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/bottomWater/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/bottomWater/changeDictionaryDict new file mode 100644 index 0000000000000000000000000000000000000000..63a08c87a1d5a617fcd24e720b5e8af983834c51 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/bottomWater/changeDictionaryDict @@ -0,0 +1,173 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object changeDictionaryDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dictionaryReplacement +{ + U + { + internalField uniform (0.001 0 0); + + boundaryField + { + minX + { + type fixedValue; + value uniform (0.001 0 0); + } + + maxX + { + type inletOutlet; + inletValue uniform (0 0 0); + } + + ".*" + { + type fixedValue; + value uniform (0 0 0); + } + } + } + + T + { + internalField uniform 300; + + boundaryField + { + minX + { + type fixedValue; + value uniform 300; + } + + maxX + { + type inletOutlet; + inletValue uniform 300; + } + + ".*" + { + type zeroGradient; + value uniform 300; + } + + "bottomWater_to_.*" + { + type compressible::turbulentTemperatureCoupledBaffleMixed; + Tnbr T; + kappa fluidThermo; + kappaName none; + value uniform 300; + } + } + } + + epsilon + { + internalField uniform 0.01; + + boundaryField + { + minX + { + type fixedValue; + value uniform 0.01; + } + + maxX + { + type inletOutlet; + inletValue uniform 0.01; + } + + ".*" + { + type epsilonWallFunction; + value uniform 0.01; + } + } + } + + k + { + internalField uniform 0.1; + + boundaryField + { + minX + { + type inletOutlet; + inletValue uniform 0.1; + } + + maxX + { + type zeroGradient; + value uniform 0.1; + } + + ".*" + { + type kqRWallFunction; + value uniform 0.1; + } + } + } + + p_rgh + { + internalField uniform 0; + + boundaryField + { + minX + { + type zeroGradient; + value uniform 0; + } + + maxX + { + type fixedValue; + value uniform 0; + } + + ".*" + { + type fixedFluxPressure; + value uniform 0; + } + } + } + + p + { + internalField uniform 0; + + boundaryField + { + ".*" + { + type calculated; + value uniform 0; + } + } + } +} + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/bottomWater/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/bottomWater/decomposeParDict new file mode 100644 index 0000000000000000000000000000000000000000..9bdbb31cd254a0189def7c9f126c3dcfaab64f1b --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/bottomWater/decomposeParDict @@ -0,0 +1,72 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + note "mesh decomposition control dictionary"; + location "system"; + object decomposeParDict; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 4; + +//- Keep owner and neighbour on same processor for faces in zones: +// preserveFaceZones (heater solid1 solid3); + +method scotch; +// method hierarchical; +// method simple; +// method manual; + +simpleCoeffs +{ + n (2 2 1); + delta 0.001; +} + +hierarchicalCoeffs +{ + n (2 2 1); + delta 0.001; + order xyz; +} + +scotchCoeffs +{ + //processorWeights + //( + // 1 + // 1 + // 1 + // 1 + //); + //writeGraph true; + //strategy "b"; +} + +manualCoeffs +{ + dataFile "decompositionData"; +} + + +//// Is the case distributed +//distributed yes; +//// Per slave (so nProcs-1 entries) the directory above the case. +//roots +//( +// "/tmp" +// "/tmp" +//); + + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/fvSchemes b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/bottomWater/fvSchemes similarity index 70% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/fvSchemes rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/bottomWater/fvSchemes index 0b96d460748d46097063c4c0ac4c618874221ae5..1278f2856a55cbb86189001de3480d1789ba8c90 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/fvSchemes +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/bottomWater/fvSchemes @@ -16,7 +16,7 @@ FoamFile ddtSchemes { - default steadyState; + default Euler; } gradSchemes @@ -28,18 +28,19 @@ divSchemes { default none; - div(phi,U) bounded Gauss limitedLinear 0.2; - div(phi,K) bounded Gauss limitedLinear 0.2; - div(phi,h) bounded Gauss limitedLinear 0.2; - div(phi,k) bounded Gauss limitedLinear 0.2; - div(phi,epsilon) bounded Gauss limitedLinear 0.2; - div(phi,omega) bounded Gauss limitedLinear 0.2; + div(phi,U) Gauss upwind; + div(phi,K) Gauss linear; + div(phi,h) Gauss upwind; + div(phi,k) Gauss upwind; + div(phi,epsilon) Gauss upwind; + div(phi,R) Gauss upwind; + div(R) Gauss linear; div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; } laplacianSchemes { - default Gauss linear orthogonal; + default Gauss linear corrected; } interpolationSchemes @@ -49,13 +50,13 @@ interpolationSchemes snGradSchemes { - default orthogonal; + default corrected; } -wallDist +fluxRequired { - method meshWave; + default no; + p_rgh; } - // ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/fvSolution b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/bottomWater/fvSolution similarity index 62% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/fvSolution rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/bottomWater/fvSolution index d30cdf20b496e354128a273418811f504df1abed..102345b38d85b6bc5087317848e137e7bb82960a 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/fvSolution +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/bottomWater/fvSolution @@ -10,68 +10,78 @@ FoamFile version 2.0; format ascii; class dictionary; - location "system"; object fvSolution; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // solvers { + rho + { + solver PCG; + preconditioner DIC; + tolerance 1e-7; + relTol 0.1; + } + + rhoFinal + { + $rho; + tolerance 1e-7; + relTol 0; + } + p_rgh { solver GAMG; tolerance 1e-7; relTol 0.01; - smoother DICGaussSeidel; + smoother GaussSeidel; - cacheAgglomeration true; + cacheAgglomeration true; nCellsInCoarsestLevel 10; agglomerator faceAreaPair; mergeLevels 1; } - "(U|h|k|epsilon|omega)" + p_rghFinal { - solver PBiCG; - preconditioner DILU; - tolerance 1e-8; - relTol 0.1; + $p_rgh; + tolerance 1e-7; + relTol 0; } -} - -SIMPLE -{ - momentumPredictor yes; - nNonOrthogonalCorrectors 0; - pRefCell 0; - pRefValue 0; - residualControl + "(U|h|k|epsilon|R)" { - p_rgh 1e-2; - U 1e-3; - h 1e-3; + solver PBiCG; + preconditioner DILU; + tolerance 1e-7; + relTol 0.1; + } - // possibly check turbulence fields - "(k|epsilon|omega)" 1e-3; + "(U|h|k|epsilon|R)Final" + { + $U; + tolerance 1e-7; + relTol 0; } } +PIMPLE +{ + momentumPredictor on; + nCorrectors 2; + nNonOrthogonalCorrectors 0; +} + relaxationFactors { - fields - { - rho 1.0; - p_rgh 0.7; - } equations { - U 0.3; - h 0.3; - "(k|epsilon|omega)" 0.7; + "h.*" 1; + "U.*" 1; } } - // ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/controlDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/controlDict new file mode 100644 index 0000000000000000000000000000000000000000..817b7f284afd6de2a71780ef25d19d62553989aa --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/controlDict @@ -0,0 +1,96 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Library defines new boundary conditions +libs ("libOpenFOAM.so" "libjobControl.so"); + +application chtMultiRegionFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 1; + +deltaT 0.001; + +writeControl adjustableRunTime; +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 8; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +maxCo 0.6; + +// Maximum diffusion number +maxDi 10.0; + +adjustTimeStep yes; + +functions +{ + externalCoupled + { + // Where to load it from (if not already in solver) + functionObjectLibs ("libjobControl.so"); + + type externalCoupled; + + // Directory to use for communication + commsDir "${FOAM_CASE}/comms"; + + // Does external process start first + initByExternal true; + + // Additional output + log true; + + regions + { + // Region name (wildcards allowed) + "(topAir|heater)" + { + // In topAir adjust the minX patch (fixedValue) + + // Patch or patchGroup + coupleGroup + { + // Fields to output in commsDir + writeFields (T); + // Fields to read from commsDir + readFields (T); + } + } + } + } +} + + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/decomposeParDict new file mode 100644 index 0000000000000000000000000000000000000000..3eb54ba02f72b2b3cd4ed7b5e14d9720e992f463 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/decomposeParDict @@ -0,0 +1,60 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + note "mesh decomposition control dictionary"; + location "system"; + object decomposeParDict; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 4; + +//- Keep owner and neighbour on same processor for faces in zones: +// preserveFaceZones (heater solid1 solid3); + +method scotch; +// method hierarchical; +// method simple; +// method manual; + +simpleCoeffs +{ + n (2 2 1); + delta 0.001; +} + +hierarchicalCoeffs +{ + n (2 2 1); + delta 0.001; + order xyz; +} + + +manualCoeffs +{ + dataFile "decompositionData"; +} + + +//// Is the case distributed +//distributed yes; +//// Per slave (so nProcs-1 entries) the directory above the case. +//roots +//( +// "/tmp" +// "/tmp" +//); + + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/fvSchemes similarity index 82% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/decomposeParDict rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/fvSchemes index 70c6c85c2638a12be80497e330a553e29f07f4ae..e7d321e95943268ef62b4a5e1d25ebbc469551bb 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/decomposeParDict +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/fvSchemes @@ -10,19 +10,36 @@ FoamFile version 2.0; format ascii; class dictionary; - location "system"; - object decomposeParDict; + object fvSchemes; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -numberOfSubdomains 4; +ddtSchemes +{ +} + +gradSchemes +{ +} + +divSchemes +{ +} -method simple; +laplacianSchemes +{ +} + +interpolationSchemes +{ +} + +snGradSchemes +{ +} -simpleCoeffs +fluxRequired { - n (2 2 1); - delta 0.001; } diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/constant/turbulenceProperties b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/fvSolution similarity index 84% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/constant/turbulenceProperties rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/fvSolution index 691c02bb16454a88808746d26f92385e182e60ac..cde9e49189fb2cd3795d3a5649417e7390f543e3 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/constant/turbulenceProperties +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/fvSolution @@ -10,20 +10,13 @@ FoamFile version 2.0; format ascii; class dictionary; - object RASProperties; + object fvSolution; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -simulationType RAS; - -RAS +PIMPLE { - RASModel kOmegaSST; - - turbulence on; - - printCoeffs on; + nOuterCorrectors 1; } - // ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/heater/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/heater/changeDictionaryDict new file mode 100644 index 0000000000000000000000000000000000000000..d8d26b8376d1ae0c225033640fd414ef77883bbd --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/heater/changeDictionaryDict @@ -0,0 +1,77 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object changeDictionaryDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dictionaryReplacement +{ + boundary + { + minY + { + type patch; + inGroups (coupleGroup); + } + minZ + { + type patch; + } + maxZ + { + type patch; + } + } + + + T + { + internalField uniform 300; + + boundaryField + { + ".*" + { + type zeroGradient; + value uniform 300; + } + "heater_to_.*" + { + type compressible::turbulentTemperatureCoupledBaffleMixed; + Tnbr T; + kappa solidThermo; + kappaName none; + value uniform 300; + } + + heater_to_leftSolid + { + type compressible::turbulentTemperatureCoupledBaffleMixed; + Tnbr T; + kappa solidThermo; + kappaName none; + thicknessLayers (1e-3); + kappaLayers (5e-4); + value uniform 300; + } + + minY + { + type fixedValue; + value uniform 500; + } + } + } +} + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/controlDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/heater/decomposeParDict similarity index 68% rename from tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/controlDict rename to tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/heater/decomposeParDict index 2df20103c16f0c06e30aa012afb41611c63dad9c..e405fc009e174023192077152a7fbf471ebeef03 100644 --- a/tutorials/heatTransfer/buoyantSimpleFoam/externalCoupledCavity/system/controlDict +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/heater/decomposeParDict @@ -10,39 +10,35 @@ FoamFile version 2.0; format ascii; class dictionary; - object controlDict; + location "system"; + object decomposeParDict; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -application buoyantSimpleFoam; +numberOfSubdomains 4; -startFrom startTime; +method scotch; -startTime 0; - -stopAt endTime; - -endTime 100; - -deltaT 1; - -writeControl timeStep; - -writeInterval 10; - -purgeWrite 0; - -writeFormat ascii; - -writePrecision 6; - -writeCompression off; - -timeFormat general; +simpleCoeffs +{ + n (2 2 1); + delta 0.001; +} -timePrecision 6; +hierarchicalCoeffs +{ + n (2 2 1); + delta 0.001; + order xyz; +} -runTimeModifiable true; +scotchCoeffs +{ +} +manualCoeffs +{ + dataFile "decompositionData"; +} // ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/heater/fvSchemes b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/heater/fvSchemes new file mode 100644 index 0000000000000000000000000000000000000000..d1227f9fad6317a856ef492515ac93a46c58bcd4 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/heater/fvSchemes @@ -0,0 +1,53 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; +} + +laplacianSchemes +{ + default none; + laplacian(alpha,h) Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} + +fluxRequired +{ + default no; +} + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/heater/fvSolution b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/heater/fvSolution new file mode 100644 index 0000000000000000000000000000000000000000..ccb0d3183fb2d698ff0b6b23ca6367efb9adfe00 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/heater/fvSolution @@ -0,0 +1,40 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + h + { + solver PCG; + preconditioner DIC; + tolerance 1e-06; + relTol 0.1; + } + + hFinal + { + $h; + tolerance 1e-06; + relTol 0; + } +} + +PIMPLE +{ + nNonOrthogonalCorrectors 0; +} + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/leftSolid/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/leftSolid/changeDictionaryDict new file mode 100644 index 0000000000000000000000000000000000000000..1709662b518d6561e59d932bf3c8f408e7253b21 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/leftSolid/changeDictionaryDict @@ -0,0 +1,65 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object changeDictionaryDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dictionaryReplacement +{ + boundary + { + minZ + { + type patch; + } + maxZ + { + type patch; + } + } + + T + { + internalField uniform 300; + + boundaryField + { + ".*" + { + type zeroGradient; + value uniform 300; + } + "leftSolid_to_.*" + { + type compressible::turbulentTemperatureCoupledBaffleMixed; + Tnbr T; + kappa solidThermo; + kappaName none; + value uniform 300; + } + + leftSolid_to_heater + { + type compressible::turbulentTemperatureCoupledBaffleMixed; + Tnbr T; + kappa solidThermo; + kappaName none; + thicknessLayers (1e-3); + kappaLayers (5e-4); + value uniform 300; + } + } + } +} + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/leftSolid/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/leftSolid/decomposeParDict new file mode 100644 index 0000000000000000000000000000000000000000..e405fc009e174023192077152a7fbf471ebeef03 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/leftSolid/decomposeParDict @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object decomposeParDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 4; + +method scotch; + +simpleCoeffs +{ + n (2 2 1); + delta 0.001; +} + +hierarchicalCoeffs +{ + n (2 2 1); + delta 0.001; + order xyz; +} + +scotchCoeffs +{ +} + +manualCoeffs +{ + dataFile "decompositionData"; +} + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/leftSolid/fvSchemes b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/leftSolid/fvSchemes new file mode 120000 index 0000000000000000000000000000000000000000..63236f302cfd79847ce312cced35784fa149c827 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/leftSolid/fvSchemes @@ -0,0 +1 @@ +../heater/fvSchemes \ No newline at end of file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/leftSolid/fvSolution b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/leftSolid/fvSolution new file mode 120000 index 0000000000000000000000000000000000000000..0bde0fc62f58a1a111ce897344b26816ef3de04d --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/leftSolid/fvSolution @@ -0,0 +1 @@ +../heater/fvSolution \ No newline at end of file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/rightSolid/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/rightSolid/changeDictionaryDict new file mode 100644 index 0000000000000000000000000000000000000000..ba99b13705c6d415e7828d3138d85bebb00b4f68 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/rightSolid/changeDictionaryDict @@ -0,0 +1,54 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object changeDictionaryDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dictionaryReplacement +{ + boundary + { + minZ + { + type patch; + } + maxZ + { + type patch; + } + } + + T + { + internalField uniform 300; + + boundaryField + { + ".*" + { + type zeroGradient; + value uniform 300; + } + "rightSolid_to_.*" + { + type compressible::turbulentTemperatureCoupledBaffleMixed; + Tnbr T; + kappa solidThermo; + kappaName none; + value uniform 300; + } + } + } +} + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/rightSolid/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/rightSolid/decomposeParDict new file mode 100644 index 0000000000000000000000000000000000000000..e405fc009e174023192077152a7fbf471ebeef03 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/rightSolid/decomposeParDict @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object decomposeParDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 4; + +method scotch; + +simpleCoeffs +{ + n (2 2 1); + delta 0.001; +} + +hierarchicalCoeffs +{ + n (2 2 1); + delta 0.001; + order xyz; +} + +scotchCoeffs +{ +} + +manualCoeffs +{ + dataFile "decompositionData"; +} + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/rightSolid/fvSchemes b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/rightSolid/fvSchemes new file mode 120000 index 0000000000000000000000000000000000000000..63236f302cfd79847ce312cced35784fa149c827 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/rightSolid/fvSchemes @@ -0,0 +1 @@ +../heater/fvSchemes \ No newline at end of file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/rightSolid/fvSolution b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/rightSolid/fvSolution new file mode 120000 index 0000000000000000000000000000000000000000..0bde0fc62f58a1a111ce897344b26816ef3de04d --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/rightSolid/fvSolution @@ -0,0 +1 @@ +../heater/fvSolution \ No newline at end of file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topAir/changeDictionaryDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topAir/changeDictionaryDict new file mode 100644 index 0000000000000000000000000000000000000000..d31389b04978f26e03aab39a49bf9a05e8b9fff4 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topAir/changeDictionaryDict @@ -0,0 +1,179 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object changeDictionaryDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dictionaryReplacement +{ + boundary + { + minX + { + inGroups (coupleGroup); + } + } + + U + { + internalField uniform (0.1 0 0); + + boundaryField + { + ".*" + { + type fixedValue; + value uniform (0 0 0); + } + minX + { + type fixedValue; + value uniform ( 0.1 0 0 ); + } + maxX + { + type inletOutlet; + inletValue uniform ( 0 0 0 ); + value uniform ( 0.1 0 0 ); + } + } + } + + T + { + internalField uniform 300; + + boundaryField + { + ".*" + { + type zeroGradient; + } + + minX + { + type fixedValue; + value uniform 300; + } + maxX + { + type inletOutlet; + inletValue uniform 300; + value uniform 300; + } + + "topAir_to_.*" + { + type compressible::turbulentTemperatureCoupledBaffleMixed; + Tnbr T; + kappa fluidThermo; + kappaName none; + value uniform 300; + } + } + } + + epsilon + { + internalField uniform 0.01; + + boundaryField + { + ".*" + { + type epsilonWallFunction; + value uniform 0.01; + } + + minX + { + type fixedValue; + value uniform 0.01; + } + maxX + { + type inletOutlet; + inletValue uniform 0.01; + value uniform 0.01; + } + } + } + + k + { + internalField uniform 0.1; + + boundaryField + { + ".*" + { + type kqRWallFunction; + value uniform 0.1; + } + + minX + { + type fixedValue; + value uniform 0.1; + } + maxX + { + type inletOutlet; + inletValue uniform 0.1; + value uniform 0.1; + } + } + } + + p_rgh + { + internalField uniform 1e5; + + boundaryField + { + ".*" + { + type fixedFluxPressure; + value uniform 1e5; + } + + maxX + { + type fixedValue; + value uniform 1e5; + } + } + } + + p + { + internalField uniform 1e5; + + boundaryField + { + ".*" + { + type calculated; + value uniform 1e5; + } + + maxX + { + type calculated; + value uniform 1e5; + } + } + } +} + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topAir/decomposeParDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topAir/decomposeParDict new file mode 100644 index 0000000000000000000000000000000000000000..9bdbb31cd254a0189def7c9f126c3dcfaab64f1b --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topAir/decomposeParDict @@ -0,0 +1,72 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + note "mesh decomposition control dictionary"; + location "system"; + object decomposeParDict; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 4; + +//- Keep owner and neighbour on same processor for faces in zones: +// preserveFaceZones (heater solid1 solid3); + +method scotch; +// method hierarchical; +// method simple; +// method manual; + +simpleCoeffs +{ + n (2 2 1); + delta 0.001; +} + +hierarchicalCoeffs +{ + n (2 2 1); + delta 0.001; + order xyz; +} + +scotchCoeffs +{ + //processorWeights + //( + // 1 + // 1 + // 1 + // 1 + //); + //writeGraph true; + //strategy "b"; +} + +manualCoeffs +{ + dataFile "decompositionData"; +} + + +//// Is the case distributed +//distributed yes; +//// Per slave (so nProcs-1 entries) the directory above the case. +//roots +//( +// "/tmp" +// "/tmp" +//); + + +// ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topAir/fvSchemes b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topAir/fvSchemes new file mode 120000 index 0000000000000000000000000000000000000000..323c0787e29528c483a4560ad3cb1f0542283cfb --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topAir/fvSchemes @@ -0,0 +1 @@ +../bottomWater/fvSchemes \ No newline at end of file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topAir/fvSolution b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topAir/fvSolution new file mode 120000 index 0000000000000000000000000000000000000000..90d9c9234761adbcffeb20601556f39e118ef768 --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topAir/fvSolution @@ -0,0 +1 @@ +../bottomWater/fvSolution \ No newline at end of file diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topoSetDict b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topoSetDict new file mode 100644 index 0000000000000000000000000000000000000000..feb3d898bc2f3a5e878a15f5cdcaae51e5436c4b --- /dev/null +++ b/tutorials/heatTransfer/chtMultiRegionFoam/externalCoupledMultiRegionHeater/system/topoSetDict @@ -0,0 +1,178 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object topoSetDict; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +actions +( + // Heater + { + name heaterCellSet; + type cellSet; + action new; + source boxToCell; + sourceInfo + { + box (-0.01001 0 -100 )(0.01001 0.00999 100); + } + } + { + name heaterCellSet; + type cellSet; + action add; + source boxToCell; + sourceInfo + { + box (-0.01001 -100 -0.01001)(0.01001 0.00999 0.01001); + } + } + { + name heater; + type cellZoneSet; + action new; + source setToCellZone; + sourceInfo + { + set heaterCellSet; + } + } + + // leftSolid + { + name leftSolidCellSet; + type cellSet; + action new; + source boxToCell; + sourceInfo + { + box (-100 0 -100 )(-0.01001 0.00999 100); + } + } + { + name leftSolid; + type cellZoneSet; + action new; + source setToCellZone; + sourceInfo + { + set leftSolidCellSet; + } + } + + // rightSolid + { + name rightSolidCellSet; + type cellSet; + action new; + source boxToCell; + sourceInfo + { + box (0.01001 0 -100 )(100 0.00999 100); + } + } + { + name rightSolid; + type cellZoneSet; + action new; + source setToCellZone; + sourceInfo + { + set rightSolidCellSet; + } + } + + // topAir + { + name topAirCellSet; + type cellSet; + action new; + source boxToCell; + sourceInfo + { + box (-100 0.00999 -100 )(100 100 100); + } + } + { + name topAir; + type cellZoneSet; + action new; + source setToCellZone; + sourceInfo + { + set topAirCellSet; + } + } + + + // bottomWater is all the other cells + { + name bottomWaterCellSet; + type cellSet; + action new; + source cellToCell; + sourceInfo + { + set heaterCellSet; + } + } + { + name bottomWaterCellSet; + type cellSet; + action add; + source cellToCell; + sourceInfo + { + set leftSolidCellSet; + } + } + { + name bottomWaterCellSet; + type cellSet; + action add; + source cellToCell; + sourceInfo + { + set rightSolidCellSet; + } + } + { + name bottomWaterCellSet; + type cellSet; + action add; + source cellToCell; + sourceInfo + { + set topAirCellSet; + } + } + { + name bottomWaterCellSet; + type cellSet; + action invert; + } + { + name bottomWater; + type cellZoneSet; + action new; + source setToCellZone; + sourceInfo + { + set bottomWaterCellSet; + } + } +); + + +// ************************************************************************* // diff --git a/tutorials/mesh/moveDynamicMesh/SnakeRiverCanyon/system/fvSolution b/tutorials/mesh/moveDynamicMesh/SnakeRiverCanyon/system/fvSolution index 898ec2420b4482b3c3d4a1919eb4a0f45538be1a..04d9fe6cc656c0d79d5b33c6c07a7596340fb5dd 100644 --- a/tutorials/mesh/moveDynamicMesh/SnakeRiverCanyon/system/fvSolution +++ b/tutorials/mesh/moveDynamicMesh/SnakeRiverCanyon/system/fvSolution @@ -33,7 +33,7 @@ solvers relTol 0; } - cellDisplacement + "cellDisplacement.*" { solver GAMG; tolerance 1e-08; @@ -53,5 +53,8 @@ solvers } } +PIMPLE +{} + // ************************************************************************* //