mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Creation of OpenFOAM-dev repository 15/04/2008
This commit is contained in:
@ -0,0 +1,85 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: 1.0 |
|
||||
| \\ / A nd | Web: http://www.openfoam.org |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
// decomposePar tool definition
|
||||
|
||||
description "Mesh and Field Decomposer";
|
||||
|
||||
decomposeParDict
|
||||
{
|
||||
type dictionary;
|
||||
description "decomposePar control dictionary";
|
||||
dictionaryPath "system";
|
||||
|
||||
entries
|
||||
{
|
||||
arguments
|
||||
{
|
||||
type rootCaseArguments;
|
||||
entries
|
||||
{
|
||||
include "$FOAMX_CONFIG/entries/arguments/cellDist.cfg";
|
||||
include "$FOAMX_CONFIG/entries/arguments/fieldsOnly.cfg";
|
||||
}
|
||||
}
|
||||
|
||||
numberOfSubdomains
|
||||
{
|
||||
type label;
|
||||
default 1;
|
||||
}
|
||||
|
||||
method
|
||||
{
|
||||
type word;
|
||||
default simple;
|
||||
valueList
|
||||
(
|
||||
metis
|
||||
simple
|
||||
hierarchical
|
||||
manual
|
||||
);
|
||||
}
|
||||
|
||||
simpleCoeffs
|
||||
{
|
||||
type dictionary;
|
||||
entries
|
||||
{
|
||||
include "n.cfg";
|
||||
include "delta.cfg";
|
||||
}
|
||||
}
|
||||
|
||||
hierarchicalCoeffs
|
||||
{
|
||||
type dictionary;
|
||||
entries
|
||||
{
|
||||
include "n.cfg";
|
||||
include "delta.cfg";
|
||||
include "order.cfg";
|
||||
}
|
||||
}
|
||||
|
||||
manualCoeffs
|
||||
{
|
||||
type dictionary;
|
||||
entries
|
||||
{
|
||||
dataFile
|
||||
{
|
||||
type string;
|
||||
description "Path of decomposition data file";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,16 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: 1.0 |
|
||||
| \\ / A nd | Web: http://www.openfoam.org |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
delta
|
||||
{
|
||||
type scalar0Inf;
|
||||
description "delta";
|
||||
default 0.001;
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,19 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: 1.0 |
|
||||
| \\ / A nd | Web: http://www.openfoam.org |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
n
|
||||
{
|
||||
description "n";
|
||||
type fixedList;
|
||||
elementType label;
|
||||
numElements 3;
|
||||
elementLabels ( Nx Ny Nz );
|
||||
default ( 1 1 1 );
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,25 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: 1.0 |
|
||||
| \\ / A nd | Web: http://www.openfoam.org |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
order
|
||||
{
|
||||
type word;
|
||||
description "order";
|
||||
default xyz;
|
||||
valueList
|
||||
(
|
||||
xyz
|
||||
xzy
|
||||
yxz
|
||||
yzx
|
||||
zxy
|
||||
zyx
|
||||
);
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,9 @@
|
||||
decomposeMesh.C
|
||||
decomposePar.C
|
||||
domainDecomposition.C
|
||||
distributeCells.C
|
||||
fvFieldDecomposer.C
|
||||
pointFieldDecomposer.C
|
||||
lagrangianFieldDecomposer.C
|
||||
|
||||
EXE = $(FOAM_APPBIN)/decomposePar
|
||||
@ -0,0 +1,11 @@
|
||||
EXE_INC = \
|
||||
-I../decompositionMethods/decompositionMethods/lnInclude \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-lfiniteVolume \
|
||||
-ldecompositionMethods \
|
||||
-llagrangian \
|
||||
-lmeshTools \
|
||||
|
||||
@ -0,0 +1,780 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
InClass
|
||||
domainDecomposition
|
||||
|
||||
Description
|
||||
Private member of domainDecomposition.
|
||||
Decomposes the mesh into bits
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "domainDecomposition.H"
|
||||
#include "IOstreams.H"
|
||||
#include "SLPtrList.H"
|
||||
#include "boolList.H"
|
||||
#include "cellList.H"
|
||||
#include "primitiveMesh.H"
|
||||
#include "cyclicFvPatch.H"
|
||||
#include "fvPatchList.H"
|
||||
#include "DynamicList.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void domainDecomposition::decomposeMesh(const bool filterEmptyPatches)
|
||||
{
|
||||
// Decide which cell goes to which processor
|
||||
distributeCells();
|
||||
|
||||
// Distribute the cells according to the given processor label
|
||||
|
||||
// calculate the addressing information for the original mesh
|
||||
Info<< "\nCalculating original mesh data" << endl;
|
||||
|
||||
// set references to the original mesh
|
||||
const polyBoundaryMesh& patches = boundaryMesh();
|
||||
const faceList& fcs = faces();
|
||||
const labelList& owner = faceOwner();
|
||||
const labelList& neighbour = faceNeighbour();
|
||||
|
||||
// loop through the list of processor labels for the cell and add the
|
||||
// cell shape to the list of cells for the appropriate processor
|
||||
|
||||
Info<< "\nDistributing cells to processors" << endl;
|
||||
|
||||
// Memory management
|
||||
{
|
||||
List<SLList<label> > procCellList(nProcs_);
|
||||
|
||||
forAll (cellToProc_, celli)
|
||||
{
|
||||
if (cellToProc_[celli] >= nProcs_)
|
||||
{
|
||||
FatalErrorIn("domainDecomposition::decomposeMesh()")
|
||||
<< "Impossible processor label " << cellToProc_[celli]
|
||||
<< "for cell " << celli
|
||||
<< abort(FatalError);
|
||||
}
|
||||
else
|
||||
{
|
||||
procCellList[cellToProc_[celli]].append(celli);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert linked lists into normal lists
|
||||
forAll (procCellList, procI)
|
||||
{
|
||||
procCellAddressing_[procI] = procCellList[procI];
|
||||
}
|
||||
}
|
||||
|
||||
Info << "\nDistributing faces to processors" << endl;
|
||||
|
||||
// Loop through all internal faces and decide which processor they belong to
|
||||
// First visit all internal faces. If cells at both sides belong to the
|
||||
// same processor, the face is an internal face. If they are different,
|
||||
// it belongs to both processors.
|
||||
|
||||
// Memory management
|
||||
{
|
||||
List<SLList<label> > procFaceList(nProcs_);
|
||||
|
||||
forAll (neighbour, facei)
|
||||
{
|
||||
if (cellToProc_[owner[facei]] == cellToProc_[neighbour[facei]])
|
||||
{
|
||||
// Face internal to processor
|
||||
procFaceList[cellToProc_[owner[facei]]].append(facei);
|
||||
}
|
||||
}
|
||||
|
||||
// Detect inter-processor boundaries
|
||||
|
||||
// Neighbour processor for each subdomain
|
||||
List<SLList<label> > interProcBoundaries(nProcs_);
|
||||
|
||||
// Face labels belonging to each inter-processor boundary
|
||||
List<SLList<SLList<label> > > interProcBFaces(nProcs_);
|
||||
|
||||
List<SLList<label> > procPatchIndex(nProcs_);
|
||||
|
||||
forAll (neighbour, facei)
|
||||
{
|
||||
if (cellToProc_[owner[facei]] != cellToProc_[neighbour[facei]])
|
||||
{
|
||||
// inter - processor patch face found. Go through the list of
|
||||
// inside boundaries for the owner processor and try to find
|
||||
// this inter-processor patch.
|
||||
|
||||
label ownerProc = cellToProc_[owner[facei]];
|
||||
label neighbourProc = cellToProc_[neighbour[facei]];
|
||||
|
||||
SLList<label>::iterator curInterProcBdrsOwnIter =
|
||||
interProcBoundaries[ownerProc].begin();
|
||||
|
||||
SLList<SLList<label> >::iterator curInterProcBFacesOwnIter =
|
||||
interProcBFaces[ownerProc].begin();
|
||||
|
||||
bool interProcBouFound = false;
|
||||
|
||||
// WARNING: Synchronous SLList iterators
|
||||
|
||||
for
|
||||
(
|
||||
;
|
||||
curInterProcBdrsOwnIter
|
||||
!= interProcBoundaries[ownerProc].end()
|
||||
&& curInterProcBFacesOwnIter
|
||||
!= interProcBFaces[ownerProc].end();
|
||||
++curInterProcBdrsOwnIter, ++curInterProcBFacesOwnIter
|
||||
)
|
||||
{
|
||||
if (curInterProcBdrsOwnIter() == neighbourProc)
|
||||
{
|
||||
// the inter - processor boundary exists. Add the face
|
||||
interProcBouFound = true;
|
||||
|
||||
curInterProcBFacesOwnIter().append(facei);
|
||||
|
||||
SLList<label>::iterator curInterProcBdrsNeiIter =
|
||||
interProcBoundaries[neighbourProc].begin();
|
||||
|
||||
SLList<SLList<label> >::iterator
|
||||
curInterProcBFacesNeiIter =
|
||||
interProcBFaces[neighbourProc].begin();
|
||||
|
||||
bool neighbourFound = false;
|
||||
|
||||
// WARNING: Synchronous SLList iterators
|
||||
|
||||
for
|
||||
(
|
||||
;
|
||||
curInterProcBdrsNeiIter !=
|
||||
interProcBoundaries[neighbourProc].end()
|
||||
&& curInterProcBFacesNeiIter !=
|
||||
interProcBFaces[neighbourProc].end();
|
||||
++curInterProcBdrsNeiIter,
|
||||
++curInterProcBFacesNeiIter
|
||||
)
|
||||
{
|
||||
if (curInterProcBdrsNeiIter() == ownerProc)
|
||||
{
|
||||
// boundary found. Add the face
|
||||
neighbourFound = true;
|
||||
|
||||
curInterProcBFacesNeiIter().append(facei);
|
||||
}
|
||||
|
||||
if (neighbourFound) break;
|
||||
}
|
||||
|
||||
if (interProcBouFound && !neighbourFound)
|
||||
{
|
||||
FatalErrorIn("domainDecomposition::decomposeMesh()")
|
||||
<< "Inconsistency in inter - "
|
||||
<< "processor boundary lists for processors "
|
||||
<< ownerProc << " and " << neighbourProc
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
if (interProcBouFound) break;
|
||||
}
|
||||
|
||||
if (!interProcBouFound)
|
||||
{
|
||||
// inter - processor boundaries do not exist and need to
|
||||
// be created
|
||||
|
||||
// set the new addressing information
|
||||
|
||||
// owner
|
||||
interProcBoundaries[ownerProc].append(neighbourProc);
|
||||
interProcBFaces[ownerProc].append(SLList<label>(facei));
|
||||
|
||||
// neighbour
|
||||
interProcBoundaries[neighbourProc].append(ownerProc);
|
||||
interProcBFaces[neighbourProc].append(SLList<label>(facei));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through patches. For cyclic boundaries detect inter-processor
|
||||
// faces; for all other, add faces to the face list and remember start
|
||||
// and size of all patches.
|
||||
|
||||
// for all processors, set the size of start index and patch size
|
||||
// lists to the number of patches in the mesh
|
||||
forAll (procPatchSize_, procI)
|
||||
{
|
||||
procPatchSize_[procI].setSize(patches.size());
|
||||
procPatchStartIndex_[procI].setSize(patches.size());
|
||||
}
|
||||
|
||||
forAll (patches, patchi)
|
||||
{
|
||||
// Reset size and start index for all processors
|
||||
forAll (procPatchSize_, procI)
|
||||
{
|
||||
procPatchSize_[procI][patchi] = 0;
|
||||
procPatchStartIndex_[procI][patchi] =
|
||||
procFaceList[procI].size();
|
||||
}
|
||||
|
||||
const label patchStart = patches[patchi].start();
|
||||
|
||||
if (typeid(patches[patchi]) != typeid(cyclicPolyPatch))
|
||||
{
|
||||
// Normal patch. Add faces to processor where the cell
|
||||
// next to the face lives
|
||||
|
||||
const unallocLabelList& patchFaceCells =
|
||||
patches[patchi].faceCells();
|
||||
|
||||
forAll (patchFaceCells, facei)
|
||||
{
|
||||
const label curProc = cellToProc_[patchFaceCells[facei]];
|
||||
|
||||
// add the face
|
||||
procFaceList[curProc].append(patchStart + facei);
|
||||
|
||||
// increment the number of faces for this patch
|
||||
procPatchSize_[curProc][patchi]++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cyclic patch special treatment
|
||||
|
||||
const polyPatch& cPatch = patches[patchi];
|
||||
|
||||
const label cycOffset = cPatch.size()/2;
|
||||
|
||||
// Set reference to faceCells for both patches
|
||||
const labelList::subList firstFaceCells
|
||||
(
|
||||
cPatch.faceCells(),
|
||||
cycOffset
|
||||
);
|
||||
|
||||
const labelList::subList secondFaceCells
|
||||
(
|
||||
cPatch.faceCells(),
|
||||
cycOffset,
|
||||
cycOffset
|
||||
);
|
||||
|
||||
forAll (firstFaceCells, facei)
|
||||
{
|
||||
if
|
||||
(
|
||||
cellToProc_[firstFaceCells[facei]]
|
||||
!= cellToProc_[secondFaceCells[facei]]
|
||||
)
|
||||
{
|
||||
// This face becomes an inter-processor boundary face
|
||||
// inter - processor patch face found. Go through
|
||||
// the list of inside boundaries for the owner
|
||||
// processor and try to find this inter-processor
|
||||
// patch.
|
||||
|
||||
cyclicParallel_ = true;
|
||||
|
||||
label ownerProc = cellToProc_[firstFaceCells[facei]];
|
||||
label neighbourProc =
|
||||
cellToProc_[secondFaceCells[facei]];
|
||||
|
||||
SLList<label>::iterator curInterProcBdrsOwnIter =
|
||||
interProcBoundaries[ownerProc].begin();
|
||||
|
||||
SLList<SLList<label> >::iterator
|
||||
curInterProcBFacesOwnIter =
|
||||
interProcBFaces[ownerProc].begin();
|
||||
|
||||
bool interProcBouFound = false;
|
||||
|
||||
// WARNING: Synchronous SLList iterators
|
||||
|
||||
for
|
||||
(
|
||||
;
|
||||
curInterProcBdrsOwnIter !=
|
||||
interProcBoundaries[ownerProc].end()
|
||||
&& curInterProcBFacesOwnIter !=
|
||||
interProcBFaces[ownerProc].end();
|
||||
++curInterProcBdrsOwnIter,
|
||||
++curInterProcBFacesOwnIter
|
||||
)
|
||||
{
|
||||
if (curInterProcBdrsOwnIter() == neighbourProc)
|
||||
{
|
||||
// the inter - processor boundary exists.
|
||||
// Add the face
|
||||
interProcBouFound = true;
|
||||
|
||||
curInterProcBFacesOwnIter().append
|
||||
(patchStart + facei);
|
||||
|
||||
SLList<label>::iterator curInterProcBdrsNeiIter
|
||||
= interProcBoundaries[neighbourProc].begin();
|
||||
|
||||
SLList<SLList<label> >::iterator
|
||||
curInterProcBFacesNeiIter =
|
||||
interProcBFaces[neighbourProc].begin();
|
||||
|
||||
bool neighbourFound = false;
|
||||
|
||||
// WARNING: Synchronous SLList iterators
|
||||
|
||||
for
|
||||
(
|
||||
;
|
||||
curInterProcBdrsNeiIter
|
||||
!= interProcBoundaries[neighbourProc].end()
|
||||
&& curInterProcBFacesNeiIter
|
||||
!= interProcBFaces[neighbourProc].end();
|
||||
++curInterProcBdrsNeiIter,
|
||||
++curInterProcBFacesNeiIter
|
||||
)
|
||||
{
|
||||
if (curInterProcBdrsNeiIter() == ownerProc)
|
||||
{
|
||||
// boundary found. Add the face
|
||||
neighbourFound = true;
|
||||
|
||||
curInterProcBFacesNeiIter()
|
||||
.append
|
||||
(
|
||||
patchStart
|
||||
+ cycOffset
|
||||
+ facei
|
||||
);
|
||||
}
|
||||
|
||||
if (neighbourFound) break;
|
||||
}
|
||||
|
||||
if (interProcBouFound && !neighbourFound)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"domainDecomposition::decomposeMesh()"
|
||||
) << "Inconsistency in inter-processor "
|
||||
<< "boundary lists for processors "
|
||||
<< ownerProc << " and " << neighbourProc
|
||||
<< " in cyclic boundary matching"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
if (interProcBouFound) break;
|
||||
}
|
||||
|
||||
if (!interProcBouFound)
|
||||
{
|
||||
// inter - processor boundaries do not exist
|
||||
// and need to be created
|
||||
|
||||
// set the new addressing information
|
||||
|
||||
// owner
|
||||
interProcBoundaries[ownerProc]
|
||||
.append(neighbourProc);
|
||||
interProcBFaces[ownerProc]
|
||||
.append(SLList<label>(patchStart + facei));
|
||||
|
||||
// neighbour
|
||||
interProcBoundaries[neighbourProc]
|
||||
.append(ownerProc);
|
||||
interProcBFaces[neighbourProc]
|
||||
.append
|
||||
(
|
||||
SLList<label>
|
||||
(
|
||||
patchStart
|
||||
+ cycOffset
|
||||
+ facei
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This cyclic face remains on the processor
|
||||
label ownerProc = cellToProc_[firstFaceCells[facei]];
|
||||
|
||||
// add the face
|
||||
procFaceList[ownerProc].append(patchStart + facei);
|
||||
|
||||
// increment the number of faces for this patch
|
||||
procPatchSize_[ownerProc][patchi]++;
|
||||
|
||||
// Note: I cannot add the other side of the cyclic
|
||||
// boundary here because this would violate the order.
|
||||
// They will be added in a separate loop below
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
// Ordering in cyclic boundaries is important.
|
||||
// Add the other half of cyclic faces for cyclic boundaries
|
||||
// that remain on the processor
|
||||
forAll (secondFaceCells, facei)
|
||||
{
|
||||
if
|
||||
(
|
||||
cellToProc_[firstFaceCells[facei]]
|
||||
== cellToProc_[secondFaceCells[facei]]
|
||||
)
|
||||
{
|
||||
// This cyclic face remains on the processor
|
||||
label ownerProc = cellToProc_[firstFaceCells[facei]];
|
||||
|
||||
// add the second face
|
||||
procFaceList[ownerProc].append
|
||||
(patchStart + cycOffset + facei);
|
||||
|
||||
// increment the number of faces for this patch
|
||||
procPatchSize_[ownerProc][patchi]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert linked lists into normal lists
|
||||
// Add inter-processor boundaries and remember start indices
|
||||
forAll (procFaceList, procI)
|
||||
{
|
||||
// Get internal and regular boundary processor faces
|
||||
SLList<label>& curProcFaces = procFaceList[procI];
|
||||
|
||||
// Get reference to processor face addressing
|
||||
labelList& curProcFaceAddressing = procFaceAddressing_[procI];
|
||||
|
||||
labelList& curProcNeighbourProcessors =
|
||||
procNeighbourProcessors_[procI];
|
||||
|
||||
labelList& curProcProcessorPatchSize =
|
||||
procProcessorPatchSize_[procI];
|
||||
|
||||
labelList& curProcProcessorPatchStartIndex =
|
||||
procProcessorPatchStartIndex_[procI];
|
||||
|
||||
// calculate the size
|
||||
label nFacesOnProcessor = curProcFaces.size();
|
||||
|
||||
for
|
||||
(
|
||||
SLList<SLList<label> >::iterator curInterProcBFacesIter =
|
||||
interProcBFaces[procI].begin();
|
||||
curInterProcBFacesIter != interProcBFaces[procI].end();
|
||||
++curInterProcBFacesIter
|
||||
)
|
||||
{
|
||||
nFacesOnProcessor += curInterProcBFacesIter().size();
|
||||
}
|
||||
|
||||
curProcFaceAddressing.setSize(nFacesOnProcessor);
|
||||
|
||||
// Fill in the list. Calculate turning index.
|
||||
// Turning index will be -1 only for some faces on processor
|
||||
// boundaries, i.e. the ones where the current processor ID
|
||||
// is in the cell which is a face neighbour.
|
||||
// Turning index is stored as the sign of the face addressing list
|
||||
|
||||
label nFaces = 0;
|
||||
|
||||
// Add internal and boundary faces
|
||||
// Remember to increment the index by one such that the
|
||||
// turning index works properly.
|
||||
for
|
||||
(
|
||||
SLList<label>::iterator curProcFacesIter = curProcFaces.begin();
|
||||
curProcFacesIter != curProcFaces.end();
|
||||
++curProcFacesIter
|
||||
)
|
||||
{
|
||||
curProcFaceAddressing[nFaces] = curProcFacesIter() + 1;
|
||||
nFaces++;
|
||||
}
|
||||
|
||||
// Add inter-processor boundary faces. At the beginning of each
|
||||
// patch, grab the patch start index and size
|
||||
|
||||
curProcNeighbourProcessors.setSize
|
||||
(
|
||||
interProcBoundaries[procI].size()
|
||||
);
|
||||
|
||||
curProcProcessorPatchSize.setSize
|
||||
(
|
||||
interProcBoundaries[procI].size()
|
||||
);
|
||||
|
||||
curProcProcessorPatchStartIndex.setSize
|
||||
(
|
||||
interProcBoundaries[procI].size()
|
||||
);
|
||||
|
||||
label nProcPatches = 0;
|
||||
|
||||
SLList<label>::iterator curInterProcBdrsIter =
|
||||
interProcBoundaries[procI].begin();
|
||||
|
||||
SLList<SLList<label> >::iterator curInterProcBFacesIter =
|
||||
interProcBFaces[procI].begin();
|
||||
|
||||
for
|
||||
(
|
||||
;
|
||||
curInterProcBdrsIter != interProcBoundaries[procI].end()
|
||||
&& curInterProcBFacesIter != interProcBFaces[procI].end();
|
||||
++curInterProcBdrsIter, ++curInterProcBFacesIter
|
||||
)
|
||||
{
|
||||
curProcNeighbourProcessors[nProcPatches] =
|
||||
curInterProcBdrsIter();
|
||||
|
||||
// Get start index for processor patch
|
||||
curProcProcessorPatchStartIndex[nProcPatches] = nFaces;
|
||||
|
||||
label& curSize =
|
||||
curProcProcessorPatchSize[nProcPatches];
|
||||
|
||||
curSize = 0;
|
||||
|
||||
// add faces for this processor boundary
|
||||
|
||||
for
|
||||
(
|
||||
SLList<label>::iterator curFacesIter =
|
||||
curInterProcBFacesIter().begin();
|
||||
curFacesIter != curInterProcBFacesIter().end();
|
||||
++curFacesIter
|
||||
)
|
||||
{
|
||||
// add the face
|
||||
|
||||
// Remember to increment the index by one such that the
|
||||
// turning index works properly.
|
||||
if (cellToProc_[owner[curFacesIter()]] == procI)
|
||||
{
|
||||
curProcFaceAddressing[nFaces] = curFacesIter() + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// turning face
|
||||
curProcFaceAddressing[nFaces] = -(curFacesIter() + 1);
|
||||
}
|
||||
|
||||
// increment the size
|
||||
curSize++;
|
||||
|
||||
nFaces++;
|
||||
}
|
||||
|
||||
nProcPatches++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info << "\nCalculating processor boundary addressing" << endl;
|
||||
// For every patch of processor boundary, find the index of the original
|
||||
// patch. Mis-alignment is caused by the fact that patches with zero size
|
||||
// are omitted. For processor patches, set index to -1.
|
||||
// At the same time, filter the procPatchSize_ and procPatchStartIndex_
|
||||
// lists to exclude zero-size patches
|
||||
forAll (procPatchSize_, procI)
|
||||
{
|
||||
// Make a local copy of old lists
|
||||
const labelList oldPatchSizes = procPatchSize_[procI];
|
||||
|
||||
const labelList oldPatchStarts = procPatchStartIndex_[procI];
|
||||
|
||||
labelList& curPatchSizes = procPatchSize_[procI];
|
||||
|
||||
labelList& curPatchStarts = procPatchStartIndex_[procI];
|
||||
|
||||
const labelList& curProcessorPatchSizes =
|
||||
procProcessorPatchSize_[procI];
|
||||
|
||||
labelList& curBoundaryAddressing = procBoundaryAddressing_[procI];
|
||||
|
||||
curBoundaryAddressing.setSize
|
||||
(
|
||||
oldPatchSizes.size()
|
||||
+ curProcessorPatchSizes.size()
|
||||
);
|
||||
|
||||
label nPatches = 0;
|
||||
|
||||
forAll (oldPatchSizes, patchi)
|
||||
{
|
||||
if (!filterEmptyPatches || oldPatchSizes[patchi] > 0)
|
||||
{
|
||||
curBoundaryAddressing[nPatches] = patchi;
|
||||
|
||||
curPatchSizes[nPatches] = oldPatchSizes[patchi];
|
||||
|
||||
curPatchStarts[nPatches] = oldPatchStarts[patchi];
|
||||
|
||||
nPatches++;
|
||||
}
|
||||
}
|
||||
|
||||
// reset to the size of live patches
|
||||
curPatchSizes.setSize(nPatches);
|
||||
curPatchStarts.setSize(nPatches);
|
||||
|
||||
forAll (curProcessorPatchSizes, procPatchI)
|
||||
{
|
||||
curBoundaryAddressing[nPatches] = -1;
|
||||
|
||||
nPatches++;
|
||||
}
|
||||
|
||||
curBoundaryAddressing.setSize(nPatches);
|
||||
}
|
||||
|
||||
Info << "\nDistributing points to processors" << endl;
|
||||
// For every processor, loop through the list of faces for the processor.
|
||||
// For every face, loop through the list of points and mark the point as
|
||||
// used for the processor. Collect the list of used points for the
|
||||
// processor.
|
||||
|
||||
forAll (procPointAddressing_, procI)
|
||||
{
|
||||
boolList pointLabels(nPoints(), false);
|
||||
|
||||
// Get reference to list of used faces
|
||||
const labelList& procFaceLabels = procFaceAddressing_[procI];
|
||||
|
||||
forAll (procFaceLabels, facei)
|
||||
{
|
||||
// Because of the turning index, some labels may be negative
|
||||
const labelList& facePoints = fcs[mag(procFaceLabels[facei]) - 1];
|
||||
|
||||
forAll (facePoints, pointi)
|
||||
{
|
||||
// Mark the point as used
|
||||
pointLabels[facePoints[pointi]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Collect the used points
|
||||
labelList& procPointLabels = procPointAddressing_[procI];
|
||||
|
||||
procPointLabels.setSize(pointLabels.size());
|
||||
|
||||
label nUsedPoints = 0;
|
||||
|
||||
forAll (pointLabels, pointi)
|
||||
{
|
||||
if (pointLabels[pointi])
|
||||
{
|
||||
procPointLabels[nUsedPoints] = pointi;
|
||||
|
||||
nUsedPoints++;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the size of used points
|
||||
procPointLabels.setSize(nUsedPoints);
|
||||
}
|
||||
|
||||
// Gather data about globally shared points
|
||||
|
||||
// Memory management
|
||||
{
|
||||
labelList pointsUsage(nPoints(), 0);
|
||||
|
||||
// Globally shared points are the ones used by more than 2 processors
|
||||
// Size the list approximately and gather the points
|
||||
labelHashSet gSharedPoints
|
||||
(
|
||||
min(100, nPoints()/1000)
|
||||
);
|
||||
|
||||
// Loop through all the processors and mark up points used by
|
||||
// processor boundaries. When a point is used twice, it is a
|
||||
// globally shared point
|
||||
|
||||
for (label procI = 0; procI < nProcs_; procI++)
|
||||
{
|
||||
// Get list of face labels
|
||||
const labelList& curFaceLabels = procFaceAddressing_[procI];
|
||||
|
||||
// Get start of processor faces
|
||||
const labelList& curProcessorPatchStarts =
|
||||
procProcessorPatchStartIndex_[procI];
|
||||
|
||||
const labelList& curProcessorPatchSizes =
|
||||
procProcessorPatchSize_[procI];
|
||||
|
||||
// Reset the lookup list
|
||||
pointsUsage = 0;
|
||||
|
||||
forAll (curProcessorPatchStarts, patchi)
|
||||
{
|
||||
const label curStart = curProcessorPatchStarts[patchi];
|
||||
const label curEnd = curStart + curProcessorPatchSizes[patchi];
|
||||
|
||||
for
|
||||
(
|
||||
label facei = curStart;
|
||||
facei < curEnd;
|
||||
facei++
|
||||
)
|
||||
{
|
||||
// Mark the original face as used
|
||||
// Remember to decrement the index by one (turning index)
|
||||
//
|
||||
const label curF = mag(curFaceLabels[facei]) - 1;
|
||||
|
||||
const face& f = fcs[curF];
|
||||
|
||||
forAll (f, pointi)
|
||||
{
|
||||
if (pointsUsage[f[pointi]] == 0)
|
||||
{
|
||||
// Point not previously used
|
||||
pointsUsage[f[pointi]] = patchi + 1;
|
||||
}
|
||||
else if (pointsUsage[f[pointi]] != patchi + 1)
|
||||
{
|
||||
// Point used by some other patch = global point!
|
||||
gSharedPoints.insert(f[pointi]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Grab the result from the hash list
|
||||
globallySharedPoints_ = gSharedPoints.toc();
|
||||
sort(globallySharedPoints_);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,618 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Application
|
||||
decomposePar
|
||||
|
||||
Description
|
||||
Automatically decomposes a mesh and fields of a case for parallel execution
|
||||
of FOAM.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "OSspecific.H"
|
||||
#include "fvCFD.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "processorFvPatchFields.H"
|
||||
#include "domainDecomposition.H"
|
||||
#include "labelIOField.H"
|
||||
#include "scalarIOField.H"
|
||||
#include "vectorIOField.H"
|
||||
#include "sphericalTensorIOField.H"
|
||||
#include "symmTensorIOField.H"
|
||||
#include "tensorIOField.H"
|
||||
#include "pointFields.H"
|
||||
|
||||
#include "readFields.H"
|
||||
#include "fvFieldDecomposer.H"
|
||||
#include "pointFieldDecomposer.H"
|
||||
#include "lagrangianFieldDecomposer.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::noParallel();
|
||||
argList::validOptions.insert("fields", "");
|
||||
argList::validOptions.insert("cellDist", "");
|
||||
argList::validOptions.insert("filterPatches", "");
|
||||
argList::validOptions.insert("copyUniform", "");
|
||||
|
||||
# include "setRootCase.H"
|
||||
|
||||
bool decomposeFieldsOnly(args.options().found("fields"));
|
||||
|
||||
bool writeCellDist(args.options().found("cellDist"));
|
||||
|
||||
bool filterPatches(args.options().found("filterPatches"));
|
||||
|
||||
bool copyUniform(args.options().found("copyUniform"));
|
||||
|
||||
# include "createTime.H"
|
||||
|
||||
Info<< "Time = " << runTime.timeName() << endl;
|
||||
|
||||
Info<< "Create mesh\n" << endl;
|
||||
domainDecomposition mesh
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
domainDecomposition::defaultRegion,
|
||||
runTime.timeName(),
|
||||
runTime
|
||||
)
|
||||
);
|
||||
|
||||
// Decompose the mesh
|
||||
if (!decomposeFieldsOnly)
|
||||
{
|
||||
if (dir(runTime.path()/"processor1"))
|
||||
{
|
||||
FatalErrorIn(args.executable())
|
||||
<< "Case is already decomposed." << endl
|
||||
<< " Please remove processor directories before "
|
||||
"decomposing e.g. using:" << nl
|
||||
<< " rm -rf " << runTime.path().c_str() << "/processor*"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
mesh.decomposeMesh(filterPatches);
|
||||
|
||||
mesh.writeDecomposition();
|
||||
|
||||
if (writeCellDist)
|
||||
{
|
||||
// Write the decomposition as labelList for use with 'manual'
|
||||
// decomposition method.
|
||||
OFstream str
|
||||
(
|
||||
runTime.path()
|
||||
/ mesh.facesInstance()
|
||||
/ polyMesh::defaultRegion
|
||||
/ "cellDecomposition"
|
||||
);
|
||||
|
||||
str << mesh.cellToProc();
|
||||
|
||||
Info<< nl << "Written decomposition to "
|
||||
<< str.name() << " for use in manual decomposition."
|
||||
<< nl << endl;
|
||||
|
||||
// Write as volScalarField for postprocessing.
|
||||
volScalarField cellDist
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"cellDist",
|
||||
runTime.timeName(),
|
||||
mesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
mesh,
|
||||
dimensionedScalar("cellDist", dimless, 0),
|
||||
zeroGradientFvPatchScalarField::typeName
|
||||
);
|
||||
|
||||
const labelList& procIds = mesh.cellToProc();
|
||||
forAll(procIds, celli)
|
||||
{
|
||||
cellDist[celli] = procIds[celli];
|
||||
}
|
||||
|
||||
cellDist.write();
|
||||
|
||||
Info<< nl << "Written decomposition as volScalarField to "
|
||||
<< cellDist.name() << " for use in postprocessing."
|
||||
<< nl << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Search for list of objects for this time
|
||||
IOobjectList objects(mesh, runTime.timeName());
|
||||
|
||||
// Construct the vol fields
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
PtrList<volScalarField> volScalarFields;
|
||||
readFields(mesh, objects, volScalarFields);
|
||||
|
||||
PtrList<volVectorField> volVectorFields;
|
||||
readFields(mesh, objects, volVectorFields);
|
||||
|
||||
PtrList<volSphericalTensorField> volSphericalTensorFields;
|
||||
readFields(mesh, objects, volSphericalTensorFields);
|
||||
|
||||
PtrList<volSymmTensorField> volSymmTensorFields;
|
||||
readFields(mesh, objects, volSymmTensorFields);
|
||||
|
||||
PtrList<volTensorField> volTensorFields;
|
||||
readFields(mesh, objects, volTensorFields);
|
||||
|
||||
|
||||
// Construct the surface fields
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
PtrList<surfaceScalarField> surfaceScalarFields;
|
||||
readFields(mesh, objects, surfaceScalarFields);
|
||||
|
||||
|
||||
// Construct the point fields
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
pointMesh pMesh(mesh);
|
||||
|
||||
PtrList<pointScalarField> pointScalarFields;
|
||||
readFields(pMesh, objects, pointScalarFields);
|
||||
|
||||
PtrList<pointVectorField> pointVectorFields;
|
||||
readFields(pMesh, objects, pointVectorFields);
|
||||
|
||||
PtrList<pointSphericalTensorField> pointSphericalTensorFields;
|
||||
readFields(pMesh, objects, pointSphericalTensorFields);
|
||||
|
||||
PtrList<pointSymmTensorField> pointSymmTensorFields;
|
||||
readFields(pMesh, objects, pointSymmTensorFields);
|
||||
|
||||
PtrList<pointTensorField> pointTensorFields;
|
||||
readFields(pMesh, objects, pointTensorFields);
|
||||
|
||||
|
||||
// Construct the Lagrangian fields
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
fileNameList cloudDirs
|
||||
(
|
||||
readDir(runTime.timePath()/"lagrangian", fileName::DIRECTORY)
|
||||
);
|
||||
|
||||
// Particles
|
||||
PtrList<Cloud<indexedParticle> > lagrangianPositions(cloudDirs.size());
|
||||
// Particles per cell
|
||||
PtrList< List<SLList<indexedParticle*>*> > cellParticles(cloudDirs.size());
|
||||
|
||||
PtrList<PtrList<labelIOField> > lagrangianLabelFields(cloudDirs.size());
|
||||
PtrList<PtrList<scalarIOField> > lagrangianScalarFields(cloudDirs.size());
|
||||
PtrList<PtrList<vectorIOField> > lagrangianVectorFields(cloudDirs.size());
|
||||
PtrList<PtrList<sphericalTensorIOField> > lagrangianSphericalTensorFields
|
||||
(
|
||||
cloudDirs.size()
|
||||
);
|
||||
PtrList<PtrList<symmTensorIOField> > lagrangianSymmTensorFields
|
||||
(
|
||||
cloudDirs.size()
|
||||
);
|
||||
PtrList<PtrList<tensorIOField> > lagrangianTensorFields
|
||||
(
|
||||
cloudDirs.size()
|
||||
);
|
||||
|
||||
label cloudI = 0;
|
||||
|
||||
forAll(cloudDirs, i)
|
||||
{
|
||||
IOobjectList sprayObjs
|
||||
(
|
||||
mesh,
|
||||
runTime.timeName(),
|
||||
"lagrangian"/cloudDirs[i]
|
||||
);
|
||||
|
||||
IOobject* positionsPtr = sprayObjs.lookup("positions");
|
||||
|
||||
if (positionsPtr)
|
||||
{
|
||||
// Read lagrangian particles
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Info<< "Identified lagrangian data set: " << cloudDirs[i] << endl;
|
||||
|
||||
lagrangianPositions.set
|
||||
(
|
||||
cloudI,
|
||||
new Cloud<indexedParticle>
|
||||
(
|
||||
mesh,
|
||||
cloudDirs[i],
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Sort particles per cell
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
cellParticles.set
|
||||
(
|
||||
cloudI,
|
||||
new List<SLList<indexedParticle*>*>
|
||||
(
|
||||
mesh.nCells(),
|
||||
static_cast<SLList<indexedParticle*>*>(NULL)
|
||||
)
|
||||
);
|
||||
|
||||
label i = 0;
|
||||
|
||||
forAllIter(Cloud<indexedParticle>, lagrangianPositions[cloudI], iter)
|
||||
{
|
||||
iter().index() = i++;
|
||||
|
||||
label celli = iter().cell();
|
||||
|
||||
// Check
|
||||
if (celli < 0 || celli >= mesh.nCells())
|
||||
{
|
||||
FatalErrorIn(args.executable())
|
||||
<< "Illegal cell number " << celli
|
||||
<< " for particle with index " << iter().index()
|
||||
<< " at position " << iter().position() << nl
|
||||
<< "Cell number should be between 0 and "
|
||||
<< mesh.nCells()-1 << nl
|
||||
<< "On this mesh the particle should be in cell "
|
||||
<< mesh.findCell(iter().position())
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
if (!cellParticles[cloudI][celli])
|
||||
{
|
||||
cellParticles[cloudI][celli] = new SLList<indexedParticle*>();
|
||||
}
|
||||
|
||||
cellParticles[cloudI][celli]->append(&iter());
|
||||
}
|
||||
|
||||
// Read fields
|
||||
// ~~~~~~~~~~~
|
||||
|
||||
IOobjectList lagrangianObjects
|
||||
(
|
||||
mesh,
|
||||
runTime.timeName(),
|
||||
"lagrangian"/cloudDirs[cloudI]
|
||||
);
|
||||
|
||||
lagrangianFieldDecomposer::readFields
|
||||
(
|
||||
cloudI,
|
||||
lagrangianObjects,
|
||||
lagrangianLabelFields
|
||||
);
|
||||
|
||||
lagrangianFieldDecomposer::readFields
|
||||
(
|
||||
cloudI,
|
||||
lagrangianObjects,
|
||||
lagrangianScalarFields
|
||||
);
|
||||
|
||||
lagrangianFieldDecomposer::readFields
|
||||
(
|
||||
cloudI,
|
||||
lagrangianObjects,
|
||||
lagrangianVectorFields
|
||||
);
|
||||
|
||||
lagrangianFieldDecomposer::readFields
|
||||
(
|
||||
cloudI,
|
||||
lagrangianObjects,
|
||||
lagrangianSphericalTensorFields
|
||||
);
|
||||
|
||||
lagrangianFieldDecomposer::readFields
|
||||
(
|
||||
cloudI,
|
||||
lagrangianObjects,
|
||||
lagrangianSymmTensorFields
|
||||
);
|
||||
|
||||
lagrangianFieldDecomposer::readFields
|
||||
(
|
||||
cloudI,
|
||||
lagrangianObjects,
|
||||
lagrangianTensorFields
|
||||
);
|
||||
|
||||
cloudI++;
|
||||
}
|
||||
}
|
||||
|
||||
lagrangianPositions.setSize(cloudI);
|
||||
cellParticles.setSize(cloudI);
|
||||
lagrangianLabelFields.setSize(cloudI);
|
||||
lagrangianScalarFields.setSize(cloudI);
|
||||
lagrangianVectorFields.setSize(cloudI);
|
||||
lagrangianSphericalTensorFields.setSize(cloudI);
|
||||
lagrangianSymmTensorFields.setSize(cloudI);
|
||||
lagrangianTensorFields.setSize(cloudI);
|
||||
|
||||
|
||||
// Any uniform data to copy/link?
|
||||
|
||||
fileName uniformDir;
|
||||
|
||||
if (dir(runTime.timePath()/"uniform"))
|
||||
{
|
||||
uniformDir = runTime.timePath()/"uniform";
|
||||
|
||||
Info<< "Detected additional non-decomposed files in " << uniformDir
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
Info<< endl;
|
||||
|
||||
|
||||
// split the fields over processors
|
||||
for (label procI = 0; procI < mesh.nProcs(); procI++)
|
||||
{
|
||||
Info<< "Processor " << procI << ": field transfer" << endl;
|
||||
|
||||
// open the database
|
||||
Time processorDb
|
||||
(
|
||||
Time::controlDictName,
|
||||
args.rootPath(),
|
||||
args.caseName()/fileName(word("processor") + name(procI))
|
||||
);
|
||||
|
||||
processorDb.setTime(runTime);
|
||||
|
||||
// read the mesh
|
||||
fvMesh procMesh
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fvMesh::defaultRegion,
|
||||
processorDb.timeName(),
|
||||
processorDb
|
||||
)
|
||||
);
|
||||
|
||||
labelIOList cellProcAddressing
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"cellProcAddressing",
|
||||
"constant",
|
||||
procMesh.meshSubDir,
|
||||
procMesh,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
)
|
||||
);
|
||||
|
||||
labelIOList boundaryProcAddressing
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"boundaryProcAddressing",
|
||||
"constant",
|
||||
procMesh.meshSubDir,
|
||||
procMesh,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
)
|
||||
);
|
||||
|
||||
// FV fields
|
||||
if
|
||||
(
|
||||
volScalarFields.size()
|
||||
|| volVectorFields.size()
|
||||
|| volSphericalTensorFields.size()
|
||||
|| volSymmTensorFields.size()
|
||||
|| volTensorFields.size()
|
||||
|| surfaceScalarFields.size()
|
||||
)
|
||||
{
|
||||
labelIOList faceProcAddressing
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"faceProcAddressing",
|
||||
"constant",
|
||||
procMesh.meshSubDir,
|
||||
procMesh,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
)
|
||||
);
|
||||
|
||||
fvFieldDecomposer fieldDecomposer
|
||||
(
|
||||
mesh,
|
||||
procMesh,
|
||||
faceProcAddressing,
|
||||
cellProcAddressing,
|
||||
boundaryProcAddressing
|
||||
);
|
||||
|
||||
fieldDecomposer.decomposeFields(volScalarFields);
|
||||
fieldDecomposer.decomposeFields(volVectorFields);
|
||||
fieldDecomposer.decomposeFields(volSphericalTensorFields);
|
||||
fieldDecomposer.decomposeFields(volSymmTensorFields);
|
||||
fieldDecomposer.decomposeFields(volTensorFields);
|
||||
|
||||
fieldDecomposer.decomposeFields(surfaceScalarFields);
|
||||
}
|
||||
|
||||
|
||||
// Point fields
|
||||
if
|
||||
(
|
||||
pointScalarFields.size()
|
||||
|| pointVectorFields.size()
|
||||
|| pointSphericalTensorFields.size()
|
||||
|| pointSymmTensorFields.size()
|
||||
|| pointTensorFields.size()
|
||||
)
|
||||
{
|
||||
labelIOList pointProcAddressing
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"pointProcAddressing",
|
||||
"constant",
|
||||
procMesh.meshSubDir,
|
||||
procMesh,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
)
|
||||
);
|
||||
|
||||
pointMesh procPMesh(procMesh, true);
|
||||
|
||||
pointFieldDecomposer fieldDecomposer
|
||||
(
|
||||
pMesh,
|
||||
procPMesh,
|
||||
pointProcAddressing,
|
||||
boundaryProcAddressing
|
||||
);
|
||||
|
||||
fieldDecomposer.decomposeFields(pointScalarFields);
|
||||
fieldDecomposer.decomposeFields(pointVectorFields);
|
||||
fieldDecomposer.decomposeFields(pointSphericalTensorFields);
|
||||
fieldDecomposer.decomposeFields(pointSymmTensorFields);
|
||||
fieldDecomposer.decomposeFields(pointTensorFields);
|
||||
}
|
||||
|
||||
|
||||
// If there is lagrangian data write it out
|
||||
forAll(lagrangianPositions, cloudI)
|
||||
{
|
||||
if (lagrangianPositions[cloudI].size())
|
||||
{
|
||||
lagrangianFieldDecomposer fieldDecomposer
|
||||
(
|
||||
mesh,
|
||||
procMesh,
|
||||
cellProcAddressing,
|
||||
cloudDirs[cloudI],
|
||||
lagrangianPositions[cloudI],
|
||||
cellParticles[cloudI]
|
||||
);
|
||||
|
||||
// Lagrangian fields
|
||||
if
|
||||
(
|
||||
lagrangianLabelFields[cloudI].size()
|
||||
|| lagrangianScalarFields[cloudI].size()
|
||||
|| lagrangianVectorFields[cloudI].size()
|
||||
|| lagrangianSphericalTensorFields[cloudI].size()
|
||||
|| lagrangianSymmTensorFields[cloudI].size()
|
||||
|| lagrangianTensorFields[cloudI].size()
|
||||
)
|
||||
{
|
||||
fieldDecomposer.decomposeFields
|
||||
(
|
||||
cloudDirs[cloudI],
|
||||
lagrangianLabelFields[cloudI]
|
||||
);
|
||||
fieldDecomposer.decomposeFields
|
||||
(
|
||||
cloudDirs[cloudI],
|
||||
lagrangianScalarFields[cloudI]
|
||||
);
|
||||
fieldDecomposer.decomposeFields
|
||||
(
|
||||
cloudDirs[cloudI],
|
||||
lagrangianVectorFields[cloudI]
|
||||
);
|
||||
fieldDecomposer.decomposeFields
|
||||
(
|
||||
cloudDirs[cloudI],
|
||||
lagrangianSphericalTensorFields[cloudI]
|
||||
);
|
||||
fieldDecomposer.decomposeFields
|
||||
(
|
||||
cloudDirs[cloudI],
|
||||
lagrangianSymmTensorFields[cloudI]
|
||||
);
|
||||
fieldDecomposer.decomposeFields
|
||||
(
|
||||
cloudDirs[cloudI],
|
||||
lagrangianTensorFields[cloudI]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Any non-decomposed data to copy?
|
||||
if (uniformDir.size() > 0)
|
||||
{
|
||||
if (copyUniform || mesh.distributed())
|
||||
{
|
||||
cp(uniformDir, processorDb.timePath()/"uniform");
|
||||
}
|
||||
else
|
||||
{
|
||||
fileName timePath = processorDb.timePath();
|
||||
|
||||
if (timePath[0] != '/')
|
||||
{
|
||||
// Adapt uniformDir and timePath to be relative paths.
|
||||
string parentPath(string("..")/"..");
|
||||
fileName currentDir(cwd());
|
||||
chDir(timePath);
|
||||
ln(parentPath/uniformDir, parentPath/timePath/"uniform");
|
||||
chDir(currentDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
ln(uniformDir, timePath/"uniform");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Info<< "\nEnd.\n" << endl;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,47 @@
|
||||
// Mesh decomposition control dictionary
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
FoamFile
|
||||
{
|
||||
version 0.5;
|
||||
format ascii;
|
||||
|
||||
root "ROOT";
|
||||
case "CASE";
|
||||
instance "system";
|
||||
local "";
|
||||
|
||||
class dictionary;
|
||||
|
||||
object decompositionDict;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
numberOfSubdomains 4;
|
||||
|
||||
method simple;
|
||||
//method hierarchical;
|
||||
//method metis;
|
||||
//method manual;
|
||||
|
||||
simpleCoeffs
|
||||
{
|
||||
n (2 2 1);
|
||||
delta 0.001;
|
||||
}
|
||||
|
||||
hierarchicalCoeffs
|
||||
{
|
||||
n (2 2 1);
|
||||
delta 0.001;
|
||||
order xyz;
|
||||
}
|
||||
|
||||
manualCoeffs
|
||||
{
|
||||
dataFile "decompositionData";
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,276 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "domainDecomposition.H"
|
||||
#include "decompositionMethod.H"
|
||||
#include "cpuTime.H"
|
||||
#include "cyclicPolyPatch.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
void domainDecomposition::distributeCells()
|
||||
{
|
||||
Info<< "\nCalculating distribution of cells" << endl;
|
||||
|
||||
cpuTime decompositionTime;
|
||||
|
||||
|
||||
// See if any faces need to have owner and neighbour on same processor
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
labelHashSet sameProcFaces;
|
||||
|
||||
if (decompositionDict_.found("preservePatches"))
|
||||
{
|
||||
wordList pNames(decompositionDict_.lookup("preservePatches"));
|
||||
|
||||
Info<< "Keeping owner and neighbour of faces in patches " << pNames
|
||||
<< " on same processor" << endl;
|
||||
|
||||
const polyBoundaryMesh& patches = boundaryMesh();
|
||||
|
||||
forAll(pNames, i)
|
||||
{
|
||||
label patchI = patches.findPatchID(pNames[i]);
|
||||
|
||||
if (patchI == -1)
|
||||
{
|
||||
FatalErrorIn("domainDecomposition::distributeCells()")
|
||||
<< "Unknown preservePatch " << pNames[i]
|
||||
<< endl << "Valid patches are " << patches.names()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
const polyPatch& pp = patches[patchI];
|
||||
|
||||
forAll(pp, i)
|
||||
{
|
||||
sameProcFaces.insert(pp.start() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (decompositionDict_.found("preserveFaceZones"))
|
||||
{
|
||||
wordList zNames(decompositionDict_.lookup("preserveFaceZones"));
|
||||
|
||||
Info<< "Keeping owner and neighbour of faces in zones " << zNames
|
||||
<< " on same processor" << endl;
|
||||
|
||||
const faceZoneMesh& fZones = faceZones();
|
||||
|
||||
forAll(zNames, i)
|
||||
{
|
||||
label zoneI = fZones.findZoneID(zNames[i]);
|
||||
|
||||
if (zoneI == -1)
|
||||
{
|
||||
FatalErrorIn("domainDecomposition::distributeCells()")
|
||||
<< "Unknown preserveFaceZone " << zNames[i]
|
||||
<< endl << "Valid faceZones are " << fZones.names()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
const faceZone& fz = fZones[zoneI];
|
||||
|
||||
forAll(fz, i)
|
||||
{
|
||||
sameProcFaces.insert(fz[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sameProcFaces.size() > 0)
|
||||
{
|
||||
Info<< "Selected " << sameProcFaces.size()
|
||||
<< " faces whose owner and neighbour cell should be kept on the"
|
||||
<< " same processor" << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Construct decomposition method and either do decomposition on
|
||||
// cell centres or on agglomeration
|
||||
|
||||
|
||||
autoPtr<decompositionMethod> decomposePtr = decompositionMethod::New
|
||||
(
|
||||
decompositionDict_,
|
||||
*this
|
||||
);
|
||||
|
||||
if (sameProcFaces.size() == 0)
|
||||
{
|
||||
cellToProc_ = decomposePtr().decompose(cellCentres());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
// Work the faces whose neighbours need to be kept together into an
|
||||
// agglomeration.
|
||||
|
||||
// Per cell the region/agglomeration it is in
|
||||
labelList cellToRegion(nCells(), -1);
|
||||
|
||||
// Current region
|
||||
label regionI = 0;
|
||||
|
||||
labelHashSet freeRegions;
|
||||
|
||||
forAllConstIter(labelHashSet, sameProcFaces, iter)
|
||||
{
|
||||
label patchI = boundaryMesh().whichPatch(iter.key());
|
||||
|
||||
label own = faceOwner()[iter.key()];
|
||||
label nei = -1;
|
||||
|
||||
if (patchI == -1)
|
||||
{
|
||||
nei = faceNeighbour()[iter.key()];
|
||||
}
|
||||
else if (isA<cyclicPolyPatch>(boundaryMesh()[patchI]))
|
||||
{
|
||||
const cyclicPolyPatch& pp =
|
||||
refCast<const cyclicPolyPatch>(boundaryMesh()[patchI]);
|
||||
|
||||
nei = faceOwner()[pp.transformGlobalFace(iter.key())];
|
||||
}
|
||||
|
||||
if (nei != -1)
|
||||
{
|
||||
label ownRegion = cellToRegion[own];
|
||||
label neiRegion = cellToRegion[nei];
|
||||
|
||||
if (ownRegion == -1 && neiRegion == -1)
|
||||
{
|
||||
// Allocate new agglomeration
|
||||
cellToRegion[own] = regionI;
|
||||
cellToRegion[nei] = regionI;
|
||||
regionI++;
|
||||
}
|
||||
else if (ownRegion != -1)
|
||||
{
|
||||
// Owner already part of agglomeration. Add nei to it.
|
||||
cellToRegion[nei] = ownRegion;
|
||||
}
|
||||
else if (neiRegion != -1)
|
||||
{
|
||||
// nei already part of agglomeration. Add own to it.
|
||||
cellToRegion[own] = neiRegion;
|
||||
}
|
||||
else if (ownRegion < neiRegion)
|
||||
{
|
||||
// Renumber neiRegion
|
||||
forAll(cellToRegion, cellI)
|
||||
{
|
||||
if (cellToRegion[cellI] == neiRegion)
|
||||
{
|
||||
cellToRegion[cellI] = ownRegion;
|
||||
}
|
||||
}
|
||||
freeRegions.insert(neiRegion);
|
||||
}
|
||||
else if (ownRegion > neiRegion)
|
||||
{
|
||||
// Renumber ownRegion
|
||||
forAll(cellToRegion, cellI)
|
||||
{
|
||||
if (cellToRegion[cellI] == ownRegion)
|
||||
{
|
||||
cellToRegion[cellI] = neiRegion;
|
||||
}
|
||||
}
|
||||
freeRegions.insert(ownRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Do all other cells
|
||||
forAll(cellToRegion, cellI)
|
||||
{
|
||||
if (cellToRegion[cellI] == -1)
|
||||
{
|
||||
cellToRegion[cellI] = regionI++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Compact out freeRegions
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
{
|
||||
labelList compactRegion(regionI, -1);
|
||||
|
||||
regionI = 0;
|
||||
|
||||
forAll(compactRegion, i)
|
||||
{
|
||||
if (!freeRegions.found(compactRegion[i]))
|
||||
{
|
||||
compactRegion[i] = regionI++;
|
||||
}
|
||||
}
|
||||
|
||||
inplaceRenumber(compactRegion, cellToRegion);
|
||||
}
|
||||
|
||||
|
||||
// Determine region cell centres
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// This just takes the first cell in the region. Otherwise the problem
|
||||
// is with cyclics - if we'd average the region centre might be
|
||||
// somewhere in the middle of the domain which might not be anywhere
|
||||
// near any of the cells.
|
||||
|
||||
const point greatPoint(GREAT, GREAT, GREAT);
|
||||
|
||||
pointField regionCentres(regionI, greatPoint);
|
||||
|
||||
forAll(cellToRegion, cellI)
|
||||
{
|
||||
label regionI = cellToRegion[cellI];
|
||||
|
||||
if (regionCentres[regionI] == greatPoint)
|
||||
{
|
||||
regionCentres[regionI] = cellCentres()[cellI];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Do decomposition on agglomeration
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
cellToProc_ = decomposePtr().decompose(cellToRegion, regionCentres);
|
||||
}
|
||||
|
||||
Info<< "\nFinished decomposition in "
|
||||
<< decompositionTime.elapsedCpuTime()
|
||||
<< " s" << endl;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,689 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "domainDecomposition.H"
|
||||
#include "Time.H"
|
||||
#include "dictionary.H"
|
||||
#include "labelIOList.H"
|
||||
#include "processorPolyPatch.H"
|
||||
#include "fvMesh.H"
|
||||
#include "OSspecific.H"
|
||||
#include "Map.H"
|
||||
#include "globalMeshData.H"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void domainDecomposition::mark
|
||||
(
|
||||
const labelList& zoneElems,
|
||||
const label zoneI,
|
||||
labelList& elementToZone
|
||||
)
|
||||
{
|
||||
forAll(zoneElems, i)
|
||||
{
|
||||
label pointi = zoneElems[i];
|
||||
|
||||
if (elementToZone[pointi] == -1)
|
||||
{
|
||||
// First occurrence
|
||||
elementToZone[pointi] = zoneI;
|
||||
}
|
||||
else if (elementToZone[pointi] >= 0)
|
||||
{
|
||||
// Multiple zones
|
||||
elementToZone[pointi] = -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// from components
|
||||
domainDecomposition::domainDecomposition(const IOobject& io)
|
||||
:
|
||||
fvMesh(io),
|
||||
decompositionDict_
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"decomposeParDict",
|
||||
time().system(),
|
||||
*this,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
)
|
||||
),
|
||||
nProcs_(readInt(decompositionDict_.lookup("numberOfSubdomains"))),
|
||||
distributed_(false),
|
||||
cellToProc_(nCells()),
|
||||
procPointAddressing_(nProcs_),
|
||||
procFaceAddressing_(nProcs_),
|
||||
procCellAddressing_(nProcs_),
|
||||
procBoundaryAddressing_(nProcs_),
|
||||
procPatchSize_(nProcs_),
|
||||
procPatchStartIndex_(nProcs_),
|
||||
procNeighbourProcessors_(nProcs_),
|
||||
procProcessorPatchSize_(nProcs_),
|
||||
procProcessorPatchStartIndex_(nProcs_),
|
||||
globallySharedPoints_(0),
|
||||
cyclicParallel_(false)
|
||||
{
|
||||
if (decompositionDict_.found("distributed"))
|
||||
{
|
||||
Switch distributed(decompositionDict_.lookup("distributed"));
|
||||
distributed_ = distributed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
domainDecomposition::~domainDecomposition()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool domainDecomposition::writeDecomposition()
|
||||
{
|
||||
Info<< "\nConstructing processor meshes" << endl;
|
||||
|
||||
// Make a lookup map for globally shared points
|
||||
Map<label> sharedPointLookup(2*globallySharedPoints_.size());
|
||||
|
||||
forAll (globallySharedPoints_, pointi)
|
||||
{
|
||||
sharedPointLookup.insert(globallySharedPoints_[pointi], pointi);
|
||||
}
|
||||
|
||||
|
||||
// Mark point/faces/cells that are in zones.
|
||||
// -1 : not in zone
|
||||
// -2 : in multiple zones
|
||||
// >= 0 : in single given zone
|
||||
// This will give direct lookup of elements that are in a single zone
|
||||
// and we'll only have to revert back to searching through all zones
|
||||
// for the duplicate elements
|
||||
|
||||
// Point zones
|
||||
labelList pointToZone(points().size(), -1);
|
||||
|
||||
forAll(pointZones(), zoneI)
|
||||
{
|
||||
mark(pointZones()[zoneI], zoneI, pointToZone);
|
||||
}
|
||||
|
||||
// Face zones
|
||||
labelList faceToZone(faces().size(), -1);
|
||||
|
||||
forAll(faceZones(), zoneI)
|
||||
{
|
||||
mark(faceZones()[zoneI], zoneI, faceToZone);
|
||||
}
|
||||
|
||||
// Cell zones
|
||||
labelList cellToZone(nCells(), -1);
|
||||
|
||||
forAll(cellZones(), zoneI)
|
||||
{
|
||||
mark(cellZones()[zoneI], zoneI, cellToZone);
|
||||
}
|
||||
|
||||
|
||||
label totProcFaces = 0;
|
||||
label maxProcPatches = 0;
|
||||
label maxProcFaces = 0;
|
||||
|
||||
|
||||
// Write out the meshes
|
||||
for (label procI = 0; procI < nProcs_; procI++)
|
||||
{
|
||||
// Create processor points
|
||||
const labelList& curPointLabels = procPointAddressing_[procI];
|
||||
|
||||
const pointField& meshPoints = points();
|
||||
|
||||
labelList pointLookup(nPoints(), -1);
|
||||
|
||||
pointField procPoints(curPointLabels.size());
|
||||
|
||||
forAll (curPointLabels, pointi)
|
||||
{
|
||||
procPoints[pointi] = meshPoints[curPointLabels[pointi]];
|
||||
|
||||
pointLookup[curPointLabels[pointi]] = pointi;
|
||||
}
|
||||
|
||||
// Create processor faces
|
||||
const labelList& curFaceLabels = procFaceAddressing_[procI];
|
||||
|
||||
const faceList& meshFaces = faces();
|
||||
|
||||
labelList faceLookup(nFaces(), -1);
|
||||
|
||||
faceList procFaces(curFaceLabels.size());
|
||||
|
||||
forAll (curFaceLabels, facei)
|
||||
{
|
||||
// Mark the original face as used
|
||||
// Remember to decrement the index by one (turning index)
|
||||
//
|
||||
label curF = mag(curFaceLabels[facei]) - 1;
|
||||
|
||||
faceLookup[curF] = facei;
|
||||
|
||||
// get the original face
|
||||
labelList origFaceLabels;
|
||||
|
||||
if (curFaceLabels[facei] >= 0)
|
||||
{
|
||||
// face not turned
|
||||
origFaceLabels = meshFaces[curF];
|
||||
}
|
||||
else
|
||||
{
|
||||
origFaceLabels = meshFaces[curF].reverseFace();
|
||||
}
|
||||
|
||||
// translate face labels into local point list
|
||||
face& procFaceLabels = procFaces[facei];
|
||||
|
||||
procFaceLabels.setSize(origFaceLabels.size());
|
||||
|
||||
forAll (origFaceLabels, pointi)
|
||||
{
|
||||
procFaceLabels[pointi] = pointLookup[origFaceLabels[pointi]];
|
||||
}
|
||||
}
|
||||
|
||||
// Create processor cells
|
||||
const labelList& curCellLabels = procCellAddressing_[procI];
|
||||
|
||||
const cellList& meshCells = cells();
|
||||
|
||||
cellList procCells(curCellLabels.size());
|
||||
|
||||
forAll (curCellLabels, celli)
|
||||
{
|
||||
const labelList& origCellLabels = meshCells[curCellLabels[celli]];
|
||||
|
||||
cell& curCell = procCells[celli];
|
||||
|
||||
curCell.setSize(origCellLabels.size());
|
||||
|
||||
forAll (origCellLabels, cellFaceI)
|
||||
{
|
||||
curCell[cellFaceI] = faceLookup[origCellLabels[cellFaceI]];
|
||||
}
|
||||
}
|
||||
|
||||
// Create processor mesh without a boundary
|
||||
|
||||
fileName processorCasePath
|
||||
(
|
||||
time().caseName()/fileName(word("processor") + Foam::name(procI))
|
||||
);
|
||||
|
||||
// make the processor directory
|
||||
mkDir(time().rootPath()/processorCasePath);
|
||||
|
||||
// create a database
|
||||
Time processorDb
|
||||
(
|
||||
Time::controlDictName,
|
||||
time().rootPath(),
|
||||
processorCasePath,
|
||||
"system",
|
||||
"constant"
|
||||
);
|
||||
|
||||
// create the mesh
|
||||
polyMesh procMesh
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
polyMesh::defaultRegion,
|
||||
"constant",
|
||||
processorDb
|
||||
),
|
||||
procPoints,
|
||||
procFaces,
|
||||
procCells
|
||||
);
|
||||
|
||||
// Create processor boundary patches
|
||||
const labelList& curBoundaryAddressing = procBoundaryAddressing_[procI];
|
||||
|
||||
const labelList& curPatchSizes = procPatchSize_[procI];
|
||||
|
||||
const labelList& curPatchStarts = procPatchStartIndex_[procI];
|
||||
|
||||
const labelList& curNeighbourProcessors =
|
||||
procNeighbourProcessors_[procI];
|
||||
|
||||
const labelList& curProcessorPatchSizes =
|
||||
procProcessorPatchSize_[procI];
|
||||
|
||||
const labelList& curProcessorPatchStarts =
|
||||
procProcessorPatchStartIndex_[procI];
|
||||
|
||||
const polyPatchList& meshPatches = boundaryMesh();
|
||||
|
||||
List<polyPatch*> procPatches
|
||||
(
|
||||
curPatchSizes.size()
|
||||
+ curProcessorPatchSizes.size(),
|
||||
reinterpret_cast<polyPatch*>(NULL)
|
||||
);
|
||||
|
||||
label nPatches = 0;
|
||||
|
||||
forAll (curPatchSizes, patchi)
|
||||
{
|
||||
procPatches[nPatches] =
|
||||
meshPatches[curBoundaryAddressing[patchi]].clone
|
||||
(
|
||||
procMesh.boundaryMesh(),
|
||||
nPatches,
|
||||
curPatchSizes[patchi],
|
||||
curPatchStarts[patchi]
|
||||
).ptr();
|
||||
|
||||
nPatches++;
|
||||
}
|
||||
|
||||
forAll (curProcessorPatchSizes, procPatchI)
|
||||
{
|
||||
procPatches[nPatches] =
|
||||
new processorPolyPatch
|
||||
(
|
||||
word("procBoundary") + Foam::name(procI)
|
||||
+ word("to")
|
||||
+ Foam::name(curNeighbourProcessors[procPatchI]),
|
||||
curProcessorPatchSizes[procPatchI],
|
||||
curProcessorPatchStarts[procPatchI],
|
||||
nPatches,
|
||||
procMesh.boundaryMesh(),
|
||||
procI,
|
||||
curNeighbourProcessors[procPatchI]
|
||||
);
|
||||
|
||||
nPatches++;
|
||||
}
|
||||
|
||||
// Add boundary patches
|
||||
procMesh.addPatches(procPatches);
|
||||
|
||||
// Create and add zones
|
||||
|
||||
// Point zones
|
||||
{
|
||||
const pointZoneMesh& pz = pointZones();
|
||||
|
||||
// Go through all the zoned points and find out if they
|
||||
// belong to a zone. If so, add it to the zone as
|
||||
// necessary
|
||||
List<DynamicList<label> > zonePoints(pz.size());
|
||||
|
||||
// Estimate size
|
||||
forAll(zonePoints, zoneI)
|
||||
{
|
||||
zonePoints[zoneI].setSize(pz[zoneI].size() / nProcs_);
|
||||
}
|
||||
|
||||
// Use the pointToZone map to find out the single zone (if any),
|
||||
// use slow search only for shared points.
|
||||
forAll (curPointLabels, pointi)
|
||||
{
|
||||
label curPoint = curPointLabels[pointi];
|
||||
|
||||
label zoneI = pointToZone[curPoint];
|
||||
|
||||
if (zoneI >= 0)
|
||||
{
|
||||
// Single zone.
|
||||
zonePoints[zoneI].append(pointi);
|
||||
}
|
||||
else if (zoneI == -2)
|
||||
{
|
||||
// Multiple zones. Lookup.
|
||||
forAll(pz, zoneI)
|
||||
{
|
||||
label index = pz[zoneI].whichPoint(curPoint);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
zonePoints[zoneI].append(pointi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
procMesh.pointZones().clearAddressing();
|
||||
procMesh.pointZones().setSize(zonePoints.size());
|
||||
forAll(zonePoints, zoneI)
|
||||
{
|
||||
procMesh.pointZones().set
|
||||
(
|
||||
zoneI,
|
||||
pz[zoneI].clone
|
||||
(
|
||||
procMesh.pointZones(),
|
||||
zoneI,
|
||||
zonePoints[zoneI].shrink()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (pz.size())
|
||||
{
|
||||
// Force writing on all processors
|
||||
procMesh.pointZones().writeOpt() = IOobject::AUTO_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
// Face zones
|
||||
{
|
||||
const faceZoneMesh& fz = faceZones();
|
||||
|
||||
// Go through all the zoned face and find out if they
|
||||
// belong to a zone. If so, add it to the zone as
|
||||
// necessary
|
||||
List<DynamicList<label> > zoneFaces(fz.size());
|
||||
List<DynamicList<bool> > zoneFaceFlips(fz.size());
|
||||
|
||||
// Estimate size
|
||||
forAll(zoneFaces, zoneI)
|
||||
{
|
||||
label procSize = fz[zoneI].size() / nProcs_;
|
||||
|
||||
zoneFaces[zoneI].setSize(procSize);
|
||||
zoneFaceFlips[zoneI].setSize(procSize);
|
||||
}
|
||||
|
||||
// Go through all the zoned faces and find out if they
|
||||
// belong to a zone. If so, add it to the zone as
|
||||
// necessary
|
||||
forAll (curFaceLabels, facei)
|
||||
{
|
||||
// Remember to decrement the index by one (turning index)
|
||||
//
|
||||
label curF = mag(curFaceLabels[facei]) - 1;
|
||||
|
||||
label zoneI = faceToZone[curF];
|
||||
|
||||
if (zoneI >= 0)
|
||||
{
|
||||
// Single zone. Add the face
|
||||
zoneFaces[zoneI].append(facei);
|
||||
|
||||
label index = fz[zoneI].whichFace(curF);
|
||||
|
||||
bool flip = fz[zoneI].flipMap()[index];
|
||||
|
||||
if (curFaceLabels[facei] < 0)
|
||||
{
|
||||
flip = !flip;
|
||||
}
|
||||
|
||||
zoneFaceFlips[zoneI].append(flip);
|
||||
}
|
||||
else if (zoneI == -2)
|
||||
{
|
||||
// Multiple zones. Lookup.
|
||||
forAll(fz, zoneI)
|
||||
{
|
||||
label index = fz[zoneI].whichFace(curF);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
zoneFaces[zoneI].append(facei);
|
||||
|
||||
bool flip = fz[zoneI].flipMap()[index];
|
||||
|
||||
if (curFaceLabels[facei] < 0)
|
||||
{
|
||||
flip = !flip;
|
||||
}
|
||||
|
||||
zoneFaceFlips[zoneI].append(flip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
procMesh.faceZones().clearAddressing();
|
||||
procMesh.faceZones().setSize(zoneFaces.size());
|
||||
forAll(zoneFaces, zoneI)
|
||||
{
|
||||
procMesh.faceZones().set
|
||||
(
|
||||
zoneI,
|
||||
fz[zoneI].clone
|
||||
(
|
||||
zoneFaces[zoneI].shrink(), // addressing
|
||||
zoneFaceFlips[zoneI].shrink(), // flipmap
|
||||
zoneI,
|
||||
procMesh.faceZones()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (fz.size())
|
||||
{
|
||||
// Force writing on all processors
|
||||
procMesh.faceZones().writeOpt() = IOobject::AUTO_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
// Cell zones
|
||||
{
|
||||
const cellZoneMesh& cz = cellZones();
|
||||
|
||||
// Go through all the zoned cells and find out if they
|
||||
// belong to a zone. If so, add it to the zone as
|
||||
// necessary
|
||||
List<DynamicList<label> > zoneCells(cz.size());
|
||||
|
||||
// Estimate size
|
||||
forAll(zoneCells, zoneI)
|
||||
{
|
||||
zoneCells[zoneI].setSize(cz[zoneI].size() / nProcs_);
|
||||
}
|
||||
|
||||
forAll (curCellLabels, celli)
|
||||
{
|
||||
label curCellI = curCellLabels[celli];
|
||||
|
||||
label zoneI = cellToZone[curCellI];
|
||||
|
||||
if (zoneI >= 0)
|
||||
{
|
||||
// Single zone.
|
||||
zoneCells[zoneI].append(celli);
|
||||
}
|
||||
else if (zoneI == -2)
|
||||
{
|
||||
// Multiple zones. Lookup.
|
||||
forAll(cz, zoneI)
|
||||
{
|
||||
label index = cz[zoneI].whichCell(curCellI);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
zoneCells[zoneI].append(celli);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
procMesh.cellZones().clearAddressing();
|
||||
procMesh.cellZones().setSize(zoneCells.size());
|
||||
forAll(zoneCells, zoneI)
|
||||
{
|
||||
procMesh.cellZones().set
|
||||
(
|
||||
zoneI,
|
||||
cz[zoneI].clone
|
||||
(
|
||||
zoneCells[zoneI].shrink(),
|
||||
zoneI,
|
||||
procMesh.cellZones()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (cz.size())
|
||||
{
|
||||
// Force writing on all processors
|
||||
procMesh.cellZones().writeOpt() = IOobject::AUTO_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the precision of the points data to 10
|
||||
IOstream::defaultPrecision(10);
|
||||
|
||||
procMesh.write();
|
||||
|
||||
Info<< endl
|
||||
<< "Processor " << procI << nl
|
||||
<< " Number of cells = " << procMesh.nCells()
|
||||
<< endl;
|
||||
|
||||
label nBoundaryFaces = 0;
|
||||
label nProcPatches = 0;
|
||||
label nProcFaces = 0;
|
||||
|
||||
forAll (procMesh.boundaryMesh(), patchi)
|
||||
{
|
||||
if
|
||||
(
|
||||
procMesh.boundaryMesh()[patchi].type()
|
||||
== processorPolyPatch::typeName
|
||||
)
|
||||
{
|
||||
const processorPolyPatch& ppp =
|
||||
refCast<const processorPolyPatch>
|
||||
(
|
||||
procMesh.boundaryMesh()[patchi]
|
||||
);
|
||||
|
||||
Info<< " Number of faces shared with processor "
|
||||
<< ppp.neighbProcNo() << " = " << ppp.size() << endl;
|
||||
|
||||
nProcPatches++;
|
||||
nProcFaces += ppp.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
nBoundaryFaces += procMesh.boundaryMesh()[patchi].size();
|
||||
}
|
||||
}
|
||||
|
||||
Info<< " Number of processor patches = " << nProcPatches << nl
|
||||
<< " Number of processor faces = " << nProcFaces << nl
|
||||
<< " Number of boundary faces = " << nBoundaryFaces << endl;
|
||||
|
||||
totProcFaces += nProcFaces;
|
||||
maxProcPatches = max(maxProcPatches, nProcPatches);
|
||||
maxProcFaces = max(maxProcFaces, nProcFaces);
|
||||
|
||||
// create and write the addressing information
|
||||
labelIOList pointProcAddressing
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"pointProcAddressing",
|
||||
"constant",
|
||||
procMesh.meshSubDir,
|
||||
procMesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
procPointAddressing_[procI]
|
||||
);
|
||||
pointProcAddressing.write();
|
||||
|
||||
labelIOList faceProcAddressing
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"faceProcAddressing",
|
||||
"constant",
|
||||
procMesh.meshSubDir,
|
||||
procMesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
procFaceAddressing_[procI]
|
||||
);
|
||||
faceProcAddressing.write();
|
||||
|
||||
labelIOList cellProcAddressing
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"cellProcAddressing",
|
||||
"constant",
|
||||
procMesh.meshSubDir,
|
||||
procMesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
procCellAddressing_[procI]
|
||||
);
|
||||
cellProcAddressing.write();
|
||||
|
||||
labelIOList boundaryProcAddressing
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"boundaryProcAddressing",
|
||||
"constant",
|
||||
procMesh.meshSubDir,
|
||||
procMesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
procBoundaryAddressing_[procI]
|
||||
);
|
||||
boundaryProcAddressing.write();
|
||||
}
|
||||
|
||||
Info<< nl
|
||||
<< "Number of processor faces = " << totProcFaces/2 << nl
|
||||
<< "Max number of processor patches = " << maxProcPatches << nl
|
||||
<< "Max number of faces between processors = " << maxProcFaces
|
||||
<< endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,172 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::domainDecomposition
|
||||
|
||||
Description
|
||||
Automatic domain decomposition class for FOAM meshes
|
||||
|
||||
SourceFiles
|
||||
domainDecomposition.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef domainDecomposition_H
|
||||
#define domainDecomposition_H
|
||||
|
||||
#include "fvMesh.H"
|
||||
#include "labelList.H"
|
||||
#include "SLList.H"
|
||||
#include "PtrList.H"
|
||||
#include "point.H"
|
||||
|
||||
#ifndef namespaceFoam
|
||||
#define namespaceFoam
|
||||
using namespace Foam;
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class domainDecomposition Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class domainDecomposition
|
||||
:
|
||||
public fvMesh
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Mesh decomposition control dictionary
|
||||
IOdictionary decompositionDict_;
|
||||
|
||||
//- Number of processors in decomposition
|
||||
label nProcs_;
|
||||
|
||||
//- Is the decomposition data to be distributed for each processor
|
||||
bool distributed_;
|
||||
|
||||
//- Processor label for each cell
|
||||
labelList cellToProc_;
|
||||
|
||||
//- Labels of points for each processor
|
||||
labelListList procPointAddressing_;
|
||||
|
||||
//- Labels of faces for each processor
|
||||
// Note: Face turning index is stored as the sign on addressing
|
||||
// Only the processor boundary faces are affected: if the sign of the
|
||||
// index is negative, the processor face is the reverse of the
|
||||
// original face. In order to do this properly, all face
|
||||
// indices will be incremented by 1 and the decremented as
|
||||
// necessary t avoid the problem of face number zero having no
|
||||
// sign.
|
||||
labelListList procFaceAddressing_;
|
||||
|
||||
//- Labels of cells for each processor
|
||||
labelListList procCellAddressing_;
|
||||
|
||||
//- Original patch index for every processor patch
|
||||
labelListList procBoundaryAddressing_;
|
||||
|
||||
//- Sizes for processor mesh patches
|
||||
// Excludes inter-processor boundaries
|
||||
labelListList procPatchSize_;
|
||||
|
||||
//- Start indices for processor patches
|
||||
// Excludes inter-processor boundaries
|
||||
labelListList procPatchStartIndex_;
|
||||
|
||||
//- Neighbour processor ID for inter-processor boundaries
|
||||
labelListList procNeighbourProcessors_;
|
||||
|
||||
//- Sizes for inter-processor patches
|
||||
labelListList procProcessorPatchSize_;
|
||||
|
||||
//- Start indices for inter-processor patches
|
||||
labelListList procProcessorPatchStartIndex_;
|
||||
|
||||
//- List of globally shared point labels
|
||||
labelList globallySharedPoints_;
|
||||
|
||||
//- Are there cyclic-parallel faces
|
||||
bool cyclicParallel_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
void distributeCells();
|
||||
|
||||
//- Mark all elements with value or -2 if occur twice
|
||||
static void mark
|
||||
(
|
||||
const labelList& zoneElems,
|
||||
const label zoneI,
|
||||
labelList& elementToZone
|
||||
);
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from IOobject
|
||||
domainDecomposition(const IOobject& io);
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
~domainDecomposition();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Number of processor in decomposition
|
||||
label nProcs() const
|
||||
{
|
||||
return nProcs_;
|
||||
}
|
||||
|
||||
//- Is the decomposition data to be distributed for each processor
|
||||
bool distributed() const
|
||||
{
|
||||
return distributed_;
|
||||
}
|
||||
|
||||
//- Decompose mesh. Optionally remove zero-sized patches.
|
||||
void decomposeMesh(const bool filterEmptyPatches);
|
||||
|
||||
//- Write decomposition
|
||||
bool writeDecomposition();
|
||||
|
||||
//- Cell-processor decomposition labels
|
||||
const labelList& cellToProc() const
|
||||
{
|
||||
return cellToProc_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,226 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fvFieldDecomposer.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
fvFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer
|
||||
(
|
||||
const unallocLabelList& addressingSlice,
|
||||
const label addressingOffset
|
||||
)
|
||||
:
|
||||
directAddressing_(addressingSlice)
|
||||
{
|
||||
forAll (directAddressing_, i)
|
||||
{
|
||||
// Subtract one to align addressing.
|
||||
directAddressing_[i] -= addressingOffset + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fvFieldDecomposer::processorVolPatchFieldDecomposer::
|
||||
processorVolPatchFieldDecomposer
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const unallocLabelList& addressingSlice
|
||||
)
|
||||
:
|
||||
addressing_(addressingSlice.size()),
|
||||
weights_(addressingSlice.size())
|
||||
{
|
||||
const scalarField& weights = mesh.weights().internalField();
|
||||
const labelList& own = mesh.faceOwner();
|
||||
const labelList& neighb = mesh.faceNeighbour();
|
||||
|
||||
forAll (addressing_, i)
|
||||
{
|
||||
// Subtract one to align addressing.
|
||||
label ai = mag(addressingSlice[i]) - 1;
|
||||
|
||||
if (ai < neighb.size())
|
||||
{
|
||||
// This is a regular face. it has been an internal face
|
||||
// of the original mesh and now it has become a face
|
||||
// on the parallel boundary
|
||||
addressing_[i].setSize(2);
|
||||
weights_[i].setSize(2);
|
||||
|
||||
addressing_[i][0] = own[ai];
|
||||
addressing_[i][1] = neighb[ai];
|
||||
|
||||
weights_[i][0] = weights[ai];
|
||||
weights_[i][1] = 1.0 - weights[ai];
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a face that used to be on a cyclic boundary
|
||||
// but has now become a parallel patch face. I cannot
|
||||
// do the interpolation properly (I would need to look
|
||||
// up the different (face) list of data), so I will
|
||||
// just grab the value from the owner cell
|
||||
//
|
||||
addressing_[i].setSize(1);
|
||||
weights_[i].setSize(1);
|
||||
|
||||
addressing_[i][0] = own[ai];
|
||||
|
||||
weights_[i][0] = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fvFieldDecomposer::processorSurfacePatchFieldDecomposer::
|
||||
processorSurfacePatchFieldDecomposer
|
||||
(
|
||||
const unallocLabelList& addressingSlice
|
||||
)
|
||||
:
|
||||
addressing_(addressingSlice.size()),
|
||||
weights_(addressingSlice.size())
|
||||
{
|
||||
forAll (addressing_, i)
|
||||
{
|
||||
addressing_[i].setSize(1);
|
||||
weights_[i].setSize(1);
|
||||
|
||||
addressing_[i][0] = mag(addressingSlice[i]) - 1;
|
||||
weights_[i][0] = sign(addressingSlice[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fvFieldDecomposer::fvFieldDecomposer
|
||||
(
|
||||
const fvMesh& completeMesh,
|
||||
const fvMesh& procMesh,
|
||||
const labelList& faceAddressing,
|
||||
const labelList& cellAddressing,
|
||||
const labelList& boundaryAddressing
|
||||
)
|
||||
:
|
||||
completeMesh_(completeMesh),
|
||||
procMesh_(procMesh),
|
||||
faceAddressing_(faceAddressing),
|
||||
cellAddressing_(cellAddressing),
|
||||
boundaryAddressing_(boundaryAddressing),
|
||||
patchFieldDecomposerPtrs_
|
||||
(
|
||||
procMesh_.boundary().size(),
|
||||
static_cast<patchFieldDecomposer*>(NULL)
|
||||
),
|
||||
processorVolPatchFieldDecomposerPtrs_
|
||||
(
|
||||
procMesh_.boundary().size(),
|
||||
static_cast<processorVolPatchFieldDecomposer*>(NULL)
|
||||
),
|
||||
processorSurfacePatchFieldDecomposerPtrs_
|
||||
(
|
||||
procMesh_.boundary().size(),
|
||||
static_cast<processorSurfacePatchFieldDecomposer*>(NULL)
|
||||
)
|
||||
{
|
||||
forAll (boundaryAddressing_, patchi)
|
||||
{
|
||||
if (boundaryAddressing_[patchi] >= 0)
|
||||
{
|
||||
patchFieldDecomposerPtrs_[patchi] = new patchFieldDecomposer
|
||||
(
|
||||
procMesh_.boundary()[patchi].patchSlice(faceAddressing_),
|
||||
completeMesh_.boundaryMesh()
|
||||
[
|
||||
boundaryAddressing_[patchi]
|
||||
].start()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
processorVolPatchFieldDecomposerPtrs_[patchi] =
|
||||
new processorVolPatchFieldDecomposer
|
||||
(
|
||||
completeMesh_,
|
||||
procMesh_.boundary()[patchi].patchSlice(faceAddressing_)
|
||||
);
|
||||
|
||||
processorSurfacePatchFieldDecomposerPtrs_[patchi] =
|
||||
new processorSurfacePatchFieldDecomposer
|
||||
(
|
||||
static_cast<const unallocLabelList&>
|
||||
(
|
||||
procMesh_.boundary()[patchi].patchSlice
|
||||
(
|
||||
faceAddressing_
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
fvFieldDecomposer::~fvFieldDecomposer()
|
||||
{
|
||||
forAll (patchFieldDecomposerPtrs_, patchi)
|
||||
{
|
||||
if (patchFieldDecomposerPtrs_[patchi])
|
||||
{
|
||||
delete patchFieldDecomposerPtrs_[patchi];
|
||||
}
|
||||
}
|
||||
|
||||
forAll (processorVolPatchFieldDecomposerPtrs_, patchi)
|
||||
{
|
||||
if (processorVolPatchFieldDecomposerPtrs_[patchi])
|
||||
{
|
||||
delete processorVolPatchFieldDecomposerPtrs_[patchi];
|
||||
}
|
||||
}
|
||||
|
||||
forAll (processorSurfacePatchFieldDecomposerPtrs_, patchi)
|
||||
{
|
||||
if (processorSurfacePatchFieldDecomposerPtrs_[patchi])
|
||||
{
|
||||
delete processorSurfacePatchFieldDecomposerPtrs_[patchi];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,279 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::fvFieldDecomposer
|
||||
|
||||
Description
|
||||
Finite Volume volume and surface field decomposer.
|
||||
|
||||
SourceFiles
|
||||
fvFieldDecomposer.C
|
||||
fvFieldDecomposerDecomposeFields.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fvFieldDecomposer_H
|
||||
#define fvFieldDecomposer_H
|
||||
|
||||
#include "fvMesh.H"
|
||||
#include "fvPatchFieldMapper.H"
|
||||
#include "surfaceFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
class IOobjectList;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class fvFieldDecomposer Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class fvFieldDecomposer
|
||||
{
|
||||
public:
|
||||
|
||||
//- Patch field decomposer class
|
||||
class patchFieldDecomposer
|
||||
:
|
||||
public fvPatchFieldMapper
|
||||
{
|
||||
// Private data
|
||||
|
||||
labelList directAddressing_;
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given addressing
|
||||
patchFieldDecomposer
|
||||
(
|
||||
const unallocLabelList& addressingSlice,
|
||||
const label addressingOffset
|
||||
);
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
label size() const
|
||||
{
|
||||
return directAddressing_.size();
|
||||
}
|
||||
|
||||
bool direct() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const unallocLabelList& directAddressing() const
|
||||
{
|
||||
return directAddressing_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//- Processor patch field decomposer class
|
||||
class processorVolPatchFieldDecomposer
|
||||
:
|
||||
public fvPatchFieldMapper
|
||||
{
|
||||
// Private data
|
||||
|
||||
labelListList addressing_;
|
||||
scalarListList weights_;
|
||||
|
||||
public:
|
||||
|
||||
//- Construct given addressing
|
||||
processorVolPatchFieldDecomposer
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const unallocLabelList& addressingSlice
|
||||
);
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
label size() const
|
||||
{
|
||||
return addressing_.size();
|
||||
}
|
||||
|
||||
bool direct() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const labelListList& addressing() const
|
||||
{
|
||||
return addressing_;
|
||||
}
|
||||
|
||||
const scalarListList& weights() const
|
||||
{
|
||||
return weights_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//- Processor patch field decomposer class
|
||||
class processorSurfacePatchFieldDecomposer
|
||||
:
|
||||
public fvPatchFieldMapper
|
||||
{
|
||||
labelListList addressing_;
|
||||
scalarListList weights_;
|
||||
|
||||
public:
|
||||
|
||||
//- Construct given addressing
|
||||
processorSurfacePatchFieldDecomposer
|
||||
(
|
||||
const unallocLabelList& addressingSlice
|
||||
);
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
label size() const
|
||||
{
|
||||
return addressing_.size();
|
||||
}
|
||||
|
||||
bool direct() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const labelListList& addressing() const
|
||||
{
|
||||
return addressing_;
|
||||
}
|
||||
|
||||
const scalarListList& weights() const
|
||||
{
|
||||
return weights_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
//- Reference to complete mesh
|
||||
const fvMesh& completeMesh_;
|
||||
|
||||
//- Reference to processor mesh
|
||||
const fvMesh& procMesh_;
|
||||
|
||||
//- Reference to face addressing
|
||||
const labelList& faceAddressing_;
|
||||
|
||||
//- Reference to cell addressing
|
||||
const labelList& cellAddressing_;
|
||||
|
||||
//- Reference to boundary addressing
|
||||
const labelList& boundaryAddressing_;
|
||||
|
||||
//- List of patch field decomposers
|
||||
List<patchFieldDecomposer*> patchFieldDecomposerPtrs_;
|
||||
|
||||
List<processorVolPatchFieldDecomposer*>
|
||||
processorVolPatchFieldDecomposerPtrs_;
|
||||
|
||||
List<processorSurfacePatchFieldDecomposer*>
|
||||
processorSurfacePatchFieldDecomposerPtrs_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
fvFieldDecomposer(const fvFieldDecomposer&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const fvFieldDecomposer&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
fvFieldDecomposer
|
||||
(
|
||||
const fvMesh& completeMesh,
|
||||
const fvMesh& procMesh,
|
||||
const labelList& faceAddressing,
|
||||
const labelList& cellAddressing,
|
||||
const labelList& boundaryAddressing
|
||||
);
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
~fvFieldDecomposer();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Decompose volume field
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh> >
|
||||
decomposeField
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field
|
||||
) const;
|
||||
|
||||
//- Decompose surface field
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvsPatchField, surfaceMesh> >
|
||||
decomposeField
|
||||
(
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>& field
|
||||
) const;
|
||||
|
||||
template<class GeoField>
|
||||
void decomposeFields(const PtrList<GeoField>& fields) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
# include "fvFieldDecomposerDecomposeFields.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,236 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fvFieldDecomposer.H"
|
||||
#include "processorFvPatchField.H"
|
||||
#include "processorFvsPatchField.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh> >
|
||||
fvFieldDecomposer::decomposeField
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field
|
||||
) const
|
||||
{
|
||||
// Create and map the internal field values
|
||||
Field<Type> internalField(field.internalField(), cellAddressing_);
|
||||
|
||||
// Create and map the patch field values
|
||||
PtrList<fvPatchField<Type> > patchFields(boundaryAddressing_.size());
|
||||
|
||||
forAll (boundaryAddressing_, patchi)
|
||||
{
|
||||
if (boundaryAddressing_[patchi] >= 0)
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
patchi,
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
field.boundaryField()[boundaryAddressing_[patchi]],
|
||||
procMesh_.boundary()[patchi],
|
||||
DimensionedField<Type, volMesh>::null(),
|
||||
*patchFieldDecomposerPtrs_[patchi]
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
patchi,
|
||||
new processorFvPatchField<Type>
|
||||
(
|
||||
procMesh_.boundary()[patchi],
|
||||
DimensionedField<Type, volMesh>::null(),
|
||||
Field<Type>
|
||||
(
|
||||
field.internalField(),
|
||||
*processorVolPatchFieldDecomposerPtrs_[patchi]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the field for the processor
|
||||
return tmp<GeometricField<Type, fvPatchField, volMesh> >
|
||||
(
|
||||
new GeometricField<Type, fvPatchField, volMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
field.name(),
|
||||
procMesh_.time().timeName(),
|
||||
procMesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
procMesh_,
|
||||
field.dimensions(),
|
||||
internalField,
|
||||
patchFields
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvsPatchField, surfaceMesh> >
|
||||
fvFieldDecomposer::decomposeField
|
||||
(
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>& field
|
||||
) const
|
||||
{
|
||||
labelList mapAddr
|
||||
(
|
||||
labelList::subList
|
||||
(
|
||||
faceAddressing_,
|
||||
procMesh_.nInternalFaces()
|
||||
)
|
||||
);
|
||||
forAll (mapAddr, i)
|
||||
{
|
||||
mapAddr[i] -= 1;
|
||||
}
|
||||
|
||||
// Create and map the internal field values
|
||||
Field<Type> internalField
|
||||
(
|
||||
field.internalField(),
|
||||
mapAddr
|
||||
);
|
||||
|
||||
// Problem with addressing when a processor patch picks up both internal
|
||||
// faces and faces from cyclic boundaries. This is a bit of a hack, but
|
||||
// I cannot find a better solution without making the internal storage
|
||||
// mechanism for surfaceFields correspond to the one of faces in polyMesh
|
||||
// (i.e. using slices)
|
||||
Field<Type> allFaceField(field.mesh().nFaces());
|
||||
|
||||
forAll (field.internalField(), i)
|
||||
{
|
||||
allFaceField[i] = field.internalField()[i];
|
||||
}
|
||||
|
||||
forAll (field.boundaryField(), patchi)
|
||||
{
|
||||
const Field<Type> & p = field.boundaryField()[patchi];
|
||||
|
||||
const label patchStart = field.mesh().boundaryMesh()[patchi].start();
|
||||
|
||||
forAll (p, i)
|
||||
{
|
||||
allFaceField[patchStart + i] = p[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Create and map the patch field values
|
||||
PtrList<fvsPatchField<Type> > patchFields(boundaryAddressing_.size());
|
||||
|
||||
forAll (boundaryAddressing_, patchi)
|
||||
{
|
||||
if (boundaryAddressing_[patchi] >= 0)
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
patchi,
|
||||
fvsPatchField<Type>::New
|
||||
(
|
||||
field.boundaryField()[boundaryAddressing_[patchi]],
|
||||
procMesh_.boundary()[patchi],
|
||||
DimensionedField<Type, surfaceMesh>::null(),
|
||||
*patchFieldDecomposerPtrs_[patchi]
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
patchi,
|
||||
new processorFvsPatchField<Type>
|
||||
(
|
||||
procMesh_.boundary()[patchi],
|
||||
DimensionedField<Type, surfaceMesh>::null(),
|
||||
Field<Type>
|
||||
(
|
||||
allFaceField,
|
||||
*processorSurfacePatchFieldDecomposerPtrs_[patchi]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the field for the processor
|
||||
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh> >
|
||||
(
|
||||
new GeometricField<Type, fvsPatchField, surfaceMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
field.name(),
|
||||
procMesh_.time().timeName(),
|
||||
procMesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
procMesh_,
|
||||
field.dimensions(),
|
||||
internalField,
|
||||
patchFields
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class GeoField>
|
||||
void fvFieldDecomposer::decomposeFields
|
||||
(
|
||||
const PtrList<GeoField>& fields
|
||||
) const
|
||||
{
|
||||
forAll (fields, fieldI)
|
||||
{
|
||||
decomposeField(fields[fieldI])().write();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,93 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Description
|
||||
Lagrangian field decomposer.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "lagrangianFieldDecomposer.H"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from components
|
||||
lagrangianFieldDecomposer::lagrangianFieldDecomposer
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const polyMesh& procMesh,
|
||||
const labelList& cellProcAddressing,
|
||||
const word& cloudName,
|
||||
const Cloud<indexedParticle>& lagrangianPositions,
|
||||
const List<SLList<indexedParticle*>*>& cellParticles
|
||||
)
|
||||
:
|
||||
procMesh_(procMesh),
|
||||
positions_(procMesh, cloudName, false),
|
||||
particleIndices_(lagrangianPositions.size())
|
||||
{
|
||||
label pi = 0;
|
||||
|
||||
forAll(cellProcAddressing, procCelli)
|
||||
{
|
||||
label celli = cellProcAddressing[procCelli];
|
||||
|
||||
if (cellParticles[celli])
|
||||
{
|
||||
SLList<indexedParticle*>& particlePtrs = *cellParticles[celli];
|
||||
|
||||
forAllIter(SLList<indexedParticle*>, particlePtrs, iter)
|
||||
{
|
||||
const indexedParticle& ppi = *iter();
|
||||
particleIndices_[pi++] = ppi.index();
|
||||
|
||||
positions_.append
|
||||
(
|
||||
new passiveParticle
|
||||
(
|
||||
positions_,
|
||||
ppi.position(),
|
||||
procCelli
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
particleIndices_.setSize(pi);
|
||||
|
||||
IOPosition<passiveParticle>(positions_).write();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,137 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::lagrangianFieldDecomposer
|
||||
|
||||
Description
|
||||
Lagrangian field decomposer.
|
||||
|
||||
SourceFiles
|
||||
lagrangianFieldDecomposer.C
|
||||
lagrangianFieldDecomposerDecomposeFields.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef lagrangianFieldDecomposer_H
|
||||
#define lagrangianFieldDecomposer_H
|
||||
|
||||
#include "Cloud.H"
|
||||
#include "indexedParticle.H"
|
||||
#include "passiveParticle.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
class IOobjectList;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class lagrangianFieldDecomposer Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class lagrangianFieldDecomposer
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Reference to processor mesh
|
||||
const polyMesh& procMesh_;
|
||||
|
||||
//- Lagrangian positions for this processor
|
||||
Cloud<passiveParticle> positions_;
|
||||
|
||||
//- The indices of the particles on this processor
|
||||
labelList particleIndices_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
lagrangianFieldDecomposer(const lagrangianFieldDecomposer&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const lagrangianFieldDecomposer&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
lagrangianFieldDecomposer
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const polyMesh& procMesh,
|
||||
const labelList& cellProcAddressing,
|
||||
const word& cloudName,
|
||||
const Cloud<indexedParticle>& lagrangianPositions,
|
||||
const List<SLList<indexedParticle*>*>& cellParticles
|
||||
);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Read the fields and hold on the pointer list
|
||||
template<class Type>
|
||||
static void readFields
|
||||
(
|
||||
const label cloudI,
|
||||
const IOobjectList& lagrangianObjects,
|
||||
PtrList<PtrList<IOField<Type> > >& lagrangianFields
|
||||
// PtrList<IOField<Type> >& lagrangianFields
|
||||
);
|
||||
|
||||
//- Decompose volume field
|
||||
template<class Type>
|
||||
tmp<IOField<Type> > decomposeField
|
||||
(
|
||||
const word& cloudName,
|
||||
const IOField<Type>& field
|
||||
) const;
|
||||
|
||||
template<class GeoField>
|
||||
void decomposeFields
|
||||
(
|
||||
const word& cloudName,
|
||||
const PtrList<GeoField>& fields
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
# include "lagrangianFieldDecomposerDecomposeFields.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,123 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "lagrangianFieldDecomposer.H"
|
||||
#include "IOobjectList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void lagrangianFieldDecomposer::readFields
|
||||
(
|
||||
const label cloudI,
|
||||
const IOobjectList& lagrangianObjects,
|
||||
PtrList<PtrList<IOField<Type> > >& lagrangianFields
|
||||
)
|
||||
{
|
||||
// Search list of objects for lagrangian fields
|
||||
IOobjectList lagrangianTypeObjects
|
||||
(
|
||||
lagrangianObjects.lookupClass(IOField<Type>::typeName)
|
||||
);
|
||||
|
||||
lagrangianFields.set
|
||||
(
|
||||
cloudI,
|
||||
new PtrList<IOField<Type> >
|
||||
(
|
||||
lagrangianTypeObjects.size()
|
||||
)
|
||||
);
|
||||
|
||||
label lagrangianFieldi=0;
|
||||
forAllIter(IOobjectList, lagrangianTypeObjects, iter)
|
||||
{
|
||||
lagrangianFields[cloudI].set
|
||||
(
|
||||
lagrangianFieldi++,
|
||||
new IOField<Type>(*iter())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
tmp<IOField<Type> > lagrangianFieldDecomposer::decomposeField
|
||||
(
|
||||
const word& cloudName,
|
||||
const IOField<Type>& field
|
||||
) const
|
||||
{
|
||||
// Create and map the internal field values
|
||||
Field<Type> procField(field, particleIndices_);
|
||||
|
||||
// Create the field for the processor
|
||||
return tmp<IOField<Type> >
|
||||
(
|
||||
new IOField<Type>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
field.name(),
|
||||
procMesh_.time().timeName(),
|
||||
"lagrangian"/cloudName,
|
||||
procMesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
procField
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class GeoField>
|
||||
void lagrangianFieldDecomposer::decomposeFields
|
||||
(
|
||||
const word& cloudName,
|
||||
const PtrList<GeoField>& fields
|
||||
) const
|
||||
{
|
||||
if (particleIndices_.size())
|
||||
{
|
||||
forAll (fields, fieldI)
|
||||
{
|
||||
decomposeField(cloudName, fields[fieldI])().write();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,133 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "pointFieldDecomposer.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
pointFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer
|
||||
(
|
||||
const pointPatch& completeMeshPatch,
|
||||
const pointPatch& procMeshPatch,
|
||||
const labelList& directAddr
|
||||
)
|
||||
:
|
||||
pointPatchFieldMapperPatchRef
|
||||
(
|
||||
completeMeshPatch,
|
||||
procMeshPatch
|
||||
),
|
||||
directAddressing_(procMeshPatch.size(), -1)
|
||||
{
|
||||
// Create the inverse-addressing of the patch point labels.
|
||||
labelList pointMap(completeMeshPatch.boundaryMesh().mesh().size(), -1);
|
||||
|
||||
const labelList& completeMeshPatchPoints = completeMeshPatch.meshPoints();
|
||||
|
||||
forAll (completeMeshPatchPoints, pointi)
|
||||
{
|
||||
pointMap[completeMeshPatchPoints[pointi]] = pointi;
|
||||
}
|
||||
|
||||
// Use the inverse point addressing to create the addressing table for this
|
||||
// patch
|
||||
const labelList& procMeshPatchPoints = procMeshPatch.meshPoints();
|
||||
|
||||
forAll (procMeshPatchPoints, pointi)
|
||||
{
|
||||
directAddressing_[pointi] =
|
||||
pointMap[directAddr[procMeshPatchPoints[pointi]]];
|
||||
}
|
||||
|
||||
// Check that all the patch point addresses are set
|
||||
if (directAddressing_.size() && min(directAddressing_) < 0)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"pointFieldDecomposer::patchFieldDecomposer()"
|
||||
) << "Incomplete patch point addressing"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pointFieldDecomposer::pointFieldDecomposer
|
||||
(
|
||||
const pointMesh& completeMesh,
|
||||
const pointMesh& procMesh,
|
||||
const labelList& pointAddressing,
|
||||
const labelList& boundaryAddressing
|
||||
)
|
||||
:
|
||||
completeMesh_(completeMesh),
|
||||
procMesh_(procMesh),
|
||||
pointAddressing_(pointAddressing),
|
||||
boundaryAddressing_(boundaryAddressing),
|
||||
patchFieldDecomposerPtrs_
|
||||
(
|
||||
procMesh_.boundary().size(),
|
||||
static_cast<patchFieldDecomposer*>(NULL)
|
||||
)
|
||||
{
|
||||
forAll (boundaryAddressing_, patchi)
|
||||
{
|
||||
if (boundaryAddressing_[patchi] >= 0)
|
||||
{
|
||||
patchFieldDecomposerPtrs_[patchi] = new patchFieldDecomposer
|
||||
(
|
||||
completeMesh_.boundary()[boundaryAddressing_[patchi]],
|
||||
procMesh_.boundary()[patchi],
|
||||
pointAddressing_
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
pointFieldDecomposer::~pointFieldDecomposer()
|
||||
{
|
||||
forAll (patchFieldDecomposerPtrs_, patchi)
|
||||
{
|
||||
if (patchFieldDecomposerPtrs_[patchi])
|
||||
{
|
||||
delete patchFieldDecomposerPtrs_[patchi];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,176 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::pointFieldDecomposer
|
||||
|
||||
Description
|
||||
Point field decomposer.
|
||||
|
||||
SourceFiles
|
||||
pointFieldDecomposer.C
|
||||
pointFieldDecomposerDecomposeFields.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef pointFieldDecomposer_H
|
||||
#define pointFieldDecomposer_H
|
||||
|
||||
#include "pointMesh.H"
|
||||
#include "pointPatchFieldMapperPatchRef.H"
|
||||
#include "pointFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class pointFieldDecomposer Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class pointFieldDecomposer
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//- Point patch field decomposer class
|
||||
class patchFieldDecomposer
|
||||
:
|
||||
public pointPatchFieldMapperPatchRef
|
||||
{
|
||||
// Private data
|
||||
|
||||
labelList directAddressing_;
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given addressing
|
||||
patchFieldDecomposer
|
||||
(
|
||||
const pointPatch& completeMeshPatch,
|
||||
const pointPatch& procMeshPatch,
|
||||
const labelList& directAddr
|
||||
);
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
label size() const
|
||||
{
|
||||
return directAddressing_.size();
|
||||
}
|
||||
|
||||
bool direct() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const unallocLabelList& directAddressing() const
|
||||
{
|
||||
return directAddressing_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
//- Reference to complete mesh
|
||||
const pointMesh& completeMesh_;
|
||||
|
||||
//- Reference to processor mesh
|
||||
const pointMesh& procMesh_;
|
||||
|
||||
//- Reference to point addressing
|
||||
const labelList& pointAddressing_;
|
||||
|
||||
//- Reference to boundary addressing
|
||||
const labelList& boundaryAddressing_;
|
||||
|
||||
//- List of patch field decomposers
|
||||
List<patchFieldDecomposer*> patchFieldDecomposerPtrs_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
pointFieldDecomposer(const pointFieldDecomposer&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const pointFieldDecomposer&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
pointFieldDecomposer
|
||||
(
|
||||
const pointMesh& completeMesh,
|
||||
const pointMesh& procMesh,
|
||||
const labelList& pointAddressing,
|
||||
const labelList& boundaryAddressing
|
||||
);
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
~pointFieldDecomposer();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Decompose point field
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, pointPatchField, pointMesh> >
|
||||
decomposeField
|
||||
(
|
||||
const GeometricField<Type, pointPatchField, pointMesh>&
|
||||
) const;
|
||||
|
||||
template<class GeoField>
|
||||
void decomposeFields(const PtrList<GeoField>& fields) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
# include "pointFieldDecomposerDecomposeFields.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,136 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "pointFieldDecomposer.H"
|
||||
#include "processorPointPatchFields.H"
|
||||
#include "globalPointPatchFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, pointPatchField, pointMesh> >
|
||||
pointFieldDecomposer::decomposeField
|
||||
(
|
||||
const GeometricField<Type, pointPatchField, pointMesh>& field
|
||||
) const
|
||||
{
|
||||
// Create and map the internal field values
|
||||
Field<Type> internalField(field.internalField(), pointAddressing_);
|
||||
|
||||
// Create a list of pointers for the patchFields including one extra
|
||||
// for the global patch
|
||||
PtrList<pointPatchField<Type> > patchFields
|
||||
(
|
||||
boundaryAddressing_.size() + 1
|
||||
);
|
||||
|
||||
// Create and map the patch field values
|
||||
forAll (boundaryAddressing_, patchi)
|
||||
{
|
||||
if (patchFieldDecomposerPtrs_[patchi])
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
patchi,
|
||||
pointPatchField<Type>::New
|
||||
(
|
||||
field.boundaryField()[boundaryAddressing_[patchi]],
|
||||
procMesh_.boundary()[patchi],
|
||||
DimensionedField<Type, pointMesh>::null(),
|
||||
*patchFieldDecomposerPtrs_[patchi]
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
patchi,
|
||||
new processorPointPatchField<Type>
|
||||
(
|
||||
procMesh_.boundary()[patchi],
|
||||
DimensionedField<Type, pointMesh>::null()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the global patch
|
||||
patchFields.set
|
||||
(
|
||||
boundaryAddressing_.size(),
|
||||
new globalPointPatchField<Type>
|
||||
(
|
||||
procMesh_.boundary().globalPatch(),
|
||||
DimensionedField<Type, pointMesh>::null()
|
||||
)
|
||||
);
|
||||
|
||||
// Create the field for the processor
|
||||
return tmp<GeometricField<Type, pointPatchField, pointMesh> >
|
||||
(
|
||||
new GeometricField<Type, pointPatchField, pointMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
field.name(),
|
||||
procMesh_().time().timeName(),
|
||||
procMesh_(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
procMesh_,
|
||||
field.dimensions(),
|
||||
internalField,
|
||||
patchFields
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class GeoField>
|
||||
void pointFieldDecomposer::decomposeFields
|
||||
(
|
||||
const PtrList<GeoField>& fields
|
||||
) const
|
||||
{
|
||||
forAll (fields, fieldI)
|
||||
{
|
||||
decomposeField(fields[fieldI])().write();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,73 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "readFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Mesh, class GeoField>
|
||||
void Foam::readFields
|
||||
(
|
||||
const Mesh& mesh,
|
||||
const IOobjectList& objects,
|
||||
PtrList<GeoField>& fields
|
||||
)
|
||||
{
|
||||
// Search list of objects for volScalarFields
|
||||
IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName));
|
||||
|
||||
// Remove the cellDist field
|
||||
IOobjectList::iterator celDistIter = fieldObjects.find("cellDist");
|
||||
if (celDistIter != fieldObjects.end())
|
||||
{
|
||||
fieldObjects.erase(celDistIter);
|
||||
}
|
||||
|
||||
// Construct the vol scalar fields
|
||||
fields.setSize(fieldObjects.size());
|
||||
|
||||
label fieldi=0;
|
||||
for
|
||||
(
|
||||
IOobjectList::iterator iter = fieldObjects.begin();
|
||||
iter != fieldObjects.end();
|
||||
++iter
|
||||
)
|
||||
{
|
||||
fields.set
|
||||
(
|
||||
fieldi++,
|
||||
new GeoField
|
||||
(
|
||||
*iter(),
|
||||
mesh
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,66 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Global
|
||||
readFields
|
||||
|
||||
Description
|
||||
|
||||
SourceFiles
|
||||
readFields.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef readFields_H
|
||||
#define readFields_H
|
||||
|
||||
#include "IOobjectList.H"
|
||||
#include "PtrList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
// Read the fields and hold on the pointer list
|
||||
template<class Mesh, class GeoField>
|
||||
void readFields
|
||||
(
|
||||
const Mesh& mesh,
|
||||
const IOobjectList& objects,
|
||||
PtrList<GeoField>& fields
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
# include "readFields.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user