mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'feature-pointMeshIO-shm-bufferlayers' into 'develop'
ENH: snappyHexMesh: add buffer layers before snapping See merge request Development/openfoam!715
This commit is contained in:
11
applications/test/syncTools/missing_cell/Allclean
Executable file
11
applications/test/syncTools/missing_cell/Allclean
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
cd "${0%/*}" || exit # Run from this directory
|
||||
. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions # Tutorial clean functions
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
cleanCase
|
||||
|
||||
# Remove surface and features
|
||||
rm -rf constant/triSurface
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
27
applications/test/syncTools/missing_cell/Allrun
Executable file
27
applications/test/syncTools/missing_cell/Allrun
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
cd "${0%/*}" || exit # Run from this directory
|
||||
. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions # Tutorial run functions
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#- Generate 2x2x1 cells
|
||||
runApplication blockMesh
|
||||
|
||||
#- Remove cell0
|
||||
runApplication topoSet
|
||||
runApplication subsetMesh c0 -patch exposed0 -overwrite
|
||||
|
||||
#- Put exposed faces (2) into separate patches
|
||||
runApplication -s face topoSet
|
||||
runApplication createPatch -overwrite
|
||||
|
||||
#- Decompose - creates one processor without any faces in patches
|
||||
runApplication decomposePar
|
||||
|
||||
#- Extract inter-patch points. Should include processor that does not
|
||||
#- have faces on patch ...
|
||||
mkdir -p constant/triSurface
|
||||
runParallel surfaceMeshExtract \
|
||||
-patches '(exposed0 exposed1)' -featureAngle 180 \
|
||||
constant/triSurface/blockMesh.obj
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
7
applications/test/syncTools/missing_cell/README.txt
Normal file
7
applications/test/syncTools/missing_cell/README.txt
Normal file
@ -0,0 +1,7 @@
|
||||
- 2x2x1 mesh
|
||||
- remove one cell, exposing two faces
|
||||
- move exposed faces into two patches
|
||||
- decompose onto 3
|
||||
- run surfaceMeshExtract -featureAngle 180
|
||||
- should also mark points on the processor that has no
|
||||
faces but is coupled
|
||||
@ -0,0 +1,21 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
location "constant";
|
||||
object transportProperties;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
nu 0.01;
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,88 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
object blockMeshDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
scale 1;
|
||||
|
||||
vertices
|
||||
(
|
||||
//- Single block
|
||||
(0 0 0)
|
||||
(2 0 0)
|
||||
(2 2 0)
|
||||
(0 2 0)
|
||||
(0 0 2)
|
||||
(2 0 2)
|
||||
(2 2 2)
|
||||
(0 2 2)
|
||||
);
|
||||
|
||||
blocks
|
||||
(
|
||||
hex (0 1 2 3 4 5 6 7) (2 2 1) simpleGrading (1 1 1)
|
||||
);
|
||||
|
||||
edges
|
||||
(
|
||||
);
|
||||
|
||||
boundary
|
||||
(
|
||||
topWall
|
||||
{
|
||||
type wall;
|
||||
faces
|
||||
(
|
||||
(3 7 6 2)
|
||||
);
|
||||
}
|
||||
bottomWall
|
||||
{
|
||||
type wall;
|
||||
faces
|
||||
(
|
||||
(1 5 4 0)
|
||||
);
|
||||
}
|
||||
fixedWalls
|
||||
{
|
||||
type wall;
|
||||
faces
|
||||
(
|
||||
(0 4 7 3)
|
||||
(2 6 5 1)
|
||||
);
|
||||
}
|
||||
frontAndBack
|
||||
{
|
||||
type patch;
|
||||
faces
|
||||
(
|
||||
(0 3 2 1)
|
||||
(4 5 6 7)
|
||||
);
|
||||
}
|
||||
exposed0
|
||||
{
|
||||
type patch;
|
||||
faces ();
|
||||
}
|
||||
);
|
||||
|
||||
mergePatchPairs
|
||||
(
|
||||
);
|
||||
|
||||
// ************************************************************************* //
|
||||
48
applications/test/syncTools/missing_cell/system/controlDict
Normal file
48
applications/test/syncTools/missing_cell/system/controlDict
Normal file
@ -0,0 +1,48 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
location "system";
|
||||
object controlDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
application icoFoam;
|
||||
|
||||
startFrom startTime;
|
||||
|
||||
startTime 0;
|
||||
|
||||
stopAt endTime;
|
||||
|
||||
endTime 0.5;
|
||||
|
||||
deltaT 0.005;
|
||||
|
||||
writeControl timeStep;
|
||||
|
||||
writeInterval 20;
|
||||
|
||||
purgeWrite 0;
|
||||
|
||||
writeFormat ascii;
|
||||
|
||||
writePrecision 16;
|
||||
|
||||
writeCompression off;
|
||||
|
||||
timeFormat general;
|
||||
|
||||
timePrecision 6;
|
||||
|
||||
runTimeModifiable true;
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,44 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
object createPatchDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
pointSync false;
|
||||
|
||||
// Patches to create.
|
||||
patches
|
||||
(
|
||||
// Example of creating mapped patches using geometric matching
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
{
|
||||
// Name of new patch
|
||||
name exposed1;
|
||||
|
||||
// Dictionary to construct new patch from
|
||||
patchInfo
|
||||
{
|
||||
type patch;
|
||||
}
|
||||
|
||||
// How to select the faces:
|
||||
// - set : specify faceSet in 'set'
|
||||
// - patches : specify names in 'patches'
|
||||
// - autoPatch : attempts automatic patching of the specified
|
||||
// candidates in 'patches'.
|
||||
constructFrom set;
|
||||
set exposed0;
|
||||
}
|
||||
);
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,24 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
note "mesh decomposition control dictionary";
|
||||
object decomposeParDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
//- The total number of domains (mandatory)
|
||||
numberOfSubdomains 3;
|
||||
|
||||
//- The decomposition method (mandatory)
|
||||
method scotch;
|
||||
|
||||
// ************************************************************************* //
|
||||
51
applications/test/syncTools/missing_cell/system/fvSchemes
Normal file
51
applications/test/syncTools/missing_cell/system/fvSchemes
Normal file
@ -0,0 +1,51 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
location "system";
|
||||
object fvSchemes;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
ddtSchemes
|
||||
{
|
||||
default Euler;
|
||||
}
|
||||
|
||||
gradSchemes
|
||||
{
|
||||
default Gauss linear;
|
||||
grad(p) Gauss linear;
|
||||
}
|
||||
|
||||
divSchemes
|
||||
{
|
||||
default none;
|
||||
div(phi,U) Gauss linear;
|
||||
}
|
||||
|
||||
laplacianSchemes
|
||||
{
|
||||
default Gauss linear orthogonal;
|
||||
}
|
||||
|
||||
interpolationSchemes
|
||||
{
|
||||
default linear;
|
||||
}
|
||||
|
||||
snGradSchemes
|
||||
{
|
||||
default orthogonal;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
52
applications/test/syncTools/missing_cell/system/fvSolution
Normal file
52
applications/test/syncTools/missing_cell/system/fvSolution
Normal file
@ -0,0 +1,52 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
location "system";
|
||||
object fvSolution;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
solvers
|
||||
{
|
||||
p
|
||||
{
|
||||
solver PCG;
|
||||
preconditioner DIC;
|
||||
tolerance 1e-06;
|
||||
relTol 0.05;
|
||||
}
|
||||
|
||||
pFinal
|
||||
{
|
||||
$p;
|
||||
relTol 0;
|
||||
}
|
||||
|
||||
U
|
||||
{
|
||||
solver smoothSolver;
|
||||
smoother symGaussSeidel;
|
||||
tolerance 1e-05;
|
||||
relTol 0;
|
||||
}
|
||||
}
|
||||
|
||||
PISO
|
||||
{
|
||||
nCorrectors 2;
|
||||
nNonOrthogonalCorrectors 0;
|
||||
pRefCell 0;
|
||||
pRefValue 0;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
48
applications/test/syncTools/missing_cell/system/topoSetDict
Normal file
48
applications/test/syncTools/missing_cell/system/topoSetDict
Normal file
@ -0,0 +1,48 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
object topoSetDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
actions
|
||||
(
|
||||
{
|
||||
name c0;
|
||||
type cellSet;
|
||||
action new;
|
||||
source labelToCell;
|
||||
value (0);
|
||||
}
|
||||
{
|
||||
name c0;
|
||||
type cellSet;
|
||||
action invert;
|
||||
}
|
||||
|
||||
{
|
||||
name exposed0;
|
||||
type faceSet;
|
||||
action new;
|
||||
source patchToFace;
|
||||
patch exposed0;
|
||||
}
|
||||
{
|
||||
name exposed0;
|
||||
type faceSet;
|
||||
action subset;
|
||||
source boxToFace;
|
||||
box (-100 1 -100)(100 100 100);
|
||||
}
|
||||
);
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -99,21 +99,21 @@ label findPatchID(const polyBoundaryMesh& patches, const word& name)
|
||||
}
|
||||
|
||||
|
||||
labelList patchFaces(const polyBoundaryMesh& patches, const wordList& names)
|
||||
labelList patchFaces(const polyBoundaryMesh& patches, const wordRes& names)
|
||||
{
|
||||
const labelList patchIDs(patches.indices(names));
|
||||
|
||||
label n = 0;
|
||||
|
||||
forAll(names, i)
|
||||
for (label patchi : patchIDs)
|
||||
{
|
||||
const polyPatch& pp = patches[findPatchID(patches, names[i])];
|
||||
|
||||
n += pp.size();
|
||||
n += patches[patchi].size();
|
||||
}
|
||||
labelList faceLabels(n);
|
||||
n = 0;
|
||||
forAll(names, i)
|
||||
for (label patchi : patchIDs)
|
||||
{
|
||||
const polyPatch& pp = patches[findPatchID(patches, names[i])];
|
||||
const polyPatch& pp = patches[patchi];
|
||||
|
||||
forAll(pp, j)
|
||||
{
|
||||
@ -128,24 +128,25 @@ labelList patchFaces(const polyBoundaryMesh& patches, const wordList& names)
|
||||
void zoneFaces
|
||||
(
|
||||
const faceZoneMesh& fzs,
|
||||
const wordList& names,
|
||||
const wordRes& names,
|
||||
labelList& faceLabels,
|
||||
bitSet& faceFlip
|
||||
)
|
||||
{
|
||||
const labelList zoneIDs(fzs.indices(names));
|
||||
|
||||
label n = 0;
|
||||
|
||||
forAll(names, i)
|
||||
for (label zonei : zoneIDs)
|
||||
{
|
||||
const auto& pp = fzs[fzs.findZoneID(names[i])];
|
||||
n += pp.size();
|
||||
n += fzs[zonei].size();
|
||||
}
|
||||
faceLabels.setSize(n);
|
||||
faceFlip.setSize(n);
|
||||
n = 0;
|
||||
forAll(names, i)
|
||||
for (label zonei : zoneIDs)
|
||||
{
|
||||
const auto& pp = fzs[fzs.findZoneID(names[i])];
|
||||
const auto& pp = fzs[zonei];
|
||||
const boolList& ppFlip = pp.flipMap();
|
||||
forAll(pp, i)
|
||||
{
|
||||
@ -345,8 +346,8 @@ int main(int argc, char *argv[])
|
||||
sourceCaseDir =
|
||||
sourceCaseDir/("processor" + Foam::name(Pstream::myProcNo()));
|
||||
}
|
||||
wordList sourcePatches;
|
||||
wordList sourceFaceZones;
|
||||
wordRes sourcePatches;
|
||||
wordRes sourceFaceZones;
|
||||
if
|
||||
(
|
||||
dict.readIfPresent
|
||||
@ -868,13 +869,13 @@ int main(int argc, char *argv[])
|
||||
frontPatchFaces = patchFaces
|
||||
(
|
||||
meshFromSurface().boundaryMesh(),
|
||||
wordList(1, frontPatchName)
|
||||
wordRes(1, frontPatchName)
|
||||
);
|
||||
backPatchName = "otherSide";
|
||||
backPatchFaces = patchFaces
|
||||
(
|
||||
meshFromSurface().boundaryMesh(),
|
||||
wordList(1, backPatchName)
|
||||
wordRes(1, backPatchName)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -825,6 +825,17 @@ int main(int argc, char *argv[])
|
||||
#include "setSystemMeshDictionaryIO.H"
|
||||
const IOdictionary meshDict(dictIO);
|
||||
|
||||
// Overall mesh generation mode
|
||||
const meshRefinement::MeshType meshType
|
||||
(
|
||||
meshRefinement::MeshTypeNames.getOrDefault
|
||||
(
|
||||
"type",
|
||||
meshDict,
|
||||
meshRefinement::CASTELLATED
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// all surface geometry
|
||||
const dictionary& geometryDict =
|
||||
@ -1339,6 +1350,7 @@ int main(int argc, char *argv[])
|
||||
shells, // for volume (inside/outside) refinement
|
||||
limitShells, // limit of volume refinement
|
||||
labelList(), // initial faces to test
|
||||
meshType, // how to operate
|
||||
dryRun
|
||||
);
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -220,7 +220,7 @@ PtrList<FieldType> subsetFields
|
||||
const pointMesh& pMesh
|
||||
)
|
||||
{
|
||||
const fvMesh& baseMesh = subsetter.baseMesh();
|
||||
//const fvMesh& baseMesh = subsetter.baseMesh();
|
||||
|
||||
const UPtrList<const IOobject> fieldObjects
|
||||
(
|
||||
@ -247,8 +247,8 @@ PtrList<FieldType> subsetFields
|
||||
IOobject
|
||||
(
|
||||
io.name(),
|
||||
baseMesh.time().timeName(),
|
||||
baseMesh,
|
||||
pMesh.thisDb().time().timeName(),
|
||||
pMesh.thisDb(),
|
||||
IOobjectOption::MUST_READ,
|
||||
IOobjectOption::NO_WRITE,
|
||||
IOobjectOption::NO_REGISTER
|
||||
@ -382,6 +382,8 @@ int main(int argc, char *argv[])
|
||||
#include "createTime.H"
|
||||
|
||||
#include "createNamedMesh.H"
|
||||
// Make sure pointMesh gets constructed/read as well
|
||||
(void)pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
|
||||
|
||||
// arg[1] = word (cellSet) or wordRes (cellZone)
|
||||
// const word selectionName = args[1];
|
||||
@ -583,7 +585,7 @@ int main(int argc, char *argv[])
|
||||
// Read point fields and subset
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
const pointMesh& pMesh = pointMesh::New(mesh);
|
||||
const pointMesh& pMesh = pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
|
||||
|
||||
#undef createSubsetFields
|
||||
#define createSubsetFields(FieldType, Variable) \
|
||||
@ -663,6 +665,18 @@ int main(int argc, char *argv[])
|
||||
subsetter.subMesh().write();
|
||||
processorMeshes::removeFiles(subsetter.subMesh());
|
||||
|
||||
auto* subPointMeshPtr =
|
||||
subsetter.subMesh().thisDb().findObject<pointMesh>
|
||||
(
|
||||
pointMesh::typeName
|
||||
);
|
||||
if (subPointMeshPtr)
|
||||
{
|
||||
pointMesh& subPointMesh = const_cast<pointMesh&>(*subPointMeshPtr);
|
||||
subPointMesh.setInstance(subsetter.subMesh().facesInstance());
|
||||
subPointMesh.write();
|
||||
}
|
||||
|
||||
|
||||
// Volume fields
|
||||
for (const auto& fld : vScalarFlds) { fld.write(); }
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022,2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -666,6 +666,9 @@ int main(int argc, char *argv[])
|
||||
),
|
||||
decompDictFile
|
||||
);
|
||||
// Make sure pointMesh gets read as well
|
||||
(void)pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
|
||||
|
||||
|
||||
// Decompose the mesh
|
||||
if (!decomposeFieldsOnly)
|
||||
@ -785,6 +788,7 @@ int main(int argc, char *argv[])
|
||||
PtrList<labelIOList> cellProcAddressingList(mesh.nProcs());
|
||||
PtrList<labelIOList> boundaryProcAddressingList(mesh.nProcs());
|
||||
PtrList<labelIOList> pointProcAddressingList(mesh.nProcs());
|
||||
PtrList<labelIOList> pointBoundaryProcAddressingList(mesh.nProcs());
|
||||
|
||||
PtrList<fvFieldDecomposer> fieldDecomposerList(mesh.nProcs());
|
||||
PtrList<pointFieldDecomposer> pointFieldDecomposerList
|
||||
@ -869,7 +873,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Point fields
|
||||
// ~~~~~~~~~~~~
|
||||
const pointMesh& pMesh = pointMesh::New(mesh);
|
||||
|
||||
// Read decomposed pointMesh
|
||||
const pointMesh& pMesh =
|
||||
pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
|
||||
|
||||
pointFieldDecomposer::fieldsCache pointFieldCache;
|
||||
|
||||
@ -1138,7 +1145,34 @@ int main(int argc, char *argv[])
|
||||
pointProcAddressingList
|
||||
);
|
||||
|
||||
const pointMesh& procPMesh = pointMesh::New(procMesh);
|
||||
const pointMesh& procPMesh =
|
||||
pointMesh::New(procMesh, IOobject::READ_IF_PRESENT);
|
||||
|
||||
if (!pointBoundaryProcAddressingList.set(proci))
|
||||
{
|
||||
pointBoundaryProcAddressingList.set
|
||||
(
|
||||
proci,
|
||||
autoPtr<labelIOList>::New
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"boundaryProcAddressing",
|
||||
procMesh.facesInstance(),
|
||||
polyMesh::meshSubDir
|
||||
/pointMesh::meshSubDir,
|
||||
procPMesh.thisDb(),
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
),
|
||||
boundaryProcAddressing
|
||||
)
|
||||
);
|
||||
}
|
||||
const auto& pointBoundaryProcAddressing =
|
||||
pointBoundaryProcAddressingList[proci];
|
||||
|
||||
|
||||
if (!pointFieldDecomposerList.set(proci))
|
||||
{
|
||||
@ -1150,7 +1184,7 @@ int main(int argc, char *argv[])
|
||||
pMesh,
|
||||
procPMesh,
|
||||
pointProcAddressing,
|
||||
boundaryProcAddressing
|
||||
pointBoundaryProcAddressing
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -1162,6 +1196,12 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (times.size() == 1)
|
||||
{
|
||||
// Early deletion
|
||||
pointBoundaryProcAddressingList.set
|
||||
(
|
||||
proci,
|
||||
nullptr
|
||||
);
|
||||
pointProcAddressingList.set(proci, nullptr);
|
||||
pointFieldDecomposerList.set(proci, nullptr);
|
||||
}
|
||||
|
||||
@ -44,6 +44,12 @@ License
|
||||
#include "decompositionModel.H"
|
||||
#include "hexRef8Data.H"
|
||||
|
||||
// For handling pointMeshes with additional patches
|
||||
#include "pointMesh.H"
|
||||
#include "meshPointPatch.H"
|
||||
#include "processorPointPatch.H"
|
||||
#include "DynamicField.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::domainDecomposition::mark
|
||||
@ -740,6 +746,101 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
|
||||
|
||||
procMesh.write();
|
||||
|
||||
// Add pointMesh if it was available
|
||||
const auto* pMeshPtr =
|
||||
thisDb().cfindObject<pointMesh>(pointMesh::typeName);
|
||||
if (pMeshPtr)
|
||||
{
|
||||
const auto& pMesh = *pMeshPtr;
|
||||
const auto& pMeshBoundary = pMesh.boundary();
|
||||
|
||||
|
||||
// 1. Generate pointBoundaryMesh from polyBoundaryMesh (so ignoring
|
||||
// any additional patches
|
||||
const auto& procPointMesh = pointMesh::New(procMesh);
|
||||
|
||||
pointBoundaryMesh& procBoundary =
|
||||
const_cast<pointBoundaryMesh&>(procPointMesh.boundary());
|
||||
|
||||
|
||||
// 2. Explicitly add subsetted meshPointPatches
|
||||
forAll(pMeshBoundary, patchi)
|
||||
{
|
||||
const auto* mppPtr = isA<meshPointPatch>(pMeshBoundary[patchi]);
|
||||
if (mppPtr && (procBoundary.findPatchID(mppPtr->name()) == -1))
|
||||
{
|
||||
const auto& mpp = *mppPtr;
|
||||
|
||||
DynamicList<label> procMeshPoints(mpp.size());
|
||||
DynamicField<vector> procNormals(mpp.size());
|
||||
forAll(mpp.meshPoints(), i)
|
||||
{
|
||||
const label pointi = mpp.meshPoints()[i];
|
||||
const label procPointi = pointLookup[pointi];
|
||||
if (procPointi != -1)
|
||||
{
|
||||
procMeshPoints.append(procPointi);
|
||||
procNormals.append(mpp.pointNormals()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
procBoundary.push_back
|
||||
(
|
||||
new meshPointPatch
|
||||
(
|
||||
mpp.name(),
|
||||
procMeshPoints,
|
||||
procNormals,
|
||||
procBoundary.size(),
|
||||
procBoundary,
|
||||
meshPointPatch::typeName
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Shuffle new patches before any processor patches
|
||||
labelList oldToNew(procBoundary.size());
|
||||
label newPatchi = 0;
|
||||
forAll(procBoundary, patchi)
|
||||
{
|
||||
if (!isA<processorPointPatch>(procBoundary[patchi]))
|
||||
{
|
||||
oldToNew[patchi] = newPatchi;
|
||||
newPatchi++;
|
||||
}
|
||||
}
|
||||
|
||||
// decomposed-to-undecomposed patch numbering
|
||||
labelList boundaryProcAddressing(identity(newPatchi));
|
||||
boundaryProcAddressing.setSize(procBoundary.size(), -1);
|
||||
|
||||
forAll(procBoundary, patchi)
|
||||
{
|
||||
if (isA<processorPointPatch>(procBoundary[patchi]))
|
||||
{
|
||||
oldToNew[patchi] = newPatchi++;
|
||||
}
|
||||
}
|
||||
procBoundary.reorder(oldToNew, true);
|
||||
|
||||
// Write pointMesh/boundary
|
||||
procBoundary.write();
|
||||
|
||||
// Write pointMesh/boundaryProcAddressing
|
||||
IOobject ioAddr
|
||||
(
|
||||
"boundaryProcAddressing",
|
||||
procMesh.facesInstance(),
|
||||
polyMesh::meshSubDir/pointMesh::meshSubDir,
|
||||
procPointMesh.thisDb(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
);
|
||||
IOListRef<label>(ioAddr, boundaryProcAddressing).write();
|
||||
}
|
||||
|
||||
// Write points if pointsInstance differing from facesInstance
|
||||
if (facesInstancePointsPtr_)
|
||||
{
|
||||
|
||||
@ -427,24 +427,18 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
Info<< "Reconstructing point fields" << nl << endl;
|
||||
|
||||
const pointMesh& pMesh = pointMesh::New(mesh);
|
||||
PtrList<pointMesh> pMeshes(procMeshes.meshes().size());
|
||||
|
||||
forAll(pMeshes, proci)
|
||||
{
|
||||
pMeshes.set
|
||||
(
|
||||
proci,
|
||||
new pointMesh(procMeshes.meshes()[proci])
|
||||
);
|
||||
}
|
||||
const pointMesh& pMesh = pointMesh::New
|
||||
(
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT
|
||||
);
|
||||
|
||||
pointFieldReconstructor reconstructor
|
||||
(
|
||||
pMesh,
|
||||
pMeshes,
|
||||
procMeshes.pointMeshes(),
|
||||
procMeshes.pointProcAddressing(),
|
||||
procMeshes.boundaryProcAddressing()
|
||||
procMeshes.pointMeshBoundaryProcAddressing()
|
||||
);
|
||||
|
||||
reconstructor.reconstructAllFields(objects, selectedFields);
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
EXE_INC = \
|
||||
-I$(LIB_SRC)/surfMesh/lnInclude \
|
||||
-I$(LIB_SRC)/fileFormats/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-lsurfMesh \
|
||||
-lfileFormats \
|
||||
-lmeshTools
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -34,13 +34,39 @@ Description
|
||||
Extract patch or faceZone surfaces from a polyMesh.
|
||||
Depending on output surface format triangulates faces.
|
||||
|
||||
Region numbers on faces no guaranteed to be the same as the patch indices.
|
||||
Region numbers on faces not guaranteed to be the same as the patch indices.
|
||||
|
||||
Optionally only extracts named patches.
|
||||
|
||||
Optionally filters out points on faceZones, feature-edges and
|
||||
featurePoints and generates pointPatches
|
||||
for these - written to pointMesh/boundary.
|
||||
|
||||
If run in parallel, processor patches get filtered out by default and
|
||||
the mesh is merged (based on topology).
|
||||
|
||||
Usage
|
||||
\b surfaceMeshExtract [OPTION] \<surfacefile\>
|
||||
|
||||
Options:
|
||||
- \par -patches NAME | LIST
|
||||
Specify single patch or multiple patches (name or regex) to extract
|
||||
|
||||
- \par -faceZones NAME | LIST
|
||||
Specify single zone or multiple face zones (name or regex) to extract
|
||||
|
||||
- \par -exclude-patches NAME | LIST
|
||||
Exclude single or multiple patches (name or regex) from extraction
|
||||
|
||||
- \par -excludeProcPatches
|
||||
Exclude processor patches (default if parallel)
|
||||
|
||||
- \par -featureAngle \<angle\>
|
||||
Extract feature edges/points and put into separate point-patches
|
||||
|
||||
- \par -extractZonePoints
|
||||
Extract all face zone points and put into separate point-patches
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "MeshedSurface.H"
|
||||
@ -48,6 +74,7 @@ Description
|
||||
#include "argList.H"
|
||||
#include "Time.H"
|
||||
#include "polyMesh.H"
|
||||
#include "pointMesh.H"
|
||||
#include "emptyPolyPatch.H"
|
||||
#include "processorPolyPatch.H"
|
||||
#include "ListListOps.H"
|
||||
@ -56,11 +83,79 @@ Description
|
||||
#include "globalMeshData.H"
|
||||
#include "globalIndex.H"
|
||||
#include "timeSelector.H"
|
||||
#include "meshPointPatch.H"
|
||||
#include "unitConversion.H"
|
||||
#include "dummyTransform.H"
|
||||
#include "syncTools.H"
|
||||
#include "processorPointPatch.H"
|
||||
#include "pointMeshTools.H"
|
||||
#include "OBJstream.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
void writeOBJ
|
||||
(
|
||||
const fileName& path,
|
||||
const pointPatch& pp
|
||||
)
|
||||
{
|
||||
const meshPointPatch& ppp = refCast<const meshPointPatch>(pp);
|
||||
const polyMesh& mesh = ppp.boundaryMesh().mesh().mesh();
|
||||
|
||||
// Count constraints
|
||||
label maxConstraint = 0;
|
||||
const auto& constraints = ppp.constraints();
|
||||
forAll(constraints, i)
|
||||
{
|
||||
maxConstraint = max(maxConstraint, constraints[i].first());
|
||||
}
|
||||
reduce(maxConstraint, maxOp<label>());
|
||||
|
||||
const pointField localPoints(mesh.points(), ppp.meshPoints());
|
||||
|
||||
if (maxConstraint == 3)
|
||||
{
|
||||
OBJstream os
|
||||
(
|
||||
path
|
||||
/ ppp.name()+"_fixedPoints.obj"
|
||||
);
|
||||
os.write(localPoints);
|
||||
Info<< "Written pointPatch " << ppp.name() << " to " << os.name()
|
||||
<< endl;
|
||||
}
|
||||
else if (maxConstraint == 2)
|
||||
{
|
||||
OBJstream os
|
||||
(
|
||||
path
|
||||
/ ppp.name()+"_slidingPoints.obj"
|
||||
);
|
||||
forAll(localPoints, i)
|
||||
{
|
||||
os.write(localPoints[i], constraints[i].second());
|
||||
}
|
||||
Info<< "Written pointPatch " << ppp.name() << " to " << os.name()
|
||||
<< " as coordinates and normals"
|
||||
<< endl;
|
||||
}
|
||||
else if (maxConstraint == 1)
|
||||
{
|
||||
OBJstream os
|
||||
(
|
||||
path
|
||||
/ ppp.name()+"_surfacePoints.obj"
|
||||
);
|
||||
os.write(localPoints);
|
||||
Info<< "Written pointPatch " << ppp.name() << " to " << os.name()
|
||||
<< " as coordinates"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
labelList getSelectedPatches
|
||||
(
|
||||
const polyBoundaryMesh& patches,
|
||||
@ -107,6 +202,286 @@ labelList getSelectedPatches
|
||||
}
|
||||
|
||||
|
||||
label addMeshPointPatches
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const pointMesh& pMesh,
|
||||
|
||||
const uindirectPrimitivePatch& allBoundary,
|
||||
const labelUList& faceToZone,
|
||||
const surfZoneIdentifierList& surfZones,
|
||||
const labelList& faceZoneToCompactZone,
|
||||
|
||||
const scalar edgeFeatureAngle,
|
||||
const scalar pointFeatureAngle,
|
||||
const bool verbose = true,
|
||||
const bool writePoints = false
|
||||
)
|
||||
{
|
||||
const auto& pointBm = pMesh.boundary();
|
||||
const auto& fzs = mesh.faceZones();
|
||||
const label nPointPatches = pointBm.size();
|
||||
const pointField& points = mesh.points();
|
||||
|
||||
|
||||
// Feature edge(points) internal to a zone
|
||||
labelListList zoneToMeshPoints;
|
||||
List<pointConstraintList> zoneToConstraints;
|
||||
|
||||
// Feature edge(points) in between zones
|
||||
labelList twoZoneMeshPoints;
|
||||
pointConstraintList twoZoneConstraints;
|
||||
|
||||
// Feature points on > 2 zones
|
||||
labelList multiZoneMeshPoints;
|
||||
pointConstraintList multiZoneConstraints;
|
||||
|
||||
pointMeshTools::featurePointsEdges
|
||||
(
|
||||
mesh,
|
||||
allBoundary,
|
||||
// Per boundary face to zone
|
||||
faceToZone,
|
||||
// Number of zones
|
||||
surfZones.size(),
|
||||
edgeFeatureAngle,
|
||||
//const scalar pointFeatureAngle, //not yet done
|
||||
|
||||
// Feature edge(points) internal to a zone
|
||||
zoneToMeshPoints,
|
||||
zoneToConstraints,
|
||||
|
||||
// Feature edge(points) in between zones
|
||||
twoZoneMeshPoints,
|
||||
twoZoneConstraints,
|
||||
|
||||
// Feature points on > 2 zones
|
||||
multiZoneMeshPoints,
|
||||
multiZoneConstraints
|
||||
);
|
||||
|
||||
|
||||
// Add per-zone patches
|
||||
if (faceZoneToCompactZone.size())
|
||||
{
|
||||
// Calculate point normals consistent across whole patch
|
||||
const pointField pointNormals
|
||||
(
|
||||
PatchTools::pointNormals
|
||||
(
|
||||
mesh,
|
||||
allBoundary
|
||||
)
|
||||
);
|
||||
|
||||
forAll(faceZoneToCompactZone, zonei)
|
||||
{
|
||||
const label compacti = faceZoneToCompactZone[zonei];
|
||||
if (compacti != -1)
|
||||
{
|
||||
const word patchName(surfZones[compacti].name());
|
||||
|
||||
if (pointBm.findPatchID(patchName) == -1)
|
||||
{
|
||||
// Extract the points originating from the faceZone. Can
|
||||
// - re-call featurePointsEdges with 0 feature angle so
|
||||
// all points go into the feature edges
|
||||
// - mark using faceToZone the correct points
|
||||
// - or assume the whole faceZone was extracted:
|
||||
const uindirectPrimitivePatch fzPatch
|
||||
(
|
||||
UIndirectList<face>
|
||||
(
|
||||
mesh.faces(),
|
||||
fzs[zonei].addressing()
|
||||
),
|
||||
points
|
||||
);
|
||||
const auto& mp = fzPatch.meshPoints();
|
||||
|
||||
const vector nullVector(vector::uniform(0));
|
||||
|
||||
// Extract pointNormal (or 0) on all patch/connected points
|
||||
vectorField meshPointNormals(mesh.nPoints(), nullVector);
|
||||
for (const label pointi : mp)
|
||||
{
|
||||
const label allPointi =
|
||||
allBoundary.meshPointMap()[pointi];
|
||||
meshPointNormals[pointi] = pointNormals[allPointi];
|
||||
}
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh,
|
||||
meshPointNormals,
|
||||
maxMagSqrEqOp<vector>(),
|
||||
nullVector
|
||||
);
|
||||
|
||||
// Extract indices with non-zero pointNormal
|
||||
DynamicList<label> meshPoints(mp.size());
|
||||
forAll(meshPointNormals, pointi)
|
||||
{
|
||||
if (meshPointNormals[pointi] != nullVector)
|
||||
{
|
||||
meshPoints.append(pointi);
|
||||
}
|
||||
}
|
||||
|
||||
const_cast<pointBoundaryMesh&>(pointBm).push_back
|
||||
(
|
||||
new meshPointPatch
|
||||
(
|
||||
patchName,
|
||||
meshPoints,
|
||||
vectorField(meshPointNormals, meshPoints),
|
||||
pointBm.size(),
|
||||
pointBm,
|
||||
meshPointPatch::typeName
|
||||
)
|
||||
);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
const auto& ppp = pointBm.last();
|
||||
Info<< "Added zone pointPatch " << ppp.name()
|
||||
<< " with "
|
||||
<< returnReduce(meshPoints.size(), sumOp<label>())
|
||||
<< " points" << endl;
|
||||
}
|
||||
if (writePoints)
|
||||
{
|
||||
writeOBJ(mesh.path(), pointBm.last());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add per-patch feature-edges
|
||||
forAll(zoneToMeshPoints, zonei)
|
||||
{
|
||||
const label nPoints =
|
||||
returnReduce(zoneToMeshPoints[zonei].size(), sumOp<label>());
|
||||
|
||||
const word patchName(surfZones[zonei].name() + "Edges");
|
||||
|
||||
if (nPoints && (pointBm.findPatchID(patchName) == -1))
|
||||
{
|
||||
const_cast<pointBoundaryMesh&>(pointBm).push_back
|
||||
(
|
||||
new meshPointPatch
|
||||
(
|
||||
patchName,
|
||||
zoneToMeshPoints[zonei],
|
||||
zoneToConstraints[zonei],
|
||||
pointBm.size(),
|
||||
pointBm,
|
||||
meshPointPatch::typeName
|
||||
)
|
||||
);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
const auto& ppp = pointBm.last();
|
||||
Info<< "Added feature-edges pointPatch " << ppp.name()
|
||||
<< " with " << nPoints << " points" << endl;
|
||||
}
|
||||
if (writePoints)
|
||||
{
|
||||
writeOBJ(mesh.path(), pointBm.last());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add inter-patch points
|
||||
|
||||
const word allEdgePatchName("boundaryEdges");
|
||||
const label nPatchEdgePoints =
|
||||
returnReduce(twoZoneMeshPoints.size(), sumOp<label>());
|
||||
if (nPatchEdgePoints && (pointBm.findPatchID(allEdgePatchName) == -1))
|
||||
{
|
||||
const_cast<pointBoundaryMesh&>(pointBm).push_back
|
||||
(
|
||||
new meshPointPatch
|
||||
(
|
||||
allEdgePatchName,
|
||||
twoZoneMeshPoints,
|
||||
twoZoneConstraints,
|
||||
pointBm.size(),
|
||||
pointBm,
|
||||
meshPointPatch::typeName
|
||||
)
|
||||
);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
const auto& ppp = pointBm.last();
|
||||
Info<< "Added inter-patch pointPatch " << ppp.name()
|
||||
<< " with " << nPatchEdgePoints << " points" << endl;
|
||||
}
|
||||
if (writePoints)
|
||||
{
|
||||
writeOBJ(mesh.path(), pointBm.last());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const word allPointPatchName("boundaryPoints");
|
||||
const label nMultiPoints =
|
||||
returnReduce(multiZoneMeshPoints.size(), sumOp<label>());
|
||||
if (nMultiPoints && (pointBm.findPatchID(allPointPatchName) == -1))
|
||||
{
|
||||
const_cast<pointBoundaryMesh&>(pointBm).push_back
|
||||
(
|
||||
new meshPointPatch
|
||||
(
|
||||
allPointPatchName,
|
||||
multiZoneMeshPoints,
|
||||
multiZoneConstraints,
|
||||
pointBm.size(),
|
||||
pointBm,
|
||||
meshPointPatch::typeName
|
||||
)
|
||||
);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
const auto& ppp = pointBm.last();
|
||||
Info<< "Added multi-patch pointPatch " << ppp.name()
|
||||
<< " with " << nMultiPoints << " points" << endl;
|
||||
}
|
||||
if (writePoints)
|
||||
{
|
||||
writeOBJ(mesh.path(), pointBm.last());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Shuffle into order
|
||||
labelList oldToNew(pointBm.size());
|
||||
label newPatchi = 0;
|
||||
forAll(pointBm, patchi)
|
||||
{
|
||||
if (!isA<processorPointPatch>(pointBm[patchi]))
|
||||
{
|
||||
oldToNew[patchi] = newPatchi++;
|
||||
}
|
||||
}
|
||||
forAll(pointBm, patchi)
|
||||
{
|
||||
if (isA<processorPointPatch>(pointBm[patchi]))
|
||||
{
|
||||
oldToNew[patchi] = newPatchi++;
|
||||
}
|
||||
}
|
||||
const_cast<pointBoundaryMesh&>(pointBm).reorder(oldToNew, true);
|
||||
|
||||
return pointBm.size() - nPointPatches;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@ -114,8 +489,6 @@ int main(int argc, char *argv[])
|
||||
argList::addNote
|
||||
(
|
||||
"Extract patch or faceZone surfaces from a polyMesh."
|
||||
" The name is historical, it only triangulates faces"
|
||||
" when the output format requires it."
|
||||
);
|
||||
timeSelector::addOptions();
|
||||
|
||||
@ -153,6 +526,22 @@ int main(int argc, char *argv[])
|
||||
true // mark as an advanced option
|
||||
);
|
||||
argList::addOptionCompat("exclude-patches", {"excludePatches", 2306});
|
||||
argList::addOption
|
||||
(
|
||||
"featureAngle",
|
||||
"angle",
|
||||
"Auto-extract feature edges/points and put into separate point-patches"
|
||||
);
|
||||
argList::addBoolOption
|
||||
(
|
||||
"extractZonePoints",
|
||||
"Extract point-patches for selected faceZones"
|
||||
);
|
||||
argList::addBoolOption
|
||||
(
|
||||
"writeOBJ",
|
||||
"Write added pointPatch points to .obj files"
|
||||
);
|
||||
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
@ -200,9 +589,37 @@ int main(int argc, char *argv[])
|
||||
<< nl << endl;
|
||||
}
|
||||
|
||||
scalar featureAngle = 180.0;
|
||||
const bool specifiedFeature = args.readIfPresent
|
||||
(
|
||||
"featureAngle",
|
||||
featureAngle
|
||||
);
|
||||
|
||||
const bool extractZonePoints = args.found("extractZonePoints");
|
||||
const bool writeOBJ = args.found("writeOBJ");
|
||||
|
||||
Info<< "Reading mesh from time " << runTime.value() << endl;
|
||||
|
||||
#include "createNamedPolyMesh.H"
|
||||
if (specifiedFeature)
|
||||
{
|
||||
Info<< "Detecting all sharp (>" << featureAngle
|
||||
<< " degrees) patch edges." << nl << endl;
|
||||
|
||||
if (extractZonePoints)
|
||||
{
|
||||
Info<< "Extracting all faceZone points as pointPatches."
|
||||
<< nl << endl;
|
||||
}
|
||||
|
||||
//#include "createNamedPointMesh.H"
|
||||
// Do not read constant/pointMesh - construct from polyMesh only
|
||||
Info<< "Create pointMesh for time = "
|
||||
<< runTime.timeName() << Foam::nl << Foam::endl;
|
||||
(void)pointMesh::New(mesh);
|
||||
}
|
||||
|
||||
|
||||
// User specified times
|
||||
instantList timeDirs = timeSelector::select0(runTime, args);
|
||||
@ -249,7 +666,7 @@ int main(int argc, char *argv[])
|
||||
// Construct table of patches to include.
|
||||
const polyBoundaryMesh& bMesh = mesh.boundaryMesh();
|
||||
|
||||
labelList patchIds =
|
||||
const labelList patchIds =
|
||||
(
|
||||
(includePatches.size() || excludePatches.size())
|
||||
? getSelectedPatches(bMesh, includePatches, excludePatches)
|
||||
@ -276,7 +693,13 @@ int main(int argc, char *argv[])
|
||||
// Mesh face and compact zone indx
|
||||
DynamicList<label> faceLabels;
|
||||
DynamicList<label> compactZones;
|
||||
// Per compact 'zone' index the name and location
|
||||
surfZoneIdentifierList surfZones;
|
||||
|
||||
// Per local patch to compact 'zone' index (or -1)
|
||||
labelList patchToCompactZone(bMesh.size(), -1);
|
||||
// Per local faceZone to compact 'zone' index (or -1)
|
||||
labelList faceZoneToCompactZone(bMesh.size(), -1);
|
||||
{
|
||||
// Collect sizes. Hash on names to handle local-only patches (e.g.
|
||||
// processor patches)
|
||||
@ -317,9 +740,18 @@ int main(int argc, char *argv[])
|
||||
Pstream::broadcast(compactZoneID);
|
||||
|
||||
|
||||
// Zones
|
||||
surfZones.resize_nocopy(compactZoneID.size());
|
||||
forAllConstIters(compactZoneID, iter)
|
||||
{
|
||||
surfZones[*iter] = surfZoneIdentifier(iter.key(), *iter);
|
||||
Info<< "surfZone " << *iter
|
||||
<< " : " << surfZones[*iter].name()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
// Rework HashTable into labelList just for speed of conversion
|
||||
labelList patchToCompactZone(bMesh.size(), -1);
|
||||
labelList faceZoneToCompactZone(bMesh.size(), -1);
|
||||
forAllConstIters(compactZoneID, iter)
|
||||
{
|
||||
label patchi = bMesh.findPatchID(iter.key());
|
||||
@ -362,7 +794,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
|
||||
// Addressing engine for all faces
|
||||
uindirectPrimitivePatch allBoundary
|
||||
const uindirectPrimitivePatch allBoundary
|
||||
(
|
||||
UIndirectList<face>(mesh.faces(), faceLabels),
|
||||
mesh.points()
|
||||
@ -400,7 +832,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Gather all ZoneIDs
|
||||
List<labelList> gatheredZones(Pstream::nProcs());
|
||||
gatheredZones[Pstream::myProcNo()].transfer(compactZones);
|
||||
gatheredZones[Pstream::myProcNo()] = compactZones;
|
||||
Pstream::gatherList(gatheredZones);
|
||||
|
||||
// On master combine all points, faces, zones
|
||||
@ -428,16 +860,6 @@ int main(int argc, char *argv[])
|
||||
gatheredZones.clear();
|
||||
|
||||
|
||||
// Zones
|
||||
surfZoneIdentifierList surfZones(compactZoneID.size());
|
||||
forAllConstIters(compactZoneID, iter)
|
||||
{
|
||||
surfZones[*iter] = surfZoneIdentifier(iter.key(), *iter);
|
||||
Info<< "surfZone " << *iter
|
||||
<< " : " << surfZones[*iter].name()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
UnsortedMeshedSurface<face> unsortedFace
|
||||
(
|
||||
std::move(allPoints),
|
||||
@ -464,6 +886,39 @@ int main(int argc, char *argv[])
|
||||
|
||||
sortedFace.write(globalCasePath);
|
||||
}
|
||||
|
||||
|
||||
if (specifiedFeature)
|
||||
{
|
||||
// Add edge patches
|
||||
const auto& pMesh = pointMesh::New(mesh);
|
||||
|
||||
const label nAdded = addMeshPointPatches
|
||||
(
|
||||
mesh,
|
||||
pMesh,
|
||||
|
||||
allBoundary, // all patches together
|
||||
compactZones, // originating compactZone
|
||||
surfZones, // per compactZone the index
|
||||
(
|
||||
extractZonePoints
|
||||
? faceZoneToCompactZone // per faceZone the compactZone
|
||||
: labelList::null()
|
||||
),
|
||||
|
||||
featureAngle,
|
||||
featureAngle,
|
||||
|
||||
true,
|
||||
writeOBJ
|
||||
);
|
||||
|
||||
if (nAdded)
|
||||
{
|
||||
pMesh.boundary().write();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "End\n" << endl;
|
||||
|
||||
@ -26,6 +26,7 @@ constructFrom patch;
|
||||
// If construct from patch/mesh:
|
||||
sourceCase "<case>";
|
||||
// and one of sourcePatches or sourceFaceZones (but not both):
|
||||
// (note: wildcards allowed)
|
||||
sourceFaceZones (someFacesZone);
|
||||
sourcePatches (movingWall);
|
||||
|
||||
|
||||
@ -14,6 +14,12 @@ FoamFile
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Type of mesh generation:
|
||||
// - castellated (default)
|
||||
// - castellatedBufferLayer
|
||||
//type castellatedBufferLayer;
|
||||
|
||||
|
||||
// Which of the steps to run
|
||||
castellatedMesh true;
|
||||
snap true;
|
||||
@ -267,6 +273,10 @@ castellatedMeshControls
|
||||
// these can be done with feature edge snapping (so can leave
|
||||
// level (0 0))
|
||||
//curvatureLevel (10 0 10 -1);
|
||||
|
||||
// Optional disabling of buffer layer addition (if switched on by
|
||||
// type = castellatedBufferLayer)
|
||||
addBufferLayers false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -605,6 +615,18 @@ snapControls
|
||||
//- Attract points only to the surface they originate from. Default
|
||||
// false. This can improve snapping of intersecting surfaces.
|
||||
// strictRegionSnap true;
|
||||
|
||||
|
||||
// Choice of mesh motion algorithm to inflate layers (only used for mode
|
||||
// castellatedBufferLayer)
|
||||
|
||||
//solver displacementPointSmoothing;
|
||||
//displacementPointSmoothingCoeffs
|
||||
//{
|
||||
// // Use laplacian to untangle problem areas
|
||||
// pointSmoother laplacian;
|
||||
// nPointSmootherIter 10;
|
||||
//}
|
||||
}
|
||||
|
||||
// Settings for the layer addition.
|
||||
|
||||
@ -501,6 +501,15 @@ pointSet_doc
|
||||
}
|
||||
|
||||
|
||||
//- All points of pointpatch
|
||||
{
|
||||
source patchToPoint;
|
||||
patches ("patch.*");
|
||||
// or
|
||||
patch somePatch;
|
||||
}
|
||||
|
||||
|
||||
//- Copy elements from pointSet
|
||||
{
|
||||
source pointToPoint;
|
||||
|
||||
@ -715,10 +715,15 @@ pointMeshMapper = $(pointMesh)/pointMeshMapper
|
||||
$(pointMeshMapper)/pointMapper.C
|
||||
$(pointMeshMapper)/pointPatchMapper.C
|
||||
|
||||
pointMeshTools = $(pointMesh)/pointMeshTools
|
||||
$(pointMeshTools)/pointMeshTools.C
|
||||
|
||||
pointPatches = $(pointMesh)/pointPatches
|
||||
$(pointPatches)/pointPatch/pointPatch.C
|
||||
$(pointPatches)/pointPatch/pointPatchNew.C
|
||||
$(pointPatches)/facePointPatch/facePointPatch.C
|
||||
$(pointPatches)/facePointPatch/facePointPatchNew.C
|
||||
$(pointPatches)/meshPointPatch/meshPointPatch.C
|
||||
|
||||
basicPointPatches = $(pointPatches)/basic
|
||||
$(basicPointPatches)/coupled/coupledPointPatch.C
|
||||
@ -792,6 +797,7 @@ $(Fields)/fieldTypes.C
|
||||
pointPatchFields = fields/pointPatchFields
|
||||
$(pointPatchFields)/pointPatchField/pointPatchFieldBase.C
|
||||
$(pointPatchFields)/pointPatchField/pointPatchFields.C
|
||||
$(pointPatchFields)/pointPatchField/pointConstraint/pointConstraint.C
|
||||
|
||||
basicPointPatchFields = $(pointPatchFields)/basic
|
||||
$(basicPointPatchFields)/calculated/calculatedPointPatchFields.C
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "pointConstraint.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
const char* const pTraits<pointConstraint>::typeName = "pointConstraint";
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -73,6 +73,9 @@ public:
|
||||
//- Construct from components
|
||||
inline pointConstraint(const Tuple2<label, vector>&);
|
||||
|
||||
//- Construct from components
|
||||
inline pointConstraint(const label count, const vector& n);
|
||||
|
||||
//- Construct from Istream
|
||||
inline pointConstraint(Istream&);
|
||||
|
||||
@ -97,8 +100,19 @@ public:
|
||||
};
|
||||
|
||||
|
||||
//! List of pointConstraint
|
||||
typedef List<pointConstraint> pointConstraintList;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Traits * * * * * * * * * * * * * * * * //
|
||||
|
||||
//- Template specialisation for pTraits\<pointConstraint\> to enable IO
|
||||
template<>
|
||||
struct pTraits<pointConstraint>
|
||||
{
|
||||
static const char* const typeName;
|
||||
};
|
||||
|
||||
//- Contiguous data for pointConstraint
|
||||
template<> struct is_contiguous<pointConstraint> : std::true_type {};
|
||||
|
||||
|
||||
@ -39,6 +39,16 @@ inline Foam::pointConstraint::pointConstraint(const Tuple2<label, vector>& pc)
|
||||
{}
|
||||
|
||||
|
||||
inline Foam::pointConstraint::pointConstraint
|
||||
(
|
||||
const label count,
|
||||
const vector& n
|
||||
)
|
||||
:
|
||||
Tuple2<label, vector>(count, n)
|
||||
{}
|
||||
|
||||
|
||||
inline Foam::pointConstraint::pointConstraint(Istream& is)
|
||||
:
|
||||
Tuple2<label, vector>(is)
|
||||
|
||||
10
src/OpenFOAM/include/createNamedPointMesh.H
Normal file
10
src/OpenFOAM/include/createNamedPointMesh.H
Normal file
@ -0,0 +1,10 @@
|
||||
Foam::Info
|
||||
<< "Create pointMesh for time = "
|
||||
<< runTime.timeName() << Foam::nl << Foam::endl;
|
||||
|
||||
// Register pointMesh on the database
|
||||
const Foam::pointMesh& pMesh = pointMesh::New
|
||||
(
|
||||
mesh,
|
||||
Foam::IOobject::READ_IF_PRESENT
|
||||
);
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2018-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -33,9 +33,74 @@ License
|
||||
#include "PstreamBuffers.H"
|
||||
#include "lduSchedule.H"
|
||||
#include "globalMeshData.H"
|
||||
#include "processorPointPatch.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(pointBoundaryMesh, 0);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
bool Foam::pointBoundaryMesh::hasGroupIDs() const
|
||||
{
|
||||
if (groupIDsPtr_)
|
||||
{
|
||||
// Use existing cache
|
||||
return !groupIDsPtr_->empty();
|
||||
}
|
||||
|
||||
const auto& patches = *this;
|
||||
|
||||
for (const auto& p : patches)
|
||||
{
|
||||
if (!p.inGroups().empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::pointBoundaryMesh::calcGroupIDs() const
|
||||
{
|
||||
if (groupIDsPtr_)
|
||||
{
|
||||
return; // Or FatalError
|
||||
}
|
||||
|
||||
groupIDsPtr_.emplace(16);
|
||||
auto& groupLookup = *groupIDsPtr_;
|
||||
|
||||
const auto& patches = *this;
|
||||
|
||||
forAll(patches, patchi)
|
||||
{
|
||||
for (const word& groupName : patches[patchi].inGroups())
|
||||
{
|
||||
groupLookup(groupName).push_back(patchi);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove groups that clash with patch names
|
||||
forAll(patches, patchi)
|
||||
{
|
||||
if (groupLookup.erase(patches[patchi].name()))
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Removed group '" << patches[patchi].name()
|
||||
<< "' which clashes with patch " << patchi
|
||||
<< " of the same name."
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::pointBoundaryMesh::addPatches(const polyBoundaryMesh& pbm)
|
||||
{
|
||||
// Set boundary patches
|
||||
@ -43,7 +108,7 @@ void Foam::pointBoundaryMesh::addPatches(const polyBoundaryMesh& pbm)
|
||||
|
||||
patches.resize_null(pbm.size());
|
||||
|
||||
forAll(patches, patchi)
|
||||
forAll(pbm, patchi)
|
||||
{
|
||||
// NB: needs ptr() to get *pointPatch instead of *facePointPatch
|
||||
patches.set(patchi, facePointPatch::New(pbm[patchi], *this).ptr());
|
||||
@ -60,21 +125,301 @@ Foam::pointBoundaryMesh::pointBoundaryMesh
|
||||
)
|
||||
:
|
||||
pointPatchList(),
|
||||
regIOobject
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"boundary",
|
||||
//m.thisDb().time().findInstance(m.meshDir(), "boundary"),
|
||||
pbm.mesh().facesInstance(),
|
||||
polyMesh::meshSubDir/pointMesh::meshSubDir,
|
||||
m.thisDb(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false // Avoid conflict with polyMesh/boundary
|
||||
)
|
||||
),
|
||||
mesh_(m)
|
||||
{
|
||||
addPatches(pbm);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
pointPatchList& Patches = *this;
|
||||
|
||||
Pout<< "pointBoundaryMesh::pointBoundaryMesh"
|
||||
<< "(const pointMesh&, const polyBoundaryMesh&): "
|
||||
<< "constructed pointBoundaryMesh:" << endl;
|
||||
Pout<< incrIndent;
|
||||
for (const auto& pp : Patches)
|
||||
{
|
||||
Pout<< indent
|
||||
<< "index:" << pp.index() << " patch:" << pp.name()
|
||||
<< " type:" << pp.type() << endl;
|
||||
}
|
||||
Pout<< decrIndent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::pointBoundaryMesh::pointBoundaryMesh
|
||||
(
|
||||
const IOobject& io,
|
||||
const pointMesh& m,
|
||||
const polyBoundaryMesh& pbm
|
||||
)
|
||||
:
|
||||
pointPatchList(),
|
||||
regIOobject
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"boundary",
|
||||
io.instance(),
|
||||
polyMesh::meshSubDir/pointMesh::meshSubDir,
|
||||
io.db(),
|
||||
io.readOpt(),
|
||||
io.writeOpt(),
|
||||
false //io.registerObject() // or always set to false?
|
||||
)
|
||||
),
|
||||
mesh_(m)
|
||||
{
|
||||
pointPatchList& Patches = *this;
|
||||
|
||||
if (isReadRequired() || (isReadOptional() && headerOk()))
|
||||
{
|
||||
if (readOpt() == IOobject::MUST_READ_IF_MODIFIED)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Specified IOobject::MUST_READ_IF_MODIFIED but class"
|
||||
<< " does not support automatic rereading."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "pointBoundaryMesh::pointBoundaryMesh"
|
||||
<< "(const IOobject&, const pointMesh&,"
|
||||
<< " const polyBoundaryMesh&): "
|
||||
<< "Constructing from boundary file " << objectRelPath()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Read pointPatchList
|
||||
Istream& is = readStream(typeName);
|
||||
|
||||
PtrList<entry> patchEntries(is);
|
||||
Patches.setSize(patchEntries.size());
|
||||
|
||||
forAll(Patches, patchi)
|
||||
{
|
||||
// Try construct-from-dictionary first
|
||||
const word& name = patchEntries[patchi].keyword();
|
||||
|
||||
autoPtr<pointPatch> pPtr
|
||||
(
|
||||
pointPatch::New
|
||||
(
|
||||
name,
|
||||
patchEntries[patchi].dict(),
|
||||
patchi,
|
||||
*this
|
||||
)
|
||||
);
|
||||
|
||||
if (!pPtr)
|
||||
{
|
||||
const label polyPatchi = pbm.findPatchID(name, false);
|
||||
// Try as facePointPatch from polyPatch
|
||||
pPtr = facePointPatch::New(pbm[polyPatchi], *this);
|
||||
pPtr->index() = patchi;
|
||||
}
|
||||
|
||||
Patches.set(patchi, pPtr);
|
||||
}
|
||||
|
||||
// Check state of IOstream
|
||||
is.check
|
||||
(
|
||||
"pointBoundaryMesh::pointBoundaryMesh"
|
||||
"(const IOobject&, const pointMesh&,"
|
||||
" const polyBoundaryMesh&)"
|
||||
);
|
||||
|
||||
close();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "pointBoundaryMesh::pointBoundaryMesh"
|
||||
<< "(const IOobject&, const pointMesh&,"
|
||||
<< " const polyBoundaryMesh&): "
|
||||
<< "Constructing from polyBoundaryMesh only"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
addPatches(pbm);
|
||||
}
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "pointBoundaryMesh::pointBoundaryMesh"
|
||||
<< "(const IOobject&, const pointMesh&, const polyBoundaryMesh&): "
|
||||
<< "constructed pointBoundaryMesh:" << endl;
|
||||
Pout<< incrIndent;
|
||||
for (const auto& pp : Patches)
|
||||
{
|
||||
Pout<< indent
|
||||
<< "index:" << pp.index() << " patch:" << pp.name()
|
||||
<< " type:" << pp.type() << endl;
|
||||
}
|
||||
Pout<< decrIndent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::label Foam::pointBoundaryMesh::nNonProcessor() const
|
||||
{
|
||||
const pointPatchList& patches = *this;
|
||||
|
||||
label count = 0;
|
||||
|
||||
for (const auto& p : patches)
|
||||
{
|
||||
if (isA<processorPointPatch>(p))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::pointBoundaryMesh::nProcessorPatches() const
|
||||
{
|
||||
const pointPatchList& patches = *this;
|
||||
|
||||
label count = 0;
|
||||
|
||||
for (const auto& p : patches)
|
||||
{
|
||||
if (isA<processorPointPatch>(p))
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
Foam::wordList Foam::pointBoundaryMesh::names() const
|
||||
{
|
||||
return PtrListOps::get<word>(*this, nameOp<pointPatch>());
|
||||
}
|
||||
|
||||
|
||||
Foam::wordList Foam::pointBoundaryMesh::types() const
|
||||
{
|
||||
return PtrListOps::get<word>(*this, typeOp<pointPatch>());
|
||||
}
|
||||
|
||||
|
||||
Foam::wordList Foam::pointBoundaryMesh::physicalTypes() const
|
||||
{
|
||||
return
|
||||
PtrListOps::get<word>
|
||||
(
|
||||
*this,
|
||||
[](const pointPatch& p) { return p.physicalType(); }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const Foam::HashTable<Foam::labelList>&
|
||||
Foam::pointBoundaryMesh::groupPatchIDs() const
|
||||
{
|
||||
if (!groupIDsPtr_)
|
||||
{
|
||||
calcGroupIDs();
|
||||
}
|
||||
|
||||
return *groupIDsPtr_;
|
||||
}
|
||||
|
||||
|
||||
Foam::labelList Foam::pointBoundaryMesh::indices
|
||||
(
|
||||
const wordRe& matcher,
|
||||
const bool useGroups
|
||||
) const
|
||||
{
|
||||
return mesh().boundaryMesh().indices(matcher, useGroups);
|
||||
if (matcher.empty())
|
||||
{
|
||||
return labelList();
|
||||
}
|
||||
|
||||
// Only check groups if requested and they exist
|
||||
const bool checkGroups = (useGroups && this->hasGroupIDs());
|
||||
|
||||
labelHashSet ids(0);
|
||||
|
||||
if (matcher.isPattern())
|
||||
{
|
||||
if (checkGroups)
|
||||
{
|
||||
const auto& groupLookup = groupPatchIDs();
|
||||
forAllConstIters(groupLookup, iter)
|
||||
{
|
||||
if (matcher(iter.key()))
|
||||
{
|
||||
// Add patch ids associated with the group
|
||||
ids.insert(iter.val());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ids.empty())
|
||||
{
|
||||
return PtrListOps::findMatching(*this, matcher);
|
||||
}
|
||||
else
|
||||
{
|
||||
ids.insert(PtrListOps::findMatching(*this, matcher));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Literal string.
|
||||
// Special version of above for reduced memory footprint.
|
||||
|
||||
const label patchId = PtrListOps::firstMatching(*this, matcher);
|
||||
|
||||
if (patchId >= 0)
|
||||
{
|
||||
return labelList(one{}, patchId);
|
||||
}
|
||||
else if (checkGroups)
|
||||
{
|
||||
const auto iter = groupPatchIDs().cfind(matcher);
|
||||
|
||||
if (iter.good())
|
||||
{
|
||||
// Hash ids associated with the group
|
||||
ids.insert(iter.val());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ids.sortedToc();
|
||||
}
|
||||
|
||||
|
||||
@ -84,7 +429,43 @@ Foam::labelList Foam::pointBoundaryMesh::indices
|
||||
const bool useGroups
|
||||
) const
|
||||
{
|
||||
return mesh().boundaryMesh().indices(matcher, useGroups);
|
||||
if (matcher.empty())
|
||||
{
|
||||
return labelList();
|
||||
}
|
||||
else if (matcher.size() == 1)
|
||||
{
|
||||
return this->indices(matcher.front(), useGroups);
|
||||
}
|
||||
|
||||
labelHashSet ids(0);
|
||||
|
||||
// Only check groups if requested and they exist
|
||||
if (useGroups && this->hasGroupIDs())
|
||||
{
|
||||
ids.reserve(this->size());
|
||||
|
||||
const auto& groupLookup = groupPatchIDs();
|
||||
forAllConstIters(groupLookup, iter)
|
||||
{
|
||||
if (matcher(iter.key()))
|
||||
{
|
||||
// Add patch ids associated with the group
|
||||
ids.insert(iter.val());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ids.empty())
|
||||
{
|
||||
return PtrListOps::findMatching(*this, matcher);
|
||||
}
|
||||
else
|
||||
{
|
||||
ids.insert(PtrListOps::findMatching(*this, matcher));
|
||||
}
|
||||
|
||||
return ids.sortedToc();
|
||||
}
|
||||
|
||||
|
||||
@ -95,13 +476,91 @@ Foam::labelList Foam::pointBoundaryMesh::indices
|
||||
const bool useGroups
|
||||
) const
|
||||
{
|
||||
return mesh().boundaryMesh().indices(select, ignore, useGroups);
|
||||
//return mesh().boundaryMesh().indices(select, ignore, useGroups);
|
||||
if (ignore.empty())
|
||||
{
|
||||
return this->indices(select, useGroups);
|
||||
}
|
||||
|
||||
const wordRes::filter matcher(select, ignore);
|
||||
|
||||
labelHashSet ids(0);
|
||||
|
||||
// Only check groups if requested and they exist
|
||||
if (useGroups && this->hasGroupIDs())
|
||||
{
|
||||
ids.reserve(this->size());
|
||||
|
||||
const auto& groupLookup = groupPatchIDs();
|
||||
forAllConstIters(groupLookup, iter)
|
||||
{
|
||||
if (matcher(iter.key()))
|
||||
{
|
||||
// Add patch ids associated with the group
|
||||
ids.insert(iter.val());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ids.empty())
|
||||
{
|
||||
return PtrListOps::findMatching(*this, matcher);
|
||||
}
|
||||
else
|
||||
{
|
||||
ids.insert(PtrListOps::findMatching(*this, matcher));
|
||||
}
|
||||
|
||||
return ids.sortedToc();
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::pointBoundaryMesh::findPatchID(const word& patchName) const
|
||||
Foam::label Foam::pointBoundaryMesh::findPatchID
|
||||
(
|
||||
const word& patchName,
|
||||
bool allowNotFound
|
||||
) const
|
||||
{
|
||||
return mesh().boundaryMesh().findPatchID(patchName);
|
||||
//return mesh().boundaryMesh().findPatchID(patchName);
|
||||
if (patchName.empty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
const label patchId = PtrListOps::firstMatching(*this, patchName);
|
||||
|
||||
if (patchId >= 0)
|
||||
{
|
||||
return patchId;
|
||||
}
|
||||
|
||||
if (!allowNotFound)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Patch '" << patchName << "' not found. "
|
||||
<< "Available patch names";
|
||||
|
||||
if (polyMesh::defaultRegion != mesh_.name())
|
||||
{
|
||||
FatalError
|
||||
<< " in region '" << mesh_.name() << "'";
|
||||
}
|
||||
|
||||
FatalError
|
||||
<< " include: " << names() << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
// Patch not found
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "label pointBoundaryMesh::findPatchID(const word&) const"
|
||||
<< " Patch named " << patchName << " not found. "
|
||||
<< "Available patch names: " << names() << endl;
|
||||
}
|
||||
|
||||
// Not found, return -1
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -243,4 +702,80 @@ void Foam::pointBoundaryMesh::updateMesh()
|
||||
}
|
||||
|
||||
|
||||
void Foam::pointBoundaryMesh::reorder
|
||||
(
|
||||
const labelUList& oldToNew,
|
||||
const bool validBoundary
|
||||
)
|
||||
{
|
||||
// Change order of patches
|
||||
pointPatchList::reorder(oldToNew);
|
||||
|
||||
// Adapt indices
|
||||
pointPatchList& patches = *this;
|
||||
|
||||
forAll(patches, patchi)
|
||||
{
|
||||
patches[patchi].index() = patchi;
|
||||
}
|
||||
|
||||
// Clear group-to-patch addressing. Note: could re-calculate
|
||||
groupIDsPtr_.reset(nullptr);
|
||||
|
||||
if (validBoundary)
|
||||
{
|
||||
updateMesh();
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
pointPatchList& Patches = *this;
|
||||
|
||||
Pout<< "pointBoundaryMesh::reorder"
|
||||
<< "(const labelUList&, const bool): "
|
||||
<< "reordered pointBoundaryMesh:" << endl;
|
||||
Pout<< incrIndent;
|
||||
for (const auto& pp : Patches)
|
||||
{
|
||||
Pout<< indent
|
||||
<< "index:" << pp.index() << " patch:" << pp.name()
|
||||
<< " type:" << pp.type() << endl;
|
||||
}
|
||||
Pout<< decrIndent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::pointBoundaryMesh::writeData(Ostream& os) const
|
||||
{
|
||||
const pointPatchList& patches = *this;
|
||||
|
||||
os << patches.size() << nl << token::BEGIN_LIST << incrIndent << nl;
|
||||
|
||||
forAll(patches, patchi)
|
||||
{
|
||||
os << indent << patches[patchi].name() << nl
|
||||
<< indent << token::BEGIN_BLOCK << nl
|
||||
<< incrIndent << patches[patchi] << decrIndent
|
||||
<< indent << token::END_BLOCK << endl;
|
||||
}
|
||||
|
||||
os << decrIndent << token::END_LIST;
|
||||
|
||||
// Check state of IOstream
|
||||
os.check("pointBoundaryMesh::writeData(Ostream& os) const");
|
||||
|
||||
return os.good();
|
||||
}
|
||||
|
||||
|
||||
//bool Foam::pointBoundaryMesh::writeObject
|
||||
//(
|
||||
// IOstreamOption
|
||||
//) const
|
||||
//{
|
||||
// return regIOobject::writeObject(fmt, ver, IOstream::UNCOMPRESSED);
|
||||
//}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
Copyright (C) 2018-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -39,6 +39,7 @@ SourceFiles
|
||||
#define Foam_pointBoundaryMesh_H
|
||||
|
||||
#include "pointPatch.H"
|
||||
#include "regIOobject.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -56,19 +57,29 @@ class wordRes;
|
||||
|
||||
class pointBoundaryMesh
|
||||
:
|
||||
public pointPatchList
|
||||
public pointPatchList,
|
||||
public regIOobject
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Reference to mesh
|
||||
const pointMesh& mesh_;
|
||||
|
||||
//- Demand-driven: list of patch ids per group
|
||||
mutable autoPtr<HashTable<labelList>> groupIDsPtr_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Calculate geometry for the patches (transformation tensors etc.)
|
||||
void calcGeometry();
|
||||
|
||||
//- Some patches have inGroup entries
|
||||
bool hasGroupIDs() const;
|
||||
|
||||
//- Calculate group name to patch ids lookup
|
||||
void calcGroupIDs() const;
|
||||
|
||||
//- Assign facePointPatches corresponding to the given polyBoundaryMesh
|
||||
void addPatches(const polyBoundaryMesh& pbm);
|
||||
|
||||
@ -85,11 +96,27 @@ public:
|
||||
friend class pointMesh;
|
||||
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("pointBoundaryMesh");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from polyBoundaryMesh
|
||||
pointBoundaryMesh(const pointMesh&, const polyBoundaryMesh&);
|
||||
|
||||
//- Construct from IOobject and polyBoundaryMesh
|
||||
pointBoundaryMesh
|
||||
(
|
||||
const IOobject& io,
|
||||
const pointMesh&,
|
||||
const polyBoundaryMesh&
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~pointBoundaryMesh() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
@ -99,6 +126,21 @@ public:
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
//- The number of patches before the first processor patch.
|
||||
label nNonProcessor() const;
|
||||
|
||||
//- The number of processorPointPatch patches
|
||||
label nProcessorPatches() const;
|
||||
|
||||
//- Return a list of patch names
|
||||
wordList names() const;
|
||||
|
||||
//- Return a list of patch types
|
||||
wordList types() const;
|
||||
|
||||
//- Return a list of physical types
|
||||
wordList physicalTypes() const;
|
||||
|
||||
//- Return (sorted) patch indices for all matches.
|
||||
// A no-op (returns empty list) for an empty matcher
|
||||
labelList indices(const wordRe& matcher, const bool useGroups) const;
|
||||
@ -121,14 +163,31 @@ public:
|
||||
|
||||
//- Find patch index given a name
|
||||
// A no-op (returns -1) for an empty patchName
|
||||
label findPatchID(const word& patchName) const;
|
||||
label findPatchID
|
||||
(
|
||||
const word& patchName,
|
||||
const bool allowNotFound = true
|
||||
) const;
|
||||
|
||||
//- Correct polyBoundaryMesh after moving points
|
||||
//- The patch indices per patch group
|
||||
const HashTable<labelList>& groupPatchIDs() const;
|
||||
|
||||
//- Correct pointBoundaryMesh after moving points
|
||||
void movePoints(const pointField&);
|
||||
|
||||
//- Correct polyBoundaryMesh after topology update
|
||||
//- Correct pointBoundaryMesh after topology update
|
||||
void updateMesh();
|
||||
|
||||
//- Reorders patches. Ordering does not have to be done in
|
||||
// ascending or descending order. Reordering has to be unique.
|
||||
// (is shuffle) If validBoundary calls updateMesh()
|
||||
// after reordering to recalculate data (so call needs to be parallel
|
||||
// sync in that case)
|
||||
void reorder(const labelUList& oldToNew, const bool validBoundary);
|
||||
|
||||
//- writeData member function required by regIOobject
|
||||
virtual bool writeData(Ostream&) const;
|
||||
|
||||
|
||||
// Housekeeping
|
||||
|
||||
|
||||
@ -40,6 +40,8 @@ namespace Foam
|
||||
defineTypeNameAndDebug(pointMesh, 0);
|
||||
}
|
||||
|
||||
Foam::word Foam::pointMesh::meshSubDir = "pointMesh";
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
@ -89,8 +91,66 @@ Foam::pointMesh::pointMesh(const polyMesh& pMesh)
|
||||
}
|
||||
|
||||
|
||||
Foam::pointMesh::pointMesh(const polyMesh& pMesh, const IOobject& io)
|
||||
:
|
||||
MeshObject<polyMesh, Foam::UpdateableMeshObject, pointMesh>(pMesh),
|
||||
GeoMesh<polyMesh>(pMesh),
|
||||
boundary_(io, *this, pMesh.boundaryMesh())
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "pointMesh::pointMesh(const polyMesh&): "
|
||||
<< "Constructing from IO " << io.objectRelPath()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Calculate the geometry for the patches (transformation tensors etc.)
|
||||
boundary_.calcGeometry();
|
||||
}
|
||||
|
||||
|
||||
Foam::pointMesh::pointMesh
|
||||
(
|
||||
const polyMesh& pMesh,
|
||||
const IOobjectOption::readOption rOpt
|
||||
)
|
||||
:
|
||||
pointMesh
|
||||
(
|
||||
pMesh,
|
||||
IOobject
|
||||
(
|
||||
pMesh.name(), // polyMesh region
|
||||
pMesh.facesInstance(), // polyMesh topology instance
|
||||
pMesh.time(),
|
||||
rOpt,
|
||||
Foam::IOobject::NO_WRITE
|
||||
)
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::pointMesh::setInstance
|
||||
(
|
||||
const fileName& inst,
|
||||
const IOobjectOption::writeOption wOpt
|
||||
)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "pointMesh::setInstance(): "
|
||||
<< "Setting instance to " << inst << endl;
|
||||
}
|
||||
this->writeOpt(wOpt);
|
||||
this->instance() = inst;
|
||||
|
||||
boundary_.writeOpt(wOpt);
|
||||
boundary_.instance() = inst;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::pointMesh::movePoints()
|
||||
{
|
||||
if (debug)
|
||||
@ -119,4 +179,19 @@ void Foam::pointMesh::updateMesh(const mapPolyMesh& mpm)
|
||||
}
|
||||
|
||||
|
||||
bool Foam::pointMesh::writeObject
|
||||
(
|
||||
IOstreamOption streamOpt,
|
||||
const bool writeOnProc
|
||||
) const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "pointMesh::writeObject(IOstreamOption, const bool): "
|
||||
<< "Writing to " << boundary_.objectRelPath() << endl;
|
||||
}
|
||||
return boundary_.writeObject(streamOpt, writeOnProc);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
Copyright (C) 2021-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -96,12 +96,26 @@ public:
|
||||
// Declare name of the class and its debug switch
|
||||
ClassName("pointMesh");
|
||||
|
||||
//- Return the mesh sub-directory name (usually "pointMesh")
|
||||
static word meshSubDir;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from polyMesh
|
||||
explicit pointMesh(const polyMesh& pMesh);
|
||||
|
||||
//- Construct from polyMesh and IOobject (used when reading boundary)
|
||||
explicit pointMesh(const polyMesh& pMesh, const IOobject& io);
|
||||
|
||||
//- Construct from polyMesh and readOpt. Takes instance, time etc
|
||||
//- from polyMesh. Used when reading boundary.
|
||||
explicit pointMesh
|
||||
(
|
||||
const polyMesh& pMesh,
|
||||
const IOobjectOption::readOption rOpt
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
~pointMesh() = default;
|
||||
@ -151,6 +165,13 @@ public:
|
||||
return GeoMesh<polyMesh>::mesh_.time();
|
||||
}
|
||||
|
||||
//- Set the instance for mesh files
|
||||
void setInstance
|
||||
(
|
||||
const fileName& instance,
|
||||
const IOobjectOption::writeOption wOpt = IOobject::AUTO_WRITE
|
||||
);
|
||||
|
||||
|
||||
// Volume Mesh
|
||||
|
||||
@ -181,6 +202,16 @@ public:
|
||||
{
|
||||
return &pm == this;
|
||||
}
|
||||
|
||||
|
||||
// Write
|
||||
|
||||
//- Write
|
||||
virtual bool writeObject
|
||||
(
|
||||
IOstreamOption streamOpt,
|
||||
const bool writeOnProc = true
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
542
src/OpenFOAM/meshes/pointMesh/pointMeshTools/pointMeshTools.C
Normal file
542
src/OpenFOAM/meshes/pointMesh/pointMeshTools/pointMeshTools.C
Normal file
@ -0,0 +1,542 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "pointMeshTools.H"
|
||||
#include "syncTools.H"
|
||||
#include "PatchTools.H"
|
||||
#include "dummyTransform.H"
|
||||
#include "unitConversion.H"
|
||||
//#include "OFstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
void Foam::pointMeshTools::featurePointsEdges
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
|
||||
const uindirectPrimitivePatch& allBoundary,
|
||||
|
||||
// Per boundary face to zone
|
||||
const labelUList& faceToZone,
|
||||
// Number of zones
|
||||
const label nZones,
|
||||
|
||||
const scalar edgeFeatureAngle,
|
||||
//const scalar pointFeatureAngle, //not yet done
|
||||
|
||||
// Feature edge(points) internal to a zone
|
||||
labelListList& zoneToMeshPoints,
|
||||
List<pointConstraintList>& zoneToConstraints,
|
||||
|
||||
// Feature edge(points) in between zones
|
||||
labelList& twoZoneMeshPoints,
|
||||
pointConstraintList& twoZoneConstraints,
|
||||
|
||||
// Feature points on > 2 zones
|
||||
labelList& multiZoneMeshPoints,
|
||||
pointConstraintList& multiZoneConstraints
|
||||
)
|
||||
{
|
||||
// Analyses edges on mesh faces and splits them up according to topology
|
||||
// and geometry:
|
||||
// - edges in between faces on same zone but making a feature angle
|
||||
// - edges in between faces on two different zones
|
||||
// - points on faces on > 2 zones
|
||||
|
||||
|
||||
const globalMeshData& globalData = mesh.globalData();
|
||||
const indirectPrimitivePatch& cpp = globalData.coupledPatch();
|
||||
const mapDistribute& map = globalData.globalEdgeSlavesMap();
|
||||
const auto& mp = allBoundary.meshPoints();
|
||||
|
||||
const vector nullVector(vector::uniform(0));
|
||||
const auto assignNonNull = [&](vector& x, const vector& y)
|
||||
{
|
||||
if (x == nullVector && y != nullVector)
|
||||
{
|
||||
x = y;
|
||||
}
|
||||
};
|
||||
|
||||
// Calculate parallel-consistent point normals (as unweighted average
|
||||
// of faceNormals). Note: only valid on patch points, not on mesh points
|
||||
// that are coupled to these.
|
||||
const pointField pointNormals
|
||||
(
|
||||
PatchTools::pointNormals
|
||||
(
|
||||
mesh,
|
||||
allBoundary
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Find correspondence between allBoundary and coupled edges
|
||||
labelList allEdges;
|
||||
labelList coupledEdges;
|
||||
bitSet sameEdgeOrientation;
|
||||
PatchTools::matchEdges
|
||||
(
|
||||
allBoundary,
|
||||
cpp,
|
||||
allEdges,
|
||||
coupledEdges,
|
||||
sameEdgeOrientation
|
||||
);
|
||||
|
||||
|
||||
|
||||
// To construct the patches we need to know per edge:
|
||||
// - patch on either side (if topological feature edge)
|
||||
// - faceNormal on either side (if feature angle)
|
||||
// We need to know per point:
|
||||
// - patches on all connected faces
|
||||
// - faceNormals on all connected faces? And compare to average?
|
||||
// or edge normals on all connected edges
|
||||
|
||||
|
||||
typedef Tuple2<label, vector> PN;
|
||||
const PN nullPN(-1, nullVector);
|
||||
|
||||
|
||||
|
||||
// Point-based analysis
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// Collect per (mesh)point the zones (1, 2 or >2). Note: per mesh to
|
||||
// make it easier to sync. See edge-based code below where we explicitly
|
||||
// have to transfer from patch-edge to mesh-point etc. Note sure which one
|
||||
// fits better....
|
||||
// State:
|
||||
// (-1, -1) : initial state
|
||||
// (-2, -2) : more than 2 zones
|
||||
// (>=0, >=0) : zones from connected faces
|
||||
labelPairList pointToZones(mesh.nPoints(), labelPair(-1, -1));
|
||||
{
|
||||
// Combine zones.
|
||||
const auto combineZones = [&](labelPair& x, const labelPair& y)
|
||||
{
|
||||
if (x == labelPair(-2, -2))
|
||||
{
|
||||
// Already marked as having >2 zones
|
||||
}
|
||||
else if (y == labelPair(-2, -2))
|
||||
{
|
||||
x = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find first free slot
|
||||
if (x[0] == -1)
|
||||
{
|
||||
if (y[0] != -1)
|
||||
{
|
||||
x[0] = y[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
x[0] = y[1];
|
||||
}
|
||||
}
|
||||
else if (x[1] == -1)
|
||||
{
|
||||
if (y[0] != -1 && y[0] != x[0])
|
||||
{
|
||||
x[1] = y[0];
|
||||
}
|
||||
else if (y[1] != -1 && y[1] != x[1])
|
||||
{
|
||||
x[1] = y[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Both x slots filled. See if y adds a 3rd element
|
||||
if (y[0] != -1 && y[0] != x[0] && y[0] != x[1])
|
||||
{
|
||||
x = labelPair(-2, -2);
|
||||
}
|
||||
else if (y[1] != -1 && y[1] != x[0] && y[1] != x[1])
|
||||
{
|
||||
x = labelPair(-2, -2);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
forAll(allBoundary, facei)
|
||||
{
|
||||
const auto& f = allBoundary[facei];
|
||||
const label zonei = faceToZone[facei];
|
||||
for (const label pointi : f)
|
||||
{
|
||||
auto& pZones = pointToZones[pointi];
|
||||
|
||||
if (pZones != labelPair(-2, -2) && !pZones.contains(zonei))
|
||||
{
|
||||
if (pZones.first() == -1)
|
||||
{
|
||||
pZones.first() = zonei;
|
||||
}
|
||||
else if (pZones.second() == -1)
|
||||
{
|
||||
pZones.second() = zonei;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mark as >2 zones
|
||||
pZones = labelPair(-2, -2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh,
|
||||
pointToZones,
|
||||
combineZones,
|
||||
labelPair(-1, -1),
|
||||
dummyTransform()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Edge-based analysis
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// 1. Local analysis
|
||||
|
||||
List<Pair<PN>> allEdgeToFaces
|
||||
(
|
||||
allBoundary.nEdges(),
|
||||
Pair<PN>(nullPN, nullPN)
|
||||
);
|
||||
{
|
||||
const auto& edgeFaces = allBoundary.edgeFaces();
|
||||
const auto& faceNormals = allBoundary.faceNormals();
|
||||
|
||||
forAll(edgeFaces, edgei)
|
||||
{
|
||||
const auto& eFaces = edgeFaces[edgei];
|
||||
const vector& n0 = faceNormals[eFaces[0]];
|
||||
const label zone0 = faceToZone[eFaces[0]];
|
||||
if (eFaces.size() == 1)
|
||||
{
|
||||
allEdgeToFaces[edgei] = Pair<PN>(PN(zone0, n0), nullPN);
|
||||
}
|
||||
else
|
||||
{
|
||||
const vector& n1 = faceNormals[eFaces[1]];
|
||||
const label zone1 = faceToZone[eFaces[1]];
|
||||
allEdgeToFaces[edgei] = Pair<PN>
|
||||
(
|
||||
PN(zone0, n0),
|
||||
PN(zone1, n1)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 2. Sync across coupled patches
|
||||
|
||||
{
|
||||
// Combine pair of normals
|
||||
const auto vectorPairMax = [&](Pair<PN>& x, const Pair<PN>& y)
|
||||
{
|
||||
if (x[0] == nullPN)
|
||||
{
|
||||
if (y[0] != nullPN)
|
||||
{
|
||||
x[0] = y[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
x[0] = y[1];
|
||||
}
|
||||
}
|
||||
else if (x[1] == nullPN)
|
||||
{
|
||||
if (y[0] != nullPN && y[0] != x[0])
|
||||
{
|
||||
x[1] = y[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
x[1] = y[1];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
List<Pair<PN>> cppEdgeData
|
||||
(
|
||||
map.constructSize(),
|
||||
Pair<PN>(nullPN, nullPN)
|
||||
);
|
||||
UIndirectList<Pair<PN>>(cppEdgeData, coupledEdges) =
|
||||
UIndirectList<Pair<PN>>(allEdgeToFaces, allEdges);
|
||||
|
||||
globalData.syncData
|
||||
(
|
||||
cppEdgeData,
|
||||
globalData.globalEdgeSlaves(),
|
||||
globalData.globalEdgeTransformedSlaves(),
|
||||
map,
|
||||
globalData.globalTransforms(),
|
||||
vectorPairMax,
|
||||
dummyTransform()
|
||||
);
|
||||
|
||||
UIndirectList<Pair<PN>>(allEdgeToFaces, allEdges) =
|
||||
UIndirectList<Pair<PN>>(cppEdgeData, coupledEdges);
|
||||
}
|
||||
|
||||
|
||||
// Now we have all the per-patch edge information
|
||||
// - do inter-patch edges
|
||||
// - do feature-angle edges
|
||||
// Store on mesh points
|
||||
|
||||
const auto assignNonNullPN = [&](PN& x, const PN& y)
|
||||
{
|
||||
if (x.second() == nullVector && y.second() != nullVector)
|
||||
{
|
||||
x = y;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const scalar featEdgeCos = Foam::cos(degToRad(edgeFeatureAngle));
|
||||
|
||||
|
||||
//OFstream os("allBoundary.obj");
|
||||
//Pout<< "Dumping feature edges to " << os.name() << endl;
|
||||
//OFstream interOs("interZoneBoundary.obj");
|
||||
//Pout<< "Dumping inter-zone edges to " << os.name() << endl;
|
||||
|
||||
// Storing the normal for points that are on inter-patch edges
|
||||
vectorField patchEdgeNormal(mesh.nPoints(), nullVector);
|
||||
// Storing the constraint for points that are on patch-internal feat edges
|
||||
List<PN> featEdgeNormal(mesh.nPoints(), nullPN);
|
||||
|
||||
// Use point-based sync
|
||||
{
|
||||
forAll(allEdgeToFaces, edgei)
|
||||
{
|
||||
const edge& e = allBoundary.edges()[edgei];
|
||||
const label mp0 = mp[e[0]];
|
||||
const label mp1 = mp[e[1]];
|
||||
|
||||
const Pair<PN>& facesInfo = allEdgeToFaces[edgei];
|
||||
|
||||
if (facesInfo[1] == nullPN)
|
||||
{
|
||||
// Real boundary edge. On single patch only so no need
|
||||
// to put in separate point patch ... (? tbd)
|
||||
}
|
||||
else
|
||||
{
|
||||
const label zone0 = facesInfo[0].first();
|
||||
const label zone1 = facesInfo[1].first();
|
||||
|
||||
const point& p0 = allBoundary.points()[mp0];
|
||||
const point& p1 = allBoundary.points()[mp1];
|
||||
vector eVec(p1-p0);
|
||||
eVec.normalise();
|
||||
|
||||
if (zone0 != zone1)
|
||||
{
|
||||
// Inter-patch. TBD: check for feature angle as well?
|
||||
|
||||
//patchEdgeNormal[mp0] = pointNormals[e[0]];
|
||||
//patchEdgeNormal[mp1] = pointNormals[e[1]];
|
||||
|
||||
patchEdgeNormal[mp0] = eVec;
|
||||
patchEdgeNormal[mp1] = eVec;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Same patch - check for feature angle
|
||||
|
||||
const vector& n0 = facesInfo[0].second();
|
||||
const vector& n1 = facesInfo[1].second();
|
||||
|
||||
if ((n0 & n1) < featEdgeCos)
|
||||
{
|
||||
//Pout<< "** feature edge:" << edgei
|
||||
// << " points:" << allBoundary.points()[mp0]
|
||||
// << allBoundary.points()[mp1]
|
||||
// << nl
|
||||
// << " faceNormal0:" << n0
|
||||
// << " faceNormal1:" << n1 << nl
|
||||
// << " zone0:" << zone0
|
||||
// << " zone1:" << zone1 << nl
|
||||
// << " pointNormals0:" << pointNormals[e[0]]
|
||||
// << " pointNormals1:" << pointNormals[e[1]]
|
||||
// << nl
|
||||
// << endl;
|
||||
|
||||
if (patchEdgeNormal[mp0] == nullVector)
|
||||
{
|
||||
//featEdgeNormal[mp0] = PN
|
||||
//(
|
||||
// zone0, // zone
|
||||
// pointNormals[e[0]]
|
||||
//);
|
||||
featEdgeNormal[mp0].first() = zone0;
|
||||
// Assign edge direction. TBD: average & parallel
|
||||
featEdgeNormal[mp0].second() = eVec;
|
||||
}
|
||||
if (patchEdgeNormal[mp1] == nullVector)
|
||||
{
|
||||
//featEdgeNormal[mp1] = PN
|
||||
//(
|
||||
// zone1, // zone
|
||||
// pointNormals[e[1]]
|
||||
//);
|
||||
featEdgeNormal[mp1].first() = zone1;
|
||||
// Assign edge direction. TBD: average & parallel
|
||||
featEdgeNormal[mp1].second() = eVec;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh,
|
||||
patchEdgeNormal,
|
||||
assignNonNull,
|
||||
nullVector
|
||||
);
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh,
|
||||
featEdgeNormal,
|
||||
assignNonNullPN,
|
||||
nullPN,
|
||||
dummyTransform()
|
||||
);
|
||||
}
|
||||
|
||||
// Make sure that inter-patch points are not also in feature-edge
|
||||
// points. Note: not absolutely necessary since all inter-patch points
|
||||
// will also be in the 'normal' facePointPatches.
|
||||
|
||||
DynamicList<label> dynMultiZoneMeshPoints(allBoundary.nPoints());
|
||||
DynamicList<pointConstraint> dynMultiZoneConstraints(allBoundary.nPoints());
|
||||
forAll(pointToZones, pointi)
|
||||
{
|
||||
if (pointToZones[pointi] == labelPair(-2, -2))
|
||||
{
|
||||
dynMultiZoneMeshPoints.append(pointi);
|
||||
// Note: pointConstraint just a slip constraint for now
|
||||
dynMultiZoneConstraints.append
|
||||
(
|
||||
pointConstraint
|
||||
(
|
||||
3, // feature point
|
||||
Zero //meshPointNormals[pointi]
|
||||
)
|
||||
);
|
||||
// Unmark as feature angle point
|
||||
patchEdgeNormal[pointi] = nullVector;
|
||||
featEdgeNormal[pointi] = nullPN;
|
||||
}
|
||||
}
|
||||
multiZoneMeshPoints = std::move(dynMultiZoneMeshPoints);
|
||||
multiZoneConstraints = std::move(dynMultiZoneConstraints);
|
||||
|
||||
|
||||
DynamicList<label> dynTwoZoneMeshPoints(allBoundary.nPoints());
|
||||
DynamicList<pointConstraint> dynTwoZoneConstraints(allBoundary.nPoints());
|
||||
forAll(patchEdgeNormal, pointi)
|
||||
{
|
||||
if (patchEdgeNormal[pointi] != nullVector)
|
||||
{
|
||||
dynTwoZoneMeshPoints.append(pointi);
|
||||
// Note: pointConstraint just a slip constraint for now
|
||||
dynTwoZoneConstraints.append
|
||||
(
|
||||
pointConstraint
|
||||
(
|
||||
2, // feature edge
|
||||
patchEdgeNormal[pointi]
|
||||
)
|
||||
);
|
||||
|
||||
// Unmark as feature angle point
|
||||
featEdgeNormal[pointi] = nullPN;
|
||||
}
|
||||
}
|
||||
twoZoneMeshPoints = std::move(dynTwoZoneMeshPoints);
|
||||
twoZoneConstraints = std::move(dynTwoZoneConstraints);
|
||||
|
||||
|
||||
// Sort featEdgeNormal according to zone
|
||||
zoneToMeshPoints.resize_nocopy(nZones);
|
||||
zoneToConstraints.resize_nocopy(nZones);
|
||||
{
|
||||
labelList sizes(nZones, 0);
|
||||
forAll(featEdgeNormal, pointi)
|
||||
{
|
||||
const auto& pInfo = featEdgeNormal[pointi];
|
||||
if (pInfo != nullPN)
|
||||
{
|
||||
const label zonei = pInfo.first();
|
||||
sizes[zonei]++;
|
||||
}
|
||||
}
|
||||
forAll(zoneToMeshPoints, zonei)
|
||||
{
|
||||
zoneToMeshPoints[zonei].setSize(sizes[zonei]);
|
||||
zoneToConstraints[zonei].setSize(sizes[zonei]);
|
||||
}
|
||||
sizes = 0;
|
||||
forAll(featEdgeNormal, pointi)
|
||||
{
|
||||
const auto& pInfo = featEdgeNormal[pointi];
|
||||
if (pInfo != nullPN)
|
||||
{
|
||||
const label zonei = pInfo.first();
|
||||
const label index = sizes[zonei]++;
|
||||
|
||||
zoneToMeshPoints[zonei][index] = pointi;
|
||||
zoneToConstraints[zonei][index] =
|
||||
pointConstraint(2, pInfo.second()); // constrained to slide
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,95 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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::polyMeshTools
|
||||
|
||||
Description
|
||||
Collection of static functions operating on pointMesh.
|
||||
|
||||
SourceFiles
|
||||
pointMeshTools.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_pointMeshTools_H
|
||||
#define Foam_pointMeshTools_H
|
||||
|
||||
#include "pointMesh.H"
|
||||
#include "pointConstraint.H"
|
||||
#include "uindirectPrimitivePatch.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class pointMeshTools Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class pointMeshTools
|
||||
{
|
||||
public:
|
||||
|
||||
//- Analyse patch for feature edges, feature points. Handles points
|
||||
//- not being on a face of patch but coupled to it.
|
||||
static void featurePointsEdges
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
|
||||
const uindirectPrimitivePatch& boundary,
|
||||
// Per boundary face to zone
|
||||
const labelUList& faceToZone,
|
||||
// Number of zones
|
||||
const label nZones,
|
||||
|
||||
const scalar edgeFeatureAngle,
|
||||
//const scalar pointFeatureAngle, //not yet done
|
||||
|
||||
// Feature edge(points) internal to a zone
|
||||
labelListList& zoneToMeshPoints,
|
||||
List<pointConstraintList>& zoneToConstraints,
|
||||
|
||||
// Feature edge(points) in between zones
|
||||
labelList& twoZoneMeshPoints,
|
||||
pointConstraintList& twoZoneConstraints,
|
||||
|
||||
// Feature points on > 2 zones
|
||||
labelList& multiZoneMeshPoints,
|
||||
pointConstraintList& multiZoneConstraints
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -72,6 +72,39 @@ public:
|
||||
:
|
||||
facePointPatch(patch, bm)
|
||||
{}
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
genericPointPatch
|
||||
(
|
||||
const genericPointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
facePointPatch(patch, bm, index, mapAddressing, reversePointMap)
|
||||
{}
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::NewFrom<genericPointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -91,6 +91,20 @@ Foam::cyclicPointPatch::cyclicPointPatch
|
||||
{}
|
||||
|
||||
|
||||
Foam::cyclicPointPatch::cyclicPointPatch
|
||||
(
|
||||
const cyclicPointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
coupledFacePointPatch(patch, bm, index, mapAddressing, reversePointMap),
|
||||
cyclicPolyPatch_(refCast<const cyclicPolyPatch>(patch.patch()))
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::cyclicPointPatch::~cyclicPointPatch()
|
||||
|
||||
@ -105,6 +105,36 @@ public:
|
||||
const pointBoundaryMesh& bm
|
||||
);
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
cyclicPointPatch
|
||||
(
|
||||
const cyclicPointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
);
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::NewFrom<cyclicPointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~cyclicPointPatch();
|
||||
|
||||
@ -73,6 +73,39 @@ public:
|
||||
cyclicPointPatch(patch, bm)
|
||||
{}
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
cyclicSlipPointPatch
|
||||
(
|
||||
const cyclicSlipPointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
cyclicPointPatch(patch, bm, index, mapAddressing, reversePointMap)
|
||||
{}
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::NewFrom<cyclicSlipPointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~cyclicSlipPointPatch() = default;
|
||||
|
||||
@ -72,6 +72,39 @@ public:
|
||||
facePointPatch(patch, bm)
|
||||
{}
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
emptyPointPatch
|
||||
(
|
||||
const emptyPointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
facePointPatch(patch, bm, index, mapAddressing, reversePointMap)
|
||||
{}
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::NewFrom<emptyPointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
|
||||
@ -73,6 +73,40 @@ public:
|
||||
cyclicPointPatch(patch, bm)
|
||||
{}
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
nonuniformTransformCyclicPointPatch
|
||||
(
|
||||
const nonuniformTransformCyclicPointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
cyclicPointPatch(patch, bm, index, mapAddressing, reversePointMap)
|
||||
{}
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::
|
||||
NewFrom<nonuniformTransformCyclicPointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
|
||||
@ -117,4 +117,20 @@ Foam::processorPointPatch::processorPointPatch
|
||||
{}
|
||||
|
||||
|
||||
Foam::processorPointPatch::processorPointPatch
|
||||
(
|
||||
const processorPointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
coupledFacePointPatch(patch, bm, index, mapAddressing, reversePointMap),
|
||||
procPolyPatch_(refCast<const processorPolyPatch>(patch.patch()))
|
||||
{
|
||||
//? map reverseMeshPoints_ or leave demand-driven
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -111,6 +111,36 @@ public:
|
||||
const pointBoundaryMesh& bm
|
||||
);
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
processorPointPatch
|
||||
(
|
||||
const processorPointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
);
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::NewFrom<processorPointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~processorPointPatch() = default;
|
||||
|
||||
@ -59,6 +59,20 @@ processorCyclicPointPatch::processorCyclicPointPatch
|
||||
{}
|
||||
|
||||
|
||||
Foam::processorCyclicPointPatch::processorCyclicPointPatch
|
||||
(
|
||||
const processorCyclicPointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
processorPointPatch(patch, bm, index, mapAddressing, reversePointMap),
|
||||
procCycPolyPatch_(refCast<const processorCyclicPolyPatch>(patch.patch()))
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
processorCyclicPointPatch::~processorCyclicPointPatch()
|
||||
|
||||
@ -89,6 +89,36 @@ public:
|
||||
const pointBoundaryMesh& bm
|
||||
);
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
processorCyclicPointPatch
|
||||
(
|
||||
const processorCyclicPointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
);
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::NewFrom<processorCyclicPointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~processorCyclicPointPatch();
|
||||
|
||||
@ -75,6 +75,38 @@ public:
|
||||
facePointPatch(patch, bm)
|
||||
{}
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
symmetryPointPatch
|
||||
(
|
||||
const symmetryPointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
):
|
||||
facePointPatch(patch, bm, index, mapAddressing, reversePointMap)
|
||||
{}
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::NewFrom<symmetryPointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
|
||||
@ -58,6 +58,23 @@ Foam::symmetryPlanePointPatch::symmetryPlanePointPatch
|
||||
{}
|
||||
|
||||
|
||||
Foam::symmetryPlanePointPatch::symmetryPlanePointPatch
|
||||
(
|
||||
const symmetryPlanePointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
facePointPatch(patch, bm, index, mapAddressing, reversePointMap),
|
||||
symmetryPlanePolyPatch_
|
||||
(
|
||||
refCast<const symmetryPlanePolyPatch>(patch.patch())
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::symmetryPlanePointPatch::applyConstraint
|
||||
|
||||
@ -74,6 +74,36 @@ public:
|
||||
const pointBoundaryMesh& bm
|
||||
);
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
symmetryPlanePointPatch
|
||||
(
|
||||
const symmetryPlanePointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
);
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::NewFrom<symmetryPlanePointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
|
||||
@ -58,6 +58,20 @@ Foam::wedgePointPatch::wedgePointPatch
|
||||
{}
|
||||
|
||||
|
||||
Foam::wedgePointPatch::wedgePointPatch
|
||||
(
|
||||
const wedgePointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
facePointPatch(patch, bm, index, mapAddressing, reversePointMap),
|
||||
wedgePolyPatch_(refCast<const wedgePolyPatch>(patch.patch()))
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::wedgePointPatch::applyConstraint
|
||||
|
||||
@ -74,6 +74,36 @@ public:
|
||||
const pointBoundaryMesh& bm
|
||||
);
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
wedgePointPatch
|
||||
(
|
||||
const wedgePointPatch& pp,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
);
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::NewFrom<wedgePointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
|
||||
@ -50,4 +50,19 @@ Foam::coupledFacePointPatch::coupledFacePointPatch
|
||||
{}
|
||||
|
||||
|
||||
Foam::coupledFacePointPatch::coupledFacePointPatch
|
||||
(
|
||||
const coupledFacePointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
facePointPatch(patch, bm, index, mapAddressing, reversePointMap),
|
||||
coupledPointPatch(bm),
|
||||
coupledPolyPatch_(refCast<const coupledPolyPatch>(patch.patch()))
|
||||
{}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -91,6 +91,16 @@ public:
|
||||
const pointBoundaryMesh& bm
|
||||
);
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
coupledFacePointPatch
|
||||
(
|
||||
const coupledFacePointPatch& pp,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~coupledFacePointPatch() = default;
|
||||
|
||||
@ -71,6 +71,39 @@ public:
|
||||
:
|
||||
facePointPatch(patch, bm)
|
||||
{}
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
wallPointPatch
|
||||
(
|
||||
const wallPointPatch& patch,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
facePointPatch(patch, bm, index, mapAddressing, reversePointMap)
|
||||
{}
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::NewFrom<wallPointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -84,9 +84,30 @@ Foam::facePointPatch::facePointPatch
|
||||
const pointBoundaryMesh& bm
|
||||
)
|
||||
:
|
||||
pointPatch(bm),
|
||||
pointPatch(p.name(), p.index(), bm, p.physicalType(), p.inGroups()),
|
||||
polyPatch_(p)
|
||||
{}
|
||||
|
||||
|
||||
Foam::facePointPatch::facePointPatch
|
||||
(
|
||||
const facePointPatch& pp,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
pointPatch
|
||||
(
|
||||
pp.name(),
|
||||
index,
|
||||
bm,
|
||||
pp.physicalType(),
|
||||
pp.inGroups()
|
||||
),
|
||||
polyPatch_(pp.patch())
|
||||
{}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -128,6 +128,36 @@ public:
|
||||
const pointBoundaryMesh& pm
|
||||
);
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
facePointPatch
|
||||
(
|
||||
const facePointPatch& pp,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
);
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::NewFrom<facePointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
|
||||
@ -0,0 +1,235 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016 OpenFOAM Foundation
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "meshPointPatch.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "pointMesh.H"
|
||||
#include "pointConstraint.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
defineTypeNameAndDebug(meshPointPatch, 0);
|
||||
|
||||
//- Needs run-time selection table on pointPatch, not facePointPatch
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
pointPatch,
|
||||
meshPointPatch,
|
||||
dictionary
|
||||
);
|
||||
|
||||
static List<pointConstraint> makeConstraints(const vectorField& normals)
|
||||
{
|
||||
List<pointConstraint> cs(normals.size());
|
||||
|
||||
forAll(cs, i)
|
||||
{
|
||||
cs[i].applyConstraint(normals[i]);
|
||||
}
|
||||
return cs;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::meshPointPatch::meshPointPatch
|
||||
(
|
||||
const word& name,
|
||||
const labelUList& meshPoints,
|
||||
const List<pointConstraint>& constraints,
|
||||
const label index,
|
||||
const pointBoundaryMesh& bm,
|
||||
const word& patchType
|
||||
)
|
||||
:
|
||||
pointPatch(name, index, bm, word::null, wordList()),
|
||||
meshPoints_(meshPoints),
|
||||
constraints_(constraints)
|
||||
{
|
||||
if (meshPoints_.size() != constraints_.size())
|
||||
{
|
||||
FatalErrorInFunction << "patch " << name
|
||||
<< " size of meshPoints " << meshPoints_.size()
|
||||
<< " differs from size of constraints " << constraints_.size()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::meshPointPatch::meshPointPatch
|
||||
(
|
||||
const word& name,
|
||||
const labelUList& meshPoints,
|
||||
const vectorField& pointNormals,
|
||||
const label index,
|
||||
const pointBoundaryMesh& bm,
|
||||
const word& patchType
|
||||
)
|
||||
:
|
||||
pointPatch(name, index, bm, word::null, wordList()),
|
||||
meshPoints_(meshPoints),
|
||||
constraints_(makeConstraints(pointNormals))
|
||||
{
|
||||
if (meshPoints_.size() != pointNormals.size())
|
||||
{
|
||||
FatalErrorInFunction << "patch " << name
|
||||
<< " size of meshPoints " << meshPoints_.size()
|
||||
<< " differs from size of pointNormals " << pointNormals.size()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::meshPointPatch::meshPointPatch
|
||||
(
|
||||
const word& name,
|
||||
const dictionary& dict,
|
||||
const label index,
|
||||
const pointBoundaryMesh& bm,
|
||||
const word& patchType
|
||||
)
|
||||
:
|
||||
pointPatch(name, dict, index, bm),
|
||||
meshPoints_(dict.get<labelList>("meshPoints")),
|
||||
constraints_(dict.get<List<pointConstraint>>("constraints"))
|
||||
{}
|
||||
|
||||
|
||||
Foam::meshPointPatch::meshPointPatch
|
||||
(
|
||||
const meshPointPatch& pp,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
meshPointPatch
|
||||
(
|
||||
pp.name(),
|
||||
labelList(reversePointMap, labelList(pp.meshPoints(), mapAddressing)),
|
||||
List<pointConstraint>(pp.constraints(), mapAddressing),
|
||||
index,
|
||||
bm,
|
||||
pp.type()
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::meshPointPatch::movePoints(PstreamBuffers&, const pointField& p)
|
||||
{
|
||||
localPointsPtr_.reset(nullptr);
|
||||
|
||||
// Recalculate the point normals? Something like
|
||||
//if (owner())
|
||||
//{
|
||||
// const SubList<face> subFaces
|
||||
// (
|
||||
// mesh.faces(),
|
||||
// mesh.nBoundaryFaces(),
|
||||
// mesh.nInternalFaces()
|
||||
// );
|
||||
// const primitivePatch pp(subFaces, mesh.points());
|
||||
//
|
||||
//
|
||||
// for (const label pointi : meshPoints())
|
||||
// {
|
||||
// const auto fnd(pp.meshPointMap().find(pointi));
|
||||
// if (fnd)
|
||||
// {
|
||||
// const label patchPointi = fnd();
|
||||
// // Determine point patch equiv
|
||||
//
|
||||
// const auto& point
|
||||
//
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Foam::meshPointPatch::updateMesh(PstreamBuffers&)
|
||||
{
|
||||
localPointsPtr_.reset(nullptr);
|
||||
pointNormalsPtr_.reset(nullptr);
|
||||
// Do what to constraints_? Don't know what the new mesh points are
|
||||
}
|
||||
|
||||
|
||||
const Foam::pointField& Foam::meshPointPatch::localPoints() const
|
||||
{
|
||||
if (!localPointsPtr_)
|
||||
{
|
||||
localPointsPtr_.reset
|
||||
(
|
||||
new pointField
|
||||
(
|
||||
boundaryMesh().mesh().mesh().points(),
|
||||
meshPoints()
|
||||
)
|
||||
);
|
||||
}
|
||||
return localPointsPtr_();
|
||||
}
|
||||
|
||||
|
||||
const Foam::vectorField& Foam::meshPointPatch::pointNormals() const
|
||||
{
|
||||
if (!pointNormalsPtr_)
|
||||
{
|
||||
pointNormalsPtr_.reset(new vectorField(size()));
|
||||
vectorField& pointNormals = pointNormalsPtr_();
|
||||
forAll(constraints_, i)
|
||||
{
|
||||
pointNormals[i] = constraints_[i].second();
|
||||
}
|
||||
}
|
||||
return pointNormalsPtr_();
|
||||
}
|
||||
|
||||
|
||||
void Foam::meshPointPatch::write(Ostream& os) const
|
||||
{
|
||||
pointPatch::write(os);
|
||||
meshPoints().writeEntry("meshPoints", os);
|
||||
constraints().writeEntry("constraints", os);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,213 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016 OpenFOAM Foundation
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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::meshPointPatch
|
||||
|
||||
Description
|
||||
pointPatch with explicitly provided points instead of using the points
|
||||
of a polyPatch.
|
||||
|
||||
Note: does not constrain displacement - is not a constraint patch.
|
||||
|
||||
SourceFiles
|
||||
meshPointPatch.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef meshPointPatch_H
|
||||
#define meshPointPatch_H
|
||||
|
||||
#include "pointPatch.H"
|
||||
#include "polyPatch.H"
|
||||
#include "autoPtr.H"
|
||||
#include "patchIdentifier.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class meshPointPatch Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class meshPointPatch
|
||||
:
|
||||
public pointPatch
|
||||
{
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- No copy construct
|
||||
meshPointPatch(const meshPointPatch&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const meshPointPatch&) = delete;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Data
|
||||
|
||||
//- Explicit mesh points
|
||||
const labelList meshPoints_;
|
||||
|
||||
const List<pointConstraint> constraints_;
|
||||
|
||||
//- Demand-driven local points
|
||||
mutable autoPtr<pointField> localPointsPtr_;
|
||||
|
||||
//- Demand-driven local normals (assumes constructed with pointNormals
|
||||
// or normal-only-constraint)
|
||||
mutable autoPtr<pointField> pointNormalsPtr_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Correct patches after moving points
|
||||
virtual void movePoints(PstreamBuffers&, const pointField&);
|
||||
|
||||
//- Update of the patch topology
|
||||
virtual void updateMesh(PstreamBuffers&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("meshPoint");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
meshPointPatch
|
||||
(
|
||||
const word& name,
|
||||
const labelUList& meshPoints,
|
||||
const List<pointConstraint>& constraints,
|
||||
const label index,
|
||||
const pointBoundaryMesh& bm,
|
||||
const word& patchType
|
||||
);
|
||||
|
||||
//- Construct from single-constraint (i.e. slip, provided normals)
|
||||
meshPointPatch
|
||||
(
|
||||
const word& name,
|
||||
const labelUList& meshPoints,
|
||||
const vectorField& pointNormals,
|
||||
const label index,
|
||||
const pointBoundaryMesh& bm,
|
||||
const word& patchType
|
||||
);
|
||||
|
||||
//- Construct from dictionary
|
||||
meshPointPatch
|
||||
(
|
||||
const word& name,
|
||||
const dictionary& dict,
|
||||
const label index,
|
||||
const pointBoundaryMesh& bm,
|
||||
const word& patchType
|
||||
);
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
meshPointPatch
|
||||
(
|
||||
const meshPointPatch& pp,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
);
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const
|
||||
{
|
||||
return autoPtr<pointPatch>::NewFrom<meshPointPatch>
|
||||
(
|
||||
*this,
|
||||
bm,
|
||||
index,
|
||||
mapAddressing,
|
||||
reversePointMap
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~meshPointPatch() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return size
|
||||
virtual label size() const
|
||||
{
|
||||
return meshPoints().size();
|
||||
}
|
||||
|
||||
//- Return mesh points
|
||||
virtual const labelList& meshPoints() const
|
||||
{
|
||||
return meshPoints_;
|
||||
}
|
||||
|
||||
//- Return constraints
|
||||
virtual const List<pointConstraint>& constraints() const
|
||||
{
|
||||
return constraints_;
|
||||
}
|
||||
|
||||
//- Return pointField of points in patch
|
||||
virtual const pointField& localPoints() const;
|
||||
|
||||
//- Return point unit normals. Assumes single constraint
|
||||
virtual const vectorField& pointNormals() const;
|
||||
|
||||
//- Write the pointPatch data as a dictionary
|
||||
virtual void write(Ostream&) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -6,6 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -31,7 +32,33 @@ License
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(pointPatch, 0);
|
||||
defineTypeNameAndDebug(pointPatch, 0);
|
||||
|
||||
// int pointPatch::disallowGenericPointPatch
|
||||
// (
|
||||
// debug::debugSwitch("disallowGenericPointPatch", 0)
|
||||
// );
|
||||
|
||||
defineRunTimeSelectionTable(pointPatch, dictionary);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::pointPatch::write(Ostream& os) const
|
||||
{
|
||||
os.writeKeyword("type") << type() << token::END_STATEMENT << nl;
|
||||
patchIdentifier::write(os);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||
|
||||
Foam::Ostream& Foam::operator<<(Ostream& os, const pointPatch& p)
|
||||
{
|
||||
p.write(os);
|
||||
os.check("Ostream& operator<<(Ostream& os, const pointPatch& p");
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@ SourceFiles
|
||||
#ifndef Foam_pointPatch_H
|
||||
#define Foam_pointPatch_H
|
||||
|
||||
#include "patchIdentifier.H"
|
||||
#include "labelList.H"
|
||||
#include "vectorField.H"
|
||||
#include "pointField.H"
|
||||
@ -54,6 +55,8 @@ class pointConstraint;
|
||||
class pointPatch;
|
||||
class PstreamBuffers;
|
||||
|
||||
Ostream& operator<<(Ostream&, const pointPatch&);
|
||||
|
||||
//- Store lists of pointPatch as a PtrList
|
||||
typedef PtrList<pointPatch> pointPatchList;
|
||||
|
||||
@ -62,6 +65,8 @@ typedef PtrList<pointPatch> pointPatchList;
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class pointPatch
|
||||
:
|
||||
public patchIdentifier
|
||||
{
|
||||
// Private Data
|
||||
|
||||
@ -114,14 +119,90 @@ public:
|
||||
TypeName("basePatch");
|
||||
|
||||
|
||||
// Declare run-time constructor selection tables
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
pointPatch,
|
||||
dictionary,
|
||||
(
|
||||
const word& name,
|
||||
const dictionary& dict,
|
||||
const label index,
|
||||
const pointBoundaryMesh& bm,
|
||||
const word& patchType
|
||||
),
|
||||
(name, dict, index, bm, patchType)
|
||||
);
|
||||
|
||||
|
||||
// Constructor
|
||||
|
||||
//- Construct from boundary mesh
|
||||
explicit pointPatch(const pointBoundaryMesh& bm)
|
||||
//- Construct from components
|
||||
explicit pointPatch
|
||||
(
|
||||
const word& name,
|
||||
const label index,
|
||||
const pointBoundaryMesh& bm,
|
||||
const word& physicalType,
|
||||
const wordList& inGroups
|
||||
)
|
||||
:
|
||||
patchIdentifier(name, index, physicalType, inGroups),
|
||||
boundaryMesh_(bm)
|
||||
{}
|
||||
|
||||
//- Construct from dictionary
|
||||
explicit pointPatch
|
||||
(
|
||||
const word& name,
|
||||
const dictionary& dict,
|
||||
const label index,
|
||||
const pointBoundaryMesh& bm
|
||||
)
|
||||
:
|
||||
patchIdentifier(name, dict, index),
|
||||
boundaryMesh_(bm)
|
||||
{}
|
||||
|
||||
//- Construct given the original patch and a map
|
||||
explicit pointPatch
|
||||
(
|
||||
const pointPatch& pp,
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
)
|
||||
:
|
||||
patchIdentifier(pp.name(), index, pp.physicalType(), pp.inGroups()),
|
||||
boundaryMesh_(bm)
|
||||
{}
|
||||
|
||||
//- Construct and return a subset clone,
|
||||
//- resetting the point list and boundary mesh
|
||||
virtual autoPtr<pointPatch> clone
|
||||
(
|
||||
const pointBoundaryMesh& bm,
|
||||
const label index,
|
||||
const labelUList& mapAddressing,
|
||||
const labelUList& reversePointMap
|
||||
) const = 0;
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a pointer to a new patch created on freestore. Returns
|
||||
//- null if not found
|
||||
static autoPtr<pointPatch> New
|
||||
(
|
||||
const word& name,
|
||||
const dictionary& dict,
|
||||
const label index,
|
||||
const pointBoundaryMesh&
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~pointPatch() = default;
|
||||
@ -129,15 +210,9 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return name
|
||||
virtual const word& name() const = 0;
|
||||
|
||||
//- Return size
|
||||
virtual label size() const = 0;
|
||||
|
||||
//- Return the index of this patch in the pointBoundaryMesh
|
||||
virtual label index() const = 0;
|
||||
|
||||
//- Return boundaryMesh reference
|
||||
const pointBoundaryMesh& boundaryMesh() const
|
||||
{
|
||||
@ -172,6 +247,14 @@ public:
|
||||
pointConstraint&
|
||||
) const
|
||||
{}
|
||||
|
||||
//- Write the pointPatch data as a dictionary
|
||||
virtual void write(Ostream&) const;
|
||||
|
||||
|
||||
// Ostream Operator
|
||||
|
||||
friend Ostream& operator<<(Ostream&, const pointPatch&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2016 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "pointPatch.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::pointPatch> Foam::pointPatch::New
|
||||
(
|
||||
const word& name,
|
||||
const dictionary& dict,
|
||||
const label index,
|
||||
const pointBoundaryMesh& bm
|
||||
)
|
||||
{
|
||||
// Similar to polyPatchNew but no support for generic since we want it
|
||||
// to fall through to the construct-from-polyPatch
|
||||
DebugInFunction << "Constructing pointPatch" << endl;
|
||||
|
||||
const word patchType(dict.lookup("type"));
|
||||
//dict.readIfPresent("geometricType", patchType);
|
||||
|
||||
auto* ctorPtr = dictionaryConstructorTable(patchType);
|
||||
|
||||
if (!ctorPtr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return autoPtr<pointPatch>(ctorPtr(name, dict, index, bm, patchType));
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1418,6 +1418,9 @@ void Foam::polyBoundaryMesh::reorder
|
||||
patches[patchi].index() = patchi;
|
||||
}
|
||||
|
||||
// Clear group-to-patch addressing. Note: could re-calculate
|
||||
groupIDsPtr_.reset(nullptr);
|
||||
|
||||
if (validBoundary)
|
||||
{
|
||||
updateMesh();
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2013-2015 OpenFOAM Foundation
|
||||
Copyright (C) 2022 OpenCFD Ltd.
|
||||
Copyright (C) 2022,2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -49,8 +49,12 @@ void Foam::symmetryPlanePolyPatch::calcGeometry(PstreamBuffers&)
|
||||
{
|
||||
if (returnReduceOr(size()))
|
||||
{
|
||||
const vectorField& nf = faceNormals();
|
||||
n_ = gAverage(nf);
|
||||
// Instead of using the average unit-normal use an area weighted
|
||||
// average instead. This avoids problem when adding zero-sized
|
||||
// faces since these have a calculated area vector of (0 0 0)
|
||||
const auto& areas = faceAreas();
|
||||
|
||||
n_ = gSum(areas).normalise(ROOTVSMALL);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
@ -60,22 +64,30 @@ void Foam::symmetryPlanePolyPatch::calcGeometry(PstreamBuffers&)
|
||||
|
||||
|
||||
// Check the symmetry plane is planar
|
||||
forAll(nf, facei)
|
||||
forAll(areas, facei)
|
||||
{
|
||||
if (magSqr(n_ - nf[facei]) > SMALL)
|
||||
const scalar a = mag(areas[facei]);
|
||||
|
||||
// Calculate only if non-zero area
|
||||
if (a > ROOTVSMALL)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Symmetry plane '" << name() << "' is not planar."
|
||||
<< endl
|
||||
<< "At local face at "
|
||||
<< primitivePatch::faceCentres()[facei]
|
||||
<< " the normal " << nf[facei]
|
||||
<< " differs from the average normal " << n_
|
||||
<< " by " << magSqr(n_ - nf[facei]) << endl
|
||||
<< "Either split the patch into planar parts"
|
||||
<< " or use the " << symmetryPolyPatch::typeName
|
||||
<< " patch type"
|
||||
<< exit(FatalError);
|
||||
const vector nf(areas[facei]/a);
|
||||
|
||||
if (magSqr(n_ - nf) > SMALL)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Symmetry plane '" << name()
|
||||
<< "' is not planar." << endl
|
||||
<< "At local face at "
|
||||
<< primitivePatch::faceCentres()[facei]
|
||||
<< " the normal " << nf
|
||||
<< " differs from the average normal " << n_
|
||||
<< " by " << magSqr(n_ - nf) << endl
|
||||
<< "Either split the patch into planar parts"
|
||||
<< " or use the " << symmetryPolyPatch::typeName
|
||||
<< " patch type"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,6 +101,7 @@ motionSolvers/displacement/displacement/displacementMotionSolver.C
|
||||
motionSolvers/displacement/interpolation/displacementInterpolationMotionSolver.C
|
||||
motionSolvers/displacement/layeredSolver/displacementLayeredMotionMotionSolver.C
|
||||
motionSolvers/displacement/layeredSolver/pointEdgeStructuredWalk.C
|
||||
motionSolvers/displacement/multiDisplacement/multiDisplacementMotionSolver.C
|
||||
motionSolvers/componentDisplacement/componentDisplacementMotionSolver.C
|
||||
motionSolvers/velocity/velocityMotionSolver.C
|
||||
motionSolvers/velocity/velocityDisplacement/velocityDisplacementMotionSolver.C
|
||||
@ -111,6 +112,23 @@ motionSolvers/displacement/codedPoints0/codedPoints0MotionSolver.C
|
||||
|
||||
motionSolvers/displacement/solidBody/pointPatchFields/derived/solidBodyMotionDisplacement/solidBodyMotionDisplacementPointPatchVectorField.C
|
||||
|
||||
pointSmoothing = motionSolvers/displacement/pointSmoothing
|
||||
$(pointSmoothing)/displacementPointSmoothingMotionSolver.C
|
||||
/*
|
||||
$(pointSmoothing)/displacementPointSmoothingMotionSolver2.C
|
||||
$(pointSmoothing)/displacementPointSmoothingMotionSolver3.C
|
||||
*/
|
||||
$(pointSmoothing)/hexMeshSmootherMotionSolver.C
|
||||
$(pointSmoothing)/displacementSmartPointSmoothingMotionSolver.C
|
||||
|
||||
pointSmoothers = $(pointSmoothing)/pointSmoothers
|
||||
$(pointSmoothers)/pointSmoother/pointSmoother.C
|
||||
$(pointSmoothers)/equipotentialPointSmoother/equipotentialPointSmoother.C
|
||||
$(pointSmoothers)/geometricElementTransformPointSmoother/geometricElementTransformPointSmoother.C
|
||||
$(pointSmoothers)/geometricElementTransformPointSmoother/cellPointConnectivity/cellPointConnectivity.C
|
||||
$(pointSmoothers)/laplacianPointSmoother/laplacianPointSmoother.C
|
||||
$(pointSmoothers)/laplacianPointSmoother/laplacianConstraintPointSmoother.C
|
||||
|
||||
createShellMesh/createShellMesh.C
|
||||
|
||||
extrudePatchMesh/extrudePatchMesh.C
|
||||
|
||||
@ -57,7 +57,7 @@ Foam::displacementMotionSolver::displacementMotionSolver
|
||||
IOobject::MUST_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
pointMesh::New(mesh)
|
||||
pointMesh::New(mesh, Foam::IOobject::READ_IF_PRESENT)
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
@ -0,0 +1,271 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "multiDisplacementMotionSolver.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(multiDisplacementMotionSolver, 0);
|
||||
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
motionSolver,
|
||||
multiDisplacementMotionSolver,
|
||||
dictionary
|
||||
);
|
||||
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
displacementMotionSolver,
|
||||
multiDisplacementMotionSolver,
|
||||
displacement
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::multiDisplacementMotionSolver::multiDisplacementMotionSolver
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const IOdictionary& dict
|
||||
)
|
||||
:
|
||||
displacementMotionSolver(mesh, dict, typeName),
|
||||
curPoints_(mesh.points())
|
||||
{
|
||||
// Make pointDisplacement is not registered since all lower levels
|
||||
// have a pointDisplacement as well.
|
||||
pointDisplacement().checkOut();
|
||||
|
||||
label i = 0;
|
||||
|
||||
const dictionary& solverDict = dict.subDict("solvers");
|
||||
|
||||
motionSolvers_.setSize(solverDict.size());
|
||||
|
||||
for (const entry& dEntry : solverDict)
|
||||
{
|
||||
if (dEntry.isDict())
|
||||
{
|
||||
IOobject io(dict);
|
||||
io.readOpt(IOobject::NO_READ);
|
||||
io.writeOpt(IOobject::AUTO_WRITE);
|
||||
io.rename(dEntry.dict().dictName());
|
||||
|
||||
IOdictionary IOsolverDict
|
||||
(
|
||||
io,
|
||||
dEntry.dict()
|
||||
);
|
||||
|
||||
auto* msPtr = motionSolver::New(mesh, IOsolverDict).ptr();
|
||||
|
||||
motionSolvers_.set
|
||||
(
|
||||
i,
|
||||
dynamic_cast<displacementMotionSolver*>(msPtr)
|
||||
);
|
||||
|
||||
// Avoid conflicts with multiple registrations
|
||||
motionSolvers_[i].pointDisplacement().checkOut();
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
motionSolvers_.setSize(i);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
FatalErrorInFunction << "No displacementMotionSolvers in dictionary "
|
||||
<< dict << exit(FatalError);
|
||||
}
|
||||
|
||||
// Re-register so only our 'pointDisplacement' is on the database.
|
||||
pointDisplacement().checkIn();
|
||||
}
|
||||
|
||||
|
||||
Foam::multiDisplacementMotionSolver::
|
||||
multiDisplacementMotionSolver
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const IOdictionary& dict,
|
||||
const pointVectorField& pointDisplacement,
|
||||
const pointIOField& points0
|
||||
)
|
||||
:
|
||||
displacementMotionSolver(mesh, dict, pointDisplacement, points0, typeName),
|
||||
curPoints_(mesh.points())
|
||||
{
|
||||
// Make pointDisplacement is not registered since all lower levels
|
||||
// have a pointDisplacement as well.
|
||||
this->pointDisplacement().checkOut();
|
||||
|
||||
label i = 0;
|
||||
|
||||
const dictionary& solverDict = dict.subDict("solvers");
|
||||
|
||||
motionSolvers_.setSize(solverDict.size());
|
||||
|
||||
for (const entry& dEntry : solverDict)
|
||||
{
|
||||
if (dEntry.isDict())
|
||||
{
|
||||
IOobject io(dict);
|
||||
io.readOpt(IOobject::NO_READ);
|
||||
io.writeOpt(IOobject::AUTO_WRITE);
|
||||
io.rename(dEntry.dict().dictName());
|
||||
|
||||
IOdictionary IOsolverDict
|
||||
(
|
||||
io,
|
||||
dEntry.dict()
|
||||
);
|
||||
|
||||
auto msPtr = displacementMotionSolver::New
|
||||
(
|
||||
dEntry.keyword(),
|
||||
mesh,
|
||||
IOsolverDict,
|
||||
pointDisplacement,
|
||||
points0
|
||||
);
|
||||
|
||||
// Avoid conflicts with multiple registrations
|
||||
msPtr->pointDisplacement().checkOut();
|
||||
|
||||
motionSolvers_.set(i++, msPtr);
|
||||
}
|
||||
}
|
||||
motionSolvers_.setSize(i);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
FatalErrorInFunction << "No displacementMotionSolvers in dictionary "
|
||||
<< dict << exit(FatalError);
|
||||
}
|
||||
|
||||
// Re-register so only our 'pointDisplacement' is on the database.
|
||||
this->pointDisplacement().checkIn();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::tmp<Foam::pointField>
|
||||
Foam::multiDisplacementMotionSolver::curPoints() const
|
||||
{
|
||||
return curPoints_;
|
||||
}
|
||||
|
||||
|
||||
void Foam::multiDisplacementMotionSolver::solve()
|
||||
{
|
||||
if (!motionSolvers_.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Bit tricky:
|
||||
// - make sure only one copy of pointDisplacement is registered. This is
|
||||
// for if cellDisplacement tries to look up the pointDisplacement it
|
||||
// looks up its version. Or maybe we always should use our own version
|
||||
// only?
|
||||
// - copy the last set of calculated points into our copy (curPoints_)
|
||||
// - move the mesh to update the faceCentres, cellCentres etc. This assumes
|
||||
// that we can call movePoints() multiple times inside a time step.
|
||||
// (note that this is supported in pimpleFoam with the
|
||||
// moveMeshOuterCorrectors option)
|
||||
|
||||
pointDisplacement().checkOut();
|
||||
|
||||
// Doing first motion solver
|
||||
motionSolvers_[0].pointDisplacement().checkIn();
|
||||
// Take over my bc values
|
||||
motionSolvers_[0].pointDisplacement() == pointDisplacement();
|
||||
|
||||
motionSolvers_[0].solve();
|
||||
motionSolvers_[0].pointDisplacement().checkOut();
|
||||
|
||||
// Update my values
|
||||
curPoints_ = motionSolvers_[0].curPoints();
|
||||
pointDisplacement() == motionSolvers_[0].pointDisplacement();
|
||||
|
||||
for (label i = 1; i < motionSolvers_.size(); i++)
|
||||
{
|
||||
// Doing other motion solvers using new locations/face/cellCentres etc.
|
||||
const_cast<polyMesh&>(mesh()).movePoints(curPoints_);
|
||||
motionSolvers_[i].pointDisplacement().checkIn();
|
||||
|
||||
// Take over my bc values
|
||||
motionSolvers_[i].pointDisplacement() == pointDisplacement();
|
||||
|
||||
motionSolvers_[i].solve();
|
||||
motionSolvers_[i].pointDisplacement().checkOut();
|
||||
|
||||
// Update my values
|
||||
curPoints_ = motionSolvers_[i].curPoints();
|
||||
pointDisplacement() == motionSolvers_[i].pointDisplacement();
|
||||
}
|
||||
|
||||
pointDisplacement().checkIn();
|
||||
|
||||
// Push my pointDisplacement onto all motionSolvers
|
||||
for (auto& ms : motionSolvers_)
|
||||
{
|
||||
ms.pointDisplacement() == pointDisplacement();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::multiDisplacementMotionSolver::movePoints
|
||||
(
|
||||
const pointField& newPoints
|
||||
)
|
||||
{
|
||||
curPoints_ = newPoints;
|
||||
for (auto& ms : motionSolvers_)
|
||||
{
|
||||
ms.movePoints(newPoints);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::multiDisplacementMotionSolver::updateMesh(const mapPolyMesh& mpm)
|
||||
{
|
||||
for (auto& ms : motionSolvers_)
|
||||
{
|
||||
ms.updateMesh(mpm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,170 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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::multiDisplacementMotionSolver
|
||||
|
||||
Group
|
||||
grpMeshMotionSolvers
|
||||
|
||||
Description
|
||||
Mesh motion solver for a polyMesh. Applies multiple (displacement) motion
|
||||
solvers in order.
|
||||
|
||||
Not very efficient : all displacementMotionSolvers store a copy
|
||||
of the initial points (points0) and the displacement (pointDisplacement
|
||||
or also cellDisplacement).
|
||||
Used to combine large-scale, implicit displacement smoothing (e.g.
|
||||
displacementLaplacian) with point smoothing.
|
||||
|
||||
Usage
|
||||
Example of the dynamicMeshDict specification:
|
||||
\verbatim
|
||||
motionSolver multiDisplacement;
|
||||
solvers
|
||||
{
|
||||
// Solve finite volume laplacian to efficiently smooth displacement
|
||||
// (not point locations)
|
||||
displacementLaplacian
|
||||
{
|
||||
motionSolver displacementLaplacian;
|
||||
diffusivity uniform;
|
||||
}
|
||||
|
||||
// Apply few iterations of smoothing of point locations
|
||||
displacementPointSmoothing
|
||||
{
|
||||
motionSolver displacementPointSmoothing;
|
||||
pointSmoother laplacian;
|
||||
nPointSmootherIter 10;
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Note
|
||||
When using displacementLaplacian: the default behaviour for the
|
||||
cellDisplacement is to apply fixed value boundary conditions (by averaging
|
||||
point values) only to those pointDisplacement boundary conditions that
|
||||
are fixed value. Quite a few point boundary conditions (e.g. surfaceSlip,
|
||||
edgeSlip) are not so require an explicitly provided cellDisplacement
|
||||
field with 'cellMotion' boundary conditions for those patches.
|
||||
|
||||
SourceFiles
|
||||
isplacementMultiMotionSolver.C
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_multiDisplacementMotionSolver_H
|
||||
#define Foam_multiDisplacementMotionSolver_H
|
||||
|
||||
#include "displacementMotionSolver.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class multiDisplacementMotionSolver Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class multiDisplacementMotionSolver
|
||||
:
|
||||
public displacementMotionSolver
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Current points
|
||||
pointField curPoints_;
|
||||
|
||||
//- List of motion solvers
|
||||
PtrList<displacementMotionSolver> motionSolvers_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- No copy construct
|
||||
multiDisplacementMotionSolver
|
||||
(
|
||||
const multiDisplacementMotionSolver&
|
||||
) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const multiDisplacementMotionSolver&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("multiDisplacement");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from polyMesh and IOdictionary
|
||||
multiDisplacementMotionSolver
|
||||
(
|
||||
const polyMesh&,
|
||||
const IOdictionary&
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
multiDisplacementMotionSolver
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const IOdictionary& dict,
|
||||
const pointVectorField& pointDisplacement,
|
||||
const pointIOField& points0
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
~multiDisplacementMotionSolver() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Provide current points for motion
|
||||
virtual tmp<pointField> curPoints() const;
|
||||
|
||||
//- Solve for motion
|
||||
virtual void solve();
|
||||
|
||||
//- Update local data for geometry changes
|
||||
virtual void movePoints(const pointField&);
|
||||
|
||||
//- Update local data for topology changes
|
||||
virtual void updateMesh(const mapPolyMesh&);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,434 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "displacementPointSmoothingMotionSolver.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "syncTools.H"
|
||||
#include "pointConstraints.H"
|
||||
#include "motionSmootherAlgo.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(displacementPointSmoothingMotionSolver, 0);
|
||||
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
motionSolver,
|
||||
displacementPointSmoothingMotionSolver,
|
||||
dictionary
|
||||
);
|
||||
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
displacementMotionSolver,
|
||||
displacementPointSmoothingMotionSolver,
|
||||
displacement
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::displacementPointSmoothingMotionSolver::markAffectedFaces
|
||||
(
|
||||
const labelHashSet& changedFaces,
|
||||
labelHashSet& affectedFaces
|
||||
)
|
||||
{
|
||||
PackedBoolList affectedPoints(mesh().nPoints(), false);
|
||||
|
||||
forAllConstIter(labelHashSet, changedFaces, iter)
|
||||
{
|
||||
const label faceI(iter.key());
|
||||
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
affectedPoints[pointI] = true;
|
||||
}
|
||||
}
|
||||
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh(),
|
||||
affectedPoints,
|
||||
orEqOp<unsigned int>(),
|
||||
0U
|
||||
);
|
||||
|
||||
forAll(affectedPoints, pointI)
|
||||
{
|
||||
if (affectedPoints[pointI])
|
||||
{
|
||||
const labelList& pCells(mesh().pointCells()[pointI]);
|
||||
|
||||
forAll(pCells, pointCellI)
|
||||
{
|
||||
const label cellI(pCells[pointCellI]);
|
||||
|
||||
const labelList& cFaces(mesh().cells()[cellI]);
|
||||
|
||||
affectedFaces.insert(cFaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::displacementPointSmoothingMotionSolver::relax()
|
||||
{
|
||||
if
|
||||
(
|
||||
(relaxationFactors_.size() == 0)
|
||||
|| (relaxationFactors_.size() == 1 && relaxationFactors_[0] == 1.0)
|
||||
)
|
||||
{
|
||||
relaxedPoints_ = points0() + pointDisplacement().internalField();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const pointField oldRelaxedPoints(relaxedPoints_);
|
||||
|
||||
labelHashSet affectedFaces(facesToMove_);
|
||||
|
||||
// Create a list of relaxation levels
|
||||
// -1 indicates a point which is not to be moved
|
||||
// 0 is the starting value for a moving point
|
||||
labelList relaxationLevel(mesh().nPoints(), -1);
|
||||
forAllConstIter(labelHashSet, affectedFaces, iter)
|
||||
{
|
||||
const label faceI(iter.key());
|
||||
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
relaxationLevel[pointI] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh(),
|
||||
relaxationLevel,
|
||||
maxEqOp<label>(),
|
||||
label(-1)
|
||||
);
|
||||
|
||||
// Loop whilst relaxation levels are being incremented
|
||||
bool complete(false);
|
||||
while (!complete)
|
||||
{
|
||||
//scalar nAffectedFaces(affectedFaces.size());
|
||||
//reduce(nAffectedFaces, sumOp<scalar>());
|
||||
//Info << " Moving " << nAffectedFaces << " faces" << endl;
|
||||
|
||||
// Move the points
|
||||
forAll(relaxationLevel, pointI)
|
||||
{
|
||||
if (relaxationLevel[pointI] >= 0)
|
||||
{
|
||||
const scalar x
|
||||
(
|
||||
relaxationFactors_[relaxationLevel[pointI]]
|
||||
);
|
||||
|
||||
relaxedPoints_[pointI] =
|
||||
(1 - x)*oldRelaxedPoints[pointI]
|
||||
+ x*(points0()[pointI] + pointDisplacement()[pointI]);
|
||||
}
|
||||
}
|
||||
|
||||
// Get a list of changed faces
|
||||
labelHashSet markedFaces;
|
||||
markAffectedFaces(affectedFaces, markedFaces);
|
||||
labelList markedFacesList(markedFaces.toc());
|
||||
|
||||
// Update the geometry
|
||||
meshGeometry_.correct(relaxedPoints_, markedFacesList);
|
||||
|
||||
// Check the modified face quality
|
||||
markedFaces.clear();
|
||||
motionSmootherAlgo::checkMesh
|
||||
(
|
||||
false,
|
||||
meshQualityDict_,
|
||||
meshGeometry_,
|
||||
relaxedPoints_,
|
||||
markedFacesList,
|
||||
markedFaces
|
||||
);
|
||||
|
||||
// Mark the affected faces
|
||||
affectedFaces.clear();
|
||||
markAffectedFaces(markedFaces, affectedFaces);
|
||||
|
||||
// Increase relaxation and check convergence
|
||||
PackedBoolList pointsToRelax(mesh().nPoints(), false);
|
||||
complete = true;
|
||||
forAllConstIter(labelHashSet, affectedFaces, iter)
|
||||
{
|
||||
const label faceI(iter.key());
|
||||
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
pointsToRelax[pointI] = true;
|
||||
}
|
||||
}
|
||||
|
||||
forAll(pointsToRelax, pointI)
|
||||
{
|
||||
if
|
||||
(
|
||||
pointsToRelax[pointI]
|
||||
&& (relaxationLevel[pointI] < relaxationFactors_.size() - 1)
|
||||
)
|
||||
{
|
||||
++ relaxationLevel[pointI];
|
||||
|
||||
complete = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronise relaxation levels
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh(),
|
||||
relaxationLevel,
|
||||
maxEqOp<label>(),
|
||||
label(0)
|
||||
);
|
||||
|
||||
// Synchronise completion
|
||||
reduce(complete, andOp<bool>());
|
||||
}
|
||||
|
||||
// Check for convergence
|
||||
bool converged(true);
|
||||
forAll(mesh().faces(), faceI)
|
||||
{
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
if (relaxationLevel[pointI] > 0)
|
||||
{
|
||||
facesToMove_.insert(faceI);
|
||||
|
||||
converged = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Syncronise convergence
|
||||
reduce(converged, andOp<bool>());
|
||||
|
||||
//if (converged)
|
||||
//{
|
||||
// Info<< "... Converged" << endl << endl;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// Info<< "... Not converged" << endl << endl;
|
||||
//}
|
||||
|
||||
return converged;
|
||||
}
|
||||
|
||||
|
||||
void Foam::displacementPointSmoothingMotionSolver::setFacesToMove
|
||||
(
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
if (dict.getOrDefault<bool>("moveInternalFaces", true))
|
||||
{
|
||||
facesToMove_.resize(2*mesh().nFaces());
|
||||
forAll(mesh().faces(), faceI)
|
||||
{
|
||||
facesToMove_.insert(faceI);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
facesToMove_.resize(2*(mesh().nBoundaryFaces()));
|
||||
for
|
||||
(
|
||||
label faceI = mesh().nInternalFaces();
|
||||
faceI < mesh().nFaces();
|
||||
++ faceI
|
||||
)
|
||||
{
|
||||
facesToMove_.insert(faceI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::displacementPointSmoothingMotionSolver::
|
||||
displacementPointSmoothingMotionSolver
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const IOdictionary& dict
|
||||
)
|
||||
:
|
||||
displacementMotionSolver(mesh, dict, typeName),
|
||||
meshGeometry_(mesh),
|
||||
pointSmoother_(pointSmoother::New(mesh, coeffDict())),
|
||||
nPointSmootherIter_
|
||||
(
|
||||
readLabel(coeffDict().lookup("nPointSmootherIter"))
|
||||
),
|
||||
relaxedPoints_(mesh.points())
|
||||
{
|
||||
if (coeffDict().readIfPresent("relaxationFactors", relaxationFactors_))
|
||||
{
|
||||
meshQualityDict_ = coeffDict().subDict("meshQuality");
|
||||
}
|
||||
setFacesToMove(coeffDict());
|
||||
}
|
||||
|
||||
|
||||
Foam::displacementPointSmoothingMotionSolver::
|
||||
displacementPointSmoothingMotionSolver
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const IOdictionary& dict,
|
||||
const pointVectorField& pointDisplacement,
|
||||
const pointIOField& points0
|
||||
)
|
||||
:
|
||||
displacementMotionSolver(mesh, dict, pointDisplacement, points0, typeName),
|
||||
meshGeometry_(mesh),
|
||||
pointSmoother_
|
||||
(
|
||||
pointSmoother::New
|
||||
(
|
||||
mesh,
|
||||
coeffDict()
|
||||
)
|
||||
),
|
||||
nPointSmootherIter_
|
||||
(
|
||||
readLabel(coeffDict().lookup("nPointSmootherIter"))
|
||||
),
|
||||
relaxedPoints_(mesh.points())
|
||||
{
|
||||
if (coeffDict().readIfPresent("relaxationFactors", relaxationFactors_))
|
||||
{
|
||||
meshQualityDict_ = coeffDict().subDict("meshQuality");
|
||||
}
|
||||
setFacesToMove(coeffDict());
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::tmp<Foam::pointField>
|
||||
Foam::displacementPointSmoothingMotionSolver::curPoints() const
|
||||
{
|
||||
//Note: twoDCorrect already done by ::solve
|
||||
|
||||
return relaxedPoints_;
|
||||
}
|
||||
|
||||
|
||||
void Foam::displacementPointSmoothingMotionSolver::solve()
|
||||
{
|
||||
//Pout<< "time:" << mesh().time().timeName()
|
||||
// << " mesh faceCentres:" << gAverage(mesh().faceCentres())
|
||||
// << " mesh cellCentres:" << gAverage(mesh().cellCentres())
|
||||
// << endl;
|
||||
|
||||
movePoints(curPoints());
|
||||
|
||||
// Update values on pointDisplacement
|
||||
pointDisplacement().boundaryFieldRef().updateCoeffs();
|
||||
|
||||
// Extend: face-to-point-to-cell-to-faces
|
||||
labelHashSet affectedFaces;
|
||||
markAffectedFaces(facesToMove_, affectedFaces);
|
||||
|
||||
for(label i = 0; i < nPointSmootherIter_; i ++)
|
||||
{
|
||||
meshGeometry_.correct
|
||||
(
|
||||
points0() + pointDisplacement().internalField(),
|
||||
affectedFaces.toc()
|
||||
);
|
||||
//Pout<< "iter:" << i
|
||||
// << " faceCentres:" << gAverage(meshGeometry_.faceCentres())
|
||||
// << " cellCentres:" << gAverage(meshGeometry_.cellCentres())
|
||||
// << endl;
|
||||
|
||||
pointSmoother_->update
|
||||
(
|
||||
affectedFaces.toc(),
|
||||
points0(),
|
||||
points0() + pointDisplacement().internalField(),
|
||||
meshGeometry_,
|
||||
pointDisplacement()
|
||||
);
|
||||
}
|
||||
|
||||
relax();
|
||||
|
||||
twoDCorrectPoints(relaxedPoints_);
|
||||
|
||||
// Update pointDisplacement for actual relaxedPoints. Keep fixed-value
|
||||
// bcs.
|
||||
pointDisplacement().primitiveFieldRef() = relaxedPoints_-points0();
|
||||
|
||||
// Adhere to multi-point constraints
|
||||
const pointConstraints& pcs =
|
||||
pointConstraints::New(pointDisplacement().mesh());
|
||||
pcs.constrainDisplacement(pointDisplacement(), false);
|
||||
|
||||
// Update relaxedPoints to take constraints into account
|
||||
relaxedPoints_ = points0() + pointDisplacement().internalField();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,149 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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::displacementPointSmoothingMotionSolver
|
||||
|
||||
Description
|
||||
Quality-based under-relaxation for run-time selectable point smoothing.
|
||||
|
||||
SourceFiles
|
||||
displacementPointSmoothingMotionSolver.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef displacementPointSmoothingMotionSolver_H
|
||||
#define displacementPointSmoothingMotionSolver_H
|
||||
|
||||
#include "displacementMotionSolver.H"
|
||||
#include "pointSmoother.H"
|
||||
#include "polyMeshGeometry.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class displacementPointSmoothingMotionSolver Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class displacementPointSmoothingMotionSolver
|
||||
:
|
||||
public displacementMotionSolver
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Part-updatable mesh geometry
|
||||
polyMeshGeometry meshGeometry_;
|
||||
|
||||
//- Point smoothing method
|
||||
autoPtr<pointSmoother> pointSmoother_;
|
||||
|
||||
//- Number of point smoother iterations per timestep
|
||||
const label nPointSmootherIter_;
|
||||
|
||||
|
||||
// Mesh quality based relaxation of smoothed position
|
||||
|
||||
//- Relaxation factors to use in each iteration
|
||||
scalarList relaxationFactors_;
|
||||
|
||||
//- Relaxed point field
|
||||
pointField relaxedPoints_;
|
||||
|
||||
//- Set of the faces which are to be moved
|
||||
labelHashSet facesToMove_;
|
||||
|
||||
//- Mesh quality dictionary
|
||||
dictionary meshQualityDict_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Mark affected faces
|
||||
void markAffectedFaces
|
||||
(
|
||||
const labelHashSet& changedFaces,
|
||||
labelHashSet& affectedFaces
|
||||
);
|
||||
|
||||
//- Relax the points
|
||||
bool relax();
|
||||
|
||||
//- Set all the faces to be moved
|
||||
void virtual setFacesToMove(const dictionary&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("displacementPointSmoothing");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from a polyMesh and an IOdictionary
|
||||
displacementPointSmoothingMotionSolver
|
||||
(
|
||||
const polyMesh&,
|
||||
const IOdictionary&
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
displacementPointSmoothingMotionSolver
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const IOdictionary& dict,
|
||||
const pointVectorField& pointDisplacement,
|
||||
const pointIOField& points0
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~displacementPointSmoothingMotionSolver() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return point location obtained from the current motion field
|
||||
virtual tmp<pointField> curPoints() const;
|
||||
|
||||
//- Solve for motion
|
||||
virtual void solve();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,746 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "displacementSmartPointSmoothingMotionSolver.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "syncTools.H"
|
||||
#include "pointConstraints.H"
|
||||
#include "motionSmootherAlgo.H"
|
||||
|
||||
//#include "fvMesh.H"
|
||||
//#include "fvGeometryScheme.H"
|
||||
#include "OBJstream.H"
|
||||
#include "emptyPointPatchFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(displacementSmartPointSmoothingMotionSolver, 0);
|
||||
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
motionSolver,
|
||||
displacementSmartPointSmoothingMotionSolver,
|
||||
dictionary
|
||||
);
|
||||
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
displacementMotionSolver,
|
||||
displacementSmartPointSmoothingMotionSolver,
|
||||
displacement
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::displacementSmartPointSmoothingMotionSolver::markAffectedFaces
|
||||
(
|
||||
const labelHashSet& changedFaces,
|
||||
labelHashSet& affectedFaces
|
||||
)
|
||||
{
|
||||
PackedBoolList affectedPoints(mesh().nPoints(), false);
|
||||
|
||||
forAllConstIter(labelHashSet, changedFaces, iter)
|
||||
{
|
||||
const label faceI(iter.key());
|
||||
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
affectedPoints[pointI] = true;
|
||||
}
|
||||
}
|
||||
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh(),
|
||||
affectedPoints,
|
||||
orEqOp<unsigned int>(),
|
||||
0U
|
||||
);
|
||||
|
||||
forAll(affectedPoints, pointI)
|
||||
{
|
||||
if (affectedPoints[pointI])
|
||||
{
|
||||
const labelList& pCells(mesh().pointCells()[pointI]);
|
||||
|
||||
forAll(pCells, pointCellI)
|
||||
{
|
||||
const label cellI(pCells[pointCellI]);
|
||||
|
||||
const labelList& cFaces(mesh().cells()[cellI]);
|
||||
|
||||
affectedFaces.insert(cFaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::displacementSmartPointSmoothingMotionSolver::relax()
|
||||
{
|
||||
if
|
||||
(
|
||||
(relaxationFactors_.size() == 0)
|
||||
|| (relaxationFactors_.size() == 1 && relaxationFactors_[0] == 1.0)
|
||||
)
|
||||
{
|
||||
relaxedPoints_ = points0() + pointDisplacement().internalField();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const pointField oldRelaxedPoints(relaxedPoints_);
|
||||
|
||||
labelHashSet affectedFaces(facesToMove_);
|
||||
|
||||
// Create a list of relaxation levels
|
||||
// -1 indicates a point which is not to be moved
|
||||
// 0 is the starting value for a moving point
|
||||
labelList relaxationLevel(mesh().nPoints(), -1);
|
||||
forAllConstIter(labelHashSet, affectedFaces, iter)
|
||||
{
|
||||
const label faceI(iter.key());
|
||||
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
relaxationLevel[pointI] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh(),
|
||||
relaxationLevel,
|
||||
maxEqOp<label>(),
|
||||
label(-1)
|
||||
);
|
||||
|
||||
// Loop whilst relaxation levels are being incremented
|
||||
bool complete(false);
|
||||
while (!complete)
|
||||
{
|
||||
//scalar nAffectedFaces(affectedFaces.size());
|
||||
//reduce(nAffectedFaces, sumOp<scalar>());
|
||||
//Info << " Moving " << nAffectedFaces << " faces" << endl;
|
||||
|
||||
// Move the points
|
||||
forAll(relaxationLevel, pointI)
|
||||
{
|
||||
if (relaxationLevel[pointI] >= 0)
|
||||
{
|
||||
const scalar x
|
||||
(
|
||||
relaxationFactors_[relaxationLevel[pointI]]
|
||||
);
|
||||
|
||||
relaxedPoints_[pointI] =
|
||||
(1 - x)*oldRelaxedPoints[pointI]
|
||||
+ x*(points0()[pointI] + pointDisplacement()[pointI]);
|
||||
}
|
||||
}
|
||||
|
||||
// Get a list of changed faces
|
||||
labelHashSet markedFaces;
|
||||
markAffectedFaces(affectedFaces, markedFaces);
|
||||
labelList markedFacesList(markedFaces.toc());
|
||||
|
||||
// Update the geometry
|
||||
meshGeometry_.correct(relaxedPoints_, markedFacesList);
|
||||
|
||||
// Check the modified face quality
|
||||
if (false)
|
||||
{
|
||||
// Use snappyHexMesh compatible checks
|
||||
markedFaces.clear();
|
||||
motionSmootherAlgo::checkMesh
|
||||
(
|
||||
false,
|
||||
meshQualityDict_,
|
||||
meshGeometry_,
|
||||
relaxedPoints_,
|
||||
markedFacesList,
|
||||
markedFaces
|
||||
);
|
||||
|
||||
// Mark the affected faces
|
||||
affectedFaces.clear();
|
||||
markAffectedFaces(markedFaces, affectedFaces);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use pointSmoother specific
|
||||
tmp<scalarField> tfaceQ
|
||||
(
|
||||
pointUntangler_->faceQuality
|
||||
(
|
||||
relaxedPoints_,
|
||||
meshGeometry_.faceCentres(),
|
||||
meshGeometry_.faceAreas(),
|
||||
meshGeometry_.cellCentres(),
|
||||
meshGeometry_.cellVolumes()
|
||||
)
|
||||
);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
MinMax<scalar> range(gMinMax(tfaceQ()));
|
||||
Pout<< " min:" << range.min() << nl
|
||||
<< " max:" << range.max() << endl;
|
||||
}
|
||||
|
||||
labelList order;
|
||||
Foam::sortedOrder(tfaceQ(), order);
|
||||
|
||||
label nUntangle = 0;
|
||||
forAll(order, i)
|
||||
{
|
||||
if (tfaceQ()[order[i]] > untangleQ_)
|
||||
{
|
||||
nUntangle = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
affectedFaces = labelList(SubList<label>(order, nUntangle));
|
||||
}
|
||||
|
||||
// Increase relaxation and check convergence
|
||||
PackedBoolList pointsToRelax(mesh().nPoints(), false);
|
||||
complete = true;
|
||||
forAllConstIter(labelHashSet, affectedFaces, iter)
|
||||
{
|
||||
const label faceI(iter.key());
|
||||
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
pointsToRelax[pointI] = true;
|
||||
}
|
||||
}
|
||||
|
||||
forAll(pointsToRelax, pointI)
|
||||
{
|
||||
if
|
||||
(
|
||||
pointsToRelax[pointI]
|
||||
&& (relaxationLevel[pointI] < relaxationFactors_.size() - 1)
|
||||
)
|
||||
{
|
||||
++ relaxationLevel[pointI];
|
||||
|
||||
complete = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronise relaxation levels
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh(),
|
||||
relaxationLevel,
|
||||
maxEqOp<label>(),
|
||||
label(0)
|
||||
);
|
||||
|
||||
// Synchronise completion
|
||||
reduce(complete, andOp<bool>());
|
||||
}
|
||||
|
||||
// Check for convergence
|
||||
bool converged(true);
|
||||
forAll(mesh().faces(), faceI)
|
||||
{
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
if (relaxationLevel[pointI] > 0)
|
||||
{
|
||||
facesToMove_.insert(faceI);
|
||||
|
||||
converged = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Syncronise convergence
|
||||
reduce(converged, andOp<bool>());
|
||||
|
||||
//if (converged)
|
||||
//{
|
||||
// Info<< "... Converged" << endl << endl;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// Info<< "... Not converged" << endl << endl;
|
||||
//}
|
||||
|
||||
return converged;
|
||||
}
|
||||
|
||||
|
||||
void Foam::displacementSmartPointSmoothingMotionSolver::setFacesToMove
|
||||
(
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
if (dict.getOrDefault<bool>("moveInternalFaces", true))
|
||||
{
|
||||
facesToMove_.resize(2*mesh().nFaces());
|
||||
forAll(mesh().faces(), faceI)
|
||||
{
|
||||
facesToMove_.insert(faceI);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
facesToMove_.resize(2*(mesh().nBoundaryFaces()));
|
||||
for
|
||||
(
|
||||
label faceI = mesh().nInternalFaces();
|
||||
faceI < mesh().nFaces();
|
||||
++ faceI
|
||||
)
|
||||
{
|
||||
facesToMove_.insert(faceI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::displacementSmartPointSmoothingMotionSolver::emptyCorrectPoints
|
||||
(
|
||||
pointVectorField& pointDisplacement
|
||||
)
|
||||
{
|
||||
// Assume empty point patches are already in correct location
|
||||
// so knock out any off-plane displacement.
|
||||
auto& fld = pointDisplacement.primitiveFieldRef();
|
||||
for (const auto& ppf : pointDisplacement.boundaryField())
|
||||
{
|
||||
if (isA<emptyPointPatchVectorField>(ppf))
|
||||
{
|
||||
const auto& mp = ppf.patch().meshPoints();
|
||||
forAll(mp, i)
|
||||
{
|
||||
pointConstraint pc;
|
||||
ppf.patch().applyConstraint(i, pc);
|
||||
fld[mp[i]] = pc.constrainDisplacement(fld[mp[i]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pointField wantedPoints(points0() + fld);
|
||||
twoDCorrectPoints(wantedPoints);
|
||||
fld = wantedPoints-points0();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::displacementSmartPointSmoothingMotionSolver::
|
||||
displacementSmartPointSmoothingMotionSolver
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const IOdictionary& dict
|
||||
)
|
||||
:
|
||||
displacementMotionSolver(mesh, dict, typeName),
|
||||
meshGeometry_(mesh),
|
||||
pointUntangler_
|
||||
(
|
||||
pointSmoother::New
|
||||
(
|
||||
coeffDict().get<word>("untangler"),
|
||||
mesh,
|
||||
coeffDict()
|
||||
)
|
||||
),
|
||||
untangleQ_(coeffDict().get<scalar>("untangleQ")),
|
||||
minQ_(coeffDict().get<scalar>("minQ")),
|
||||
pointSmoother_(pointSmoother::New(mesh, coeffDict())),
|
||||
nPointSmootherIter_
|
||||
(
|
||||
readLabel(coeffDict().lookup("nPointSmootherIter"))
|
||||
),
|
||||
relaxedPoints_(mesh.points())
|
||||
{
|
||||
if (coeffDict().readIfPresent("relaxationFactors", relaxationFactors_))
|
||||
{
|
||||
meshQualityDict_ = coeffDict().subDict("meshQuality");
|
||||
}
|
||||
setFacesToMove(coeffDict());
|
||||
}
|
||||
|
||||
|
||||
Foam::displacementSmartPointSmoothingMotionSolver::
|
||||
displacementSmartPointSmoothingMotionSolver
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const IOdictionary& dict,
|
||||
const pointVectorField& pointDisplacement,
|
||||
const pointIOField& points0
|
||||
)
|
||||
:
|
||||
displacementMotionSolver(mesh, dict, pointDisplacement, points0, typeName),
|
||||
meshGeometry_(mesh),
|
||||
pointUntangler_
|
||||
(
|
||||
pointSmoother::New
|
||||
(
|
||||
coeffDict().get<word>("untangler"),
|
||||
mesh,
|
||||
coeffDict()
|
||||
)
|
||||
),
|
||||
untangleQ_(coeffDict().get<scalar>("untangleQ")),
|
||||
minQ_(coeffDict().get<scalar>("minQ")),
|
||||
pointSmoother_
|
||||
(
|
||||
pointSmoother::New
|
||||
(
|
||||
mesh,
|
||||
coeffDict()
|
||||
)
|
||||
),
|
||||
nPointSmootherIter_
|
||||
(
|
||||
readLabel(coeffDict().lookup("nPointSmootherIter"))
|
||||
),
|
||||
relaxedPoints_(mesh.points())
|
||||
{
|
||||
if (coeffDict().readIfPresent("relaxationFactors", relaxationFactors_))
|
||||
{
|
||||
meshQualityDict_ = coeffDict().subDict("meshQuality");
|
||||
}
|
||||
setFacesToMove(coeffDict());
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::tmp<Foam::pointField>
|
||||
Foam::displacementSmartPointSmoothingMotionSolver::curPoints() const
|
||||
{
|
||||
//Note: twoDCorrect already done by ::solve
|
||||
|
||||
return relaxedPoints_;
|
||||
}
|
||||
|
||||
|
||||
void Foam::displacementSmartPointSmoothingMotionSolver::solve()
|
||||
{
|
||||
movePoints(curPoints());
|
||||
|
||||
// Update values on pointDisplacement. Note: should also evaluate? Since
|
||||
// e.g. cellMotionBC uses pointDisplacement value.
|
||||
pointDisplacement().boundaryFieldRef().updateCoeffs();
|
||||
|
||||
|
||||
fileName debugDir;
|
||||
if (debug & 2)
|
||||
{
|
||||
debugDir = mesh().time().timePath();
|
||||
mkDir(debugDir);
|
||||
OBJstream os(debugDir/"bc.obj");
|
||||
|
||||
const pointField wantedPoints
|
||||
(
|
||||
points0()
|
||||
+ pointDisplacement().internalField()
|
||||
);
|
||||
const auto& pbm = pointDisplacement().mesh().boundary();
|
||||
for (const auto& ppp : pbm)
|
||||
{
|
||||
if (!isA<emptyPointPatch>(ppp))
|
||||
{
|
||||
const auto& mp = ppp.meshPoints();
|
||||
for (const label pointi : mp)
|
||||
{
|
||||
os.write
|
||||
(
|
||||
linePointRef
|
||||
(
|
||||
points0()[pointi],
|
||||
wantedPoints[pointi]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Pout<< "Written " << os.nVertices() << " initial displacements to "
|
||||
<< os.name() << endl;
|
||||
}
|
||||
|
||||
|
||||
// Extend: face-to-point-to-cell-to-faces
|
||||
labelHashSet affectedFaces;
|
||||
markAffectedFaces(facesToMove_, affectedFaces);
|
||||
|
||||
|
||||
for(label i = 0; i < nPointSmootherIter_; i ++)
|
||||
{
|
||||
const pointField wantedPoints
|
||||
(
|
||||
points0()
|
||||
+ pointDisplacement().internalField()
|
||||
);
|
||||
|
||||
meshGeometry_.correct
|
||||
(
|
||||
wantedPoints,
|
||||
affectedFaces.toc()
|
||||
);
|
||||
|
||||
//{
|
||||
// // Debugging: check meshGeometry consistent with fvGeometryScheme
|
||||
// const auto& geom =
|
||||
// reinterpret_cast<const fvMesh&>(mesh()).geometry();
|
||||
// pointField faceCentres(mesh().nFaces());
|
||||
// vectorField faceAreas(mesh().nFaces());
|
||||
// pointField cellCentres(mesh().nCells());
|
||||
// scalarField cellVolumes(mesh().nCells());
|
||||
// geom.updateGeom
|
||||
// (
|
||||
// wantedPoints,
|
||||
// mesh().points(), // old points
|
||||
// faceCentres,
|
||||
// faceAreas,
|
||||
// cellCentres,
|
||||
// cellVolumes
|
||||
// );
|
||||
// forAll(faceCentres, facei)
|
||||
// {
|
||||
// const point& meshFc = mesh().faceCentres()[facei];
|
||||
// const point& meshGeomFc = meshGeometry_.faceCentres()[facei];
|
||||
// const point& updatedFc = faceCentres[facei];
|
||||
//
|
||||
// if (updatedFc != meshGeomFc)
|
||||
// {
|
||||
// const face& f = mesh().faces()[facei];
|
||||
//
|
||||
// Pout<< "At face:" << facei << nl
|
||||
// << " old :" << meshFc << nl
|
||||
// << " new :" << updatedFc << nl
|
||||
// << " polyMeshGeom:" << meshGeomFc << nl
|
||||
// << " oldPoints :"
|
||||
// << UIndirectList<point>(mesh().points(), f) << nl
|
||||
// << " wantedPoints:"
|
||||
// << UIndirectList<point>(wantedPoints, f) << nl
|
||||
// << endl;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
// Get measure of face quality
|
||||
tmp<scalarField> tfaceQ
|
||||
(
|
||||
pointUntangler_->faceQuality
|
||||
(
|
||||
wantedPoints,
|
||||
meshGeometry_.faceCentres(),
|
||||
meshGeometry_.faceAreas(),
|
||||
meshGeometry_.cellCentres(),
|
||||
meshGeometry_.cellVolumes()
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
MinMax<scalar> range(gMinMax(tfaceQ()));
|
||||
Pout<< " min:" << range.min() << nl
|
||||
<< " max:" << range.max() << endl;
|
||||
}
|
||||
|
||||
labelList order;
|
||||
Foam::sortedOrder(tfaceQ(), order);
|
||||
|
||||
label nUntangle = 0;
|
||||
forAll(order, i)
|
||||
{
|
||||
if (tfaceQ()[order[i]] > untangleQ_)
|
||||
{
|
||||
nUntangle = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
label nLow = 0;
|
||||
forAll(order, i)
|
||||
{
|
||||
if (tfaceQ()[order[i]] > minQ_)
|
||||
{
|
||||
nLow = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< " nUntangle:" << returnReduce(nUntangle, sumOp<label>())
|
||||
<< nl
|
||||
<< " nLow :" << returnReduce(nLow, sumOp<label>())
|
||||
<< nl;
|
||||
}
|
||||
|
||||
|
||||
if (returnReduce(nUntangle, sumOp<label>()))
|
||||
{
|
||||
// Start untangling
|
||||
labelList lowQFaces(SubList<label>(order, nUntangle));
|
||||
//{
|
||||
// // Grow set (non parallel)
|
||||
// bitSet isMarkedFace(mesh().nFaces());
|
||||
// for (const label facei : lowQFaces)
|
||||
// {
|
||||
// for (const label pointi : mesh().faces()[facei])
|
||||
// {
|
||||
// isMarkedFace.set(mesh().pointFaces()[pointi]);
|
||||
// }
|
||||
// }
|
||||
// lowQFaces = isMarkedFace.sortedToc();
|
||||
//}
|
||||
|
||||
//Pout<< " untangling "
|
||||
// << returnReduce(lowQFaces.size(), sumOp<label>())
|
||||
// << " faces" << endl;
|
||||
pointUntangler_->update
|
||||
(
|
||||
lowQFaces,
|
||||
points0(),
|
||||
wantedPoints,
|
||||
meshGeometry_,
|
||||
pointDisplacement()
|
||||
//false // ! do NOT apply bcs, constraints
|
||||
);
|
||||
|
||||
// Keep points on empty patches. Note: since pointConstraints
|
||||
// does not implement constraints on emptyPointPatches and
|
||||
// emptyPointPatchField does not either.
|
||||
emptyCorrectPoints(pointDisplacement());
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
OBJstream os(debugDir/"untangle_" + Foam::name(i) + ".obj");
|
||||
|
||||
const pointField wantedPoints
|
||||
(
|
||||
points0()
|
||||
+ pointDisplacement().internalField()
|
||||
);
|
||||
forAll(wantedPoints, pointi)
|
||||
{
|
||||
os.write
|
||||
(
|
||||
linePointRef
|
||||
(
|
||||
points0()[pointi],
|
||||
wantedPoints[pointi]
|
||||
)
|
||||
);
|
||||
}
|
||||
Pout<< "Written " << os.nVertices() << " wanted untangle to "
|
||||
<< os.name() << endl;
|
||||
}
|
||||
}
|
||||
else if (returnReduce(nLow, sumOp<label>()))
|
||||
{
|
||||
labelList lowQFaces(SubList<label>(order, nLow));
|
||||
//{
|
||||
// // Grow set (non parallel)
|
||||
// bitSet isMarkedFace(mesh().nFaces());
|
||||
// for (const label facei : lowQFaces)
|
||||
// {
|
||||
// for (const label pointi : mesh().faces()[facei])
|
||||
// {
|
||||
// isMarkedFace.set(mesh().pointFaces()[pointi]);
|
||||
// }
|
||||
// }
|
||||
// lowQFaces = isMarkedFace.sortedToc();
|
||||
//}
|
||||
|
||||
//Pout<< " smoothing "
|
||||
// << returnReduce(lowQFaces.size(), sumOp<label>())
|
||||
// << " faces" << endl;
|
||||
|
||||
pointSmoother_->update
|
||||
(
|
||||
lowQFaces,
|
||||
points0(),
|
||||
wantedPoints,
|
||||
meshGeometry_,
|
||||
pointDisplacement()
|
||||
);
|
||||
// Keep points on empty patches
|
||||
emptyCorrectPoints(pointDisplacement());
|
||||
}
|
||||
else
|
||||
{
|
||||
//Pout<< "** converged" << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
relax();
|
||||
//relaxedPoints_ = points0() + pointDisplacement().internalField();
|
||||
|
||||
twoDCorrectPoints(relaxedPoints_);
|
||||
|
||||
// Update pointDisplacement for actual relaxedPoints. Keep fixed-value
|
||||
// bcs.
|
||||
pointDisplacement().primitiveFieldRef() = relaxedPoints_-points0();
|
||||
|
||||
// Adhere to multi-point constraints. Does correctBoundaryConditions +
|
||||
// multi-patch issues.
|
||||
const pointConstraints& pcs =
|
||||
pointConstraints::New(pointDisplacement().mesh());
|
||||
pcs.constrainDisplacement(pointDisplacement(), false);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,193 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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::displacementSmartPointSmoothingMotionSolver
|
||||
|
||||
Description
|
||||
Quality-based under-relaxation for run-time selectable point smoothing. WIP.
|
||||
|
||||
Usage
|
||||
\table
|
||||
Property | Description | Required | Default value
|
||||
untangler | pointSmoother for untangling | yes |
|
||||
untangleQ | quality below which untangling is applied | yes |
|
||||
|
||||
pointSmoother | pointSmoother in 'normal' mode | yes
|
||||
minQ | quality below which pointSmoother is applied | yes
|
||||
nPointSmootherIter | max number of iterations
|
||||
\endtable
|
||||
|
||||
Example of the motion solver specification in dynamicMeshDict:
|
||||
\verbatim
|
||||
motionSolver displacementSmartPointSmoothing;
|
||||
displacementSmartPointSmoothingCoeffs
|
||||
{
|
||||
//- Overall max number of smoothing iterations
|
||||
nPointSmootherIter 10;
|
||||
|
||||
//- If any faces have quality below untangleQ apply untangler
|
||||
untangleQ 0.001;
|
||||
untangler laplacian;
|
||||
|
||||
//- If any faces have quality below minQ apply 'normal' smoother
|
||||
minQ 0.9;
|
||||
pointSmoother geometricElementTransform;
|
||||
transformationParameter 0.667;
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
SourceFiles
|
||||
displacementSmartPointSmoothingMotionSolver.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef displacementSmartPointSmoothingMotionSolver_H
|
||||
#define displacementSmartPointSmoothingMotionSolver_H
|
||||
|
||||
#include "displacementMotionSolver.H"
|
||||
#include "pointSmoother.H"
|
||||
#include "polyMeshGeometry.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class displacementSmartPointSmoothingMotionSolver Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class displacementSmartPointSmoothingMotionSolver
|
||||
:
|
||||
public displacementMotionSolver
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Part-updatable mesh geometry
|
||||
polyMeshGeometry meshGeometry_;
|
||||
|
||||
//- Point untangler method
|
||||
autoPtr<pointSmoother> pointUntangler_;
|
||||
|
||||
//- Minimum allowed quality
|
||||
const scalar untangleQ_;
|
||||
|
||||
//- Minimum allowed quality
|
||||
const scalar minQ_;
|
||||
|
||||
//- Point smoothing method
|
||||
autoPtr<pointSmoother> pointSmoother_;
|
||||
|
||||
//- Number of point smoother iterations per timestep
|
||||
const label nPointSmootherIter_;
|
||||
|
||||
|
||||
// Mesh quality based relaxation of smoothed position
|
||||
|
||||
//- Relaxation factors to use in each iteration
|
||||
scalarList relaxationFactors_;
|
||||
|
||||
//- Relaxed point field
|
||||
pointField relaxedPoints_;
|
||||
|
||||
//- Set of the faces which are to be moved
|
||||
labelHashSet facesToMove_;
|
||||
|
||||
//- Mesh quality dictionary
|
||||
dictionary meshQualityDict_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Mark affected faces
|
||||
void markAffectedFaces
|
||||
(
|
||||
const labelHashSet& changedFaces,
|
||||
labelHashSet& affectedFaces
|
||||
);
|
||||
|
||||
//- Relax the points
|
||||
bool relax();
|
||||
|
||||
//- Set all the faces to be moved
|
||||
void virtual setFacesToMove(const dictionary&);
|
||||
|
||||
//- Handle 2D & empty bcs. Assume in both cases the starting mesh
|
||||
// - has all edges aligned with 3rd dimension
|
||||
// - is on planes of the empty patches
|
||||
void emptyCorrectPoints(pointVectorField& pointDisplacement);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("displacementSmartPointSmoothing");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from a polyMesh and an IOdictionary
|
||||
displacementSmartPointSmoothingMotionSolver
|
||||
(
|
||||
const polyMesh&,
|
||||
const IOdictionary&
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
displacementSmartPointSmoothingMotionSolver
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const IOdictionary& dict,
|
||||
const pointVectorField& pointDisplacement,
|
||||
const pointIOField& points0
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~displacementSmartPointSmoothingMotionSolver() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return point location obtained from the current motion field
|
||||
virtual tmp<pointField> curPoints() const;
|
||||
|
||||
//- Solve for motion
|
||||
virtual void solve();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,258 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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::hexMeshSmootherMotionSolver
|
||||
|
||||
Description
|
||||
Implementation of hexMeshSmoother (part of extBlockMesh). WIP.
|
||||
|
||||
See https://github.com/Etudes-NG/extBlockMesh
|
||||
extBlockMesh Copyright (C) 2014 Etudes-NG
|
||||
|
||||
Quality-based under-relaxation of point smoothing.
|
||||
|
||||
Usage
|
||||
Example of the motion solver specification in dynamicMeshDict:
|
||||
\verbatim
|
||||
motionSolver hexMeshSmoother;
|
||||
hexMeshSmootherCoeffs
|
||||
{
|
||||
//- Number of smoothing iterations
|
||||
nPointSmootherIter 10;
|
||||
|
||||
//- Smoother to apply
|
||||
pointSmoother geometricElementTransform;
|
||||
|
||||
//- Any smoother-specific settings
|
||||
transformationParameter 0.667;
|
||||
|
||||
//- Underrelax boundary condition
|
||||
snapScale table ((0 0.1) (10 1.0));
|
||||
}
|
||||
|
||||
SourceFiles
|
||||
hexMeshSmootherMotionSolver.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef hexMeshSmootherMotionSolver_H
|
||||
#define hexMeshSmootherMotionSolver_H
|
||||
|
||||
#include "displacementMotionSolver.H"
|
||||
#include "Function1.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
//class searchableSurfaces;
|
||||
class pointSmoother;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class hexMeshSmootherMotionSolver Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class hexMeshSmootherMotionSolver
|
||||
:
|
||||
public displacementMotionSolver
|
||||
{
|
||||
public:
|
||||
|
||||
// Public Data
|
||||
|
||||
//- Enumeration defining the type of attraction
|
||||
enum pointType
|
||||
{
|
||||
INTERIOR = 0,
|
||||
SURFACE = 1,
|
||||
EDGE = 2,
|
||||
POINT = 3
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Point smoothing method
|
||||
autoPtr<pointSmoother> pointSmoother_;
|
||||
|
||||
//- Number of point smoother iterations per timestep
|
||||
const label nPointSmootherIter_;
|
||||
|
||||
|
||||
// Mesh quality based relaxation of smoothed position
|
||||
|
||||
//- Relaxation factors to use in each iteration
|
||||
const scalarList relaxationFactors_;
|
||||
|
||||
//- Per mesh point (including internal) what type
|
||||
labelList pointTypes_;
|
||||
|
||||
//- Per mesh point the last used relaxation factor
|
||||
labelList relaxationLevel_;
|
||||
|
||||
//- Relaxed point field
|
||||
pointField relaxedPoints_;
|
||||
|
||||
|
||||
////- Patches that are to be snapped
|
||||
//const labelList snapPatches_;
|
||||
//
|
||||
////- FaceZones that are to be snapped
|
||||
//const labelList snapZones_;
|
||||
|
||||
//- Scaling for snapping
|
||||
const autoPtr<Function1<scalar>> snapScale_;
|
||||
|
||||
//- Cached per-point coupled status. For guaranteeing contributions
|
||||
// of coupled points only done once
|
||||
const bitSet isMasterPoint_;
|
||||
|
||||
//- Create big primitivePatch for all outside and any features on it
|
||||
const autoPtr<indirectPrimitivePatch> bnd0Ptr_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Collect all non-constraint (i.e. no processor, cyclic, empty etc)
|
||||
//- patches
|
||||
static labelList nonConstraintPatches(const polyMesh& mesh);
|
||||
|
||||
//- Create single patch of all supplied faces
|
||||
static autoPtr<indirectPrimitivePatch> makePatch
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const labelList& patchIDs,
|
||||
const labelList& zoneIDs,
|
||||
const pointField& points0
|
||||
);
|
||||
|
||||
//- Check with current points
|
||||
void checkMesh
|
||||
(
|
||||
const pointField& currentPoints,
|
||||
const vectorField& fCtrs,
|
||||
const vectorField& fAreas,
|
||||
const vectorField& cellCtrs,
|
||||
const scalarField& cellVols,
|
||||
labelHashSet& markedFaces,
|
||||
bitSet& markedPoints
|
||||
) const;
|
||||
|
||||
//- Apply current constraints (from pointDisplacement) to supplied
|
||||
// locations
|
||||
void constrainDisplacement(pointField& points) const;
|
||||
|
||||
//- Relax the points (supplied in pointDisplacement)
|
||||
bool relax
|
||||
(
|
||||
const scalarList& relaxationFactors,
|
||||
const bitSet& pointsToRelax,
|
||||
const pointField& initialPoints,
|
||||
const pointField& wantedPoints,
|
||||
pointField& relaxedPoints,
|
||||
labelList& relaxationLevel
|
||||
) const;
|
||||
label countPos(const labelList& elems) const;
|
||||
labelList countZeroOrPos(const label size, const labelList& lst) const;
|
||||
|
||||
//- Helper: set in bitSet all elements with a certain value
|
||||
void select(const labelUList&, const label val, bitSet& isVal) const;
|
||||
|
||||
void laplaceSmooth
|
||||
(
|
||||
const label type,
|
||||
const pointField& initialPoints,
|
||||
pointField& newPoints
|
||||
) const;
|
||||
void featLaplaceSmooth
|
||||
(
|
||||
const indirectPrimitivePatch& pp,
|
||||
const pointField& initialPoints,
|
||||
pointField& newPoints
|
||||
) const;
|
||||
// Snap points using boundary evaluation ...
|
||||
void snapBoundaryPoints
|
||||
(
|
||||
const scalar scale,
|
||||
const pointField& initialPoints,
|
||||
pointField& newPoints
|
||||
) const;
|
||||
|
||||
//- Keep points on empty patches
|
||||
void emptyCorrectPoints(pointVectorField& pointDisplacement) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("hexMeshSmoother");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from a polyMesh and an IOdictionary
|
||||
hexMeshSmootherMotionSolver
|
||||
(
|
||||
const polyMesh&,
|
||||
const IOdictionary&
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
hexMeshSmootherMotionSolver
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const IOdictionary& dict,
|
||||
const pointVectorField& pointDisplacement,
|
||||
const pointIOField& points0
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~hexMeshSmootherMotionSolver();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return point location obtained from the current motion field
|
||||
virtual tmp<pointField> curPoints() const;
|
||||
|
||||
//- Solve for motion
|
||||
virtual void solve();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,148 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "equipotentialPointSmoother.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace pointSmoothers
|
||||
{
|
||||
defineTypeNameAndDebug(equipotentialPointSmoother, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
pointSmoother,
|
||||
equipotentialPointSmoother,
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointSmoothers::equipotentialPointSmoother::equipotentialPointSmoother
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
pointSmoother(mesh, dict)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::pointSmoothers::equipotentialPointSmoother::calculate
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes,
|
||||
vectorField& pointDisplacement
|
||||
) const
|
||||
{
|
||||
// Number of points used in each average
|
||||
scalarField weights(mesh().nPoints(), 0);
|
||||
|
||||
// Reset the displacements which are about to be calculated
|
||||
reset(facesToMove, weights, pointDisplacement);
|
||||
|
||||
// Sum the non-internal face displacements
|
||||
forAll(facesToMove, faceToMoveI)
|
||||
{
|
||||
const label faceI(facesToMove[faceToMoveI]);
|
||||
|
||||
if (!isInternalOrProcessorFace(faceI))
|
||||
{
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
const scalar area(mag(mesh().faceAreas()[faceI]));
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
pointDisplacement[pointI] +=
|
||||
area
|
||||
*(
|
||||
faceCentres[faceI]
|
||||
- oldPoints[pointI]
|
||||
);
|
||||
|
||||
weights[pointI] += area;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sum the internal face displacements
|
||||
forAll(facesToMove, faceToMoveI)
|
||||
{
|
||||
const label faceI(facesToMove[faceToMoveI]);
|
||||
|
||||
if (isInternalOrProcessorFace(faceI))
|
||||
{
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
if (weights[pointI] < SMALL)
|
||||
{
|
||||
const labelList& pCells(mesh().pointCells()[pointI]);
|
||||
|
||||
forAll(pCells, pCellI)
|
||||
{
|
||||
const label cellI(pCells[pCellI]);
|
||||
|
||||
const scalar volume(mesh().cellVolumes()[cellI]);
|
||||
|
||||
pointDisplacement[pointI] +=
|
||||
volume
|
||||
*(
|
||||
cellCentres[cellI]
|
||||
- oldPoints[pointI]
|
||||
);
|
||||
|
||||
weights[pointI] += volume;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Average
|
||||
average(facesToMove, weights, pointDisplacement);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,105 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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::equipotentialPointSmoother
|
||||
|
||||
Description
|
||||
Equipotential point smoothing. Points are moved towards the centroid of the
|
||||
surrounding cell volumes. This method tends to equilise cell volumes, and
|
||||
can generate distorted cells around refinement patterns.
|
||||
|
||||
SourceFiles
|
||||
equipotentialPointSmoother.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef equipotentialPointSmoother_H
|
||||
#define equipotentialPointSmoother_H
|
||||
|
||||
#include "pointSmoother.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace pointSmoothers
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class equipotentialPointSmoother Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class equipotentialPointSmoother
|
||||
:
|
||||
public pointSmoother
|
||||
{
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("equipotential");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from a dictionary and a polyMesh
|
||||
equipotentialPointSmoother
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~equipotentialPointSmoother() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Calculate the point displacements
|
||||
virtual void calculate
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes,
|
||||
vectorField& pointDisplacement
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace pointSmoothers
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,292 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "cellPointConnectivity.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(cellPointConnectivity, 0);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::cellPointConnectivity::generateCellPointConnectivity(label cellI)
|
||||
{
|
||||
const cell& cFaceLabels(mesh_.cells()[cellI]);
|
||||
const labelList cPointLabels(cFaceLabels.labels(mesh_.faces()));
|
||||
const edgeList cEdges(cFaceLabels.edges(mesh_.faces()));
|
||||
|
||||
// Generate a sorted list of points and corresponding point indices
|
||||
labelPairList pointLabelPointIndices(cPointLabels.size());
|
||||
forAll(cPointLabels, pointI)
|
||||
{
|
||||
pointLabelPointIndices[pointI] =
|
||||
labelPair(cPointLabels[pointI], pointI);
|
||||
}
|
||||
sort(pointLabelPointIndices);
|
||||
|
||||
// Generate a sorted list of edge labels and corresponding edge indices
|
||||
// Negative values indicate an edge which runs in an opposite direction to
|
||||
// the face node listing
|
||||
labelListList edgeLabelsEdgeIndices
|
||||
(
|
||||
2*cEdges.size(),
|
||||
labelList(3, label(-1))
|
||||
);
|
||||
forAll(cEdges, cEdgeI)
|
||||
{
|
||||
edgeLabelsEdgeIndices[2*cEdgeI][0] = cEdges[cEdgeI][0];
|
||||
edgeLabelsEdgeIndices[2*cEdgeI][1] = cEdges[cEdgeI][1];
|
||||
edgeLabelsEdgeIndices[2*cEdgeI][2] = cEdgeI;
|
||||
|
||||
edgeLabelsEdgeIndices[2*cEdgeI+1][0] = cEdges[cEdgeI][1];
|
||||
edgeLabelsEdgeIndices[2*cEdgeI+1][1] = cEdges[cEdgeI][0];
|
||||
edgeLabelsEdgeIndices[2*cEdgeI+1][2] = - cEdgeI - 1;
|
||||
}
|
||||
sort(edgeLabelsEdgeIndices);
|
||||
|
||||
// Generate a sorted list of edge labels and correspoinding face indices
|
||||
labelListList edgeLabelsFaceIndices;
|
||||
forAll(cFaceLabels, cFaceI)
|
||||
{
|
||||
const face& cFace(mesh_.faces()[cFaceLabels[cFaceI]]);
|
||||
|
||||
const bool owner(mesh_.faceOwner()[cFaceLabels[cFaceI]] == cellI);
|
||||
|
||||
const label cFaceNEdges(cFace.size());
|
||||
forAll(cFace, cFaceEdgeI)
|
||||
{
|
||||
edgeLabelsFaceIndices.append(labelList(3, label(-1)));
|
||||
edgeLabelsFaceIndices.last()[0] =
|
||||
cFace[(cFaceEdgeI + owner) % cFaceNEdges];
|
||||
edgeLabelsFaceIndices.last()[1] =
|
||||
cFace[(cFaceEdgeI + !owner) % cFaceNEdges];
|
||||
edgeLabelsFaceIndices.last()[2] = cFaceI;
|
||||
}
|
||||
}
|
||||
sort(edgeLabelsFaceIndices);
|
||||
|
||||
// Assemble lists of edge-face and cell-face connectivities
|
||||
// Negative values indicate an edge which runs in an opposite direction to
|
||||
// the face node listing
|
||||
labelListList edgeFaceIndices(cEdges.size());
|
||||
labelListList faceEdgeIndices(cFaceLabels.size());
|
||||
forAll(edgeLabelsFaceIndices, I)
|
||||
{
|
||||
const label edgeLabelsEdgeIndex(edgeLabelsEdgeIndices[I][2]);
|
||||
const label absCellEdgeEdgeIndex
|
||||
(
|
||||
edgeLabelsEdgeIndex >= 0
|
||||
? edgeLabelsEdgeIndex
|
||||
: - edgeLabelsEdgeIndex - 1
|
||||
);
|
||||
const label absCellEdgeFaceIndex(edgeLabelsFaceIndices[I][2]);
|
||||
const label edgeLabelsFaceIndex
|
||||
(
|
||||
edgeLabelsEdgeIndex >= 0
|
||||
? absCellEdgeFaceIndex
|
||||
: - absCellEdgeFaceIndex - 1
|
||||
);
|
||||
|
||||
edgeFaceIndices[absCellEdgeEdgeIndex].append(edgeLabelsFaceIndex);
|
||||
faceEdgeIndices[absCellEdgeFaceIndex].append(edgeLabelsEdgeIndex);
|
||||
}
|
||||
|
||||
// Generate a list of point labels and face index pairs
|
||||
labelListList pointLabelEdgeIndexFaceIndexPairs;
|
||||
forAll(cEdges, edgeI)
|
||||
{
|
||||
const labelPair pointIndices(cEdges[edgeI]);
|
||||
|
||||
const labelPair faceIndices
|
||||
(
|
||||
edgeFaceIndices[edgeI][0],
|
||||
edgeFaceIndices[edgeI][1]
|
||||
);
|
||||
const labelPair absFaceIndices
|
||||
(
|
||||
faceIndices[0] >= 0 ? faceIndices[0] : - faceIndices[0] - 1,
|
||||
faceIndices[1] >= 0 ? faceIndices[1] : - faceIndices[1] - 1
|
||||
);
|
||||
|
||||
const bool order(faceIndices[0] > faceIndices[1]);
|
||||
|
||||
pointLabelEdgeIndexFaceIndexPairs.append(labelList(4, label(-1)));
|
||||
pointLabelEdgeIndexFaceIndexPairs.last()[0] = pointIndices[0];
|
||||
pointLabelEdgeIndexFaceIndexPairs.last()[1] = edgeI;
|
||||
pointLabelEdgeIndexFaceIndexPairs.last()[2] = absFaceIndices[order];
|
||||
pointLabelEdgeIndexFaceIndexPairs.last()[3] = absFaceIndices[!order];
|
||||
|
||||
pointLabelEdgeIndexFaceIndexPairs.append(labelList(4, label(-1)));
|
||||
pointLabelEdgeIndexFaceIndexPairs.last()[0] = pointIndices[1];
|
||||
pointLabelEdgeIndexFaceIndexPairs.last()[1] = edgeI;
|
||||
pointLabelEdgeIndexFaceIndexPairs.last()[2] = absFaceIndices[!order];
|
||||
pointLabelEdgeIndexFaceIndexPairs.last()[3] = absFaceIndices[order];
|
||||
}
|
||||
sort(pointLabelEdgeIndexFaceIndexPairs);
|
||||
|
||||
// Assemble a list of point face pairs from the sorted lists
|
||||
labelListList pointEdgeIndices(cPointLabels.size());
|
||||
List<List<Pair<label> > > pointFaceIndexPairs(cPointLabels.size());
|
||||
{
|
||||
label I(0);
|
||||
label pointLabelOld(pointLabelEdgeIndexFaceIndexPairs[0][0]);
|
||||
forAll
|
||||
(
|
||||
pointLabelEdgeIndexFaceIndexPairs,
|
||||
pointLabelEdgeIndexFaceIndexPairI
|
||||
)
|
||||
{
|
||||
const labelList& pointLabelEdgeIndexFaceIndexPair
|
||||
(
|
||||
pointLabelEdgeIndexFaceIndexPairs
|
||||
[
|
||||
pointLabelEdgeIndexFaceIndexPairI
|
||||
]
|
||||
);
|
||||
|
||||
if (pointLabelOld != pointLabelEdgeIndexFaceIndexPair[0])
|
||||
{
|
||||
I ++;
|
||||
pointLabelOld = pointLabelEdgeIndexFaceIndexPair[0];
|
||||
}
|
||||
|
||||
const label pointI(pointLabelPointIndices[I][1]);
|
||||
|
||||
pointEdgeIndices[pointI].append
|
||||
(
|
||||
pointLabelEdgeIndexFaceIndexPair[1]
|
||||
);
|
||||
|
||||
pointFaceIndexPairs[pointI].append
|
||||
(
|
||||
labelPair
|
||||
(
|
||||
pointLabelEdgeIndexFaceIndexPair[2],
|
||||
pointLabelEdgeIndexFaceIndexPair[3]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Order the point face pairs and assemble a list of point face indices
|
||||
labelListList pointFaceIndices(cPointLabels.size());
|
||||
forAll(pointFaceIndexPairs, pointI)
|
||||
{
|
||||
labelPairList& faceIndexPairs(pointFaceIndexPairs[pointI]);
|
||||
|
||||
pointFaceIndices[pointI].append(faceIndexPairs[0][0]);
|
||||
|
||||
for (label pairI = 1; pairI < faceIndexPairs.size(); pairI ++)
|
||||
{
|
||||
for (label pairJ = pairI; pairJ < faceIndexPairs.size(); ++ pairJ)
|
||||
{
|
||||
if (faceIndexPairs[pairI-1][1] == faceIndexPairs[pairJ][0])
|
||||
{
|
||||
Swap
|
||||
(
|
||||
pointEdgeIndices[pointI][pairI],
|
||||
pointEdgeIndices[pointI][pairJ]
|
||||
);
|
||||
|
||||
Swap
|
||||
(
|
||||
faceIndexPairs[pairI],
|
||||
faceIndexPairs[pairJ]
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
pointFaceIndices[pointI].append(faceIndexPairs[pairI][0]);
|
||||
}
|
||||
}
|
||||
|
||||
// convert to global indices
|
||||
forAll(cPointLabels, pointI)
|
||||
{
|
||||
labelList& edgeIndices(pointEdgeIndices[pointI]);
|
||||
labelList& faceIndices(pointFaceIndices[pointI]);
|
||||
|
||||
const label nPointFaces(faceIndices.size());
|
||||
|
||||
cellPointPoints_[cellI][pointI].resize(nPointFaces);
|
||||
|
||||
forAll(edgeIndices, edgeI)
|
||||
{
|
||||
cellPointPoints_[cellI][pointI][edgeI] =
|
||||
cEdges[edgeIndices[edgeI]]
|
||||
[
|
||||
cEdges[edgeIndices[edgeI]][0] == cPointLabels[pointI]
|
||||
];
|
||||
}
|
||||
|
||||
cellPointFaces_[cellI][pointI].resize(nPointFaces);
|
||||
|
||||
forAll(faceIndices, faceI)
|
||||
{
|
||||
cellPointFaces_[cellI][pointI][faceI] =
|
||||
cFaceLabels
|
||||
[
|
||||
faceIndices[faceI]
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::cellPointConnectivity::cellPointConnectivity(const polyMesh& mesh)
|
||||
:
|
||||
MoveableMeshObject<polyMesh>(typeName, mesh),
|
||||
mesh_(mesh),
|
||||
cellPointPoints_(mesh.nCells()),
|
||||
cellPointFaces_(mesh.nCells())
|
||||
{
|
||||
forAll(mesh.cells(), cellI)
|
||||
{
|
||||
const label nPoints(mesh.cellPoints()[cellI].size());
|
||||
|
||||
cellPointPoints_[cellI].resize(nPoints);
|
||||
cellPointFaces_[cellI].resize(nPoints);
|
||||
|
||||
generateCellPointConnectivity(cellI);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::cellPointConnectivity::~cellPointConnectivity()
|
||||
{}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,139 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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::cellPointConnectivity
|
||||
|
||||
Description
|
||||
This class provides ordered connectivity for each point of each cell. Lists
|
||||
are available of the points and faces surrounding each point of a cell. The
|
||||
lists are ordered so that the connected points describe a polygonal cone.
|
||||
For a convex cell, any three sequantial cone edges form a positive basis.
|
||||
|
||||
SourceFiles
|
||||
cellPointConnectivity.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef cellPointConnectivity_H
|
||||
#define cellPointConnectivity_H
|
||||
|
||||
#include "polyMesh.H"
|
||||
#include "MeshObject.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class cellPointConnectivity Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class cellPointConnectivity
|
||||
:
|
||||
public MoveableMeshObject<polyMesh>
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Reference to the polyMesh
|
||||
const polyMesh& mesh_;
|
||||
|
||||
//- Lists of point-point connections
|
||||
labelListListList cellPointPoints_;
|
||||
|
||||
//- Lists of point-face connections
|
||||
labelListListList cellPointFaces_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
cellPointConnectivity(const cellPointConnectivity&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const cellPointConnectivity&);
|
||||
|
||||
//- Generate the connectivity
|
||||
void generateCellPointConnectivity(label cellI);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Run-time type information
|
||||
TypeName("cellPointConnectivity");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct an IOobject and a polymesh
|
||||
cellPointConnectivity(const polyMesh&);
|
||||
|
||||
|
||||
//- Destructor
|
||||
~cellPointConnectivity();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Access the point-point connections
|
||||
const labelListListList& cellPointPoints() const
|
||||
{
|
||||
return cellPointPoints_;
|
||||
}
|
||||
|
||||
//- Access the point-face connections
|
||||
const labelListListList& cellPointFaces() const
|
||||
{
|
||||
return cellPointFaces_;
|
||||
}
|
||||
|
||||
// Edit
|
||||
|
||||
//- No action required on move points
|
||||
virtual bool movePoints()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//- Dummy write for regIOobject
|
||||
virtual bool writeData(Ostream&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,479 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "geometricElementTransformPointSmoother.H"
|
||||
#include "cellPointConnectivity.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace pointSmoothers
|
||||
{
|
||||
defineTypeNameAndDebug(geometricElementTransformPointSmoother, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
pointSmoother,
|
||||
geometricElementTransformPointSmoother,
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::scalar
|
||||
Foam::pointSmoothers::geometricElementTransformPointSmoother::cellQuality
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const pointField& currentPoints,
|
||||
const cellPointConnectivity& connectivity,
|
||||
const label celli
|
||||
)
|
||||
{
|
||||
const cell& cFaces = mesh.cells()[celli];
|
||||
const labelList cPoints(cFaces.labels(mesh.faces()));
|
||||
|
||||
// Calculate a transformed point for each cell point
|
||||
|
||||
scalar cellQ = 0.0;
|
||||
label nTets = 0;
|
||||
|
||||
forAll(cPoints, cPointi)
|
||||
{
|
||||
const label pointi(cPoints[cPointi]);
|
||||
const point& pt = currentPoints[pointi];
|
||||
const labelList& pPoints
|
||||
(
|
||||
connectivity.cellPointPoints()[celli][cPointi]
|
||||
);
|
||||
if (pPoints.size() != 3)
|
||||
{
|
||||
WarningInFunction<< "Cell:" << celli
|
||||
<< " point:" << pointi
|
||||
<< " connected points:" << pPoints << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
const Tensor<scalar> mA
|
||||
(
|
||||
currentPoints[pPoints[0]] - pt,
|
||||
currentPoints[pPoints[1]] - pt,
|
||||
currentPoints[pPoints[2]] - pt
|
||||
);
|
||||
const scalar sigma(det(mA));
|
||||
|
||||
if (sigma < ROOTVSMALL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3 * pow(sigma, 2.0/3.0)/magSqr(mA)
|
||||
const scalar tetQ =
|
||||
scalar(3) * Foam::cbrt(Foam::sqr(sigma)) / magSqr(mA);
|
||||
cellQ += tetQ;
|
||||
nTets++;
|
||||
}
|
||||
}
|
||||
|
||||
return cellQ/nTets;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointSmoothers::geometricElementTransformPointSmoother::
|
||||
geometricElementTransformPointSmoother
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
pointSmoother(mesh, dict),
|
||||
transformationParameter_
|
||||
(
|
||||
readScalar(dict.lookup("transformationParameter"))
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::pointSmoothers::geometricElementTransformPointSmoother::calculate
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes,
|
||||
vectorField& pointDisplacement
|
||||
) const
|
||||
{
|
||||
// Lookup or generate the cell-point connectivity/
|
||||
const cellPointConnectivity& connectivity =
|
||||
MeshObject<polyMesh, MoveableMeshObject, cellPointConnectivity>::New
|
||||
(
|
||||
mesh()
|
||||
);
|
||||
|
||||
// Number of points used in each average
|
||||
labelField counts(mesh().nPoints(), -1);
|
||||
|
||||
// Reset the displacements which are about to be calculated
|
||||
reset(facesToMove, counts, pointDisplacement);
|
||||
|
||||
// Identify the cells which are to be moved
|
||||
labelHashSet cellsToMove(facesToMove.size()*2/3);
|
||||
forAll(facesToMove, faceToMoveI)
|
||||
{
|
||||
const label faceI(facesToMove[faceToMoveI]);
|
||||
|
||||
cellsToMove.insert(mesh().faceOwner()[faceI]);
|
||||
|
||||
if (mesh().isInternalFace(faceI))
|
||||
{
|
||||
cellsToMove.insert(mesh().faceNeighbour()[faceI]);
|
||||
}
|
||||
}
|
||||
|
||||
// Transformed point field
|
||||
pointField transformedPoints(currentPoints);
|
||||
|
||||
// Calculate the internal transformations
|
||||
forAllConstIter(labelHashSet, cellsToMove, iter)
|
||||
{
|
||||
const label cellI(iter.key());
|
||||
|
||||
const cell& cFaces
|
||||
(
|
||||
mesh().cells()[cellI]
|
||||
);
|
||||
const labelList cPoints
|
||||
(
|
||||
cFaces.labels(mesh().faces())
|
||||
);
|
||||
const edgeList cEdges
|
||||
(
|
||||
cFaces.edges(mesh().faces())
|
||||
);
|
||||
|
||||
// Calculate a transformed point for each cell point
|
||||
forAll(cPoints, cPointI)
|
||||
{
|
||||
const label pointI(cPoints[cPointI]);
|
||||
|
||||
if (counts[pointI] == -1) continue;
|
||||
|
||||
const labelList& pPoints
|
||||
(
|
||||
connectivity.cellPointPoints()[cellI][cPointI]
|
||||
);
|
||||
const labelList& pFaces
|
||||
(
|
||||
connectivity.cellPointFaces()[cellI][cPointI]
|
||||
);
|
||||
const label nPPoints(pPoints.size());
|
||||
|
||||
// Initial guess of the dual face centre
|
||||
vector dualAverage(vector::zero);
|
||||
forAll(pPoints, pPointI)
|
||||
{
|
||||
dualAverage +=
|
||||
currentPoints[pPoints[pPointI]]
|
||||
+ faceCentres[pFaces[pPointI]];
|
||||
}
|
||||
dualAverage /= 2*nPPoints;
|
||||
|
||||
// Calculate the dual face centre and normal
|
||||
vector dualNormal(vector::zero);
|
||||
forAll(pPoints, pPointI)
|
||||
{
|
||||
const label nextPPointI((pPointI + 1) % nPPoints);
|
||||
|
||||
point edgeCentre
|
||||
(
|
||||
0.5
|
||||
*(
|
||||
currentPoints[pPoints[pPointI]]
|
||||
+ currentPoints[pointI]
|
||||
)
|
||||
);
|
||||
point nextFaceCentre
|
||||
(
|
||||
faceCentres[pFaces[nextPPointI]]
|
||||
);
|
||||
point nextEdgeCentre
|
||||
(
|
||||
0.5
|
||||
*(
|
||||
currentPoints[pPoints[nextPPointI]]
|
||||
+ currentPoints[pointI]
|
||||
)
|
||||
);
|
||||
|
||||
dualNormal +=
|
||||
(nextFaceCentre - edgeCentre)
|
||||
^(edgeCentre - dualAverage);
|
||||
dualNormal +=
|
||||
(nextEdgeCentre - nextFaceCentre)
|
||||
^(nextFaceCentre - dualAverage);
|
||||
}
|
||||
vector dualNormalHat(dualNormal/max(mag(dualNormal), ROOTVSMALL));
|
||||
|
||||
scalar sumA(0);
|
||||
vector sumAc(vector::zero);
|
||||
forAll(pPoints, pPointI)
|
||||
{
|
||||
const label nextPPointI((pPointI + 1) % nPPoints);
|
||||
|
||||
point edgeCentre
|
||||
(
|
||||
0.5
|
||||
*(
|
||||
currentPoints[pPoints[pPointI]]
|
||||
+ currentPoints[pointI]
|
||||
)
|
||||
);
|
||||
point nextFaceCentre
|
||||
(
|
||||
faceCentres[pFaces[nextPPointI]]
|
||||
);
|
||||
point nextEdgeCentre
|
||||
(
|
||||
0.5
|
||||
*(
|
||||
currentPoints[pPoints[nextPPointI]]
|
||||
+ currentPoints[pointI]
|
||||
)
|
||||
);
|
||||
|
||||
vector c1 = edgeCentre + nextFaceCentre + dualAverage;
|
||||
vector c2 = nextFaceCentre + nextEdgeCentre + dualAverage;
|
||||
|
||||
vector n1 =
|
||||
(nextFaceCentre - edgeCentre)
|
||||
^(edgeCentre - dualAverage);
|
||||
vector n2 =
|
||||
(nextEdgeCentre - nextFaceCentre)
|
||||
^(nextFaceCentre - dualAverage);
|
||||
|
||||
scalar a1 = n1 & dualNormalHat;
|
||||
scalar a2 = n2 & dualNormalHat;
|
||||
|
||||
sumA += a1 + a2;
|
||||
sumAc += a1*c1 + a2*c2;
|
||||
}
|
||||
|
||||
const vector dualCentre(sumAc/max(sumA, ROOTVSMALL)/3);
|
||||
|
||||
// Calculate the transformed point
|
||||
transformedPoints[pointI] =
|
||||
dualCentre
|
||||
+ transformationParameter_
|
||||
*dualNormal/sqrt(max(mag(dualNormal), ROOTVSMALL));
|
||||
}
|
||||
|
||||
// Length scale
|
||||
scalar lengthScale(0), transformedLengthScale(0);
|
||||
forAll(cEdges, cEdgeI)
|
||||
{
|
||||
lengthScale +=
|
||||
cEdges[cEdgeI].mag(currentPoints);
|
||||
transformedLengthScale +=
|
||||
cEdges[cEdgeI].mag(transformedPoints);
|
||||
}
|
||||
lengthScale /= cEdges.size();
|
||||
transformedLengthScale /= cEdges.size();
|
||||
|
||||
const scalar lengthScaleRatio =
|
||||
(
|
||||
(transformedLengthScale > SMALL)
|
||||
? lengthScale/transformedLengthScale
|
||||
: scalar(0)
|
||||
);
|
||||
|
||||
// Add the displacement to the average
|
||||
forAll(cPoints, cPointI)
|
||||
{
|
||||
const label pointI(cPoints[cPointI]);
|
||||
|
||||
if (counts[pointI] == -1) continue;
|
||||
|
||||
const vector newPoint
|
||||
(
|
||||
cellCentres[cellI]
|
||||
+ lengthScaleRatio
|
||||
*(
|
||||
transformedPoints[pointI]
|
||||
- cellCentres[cellI]
|
||||
)
|
||||
);
|
||||
|
||||
++ counts[pointI];
|
||||
|
||||
pointDisplacement[pointI] += newPoint - oldPoints[pointI];
|
||||
}
|
||||
}
|
||||
|
||||
// Reset all the boundary faces
|
||||
reset(facesToMove, counts, pointDisplacement, false);
|
||||
|
||||
// Calculate the boundary transformations
|
||||
forAll(facesToMove, faceToMoveI)
|
||||
{
|
||||
const label faceI(facesToMove[faceToMoveI]);
|
||||
|
||||
if (!isInternalOrProcessorFace(faceI))
|
||||
{
|
||||
const labelList& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
// Face normal
|
||||
vector faceNormalHat(faceAreas[faceI]);
|
||||
faceNormalHat /= max(SMALL, mag(faceNormalHat));
|
||||
|
||||
// Calculate a transformed point for each face point
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
const label fPointIPrev
|
||||
(
|
||||
(fPointI - 1 + fPoints.size()) % fPoints.size()
|
||||
);
|
||||
const label fPointINext
|
||||
(
|
||||
(fPointI + 1) % fPoints.size()
|
||||
);
|
||||
|
||||
const vector dualCentre
|
||||
(
|
||||
currentPoints[pointI]/2
|
||||
+ (
|
||||
currentPoints[fPoints[fPointINext]]
|
||||
+ currentPoints[fPoints[fPointIPrev]]
|
||||
)/4
|
||||
);
|
||||
const vector dualNormal
|
||||
(
|
||||
(
|
||||
currentPoints[fPoints[fPointINext]]
|
||||
- currentPoints[fPoints[fPointIPrev]]
|
||||
)/2
|
||||
^faceNormalHat
|
||||
);
|
||||
|
||||
transformedPoints[pointI] =
|
||||
dualCentre
|
||||
+ transformationParameter_
|
||||
*dualNormal/sqrt(max(mag(dualNormal), ROOTVSMALL));
|
||||
}
|
||||
|
||||
// Length scale
|
||||
scalar lengthScale(0), transformedLengthScale(0);
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label fPointINext((fPointI + 1)%fPoints.size());
|
||||
|
||||
const label pointI(fPoints[fPointI]);
|
||||
const label pointINext(fPoints[fPointINext]);
|
||||
|
||||
lengthScale += mag
|
||||
(
|
||||
currentPoints[pointINext] - currentPoints[pointI]
|
||||
);
|
||||
transformedLengthScale += mag
|
||||
(
|
||||
transformedPoints[pointINext] - transformedPoints[pointI]
|
||||
);
|
||||
}
|
||||
lengthScale /= fPoints.size();
|
||||
transformedLengthScale /= fPoints.size();
|
||||
|
||||
const scalar lengthScaleRatio
|
||||
(
|
||||
(transformedLengthScale > SMALL)
|
||||
? lengthScale/transformedLengthScale
|
||||
: scalar(0)
|
||||
);
|
||||
|
||||
// Add the displacement to the average
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
const vector newPoint
|
||||
(
|
||||
faceCentres[faceI]
|
||||
+ lengthScaleRatio
|
||||
*(
|
||||
transformedPoints[pointI]
|
||||
- faceCentres[faceI]
|
||||
)
|
||||
);
|
||||
|
||||
++ counts[pointI];
|
||||
|
||||
pointDisplacement[pointI] += newPoint - oldPoints[pointI];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Average
|
||||
average(facesToMove, counts, pointDisplacement);
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::scalarField>
|
||||
Foam::pointSmoothers::geometricElementTransformPointSmoother::cellQuality
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const pointField& currentPoints
|
||||
)
|
||||
{
|
||||
const cellPointConnectivity& connectivity =
|
||||
MeshObject<polyMesh, MoveableMeshObject, cellPointConnectivity>::New
|
||||
(
|
||||
mesh
|
||||
);
|
||||
|
||||
tmp<scalarField> tfld(tmp<scalarField>::New(mesh.nCells()));
|
||||
scalarField& fld = tfld.ref();
|
||||
|
||||
forAll(fld, celli)
|
||||
{
|
||||
fld[celli] = cellQuality(mesh, currentPoints, connectivity, celli);
|
||||
}
|
||||
|
||||
return tfld;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,149 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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::pointSmoothers::geometricElementTransformPointSmoother
|
||||
|
||||
Description
|
||||
Geometric Element Transformation Method (GETMe) point smoother. Points are
|
||||
moved in a direction normal to the face of the dual element. This tends to
|
||||
orthogonalise elements. This method can "push" as well as "pull".
|
||||
|
||||
The original references for this method only formulate it for a limited
|
||||
variety of specific polyhedra. This version is written for arbitrary
|
||||
polyhedra, and most closely follows the following reference:
|
||||
|
||||
\verbatim
|
||||
"Fast smoothing of mixed volume meshes based on the effective geometric
|
||||
element transformation method"
|
||||
Dimitris Vartziotis, Joachim Wipper,
|
||||
Comput. Methods Appl. Mech. Engrg. 201-204 (2012) 65-81
|
||||
\endverbatim
|
||||
|
||||
This implementation does not include the various specific measures employed
|
||||
in the referred article to improve the quality of types of irregular
|
||||
polyhedra. It also does not use the same quality criteria as these are only
|
||||
suitable for cell vertices with exactly three connecting edges.
|
||||
|
||||
SourceFiles
|
||||
geometricElementTransformPointSmoother.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef geometricElementTransformPointSmoother_H
|
||||
#define geometricElementTransformPointSmoother_H
|
||||
|
||||
#include "pointSmoother.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
class cellPointConnectivity;
|
||||
|
||||
namespace pointSmoothers
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class geometricElementTransformPointSmoother Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class geometricElementTransformPointSmoother
|
||||
:
|
||||
public pointSmoother
|
||||
{
|
||||
private:
|
||||
|
||||
// Private Data
|
||||
|
||||
//- Transformation parameter
|
||||
const scalar transformationParameter_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
static scalar cellQuality
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const pointField& currentPoints,
|
||||
const cellPointConnectivity& connectivity,
|
||||
const label celli
|
||||
);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("geometricElementTransform");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from a dictionary and a mesh
|
||||
geometricElementTransformPointSmoother
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~geometricElementTransformPointSmoother() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Calculate the point displacements
|
||||
virtual void calculate
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes,
|
||||
vectorField& pointDisplacement
|
||||
) const;
|
||||
|
||||
static tmp<scalarField> cellQuality
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const pointField& currentPoints
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace pointSmoothers
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,164 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "laplacianConstraintPointSmoother.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "meshPointPatch.H"
|
||||
#include "processorPointPatch.H"
|
||||
#include "pointConstraint.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace pointSmoothers
|
||||
{
|
||||
defineTypeNameAndDebug(laplacianConstraintPointSmoother, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
pointSmoother,
|
||||
laplacianConstraintPointSmoother,
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointSmoothers::laplacianConstraintPointSmoother::
|
||||
laplacianConstraintPointSmoother
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
pointSmoother(mesh, dict)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::pointSmoothers::laplacianConstraintPointSmoother::calculate
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes,
|
||||
vectorField& pointDisplacement
|
||||
) const
|
||||
{
|
||||
// Get pointMesh so we can get at the constraints
|
||||
const auto& pMesh = pointMesh::New(mesh());
|
||||
|
||||
// Number of points used in each average
|
||||
labelField counts(mesh().nPoints(), 0);
|
||||
|
||||
// Reset the displacements which are about to be calculated
|
||||
reset(facesToMove, counts, pointDisplacement);
|
||||
|
||||
// Get affected points
|
||||
const bitSet isMovingPoint(pointsToMove(facesToMove, true));
|
||||
|
||||
|
||||
// Set constraints:
|
||||
// - internal points : 0
|
||||
// - normal boundary points : 1
|
||||
// - meshPointPatch : 1 (surface)
|
||||
// 2 (feat-edge)
|
||||
// 3 (feat-point)
|
||||
labelList nConstraints(mesh().nPoints(), Zero);
|
||||
|
||||
for (const auto& pp : pMesh.boundary())
|
||||
{
|
||||
const auto& mp = pp.meshPoints();
|
||||
const auto* mppPtr = isA<meshPointPatch>(pp);
|
||||
if (mppPtr)
|
||||
{
|
||||
const auto& pc = mppPtr->constraints();
|
||||
forAll(mp, i)
|
||||
{
|
||||
nConstraints[mp[i]] = pc[i].first();
|
||||
}
|
||||
}
|
||||
else //if (!isA<processorPointPatch>(pp)) // what about cyclic? AMI?
|
||||
{
|
||||
forAll(mp, i)
|
||||
{
|
||||
// Indirectly detect any constraint
|
||||
pointConstraint pc;
|
||||
pp.applyConstraint(i, pc);
|
||||
nConstraints[mp[i]] = pc.first();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Average from equally constrained points
|
||||
|
||||
const auto& edges = mesh().edges();
|
||||
const auto& pointEdges = mesh().pointEdges();
|
||||
forAll(pointEdges, pointi)
|
||||
{
|
||||
if (isMovingPoint[pointi])
|
||||
{
|
||||
const auto& pEdges = pointEdges[pointi];
|
||||
for (const label edgei : pEdges)
|
||||
{
|
||||
const label otherPointi = edges[edgei].otherVertex(pointi);
|
||||
if (nConstraints[otherPointi] >= nConstraints[pointi])
|
||||
{
|
||||
pointDisplacement[pointi] +=
|
||||
currentPoints[otherPointi]
|
||||
- oldPoints[pointi];
|
||||
|
||||
++ counts[pointi];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Average
|
||||
average(facesToMove, counts, pointDisplacement);
|
||||
|
||||
|
||||
// Make sure to set any unconnected points (or boundary feature points)
|
||||
// since otherwise they never see the effect of the boundary conditions
|
||||
forAll(counts, pointi)
|
||||
{
|
||||
if (isMovingPoint[pointi] && !counts[pointi])
|
||||
{
|
||||
pointDisplacement[pointi] = currentPoints[pointi]-oldPoints[pointi];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,105 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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::laplacianConstraintPointSmoother
|
||||
|
||||
Description
|
||||
Laplacian point smoothing. Points are moved towards the average of the
|
||||
surrounding points. In case of constraints (boundary points) only
|
||||
use average of equal or higher constrained points.
|
||||
|
||||
SourceFiles
|
||||
laplacianConstraintPointSmoother.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef laplacianConstraintPointSmoother_H
|
||||
#define laplacianConstraintPointSmoother_H
|
||||
|
||||
#include "pointSmoother.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace pointSmoothers
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class laplacianConstraintPointSmoother Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class laplacianConstraintPointSmoother
|
||||
:
|
||||
public pointSmoother
|
||||
{
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("laplacianConstraint");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from a dictionary and a polyMesh
|
||||
laplacianConstraintPointSmoother
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~laplacianConstraintPointSmoother() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Calculate the point displacement
|
||||
virtual void calculate
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes,
|
||||
vectorField& pointDisplacement
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace pointSmoothers
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,139 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "laplacianPointSmoother.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace pointSmoothers
|
||||
{
|
||||
defineTypeNameAndDebug(laplacianPointSmoother, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
pointSmoother,
|
||||
laplacianPointSmoother,
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointSmoothers::laplacianPointSmoother::laplacianPointSmoother
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
pointSmoother(mesh, dict)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::pointSmoothers::laplacianPointSmoother::calculate
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes,
|
||||
vectorField& pointDisplacement
|
||||
) const
|
||||
{
|
||||
// Number of points used in each average
|
||||
labelField counts(mesh().nPoints(), 0);
|
||||
|
||||
// Reset the displacements which are about to be calculated
|
||||
reset(facesToMove, counts, pointDisplacement);
|
||||
|
||||
// Sum the non-internal face displacements
|
||||
forAll(facesToMove, faceToMoveI)
|
||||
{
|
||||
const label faceI(facesToMove[faceToMoveI]);
|
||||
|
||||
if (!isInternalOrProcessorFace(faceI))
|
||||
{
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
pointDisplacement[pointI] +=
|
||||
faceCentres[faceI]
|
||||
- oldPoints[pointI];
|
||||
|
||||
++ counts[pointI];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sum the internal face displacements
|
||||
forAll(facesToMove, faceToMoveI)
|
||||
{
|
||||
const label faceI(facesToMove[faceToMoveI]);
|
||||
|
||||
if (isInternalOrProcessorFace(faceI))
|
||||
{
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
if (counts[pointI] == 0)
|
||||
{
|
||||
const labelList& pCells(mesh().pointCells()[pointI]);
|
||||
|
||||
forAll(pCells, pCellI)
|
||||
{
|
||||
const label cellI(pCells[pCellI]);
|
||||
|
||||
pointDisplacement[pointI] +=
|
||||
cellCentres[cellI]
|
||||
- oldPoints[pointI];
|
||||
|
||||
++ counts[pointI];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Average
|
||||
average(facesToMove, counts, pointDisplacement);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,105 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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::laplacianPointSmoother
|
||||
|
||||
Description
|
||||
Laplacian point smoothing (or rather Lloyds). Points are moved towards
|
||||
the average of the surrounding cell centres (or average of boundary
|
||||
face centres for points on boundary)
|
||||
|
||||
SourceFiles
|
||||
laplacianPointSmoother.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef laplacianPointSmoother_H
|
||||
#define laplacianPointSmoother_H
|
||||
|
||||
#include "pointSmoother.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace pointSmoothers
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class laplacianPointSmoother Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class laplacianPointSmoother
|
||||
:
|
||||
public pointSmoother
|
||||
{
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("laplacian");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from a dictionary and a polyMesh
|
||||
laplacianPointSmoother
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~laplacianPointSmoother() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Calculate the point displacement
|
||||
virtual void calculate
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes,
|
||||
vectorField& pointDisplacement
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace pointSmoothers
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,300 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "pointSmoother.H"
|
||||
#include "pointConstraints.H"
|
||||
#include "polyMeshTools.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(pointSmoother, 0);
|
||||
defineRunTimeSelectionTable(pointSmoother, dictionary);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
bool Foam::pointSmoother::isInternalOrProcessorFace(const label faceI) const
|
||||
{
|
||||
if (mesh().isInternalFace(faceI))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
processorPatchIDs_
|
||||
[
|
||||
mesh().boundaryMesh().patchID()
|
||||
[
|
||||
faceI - mesh().nInternalFaces()
|
||||
]
|
||||
]
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Foam::autoPtr<Foam::PackedBoolList> Foam::pointSmoother::pointsToMove
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const bool moveInternalFaces
|
||||
) const
|
||||
{
|
||||
autoPtr<PackedBoolList> markerPtr
|
||||
(
|
||||
new PackedBoolList(mesh().nPoints(), false)
|
||||
);
|
||||
|
||||
PackedBoolList& marker(markerPtr());
|
||||
|
||||
forAll(facesToMove, faceToMoveI)
|
||||
{
|
||||
const label faceI(facesToMove[faceToMoveI]);
|
||||
|
||||
if (moveInternalFaces || !isInternalOrProcessorFace(faceI))
|
||||
{
|
||||
const face& fPoints(mesh().faces()[faceI]);
|
||||
|
||||
forAll(fPoints, fPointI)
|
||||
{
|
||||
const label pointI(fPoints[fPointI]);
|
||||
|
||||
marker[pointI] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh(),
|
||||
marker,
|
||||
orEqOp<unsigned int>(),
|
||||
0U
|
||||
);
|
||||
|
||||
return markerPtr;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointSmoother::pointSmoother
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
mesh_(mesh)
|
||||
{
|
||||
for (const auto& pp : mesh.boundaryMesh())
|
||||
{
|
||||
if (isA<processorPolyPatch>(pp))
|
||||
{
|
||||
processorPatchIDs_.insert(pp.index());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::pointSmoother>
|
||||
Foam::pointSmoother::New
|
||||
(
|
||||
const word& pointSmootherType,
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
Info<< "Selecting pointSmoother type " << pointSmootherType << endl;
|
||||
|
||||
auto cstrIter = dictionaryConstructorTablePtr_->find(pointSmootherType);
|
||||
|
||||
if (cstrIter == dictionaryConstructorTablePtr_->end())
|
||||
{
|
||||
FatalErrorIn("pointSmoother::New")
|
||||
<< "Unknown " << typeName << " type "
|
||||
<< pointSmootherType << endl << endl
|
||||
<< "Valid " << typeName << " types are : " << endl
|
||||
<< dictionaryConstructorTablePtr_->sortedToc()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
return cstrIter()(mesh, dict);
|
||||
}
|
||||
|
||||
|
||||
Foam::autoPtr<Foam::pointSmoother>
|
||||
Foam::pointSmoother::New
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
word pointSmootherType(dict.lookup(typeName));
|
||||
|
||||
return New(pointSmootherType, mesh, dict);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointSmoother::~pointSmoother()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::pointSmoother::update
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes,
|
||||
pointVectorField& pointDisplacement,
|
||||
const bool correctBCs
|
||||
) const
|
||||
{
|
||||
// Apply point smoothing (without boundary conditions!)
|
||||
calculate
|
||||
(
|
||||
facesToMove,
|
||||
oldPoints,
|
||||
currentPoints,
|
||||
faceCentres,
|
||||
faceAreas,
|
||||
cellCentres,
|
||||
cellVolumes,
|
||||
pointDisplacement.ref()
|
||||
);
|
||||
|
||||
// Note: do not want to apply boundary conditions whilst smoothing so
|
||||
// disable for now
|
||||
//// Take over boundary values
|
||||
//for (auto& ppf : pointDisplacement.boundaryFieldRef())
|
||||
//{
|
||||
// ppf.operator==(ppf.patchInternalField());
|
||||
//}
|
||||
|
||||
if (correctBCs)
|
||||
{
|
||||
// Apply (multi-)patch constraints
|
||||
pointConstraints::New
|
||||
(
|
||||
pointDisplacement().mesh()
|
||||
).constrainDisplacement(pointDisplacement);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::scalarField> Foam::pointSmoother::faceQuality
|
||||
(
|
||||
const pointField& points,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes
|
||||
) const
|
||||
{
|
||||
// See e.g.
|
||||
// - src/functionObjects/field/stabilityBlendingFactor/
|
||||
// stabilityBlendingFactor.H
|
||||
// - maybe add function to motionSmootherCheck to return value instead
|
||||
// of yes/no for invalid?
|
||||
// - for now just look at non-ortho
|
||||
|
||||
tmp<scalarField> tortho
|
||||
(
|
||||
polyMeshTools::faceOrthogonality
|
||||
(
|
||||
mesh(),
|
||||
faceAreas,
|
||||
cellCentres
|
||||
)
|
||||
);
|
||||
|
||||
//return max(tortho, scalar(0.0));
|
||||
return tortho;
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::scalarField> Foam::pointSmoother::cellQuality
|
||||
(
|
||||
const pointField& points,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes
|
||||
) const
|
||||
{
|
||||
// Get face-based non-ortho
|
||||
tmp<scalarField> tfaceOrtho
|
||||
(
|
||||
faceQuality
|
||||
(
|
||||
points,
|
||||
faceCentres,
|
||||
faceAreas,
|
||||
cellCentres,
|
||||
cellVolumes
|
||||
)
|
||||
);
|
||||
const auto& faceOrtho = tfaceOrtho();
|
||||
|
||||
// Min over cells
|
||||
tmp<scalarField> tortho(new scalarField(mesh().nCells(), GREAT));
|
||||
auto& ortho = tortho.ref();
|
||||
|
||||
const auto& own = mesh().faceOwner();
|
||||
const auto& nei = mesh().faceNeighbour();
|
||||
|
||||
forAll(own, facei)
|
||||
{
|
||||
auto& o = ortho[own[facei]];
|
||||
o = min(o, faceOrtho[facei]);
|
||||
}
|
||||
for (label facei = 0; facei < mesh().nInternalFaces(); facei++)
|
||||
{
|
||||
auto& o = ortho[nei[facei]];
|
||||
o = min(o, faceOrtho[facei]);
|
||||
}
|
||||
|
||||
return tortho;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,279 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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::pointSmoother
|
||||
|
||||
Description
|
||||
Abstract base class for point smoothing methods. Handles parallel
|
||||
communication via reset and average functions.
|
||||
|
||||
SourceFiles
|
||||
pointSmoother.C
|
||||
pointSmootherTemplates.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef pointSmoother_H
|
||||
#define pointSmoother_H
|
||||
|
||||
#include "polyMeshGeometry.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
#include "PackedBoolList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class pointSmoother Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class pointSmoother
|
||||
{
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
//- Reference to the polyMesh
|
||||
const polyMesh& mesh_;
|
||||
|
||||
//- Set of the processor patch indices
|
||||
labelHashSet processorPatchIDs_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
pointSmoother(const pointSmoother&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const pointSmoother&);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Test if the given face is internal or on a processor boundary
|
||||
bool isInternalOrProcessorFace(const label faceI) const;
|
||||
|
||||
//- Get a boolean list of the points to be moved
|
||||
autoPtr<PackedBoolList> pointsToMove
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const bool moveInternalFaces
|
||||
) const;
|
||||
|
||||
//- Reset the relevant weights and displacements to zero
|
||||
template <class weightType>
|
||||
void reset
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
Field<weightType>& weights,
|
||||
vectorField& pointDisplacement,
|
||||
const bool resetInternalFaces = true
|
||||
) const;
|
||||
|
||||
//- Average the displacements using the weights provided
|
||||
template <class weightType>
|
||||
void average
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
Field<weightType>& weights,
|
||||
vectorField& pointDisplacement
|
||||
) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("pointSmoother");
|
||||
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
pointSmoother,
|
||||
dictionary,
|
||||
(const polyMesh& mesh, const dictionary& dict),
|
||||
(mesh, dict)
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from a dictionary and a point displacement field
|
||||
pointSmoother(const polyMesh& mesh, const dictionary&);
|
||||
|
||||
|
||||
// Selector
|
||||
|
||||
//- Construct given type
|
||||
static autoPtr<pointSmoother> New
|
||||
(
|
||||
const word& pointSmootherType,
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
//- Construct with type looked up from dictionary
|
||||
static autoPtr<pointSmoother> New
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~pointSmoother();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access the mesh
|
||||
const polyMesh& mesh() const
|
||||
{
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
//- Update the point displacements and apply constraints
|
||||
void update
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes,
|
||||
pointVectorField& pointDisplacement,
|
||||
const bool correctBCs = true
|
||||
) const;
|
||||
|
||||
//- Update the point displacements and apply constraints
|
||||
void update
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const polyMeshGeometry& meshGeometry,
|
||||
pointVectorField& pointDisplacement,
|
||||
const bool correctBCs = true
|
||||
) const
|
||||
{
|
||||
update
|
||||
(
|
||||
facesToMove,
|
||||
oldPoints,
|
||||
currentPoints,
|
||||
meshGeometry.faceCentres(),
|
||||
meshGeometry.faceAreas(),
|
||||
meshGeometry.cellCentres(),
|
||||
meshGeometry.cellVolumes(),
|
||||
pointDisplacement,
|
||||
correctBCs
|
||||
);
|
||||
}
|
||||
|
||||
//- Calculate the point displacement
|
||||
virtual void calculate
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes,
|
||||
vectorField& pointDisplacement
|
||||
) const = 0;
|
||||
|
||||
//- Update the point displacements
|
||||
virtual void calculate
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
const pointField& oldPoints,
|
||||
const pointField& currentPoints,
|
||||
const polyMeshGeometry& meshGeometry,
|
||||
vectorField& pointDisplacement
|
||||
) const
|
||||
{
|
||||
calculate
|
||||
(
|
||||
facesToMove,
|
||||
oldPoints,
|
||||
currentPoints,
|
||||
meshGeometry.faceCentres(),
|
||||
meshGeometry.faceAreas(),
|
||||
meshGeometry.cellCentres(),
|
||||
meshGeometry.cellVolumes(),
|
||||
pointDisplacement
|
||||
);
|
||||
}
|
||||
|
||||
//- Check element quality: 1 = best, 0 = invalid. (also negative?)
|
||||
//- Topology from mesh, point locations supplied.
|
||||
//- Move to motionSolver level?
|
||||
virtual tmp<scalarField> faceQuality
|
||||
(
|
||||
const pointField& points,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes
|
||||
) const;
|
||||
|
||||
//- Check element quality: 1 = best, 0 = invalid.
|
||||
//- Topology from mesh, point locations supplied.
|
||||
//- Move to motionSolver level?
|
||||
virtual tmp<scalarField> cellQuality
|
||||
(
|
||||
const pointField& points,
|
||||
const pointField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const pointField& cellCentres,
|
||||
const scalarField& cellVolumes
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "pointSmootherTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,105 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "pointSmoother.H"
|
||||
#include "syncTools.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
template <class weightType>
|
||||
void Foam::pointSmoother::reset
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
Field<weightType>& weights,
|
||||
vectorField& pointDisplacement,
|
||||
const bool resetInternalFaces
|
||||
) const
|
||||
{
|
||||
autoPtr<PackedBoolList> resetPointsPtr
|
||||
(
|
||||
pointsToMove(facesToMove, resetInternalFaces)
|
||||
);
|
||||
|
||||
const PackedBoolList& resetPoints(resetPointsPtr);
|
||||
|
||||
forAll(resetPoints, pointI)
|
||||
{
|
||||
if (resetPoints[pointI])
|
||||
{
|
||||
weights[pointI] = pTraits<weightType>::zero;
|
||||
pointDisplacement[pointI] = vector::zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class weightType>
|
||||
void Foam::pointSmoother::average
|
||||
(
|
||||
const labelList& facesToMove,
|
||||
Field<weightType>& weights,
|
||||
vectorField& pointDisplacement
|
||||
) const
|
||||
{
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh(),
|
||||
weights,
|
||||
plusEqOp<weightType>(),
|
||||
pTraits<weightType>::zero
|
||||
);
|
||||
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh(),
|
||||
pointDisplacement,
|
||||
plusEqOp<vector>(),
|
||||
vector::zero
|
||||
);
|
||||
|
||||
autoPtr<PackedBoolList> averagePointsPtr
|
||||
(
|
||||
pointsToMove(facesToMove, true)
|
||||
);
|
||||
|
||||
const PackedBoolList& averagePoints(averagePointsPtr);
|
||||
|
||||
forAll(averagePoints, pointI)
|
||||
{
|
||||
if
|
||||
(
|
||||
averagePoints[pointI]
|
||||
&& weights[pointI] != pTraits<weightType>::zero
|
||||
)
|
||||
{
|
||||
pointDisplacement[pointI] /= weights[pointI];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2015 OpenFOAM Foundation
|
||||
Copyright (C) 2020 OpenCFD Ltd.
|
||||
Copyright (C) 2020,2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -28,8 +28,8 @@ Class
|
||||
Foam::addPatchCellLayer
|
||||
|
||||
Description
|
||||
Adds layers of cells to outside of polyPatch. Can optionally create
|
||||
stand-alone extruded mesh (addToMesh=false).
|
||||
Adds layers of cells to outside (or inside) of polyMesh. Can optionally
|
||||
create stand-alone extruded mesh (addToMesh=false).
|
||||
|
||||
Call setRefinement with offset vector for every patch point and number
|
||||
of layers per patch face and number of layers per patch point.
|
||||
@ -51,24 +51,47 @@ Description
|
||||
\verbatim
|
||||
Was:
|
||||
|
||||
a b <- patch of boundary face
|
||||
+------+------+
|
||||
| | | <- original cells
|
||||
+------+------+
|
||||
a b <- patch of boundary face
|
||||
+------+------+
|
||||
| | | <- original cells
|
||||
+------+------+
|
||||
|
||||
Becomes:
|
||||
Extrusion:
|
||||
|
||||
a b <- patch of boundary face
|
||||
+------+------+
|
||||
+ +------+
|
||||
+------+------+
|
||||
+------+------+
|
||||
| | | <- original cells
|
||||
+------+------+
|
||||
|
||||
added added
|
||||
face cell
|
||||
---- ----
|
||||
a b <- patch of boundary face
|
||||
+------+------+ 3
|
||||
| | | 2
|
||||
+ +------+ 2
|
||||
| | | 1
|
||||
+------+------+ 1
|
||||
| | | 0
|
||||
+------+------+ 0 <- original boundary faces
|
||||
| | | <- original cells
|
||||
+------+------+
|
||||
|
||||
|
||||
|
||||
Intrusion:
|
||||
|
||||
face cell
|
||||
---- ----
|
||||
a b <- patch of boundary face
|
||||
+------+------+ 0
|
||||
| | | 0
|
||||
+------+------+ 1
|
||||
| | | 1
|
||||
+ +------+ 2
|
||||
| | | 2
|
||||
+------+------+ 3
|
||||
| | | <- original cells
|
||||
+------+------+
|
||||
\endverbatim
|
||||
|
||||
|
||||
- added faces get same patchID as face they are extruded from
|
||||
- 'side' faces (i.e. on the edge of pp) get the patchID/zoneID of the
|
||||
other patch/zone they are connected to (hopefully only 1)
|
||||
|
||||
@ -78,10 +101,15 @@ Description
|
||||
\verbatim
|
||||
a b b <- patch of boundary face
|
||||
+------+------+------+
|
||||
| | | |
|
||||
| | | | <- cells
|
||||
| | | |
|
||||
+------+------+------+
|
||||
|
||||
|
||||
(shown for extrusion mode only):
|
||||
|
||||
|
||||
^ ^ <- wanted extrusion vector (none at far right)
|
||||
a | b | b <- patch of boundary face
|
||||
+------+------+------+
|
||||
@ -123,7 +151,7 @@ class primitiveMesh;
|
||||
class globalIndex;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class addPatchCellLayer Declaration
|
||||
Class addPatchCellLayer Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class addPatchCellLayer
|
||||
@ -136,15 +164,23 @@ class addPatchCellLayer
|
||||
//- Add layers to existing mesh or create new mesh
|
||||
const bool addToMesh_;
|
||||
|
||||
//- Add layers to outside of mesh or to inside
|
||||
const bool extrude_;
|
||||
|
||||
|
||||
//- For all patchpoints: list of added points (size 0 or nLayers)
|
||||
// First point in list is one nearest to original point in patch,
|
||||
// last one is the new point on the surface.
|
||||
// last one is
|
||||
// - extrude : the new point on the surface
|
||||
// - intrude : the point connecting to the original cell.
|
||||
labelListList addedPoints_;
|
||||
|
||||
//- For all patchfaces: list of layer faces.
|
||||
// - empty if no face extruded
|
||||
// - first face is original boundary face
|
||||
// - last one is new boundary face.
|
||||
// - first element is original patch face
|
||||
// - last element is
|
||||
// - extrude : the new boundary face
|
||||
// - intrude : the new internal face to the original cell.
|
||||
labelListList layerFaces_;
|
||||
|
||||
|
||||
@ -226,25 +262,6 @@ class addPatchCellLayer
|
||||
label& inflateFaceI
|
||||
);
|
||||
|
||||
//- Find internal or boundary face to get extrude properties
|
||||
// from. zoneFlip consistent with ppEdge ordering
|
||||
static void findZoneFace
|
||||
(
|
||||
const bool useInternalFaces,
|
||||
const bool useBoundaryFaces,
|
||||
|
||||
const polyMesh& mesh,
|
||||
const indirectPrimitivePatch& pp,
|
||||
const label ppEdgeI,
|
||||
const labelUIndList& excludeFaces,
|
||||
const labelList& meshFaces,
|
||||
|
||||
label& inflateFaceI,
|
||||
label& patchI,
|
||||
label& zoneI,
|
||||
bool& zoneFlip
|
||||
);
|
||||
|
||||
//- Mark internal and boundary edges of patch. In mesh edges
|
||||
//- since processor might not have pp but does have edge.
|
||||
static void markPatchEdges
|
||||
@ -294,7 +311,12 @@ public:
|
||||
// Constructors
|
||||
|
||||
//- Construct from mesh.
|
||||
explicit addPatchCellLayer(const polyMesh&, const bool addToMesh=true);
|
||||
explicit addPatchCellLayer
|
||||
(
|
||||
const polyMesh&,
|
||||
const bool addToMesh=true,
|
||||
const bool extrude=true
|
||||
);
|
||||
|
||||
|
||||
// Member Functions
|
||||
@ -314,8 +336,13 @@ public:
|
||||
}
|
||||
|
||||
//- Helper: get added cells per patch face.
|
||||
// addedCells[patchFace] is list of cells added. Last element is
|
||||
// the top cells (i.e. the boundary cell)
|
||||
// addedCells[patchFace] is list of cells added.
|
||||
// extrude :
|
||||
// first element : next to original cell
|
||||
// last element : is the top cell (i.e. the boundary cell)
|
||||
// intrude :
|
||||
// first element : top cell
|
||||
// last element : next to original cell
|
||||
static labelListList addedCells
|
||||
(
|
||||
const polyMesh&,
|
||||
@ -328,6 +355,18 @@ public:
|
||||
|
||||
// Edit
|
||||
|
||||
//- Per patch edge the pp faces (in global indices) using it.
|
||||
// Uses ListOps::uniqueEqOp to remove duplicates. On coupled
|
||||
// faces only selects the one with the correct orientation/flip
|
||||
// (assumes the orientation is opposite on a coupled face pair)
|
||||
static labelListList globalEdgeFaces
|
||||
(
|
||||
const polyMesh&,
|
||||
const globalIndex& globalFaces,
|
||||
const indirectPrimitivePatch& pp,
|
||||
const bitSet& orientation
|
||||
);
|
||||
|
||||
//- Per patch edge the pp faces (in global indices) using it.
|
||||
// Uses ListOps::uniqueEqOp to remove duplicates.
|
||||
static labelListList globalEdgeFaces
|
||||
@ -454,6 +493,28 @@ public:
|
||||
const labelList& faceMap, // new to old patch faces
|
||||
const labelList& pointMap // new to old patch points
|
||||
);
|
||||
|
||||
|
||||
|
||||
//- Helper: given patch and points on patch that are extruded
|
||||
// (to slave side or master side) find the affected
|
||||
// points. Calculates by walking across faces which vertices on
|
||||
// which face are affected. isDupMeshPoint:
|
||||
// -1 : unaffected
|
||||
// >=0 : should use local duplicate of point
|
||||
// (though it does not tell us whether it should use
|
||||
// slave side or master side)
|
||||
static void findDuplicatedPoints
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const indirectPrimitivePatch& pp,
|
||||
const bitSet& ppFlip, // optional orientation on top of pp
|
||||
const bitSet& isBlockedFace,// any mesh faces not to be
|
||||
// traversed.Usually pp.addressing()
|
||||
const bitSet& isDupPatchPoint,
|
||||
const bool extrude, // which side to extrude
|
||||
faceList& isDupMeshPoint
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ Usage
|
||||
\table
|
||||
Property | Description | Required | Default value
|
||||
scale | Time varying scale | yes |
|
||||
patch | patchField providing the raw patch value | yes |
|
||||
refValue | patchField providing the raw patch value | yes |
|
||||
\endtable
|
||||
|
||||
Example of the boundary condition specification to scale a reference
|
||||
|
||||
@ -164,6 +164,23 @@ public:
|
||||
|
||||
//- Do what is necessary if the mesh has moved
|
||||
virtual void movePoints();
|
||||
|
||||
//- Calculate geometry quantities using mesh topology and provided
|
||||
//- points. If oldPoints provided only does local update. Returns
|
||||
//- true if anything changed, false otherwise
|
||||
virtual bool updateGeom
|
||||
(
|
||||
const pointField& points,
|
||||
const refPtr<pointField>& oldPoints, // optional old points
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas,
|
||||
pointField& cellCentres,
|
||||
scalarField& cellVolumes
|
||||
) const
|
||||
{
|
||||
NotImplemented;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@ License
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "surfaceFields.H"
|
||||
#include "volFields.H"
|
||||
#include "primitiveMeshTools.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
@ -390,4 +391,36 @@ Foam::basicFvGeometryScheme::nonOrthCorrectionVectors() const
|
||||
}
|
||||
|
||||
|
||||
bool Foam::basicFvGeometryScheme::updateGeom
|
||||
(
|
||||
const pointField& points,
|
||||
const refPtr<pointField>& oldPoints,
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas,
|
||||
pointField& cellCentres,
|
||||
scalarField& cellVolumes
|
||||
) const
|
||||
{
|
||||
primitiveMeshTools::makeFaceCentresAndAreas
|
||||
(
|
||||
mesh_,
|
||||
points,
|
||||
faceCentres,
|
||||
faceAreas
|
||||
);
|
||||
|
||||
primitiveMeshTools::makeCellCentresAndVols
|
||||
(
|
||||
mesh_,
|
||||
faceCentres,
|
||||
faceAreas,
|
||||
cellCentres,
|
||||
cellVolumes
|
||||
);
|
||||
|
||||
// Assume something has changed
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -93,6 +93,19 @@ public:
|
||||
|
||||
//- Return non-orthogonality correction vectors
|
||||
virtual tmp<surfaceVectorField> nonOrthCorrectionVectors() const;
|
||||
|
||||
//- Calculate geometry quantities using mesh topology and provided
|
||||
//- points. If oldPoints provided only does local update. Returns
|
||||
//- true if anything changed, false otherwise
|
||||
virtual bool updateGeom
|
||||
(
|
||||
const pointField& points,
|
||||
const refPtr<pointField>& oldPoints, // optional old points
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas,
|
||||
pointField& cellCentres,
|
||||
scalarField& cellVolumes
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -160,6 +160,19 @@ public:
|
||||
// const labelHashSet& patchIDs,
|
||||
// const word& defaultPatchDistMethod
|
||||
//) const = 0;
|
||||
|
||||
//- Calculate geometry quantities using mesh topology and provided
|
||||
//- points. If oldPoints provided only does local update. Returns
|
||||
//- true if anything changed, false otherwise
|
||||
virtual bool updateGeom
|
||||
(
|
||||
const pointField& points,
|
||||
const refPtr<pointField>& oldPoints, // optional old points
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas,
|
||||
pointField& cellCentres,
|
||||
scalarField& cellVolumes
|
||||
) const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -456,4 +456,46 @@ void Foam::highAspectRatioFvGeometryScheme::movePoints()
|
||||
}
|
||||
|
||||
|
||||
bool Foam::highAspectRatioFvGeometryScheme::updateGeom
|
||||
(
|
||||
const pointField& points,
|
||||
const refPtr<pointField>& oldPoints,
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas,
|
||||
pointField& cellCentres,
|
||||
scalarField& cellVolumes
|
||||
) const
|
||||
{
|
||||
// Basic
|
||||
basicFvGeometryScheme::updateGeom
|
||||
(
|
||||
points,
|
||||
oldPoints,
|
||||
faceCentres,
|
||||
faceAreas,
|
||||
cellCentres,
|
||||
cellVolumes
|
||||
);
|
||||
|
||||
// Average opposite faces
|
||||
pointField avgFaceCentres;
|
||||
pointField avgCellCentres;
|
||||
makeAverageCentres
|
||||
(
|
||||
mesh_,
|
||||
points,
|
||||
faceAreas,
|
||||
mag(faceAreas),
|
||||
avgFaceCentres,
|
||||
avgCellCentres
|
||||
);
|
||||
|
||||
faceCentres = std::move(avgFaceCentres);
|
||||
cellCentres = std::move(avgCellCentres);
|
||||
|
||||
// Assume something has changed.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -123,6 +123,19 @@ public:
|
||||
|
||||
//- Do what is necessary if the mesh has moved
|
||||
virtual void movePoints();
|
||||
|
||||
//- Calculate geometry quantities using mesh topology and provided
|
||||
//- points. If oldPoints provided only does local update. Returns
|
||||
//- true if anything changed, false otherwise
|
||||
virtual bool updateGeom
|
||||
(
|
||||
const pointField& points,
|
||||
const refPtr<pointField>& oldPoints, // optional old points
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas,
|
||||
pointField& cellCentres,
|
||||
scalarField& cellVolumes
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -47,6 +47,92 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::parallelFvGeometryScheme::adjustGeometry
|
||||
(
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas
|
||||
) const
|
||||
{
|
||||
pointField syncedBCentres;
|
||||
syncedBCentres = SubField<vector>
|
||||
(
|
||||
faceCentres,
|
||||
mesh_.nBoundaryFaces(),
|
||||
mesh_.nInternalFaces()
|
||||
);
|
||||
syncTools::swapBoundaryFaceList
|
||||
(
|
||||
mesh_,
|
||||
syncedBCentres
|
||||
);
|
||||
|
||||
vectorField syncedBAreas;
|
||||
syncedBAreas = SubField<vector>
|
||||
(
|
||||
faceAreas,
|
||||
mesh_.nBoundaryFaces(),
|
||||
mesh_.nInternalFaces()
|
||||
);
|
||||
syncTools::syncBoundaryFaceList
|
||||
(
|
||||
mesh_,
|
||||
syncedBAreas,
|
||||
eqOp<vector>(),
|
||||
transformOriented()
|
||||
);
|
||||
|
||||
const auto& pbm = mesh_.boundaryMesh();
|
||||
for (const auto& pp : pbm)
|
||||
{
|
||||
const auto* ppp = isA<coupledPolyPatch>(pp);
|
||||
|
||||
//if (ppp)
|
||||
//{
|
||||
// Pout<< "For patch:" << ppp->name()
|
||||
// << " size:" << ppp->size()
|
||||
// << endl;
|
||||
// forAll(*ppp, i)
|
||||
// {
|
||||
// const label facei = ppp->start()+i;
|
||||
// Pout<< " Face:" << facei << nl
|
||||
// << " meshFc:" << faceCentres[facei] << nl
|
||||
// << " meshFa:" << faceAreas[facei] << nl
|
||||
// << endl;
|
||||
// }
|
||||
//}
|
||||
|
||||
if (ppp && !ppp->owner())
|
||||
{
|
||||
SubField<point> patchFc
|
||||
(
|
||||
faceCentres,
|
||||
ppp->size(),
|
||||
ppp->start()
|
||||
);
|
||||
patchFc = SubField<vector>
|
||||
(
|
||||
syncedBCentres,
|
||||
ppp->size(),
|
||||
ppp->offset()
|
||||
);
|
||||
|
||||
SubField<vector> patchArea
|
||||
(
|
||||
faceAreas,
|
||||
ppp->size(),
|
||||
ppp->start()
|
||||
);
|
||||
patchArea = SubField<vector>
|
||||
(
|
||||
syncedBAreas,
|
||||
ppp->size(),
|
||||
ppp->offset()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::parallelFvGeometryScheme::adjustGeometry()
|
||||
{
|
||||
// Swap face centres and areas
|
||||
@ -304,5 +390,38 @@ Foam::parallelFvGeometryScheme::nonOrthCorrectionVectors() const
|
||||
}
|
||||
|
||||
|
||||
bool Foam::parallelFvGeometryScheme::updateGeom
|
||||
(
|
||||
const pointField& points,
|
||||
const refPtr<pointField>& oldPoints,
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas,
|
||||
pointField& cellCentres,
|
||||
scalarField& cellVolumes
|
||||
) const
|
||||
{
|
||||
primitiveMeshTools::makeFaceCentresAndAreas
|
||||
(
|
||||
mesh_,
|
||||
points,
|
||||
faceCentres,
|
||||
cellCentres
|
||||
);
|
||||
|
||||
// Parallel consistency
|
||||
adjustGeometry(faceCentres, faceAreas);
|
||||
|
||||
primitiveMeshTools::makeCellCentresAndVols
|
||||
(
|
||||
mesh_,
|
||||
faceCentres,
|
||||
faceAreas,
|
||||
cellCentres,
|
||||
cellVolumes
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -102,6 +102,13 @@ private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Swap processor-face geometry
|
||||
void adjustGeometry
|
||||
(
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas
|
||||
) const;
|
||||
|
||||
//- Swap processor-face geometry
|
||||
void adjustGeometry();
|
||||
|
||||
@ -181,6 +188,19 @@ public:
|
||||
|
||||
//- Return non-orthogonality correction vectors
|
||||
virtual tmp<surfaceVectorField> nonOrthCorrectionVectors() const;
|
||||
|
||||
//- Calculate geometry quantities using mesh topology and provided
|
||||
//- points. If oldPoints provided only does local update. Returns
|
||||
//- true if anything changed, false otherwise
|
||||
virtual bool updateGeom
|
||||
(
|
||||
const pointField& points,
|
||||
const refPtr<pointField>& oldPoints, // optional old points
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas,
|
||||
pointField& cellCentres,
|
||||
scalarField& cellVolumes
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -45,6 +45,68 @@ namespace Foam
|
||||
}
|
||||
|
||||
|
||||
bool Foam::solidBodyFvGeometryScheme::markChanges
|
||||
(
|
||||
const pointField& oldPoints,
|
||||
const pointField& currPoints,
|
||||
bitSet& isChangedPoint,
|
||||
bitSet& isChangedFace,
|
||||
bitSet& isChangedCell
|
||||
) const
|
||||
{
|
||||
isChangedPoint.setSize(oldPoints.size());
|
||||
|
||||
// Check for non-identical points
|
||||
forAll(isChangedPoint, pointi)
|
||||
{
|
||||
isChangedPoint.set(pointi, oldPoints[pointi] != currPoints[pointi]);
|
||||
}
|
||||
|
||||
DebugInfo
|
||||
<< "SBM --- Changed points:"
|
||||
<< returnReduce(isChangedPoint.count(), sumOp<label>())
|
||||
<< endl;
|
||||
|
||||
// Quick return if no points have moved
|
||||
if (returnReduceAnd(isChangedPoint.none()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
isChangedFace.setSize(mesh_.nFaces());
|
||||
isChangedFace = false;
|
||||
|
||||
isChangedCell.setSize(mesh_.nCells());
|
||||
isChangedCell = false;
|
||||
|
||||
const auto& pointFaces = mesh_.pointFaces();
|
||||
const auto& own = mesh_.faceOwner();
|
||||
const auto& nbr = mesh_.faceNeighbour();
|
||||
|
||||
// Identify faces and cells attached to moving points
|
||||
for (const label pointi : isChangedPoint)
|
||||
{
|
||||
for (const auto facei : pointFaces[pointi])
|
||||
{
|
||||
isChangedFace.set(facei);
|
||||
|
||||
isChangedCell.set(own[facei]);
|
||||
if (facei < mesh_.nInternalFaces())
|
||||
{
|
||||
isChangedCell.set(nbr[facei]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DebugInfo
|
||||
<< "SBM --- Changed cells:"
|
||||
<< returnReduce(isChangedCell.count(), sumOp<label>())
|
||||
<< endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Foam::solidBodyFvGeometryScheme::setMeshMotionData()
|
||||
{
|
||||
if (!cacheInitialised_ || !cacheMotion_)
|
||||
@ -67,64 +129,86 @@ void Foam::solidBodyFvGeometryScheme::setMeshMotionData()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
bitSet changedPoints(oldPoints.size());
|
||||
//bitSet changedPoints(oldPoints.size());
|
||||
//
|
||||
//// Check for non-identical points
|
||||
//forAll(changedPoints, pointi)
|
||||
//{
|
||||
// changedPoints.set
|
||||
// (
|
||||
// pointi,
|
||||
// oldPoints[pointi] != currPoints[pointi]
|
||||
// );
|
||||
//}
|
||||
//
|
||||
//DebugInfo
|
||||
// << "SBM --- Changed points:"
|
||||
// << returnReduce(changedPoints.count(), sumOp<label>())
|
||||
// << endl;
|
||||
//
|
||||
//// Quick return if no points have moved
|
||||
//if (returnReduceAnd(changedPoints.none()))
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//bitSet cellIDs(mesh_.nCells());
|
||||
//bitSet faceIDs(mesh_.nFaces());
|
||||
//
|
||||
//const auto& pointFaces = mesh_.pointFaces();
|
||||
//const auto& own = mesh_.faceOwner();
|
||||
//const auto& nbr = mesh_.faceNeighbour();
|
||||
//
|
||||
//// Identify faces and cells attached to moving points
|
||||
//for (const label pointi : changedPoints)
|
||||
//{
|
||||
// for (const auto facei : pointFaces[pointi])
|
||||
// {
|
||||
// faceIDs.set(facei);
|
||||
//
|
||||
// cellIDs.set(own[facei]);
|
||||
// if (facei < mesh_.nInternalFaces())
|
||||
// {
|
||||
// cellIDs.set(nbr[facei]);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//changedCellIDs_ = cellIDs.toc();
|
||||
//
|
||||
//DebugInfo
|
||||
// << "SBM --- Changed cells:"
|
||||
// << returnReduce(changedCellIDs_.size(), sumOp<label>())
|
||||
// << endl;
|
||||
|
||||
// Check for non-identical points
|
||||
forAll(changedPoints, pointi)
|
||||
{
|
||||
changedPoints.set(pointi, oldPoints[pointi] != currPoints[pointi]);
|
||||
}
|
||||
|
||||
DebugInfo
|
||||
<< "SBM --- Changed points:"
|
||||
<< returnReduce(changedPoints.count(), sumOp<label>())
|
||||
<< endl;
|
||||
bitSet isChangedPoint;
|
||||
bitSet isChangedFace;
|
||||
bitSet isChangedCell;
|
||||
const bool changed = markChanges
|
||||
(
|
||||
oldPoints,
|
||||
currPoints,
|
||||
isChangedPoint,
|
||||
isChangedFace,
|
||||
isChangedCell
|
||||
);
|
||||
|
||||
// Quick return if no points have moved
|
||||
if (returnReduceAnd(changedPoints.none()))
|
||||
if (!changed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bitSet cellIDs(mesh_.nCells());
|
||||
bitSet faceIDs(mesh_.nFaces());
|
||||
|
||||
const auto& pointFaces = mesh_.pointFaces();
|
||||
const auto& own = mesh_.faceOwner();
|
||||
const auto& nbr = mesh_.faceNeighbour();
|
||||
|
||||
// Identify faces and cells attached to moving points
|
||||
for (const label pointi : changedPoints)
|
||||
{
|
||||
for (const auto facei : pointFaces[pointi])
|
||||
{
|
||||
faceIDs.set(facei);
|
||||
|
||||
cellIDs.set(own[facei]);
|
||||
if (facei < mesh_.nInternalFaces())
|
||||
{
|
||||
cellIDs.set(nbr[facei]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
changedCellIDs_ = cellIDs.toc();
|
||||
|
||||
DebugInfo
|
||||
<< "SBM --- Changed cells:"
|
||||
<< returnReduce(changedCellIDs_.size(), sumOp<label>())
|
||||
<< endl;
|
||||
changedCellIDs_ = isChangedCell.toc();
|
||||
|
||||
|
||||
// Construct face and patch ID info
|
||||
|
||||
const auto changedFaceFlag = faceIDs.values();
|
||||
|
||||
DynamicList<label> changedFaceIDs(faceIDs.count());
|
||||
DynamicList<label> changedPatchIDs(faceIDs.count());
|
||||
DynamicList<label> changedFaceIDs(isChangedFace.count());
|
||||
DynamicList<label> changedPatchIDs(changedFaceIDs.capacity());
|
||||
for (label facei = 0; facei < mesh_.nInternalFaces(); ++facei)
|
||||
{
|
||||
if (changedFaceFlag[facei])
|
||||
if (isChangedFace[facei])
|
||||
{
|
||||
changedFaceIDs.append(facei);
|
||||
changedPatchIDs.append(-1);
|
||||
@ -138,7 +222,7 @@ void Foam::solidBodyFvGeometryScheme::setMeshMotionData()
|
||||
|
||||
for (const label meshFacei : pp.range())
|
||||
{
|
||||
if (changedFaceFlag[meshFacei])
|
||||
if (isChangedFace[meshFacei])
|
||||
{
|
||||
changedFaceIDs.append(meshFacei);
|
||||
changedPatchIDs.append(patchi);
|
||||
@ -343,4 +427,82 @@ void Foam::solidBodyFvGeometryScheme::updateMesh(const mapPolyMesh& mpm)
|
||||
}
|
||||
|
||||
|
||||
bool Foam::solidBodyFvGeometryScheme::updateGeom
|
||||
(
|
||||
const pointField& points,
|
||||
const refPtr<pointField>& oldPoints,
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas,
|
||||
pointField& cellCentres,
|
||||
scalarField& cellVolumes
|
||||
) const
|
||||
{
|
||||
if
|
||||
(
|
||||
(faceCentres.size() != mesh_.nFaces())
|
||||
|| (faceAreas.size() != mesh_.nFaces())
|
||||
|| (cellCentres.size() != mesh_.nCells())
|
||||
|| (cellVolumes.size() != mesh_.nCells())
|
||||
|| !oldPoints
|
||||
)
|
||||
{
|
||||
// Do all
|
||||
return basicFvGeometryScheme::updateGeom
|
||||
(
|
||||
points,
|
||||
oldPoints,
|
||||
faceCentres,
|
||||
faceAreas,
|
||||
cellCentres,
|
||||
cellVolumes
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Since oldPoints provided assume that face & cell geometry is
|
||||
// up to date with it
|
||||
|
||||
bitSet isChangedPoint;
|
||||
bitSet isChangedFace;
|
||||
bitSet isChangedCell;
|
||||
const bool changed = markChanges
|
||||
(
|
||||
oldPoints(),
|
||||
points,
|
||||
isChangedPoint,
|
||||
isChangedFace,
|
||||
isChangedCell
|
||||
);
|
||||
|
||||
if (!changed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make face centres and areas consistent with new points
|
||||
primitiveMeshTools::updateFaceCentresAndAreas
|
||||
(
|
||||
mesh_,
|
||||
isChangedFace.toc(),
|
||||
points,
|
||||
faceCentres,
|
||||
faceAreas
|
||||
);
|
||||
|
||||
primitiveMeshTools::updateCellCentresAndVols
|
||||
(
|
||||
mesh_,
|
||||
faceCentres,
|
||||
faceAreas,
|
||||
isChangedCell.toc(),
|
||||
mesh_.cells(),
|
||||
cellCentres,
|
||||
cellVolumes
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -94,6 +94,16 @@ class solidBodyFvGeometryScheme
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Detect what geometry has changed. Return true if anything has.
|
||||
bool markChanges
|
||||
(
|
||||
const pointField& oldPoints,
|
||||
const pointField& currPoints,
|
||||
bitSet& isChangedPoint,
|
||||
bitSet& isChangedFace,
|
||||
bitSet& isChangedCell
|
||||
) const;
|
||||
|
||||
//- Set the mesh motion data (point, face IDs)
|
||||
void setMeshMotionData();
|
||||
|
||||
@ -127,6 +137,19 @@ public:
|
||||
|
||||
//- Update mesh for topology changes
|
||||
virtual void updateMesh(const mapPolyMesh& mpm);
|
||||
|
||||
//- Calculate geometry quantities using mesh topology and provided
|
||||
//- points. If oldPoints provided only does local update. Returns
|
||||
//- true if anything changed, false otherwise
|
||||
virtual bool updateGeom
|
||||
(
|
||||
const pointField& points,
|
||||
const refPtr<pointField>& oldPoints, // optional old points
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas,
|
||||
pointField& cellCentres,
|
||||
scalarField& cellVolumes
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -208,4 +208,35 @@ void Foam::stabilisedFvGeometryScheme::movePoints()
|
||||
}
|
||||
|
||||
|
||||
bool Foam::stabilisedFvGeometryScheme::updateGeom
|
||||
(
|
||||
const pointField& points,
|
||||
const refPtr<pointField>& oldPoints,
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas,
|
||||
pointField& cellCentres,
|
||||
scalarField& cellVolumes
|
||||
) const
|
||||
{
|
||||
makeFaceCentresAndAreas
|
||||
(
|
||||
mesh_,
|
||||
points,
|
||||
faceCentres,
|
||||
faceAreas
|
||||
);
|
||||
|
||||
primitiveMeshTools::makeCellCentresAndVols
|
||||
(
|
||||
mesh_,
|
||||
faceCentres,
|
||||
faceAreas,
|
||||
cellCentres,
|
||||
cellVolumes
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -112,6 +112,19 @@ public:
|
||||
|
||||
//- Do what is necessary if the mesh has moved
|
||||
virtual void movePoints();
|
||||
|
||||
//- Calculate geometry quantities using mesh topology and provided
|
||||
//- points. If oldPoints provided only does local update. Returns
|
||||
//- true if anything changed, false otherwise
|
||||
virtual bool updateGeom
|
||||
(
|
||||
const pointField& points,
|
||||
const refPtr<pointField>& oldPoints, // optional old points
|
||||
pointField& faceCentres,
|
||||
vectorField& faceAreas,
|
||||
pointField& cellCentres,
|
||||
scalarField& cellVolumes
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -32,10 +32,16 @@ License
|
||||
#include "cyclicPolyPatch.H"
|
||||
#include "emptyPolyPatch.H"
|
||||
#include "processorPolyPatch.H"
|
||||
#include "meshPointPatch.H"
|
||||
#include "processorPointPatch.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
Foam::word Foam::fvMeshSubset::exposedPatchName("oldInternalFaces");
|
||||
namespace Foam
|
||||
{
|
||||
word fvMeshSubset::exposedPatchName("oldInternalFaces");
|
||||
defineTypeNameAndDebug(fvMeshSubset, 0);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
@ -522,6 +528,16 @@ void Foam::fvMeshSubset::reset
|
||||
|
||||
void Foam::fvMeshSubset::reset(const Foam::zero)
|
||||
{
|
||||
// Was old pointMesh present?
|
||||
const auto* basePointMeshPtr =
|
||||
baseMesh_.thisDb().cfindObject<pointMesh>(pointMesh::typeName);
|
||||
if (basePointMeshPtr)
|
||||
{
|
||||
DebugPout<< "fvMeshSubset::reset(const Foam::zero) :"
|
||||
<< " Detected pointMesh" << endl;
|
||||
}
|
||||
|
||||
|
||||
clear();
|
||||
|
||||
// Create zero-sized subMesh
|
||||
@ -574,6 +590,46 @@ void Foam::fvMeshSubset::reset(const Foam::zero)
|
||||
}
|
||||
|
||||
|
||||
// Clone old additional point patches
|
||||
if (basePointMeshPtr)
|
||||
{
|
||||
DebugPout<< "Subsetting pointMesh" << endl;
|
||||
const auto& basePointMesh = *basePointMeshPtr;
|
||||
const auto& oldPointBoundary = basePointMesh.boundary();
|
||||
|
||||
// 1. Generate pointBoundaryMesh from polyBoundaryMesh (so ignoring
|
||||
// any additional patches
|
||||
const auto& newSubPointMesh = pointMesh::New(newSubMesh);
|
||||
|
||||
auto& newBoundary =
|
||||
const_cast<pointBoundaryMesh&>(newSubPointMesh.boundary());
|
||||
|
||||
// Start off from (poly)patch map
|
||||
pointPatchMap_ = patchMap_;
|
||||
|
||||
// 2. Explicitly add subsetted meshPointPatches
|
||||
for (const auto& oldPointPatch : oldPointBoundary)
|
||||
{
|
||||
const auto* mppPtr = isA<meshPointPatch>(oldPointPatch);
|
||||
if (mppPtr && (newBoundary.findPatchID(mppPtr->name()) == -1))
|
||||
{
|
||||
newBoundary.push_back
|
||||
(
|
||||
mppPtr->clone
|
||||
(
|
||||
newBoundary,
|
||||
newBoundary.size(),
|
||||
labelList::null(), // map
|
||||
labelList::null() // map
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Extend patchMap with -1
|
||||
pointPatchMap_.setSize(newBoundary.size(), -1);
|
||||
}
|
||||
|
||||
// Add the zones
|
||||
subsetZones();
|
||||
}
|
||||
@ -586,6 +642,16 @@ void Foam::fvMeshSubset::reset
|
||||
const bool syncPar
|
||||
)
|
||||
{
|
||||
// Was old pointMesh present?
|
||||
const auto* basePointMeshPtr =
|
||||
baseMesh_.thisDb().cfindObject<pointMesh>(pointMesh::typeName);
|
||||
if (basePointMeshPtr)
|
||||
{
|
||||
DebugPout<< "fvMeshSubset::reset(const bitSet&) :"
|
||||
<< " Detected pointMesh" << endl;
|
||||
}
|
||||
|
||||
|
||||
// Clear all old maps and pointers
|
||||
clear();
|
||||
|
||||
@ -1126,6 +1192,8 @@ void Foam::fvMeshSubset::reset
|
||||
|
||||
// Inserted patch
|
||||
|
||||
label newInternalPatchID = -1;
|
||||
|
||||
if (wantedPatchID == -1)
|
||||
{
|
||||
label oldInternalSize = boundaryPatchSizes[oldInternalPatchID];
|
||||
@ -1159,6 +1227,7 @@ void Foam::fvMeshSubset::reset
|
||||
// the internal faces
|
||||
patchStart += boundaryPatchSizes[oldInternalPatchID];
|
||||
patchMap_[nNewPatches] = -1;
|
||||
newInternalPatchID = nNewPatches;
|
||||
++nNewPatches;
|
||||
}
|
||||
}
|
||||
@ -1233,6 +1302,98 @@ void Foam::fvMeshSubset::reset
|
||||
|
||||
// Subset and add any zones
|
||||
subsetZones();
|
||||
|
||||
|
||||
if (basePointMeshPtr)
|
||||
{
|
||||
DebugPout<< "Subsetting pointMesh" << endl;
|
||||
const auto& basePointMesh = *basePointMeshPtr;
|
||||
const auto& oldPointBoundary = basePointMesh.boundary();
|
||||
|
||||
// 1. Generate pointBoundaryMesh from polyBoundaryMesh (so ignoring
|
||||
// any additional patches
|
||||
const auto& newSubPointMesh = pointMesh::New(subMeshPtr_());
|
||||
|
||||
pointPatchMap_ = patchMap_;
|
||||
|
||||
auto& newBoundary =
|
||||
const_cast<pointBoundaryMesh&>(newSubPointMesh.boundary());
|
||||
|
||||
|
||||
// 2. Explicitly add subsetted meshPointPatches
|
||||
labelList oldToNewPoints(baseMesh_.nPoints(), -1);
|
||||
forAll(pointMap_, i)
|
||||
{
|
||||
oldToNewPoints[pointMap_[i]] = i;
|
||||
}
|
||||
|
||||
|
||||
// Add meshPointPatches
|
||||
pointPatchMap_.setSize(newBoundary.size(), -1);
|
||||
|
||||
for (const auto& oldPointPatch : oldPointBoundary)
|
||||
{
|
||||
const auto* mppPtr = isA<meshPointPatch>(oldPointPatch);
|
||||
if (mppPtr && (newBoundary.findPatchID(mppPtr->name()) == -1))
|
||||
{
|
||||
const auto& mp = mppPtr->meshPoints();
|
||||
DynamicList<label> subPointMap(mp.size());
|
||||
forAll(mp, i)
|
||||
{
|
||||
const label newPointi = oldToNewPoints[mp[i]];
|
||||
if (newPointi != -1)
|
||||
{
|
||||
subPointMap.append(i);
|
||||
}
|
||||
}
|
||||
|
||||
pointPatchMap_.push_back(mppPtr->index());
|
||||
|
||||
newBoundary.push_back
|
||||
(
|
||||
mppPtr->clone
|
||||
(
|
||||
newBoundary,
|
||||
newBoundary.size(),
|
||||
subPointMap, // map
|
||||
oldToNewPoints
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 3. rotate into place:
|
||||
// - global patches (including meshPointPatches)
|
||||
// - optional 'internalFaces' patch
|
||||
// - processor patches
|
||||
labelList oldToNew(newBoundary.size());
|
||||
label newPatchi = 0;
|
||||
forAll(newBoundary, patchi)
|
||||
{
|
||||
if
|
||||
(
|
||||
patchi != newInternalPatchID
|
||||
&& !isA<processorPointPatch>(newBoundary[patchi])
|
||||
)
|
||||
{
|
||||
oldToNew[patchi] = newPatchi++;
|
||||
}
|
||||
}
|
||||
if (newInternalPatchID != -1)
|
||||
{
|
||||
oldToNew[newInternalPatchID] = newPatchi++;
|
||||
}
|
||||
forAll(newBoundary, patchi)
|
||||
{
|
||||
if (isA<processorPointPatch>(newBoundary[patchi]))
|
||||
{
|
||||
oldToNew[patchi] = newPatchi++;
|
||||
}
|
||||
}
|
||||
newBoundary.reorder(oldToNew, true);
|
||||
inplaceReorder(oldToNew, pointPatchMap_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -102,6 +102,9 @@ class fvMeshSubset
|
||||
//- Patch mapping array
|
||||
labelList patchMap_;
|
||||
|
||||
//- PointPatch mapping array
|
||||
labelList pointPatchMap_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
@ -135,6 +138,10 @@ protected:
|
||||
|
||||
public:
|
||||
|
||||
// Declare name of the class and its debug switch
|
||||
ClassName("fvMeshSubset");
|
||||
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Name for exposed internal faces (default: oldInternalFaces)
|
||||
@ -225,6 +232,10 @@ public:
|
||||
//- Return patch map
|
||||
inline const labelList& patchMap() const;
|
||||
|
||||
//- Return point-patch map. Usually identical to patchMap except if
|
||||
//- additional patches are added to the pointMesh.
|
||||
inline const labelList& pointPatchMap() const;
|
||||
|
||||
|
||||
// Edit
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user