From ebb9a9e1acc66df9eac9d85363810d1a4814e655 Mon Sep 17 00:00:00 2001 From: graham <g.macpherson@opencfd.co.uk> Date: Fri, 17 Sep 2010 16:59:17 +0100 Subject: [PATCH] ENH: tet decomposed particle tracking. Squashed merge of particleInteractions up to commit e7cb5bcf0315c359539ef1e715e1d51991343391 --- .../combustion/dieselEngineFoam/Make/options | 2 + .../combustion/dieselFoam/Make/options | 2 + .../dsmc/dsmcFoam/Make/options | 1 - .../Make/files | 3 + .../Make/options | 33 + .../createFields.H | 147 +++ ...pressibleUncoupledKinematicParcelDyMFoam.C | 92 ++ .../test/findCell-octree/findCell-octree.C | 61 +- .../snappyHexMesh/snappyHexMeshDict | 13 +- .../manipulation/checkMesh/checkGeometry.C | 28 +- .../decomposePar/decomposePar.C | 28 +- .../decomposePar/lagrangianFieldDecomposer.C | 36 + .../decomposePar/lagrangianFieldDecomposer.H | 1 + ...lagrangianFieldDecomposerDecomposeFields.C | 4 +- .../dataConversion/foamToEnsight/Make/options | 2 + .../foamToEnsightParts/Make/options | 2 + .../foamToFieldview9/Make/options | 2 + .../dataConversion/foamToGMV/Make/options | 2 + .../graphics/ensightFoamReader/Make/options | 2 + .../lagrangian/particleTracks/Make/options | 2 + .../preProcessing/dsmcInitialise/Make/options | 1 - .../mapFields/MapLagrangianFields.H | 130 +- .../preProcessing/mapFields/mapLagrangian.C | 23 +- .../surface/surfaceSubset/surfaceSubset.C | 1 - etc/controlDict | 1 + src/Allwmake | 3 +- src/OpenFOAM/Make/files | 2 + src/OpenFOAM/meshes/polyMesh/polyMesh.C | 26 + src/OpenFOAM/meshes/polyMesh/polyMesh.H | 7 + src/OpenFOAM/meshes/polyMesh/polyMeshClear.C | 3 + .../meshes/polyMesh/polyMeshFromShapeMesh.C | 2 + .../polyMeshTetDecomposition.C | 627 ++++++++++ .../polyMeshTetDecomposition.H | 151 +++ .../polyMeshTetDecomposition/tetIndices.C | 148 +++ .../polyMeshTetDecomposition/tetIndices.H | 201 +++ .../polyMeshTetDecomposition/tetIndicesI.H | 202 +++ .../constraint/processor/processorPolyPatch.H | 13 + .../polyMesh/syncTools/syncToolsTemplates.C | 6 +- .../meshes/primitiveMesh/primitiveMesh.H | 9 +- .../primitiveMeshCheck/primitiveMeshCheck.C | 108 -- .../primitiveMesh/primitiveMeshFindCell.C | 34 +- .../primitiveShapes/tetrahedron/tetrahedron.C | 1 - .../primitiveShapes/tetrahedron/tetrahedron.H | 29 +- .../tetrahedron/tetrahedronI.H | 209 +++- .../primitiveShapes/triangle/triangle.H | 21 +- .../primitiveShapes/triangle/triangleI.H | 73 +- src/OpenFOAM/primitives/Tensor/TensorI.H | 2 +- .../motionSmoother/motionSmootherCheck.C | 24 +- .../polyMeshGeometry/polyMeshGeometry.C | 158 ++- .../polyMeshGeometry/polyMeshGeometry.H | 5 +- .../interpolation/interpolation.H | 19 +- .../interpolationCell/interpolationCell.C | 4 +- .../interpolationCell/interpolationCell.H | 4 +- .../cellPointWeight/cellPointWeight.C | 365 +++--- .../cellPointWeight/cellPointWeight.H | 20 +- .../interpolationCellPoint.H | 15 +- .../interpolationCellPointI.H | 73 +- .../interpolationCellPointFace.C | 78 +- .../interpolationCellPointFace.H | 4 +- .../cellPointWeightWallModified.C | 29 +- .../cellPointWeightWallModified.H | 7 +- .../interpolationCellPointWallModified.H | 13 +- .../interpolationCellPointWallModifiedI.H | 84 +- .../interpolationPoint/interpolationPoint.H | 4 +- .../interpolationPoint/interpolationPointI.H | 6 +- .../interpolationPoint/pointMVCWeight.H | 4 +- src/lagrangian/basic/Cloud/Cloud.C | 340 +++++- src/lagrangian/basic/Cloud/Cloud.H | 95 +- src/lagrangian/basic/Cloud/CloudIO.C | 19 +- src/lagrangian/basic/Make/options | 5 + src/lagrangian/basic/Particle/Particle.C | 643 +++++++--- src/lagrangian/basic/Particle/Particle.H | 173 ++- src/lagrangian/basic/Particle/ParticleI.H | 1082 ++++++++++++++--- src/lagrangian/basic/Particle/ParticleIO.C | 56 +- .../basic/indexedParticle/indexedParticle.H | 19 +- .../basic/passiveParticle/passiveParticle.H | 17 +- .../coalCombustion/coalParcel/coalParcel.C | 17 +- .../coalCombustion/coalParcel/coalParcel.H | 6 +- src/lagrangian/dieselSpray/Make/options | 2 + .../dieselSpray/parcel/boundaryTreatment.H | 14 +- src/lagrangian/dieselSpray/parcel/parcel.C | 71 +- src/lagrangian/dieselSpray/parcel/parcel.H | 10 +- .../dieselSpray/parcel/setRelaxationTimes.C | 10 +- .../dieselSpray/spray/findInjectorCell.H | 9 +- src/lagrangian/dieselSpray/spray/spray.C | 8 +- .../dieselSpray/spray/sprayFunctions.C | 8 +- .../dieselSpray/spray/sprayInject.C | 14 +- src/lagrangian/dieselSpray/spray/sprayOps.C | 4 +- .../spraySubModels/breakupModel/SHF/SHF.C | 8 +- .../breakupModel/reitzKHRT/reitzKHRT.C | 8 +- .../wallModel/reflectParcel/reflectParcel.C | 30 +- .../wallModel/reflectParcel/reflectParcel.H | 2 +- .../wallModel/removeParcel/removeParcel.C | 2 +- .../wallModel/removeParcel/removeParcel.H | 2 +- .../wallModel/wallModel/wallModel.H | 2 +- .../clouds/Templates/DsmcCloud/DsmcCloud.C | 238 ++-- .../clouds/Templates/DsmcCloud/DsmcCloud.H | 8 +- .../parcels/Templates/DsmcParcel/DsmcParcel.C | 17 +- .../parcels/Templates/DsmcParcel/DsmcParcel.H | 15 +- .../Templates/DsmcParcel/DsmcParcelI.H | 6 +- .../parcels/derived/dsmcParcel/dsmcParcel.C | 8 +- .../parcels/derived/dsmcParcel/dsmcParcel.H | 4 +- .../BinaryCollisionModel.H | 14 +- .../LarsenBorgnakkeVariableHardSphere.C | 26 +- .../LarsenBorgnakkeVariableHardSphere.H | 14 +- .../NoBinaryCollision/NoBinaryCollision.C | 14 +- .../NoBinaryCollision/NoBinaryCollision.H | 14 +- .../VariableHardSphere/VariableHardSphere.C | 24 +- .../VariableHardSphere/VariableHardSphere.H | 14 +- .../FreeStream/FreeStream.C | 89 +- .../MaxwellianThermal/MaxwellianThermal.C | 19 +- .../MaxwellianThermal/MaxwellianThermal.H | 12 +- .../MixedDiffuseSpecular.C | 19 +- .../MixedDiffuseSpecular.H | 14 +- .../SpecularReflection/SpecularReflection.C | 11 +- .../SpecularReflection/SpecularReflection.H | 7 +- .../WallInteractionModel.H | 7 +- src/lagrangian/intermediate/Make/options | 5 +- .../Templates/KinematicCloud/KinematicCloud.H | 7 + .../KinematicCloud/KinematicCloudI.H | 7 + .../KinematicParcel/KinematicParcel.C | 52 +- .../KinematicParcel/KinematicParcel.H | 22 +- .../KinematicParcel/KinematicParcelI.H | 28 +- .../ReactingMultiphaseParcel.H | 6 +- .../ReactingMultiphaseParcelI.H | 10 +- .../Templates/ReactingParcel/ReactingParcel.C | 7 +- .../Templates/ReactingParcel/ReactingParcel.H | 6 +- .../ReactingParcel/ReactingParcelI.H | 10 +- .../Templates/ThermoParcel/ThermoParcel.C | 14 +- .../Templates/ThermoParcel/ThermoParcel.H | 6 +- .../Templates/ThermoParcel/ThermoParcelI.H | 10 +- .../basicKinematicParcel.C | 17 +- .../basicKinematicParcel.H | 6 +- .../basicReactingMultiphaseParcel.C | 14 +- .../basicReactingMultiphaseParcel.H | 6 +- .../basicReactingParcel/basicReactingParcel.C | 25 +- .../basicReactingParcel/basicReactingParcel.H | 6 +- .../basicThermoParcel/basicThermoParcel.C | 10 +- .../basicThermoParcel/basicThermoParcel.H | 6 +- .../particleForces/particleForces.C | 12 +- .../particleForces/particleForces.H | 5 +- .../DispersionModel/DispersionModel.H | 2 +- .../GradientDispersionRAS.C | 10 +- .../GradientDispersionRAS.H | 2 +- .../NoDispersion/NoDispersion.H | 2 +- .../StochasticDispersionRAS.C | 8 +- .../StochasticDispersionRAS.H | 2 +- .../ConeInjection/ConeInjection.C | 16 +- .../ConeInjection/ConeInjection.H | 12 +- .../ConeInjectionMP/ConeInjectionMP.C | 12 +- .../ConeInjectionMP/ConeInjectionMP.H | 14 +- .../FieldActivatedInjection.C | 10 +- .../FieldActivatedInjection.H | 18 +- .../InjectionModel/InjectionModel.C | 42 +- .../InjectionModel/InjectionModel.H | 8 +- .../KinematicLookupTableInjection.C | 21 +- .../KinematicLookupTableInjection.H | 16 +- .../ManualInjection/ManualInjection.C | 62 +- .../ManualInjection/ManualInjection.H | 17 +- .../InjectionModel/NoInjection/NoInjection.C | 2 + .../InjectionModel/NoInjection/NoInjection.H | 6 +- .../PatchInjection/PatchInjection.C | 32 +- .../PatchInjection/PatchInjection.H | 10 +- .../LocalInteraction/LocalInteraction.C | 46 +- .../LocalInteraction/LocalInteraction.H | 8 +- .../PatchInteractionModel.C | 165 ++- .../PatchInteractionModel.H | 26 +- .../PatchInteractionModel/Rebound/Rebound.C | 22 +- .../PatchInteractionModel/Rebound/Rebound.H | 6 +- .../StandardWallInteraction.C | 22 +- .../StandardWallInteraction.H | 6 +- .../SurfaceFilmModel/SurfaceFilmModel.C | 21 +- .../ReactingLookupTableInjection.C | 21 +- .../ReactingLookupTableInjection.H | 16 +- .../ReactingMultiphaseLookupTableInjection.C | 21 +- .../ReactingMultiphaseLookupTableInjection.H | 16 +- .../ThermoLookupTableInjection.C | 21 +- .../ThermoLookupTableInjection.H | 16 +- .../molecule/molecule/molecule.C | 18 +- .../molecule/molecule/molecule.H | 18 +- .../molecule/molecule/moleculeI.H | 6 +- .../molecule/moleculeCloud/moleculeCloud.C | 46 +- .../molecule/moleculeCloud/moleculeCloud.H | 2 + src/lagrangian/solidParticle/Make/options | 2 + src/lagrangian/solidParticle/solidParticle.C | 20 +- src/lagrangian/solidParticle/solidParticle.H | 20 +- .../solidParticle/solidParticleCloud.H | 2 + .../solidParticle/solidParticleCloudI.H | 6 + src/lagrangian/solidParticle/solidParticleI.H | 11 +- .../meshRefinement/meshRefinementRefine.C | 8 +- .../trackedParticle/ExactParticle.C | 261 ---- .../trackedParticle/ExactParticle.H | 191 --- .../trackedParticle/trackedParticle.C | 26 +- .../trackedParticle/trackedParticle.H | 25 +- src/meshTools/Make/options | 6 +- src/meshTools/surfaceSets/surfaceSets.H | 5 +- .../surfaceIntersection/surfaceIntersection.C | 2 - .../surfaceIntersectionFuncs.C | 2 - .../surfaceFeatures/surfaceFeatures.C | 196 ++- .../surfaceFeatures/surfaceFeatures.H | 28 +- .../reconstruct/reconstruct/Make/options | 2 + .../reconstructLagrangianPositions.C | 7 + .../field/streamLine/streamLine.C | 12 +- .../field/streamLine/streamLineParticle.C | 18 +- .../field/streamLine/streamLineParticle.H | 17 +- src/sampling/Make/options | 3 +- .../calculateMeshToMeshAddressing.C | 54 +- .../meshToMesh/meshToMesh.H | 6 +- .../sampledTriSurfaceMesh.C | 1 - .../aachenBomb/constant/sprayProperties | 2 +- .../iglooWithFridges/system/snappyHexMeshDict | 13 +- .../system/snappyHexMeshDict | 13 +- .../system/snappyHexMeshDict | 13 +- .../motorBike/system/snappyHexMeshDict | 13 +- .../system/snappyHexMeshDict | 13 +- .../constant/coalCloud1Properties | 2 +- .../filter/constant/reactingCloud1Properties | 2 +- .../constant/reactingCloud1Properties | 2 +- .../constant/reactingCloud1Properties | 2 +- .../constant/reactingCloud1Properties | 2 +- .../constant/reactingCloud1Properties | 2 +- .../constant/reactingCloud1Properties | 2 +- .../panel/constant/reactingCloud1Properties | 2 +- .../constant/reactingCloud1Properties | 2 +- .../0.org/pointDisplacement | 88 ++ .../simpleHarmonicMotion/Allclean | 11 + .../simpleHarmonicMotion/Allrun | 19 + .../constant/dynamicMeshDict | 26 + .../constant/polyMesh/blockMeshDict | 59 + .../constant/polyMesh/boundary} | 31 +- .../simpleHarmonicMotion/extractData | 42 + .../simpleHarmonicMotion/shm.gnuplot | 76 ++ .../simpleHarmonicMotion/system/controlDict | 68 ++ .../simpleHarmonicMotion/system/fvSchemes | 50 + .../simpleHarmonicMotion/system/fvSolution | 34 + .../simpleHarmonicMotion/system/topoSetDict} | 35 +- .../cavitatingBullet/system/snappyHexMeshDict | 13 +- 237 files changed, 6895 insertions(+), 2499 deletions(-) create mode 100644 applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/Make/files create mode 100644 applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/Make/options create mode 100644 applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/createFields.H create mode 100644 applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/incompressibleUncoupledKinematicParcelDyMFoam.C create mode 100644 src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.C create mode 100644 src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.H create mode 100644 src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndices.C create mode 100644 src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndices.H create mode 100644 src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndicesI.H delete mode 100644 src/mesh/autoMesh/autoHexMesh/trackedParticle/ExactParticle.C delete mode 100644 src/mesh/autoMesh/autoHexMesh/trackedParticle/ExactParticle.H create mode 100644 tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/0.org/pointDisplacement create mode 100755 tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/Allclean create mode 100755 tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/Allrun create mode 100644 tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/constant/dynamicMeshDict create mode 100644 tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/constant/polyMesh/blockMeshDict rename tutorials/{discreteMethods/molecularDynamics/mdEquilibrationFoam/periodicCubeWater/0/U => mesh/moveDynamicMesh/simpleHarmonicMotion/constant/polyMesh/boundary} (71%) create mode 100755 tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/extractData create mode 100644 tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/shm.gnuplot create mode 100644 tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/controlDict create mode 100644 tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/fvSchemes create mode 100644 tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/fvSolution rename tutorials/{discreteMethods/molecularDynamics/mdEquilibrationFoam/periodicCubeArgon/0/U => mesh/moveDynamicMesh/simpleHarmonicMotion/system/topoSetDict} (72%) diff --git a/applications/solvers/combustion/dieselEngineFoam/Make/options b/applications/solvers/combustion/dieselEngineFoam/Make/options index d0a572b86fe..9a452478199 100644 --- a/applications/solvers/combustion/dieselEngineFoam/Make/options +++ b/applications/solvers/combustion/dieselEngineFoam/Make/options @@ -2,6 +2,7 @@ EXE_INC = \ -I../engineFoam \ -I$(LIB_SRC)/turbulenceModels/compressible/turbulenceModel \ -I$(LIB_SRC)/lagrangian/basic/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/lagrangian/dieselSpray/lnInclude \ -I$(LIB_SRC)/thermophysicalModels/liquids/lnInclude \ -I$(LIB_SRC)/thermophysicalModels/liquidMixture/lnInclude \ @@ -24,6 +25,7 @@ EXE_LIBS = \ -lreactionThermophysicalModels \ -lfiniteVolume \ -llagrangian \ + -lmeshTools \ -ldieselSpray \ -lliquids \ -lliquidMixture \ diff --git a/applications/solvers/combustion/dieselFoam/Make/options b/applications/solvers/combustion/dieselFoam/Make/options index 9096934c2dd..3b1786aa08b 100644 --- a/applications/solvers/combustion/dieselFoam/Make/options +++ b/applications/solvers/combustion/dieselFoam/Make/options @@ -3,6 +3,7 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/turbulenceModels/compressible/turbulenceModel \ -I$(LIB_SRC)/lagrangian/basic/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/lagrangian/dieselSpray/lnInclude \ -I$(LIB_SRC)/thermophysicalModels/liquids/lnInclude \ -I$(LIB_SRC)/thermophysicalModels/liquidMixture/lnInclude \ @@ -21,6 +22,7 @@ EXE_LIBS = \ -lcompressibleLESModels \ -lreactionThermophysicalModels \ -llagrangian \ + -lmeshTools \ -ldieselSpray \ -lliquids \ -lliquidMixture \ diff --git a/applications/solvers/discreteMethods/dsmc/dsmcFoam/Make/options b/applications/solvers/discreteMethods/dsmc/dsmcFoam/Make/options index bc99834af6e..62520c19b0e 100644 --- a/applications/solvers/discreteMethods/dsmc/dsmcFoam/Make/options +++ b/applications/solvers/discreteMethods/dsmc/dsmcFoam/Make/options @@ -9,4 +9,3 @@ EXE_LIBS = \ -lfiniteVolume \ -llagrangian \ -ldsmc - diff --git a/applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/Make/files b/applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/Make/files new file mode 100644 index 00000000000..e233a549b84 --- /dev/null +++ b/applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/Make/files @@ -0,0 +1,3 @@ +incompressibleUncoupledKinematicParcelDyMFoam.C + +EXE = $(FOAM_APPBIN)/incompressibleUncoupledKinematicParcelDyMFoam diff --git a/applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/Make/options b/applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/Make/options new file mode 100644 index 00000000000..3c4206dc24a --- /dev/null +++ b/applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/Make/options @@ -0,0 +1,33 @@ +EXE_INC = \ + -I$(LIB_SRC)/lagrangian/basic/lnInclude \ + -I$(LIB_SRC)/lagrangian/intermediate/lnInclude \ + -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \ + -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \ + -I$(LIB_SRC)/thermophysicalModels/reactionThermo/lnInclude \ + -I$(LIB_SRC)/thermophysicalModels/radiation/lnInclude \ + -I$(LIB_SRC)/turbulenceModels/incompressible/turbulenceModel \ + -I$(LIB_SRC)/transportModels \ + -I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/surfaceFilmModels/lnInclude \ + -I$(LIB_SRC)/dynamicMesh/lnInclude \ + -I$(LIB_SRC)/dynamicFvMesh/lnInclude + + +EXE_LIBS = \ + -llagrangian \ + -llagrangianIntermediate \ + -lthermophysicalFunctions \ + -lbasicThermophysicalModels \ + -lspecie \ + -lradiation \ + -lincompressibleRASModels \ + -lincompressibleLESModels \ + -lincompressibleTransportModels \ + -lfiniteVolume \ + -lmeshTools \ + -lsurfaceFilmModels \ + -ldynamicMesh \ + -ldynamicFvMesh \ + -ltopoChangerFvMesh diff --git a/applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/createFields.H b/applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/createFields.H new file mode 100644 index 00000000000..0ad057e2299 --- /dev/null +++ b/applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/createFields.H @@ -0,0 +1,147 @@ + Info<< "\nReading transportProperties\n" << endl; + + IOdictionary transportProperties + ( + IOobject + ( + "transportProperties", + runTime.constant(), + mesh, + IOobject::MUST_READ_IF_MODIFIED, + IOobject::NO_WRITE + ) + ); + + dimensionedScalar rhoInfValue + ( + transportProperties.lookup("rhoInf") + ); + + volScalarField rhoInf + ( + IOobject + ( + "rho", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh, + rhoInfValue + ); + + Info<< "Reading field U\n" << endl; + volVectorField U + ( + IOobject + ( + "U", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + #include "createPhi.H" + + Info<< "Creating turbulence model\n" << endl; + + singlePhaseTransportModel laminarTransport(U, phi); + + const volScalarField nu = laminarTransport.nu(); + + autoPtr<incompressible::turbulenceModel> turbulence + ( + incompressible::turbulenceModel::New(U, phi, laminarTransport) + ); + + volScalarField mu + ( + IOobject + ( + "mu", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + nu*rhoInfValue + ); + + word kinematicCloudName("kinematicCloud"); + args.optionReadIfPresent("cloudName", kinematicCloudName); + + Info<< "Constructing kinematicCloud " << kinematicCloudName << endl; + basicKinematicCloud kinematicCloud + ( + kinematicCloudName, + rhoInf, + U, + mu, + g + ); + + IOobject Hheader + ( + "H", + runTime.timeName(), + mesh, + IOobject::NO_READ + ); + + autoPtr<volVectorField> HPtr_; + + if (Hheader.headerOk()) + { + Info<< "\nReading field H\n" << endl; + + HPtr_.reset + ( + new volVectorField + ( + IOobject + ( + "H", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ) + ); + } + + IOobject HdotGradHheader + ( + "HdotGradH", + runTime.timeName(), + mesh, + IOobject::NO_READ + ); + + autoPtr<volVectorField> HdotGradHPtr_; + + if (HdotGradHheader.headerOk()) + { + Info<< "Reading field HdotGradH" << endl; + + HdotGradHPtr_.reset + ( + new volVectorField + ( + IOobject + ( + "HdotGradH", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ) + ); + } diff --git a/applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/incompressibleUncoupledKinematicParcelDyMFoam.C b/applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/incompressibleUncoupledKinematicParcelDyMFoam.C new file mode 100644 index 00000000000..f5fba006e02 --- /dev/null +++ b/applications/solvers/lagrangian/incompressibleUncoupledKinematicParcelDyMFoam/incompressibleUncoupledKinematicParcelDyMFoam.C @@ -0,0 +1,92 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Application + uncoupledKinematicParcelFoam + +Description + Transient solver for the passive transport of a single kinematic + particle could. + + Uses a pre-calculated velocity field to evolve the cloud. + +\*---------------------------------------------------------------------------*/ + +#include "fvCFD.H" +#include "dynamicFvMesh.H" +#include "singlePhaseTransportModel.H" +#include "turbulenceModel.H" +#include "basicKinematicCloud.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + argList::addOption + ( + "cloudName", + "name", + "specify alternative cloud name. default is 'kinematicCloud'" + ); + + #include "setRootCase.H" + #include "createTime.H" + # include "createDynamicFvMesh.H" + + #include "readGravitationalAcceleration.H" + #include "createFields.H" + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info<< "\nStarting time loop\n" << endl; + + while (runTime.loop()) + { + Info<< "Time = " << runTime.timeName() << nl << endl; + + mesh.update(); + + U.correctBoundaryConditions(); + + Info<< "Evolving " << kinematicCloud.name() << endl; + + laminarTransport.correct(); + + mu = nu*rhoInfValue; + + kinematicCloud.evolve(); + + runTime.write(); + + Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" + << " ClockTime = " << runTime.elapsedClockTime() << " s" + << nl << endl; + } + + Info<< "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/test/findCell-octree/findCell-octree.C b/applications/test/findCell-octree/findCell-octree.C index 2fbb9c0703f..df8797eeb06 100644 --- a/applications/test/findCell-octree/findCell-octree.C +++ b/applications/test/findCell-octree/findCell-octree.C @@ -29,6 +29,8 @@ License #include "IStringStream.H" #include "octree.H" #include "octreeDataCell.H" +#include "indexedOctree.H" +#include "treeDataCell.H" #include "OFstream.H" using namespace Foam; @@ -44,11 +46,13 @@ int main(int argc, char *argv[]) # include "createTime.H" # include "createMesh.H" + label nReps = 100000; + const point sample = args.argRead<point>(1); - treeBoundBox meshBb(mesh.points()); + treeBoundBox meshBb(mesh.bounds()); - // Calculate typical cell releated size to shift bb by. + // Calculate typical cell related size to shift bb by. scalar typDim = meshBb.avgDim()/(2.0*Foam::cbrt(scalar(mesh.nCells()))); treeBoundBox shiftedBb @@ -57,16 +61,13 @@ int main(int argc, char *argv[]) meshBb.max() + vector(typDim, typDim, typDim) ); - Info<< "Mesh" << endl; Info<< " bounding box : " << meshBb << endl; Info<< " bounding box (shifted) : " << shiftedBb << endl; Info<< " typical dimension : " << shiftedBb.typDim() << endl; - - /* - * Now we have allBb and shiftedBb - */ + Info<< "Initialised mesh in " + << runTime.cpuTimeIncrement() << " s" << endl; // Wrap indices and mesh information into helper object octreeDataCell shapes(mesh); @@ -80,14 +81,52 @@ int main(int argc, char *argv[]) 10.0 // maximum ratio of cubes v.s. cells ); - Info<< "Point:" << sample << " is in shape " - << oc.find(sample) << nl - << "Point:" << sample << " is in cell " - << mesh.findCell(sample) << endl; + for (label i = 0; i < nReps - 1 ; i++) + { + oc.find(sample); + } + Info<< "Point:" << sample << " is in shape " + << oc.find(sample) << endl; oc.printStats(Info); + Info<< "Found in octree " << nReps << " times in " + << runTime.cpuTimeIncrement() << " s" << endl; + + indexedOctree<treeDataCell> ioc + ( + treeDataCell(true, mesh), + shiftedBb, + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity + ); + + for (label i = 0; i < nReps - 1 ; i++) + { + ioc.findInside(sample); + } + + Info<< "Point:" << sample << " is in shape " + << ioc.findInside(sample) + << ", where the possible cells were:" << nl + << ioc.findIndices(sample) + << endl; + + Info<< "Found in indexedOctree " << nReps << " times in " + << runTime.cpuTimeIncrement() << " s" << endl; + + for (label i = 0; i < nReps - 1 ; i++) + { + mesh.findCell(sample); + } + + Info<< "Point:" << sample << " is in cell " + << mesh.findCell(sample) << endl; + + Info<< "Found in mesh.findCell " << nReps << " times in " + << runTime.cpuTimeIncrement() << " s" << endl; Info<< "End\n" << endl; diff --git a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMeshDict b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMeshDict index 476dbe1afb4..a15aa483c4f 100644 --- a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMeshDict +++ b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMeshDict @@ -341,11 +341,14 @@ meshQualityControls // Set to very negative number (e.g. -1E30) to disable. minVol 1e-13; - //- Minimum tet volume. Is absolute volume of the tet formed by the - // face-centre decomposition triangle and the cell centre. - // Set to a sensible fraction of the smallest cell volume expected. - // Set to very negative number (e.g. -1E30) to disable. - minTetVol 1e-20; + //- Minimum quality of the tet formed by the face-centre + // and variable base point minimum decomposition triangles and + // the cell centre. Set to very negative number (e.g. -1E30) to + // disable. + // <0 = inside out tet, + // 0 = flat tet + // 1 = regular tet + minTetQuality 1e-9; //- Minimum face area. Set to <0 to disable. minArea -1; diff --git a/applications/utilities/mesh/manipulation/checkMesh/checkGeometry.C b/applications/utilities/mesh/manipulation/checkMesh/checkGeometry.C index 57f892b8e44..82e0dedd82c 100644 --- a/applications/utilities/mesh/manipulation/checkMesh/checkGeometry.C +++ b/applications/utilities/mesh/manipulation/checkMesh/checkGeometry.C @@ -6,6 +6,7 @@ #include "EdgeMap.H" #include "wedgePolyPatch.H" #include "unitConversion.H" +#include "polyMeshTetDecomposition.H" // Find wedge with opposite orientation. Note: does not actually check that @@ -83,7 +84,7 @@ bool Foam::checkWedges { Info<< " Wedge " << pp.name() << " with angle " << radToDeg(wedgeAngle) << " degrees" - << endl; + << endl; } // Find opposite @@ -413,7 +414,6 @@ Foam::label Foam::checkGeometry(const polyMesh& mesh, const bool allGeometry) } } - { faceSet faces(mesh, "wrongOrientedFaces", mesh.nFaces()/100 + 1); if (mesh.checkFacePyramids(true, -SMALL, &faces)) @@ -434,8 +434,8 @@ Foam::label Foam::checkGeometry(const polyMesh& mesh, const bool allGeometry) } { - faceSet faces(mesh, "wrongOrientedTriangleFaces", mesh.nFaces()/100+1); - if (mesh.checkFaceTets(true, 0, &faces)) + faceSet faces(mesh, "skewFaces", mesh.nFaces()/100+1); + if (mesh.checkFaceSkewness(true, &faces)) { noFailedChecks++; @@ -444,17 +444,26 @@ Foam::label Foam::checkGeometry(const polyMesh& mesh, const bool allGeometry) if (nFaces > 0) { Info<< " <<Writing " << nFaces - << " faces with incorrectly orientated triangles to set " - << faces.name() << endl; + << " skew faces to set " << faces.name() << endl; faces.instance() = mesh.pointsInstance(); faces.write(); } } } + if (allGeometry) { - faceSet faces(mesh, "skewFaces", mesh.nFaces()/100+1); - if (mesh.checkFaceSkewness(true, &faces)) + faceSet faces(mesh, "lowQualityTetFaces", mesh.nFaces()/100+1); + if + ( + polyMeshTetDecomposition::checkFaceTets + ( + mesh, + polyMeshTetDecomposition::minTetQuality, + true, + &faces + ) + ) { noFailedChecks++; @@ -463,7 +472,8 @@ Foam::label Foam::checkGeometry(const polyMesh& mesh, const bool allGeometry) if (nFaces > 0) { Info<< " <<Writing " << nFaces - << " skew faces to set " << faces.name() << endl; + << " faces with low quality or negative volume " + << "decomposition tets to set " << faces.name() << endl; faces.instance() = mesh.pointsInstance(); faces.write(); } diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C index 91a51e2ae57..0c72ca7ee72 100644 --- a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C +++ b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C @@ -558,7 +558,6 @@ int main(int argc, char *argv[]) lagrangianScalarFieldFields ); - lagrangianFieldDecomposer::readFields ( cloudI, @@ -687,6 +686,19 @@ int main(int argc, char *argv[]) ) ); + labelIOList faceProcAddressing + ( + IOobject + ( + "faceProcAddressing", + procMesh.facesInstance(), + procMesh.meshSubDir, + procMesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ); + labelIOList cellProcAddressing ( IOobject @@ -728,19 +740,6 @@ int main(int argc, char *argv[]) || surfaceTensorFields.size() ) { - labelIOList faceProcAddressing - ( - IOobject - ( - "faceProcAddressing", - procMesh.facesInstance(), - procMesh.meshSubDir, - procMesh, - IOobject::MUST_READ, - IOobject::NO_WRITE - ) - ); - fvFieldDecomposer fieldDecomposer ( mesh, @@ -814,6 +813,7 @@ int main(int argc, char *argv[]) ( mesh, procMesh, + faceProcAddressing, cellProcAddressing, cloudDirs[cloudI], lagrangianPositions[cloudI], diff --git a/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposer.C b/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposer.C index 234565fb488..efe0c37ff6f 100644 --- a/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposer.C +++ b/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposer.C @@ -35,6 +35,7 @@ Foam::lagrangianFieldDecomposer::lagrangianFieldDecomposer ( const polyMesh& mesh, const polyMesh& procMesh, + const labelList& faceProcAddressing, const labelList& cellProcAddressing, const word& cloudName, const Cloud<indexedParticle>& lagrangianPositions, @@ -47,6 +48,14 @@ Foam::lagrangianFieldDecomposer::lagrangianFieldDecomposer { label pi = 0; + // faceProcAddressing not required currently + // labelList decodedProcFaceAddressing(faceProcAddressing.size()); + + // forAll(faceProcAddressing, i) + // { + // decodedProcFaceAddressing[i] = mag(faceProcAddressing[i]) - 1; + // } + forAll(cellProcAddressing, procCelli) { label celli = cellProcAddressing[procCelli]; @@ -60,6 +69,33 @@ Foam::lagrangianFieldDecomposer::lagrangianFieldDecomposer const indexedParticle& ppi = *iter(); particleIndices_[pi++] = ppi.index(); + // label mappedTetFace = findIndex + // ( + // decodedProcFaceAddressing, + // ppi.tetFace() + // ); + + // if (mappedTetFace == -1) + // { + // FatalErrorIn + // ( + // "Foam::lagrangianFieldDecomposer" + // "::lagrangianFieldDecomposer" + // "(" + // "const polyMesh& mesh, " + // "const polyMesh& procMesh, " + // "const labelList& faceProcAddressing, " + // "const labelList& cellProcAddressing, " + // "const word& cloudName, " + // "const Cloud<indexedParticle>& " + // "lagrangianPositions, " + // "const List<SLList<indexedParticle*>*>& " + // "cellParticles" + // ")" + // ) << "Face lookup failure." << nl + // << abort(FatalError); + // } + positions_.append ( new passiveParticle diff --git a/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposer.H b/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposer.H index bc0d42c5ed8..dafd94c3430 100644 --- a/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposer.H +++ b/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposer.H @@ -84,6 +84,7 @@ public: ( const polyMesh& mesh, const polyMesh& procMesh, + const labelList& faceProcAddressing, const labelList& cellProcAddressing, const word& cloudName, const Cloud<indexedParticle>& lagrangianPositions, diff --git a/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposerDecomposeFields.C b/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposerDecomposeFields.C index 00c025c953d..7e42907fd0d 100644 --- a/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposerDecomposeFields.C +++ b/applications/utilities/parallelProcessing/decomposePar/lagrangianFieldDecomposerDecomposeFields.C @@ -51,7 +51,7 @@ void Foam::lagrangianFieldDecomposer::readFields ) ); - label lagrangianFieldi=0; + label lagrangianFieldi = 0; forAllIter(IOobjectList, lagrangianTypeObjects, iter) { lagrangianFields[cloudI].set @@ -91,7 +91,7 @@ void Foam::lagrangianFieldDecomposer::readFieldFields ) ); - label lagrangianFieldi=0; + label lagrangianFieldi = 0; forAllIter(IOobjectList, lagrangianTypeObjectsA, iter) { diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options index 01bd39cf760..5d00838fdcd 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options @@ -1,10 +1,12 @@ EXE_INC = \ /* -DFULLDEBUG -g -O0 */ \ -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude EXE_LIBS = \ -lfiniteVolume \ + -lmeshTools \ -lgenericPatchFields \ -llagrangian diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/options b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/options index 9243ffdb03d..40a58886bfc 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/options +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/options @@ -1,10 +1,12 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude \ -I$(LIB_SRC)/conversion/lnInclude EXE_LIBS = \ -lfiniteVolume \ -llagrangian \ + -lmeshTools \ -lgenericPatchFields \ -lconversion diff --git a/applications/utilities/postProcessing/dataConversion/foamToFieldview9/Make/options b/applications/utilities/postProcessing/dataConversion/foamToFieldview9/Make/options index a61c912ba0c..0bc784e4c51 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToFieldview9/Make/options +++ b/applications/utilities/postProcessing/dataConversion/foamToFieldview9/Make/options @@ -1,8 +1,10 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude EXE_LIBS = \ -lfiniteVolume \ + -lmeshTools \ -lgenericPatchFields \ -llagrangian diff --git a/applications/utilities/postProcessing/dataConversion/foamToGMV/Make/options b/applications/utilities/postProcessing/dataConversion/foamToGMV/Make/options index e09f6bdc7f1..5664dc4494e 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToGMV/Make/options +++ b/applications/utilities/postProcessing/dataConversion/foamToGMV/Make/options @@ -1,6 +1,7 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/sampling/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/turbulenceModels/incompressible/lnInclude \ -I$(LIB_SRC)/transportModels/incompressible/lnInclude \ -I$(LIB_SRC)/lagrangian/lnInclude \ @@ -14,5 +15,6 @@ EXE_INC = \ EXE_LIBS = \ -lfiniteVolume \ + -lmeshTools \ -lgenericPatchFields \ -llagrangian diff --git a/applications/utilities/postProcessing/graphics/ensightFoamReader/Make/options b/applications/utilities/postProcessing/graphics/ensightFoamReader/Make/options index 8d21a9eae4b..0d76f0304cb 100644 --- a/applications/utilities/postProcessing/graphics/ensightFoamReader/Make/options +++ b/applications/utilities/postProcessing/graphics/ensightFoamReader/Make/options @@ -1,5 +1,6 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/browser/lnInclude \ -I$(LIB_SRC)/sampling/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude @@ -7,6 +8,7 @@ EXE_INC = \ LIB_LIBS = \ -lOpenFOAM \ -lfiniteVolume \ + -lmeshTools \ -lgenericPatchFields \ -llagrangian \ $(PROJECT_LIBS) diff --git a/applications/utilities/postProcessing/lagrangian/particleTracks/Make/options b/applications/utilities/postProcessing/lagrangian/particleTracks/Make/options index a61c912ba0c..0bc784e4c51 100644 --- a/applications/utilities/postProcessing/lagrangian/particleTracks/Make/options +++ b/applications/utilities/postProcessing/lagrangian/particleTracks/Make/options @@ -1,8 +1,10 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude EXE_LIBS = \ -lfiniteVolume \ + -lmeshTools \ -lgenericPatchFields \ -llagrangian diff --git a/applications/utilities/preProcessing/dsmcInitialise/Make/options b/applications/utilities/preProcessing/dsmcInitialise/Make/options index bc99834af6e..62520c19b0e 100644 --- a/applications/utilities/preProcessing/dsmcInitialise/Make/options +++ b/applications/utilities/preProcessing/dsmcInitialise/Make/options @@ -9,4 +9,3 @@ EXE_LIBS = \ -lfiniteVolume \ -llagrangian \ -ldsmc - diff --git a/applications/utilities/preProcessing/mapFields/MapLagrangianFields.H b/applications/utilities/preProcessing/mapFields/MapLagrangianFields.H index 3b9960408c4..87b3746484a 100644 --- a/applications/utilities/preProcessing/mapFields/MapLagrangianFields.H +++ b/applications/utilities/preProcessing/mapFields/MapLagrangianFields.H @@ -37,6 +37,7 @@ Description #include "GeometricField.H" #include "meshToMesh.H" #include "IOobjectList.H" +#include "IOFieldField.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -56,37 +57,118 @@ void MapLagrangianFields { const fvMesh& meshTarget = meshToMeshInterp.toMesh(); - IOobjectList fields = objects.lookupClass(IOField<Type>::typeName); - - forAllIter(IOobjectList, fields, fieldIter) { - Info<< " mapping lagrangian field " << fieldIter()->name() << endl; + IOobjectList fields = objects.lookupClass(IOField<Type>::typeName); + + forAllIter(IOobjectList, fields, fieldIter) + { + Info<< " mapping lagrangian field " + << fieldIter()->name() << endl; - // Read field (does not need mesh) - IOField<Type> fieldSource(*fieldIter()); + // Read field (does not need mesh) + IOField<Type> fieldSource(*fieldIter()); - // Map - IOField<Type> fieldTarget - ( - IOobject + // Map + IOField<Type> fieldTarget ( - fieldIter()->name(), - meshTarget.time().timeName(), - cloud::prefix/cloudName, - meshTarget, - IOobject::NO_READ, - IOobject::NO_WRITE, - false - ), - addParticles.size() - ); - forAll(addParticles, i) + IOobject + ( + fieldIter()->name(), + meshTarget.time().timeName(), + cloud::prefix/cloudName, + meshTarget, + IOobject::NO_READ, + IOobject::NO_WRITE, + false + ), + addParticles.size() + ); + + forAll(addParticles, i) + { + fieldTarget[i] = fieldSource[addParticles[i]]; + } + + // Write field + fieldTarget.write(); + } + } + + { + IOobjectList fieldFields = + objects.lookupClass(IOField<Field<Type> >::typeName); + + forAllIter(IOobjectList, fieldFields, fieldIter) { - fieldTarget[i] = fieldSource[addParticles[i]]; + Info<< " mapping lagrangian fieldField " + << fieldIter()->name() << endl; + + // Read field (does not need mesh) + IOField<Field<Type> > fieldSource(*fieldIter()); + + // Map - use IOFieldField to automatically write in + // compact form for binary format. + IOFieldField<Field<Type>, Type> fieldTarget + ( + IOobject + ( + fieldIter()->name(), + meshTarget.time().timeName(), + cloud::prefix/cloudName, + meshTarget, + IOobject::NO_READ, + IOobject::NO_WRITE, + false + ), + addParticles.size() + ); + + forAll(addParticles, i) + { + fieldTarget[i] = fieldSource[addParticles[i]]; + } + + // Write field + fieldTarget.write(); } + } - // Write field - fieldTarget.write(); + { + IOobjectList fieldFields = + objects.lookupClass(IOFieldField<Field<Type>, Type>::typeName); + + forAllIter(IOobjectList, fieldFields, fieldIter) + { + Info<< " mapping lagrangian fieldField " + << fieldIter()->name() << endl; + + // Read field (does not need mesh) + IOFieldField<Field<Type>, Type> fieldSource(*fieldIter()); + + // Map + IOFieldField<Field<Type>, Type> fieldTarget + ( + IOobject + ( + fieldIter()->name(), + meshTarget.time().timeName(), + cloud::prefix/cloudName, + meshTarget, + IOobject::NO_READ, + IOobject::NO_WRITE, + false + ), + addParticles.size() + ); + + forAll(addParticles, i) + { + fieldTarget[i] = fieldSource[addParticles[i]]; + } + + // Write field + fieldTarget.write(); + } } } diff --git a/applications/utilities/preProcessing/mapFields/mapLagrangian.C b/applications/utilities/preProcessing/mapFields/mapLagrangian.C index 72e402b934c..17f03ea3403 100644 --- a/applications/utilities/preProcessing/mapFields/mapLagrangian.C +++ b/applications/utilities/preProcessing/mapFields/mapLagrangian.C @@ -38,12 +38,13 @@ static const scalar perturbFactor = 1E-6; // Special version of findCell that generates a cell guaranteed to be // compatible with tracking. -static label findCell(const meshSearch& meshSearcher, const point& pt) +static label findCell(const Cloud<passiveParticle>& cloud, const point& pt) { - const polyMesh& mesh = meshSearcher.mesh(); + label cellI = -1; + label tetFaceI = -1; + label tetPtI = -1; - // Use tracking to find cell containing pt - label cellI = meshSearcher.findCell(pt); + cloud.findCellFacePt(pt, cellI, tetFaceI, tetPtI); if (cellI >= 0) { @@ -54,16 +55,24 @@ static label findCell(const meshSearch& meshSearcher, const point& pt) // See if particle on face by finding nearest face and shifting // particle. + const polyMesh& mesh = cloud.pMesh(); + + meshSearch meshSearcher(mesh, false); + label faceI = meshSearcher.findNearestBoundaryFace(pt); if (faceI >= 0) { const point& cc = mesh.cellCentres()[mesh.faceOwner()[faceI]]; + const point perturbPt = (1-perturbFactor)*pt+perturbFactor*cc; - return meshSearcher.findCell(perturbPt); + cloud.findCellFacePt(perturbPt, cellI, tetFaceI, tetPtI); + + return cellI; } } + return -1; } @@ -207,8 +216,6 @@ void mapLagrangian(const meshToMesh& meshToMeshInterp) if (unmappedSource.size()) { - meshSearch targetSearcher(meshTarget, false); - sourceParticleI = 0; forAllIter(Cloud<passiveParticle>, sourceParcels, iter) @@ -216,7 +223,7 @@ void mapLagrangian(const meshToMesh& meshToMeshInterp) if (unmappedSource.found(sourceParticleI)) { label targetCell = - findCell(targetSearcher, iter().position()); + findCell(targetParcels, iter().position()); if (targetCell >= 0) { diff --git a/applications/utilities/surface/surfaceSubset/surfaceSubset.C b/applications/utilities/surface/surfaceSubset/surfaceSubset.C index 51255242ef9..6bc54d40add 100644 --- a/applications/utilities/surface/surfaceSubset/surfaceSubset.C +++ b/applications/utilities/surface/surfaceSubset/surfaceSubset.C @@ -35,7 +35,6 @@ Description #include "IOdictionary.H" #include "boundBox.H" #include "indexedOctree.H" -#include "octree.H" #include "treeDataTriSurface.H" #include "Random.H" diff --git a/etc/controlDict b/etc/controlDict index 3d5aff59304..691e9701243 100644 --- a/etc/controlDict +++ b/etc/controlDict @@ -780,6 +780,7 @@ DebugSwitches syringePressure 0; tensorAverageField 0; tensorField 0; + tetDecomposedPolyMesh 0; thermoCloud 0; thermophysicalFunction 0; time 0; diff --git a/src/Allwmake b/src/Allwmake index 33966ddb97b..43458cfc621 100755 --- a/src/Allwmake +++ b/src/Allwmake @@ -20,8 +20,6 @@ Pstream/Allwmake OSspecific/$WM_OSTYPE/Allwmake wmake libso OpenFOAM -wmake libso lagrangian/basic - wmake libso fileFormats wmake libso edgeMesh wmake libso surfMesh @@ -33,6 +31,7 @@ parallel/decompose/AllwmakeLnInclude dummyThirdParty/Allwmake wmake libso meshTools +wmake libso lagrangian/basic wmake libso finiteVolume wmake libso genericPatchFields diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index e9103f8020e..599d30fa094 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -365,6 +365,8 @@ $(globalMeshData)/globalPoints.C $(globalMeshData)/globalIndex.C $(polyMesh)/syncTools/syncTools.C +$(polyMesh)/polyMeshTetDecomposition/polyMeshTetDecomposition.C +$(polyMesh)/polyMeshTetDecomposition/tetIndices.C zone = $(polyMesh)/zones/zone $(zone)/zone.C diff --git a/src/OpenFOAM/meshes/polyMesh/polyMesh.C b/src/OpenFOAM/meshes/polyMesh/polyMesh.C index 2cbde73f8b3..668320e1d6d 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyMesh.C +++ b/src/OpenFOAM/meshes/polyMesh/polyMesh.C @@ -33,6 +33,7 @@ License #include "processorPolyPatch.H" #include "OSspecific.H" #include "demandDrivenData.H" +#include "polyMeshTetDecomposition.H" #include "pointMesh.H" @@ -204,6 +205,7 @@ Foam::polyMesh::polyMesh(const IOobject& io) bounds_(points_), geometricD_(Vector<label>::zero), solutionD_(Vector<label>::zero), + tetBasePtIsPtr_(NULL), pointZones_ ( IOobject @@ -392,6 +394,7 @@ Foam::polyMesh::polyMesh bounds_(points_, syncPar), geometricD_(Vector<label>::zero), solutionD_(Vector<label>::zero), + tetBasePtIsPtr_(NULL), pointZones_ ( IOobject @@ -548,6 +551,7 @@ Foam::polyMesh::polyMesh bounds_(points_, syncPar), geometricD_(Vector<label>::zero), solutionD_(Vector<label>::zero), + tetBasePtIsPtr_(NULL), pointZones_ ( IOobject @@ -847,6 +851,28 @@ Foam::label Foam::polyMesh::nSolutionD() const } +const Foam::labelList& Foam::polyMesh::tetBasePtIs() const +{ + if (!tetBasePtIsPtr_) + { + if (debug) + { + WarningIn("const labelList& polyMesh::tetBasePtIs() const") + << "Tet base point indices not available. " + << "Forcing storage of base points." + << endl; + } + + tetBasePtIsPtr_ = new labelList + ( + polyMeshTetDecomposition::findFaceBasePts(*this) + ); + } + + return *tetBasePtIsPtr_; +} + + // Add boundary patches. Constructor helper void Foam::polyMesh::addPatches ( diff --git a/src/OpenFOAM/meshes/polyMesh/polyMesh.H b/src/OpenFOAM/meshes/polyMesh/polyMesh.H index ec57faa9fbd..a100a358e15 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyMesh.H +++ b/src/OpenFOAM/meshes/polyMesh/polyMesh.H @@ -62,6 +62,7 @@ namespace Foam class globalMeshData; class mapPolyMesh; +class polyMeshTetDecomposition; /*---------------------------------------------------------------------------*\ Class polyMesh Declaration @@ -127,6 +128,9 @@ private: // defined according to the presence of empty patches mutable Vector<label> solutionD_; + //- Base point for face decomposition into tets + mutable labelList* tetBasePtIsPtr_; + // Zoning information @@ -356,6 +360,9 @@ public: //- Return the number of valid solved-for dimensions in the mesh label nSolutionD() const; + //- Return the tetBasePtIs + const labelList& tetBasePtIs() const; + //- Return point zone mesh const pointZoneMesh& pointZones() const { diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshClear.C b/src/OpenFOAM/meshes/polyMesh/polyMeshClear.C index 187d3c128fa..56c2f2428cd 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyMeshClear.C +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshClear.C @@ -71,6 +71,9 @@ void Foam::polyMesh::clearGeom() geometricD_ = Vector<label>::zero; solutionD_ = Vector<label>::zero; + // Remove the stored tet base points + deleteDemandDrivenData(tetBasePtIsPtr_); + pointMesh::Delete(*this); } diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshFromShapeMesh.C b/src/OpenFOAM/meshes/polyMesh/polyMeshFromShapeMesh.C index 0f35692b0ce..73434502f45 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyMeshFromShapeMesh.C +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshFromShapeMesh.C @@ -503,6 +503,7 @@ Foam::polyMesh::polyMesh bounds_(points_, syncPar), geometricD_(Vector<label>::zero), solutionD_(Vector<label>::zero), + tetBasePtIsPtr_(NULL), pointZones_ ( IOobject @@ -775,6 +776,7 @@ Foam::polyMesh::polyMesh bounds_(points_, syncPar), geometricD_(Vector<label>::zero), solutionD_(Vector<label>::zero), + tetBasePtIsPtr_(NULL), pointZones_ ( IOobject diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.C b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.C new file mode 100644 index 00000000000..23e7a3c52e2 --- /dev/null +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.C @@ -0,0 +1,627 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 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 "polyMeshTetDecomposition.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const Foam::scalar Foam::polyMeshTetDecomposition::minTetQuality = 1e-9; + + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +Foam::label Foam::polyMeshTetDecomposition::findSharedBasePoint +( + const polyMesh& mesh, + label fI, + const point& nCc, + scalar tol, + bool report +) +{ + const faceList& pFaces = mesh.faces(); + const pointField& pPts = mesh.points(); + const vectorField& pC = mesh.cellCentres(); + const labelList& pOwner = mesh.faceOwner(); + + const face& f = pFaces[fI]; + + label oCI = pOwner[fI]; + + const point& oCc = pC[oCI]; + + forAll(f, faceBasePtI) + { + scalar thisBaseMinTetQuality = VGREAT; + + const point& tetBasePt = pPts[f[faceBasePtI]]; + + for (label tetPtI = 1; tetPtI < f.size() - 1; tetPtI++) + { + label facePtI = (tetPtI + faceBasePtI) % f.size(); + label otherFacePtI = f.fcIndex(facePtI); + + List<scalar> tetQualities(2, 0.0); + + { + // owner cell tet + label ptAI = f[facePtI]; + label ptBI = f[otherFacePtI]; + + const point& pA = pPts[ptAI]; + const point& pB = pPts[ptBI]; + + tetPointRef tet(oCc, tetBasePt, pA, pB); + + tetQualities[0] = tet.quality(); + } + + { + // neighbour cell tet + label ptAI = f[otherFacePtI]; + label ptBI = f[facePtI]; + + const point& pA = pPts[ptAI]; + const point& pB = pPts[ptBI]; + + tetPointRef tet(nCc, tetBasePt, pA, pB); + + tetQualities[1] = tet.quality(); + } + + if (min(tetQualities) < thisBaseMinTetQuality) + { + thisBaseMinTetQuality = min(tetQualities); + } + } + + if (thisBaseMinTetQuality > tol) + { + return faceBasePtI; + } + + } + + // If a base point hasn't triggered a return by now, then there is + // non that can produce a good decomposition + return -1; +} + + +Foam::label Foam::polyMeshTetDecomposition::findSharedBasePoint +( + const polyMesh& mesh, + label fI, + scalar tol, + bool report +) +{ + return findSharedBasePoint + ( + mesh, + fI, + mesh.cellCentres()[mesh.faceNeighbour()[fI]], + tol, + report + ); +} + + +Foam::label Foam::polyMeshTetDecomposition::findBasePoint +( + const polyMesh& mesh, + label fI, + scalar tol, + bool report +) +{ + const faceList& pFaces = mesh.faces(); + const pointField& pPts = mesh.points(); + const vectorField& pC = mesh.cellCentres(); + const labelList& pOwner = mesh.faceOwner(); + + const face& f = pFaces[fI]; + + label cI = pOwner[fI]; + + bool own = (pOwner[fI] == cI); + + const point& cC = pC[cI]; + + forAll(f, faceBasePtI) + { + scalar thisBaseMinTetQuality = VGREAT; + + const point& tetBasePt = pPts[f[faceBasePtI]]; + + for (label tetPtI = 1; tetPtI < f.size() - 1; tetPtI++) + { + label facePtI = (tetPtI + faceBasePtI) % f.size(); + label otherFacePtI = f.fcIndex(facePtI); + + label ptAI = -1; + label ptBI = -1; + + if (own) + { + ptAI = f[facePtI]; + ptBI = f[otherFacePtI]; + } + else + { + ptAI = f[otherFacePtI]; + ptBI = f[facePtI]; + } + + const point& pA = pPts[ptAI]; + const point& pB = pPts[ptBI]; + + tetPointRef tet(cC, tetBasePt, pA, pB); + + scalar tetQuality = tet.quality(); + + if (tetQuality < thisBaseMinTetQuality) + { + thisBaseMinTetQuality = tetQuality; + } + } + + if (thisBaseMinTetQuality > tol) + { + return faceBasePtI; + } + } + + // If a base point hasn't triggered a return by now, then there is + // non that can produce a good decomposition + return -1; +} + + +Foam::labelList Foam::polyMeshTetDecomposition::findFaceBasePts +( + const polyMesh& mesh, + scalar tol, + bool report +) +{ + const labelList& pOwner = mesh.faceOwner(); + + // Find a suitable base point for each face, considering both + // cells for interface faces or those on coupled patches + + labelList tetBasePtIs(mesh.nFaces(), -1); + + label nInternalFaces = mesh.nInternalFaces(); + + for (label fI = 0; fI < nInternalFaces; fI++) + { + tetBasePtIs[fI] = findSharedBasePoint(mesh, fI, tol, report); + } + + pointField neighbourCellCentres(mesh.nFaces() - nInternalFaces); + + for(label faceI = nInternalFaces; faceI < mesh.nFaces(); faceI++) + { + neighbourCellCentres[faceI - nInternalFaces] = + mesh.cellCentres()[pOwner[faceI]]; + } + + syncTools::swapBoundaryFacePositions(mesh, neighbourCellCentres); + + const polyBoundaryMesh& patches = mesh.boundaryMesh(); + + SubList<label> boundaryFaceTetBasePtIs + ( + tetBasePtIs, + mesh.nFaces() - nInternalFaces, + nInternalFaces + ); + + for + ( + label fI = nInternalFaces, bFI = 0; + fI < mesh.nFaces(); + fI++, bFI++ + ) + { + label patchI = + mesh.boundaryMesh().patchID()[bFI]; + + if (patches[patchI].coupled()) + { + const coupledPolyPatch& pp = + refCast<const coupledPolyPatch>(patches[patchI]); + + if (pp.owner()) + { + boundaryFaceTetBasePtIs[bFI] = findSharedBasePoint + ( + mesh, + fI, + neighbourCellCentres[bFI], + tol, + report + ); + } + else + { + // Assign -2, to distinguish from a failed base point + // find, which returns -1. + boundaryFaceTetBasePtIs[bFI] = -2; + } + } + else + { + boundaryFaceTetBasePtIs[bFI] = findBasePoint + ( + mesh, + fI, + tol, + report + ); + } + } + + // maxEqOp will replace the -2 values on the neighbour patches + // with the result from the owner base point find. + + syncTools::syncBoundaryFaceList + ( + mesh, + boundaryFaceTetBasePtIs, + maxEqOp<label>() + ); + + for + ( + label fI = nInternalFaces, bFI = 0; + fI < mesh.nFaces(); + fI++, bFI++ + ) + { + label& bFTetBasePtI = boundaryFaceTetBasePtIs[bFI]; + + if (bFTetBasePtI == -2) + { + FatalErrorIn + ( + "Foam::labelList" + "Foam::polyMeshTetDecomposition::findFaceBasePts" + "(" + "const polyMesh& mesh, " + "scalar tol, " + "bool report" + ")" + ) + << "Coupled face base point exchange failure for face " + << fI + << abort(FatalError); + } + + if (bFTetBasePtI < 1) + { + // If the base point is -1, it should be left as such to + // indicate a problem, if it is 0, then no action is required. + + continue; + } + + label patchI = mesh.boundaryMesh().patchID()[bFI]; + + if (patches[patchI].coupled()) + { + const coupledPolyPatch& pp = + refCast<const coupledPolyPatch>(patches[patchI]); + + // Calculated base points on coupled faces are those of + // the owner patch face. They need to be reindexed to for + // the non-owner face, which has the opposite order. + + // So, for fPtI_o != 0, fPtI_n = f.size() - fPtI_o + + // i.e.: + + // owner coupledPolyPatch face + // face (a b c d e f) + // fPtI 0 1 2 3 4 5 + // + + // # + + // neighbour coupledPolyPatch face + // face (a f e d c b) + // fPtI 0 1 2 3 4 5 + // + + // # + // +: 6 - 1 = 5 + // #: 6 - 2 = 4 + + if (!pp.owner()) + { + bFTetBasePtI = mesh.faces()[fI].size() - bFTetBasePtI; + } + } + } + + return tetBasePtIs; +} + + +bool Foam::polyMeshTetDecomposition::checkFaceTets +( + const polyMesh& mesh, + scalar tol, + const bool report, + labelHashSet* setPtr +) +{ + const labelList& own = mesh.faceOwner(); + const labelList& nei = mesh.faceNeighbour(); + const polyBoundaryMesh& patches = mesh.boundaryMesh(); + + const vectorField& cc = mesh.cellCentres(); + const vectorField& fc = mesh.faceCentres(); + + // Calculate coupled cell centre + pointField neiCc(mesh.nFaces() - mesh.nInternalFaces()); + + for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++) + { + neiCc[faceI - mesh.nInternalFaces()] = cc[own[faceI]]; + } + + syncTools::swapBoundaryFacePositions(mesh, neiCc); + + const faceList& fcs = mesh.faces(); + + const pointField& p = mesh.points(); + + label nErrorTets = 0; + + forAll(fcs, faceI) + { + const face& f = fcs[faceI]; + + forAll(f, fPtI) + { + scalar tetQual = tetPointRef + ( + p[f[fPtI]], + p[f.nextLabel(fPtI)], + fc[faceI], + cc[own[faceI]] + ).quality(); + + if (tetQual > -tol) + { + if (setPtr) + { + setPtr->insert(faceI); + } + + nErrorTets++; + break; // no need to check other tets + } + } + + if (mesh.isInternalFace(faceI)) + { + // Create the neighbour tet - it will have positive volume + const face& f = fcs[faceI]; + + forAll(f, fPtI) + { + scalar tetQual = tetPointRef + ( + p[f[fPtI]], + p[f.nextLabel(fPtI)], + fc[faceI], + cc[nei[faceI]] + ).quality(); + + if (tetQual < tol) + { + if (setPtr) + { + setPtr->insert(faceI); + } + + nErrorTets++; + break; + } + } + + if (findSharedBasePoint(mesh, faceI, tol, report) == -1) + { + if (setPtr) + { + setPtr->insert(faceI); + } + + nErrorTets++; + } + } + else + { + label patchI = patches.patchID()[faceI - mesh.nInternalFaces()]; + + if (patches[patchI].coupled()) + { + if + ( + findSharedBasePoint + ( + mesh, + faceI, + neiCc[faceI - mesh.nInternalFaces()], + tol, + report + ) == -1 + ) + { + if (setPtr) + { + setPtr->insert(faceI); + } + + nErrorTets++; + } + } + else + { + if (findBasePoint(mesh, faceI, tol, report) == -1) + { + if (setPtr) + { + setPtr->insert(faceI); + } + + nErrorTets++; + } + } + } + } + + reduce(nErrorTets, sumOp<label>()); + + if (nErrorTets > 0) + { + if (report) + { + Info<< " ***Error in face tets: " + << nErrorTets << " faces with low quality or negative volume " + << "decomposition tets." << endl; + } + + return true; + } + else + { + if (report) + { + Info<< " Face tets OK." << endl; + } + + return false; + } +} + + +Foam::List<Foam::tetIndices> Foam::polyMeshTetDecomposition::faceTetIndices +( + const polyMesh& mesh, + label fI, + label cI +) +{ + const faceList& pFaces = mesh.faces(); + const labelList& pOwner = mesh.faceOwner(); + + const face& f = pFaces[fI]; + + label nTets = f.size() - 2; + + List<tetIndices> faceTets(nTets); + + bool own = (pOwner[fI] == cI); + + label tetBasePtI = mesh.tetBasePtIs()[fI]; + + if (tetBasePtI == -1) + { + FatalErrorIn + ( + "Foam::List<Foam::FixedList<Foam::label, 4> >" + "Foam::Cloud<ParticleType>::" + "faceTetIndices(label fI, label cI) const" + ) + << "No base point for face " << fI << ", " << f + << ", produces a valid tet decomposition." + << abort(FatalError); + } + + for (label tetPtI = 1; tetPtI < f.size() - 1; tetPtI++) + { + tetIndices& faceTetIs = faceTets[tetPtI - 1]; + + label facePtI = (tetPtI + tetBasePtI) % f.size(); + label otherFacePtI = f.fcIndex(facePtI); + + faceTetIs.cell() = cI; + + faceTetIs.face() = fI; + + faceTetIs.faceBasePt() = tetBasePtI; + + if (own) + { + faceTetIs.facePtA() = facePtI; + faceTetIs.facePtB() = otherFacePtI; + } + else + { + faceTetIs.facePtA() = otherFacePtI; + faceTetIs.facePtB() = facePtI; + } + + faceTetIs.tetPt() = tetPtI; + } + + return faceTets; +} + + +Foam::List<Foam::tetIndices> Foam::polyMeshTetDecomposition::cellTetIndices +( + const polyMesh& mesh, + label cI +) +{ + const faceList& pFaces = mesh.faces(); + const cellList& pCells = mesh.cells(); + + const cell& thisCell = pCells[cI]; + + label nTets = 0; + + forAll(thisCell, cFI) + { + nTets += pFaces[thisCell[cFI]].size() - 2; + } + + DynamicList<tetIndices> cellTets(nTets); + + forAll(thisCell, cFI) + { + label fI = thisCell[cFI]; + + cellTets.append(faceTetIndices(mesh, fI, cI)); + } + + return cellTets; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.H b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.H new file mode 100644 index 00000000000..cf2ea5e2971 --- /dev/null +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.H @@ -0,0 +1,151 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::polyMeshTetDecomposition + +Description + Tools for performing the minimum decomposition of faces of the + mesh into triangles so that the cells may be tet decomposed. + Includes functions for finding variable face starting (base) + points on each face to avoid the decomposition of cells into tets + that have negative or zero volume. + +SourceFiles + polyMeshTetDecomposition.C + +\*---------------------------------------------------------------------------*/ + +#ifndef polyMeshTetDecomposition_H +#define polyMeshTetDecomposition_H + +#include "polyMesh.H" +#include "coupledPolyPatch.H" +#include "syncTools.H" +#include "tetPointRef.H" +#include "tetIndices.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class polyMeshTetDecomposition Declaration +\*---------------------------------------------------------------------------*/ + +class polyMeshTetDecomposition +{ + +public: + + // Static data members + + //- Minimum tetrahedron quality + static const scalar minTetQuality; + + + // Member Functions + + //- Find the first suitable base point to use for a minimum + // triangle decomposition of the face, suiting owner and + // neighbour cells. Finds the first base point on the face + // whose worst quality tet from either cell is better than + // tolerance. Neighbour cell centre supplied. For coupled + // patches. + static label findSharedBasePoint + ( + const polyMesh& mesh, + label fI, + const point& nCc, + scalar tol, + bool report = false + ); + + //- As for findSharedBasePoint, but using neighbour cell + // centre from the mesh. For internal faces. + static label findSharedBasePoint + ( + const polyMesh& mesh, + label fI, + scalar tol, + bool report = false + ); + + //- Find the base point to use for a minimum triangle + // decomposition of the face, using only the owner + // information. For non-coupled boundary faces. + static label findBasePoint + ( + const polyMesh& mesh, + label fI, + scalar tol, + bool report = false + ); + + //- Find a suitable base point for each face for decomposition + // into tets + static labelList findFaceBasePts + ( + const polyMesh& mesh, + scalar tol = minTetQuality, + bool report = false + ); + + //- Check face-decomposition tet volume + static bool checkFaceTets + ( + const polyMesh& mesh, + scalar tol = minTetQuality, + const bool report = false, + labelHashSet* setPtr = NULL + ); + + //- Return the tet decomposition of the given face, with + // respect to the given cell + static List<tetIndices> faceTetIndices + ( + const polyMesh& mesh, + label fI, + label cI + ); + + //- Return the tet decomposition of the given cell, see + // findFacePt for the meaning of the indices + static List<tetIndices> cellTetIndices + ( + const polyMesh& mesh, + label cI + ); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndices.C b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndices.C new file mode 100644 index 00000000000..163fccf49f3 --- /dev/null +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndices.C @@ -0,0 +1,148 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 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 "tetIndices.H" + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::tetIndices::tetIndices() +: + cellI_(-1), + faceI_(-1), + faceBasePtI_(-1), + facePtAI_(-1), + facePtBI_(-1), + tetPtI_(-1) +{} + + +Foam::tetIndices::tetIndices +( + label cellI, + label faceI, + label faceBasePtI, + label facePtAI, + label facePtBI, + label tetPtI +) +: + cellI_(cellI), + faceI_(faceI), + faceBasePtI_(faceBasePtI), + facePtAI_(facePtAI), + facePtBI_(facePtBI), + tetPtI_(tetPtI) +{} + + +Foam::tetIndices::tetIndices +( + label cellI, + label faceI, + label tetPtI, + const polyMesh& mesh +) +: + cellI_(cellI), + faceI_(faceI), + faceBasePtI_(-1), + facePtAI_(-1), + facePtBI_(-1), + tetPtI_(tetPtI) +{ + const faceList& pFaces = mesh.faces(); + const labelList& pOwner = mesh.faceOwner(); + + const Foam::face& f = pFaces[faceI_]; + + bool own = (pOwner[faceI_] == cellI_); + + faceBasePtI_ = mesh.tetBasePtIs()[faceI_]; + + label facePtI = (tetPtI_ + faceBasePtI_) % f.size(); + label otherFacePtI = f.fcIndex(facePtI); + + if (own) + { + facePtAI_ = facePtI; + facePtBI_ = otherFacePtI; + } + else + { + facePtAI_ = otherFacePtI; + facePtBI_ = facePtI; + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::tetIndices::~tetIndices() +{} + + +// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // + +Foam::Istream& Foam::operator>>(Istream& is, tetIndices& tI) +{ + is >> tI.cell() + >> tI.face() + >> tI.faceBasePt() + >> tI.facePtA() + >> tI.facePtB() + >> tI.tetPt(); + + // Check state of Istream + is.check + ( + "Foam::Istream& Foam::operator>>(Foam::Istream&, Foam::tetIndices&)" + ); + + return is; +} + + +Foam::Ostream& Foam::operator<<(Ostream& os, const tetIndices& tI) +{ + os << tI.cell() << token::SPACE + << tI.face() << token::SPACE + << tI.faceBasePt() << token::SPACE + << tI.facePtA() << token::SPACE + << tI.facePtB() << token::SPACE + << tI.tetPt() << token::SPACE + << endl; + + // Check state of Ostream + os.check + ( + "Foam::Ostream& Foam::operator<<(Foam::Ostream&, " + "const Foam::tetIndices&)" + ); + + return os; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndices.H b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndices.H new file mode 100644 index 00000000000..3e5ee425d6e --- /dev/null +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndices.H @@ -0,0 +1,201 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::tetIndices + +Description + Storage and named access for the indices of a tet which is part of + the decomposition of a cell. + +SourceFiles + tetIndicesI.H + tetIndices.C + +\*---------------------------------------------------------------------------*/ + +#ifndef tetIndices_H +#define tetIndices_H + +#include "label.H" +#include "tetPointRef.H" +#include "triPointRef.H" +#include "polyMesh.H" +#include "face.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class tetIndices Declaration +\*---------------------------------------------------------------------------*/ + +class tetIndices +{ + // Private data + + //- cell that this is a decomposed tet of + label cellI_; + + //- face that holds this decomposed tet + label faceI_; + + //- base point on the face + label faceBasePtI_; + + //- point on the face such that the right-hand circulation + // {faceBasePtI_, facePtIA_, facePtBI_} + // forms a triangle that points out of the tet + label facePtAI_; + + //- point on the face such that the right-hand circulation + // {faceBasePtI_, facePtIA_, facePtBI_} + // forms a triangle that points out of the tet + label facePtBI_; + + //- point on the face, *relative to the base point*, which + // characterises this tet on the face. + label tetPtI_; + + +public: + + // Constructors + + //- Construct null + tetIndices(); + + //- Construct from components + tetIndices + ( + label cellI, + label faceI, + label faceBasePtI, + label facePtAI, + label facePtBI, + label tetPtI + ); + + //- Construct from cell, face, pt description of tet + tetIndices + ( + label cellI, + label faceI, + label tetPtI, + const polyMesh& mesh + ); + + + //- Destructor + ~tetIndices(); + + + // Member Functions + + // Access + + //- Return the cell + inline label cell() const; + + //- Return the face + inline label face() const; + + //- Return the face base point + inline label faceBasePt() const; + + //- Return face point A + inline label facePtA() const; + + //- Return face point B + inline label facePtB() const; + + //- Return the characterising tetPtI + inline label tetPt() const; + + //- Return the geometry corresponding to this tet from the + // supplied mesh + inline tetPointRef tet(const polyMesh& mesh) const; + + //- Return the geometry corresponding to this tet from the + // supplied mesh using the old positions + inline tetPointRef oldTet(const polyMesh& mesh) const; + + //- Return the geometry corresponding to the tri on the + // mesh face for this tet from the supplied mesh + inline triPointRef faceTri(const polyMesh& mesh) const; + + //- Return the geometry corresponding to the tri on the + // mesh face for this tet from the supplied mesh using + // the old position + inline triPointRef oldFaceTri(const polyMesh& mesh) const; + + + // Edit + + //- Return non-const access to the cell + inline label& cell(); + + //- Return non-const access to the face + inline label& face(); + + //- Return non-const access to the face base point + inline label& faceBasePt(); + + //- Return non-const access to face point A + inline label& facePtA(); + + //- Return non-const access to face point B + inline label& facePtB(); + + //- Return non-const access to the characterising tetPtI + inline label& tetPt(); + + + // Member Operators + + inline bool operator==(const tetIndices&) const; + inline bool operator!=(const tetIndices&) const; + + + // IOstream Operators + + friend Istream& operator>>(Istream&, tetIndices&); + friend Ostream& operator<<(Ostream&, const tetIndices&); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "tetIndicesI.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndicesI.H b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndicesI.H new file mode 100644 index 00000000000..6b8a7871a04 --- /dev/null +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndicesI.H @@ -0,0 +1,202 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 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/>. + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::label Foam::tetIndices::cell() const +{ + return cellI_; +} + + +Foam::label Foam::tetIndices::face() const +{ + return faceI_; +} + + +Foam::label Foam::tetIndices::faceBasePt() const +{ + return faceBasePtI_; +} + + +Foam::label Foam::tetIndices::facePtA() const +{ + return facePtAI_; +} + + +Foam::label Foam::tetIndices::facePtB() const +{ + return facePtBI_; +} + + +Foam::label Foam::tetIndices::tetPt() const +{ + return tetPtI_; +} + + +Foam::tetPointRef Foam::tetIndices::tet(const polyMesh& mesh) const +{ + const pointField& pPts = mesh.points(); + const faceList& pFaces = mesh.faces(); + const vectorField& pC = mesh.cellCentres(); + + const Foam::face& f = pFaces[faceI_]; + + return tetPointRef + ( + pC[cellI_], + pPts[f[faceBasePtI_]], + pPts[f[facePtAI_]], + pPts[f[facePtBI_]] + ); +} + + +Foam::tetPointRef Foam::tetIndices::oldTet(const polyMesh& mesh) const +{ + const pointField& oldPPts = mesh.oldPoints(); + const faceList& pFaces = mesh.faces(); + + // We need to reconstruct the old Cc from oldPoints (it isn't + // stored) + point oldC = mesh.cells()[cellI_].centre + ( + oldPPts, + pFaces + ); + + const Foam::face& f = pFaces[faceI_]; + + return tetPointRef + ( + oldC, + oldPPts[f[faceBasePtI_]], + oldPPts[f[facePtAI_]], + oldPPts[f[facePtBI_]] + ); +} + + +Foam::triPointRef Foam::tetIndices::faceTri(const polyMesh& mesh) const +{ + const pointField& pPts = mesh.points(); + const faceList& pFaces = mesh.faces(); + + const Foam::face& f = pFaces[faceI_]; + + return triPointRef + ( + pPts[f[faceBasePtI_]], + pPts[f[facePtAI_]], + pPts[f[facePtBI_]] + ); +} + + +Foam::triPointRef Foam::tetIndices::oldFaceTri(const polyMesh& mesh) const +{ + const pointField& oldPPts = mesh.oldPoints(); + const faceList& pFaces = mesh.faces(); + + const Foam::face& f = pFaces[faceI_]; + + return triPointRef + ( + oldPPts[f[faceBasePtI_]], + oldPPts[f[facePtAI_]], + oldPPts[f[facePtBI_]] + ); +} + + +Foam::label& Foam::tetIndices::cell() +{ + return cellI_; +} + + +Foam::label& Foam::tetIndices::face() +{ + return faceI_; +} + + +Foam::label& Foam::tetIndices::faceBasePt() +{ + return faceBasePtI_; +} + + +Foam::label& Foam::tetIndices::facePtA() +{ + return facePtAI_; +} + + +Foam::label& Foam::tetIndices::facePtB() +{ + return facePtBI_; +} + + +Foam::label& Foam::tetIndices::tetPt() +{ + return tetPtI_; +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +inline bool Foam::tetIndices::operator==(const Foam::tetIndices& rhs) const +{ + return + ( + cell() == rhs.cell() + && face() == rhs.face() + && faceBasePt() == rhs.faceBasePt() + && facePtA() == rhs.facePtA() + && facePtB() == rhs.facePtB() + && tetPt() == rhs.tetPt() + ); +} + + +inline bool Foam::tetIndices::operator!=(const Foam::tetIndices& rhs) const +{ + return !(*this == rhs); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// ************************************************************************* // diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/processor/processorPolyPatch.H b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/processor/processorPolyPatch.H index 53aba7fd17f..bda2eb19d6c 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/processor/processorPolyPatch.H +++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/processor/processorPolyPatch.H @@ -229,6 +229,19 @@ public: // Member functions + //- Return true only if this is a parallel run + virtual bool coupled() const + { + if (Pstream::parRun()) + { + return true; + } + else + { + return false; + } + } + //- Return processor number int myProcNo() const { diff --git a/src/OpenFOAM/meshes/polyMesh/syncTools/syncToolsTemplates.C b/src/OpenFOAM/meshes/polyMesh/syncTools/syncToolsTemplates.C index 5d35b85f758..539aa1b6c6e 100644 --- a/src/OpenFOAM/meshes/polyMesh/syncTools/syncToolsTemplates.C +++ b/src/OpenFOAM/meshes/polyMesh/syncTools/syncToolsTemplates.C @@ -1223,7 +1223,7 @@ void Foam::syncTools::syncBoundaryFaceList label patchStart = procPatch.start()-mesh.nInternalFaces(); UOPstream toNbr(procPatch.neighbProcNo(), pBufs); - toNbr << + toNbr << SubField<T> ( faceValues, @@ -1423,7 +1423,7 @@ void Foam::syncTools::syncFaceList cop(t, val1); faceValues[meshFace0] = t; - cop(val1, val0); + cop(val1, val0); faceValues[meshFace1] = val1; } } @@ -1683,7 +1683,7 @@ void Foam::syncTools::syncEdgeList const processorPolyPatch& procPatch = refCast<const processorPolyPatch>(patches[patchI]); - // Receive from neighbour. + // Receive from neighbour. List<unsigned int> nbrPatchInfo(procPatch.nEdges()); { diff --git a/src/OpenFOAM/meshes/primitiveMesh/primitiveMesh.H b/src/OpenFOAM/meshes/primitiveMesh/primitiveMesh.H index efa78e3b303..61c3da9bb9f 100644 --- a/src/OpenFOAM/meshes/primitiveMesh/primitiveMesh.H +++ b/src/OpenFOAM/meshes/primitiveMesh/primitiveMesh.H @@ -66,6 +66,7 @@ SourceFiles #include "HashSet.H" #include "Map.H" #include "EdgeMap.H" +#include "boundBox.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -577,14 +578,6 @@ public: labelHashSet* setPtr = NULL ) const; - //- Check face-decomposition tet volume - bool checkFaceTets - ( - const bool report = false, - const scalar minTetVol = 0, - labelHashSet* setPtr = NULL - ) const; - //- Check face skewness bool checkFaceSkewness ( diff --git a/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck/primitiveMeshCheck.C b/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck/primitiveMeshCheck.C index 04ef5b21bb4..17b5bfd78eb 100644 --- a/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck/primitiveMeshCheck.C +++ b/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck/primitiveMeshCheck.C @@ -618,114 +618,6 @@ bool Foam::primitiveMesh::checkFacePyramids } -bool Foam::primitiveMesh::checkFaceTets -( - const bool report, - const scalar minTetVol, - labelHashSet* setPtr -) const -{ - if (debug) - { - Info<< "bool primitiveMesh::checkFaceTets(" - << "const bool, const scalar, labelHashSet*) const: " - << "checking face orientation" << endl; - } - - // check whether face area vector points to the cell with higher label - const vectorField& cc = cellCentres(); - const vectorField& fc = faceCentres(); - - const labelList& own = faceOwner(); - const labelList& nei = faceNeighbour(); - - const faceList& fcs = faces(); - - const pointField& p = points(); - - label nErrorPyrs = 0; - - forAll(fcs, faceI) - { - // Create the owner tets - they will have negative volume - const face& f = fcs[faceI]; - - forAll(f, fp) - { - scalar tetVol = tetPointRef - ( - p[f[fp]], - p[f.nextLabel(fp)], - fc[faceI], - cc[own[faceI]] - ).mag(); - - if (tetVol > -minTetVol) - { - if (setPtr) - { - setPtr->insert(faceI); - } - - nErrorPyrs++; - break; // no need to check other tets - } - } - - if (isInternalFace(faceI)) - { - // Create the neighbour tet - it will have positive volume - const face& f = fcs[faceI]; - - forAll(f, fp) - { - scalar tetVol = tetPointRef - ( - p[f[fp]], - p[f.nextLabel(fp)], - fc[faceI], - cc[nei[faceI]] - ).mag(); - - if (tetVol < minTetVol) - { - if (setPtr) - { - setPtr->insert(faceI); - } - - nErrorPyrs++; - break; - } - } - } - } - - reduce(nErrorPyrs, sumOp<label>()); - - if (nErrorPyrs > 0) - { - if (debug || report) - { - Info<< " ***Error in face tets: " - << nErrorPyrs << " faces have incorrectly oriented face" - << " decomposition triangles." << endl; - } - - return true; - } - else - { - if (debug || report) - { - Info<< " Face tets OK." << endl; - } - - return false; - } -} - - bool Foam::primitiveMesh::checkFaceSkewness ( const bool report, diff --git a/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshFindCell.C b/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshFindCell.C index 6918235551d..fecbc3c6fbd 100644 --- a/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshFindCell.C +++ b/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshFindCell.C @@ -32,32 +32,14 @@ License // Is the point in the cell bounding box bool Foam::primitiveMesh::pointInCellBB(const point& p, label celli) const { - const pointField& points = this->points(); - const faceList& f = faces(); - const vectorField& centres = cellCentres(); - const cellList& cf = cells(); - - labelList cellVertices = cf[celli].labels(f); - - vector bbmax = -GREAT*vector::one; - vector bbmin = GREAT*vector::one; - - forAll(cellVertices, vertexI) - { - bbmax = max(bbmax, points[cellVertices[vertexI]]); - bbmin = min(bbmin, points[cellVertices[vertexI]]); - } - - scalar distance = mag(centres[celli] - p); - - if ((distance - mag(bbmax - bbmin)) < SMALL) - { - return true; - } - else - { - return false; - } + return boundBox + ( + cells()[celli].points + ( + faces(), + points() + ) + ).contains(p); } diff --git a/src/OpenFOAM/meshes/primitiveShapes/tetrahedron/tetrahedron.C b/src/OpenFOAM/meshes/primitiveShapes/tetrahedron/tetrahedron.C index 2c801c1db9f..54f8168b605 100644 --- a/src/OpenFOAM/meshes/primitiveShapes/tetrahedron/tetrahedron.C +++ b/src/OpenFOAM/meshes/primitiveShapes/tetrahedron/tetrahedron.C @@ -30,7 +30,6 @@ Description #include "triPointRef.H" #include "scalarField.H" - // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // (Probably very inefficient) minimum containment sphere calculation. diff --git a/src/OpenFOAM/meshes/primitiveShapes/tetrahedron/tetrahedron.H b/src/OpenFOAM/meshes/primitiveShapes/tetrahedron/tetrahedron.H index fe036de2d23..f80ac49d406 100644 --- a/src/OpenFOAM/meshes/primitiveShapes/tetrahedron/tetrahedron.H +++ b/src/OpenFOAM/meshes/primitiveShapes/tetrahedron/tetrahedron.H @@ -42,6 +42,7 @@ SourceFiles #include "point.H" #include "primitiveFieldsFwd.H" #include "pointHit.H" +#include "Random.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -133,16 +134,42 @@ public: inline vector Sd() const; + //- Return centre (centroid) + inline Point centre() const; //- Return volume inline scalar mag() const; //- Return circum-centre - inline vector circumCentre() const; + inline Point circumCentre() const; //- Return circum-radius inline scalar circumRadius() const; + //- Return quality: Ratio of tetrahedron and circum-sphere + // volume, scaled so that a regular tetrahedron has a + // quality of 1 + inline scalar quality() const; + + //- Return a random point in the tetrahedron from a + // uniform distribution + inline Point randomPoint(Random& rndGen) const; + + //- Calculate the barycentric coordinates of the given + // point, in the same order as a, b, c, d. Returns the + // determinant of the solution. + inline scalar barycentric + ( + const point& pt, + List<scalar>& bary + ) const; + + //- Return nearest point to p on tetrahedron + inline pointHit nearestPoint + ( + const point& p + ) const; + //- Return (min)containment sphere, i.e. the smallest sphere with // all points inside. Returns pointHit with: // - hit : if sphere is equal to circumsphere diff --git a/src/OpenFOAM/meshes/primitiveShapes/tetrahedron/tetrahedronI.H b/src/OpenFOAM/meshes/primitiveShapes/tetrahedron/tetrahedronI.H index 5fab6fa5381..a96d9f577fc 100644 --- a/src/OpenFOAM/meshes/primitiveShapes/tetrahedron/tetrahedronI.H +++ b/src/OpenFOAM/meshes/primitiveShapes/tetrahedron/tetrahedronI.H @@ -125,6 +125,13 @@ inline vector tetrahedron<Point, PointRef>::Sd() const } +template<class Point, class PointRef> +inline Point tetrahedron<Point, PointRef>::centre() const +{ + return 0.25*(a_ + b_ + c_ + d_); +} + + template<class Point, class PointRef> inline scalar tetrahedron<Point, PointRef>::mag() const { @@ -133,19 +140,19 @@ inline scalar tetrahedron<Point, PointRef>::mag() const template<class Point, class PointRef> -inline vector tetrahedron<Point, PointRef>::circumCentre() const +inline Point tetrahedron<Point, PointRef>::circumCentre() const { vector a = b_ - a_; vector b = c_ - a_; vector c = d_ - a_; - scalar lamda = magSqr(c) - (a&c); - scalar mu = magSqr(b) - (a&b); + scalar lambda = magSqr(c) - (a & c); + scalar mu = magSqr(b) - (a & b); - vector ba = b^a; - vector ca = c^a; + vector ba = b ^ a; + vector ca = c ^ a; - return a_ + 0.5*(a + (lamda*ba - mu*ca)/(c&ba)); + return a_ + 0.5*(a + (lambda*ba - mu*ca)/((c & ba) + ROOTVSMALL)); } @@ -156,6 +163,196 @@ inline scalar tetrahedron<Point, PointRef>::circumRadius() const } +template<class Point, class PointRef> +inline scalar tetrahedron<Point, PointRef>::quality() const +{ + // Note: 8/(9*sqrt(3)) = 0.5132002393 + + return mag()/(0.5132002393*pow3(min(circumRadius(), GREAT)) + ROOTVSMALL); +} + + +template<class Point, class PointRef> +inline Point tetrahedron<Point, PointRef>::randomPoint(Random& rndGen) const +{ + // Adapted from + // http://vcg.isti.cnr.it/activities/geometryegraphics/pointintetraedro.html + + scalar s = rndGen.scalar01(); + scalar t = rndGen.scalar01(); + scalar u = rndGen.scalar01(); + + if (s + t > 1.0) + { + s = 1.0 - s; + t = 1.0 - t; + } + + if (t + u > 1.0) + { + scalar tmp = u; + u = 1.0 - s - t; + t = 1.0 - tmp; + } + else if (s + t + u > 1.0) + { + scalar tmp = u; + u = s + t + u - 1.0; + s = 1.0 - t - tmp; + } + + return (1 - s - t - u)*a_ + s*b_ + t*c_ + u*d_; +} + + +template<class Point, class PointRef> +scalar tetrahedron<Point, PointRef>::barycentric +( + const point& pt, + List<scalar>& bary +) const +{ + // From: + // http://en.wikipedia.org/wiki/Barycentric_coordinate_system_(mathematics) + + vector e0(a_ - d_); + vector e1(b_ - d_); + vector e2(c_ - d_); + + tensor t + ( + e0.x(), e1.x(), e2.x(), + e0.y(), e1.y(), e2.y(), + e0.z(), e1.z(), e2.z() + ); + + scalar detT = det(t); + + if (Foam::mag(detT) < SMALL) + { + WarningIn + ( + "List<scalar> tetrahedron<Point, PointRef>::barycentric" + "(" + "const point& pt" + ") const" + ) + << "Degenerate triangle - returning 1/4 barycentric coordinates." + << endl; + + bary = List<scalar>(4, 0.25); + + return detT; + } + + vector res = inv(t, detT) & (pt - d_); + + bary.setSize(4); + + bary[0] = res.x(); + bary[1] = res.y(); + bary[2] = res.z(); + bary[3] = (1.0 - res.x() - res.y() - res.z()); + + return detT; +} + + +template<class Point, class PointRef> +inline pointHit tetrahedron<Point, PointRef>::nearestPoint +( + const point& p +) const +{ + // Adapted from: + // Real-time collision detection, Christer Ericson, 2005, p142-144 + + // Assuming initially that the point is inside all of the + // halfspaces, so closest to itself. + + point closestPt = p; + + scalar minOutsideDistance = VGREAT; + + bool inside = true; + + if (((p - b_) & Sa()) >= 0) + { + // p is outside halfspace plane of tri + pointHit info = triangle<Point, PointRef>(b_, c_, d_).nearestPoint(p); + + inside = false; + + if (info.distance() < minOutsideDistance) + { + closestPt = info.rawPoint(); + + minOutsideDistance = info.distance(); + } + } + + if (((p - a_) & Sb()) >= 0) + { + // p is outside halfspace plane of tri + pointHit info = triangle<Point, PointRef>(a_, d_, c_).nearestPoint(p); + + inside = false; + + if (info.distance() < minOutsideDistance) + { + closestPt = info.rawPoint(); + + minOutsideDistance = info.distance(); + } + } + + if (((p - a_) & Sc()) >= 0) + { + // p is outside halfspace plane of tri + pointHit info = triangle<Point, PointRef>(a_, b_, d_).nearestPoint(p); + + inside = false; + + if (info.distance() < minOutsideDistance) + { + closestPt = info.rawPoint(); + + minOutsideDistance = info.distance(); + } + } + + if (((p - a_) & Sd()) >= 0) + { + // p is outside halfspace plane of tri + pointHit info = triangle<Point, PointRef>(a_, c_, b_).nearestPoint(p); + + inside = false; + + if (info.distance() < minOutsideDistance) + { + closestPt = info.rawPoint(); + + minOutsideDistance = info.distance(); + } + } + + // If the point is inside, then the distance to the closest point + // is zero + if (inside) + { + minOutsideDistance = 0; + } + + return pointHit + ( + inside, + closestPt, + minOutsideDistance, + !inside + ); +} + + // * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * // template<class point, class pointRef> diff --git a/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.H b/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.H index a5c246a3607..64d9318306f 100644 --- a/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.H +++ b/src/OpenFOAM/meshes/primitiveShapes/triangle/triangle.H @@ -39,7 +39,7 @@ SourceFiles #include "vector.H" #include "tensor.H" #include "pointHit.H" - +#include "Random.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -141,12 +141,14 @@ public: inline vector normal() const; //- Return circum-centre - inline vector circumCentre() const; + inline Point circumCentre() const; //- Return circum-radius inline scalar circumRadius() const; - //- Return quality: Ratio triangle and circum-circle area + //- Return quality: Ratio of triangle and circum-circle + // area, scaled so that an equilateral triangle has a + // quality of 1 inline scalar quality() const; //- Return swept-volume @@ -160,6 +162,19 @@ public: scalar density = 1.0 ) const; + //- Return a random point on the triangle from a uniform + // distribution + inline Point randomPoint(Random& rndGen) const; + + //- Calculate the barycentric coordinates of the given + // point, in the same order as a, b, c. Returns the + // determinant of the solution. + inline scalar barycentric + ( + const point& pt, + List<scalar>& bary + ) const; + //- Return point intersection with a ray. // For a hit, the distance is signed. Positive number // represents the point in front of triangle. diff --git a/src/OpenFOAM/meshes/primitiveShapes/triangle/triangleI.H b/src/OpenFOAM/meshes/primitiveShapes/triangle/triangleI.H index 3587ac8d907..10267a923f7 100644 --- a/src/OpenFOAM/meshes/primitiveShapes/triangle/triangleI.H +++ b/src/OpenFOAM/meshes/primitiveShapes/triangle/triangleI.H @@ -259,7 +259,7 @@ inline vector triangle<Point, PointRef>::normal() const template<class Point, class PointRef> -inline vector triangle<Point, PointRef>::circumCentre() const +inline Point triangle<Point, PointRef>::circumCentre() const { scalar d1 = (c_ - a_)&(b_ - a_); scalar d2 = -(c_ - b_)&(b_ - a_); @@ -303,12 +303,14 @@ inline scalar triangle<Point, PointRef>::circumRadius() const template<class Point, class PointRef> inline scalar triangle<Point, PointRef>::quality() const { + // Note: 3*sqr(3)/(4*pi) = 0.4134966716 + return mag() / ( constant::mathematical::pi *Foam::sqr(circumRadius()) - *0.413497 + *0.4134966716 + VSMALL ); } @@ -366,6 +368,72 @@ inline tensor triangle<Point, PointRef>::inertia *density; } + +template<class Point, class PointRef> +inline Point triangle<Point, PointRef>::randomPoint(Random& rndGen) const +{ + // Generating Random Points in Triangles + // by Greg Turk + // from "Graphics Gems", Academic Press, 1990 + // http://tog.acm.org/GraphicsGems/gems/TriPoints.c + + scalar s = rndGen.scalar01(); + + scalar t = sqrt(rndGen.scalar01()); + + return (1 - t)*a_ + (1 - s)*t*b_ + s*t*c_; +} + + +template<class Point, class PointRef> +scalar triangle<Point, PointRef>::barycentric +( + const point& pt, + List<scalar>& bary +) const +{ + // From: + // Real-time collision detection, Christer Ericson, 2005, p47-48 + + vector v0 = b_ - a_; + vector v1 = c_ - a_; + vector v2 = pt - a_; + + scalar d00 = v0 & v0; + scalar d01 = v0 & v1; + scalar d11 = v1 & v1; + scalar d20 = v2 & v0; + scalar d21 = v2 & v1; + + scalar denom = d00*d11 - d01*d01; + + if (Foam::mag(denom) < SMALL) + { + WarningIn + ( + "List<scalar> triangle<Point, PointRef>::barycentric" + "(" + "const point& pt" + ") const" + ) + << "Degenerate triangle - returning 1/3 barycentric coordinates." + << endl; + + bary = List<scalar>(3, 1.0/3.0); + + return denom; + } + + bary.setSize(3); + + bary[0] = (d11*d20 - d01*d21)/denom; + bary[1] = (d00*d21 - d01*d20)/denom; + bary[2] = 1.0 - bary[0] - bary[1]; + + return denom; +} + + template<class Point, class PointRef> inline pointHit triangle<Point, PointRef>::ray ( @@ -775,4 +843,3 @@ inline Ostream& operator<<(Ostream& os, const triangle<Point, PointRef>& t) } // End namespace Foam // ************************************************************************* // - diff --git a/src/OpenFOAM/primitives/Tensor/TensorI.H b/src/OpenFOAM/primitives/Tensor/TensorI.H index 8ca4f601693..11860b5c4c9 100644 --- a/src/OpenFOAM/primitives/Tensor/TensorI.H +++ b/src/OpenFOAM/primitives/Tensor/TensorI.H @@ -481,7 +481,7 @@ inline Tensor<Cmpt> cof(const Tensor<Cmpt>& t) } -//- Return the inverse of a tensor give the determinant +//- Return the inverse of a tensor given the determinant template <class Cmpt> inline Tensor<Cmpt> inv(const Tensor<Cmpt>& t, const Cmpt dett) { diff --git a/src/dynamicMesh/motionSmoother/motionSmootherCheck.C b/src/dynamicMesh/motionSmoother/motionSmootherCheck.C index 4823c3a429d..5df1ca1dbcf 100644 --- a/src/dynamicMesh/motionSmoother/motionSmootherCheck.C +++ b/src/dynamicMesh/motionSmoother/motionSmootherCheck.C @@ -68,9 +68,9 @@ bool Foam::motionSmoother::checkMesh ( readScalar(dict.lookup("minVol", true)) ); - const scalar minTetVol + const scalar minTetQuality ( - readScalar(dict.lookup("minTetVol", true)) + readScalar(dict.lookup("minTetQuality", true)) ); const scalar maxConcave ( @@ -160,12 +160,12 @@ bool Foam::motionSmoother::checkMesh nWrongFaces = nNewWrongFaces; } - if (minTetVol > -GREAT) + if (minTetQuality > -GREAT) { polyMeshGeometry::checkFaceTets ( report, - minTetVol, + minTetQuality, mesh, mesh.cellCentres(), mesh.faceCentres(), @@ -177,8 +177,8 @@ bool Foam::motionSmoother::checkMesh label nNewWrongFaces = returnReduce(wrongFaces.size(), sumOp<label>()); - Info<< " faces with face-decomposition tet volume < " - << setw(5) << minTetVol << " : " + Info<< " faces with face-decomposition tet quality < " + << setw(5) << minTetQuality << " : " << nNewWrongFaces-nWrongFaces << endl; nWrongFaces = nNewWrongFaces; @@ -443,9 +443,9 @@ bool Foam::motionSmoother::checkMesh ( readScalar(dict.lookup("minVol", true)) ); - const scalar minTetVol + const scalar minTetQuality ( - readScalar(dict.lookup("minTetVol", true)) + readScalar(dict.lookup("minTetQuality", true)) ); const scalar maxConcave ( @@ -531,12 +531,12 @@ bool Foam::motionSmoother::checkMesh nWrongFaces = nNewWrongFaces; } - if (minTetVol > -GREAT) + if (minTetQuality > -GREAT) { meshGeom.checkFaceTets ( report, - minTetVol, + minTetQuality, meshGeom.mesh().points(), checkFaces, baffles, @@ -545,8 +545,8 @@ bool Foam::motionSmoother::checkMesh label nNewWrongFaces = returnReduce(wrongFaces.size(), sumOp<label>()); - Info<< " faces with face-decomposition tet volume < " - << setw(5) << minTetVol << " : " + Info<< " faces with face-decomposition tet quality < " + << setw(5) << minTetQuality << " : " << nNewWrongFaces-nWrongFaces << endl; nWrongFaces = nNewWrongFaces; diff --git a/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.C b/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.C index fb9ccb9631f..4df209498a8 100644 --- a/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.C +++ b/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.C @@ -24,6 +24,7 @@ License \*---------------------------------------------------------------------------*/ #include "polyMeshGeometry.H" +#include "polyMeshTetDecomposition.H" #include "pyramidPointFaceRef.H" #include "tetPointRef.H" #include "syncTools.H" @@ -313,7 +314,7 @@ bool Foam::polyMeshGeometry::checkFaceTet ( const polyMesh& mesh, const bool report, - const scalar minTetVol, + const scalar minTetQuality, const pointField& p, const label faceI, const point& fc, // face centre @@ -326,15 +327,15 @@ bool Foam::polyMeshGeometry::checkFaceTet forAll(f, fp) { - scalar tetVol = tetPointRef + scalar tetQual = tetPointRef ( p[f[fp]], p[f.nextLabel(fp)], fc, cc - ).mag(); + ).quality(); - if (tetVol < minTetVol) + if (tetQual < minTetQuality) { if (report) { @@ -345,7 +346,7 @@ bool Foam::polyMeshGeometry::checkFaceTet << "face " << faceI << " has a triangle that points the wrong way." << endl - << "Tet volume: " << tetVol + << "Tet quality: " << tetQual << " Face " << faceI << endl; } @@ -423,16 +424,15 @@ bool Foam::polyMeshGeometry::checkFaceDotProduct // Severe nonorthogonality threshold const scalar severeNonorthogonalityThreshold = ::cos(degToRad(orthWarn)); - // Calculate coupled cell centre - pointField neiCc(mesh.nFaces()-mesh.nInternalFaces()); + pointField neiCc(mesh.nFaces() - mesh.nInternalFaces()); for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++) { neiCc[faceI-mesh.nInternalFaces()] = cellCentres[own[faceI]]; } - syncTools::swapBoundaryFacePositions(mesh, neiCc); + syncTools::swapBoundaryFacePositions(mesh, neiCc); scalar minDDotS = GREAT; @@ -754,7 +754,7 @@ bool Foam::polyMeshGeometry::checkFacePyramids "polyMeshGeometry::checkFacePyramids(" "const bool, const scalar, const pointField&" ", const labelList&, labelHashSet*)" - ) << "Error in face pyramids: faces pointing the wrong way!" + ) << "Error in face pyramids: faces pointing the wrong way." << endl; } @@ -775,7 +775,7 @@ bool Foam::polyMeshGeometry::checkFacePyramids bool Foam::polyMeshGeometry::checkFaceTets ( const bool report, - const scalar minTetVol, + const scalar minTetQuality, const polyMesh& mesh, const vectorField& cellCentres, const vectorField& faceCentres, @@ -785,11 +785,23 @@ bool Foam::polyMeshGeometry::checkFaceTets labelHashSet* setPtr ) { - // check whether face area vector points to the cell with higher label + // check whether decomposing each cell into tets results in + // positive volume, non-flat tets const labelList& own = mesh.faceOwner(); const labelList& nei = mesh.faceNeighbour(); + const polyBoundaryMesh& patches = mesh.boundaryMesh(); - label nErrorPyrs = 0; + // Calculate coupled cell centre + pointField neiCc(mesh.nFaces() - mesh.nInternalFaces()); + + for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++) + { + neiCc[faceI - mesh.nInternalFaces()] = cellCentres[own[faceI]]; + } + + syncTools::swapBoundaryFacePositions(mesh, neiCc); + + label nErrorTets = 0; forAll(checkFaces, i) { @@ -801,36 +813,104 @@ bool Foam::polyMeshGeometry::checkFaceTets ( mesh, report, - minTetVol, + minTetQuality, p, faceI, cellCentres[own[faceI]], // face centre - faceCentres[faceI], // cell centre + faceCentres[faceI], // cell centre setPtr ); if (tetError) { - nErrorPyrs++; + nErrorTets++; } if (mesh.isInternalFace(faceI)) { - // Create the neighbour pyramid - it will have positive volume + // Create the neighbour tets - they will have positive volume bool tetError = checkFaceTet ( mesh, report, - minTetVol, + minTetQuality, p, faceI, - faceCentres[faceI], // face centre + faceCentres[faceI], // face centre cellCentres[nei[faceI]], // cell centre setPtr ); + if (tetError) { - nErrorPyrs++; + nErrorTets++; + } + + if + ( + polyMeshTetDecomposition::findSharedBasePoint + ( + mesh, + faceI, + minTetQuality, + report + ) == -1 + ) + { + if (setPtr) + { + setPtr->insert(faceI); + } + + nErrorTets++; + } + } + else + { + label patchI = patches.whichPatch(faceI); + + if (patches[patchI].coupled()) + { + if + ( + polyMeshTetDecomposition::findSharedBasePoint + ( + mesh, + faceI, + neiCc[faceI - mesh.nInternalFaces()], + minTetQuality, + report + ) == -1 + ) + { + if (setPtr) + { + setPtr->insert(faceI); + } + + nErrorTets++; + } + } + else + { + if + ( + polyMeshTetDecomposition::findBasePoint + ( + mesh, + faceI, + minTetQuality, + report + ) == -1 + ) + { + if (setPtr) + { + setPtr->insert(faceI); + } + + nErrorTets++; + } } } } @@ -844,7 +924,7 @@ bool Foam::polyMeshGeometry::checkFaceTets ( mesh, report, - minTetVol, + minTetQuality, p, face0, cellCentres[own[face0]], // face centre @@ -854,15 +934,15 @@ bool Foam::polyMeshGeometry::checkFaceTets if (tetError) { - nErrorPyrs++; + nErrorTets++; } - // Create the neighbour pyramid - it will have positive volume + // Create the neighbour tets - they will have positive volume tetError = checkFaceTet ( mesh, report, - minTetVol, + minTetQuality, p, face0, faceCentres[face0], // face centre @@ -872,13 +952,33 @@ bool Foam::polyMeshGeometry::checkFaceTets if (tetError) { - nErrorPyrs++; + nErrorTets++; + } + + if + ( + polyMeshTetDecomposition::findSharedBasePoint + ( + mesh, + face0, + cellCentres[own[face1]], + minTetQuality, + report + ) == -1 + ) + { + if (setPtr) + { + setPtr->insert(face0); + } + + nErrorTets++; } } - reduce(nErrorPyrs, sumOp<label>()); + reduce(nErrorTets, sumOp<label>()); - if (nErrorPyrs > 0) + if (nErrorTets > 0) { if (report) { @@ -887,7 +987,7 @@ bool Foam::polyMeshGeometry::checkFaceTets "polyMeshGeometry::checkFaceTets(" "const bool, const scalar, const pointField&, const pointField&" ", const labelList&, labelHashSet*)" - ) << "Error in face pyramids: faces pointing the wrong way!" + ) << "Error in face decomposition: negative tets." << endl; } @@ -2135,7 +2235,7 @@ bool Foam::polyMeshGeometry::checkFacePyramids bool Foam::polyMeshGeometry::checkFaceTets ( const bool report, - const scalar minTetVol, + const scalar minTetQuality, const pointField& p, const labelList& checkFaces, const List<labelPair>& baffles, @@ -2145,7 +2245,7 @@ bool Foam::polyMeshGeometry::checkFaceTets return checkFaceTets ( report, - minTetVol, + minTetQuality, mesh_, cellCentres_, faceCentres_, diff --git a/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.H b/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.H index 4a8178b8f60..71f61447b53 100644 --- a/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.H +++ b/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.H @@ -113,7 +113,7 @@ class polyMeshGeometry ( const polyMesh&, const bool report, - const scalar minTetVol, + const scalar minTetQuality, const pointField& p, const label faceI, const point& fc, // face centre @@ -121,6 +121,7 @@ class polyMeshGeometry labelHashSet* setPtr ); + public: ClassName("polyMeshGeometry"); @@ -350,7 +351,7 @@ public: bool checkFaceTets ( const bool report, - const scalar minTetVol, + const scalar minTetQuality, const pointField& p, const labelList& checkFaces, const List<labelPair>& baffles, diff --git a/src/finiteVolume/interpolation/interpolation/interpolation/interpolation.H b/src/finiteVolume/interpolation/interpolation/interpolation/interpolation.H index ef200b354a8..e6df2154a4f 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolation/interpolation.H +++ b/src/finiteVolume/interpolation/interpolation/interpolation/interpolation.H @@ -38,6 +38,7 @@ Description #include "typeInfo.H" #include "autoPtr.H" #include "runTimeSelectionTables.H" +#include "tetIndices.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -130,9 +131,23 @@ public: virtual Type interpolate ( const vector& position, - const label nCell, - const label facei = -1 + const label cellI, + const label faceI = -1 ) const = 0; + + //- Interpolate field to the given point in the tetrahedron + // defined by the given indices. Calls interpolate function + // above here execpt where overridden by derived + // interpolation types. + virtual Type interpolate + ( + const vector& position, + const tetIndices& tetIs, + const label faceI = -1 + ) const + { + return interpolate(position, tetIs.cell(), faceI); + } }; diff --git a/src/finiteVolume/interpolation/interpolation/interpolationCell/interpolationCell.C b/src/finiteVolume/interpolation/interpolation/interpolationCell/interpolationCell.C index fbf1bfa14ac..760fd2ff633 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationCell/interpolationCell.C +++ b/src/finiteVolume/interpolation/interpolation/interpolationCell/interpolationCell.C @@ -49,11 +49,11 @@ template<class Type> Type interpolationCell<Type>::interpolate ( const vector&, - const label celli, + const label cellI, const label ) const { - return this->psi_[celli]; + return this->psi_[cellI]; } diff --git a/src/finiteVolume/interpolation/interpolation/interpolationCell/interpolationCell.H b/src/finiteVolume/interpolation/interpolation/interpolationCell/interpolationCell.H index 3c852da8679..fa9461805b1 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationCell/interpolationCell.H +++ b/src/finiteVolume/interpolation/interpolation/interpolationCell/interpolationCell.H @@ -72,8 +72,8 @@ public: Type interpolate ( const vector& position, - const label nCell, - const label facei = -1 + const label cellI, + const label faceI = -1 ) const; }; diff --git a/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/cellPointWeight/cellPointWeight.C b/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/cellPointWeight/cellPointWeight.C index 52ce6ba21e6..99b10c10b54 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/cellPointWeight/cellPointWeight.C +++ b/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/cellPointWeight/cellPointWeight.C @@ -25,10 +25,13 @@ License #include "cellPointWeight.H" #include "polyMesh.H" +#include "tetPointRef.H" +#include "polyMeshTetDecomposition.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // int Foam::cellPointWeight::debug(debug::debugSwitch("cellPointWeight", 0)); + Foam::scalar Foam::cellPointWeight::tol(SMALL); // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // @@ -37,148 +40,101 @@ void Foam::cellPointWeight::findTetrahedron ( const polyMesh& mesh, const vector& position, - const label cellIndex + const label cellI ) { if (debug) { - Pout<< "\nFoam::cellPointWeight::findTetrahedron" << nl + Pout<< nl << "Foam::cellPointWeight::findTetrahedron" << nl << "position = " << position << nl - << "cellIndex = " << cellIndex << endl; + << "cellI = " << cellI << endl; } - // Initialise closest triangle variables - scalar minUVWClose = VGREAT; - label pointIClose = 0; - label faceClose = 0; + List<tetIndices> cellTets = polyMeshTetDecomposition::cellTetIndices + ( + mesh, + cellI + ); - const vector& P0 = mesh.cellCentres()[cellIndex]; - const labelList& cellFaces = mesh.cells()[cellIndex]; - const scalar cellVolume = mesh.cellVolumes()[cellIndex]; + const faceList& pFaces = mesh.faces(); + const scalar cellVolume = mesh.cellVolumes()[cellI]; - // Find the tet that the point occupies - forAll(cellFaces, faceI) + forAll(cellTets, tetI) { - // Decompose each face into triangles, making a tet when - // augmented by the cell centre - const labelList& facePoints = mesh.faces()[cellFaces[faceI]]; + const tetIndices& tetIs = cellTets[tetI]; + + const face& f = pFaces[tetIs.face()]; + + // Barycentric coordinates of the position + scalar det = tetIs.tet(mesh).barycentric(position, weights_); - label pointI = 1; - while ((pointI + 1) < facePoints.size()) + if (mag(det/cellVolume) > tol) { - // Cartesian co-ordinates of the triangle vertices - const vector& P1 = mesh.points()[facePoints[0]]; - const vector& P2 = mesh.points()[facePoints[pointI]]; - const vector& P3 = mesh.points()[facePoints[pointI + 1]]; + const scalar& u = weights_[0]; + const scalar& v = weights_[1]; + const scalar& w = weights_[2]; + + if + ( + (u + tol > 0) + && (v + tol > 0) + && (w + tol > 0) + && (u + v + w < 1 + tol) + ) + { + faceVertices_[0] = f[tetIs.faceBasePt()]; + faceVertices_[1] = f[tetIs.facePtA()];; + faceVertices_[2] = f[tetIs.facePtB()];; - // Edge vectors - const vector e1 = P1 - P0; - const vector e2 = P2 - P0; - const vector e3 = P3 - P0; + return; + } + } + } - // Solve for interpolation weighting factors + // A suitable point in a tetrahedron was not found, find the + // nearest. - // Source term - const vector rhs = position - P0; + scalar minNearDist = VGREAT; - // Determinant of coefficients matrix - // Note: if det(A) = 0 the tet is degenerate - const scalar detA = - e1.x()*e2.y()*e3.z() + e2.x()*e3.y()*e1.z() - + e3.x()*e1.y()*e2.z() - e1.x()*e3.y()*e2.z() - - e2.x()*e1.y()*e3.z() - e3.x()*e2.y()*e1.z(); + label nearestTetI = -1; - if (mag(detA/cellVolume) > tol) - { - // Solve using Cramers' rule - const scalar u = - ( - rhs.x()*e2.y()*e3.z() + e2.x()*e3.y()*rhs.z() - + e3.x()*rhs.y()*e2.z() - rhs.x()*e3.y()*e2.z() - - e2.x()*rhs.y()*e3.z() - e3.x()*e2.y()*rhs.z() - )/detA; - - const scalar v = - ( - e1.x()*rhs.y()*e3.z() + rhs.x()*e3.y()*e1.z() - + e3.x()*e1.y()*rhs.z() - e1.x()*e3.y()*rhs.z() - - rhs.x()*e1.y()*e3.z() - e3.x()*rhs.y()*e1.z() - )/detA; - - const scalar w = - ( - e1.x()*e2.y()*rhs.z() + e2.x()*rhs.y()*e1.z() - + rhs.x()*e1.y()*e2.z() - e1.x()*rhs.y()*e2.z() - - e2.x()*e1.y()*rhs.z() - rhs.x()*e2.y()*e1.z() - )/detA; - - // Check if point is in tet - // value = 0 indicates position lies on a tet face - if - ( - (u + tol > 0) && (v + tol > 0) && (w + tol > 0) - && (u + v + w < 1 + tol) - ) - { - faceVertices_[0] = facePoints[0]; - faceVertices_[1] = facePoints[pointI]; - faceVertices_[2] = facePoints[pointI + 1]; - - weights_[0] = u; - weights_[1] = v; - weights_[2] = w; - weights_[3] = 1.0 - (u + v + w); - - return; - } - else - { - scalar minU = mag(u); - scalar minV = mag(v); - scalar minW = mag(w); - if (minU > 1.0) - { - minU -= 1.0; - } - if (minV > 1.0) - { - minV -= 1.0; - } - if (minW > 1.0) - { - minW -= 1.0; - } - const scalar minUVW = mag(minU + minV + minW); - - if (minUVW < minUVWClose) - { - minUVWClose = minUVW; - pointIClose = pointI; - faceClose = faceI; - } - } - } + forAll(cellTets, tetI) + { + const tetIndices& tetIs = cellTets[tetI]; + + scalar nearDist = tetIs.tet(mesh).nearestPoint(position).distance(); - pointI++; + if (nearDist < minNearDist) + { + minNearDist = nearDist; + + nearestTetI = tetI; } } if (debug) { Pout<< "cellPointWeight::findTetrahedron" << nl - << " Tetrahedron search failed; using closest tet values to " - << "point " << nl << " cell: " << cellIndex << nl << endl; + << " Tetrahedron search failed; using closest tet to point " + << position << nl + << " cell: " + << cellI << nl + << endl; } - const labelList& facePointsClose = mesh.faces()[cellFaces[faceClose]]; - faceVertices_[0] = facePointsClose[0]; - faceVertices_[1] = facePointsClose[pointIClose]; - faceVertices_[2] = facePointsClose[pointIClose + 1]; - weights_[0] = 0.25; - weights_[1] = 0.25; - weights_[2] = 0.25; - weights_[3] = 0.25; + const tetIndices& tetIs = cellTets[nearestTetI]; + + const face& f = pFaces[tetIs.face()]; + + // Barycentric coordinates of the position, ignoring if the + // determinant is suitable. If not, the return from barycentric + // to weights_ is safe. + tetIs.tet(mesh).barycentric(position, weights_); + + faceVertices_[0] = f[tetIs.faceBasePt()]; + faceVertices_[1] = f[tetIs.facePtA()]; + faceVertices_[2] = f[tetIs.facePtB()]; } @@ -186,119 +142,112 @@ void Foam::cellPointWeight::findTriangle ( const polyMesh& mesh, const vector& position, - const label faceIndex + const label faceI ) { if (debug) { Pout<< "\nbool Foam::cellPointWeight::findTriangle" << nl << "position = " << position << nl - << "faceIndex = " << faceIndex << endl; + << "faceI = " << faceI << endl; } - // Initialise closest triangle variables - scalar minUVClose = VGREAT; - label pointIClose = 0; + List<tetIndices> faceTets = polyMeshTetDecomposition::faceTetIndices + ( + mesh, + mesh.faceOwner()[faceI], + faceI + ); - // Decompose each face into triangles, making a tet when - // augmented by the cell centre - const labelList& facePoints = mesh.faces()[faceIndex]; + const scalar faceAreaSqr = magSqr(mesh.faceAreas()[faceI]); - const scalar faceArea2 = magSqr(mesh.faceAreas()[faceIndex]); + const face& f = mesh.faces()[faceI]; - label pointI = 1; - while ((pointI + 1) < facePoints.size()) + forAll(faceTets, tetI) { - // Cartesian co-ordinates of the triangle vertices - const vector& P1 = mesh.points()[facePoints[0]]; - const vector& P2 = mesh.points()[facePoints[pointI]]; - const vector& P3 = mesh.points()[facePoints[pointI + 1]]; - - // Direction vectors - vector v1 = position - P1; - const vector v2 = P2 - P1; - const vector v3 = P3 - P1; - - // Plane normal - vector n = v2 ^ v3; - n /= mag(n); - - // Remove any offset to plane - v1 -= (n & v1)*v1; - - // Helper variables - const scalar d12 = v1 & v2; - const scalar d13 = v1 & v3; - const scalar d22 = v2 & v2; - const scalar d23 = v2 & v3; - const scalar d33 = v3 & v3; - - // Determinant of coefficients matrix - // Note: if det(A) = 0 the triangle is degenerate - const scalar detA = d22*d33 - d23*d23; - - if (0.25*detA/faceArea2 > tol) - { - // Solve using Cramers' rule - const scalar u = (d12*d33 - d23*d13)/detA; - const scalar v = (d22*d13 - d12*d23)/detA; + const tetIndices& tetIs = faceTets[tetI]; + + List<scalar> triWeights(3); - // Check if point is in triangle - if ((u + tol > 0) && (v + tol > 0) && (u + v < 1 + tol)) + // Barycentric coordinates of the position + scalar det = tetIs.faceTri(mesh).barycentric(position, triWeights); + + if (0.25*mag(det)/faceAreaSqr > tol) + { + const scalar& u = triWeights[0]; + const scalar& v = triWeights[1]; + + if + ( + (u + tol > 0) + && (v + tol > 0) + && (u + v < 1 + tol) + ) { - // Indices of the cell vertices making up the triangle - faceVertices_[0] = facePoints[0]; - faceVertices_[1] = facePoints[pointI]; - faceVertices_[2] = facePoints[pointI + 1]; + // Weight[0] is for the cell centre. + weights_[0] = 0; + weights_[1] = triWeights[0]; + weights_[2] = triWeights[1]; + weights_[3] = triWeights[2]; - weights_[0] = u; - weights_[1] = v; - weights_[2] = 1.0 - (u + v); - weights_[3] = 0.0; + faceVertices_[0] = f[tetIs.faceBasePt()]; + faceVertices_[1] = f[tetIs.facePtA()];; + faceVertices_[2] = f[tetIs.facePtB()];; return; } - else - { - scalar minU = mag(u); - scalar minV = mag(v); - if (minU > 1.0) - { - minU -= 1.0; - } - if (minV > 1.0) - { - minV -= 1.0; - } - const scalar minUV = mag(minU + minV); - - if (minUV < minUVClose) - { - minUVClose = minUV; - pointIClose = pointI; - } - } } + } + + // A suitable point in a triangle was not found, find the nearest. + + scalar minNearDist = VGREAT; + + label nearestTetI = -1; + + forAll(faceTets, tetI) + { + const tetIndices& tetIs = faceTets[tetI]; + + scalar nearDist = tetIs.faceTri(mesh).nearestPoint(position).distance(); - pointI++; + if (nearDist < minNearDist) + { + minNearDist = nearDist; + + nearestTetI = tetI; + } } if (debug) { - Pout<< "Foam::cellPointWeight::findTriangle" - << "Triangle search failed; using closest triangle to point" << nl - << " cell face: " << faceIndex << nl << endl; + Pout<< "cellPointWeight::findTriangle" << nl + << " Triangle search failed; using closest tri to point " + << position << nl + << " face: " + << faceI << nl + << endl; } - // Indices of the cell vertices making up the triangle - faceVertices_[0] = facePoints[0]; - faceVertices_[1] = facePoints[pointIClose]; - faceVertices_[2] = facePoints[pointIClose + 1]; + const tetIndices& tetIs = faceTets[nearestTetI]; + + // Barycentric coordinates of the position, ignoring if the + // determinant is suitable. If not, the return from barycentric + // to triWeights is safe. + + List<scalar> triWeights(3); + + tetIs.faceTri(mesh).barycentric(position, triWeights); + + // Weight[0] is for the cell centre. + weights_[0] = 0; + weights_[1] = triWeights[0]; + weights_[2] = triWeights[1]; + weights_[3] = triWeights[2]; - weights_[0] = 1.0/3.0; - weights_[1] = 1.0/3.0; - weights_[2] = 1.0/3.0; - weights_[3] = 0.0; + faceVertices_[0] = f[tetIs.faceBasePt()]; + faceVertices_[1] = f[tetIs.facePtA()]; + faceVertices_[2] = f[tetIs.facePtB()]; } @@ -308,21 +257,23 @@ Foam::cellPointWeight::cellPointWeight ( const polyMesh& mesh, const vector& position, - const label cellIndex, - const label faceIndex + const label cellI, + const label faceI ) : - cellIndex_(cellIndex) + cellI_(cellI), + weights_(4), + faceVertices_(3) { - if (faceIndex < 0) + if (faceI < 0) { // Face data not supplied - findTetrahedron(mesh, position, cellIndex); + findTetrahedron(mesh, position, cellI); } else { // Face data supplied - findTriangle(mesh, position, faceIndex); + findTriangle(mesh, position, faceI); } } diff --git a/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/cellPointWeight/cellPointWeight.H b/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/cellPointWeight/cellPointWeight.H index bb3647ac309..3042b926b1a 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/cellPointWeight/cellPointWeight.H +++ b/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/cellPointWeight/cellPointWeight.H @@ -55,13 +55,13 @@ protected: // Protected data //- Cell index - const label cellIndex_; + const label cellI_; //- Weights applied to tet vertices - FixedList<scalar, 4> weights_; + List<scalar> weights_; //- Face vertex indices - FixedList<label, 3> faceVertices_; + List<label> faceVertices_; // Protected Member Functions @@ -70,14 +70,14 @@ protected: ( const polyMesh& mesh, const vector& position, - const label cellIndex + const label cellI ); void findTriangle ( const polyMesh& mesh, const vector& position, - const label faceIndex + const label faceI ); @@ -98,8 +98,8 @@ public: ( const polyMesh& mesh, const vector& position, - const label nCell, - const label facei = -1 + const label cellI, + const label faceI = -1 ); @@ -108,17 +108,17 @@ public: //- Cell index inline label cell() const { - return cellIndex_; + return cellI_; } //- interpolation weights - inline const FixedList<scalar, 4>& weights() const + inline const List<scalar>& weights() const { return weights_; } //- interpolation addressing for points on face - inline const FixedList<label, 3>& faceVertices() const + inline const List<label>& faceVertices() const { return faceVertices_; } diff --git a/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/interpolationCellPoint.H b/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/interpolationCellPoint.H index e3424f3c4ce..657d8168ac1 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/interpolationCellPoint.H +++ b/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/interpolationCellPoint.H @@ -25,7 +25,7 @@ Class Foam::interpolationCellPoint Description - Given cell centre values and point (vertex) values decompose into + Given cell centre values and point (vertex) values decompose into tetrahedra and linear interpolate within them. \*---------------------------------------------------------------------------*/ @@ -82,8 +82,17 @@ public: inline Type interpolate ( const vector& position, - const label nCell, - const label facei = -1 + const label cellI, + const label faceI = -1 + ) const; + + //- Interpolate field to the given point in the tetrahedron + // defined by the given indices. + inline Type interpolate + ( + const vector& position, + const tetIndices& tetIs, + const label faceI = -1 ) const; }; diff --git a/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/interpolationCellPointI.H b/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/interpolationCellPointI.H index 16c555224ce..35171984cf6 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/interpolationCellPointI.H +++ b/src/finiteVolume/interpolation/interpolation/interpolationCellPoint/interpolationCellPointI.H @@ -31,13 +31,13 @@ inline Type Foam::interpolationCellPoint<Type>::interpolate const cellPointWeight& cpw ) const { - const FixedList<scalar, 4>& weights = cpw.weights(); - const FixedList<label, 3>& faceVertices = cpw.faceVertices(); + const List<scalar>& weights = cpw.weights(); + const List<label>& faceVertices = cpw.faceVertices(); - Type t = psip_[faceVertices[0]]*weights[0]; - t += psip_[faceVertices[1]]*weights[1]; - t += psip_[faceVertices[2]]*weights[2]; - t += this->psi_[cpw.cell()]*weights[3]; + Type t = this->psi_[cpw.cell()]*weights[0]; + t += psip_[faceVertices[0]]*weights[1]; + t += psip_[faceVertices[1]]*weights[2]; + t += psip_[faceVertices[2]]*weights[3]; return t; } @@ -47,11 +47,66 @@ template<class Type> inline Type Foam::interpolationCellPoint<Type>::interpolate ( const vector& position, - const label celli, - const label facei + const label cellI, + const label faceI ) const { - return interpolate(cellPointWeight(this->pMesh_, position, celli, facei)); + return interpolate(cellPointWeight(this->pMesh_, position, cellI, faceI)); +} + + +template<class Type> +inline Type Foam::interpolationCellPoint<Type>::interpolate +( + const vector& position, + const tetIndices& tetIs, + const label faceI +) const +{ + // Assumes that the position is consistent with the supplied + // tetIndices. Does not pay attention to whether or not faceI is + // supplied or not - the result will be essentially the same. + // Performs a consistency check, however. + + if (faceI >= 0) + { + if (faceI != tetIs.face()) + { + FatalErrorIn + ( + "inline Type Foam::interpolationCellPoint<Type>::interpolate" + "(" + "const vector& position, " + "const tetIndices& tetIs, " + "const label faceI" + ") const" + ) + << "specified face " << faceI << " inconsistent with the face " + << "stored by tetIndices: " << tetIs.face() + << exit(FatalError); + } + } + + List<scalar> weights; + + tetIs.tet(this->pMesh_).barycentric(position, weights); + + const faceList& pFaces = this->pMesh_.faces(); + + const face& f = pFaces[tetIs.face()]; + + // Order of weights is the same as that of the vertices of the tet, i.e. + // cellCentre, faceBasePt, facePtA, facePtB. + + Type t = this->psi_[tetIs.cell()]*weights[0]; + + t += psip_[f[tetIs.faceBasePt()]]*weights[1]; + + t += psip_[f[tetIs.facePtA()]]*weights[2]; + + t += psip_[f[tetIs.facePtB()]]*weights[3]; + + return t; } diff --git a/src/finiteVolume/interpolation/interpolation/interpolationCellPointFace/interpolationCellPointFace.C b/src/finiteVolume/interpolation/interpolation/interpolationCellPointFace/interpolationCellPointFace.C index e075cb90143..c583a6555c2 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationCellPointFace/interpolationCellPointFace.C +++ b/src/finiteVolume/interpolation/interpolation/interpolationCellPointFace/interpolationCellPointFace.C @@ -56,8 +56,8 @@ template<class Type> Type interpolationCellPointFace<Type>::interpolate ( const vector& position, - const label nCell, - const label facei + const label cellI, + const label faceI ) const { Type ts[4]; @@ -68,10 +68,10 @@ Type interpolationCellPointFace<Type>::interpolate Type t = pTraits<Type>::zero; // only use face information when the position is on a face - if (facei < 0) + if (faceI < 0) { - const vector& cellCentre = this->pMesh_.cellCentres()[nCell]; - const labelList& cellFaces = this->pMesh_.cells()[nCell]; + const vector& cellCentre = this->pMesh_.cellCentres()[cellI]; + const labelList& cellFaces = this->pMesh_.cells()[cellI]; vector projection = position - cellCentre; tetPoints[3] = cellCentre; @@ -85,9 +85,9 @@ Type interpolationCellPointFace<Type>::interpolate label closestFace = -1; scalar minDistance = GREAT; - forAll(cellFaces, facei) + forAll(cellFaces, faceI) { - label nFace = cellFaces[facei]; + label nFace = cellFaces[faceI]; vector normal = this->pMeshFaceAreas_[nFace]; normal /= mag(normal); @@ -160,10 +160,10 @@ Type interpolationCellPointFace<Type>::interpolate { minDistance = GREAT; - label facei = 0; - while (facei < cellFaces.size() && !foundTet) + label faceI = 0; + while (faceI < cellFaces.size() && !foundTet) { - label nFace = cellFaces[facei]; + label nFace = cellFaces[faceI]; if (nFace < this->pMeshFaceAreas_.size()) { foundTet = findTet @@ -179,7 +179,7 @@ Type interpolationCellPointFace<Type>::interpolate minDistance ); } - facei++; + faceI++; } } @@ -217,16 +217,16 @@ Type interpolationCellPointFace<Type>::interpolate } else { - label patchi = + label patchI = this->pMesh_.boundaryMesh().whichPatch(closestFace); // If the boundary patch is not empty use the face value // else use the cell value - if (this->psi_.boundaryField()[patchi].size()) + if (this->psi_.boundaryField()[patchI].size()) { - ts[2] = this->psi_.boundaryField()[patchi] + ts[2] = this->psi_.boundaryField()[patchI] [ - this->pMesh_.boundaryMesh()[patchi].whichFace + this->pMesh_.boundaryMesh()[patchI].whichFace ( closestFace ) @@ -234,11 +234,11 @@ Type interpolationCellPointFace<Type>::interpolate } else { - ts[2] = this->psi_[nCell]; + ts[2] = this->psi_[cellI]; } } - ts[3] = this->psi_[nCell]; + ts[3] = this->psi_[cellI]; for (label n=0; n<4; n++) { @@ -251,9 +251,9 @@ Type interpolationCellPointFace<Type>::interpolate else { Info<< "interpolationCellPointFace<Type>::interpolate" - << "(const vector&, const label nCell) const : " + << "(const vector&, const label cellI) const : " << "search failed; using closest cellFace value" << endl - << "cell number " << nCell << tab + << "cell number " << cellI << tab << "position " << position << endl; if (closestFace < psis_.size()) @@ -262,16 +262,16 @@ Type interpolationCellPointFace<Type>::interpolate } else { - label patchi = + label patchI = this->pMesh_.boundaryMesh().whichPatch(closestFace); // If the boundary patch is not empty use the face value // else use the cell value - if (this->psi_.boundaryField()[patchi].size()) + if (this->psi_.boundaryField()[patchI].size()) { - t = this->psi_.boundaryField()[patchi] + t = this->psi_.boundaryField()[patchI] [ - this->pMesh_.boundaryMesh()[patchi].whichFace + this->pMesh_.boundaryMesh()[patchI].whichFace ( closestFace ) @@ -279,7 +279,7 @@ Type interpolationCellPointFace<Type>::interpolate } else { - t = this->psi_[nCell]; + t = this->psi_[cellI]; } } } @@ -289,7 +289,7 @@ Type interpolationCellPointFace<Type>::interpolate bool foundTriangle = findTriangle ( position, - facei, + faceI, tetPointLabels, phi ); @@ -304,48 +304,48 @@ Type interpolationCellPointFace<Type>::interpolate } // ... and the face value - if (facei < psis_.size()) + if (faceI < psis_.size()) { - t += phi[2]*psis_[facei]; + t += phi[2]*psis_[faceI]; } else { - label patchi = this->pMesh_.boundaryMesh().whichPatch(facei); + label patchI = this->pMesh_.boundaryMesh().whichPatch(faceI); // If the boundary patch is not empty use the face value // else use the cell value - if (this->psi_.boundaryField()[patchi].size()) + if (this->psi_.boundaryField()[patchI].size()) { - t += phi[2]*this->psi_.boundaryField()[patchi] - [this->pMesh_.boundaryMesh()[patchi].whichFace(facei)]; + t += phi[2]*this->psi_.boundaryField()[patchI] + [this->pMesh_.boundaryMesh()[patchI].whichFace(faceI)]; } else { - t += phi[2]*this->psi_[nCell]; + t += phi[2]*this->psi_[cellI]; } } } else { // use face value only - if (facei < psis_.size()) + if (faceI < psis_.size()) { - t = psis_[facei]; + t = psis_[faceI]; } else { - label patchi = this->pMesh_.boundaryMesh().whichPatch(facei); + label patchI = this->pMesh_.boundaryMesh().whichPatch(faceI); // If the boundary patch is not empty use the face value // else use the cell value - if (this->psi_.boundaryField()[patchi].size()) + if (this->psi_.boundaryField()[patchI].size()) { - t = this->psi_.boundaryField()[patchi] - [this->pMesh_.boundaryMesh()[patchi].whichFace(facei)]; + t = this->psi_.boundaryField()[patchI] + [this->pMesh_.boundaryMesh()[patchI].whichFace(faceI)]; } else { - t = this->psi_[nCell]; + t = this->psi_[cellI]; } } } diff --git a/src/finiteVolume/interpolation/interpolation/interpolationCellPointFace/interpolationCellPointFace.H b/src/finiteVolume/interpolation/interpolation/interpolationCellPointFace/interpolationCellPointFace.H index e32b2ad68bb..fb2f9954f81 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationCellPointFace/interpolationCellPointFace.H +++ b/src/finiteVolume/interpolation/interpolation/interpolationCellPointFace/interpolationCellPointFace.H @@ -99,8 +99,8 @@ public: Type interpolate ( const vector& position, - const label nCell, - const label facei = -1 + const label cellI, + const label faceI = -1 ) const; }; diff --git a/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/cellPointWeightWallModified/cellPointWeightWallModified.C b/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/cellPointWeightWallModified/cellPointWeightWallModified.C index 5448de2dafe..8716ade026b 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/cellPointWeightWallModified/cellPointWeightWallModified.C +++ b/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/cellPointWeightWallModified/cellPointWeightWallModified.C @@ -24,9 +24,6 @@ License \*---------------------------------------------------------------------------*/ #include "cellPointWeightWallModified.H" -#include "wallPolyPatch.H" -#include "polyMesh.H" -#include "polyBoundaryMesh.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -34,36 +31,30 @@ Foam::cellPointWeightWallModified::cellPointWeightWallModified ( const polyMesh& mesh, const vector& position, - const label cellIndex, - const label faceIndex + const label cellI, + const label faceI ) : - cellPointWeight(mesh, position, cellIndex, faceIndex) + cellPointWeight(mesh, position, cellI, faceI) { - if (faceIndex < 0) - { - findTetrahedron(mesh, position, cellIndex); - } - else + // findTetrahedron or findTriangle will already have been called + // by the cellPointWeight constructor + + if (faceI >= 0) { const polyBoundaryMesh& bm = mesh.boundaryMesh(); - label patchI = bm.whichPatch(faceIndex); + label patchI = bm.whichPatch(faceI); if (patchI != -1) { if (isA<wallPolyPatch>(bm[patchI])) { // Apply cell centre value wall faces - weights_[0] = 0.0; + weights_[0] = 1.0; weights_[1] = 0.0; weights_[2] = 0.0; - weights_[3] = 1.0; + weights_[3] = 0.0; } } - else - { - // Interpolate - findTriangle(mesh, position, faceIndex); - } } } diff --git a/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/cellPointWeightWallModified/cellPointWeightWallModified.H b/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/cellPointWeightWallModified/cellPointWeightWallModified.H index db4e35575d8..0e12a145284 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/cellPointWeightWallModified/cellPointWeightWallModified.H +++ b/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/cellPointWeightWallModified/cellPointWeightWallModified.H @@ -36,6 +36,9 @@ SourceFiles #define cellPointWeightWallModified_H #include "cellPointWeight.H" +#include "wallPolyPatch.H" +#include "polyMesh.H" +#include "polyBoundaryMesh.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -61,8 +64,8 @@ public: ( const polyMesh& mesh, const vector& position, - const label nCell, - const label facei = -1 + const label cellI, + const label faceI = -1 ); }; diff --git a/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/interpolationCellPointWallModified.H b/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/interpolationCellPointWallModified.H index d7b35c9a383..8bef893c58e 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/interpolationCellPointWallModified.H +++ b/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/interpolationCellPointWallModified.H @@ -74,8 +74,17 @@ public: inline Type interpolate ( const vector& position, - const label nCell, - const label facei = -1 + const label cellI, + const label faceI = -1 + ) const; + + //- Interpolate field to the given point in the tetrahedron + // defined by the given indices. + inline Type interpolate + ( + const vector& position, + const tetIndices& tetIs, + const label faceI = -1 ) const; }; diff --git a/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/interpolationCellPointWallModifiedI.H b/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/interpolationCellPointWallModifiedI.H index d0284f0b0f5..d0ed41eef73 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/interpolationCellPointWallModifiedI.H +++ b/src/finiteVolume/interpolation/interpolation/interpolationCellPointWallModified/interpolationCellPointWallModifiedI.H @@ -31,13 +31,13 @@ inline Type Foam::interpolationCellPointWallModified<Type>::interpolate const cellPointWeightWallModified& cpw ) const { - const FixedList<scalar, 4>& weights = cpw.weights(); - const FixedList<label, 3>& faceVertices = cpw.faceVertices(); + const List<scalar>& weights = cpw.weights(); + const List<label>& faceVertices = cpw.faceVertices(); - Type t = this->psip_[faceVertices[0]]*weights[0]; - t += this->psip_[faceVertices[1]]*weights[1]; - t += this->psip_[faceVertices[2]]*weights[2]; - t += this->psi_[cpw.cell()]*weights[3]; + Type t = this->psi_[cpw.cell()]*weights[0]; + t += this->psip_[faceVertices[0]]*weights[1]; + t += this->psip_[faceVertices[1]]*weights[2]; + t += this->psip_[faceVertices[2]]*weights[3]; return t; } @@ -47,21 +47,73 @@ template<class Type> inline Type Foam::interpolationCellPointWallModified<Type>::interpolate ( const vector& position, - const label celli, - const label facei + const label cellI, + const label faceI ) const { - return - interpolate + return interpolate + ( + cellPointWeightWallModified ( - cellPointWeightWallModified + this->pMesh_, + position, + cellI, + faceI + ) + ); +} + + +template<class Type> +inline Type Foam::interpolationCellPointWallModified<Type>::interpolate +( + const vector& position, + const tetIndices& tetIs, + const label faceI +) const +{ + if (faceI >= 0) + { + if (faceI != tetIs.face()) + { + FatalErrorIn ( - this->pMesh_, - position, - celli, - facei + "inline Type " + "Foam::interpolationCellPointWallModifie<Type>::interpolate" + "(" + "const vector& position, " + "const tetIndices& tetIs, " + "const label faceI" + ") const" ) - ); + << "specified face " << faceI << " inconsistent with the face " + << "stored by tetIndices: " << tetIs.face() + << exit(FatalError); + } + + const polyBoundaryMesh& bm = this->pMesh_.boundaryMesh(); + label patchI = bm.whichPatch(faceI); + + if (patchI != -1) + { + if (isA<wallPolyPatch>(bm[patchI])) + { + Type t = this->psi_[tetIs.cell()]; + + return t; + } + } + } + + // If the wall face selection did not return, then use the normal + // interpolate method + + return interpolationCellPoint<Type>::interpolate + ( + position, + tetIs, + faceI + ); } diff --git a/src/finiteVolume/interpolation/interpolation/interpolationPoint/interpolationPoint.H b/src/finiteVolume/interpolation/interpolation/interpolationPoint/interpolationPoint.H index a3dc106eb02..46f102187fc 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationPoint/interpolationPoint.H +++ b/src/finiteVolume/interpolation/interpolation/interpolationPoint/interpolationPoint.H @@ -81,8 +81,8 @@ public: inline Type interpolate ( const vector& position, - const label nCell, - const label facei = -1 + const label cellI, + const label faceI = -1 ) const; }; diff --git a/src/finiteVolume/interpolation/interpolation/interpolationPoint/interpolationPointI.H b/src/finiteVolume/interpolation/interpolation/interpolationPoint/interpolationPointI.H index e297e569fca..624bb9f5627 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationPoint/interpolationPointI.H +++ b/src/finiteVolume/interpolation/interpolation/interpolationPoint/interpolationPointI.H @@ -39,13 +39,13 @@ template<class Type> inline Type Foam::interpolationPoint<Type>::interpolate ( const vector& position, - const label celli, - const label facei + const label cellI, + const label faceI ) const { return interpolate ( - pointMVCWeight(this->pMesh_, position, celli, facei) + pointMVCWeight(this->pMesh_, position, cellI, faceI) ); } diff --git a/src/finiteVolume/interpolation/interpolation/interpolationPoint/pointMVCWeight.H b/src/finiteVolume/interpolation/interpolation/interpolationPoint/pointMVCWeight.H index a1cfd4507b0..9cd2bec95b3 100644 --- a/src/finiteVolume/interpolation/interpolation/interpolationPoint/pointMVCWeight.H +++ b/src/finiteVolume/interpolation/interpolation/interpolationPoint/pointMVCWeight.H @@ -119,8 +119,8 @@ public: ( const polyMesh& mesh, const vector& position, - const label nCell, - const label facei = -1 + const label cellI, + const label faceI = -1 ); diff --git a/src/lagrangian/basic/Cloud/Cloud.C b/src/lagrangian/basic/Cloud/Cloud.C index 8f817df7fb1..2b39e286f26 100644 --- a/src/lagrangian/basic/Cloud/Cloud.C +++ b/src/lagrangian/basic/Cloud/Cloud.C @@ -30,6 +30,41 @@ License #include "mapPolyMesh.H" #include "Time.H" #include "OFstream.H" +#include "wallPolyPatch.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +template<class ParticleType> +const Foam::scalar Foam::Cloud<ParticleType>::trackingCorrectionTol = 1e-5; + + +// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // + +template<class ParticleType> +void Foam::Cloud<ParticleType>::calcCellWallFaces() const +{ + cellWallFacesPtr_.reset(new PackedBoolList(pMesh().nCells(), false)); + + PackedBoolList& cellWallFaces = cellWallFacesPtr_(); + + const polyBoundaryMesh& patches = pMesh().boundaryMesh(); + + forAll(patches, patchI) + { + if (isA<wallPolyPatch>(patches[patchI])) + { + const polyPatch& patch = patches[patchI]; + + const labelList& pFaceCells = patch.faceCells(); + + forAll(pFaceCells, pFCI) + { + cellWallFaces[pFaceCells[pFCI]] = true; + } + } + } +} + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -43,7 +78,11 @@ Foam::Cloud<ParticleType>::Cloud cloud(pMesh), IDLList<ParticleType>(), polyMesh_(pMesh), - particleCount_(0) + particleCount_(0), + labels_(), + cellTree_(), + nTrackingRescues_(), + cellWallFacesPtr_() { IDLList<ParticleType>::operator=(particles); } @@ -60,7 +99,11 @@ Foam::Cloud<ParticleType>::Cloud cloud(pMesh, cloudName), IDLList<ParticleType>(), polyMesh_(pMesh), - particleCount_(0) + particleCount_(0), + labels_(), + cellTree_(), + nTrackingRescues_(), + cellWallFacesPtr_() { IDLList<ParticleType>::operator=(particles); } @@ -68,6 +111,250 @@ Foam::Cloud<ParticleType>::Cloud // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +template<class ParticleType> +void Foam::Cloud<ParticleType>::findCellFacePt +( + const point& pt, + label& cellI, + label& tetFaceI, + label& tetPtI +) const +{ + cellI = -1; + tetFaceI = -1; + tetPtI = -1; + + const indexedOctree<treeDataCell>& tree = cellTree(); + + // Find nearest cell to the point + + pointIndexHit info = tree.findNearest(pt, sqr(GREAT)); + + if (info.hit()) + { + label nearestCellI = tree.shapes().cellLabels()[info.index()]; + + // Check the nearest cell to see if the point is inside. + findFacePt(nearestCellI, pt, tetFaceI, tetPtI); + + if (tetFaceI != -1) + { + // Point was in the nearest cell + + cellI = nearestCellI; + + return; + } + else + { + // Check the other possible cells that the point may be in + + labelList testCells = tree.findIndices(pt); + + forAll(testCells, pCI) + { + label testCellI = tree.shapes().cellLabels()[testCells[pCI]]; + + if (testCellI == nearestCellI) + { + // Don't retest the nearest cell + + continue; + } + + // Check the test cell to see if the point is inside. + findFacePt(testCellI, pt, tetFaceI, tetPtI); + + if (tetFaceI != -1) + { + // Point was in the test cell + + cellI = testCellI; + + return; + } + } + } + } + else + { + FatalErrorIn + ( + "void Foam::Cloud<ParticleType>::findCellFacePt" + "(" + "const point& pt, " + "label& cellI, " + "label& tetFaceI, " + "label& tetPtI" + ") const" + ) << "Did not find nearest cell in search tree." + << abort(FatalError); + } +} + + +template<class ParticleType> +void Foam::Cloud<ParticleType>::findFacePt +( + label cellI, + const point& pt, + label& tetFaceI, + label& tetPtI +) const +{ + tetFaceI = -1; + tetPtI = -1; + + List<tetIndices> cellTets = polyMeshTetDecomposition::cellTetIndices + ( + polyMesh_, + cellI + ); + + forAll(cellTets, tetI) + { + const tetIndices& cellTetIs = cellTets[tetI]; + + if (inTet(pt, cellTetIs.tet(polyMesh_))) + { + tetFaceI = cellTetIs.face(); + tetPtI = cellTetIs.tetPt(); + + return; + } + } +} + + +template<class ParticleType> +bool Foam::Cloud<ParticleType>::inTet +( + const point& pt, + const tetPointRef& tet +) const +{ + // For robustness, assuming that the point is in the tet unless + // "definitively" shown otherwise by obtaining a positive dot + // product greater than a tolerance of SMALL. + + // The tet is defined: tet(Cc, tetBasePt, pA, pB) where the normal + // vectors and base points for the half-space planes are: + // area[0] = tet.Sa(); + // area[1] = tet.Sb(); + // area[2] = tet.Sc(); + // area[3] = tet.Sd(); + // planeBase[0] = tetBasePt = tet.b() + // planeBase[1] = ptA = tet.c() + // planeBase[2] = tetBasePt = tet.b() + // planeBase[3] = tetBasePt = tet.b() + + vector n = vector::zero; + + { + // 0, a + const point& basePt = tet.b(); + + n = tet.Sa(); + n /= (mag(n) + VSMALL); + + if (((pt - basePt) & n) > SMALL) + { + return false; + } + } + + { + // 1, b + const point& basePt = tet.c(); + + n = tet.Sb(); + n /= (mag(n) + VSMALL); + + if (((pt - basePt) & n) > SMALL) + { + return false; + } + } + + { + // 2, c + const point& basePt = tet.b(); + + n = tet.Sc(); + n /= (mag(n) + VSMALL); + + if (((pt - basePt) & n) > SMALL) + { + return false; + } + } + + { + // 3, d + const point& basePt = tet.b(); + + n = tet.Sd(); + n /= (mag(n) + VSMALL); + + if (((pt - basePt) & n) > SMALL) + { + return false; + } + } + + return true; +} + + +template<class ParticleType> +const Foam::indexedOctree<Foam::treeDataCell>& +Foam::Cloud<ParticleType>::cellTree() const +{ + if (cellTree_.empty()) + { + treeBoundBox overallBb(polyMesh_.points()); + + Random rndGen(261782); + + overallBb = overallBb.extend(rndGen, 1E-4); + overallBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL); + overallBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL); + + cellTree_.reset + ( + new indexedOctree<treeDataCell> + ( + treeDataCell + ( + false, // not cache bb + polyMesh_ + ), + overallBb, + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity + ) + ); + } + + return cellTree_(); +} + + +template<class ParticleType> +const Foam::PackedBoolList& Foam::Cloud<ParticleType>::cellHasWallFaces() +const +{ + if (!cellWallFacesPtr_.valid()) + { + calcCellWallFaces(); + } + + return cellWallFacesPtr_(); +} + + + template<class ParticleType> Foam::label Foam::Cloud<ParticleType>::getNewParticleID() const { @@ -131,6 +418,9 @@ void Foam::Cloud<ParticleType>::move(TrackingData& td) pIter().stepFraction() = 0; } + // Reset nTrackingRescues + nTrackingRescues_ = 0; + // While there are particles to transfer while (true) { @@ -162,29 +452,29 @@ void Foam::Cloud<ParticleType>::move(TrackingData& td) { // If we are running in parallel and the particle is on a // boundary face - if (Pstream::parRun() && p.facei_ >= pMesh().nInternalFaces()) + if (Pstream::parRun() && p.faceI_ >= pMesh().nInternalFaces()) { - label patchi = pbm.whichPatch(p.facei_); + label patchI = pbm.whichPatch(p.faceI_); // ... and the face is on a processor patch // prepare it for transfer - if (procPatchIndices[patchi] != -1) + if (procPatchIndices[patchI] != -1) { label n = neighbourProcIndices [ refCast<const processorPolyPatch> ( - pbm[patchi] + pbm[patchI] ).neighbProcNo() ]; - p.prepareForParallelTransfer(patchi, td); + p.prepareForParallelTransfer(patchI, td); particleTransferLists[n].append(this->remove(&p)); patchIndexTransferLists[n].append ( - procPatchNeighbours[patchi] + procPatchNeighbours[patchI] ); } } @@ -270,15 +560,22 @@ void Foam::Cloud<ParticleType>::move(TrackingData& td) { ParticleType& newp = newpIter(); - label patchi = procPatches[receivePatchIndex[pI++]]; + label patchI = procPatches[receivePatchIndex[pI++]]; - newp.correctAfterParallelTransfer(patchi, td); + newp.correctAfterParallelTransfer(patchI, td); addParticle(newParticles.remove(&newp)); } } } } + + reduce(nTrackingRescues_, sumOp<label>()); + + if (nTrackingRescues_ > 0) + { + Info<< nTrackingRescues_ << " tracking rescue corrections" << endl; + } } @@ -294,24 +591,30 @@ void Foam::Cloud<ParticleType>::autoMap(const mapPolyMesh& mapper) const labelList& reverseCellMap = mapper.reverseCellMap(); const labelList& reverseFaceMap = mapper.reverseFaceMap(); + // Reset stored data that relies on the mesh + cellTree_.clear(); + cellWallFacesPtr_.clear(); + forAllIter(typename Cloud<ParticleType>, *this, pIter) { - if (reverseCellMap[pIter().celli_] >= 0) + if (reverseCellMap[pIter().cellI_] >= 0) { - pIter().celli_ = reverseCellMap[pIter().celli_]; + pIter().cellI_ = reverseCellMap[pIter().cellI_]; - if (pIter().facei_ >= 0 && reverseFaceMap[pIter().facei_] >= 0) + if (pIter().faceI_ >= 0 && reverseFaceMap[pIter().faceI_] >= 0) { - pIter().facei_ = reverseFaceMap[pIter().facei_]; + pIter().faceI_ = reverseFaceMap[pIter().faceI_]; } else { - pIter().facei_ = -1; + pIter().faceI_ = -1; } + + pIter().initCellFacePt(); } else { - label trackStartCell = mapper.mergedCell(pIter().celli_); + label trackStartCell = mapper.mergedCell(pIter().cellI_); if (trackStartCell < 0) { @@ -319,9 +622,14 @@ void Foam::Cloud<ParticleType>::autoMap(const mapPolyMesh& mapper) } vector p = pIter().position(); + const_cast<vector&>(pIter().position()) = polyMesh_.cellCentres()[trackStartCell]; + pIter().stepFraction() = 0; + + pIter().initCellFacePt(); + pIter().track(p); } } diff --git a/src/lagrangian/basic/Cloud/Cloud.H b/src/lagrangian/basic/Cloud/Cloud.H index 25cf3fce33d..0c9b32ebac5 100644 --- a/src/lagrangian/basic/Cloud/Cloud.H +++ b/src/lagrangian/basic/Cloud/Cloud.H @@ -40,6 +40,11 @@ SourceFiles #include "IOField.H" #include "IOFieldField.H" #include "polyMesh.H" +#include "indexedOctree.H" +#include "treeDataCell.H" +#include "tetPointRef.H" +#include "polyMeshTetDecomposition.H" +#include "PackedBoolList.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -78,15 +83,28 @@ class Cloud //- Overall count of particles ever created. Never decreases. mutable label particleCount_; - //- Temporary storage for addressing. Used in findFaces. + //- Temporary storage for addressing. Used in findTris. mutable DynamicList<label> labels_; + //- Search tree to allow spatial tet searching + mutable autoPtr<indexedOctree<treeDataCell> > cellTree_; + + //- Count of how many tracking rescue corrections have been + // applied + mutable label nTrackingRescues_; + + //- Does the cell have wall faces + mutable autoPtr<PackedBoolList> cellWallFacesPtr_; + // Private Member Functions //- Initialise cloud on IO constructor void initCloud(const bool checkClass); + //- Find all cells which have wall faces + void calcCellWallFaces() const; + //- Read cloud properties dictionary void readCloudUniformProperties(); @@ -115,6 +133,10 @@ public: //- Name of cloud properties dictionary static word cloudPropertiesName; + //- Fraction of distance to tet centre to move a particle to + // 'rescue' it from a tracking problem + static const scalar trackingCorrectionTol; + // Constructors @@ -163,27 +185,27 @@ public: } //- Is this global face an internal face? - bool internalFace(const label facei) const + bool internalFace(const label faceI) const { - return polyMesh_.isInternalFace(facei); + return polyMesh_.isInternalFace(faceI); } //- Is this global face a boundary face? - bool boundaryFace(const label facei) const + bool boundaryFace(const label faceI) const { - return !internalFace(facei); + return !internalFace(faceI); } //- Which patch is this global face on - label facePatch(const label facei) const + label facePatch(const label faceI) const { - return polyMesh_.boundaryMesh().whichPatch(facei); + return polyMesh_.boundaryMesh().whichPatch(faceI); } //- Which face of this patch is this global face - label patchFace(const label patchi, const label facei) const + label patchFace(const label patchI, const label faceI) const { - return polyMesh_.boundaryMesh()[patchi].whichFace(facei); + return polyMesh_.boundaryMesh()[patchI].whichFace(faceI); } label size() const @@ -191,6 +213,61 @@ public: return IDLList<ParticleType>::size(); }; + //- Find the cell, tetFaceI and tetPtI for the given + // position + void findCellFacePt + ( + const point& pt, + label& cellI, + label& tetFaceI, + label& tetPtI + ) const; + + //- Find the tetFaceI and tetPtI for the given position in + // the supplied cell, tetFaceI and tetPtI = -1 if not + // found + void findFacePt + ( + label cellI, + const point& pt, + label& tetFaceI, + label& tetPtI + ) const; + + //- Test if the given position is inside the give tet + bool inTet + ( + const point& pt, + const tetPointRef& tet + ) const; + + //- Build (if necessary) and return the cell search tree + const indexedOctree<treeDataCell>& cellTree() const; + + //- Return nTrackingRescues + label nTrackingRescues() const + { + return nTrackingRescues_; + } + + //- Increment the nTrackingRescues counter + void trackingRescue() const + { + nTrackingRescues_++; + } + + //- Whether each cell has any wall faces (demand driven data) + const PackedBoolList& cellHasWallFaces() const; + + //- Switch to specify if particles of the cloud can return + // non-zero wall distance values. By default, assume + // that they can't (default for wallImpactDistance in + // Particle is 0.0). + virtual bool hasWallImpactDistance() const + { + return false; + } + // Iterators diff --git a/src/lagrangian/basic/Cloud/CloudIO.C b/src/lagrangian/basic/Cloud/CloudIO.C index 388fba1c574..c12d12d6a51 100644 --- a/src/lagrangian/basic/Cloud/CloudIO.C +++ b/src/lagrangian/basic/Cloud/CloudIO.C @@ -126,6 +126,13 @@ void Foam::Cloud<ParticleType>::initCloud(const bool checkClass) << " " << ioP.path() << nl << " assuming the initial cloud contains 0 particles." << endl; } + + forAllIter(typename Cloud<ParticleType>, *this, pIter) + { + ParticleType& p = pIter(); + + p.initCellFacePt(); + } } @@ -140,7 +147,11 @@ Foam::Cloud<ParticleType>::Cloud : cloud(pMesh), polyMesh_(pMesh), - particleCount_(0) + particleCount_(0), + labels_(), + cellTree_(), + nTrackingRescues_(), + cellWallFacesPtr_() { initCloud(checkClass); } @@ -156,7 +167,11 @@ Foam::Cloud<ParticleType>::Cloud : cloud(pMesh, cloudName), polyMesh_(pMesh), - particleCount_(0) + particleCount_(0), + labels_(), + cellTree_(), + nTrackingRescues_(), + cellWallFacesPtr_() { initCloud(checkClass); } diff --git a/src/lagrangian/basic/Make/options b/src/lagrangian/basic/Make/options index e69de29bb2d..4b2f0a059fb 100644 --- a/src/lagrangian/basic/Make/options +++ b/src/lagrangian/basic/Make/options @@ -0,0 +1,5 @@ +EXE_INC = \ + -I$(LIB_SRC)/meshTools/lnInclude + +LIB_LIBS = \ + -lmeshTools diff --git a/src/lagrangian/basic/Particle/Particle.C b/src/lagrangian/basic/Particle/Particle.C index 99c00f07e55..9ad51cdeaff 100644 --- a/src/lagrangian/basic/Particle/Particle.C +++ b/src/lagrangian/basic/Particle/Particle.C @@ -29,73 +29,20 @@ License #include "symmetryPolyPatch.H" #include "cyclicPolyPatch.H" #include "processorPolyPatch.H" -#include "wallPolyPatch.H" #include "transform.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -template<class ParticleType> -void Foam::Particle<ParticleType>::findFaces -( - const vector& position, - DynamicList<label>& faceList -) const -{ - const polyMesh& mesh = cloud_.polyMesh_; - const labelList& faces = mesh.cells()[celli_]; - const vector& C = mesh.cellCentres()[celli_]; - - faceList.clear(); - forAll(faces, i) - { - label facei = faces[i]; - scalar lam = lambda(C, position, facei); - - if ((lam > 0) && (lam < 1.0)) - { - faceList.append(facei); - } - } -} - - -template<class ParticleType> -void Foam::Particle<ParticleType>::findFaces -( - const vector& position, - const label celli, - const scalar stepFraction, - DynamicList<label>& faceList -) const -{ - const polyMesh& mesh = cloud_.pMesh(); - const labelList& faces = mesh.cells()[celli]; - const vector& C = mesh.cellCentres()[celli]; - - faceList.clear(); - forAll(faces, i) - { - label facei = faces[i]; - scalar lam = lambda(C, position, facei, stepFraction); - - if ((lam > 0) && (lam < 1.0)) - { - faceList.append(facei); - } - } -} - - template<class ParticleType> template<class TrackData> void Foam::Particle<ParticleType>::prepareForParallelTransfer ( - const label patchi, + const label patchI, TrackData& td ) { // Convert the face index to be local to the processor patch - facei_ = patchFace(patchi, facei_); + faceI_ = patchFace(patchI, faceI_); } @@ -103,15 +50,15 @@ template<class ParticleType> template<class TrackData> void Foam::Particle<ParticleType>::correctAfterParallelTransfer ( - const label patchi, + const label patchI, TrackData& td ) { const processorPolyPatch& ppp = refCast<const processorPolyPatch> - (cloud_.pMesh().boundaryMesh()[patchi]); + (cloud_.pMesh().boundaryMesh()[patchI]); - celli_ = ppp.faceCells()[facei_]; + cellI_ = ppp.faceCells()[faceI_]; if (!ppp.parallel()) { @@ -123,7 +70,7 @@ void Foam::Particle<ParticleType>::correctAfterParallelTransfer } else { - const tensor& T = ppp.forwardT()[facei_]; + const tensor& T = ppp.forwardT()[faceI_]; transformPosition(T); static_cast<ParticleType&>(*this).transformProperties(T); } @@ -140,23 +87,48 @@ void Foam::Particle<ParticleType>::correctAfterParallelTransfer } else { - position_ -= ppp.separation()[facei_]; + position_ -= ppp.separation()[faceI_]; static_cast<ParticleType&>(*this).transformProperties ( - -ppp.separation()[facei_] + -ppp.separation()[faceI_] ); } } + tetFaceI_ = faceI_ + ppp.start(); + + // Faces either side of a coupled patch have matched base indices, + // tetPtI is specified relative to the base point, already and + // opposite circulation directions by design, so if the vertices + // are: + // source: + // face (a b c d e f) + // fPtI 0 1 2 3 4 5 + // + + // destination: + // face (a f e d c b) + // fPtI 0 1 2 3 4 5 + // + + // where a is the base point of the face are matching , and we + // have fPtI = 1 on the source processor face, i.e. vertex b, then + // this because of the face circulation direction change, vertex c + // is the characterising point on the destination processor face, + // giving the destination fPtI as: + // fPtI_d = f.size() - 1 - fPtI_s = 6 - 1 - 1 = 4 + // This relationship can be verified for other points and sizes of + // face. + + tetPtI_ = cloud_.polyMesh_.faces()[tetFaceI_].size() - 1 - tetPtI_; + // Reset the face index for the next tracking operation if (stepFraction_ > (1.0 - SMALL)) { stepFraction_ = 1.0; - facei_ = -1; + faceI_ = -1; } else { - facei_ += ppp.start(); + faceI_ += ppp.start(); } } @@ -168,27 +140,55 @@ Foam::Particle<ParticleType>::Particle ( const Cloud<ParticleType>& cloud, const vector& position, - const label celli + const label cellI, + const label tetFaceI, + const label tetPtI ) : cloud_(cloud), position_(position), - celli_(celli), - facei_(-1), + cellI_(cellI), + faceI_(-1), stepFraction_(0.0), + tetFaceI_(tetFaceI), + tetPtI_(tetPtI), origProc_(Pstream::myProcNo()), origId_(cloud_.getNewParticleID()) {} +template<class ParticleType> +Foam::Particle<ParticleType>::Particle +( + const Cloud<ParticleType>& cloud, + const vector& position, + const label cellI +) +: + cloud_(cloud), + position_(position), + cellI_(cellI), + faceI_(-1), + stepFraction_(0.0), + tetFaceI_(-1), + tetPtI_(-1), + origProc_(Pstream::myProcNo()), + origId_(cloud_.getNewParticleID()) +{ + initCellFacePt(); +} + + template<class ParticleType> Foam::Particle<ParticleType>::Particle(const Particle<ParticleType>& p) : cloud_(p.cloud_), position_(p.position_), - celli_(p.celli_), - facei_(p.facei_), + cellI_(p.cellI_), + faceI_(p.faceI_), stepFraction_(p.stepFraction_), + tetFaceI_(p.tetFaceI_), + tetPtI_(p.tetPtI_), origProc_(p.origProc_), origId_(p.origId_) {} @@ -204,7 +204,7 @@ Foam::label Foam::Particle<ParticleType>::track TrackData& td ) { - facei_ = -1; + faceI_ = -1; // Tracks to endPosition or stop on boundary while (!onBoundary() && stepFraction_ < 1.0 - SMALL) @@ -212,7 +212,7 @@ Foam::label Foam::Particle<ParticleType>::track stepFraction_ += trackToFace(endPosition, td)*(1.0 - stepFraction_); } - return facei_; + return faceI_; } @@ -224,6 +224,7 @@ Foam::label Foam::Particle<ParticleType>::track(const vector& endPosition) return track(endPosition, dummyTd); } + template<class ParticleType> template<class TrackData> Foam::scalar Foam::Particle<ParticleType>::trackToFace @@ -234,175 +235,414 @@ Foam::scalar Foam::Particle<ParticleType>::trackToFace { const polyMesh& mesh = cloud_.polyMesh_; - DynamicList<label>& faces = cloud_.labels_; - findFaces(endPosition, faces); + const faceList& pFaces = mesh.faces(); + const pointField& pPts = mesh.points(); + const vectorField& pC = mesh.cellCentres(); + + faceI_ = -1; - facei_ = -1; scalar trackFraction = 0.0; - if (faces.empty()) // inside cell + // Minimum tetrahedron decomposition of each cell of the mesh into + // using the cell centre, base point on face, and further two + // points on the face. For each face of n points, there are n - 2 + // tets generated. + + // The points for each tet are organised to match those used in the + // tetrahedron class, supplying them in the order: + // Cc, basePt, pA, pB + // where: + // + Cc is the cell centre; + // + basePt is the base point on the face; + // + pA and pB are the remaining points on the face, such that + // the circulation, {basePt, pA, pB} produces a positive + // normal by the right-hand rule. pA and pB are chosen from + // tetPtI_ do accomplish this depending if the cell owns the + // face, tetPtI_ is the vertex that characterises the tet, and + // is the first vertex on the tet when circulating around the + // face. Therefore, the same tetPtI represents the same face + // triangle for both the owner and neighbour cell. + // + // Each tet has its four triangles represented in the same order: + // 0) tri joining a tet to the tet across the face in next cell. + // This is the triangle opposite Cc. + // 1) tri joining a tet to the tet that is in the same cell, but + // belongs to the face that shares the edge of the current face + // that doesn't contain basePt. This is the triangle opposite + // basePt. + + // 2) tri joining a tet to the tet that is in the same cell, but + // belongs to the face that shares the tet-edge (basePt - pB). + // This may be on the same face, or a different one. This is + // the triangle opposite basePt. This is the triangle opposite + // pA. + + // 4) tri joining a tet to the tet that is in the same cell, but + // belongs to the face that shares the tet-edge (basePt - pA). + // This may be on the same face, or a different one. This is + // the triangle opposite basePt. This is the triangle opposite + // pA. + + // Which tri (0..3) of the tet has been crossed + label triI = -1; + + // Determine which face was actually crossed. lambdaMin < SMALL + // is considered a trigger for a tracking correction towards the + // current tet centre. + scalar lambdaMin = VGREAT; + + DynamicList<label>& tris = cloud_.labels_; + + // Tet indices that will be set by hitWallFaces if a wall face is + // to be hit, or are set when any wall tri of a tet is hit. + // Carries the description of the tet on which the cell face has + // been hit. For the case of being set in hitWallFaces, this may + // be a different tet to the one that the particle occupies. + tetIndices faceHitTetIs; + + do { - trackFraction = 1.0; - position_ = endPosition; - } - else // hit face - { - scalar lambdaMin = GREAT; + if (triI != -1) + { + // Change tet ownership because a tri face has been crossed + tetNeighbour(triI); + } + + const Foam::face& f = pFaces[tetFaceI_]; + + bool own = (mesh.faceOwner()[tetFaceI_] == cellI_); + + label tetBasePtI = mesh.tetBasePtIs()[tetFaceI_]; + + label basePtI = f[tetBasePtI]; - if (faces.size() == 1) + label facePtI = (tetPtI_ + tetBasePtI) % f.size(); + label otherFacePtI = f.fcIndex(facePtI); + + label fPtAI = -1; + label fPtBI = -1; + + if (own) { - lambdaMin = lambda(position_, endPosition, faces[0], stepFraction_); - facei_ = faces[0]; + fPtAI = facePtI; + fPtBI = otherFacePtI; } else { - // If the particle has to cross more than one cell to reach the - // endPosition, we check which way to go. - // If one of the faces is a boundary face and the particle is - // outside, we choose the boundary face. - // The particle is outside if one of the lambda's is > 1 or < 0 - forAll(faces, i) + fPtAI = otherFacePtI; + fPtBI = facePtI; + } + + tetPointRef tet + ( + pC[cellI_], + pPts[basePtI], + pPts[f[fPtAI]], + pPts[f[fPtBI]] + ); + + if (lambdaMin < SMALL) + { + // Apply tracking correction towards tet centre + + position_ += + Cloud<ParticleType>::trackingCorrectionTol + *(tet.centre() - position_); + + cloud_.trackingRescue(); + + return trackFraction; + } + + if (triI != -1 && mesh.moving()) + { + // Mesh motion requires stepFraction to be correct for + // each tracking portion, so trackToFace must return after + // every lambda calculation. + return trackFraction; + } + + FixedList<vector, 4> tetAreas; + + tetAreas[0] = tet.Sa(); + tetAreas[1] = tet.Sb(); + tetAreas[2] = tet.Sc(); + tetAreas[3] = tet.Sd(); + + FixedList<label, 4> tetPlaneBasePtIs; + + tetPlaneBasePtIs[0] = basePtI; + tetPlaneBasePtIs[1] = f[fPtAI]; + tetPlaneBasePtIs[2] = basePtI; + tetPlaneBasePtIs[3] = basePtI; + + findTris(endPosition, tris, tet, tetAreas, tetPlaneBasePtIs); + + // Reset variables for new track + triI = -1; + lambdaMin = VGREAT; + + // Sets a value for lambdaMin and faceI_ if a wall face is hit + // by the track. + hitWallFaces(position_, endPosition, lambdaMin, faceHitTetIs); + + // Did not hit any tet tri faces, and no wall face has been + // found to hit. + if (tris.empty() && faceI_ < 0) + { + position_ = endPosition; + + return 1.0; + } + else + { + // Loop over all found tris and see if any of them find a + // lambda value smaller than that found for a wall face. + forAll(tris, i) { - scalar lam = - lambda(position_, endPosition, faces[i], stepFraction_); + label tI = tris[i]; + + scalar lam = tetLambda + ( + position_, + endPosition, + triI, + tetAreas[tI], + tetPlaneBasePtIs[tI], + cellI_, + tetFaceI_, + tetPtI_ + ); if (lam < lambdaMin) { lambdaMin = lam; - facei_ = faces[i]; + + triI = tI; } } } - bool internalFace = cloud_.internalFace(facei_); + if (triI == 0) + { + // This must be a cell face crossing + faceI_ = tetFaceI_; - // For warped faces the particle can be 'outside' the cell. - // This will yield a lambda larger than 1, or smaller than 0 - // For values < 0, the particle travels away from the cell - // and we don't move the particle, only change cell. - // For values larger than 1, we move the particle to endPosition only. - if (lambdaMin > 0.0) + // Set the faceHitTetIs to those for the current tet in case a + // wall interaction is required with the cell face + faceHitTetIs = tetIndices + ( + cellI_, + tetFaceI_, + tetBasePtI, + fPtAI, + fPtBI, + tetPtI_ + ); + } + else if (triI > 0) + { + // A tri was found to be crossed before a wall face was hit (if any) + faceI_ = -1; + } + + // The particle can be 'outside' the tet. This will yield a + // lambda larger than 1, or smaller than 0. For values < 0, + // the particle travels away from the tet and we don't move + // the particle, only change tet/cell. For values larger than + // 1, we move the particle to endPosition before the tet/cell + // change. + if (lambdaMin > SMALL) { if (lambdaMin <= 1.0) { - trackFraction = lambdaMin; - position_ += trackFraction*(endPosition - position_); + trackFraction += lambdaMin*(1 - trackFraction); + + position_ += lambdaMin*(endPosition - position_); } else { trackFraction = 1.0; + position_ = endPosition; } } - else if (static_cast<ParticleType&>(*this).softImpact()) + else { - // Soft-sphere particles can travel outside the domain - // but we don't use lambda since this the particle - // is going away from face - trackFraction = 1.0; - position_ = endPosition; + // Set lambdaMin to zero to force a towards-tet-centre + // correction. + lambdaMin = 0.0; } - // change cell - if (internalFace) // Internal face + } while (faceI_ < 0); + + if (cloud_.internalFace(faceI_)) + { + // Change tet ownership because a tri face has been crossed, + // in general this is: + // tetNeighbour(triI); + // but triI must be 0; + // No modifications are required for triI = 0, no call required to + // tetNeighbour(0); + + if (cellI_ == mesh.faceOwner()[faceI_]) + { + cellI_ = mesh.faceNeighbour()[faceI_]; + } + else if (cellI_ == mesh.faceNeighbour()[faceI_]) { - if (celli_ == mesh.faceOwner()[facei_]) + cellI_ = mesh.faceOwner()[faceI_]; + } + else + { + FatalErrorIn + ( + "Particle::trackToFace(const vector&, TrackData&)" + ) << "addressing failure" << nl + << abort(FatalError); + } + } + else + { + ParticleType& p = static_cast<ParticleType&>(*this); + + label origFaceI = faceI_; + label patchI = patch(faceI_); + + // No action taken for tetPtI_ for tetFaceI_ here, handled by + // patch interaction call or later during processor transfer. + + if + ( + !p.hitPatch + ( + mesh.boundaryMesh()[patchI], + td, + patchI, + trackFraction, + faceHitTetIs + ) + ) + { + // Did patch interaction model switch patches? + if (faceI_ != origFaceI) { - celli_ = mesh.faceNeighbour()[facei_]; + patchI = patch(faceI_); } - else if (celli_ == mesh.faceNeighbour()[facei_]) + + const polyPatch& patch = mesh.boundaryMesh()[patchI]; + + if (isA<wedgePolyPatch>(patch)) { - celli_ = mesh.faceOwner()[facei_]; + p.hitWedgePatch + ( + static_cast<const wedgePolyPatch&>(patch), td + ); } - else + else if (isA<symmetryPolyPatch>(patch)) { - FatalErrorIn + p.hitSymmetryPatch ( - "Particle::trackToFace(const vector&, TrackData&)" - )<< "addressing failure" << nl - << abort(FatalError); + static_cast<const symmetryPolyPatch&>(patch), td + ); + } + else if (isA<cyclicPolyPatch>(patch)) + { + p.hitCyclicPatch + ( + static_cast<const cyclicPolyPatch&>(patch), td + ); + } + else if (isA<processorPolyPatch>(patch)) + { + p.hitProcessorPatch + ( + static_cast<const processorPolyPatch&>(patch), td + ); + } + else if (isA<wallPolyPatch>(patch)) + { + p.hitWallPatch + ( + static_cast<const wallPolyPatch&>(patch), td, faceHitTetIs + ); + } + else + { + p.hitPatch(patch, td); } } - else + } + + if (lambdaMin < SMALL) + { + // Apply tracking correction towards tet centre. + // Generate current tet to find centre to apply correction. + + tetPointRef tet = currentTet(); + + position_ += + Cloud<ParticleType>::trackingCorrectionTol + *(tet.centre() - position_); + + if + ( + cloud_.hasWallImpactDistance() + && !cloud_.internalFace(faceHitTetIs.face()) + && cloud_.cellHasWallFaces()[faceHitTetIs.cell()] + ) { - ParticleType& p = static_cast<ParticleType&>(*this); + const polyBoundaryMesh& patches = mesh.boundaryMesh(); - // Soft-sphere algorithm ignores the boundary - if (p.softImpact()) - { - trackFraction = 1.0; - position_ = endPosition; - } + label fI = faceHitTetIs.face(); - label origFacei = facei_; - label patchi = patch(facei_); + label patchI = patches.patchID()[fI - mesh.nInternalFaces()]; - if (!p.hitPatch(mesh.boundaryMesh()[patchi], td, patchi)) + if (isA<wallPolyPatch>(patches[patchI])) { - // Did patch interaction model switch patches? - if (facei_ != origFacei) - { - patchi = patch(facei_); - } - const polyPatch& patch = mesh.boundaryMesh()[patchi]; - - if (isA<wedgePolyPatch>(patch)) - { - p.hitWedgePatch - ( - static_cast<const wedgePolyPatch&>(patch), td - ); - } - else if (isA<symmetryPolyPatch>(patch)) - { - p.hitSymmetryPatch - ( - static_cast<const symmetryPolyPatch&>(patch), td + // In the case of collision with a wall where there is + // a non-zero wallImpactDistance, it is possible for + // there to be a tracking correction required to bring + // the particle into the domain, but the position of + // the particle is further from the wall than the tet + // centre, in which case the normal correction can be + // counter-productive, i.e. pushes the particle + // further out of the domain. In this case it is the + // position that hit the wall that is in need of a + // rescue correction. + + triPointRef wallTri = faceHitTetIs.faceTri(mesh); + + tetPointRef wallTet = faceHitTetIs.tet(mesh); + + vector nHat = wallTri.normal(); + nHat /= mag(nHat); + + const ParticleType& p = static_cast<const ParticleType&>(*this); + + scalar r = p.wallImpactDistance(nHat); + + // Removing (approximately) the wallTri normal + // component of the existing correction, to avoid the + // situation where the existing correction in the wall + // normal direction is larger towards the wall than + // the new correction is away from it. + position_ += + Cloud<ParticleType>::trackingCorrectionTol + *( + (wallTet.centre() - (position_ + r*nHat)) + - (nHat & (tet.centre() - position_))*nHat ); - } - else if (isA<cyclicPolyPatch>(patch)) - { - p.hitCyclicPatch - ( - static_cast<const cyclicPolyPatch&>(patch), td - ); - } - else if (isA<processorPolyPatch>(patch)) - { - p.hitProcessorPatch - ( - static_cast<const processorPolyPatch&>(patch), td - ); - } - else if (isA<wallPolyPatch>(patch)) - { - p.hitWallPatch - ( - static_cast<const wallPolyPatch&>(patch), td - ); - } - else - { - p.hitPatch(patch, td); - } } } - } - // If the trackFraction = 0 something went wrong. - // Either the particle is flipping back and forth across a face perhaps - // due to velocity interpolation errors or it is in a "hole" in the mesh - // caused by face warpage. - // In both cases resolve the positional ambiguity by moving the particle - // slightly towards the cell-centre. - if (trackFraction < SMALL) - { - position_ += 1.0e-3*(mesh.cellCentres()[celli_] - position_); + cloud_.trackingRescue(); } return trackFraction; } + template<class ParticleType> Foam::scalar Foam::Particle<ParticleType>::trackToFace ( @@ -413,6 +653,7 @@ Foam::scalar Foam::Particle<ParticleType>::trackToFace return trackToFace(endPosition, dummyTd); } + template<class ParticleType> void Foam::Particle<ParticleType>::transformPosition(const tensor& T) { @@ -436,7 +677,9 @@ bool Foam::Particle<ParticleType>::hitPatch ( const polyPatch&, TrackData&, - const label + const label, + const scalar, + const tetIndices& ) { return false; @@ -451,7 +694,17 @@ void Foam::Particle<ParticleType>::hitWedgePatch TrackData& ) { - vector nf = wpp.faceAreas()[wpp.whichFace(facei_)]; + FatalErrorIn + ( + "void Foam::Particle<ParticleType>::hitWedgePatch" + "(" + "const wedgePolyPatch& wpp, " + "TrackData&" + ")" + ) << "Hitting a wedge patch should not be possible." + << abort(FatalError); + + vector nf = normal(); nf /= mag(nf); static_cast<ParticleType&>(*this).transformProperties(I - 2.0*nf*nf); @@ -466,7 +719,7 @@ void Foam::Particle<ParticleType>::hitSymmetryPatch TrackData& ) { - vector nf = spp.faceAreas()[spp.whichFace(facei_)]; + vector nf = normal(); nf /= mag(nf); static_cast<ParticleType&>(*this).transformProperties(I - 2.0*nf*nf); @@ -481,11 +734,16 @@ void Foam::Particle<ParticleType>::hitCyclicPatch TrackData& ) { -// label patchFacei_ = cpp.whichFace(facei_); + // label patchFaceI_ = cpp.whichFace(faceI_); + + faceI_ = cpp.transformGlobalFace(faceI_); + + cellI_ = cloud_.polyMesh_.faceOwner()[faceI_]; - facei_ = cpp.transformGlobalFace(facei_); + tetFaceI_ = faceI_; - celli_ = cloud_.polyMesh_.faceOwner()[facei_]; + // See note in correctAfterParallelTransfer for tetPtI_ addressing. + tetPtI_ = cloud_.polyMesh_.faces()[tetFaceI_].size() - 1 - tetPtI_; // Now the particle is on the receiving side @@ -522,7 +780,8 @@ template<class TrackData> void Foam::Particle<ParticleType>::hitWallPatch ( const wallPolyPatch& spp, - TrackData& + TrackData&, + const tetIndices& ) {} @@ -549,7 +808,7 @@ bool Foam::operator== return ( pA.origProc() == pB.origProc() - && pA.origId() == pB.origId() + && pA.origId() == pB.origId() ); } diff --git a/src/lagrangian/basic/Particle/Particle.H b/src/lagrangian/basic/Particle/Particle.H index 39c21de0767..8dbdebd4e1b 100644 --- a/src/lagrangian/basic/Particle/Particle.H +++ b/src/lagrangian/basic/Particle/Particle.H @@ -38,6 +38,10 @@ Description #include "faceList.H" #include "typeInfo.H" #include "OFstream.H" +#include "tetPointRef.H" +#include "FixedList.H" +#include "polyMeshTetDecomposition.H" +#include "wallPolyPatch.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -125,14 +129,23 @@ protected: vector position_; //- Index of the cell it is in - label celli_; + label cellI_; //- Face index if the particle is on a face otherwise -1 - label facei_; + label faceI_; //- Fraction of time-step completed scalar stepFraction_; + //- Index of the face that owns the decomposed tet that the + // particle is in + label tetFaceI_; + + //- Index of the point on the face that defines the decomposed + // tet that the particle is in. Relative to the face base + // point. + label tetPtI_; + //- Originating processor id label origProc_; @@ -142,54 +155,82 @@ protected: // Private Member Functions - //- Return the 'lambda' value for the position, p, on the face, - // where, p = from + lamda*(to - from) - // for non-static meshes - inline scalar lambda + //- Find the tet tri faces between position and tet centre + inline void findTris ( - const vector& from, - const vector& to, - const label facei, - const scalar stepFraction + const vector& position, + DynamicList<label>& faceList, + const tetPointRef& tet, + const FixedList<vector, 4>& tetAreas, + const FixedList<label, 4>& tetPlaneBasePtIs ) const; - //- Return the 'lambda' value for the position, p, on the face, - // where, p = from + lamda*(to - from) - // for static meshes - inline scalar lambda + //- Find the lambda value for the line to-from across the + // given tri face, where p = from + lambda*(to - from) + inline scalar tetLambda ( const vector& from, const vector& to, - const label facei + const label triI, + const vector& tetArea, + const label tetPlaneBasePtI, + const label cellI, + const label tetFaceI, + const label tetPtI ) const; - //- Find the faces between position and cell centre - void findFaces + //- Find the lambda value for a moving tri face + inline scalar movingTetLambda + ( + const vector& from, + const vector& to, + const label triI, + const vector& tetArea, + const label tetPlaneBasePtI, + const label cellI, + const label tetFaceI, + const label tetPtI + ) const; + + //- Modify the tet owner data by crossing triI + inline void tetNeighbour(label triI); + + //- Cross the from the given face across the given edge of the + // given cell to find the resulting face and tetPtI + inline void crossEdgeConnectedFace ( - const vector& position, - DynamicList<label>& faceList - ) const; + const label& cellI, + label& tetFaceI, + label& tetPtI, + const edge& e + ); - //- Find the faces between position and cell centre - void findFaces + //- Hit wall faces in the current cell if the + //- wallImpactDistance is non-zero. They may not be in + //- different tets to the current. + inline void hitWallFaces ( - const vector& position, - const label celli, - const scalar stepFraction, - DynamicList<label>& faceList - ) const; + const vector& from, + const vector& to, + scalar& lambdaMin, + tetIndices& closestTetIs + ); // Patch interactions - //- Overridable function to handle the particle hitting a patch - // Executed before other patch-hitting functions + //- Overridable function to handle the particle hitting a + // patch. Executed before other patch-hitting functions. + // trackFraction is passed in to allow mesh motion to + // interpolate in time to the correct face state. template<class TrackData> bool hitPatch ( const polyPatch&, TrackData& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ); //- Overridable function to handle the particle hitting a wedgePatch @@ -231,7 +272,8 @@ protected: void hitWallPatch ( const wallPolyPatch&, - TrackData& td + TrackData& td, + const tetIndices& tetIs ); //- Overridable function to handle the particle hitting a @@ -264,12 +306,12 @@ protected: //- Convert global addressing to the processor patch // local equivalents template<class TrackData> - void prepareForParallelTransfer(const label patchi, TrackData& td); + void prepareForParallelTransfer(const label patchI, TrackData& td); //- Convert processor patch addressing to the global equivalents - // and set the celli to the face-neighbour + // and set the cellI to the face-neighbour template<class TrackData> - void correctAfterParallelTransfer(const label patchi, TrackData& td); + void correctAfterParallelTransfer(const label patchI, TrackData& td); public: @@ -293,7 +335,18 @@ public: ( const Cloud<ParticleType>&, const vector& position, - const label celli + const label cellI, + const label tetFaceI, + const label tetPtI + ); + + //- Construct from components, tetFaceI_ and tetPtI_ are not + // supplied so they will be deduced by a search + Particle + ( + const Cloud<ParticleType>&, + const vector& position, + const label cellI ); //- Construct from Istream @@ -355,17 +408,6 @@ public: // Access - //- Return true if particle is in cell - inline bool inCell() const; - - //- Return true if position is in cell i - inline bool inCell - ( - const vector& position, - const label celli, - const scalar stepFraction - ) const; - //- Return current particle position inline const vector& position() const; @@ -378,6 +420,35 @@ public: //- Return current cell particle is in inline label cell() const; + //- Return current tet face particle is in + inline label& tetFace(); + + //- Return current tet face particle is in + inline label tetFace() const; + + //- Return current tet face particle is in + inline label& tetPt(); + + //- Return current tet face particle is in + inline label tetPt() const; + + //- Return the indices of the current tet that the + // particle occupies. + inline tetIndices currentTetIndices() const; + + //- Return the geometry of the current tet that the + // particle occupies. + inline tetPointRef currentTet() const; + + //- Return the normal of the tri on tetFaceI_ for the + // current tet. + inline vector normal() const; + + //- Return the normal of the tri on tetFaceI_ for the + // current tet at the start of the timestep, i.e. based + // on oldPoints + inline vector oldNormal() const; + //- Return current face particle is on otherwise -1 inline label& face(); @@ -396,17 +467,21 @@ public: // Check + //- Check the stored cell value (setting if necessary) and + // initialise the tetFace and tetPt values + inline void initCellFacePt(); + //- Is the particle on the boundary/(or outside the domain)? inline bool onBoundary() const; //- Which patch is particle on - inline label patch(const label facei) const; + inline label patch(const label faceI) const; //- Which face of this patch is this particle on inline label patchFace ( - const label patchi, - const label facei + const label patchI, + const label faceI ) const; //- The nearest distance to a wall that diff --git a/src/lagrangian/basic/Particle/ParticleI.H b/src/lagrangian/basic/Particle/ParticleI.H index 43fd1d38065..35d658d1153 100644 --- a/src/lagrangian/basic/Particle/ParticleI.H +++ b/src/lagrangian/basic/Particle/ParticleI.H @@ -24,243 +24,776 @@ License \*---------------------------------------------------------------------------*/ #include "polyMesh.H" -#include "wallPolyPatch.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // template<class ParticleType> -inline Foam::scalar Foam::Particle<ParticleType>::lambda +inline void Foam::Particle<ParticleType>::findTris +( + const vector& position, + DynamicList<label>& faceList, + const tetPointRef& tet, + const FixedList<vector, 4>& tetAreas, + const FixedList<label, 4>& tetPlaneBasePtIs +) const +{ + faceList.clear(); + + const point Ct = tet.centre(); + + for (label i = 0; i < 4; i++) + { + scalar lambda = tetLambda + ( + Ct, + position, + i, + tetAreas[i], + tetPlaneBasePtIs[i], + cellI_, + tetFaceI_, + tetPtI_ + ); + + if ((lambda > 0.0) && (lambda < 1.0)) + { + faceList.append(i); + } + } +} + + +template<class ParticleType> +inline Foam::scalar Foam::Particle<ParticleType>::tetLambda +( + const vector& from, + const vector& to, + const label triI, + const vector& n, + const label tetPlaneBasePtI, + const label cellI, + const label tetFaceI, + const label tetPtI +) const +{ + const polyMesh& mesh = cloud_.polyMesh_; + const pointField& pPts = mesh.points(); + + if (mesh.moving()) + { + return movingTetLambda + ( + from, + to, + triI, + n, + tetPlaneBasePtI, + cellI, + tetFaceI, + tetPtI + ); + } + + const point& base = pPts[tetPlaneBasePtI]; + + scalar lambdaNumerator = (base - from) & n; + scalar lambdaDenominator = (to - from) & n; + + if (mag(lambdaDenominator) < SMALL) + { + if (mag(lambdaNumerator) < SMALL) + { + // Track starts on the face, and is potentially + // parallel to it. +-SMALL)/+-SMALL is not a good + // comparison, return 0.0, in anticipation of tet + // centre correction. + + return 0.0; + } + else + { + if (mag((to - from)) < SMALL) + { + // Zero length track, not along the face, face + // cannot be crossed. + + return GREAT; + } + else + { + // Trajectory is non-zero and parallel to face + + lambdaDenominator = sign(lambdaDenominator)*SMALL; + } + } + } + + return lambdaNumerator/lambdaDenominator; +} + + + +template<class ParticleType> +inline Foam::scalar Foam::Particle<ParticleType>::movingTetLambda ( const vector& from, const vector& to, - const label facei, - const scalar stepFraction + const label triI, + const vector& n, + const label tetPlaneBasePtI, + const label cellI, + const label tetFaceI, + const label tetPtI ) const { const polyMesh& mesh = cloud_.polyMesh_; - bool movingMesh = mesh.moving(); + const pointField& pPts = mesh.points(); + const pointField& oldPPts = mesh.oldPoints(); + + // Base point of plane at end of motion + const point& b = pPts[tetPlaneBasePtI]; + + // n: Normal of plane at end of motion + + // Base point of plane at start of timestep + const point& b00 = oldPPts[tetPlaneBasePtI]; + + // Base point of plane at start of tracking portion (cast forward by + // stepFraction) + point b0 = b00 + stepFraction_*(b - b00); + + // Normal of plane at start of tracking portion + vector n0 = vector::zero; - if (movingMesh) { - vector Sf = mesh.faceAreas()[facei]; - Sf /= mag(Sf); - vector Cf = mesh.faceCentres()[facei]; + tetIndices tetIs(cellI, tetFaceI, tetPtI, mesh); + + // tet at timestep start + tetPointRef tet00 = tetIs.oldTet(mesh); - // patch interaction - if (!cloud_.internalFace(facei)) + // tet at timestep end + tetPointRef tet = tetIs.tet(mesh); + + point tet0PtA = tet00.a() + stepFraction_*(tet.a() - tet00.a()); + point tet0PtB = tet00.b() + stepFraction_*(tet.b() - tet00.b()); + point tet0PtC = tet00.c() + stepFraction_*(tet.c() - tet00.c()); + point tet0PtD = tet00.d() + stepFraction_*(tet.d() - tet00.d()); + + // Tracking portion start tet (cast forward by stepFraction) + tetPointRef tet0(tet0PtA, tet0PtB, tet0PtC, tet0PtD); + + switch (triI) { - label patchi = patch(facei); - const polyPatch& patch = mesh.boundaryMesh()[patchi]; + case 0: + { + n0 = tet0.Sa(); + break; + } + case 1: + { + n0 = tet0.Sb(); + break; + } + case 2: + { + n0 = tet0.Sc(); + break; + } + case 3: + { + n0 = tet0.Sd(); + break; + } + default: + { + break; + } + } + } + + if (mag(n0) < SMALL) + { + // If the old normal is zero (for example in layer addition) + // then use the current normal; - // move reference point for wall - if (isA<wallPolyPatch>(patch)) + n0 = n; + } + + scalar lambdaNumerator = 0; + scalar lambdaDenominator = 0; + + vector dP = to - from; + vector dN = n - n0; + vector dB = b - b0; + vector dS = from - b0; + + if (mag(dN) > SMALL) + { + scalar a = (dP - dB) & dN; + scalar b = ((dP - dB) & n0) + (dS & dN); + scalar c = dS & n0; + + if (mag(a) > SMALL) + { + + // Solve quadratic for lambda + scalar discriminant = sqr(b) - 4.0*a*c; + + if (discriminant < 0) + { + // Imaginary roots only - face not crossed + return GREAT; + } + else { - const vector& C = mesh.cellCentres()[celli_]; - scalar CCf = mag((C - Cf) & Sf); - // check if distance between cell centre and face centre - // is larger than wallImpactDistance - const ParticleType& p = - static_cast<const ParticleType&>(*this); - if (CCf > p.wallImpactDistance(Sf)) + // Numerical Recipes in C, + // Second Edition (1992), + // Section 5.6. + // q = -0.5*(b + sgn(b)*sqrt(b^2 - 4ac)) + // x1 = q/a + // x2 = c/q + + scalar q = -0.5*(b + sign(b)*Foam::sqrt(discriminant)); + + if (mag(q) < VSMALL) { - Cf -=p.wallImpactDistance(Sf)*Sf; + // If q is zero, then l1 = q/a is the required + // value of lambda, and is zero. + + return 0.0; + } + + scalar l1 = q/a; + scalar l2 = c/q; + + // There will be two roots, a big one and a little + // one, choose the little one. + + if (mag(l1) < mag(l2)) + { + return l1; + } + else + { + return l2; } } } + { + // When a is zero, solve the first order polynomial - // for a moving mesh we need to reconstruct the old - // Sf and Cf from oldPoints (they aren't stored) - - const vectorField& oldPoints = mesh.oldPoints(); + lambdaNumerator = -c; + lambdaDenominator = b; + } + } + else + { + // when n = n0 is zero, there is no plane rotation, solve the + // first order polynomial - vector Cf00 = mesh.faces()[facei].centre(oldPoints); - vector Cf0 = Cf00 + stepFraction*(Cf - Cf00); + lambdaNumerator = -(dS & n0); + lambdaDenominator = ((dP - dB) & n0); - vector Sf00 = mesh.faces()[facei].normal(oldPoints); + } - // for layer addition Sf00 = vector::zero and we use Sf - if (mag(Sf00) > SMALL) + if (mag(lambdaDenominator) < SMALL) + { + if (mag(lambdaNumerator) < SMALL) { - Sf00 /= mag(Sf00); + // Track starts on the face, and is potentially + // parallel to it. +-SMALL)/+-SMALL is not a good + // comparison, return 0.0, in anticipation of tet + // centre correction. + + return 0.0; } else { - Sf00 = Sf; + if (mag((to - from)) < SMALL) + { + // Zero length track, not along the face, face + // cannot be crossed. + + return GREAT; + } + else + { + // Trajectory is non-zero and parallel to face + + lambdaDenominator = sign(lambdaDenominator)*SMALL; + } } + } + + return lambdaNumerator/lambdaDenominator; +} + + +template<class ParticleType> +inline void Foam::Particle<ParticleType>::tetNeighbour(label triI) +{ + const polyMesh& mesh = cloud_.polyMesh_; - scalar magSfDiff = mag(Sf - Sf00); + const labelList& pOwner = mesh.faceOwner(); + const faceList& pFaces = mesh.faces(); - // check if the face is rotating - if (magSfDiff > SMALL) + bool own = (pOwner[tetFaceI_] == cellI_); + + const Foam::face& f = pFaces[tetFaceI_]; + + label tetBasePtI = mesh.tetBasePtIs()[tetFaceI_]; + + label facePtI = (tetPtI_ + tetBasePtI) % f.size(); + label otherFacePtI = f.fcIndex(facePtI); + + if (tetBasePtI == -1) + { + FatalErrorIn + ( + "inline void Foam::Particle<ParticleType>::tetNeighbour(label triI)" + ) + << "No base point for face " << tetFaceI_ << ", " << f + << ", produces a valid tet decomposition." + << abort(FatalError); + } + + switch (triI) + { + case 0: { - vector Sf0 = Sf00 + stepFraction*(Sf - Sf00); - - // find center of rotation - vector omega = Sf0 ^ Sf; - scalar magOmega = mag(omega); - omega /= magOmega + SMALL; - vector n0 = omega ^ Sf0; - scalar lam = ((Cf - Cf0) & Sf)/(n0 & Sf); - vector r0 = Cf0 + lam*n0; - - // solve '(p - r0) & Sfp = 0', where - // p = from + lambda*(to - from) - // Sfp = Sf0 + lambda*(Sf - Sf0) - // which results in the quadratic eq. - // a*lambda^2 + b*lambda + c = 0 - vector alpha = from - r0; - vector beta = to - from; - scalar a = beta & (Sf - Sf0); - scalar b = (alpha & (Sf - Sf0)) + (beta & Sf0); - scalar c = alpha & Sf0; - - if (mag(a) > SMALL) - { - // solve the second order polynomial - scalar ap = b/a; - scalar bp = c/a; - scalar cp = ap*ap - 4.0*bp; + // Crossing this triangle changes tet to that in the + // neighbour cell over tetFaceI + + // Modification of cellI_ will happen by other indexing, + // tetFaceI_ and tetPtI don't change. - if (cp < 0.0) + break; + } + case 1: + { + crossEdgeConnectedFace + ( + cellI_, + tetFaceI_, + tetPtI_, + Foam::edge(f[facePtI], f[otherFacePtI]) + ); + + break; + } + case 2: + { + if (own) + { + if (tetPtI_ < f.size() - 2) { - // imaginary roots only - return GREAT; + tetPtI_ = f.fcIndex(tetPtI_); } else { - scalar l1 = -0.5*(ap - ::sqrt(cp)); - scalar l2 = -0.5*(ap + ::sqrt(cp)); - - // one root is around 0-1, while - // the other is very large in mag - if (mag(l1) < mag(l2)) - { - return l1; - } - else - { - return l2; - } + crossEdgeConnectedFace + ( + cellI_, + tetFaceI_, + tetPtI_, + Foam::edge(f[tetBasePtI], f[otherFacePtI]) + ); } } else { - // when a==0, solve the first order polynomial - return (-c/b); + if (tetPtI_ > 1) + { + tetPtI_ = f.rcIndex(tetPtI_); + } + else + { + crossEdgeConnectedFace + ( + cellI_, + tetFaceI_, + tetPtI_, + Foam::edge(f[tetBasePtI], f[facePtI]) + ); + } } + + break; } - else // no rotation + case 3: { - vector alpha = from - Cf0; - vector beta = to - from - (Cf - Cf0); - scalar lambdaNominator = alpha & Sf; - scalar lambdaDenominator = beta & Sf; - - // check if trajectory is parallel to face - if (mag(lambdaDenominator) < SMALL) + if (own) + { + if (tetPtI_ > 1) + { + tetPtI_ = f.rcIndex(tetPtI_); + } + else + { + crossEdgeConnectedFace + ( + cellI_, + tetFaceI_, + tetPtI_, + Foam::edge(f[tetBasePtI], f[facePtI]) + ); + } + } + else { - if (lambdaDenominator < 0.0) + if (tetPtI_ < f.size() - 2) { - lambdaDenominator = -SMALL; + tetPtI_ = f.fcIndex(tetPtI_); } else { - lambdaDenominator = SMALL; + crossEdgeConnectedFace + ( + cellI_, + tetFaceI_, + tetPtI_, + Foam::edge(f[tetBasePtI], f[otherFacePtI]) + ); } } - return (-lambdaNominator/lambdaDenominator); + break; + } + default: + { + FatalErrorIn + ( + "inline void " + "Foam::Particle<ParticleType>::tetNeighbour(label triI)" + ) + << "Tet tri face index error, can only be 0..3, supplied " + << triI << nl + << abort(FatalError); + + break; } - } - else - { - // mesh is static and stepFraction is not needed - return lambda(from, to, facei); } } - template<class ParticleType> -inline Foam::scalar Foam::Particle<ParticleType>::lambda +inline void Foam::Particle<ParticleType>::crossEdgeConnectedFace ( - const vector& from, - const vector& to, - const label facei -) const + const label& cellI, + label& tetFaceI, + label& tetPtI, + const edge& e +) { const polyMesh& mesh = cloud_.polyMesh_; - vector Sf = mesh.faceAreas()[facei]; - Sf /= mag(Sf); - vector Cf = mesh.faceCentres()[facei]; + const faceList& pFaces = mesh.faces(); + const cellList& pCells = mesh.cells(); + + const Foam::face& f = pFaces[tetFaceI]; + + const Foam::cell& thisCell = pCells[cellI]; - // patch interaction - if (!cloud_.internalFace(facei)) + forAll(thisCell, cFI) { - label patchi = patch(facei); - const polyPatch& patch = mesh.boundaryMesh()[patchi]; + // Loop over all other faces of this cell and + // find the one that shares this edge - // move reference point for wall - if (isA<wallPolyPatch>(patch)) + label fI = thisCell[cFI]; + + if (tetFaceI == fI) { - const vector& C = mesh.cellCentres()[celli_]; - scalar CCf = mag((C - Cf) & Sf); - // check if distance between cell centre and face centre - // is larger than wallImpactDistance - const ParticleType& p = static_cast<const ParticleType&>(*this); - if (CCf > p.wallImpactDistance(Sf)) - { - Cf -=p.wallImpactDistance(Sf)*Sf; - } + continue; } - } - scalar lambdaNominator = (Cf - from) & Sf; - scalar lambdaDenominator = (to - from) & Sf; + const Foam::face& otherFace = pFaces[fI]; - // check if trajectory is parallel to face - if (mag(lambdaDenominator) < SMALL) - { - if (lambdaDenominator < 0.0) + label edDir = otherFace.edgeDirection(e); + + if (edDir == 0) { - lambdaDenominator = -SMALL; + continue; } else { - lambdaDenominator = SMALL; - } - } + //Found edge on other face + tetFaceI = fI; - return lambdaNominator/lambdaDenominator; -} + label eIndex = -1; + if (edDir == 1) + { + // Edge is in the forward circulation of this face, so + // work with the start point of the edge -template<class ParticleType> -inline bool Foam::Particle<ParticleType>::inCell() const -{ - DynamicList<label>& faces = cloud_.labels_; - findFaces(position_, faces); + eIndex = findIndex(otherFace, e.start()); + } + else + { + // edDir == -1, so the edge is in the reverse + // circulation of this face, so work with the end + // point of the edge - return (!faces.size()); + eIndex = findIndex(otherFace, e.end()); + } + + label tetBasePtI = mesh.tetBasePtIs()[fI]; + + if (tetBasePtI == -1) + { + FatalErrorIn + ( + "inline void " + "Foam::Particle<ParticleType>::crossEdgeConnectedFace" + "(" + "const label& cellI," + "label& tetFaceI," + "label& tetPtI," + "const edge& e" + ")" + ) + << "No base point for face " << fI << ", " << f + << ", produces a decomposition that has a minimum " + << "volume greater than tolerance." + << abort(FatalError); + } + + // Find eIndex relative to the base point on new face + eIndex -= tetBasePtI; + + if (neg(eIndex)) + { + eIndex = (eIndex + otherFace.size()) % otherFace.size(); + } + + if (eIndex == 0) + { + // The point is the base point, so this is first tet + // in the face circulation + + tetPtI = 1; + } + else if (eIndex == otherFace.size() - 1) + { + // The point is the last before the base point, so + // this is the last tet in the face circulation + + tetPtI = otherFace.size() - 2; + } + else + { + tetPtI = eIndex; + } + + break; + } + } } template<class ParticleType> -inline bool Foam::Particle<ParticleType>::inCell +inline void Foam::Particle<ParticleType>::hitWallFaces ( - const vector& position, - const label celli, - const scalar stepFraction -) const + const vector& from, + const vector& to, + scalar& lambdaMin, + tetIndices& closestTetIs +) { - DynamicList<label>& faces = cloud_.labels_; - findFaces(position, celli, stepFraction, faces); + if (!(cloud_.hasWallImpactDistance() && cloud_.cellHasWallFaces()[cellI_])) + { + return; + } + + const polyMesh& mesh = cloud_.polyMesh_; + const faceList& pFaces = mesh.faces(); + + const ParticleType& p = static_cast<const ParticleType&>(*this); - return (!faces.size()); + const Foam::cell& thisCell = mesh.cells()[cellI_]; + + const polyBoundaryMesh& patches = mesh.boundaryMesh(); + + forAll(thisCell, cFI) + { + label fI = thisCell[cFI]; + + if (cloud_.internalFace(fI)) + { + continue; + } + + label patchI = patches.patchID()[fI - mesh.nInternalFaces()]; + + if (isA<wallPolyPatch>(patches[patchI])) + { + // Get the decomposition of this wall face + + const List<tetIndices>& faceTetIs = + polyMeshTetDecomposition::faceTetIndices(mesh, fI, cellI_); + + const Foam::face& f = pFaces[fI]; + + forAll(faceTetIs, tI) + { + const tetIndices& tetIs = faceTetIs[tI]; + + triPointRef tri = tetIs.faceTri(mesh); + + vector n = tri.normal(); + + vector nHat = n/mag(n); + + // Radius of particle with respect to this wall face + // triangle. Assuming that the wallImpactDistance + // does not change as the particle or the mesh moves + // forward in time. + scalar r = p.wallImpactDistance(nHat); + + vector toPlusRNHat = to + r*nHat; + + // triI = 0 because it is the cell face tri of the tet + // we are concerned with. + scalar tetClambda = tetLambda + ( + tetIs.tet(mesh).centre(), + toPlusRNHat, + 0, + n, + f[tetIs.faceBasePt()], + cellI_, + fI, + tetIs.tetPt() + ); + + if ((tetClambda <= 0.0) || (tetClambda >= 1.0)) + { + // toPlusRNHat is not on the outside of the plane of + // the wall face tri, the tri cannot be hit. + continue; + } + + // Check if the actual trajectory of the near-tri + // points intersects the triangle. + + vector fromPlusRNHat = from + r*nHat; + + // triI = 0 because it is the cell face tri of the tet + // we are concerned with. + scalar lambda = tetLambda + ( + fromPlusRNHat, + toPlusRNHat, + 0, + n, + f[tetIs.faceBasePt()], + cellI_, + fI, + tetIs.tetPt() + ); + + pointHit hitInfo(vector::zero); + + if (mesh.moving()) + { + // For a moving mesh, the position of wall + // triangle needs to be moved in time to be + // consistent with the moment defined by the + // current value of stepFraction and the value of + // lambda just calculated. + + // Total fraction thought the timestep of the + // motion, including stepFraction before the + // current tracking step and the current + // lambda + // i.e. + // let s = stepFraction, l = lambda + // Motion of x in time: + // |-----------------|---------|---------| + // x00 x0 xi x + // + // where xi is the correct value of x at the required + // tracking instant. + // + // x0 = x00 + s*(x - x00) = s*x + (1 - s)*x00 + // + // i.e. the motion covered by previous tracking portions + // within this timestep, and + // + // xi = x0 + l*(x - x0) + // = l*x + (1 - l)*x0 + // = l*x + (1 - l)*(s*x + (1 - s)*x00) + // = (s + l - s*l)*x + (1 - (s + l - s*l))*x00 + // + // let m = (s + l - s*l) + // + // xi = m*x + (1 - m)*x00 = x00 + m*(x - x00); + // + // In the same form as before. + + // Clip lambda to 0.0-1.0 to ensure that sensible + // positions are used for triangle intersections. + scalar lam = max(0.0, min(1.0, lambda)); + + scalar m = stepFraction_ + lam - (stepFraction_*lam); + + triPointRef tri00 = tetIs.oldFaceTri(mesh); + + // Use SMALL positive tolerance to make the triangle + // slightly "fat" to improve robustness. Intersection + // is calculated as the ray (from + r*nHat) -> (to + + // r*nHat). + + point tPtA = tri00.a() + m*(tri.a() - tri00.a()); + point tPtB = tri00.b() + m*(tri.b() - tri00.b()); + point tPtC = tri00.c() + m*(tri.c() - tri00.c()); + + triPointRef t(tPtA, tPtB, tPtC); + + // The point fromPlusRNHat + m*(to - from) is on the + // plane of the triangle. Determine the + // intersection with this triangle by testing if + // this point is inside or outside of the triangle. + hitInfo = t.intersection + ( + fromPlusRNHat + m*(to - from), + t.normal(), + intersection::FULL_RAY, + SMALL + ); + } + else + { + // Use SMALL positive tolerance to make the triangle + // slightly "fat" to improve robustness. Intersection + // is calculated as the ray (from + r*nHat) -> (to + + // r*nHat). + hitInfo = tri.intersection + ( + fromPlusRNHat, + (to - from), + intersection::FULL_RAY, + SMALL + ); + } + + if (hitInfo.hit()) + { + if (lambda < lambdaMin) + { + lambdaMin = lambda; + + faceI_ = fI; + + closestTetIs = tetIs; + } + } + } + } + } } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template<class ParticleType> inline Foam::Particle<ParticleType>::trackData::trackData @@ -272,6 +805,8 @@ inline Foam::Particle<ParticleType>::trackData::trackData {} +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + template<class ParticleType> inline Foam::Cloud<ParticleType>& Foam::Particle<ParticleType>::trackData::cloud() @@ -280,8 +815,6 @@ Foam::Particle<ParticleType>::trackData::cloud() } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - template<class ParticleType> inline const Foam::Cloud<ParticleType>& Foam::Particle<ParticleType>::cloud() const @@ -307,35 +840,256 @@ inline Foam::vector& Foam::Particle<ParticleType>::position() template<class ParticleType> inline Foam::label Foam::Particle<ParticleType>::cell() const { - return celli_; + return cellI_; } template<class ParticleType> inline Foam::label& Foam::Particle<ParticleType>::cell() { - return celli_; + return cellI_; +} + + +template<class ParticleType> +inline Foam::label Foam::Particle<ParticleType>::tetFace() const +{ + return tetFaceI_; +} + + +template<class ParticleType> +inline Foam::label& Foam::Particle<ParticleType>::tetFace() +{ + return tetFaceI_; +} + + +template<class ParticleType> +inline Foam::label Foam::Particle<ParticleType>::tetPt() const +{ + return tetPtI_; +} + + +template<class ParticleType> +inline Foam::label& Foam::Particle<ParticleType>::tetPt() +{ + return tetPtI_; +} + + +template<class ParticleType> +inline Foam::tetIndices Foam::Particle<ParticleType>::currentTetIndices() const +{ + return tetIndices(cellI_, tetFaceI_, tetPtI_, cloud_.polyMesh_); +} + + +template<class ParticleType> +inline Foam::tetPointRef Foam::Particle<ParticleType>::currentTet() const +{ + return currentTetIndices().tet(cloud_.polyMesh_); +} + + +template<class ParticleType> +inline Foam::vector Foam::Particle<ParticleType>::normal() const +{ + return currentTetIndices().faceTri(cloud_.polyMesh_).normal(); +} + + +template<class ParticleType> +inline Foam::vector +Foam::Particle<ParticleType>::oldNormal() const +{ + return currentTetIndices().oldFaceTri(cloud_.polyMesh_).normal(); } template<class ParticleType> inline Foam::label Foam::Particle<ParticleType>::face() const { - return facei_; + return faceI_; } template<class ParticleType> inline Foam::label& Foam::Particle<ParticleType>::face() { - return facei_; + return faceI_; +} + + +template<class ParticleType> +inline void Foam::Particle<ParticleType>::initCellFacePt() +{ + if (cellI_ == -1) + { + cloud_.findCellFacePt + ( + position_, + cellI_, + tetFaceI_, + tetPtI_ + ); + + if (cellI_ == -1) + { + FatalErrorIn + ( + "Foam::Particle<ParticleType>::Particle" + "(" + "void Foam::Particle<ParticleType>::initCellFacePt()" + ")" + ) << "cell, tetFace and tetPt search failure at position " + << position_ << nl + << abort(FatalError); + } + } + else + { + cloud_.findFacePt(cellI_, position_, tetFaceI_, tetPtI_); + + if (tetFaceI_ == -1 || tetPtI_ == -1) + { + label oldCellI = cellI_; + + cloud_.findCellFacePt + ( + position_, + cellI_, + tetFaceI_, + tetPtI_ + ); + + if (cellI_ == -1 || tetFaceI_ == -1 || tetPtI_ == -1) + { + // The particle has entered this function with a cell + // number, but hasn't been able to find a cell to + // occupy. + + if(!cloud_.polyMesh_.pointInCellBB(position_, oldCellI)) + { + // If the position is not inside the bound-box of + // the cell that it thought it should be in, then + // this is considered an error. + + FatalErrorIn + ( + "Foam::Particle<ParticleType>::Particle" + "(" + "void " + "Foam::Particle<ParticleType>::initCellFacePt()" + ")" + ) << "cell, tetFace and tetPt search failure at position " + << position_ << nl + << abort(FatalError); + } + + // The position is in the bound-box of the cell. This + // situation may arise because the face decomposition + // of the cell is not the same as when the particle + // acquired the cell index. For example, it has been + // read into a mesh that has made a different face + // base-point decision for a boundary face and now + // this particle is in a position that is not in the + // mesh. Gradually move the particle towards the + // centre of the cell that it thought that it was in. + + cellI_ = oldCellI; + + point newPosition = position_; + + const point& cC = cloud_.polyMesh_.cellCentres()[cellI_]; + + label trap(1.0/Cloud<ParticleType>::trackingCorrectionTol + 1); + + label iterNo = 0; + + do + { + newPosition += + Cloud<ParticleType>::trackingCorrectionTol + *(cC - position_); + + cloud_.findFacePt + ( + cellI_, + newPosition, + tetFaceI_, + tetPtI_ + ); + + iterNo++; + + } while (tetFaceI_ < 0 && iterNo <= trap); + + if(tetFaceI_ == -1) + { + FatalErrorIn + ( + "Foam::Particle<ParticleType>::Particle" + "(" + "void " + "Foam::Particle<ParticleType>::initCellFacePt()" + ")" + ) << "cell, tetFace and tetPt search failure at position " + << position_ << nl + << abort(FatalError); + } + + WarningIn + ( + "Foam::Particle<ParticleType>::Particle" + "(" + "void Foam::Particle<ParticleType>::initCellFacePt()" + ")" + ) + << "Particle moved from " << position_ + << " to " << newPosition + << " in cell " << cellI_ + << " tetFace " << tetFaceI_ + << " tetPt " << tetPtI_ << nl + << " (A fraction of " + << 1.0 - mag(cC - newPosition)/mag(cC - position_) + << " of the distance to the cell centre)" + << " because a decomposition tetFace and tetPt " + << "could not be found." + << endl; + + position_ = newPosition; + } + + if (cellI_ != oldCellI) + { + WarningIn + ( + "Foam::Particle<ParticleType>::Particle" + "(" + "void Foam::Particle<ParticleType>::initCellFacePt()" + ")" + ) + << "Particle at position " << position_ + << " searched for a cell, tetFace and tetPt." << nl + << " Found" + << " cell " << cellI_ + << " tetFace " << tetFaceI_ + << " tetPt " << tetPtI_ << nl + << " This is a different cell to that which was supplied" + << " (" << oldCellI << ")." << nl + << endl; + } + } + } } template<class ParticleType> inline bool Foam::Particle<ParticleType>::onBoundary() const { - return facei_ != -1 && facei_ >= cloud_.pMesh().nInternalFaces(); + return faceI_ != -1 && faceI_ >= cloud_.pMesh().nInternalFaces(); } @@ -384,20 +1138,20 @@ inline Foam::scalar Foam::Particle<ParticleType>::currentTime() const template<class ParticleType> -inline Foam::label Foam::Particle<ParticleType>::patch(const label facei) const +inline Foam::label Foam::Particle<ParticleType>::patch(const label faceI) const { - return cloud_.facePatch(facei); + return cloud_.facePatch(faceI); } template<class ParticleType> inline Foam::label Foam::Particle<ParticleType>::patchFace ( - const label patchi, - const label facei + const label patchI, + const label faceI ) const { - return cloud_.patchFace(patchi, facei); + return cloud_.patchFace(patchI, faceI); } @@ -412,7 +1166,7 @@ Foam::Particle<ParticleType>::wallImpactDistance(const vector&) const template<class ParticleType> inline Foam::label Foam::Particle<ParticleType>::faceInterpolation() const { - return facei_; + return faceI_; } diff --git a/src/lagrangian/basic/Particle/ParticleIO.C b/src/lagrangian/basic/Particle/ParticleIO.C index 3212c1f4861..18d17064598 100644 --- a/src/lagrangian/basic/Particle/ParticleIO.C +++ b/src/lagrangian/basic/Particle/ParticleIO.C @@ -31,7 +31,8 @@ License template<class ParticleType> Foam::string Foam::Particle<ParticleType>::propHeader = - "(Px Py Pz) cellI origProc origId"; + "(Px Py Pz) cellI tetFaceI tetPtI origProc origId"; + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -44,20 +45,24 @@ Foam::Particle<ParticleType>::Particle ) : cloud_(cloud), - facei_(-1), + position_(), + cellI_(-1), + faceI_(-1), stepFraction_(0.0), + tetFaceI_(-1), + tetPtI_(-1), origProc_(Pstream::myProcNo()), origId_(-1) { - // readFields : read additional data. Should be consistent with writeFields. if (is.format() == IOstream::ASCII) { - is >> position_ >> celli_; + is >> position_ >> cellI_; + if (readFields) { - is >> origProc_ >> origId_; + is >> tetFaceI_ >> tetPtI_ >> origProc_ >> origId_; } } else @@ -69,9 +74,11 @@ Foam::Particle<ParticleType>::Particle ( reinterpret_cast<char*>(&position_), sizeof(position_) - + sizeof(celli_) - + sizeof(facei_) + + sizeof(cellI_) + + sizeof(faceI_) + sizeof(stepFraction_) + + sizeof(tetFaceI_) + + sizeof(tetPtI_) + sizeof(origProc_) + sizeof(origId_) ); @@ -82,18 +89,13 @@ Foam::Particle<ParticleType>::Particle ( reinterpret_cast<char*>(&position_), sizeof(position_) - + sizeof(celli_) - + sizeof(facei_) + + sizeof(cellI_) + + sizeof(faceI_) + sizeof(stepFraction_) ); } } - if (celli_ == -1) - { - celli_ = cloud_.pMesh().findCell(position_); - } - // Check state of Istream is.check("Particle<ParticleType>::Particle(Istream&)"); } @@ -176,29 +178,33 @@ void Foam::Particle<ParticleType>::write(Ostream& os, bool writeFields) const if (writeFields) { // Write the additional entries - os << position_ - << token::SPACE << celli_ - << token::SPACE << origProc_ - << token::SPACE << origId_; + os << position_ + << token::SPACE << cellI_ + << token::SPACE << tetFaceI_ + << token::SPACE << tetPtI_ + << token::SPACE << origProc_ + << token::SPACE << origId_; } else { - os << position_ - << token::SPACE << celli_; + os << position_ + << token::SPACE << cellI_; } } else { - // In binary write both celli_ and facei_, needed for parallel transfer + // In binary write both cellI_ and faceI_, needed for parallel transfer if (writeFields) { os.write ( reinterpret_cast<const char*>(&position_), sizeof(position_) - + sizeof(celli_) - + sizeof(facei_) + + sizeof(cellI_) + + sizeof(faceI_) + sizeof(stepFraction_) + + sizeof(tetFaceI_) + + sizeof(tetPtI_) + sizeof(origProc_) + sizeof(origId_) ); @@ -209,8 +215,8 @@ void Foam::Particle<ParticleType>::write(Ostream& os, bool writeFields) const ( reinterpret_cast<const char*>(&position_), sizeof(position_) - + sizeof(celli_) - + sizeof(facei_) + + sizeof(cellI_) + + sizeof(faceI_) + sizeof(stepFraction_) ); } diff --git a/src/lagrangian/basic/indexedParticle/indexedParticle.H b/src/lagrangian/basic/indexedParticle/indexedParticle.H index 9f725d5f550..6c940d0b70b 100644 --- a/src/lagrangian/basic/indexedParticle/indexedParticle.H +++ b/src/lagrangian/basic/indexedParticle/indexedParticle.H @@ -67,11 +67,26 @@ public: ( const Cloud<indexedParticle>& c, const vector& position, - const label celli, + const label cellI, + const label tetFaceI, + const label tetPtI, const label index = 0 ) : - Particle<indexedParticle>(c, position, celli), + Particle<indexedParticle>(c, position, cellI, tetFaceI, tetPtI), + index_(index) + {} + + //- Construct from components, with searching for tetFace and tetPt + indexedParticle + ( + const Cloud<indexedParticle>& c, + const vector& position, + const label cellI, + const label index = 0 + ) + : + Particle<indexedParticle>(c, position, cellI), index_(index) {} diff --git a/src/lagrangian/basic/passiveParticle/passiveParticle.H b/src/lagrangian/basic/passiveParticle/passiveParticle.H index fec00ea922f..49de4eba667 100644 --- a/src/lagrangian/basic/passiveParticle/passiveParticle.H +++ b/src/lagrangian/basic/passiveParticle/passiveParticle.H @@ -60,10 +60,23 @@ public: ( const Cloud<passiveParticle>& c, const vector& position, - const label celli + const label cellI, + const label tetFaceI, + const label tetPtI ) : - Particle<passiveParticle>(c, position, celli) + Particle<passiveParticle>(c, position, cellI, tetFaceI, tetPtI) + {} + + //- Construct from components, with searching for tetFace and tetPt + passiveParticle + ( + const Cloud<passiveParticle>& c, + const vector& position, + const label cellI + ) + : + Particle<passiveParticle>(c, position, cellI) {} //- Construct from Istream diff --git a/src/lagrangian/coalCombustion/coalParcel/coalParcel.C b/src/lagrangian/coalCombustion/coalParcel/coalParcel.C index 21086b996cd..a6500c8388e 100644 --- a/src/lagrangian/coalCombustion/coalParcel/coalParcel.C +++ b/src/lagrangian/coalCombustion/coalParcel/coalParcel.C @@ -31,10 +31,19 @@ Foam::coalParcel::coalParcel ( ReactingMultiphaseCloud<coalParcel>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ) : - ReactingMultiphaseParcel<coalParcel>(owner, position, cellI) + ReactingMultiphaseParcel<coalParcel> + ( + owner, + position, + cellI, + tetFaceI, + tetPtI + ) {} @@ -43,6 +52,8 @@ Foam::coalParcel::coalParcel ReactingMultiphaseCloud<coalParcel>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, @@ -62,6 +73,8 @@ Foam::coalParcel::coalParcel owner, position, cellI, + tetFaceI, + tetPtI, typeId, nParticle0, d0, diff --git a/src/lagrangian/coalCombustion/coalParcel/coalParcel.H b/src/lagrangian/coalCombustion/coalParcel/coalParcel.H index 2904ccbbcfd..81f6447320c 100644 --- a/src/lagrangian/coalCombustion/coalParcel/coalParcel.H +++ b/src/lagrangian/coalCombustion/coalParcel/coalParcel.H @@ -63,7 +63,9 @@ public: ( ReactingMultiphaseCloud<coalParcel>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ); //- Construct from components @@ -72,6 +74,8 @@ public: ReactingMultiphaseCloud<coalParcel>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, diff --git a/src/lagrangian/dieselSpray/Make/options b/src/lagrangian/dieselSpray/Make/options index 454c4f15bfa..40cb013fbb7 100644 --- a/src/lagrangian/dieselSpray/Make/options +++ b/src/lagrangian/dieselSpray/Make/options @@ -1,5 +1,6 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude \ -I$(LIB_SRC)/turbulenceModels \ -I$(LIB_SRC)/turbulenceModels/compressible/turbulenceModel \ @@ -16,6 +17,7 @@ EXE_INC = \ LIB_LIBS = \ -llagrangian \ + -lmeshTools \ -lfiniteVolume \ -lcompressibleRASModels \ -lcompressibleLESModels \ diff --git a/src/lagrangian/dieselSpray/parcel/boundaryTreatment.H b/src/lagrangian/dieselSpray/parcel/boundaryTreatment.H index 4420773172b..a2e03dc676f 100644 --- a/src/lagrangian/dieselSpray/parcel/boundaryTreatment.H +++ b/src/lagrangian/dieselSpray/parcel/boundaryTreatment.H @@ -15,12 +15,11 @@ if (isA<wallPolyPatch>(pbMesh[patch(face())])) else if (isA<wedgePolyPatch>(pbMesh[patch(face())])) { // check if parcel is trying to move out of the domain - label patchi = patch(face()); - label patchFacei = patchFace(patchi, face()); - const polyPatch& patch = mesh.boundaryMesh()[patchi]; - vector nf = patch.faceAreas()[patchFacei]; + + vector nf = normal(); scalar Un = U() & nf; + if (Un > 0) { scalar Un2 = U() & n(); @@ -30,12 +29,11 @@ else if (isA<wedgePolyPatch>(pbMesh[patch(face())])) else if (isA<symmetryPolyPatch>(pbMesh[patch(face())])) { // check if parcel is trying to move out of the domain - label patchi = patch(face()); - label patchFacei = patchFace(patchi, face()); - const polyPatch& patch = mesh.boundaryMesh()[patchi]; - vector nf = patch.faceAreas()[patchFacei]; + + vector nf = normal(); scalar Un = U() & nf; + if (Un > 0) { if (sDB.twoD()) diff --git a/src/lagrangian/dieselSpray/parcel/parcel.C b/src/lagrangian/dieselSpray/parcel/parcel.C index 4b0b1ef620c..50837a923d4 100644 --- a/src/lagrangian/dieselSpray/parcel/parcel.C +++ b/src/lagrangian/dieselSpray/parcel/parcel.C @@ -50,6 +50,8 @@ Foam::parcel::parcel const Cloud<parcel>& cloud, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const vector& n, const scalar d, const scalar T, @@ -67,7 +69,7 @@ Foam::parcel::parcel const List<word>& liquidNames ) : - Particle<parcel>(cloud, position, cellI), + Particle<parcel>(cloud, position, cellI, tetFaceI, tetPtI), liquidComponents_ ( liquidNames @@ -103,12 +105,13 @@ bool Foam::parcel::move(spray& sDB) label Nf = fuels.components().size(); label Ns = sDB.composition().Y().size(); + tetIndices tetIs = this->currentTetIndices(); + // Calculate the interpolated gas properties at the position of the parcel - vector Up = sDB.UInterpolator().interpolate(position(), cell()) - + Uturb(); - scalar rhog = sDB.rhoInterpolator().interpolate(position(), cell()); - scalar pg = sDB.pInterpolator().interpolate(position(), cell()); - scalar Tg = sDB.TInterpolator().interpolate(position(), cell()); + vector Up = sDB.UInterpolator().interpolate(position(), tetIs) + Uturb(); + scalar rhog = sDB.rhoInterpolator().interpolate(position(), tetIs); + scalar pg = sDB.pInterpolator().interpolate(position(), tetIs); + scalar Tg = sDB.TInterpolator().interpolate(position(), tetIs); scalarField Yfg(Nf, 0.0); @@ -119,8 +122,8 @@ bool Foam::parcel::move(spray& sDB) if (sDB.isLiquidFuel()[i]) { label j = sDB.gasToLiquidIndex()[i]; - scalar Yicelli = Yi[cell()]; - Yfg[j] = Yicelli; + scalar YicellI = Yi[cell()]; + Yfg[j] = YicellI; } cpMixture += Yi[cell()]*sDB.gasProperties()[i].Cp(Tg); } @@ -199,8 +202,8 @@ bool Foam::parcel::move(spray& sDB) // remember which cell the parcel is in // since this will change if a face is hit - label celli = cell(); - scalar p = sDB.p()[celli]; + label cellI = cell(); + scalar p = sDB.p()[cellI]; // track parcel to face, or end of trajectory if (keepParcel) @@ -259,7 +262,7 @@ bool Foam::parcel::move(spray& sDB) ( dt, sDB, - celli, + cellI, face() ); @@ -283,11 +286,11 @@ bool Foam::parcel::move(spray& sDB) // Update the Spray Source Terms forAll(nMass, i) { - sDB.srhos()[i][celli] += oMass[i] - nMass[i]; + sDB.srhos()[i][cellI] += oMass[i] - nMass[i]; } - sDB.sms()[celli] += oMom - nMom; + sDB.sms()[cellI] += oMom - nMom; - sDB.shs()[celli] += oTotMass*(oH + oPE) - m()*(nH + nPE); + sDB.shs()[cellI] += oTotMass*(oH + oPE) - m()*(nH + nPE); // Remove evaporated mass from stripped mass ms() -= ms()*(oTotMass-m())/oTotMass; @@ -300,11 +303,11 @@ bool Foam::parcel::move(spray& sDB) // ... and add the removed 'stuff' to the gas forAll(nMass, i) { - sDB.srhos()[i][celli] += nMass[i]; + sDB.srhos()[i][cellI] += nMass[i]; } - sDB.sms()[celli] += nMom; - sDB.shs()[celli] += m()*(nH + nPE); + sDB.sms()[cellI] += nMom; + sDB.shs()[cellI] += m()*(nH + nPE); } if (onBoundary() && keepParcel) @@ -327,8 +330,8 @@ void Foam::parcel::updateParcelProperties ( const scalar dt, spray& sDB, - const label celli, - const label facei + const label cellI, + const label faceI ) { const liquidMixture& fuels = sDB.fuels(); @@ -340,34 +343,34 @@ void Foam::parcel::updateParcelProperties scalar W = 0.0; for (label i=0; i<Ns; i++) { - W += sDB.composition().Y()[i][celli]/sDB.gasProperties()[i].W(); + W += sDB.composition().Y()[i][cellI]/sDB.gasProperties()[i].W(); } W = 1.0/W; // Calculate the interpolated gas properties at the position of the parcel - vector Up = sDB.UInterpolator().interpolate(position(), celli, facei) + vector Up = sDB.UInterpolator().interpolate(position(), cellI, faceI) + Uturb(); - scalar rhog = sDB.rhoInterpolator().interpolate(position(), celli, facei); - scalar pg = sDB.pInterpolator().interpolate(position(), celli, facei); - scalar Tg0 = sDB.TInterpolator().interpolate(position(), celli, facei); + scalar rhog = sDB.rhoInterpolator().interpolate(position(), cellI, faceI); + scalar pg = sDB.pInterpolator().interpolate(position(), cellI, faceI); + scalar Tg0 = sDB.TInterpolator().interpolate(position(), cellI, faceI); // correct the gaseous temperature for evaporated fuel scalar cpMix = 0.0; for (label i=0; i<Ns; i++) { - cpMix += sDB.composition().Y()[i][celli] + cpMix += sDB.composition().Y()[i][cellI] *sDB.gasProperties()[i].Cp(T()); } - scalar cellV = sDB.mesh().V()[celli]; - scalar rho = sDB.rho()[celli]; + scalar cellV = sDB.mesh().V()[cellI]; + scalar rho = sDB.rho()[cellI]; scalar cellMass = rho*cellV; - scalar dh = sDB.shs()[celli]; + scalar dh = sDB.shs()[cellI]; scalarField addedMass(Nf, 0.0); forAll(addedMass, i) { - addedMass[i] += sDB.srhos()[i][celli]*cellV; + addedMass[i] += sDB.srhos()[i][cellI]*cellV; } scalar Tg = Tg0 + dh/(cpMix*cellMass); @@ -378,7 +381,7 @@ void Foam::parcel::updateParcelProperties { label j = sDB.liquidToGasIndex()[i]; const volScalarField& Yj = sDB.composition().Y()[j]; - scalar Yfg0 = Yj[celli]; + scalar Yfg0 = Yj[cellI]; Yfg[i] = (Yfg0*cellMass + addedMass[i])/(addedMass[i] + cellMass); } @@ -389,7 +392,7 @@ void Foam::parcel::updateParcelProperties setRelaxationTimes ( - celli, + cellI, tauMomentum, tauEvaporation, tauHeatTransfer, @@ -492,14 +495,14 @@ void Foam::parcel::updateParcelProperties { label j = sDB.liquidToGasIndex()[i]; const volScalarField& Yj = sDB.composition().Y()[j]; - scalar Yfg0 = Yj[celli]; + scalar Yfg0 = Yj[cellI]; Yfg[i] = (Yfg0*cellMass + addedMass[i] + dm) /(addedMass[i] + cellMass + dm); } setRelaxationTimes ( - celli, + cellI, tauMomentum, tauEvaporation, tauHeatTransfer, @@ -530,7 +533,7 @@ void Foam::parcel::updateParcelProperties } else { - scalar Y = sDB.composition().Y()[i][celli]; + scalar Y = sDB.composition().Y()[i][cellI]; cpMix += Y*sDB.gasProperties()[i].Cp(Taverage); } } diff --git a/src/lagrangian/dieselSpray/parcel/parcel.H b/src/lagrangian/dieselSpray/parcel/parcel.H index c96abd9155c..90d46e0231e 100644 --- a/src/lagrangian/dieselSpray/parcel/parcel.H +++ b/src/lagrangian/dieselSpray/parcel/parcel.H @@ -113,7 +113,7 @@ class parcel //- Set the relaxation times void setRelaxationTimes ( - label celli, + label cellI, scalar& tauMomentum, scalarField& tauEvaporation, scalar& tauHeatTransfer, @@ -133,8 +133,8 @@ class parcel ( const scalar dt, spray& sprayData, - const label celli, - const label facei + const label cellI, + const label faceI ); @@ -150,7 +150,9 @@ public: ( const Cloud<parcel>& cloud, const vector& position, - const label celli, + const label cellI, + const label tetFaceI, + const label tetPtI, const vector& n, const scalar d, const scalar T, diff --git a/src/lagrangian/dieselSpray/parcel/setRelaxationTimes.C b/src/lagrangian/dieselSpray/parcel/setRelaxationTimes.C index 7565a747102..0b4b305f0cd 100644 --- a/src/lagrangian/dieselSpray/parcel/setRelaxationTimes.C +++ b/src/lagrangian/dieselSpray/parcel/setRelaxationTimes.C @@ -36,7 +36,7 @@ License void Foam::parcel::setRelaxationTimes ( - label celli, + label cellI, scalar& tauMomentum, scalarField& tauEvaporation, scalar& tauHeatTransfer, @@ -70,7 +70,7 @@ void Foam::parcel::setRelaxationTimes for (label i=0; i<Ns; i++) { - scalar Y = sDB.composition().Y()[i][celli]; + scalar Y = sDB.composition().Y()[i][cellI]; W += Y/sDB.gasProperties()[i].W(); // Using mass-fractions to average... kMixture += Y*sDB.gasProperties()[i].kappa(Tf); @@ -87,7 +87,7 @@ void Foam::parcel::setRelaxationTimes for (label i=0; i<Nf; i++) { label j = sDB.liquidToGasIndex()[i]; - scalar Y = sDB.composition().Y()[j][celli]; + scalar Y = sDB.composition().Y()[j][cellI]; scalar Wi = sDB.gasProperties()[j].W(); Yf[i] = Y; Xf[i] = Y*W/Wi; @@ -264,10 +264,10 @@ void Foam::parcel::setRelaxationTimes forAll(sDB.gasProperties(), k) { vapourSurfaceEnthalpy += - sDB.composition().Y()[k][celli] + sDB.composition().Y()[k][cellI] *sDB.gasProperties()[k].H(tBoilingSurface); vapourFarEnthalpy += - sDB.composition().Y()[k][celli] + sDB.composition().Y()[k][cellI] *sDB.gasProperties()[k].H(temperature); } diff --git a/src/lagrangian/dieselSpray/spray/findInjectorCell.H b/src/lagrangian/dieselSpray/spray/findInjectorCell.H index ff4eea7904a..e9e8a7bfa80 100644 --- a/src/lagrangian/dieselSpray/spray/findInjectorCell.H +++ b/src/lagrangian/dieselSpray/spray/findInjectorCell.H @@ -22,7 +22,14 @@ reduce(foundCell, orOp<bool>()); if (!foundCell) { injectionPosition = it->position(n); - injectorCell = mesh_.findCell(injectionPosition); + + findCellFacePt + ( + injectionPosition, + injectorCell, + injectorTetFaceI, + injectorTetPtI + ); if (injectorCell >= 0) { diff --git a/src/lagrangian/dieselSpray/spray/spray.C b/src/lagrangian/dieselSpray/spray/spray.C index 6ff9319f9a5..81047c68094 100644 --- a/src/lagrangian/dieselSpray/spray/spray.C +++ b/src/lagrangian/dieselSpray/spray/spray.C @@ -241,16 +241,16 @@ Foam::spray::spray label n=0; // check for the type of boundary condition - forAll(bMesh, patchi) + forAll(bMesh, patchI) { - if (isA<symmetryPolyPatch>(bMesh[patchi])) + if (isA<symmetryPolyPatch>(bMesh[patchI])) { symPlaneExist = true; } - else if (isA<wedgePolyPatch>(bMesh[patchi])) + else if (isA<wedgePolyPatch>(bMesh[patchI])) { wedgeExist = true; - patches[n++] = patchi; + patches[n++] = patchI; } } diff --git a/src/lagrangian/dieselSpray/spray/sprayFunctions.C b/src/lagrangian/dieselSpray/spray/sprayFunctions.C index 2a7de13c54c..9a1d0669428 100644 --- a/src/lagrangian/dieselSpray/spray/sprayFunctions.C +++ b/src/lagrangian/dieselSpray/spray/sprayFunctions.C @@ -149,9 +149,9 @@ Foam::scalar Foam::spray::liquidTotalEnthalpy() const forAllConstIter(spray, *this, iter) { - label celli = iter().cell(); + label cellI = iter().cell(); scalar T = iter().T(); - scalar pc = p()[celli]; + scalar pc = p()[cellI]; scalar rho = fuels().rho(pc, T, iter().X()); scalar hlat = fuels().hl(pc, T, iter().X()); scalar hg = 0.0; @@ -351,8 +351,8 @@ Foam::scalar Foam::spray::smd() const forAllConstIter(spray, *this, iter) { - label celli = iter().cell(); - scalar Pc = p()[celli]; + label cellI = iter().cell(); + scalar Pc = p()[cellI]; scalar T = iter().T(); scalar rho = fuels_->rho(Pc, T, iter().X()); diff --git a/src/lagrangian/dieselSpray/spray/sprayInject.C b/src/lagrangian/dieselSpray/spray/sprayInject.C index f27769dfb6d..06dbc9b7c61 100644 --- a/src/lagrangian/dieselSpray/spray/sprayInject.C +++ b/src/lagrangian/dieselSpray/spray/sprayInject.C @@ -107,7 +107,17 @@ void Foam::spray::inject() scalar deviation = breakup().y0(); scalar ddev = breakup().yDot0(); - label injectorCell = mesh_.findCell(injectionPosition); + label injectorCell = -1; + label injectorTetFaceI = -1; + label injectorTetPtI = -1; + + findCellFacePt + ( + injectionPosition, + injectorCell, + injectorTetFaceI, + injectorTetPtI + ); # include "findInjectorCell.H" @@ -122,6 +132,8 @@ void Foam::spray::inject() *this, injectionPosition, injectorCell, + injectorTetFaceI, + injectorTetPtI, normal, diameter, it->T(toi), diff --git a/src/lagrangian/dieselSpray/spray/sprayOps.C b/src/lagrangian/dieselSpray/spray/sprayOps.C index 6210c019672..7904771fa14 100644 --- a/src/lagrangian/dieselSpray/spray/sprayOps.C +++ b/src/lagrangian/dieselSpray/spray/sprayOps.C @@ -88,7 +88,7 @@ void Foam::spray::breakupLoop() vector velocity = UInterpolator().interpolate ( elmnt().position(), - elmnt().cell() + elmnt().currentTetIndices() ); // liquidCore < 0.5 indicates discrete drops @@ -122,7 +122,7 @@ void Foam::spray::atomizationLoop() vector velocity = UInterpolator().interpolate ( elmnt().position(), - elmnt().cell() + elmnt().currentTetIndices() ); // liquidCore > 0.5 indicates a liquid core diff --git a/src/lagrangian/dieselSpray/spraySubModels/breakupModel/SHF/SHF.C b/src/lagrangian/dieselSpray/spraySubModels/breakupModel/SHF/SHF.C index 12a3a6771b9..4824d253f85 100644 --- a/src/lagrangian/dieselSpray/spraySubModels/breakupModel/SHF/SHF.C +++ b/src/lagrangian/dieselSpray/spraySubModels/breakupModel/SHF/SHF.C @@ -102,14 +102,14 @@ void Foam::SHF::breakupParcel const liquidMixture& fuels ) const { - label celli = p.cell(); + label cellI = p.cell(); scalar T = p.T(); - scalar pc = spray_.p()[celli]; + scalar pc = spray_.p()[cellI]; scalar sigma = fuels.sigma(pc, T, p.X()); scalar rhoLiquid = fuels.rho(pc, T, p.X()); scalar muLiquid = fuels.mu(pc, T, p.X()); - scalar rhoGas = spray_.rho()[celli]; + scalar rhoGas = spray_.rho()[cellI]; scalar weGas = p.We(vel, rhoGas, sigma); scalar weLiquid = p.We(vel, rhoLiquid, sigma); @@ -237,6 +237,8 @@ void Foam::SHF::breakupParcel spray_, p.position(), p.cell(), + p.tetFace(), + p.tetPt(), p.n(), d, p.T(), diff --git a/src/lagrangian/dieselSpray/spraySubModels/breakupModel/reitzKHRT/reitzKHRT.C b/src/lagrangian/dieselSpray/spraySubModels/breakupModel/reitzKHRT/reitzKHRT.C index 921af9c5858..5c03fedba98 100644 --- a/src/lagrangian/dieselSpray/spraySubModels/breakupModel/reitzKHRT/reitzKHRT.C +++ b/src/lagrangian/dieselSpray/spraySubModels/breakupModel/reitzKHRT/reitzKHRT.C @@ -78,15 +78,15 @@ void Foam::reitzKHRT::breakupParcel const liquidMixture& fuels ) const { - label celli = p.cell(); + label cellI = p.cell(); scalar T = p.T(); scalar r = 0.5*p.d(); - scalar pc = spray_.p()[celli]; + scalar pc = spray_.p()[cellI]; scalar sigma = fuels.sigma(pc, T, p.X()); scalar rhoLiquid = fuels.rho(pc, T, p.X()); scalar muLiquid = fuels.mu(pc, T, p.X()); - scalar rhoGas = spray_.rho()[celli]; + scalar rhoGas = spray_.rho()[cellI]; scalar Np = p.N(rhoLiquid); scalar semiMass = Np*pow3(p.d()); @@ -198,6 +198,8 @@ void Foam::reitzKHRT::breakupParcel spray_, p.position(), p.cell(), + p.tetFace(), + p.tetPt(), p.n(), dc, p.T(), diff --git a/src/lagrangian/dieselSpray/spraySubModels/wallModel/reflectParcel/reflectParcel.C b/src/lagrangian/dieselSpray/spraySubModels/wallModel/reflectParcel/reflectParcel.C index e776b78f490..162484d5f23 100644 --- a/src/lagrangian/dieselSpray/spraySubModels/wallModel/reflectParcel/reflectParcel.C +++ b/src/lagrangian/dieselSpray/spraySubModels/wallModel/reflectParcel/reflectParcel.C @@ -70,18 +70,18 @@ Foam::reflectParcel::~reflectParcel() bool Foam::reflectParcel::wallTreatment ( parcel& p, - const label globalFacei + const label globalFaceI ) const { - label patchi = p.patch(globalFacei); - label facei = p.patchFace(patchi, globalFacei); + label patchI = p.patch(globalFaceI); + label faceI = p.patchFace(patchI, globalFaceI); const polyMesh& mesh = spray_.mesh(); - if (isA<wallPolyPatch>(mesh_.boundaryMesh()[patchi])) + if (isA<wallPolyPatch>(mesh_.boundaryMesh()[patchI])) { // wallNormal defined to point outwards of domain - vector Sf = mesh_.Sf().boundaryField()[patchi][facei]; + vector Sf = mesh_.Sf().boundaryField()[patchI][faceI]; Sf /= mag(Sf); if (!mesh.moving()) @@ -97,17 +97,17 @@ bool Foam::reflectParcel::wallTreatment else { // moving mesh - vector Ub1 = U_.boundaryField()[patchi][facei]; - vector Ub0 = U_.oldTime().boundaryField()[patchi][facei]; + vector Ub1 = U_.boundaryField()[patchI][faceI]; + vector Ub0 = U_.oldTime().boundaryField()[patchI][faceI]; scalar dt = spray_.runTime().deltaTValue(); const vectorField& oldPoints = mesh.oldPoints(); - const vector& Cf1 = mesh.faceCentres()[globalFacei]; + const vector& Cf1 = mesh.faceCentres()[globalFaceI]; - vector Cf0 = mesh.faces()[globalFacei].centre(oldPoints); + vector Cf0 = mesh.faces()[globalFaceI].centre(oldPoints); vector Cf = Cf0 + p.stepFraction()*(Cf1 - Cf0); - vector Sf0 = mesh.faces()[globalFacei].normal(oldPoints); + vector Sf0 = mesh.faces()[globalFaceI].normal(oldPoints); // for layer addition Sf0 = vector::zero and we use Sf if (mag(Sf0) > SMALL) @@ -157,10 +157,10 @@ bool Foam::reflectParcel::wallTreatment { Info<< "reflectParcel:: v = " << v << ", Ub = " << Ub - << ", facei = " << facei - << ", patchi = " << patchi - << ", globalFacei = " << globalFacei - << ", name = " << mesh_.boundaryMesh()[patchi].name() + << ", faceI = " << faceI + << ", patchI = " << patchI + << ", globalFaceI = " << globalFaceI + << ", name = " << mesh_.boundaryMesh()[patchI].name() << endl; } */ @@ -175,7 +175,7 @@ bool Foam::reflectParcel::wallTreatment else { FatalErrorIn("bool reflectParcel::wallTreatment(parcel& parcel) const") - << " parcel has hit a boundary " << mesh_.boundary()[patchi].type() + << " parcel has hit a boundary " << mesh_.boundary()[patchI].type() << " which not yet has been implemented." << nl << abort(FatalError); } diff --git a/src/lagrangian/dieselSpray/spraySubModels/wallModel/reflectParcel/reflectParcel.H b/src/lagrangian/dieselSpray/spraySubModels/wallModel/reflectParcel/reflectParcel.H index be19fafe24b..0316e1d819e 100644 --- a/src/lagrangian/dieselSpray/spraySubModels/wallModel/reflectParcel/reflectParcel.H +++ b/src/lagrangian/dieselSpray/spraySubModels/wallModel/reflectParcel/reflectParcel.H @@ -87,7 +87,7 @@ public: //- Return true if parcel is to be kept, and false if it is to be // removed - bool wallTreatment(parcel& parcel, const label facei) const; + bool wallTreatment(parcel& parcel, const label faceI) const; }; diff --git a/src/lagrangian/dieselSpray/spraySubModels/wallModel/removeParcel/removeParcel.C b/src/lagrangian/dieselSpray/spraySubModels/wallModel/removeParcel/removeParcel.C index b62ba09778d..f4f74742de9 100644 --- a/src/lagrangian/dieselSpray/spraySubModels/wallModel/removeParcel/removeParcel.C +++ b/src/lagrangian/dieselSpray/spraySubModels/wallModel/removeParcel/removeParcel.C @@ -65,7 +65,7 @@ Foam::removeParcel::~removeParcel() bool Foam::removeParcel::wallTreatment ( parcel&, - const label facei + const label faceI ) const { return false; diff --git a/src/lagrangian/dieselSpray/spraySubModels/wallModel/removeParcel/removeParcel.H b/src/lagrangian/dieselSpray/spraySubModels/wallModel/removeParcel/removeParcel.H index f07761847a9..a25b04b565d 100644 --- a/src/lagrangian/dieselSpray/spraySubModels/wallModel/removeParcel/removeParcel.H +++ b/src/lagrangian/dieselSpray/spraySubModels/wallModel/removeParcel/removeParcel.H @@ -73,7 +73,7 @@ public: //- Return true if parcel is to be kept, and false if it is to be // removed - bool wallTreatment(parcel& parcel, const label facei) const; + bool wallTreatment(parcel& parcel, const label faceI) const; }; diff --git a/src/lagrangian/dieselSpray/spraySubModels/wallModel/wallModel/wallModel.H b/src/lagrangian/dieselSpray/spraySubModels/wallModel/wallModel/wallModel.H index 598c6803d12..a17e4c078fb 100644 --- a/src/lagrangian/dieselSpray/spraySubModels/wallModel/wallModel/wallModel.H +++ b/src/lagrangian/dieselSpray/spraySubModels/wallModel/wallModel/wallModel.H @@ -118,7 +118,7 @@ public: virtual bool wallTreatment ( parcel&, - const label facei + const label faceI ) const = 0; }; diff --git a/src/lagrangian/dsmc/clouds/Templates/DsmcCloud/DsmcCloud.C b/src/lagrangian/dsmc/clouds/Templates/DsmcCloud/DsmcCloud.C index 80e0dea37d5..8b92319bcb5 100644 --- a/src/lagrangian/dsmc/clouds/Templates/DsmcCloud/DsmcCloud.C +++ b/src/lagrangian/dsmc/clouds/Templates/DsmcCloud/DsmcCloud.C @@ -109,161 +109,86 @@ void Foam::DsmcCloud<ParcelType>::initialise numberDensities /= nParticle_; - forAll(mesh_.cells(), cell) + forAll(mesh_.cells(), cellI) { - const vector& cC = mesh_.cellCentres()[cell]; - const labelList& cellFaces = mesh_.cells()[cell]; - const scalar cV = mesh_.cellVolumes()[cell]; - - label nTets = 0; + List<tetIndices> cellTets = polyMeshTetDecomposition::cellTetIndices + ( + mesh_, + cellI + ); - // Each face is split into nEdges (or nVertices) - 2 tets. - forAll(cellFaces, face) + forAll(cellTets, tetI) { - nTets += mesh_.faces()[cellFaces[face]].size() - 2; - } - - // Calculate the cumulative tet volumes circulating around the cell and - // record the vertex labels of each. - scalarList cTetVFracs(nTets, 0.0); + const tetIndices& cellTetIs = cellTets[tetI]; - List<labelList> tetPtIs(nTets, labelList(3,-1)); + tetPointRef tet = cellTetIs.tet(mesh_); - // Keep track of which tet this is. - label tet = 0; + scalar tetVolume = tet.mag(); - forAll(cellFaces, face) - { - const labelList& facePoints = mesh_.faces()[cellFaces[face]]; - - label pointI = 1; - while ((pointI + 1) < facePoints.size()) + forAll(molecules, i) { + const word& moleculeName(molecules[i]); - const vector& pA = mesh_.points()[facePoints[0]]; - const vector& pB = mesh_.points()[facePoints[pointI]]; - const vector& pC = mesh_.points()[facePoints[pointI + 1]]; - - cTetVFracs[tet] = - mag(((pA - cC) ^ (pB - cC)) & (pC - cC))/(cV*6.0) - + cTetVFracs[max((tet - 1),0)]; - - tetPtIs[tet][0] = facePoints[0]; - tetPtIs[tet][1] = facePoints[pointI]; - tetPtIs[tet][2] = facePoints[pointI + 1]; - - pointI++; - tet++; - } - } - - // Force the last volume fraction value to 1.0 to avoid any - // rounding/non-flat face errors giving a value < 1.0 - cTetVFracs[nTets - 1] = 1.0; - - forAll(molecules, i) - { - const word& moleculeName(molecules[i]); - - label typeId(findIndex(typeIdList_, moleculeName)); + label typeId(findIndex(typeIdList_, moleculeName)); - if (typeId == -1) - { - FatalErrorIn("Foam::DsmcCloud<ParcelType>::initialise") - << "typeId " << moleculeName << "not defined." << nl - << abort(FatalError); - } + if (typeId == -1) + { + FatalErrorIn("Foam::DsmcCloud<ParcelType>::initialise") + << "typeId " << moleculeName << "not defined." << nl + << abort(FatalError); + } - const typename ParcelType::constantProperties& cP = + const typename ParcelType::constantProperties& cP = constProps(typeId); - scalar numberDensity = numberDensities[i]; - - // Calculate the number of particles required - scalar particlesRequired = numberDensity*mesh_.cellVolumes()[cell]; - - // Only integer numbers of particles can be inserted - label nParticlesToInsert = label(particlesRequired); + scalar numberDensity = numberDensities[i]; - // Add another particle with a probability proportional to the - // remainder of taking the integer part of particlesRequired - if ((particlesRequired - nParticlesToInsert) > rndGen_.scalar01()) - { - nParticlesToInsert++; - } + // Calculate the number of particles required + scalar particlesRequired = numberDensity*tetVolume; - for (label pI = 0; pI < nParticlesToInsert; pI++) - { - // Choose a random point in a generic tetrahedron + // Only integer numbers of particles can be inserted + label nParticlesToInsert = label(particlesRequired); - scalar s = rndGen_.scalar01(); - scalar t = rndGen_.scalar01(); - scalar u = rndGen_.scalar01(); - - if (s + t > 1.0) + // Add another particle with a probability proportional to the + // remainder of taking the integer part of particlesRequired + if + ( + (particlesRequired - nParticlesToInsert) + > rndGen_.scalar01() + ) { - s = 1.0 - s; - t = 1.0 - t; + nParticlesToInsert++; } - if (t + u > 1.0) - { - scalar tmp = u; - u = 1.0 - s - t; - t = 1.0 - tmp; - } - else if (s + t + u > 1.0) + for (label pI = 0; pI < nParticlesToInsert; pI++) { - scalar tmp = u; - u = s + t + u - 1.0; - s = 1.0 - t - tmp; - } + point p = tet.randomPoint(rndGen_); - // Choose a tetrahedron to insert in, based on their relative - // volumes - scalar tetSelection = rndGen_.scalar01(); + vector U = equipartitionLinearVelocity + ( + temperature, + cP.mass() + ); - // Selected tetrahedron - label sTet = -1; + scalar Ei = equipartitionInternalEnergy + ( + temperature, + cP.internalDegreesOfFreedom() + ); - forAll(cTetVFracs, tet) - { - sTet = tet; + U += velocity; - if (cTetVFracs[tet] >= tetSelection) - { - break; - } + addNewParcel + ( + p, + U, + Ei, + cellI, + cellTetIs.face(), + cellTetIs.tetPt(), + typeId + ); } - - vector p = - (1 - s - t - u)*cC - + s*mesh_.points()[tetPtIs[sTet][0]] - + t*mesh_.points()[tetPtIs[sTet][1]] - + u*mesh_.points()[tetPtIs[sTet][2]]; - - vector U = equipartitionLinearVelocity - ( - temperature, - cP.mass() - ); - - scalar Ei = equipartitionInternalEnergy - ( - temperature, - cP.internalDegreesOfFreedom() - ); - - U += velocity; - - addNewParcel - ( - p, - U, - Ei, - cell, - typeId - ); } } } @@ -306,9 +231,9 @@ void Foam::DsmcCloud<ParcelType>::collisions() label collisions = 0; - forAll(cellOccupancy_, celli) + forAll(cellOccupancy_, cellI) { - const DynamicList<ParcelType*>& cellParcels(cellOccupancy_[celli]); + const DynamicList<ParcelType*>& cellParcels(cellOccupancy_[cellI]); label nC(cellParcels.size()); @@ -327,13 +252,13 @@ void Foam::DsmcCloud<ParcelType>::collisions() // Inverse addressing specifying which subCell a parcel is in List<label> whichSubCell(cellParcels.size()); - const point& cC = mesh_.cellCentres()[celli]; + const point& cC = mesh_.cellCentres()[cellI]; forAll(cellParcels, i) { - ParcelType* p = cellParcels[i]; + const ParcelType& p = *cellParcels[i]; - vector relPos = p->position() - cC; + vector relPos = p.position() - cC; label subCell = pos(relPos.x()) + 2*pos(relPos.y()) + 4*pos(relPos.z()); @@ -345,16 +270,16 @@ void Foam::DsmcCloud<ParcelType>::collisions() // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - scalar sigmaTcRMax = sigmaTcRMax_[celli]; + scalar sigmaTcRMax = sigmaTcRMax_[cellI]; scalar selectedPairs = - collisionSelectionRemainder_[celli] + collisionSelectionRemainder_[cellI] + 0.5*nC*(nC - 1)*nParticle_*sigmaTcRMax*deltaT - /mesh_.cellVolumes()[celli]; + /mesh_.cellVolumes()[cellI]; label nCandidates(selectedPairs); - collisionSelectionRemainder_[celli] = selectedPairs - nCandidates; + collisionSelectionRemainder_[cellI] = selectedPairs - nCandidates; collisionCandidates += nCandidates; @@ -415,39 +340,30 @@ void Foam::DsmcCloud<ParcelType>::collisions() // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ParcelType* parcelP = cellParcels[candidateP]; - ParcelType* parcelQ = cellParcels[candidateQ]; - - label typeIdP = parcelP->typeId(); - label typeIdQ = parcelQ->typeId(); + ParcelType& parcelP = *cellParcels[candidateP]; + ParcelType& parcelQ = *cellParcels[candidateQ]; scalar sigmaTcR = binaryCollision().sigmaTcR ( - typeIdP, - typeIdQ, - parcelP->U(), - parcelQ->U() + parcelP, + parcelQ ); // Update the maximum value of sigmaTcR stored, but use the // initial value in the acceptance-rejection criteria because // the number of collision candidates selected was based on this - if (sigmaTcR > sigmaTcRMax_[celli]) + if (sigmaTcR > sigmaTcRMax_[cellI]) { - sigmaTcRMax_[celli] = sigmaTcR; + sigmaTcRMax_[cellI] = sigmaTcR; } if ((sigmaTcR/sigmaTcRMax) > rndGen_.scalar01()) { binaryCollision().collide ( - typeIdP, - typeIdQ, - parcelP->U(), - parcelQ->U(), - parcelP->Ei(), - parcelQ->Ei() + parcelP, + parcelQ ); collisions++; @@ -577,7 +493,9 @@ void Foam::DsmcCloud<ParcelType>::addNewParcel const vector& position, const vector& U, const scalar Ei, - const label cellId, + const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId ) { @@ -587,7 +505,9 @@ void Foam::DsmcCloud<ParcelType>::addNewParcel position, U, Ei, - cellId, + cellI, + tetFaceI, + tetPtI, typeId ); diff --git a/src/lagrangian/dsmc/clouds/Templates/DsmcCloud/DsmcCloud.H b/src/lagrangian/dsmc/clouds/Templates/DsmcCloud/DsmcCloud.H index aba26e7bf83..1df0dee9748 100644 --- a/src/lagrangian/dsmc/clouds/Templates/DsmcCloud/DsmcCloud.H +++ b/src/lagrangian/dsmc/clouds/Templates/DsmcCloud/DsmcCloud.H @@ -214,6 +214,10 @@ public: virtual ~DsmcCloud(); + //- Type of parcel the cloud was instantiated for + typedef ParcelType parcelType; + + // Member Functions // Access @@ -452,7 +456,9 @@ public: const vector& position, const vector& U, const scalar Ei, - const label cellId, + const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId ); diff --git a/src/lagrangian/dsmc/parcels/Templates/DsmcParcel/DsmcParcel.C b/src/lagrangian/dsmc/parcels/Templates/DsmcParcel/DsmcParcel.C index a8883630924..a6a6949122c 100644 --- a/src/lagrangian/dsmc/parcels/Templates/DsmcParcel/DsmcParcel.C +++ b/src/lagrangian/dsmc/parcels/Templates/DsmcParcel/DsmcParcel.C @@ -92,7 +92,9 @@ bool Foam::DsmcParcel<ParcelType>::hitPatch ( const polyPatch&, TrackData& td, - const label patchI + const label, + const scalar, + const tetIndices& ) { return false; @@ -125,7 +127,8 @@ template<class TrackData> void Foam::DsmcParcel<ParcelType>::hitWallPatch ( const wallPolyPatch& wpp, - TrackData& td + TrackData& td, + const tetIndices& tetIs ) { label wppIndex = wpp.index(); @@ -171,11 +174,8 @@ void Foam::DsmcParcel<ParcelType>::hitWallPatch td.cloud().wallInteraction().correct ( - wpp, - this->face(), - U_, - Ei_, - typeId_ + static_cast<ParcelType&>(*this), + wpp ); U_dot_nw = U_ & nw; @@ -219,7 +219,8 @@ template<class ParcelType> void Foam::DsmcParcel<ParcelType>::hitWallPatch ( const wallPolyPatch&, - int& + int&, + const tetIndices& ) {} diff --git a/src/lagrangian/dsmc/parcels/Templates/DsmcParcel/DsmcParcel.H b/src/lagrangian/dsmc/parcels/Templates/DsmcParcel/DsmcParcel.H index 8a644652d0c..8d09a91e8d7 100644 --- a/src/lagrangian/dsmc/parcels/Templates/DsmcParcel/DsmcParcel.H +++ b/src/lagrangian/dsmc/parcels/Templates/DsmcParcel/DsmcParcel.H @@ -185,7 +185,9 @@ public: const vector& position, const vector& U, const scalar Ei, - const label celli, + const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId ); @@ -244,7 +246,9 @@ public: ( const polyPatch&, TrackData& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ); //- Overridable function to handle the particle hitting a @@ -269,7 +273,8 @@ public: void hitWallPatch ( const wallPolyPatch&, - TrackData& td + TrackData& td, + const tetIndices& ); //- Overridable function to handle the particle hitting a wallPatch @@ -277,7 +282,8 @@ public: void hitWallPatch ( const wallPolyPatch&, - int& + int&, + const tetIndices& ); //- Overridable function to handle the particle hitting a polyPatch @@ -352,4 +358,3 @@ public: #endif // ************************************************************************* // - diff --git a/src/lagrangian/dsmc/parcels/Templates/DsmcParcel/DsmcParcelI.H b/src/lagrangian/dsmc/parcels/Templates/DsmcParcel/DsmcParcelI.H index 9f6d661ec6b..5bfc61b44b0 100644 --- a/src/lagrangian/dsmc/parcels/Templates/DsmcParcel/DsmcParcelI.H +++ b/src/lagrangian/dsmc/parcels/Templates/DsmcParcel/DsmcParcelI.H @@ -69,11 +69,13 @@ inline Foam::DsmcParcel<ParcelType>::DsmcParcel const vector& position, const vector& U, const scalar Ei, - const label celli, + const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId ) : - Particle<ParcelType>(owner, position, celli), + Particle<ParcelType>(owner, position, cellI, tetFaceI, tetPtI), U_(U), Ei_(Ei), typeId_(typeId) diff --git a/src/lagrangian/dsmc/parcels/derived/dsmcParcel/dsmcParcel.C b/src/lagrangian/dsmc/parcels/derived/dsmcParcel/dsmcParcel.C index b46bb2452fc..91fa156c639 100644 --- a/src/lagrangian/dsmc/parcels/derived/dsmcParcel/dsmcParcel.C +++ b/src/lagrangian/dsmc/parcels/derived/dsmcParcel/dsmcParcel.C @@ -43,7 +43,9 @@ Foam::dsmcParcel::dsmcParcel const vector& position, const vector& U, const scalar Ei, - const label celli, + const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId ) : @@ -53,7 +55,9 @@ Foam::dsmcParcel::dsmcParcel position, U, Ei, - celli, + cellI, + tetFaceI, + tetPtI, typeId ) {} diff --git a/src/lagrangian/dsmc/parcels/derived/dsmcParcel/dsmcParcel.H b/src/lagrangian/dsmc/parcels/derived/dsmcParcel/dsmcParcel.H index 8cc4bf11849..6286e06c60e 100644 --- a/src/lagrangian/dsmc/parcels/derived/dsmcParcel/dsmcParcel.H +++ b/src/lagrangian/dsmc/parcels/derived/dsmcParcel/dsmcParcel.H @@ -66,7 +66,9 @@ public: const vector& position, const vector& U, const scalar Ei, - const label celli, + const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId ); diff --git a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/BinaryCollisionModel/BinaryCollisionModel.H b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/BinaryCollisionModel/BinaryCollisionModel.H index 0136cd5f6a0..bd0ce0fa315 100644 --- a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/BinaryCollisionModel/BinaryCollisionModel.H +++ b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/BinaryCollisionModel/BinaryCollisionModel.H @@ -132,21 +132,15 @@ public: //- Return the collision cross section * relative velocity product virtual scalar sigmaTcR ( - label typeIdP, - label typeIdQ, - const vector& UP, - const vector& UQ + const typename CloudType::parcelType& pP, + const typename CloudType::parcelType& pQ ) const = 0; //- Apply collision virtual void collide ( - label typeIdP, - label typeIdQ, - vector& UP, - vector& UQ, - scalar& EiP, - scalar& EiQ + typename CloudType::parcelType& pP, + typename CloudType::parcelType& pQ ) = 0; }; diff --git a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/LarsenBorgnakkeVariableHardSphere/LarsenBorgnakkeVariableHardSphere.C b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/LarsenBorgnakkeVariableHardSphere/LarsenBorgnakkeVariableHardSphere.C index 85f0eb12ec7..5e067847b5d 100644 --- a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/LarsenBorgnakkeVariableHardSphere/LarsenBorgnakkeVariableHardSphere.C +++ b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/LarsenBorgnakkeVariableHardSphere/LarsenBorgnakkeVariableHardSphere.C @@ -128,14 +128,15 @@ bool Foam::LarsenBorgnakkeVariableHardSphere<CloudType>::active() const template <class CloudType> Foam::scalar Foam::LarsenBorgnakkeVariableHardSphere<CloudType>::sigmaTcR ( - label typeIdP, - label typeIdQ, - const vector& UP, - const vector& UQ + const typename CloudType::parcelType& pP, + const typename CloudType::parcelType& pQ ) const { const CloudType& cloud(this->owner()); + label typeIdP = pP.typeId(); + label typeIdQ = pQ.typeId(); + scalar dPQ = 0.5 *( @@ -150,7 +151,7 @@ Foam::scalar Foam::LarsenBorgnakkeVariableHardSphere<CloudType>::sigmaTcR + cloud.constProps(typeIdQ).omega() ); - scalar cR = mag(UP - UQ); + scalar cR = mag(pP.U() - pQ.U()); if (cR < VSMALL) { @@ -176,16 +177,19 @@ Foam::scalar Foam::LarsenBorgnakkeVariableHardSphere<CloudType>::sigmaTcR template <class CloudType> void Foam::LarsenBorgnakkeVariableHardSphere<CloudType>::collide ( - label typeIdP, - label typeIdQ, - vector& UP, - vector& UQ, - scalar& EiP, - scalar& EiQ + typename CloudType::parcelType& pP, + typename CloudType::parcelType& pQ ) { CloudType& cloud(this->owner()); + label typeIdP = pP.typeId(); + label typeIdQ = pQ.typeId(); + vector& UP = pP.U(); + vector& UQ = pQ.U(); + scalar& EiP = pP.Ei(); + scalar& EiQ = pQ.Ei(); + Random& rndGen(cloud.rndGen()); scalar inverseCollisionNumber = 1/relaxationCollisionNumber_; diff --git a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/LarsenBorgnakkeVariableHardSphere/LarsenBorgnakkeVariableHardSphere.H b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/LarsenBorgnakkeVariableHardSphere/LarsenBorgnakkeVariableHardSphere.H index 3f742a78ae6..fa4f232a02b 100644 --- a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/LarsenBorgnakkeVariableHardSphere/LarsenBorgnakkeVariableHardSphere.H +++ b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/LarsenBorgnakkeVariableHardSphere/LarsenBorgnakkeVariableHardSphere.H @@ -95,21 +95,15 @@ public: //- Return the collision cross section * relative velocity product virtual scalar sigmaTcR ( - label typeIdP, - label typeIdQ, - const vector& UP, - const vector& UQ + const typename CloudType::parcelType& pP, + const typename CloudType::parcelType& pQ ) const; //- Apply collision virtual void collide ( - label typeIdP, - label typeIdQ, - vector& UP, - vector& UQ, - scalar& EiP, - scalar& EiQ + typename CloudType::parcelType& pP, + typename CloudType::parcelType& pQ ); }; diff --git a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/NoBinaryCollision/NoBinaryCollision.C b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/NoBinaryCollision/NoBinaryCollision.C index 5ff98896383..67a1b4443ea 100644 --- a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/NoBinaryCollision/NoBinaryCollision.C +++ b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/NoBinaryCollision/NoBinaryCollision.C @@ -60,10 +60,8 @@ bool Foam::NoBinaryCollision<CloudType>::active() const template <class CloudType> Foam::scalar Foam::NoBinaryCollision<CloudType>::sigmaTcR ( - label typeIdP, - label typeIdQ, - const vector& UP, - const vector& UQ + const typename CloudType::parcelType& pP, + const typename CloudType::parcelType& pQ ) const { FatalErrorIn @@ -89,12 +87,8 @@ Foam::scalar Foam::NoBinaryCollision<CloudType>::sigmaTcR template <class CloudType> void Foam::NoBinaryCollision<CloudType>::collide ( - label typeIdP, - label typeIdQ, - vector& UP, - vector& UQ, - scalar& EiP, - scalar& EiQ + typename CloudType::parcelType& pP, + typename CloudType::parcelType& pQ ) {} diff --git a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/NoBinaryCollision/NoBinaryCollision.H b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/NoBinaryCollision/NoBinaryCollision.H index b48cedb316e..9ceea73e303 100644 --- a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/NoBinaryCollision/NoBinaryCollision.H +++ b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/NoBinaryCollision/NoBinaryCollision.H @@ -74,21 +74,15 @@ public: //- Return the collision cross section * relative velocity product virtual scalar sigmaTcR ( - label typeIdP, - label typeIdQ, - const vector& UP, - const vector& UQ + const typename CloudType::parcelType& pP, + const typename CloudType::parcelType& pQ ) const; //- Apply collision virtual void collide ( - label typeIdP, - label typeIdQ, - vector& UP, - vector& UQ, - scalar& EiP, - scalar& EiQ + typename CloudType::parcelType& pP, + typename CloudType::parcelType& pQ ); }; diff --git a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/VariableHardSphere/VariableHardSphere.C b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/VariableHardSphere/VariableHardSphere.C index 8f7d13dd7de..450e1218ed0 100644 --- a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/VariableHardSphere/VariableHardSphere.C +++ b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/VariableHardSphere/VariableHardSphere.C @@ -61,14 +61,15 @@ bool Foam::VariableHardSphere<CloudType>::active() const template <class CloudType> Foam::scalar Foam::VariableHardSphere<CloudType>::sigmaTcR ( - label typeIdP, - label typeIdQ, - const vector& UP, - const vector& UQ + const typename CloudType::parcelType& pP, + const typename CloudType::parcelType& pQ ) const { const CloudType& cloud(this->owner()); + label typeIdP = pP.typeId(); + label typeIdQ = pQ.typeId(); + scalar dPQ = 0.5 *( @@ -83,7 +84,7 @@ Foam::scalar Foam::VariableHardSphere<CloudType>::sigmaTcR + cloud.constProps(typeIdQ).omega() ); - scalar cR = mag(UP - UQ); + scalar cR = mag(pP.U() - pQ.U()); if (cR < VSMALL) { @@ -109,16 +110,17 @@ Foam::scalar Foam::VariableHardSphere<CloudType>::sigmaTcR template <class CloudType> void Foam::VariableHardSphere<CloudType>::collide ( - label typeIdP, - label typeIdQ, - vector& UP, - vector& UQ, - scalar& EiP, - scalar& EiQ + typename CloudType::parcelType& pP, + typename CloudType::parcelType& pQ ) { CloudType& cloud(this->owner()); + label typeIdP = pP.typeId(); + label typeIdQ = pQ.typeId(); + vector& UP = pP.U(); + vector& UQ = pQ.U(); + Random& rndGen(cloud.rndGen()); scalar mP = cloud.constProps(typeIdP).mass(); diff --git a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/VariableHardSphere/VariableHardSphere.H b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/VariableHardSphere/VariableHardSphere.H index bf986189c0b..2540107f7b1 100644 --- a/src/lagrangian/dsmc/submodels/BinaryCollisionModel/VariableHardSphere/VariableHardSphere.H +++ b/src/lagrangian/dsmc/submodels/BinaryCollisionModel/VariableHardSphere/VariableHardSphere.H @@ -80,21 +80,15 @@ public: //- Return the collision cross section * relative velocity product virtual scalar sigmaTcR ( - label typeIdP, - label typeIdQ, - const vector& UP, - const vector& UQ + const typename CloudType::parcelType& pP, + const typename CloudType::parcelType& pQ ) const; //- Apply collision virtual void collide ( - label typeIdP, - label typeIdQ, - vector& UP, - vector& UQ, - scalar& EiP, - scalar& EiQ + typename CloudType::parcelType& pP, + typename CloudType::parcelType& pQ ); }; diff --git a/src/lagrangian/dsmc/submodels/InflowBoundaryModel/FreeStream/FreeStream.C b/src/lagrangian/dsmc/submodels/InflowBoundaryModel/FreeStream/FreeStream.C index b8818aa9cdf..df835e735d0 100644 --- a/src/lagrangian/dsmc/submodels/InflowBoundaryModel/FreeStream/FreeStream.C +++ b/src/lagrangian/dsmc/submodels/InflowBoundaryModel/FreeStream/FreeStream.C @@ -25,6 +25,8 @@ License #include "FreeStream.H" #include "constants.H" +#include "triPointRef.H" +#include "tetIndices.H" using namespace Foam::constant::mathematical; @@ -181,13 +183,13 @@ void Foam::FreeStream<CloudType>::inflow() ) ); - // Dotting boundary velocity with the face unit normal (which points - // out of the domain, so it must be negated), dividing by the most - // probable speed to form molecularSpeedRatio * cosTheta + // Dotting boundary velocity with the face unit normal + // (which points out of the domain, so it must be + // negated), dividing by the most probable speed to form + // molecularSpeedRatio * cosTheta scalarField sCosTheta = - boundaryU[patchI] - & -patch.faceAreas()/mag(patch.faceAreas()) + (boundaryU[patchI] & -patch.faceAreas()/mag(patch.faceAreas())) /mostProbableSpeed; // From Bird eqn 4.22 @@ -201,50 +203,56 @@ void Foam::FreeStream<CloudType>::inflow() /(2.0*sqrtPi); } - forAll(patch, f) + forAll(patch, pFI) { // Loop over all faces as the outer loop to avoid calculating // geometrical properties multiple times. - labelList faceVertices = patch[f]; + const face& f = patch[pFI]; - label nVertices = faceVertices.size(); + label globalFaceIndex = pFI + patch.start(); - label globalFaceIndex = f + patch.start(); + label cellI = mesh.faceOwner()[globalFaceIndex]; - label cell = mesh.faceOwner()[globalFaceIndex]; + const vector& fC = patch.faceCentres()[pFI]; - const vector& fC = patch.faceCentres()[f]; + scalar fA = mag(patch.faceAreas()[pFI]); - scalar fA = mag(patch.faceAreas()[f]); + List<tetIndices> faceTets = polyMeshTetDecomposition::faceTetIndices + ( + mesh, + globalFaceIndex, + cellI + ); // Cumulative triangle area fractions - List<scalar> cTriAFracs(nVertices); - cTriAFracs[0] = 0.0; + List<scalar> cTriAFracs(faceTets.size(), 0.0); - for (label v = 0; v < nVertices - 1; v++) + scalar previousCummulativeSum = 0.0; + + forAll(faceTets, triI) { - const point& vA = mesh.points()[faceVertices[v]]; + const tetIndices& faceTetIs = faceTets[triI]; - const point& vB = mesh.points()[faceVertices[(v + 1)]]; + cTriAFracs[triI] = + faceTetIs.faceTri(mesh).mag()/fA + + previousCummulativeSum; - cTriAFracs[v] = - 0.5*mag((vA - fC)^(vB - fC))/fA - + cTriAFracs[max((v - 1), 0)]; + previousCummulativeSum = cTriAFracs[triI]; } // Force the last area fraction value to 1.0 to avoid any // rounding/non-flat face errors giving a value < 1.0 - cTriAFracs[nVertices - 1] = 1.0; + cTriAFracs.last() = 1.0; // Normal unit vector *negative* so normal is pointing into the // domain - vector n = patch.faceAreas()[f]; + vector n = patch.faceAreas()[pFI]; n /= -mag(n); // Wall tangential unit vector. Use the direction between the // face centre and the first vertex in the list - vector t1 = fC - (mesh.points()[faceVertices[0]]); + vector t1 = fC - (mesh.points()[f[0]]); t1 /= mag(t1); // Other tangential unit vector. Rescaling in case face is not @@ -252,13 +260,13 @@ void Foam::FreeStream<CloudType>::inflow() vector t2 = n^t1; t2 /= mag(t2); - scalar faceTemperature = boundaryT[patchI][f]; + scalar faceTemperature = boundaryT[patchI][pFI]; - const vector& faceVelocity = boundaryU[patchI][f]; + const vector& faceVelocity = boundaryU[patchI][pFI]; forAll(pFA, i) { - scalar& faceAccumulator = pFA[i][f]; + scalar& faceAccumulator = pFA[i][pFI]; // Number of whole particles to insert label nI = max(label(faceAccumulator), 0); @@ -284,34 +292,23 @@ void Foam::FreeStream<CloudType>::inflow() scalar triSelection = rndGen.scalar01(); // Selected triangle - label sTri = -1; + label selectedTriI = -1; - forAll(cTriAFracs, tri) + forAll(cTriAFracs, triI) { - sTri = tri; + selectedTriI = triI; - if (cTriAFracs[tri] >= triSelection) + if (cTriAFracs[triI] >= triSelection) { break; } } - // Randomly distribute the points on the triangle, using the - // method from: - // Generating Random Points in Triangles - // by Greg Turk - // from "Graphics Gems", Academic Press, 1990 - // http://tog.acm.org/GraphicsGems/gems/TriPoints.c - - const point& A = fC; - const point& B = mesh.points()[faceVertices[sTri]]; - const point& C = - mesh.points()[faceVertices[(sTri + 1) % nVertices]]; + // Randomly distribute the points on the triangle. - scalar s = rndGen.scalar01(); - scalar t = sqrt(rndGen.scalar01()); + const tetIndices& faceTetIs = faceTets[selectedTriI]; - point p = (1 - t)*A + (1 - s)*t*B + s*t*C; + point p = faceTetIs.faceTri(mesh).randomPoint(rndGen); // Velocity generation @@ -393,7 +390,9 @@ void Foam::FreeStream<CloudType>::inflow() p, U, Ei, - cell, + cellI, + globalFaceIndex, + faceTetIs.tetPt(), typeId ); diff --git a/src/lagrangian/dsmc/submodels/WallInteractionModel/MaxwellianThermal/MaxwellianThermal.C b/src/lagrangian/dsmc/submodels/WallInteractionModel/MaxwellianThermal/MaxwellianThermal.C index 467e5fad4fe..c05e6ae2013 100644 --- a/src/lagrangian/dsmc/submodels/WallInteractionModel/MaxwellianThermal/MaxwellianThermal.C +++ b/src/lagrangian/dsmc/submodels/WallInteractionModel/MaxwellianThermal/MaxwellianThermal.C @@ -53,20 +53,21 @@ Foam::MaxwellianThermal<CloudType>::~MaxwellianThermal() template <class CloudType> void Foam::MaxwellianThermal<CloudType>::correct ( - const wallPolyPatch& wpp, - const label faceId, - vector& U, - scalar& Ei, - label typeId + typename CloudType::parcelType& p, + const wallPolyPatch& wpp ) { - label wppIndex = wpp.index(); + vector& U = p.U(); + + scalar& Ei = p.Ei(); - label wppLocalFace = wpp.whichFace(faceId); + label typeId = p.typeId(); + + label wppIndex = wpp.index(); - vector nw = wpp.faceAreas()[wppLocalFace]; + label wppLocalFace = wpp.whichFace(p.face()); - // Normal unit vector + vector nw = p.normal(); nw /= mag(nw); // Normal velocity magnitude diff --git a/src/lagrangian/dsmc/submodels/WallInteractionModel/MaxwellianThermal/MaxwellianThermal.H b/src/lagrangian/dsmc/submodels/WallInteractionModel/MaxwellianThermal/MaxwellianThermal.H index f42382b7da0..2ed030bbe74 100644 --- a/src/lagrangian/dsmc/submodels/WallInteractionModel/MaxwellianThermal/MaxwellianThermal.H +++ b/src/lagrangian/dsmc/submodels/WallInteractionModel/MaxwellianThermal/MaxwellianThermal.H @@ -25,8 +25,9 @@ Class Foam::MaxwellianThermal Description - Wall interaction setting microscopic velocity to a random one drawn from a - Maxwellian distribution corresponding to a specified temperature + Wall interaction setting microscopic velocity to a random one + drawn from a Maxwellian distribution corresponding to a specified + temperature \*---------------------------------------------------------------------------*/ @@ -73,11 +74,8 @@ public: //- Apply wall correction virtual void correct ( - const wallPolyPatch& wpp, - const label faceId, - vector& U, - scalar& Ei, - label typeId + typename CloudType::parcelType& p, + const wallPolyPatch& wpp ); }; diff --git a/src/lagrangian/dsmc/submodels/WallInteractionModel/MixedDiffuseSpecular/MixedDiffuseSpecular.C b/src/lagrangian/dsmc/submodels/WallInteractionModel/MixedDiffuseSpecular/MixedDiffuseSpecular.C index 91c103a4aa4..9614c81cff8 100644 --- a/src/lagrangian/dsmc/submodels/WallInteractionModel/MixedDiffuseSpecular/MixedDiffuseSpecular.C +++ b/src/lagrangian/dsmc/submodels/WallInteractionModel/MixedDiffuseSpecular/MixedDiffuseSpecular.C @@ -51,20 +51,21 @@ Foam::MixedDiffuseSpecular<CloudType>::~MixedDiffuseSpecular() template <class CloudType> void Foam::MixedDiffuseSpecular<CloudType>::correct ( - const wallPolyPatch& wpp, - const label faceId, - vector& U, - scalar& Ei, - label typeId + typename CloudType::parcelType& p, + const wallPolyPatch& wpp ) { - label wppIndex = wpp.index(); + vector& U = p.U(); + + scalar& Ei = p.Ei(); - label wppLocalFace = wpp.whichFace(faceId); + label typeId = p.typeId(); + + label wppIndex = wpp.index(); - vector nw = wpp.faceAreas()[wppLocalFace]; + label wppLocalFace = wpp.whichFace(p.face()); - // Normal unit vector + vector nw = p.normal(); nw /= mag(nw); // Normal velocity magnitude diff --git a/src/lagrangian/dsmc/submodels/WallInteractionModel/MixedDiffuseSpecular/MixedDiffuseSpecular.H b/src/lagrangian/dsmc/submodels/WallInteractionModel/MixedDiffuseSpecular/MixedDiffuseSpecular.H index f3745dbc907..3a375d5c7a6 100644 --- a/src/lagrangian/dsmc/submodels/WallInteractionModel/MixedDiffuseSpecular/MixedDiffuseSpecular.H +++ b/src/lagrangian/dsmc/submodels/WallInteractionModel/MixedDiffuseSpecular/MixedDiffuseSpecular.H @@ -25,8 +25,11 @@ Class Foam::MixedDiffuseSpecular Description - Wall interaction setting microscopic velocity to a random one drawn from a - Maxwellian distribution corresponding to a specified temperature + Wall interaction setting microscopic velocity to a random one + drawn from a Maxwellian distribution corresponding to a specified + temperature for a specified fraction of collisions, and reversing + the wall-normal component of the particle velocity for the + remainder. \*---------------------------------------------------------------------------*/ @@ -79,11 +82,8 @@ public: //- Apply wall correction virtual void correct ( - const wallPolyPatch& wpp, - const label faceId, - vector& U, - scalar& Ei, - label typeId + typename CloudType::parcelType& p, + const wallPolyPatch& wpp ); }; diff --git a/src/lagrangian/dsmc/submodels/WallInteractionModel/SpecularReflection/SpecularReflection.C b/src/lagrangian/dsmc/submodels/WallInteractionModel/SpecularReflection/SpecularReflection.C index b690a0f87e8..e15a416dd67 100644 --- a/src/lagrangian/dsmc/submodels/WallInteractionModel/SpecularReflection/SpecularReflection.C +++ b/src/lagrangian/dsmc/submodels/WallInteractionModel/SpecularReflection/SpecularReflection.C @@ -52,14 +52,13 @@ Foam::SpecularReflection<CloudType>::~SpecularReflection() template <class CloudType> void Foam::SpecularReflection<CloudType>::correct ( - const wallPolyPatch& wpp, - const label faceId, - vector& U, - scalar& Ei, - label typeId + typename CloudType::parcelType& p, + const wallPolyPatch& wpp ) { - vector nw = wpp.faceAreas()[wpp.whichFace(faceId)]; + vector& U = p.U(); + + vector nw = p.normal(); nw /= mag(nw); scalar U_dot_nw = U & nw; diff --git a/src/lagrangian/dsmc/submodels/WallInteractionModel/SpecularReflection/SpecularReflection.H b/src/lagrangian/dsmc/submodels/WallInteractionModel/SpecularReflection/SpecularReflection.H index 1c47640fe38..68bf2da6891 100644 --- a/src/lagrangian/dsmc/submodels/WallInteractionModel/SpecularReflection/SpecularReflection.H +++ b/src/lagrangian/dsmc/submodels/WallInteractionModel/SpecularReflection/SpecularReflection.H @@ -72,11 +72,8 @@ public: //- Apply wall correction virtual void correct ( - const wallPolyPatch& wpp, - const label faceId, - vector& U, - scalar& Ei, - label typeId + typename CloudType::parcelType& p, + const wallPolyPatch& wpp ); }; diff --git a/src/lagrangian/dsmc/submodels/WallInteractionModel/WallInteractionModel/WallInteractionModel.H b/src/lagrangian/dsmc/submodels/WallInteractionModel/WallInteractionModel/WallInteractionModel.H index dfed430ff76..e0af2025a93 100644 --- a/src/lagrangian/dsmc/submodels/WallInteractionModel/WallInteractionModel/WallInteractionModel.H +++ b/src/lagrangian/dsmc/submodels/WallInteractionModel/WallInteractionModel/WallInteractionModel.H @@ -129,11 +129,8 @@ public: //- Apply wall correction virtual void correct ( - const wallPolyPatch& wpp, - const label faceId, - vector& U, - scalar& Ei, - label typeId + typename CloudType::parcelType& p, + const wallPolyPatch& wpp ) = 0; }; diff --git a/src/lagrangian/intermediate/Make/options b/src/lagrangian/intermediate/Make/options index 5625914e28d..7a208454538 100644 --- a/src/lagrangian/intermediate/Make/options +++ b/src/lagrangian/intermediate/Make/options @@ -17,7 +17,8 @@ EXE_INC = \ -I$(LIB_SRC)/turbulenceModels/compressible/RAS/lnInclude \ -I$(LIB_SRC)/turbulenceModels/LES/LESdeltas/lnInclude \ -I$(LIB_SRC)/turbulenceModels/compressible/LES/lnInclude \ - -I$(LIB_SRC)/surfaceFilmModels/lnInclude + -I$(LIB_SRC)/surfaceFilmModels/lnInclude \ + -I$(LIB_SRC)/dynamicFvMesh/lnInclude LIB_LIBS = \ -lfiniteVolume \ @@ -37,4 +38,6 @@ LIB_LIBS = \ -lODE \ -lcompressibleRASModels \ -lcompressibleLESModels \ + -ldynamicFvMesh \ -lsurfaceFilmModels + diff --git a/src/lagrangian/intermediate/clouds/Templates/KinematicCloud/KinematicCloud.H b/src/lagrangian/intermediate/clouds/Templates/KinematicCloud/KinematicCloud.H index c09988c76d7..5d36cb575e9 100644 --- a/src/lagrangian/intermediate/clouds/Templates/KinematicCloud/KinematicCloud.H +++ b/src/lagrangian/intermediate/clouds/Templates/KinematicCloud/KinematicCloud.H @@ -247,6 +247,13 @@ public: // Access + //- If the collision model controls the wall interaction, + // then the wall impact distance should be zero. + // Otherwise, it should be allowed to be the value from + // the Parcel. + inline bool hasWallImpactDistance() const; + + // References to the mesh and databases //- Return refernce to the mesh diff --git a/src/lagrangian/intermediate/clouds/Templates/KinematicCloud/KinematicCloudI.H b/src/lagrangian/intermediate/clouds/Templates/KinematicCloud/KinematicCloudI.H index ed65e9809ba..9f9b441f43d 100644 --- a/src/lagrangian/intermediate/clouds/Templates/KinematicCloud/KinematicCloudI.H +++ b/src/lagrangian/intermediate/clouds/Templates/KinematicCloud/KinematicCloudI.H @@ -27,6 +27,13 @@ License // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +template<class ParcelType> +inline bool Foam::KinematicCloud<ParcelType>::hasWallImpactDistance() const +{ + return !collision().controlsWallInteraction(); +} + + template<class ParcelType> inline Foam::label Foam::KinematicCloud<ParcelType>::parcelTypeId() const { diff --git a/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcel.C b/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcel.C index 66e4523fcb2..26acc7d9e6e 100644 --- a/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcel.C +++ b/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcel.C @@ -36,7 +36,10 @@ void Foam::KinematicParcel<ParcelType>::setCellValues const label cellI ) { - rhoc_ = td.rhoInterp().interpolate(this->position(), cellI); + tetIndices tetIs = this->currentTetIndices(); + + rhoc_ = td.rhoInterp().interpolate(this->position(), tetIs); + if (rhoc_ < td.constProps().rhoMin()) { WarningIn @@ -53,9 +56,9 @@ void Foam::KinematicParcel<ParcelType>::setCellValues rhoc_ = td.constProps().rhoMin(); } - Uc_ = td.UInterp().interpolate(this->position(), cellI); + Uc_ = td.UInterp().interpolate(this->position(), tetIs); - muc_ = td.muInterp().interpolate(this->position(), cellI); + muc_ = td.muInterp().interpolate(this->position(), tetIs); // Apply dispersion components to carrier phase velocity Uc_ = td.cloud().dispersion().update @@ -159,11 +162,13 @@ const Foam::vector Foam::KinematicParcel<ParcelType>::calcVelocity // Momentum transfer coefficient const scalar utc = td.cloud().drag().utc(Re, d, mu) + ROOTVSMALL; + tetIndices tetIs = this->currentTetIndices(); + // Momentum source due to particle forces const vector FCoupled = mass*td.cloud().forces().calcCoupled ( this->position(), - cellI, + tetIs, dt, rhoc_, rho, @@ -175,7 +180,7 @@ const Foam::vector Foam::KinematicParcel<ParcelType>::calcVelocity const vector FNonCoupled = mass*td.cloud().forces().calcNonCoupled ( this->position(), - cellI, + tetIs, dt, rhoc_, rho, @@ -340,7 +345,9 @@ bool Foam::KinematicParcel<ParcelType>::hitPatch ( const polyPatch& pp, TrackData& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ) { ParcelType& p = static_cast<ParcelType&>(*this); @@ -360,15 +367,14 @@ bool Foam::KinematicParcel<ParcelType>::hitPatch else { // Invoke patch interaction model - return - td.cloud().patchInteraction().correct - ( - pp, - this->face(), - td.keepParticle, - active_, - U_ - ); + return td.cloud().patchInteraction().correct + ( + static_cast<ParcelType&>(*this), + pp, + td.keepParticle, + trackFraction, + tetIs + ); } } @@ -378,7 +384,9 @@ bool Foam::KinematicParcel<ParcelType>::hitPatch ( const polyPatch& pp, int& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ) { return false; @@ -411,7 +419,8 @@ template<class TrackData> void Foam::KinematicParcel<ParcelType>::hitWallPatch ( const wallPolyPatch& wpp, - TrackData& td + TrackData& td, + const tetIndices& ) { // Wall interactions handled by generic hitPatch function @@ -422,7 +431,8 @@ template<class ParcelType> void Foam::KinematicParcel<ParcelType>::hitWallPatch ( const wallPolyPatch&, - int& + int&, + const tetIndices& ) {} @@ -440,7 +450,11 @@ void Foam::KinematicParcel<ParcelType>::hitPatch template<class ParcelType> -void Foam::KinematicParcel<ParcelType>::hitPatch(const polyPatch&, int&) +void Foam::KinematicParcel<ParcelType>::hitPatch +( + const polyPatch&, + int& +) {} diff --git a/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcel.H b/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcel.H index 8b693c62208..b87a1390df4 100644 --- a/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcel.H +++ b/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcel.H @@ -331,7 +331,9 @@ public: ( KinematicCloud<ParcelType>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ); //- Construct from components @@ -340,6 +342,8 @@ public: KinematicCloud<ParcelType>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, @@ -544,20 +548,22 @@ public: ( const polyPatch& p, TrackData& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ); - //- Overridable function to handle the particle hitting a patch // Executed before other patch-hitting functions without trackData bool hitPatch ( const polyPatch& p, int& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ); - //- Overridable function to handle the particle hitting a // processorPatch template<class TrackData> @@ -580,7 +586,8 @@ public: void hitWallPatch ( const wallPolyPatch&, - TrackData& td + TrackData& td, + const tetIndices& ); //- Overridable function to handle the particle hitting a wallPatch @@ -588,7 +595,8 @@ public: void hitWallPatch ( const wallPolyPatch&, - int& + int&, + const tetIndices& ); //- Overridable function to handle the particle hitting a polyPatch diff --git a/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcelI.H b/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcelI.H index 1a274b258b1..a6f41647c78 100644 --- a/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcelI.H +++ b/src/lagrangian/intermediate/parcels/Templates/KinematicParcel/KinematicParcelI.H @@ -81,10 +81,12 @@ inline Foam::KinematicParcel<ParcelType>::KinematicParcel ( KinematicCloud<ParcelType>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ) : - Particle<ParcelType>(owner, position, cellI), + Particle<ParcelType>(owner, position, cellI, tetFaceI, tetPtI), active_(true), typeId_(owner.parcelTypeId()), nParticle_(0), @@ -109,6 +111,8 @@ inline Foam::KinematicParcel<ParcelType>::KinematicParcel KinematicCloud<ParcelType>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, @@ -119,7 +123,7 @@ inline Foam::KinematicParcel<ParcelType>::KinematicParcel const constantProperties& constProps ) : - Particle<ParcelType>(owner, position, cellI), + Particle<ParcelType>(owner, position, cellI, tetFaceI, tetPtI), active_(true), typeId_(typeId), nParticle_(nParticle0), @@ -439,23 +443,7 @@ inline Foam::scalar Foam::KinematicParcel<ParcelType>::wallImpactDistance const vector& ) const { - const KinematicCloud<ParcelType>& c = - dynamic_cast<const KinematicCloud<ParcelType>&>(this->cloud()); - - if (c.collision().controlsWallInteraction()) - { - // Do not use a wall impact distance if the collision model - // controls wall interactions to allow proper multiple face - // collisions. In a twisted mesh the particle can be within - // range of a wall but not in the cell attached to a wall - // face, hence miss the interaction. - - return 0.0; - } - else - { - return 0.5*d_; - } + return 0.5*d_; } diff --git a/src/lagrangian/intermediate/parcels/Templates/ReactingMultiphaseParcel/ReactingMultiphaseParcel.H b/src/lagrangian/intermediate/parcels/Templates/ReactingMultiphaseParcel/ReactingMultiphaseParcel.H index ffb7f9b47e1..3fb4ef24218 100644 --- a/src/lagrangian/intermediate/parcels/Templates/ReactingMultiphaseParcel/ReactingMultiphaseParcel.H +++ b/src/lagrangian/intermediate/parcels/Templates/ReactingMultiphaseParcel/ReactingMultiphaseParcel.H @@ -289,7 +289,9 @@ public: ( ReactingMultiphaseCloud<ParcelType>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ); @@ -299,6 +301,8 @@ public: ReactingMultiphaseCloud<ParcelType>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, diff --git a/src/lagrangian/intermediate/parcels/Templates/ReactingMultiphaseParcel/ReactingMultiphaseParcelI.H b/src/lagrangian/intermediate/parcels/Templates/ReactingMultiphaseParcel/ReactingMultiphaseParcelI.H index c7a557fba6f..5899d2a6666 100644 --- a/src/lagrangian/intermediate/parcels/Templates/ReactingMultiphaseParcel/ReactingMultiphaseParcelI.H +++ b/src/lagrangian/intermediate/parcels/Templates/ReactingMultiphaseParcel/ReactingMultiphaseParcelI.H @@ -89,10 +89,12 @@ inline Foam::ReactingMultiphaseParcel<ParcelType>::ReactingMultiphaseParcel ( ReactingMultiphaseCloud<ParcelType>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ) : - ReactingParcel<ParcelType>(owner, position, cellI), + ReactingParcel<ParcelType>(owner, position, cellI, tetFaceI, tetPtI), YGas_(0), YLiquid_(0), YSolid_(0), @@ -106,6 +108,8 @@ inline Foam::ReactingMultiphaseParcel<ParcelType>::ReactingMultiphaseParcel ReactingMultiphaseCloud<ParcelType>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, @@ -125,6 +129,8 @@ inline Foam::ReactingMultiphaseParcel<ParcelType>::ReactingMultiphaseParcel owner, position, cellI, + tetFaceI, + tetPtI, typeId, nParticle0, d0, diff --git a/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcel.C b/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcel.C index fa5f3f5ede3..f0321988560 100644 --- a/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcel.C +++ b/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcel.C @@ -42,7 +42,12 @@ void Foam::ReactingParcel<ParcelType>::setCellValues { ThermoParcel<ParcelType>::setCellValues(td, dt, cellI); - pc_ = td.pInterp().interpolate(this->position(), cellI); + pc_ = td.pInterp().interpolate + ( + this->position(), + this->currentTetIndices() + ); + if (pc_ < td.constProps().pMin()) { WarningIn diff --git a/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcel.H b/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcel.H index 38e607bd39f..415967c7c53 100644 --- a/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcel.H +++ b/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcel.H @@ -239,7 +239,9 @@ public: ( ReactingCloud<ParcelType>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ); //- Construct from components @@ -248,6 +250,8 @@ public: ReactingCloud<ParcelType>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, diff --git a/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcelI.H b/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcelI.H index 736b230f08b..39beae61cf0 100644 --- a/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcelI.H +++ b/src/lagrangian/intermediate/parcels/Templates/ReactingParcel/ReactingParcelI.H @@ -75,10 +75,12 @@ inline Foam::ReactingParcel<ParcelType>::ReactingParcel ( ReactingCloud<ParcelType>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ) : - ThermoParcel<ParcelType>(owner, position, cellI), + ThermoParcel<ParcelType>(owner, position, cellI, tetFaceI, tetPtI), mass0_(0.0), Y_(0), pc_(0.0) @@ -91,6 +93,8 @@ inline Foam::ReactingParcel<ParcelType>::ReactingParcel ReactingCloud<ParcelType>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, @@ -107,6 +111,8 @@ inline Foam::ReactingParcel<ParcelType>::ReactingParcel owner, position, cellI, + tetFaceI, + tetPtI, typeId, nParticle0, d0, diff --git a/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcel.C b/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcel.C index 6800129a9bd..dbcc01ad2ab 100644 --- a/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcel.C +++ b/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcel.C @@ -41,9 +41,11 @@ void Foam::ThermoParcel<ParcelType>::setCellValues { KinematicParcel<ParcelType>::setCellValues(td, dt, cellI); - cpc_ = td.cpInterp().interpolate(this->position(), cellI); + tetIndices tetIs = this->currentTetIndices(); - Tc_ = td.TInterp().interpolate(this->position(), cellI); + cpc_ = td.cpInterp().interpolate(this->position(), tetIs); + + Tc_ = td.TInterp().interpolate(this->position(), tetIs); if (Tc_ < td.constProps().TMin()) { @@ -96,10 +98,14 @@ void Foam::ThermoParcel<ParcelType>::calcSurfaceValues // Surface temperature using two thirds rule Ts = (2.0*T + Tc_)/3.0; + tetIndices tetIs = this->currentTetIndices(); + // Assuming thermo props vary linearly with T for small dT - scalar factor = td.TInterp().interpolate(this->position(), cellI)/Ts; + scalar factor = td.TInterp().interpolate (this->position(), tetIs)/Ts; + rhos = this->rhoc_*factor; - mus = td.muInterp().interpolate(this->position(), cellI)/factor; + + mus = td.muInterp().interpolate (this->position(), tetIs)/factor; Pr = td.constProps().Pr(); kappa = cpc_*mus/Pr; diff --git a/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcel.H b/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcel.H index 8715aa570e9..5632d76592b 100644 --- a/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcel.H +++ b/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcel.H @@ -252,7 +252,9 @@ public: ( ThermoCloud<ParcelType>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ); //- Construct from components @@ -261,6 +263,8 @@ public: ThermoCloud<ParcelType>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, diff --git a/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcelI.H b/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcelI.H index 05dce5832d9..b046f142ddd 100644 --- a/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcelI.H +++ b/src/lagrangian/intermediate/parcels/Templates/ThermoParcel/ThermoParcelI.H @@ -75,10 +75,12 @@ inline Foam::ThermoParcel<ParcelType>::ThermoParcel ( ThermoCloud<ParcelType>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ) : - KinematicParcel<ParcelType>(owner, position, cellI), + KinematicParcel<ParcelType>(owner, position, cellI, tetFaceI, tetPtI), T_(0.0), cp_(0.0), Tc_(0.0), @@ -92,6 +94,8 @@ inline Foam::ThermoParcel<ParcelType>::ThermoParcel ThermoCloud<ParcelType>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, @@ -107,6 +111,8 @@ inline Foam::ThermoParcel<ParcelType>::ThermoParcel owner, position, cellI, + tetFaceI, + tetPtI, typeId, nParticle0, d0, diff --git a/src/lagrangian/intermediate/parcels/derived/basicKinematicParcel/basicKinematicParcel.C b/src/lagrangian/intermediate/parcels/derived/basicKinematicParcel/basicKinematicParcel.C index 61b201f282b..4ec2941bf78 100644 --- a/src/lagrangian/intermediate/parcels/derived/basicKinematicParcel/basicKinematicParcel.C +++ b/src/lagrangian/intermediate/parcels/derived/basicKinematicParcel/basicKinematicParcel.C @@ -41,10 +41,19 @@ Foam::basicKinematicParcel::basicKinematicParcel ( KinematicCloud<basicKinematicParcel>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ) : - KinematicParcel<basicKinematicParcel>(owner, position, cellI) + KinematicParcel<basicKinematicParcel> + ( + owner, + position, + cellI, + tetFaceI, + tetPtI + ) {} @@ -53,6 +62,8 @@ Foam::basicKinematicParcel::basicKinematicParcel KinematicCloud<basicKinematicParcel>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, @@ -68,6 +79,8 @@ Foam::basicKinematicParcel::basicKinematicParcel owner, position, cellI, + tetFaceI, + tetPtI, typeId, nParticle0, d0, diff --git a/src/lagrangian/intermediate/parcels/derived/basicKinematicParcel/basicKinematicParcel.H b/src/lagrangian/intermediate/parcels/derived/basicKinematicParcel/basicKinematicParcel.H index bd86c395b75..56d9cad296e 100644 --- a/src/lagrangian/intermediate/parcels/derived/basicKinematicParcel/basicKinematicParcel.H +++ b/src/lagrangian/intermediate/parcels/derived/basicKinematicParcel/basicKinematicParcel.H @@ -65,7 +65,9 @@ public: ( KinematicCloud<basicKinematicParcel>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ); //- Construct from components @@ -74,6 +76,8 @@ public: KinematicCloud<basicKinematicParcel>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, diff --git a/src/lagrangian/intermediate/parcels/derived/basicReactingMultiphaseParcel/basicReactingMultiphaseParcel.C b/src/lagrangian/intermediate/parcels/derived/basicReactingMultiphaseParcel/basicReactingMultiphaseParcel.C index 56359e0d961..49e4e06ef4c 100644 --- a/src/lagrangian/intermediate/parcels/derived/basicReactingMultiphaseParcel/basicReactingMultiphaseParcel.C +++ b/src/lagrangian/intermediate/parcels/derived/basicReactingMultiphaseParcel/basicReactingMultiphaseParcel.C @@ -31,14 +31,18 @@ Foam::basicReactingMultiphaseParcel::basicReactingMultiphaseParcel ( ReactingMultiphaseCloud<basicReactingMultiphaseParcel>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ) : ReactingMultiphaseParcel<basicReactingMultiphaseParcel> ( owner, position, - cellI + cellI, + tetFaceI, + tetPtI ) {} @@ -48,6 +52,8 @@ Foam::basicReactingMultiphaseParcel::basicReactingMultiphaseParcel ReactingMultiphaseCloud<basicReactingMultiphaseParcel>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, @@ -63,11 +69,13 @@ Foam::basicReactingMultiphaseParcel::basicReactingMultiphaseParcel constantProperties& constProps ) : - ReactingMultiphaseParcel<basicReactingMultiphaseParcel > + ReactingMultiphaseParcel<basicReactingMultiphaseParcel> ( owner, position, cellI, + tetFaceI, + tetPtI, typeId, nParticle0, d0, diff --git a/src/lagrangian/intermediate/parcels/derived/basicReactingMultiphaseParcel/basicReactingMultiphaseParcel.H b/src/lagrangian/intermediate/parcels/derived/basicReactingMultiphaseParcel/basicReactingMultiphaseParcel.H index 6cc9d2f535a..1c9d2db2d72 100644 --- a/src/lagrangian/intermediate/parcels/derived/basicReactingMultiphaseParcel/basicReactingMultiphaseParcel.H +++ b/src/lagrangian/intermediate/parcels/derived/basicReactingMultiphaseParcel/basicReactingMultiphaseParcel.H @@ -66,7 +66,9 @@ public: ( ReactingMultiphaseCloud<basicReactingMultiphaseParcel>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ); //- Construct from components @@ -75,6 +77,8 @@ public: ReactingMultiphaseCloud<basicReactingMultiphaseParcel>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, diff --git a/src/lagrangian/intermediate/parcels/derived/basicReactingParcel/basicReactingParcel.C b/src/lagrangian/intermediate/parcels/derived/basicReactingParcel/basicReactingParcel.C index 23ef85c02ec..f60f30b552b 100644 --- a/src/lagrangian/intermediate/parcels/derived/basicReactingParcel/basicReactingParcel.C +++ b/src/lagrangian/intermediate/parcels/derived/basicReactingParcel/basicReactingParcel.C @@ -29,20 +29,31 @@ License Foam::basicReactingParcel::basicReactingParcel ( - ReactingCloud<basicReactingParcel >& owner, + ReactingCloud<basicReactingParcel>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ) : - ReactingParcel<basicReactingParcel >(owner, position, cellI) + ReactingParcel<basicReactingParcel> + ( + owner, + position, + cellI, + tetFaceI, + tetPtI + ) {} Foam::basicReactingParcel::basicReactingParcel ( - ReactingCloud<basicReactingParcel >& owner, + ReactingCloud<basicReactingParcel>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, @@ -54,11 +65,13 @@ Foam::basicReactingParcel::basicReactingParcel const ReactingParcel<basicReactingParcel>::constantProperties& constProps ) : - ReactingParcel<basicReactingParcel > + ReactingParcel<basicReactingParcel> ( owner, position, cellI, + tetFaceI, + tetPtI, typeId, nParticle0, d0, @@ -74,7 +87,7 @@ Foam::basicReactingParcel::basicReactingParcel Foam::basicReactingParcel::basicReactingParcel ( - const Cloud<basicReactingParcel >& cloud, + const Cloud<basicReactingParcel>& cloud, Istream& is, bool readFields ) diff --git a/src/lagrangian/intermediate/parcels/derived/basicReactingParcel/basicReactingParcel.H b/src/lagrangian/intermediate/parcels/derived/basicReactingParcel/basicReactingParcel.H index 86e9d726f5a..4329c61d9c3 100644 --- a/src/lagrangian/intermediate/parcels/derived/basicReactingParcel/basicReactingParcel.H +++ b/src/lagrangian/intermediate/parcels/derived/basicReactingParcel/basicReactingParcel.H @@ -64,7 +64,9 @@ public: ( ReactingCloud<basicReactingParcel>& owner, const vector& position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ); //- Construct from components @@ -73,6 +75,8 @@ public: ReactingCloud<basicReactingParcel>& owner, const vector& position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, diff --git a/src/lagrangian/intermediate/parcels/derived/basicThermoParcel/basicThermoParcel.C b/src/lagrangian/intermediate/parcels/derived/basicThermoParcel/basicThermoParcel.C index c233efbd6fe..b77bf79b93c 100644 --- a/src/lagrangian/intermediate/parcels/derived/basicThermoParcel/basicThermoParcel.C +++ b/src/lagrangian/intermediate/parcels/derived/basicThermoParcel/basicThermoParcel.C @@ -41,10 +41,12 @@ Foam::basicThermoParcel::basicThermoParcel ( ThermoCloud<basicThermoParcel>& owner, const vector position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ) : - ThermoParcel<basicThermoParcel>(owner, position, cellI) + ThermoParcel<basicThermoParcel>(owner, position, cellI, tetFaceI, tetPtI) {} @@ -53,6 +55,8 @@ Foam::basicThermoParcel::basicThermoParcel ThermoCloud<basicThermoParcel>& owner, const vector position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, @@ -68,6 +72,8 @@ Foam::basicThermoParcel::basicThermoParcel owner, position, cellI, + tetFaceI, + tetPtI, typeId, nParticle0, d0, diff --git a/src/lagrangian/intermediate/parcels/derived/basicThermoParcel/basicThermoParcel.H b/src/lagrangian/intermediate/parcels/derived/basicThermoParcel/basicThermoParcel.H index 63c5b505570..71614c7d9d0 100644 --- a/src/lagrangian/intermediate/parcels/derived/basicThermoParcel/basicThermoParcel.H +++ b/src/lagrangian/intermediate/parcels/derived/basicThermoParcel/basicThermoParcel.H @@ -64,7 +64,9 @@ public: ( ThermoCloud<basicThermoParcel>& owner, const vector position, - const label cellI + const label cellI, + const label tetFaceI, + const label tetPtI ); //- Construct from components @@ -73,6 +75,8 @@ public: ThermoCloud<basicThermoParcel>& owner, const vector position, const label cellI, + const label tetFaceI, + const label tetPtI, const label typeId, const scalar nParticle0, const scalar d0, diff --git a/src/lagrangian/intermediate/particleForces/particleForces.C b/src/lagrangian/intermediate/particleForces/particleForces.C index 6591d2b8d44..3a2865d41db 100644 --- a/src/lagrangian/intermediate/particleForces/particleForces.C +++ b/src/lagrangian/intermediate/particleForces/particleForces.C @@ -68,8 +68,8 @@ Foam::particleForces::particleForces pressureGradient_(dict_.lookup("pressureGradient")), paramagnetic_(dict_.lookup("paramagnetic")), magneticSusceptibility_(0.0), - UName_(dict_.lookupOrDefault<word>("U", "U")), - HdotGradHName_(dict_.lookupOrDefault<word>("HdotGradH", "HdotGradH")) + UName_(dict_.lookupOrDefault<word>("UName", "U")), + HdotGradHName_(dict_.lookupOrDefault<word>("HdotGradHName", "HdotGradH")) { if (virtualMass_) { @@ -211,7 +211,7 @@ void Foam::particleForces::cacheFields Foam::vector Foam::particleForces::calcCoupled ( const vector& position, - const label cellI, + const tetIndices& tetIs, const scalar dt, const scalar rhoc, const scalar rho, @@ -236,7 +236,7 @@ Foam::vector Foam::particleForces::calcCoupled if (pressureGradient_) { const volTensorField& gradU = *gradUPtr_; - accelTot += rhoc/rho*(U & gradU[cellI]); + accelTot += rhoc/rho*(U & gradU[tetIs.cell()]); } return accelTot; @@ -246,7 +246,7 @@ Foam::vector Foam::particleForces::calcCoupled Foam::vector Foam::particleForces::calcNonCoupled ( const vector& position, - const label cellI, + const tetIndices& tetIs, const scalar dt, const scalar rhoc, const scalar rho, @@ -272,7 +272,7 @@ Foam::vector Foam::particleForces::calcNonCoupled accelTot += 3.0*constant::electromagnetic::mu0.value()/rho *magneticSusceptibility_/(magneticSusceptibility_ + 3) - *HdotGradHInter.interpolate(position, cellI); + *HdotGradHInter.interpolate(position, tetIs); // force is: diff --git a/src/lagrangian/intermediate/particleForces/particleForces.H b/src/lagrangian/intermediate/particleForces/particleForces.H index 8c76b1f773d..7aacee74b34 100644 --- a/src/lagrangian/intermediate/particleForces/particleForces.H +++ b/src/lagrangian/intermediate/particleForces/particleForces.H @@ -41,6 +41,7 @@ SourceFiles #include "vector.H" #include "volFieldsFwd.H" #include "interpolation.H" +#include "tetIndices.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -179,7 +180,7 @@ public: vector calcCoupled ( const vector& position, - const label cellI, + const tetIndices& tetIs, const scalar dt, const scalar rhoc, const scalar rho, @@ -192,7 +193,7 @@ public: vector calcNonCoupled ( const vector& position, - const label cellI, + const tetIndices& tetIs, const scalar dt, const scalar rhoc, const scalar rho, diff --git a/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/DispersionModel/DispersionModel.H b/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/DispersionModel/DispersionModel.H index b1634db21e1..afb063d0f5c 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/DispersionModel/DispersionModel.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/DispersionModel/DispersionModel.H @@ -127,7 +127,7 @@ public: virtual vector update ( const scalar dt, - const label celli, + const label cellI, const vector& U, const vector& Uc, vector& UTurb, diff --git a/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/GradientDispersionRAS/GradientDispersionRAS.C b/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/GradientDispersionRAS/GradientDispersionRAS.C index d214303427e..05617f25dae 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/GradientDispersionRAS/GradientDispersionRAS.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/GradientDispersionRAS/GradientDispersionRAS.C @@ -81,7 +81,7 @@ template<class CloudType> Foam::vector Foam::GradientDispersionRAS<CloudType>::update ( const scalar dt, - const label celli, + const label cellI, const vector& U, const vector& Uc, vector& UTurb, @@ -98,8 +98,8 @@ Foam::vector Foam::GradientDispersionRAS<CloudType>::update const scalar tTurbLoc = min ( - k[celli]/epsilon[celli], - cps*pow(k[celli], 1.5)/epsilon[celli]/(UrelMag + SMALL) + k[cellI]/epsilon[cellI], + cps*pow(k[cellI], 1.5)/epsilon[cellI]/(UrelMag + SMALL) ); // Parcel is perturbed by the turbulence @@ -111,8 +111,8 @@ Foam::vector Foam::GradientDispersionRAS<CloudType>::update { tTurb = 0.0; - scalar sigma = sqrt(2.0*k[celli]/3.0); - vector dir = -gradk[celli]/(mag(gradk[celli]) + SMALL); + scalar sigma = sqrt(2.0*k[cellI]/3.0); + vector dir = -gradk[cellI]/(mag(gradk[cellI]) + SMALL); // Numerical Recipes... Ch. 7. Random Numbers... scalar x1 = 0.0; diff --git a/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/GradientDispersionRAS/GradientDispersionRAS.H b/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/GradientDispersionRAS/GradientDispersionRAS.H index eb4c97e0614..af74d2578b1 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/GradientDispersionRAS/GradientDispersionRAS.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/GradientDispersionRAS/GradientDispersionRAS.H @@ -90,7 +90,7 @@ public: virtual vector update ( const scalar dt, - const label celli, + const label cellI, const vector& U, const vector& Uc, vector& UTurb, diff --git a/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/NoDispersion/NoDispersion.H b/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/NoDispersion/NoDispersion.H index a8bba39ef46..e63abbda213 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/NoDispersion/NoDispersion.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/NoDispersion/NoDispersion.H @@ -80,7 +80,7 @@ public: virtual vector update ( const scalar dt, - const label celli, + const label cellI, const vector& U, const vector& Uc, vector& UTurb, diff --git a/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/StochasticDispersionRAS/StochasticDispersionRAS.C b/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/StochasticDispersionRAS/StochasticDispersionRAS.C index 20368957d70..a43b00c10f9 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/StochasticDispersionRAS/StochasticDispersionRAS.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/StochasticDispersionRAS/StochasticDispersionRAS.C @@ -58,7 +58,7 @@ template<class CloudType> Foam::vector Foam::StochasticDispersionRAS<CloudType>::update ( const scalar dt, - const label celli, + const label cellI, const vector& U, const vector& Uc, vector& UTurb, @@ -74,8 +74,8 @@ Foam::vector Foam::StochasticDispersionRAS<CloudType>::update const scalar tTurbLoc = min ( - k[celli]/epsilon[celli], - cps*pow(k[celli], 1.5)/epsilon[celli]/(UrelMag + SMALL) + k[cellI]/epsilon[cellI], + cps*pow(k[cellI], 1.5)/epsilon[cellI]/(UrelMag + SMALL) ); // Parcel is perturbed by the turbulence @@ -87,7 +87,7 @@ Foam::vector Foam::StochasticDispersionRAS<CloudType>::update { tTurb = 0.0; - scalar sigma = sqrt(2.0*k[celli]/3.0); + scalar sigma = sqrt(2.0*k[cellI]/3.0); vector dir = 2.0*this->owner().rndGen().vector01() - vector::one; dir /= mag(dir) + SMALL; diff --git a/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/StochasticDispersionRAS/StochasticDispersionRAS.H b/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/StochasticDispersionRAS/StochasticDispersionRAS.H index b9663a90595..dae1658c912 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/StochasticDispersionRAS/StochasticDispersionRAS.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/DispersionModel/StochasticDispersionRAS/StochasticDispersionRAS.H @@ -79,7 +79,7 @@ public: virtual vector update ( const scalar dt, - const label celli, + const label cellI, const vector& U, const vector& Uc, vector& UTurb, diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjection/ConeInjection.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjection/ConeInjection.C index cb665641ccb..3047f909aff 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjection/ConeInjection.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjection/ConeInjection.C @@ -80,6 +80,8 @@ Foam::ConeInjection<CloudType>::ConeInjection duration_(readScalar(this->coeffDict().lookup("duration"))), position_(this->coeffDict().lookup("position")), injectorCell_(-1), + injectorTetFace_(-1), + injectorTetPt_(-1), direction_(this->coeffDict().lookup("direction")), parcelsPerSecond_ ( @@ -150,7 +152,13 @@ Foam::ConeInjection<CloudType>::ConeInjection this->volumeTotal_ = flowRateProfile_().integrate(0.0, duration_); // Set/cache the injector cell - this->findCellAtPosition(injectorCell_, position_); + this->findCellAtPosition + ( + injectorCell_, + injectorTetFace_, + injectorTetPt_, + position_ + ); } @@ -184,11 +192,15 @@ void Foam::ConeInjection<CloudType>::setPositionAndCell const label, const scalar, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ) { position = position_; cellOwner = injectorCell_; + tetFaceI = injectorTetFace_; + tetPtI = injectorTetPt_; } diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjection/ConeInjection.H b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjection/ConeInjection.H index 6246f4cdc9e..58309fa8654 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjection/ConeInjection.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjection/ConeInjection.H @@ -77,6 +77,12 @@ class ConeInjection //- Cell containing injector position [] label injectorCell_; + //- tetFace of tet containing injector position [] + label injectorTetFace_; + + //- tetPt of tet containing injector position [] + label injectorTetPt_; + //- Injector direction [] vector direction_; @@ -158,14 +164,16 @@ public: // Injection geometry - //- Set the injection position and owner cell + //- Set the injection position and owner cell, tetFace and tetPt virtual void setPositionAndCell ( const label parcelI, const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ); //- Set the parcel properties diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjectionMP/ConeInjectionMP.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjectionMP/ConeInjectionMP.C index 1d3f49aaa59..05cfb680a4f 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjectionMP/ConeInjectionMP.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjectionMP/ConeInjectionMP.C @@ -99,6 +99,8 @@ Foam::ConeInjectionMP<CloudType>::ConeInjectionMP ) ), injectorCells_(positions_.size()), + injectorTetFaces_(positions_.size()), + injectorTetPts_(positions_.size()), axesFile_(this->coeffDict().lookup("axesFile")), axes_ ( @@ -190,6 +192,8 @@ Foam::ConeInjectionMP<CloudType>::ConeInjectionMP this->findCellAtPosition ( injectorCells_[i], + injectorTetFaces_[i], + injectorTetPts_[i], positions_[i] ); } @@ -226,13 +230,17 @@ void Foam::ConeInjectionMP<CloudType>::setPositionAndCell const label, const scalar, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ) { - const label i = parcelI%positions_.size(); + const label i = parcelI % positions_.size(); position = positions_[i]; cellOwner = injectorCells_[i]; + tetFaceI = injectorTetFaces_[i]; + tetPtI = injectorTetPts_[i]; } diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjectionMP/ConeInjectionMP.H b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjectionMP/ConeInjectionMP.H index 5401deebee8..1033defe8b5 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjectionMP/ConeInjectionMP.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeInjectionMP/ConeInjectionMP.H @@ -75,9 +75,15 @@ class ConeInjectionMP //- Field of injector positions vectorIOField positions_; - //- Field of cell labels corresoponding to injector positions + //- List of cell labels corresponding to injector positions labelList injectorCells_; + //- List of tetFace labels corresponding to injector positions + labelList injectorTetFaces_; + + //- List of tetPt labels corresponding to injector positions + labelList injectorTetPts_; + //- Name of file containing axes data const word axesFile_; @@ -168,14 +174,16 @@ public: // Injection geometry - //- Set the injection position and owner cell + //- Set the injection position and owner cell, tetFace and tetPt virtual void setPositionAndCell ( const label parcelI, const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ); //- Set the parcel properties diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/FieldActivatedInjection/FieldActivatedInjection.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/FieldActivatedInjection/FieldActivatedInjection.C index 533febfadcf..a0dae5cb34f 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/FieldActivatedInjection/FieldActivatedInjection.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/FieldActivatedInjection/FieldActivatedInjection.C @@ -105,6 +105,8 @@ Foam::FieldActivatedInjection<CloudType>::FieldActivatedInjection ) ), injectorCells_(positions_.size()), + injectorTetFaces_(positions_.size()), + injectorTetPts_(positions_.size()), nParcelsPerInjector_ ( readLabel(this->coeffDict().lookup("parcelsPerInjector")) @@ -137,6 +139,8 @@ Foam::FieldActivatedInjection<CloudType>::FieldActivatedInjection this->findCellAtPosition ( injectorCells_[i], + injectorTetFaces_[i], + injectorTetPts_[i], positions_[i] ); } @@ -173,11 +177,15 @@ void Foam::FieldActivatedInjection<CloudType>::setPositionAndCell const label, const scalar, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ) { position = positions_[parcelI]; cellOwner = injectorCells_[parcelI]; + tetFaceI = injectorTetFaces_[parcelI]; + tetPtI = injectorTetPts_[parcelI]; } diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/FieldActivatedInjection/FieldActivatedInjection.H b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/FieldActivatedInjection/FieldActivatedInjection.H index f2aebb0fd8c..282e876cc66 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/FieldActivatedInjection/FieldActivatedInjection.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/FieldActivatedInjection/FieldActivatedInjection.H @@ -86,13 +86,19 @@ class FieldActivatedInjection //- Field of injector (x,y,z) positions vectorIOField positions_; - //- Field of cell labels corresponding to injector positions + //- List of cell labels corresponding to injector positions labelList injectorCells_; + //- List of tetFace labels corresponding to injector positions + labelList injectorTetFaces_; + + //- List of tetPt labels corresponding to injector positions + labelList injectorTetPts_; + //- Number of parcels per injector const label nParcelsPerInjector_; - //- Field of number of parcels injected for each injector + //- List of number of parcels injected for each injector labelList nParcelsInjected_; @@ -101,7 +107,7 @@ class FieldActivatedInjection //- Initial parcel velocity const vector U0_; - //- Field of parcel diameters + //- List of parcel diameters scalarList diameters_; //- Parcel size PDF model @@ -158,14 +164,16 @@ public: // Injection geometry - //- Set the injection position and owner cell + //- Set the injection position and owner cell, tetFace and tetPt virtual void setPositionAndCell ( const label parcelI, const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ); //- Set the parcel properties diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.C index c56ff296183..9136baa6079 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.C @@ -132,6 +132,8 @@ template<class CloudType> bool Foam::InjectionModel<CloudType>::findCellAtPosition ( label& cellI, + label& tetFaceI, + label& tetPtI, vector& position, bool errorOnNotFound ) @@ -140,7 +142,13 @@ bool Foam::InjectionModel<CloudType>::findCellAtPosition const vector p0 = position; - cellI = owner_.mesh().findCell(position); + owner_.findCellFacePt + ( + position, + cellI, + tetFaceI, + tetPtI + ); label procI = -1; @@ -148,10 +156,14 @@ bool Foam::InjectionModel<CloudType>::findCellAtPosition { procI = Pstream::myProcNo(); } + reduce(procI, maxOp<label>()); + if (procI != Pstream::myProcNo()) { cellI = -1; + tetFaceI = -1; + tetPtI = -1; } // Last chance - find nearest cell and try that one @@ -168,10 +180,14 @@ bool Foam::InjectionModel<CloudType>::findCellAtPosition procI = Pstream::myProcNo(); } } + reduce(procI, maxOp<label>()); + if (procI != Pstream::myProcNo()) { cellI = -1; + tetFaceI = -1; + tetPtI = -1; } } @@ -421,8 +437,21 @@ void Foam::InjectionModel<CloudType>::inject(TrackData& td) // Determine the injection position and owner cell label cellI = -1; + label tetFaceI = -1; + label tetPtI = -1; + vector pos = vector::zero; - setPositionAndCell(parcelI, newParcels, timeInj, pos, cellI); + + setPositionAndCell + ( + parcelI, + newParcels, + timeInj, + pos, + cellI, + tetFaceI, + tetPtI + ); if (cellI > -1) { @@ -433,7 +462,14 @@ void Foam::InjectionModel<CloudType>::inject(TrackData& td) meshTools::constrainToMeshCentre(mesh, pos); // Create a new parcel - parcelType* pPtr = new parcelType(td.cloud(), pos, cellI); + parcelType* pPtr = new parcelType + ( + td.cloud(), + pos, + cellI, + tetFaceI, + tetPtI + ); // Assign new parcel properties in injection model setProperties(parcelI, newParcels, timeInj, *pPtr); diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.H b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.H index b40abbde90f..542e038b4ac 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/InjectionModel/InjectionModel.H @@ -183,6 +183,8 @@ protected: virtual bool findCellAtPosition ( label& cellI, + label& tetFaceI, + label& tetPtI, vector& position, bool errorOnNotFound = true ); @@ -305,14 +307,16 @@ public: // Injection geometry - //- Set the injection position and owner cell + //- Set the injection position and owner cell, tetFace and tetPt virtual void setPositionAndCell ( const label parcelI, const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ) = 0; //- Set the parcel properties diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/KinematicLookupTableInjection/KinematicLookupTableInjection.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/KinematicLookupTableInjection/KinematicLookupTableInjection.C index 413af8a0731..45fd5b0df6a 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/KinematicLookupTableInjection/KinematicLookupTableInjection.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/KinematicLookupTableInjection/KinematicLookupTableInjection.C @@ -93,13 +93,24 @@ Foam::KinematicLookupTableInjection<CloudType>::KinematicLookupTableInjection IOobject::NO_WRITE ) ), - injectorCells_(0) + injectorCells_(0), + injectorTetFaces_(0), + injectorTetPts_(0) { // Set/cache the injector cells injectorCells_.setSize(injectors_.size()); + injectorTetFaces_.setSize(injectors_.size()); + injectorTetPts_.setSize(injectors_.size()); + forAll(injectors_, i) { - this->findCellAtPosition(injectorCells_[i], injectors_[i].x()); + this->findCellAtPosition + ( + injectorCells_[i], + injectorTetFaces_[i], + injectorTetPts_[i], + injectors_[i].x() + ); } // Determine volume of particles to inject @@ -142,13 +153,17 @@ void Foam::KinematicLookupTableInjection<CloudType>::setPositionAndCell const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ) { label injectorI = parcelI*injectorCells_.size()/nParcels; position = injectors_[injectorI].x(); cellOwner = injectorCells_[injectorI]; + tetFaceI = injectorTetFaces_[injectorI]; + tetPtI = injectorTetPts_[injectorI]; } diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/KinematicLookupTableInjection/KinematicLookupTableInjection.H b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/KinematicLookupTableInjection/KinematicLookupTableInjection.H index d888c47582e..1692c92a0f0 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/KinematicLookupTableInjection/KinematicLookupTableInjection.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/KinematicLookupTableInjection/KinematicLookupTableInjection.H @@ -81,8 +81,14 @@ class KinematicLookupTableInjection //- List of injectors kinematicParcelInjectionDataIOList injectors_; - //- List of injector cells per injector - List<label> injectorCells_; + //- List of cell labels corresponding to injector positions + labelList injectorCells_; + + //- List of tetFace labels corresponding to injector positions + labelList injectorTetFaces_; + + //- List of tetPt labels corresponding to injector positions + labelList injectorTetPts_; protected: @@ -135,14 +141,16 @@ public: // Injection geometry - //- Set the injection position and owner cell + //- Set the injection position and owner cell, tetFace and tetPt virtual void setPositionAndCell ( const label parcelI, const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ); //- Set the parcel properties diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ManualInjection/ManualInjection.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ManualInjection/ManualInjection.C index f64cdc22681..b7e3c702274 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ManualInjection/ManualInjection.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ManualInjection/ManualInjection.C @@ -92,6 +92,9 @@ Foam::ManualInjection<CloudType>::ManualInjection ) ), diameters_(positions_.size()), + injectorCells_(positions_.size(), -1), + injectorTetFaces_(positions_.size(), -1), + injectorTetPts_(positions_.size(), -1), U0_(this->coeffDict().lookup("U0")), parcelPDF_ ( @@ -102,38 +105,45 @@ Foam::ManualInjection<CloudType>::ManualInjection ) ) { - Switch checkAndIgnoreOutOfBounds + Switch ignoreOutOfBounds ( - this->coeffDict().lookupOrDefault("checkAndIgnoreOutOfBounds", false) + this->coeffDict().lookupOrDefault("ignoreOutOfBounds", false) ); label nRejected = 0; - if (checkAndIgnoreOutOfBounds) - { - // Dummy cell - label cellI = -1; - - PackedBoolList keep(positions_.size(), true); + PackedBoolList keep(positions_.size(), true); - forAll(positions_, pI) + forAll(positions_, pI) + { + if + ( + !this->findCellAtPosition + ( + injectorCells_[pI], + injectorTetFaces_[pI], + injectorTetPts_[pI], + positions_[pI], + !ignoreOutOfBounds + ) + ) { - if (!this->findCellAtPosition(cellI, positions_[pI], false)) - { - keep[pI] = false; + keep[pI] = false; - nRejected++; - } + nRejected++; } + } - if (nRejected > 0) - { - inplaceSubset(keep, positions_); - inplaceSubset(keep, diameters_); - - Info<< " " << nRejected - << " particles ignored, out of bounds." << endl; - } + if (nRejected > 0) + { + inplaceSubset(keep, positions_); + inplaceSubset(keep, diameters_); + inplaceSubset(keep, injectorCells_); + inplaceSubset(keep, injectorTetFaces_); + inplaceSubset(keep, injectorTetPts_); + + Info<< " " << nRejected + << " particles ignored, out of bounds." << endl; } // Construct parcel diameters @@ -178,11 +188,15 @@ void Foam::ManualInjection<CloudType>::setPositionAndCell const label, const scalar, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ) { position = positions_[parcelI]; - this->findCellAtPosition(cellOwner, position); + cellOwner = injectorCells_[parcelI]; + tetFaceI = injectorTetFaces_[parcelI]; + tetPtI = injectorTetPts_[parcelI]; } diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ManualInjection/ManualInjection.H b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ManualInjection/ManualInjection.H index 0202c9eb60b..a001f940534 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ManualInjection/ManualInjection.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ManualInjection/ManualInjection.H @@ -70,7 +70,16 @@ class ManualInjection //- Field of parcel diameters scalarList diameters_; - //- Initial parcel velocity + //- List of cell labels corresponding to injector positions + labelList injectorCells_; + + //- List of tetFace labels corresponding to injector positions + labelList injectorTetFaces_; + + //- List of tetPt labels corresponding to injector positions + labelList injectorTetPts_; + + //- Initial parcel velocity const vector U0_; //- Parcel size PDF model @@ -127,14 +136,16 @@ public: // Injection geometry - //- Set the injection position and owner cell + //- Set the injection position and owner cell, tetFace and tetPt virtual void setPositionAndCell ( const label parcelI, const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ); //- Set the parcel properties diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/NoInjection/NoInjection.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/NoInjection/NoInjection.C index 15452159300..6303a8f30fa 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/NoInjection/NoInjection.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/NoInjection/NoInjection.C @@ -93,6 +93,8 @@ void Foam::NoInjection<CloudType>::setPositionAndCell const label, const scalar, vector&, + label&, + label&, label& ) {} diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/NoInjection/NoInjection.H b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/NoInjection/NoInjection.H index 6dea7c9dd15..d5026cc75d4 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/NoInjection/NoInjection.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/NoInjection/NoInjection.H @@ -101,14 +101,16 @@ public: // Injection geometry - //- Set the injection position and owner cell + //- Set the injection position and owner cell, tetFace and tetPt virtual void setPositionAndCell ( const label parcelI, const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ); virtual void setProperties diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/PatchInjection/PatchInjection.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/PatchInjection/PatchInjection.C index b3ed38cf884..8c50cec0e09 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/PatchInjection/PatchInjection.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/PatchInjection/PatchInjection.C @@ -98,7 +98,7 @@ Foam::PatchInjection<CloudType>::PatchInjection owner.rndGen() ) ), - cellOwners_(), + injectorCells_(), fraction_(1.0) { const label patchId = owner.mesh().boundaryMesh().findPatchID(patchName_); @@ -119,9 +119,9 @@ Foam::PatchInjection<CloudType>::PatchInjection const polyPatch& patch = owner.mesh().boundaryMesh()[patchId]; - cellOwners_ = patch.faceCells(); + injectorCells_ = patch.faceCells(); - label patchSize = cellOwners_.size(); + label patchSize = injectorCells_.size(); label totalPatchSize = patchSize; reduce(totalPatchSize, sumOp<label>()); fraction_ = scalar(patchSize)/totalPatchSize; @@ -162,19 +162,37 @@ void Foam::PatchInjection<CloudType>::setPositionAndCell const label, const scalar, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ) { - if (cellOwners_.size() > 0) + if (injectorCells_.size() > 0) { - label cellI = this->owner().rndGen().integer(0, cellOwners_.size() - 1); + label cellI = this->owner().rndGen().integer + ( + 0, + injectorCells_.size() - 1 + ); + + cellOwner = injectorCells_[cellI]; + + // The position is at the cell centre, which could be in any + // tet of the decomposed cell, so arbitrarily choose the first + // face of the cell as the tetFace and the first point after + // the base point on the face as the tetPt. The tracking will + // pick the cell consistent with the motion in the first + // tracking step. + tetFaceI = this->owner().mesh().cells()[cellOwner][0]; + tetPtI = 1; - cellOwner = cellOwners_[cellI]; position = this->owner().mesh().C()[cellOwner]; } else { cellOwner = -1; + tetFaceI = -1; + tetPtI = -1; // dummy position position = pTraits<vector>::max; } diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/PatchInjection/PatchInjection.H b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/PatchInjection/PatchInjection.H index f8d5840ffe0..ee6a5edeb0a 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/PatchInjection/PatchInjection.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/PatchInjection/PatchInjection.H @@ -85,8 +85,8 @@ class PatchInjection //- Parcel size PDF model const autoPtr<pdfs::pdf> parcelPDF_; - //- Cell owners - labelList cellOwners_; + //- List of cell labels corresponding to injector positions + labelList injectorCells_; //- Fraction of injection controlled by this processor scalar fraction_; @@ -142,14 +142,16 @@ public: // Injection geometry - //- Set the injection position and owner cell + //- Set the injection position and owner cell, tetFace and tetPt virtual void setPositionAndCell ( const label parcelI, const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ); virtual void setProperties diff --git a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/LocalInteraction/LocalInteraction.C b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/LocalInteraction/LocalInteraction.C index b9fd7b819e5..0786df08a75 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/LocalInteraction/LocalInteraction.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/LocalInteraction/LocalInteraction.C @@ -55,16 +55,16 @@ Foam::LocalInteraction<CloudType>::LocalInteraction ) : PatchInteractionModel<CloudType>(dict, cloud, typeName), - patchData_(this->coeffDict().lookup("patches")), - patchIds_(patchData_.size()) + patchProperties_(this->coeffDict().lookup("patches")), + patchIds_(patchProperties_.size()) { const polyMesh& mesh = cloud.mesh(); const polyBoundaryMesh& bMesh = mesh.boundaryMesh(); // check that user patches are valid region patches - forAll(patchData_, patchI) + forAll(patchProperties_, patchI) { - const word& patchName = patchData_[patchI].patchName(); + const word& patchName = patchProperties_[patchI].patchName(); patchIds_[patchI] = bMesh.findPatchID(patchName); if (patchIds_[patchI] < 0) { @@ -97,16 +97,16 @@ Foam::LocalInteraction<CloudType>::LocalInteraction } // check that interactions are valid/specified - forAll(patchData_, patchI) + forAll(patchProperties_, patchI) { const word& interactionTypeName = - patchData_[patchI].interactionTypeName(); + patchProperties_[patchI].interactionTypeName(); const typename PatchInteractionModel<CloudType>::interactionType& it = this->wordToInteractionType(interactionTypeName); if (it == PatchInteractionModel<CloudType>::itOther) { - const word& patchName = patchData_[patchI].patchName(); + const word& patchName = patchProperties_[patchI].patchName(); FatalErrorIn("LocalInteraction(const dictionary&, CloudType&)") << "Unknown patch interaction type " << interactionTypeName << " for patch " << patchName @@ -137,13 +137,17 @@ bool Foam::LocalInteraction<CloudType>::active() const template <class CloudType> bool Foam::LocalInteraction<CloudType>::correct ( + typename CloudType::parcelType& p, const polyPatch& pp, - const label faceId, bool& keepParticle, - bool& active, - vector& U + const scalar trackFraction, + const tetIndices& tetIs ) const { + vector& U = p.U(); + + bool& active = p.active(); + label patchI = applyToPatch(pp.index()); if (patchI >= 0) @@ -151,7 +155,7 @@ bool Foam::LocalInteraction<CloudType>::correct typename PatchInteractionModel<CloudType>::interactionType it = this->wordToInteractionType ( - patchData_[patchI].interactionTypeName() + patchProperties_[patchI].interactionTypeName() ); switch (it) @@ -175,18 +179,26 @@ bool Foam::LocalInteraction<CloudType>::correct keepParticle = true; active = true; - vector nw = pp.faceAreas()[pp.whichFace(faceId)]; - nw /= mag(nw); + vector nw; + vector Up; + + this->patchData(p, pp, trackFraction, tetIs, nw, Up); + + // Calculate motion relative to patch velocity + U -= Up; scalar Un = U & nw; vector Ut = U - Un*nw; if (Un > 0) { - U -= (1.0 + patchData_[patchI].e())*Un*nw; + U -= (1.0 + patchProperties_[patchI].e())*Un*nw; } - U -= patchData_[patchI].mu()*Ut; + U -= patchProperties_[patchI].mu()*Ut; + + // Return velocity to global space + U += Up; break; } @@ -202,9 +214,9 @@ bool Foam::LocalInteraction<CloudType>::correct "vector&" ") const" ) << "Unknown interaction type " - << patchData_[patchI].interactionTypeName() + << patchProperties_[patchI].interactionTypeName() << "(" << it << ") for patch " - << patchData_[patchI].patchName() + << patchProperties_[patchI].patchName() << ". Valid selections are:" << this->interactionTypeNames_ << endl << abort(FatalError); } diff --git a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/LocalInteraction/LocalInteraction.H b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/LocalInteraction/LocalInteraction.H index 4fa89004230..7b5446209ac 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/LocalInteraction/LocalInteraction.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/LocalInteraction/LocalInteraction.H @@ -51,7 +51,7 @@ class LocalInteraction // Private data //- List of participating patches - const List<patchInteractionData> patchData_; + const List<patchInteractionData> patchProperties_; //- List of participating patch ids List<label> patchIds_; @@ -89,11 +89,11 @@ public: // Returns true if particle remains in same cell virtual bool correct ( + typename CloudType::parcelType& p, const polyPatch& pp, - const label faceId, bool& keepParticle, - bool& active, - vector& U + const scalar trackFraction, + const tetIndices& tetIs ) const; }; diff --git a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/PatchInteractionModel/PatchInteractionModel.C b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/PatchInteractionModel/PatchInteractionModel.C index 6947fc93bf6..0eca6dea665 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/PatchInteractionModel/PatchInteractionModel.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/PatchInteractionModel/PatchInteractionModel.C @@ -24,6 +24,9 @@ License \*---------------------------------------------------------------------------*/ #include "PatchInteractionModel.H" +#include "fvMesh.H" +#include "Time.H" +#include "volFields.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -111,7 +114,8 @@ Foam::PatchInteractionModel<CloudType>::PatchInteractionModel : dict_(dict), owner_(owner), - coeffDict_(dict.subDict(type + "Coeffs")) + coeffDict_(dict.subDict(type + "Coeffs")), + UName_(coeffDict_.lookupOrDefault<word>("UName", "U")) {} @@ -147,9 +151,166 @@ Foam::PatchInteractionModel<CloudType>::coeffDict() const } +template<class CloudType> +const Foam::word& Foam::PatchInteractionModel<CloudType>::UName() const +{ + return UName_; +} + + +template<class CloudType> +void Foam::PatchInteractionModel<CloudType>::patchData +( + typename CloudType::parcelType& p, + const polyPatch& pp, + const scalar trackFraction, + const tetIndices& tetIs, + vector& nw, + vector& Up +) const +{ + const fvMesh& mesh = this->owner().mesh(); + + const volVectorField& Ufield = + mesh.objectRegistry::lookupObject<volVectorField>(UName_); + + label patchI = pp.index(); + label patchFaceI = pp.whichFace(p.face()); + + vector n = tetIs.faceTri(mesh).normal(); + n /= mag(n); + + vector U = Ufield.boundaryField()[patchI][patchFaceI]; + + // Unless the face is rotating, the required normal is n; + nw = n; + + if (!mesh.moving()) + { + // Only wall patches may have a non-zero wall velocity from + // the velocity field when the mesh is not moving. + + if (isA<wallPolyPatch>(pp)) + { + Up = U; + } + else + { + Up = vector::zero; + } + } + else + { + vector U00 = Ufield.oldTime().boundaryField()[patchI][patchFaceI]; + + vector n00 = tetIs.oldFaceTri(mesh).normal(); + + // Difference in normal over timestep + vector dn = vector::zero; + + if (mag(n00) > SMALL) + { + // If the old normal is zero (for example in layer + // addition) then use the current normal, meaning that the + // motion can only be translational, and dn remains zero, + // otherwise, calculate dn: + + n00 /= mag(n00); + + dn = n - n00; + } + + // Total fraction thought the timestep of the motion, + // including stepFraction before the current tracking step + // and the current trackFraction + // i.e. + // let s = stepFraction, t = trackFraction + // Motion of x in time: + // |-----------------|---------|---------| + // x00 x0 xi x + // + // where xi is the correct value of x at the required + // tracking instant. + // + // x0 = x00 + s*(x - x00) = s*x + (1 - s)*x00 + // + // i.e. the motion covered by previous tracking portions + // within this timestep, and + // + // xi = x0 + t*(x - x0) + // = t*x + (1 - t)*x0 + // = t*x + (1 - t)*(s*x + (1 - s)*x00) + // = (s + t - s*t)*x + (1 - (s + t - s*t))*x00 + // + // let m = (s + t - s*t) + // + // xi = m*x + (1 - m)*x00 = x00 + m*(x - x00); + // + // In the same form as before. + + scalar m = + p.stepFraction() + + trackFraction + - (p.stepFraction()*trackFraction); + + // When the mesh is moving, the velocity field on wall patches + // will contain the velocity associated with the motion of the + // mesh, in which case it is interpolated in time using m. + // For other patches the face velocity will need to be + // reconstructed from the face centre motion. + + const vector& Cf = mesh.faceCentres()[p.face()]; + + vector Cf00 = mesh.faces()[p.face()].centre(mesh.oldPoints()); + + if (isA<wallPolyPatch>(pp)) + { + Up = U00 + m*(U - U00); + } + else + { + Up = (Cf - Cf00)/mesh.time().deltaTValue(); + } + + if (mag(dn) > SMALL) + { + // Rotational motion, nw requires interpolation and a + // rotational velocity around face centre correction to Up + // is required. + + nw = n00 + m*dn; + + // Cf at tracking instant + vector Cfi = Cf00 + m*(Cf - Cf00); + + // Normal vector cross product + vector omega = (n00 ^ n); + + scalar magOmega = mag(omega); + + // magOmega = sin(angle between unit normals) + // Normalise omega vector by magOmega, then multiply by + // angle/dt to give the correct angular velocity vector. + omega *= Foam::asin(magOmega)/(magOmega*mesh.time().deltaTValue()); + + // Project position onto face and calculate this position + // relative to the face centre. + vector facePos = + p.position() + - ((p.position() - Cfi) & nw)*nw + - Cfi; + + Up += (omega ^ facePos); + } + + // No further action is required if the motion is + // translational only, nw and Up have already been set. + } +} + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #include "PatchInteractionModelNew.C" // ************************************************************************* // - diff --git a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/PatchInteractionModel/PatchInteractionModel.H b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/PatchInteractionModel/PatchInteractionModel.H index 1bd16847733..c3c883eaeb8 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/PatchInteractionModel/PatchInteractionModel.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/PatchInteractionModel/PatchInteractionModel.H @@ -40,6 +40,8 @@ SourceFiles #include "autoPtr.H" #include "runTimeSelectionTables.H" #include "polyPatch.H" +#include "wallPolyPatch.H" +#include "tetIndices.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -82,6 +84,9 @@ private: //- The coefficients dictionary const dictionary coeffDict_; + //- Name of velocity field - default = "U" + const word UName_; + public: @@ -136,6 +141,9 @@ public: //- Return the coefficients dictionary const dictionary& coeffDict() const; + //- Return name of velocity field + const word& UName() const; + // Member Functions @@ -152,12 +160,24 @@ public: // Returns true if particle remains in same cell virtual bool correct ( + typename CloudType::parcelType& p, const polyPatch& pp, - const label faceId, bool& keepParticle, - bool& active, - vector& U + const scalar trackFraction, + const tetIndices& tetIs ) const = 0; + + //- Calculate the patch normal and velocity to interact with, + // accounting for patch motion if required. + void patchData + ( + typename CloudType::parcelType& p, + const polyPatch& pp, + const scalar trackFraction, + const tetIndices& tetIs, + vector& normal, + vector& Up + ) const; }; diff --git a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/Rebound/Rebound.C b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/Rebound/Rebound.C index 71207833079..69b3749429c 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/Rebound/Rebound.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/Rebound/Rebound.C @@ -58,18 +58,25 @@ bool Foam::Rebound<CloudType>::active() const template<class CloudType> bool Foam::Rebound<CloudType>::correct ( + typename CloudType::parcelType& p, const polyPatch& pp, - const label faceId, bool& keepParticle, - bool& active, - vector& U + const scalar trackFraction, + const tetIndices& tetIs ) const { + vector& U = p.U(); + keepParticle = true; - active = true; + p.active() = true; + + vector nw; + vector Up; - vector nw = pp.faceAreas()[pp.whichFace(faceId)]; - nw /= mag(nw); + this->patchData(p, pp, trackFraction, tetIs, nw, Up); + + // Calculate motion relative to patch velocity + U -= Up; scalar Un = U & nw; @@ -78,6 +85,9 @@ bool Foam::Rebound<CloudType>::correct U -= UFactor_*2.0*Un*nw; } + // Return velocity to global space + U += Up; + return true; } diff --git a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/Rebound/Rebound.H b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/Rebound/Rebound.H index e9cc326c302..c1ca658470a 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/Rebound/Rebound.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/Rebound/Rebound.H @@ -79,11 +79,11 @@ public: // Returns true if particle remains in same cell virtual bool correct ( + typename CloudType::parcelType& p, const polyPatch& pp, - const label faceId, bool& keepParticle, - bool& active, - vector& U + const scalar trackFraction, + const tetIndices& tetIs ) const; }; diff --git a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/StandardWallInteraction/StandardWallInteraction.C b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/StandardWallInteraction/StandardWallInteraction.C index 7d89c40df67..7d2b11cdca4 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/StandardWallInteraction/StandardWallInteraction.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/StandardWallInteraction/StandardWallInteraction.C @@ -95,13 +95,17 @@ bool Foam::StandardWallInteraction<CloudType>::active() const template <class CloudType> bool Foam::StandardWallInteraction<CloudType>::correct ( + typename CloudType::parcelType& p, const polyPatch& pp, - const label faceId, bool& keepParticle, - bool& active, - vector& U + const scalar trackFraction, + const tetIndices& tetIs ) const { + vector& U = p.U(); + + bool& active = p.active(); + if (isA<wallPolyPatch>(pp)) { switch (interactionType_) @@ -125,8 +129,13 @@ bool Foam::StandardWallInteraction<CloudType>::correct keepParticle = true; active = true; - vector nw = pp.faceAreas()[pp.whichFace(faceId)]; - nw /= mag(nw); + vector nw; + vector Up; + + this->patchData(p, pp, trackFraction, tetIs, nw, Up); + + // Calculate motion relative to patch velocity + U -= Up; scalar Un = U & nw; vector Ut = U - Un*nw; @@ -138,6 +147,9 @@ bool Foam::StandardWallInteraction<CloudType>::correct U -= mu_*Ut; + // Return velocity to global space + U += Up; + break; } default: diff --git a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/StandardWallInteraction/StandardWallInteraction.H b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/StandardWallInteraction/StandardWallInteraction.H index 476bd7d63a2..bae46785ea2 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/StandardWallInteraction/StandardWallInteraction.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/StandardWallInteraction/StandardWallInteraction.H @@ -99,11 +99,11 @@ public: // Returns true if particle remains in same cell virtual bool correct ( + typename CloudType::parcelType& p, const polyPatch& pp, - const label faceId, bool& keepParticle, - bool& active, - vector& U + const scalar trackFraction, + const tetIndices& tetIs ) const; }; diff --git a/src/lagrangian/intermediate/submodels/Kinematic/SurfaceFilmModel/SurfaceFilmModel/SurfaceFilmModel.C b/src/lagrangian/intermediate/submodels/Kinematic/SurfaceFilmModel/SurfaceFilmModel/SurfaceFilmModel.C index 5ef3c76eb34..41d31901cad 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/SurfaceFilmModel/SurfaceFilmModel/SurfaceFilmModel.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/SurfaceFilmModel/SurfaceFilmModel/SurfaceFilmModel.C @@ -121,11 +121,30 @@ void Foam::SurfaceFilmModel<CloudType>::inject(TrackData& td) if (diameterParcelPatch_[j] > 0) { const label cellI = injectorCellsPatch[j]; + + // The position is at the cell centre, which could be + // in any tet of the decomposed cell, so arbitrarily + // choose the first face of the cell as the tetFace + // and the first point on the face after the base + // point as the tetPt. The tracking will + // pick the cell consistent with the motion in the + // first tracking step. + const label tetFaceI = this->owner().mesh().cells()[cellI][0]; + const label tetPtI = 1; + const point& pos = this->owner().mesh().C()[cellI]; // Create a new parcel typename CloudType::parcelType* pPtr = - new typename CloudType::parcelType(td.cloud(), pos, cellI); + new typename CloudType::parcelType + ( + td.cloud(), + pos, + cellI, + tetFaceI, + tetPtI + ); + setParcelProperties(*pPtr, j); // Check new parcel properties diff --git a/src/lagrangian/intermediate/submodels/Reacting/InjectionModel/ReactingLookupTableInjection/ReactingLookupTableInjection.C b/src/lagrangian/intermediate/submodels/Reacting/InjectionModel/ReactingLookupTableInjection/ReactingLookupTableInjection.C index 00b6667f9d5..8ba48ca48d0 100644 --- a/src/lagrangian/intermediate/submodels/Reacting/InjectionModel/ReactingLookupTableInjection/ReactingLookupTableInjection.C +++ b/src/lagrangian/intermediate/submodels/Reacting/InjectionModel/ReactingLookupTableInjection/ReactingLookupTableInjection.C @@ -92,13 +92,24 @@ Foam::ReactingLookupTableInjection<CloudType>::ReactingLookupTableInjection IOobject::NO_WRITE ) ), - injectorCells_(0) + injectorCells_(0), + injectorTetFaces_(0), + injectorTetPts_(0) { // Set/cache the injector cells injectorCells_.setSize(injectors_.size()); + injectorTetFaces_.setSize(injectors_.size()); + injectorTetPts_.setSize(injectors_.size()); + forAll(injectors_, i) { - this->findCellAtPosition(injectorCells_[i], injectors_[i].x()); + this->findCellAtPosition + ( + injectorCells_[i], + injectorTetFaces_[i], + injectorTetPts_[i], + injectors_[i].x() + ); } // Determine volume of particles to inject @@ -141,13 +152,17 @@ void Foam::ReactingLookupTableInjection<CloudType>::setPositionAndCell const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ) { label injectorI = parcelI*injectorCells_.size()/nParcels; position = injectors_[injectorI].x(); cellOwner = injectorCells_[injectorI]; + tetFaceI = injectorTetFaces_[injectorI]; + tetPtI = injectorTetPts_[injectorI]; } diff --git a/src/lagrangian/intermediate/submodels/Reacting/InjectionModel/ReactingLookupTableInjection/ReactingLookupTableInjection.H b/src/lagrangian/intermediate/submodels/Reacting/InjectionModel/ReactingLookupTableInjection/ReactingLookupTableInjection.H index 52cf535665e..88bb33005f2 100644 --- a/src/lagrangian/intermediate/submodels/Reacting/InjectionModel/ReactingLookupTableInjection/ReactingLookupTableInjection.H +++ b/src/lagrangian/intermediate/submodels/Reacting/InjectionModel/ReactingLookupTableInjection/ReactingLookupTableInjection.H @@ -84,8 +84,14 @@ class ReactingLookupTableInjection //- List of injectors reactingParcelInjectionDataIOList injectors_; - //- List of injector cells per injector - List<label> injectorCells_; + //- List of cell labels corresoponding to injector positions + labelList injectorCells_; + + //- List of tetFace labels corresoponding to injector positions + labelList injectorTetFaces_; + + //- List of tetPt labels corresoponding to injector positions + labelList injectorTetPts_; protected: @@ -138,14 +144,16 @@ public: // Injection geometry - //- Set the injection position and owner cell + //- Set the injection position and owner cell, tetFace and tetPt virtual void setPositionAndCell ( const label parcelI, const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ); //- Set the parcel properties diff --git a/src/lagrangian/intermediate/submodels/ReactingMultiphase/InjectionModel/ReactingMultiphaseLookupTableInjection/ReactingMultiphaseLookupTableInjection.C b/src/lagrangian/intermediate/submodels/ReactingMultiphase/InjectionModel/ReactingMultiphaseLookupTableInjection/ReactingMultiphaseLookupTableInjection.C index 4d68b40b09d..a97ab2d4d89 100644 --- a/src/lagrangian/intermediate/submodels/ReactingMultiphase/InjectionModel/ReactingMultiphaseLookupTableInjection/ReactingMultiphaseLookupTableInjection.C +++ b/src/lagrangian/intermediate/submodels/ReactingMultiphase/InjectionModel/ReactingMultiphaseLookupTableInjection/ReactingMultiphaseLookupTableInjection.C @@ -95,13 +95,24 @@ ReactingMultiphaseLookupTableInjection IOobject::NO_WRITE ) ), - injectorCells_(0) + injectorCells_(0), + injectorTetFaces_(0), + injectorTetPts_(0) { // Set/cache the injector cells injectorCells_.setSize(injectors_.size()); + injectorTetFaces_.setSize(injectors_.size()); + injectorTetPts_.setSize(injectors_.size()); + forAll(injectors_, i) { - this->findCellAtPosition(injectorCells_[i], injectors_[i].x()); + this->findCellAtPosition + ( + injectorCells_[i], + injectorTetFaces_[i], + injectorTetPts_[i], + injectors_[i].x() + ); } // Determine volume of particles to inject @@ -146,13 +157,17 @@ void Foam::ReactingMultiphaseLookupTableInjection<CloudType>::setPositionAndCell const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ) { label injectorI = parcelI*injectorCells_.size()/nParcels; position = injectors_[injectorI].x(); cellOwner = injectorCells_[injectorI]; + tetFaceI = injectorTetFaces_[injectorI]; + tetPtI = injectorTetPts_[injectorI]; } diff --git a/src/lagrangian/intermediate/submodels/ReactingMultiphase/InjectionModel/ReactingMultiphaseLookupTableInjection/ReactingMultiphaseLookupTableInjection.H b/src/lagrangian/intermediate/submodels/ReactingMultiphase/InjectionModel/ReactingMultiphaseLookupTableInjection/ReactingMultiphaseLookupTableInjection.H index 2307ca20050..289f664550e 100644 --- a/src/lagrangian/intermediate/submodels/ReactingMultiphase/InjectionModel/ReactingMultiphaseLookupTableInjection/ReactingMultiphaseLookupTableInjection.H +++ b/src/lagrangian/intermediate/submodels/ReactingMultiphase/InjectionModel/ReactingMultiphaseLookupTableInjection/ReactingMultiphaseLookupTableInjection.H @@ -87,8 +87,14 @@ class ReactingMultiphaseLookupTableInjection //- List of injectors reactingMultiphaseParcelInjectionDataIOList injectors_; - //- List of injector cells per injector - List<label> injectorCells_; + //- List of cell labels corresoponding to injector positions + labelList injectorCells_; + + //- List of tetFace labels corresoponding to injector positions + labelList injectorTetFaces_; + + //- List of tetPt labels corresoponding to injector positions + labelList injectorTetPts_; protected: @@ -141,14 +147,16 @@ public: // Injection geometry - //- Set the injection position and owner cell + //- Set the injection position and owner cell, tetFace and tetPt virtual void setPositionAndCell ( const label parcelI, const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ); //- Set the parcel properties diff --git a/src/lagrangian/intermediate/submodels/Thermodynamic/InjectionModel/ThermoLookupTableInjection/ThermoLookupTableInjection.C b/src/lagrangian/intermediate/submodels/Thermodynamic/InjectionModel/ThermoLookupTableInjection/ThermoLookupTableInjection.C index 88c13c4f8f7..6138a8a5f54 100644 --- a/src/lagrangian/intermediate/submodels/Thermodynamic/InjectionModel/ThermoLookupTableInjection/ThermoLookupTableInjection.C +++ b/src/lagrangian/intermediate/submodels/Thermodynamic/InjectionModel/ThermoLookupTableInjection/ThermoLookupTableInjection.C @@ -93,13 +93,24 @@ Foam::ThermoLookupTableInjection<CloudType>::ThermoLookupTableInjection IOobject::NO_WRITE ) ), - injectorCells_(0) + injectorCells_(0), + injectorTetFaces_(0), + injectorTetPts_(0) { // Set/cache the injector cells injectorCells_.setSize(injectors_.size()); + injectorTetFaces_.setSize(injectors_.size()); + injectorTetPts_.setSize(injectors_.size()); + forAll(injectors_, i) { - this->findCellAtPosition(injectorCells_[injectorI], injectors_[i].x()); + this->findCellAtPosition + ( + injectorCells_[i], + injectorTetFaces_[i], + injectorTetPts_[i], + injectors_[i].x() + ); } // Determine volume of particles to inject @@ -142,13 +153,17 @@ void Foam::ThermoLookupTableInjection<CloudType>::setPositionAndCell const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ) { label injectorI = parcelI*injectorCells_.size()/nParcels; position = injectors_[injectorI].x(); cellOwner = injectorCells_[injectorI]; + tetFaceI = injectorTetFaces_[injectorI]; + tetPtI = injectorTetPts_[injectorI]; } diff --git a/src/lagrangian/intermediate/submodels/Thermodynamic/InjectionModel/ThermoLookupTableInjection/ThermoLookupTableInjection.H b/src/lagrangian/intermediate/submodels/Thermodynamic/InjectionModel/ThermoLookupTableInjection/ThermoLookupTableInjection.H index fa009ff00e4..c66f0778f64 100644 --- a/src/lagrangian/intermediate/submodels/Thermodynamic/InjectionModel/ThermoLookupTableInjection/ThermoLookupTableInjection.H +++ b/src/lagrangian/intermediate/submodels/Thermodynamic/InjectionModel/ThermoLookupTableInjection/ThermoLookupTableInjection.H @@ -83,8 +83,14 @@ class ThermoLookupTableInjection //- List of injectors kinematicParcelInjectionDataIOList injectors_; - //- List of injector cells per injector - List<label> injectorCells_; + //- List of cell labels corresoponding to injector positions + labelList injectorCells_; + + //- List of tetFace labels corresoponding to injector positions + labelList injectorTetFaces_; + + //- List of tetPt labels corresoponding to injector positions + labelList injectorTetPts_; protected: @@ -137,14 +143,16 @@ public: // Injection geometry - //- Set the injection position and owner cell + //- Set the injection position and owner cell, tetFace and tetPt virtual void setPositionAndCell ( const label parcelI, const label nParcels, const scalar time, vector& position, - label& cellOwner + label& cellOwner, + label& tetFaceI, + label& tetPtI ); //- Set the parcel properties diff --git a/src/lagrangian/molecularDynamics/molecule/molecule/molecule.C b/src/lagrangian/molecularDynamics/molecule/molecule/molecule.C index 2af297c6ac4..ef3b1395cc8 100644 --- a/src/lagrangian/molecularDynamics/molecule/molecule/molecule.C +++ b/src/lagrangian/molecularDynamics/molecule/molecule/molecule.C @@ -260,7 +260,9 @@ bool Foam::molecule::hitPatch ( const polyPatch&, molecule::trackData&, - const label + const label, + const scalar, + const tetIndices& ) { return false; @@ -271,7 +273,9 @@ bool Foam::molecule::hitPatch ( const polyPatch&, int&, - const label + const label, + const scalar, + const tetIndices& ) { return false; @@ -299,10 +303,13 @@ void Foam::molecule::hitProcessorPatch void Foam::molecule::hitWallPatch ( const wallPolyPatch& wpp, - molecule::trackData& td + molecule::trackData& td, + const tetIndices& tetIs ) { - vector nw = wpp.faceAreas()[wpp.whichFace(face())]; + // Use of the normal from tetIs is not required as + // hasWallImpactDistance for a moleculeCloud is false. + vector nw = normal(); nw /= mag(nw); scalar vn = v_ & nw; @@ -318,7 +325,8 @@ void Foam::molecule::hitWallPatch void Foam::molecule::hitWallPatch ( const wallPolyPatch&, - int& + int&, + const tetIndices& ) {} diff --git a/src/lagrangian/molecularDynamics/molecule/molecule/molecule.H b/src/lagrangian/molecularDynamics/molecule/molecule/molecule.H index 448cb0955be..8df55ca8faf 100644 --- a/src/lagrangian/molecularDynamics/molecule/molecule/molecule.H +++ b/src/lagrangian/molecularDynamics/molecule/molecule/molecule.H @@ -228,7 +228,9 @@ public: ( const Cloud<molecule>& c, const vector& position, - const label celli, + const label cellI, + const label tetFaceI, + const label tetPtI, const tensor& Q, const vector& v, const vector& a, @@ -317,7 +319,9 @@ public: ( const polyPatch&, molecule::trackData& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ); //- Overridable function to handle the particle hitting a patch @@ -326,7 +330,9 @@ public: ( const polyPatch& p, int& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ); //- Overridable function to handle the particle hitting a processorPatch @@ -348,7 +354,8 @@ public: void hitWallPatch ( const wallPolyPatch&, - molecule::trackData& td + molecule::trackData& td, + const tetIndices& ); //- Overridable function to handle the particle hitting a wallPatch @@ -356,7 +363,8 @@ public: void hitWallPatch ( const wallPolyPatch&, - int& + int&, + const tetIndices& ); //- Overridable function to handle the particle hitting a polyPatch diff --git a/src/lagrangian/molecularDynamics/molecule/molecule/moleculeI.H b/src/lagrangian/molecularDynamics/molecule/molecule/moleculeI.H index b759d4731be..be0c19985e3 100644 --- a/src/lagrangian/molecularDynamics/molecule/molecule/moleculeI.H +++ b/src/lagrangian/molecularDynamics/molecule/molecule/moleculeI.H @@ -221,7 +221,9 @@ inline Foam::molecule::molecule ( const Cloud<molecule>& c, const vector& position, - const label celli, + const label cellI, + const label tetFaceI, + const label tetPtI, const tensor& Q, const vector& v, const vector& a, @@ -234,7 +236,7 @@ inline Foam::molecule::molecule ) : - Particle<molecule>(c, position, celli), + Particle<molecule>(c, position, cellI, tetFaceI, tetPtI), Q_(Q), v_(v), a_(a), diff --git a/src/lagrangian/molecularDynamics/molecule/moleculeCloud/moleculeCloud.C b/src/lagrangian/molecularDynamics/molecule/moleculeCloud/moleculeCloud.C index 5fef0b1d0d4..ef50886ebf2 100644 --- a/src/lagrangian/molecularDynamics/molecule/moleculeCloud/moleculeCloud.C +++ b/src/lagrangian/molecularDynamics/molecule/moleculeCloud/moleculeCloud.C @@ -742,7 +742,17 @@ void Foam::moleculeCloud::initialiseMolecules globalPosition ); - label cell = mesh_.findCell(globalPosition); + label cell = -1; + label tetFace = -1; + label tetPt = -1; + + findCellFacePt + ( + globalPosition, + cell, + tetFace, + tetPt + ); if (findIndex(zone, cell) != -1) { @@ -750,6 +760,8 @@ void Foam::moleculeCloud::initialiseMolecules ( globalPosition, cell, + tetFace, + tetPt, id, tethered, temperature, @@ -818,9 +830,16 @@ void Foam::moleculeCloud::initialiseMolecules globalPosition ); - label cell = mesh_.findCell + label cell = -1; + label tetFace = -1; + label tetPt = -1; + + findCellFacePt ( - globalPosition + globalPosition, + cell, + tetFace, + tetPt ); if (findIndex(zone, cell) != -1) @@ -829,6 +848,8 @@ void Foam::moleculeCloud::initialiseMolecules ( globalPosition, cell, + tetFace, + tetPt, id, tethered, temperature, @@ -888,9 +909,16 @@ void Foam::moleculeCloud::initialiseMolecules globalPosition ); - label cell = mesh_.findCell + label cell = -1; + label tetFace = -1; + label tetPt = -1; + + findCellFacePt ( - globalPosition + globalPosition, + cell, + tetFace, + tetPt ); if (findIndex(zone, cell) != -1) @@ -899,6 +927,8 @@ void Foam::moleculeCloud::initialiseMolecules ( globalPosition, cell, + tetFace, + tetPt, id, tethered, temperature, @@ -962,6 +992,8 @@ void Foam::moleculeCloud::createMolecule ( const point& position, label cell, + label tetFace, + label tetPt, label id, bool tethered, scalar temperature, @@ -972,7 +1004,7 @@ void Foam::moleculeCloud::createMolecule if (cell == -1) { - cell = mesh_.findCell(position); + findCellFacePt(position, cell, tetFace, tetPt); } if (cell == -1) @@ -1034,6 +1066,8 @@ void Foam::moleculeCloud::createMolecule cloud, position, cell, + tetFace, + tetPt, Q, v, vector::zero, diff --git a/src/lagrangian/molecularDynamics/molecule/moleculeCloud/moleculeCloud.H b/src/lagrangian/molecularDynamics/molecule/moleculeCloud/moleculeCloud.H index b92f4e5e7b5..7cf3359a351 100644 --- a/src/lagrangian/molecularDynamics/molecule/moleculeCloud/moleculeCloud.H +++ b/src/lagrangian/molecularDynamics/molecule/moleculeCloud/moleculeCloud.H @@ -114,6 +114,8 @@ private: ( const point& position, label cell, + label tetFace, + label tetPt, label id, bool tethered, scalar temperature, diff --git a/src/lagrangian/solidParticle/Make/options b/src/lagrangian/solidParticle/Make/options index 15874b7b55a..9fe79c9220b 100644 --- a/src/lagrangian/solidParticle/Make/options +++ b/src/lagrangian/solidParticle/Make/options @@ -1,7 +1,9 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude LIB_LIBS = \ -llagrangian \ + -lmeshTools \ -lfiniteVolume diff --git a/src/lagrangian/solidParticle/solidParticle.C b/src/lagrangian/solidParticle/solidParticle.C index 37c8b4478c0..e802e67d06a 100644 --- a/src/lagrangian/solidParticle/solidParticle.C +++ b/src/lagrangian/solidParticle/solidParticle.C @@ -54,14 +54,14 @@ bool Foam::solidParticle::move(solidParticle::trackData& td) // remember which cell the parcel is in // since this will change if a face is hit - label celli = cell(); + label cellI = cell(); dt *= trackToFace(position() + dt*U_, td); tEnd -= dt; stepFraction() = 1.0 - tEnd/deltaT; - cellPointWeight cpw(mesh, position(), celli, face()); + cellPointWeight cpw(mesh, position(), cellI, face()); scalar rhoc = td.rhoInterp().interpolate(cpw); vector Uc = td.UInterp().interpolate(cpw); scalar nuc = td.nuInterp().interpolate(cpw); @@ -98,7 +98,9 @@ bool Foam::solidParticle::hitPatch ( const polyPatch&, solidParticle::trackData&, - const label + const label, + const scalar, + const tetIndices& ) { return false; @@ -109,7 +111,9 @@ bool Foam::solidParticle::hitPatch ( const polyPatch&, int&, - const label + const label, + const scalar, + const tetIndices& ) { return false; @@ -137,10 +141,11 @@ void Foam::solidParticle::hitProcessorPatch void Foam::solidParticle::hitWallPatch ( const wallPolyPatch& wpp, - solidParticle::trackData& td + solidParticle::trackData& td, + const tetIndices& tetIs ) { - vector nw = wpp.faceAreas()[wpp.whichFace(face())]; + vector nw = tetIs.faceTri(cloud().pMesh()).normal(); nw /= mag(nw); scalar Un = U_ & nw; @@ -158,7 +163,8 @@ void Foam::solidParticle::hitWallPatch void Foam::solidParticle::hitWallPatch ( const wallPolyPatch&, - int& + int&, + const tetIndices& ) {} diff --git a/src/lagrangian/solidParticle/solidParticle.H b/src/lagrangian/solidParticle/solidParticle.H index 842b0045325..04ff8e9e510 100644 --- a/src/lagrangian/solidParticle/solidParticle.H +++ b/src/lagrangian/solidParticle/solidParticle.H @@ -127,8 +127,10 @@ public: ( const Cloud<solidParticle>& c, const vector& position, - const label celli, - const scalar m, + const label cellI, + const label tetFaceI, + const label tetPtI, + const scalar d, const vector& U ); @@ -176,7 +178,9 @@ public: ( const polyPatch&, solidParticle::trackData& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ); //- Overridable function to handle the particle hitting a patch @@ -185,7 +189,9 @@ public: ( const polyPatch& p, int& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ); //- Overridable function to handle the particle hitting a @@ -208,7 +214,8 @@ public: void hitWallPatch ( const wallPolyPatch&, - solidParticle::trackData& td + solidParticle::trackData& td, + const tetIndices& ); //- Overridable function to handle the particle hitting a wallPatch @@ -216,7 +223,8 @@ public: void hitWallPatch ( const wallPolyPatch&, - int& + int&, + const tetIndices& ); //- Overridable function to handle the particle hitting a polyPatch diff --git a/src/lagrangian/solidParticle/solidParticleCloud.H b/src/lagrangian/solidParticle/solidParticleCloud.H index b4e87423b33..7a1761593b2 100644 --- a/src/lagrangian/solidParticle/solidParticleCloud.H +++ b/src/lagrangian/solidParticle/solidParticleCloud.H @@ -94,6 +94,8 @@ public: // Access + inline bool hasWallImpactDistance() const; + inline const fvMesh& mesh() const; inline scalar rhop() const; diff --git a/src/lagrangian/solidParticle/solidParticleCloudI.H b/src/lagrangian/solidParticle/solidParticleCloudI.H index db8b817901a..3b830c0887c 100644 --- a/src/lagrangian/solidParticle/solidParticleCloudI.H +++ b/src/lagrangian/solidParticle/solidParticleCloudI.H @@ -25,6 +25,12 @@ License // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +inline bool Foam::solidParticleCloud::hasWallImpactDistance() const +{ + return true; +} + + inline const Foam::fvMesh& Foam::solidParticleCloud::mesh() const { return mesh_; diff --git a/src/lagrangian/solidParticle/solidParticleI.H b/src/lagrangian/solidParticle/solidParticleI.H index a0af6bfad53..5bc146941a1 100644 --- a/src/lagrangian/solidParticle/solidParticleI.H +++ b/src/lagrangian/solidParticle/solidParticleI.H @@ -46,12 +46,14 @@ inline Foam::solidParticle::solidParticle ( const Cloud<solidParticle>& c, const vector& position, - const label celli, + const label cellI, + const label tetFaceI, + const label tetPtI, const scalar d, const vector& U ) : - Particle<solidParticle>(c, position, celli), + Particle<solidParticle>(c, position, cellI, tetFaceI, tetPtI), d_(d), U_(U) {} @@ -64,18 +66,21 @@ inline Foam::solidParticleCloud& Foam::solidParticle::trackData::spc() return spc_; } + inline const Foam::interpolationCellPoint<Foam::scalar>& Foam::solidParticle::trackData::rhoInterp() const { return rhoInterp_; } + inline const Foam::interpolationCellPoint<Foam::vector>& Foam::solidParticle::trackData::UInterp() const { return UInterp_; } + inline const Foam::interpolationCellPoint<Foam::scalar>& Foam::solidParticle::trackData::nuInterp() const { @@ -93,11 +98,13 @@ inline Foam::scalar Foam::solidParticle::d() const return d_; } + inline Foam::scalar Foam::solidParticle::wallImpactDistance(const vector&) const { return 0.5*d_; } + inline const Foam::vector& Foam::solidParticle::U() const { return U_; diff --git a/src/mesh/autoMesh/autoHexMesh/meshRefinement/meshRefinementRefine.C b/src/mesh/autoMesh/autoHexMesh/meshRefinement/meshRefinementRefine.C index 1c867ba760f..bda9fc6e8e9 100644 --- a/src/mesh/autoMesh/autoHexMesh/meshRefinement/meshRefinementRefine.C +++ b/src/mesh/autoMesh/autoHexMesh/meshRefinement/meshRefinementRefine.C @@ -279,7 +279,11 @@ Foam::label Foam::meshRefinement::markFeatureRefinement Cloud<trackedParticle> cloud(mesh_, IDLList<trackedParticle>()); // Create particles on whichever processor holds the keepPoint. - label cellI = mesh_.findCell(keepPoint); + label cellI = -1; + label tetFaceI = -1; + label tetPtI = -1; + + cloud.findCellFacePt(keepPoint, cellI, tetFaceI, tetPtI); if (cellI != -1) { @@ -308,6 +312,8 @@ Foam::label Foam::meshRefinement::markFeatureRefinement cloud, keepPoint, cellI, + tetFaceI, + tetPtI, featureMesh.points()[pointI], // endpos featureLevels[featI], // level featI, // featureMesh diff --git a/src/mesh/autoMesh/autoHexMesh/trackedParticle/ExactParticle.C b/src/mesh/autoMesh/autoHexMesh/trackedParticle/ExactParticle.C deleted file mode 100644 index 8efba5dc0cc..00000000000 --- a/src/mesh/autoMesh/autoHexMesh/trackedParticle/ExactParticle.C +++ /dev/null @@ -1,261 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. - \\/ M anipulation | -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 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 "ExactParticle.H" - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -template<class ParticleType> -template<class TrackingData> -Foam::label Foam::ExactParticle<ParticleType>::track -( - const vector& endPosition, - TrackingData& td -) -{ - this->facei_ = -1; - - // Tracks to endPosition or stop on boundary - while (!this->onBoundary() && this->stepFraction_ < 1.0 - SMALL) - { - this->stepFraction_ += - trackToFace(endPosition, td) - *(1.0 - this->stepFraction_); - } - - return this->facei_; -} - - -template<class ParticleType> -Foam::label Foam::ExactParticle<ParticleType>::track -( - const vector& endPosition -) -{ - int dummyTd; - return track(endPosition, dummyTd); -} - - -template<class ParticleType> -template<class TrackingData> -Foam::scalar Foam::ExactParticle<ParticleType>::trackToFace -( - const vector& endPosition, - TrackingData& td -) -{ - const polyMesh& mesh = this->cloud().pMesh(); - const labelList& cFaces = mesh.cells()[this->celli_]; - - point intersection(vector::zero); - scalar trackFraction = VGREAT; - label hitFacei = -1; - - const vector vec = endPosition-this->position_; - - forAll(cFaces, i) - { - label facei = cFaces[i]; - - if (facei != this->face()) - { - pointHit inter = mesh.faces()[facei].intersection - ( - this->position_, - vec, - mesh.faceCentres()[facei], - mesh.points(), - intersection::HALF_RAY - ); - - if (inter.hit() && inter.distance() < trackFraction) - { - trackFraction = inter.distance(); - hitFacei = facei; - intersection = inter.hitPoint(); - } - } - } - - if (hitFacei == -1) - { - // Did not find any intersection. Fall back to original approximate - // algorithm - return Particle<ParticleType>::trackToFace - ( - endPosition, - td - ); - } - - if (trackFraction >= (1.0-SMALL)) - { - // Nearest intersection beyond endPosition so we hit endPosition. - trackFraction = 1.0; - this->position_ = endPosition; - this->facei_ = -1; - return 1.0; - } - else - { - this->position_ = intersection; - this->facei_ = hitFacei; - } - - - // Normal situation (trackFraction 0..1). Straight copy - // of Particle::trackToFace. - - bool internalFace = this->cloud().internalFace(this->facei_); - - // change cell - if (internalFace) // Internal face - { - if (this->celli_ == mesh.faceOwner()[this->facei_]) - { - this->celli_ = mesh.faceNeighbour()[this->facei_]; - } - else if (this->celli_ == mesh.faceNeighbour()[this->facei_]) - { - this->celli_ = mesh.faceOwner()[this->facei_]; - } - else - { - FatalErrorIn - ( - "ExactParticle::trackToFace" - "(const vector&, TrackingData&)" - )<< "addressing failure" << nl - << abort(FatalError); - } - } - else - { - ParticleType& p = static_cast<ParticleType&>(*this); - - // Soft-sphere algorithm ignores the boundary - if (p.softImpact()) - { - trackFraction = 1.0; - this->position_ = endPosition; - } - - label patchi = patch(this->facei_); - const polyPatch& patch = mesh.boundaryMesh()[patchi]; - - if (isA<wedgePolyPatch>(patch)) - { - p.hitWedgePatch - ( - static_cast<const wedgePolyPatch&>(patch), td - ); - } - else if (isA<symmetryPolyPatch>(patch)) - { - p.hitSymmetryPatch - ( - static_cast<const symmetryPolyPatch&>(patch), td - ); - } - else if (isA<cyclicPolyPatch>(patch)) - { - p.hitCyclicPatch - ( - static_cast<const cyclicPolyPatch&>(patch), td - ); - } - else if (isA<processorPolyPatch>(patch)) - { - p.hitProcessorPatch - ( - static_cast<const processorPolyPatch&>(patch), td - ); - } - else if (isA<wallPolyPatch>(patch)) - { - p.hitWallPatch - ( - static_cast<const wallPolyPatch&>(patch), td - ); - } - else if (isA<polyPatch>(patch)) - { - p.hitPatch - ( - static_cast<const polyPatch&>(patch), td - ); - } - else - { - FatalErrorIn - ( - "ExactParticle::trackToFace" - "(const vector& endPosition, scalar& trackFraction)" - )<< "patch type " << patch.type() << " not suported" << nl - << abort(FatalError); - } - } - - // If the trackFraction = 0 something went wrong. - // Either the particle is flipping back and forth across a face perhaps - // due to velocity interpolation errors or it is in a "hole" in the mesh - // caused by face warpage. - // In both cases resolve the positional ambiguity by moving the particle - // slightly towards the cell-centre. - if (trackFraction < SMALL) - { - this->position_ += - 1.0e-6*(mesh.cellCentres()[this->celli_] - this->position_); - } - - return trackFraction; -} - - -template<class ParticleType> -Foam::scalar Foam::ExactParticle<ParticleType>::trackToFace -( - const vector& endPosition -) -{ - int dummyTd; - return trackToFace(endPosition, dummyTd); -} - - -template<class ParticleType> -Foam::Ostream& Foam::operator<< -( - Ostream& os, - const ExactParticle<ParticleType>& p -) -{ - return operator<<(os, static_cast<const Particle<ParticleType>&>(p)); -} - - -// ************************************************************************* // diff --git a/src/mesh/autoMesh/autoHexMesh/trackedParticle/ExactParticle.H b/src/mesh/autoMesh/autoHexMesh/trackedParticle/ExactParticle.H deleted file mode 100644 index 5965815d02f..00000000000 --- a/src/mesh/autoMesh/autoHexMesh/trackedParticle/ExactParticle.H +++ /dev/null @@ -1,191 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. - \\/ M anipulation | -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -Class - Foam::ExactParticle - -Description - Special version of Particle to do tracking on non-convex cells. - -\*---------------------------------------------------------------------------*/ - -#ifndef ExactParticle_H -#define ExactParticle_H - -#include "face.H" -#include "Particle.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -template<class ExactParticle> -class Cloud; - -// Forward declaration of friend functions and operators - -template<class ParticleType> -class ExactParticle; - -template<class ParticleType> -Ostream& operator<< -( - Ostream&, - const ExactParticle<ParticleType>& -); - - -/*---------------------------------------------------------------------------*\ - Class ExactParticle Declaration -\*---------------------------------------------------------------------------*/ - -template<class ParticleType> -class ExactParticle -: - public Particle<ParticleType> -{ - -public: - - friend class Cloud<ParticleType>; - - - // Constructors - - //- Construct from components - ExactParticle - ( - const Cloud<ParticleType>& cloud, - const vector& position, - const label celli - ) - : - Particle<ParticleType>(cloud, position, celli) - {} - - - //- Construct from Istream - ExactParticle - ( - const Cloud<ParticleType>& cloud, - Istream& is, - bool readFields = true - ) - : - Particle<ParticleType>(cloud, is, readFields) - {} - - - //- Factory class to read-construct particles used for parallel transfer - class iNew - { - - // Private data - - const Cloud<ParticleType>& cloud_; - - - public: - - iNew(const Cloud<ParticleType>& cloud) - : - cloud_(cloud) - {} - - autoPtr<ParticleType> operator()(Istream& is) const - { - return autoPtr<ParticleType> - ( - new ParticleType(cloud_, is) - ); - } - }; - - - //- Destructor - virtual ~ExactParticle() - {} - - - // Member Functions - - //- Track particle to end of trajectory - // or until it hits the boundary. - // On entry 'stepFraction()' should be set to the fraction of the - // time-step at which the tracking starts and on exit it contains - // the fraction of the time-step completed. - // Returns the boundary face index if the track stops at the - // boundary, -1 otherwise. - template<class TrackingData> - label track - ( - const vector& endPosition, - TrackingData& td - ); - - //- Calls the templated track with dummy TrackingData - label track(const vector& endPosition); - - //- Track particle to a given position and returns 1.0 if the - // trajectory is completed without hitting a face otherwise - // stops at the face and returns the fraction of the trajectory - // completed. - // on entry 'stepFraction()' should be set to the fraction of the - // time-step at which the tracking starts. - template<class TrackingData> - scalar trackToFace - ( - const vector& endPosition, - TrackingData& td - ); - - //- Calls the templated trackToFace with dummy TrackingData - scalar trackToFace(const vector& endPosition); - - - // Ostream Operator - - friend Ostream& operator<< <ParticleType> - ( - Ostream&, - const ExactParticle<ParticleType>& - ); -}; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#ifdef NoRepository -# include "ExactParticle.C" -#endif - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#endif - -// ************************************************************************* // diff --git a/src/mesh/autoMesh/autoHexMesh/trackedParticle/trackedParticle.C b/src/mesh/autoMesh/autoHexMesh/trackedParticle/trackedParticle.C index ad4a5079d57..5714b3062ee 100644 --- a/src/mesh/autoMesh/autoHexMesh/trackedParticle/trackedParticle.C +++ b/src/mesh/autoMesh/autoHexMesh/trackedParticle/trackedParticle.C @@ -32,14 +32,16 @@ Foam::trackedParticle::trackedParticle ( const Cloud<trackedParticle>& c, const vector& position, - const label celli, + const label cellI, + const label tetFaceI, + const label tetPtI, const point& end, const label level, const label i, const label j ) : - ExactParticle<trackedParticle>(c, position, celli), + Particle<trackedParticle>(c, position, cellI, tetFaceI, tetPtI), end_(end), level_(level), i_(i), @@ -55,7 +57,7 @@ Foam::trackedParticle::trackedParticle bool readFields ) : - ExactParticle<trackedParticle>(c, is, readFields) + Particle<trackedParticle>(c, is, readFields) { if (readFields) { @@ -118,7 +120,9 @@ bool Foam::trackedParticle::hitPatch ( const polyPatch&, trackedParticle::trackData& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ) { return false; @@ -129,7 +133,9 @@ bool Foam::trackedParticle::hitPatch ( const polyPatch&, int&, - const label + const label, + const scalar trackFraction, + const tetIndices& tetIs ) { return false; @@ -215,7 +221,8 @@ void Foam::trackedParticle::hitProcessorPatch void Foam::trackedParticle::hitWallPatch ( const wallPolyPatch& wpp, - trackedParticle::trackData& td + trackedParticle::trackData& td, + const tetIndices& ) { // Remove particle @@ -226,7 +233,8 @@ void Foam::trackedParticle::hitWallPatch void Foam::trackedParticle::hitWallPatch ( const wallPolyPatch& wpp, - int& + int&, + const tetIndices& ) {} @@ -256,7 +264,7 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const trackedParticle& p) { if (os.format() == IOstream::ASCII) { - os << static_cast<const ExactParticle<trackedParticle>&>(p) + os << static_cast<const Particle<trackedParticle>&>(p) << token::SPACE << p.end_ << token::SPACE << p.level_ << token::SPACE << p.i_ @@ -264,7 +272,7 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const trackedParticle& p) } else { - os << static_cast<const ExactParticle<trackedParticle>&>(p); + os << static_cast<const Particle<trackedParticle>&>(p); os.write ( reinterpret_cast<const char*>(&p.end_), diff --git a/src/mesh/autoMesh/autoHexMesh/trackedParticle/trackedParticle.H b/src/mesh/autoMesh/autoHexMesh/trackedParticle/trackedParticle.H index ef0c2695e4b..1f62e6f37a5 100644 --- a/src/mesh/autoMesh/autoHexMesh/trackedParticle/trackedParticle.H +++ b/src/mesh/autoMesh/autoHexMesh/trackedParticle/trackedParticle.H @@ -26,8 +26,7 @@ Class Description Particle class that marks cells it passes through. Used to mark cells - visited by feature edges. Uses ExactParticle tracking class so - will work on concave cells. + visited by feature edges. SourceFiles trackedParticle.C @@ -37,7 +36,7 @@ SourceFiles #ifndef trackedParticle_H #define trackedParticle_H -#include "ExactParticle.H" +#include "Particle.H" #include "autoPtr.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -53,7 +52,7 @@ class trackedParticleCloud; class trackedParticle : - public ExactParticle<trackedParticle> + public Particle<trackedParticle> { // Private data @@ -118,7 +117,9 @@ public: ( const Cloud<trackedParticle>& c, const vector& position, - const label celli, + const label cellI, + const label tetFaceI, + const label tetPtI, const point& end, const label level, const label i, @@ -174,13 +175,17 @@ public: ( const polyPatch&, trackedParticle::trackData& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ); bool hitPatch ( const polyPatch&, int&, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ); //- Overridable function to handle the particle hitting a wedge @@ -237,12 +242,14 @@ public: void hitWallPatch ( const wallPolyPatch&, - trackedParticle::trackData& td + trackedParticle::trackData& td, + const tetIndices& ); void hitWallPatch ( const wallPolyPatch&, - int& + int&, + const tetIndices& ); //- Overridable function to handle the particle hitting a polyPatch diff --git a/src/meshTools/Make/options b/src/meshTools/Make/options index ef1033b0e8e..45765759c16 100644 --- a/src/meshTools/Make/options +++ b/src/meshTools/Make/options @@ -1,7 +1,5 @@ EXE_INC = \ - -I$(LIB_SRC)/triSurface/lnInclude \ - -I$(LIB_SRC)/lagrangian/basic/lnInclude + -I$(LIB_SRC)/triSurface/lnInclude LIB_LIBS = \ - -ltriSurface \ - -llagrangian + -ltriSurface diff --git a/src/meshTools/surfaceSets/surfaceSets.H b/src/meshTools/surfaceSets/surfaceSets.H index 3fd75716fac..faeb38aa4d7 100644 --- a/src/meshTools/surfaceSets/surfaceSets.H +++ b/src/meshTools/surfaceSets/surfaceSets.H @@ -102,9 +102,8 @@ class surfaceSets //); ////- Select all points out of pointSet where the distance to - //// the surface is less - //// than a factor times a local length scale (minimum length of - //// connected edges) + //// the surface is less than a factor times a local length + //// scale (minimum length of connected edges) //static void getNearPoints //( // const primitiveMesh& mesh, diff --git a/src/meshTools/triSurface/booleanOps/surfaceIntersection/surfaceIntersection.C b/src/meshTools/triSurface/booleanOps/surfaceIntersection/surfaceIntersection.C index 9e164f73feb..6602fbcf430 100644 --- a/src/meshTools/triSurface/booleanOps/surfaceIntersection/surfaceIntersection.C +++ b/src/meshTools/triSurface/booleanOps/surfaceIntersection/surfaceIntersection.C @@ -30,8 +30,6 @@ License #include "HashSet.H" #include "triSurface.H" #include "pointIndexHit.H" -#include "octreeDataTriSurface.H" -#include "octree.H" #include "mergePoints.H" #include "plane.H" #include "edgeIntersections.H" diff --git a/src/meshTools/triSurface/booleanOps/surfaceIntersection/surfaceIntersectionFuncs.C b/src/meshTools/triSurface/booleanOps/surfaceIntersection/surfaceIntersectionFuncs.C index ec9f3705539..18ebd6988c0 100644 --- a/src/meshTools/triSurface/booleanOps/surfaceIntersection/surfaceIntersectionFuncs.C +++ b/src/meshTools/triSurface/booleanOps/surfaceIntersection/surfaceIntersectionFuncs.C @@ -30,8 +30,6 @@ License #include "HashSet.H" #include "triSurface.H" #include "pointIndexHit.H" -#include "octreeDataTriSurface.H" -#include "octree.H" #include "meshTools.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // diff --git a/src/meshTools/triSurface/surfaceFeatures/surfaceFeatures.C b/src/meshTools/triSurface/surfaceFeatures/surfaceFeatures.C index acfb6749144..3cbe1157a98 100644 --- a/src/meshTools/triSurface/surfaceFeatures/surfaceFeatures.C +++ b/src/meshTools/triSurface/surfaceFeatures/surfaceFeatures.C @@ -25,9 +25,9 @@ License #include "surfaceFeatures.H" #include "triSurface.H" -#include "octree.H" -#include "octreeDataEdges.H" -#include "octreeDataPoint.H" +#include "indexedOctree.H" +#include "treeDataEdge.H" +#include "treeDataPoint.H" #include "meshTools.H" #include "linePointRef.H" #include "OFstream.H" @@ -752,21 +752,21 @@ Foam::Map<Foam::label> Foam::surfaceFeatures::nearestSamples ( const labelList& pointLabels, const pointField& samples, - const scalarField& maxDist + const scalarField& maxDistSqr ) const { // Build tree out of all samples. - //Note: cannot be done one the fly - gcc4.4 compiler bug. + // Note: cannot be done one the fly - gcc4.4 compiler bug. treeBoundBox bb(samples); - octree<octreeDataPoint> ppTree + indexedOctree<treeDataPoint> ppTree ( - bb, // overall search domain - octreeDataPoint(samples), // all information needed to do checks - 1, // min levels - 20.0, // maximum ratio of cubes v.s. cells - 100.0 // max. duplicity; n/a since no bounding boxes. + treeDataPoint(samples), // all information needed to do checks + bb, // overall search domain + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity ); // From patch point to surface point @@ -780,31 +780,23 @@ Foam::Map<Foam::label> Foam::surfaceFeatures::nearestSamples const point& surfPt = surfPoints[surfPointI]; - point maxDistPt(maxDist[i], maxDist[i], maxDist[i]); - - treeBoundBox tightest(surfPt - maxDistPt, surfPt + maxDistPt); - scalar tightestDist = Foam::GREAT; - - label sampleI = ppTree.findNearest + pointIndexHit info = ppTree.findNearest ( surfPt, - tightest, - tightestDist + maxDistSqr[i] ); - if (sampleI == -1) + if (!info.hit()) { FatalErrorIn("surfaceFeatures::nearestSamples") << "Problem for point " - << surfPointI << " in tree " << ppTree.octreeBb() + << surfPointI << " in tree " << ppTree.bb() << abort(FatalError); } - if - ( - magSqr(samples[sampleI] - surfPt) - < Foam::sqr(maxDist[sampleI]) - ) + label sampleI = info.index(); + + if (magSqr(samples[sampleI] - surfPt) < maxDistSqr[sampleI]) { nearest.insert(sampleI, surfPointI); } @@ -845,26 +837,25 @@ Foam::Map<Foam::label> Foam::surfaceFeatures::nearestSamples const labelList& selectedEdges, const pointField& samples, const scalarField& sampleDist, - const scalarField& maxDist, + const scalarField& maxDistSqr, const scalar minSampleDist ) const { const pointField& surfPoints = surf_.localPoints(); const edgeList& surfEdges = surf_.edges(); - scalar maxSearch = max(maxDist); - vector span(maxSearch, maxSearch, maxSearch); + scalar maxSearchSqr = max(maxDistSqr); //Note: cannot be done one the fly - gcc4.4 compiler bug. treeBoundBox bb(samples); - octree<octreeDataPoint> ppTree + indexedOctree<treeDataPoint> ppTree ( + treeDataPoint(samples), // all information needed to do checks bb, // overall search domain - octreeDataPoint(samples), // all information needed to do checks - 1, // min levels - 20.0, // maximum ratio of cubes v.s. cells - 100.0 // max. duplicity; n/a since no bounding boxes. + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity ); // From patch point to surface edge. @@ -902,22 +893,21 @@ Foam::Map<Foam::label> Foam::surfaceFeatures::nearestSamples { point edgePoint(surfPoints[e.start()] + s*eVec); - treeBoundBox tightest(edgePoint - span, edgePoint + span); - scalar tightestDist = Foam::GREAT; - - label sampleI = ppTree.findNearest + pointIndexHit info = ppTree.findNearest ( edgePoint, - tightest, - tightestDist + maxSearchSqr ); - if (sampleI == -1) + if (!info.hit()) { // No point close enough to surface edge. break; } - if (tightestDist < maxDist[sampleI]) + + label sampleI = info.index(); + + if (magSqr(info.hitPoint() - edgePoint) < maxDistSqr[sampleI]) { nearest.insert(sampleI, surfEdgeI); } @@ -985,31 +975,30 @@ Foam::Map<Foam::pointIndexHit> Foam::surfaceFeatures::nearestEdges const labelList& selectedSampleEdges, const pointField& samplePoints, const scalarField& sampleDist, - const scalarField& maxDist, + const scalarField& maxDistSqr, const scalar minSampleDist ) const { // Build tree out of selected sample edges. - octree<octreeDataEdges> ppTree + indexedOctree<treeDataEdge> ppTree ( - treeBoundBox(samplePoints), // overall search domain - octreeDataEdges + treeDataEdge ( + false, sampleEdges, samplePoints, selectedSampleEdges ), // geometric info container for edges - 1, // min levels - 20.0, // maximum ratio of cubes v.s. cells - 10.0 // max. duplicity + treeBoundBox(samplePoints), // overall search domain + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity ); const pointField& surfPoints = surf_.localPoints(); const edgeList& surfEdges = surf_.edges(); - scalar maxSearch = max(maxDist); - vector span(maxSearch, maxSearch, maxSearch); - + scalar maxSearchSqr = max(maxDistSqr); Map<pointIndexHit> nearest(2*sampleEdges.size()); @@ -1050,27 +1039,25 @@ Foam::Map<Foam::pointIndexHit> Foam::surfaceFeatures::nearestEdges { point edgePoint(surfPoints[e.start()] + s*eVec); - treeBoundBox tightest(edgePoint - span, edgePoint + span); - scalar tightestDist = Foam::GREAT; - - label index = ppTree.findNearest + pointIndexHit info = ppTree.findNearest ( edgePoint, - tightest, - tightestDist + maxSearchSqr ); - if (index == -1) + if (!info.hit()) { // No edge close enough to surface edge. break; } + label index = info.index(); + label sampleEdgeI = ppTree.shapes().edgeLabels()[index]; const edge& e = sampleEdges[sampleEdgeI]; - if (tightestDist < maxDist[e.start()]) + if (magSqr(info.hitPoint() - edgePoint) < maxDistSqr[e.start()]) { nearest.insert ( @@ -1136,7 +1123,7 @@ void Foam::surfaceFeatures::nearestSurfEdge ( const labelList& selectedEdges, const pointField& samples, - const vector& searchSpan, // Search span + scalar searchSpanSqr, // Search span labelList& edgeLabel, labelList& edgeEndPoint, pointField& edgePoint @@ -1148,57 +1135,48 @@ void Foam::surfaceFeatures::nearestSurfEdge const pointField& localPoints = surf_.localPoints(); - octree<octreeDataEdges> ppTree + indexedOctree<treeDataEdge> ppTree ( - treeBoundBox(localPoints), // overall search domain - octreeDataEdges + treeDataEdge ( + false, surf_.edges(), localPoints, selectedEdges ), // all information needed to do geometric checks - 1, // min levels - 20.0, // maximum ratio of cubes v.s. cells - 10.0 // max. duplicity + treeBoundBox(localPoints), // overall search domain + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity ); - forAll(samples, i) { const point& sample = samples[i]; - treeBoundBox tightest(sample - searchSpan, sample + searchSpan); - - scalar tightestDist = magSqr(searchSpan); - - label index = - ppTree.findNearest - ( - sample, - tightest, - tightestDist - ); - + pointIndexHit info = ppTree.findNearest + ( + sample, + searchSpanSqr + ); - if (index == -1) + if (!info.hit()) { edgeLabel[i] = -1; } else { - edgeLabel[i] = selectedEdges[index]; + edgeLabel[i] = selectedEdges[info.index()]; - // Unfortunately findNearest does not return nearest point so - // recalculate + // Need to recalculate to classify edgeEndPoint const edge& e = surf_.edges()[edgeLabel[i]]; - pointIndexHit pHit = - edgeNearest - ( - localPoints[e.start()], - localPoints[e.end()], - sample - ); + pointIndexHit pHit = edgeNearest + ( + localPoints[e.start()], + localPoints[e.end()], + sample + ); edgePoint[i] = pHit.rawPoint(); edgeEndPoint[i] = pHit.index(); @@ -1226,22 +1204,21 @@ void Foam::surfaceFeatures::nearestSurfEdge pointOnEdge.setSize(selectedSampleEdges.size()); pointOnFeature.setSize(selectedSampleEdges.size()); - - octree<octreeDataEdges> ppTree + indexedOctree<treeDataEdge> ppTree ( - treeBoundBox(surf_.localPoints()), // overall search domain - octreeDataEdges + treeDataEdge ( + false, surf_.edges(), surf_.localPoints(), selectedEdges ), // all information needed to do geometric checks - 1, // min levels - 10.0, // maximum ratio of cubes v.s. cells - 10.0 // max. duplicity + treeBoundBox(surf_.localPoints()), // overall search domain + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity ); - forAll(selectedSampleEdges, i) { const edge& e = sampleEdges[selectedSampleEdges[i]]; @@ -1252,23 +1229,22 @@ void Foam::surfaceFeatures::nearestSurfEdge treeBoundBox tightest(eMid - searchSpan, eMid + searchSpan); - label index = - ppTree.findNearest - ( - edgeLine, - tightest, - pointOnEdge[i], - pointOnFeature[i] - ); - + pointIndexHit info = ppTree.findNearest + ( + edgeLine, + tightest, + pointOnEdge[i] + ); - if (index == -1) + if (!info.hit()) { edgeLabel[i] = -1; } else { - edgeLabel[i] = featureEdges_[index]; + edgeLabel[i] = selectedEdges[info.index()]; + + pointOnFeature[i] = info.hitPoint(); } } } diff --git a/src/meshTools/triSurface/surfaceFeatures/surfaceFeatures.H b/src/meshTools/triSurface/surfaceFeatures/surfaceFeatures.H index 60e9c470859..a12fc0f7615 100644 --- a/src/meshTools/triSurface/surfaceFeatures/surfaceFeatures.H +++ b/src/meshTools/triSurface/surfaceFeatures/surfaceFeatures.H @@ -268,28 +268,30 @@ public: // Find - //- Find nearest sample for selected surface points (usually the - // set of featurePoints). Return map from index in - // samples to surface point. Do not include points that are further - // than maxDist away (separate maxDist for every sample) + //- Find nearest sample for selected surface points + // (usually the set of featurePoints). Return map from + // index in samples to surface point. Do not include + // points that are further than maxDist away (separate + // maxDist for every sample). Supply maxDistSqr. Map<label> nearestSamples ( const labelList& selectedPoints, const pointField& samples, - const scalarField& maxDist + const scalarField& maxDistSqr ) const; - //- Find nearest sample for regularly sampled points along the - // selected (surface) edges. Return map from sample to edge. - // maxDist is distance below which gets snapped. - // Edge gets sampled at points sampleDist[sampleI] apart. - // (with a maximum of 10 samples per edge) + //- Find nearest sample for regularly sampled points along + // the selected (surface) edges. Return map from sample + // to edge. maxDistSqr is distance squared below which + // gets snapped. Edge gets sampled at points + // sampleDist[sampleI] apart. (with a maximum of 10 + // samples per edge) Map<label> nearestSamples ( const labelList& selectedEdges, const pointField& samples, const scalarField& sampleDist, - const scalarField& maxDist, + const scalarField& maxDistSqr, const scalar minSampleDist = 0.1 ) const; @@ -303,7 +305,7 @@ public: const labelList& selectedSampleEdges, const pointField& samplePoints, const scalarField& sampleDist, - const scalarField& maxDist, + const scalarField& maxDistSqr, const scalar minSampleDist = 0.1 ) const; @@ -319,7 +321,7 @@ public: ( const labelList& selectedEdges, const pointField& samples, - const vector& searchSpan, // search span + scalar searchSpanSqr, // search span labelList& edgeLabel, labelList& edgeEndPoint, pointField& edgePoint diff --git a/src/parallel/reconstruct/reconstruct/Make/options b/src/parallel/reconstruct/reconstruct/Make/options index 71546225cf5..7a728f9dd7c 100644 --- a/src/parallel/reconstruct/reconstruct/Make/options +++ b/src/parallel/reconstruct/reconstruct/Make/options @@ -1,7 +1,9 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude LIB_LIBS = \ -lfiniteVolume \ + -lmeshTools \ -llagrangian diff --git a/src/parallel/reconstruct/reconstruct/reconstructLagrangianPositions.C b/src/parallel/reconstruct/reconstruct/reconstructLagrangianPositions.C index d6e84638b99..bab5aa0df05 100644 --- a/src/parallel/reconstruct/reconstruct/reconstructLagrangianPositions.C +++ b/src/parallel/reconstruct/reconstruct/reconstructLagrangianPositions.C @@ -50,12 +50,19 @@ void Foam::reconstructLagrangianPositions { const labelList& cellMap = cellProcAddressing[i]; + // faceProcAddressing not required currently. + // const labelList& faceMap = faceProcAddressing[i]; + Cloud<passiveParticle> lpi(meshes[i], cloudName, false); forAllConstIter(Cloud<passiveParticle>, lpi, iter) { const passiveParticle& ppi = iter(); + // // Inverting sign if necessary and subtracting 1 from + // // faceProcAddressing + // label mappedTetFace = mag(faceMap[ppi.tetFace()]) - 1; + lagrangianPositions.append ( new passiveParticle diff --git a/src/postProcessing/functionObjects/field/streamLine/streamLine.C b/src/postProcessing/functionObjects/field/streamLine/streamLine.C index ebe01f1e8b4..8336fd8f9a9 100644 --- a/src/postProcessing/functionObjects/field/streamLine/streamLine.C +++ b/src/postProcessing/functionObjects/field/streamLine/streamLine.C @@ -56,6 +56,7 @@ void Foam::streamLine::track() //Pout<< "Seeding particles." << endl; const sampledSet& seedPoints = sampledSetPtr_(); + forAll(seedPoints, i) { //Pout<< "Seeded particle at " << seedPoints[i] @@ -73,10 +74,10 @@ void Foam::streamLine::track() ) ); } + label nSeeds = returnReduce(particles.size(), sumOp<label>()); - Info<< "Seeded " << nSeeds - << " particles." << endl; + Info<< "Seeded " << nSeeds << " particles." << endl; // Read or lookup fields PtrList<volScalarField> vsFlds; @@ -84,7 +85,6 @@ void Foam::streamLine::track() PtrList<volVectorField> vvFlds; PtrList<interpolationCellPoint<vector> > vvInterp; - label UIndex = -1; if (loadFromFiles_) @@ -188,7 +188,6 @@ void Foam::streamLine::track() vectorNames_[i] = vvInterp[i].psi().name(); } - // Check that we know the index of U in the interpolators. if (UIndex == -1) @@ -202,8 +201,6 @@ void Foam::streamLine::track() << exit(FatalError); } - - // Sampled data // ~~~~~~~~~~~~ @@ -490,7 +487,6 @@ void Foam::streamLine::write() mkDir(vtkPath); - // Convert track positions PtrList<coordSet> tracks(allTracks_.size()); @@ -508,8 +504,6 @@ void Foam::streamLine::write() tracks[trackI].transfer(allTracks_[trackI]); } - - // Convert scalar values if (allScalars_.size() > 0) diff --git a/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.C b/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.C index 01d092c5ada..78478222cb5 100644 --- a/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.C +++ b/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.C @@ -88,11 +88,11 @@ Foam::streamLineParticle::streamLineParticle ( const Cloud<streamLineParticle>& c, const vector& position, - const label celli, + const label cellI, const label lifeTime ) : - Particle<streamLineParticle>(c, position, celli), + Particle<streamLineParticle>(c, position, cellI), lifeTime_(lifeTime) {} @@ -246,7 +246,9 @@ bool Foam::streamLineParticle::hitPatch ( const polyPatch&, streamLineParticle::trackData& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ) { // Disable generic patch interaction @@ -258,7 +260,9 @@ bool Foam::streamLineParticle::hitPatch ( const polyPatch&, int&, - const label + const label, + const scalar, + const tetIndices& ) { // Disable generic patch interaction @@ -345,7 +349,8 @@ void Foam::streamLineParticle::hitProcessorPatch void Foam::streamLineParticle::hitWallPatch ( const wallPolyPatch& wpp, - streamLineParticle::trackData& td + streamLineParticle::trackData& td, + const tetIndices& ) { // Remove particle @@ -356,7 +361,8 @@ void Foam::streamLineParticle::hitWallPatch void Foam::streamLineParticle::hitWallPatch ( const wallPolyPatch& wpp, - int& + int&, + const tetIndices& ) {} diff --git a/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.H b/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.H index eceb8a3f88e..d556e4791de 100644 --- a/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.H +++ b/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.H @@ -141,7 +141,7 @@ public: ( const Cloud<streamLineParticle>& c, const vector& position, - const label celli, + const label cellI, const label lifeTime ); @@ -182,13 +182,18 @@ public: ( const polyPatch&, streamLineParticle::trackData& td, - const label patchI + const label patchI, + const scalar trackFraction, + const tetIndices& tetIs ); + bool hitPatch ( const polyPatch&, int&, - const label patchI + const label, + const scalar, + const tetIndices& ); //- Overridable function to handle the particle hitting a wedge @@ -245,12 +250,14 @@ public: void hitWallPatch ( const wallPolyPatch&, - streamLineParticle::trackData& td + streamLineParticle::trackData& td, + const tetIndices& ); void hitWallPatch ( const wallPolyPatch&, - int& + int&, + const tetIndices& ); //- Overridable function to handle the particle hitting a polyPatch diff --git a/src/sampling/Make/options b/src/sampling/Make/options index 6629b3652c0..0e2c6780d2b 100644 --- a/src/sampling/Make/options +++ b/src/sampling/Make/options @@ -9,4 +9,5 @@ LIB_LIBS = \ -lfiniteVolume \ -lmeshTools \ -lsurfMesh \ - -ltriSurface + -ltriSurface \ + -llagrangian diff --git a/src/sampling/meshToMeshInterpolation/meshToMesh/calculateMeshToMeshAddressing.C b/src/sampling/meshToMeshInterpolation/meshToMesh/calculateMeshToMeshAddressing.C index 372ba4a1c63..0248c41d30e 100644 --- a/src/sampling/meshToMeshInterpolation/meshToMesh/calculateMeshToMeshAddressing.C +++ b/src/sampling/meshToMeshInterpolation/meshToMesh/calculateMeshToMeshAddressing.C @@ -31,9 +31,9 @@ Description #include "meshToMesh.H" #include "SubField.H" -#include "octree.H" -#include "octreeDataCell.H" -#include "octreeDataFace.H" +#include "indexedOctree.H" +#include "treeDataCell.H" +#include "treeDataFace.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -100,21 +100,18 @@ void Foam::meshToMesh::calcAddressing() Info<< " typical dimension :" << shiftedBb.typDim() << endl; } - // Wrap indices and mesh information into helper object - octreeDataCell shapes(fromMesh_); - - octree<octreeDataCell> oc + indexedOctree<treeDataCell> oc ( - shiftedBb, // overall bounding box - shapes, // all information needed to do checks on cells - 1, // min. levels - 10.0, // max. size of leaves - 10.0 // maximum ratio of cubes v.s. cells + treeDataCell(false, fromMesh_), + shiftedBb, // overall bounding box + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity ); if (debug) { - oc.printStats(Info); + oc.print(Pout, false, 0); } cellAddresses @@ -174,38 +171,29 @@ void Foam::meshToMesh::calcAddressing() wallBb.max() + vector(typDim, typDim, typDim) ); - // Wrap data for octree into container - octreeDataFace shapes(fromPatch); - - octree<octreeDataFace> oc + indexedOctree<treeDataFace> oc ( + treeDataFace(false, fromPatch), shiftedBb, // overall search domain - shapes, // all information needed to do checks on cells - 1, // min levels - 20.0, // maximum ratio of cubes v.s. cells - 2.0 + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity ); - const vectorField::subField centresToBoundary = toPatch.faceCentres(); boundaryAddressing_[patchi].setSize(toPatch.size()); - treeBoundBox tightest; - scalar tightestDist; + scalar distSqr = sqr(GREAT); forAll(toPatch, toi) { - tightest = wallBb; // starting search bb - tightestDist = Foam::GREAT; // starting max distance - boundaryAddressing_[patchi][toi] = oc.findNearest ( centresToBoundary[toi], - tightest, - tightestDist - ); + distSqr + ).index(); } } } @@ -225,7 +213,7 @@ void Foam::meshToMesh::cellAddresses const pointField& points, const fvMesh& fromMesh, const List<bool>& boundaryCell, - const octree<octreeDataCell>& oc + const indexedOctree<treeDataCell>& oc ) const { // the implemented search method is a simple neighbour array search. @@ -290,7 +278,7 @@ void Foam::meshToMesh::cellAddresses // the octree search to find it. if (boundaryCell[curCell]) { - cellAddressing_[toI] = oc.find(p); + cellAddressing_[toI] = oc.findInside(p); } else { @@ -342,7 +330,7 @@ void Foam::meshToMesh::cellAddresses if (!found) { // Still not found so us the octree - cellAddressing_[toI] = oc.find(p); + cellAddressing_[toI] = oc.findInside(p); } } } diff --git a/src/sampling/meshToMeshInterpolation/meshToMesh/meshToMesh.H b/src/sampling/meshToMeshInterpolation/meshToMesh/meshToMesh.H index 1edd13866ce..a3e83a73e9b 100644 --- a/src/sampling/meshToMeshInterpolation/meshToMesh/meshToMesh.H +++ b/src/sampling/meshToMeshInterpolation/meshToMesh/meshToMesh.H @@ -50,9 +50,9 @@ namespace Foam { template<class Type> -class octree; +class indexedOctree; -class octreeDataCell; +class treeDataCell; /*---------------------------------------------------------------------------*\ Class meshToMesh Declaration @@ -99,7 +99,7 @@ class meshToMesh const pointField& points, const fvMesh& fromMesh, const List<bool>& boundaryCell, - const octree<octreeDataCell>& oc + const indexedOctree<treeDataCell>& oc ) const; void calculateInverseDistanceWeights() const; diff --git a/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C b/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C index fc5c31911e8..b117a4b2916 100644 --- a/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C +++ b/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C @@ -24,7 +24,6 @@ License \*---------------------------------------------------------------------------*/ #include "sampledTriSurfaceMesh.H" -#include "treeDataPoint.H" #include "meshSearch.H" #include "Tuple2.H" #include "globalIndex.H" diff --git a/tutorials/combustion/dieselFoam/aachenBomb/constant/sprayProperties b/tutorials/combustion/dieselFoam/aachenBomb/constant/sprayProperties index de0933465ba..878439295f1 100644 --- a/tutorials/combustion/dieselFoam/aachenBomb/constant/sprayProperties +++ b/tutorials/combustion/dieselFoam/aachenBomb/constant/sprayProperties @@ -17,7 +17,7 @@ FoamFile interpolationSchemes { - U cellPointFace; + U cellPoint; rho cell; p cell; T cell; diff --git a/tutorials/heatTransfer/buoyantBoussinesqSimpleFoam/iglooWithFridges/system/snappyHexMeshDict b/tutorials/heatTransfer/buoyantBoussinesqSimpleFoam/iglooWithFridges/system/snappyHexMeshDict index 75432f06b99..6f099592107 100644 --- a/tutorials/heatTransfer/buoyantBoussinesqSimpleFoam/iglooWithFridges/system/snappyHexMeshDict +++ b/tutorials/heatTransfer/buoyantBoussinesqSimpleFoam/iglooWithFridges/system/snappyHexMeshDict @@ -358,11 +358,14 @@ meshQualityControls // Set to very negative number (e.g. -1E30) to disable. minVol 1e-13; - //- Minimum tet volume. Is absolute volume of the tet formed by the - // face-centre decomposition triangle and the cell centre. - // Set to a sensible fraction of the smallest cell volume expected. - // Set to very negative number (e.g. -1E30) to disable. - minTetVol 1e-20; + //- Minimum quality of the tet formed by the face-centre + // and variable base point minimum decomposition triangles and + // the cell centre. Set to very negative number (e.g. -1E30) to + // disable. + // <0 = inside out tet, + // 0 = flat tet + // 1 = regular tet + minTetQuality 1e-9; //- Minimum face area. Set to <0 to disable. minArea -1; diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/snappyHexMeshDict b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/snappyHexMeshDict index 1cc6ba8dbae..f86acc42264 100644 --- a/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/snappyHexMeshDict +++ b/tutorials/heatTransfer/chtMultiRegionFoam/snappyMultiRegionHeater/system/snappyHexMeshDict @@ -340,11 +340,14 @@ meshQualityControls // Set to very negative number (e.g. -1E30) to disable. minVol 0; - //- Minimum tet volume. Is absolute volume of the tet formed by the - // face-centre decomposition triangle and the cell centre. - // Set to a sensible fraction of the smallest cell volume expected. - // Set to very negative number (e.g. -1E30) to disable. - minTetVol 1e-20; + //- Minimum quality of the tet formed by the face-centre + // and variable base point minimum decomposition triangles and + // the cell centre. Set to very negative number (e.g. -1E30) to + // disable. + // <0 = inside out tet, + // 0 = flat tet + // 1 = regular tet + minTetQuality 1e-9; //- Minimum face area. Set to <0 to disable. minArea -1; diff --git a/tutorials/incompressible/pimpleDyMFoam/wingMotion/wingMotion_snappyHexMesh/system/snappyHexMeshDict b/tutorials/incompressible/pimpleDyMFoam/wingMotion/wingMotion_snappyHexMesh/system/snappyHexMeshDict index 37b684ec9ab..78068461c3e 100644 --- a/tutorials/incompressible/pimpleDyMFoam/wingMotion/wingMotion_snappyHexMesh/system/snappyHexMeshDict +++ b/tutorials/incompressible/pimpleDyMFoam/wingMotion/wingMotion_snappyHexMesh/system/snappyHexMeshDict @@ -272,11 +272,14 @@ meshQualityControls // Set to very negative number (e.g. -1E30) to disable. minVol 1e-13; - //- Minimum tet volume. Is absolute volume of the tet formed by the - // face-centre decomposition triangle and the cell centre. - // Set to a sensible fraction of the smallest cell volume expected. - // Set to very negative number (e.g. -1E30) to disable. - minTetVol 1e-20; + //- Minimum quality of the tet formed by the face-centre + // and variable base point minimum decomposition triangles and + // the cell centre. Set to very negative number (e.g. -1E30) to + // disable. + // <0 = inside out tet, + // 0 = flat tet + // 1 = regular tet + minTetQuality 1e-9; //- Minimum face area. Set to <0 to disable. minArea -1; diff --git a/tutorials/incompressible/simpleFoam/motorBike/system/snappyHexMeshDict b/tutorials/incompressible/simpleFoam/motorBike/system/snappyHexMeshDict index 2cf5bad3999..de5c2a8aa77 100644 --- a/tutorials/incompressible/simpleFoam/motorBike/system/snappyHexMeshDict +++ b/tutorials/incompressible/simpleFoam/motorBike/system/snappyHexMeshDict @@ -551,11 +551,14 @@ meshQualityControls // Set to very negative number (e.g. -1E30) to disable. minVol 1e-13; - //- Minimum tet volume. Is absolute volume of the tet formed by the - // face-centre decomposition triangle and the cell centre. - // Set to a sensible fraction of the smallest cell volume expected. - // Set to very negative number (e.g. -1E30) to disable. - minTetVol 1e-20; + //- Minimum quality of the tet formed by the face-centre + // and variable base point minimum decomposition triangles and + // the cell centre. Set to very negative number (e.g. -1E30) to + // disable. + // <0 = inside out tet, + // 0 = flat tet + // 1 = regular tet + minTetQuality 1e-9; //- Minimum face area. Set to <0 to disable. minArea -1; diff --git a/tutorials/incompressible/simpleFoam/windTurbineTerrain/system/snappyHexMeshDict b/tutorials/incompressible/simpleFoam/windTurbineTerrain/system/snappyHexMeshDict index d32abbb74bc..7b7a4e57142 100644 --- a/tutorials/incompressible/simpleFoam/windTurbineTerrain/system/snappyHexMeshDict +++ b/tutorials/incompressible/simpleFoam/windTurbineTerrain/system/snappyHexMeshDict @@ -362,11 +362,14 @@ meshQualityControls // Set to very negative number (e.g. -1E30) to disable. minVol 1e-13; - //- Minimum tet volume. Is absolute volume of the tet formed by the - // face-centre decomposition triangle and the cell centre. - // Set to a sensible fraction of the smallest cell volume expected. - // Set to very negative number (e.g. -1E30) to disable. - minTetVol 1e-20; + //- Minimum quality of the tet formed by the face-centre + // and variable base point minimum decomposition triangles and + // the cell centre. Set to very negative number (e.g. -1E30) to + // disable. + // <0 = inside out tet, + // 0 = flat tet + // 1 = regular tet + minTetQuality 1e-9; //- Minimum face area. Set to <0 to disable. minArea -1; diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/constant/coalCloud1Properties b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/constant/coalCloud1Properties index b7eb5e23a77..5624bb507b4 100644 --- a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/constant/coalCloud1Properties +++ b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/constant/coalCloud1Properties @@ -73,7 +73,7 @@ constantProperties interpolationSchemes { rho cell; - U cellPointFace; + U cellPoint; mu cell; T cell; Cp cell; diff --git a/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/filter/constant/reactingCloud1Properties b/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/filter/constant/reactingCloud1Properties index 1e7431118ee..4534388250f 100644 --- a/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/filter/constant/reactingCloud1Properties +++ b/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/filter/constant/reactingCloud1Properties @@ -74,7 +74,7 @@ constantProperties interpolationSchemes { rho cell; - U cellPointFace; + U cellPoint; mu cell; T cell; Cp cell; diff --git a/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/parcelInBox/constant/reactingCloud1Properties b/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/parcelInBox/constant/reactingCloud1Properties index b9e6be98a56..dc6f9aba8bd 100644 --- a/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/parcelInBox/constant/reactingCloud1Properties +++ b/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/parcelInBox/constant/reactingCloud1Properties @@ -73,7 +73,7 @@ constantProperties interpolationSchemes { rho cell; - U cellPointFace; + U cellPoint; mu cell; T cell; Cp cell; diff --git a/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/verticalChannel/constant/reactingCloud1Properties b/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/verticalChannel/constant/reactingCloud1Properties index f04e8560be7..44a046965f7 100644 --- a/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/verticalChannel/constant/reactingCloud1Properties +++ b/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/verticalChannel/constant/reactingCloud1Properties @@ -73,7 +73,7 @@ constantProperties interpolationSchemes { rho cell; - U cellPointFace; + U cellPoint; mu cell; T cell; Cp cell; diff --git a/tutorials/lagrangian/reactingParcelFilmFoam/evaporationTest/constant/reactingCloud1Properties b/tutorials/lagrangian/reactingParcelFilmFoam/evaporationTest/constant/reactingCloud1Properties index fc14437180b..3f3b7a8aac9 100644 --- a/tutorials/lagrangian/reactingParcelFilmFoam/evaporationTest/constant/reactingCloud1Properties +++ b/tutorials/lagrangian/reactingParcelFilmFoam/evaporationTest/constant/reactingCloud1Properties @@ -67,7 +67,7 @@ constantProperties interpolationSchemes { rho cell; - U cell; // cellPointFace; + U cell; // cellPoint; mu cell; T cell; Cp cell; diff --git a/tutorials/lagrangian/reactingParcelFilmFoam/hotBoxes/constant/reactingCloud1Properties b/tutorials/lagrangian/reactingParcelFilmFoam/hotBoxes/constant/reactingCloud1Properties index ce8c2019aac..072f100d499 100644 --- a/tutorials/lagrangian/reactingParcelFilmFoam/hotBoxes/constant/reactingCloud1Properties +++ b/tutorials/lagrangian/reactingParcelFilmFoam/hotBoxes/constant/reactingCloud1Properties @@ -67,7 +67,7 @@ constantProperties interpolationSchemes { rho cell; - U cell; // cellPointFace; + U cell; // cellPoint; mu cell; T cell; Cp cell; diff --git a/tutorials/lagrangian/reactingParcelFilmFoam/multipleBoxes/constant/reactingCloud1Properties b/tutorials/lagrangian/reactingParcelFilmFoam/multipleBoxes/constant/reactingCloud1Properties index a148c74674b..51f281bdad5 100644 --- a/tutorials/lagrangian/reactingParcelFilmFoam/multipleBoxes/constant/reactingCloud1Properties +++ b/tutorials/lagrangian/reactingParcelFilmFoam/multipleBoxes/constant/reactingCloud1Properties @@ -67,7 +67,7 @@ constantProperties interpolationSchemes { rho cell; - U cell; // cellPointFace; + U cell; // cellPoint; mu cell; T cell; Cp cell; diff --git a/tutorials/lagrangian/reactingParcelFilmFoam/panel/constant/reactingCloud1Properties b/tutorials/lagrangian/reactingParcelFilmFoam/panel/constant/reactingCloud1Properties index 27a63e876a1..73494b022da 100644 --- a/tutorials/lagrangian/reactingParcelFilmFoam/panel/constant/reactingCloud1Properties +++ b/tutorials/lagrangian/reactingParcelFilmFoam/panel/constant/reactingCloud1Properties @@ -67,7 +67,7 @@ constantProperties interpolationSchemes { rho cell; - U cell; // cellPointFace; + U cell; // cellPoint; mu cell; T cell; Cp cell; diff --git a/tutorials/lagrangian/reactingParcelFoam/evaporationTest/constant/reactingCloud1Properties b/tutorials/lagrangian/reactingParcelFoam/evaporationTest/constant/reactingCloud1Properties index 49e1a85b97c..ca70790376d 100644 --- a/tutorials/lagrangian/reactingParcelFoam/evaporationTest/constant/reactingCloud1Properties +++ b/tutorials/lagrangian/reactingParcelFoam/evaporationTest/constant/reactingCloud1Properties @@ -67,7 +67,7 @@ constantProperties interpolationSchemes { rho cell; - U cellPointFace; + U cellPoint; mu cell; T cell; Cp cell; diff --git a/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/0.org/pointDisplacement b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/0.org/pointDisplacement new file mode 100644 index 00000000000..d2b845620a5 --- /dev/null +++ b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/0.org/pointDisplacement @@ -0,0 +1,88 @@ +/*--------------------------------*- 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 pointVectorField; + location "0.01"; + object pointDisplacement; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 0 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + stationaryWalls + { + type fixedValue; + value uniform (0 0 0); + } + movingBlock + { + type uncoupledSixDoFRigidBodyDisplacement; + centreOfMass (0.5 0.5 0.5); + momentOfInertia (0.1052 0.1052 0.1778); + mass 9.6; + velocity (0 0 0); + orientation (1 0 0 0 1 0 0 0 1); + acceleration (0 0 0); + angularMomentum (0 0 0); + torque (0 0 0); + gravity (0 0 0); + rhoInf 1; + report on; + restraints + { + topSpring + { + sixDoFRigidBodyMotionRestraint linearSpring; + + linearSpringCoeffs + { + anchor (0.5 0.5 1); + refAttachmentPt $centreOfMass; + stiffness 5000; + damping 50; + restLength 0.4; + } + } + } + constraints + { + maxIterations 500; + + fixedAxes1 + { + sixDoFRigidBodyMotionConstraint fixedOrientation; + tolerance 1e-6; + relaxationFactor 1.0; + fixedOrientationCoeffs {} + } + + fixedLine1 + { + sixDoFRigidBodyMotionConstraint fixedLine; + tolerance 1e-6; + relaxationFactor 1.0; + fixedLineCoeffs + { + refPoint $centreOfMass; + direction (0 0 1); + } + } + } + value uniform (0 0 0); + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/Allclean b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/Allclean new file mode 100755 index 00000000000..b134761b231 --- /dev/null +++ b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/Allclean @@ -0,0 +1,11 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # run from this directory + +# Source tutorial clean functions +. $WM_PROJECT_DIR/bin/tools/CleanFunctions + +rm -rf 0 t_vs_cm t_vs_lv shm.eps > /dev/null 2>&1 + +cleanCase + +# ----------------------------------------------------------------- end-of-file diff --git a/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/Allrun b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/Allrun new file mode 100755 index 00000000000..f7afb77a5ba --- /dev/null +++ b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/Allrun @@ -0,0 +1,19 @@ +#!/bin/sh + +cd ${0%/*} || exit 1 # run from this directory + +# Source tutorial run functions +. $WM_PROJECT_DIR/bin/tools/RunFunctions + +# Set application name +application="moveDynamicMesh" + +runApplication blockMesh +runApplication topoSet +runApplication subsetMesh -overwrite c0 -patch movingBlock +cp -r 0.org 0 > /dev/null 2>&1 +runApplication $application +./extractData log.$application +gnuplot shm.gnuplot + +# ----------------------------------------------------------------- end-of-file diff --git a/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/constant/dynamicMeshDict b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/constant/dynamicMeshDict new file mode 100644 index 00000000000..329480c68d6 --- /dev/null +++ b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/constant/dynamicMeshDict @@ -0,0 +1,26 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: http://www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object motionProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dynamicFvMesh dynamicMotionSolverFvMesh; + +motionSolverLibs ("libfvMotionSolvers.so"); + +solver displacementLaplacian; + +diffusivity inverseDistance (movingBlock); + + +// ************************************************************************* // diff --git a/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/constant/polyMesh/blockMeshDict b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/constant/polyMesh/blockMeshDict new file mode 100644 index 00000000000..c2ae0e3bfe8 --- /dev/null +++ b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/constant/polyMesh/blockMeshDict @@ -0,0 +1,59 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: http://www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +convertToMeters 1; + +vertices +( + (0 0 0) + (1 0 0) + (1 1 0) + (0 1 0) + (0 0 1) + (1 0 1) + (1 1 1) + (0 1 1) +); + +blocks +( + hex (0 1 2 3 4 5 6 7) (9 9 14) simpleGrading (1 1 1) +); + +edges +( +); + +patches +( + patch stationaryWalls + ( + (0 3 2 1) + (2 6 5 1) + (1 5 4 0) + (3 7 6 2) + (0 4 7 3) + (4 5 6 7) + ) + patch movingBlock + () +); + +mergePatchPairs +( +); + +// ************************************************************************* // diff --git a/tutorials/discreteMethods/molecularDynamics/mdEquilibrationFoam/periodicCubeWater/0/U b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/constant/polyMesh/boundary similarity index 71% rename from tutorials/discreteMethods/molecularDynamics/mdEquilibrationFoam/periodicCubeWater/0/U rename to tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/constant/polyMesh/boundary index c7bc8234a29..eef245f9f4c 100644 --- a/tutorials/discreteMethods/molecularDynamics/mdEquilibrationFoam/periodicCubeWater/0/U +++ b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/constant/polyMesh/boundary @@ -9,29 +9,26 @@ FoamFile { version 2.0; format ascii; - class volVectorField; - object U; + class polyBoundaryMesh; + location "constant/polyMesh"; + object boundary; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -dimensions [0 1 -1 0 0 0 0]; - -internalField uniform (0 0 0); - -boundaryField -{ - periodicX +2 +( + stationaryWalls { - type cyclic; + type wall; + nFaces 666; + startFace 2994; } - periodicY + movingBlock { - type cyclic; + type patch; + nFaces 42; + startFace 3660; } - periodicZ - { - type cyclic; - } -} +) // ************************************************************************* // diff --git a/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/extractData b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/extractData new file mode 100755 index 00000000000..784f45c5fc5 --- /dev/null +++ b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/extractData @@ -0,0 +1,42 @@ +#!/bin/sh +#------------------------------------------------------------------------------ +# ========= | +# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox +# \\ / O peration | +# \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. +# \\/ M anipulation | +#------------------------------------------------------------------------------- +# License +# This file is part of OpenFOAM. +# +# OpenFOAM is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 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/>. +# +# Script +# extractData +# +# Description +# Extracts motion data from a simple harmonic motion dynamicMesh case +# +#------------------------------------------------------------------------------ + +grep "Centre of mass" $1 | cut -d ":" -f 2 | cut -d " " -f 4 | tr -d ")" > cM +grep "Linear velocity" $1 | cut -d ":" -f 2 | cut -d " " -f 4 | tr -d ")" > lV +grep -e "^Time = " $1 | cut -d " " -f 3 > times + +paste times cM > t_vs_cm +paste times lV > t_vs_lv + +rm cM lV times + +#------------------------------------------------------------------------------ \ No newline at end of file diff --git a/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/shm.gnuplot b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/shm.gnuplot new file mode 100644 index 00000000000..8027230526e --- /dev/null +++ b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/shm.gnuplot @@ -0,0 +1,76 @@ +#------------------------------------------------------------------------------ +# ========= | +# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox +# \\ / O peration | +# \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. +# \\/ M anipulation | +#------------------------------------------------------------------------------- +# License +# This file is part of OpenFOAM. +# +# OpenFOAM is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 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/>. +# +# Script +# shm.gnuplot +# +# Description +# Creates an .eps graph of OpenFOAM results vs analytical solution +# for a simple harmonic motion dynamicMesh case +# +#------------------------------------------------------------------------------ + +reset + +set samples 2000 + +k = 5000.0 +m = 9.6 +c = 50.0 +a = -0.1 + +omega = sqrt(k/m) +zeta = c/(2.0*m*omega) + +phi = atan((sqrt(1.0 - zeta**2))/zeta) +A = a/sin(phi) + +pos(A, t, omega, phi, zeta) = A*exp(-zeta*omega*t)*sin(sqrt(1-zeta**2)*omega*t + phi) +vel(A, t, omega, phi, zeta) = \ +A*exp(-zeta*omega*t)*\ +( \ + sqrt(1-zeta**2)*omega*cos(sqrt(1-zeta**2)*omega*t + phi) \ +- zeta*omega*sin(sqrt(1-zeta**2)*omega*t + phi) \ +) + +set xlabel "Time/[s]" +set ylabel "Position" + +set ytics nomirror +set y2tics + +set yrange [-0.1:0.1] +set y2range [-2:2] + +set xzeroaxis + +set terminal postscript eps color enhanced solid +set output "shm.eps" + +plot \ + "t_vs_cm" u 1:($2 - 0.6) w l t "Simulation, centre of mass relative to start", \ + pos(A, x, omega, phi, zeta) w l t "Analytical solution, centre of mass", \ + "t_vs_lv" u 1:2 w l axes x1y2 t "Simulation, vertical velocity", \ + vel(A, x, omega, phi, zeta) w l axes x1y2 t "Analytical solution, vertical velocity" + +#------------------------------------------------------------------------------ diff --git a/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/controlDict b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/controlDict new file mode 100644 index 00000000000..2d71827bb43 --- /dev/null +++ b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/controlDict @@ -0,0 +1,68 @@ +/*--------------------------------*- 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; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application interDyMFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 4; + +deltaT 0.002; + +writeControl adjustableRunTime; + +writeInterval 0.25; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 12; + +writeCompression uncompressed; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep yes; + +maxCo 0.2; + +maxDeltaT 0.025; + +libs +( + "libincompressibleRASModels.so" + "libforces.so" +); + + +// libs +// ( +// "libgenericPatchFields.so" +// "libincompressibleRASModels.so" +// "libforces.so" +// ); + +// ************************************************************************* // diff --git a/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/fvSchemes b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/fvSchemes new file mode 100644 index 00000000000..9b11d59f3d3 --- /dev/null +++ b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/fvSchemes @@ -0,0 +1,50 @@ +/*--------------------------------*- 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 fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ +} + +fluxRequired +{ +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/fvSolution b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/fvSolution new file mode 100644 index 00000000000..209b3b035f8 --- /dev/null +++ b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/fvSolution @@ -0,0 +1,34 @@ +/*--------------------------------*- 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 fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + cellDisplacement + { + solver GAMG; + tolerance 1e-06; + relTol 0; + smoother GaussSeidel; + cacheAgglomeration true; + nCellsInCoarsestLevel 10; + agglomerator faceAreaPair; + mergeLevels 1; + } +} + + +// ************************************************************************* // diff --git a/tutorials/discreteMethods/molecularDynamics/mdEquilibrationFoam/periodicCubeArgon/0/U b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/topoSetDict similarity index 72% rename from tutorials/discreteMethods/molecularDynamics/mdEquilibrationFoam/periodicCubeArgon/0/U rename to tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/topoSetDict index c7bc8234a29..91b2397d23b 100644 --- a/tutorials/discreteMethods/molecularDynamics/mdEquilibrationFoam/periodicCubeArgon/0/U +++ b/tutorials/mesh/moveDynamicMesh/simpleHarmonicMotion/system/topoSetDict @@ -9,29 +9,30 @@ FoamFile { version 2.0; format ascii; - class volVectorField; - object U; + class dictionary; + object topoSetDict; } -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -dimensions [0 1 -1 0 0 0 0]; -internalField uniform (0 0 0); +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -boundaryField -{ - periodicX +actions +( { - type cyclic; + name c0; + type cellSet; + action new; + source boxToCell; + sourceInfo + { + box (0.35 0.35 0.44) (0.65 0.65 0.56); + } } - periodicY - { - type cyclic; - } - periodicZ + { - type cyclic; + name c0; + type cellSet; + action invert; } -} +); // ************************************************************************* // diff --git a/tutorials/multiphase/interPhaseChangeFoam/cavitatingBullet/system/snappyHexMeshDict b/tutorials/multiphase/interPhaseChangeFoam/cavitatingBullet/system/snappyHexMeshDict index d2c7fee5e42..456bd93ea0d 100644 --- a/tutorials/multiphase/interPhaseChangeFoam/cavitatingBullet/system/snappyHexMeshDict +++ b/tutorials/multiphase/interPhaseChangeFoam/cavitatingBullet/system/snappyHexMeshDict @@ -292,11 +292,14 @@ meshQualityControls // Set to very negative number (e.g. -1E30) to disable. minVol 1e-20; - //- Minimum tet volume. Is absolute volume of the tet formed by the - // face-centre decomposition triangle and the cell centre. - // Set to a sensible fraction of the smallest cell volume expected. - // Set to very negative number (e.g. -1E30) to disable. - minTetVol 1e-20; + //- Minimum quality of the tet formed by the face-centre + // and variable base point minimum decomposition triangles and + // the cell centre. Set to very negative number (e.g. -1E30) to + // disable. + // <0 = inside out tet, + // 0 = flat tet + // 1 = regular tet + minTetQuality 1e-9; //- Minimum face area. Set to <0 to disable. minArea -1; -- GitLab