Commit 44be3592 authored by graham's avatar graham
Browse files

Merge branch 'master' into cvm

parents 4bd6aba5 404a004d
......@@ -190,6 +190,10 @@
mesh. Great for postprocessing.
+ =steadyParticleTracks=: Generates VTK tracks from the output of the cloud
=ParticleTracks= post-processing sub-model
+ Sampling:
+ =patchInternalField=: new sampledSurface - like 'patch' but samples
internal field instead of boundary field.
+ =ensight=: new output format for all sampledSurfaces.
+ Function objects:
+ =residualControl=: new function object to allow users to terminate steady
state calculations when the defined residual levels are achieved
......@@ -204,7 +208,9 @@
+ =readFields=: reads field if not yet registered. Makes functionObjects
useable through standalone execFlowFunctionObjects.
+ =faceSource=: can now calculate on a sampledSurface (e.g. flow through a
triSurfaceMesh)
triSurfaceMesh).
+ =nearWallFields=: constructs field with on selected patches interpolated
internal field for further postprocessing.
* New tutorials
There is a large number of new tutorials for existing and new solvers in the
......
......@@ -129,15 +129,7 @@ int main(int argc, char *argv[])
mapDistribute map(constructSize, sendMap.xfer(), recvMap.xfer());
// Distribute complexData
mapDistribute::distribute
(
Pstream::nonBlocking,
List<labelPair>(),
map.constructSize(),
map.subMap(),
map.constructMap(),
complexData
);
mapDistribute::distribute(complexData);
Pout<< "complexData:" << complexData << endl;
}
......
......@@ -36,6 +36,7 @@ Description
------ local definitions
\* ------------------------------------------------------------------------ */
#include "cyclicPolyPatch.H"
#include "argList.H"
#include "Time.H"
#include "polyMesh.H"
......@@ -904,6 +905,13 @@ int main(int argc, char *argv[])
fluentToFoamType.insert("radiator", polyPatch::typeName);
fluentToFoamType.insert("porous-jump", polyPatch::typeName);
//- Periodic halves map directly into split cyclics. The problem is the
// initial matching since we require knowledge of the transformation.
// It is ok if the periodics are already ordered. We should read the
// periodic shadow faces section (section 18) to give use the ordering
// For now just disable.
//fluentToFoamType.insert("periodic", cyclicPolyPatch::typeName);
// Foam patch type for Fluent zone type
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -1039,15 +1047,59 @@ int main(int argc, char *argv[])
if (iter != fluentToFoamType.end())
{
newPatches[patchi] = polyPatch::New
(
iter(),
name,
0,
0,
patchi,
mesh.boundaryMesh()
).ptr();
// See if we have a periodic and can derive the other side.
word neighbPatchName;
if (iter() == cyclicPolyPatch::typeName)
{
// Periodic
size_t n = name.rfind("-SIDE-1");
if (n != string::npos)
{
neighbPatchName = name.substr(0, n) + "-SIDE-2";
}
else
{
n = name.rfind("-SIDE-2");
if (n != string::npos)
{
neighbPatchName = name.substr(0, n) + "-SIDE-1";
}
}
}
if (neighbPatchName.size())
{
Info<< "Adding cyclicPolyPatch for Fluent zone " << name
<< " with neighbour patch " << neighbPatchName
<< endl;
newPatches[patchi] = new cyclicPolyPatch
(
name,
0,
0,
patchi,
mesh.boundaryMesh(),
neighbPatchName,
cyclicPolyPatch::NOORDERING,
vector::zero,
vector::zero,
vector::zero
);
}
else
{
newPatches[patchi] = polyPatch::New
(
iter(),
name,
0,
0,
patchi,
mesh.boundaryMesh()
).ptr();
}
}
else
{
......
......@@ -19,15 +19,17 @@ FoamFile
numberOfSubdomains 8;
//- Keep owner and neighbour on same processor for faces in zones:
// preserveFaceZones (heater solid1 solid3);
//- Keep owner and neighbour on same processor for faces in patches:
// (makes sense only for cyclic patches)
//preservePatches (cyclic_half0 cyclic_half1);
//- Use the volScalarField named here as a weight for each cell in the
// decomposition. For example, use a particle population field to decompose
// for a balanced number of particles in a lagrangian simulation.
// weightField dsmcRhoNMean;
method scotch;
// method hierarchical;
......@@ -59,11 +61,8 @@ multiLevelCoeffs
}
}
// Desired output
simpleCoeffs
{
n (2 1 1);
......
......@@ -24,7 +24,6 @@ License
\*---------------------------------------------------------------------------*/
#include "domainDecomposition.H"
#include "Time.H"
#include "dictionary.H"
#include "labelIOList.H"
#include "processorPolyPatch.H"
......@@ -341,10 +340,10 @@ bool Foam::domainDecomposition::writeDecomposition()
const labelList& curProcessorPatchStarts =
procProcessorPatchStartIndex_[procI];
const labelListList& curSubPatchIDs =
const labelListList& curSubPatchIDs =
procProcessorPatchSubPatchIDs_[procI];
const labelListList& curSubStarts =
const labelListList& curSubStarts =
procProcessorPatchSubPatchStarts_[procI];
const polyPatchList& meshPatches = boundaryMesh();
......
......@@ -41,6 +41,9 @@ SourceFiles
#include "SLList.H"
#include "PtrList.H"
#include "point.H"
#include "Time.H"
#include "volFields.H"
namespace Foam
{
......@@ -80,7 +83,7 @@ class domainDecomposition
// original face. In order to do this properly, all face
// indices will be incremented by 1 and the decremented as
// necessary to avoid the problem of face number zero having no
// sign.
// sign.
List<DynamicList<label> > procFaceAddressing_;
//- Labels of cells for each processor
......
......@@ -114,7 +114,35 @@ void Foam::domainDecomposition::distributeCells()
if (sameProcFaces.empty())
{
cellToProc_ = decomposePtr().decompose(*this, cellCentres());
if (decompositionDict_.found("weightField"))
{
word weightName = decompositionDict_.lookup("weightField");
volScalarField weights
(
IOobject
(
weightName,
time().timeName(),
*this,
IOobject::MUST_READ,
IOobject::NO_WRITE
),
*this
);
cellToProc_ = decomposePtr().decompose
(
*this,
cellCentres(),
weights.internalField()
);
}
else
{
cellToProc_ = decomposePtr().decompose(*this, cellCentres());
}
}
else
{
......@@ -173,12 +201,49 @@ void Foam::domainDecomposition::distributeCells()
// Do decomposition on agglomeration
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cellToProc_ = decomposePtr().decompose
(
*this,
globalRegion,
regionCentres
);
if (decompositionDict_.found("weightField"))
{
scalarField regionWeights(globalRegion.nRegions(), 0);
word weightName = decompositionDict_.lookup("weightField");
volScalarField weights
(
IOobject
(
weightName,
time().timeName(),
*this,
IOobject::MUST_READ,
IOobject::NO_WRITE
),
*this
);
forAll(globalRegion, cellI)
{
label regionI = globalRegion[cellI];
regionWeights[regionI] += weights.internalField()[cellI];
}
cellToProc_ = decomposePtr().decompose
(
*this,
globalRegion,
regionCentres,
regionWeights
);
}
else
{
cellToProc_ = decomposePtr().decompose
(
*this,
globalRegion,
regionCentres
);
}
}
Info<< "\nFinished decomposition in "
......
......@@ -6,6 +6,7 @@ EXE_INC = \
EXE_LIBS = \
-lfiniteVolume \
-lgenericPatchFields \
-ldecompositionMethods \
-L$(FOAM_LIBBIN)/dummy -lptscotchDecomp \
-lmeshTools \
......
......@@ -86,33 +86,49 @@ autoPtr<fvMesh> createMesh
if (!haveMesh)
{
// Create dummy mesh. Only used on procs that don't have mesh.
// WIP: how to avoid parallel comms when loading IOdictionaries?
// For now just give error message.
if
(
regIOobject::fileModificationChecking
== regIOobject::timeStampMaster
|| regIOobject::fileModificationChecking
== regIOobject::inotifyMaster
)
{
FatalErrorIn("createMesh(..)")
<< "Cannot use 'fileModificationChecking' mode "
<< regIOobject::fileCheckTypesNames
[
regIOobject::fileModificationChecking
]
<< " since this uses parallel communication."
<< exit(FatalError);
IOdictionary fvSolution
(
IOobject
(
"fvSolution",
runTime.system(),
runTime,
IOobject::NO_READ,
IOobject::NO_WRITE
)
);
Pout<< "Writing dummy " << fvSolution.objectPath() << endl;
fvSolution.regIOobject::write();
}
{
IOdictionary fvSchemes
(
IOobject
(
"fvSchemes",
runTime.system(),
runTime,
IOobject::NO_READ,
IOobject::NO_WRITE
)
);
fvSchemes.add("divSchemes", dictionary());
fvSchemes.add("gradSchemes", dictionary());
fvSchemes.add("laplacianSchemes", dictionary());
Pout<< "Writing dummy " << fvSchemes.objectPath() << endl;
fvSchemes.regIOobject::write();
}
Pout<< "Creating dummy mesh from " << io.objectPath() << endl;
fvMesh dummyMesh
(
IOobject
(
regionName,
instDir,
runTime,
io.name(),
io.instance(),
io.db(),
IOobject::NO_READ
),
xferCopy(pointField()),
......@@ -545,8 +561,13 @@ int main(int argc, char *argv[])
mkDir(args.path());
}
// Switch timeStamp checking to one which does not do any
// parallel sync for same reason
regIOobject::fileModificationChecking = regIOobject::timeStamp;
# include "createTime.H"
word regionName = polyMesh::defaultRegion;
fileName meshSubDir;
......
......@@ -166,6 +166,18 @@ surfaces
// triangulate false;
}
movingNearWall_interpolated
{
// Sample cell values off patch. Does not need to be the near-wall
// cell, can be arbitrarily far away.
type patchInternalField;
patchName movingWall;
distance 0.0001;
interpolate true;
// Optional: whether to leave as faces (=default) or triangulate
// triangulate false;
}
interpolatedIso
{
// Iso surface for interpolated values only
......
......@@ -57,8 +57,10 @@ runParallel()
then
echo "$APP_RUN already run on $PWD: remove log file to run"
else
echo "Running $APP_RUN in parallel on $PWD using $1 processes"
( mpirun -np $1 $APP_RUN -parallel < /dev/null > log.$APP_RUN 2>&1 )
nProcs=$1
shift
echo "Running $APP_RUN in parallel on $PWD using $nProcs processes"
( mpirun -np $nProcs $APP_RUN -parallel $* < /dev/null > log.$APP_RUN 2>&1 )
fi
}
......
......@@ -70,8 +70,12 @@ are READ_IF_MODIFIED. It means that slaves read exactly the same dictionary
as the master so cannot be used for dictionaries that contain e.g. mesh
specific information.
- note: even if the file does not exist (e.g. when timeStampMaster) it
will still register a local file with the fileMonitor. This is so fileMonitor
stays synchronised. So take care when reading/creating non-parallel dictionary.
- inotify is a monitoring framework used to monitor changes in
lots of files (e.g. used in desktop searched like beagle). You specify
lots of files (e.g. used in desktop search engines like beagle). You specify
files to monitor and then get warned for any changes to these files.
It does not need timestamps. There is no need for fileModificationSkew
to allow for time differences. (there can still temporarily be a difference
......
......@@ -537,7 +537,7 @@ void Foam::FaceCellWave<Type, TrackingData>::handleProcPatches()
{
transform
(
procPatch.reverseT(),
procPatch.forwardT(),
receiveFaces.size(),
receiveFacesInfo
);
......
......@@ -55,46 +55,59 @@ void Foam::IOdictionary::readFile(const bool masterOnly)
close();
}
if (masterOnly)
if (masterOnly && Pstream::parRun())
{
// Scatter master data
if (Pstream::master())
// Scatter master data using communication scheme
const List<Pstream::commsStruct>& comms =
(
(Pstream::nProcs() < Pstream::nProcsSimpleSum)
? Pstream::linearCommunication()
: Pstream::treeCommunication()
);
// Get my communication order
const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
// Reveive from up
if (myComm.above() != -1)
{
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
slave++
)
if (debug)
{
// Note: use ASCII for now - binary IO of dictionaries is
// not currently supported
OPstream toSlave
(
Pstream::scheduled,
slave,
0,
UPstream::msgType(),
IOstream::ASCII
);
IOdictionary::writeData(toSlave);
Pout<< "IOdictionary : Reading " << objectPath()
<< " from processor " << myComm.above() << endl;
}
// Note: use ASCII for now - binary IO of dictionaries is
// not currently supported
IPstream fromAbove
(
Pstream::scheduled,
myComm.above(),
0,
IOstream::ASCII
);
IOdictionary::readData(fromAbove);
}
else
// Send to my downstairs neighbours
forAll(myComm.below(), belowI)
{
if (debug)
{
Pout<< "IOdictionary : Reading " << objectPath()
<< " from master processor " << Pstream::masterNo() << endl;
Pout<< "IOdictionary : Sending " << objectPath()
<< " to processor " << myComm.below()[belowI] << endl;
}
IPstream fromMaster
OPstream toBelow
(
Pstream::scheduled,
Pstream::masterNo(),
myComm.below()[belowI],
0,
Pstream::msgType(),
IOstream::ASCII
);
IOdictionary::readData(fromMaster);
IOdictionary::writeData(toBelow);
}
}
}
......
......@@ -177,55 +177,69 @@ bool Foam::regIOobject::read()
regIOobject::fileModificationChecking == timeStampMaster
|| regIOobject::fileModificationChecking == inotifyMaster;
bool ok;
bool ok = true;
if (Pstream::master() || !masterOnly)
{
if (IFstream::debug)
{
Pout<< "regIOobject::read() : "
<< "reading object " << name()
<< " from file " << endl;
}
ok = readData(readStream(type()));
close();
}
if (masterOnly)
if (masterOnly && Pstream::parRun())
{
// Scatter master data
if (Pstream::master())
{
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
slave++
)
{
// Note: use ASCII for now - binary IO of dictionaries is
// not currently supported
OPstream toSlave
(
Pstream::scheduled,
slave,
0,
UPstream::msgType(),
IOstream::ASCII
);
writeData(toSlave);
}
}
else
// Scatter master data using communication scheme
const List<Pstream::commsStruct>& comms =
(
(Pstream::nProcs() < Pstream::nProcsSimpleSum)
? Pstream::linearCommunication()
: Pstream::treeCommunication()
);
// Get my communication order
const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
// Reveive from up
if (myComm.above() != -1)
{
if (IFstream::debug)
{
Pout<< "re