mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'develop-pre-release' of develop.openfoam.com:Development/OpenFOAM-plus into develop-pre-release
This commit is contained in:
@ -3,7 +3,7 @@ cd ${0%/*} || exit 1 # Run from this directory
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
wmake libso CompressibleTwoPhaseMixtureTurbulenceModels
|
||||
wmake
|
||||
wmake $targetType CompressibleTwoPhaseMixtureTurbulenceModels
|
||||
wmake $targetType
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
#!/bin/sh
|
||||
cd ${0%/*} || exit 1 # Run from this directory
|
||||
targetType=libso # Preferred library type
|
||||
. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
wmake $targetType temperaturePhaseChangeTwoPhaseMixtures
|
||||
wmake
|
||||
wmake $targetType
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -12,8 +12,8 @@ if have_cgal
|
||||
then
|
||||
wmake $targetType conformalVoronoiMesh
|
||||
wmake $targetType conformalVoronoi2DMesh
|
||||
wmake foamyQuadMesh
|
||||
wmake foamyHexMesh
|
||||
wmake $targetType foamyQuadMesh
|
||||
wmake $targetType foamyHexMesh
|
||||
# wmake foamyHexMeshBackgroundMesh
|
||||
# (cd foamyHexMeshSurfaceSimplify && ./Allwmake)
|
||||
# wmake cellSizeAndAlignmentGrid
|
||||
|
||||
@ -356,6 +356,9 @@ int main(int argc, char *argv[])
|
||||
)
|
||||
);
|
||||
|
||||
// Give file handler a chance to determine the output directory
|
||||
const_cast<fileOperation&>(fileHandler()).setNProcs(nDomains);
|
||||
|
||||
if (decomposeFieldsOnly)
|
||||
{
|
||||
// Sanity check on previously decomposed case
|
||||
@ -395,22 +398,42 @@ int main(int argc, char *argv[])
|
||||
Info<< "Removing " << nProcs
|
||||
<< " existing processor directories" << endl;
|
||||
|
||||
fileHandler().rmDir
|
||||
// Remove existing processors directory
|
||||
fileNameList dirs
|
||||
(
|
||||
runTime.path()/word("processors"),
|
||||
true // silent (may not have been collated)
|
||||
);
|
||||
|
||||
// remove existing processor dirs
|
||||
// reverse order to avoid gaps if someone interrupts the process
|
||||
for (label proci = nProcs-1; proci >= 0; --proci)
|
||||
{
|
||||
fileName procDir
|
||||
fileHandler().readDir
|
||||
(
|
||||
runTime.path()/(word("processor") + name(proci))
|
||||
);
|
||||
runTime.path(),
|
||||
fileName::Type::DIRECTORY
|
||||
)
|
||||
);
|
||||
forAllReverse(dirs, diri)
|
||||
{
|
||||
const fileName& d = dirs[diri];
|
||||
|
||||
fileHandler().rmDir(procDir);
|
||||
// Starts with 'processors'
|
||||
if (d.find("processors") == 0)
|
||||
{
|
||||
if (fileHandler().exists(d))
|
||||
{
|
||||
fileHandler().rmDir(d);
|
||||
}
|
||||
}
|
||||
|
||||
// Starts with 'processor'
|
||||
if (d.find("processor") == 0)
|
||||
{
|
||||
// Check that integer after processor
|
||||
fileName num(d.substr(9));
|
||||
label proci = -1;
|
||||
if (Foam::read(num.c_str(), proci))
|
||||
{
|
||||
if (fileHandler().exists(d))
|
||||
{
|
||||
fileHandler().rmDir(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
procDirsProblem = false;
|
||||
|
||||
@ -216,6 +216,9 @@ int main(int argc, char *argv[])
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
// Warn fileHandler of number of processors
|
||||
const_cast<fileOperation&>(fileHandler()).setNProcs(nProcs);
|
||||
|
||||
// Create the processor databases
|
||||
PtrList<Time> databases(nProcs);
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@ License
|
||||
#include "Time.H"
|
||||
#include "patchZones.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "collatedFileOperation.H"
|
||||
|
||||
// VTK includes
|
||||
#include "vtkDataArraySelection.h"
|
||||
@ -268,7 +269,7 @@ Foam::word Foam::vtkPVFoam::getReaderPartName(const int partId) const
|
||||
|
||||
Foam::vtkPVFoam::vtkPVFoam
|
||||
(
|
||||
const char* const FileName,
|
||||
const char* const vtkFileName,
|
||||
vtkPVFoamReader* reader
|
||||
)
|
||||
:
|
||||
@ -294,12 +295,19 @@ Foam::vtkPVFoam::vtkPVFoam
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "vtkPVFoam - " << FileName << nl;
|
||||
Info<< "vtkPVFoam - " << vtkFileName << nl;
|
||||
printMemory();
|
||||
}
|
||||
|
||||
fileName FileName(vtkFileName);
|
||||
|
||||
// Make sure not to use the threaded version - it does not like
|
||||
// being loaded as a shared library - static cleanup order is problematic.
|
||||
// For now just disable the threaded writer.
|
||||
fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0;
|
||||
|
||||
// avoid argList and get rootPath/caseName directly from the file
|
||||
fileName fullCasePath(fileName(FileName).path());
|
||||
fileName fullCasePath(FileName.path());
|
||||
|
||||
if (!isDir(fullCasePath))
|
||||
{
|
||||
@ -314,8 +322,20 @@ Foam::vtkPVFoam::vtkPVFoam
|
||||
setEnv("FOAM_EXECUTABLE", "paraview", false);
|
||||
|
||||
// Set the case as an environment variable - some BCs might use this
|
||||
if (fullCasePath.name().find("processors", 0) == 0)
|
||||
{
|
||||
// FileName e.g. "cavity/processors256/processor1.OpenFOAM
|
||||
// Remove the processors section so it goes into processorDDD
|
||||
// checking below.
|
||||
fullCasePath = fullCasePath.path()/fileName(FileName.name()).lessExt();
|
||||
}
|
||||
|
||||
|
||||
if (fullCasePath.name().find("processor", 0) == 0)
|
||||
{
|
||||
// Give filehandler opportunity to analyse number of processors
|
||||
(void)fileHandler().filePath(fullCasePath);
|
||||
|
||||
const fileName globalCase = fullCasePath.path();
|
||||
|
||||
setEnv("FOAM_CASE", globalCase, true);
|
||||
|
||||
@ -2,6 +2,6 @@
|
||||
cd ${0%/*} || exit 1 # Run from this directory
|
||||
. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments
|
||||
|
||||
(wmake libso extractionMethod && wmake)
|
||||
(wmake $targetType extractionMethod && wmake $targetType)
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
| \\ / A nd | Web: www.OpenFOAM.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
// Insitu processing of finiteVolume fields with ParaView Catalyst
|
||||
// Insitu processing with ParaView Catalyst
|
||||
|
||||
type catalyst;
|
||||
libs ("libcatalystFoam.so");
|
||||
68
etc/caseDicts/insitu/catalyst/printChannels.py
Normal file
68
etc/caseDicts/insitu/catalyst/printChannels.py
Normal file
@ -0,0 +1,68 @@
|
||||
from paraview.simple import *
|
||||
from paraview import coprocessing
|
||||
|
||||
# The frequency to output everything
|
||||
outputfrequency = 1
|
||||
|
||||
# Simply print out all channel names that our function object is producing
|
||||
|
||||
# ----------------------- CoProcessor definition -----------------------
|
||||
|
||||
def CreateCoProcessor():
|
||||
def _CreatePipeline(coprocessor, datadescription):
|
||||
class Pipeline:
|
||||
for i in range(datadescription.GetNumberOfInputDescriptions()):
|
||||
name = datadescription.GetInputDescriptionName(i)
|
||||
input = coprocessor.CreateProducer(datadescription, name)
|
||||
grid = input.GetClientSideObject().GetOutputDataObject(0)
|
||||
print "Channel <" + name + "> is", grid.GetClassName()
|
||||
|
||||
return Pipeline()
|
||||
|
||||
class CoProcessor(coprocessing.CoProcessor):
|
||||
def CreatePipeline(self, datadescription):
|
||||
self.Pipeline = _CreatePipeline(self, datadescription)
|
||||
|
||||
return CoProcessor()
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Global variables that will hold the pipeline for each timestep
|
||||
# Creating the CoProcessor object, doesn't actually create the ParaView pipeline.
|
||||
# It will be automatically setup when coprocessor.UpdateProducers() is called the
|
||||
# first time.
|
||||
coprocessor = CreateCoProcessor()
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Enable Live-Visualizaton with ParaView
|
||||
coprocessor.EnableLiveVisualization(False)
|
||||
|
||||
|
||||
# ---------------------- Data Selection method ----------------------
|
||||
|
||||
def RequestDataDescription(datadescription):
|
||||
"Callback to populate the request for current timestep"
|
||||
global coprocessor
|
||||
if datadescription.GetForceOutput() == True or datadescription.GetTimeStep() % outputfrequency == 0:
|
||||
# We are just going to request all fields and meshes from the simulation
|
||||
# code/adaptor.
|
||||
for i in range(datadescription.GetNumberOfInputDescriptions()):
|
||||
datadescription.GetInputDescription(i).AllFieldsOn()
|
||||
datadescription.GetInputDescription(i).GenerateMeshOn()
|
||||
return
|
||||
|
||||
# setup requests for all inputs based on the requirements of the
|
||||
# pipeline.
|
||||
coprocessor.LoadRequestedData(datadescription)
|
||||
|
||||
# ------------------------ Processing method ------------------------
|
||||
|
||||
def DoCoProcessing(datadescription):
|
||||
"Callback to do co-processing for current timestep"
|
||||
global coprocessor
|
||||
|
||||
# Update the coprocessor by providing it the newly generated simulation data.
|
||||
# If the pipeline hasn't been setup yet, this will setup the pipeline.
|
||||
coprocessor.UpdateProducers(datadescription)
|
||||
|
||||
# Write output data, if appropriate.
|
||||
coprocessor.WriteData(datadescription);
|
||||
77
etc/caseDicts/insitu/catalyst/writeAll.py
Normal file
77
etc/caseDicts/insitu/catalyst/writeAll.py
Normal file
@ -0,0 +1,77 @@
|
||||
from paraview.simple import *
|
||||
from paraview import coprocessing
|
||||
|
||||
# The frequency to output everything
|
||||
outputfrequency = 5
|
||||
|
||||
# This is largely identical to the Catalyst allinputsgridwriter.py example
|
||||
# but only handle vtkMultiBlockDataSet, since that is what we generate
|
||||
|
||||
# ----------------------- CoProcessor definition -----------------------
|
||||
|
||||
def CreateCoProcessor():
|
||||
def _CreatePipeline(coprocessor, datadescription):
|
||||
class Pipeline:
|
||||
for i in range(datadescription.GetNumberOfInputDescriptions()):
|
||||
name = datadescription.GetInputDescriptionName(i)
|
||||
input = coprocessor.CreateProducer(datadescription, name)
|
||||
grid = input.GetClientSideObject().GetOutputDataObject(0)
|
||||
if grid.IsA('vtkMultiBlockDataSet'):
|
||||
writer = servermanager.writers.XMLMultiBlockDataWriter(Input=input)
|
||||
coprocessor.RegisterWriter(writer, filename=name+'_%t.vtm', freq=outputfrequency)
|
||||
|
||||
return Pipeline()
|
||||
|
||||
class CoProcessor(coprocessing.CoProcessor):
|
||||
def CreatePipeline(self, datadescription):
|
||||
self.Pipeline = _CreatePipeline(self, datadescription)
|
||||
|
||||
return CoProcessor()
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Global variables that will hold the pipeline for each timestep
|
||||
# Creating the CoProcessor object, doesn't actually create the ParaView pipeline.
|
||||
# It will be automatically setup when coprocessor.UpdateProducers() is called the
|
||||
# first time.
|
||||
coprocessor = CreateCoProcessor()
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Enable Live-Visualizaton with ParaView
|
||||
coprocessor.EnableLiveVisualization(False)
|
||||
|
||||
|
||||
# ---------------------- Data Selection method ----------------------
|
||||
|
||||
def RequestDataDescription(datadescription):
|
||||
"Callback to populate the request for current timestep"
|
||||
global coprocessor
|
||||
if datadescription.GetForceOutput() == True or datadescription.GetTimeStep() % outputfrequency == 0:
|
||||
# We are just going to request all fields and meshes from the simulation
|
||||
# code/adaptor.
|
||||
for i in range(datadescription.GetNumberOfInputDescriptions()):
|
||||
datadescription.GetInputDescription(i).AllFieldsOn()
|
||||
datadescription.GetInputDescription(i).GenerateMeshOn()
|
||||
return
|
||||
|
||||
# setup requests for all inputs based on the requirements of the
|
||||
# pipeline.
|
||||
coprocessor.LoadRequestedData(datadescription)
|
||||
|
||||
# ------------------------ Processing method ------------------------
|
||||
|
||||
def DoCoProcessing(datadescription):
|
||||
"Callback to do co-processing for current timestep"
|
||||
global coprocessor
|
||||
|
||||
# Update the coprocessor by providing it the newly generated simulation data.
|
||||
# If the pipeline hasn't been setup yet, this will setup the pipeline.
|
||||
coprocessor.UpdateProducers(datadescription)
|
||||
|
||||
# Write output data, if appropriate.
|
||||
coprocessor.WriteData(datadescription);
|
||||
|
||||
# Write image capture (Last arg: rescale lookup table), if appropriate.
|
||||
coprocessor.WriteImages(datadescription, rescale_lookuptable=False)
|
||||
|
||||
# Live Visualization, if enabled.
|
||||
coprocessor.DoLiveVisualization(datadescription, "localhost", 22222)
|
||||
78
etc/caseDicts/insitu/catalyst/writeMesh.py
Normal file
78
etc/caseDicts/insitu/catalyst/writeMesh.py
Normal file
@ -0,0 +1,78 @@
|
||||
from paraview.simple import *
|
||||
from paraview import coprocessing
|
||||
|
||||
# The frequency to output everything
|
||||
outputfrequency = 5
|
||||
|
||||
# As per writeAll, but only for "/mesh" sub-channels.
|
||||
|
||||
# ----------------------- CoProcessor definition -----------------------
|
||||
|
||||
def CreateCoProcessor():
|
||||
def _CreatePipeline(coprocessor, datadescription):
|
||||
class Pipeline:
|
||||
for i in range(datadescription.GetNumberOfInputDescriptions()):
|
||||
name = datadescription.GetInputDescriptionName(i)
|
||||
if not name.endswith('/mesh'):
|
||||
continue
|
||||
input = coprocessor.CreateProducer(datadescription, name)
|
||||
grid = input.GetClientSideObject().GetOutputDataObject(0)
|
||||
if grid.IsA('vtkMultiBlockDataSet'):
|
||||
writer = servermanager.writers.XMLMultiBlockDataWriter(Input=input)
|
||||
coprocessor.RegisterWriter(writer, filename=name+'_%t.vtm', freq=outputfrequency)
|
||||
|
||||
return Pipeline()
|
||||
|
||||
class CoProcessor(coprocessing.CoProcessor):
|
||||
def CreatePipeline(self, datadescription):
|
||||
self.Pipeline = _CreatePipeline(self, datadescription)
|
||||
|
||||
return CoProcessor()
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Global variables that will hold the pipeline for each timestep
|
||||
# Creating the CoProcessor object, doesn't actually create the ParaView pipeline.
|
||||
# It will be automatically setup when coprocessor.UpdateProducers() is called the
|
||||
# first time.
|
||||
coprocessor = CreateCoProcessor()
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Enable Live-Visualizaton with ParaView
|
||||
coprocessor.EnableLiveVisualization(False)
|
||||
|
||||
|
||||
# ---------------------- Data Selection method ----------------------
|
||||
|
||||
def RequestDataDescription(datadescription):
|
||||
"Callback to populate the request for current timestep"
|
||||
global coprocessor
|
||||
if datadescription.GetForceOutput() == True or datadescription.GetTimeStep() % outputfrequency == 0:
|
||||
# We are just going to request all fields and meshes from the simulation
|
||||
# code/adaptor.
|
||||
for i in range(datadescription.GetNumberOfInputDescriptions()):
|
||||
datadescription.GetInputDescription(i).AllFieldsOn()
|
||||
datadescription.GetInputDescription(i).GenerateMeshOn()
|
||||
return
|
||||
|
||||
# setup requests for all inputs based on the requirements of the
|
||||
# pipeline.
|
||||
coprocessor.LoadRequestedData(datadescription)
|
||||
|
||||
# ------------------------ Processing method ------------------------
|
||||
|
||||
def DoCoProcessing(datadescription):
|
||||
"Callback to do co-processing for current timestep"
|
||||
global coprocessor
|
||||
|
||||
# Update the coprocessor by providing it the newly generated simulation data.
|
||||
# If the pipeline hasn't been setup yet, this will setup the pipeline.
|
||||
coprocessor.UpdateProducers(datadescription)
|
||||
|
||||
# Write output data, if appropriate.
|
||||
coprocessor.WriteData(datadescription);
|
||||
|
||||
# Write image capture (Last arg: rescale lookup table), if appropriate.
|
||||
coprocessor.WriteImages(datadescription, rescale_lookuptable=False)
|
||||
|
||||
# Live Visualization, if enabled.
|
||||
coprocessor.DoLiveVisualization(datadescription, "localhost", 22222)
|
||||
78
etc/caseDicts/insitu/catalyst/writePatches.py
Normal file
78
etc/caseDicts/insitu/catalyst/writePatches.py
Normal file
@ -0,0 +1,78 @@
|
||||
from paraview.simple import *
|
||||
from paraview import coprocessing
|
||||
|
||||
# The frequency to output everything
|
||||
outputfrequency = 5
|
||||
|
||||
# As per writeAll, but only for "/patches" sub-channels.
|
||||
|
||||
# ----------------------- CoProcessor definition -----------------------
|
||||
|
||||
def CreateCoProcessor():
|
||||
def _CreatePipeline(coprocessor, datadescription):
|
||||
class Pipeline:
|
||||
for i in range(datadescription.GetNumberOfInputDescriptions()):
|
||||
name = datadescription.GetInputDescriptionName(i)
|
||||
if not name.endswith('/patches'):
|
||||
continue
|
||||
input = coprocessor.CreateProducer(datadescription, name)
|
||||
grid = input.GetClientSideObject().GetOutputDataObject(0)
|
||||
if grid.IsA('vtkMultiBlockDataSet'):
|
||||
writer = servermanager.writers.XMLMultiBlockDataWriter(Input=input)
|
||||
coprocessor.RegisterWriter(writer, filename=name+'_%t.vtm', freq=outputfrequency)
|
||||
|
||||
return Pipeline()
|
||||
|
||||
class CoProcessor(coprocessing.CoProcessor):
|
||||
def CreatePipeline(self, datadescription):
|
||||
self.Pipeline = _CreatePipeline(self, datadescription)
|
||||
|
||||
return CoProcessor()
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Global variables that will hold the pipeline for each timestep
|
||||
# Creating the CoProcessor object, doesn't actually create the ParaView pipeline.
|
||||
# It will be automatically setup when coprocessor.UpdateProducers() is called the
|
||||
# first time.
|
||||
coprocessor = CreateCoProcessor()
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Enable Live-Visualizaton with ParaView
|
||||
coprocessor.EnableLiveVisualization(False)
|
||||
|
||||
|
||||
# ---------------------- Data Selection method ----------------------
|
||||
|
||||
def RequestDataDescription(datadescription):
|
||||
"Callback to populate the request for current timestep"
|
||||
global coprocessor
|
||||
if datadescription.GetForceOutput() == True or datadescription.GetTimeStep() % outputfrequency == 0:
|
||||
# We are just going to request all fields and meshes from the simulation
|
||||
# code/adaptor.
|
||||
for i in range(datadescription.GetNumberOfInputDescriptions()):
|
||||
datadescription.GetInputDescription(i).AllFieldsOn()
|
||||
datadescription.GetInputDescription(i).GenerateMeshOn()
|
||||
return
|
||||
|
||||
# setup requests for all inputs based on the requirements of the
|
||||
# pipeline.
|
||||
coprocessor.LoadRequestedData(datadescription)
|
||||
|
||||
# ------------------------ Processing method ------------------------
|
||||
|
||||
def DoCoProcessing(datadescription):
|
||||
"Callback to do co-processing for current timestep"
|
||||
global coprocessor
|
||||
|
||||
# Update the coprocessor by providing it the newly generated simulation data.
|
||||
# If the pipeline hasn't been setup yet, this will setup the pipeline.
|
||||
coprocessor.UpdateProducers(datadescription)
|
||||
|
||||
# Write output data, if appropriate.
|
||||
coprocessor.WriteData(datadescription);
|
||||
|
||||
# Write image capture (Last arg: rescale lookup table), if appropriate.
|
||||
coprocessor.WriteImages(datadescription, rescale_lookuptable=False)
|
||||
|
||||
# Live Visualization, if enabled.
|
||||
coprocessor.DoLiveVisualization(datadescription, "localhost", 22222)
|
||||
@ -13,8 +13,8 @@
|
||||
# config.csh/example/paraview
|
||||
#
|
||||
# Description
|
||||
# Example of defining a different ParaView_VERSION but retaining
|
||||
# the standard config.csh/paraview mechanism
|
||||
# Example of defining a different ParaView_VERSION but retaining the
|
||||
# standard config.csh/paraview mechanism
|
||||
#
|
||||
# Note
|
||||
# This file could be copied to a user or site location, but should never
|
||||
@ -25,7 +25,8 @@
|
||||
|
||||
set pv=5.5.0
|
||||
set pv=5.5.0-mpipy
|
||||
set qt=qt-5.9.0
|
||||
|
||||
eval `foamEtcFile -csh -config -mode=o paraview -- ParaView_VERSION=$pv`
|
||||
eval `foamEtcFile -csh -config -mode=o paraview -- ParaView_VERSION=$pv ParaView_QT=$qt`
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -120,8 +120,16 @@ if ( $?ParaView_VERSION ) then
|
||||
#OBSOLETE? endif
|
||||
|
||||
# QT libraries as required
|
||||
# Set Qt5_DIR to root directory.
|
||||
# Another possibility: "qtpaths --qt-version"
|
||||
|
||||
set qtDir="$archDir/$ParaView_QT"
|
||||
if ( -d "$qtDir" ) then
|
||||
switch ($ParaView_QT)
|
||||
case *-qt*:
|
||||
setenv Qt5_DIR $qtDir
|
||||
breaksw
|
||||
endsw
|
||||
foreach qtLibDir ("$qtDir/lib$WM_COMPILER_LIB_ARCH" "$qtDir/lib")
|
||||
if ( -d "$qtLibDir" ) then
|
||||
setenv LD_LIBRARY_PATH "${qtLibDir}:${LD_LIBRARY_PATH}"
|
||||
|
||||
@ -111,6 +111,7 @@ unsetenv ParaView_INCLUDE_DIR
|
||||
unsetenv ParaView_VERSION
|
||||
unsetenv PV_PLUGIN_PATH
|
||||
unsetenv VTK_DIR
|
||||
unsetenv Qt5_DIR # Perhaps only unset if it is in WM_THIRD_PARTY_DIR?
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Unset other ThirdParty environment variables
|
||||
|
||||
@ -13,8 +13,8 @@
|
||||
# config.sh/example/paraview
|
||||
#
|
||||
# Description
|
||||
# Example of defining a different ParaView_VERSION but retaining
|
||||
# the standard config.sh/paraview mechanism
|
||||
# Example of defining a different ParaView_VERSION but retaining the
|
||||
# standard config.sh/paraview mechanism
|
||||
#
|
||||
# Note
|
||||
# This file could be copied to a user or site location, but should never
|
||||
@ -25,7 +25,8 @@
|
||||
|
||||
pv=5.5.0
|
||||
pv=5.5.0-mpipy
|
||||
qt=qt-5.9.0
|
||||
|
||||
eval $(foamEtcFile -sh -config -mode=o paraview -- ParaView_VERSION=$pv)
|
||||
eval $(foamEtcFile -sh -config -mode=o paraview -- ParaView_VERSION=$pv ParaView_QT=$qt)
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -127,10 +127,16 @@ then
|
||||
#OBSOLETE? export PYTHONPATH=$PYTHONPATH:${PYTHONPATH:+:}$pvPython:$pvLibDir
|
||||
#OBSOLETE? fi
|
||||
|
||||
# QT libraries as required
|
||||
# QT libraries as required, and Qt5_DIR for the root directory.
|
||||
# Another possibility: "qtpaths --qt-version"
|
||||
qtDir="$archDir/$ParaView_QT"
|
||||
if [ -d "$qtDir" ]
|
||||
then
|
||||
case "$ParaView_QT" in
|
||||
*-5*)
|
||||
export Qt5_DIR=$qtDir
|
||||
;;
|
||||
esac
|
||||
for qtLibDir in $qtDir/lib$WM_COMPILER_LIB_ARCH $qtDir/lib
|
||||
do
|
||||
if [ -d "$qtLibDir" ]
|
||||
|
||||
@ -97,7 +97,6 @@ then
|
||||
unset OPAL_PREFIX
|
||||
fi
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Unset Ensight/ParaView-related environment variables
|
||||
|
||||
@ -108,6 +107,12 @@ unset ParaView_VERSION
|
||||
unset PV_PLUGIN_PATH
|
||||
unset VTK_DIR
|
||||
|
||||
# Undefine Qt5_DIR if set to one of the paths on foamOldDirs
|
||||
if [ -z "$($foamClean -env=Qt5_DIR "$foamOldDirs")" ]
|
||||
then
|
||||
unset Qt5_DIR
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Unset other ThirdParty environment variables
|
||||
|
||||
|
||||
@ -39,8 +39,8 @@ InfoSwitches
|
||||
writeDictionaries 0;
|
||||
writeOptionalEntries 0;
|
||||
|
||||
// Write lagrangian "positions" file in v1706 format (at earlier)
|
||||
writeLagrangianPositions 0;
|
||||
// Write lagrangian "positions" file in v1706 format (and earlier)
|
||||
writeLagrangianPositions 1;
|
||||
|
||||
// Report hosts used (parallel)
|
||||
// - 0 = none
|
||||
|
||||
Submodule modules/avalanche updated: 99e68179fa...6e6e105844
Submodule modules/catalyst updated: 3c0a2e7959...5828d45108
Submodule modules/cfmesh updated: 8f6e65ae7c...288f05e08f
@ -489,6 +489,10 @@ mode_t Foam::mode(const fileName& name, const bool followLink)
|
||||
if (POSIX::debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME << " : name:" << name << endl;
|
||||
if ((POSIX::debug & 2) && !Pstream::master())
|
||||
{
|
||||
error::printStack(Pout);
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore an empty name => always 0
|
||||
@ -516,10 +520,6 @@ Foam::fileName::Type Foam::type(const fileName& name, const bool followLink)
|
||||
if (POSIX::debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME << " : name:" << name << endl;
|
||||
if ((POSIX::debug & 2) && !Pstream::master())
|
||||
{
|
||||
error::printStack(Pout);
|
||||
}
|
||||
}
|
||||
|
||||
mode_t m = mode(name, followLink);
|
||||
@ -1678,142 +1678,4 @@ Foam::fileNameList Foam::dlLoaded()
|
||||
}
|
||||
|
||||
|
||||
static Foam::DynamicList<Foam::autoPtr<pthread_t>> threads_;
|
||||
static Foam::DynamicList<Foam::autoPtr<pthread_mutex_t>> mutexes_;
|
||||
|
||||
Foam::label Foam::allocateThread()
|
||||
{
|
||||
forAll(threads_, i)
|
||||
{
|
||||
if (!threads_[i].valid())
|
||||
{
|
||||
if (POSIX::debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME << " : reusing index:" << i << endl;
|
||||
}
|
||||
// Reuse entry
|
||||
threads_[i].reset(new pthread_t());
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
const label index = threads_.size();
|
||||
if (POSIX::debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME << " : new index:" << index << endl;
|
||||
}
|
||||
threads_.append(autoPtr<pthread_t>(new pthread_t()));
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
void Foam::createThread
|
||||
(
|
||||
const label index,
|
||||
void *(*start_routine) (void *),
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
if (POSIX::debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME << " : index:" << index << endl;
|
||||
}
|
||||
if (pthread_create(&threads_[index](), nullptr, start_routine, arg))
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Failed starting thread " << index << exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::joinThread(const label index)
|
||||
{
|
||||
if (POSIX::debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME << " : index:" << index << endl;
|
||||
}
|
||||
if (pthread_join(threads_[index](), nullptr))
|
||||
{
|
||||
FatalErrorInFunction << "Failed joining thread " << index
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::freeThread(const label index)
|
||||
{
|
||||
if (POSIX::debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME << " : index:" << index << endl;
|
||||
}
|
||||
threads_[index].clear();
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::allocateMutex()
|
||||
{
|
||||
forAll(mutexes_, i)
|
||||
{
|
||||
if (!mutexes_[i].valid())
|
||||
{
|
||||
if (POSIX::debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME << " : reusing index:" << i << endl;
|
||||
}
|
||||
// Reuse entry
|
||||
mutexes_[i].reset(new pthread_mutex_t());
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
const label index = mutexes_.size();
|
||||
|
||||
if (POSIX::debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME << " : new index:" << index << endl;
|
||||
}
|
||||
mutexes_.append(autoPtr<pthread_mutex_t>(new pthread_mutex_t()));
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
void Foam::lockMutex(const label index)
|
||||
{
|
||||
if (POSIX::debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME << " : index:" << index << endl;
|
||||
}
|
||||
if (pthread_mutex_lock(&mutexes_[index]()))
|
||||
{
|
||||
FatalErrorInFunction << "Failed locking mutex " << index
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::unlockMutex(const label index)
|
||||
{
|
||||
if (POSIX::debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME << " : index:" << index << endl;
|
||||
}
|
||||
if (pthread_mutex_unlock(&mutexes_[index]()))
|
||||
{
|
||||
FatalErrorInFunction << "Failed unlocking mutex " << index
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::freeMutex(const label index)
|
||||
{
|
||||
if (POSIX::debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME << " : index:" << index << endl;
|
||||
}
|
||||
mutexes_[index].clear();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -11,9 +11,11 @@ global/etcFiles/etcFiles.C
|
||||
|
||||
fileOps = global/fileOperations
|
||||
$(fileOps)/fileOperation/fileOperation.C
|
||||
$(fileOps)/fileOperationInitialise/fileOperationInitialise.C
|
||||
$(fileOps)/uncollatedFileOperation/uncollatedFileOperation.C
|
||||
$(fileOps)/masterUncollatedFileOperation/masterUncollatedFileOperation.C
|
||||
$(fileOps)/collatedFileOperation/collatedFileOperation.C
|
||||
$(fileOps)/collatedFileOperation/hostCollatedFileOperation.C
|
||||
$(fileOps)/collatedFileOperation/threadedCollatedOFstream.C
|
||||
$(fileOps)/collatedFileOperation/OFstreamCollator.C
|
||||
|
||||
@ -288,7 +290,6 @@ $(Time)/TimeIO.C
|
||||
$(Time)/findTimes.C
|
||||
$(Time)/subCycleTime.C
|
||||
$(Time)/subLoopTime.C
|
||||
$(Time)/findInstance.C
|
||||
$(Time)/timeSelector.C
|
||||
|
||||
$(Time)/instant/instant.C
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -681,14 +681,15 @@ void Foam::decomposedBlockData::gather
|
||||
|
||||
List<int> recvOffsets;
|
||||
List<int> recvSizes;
|
||||
if (UPstream::master())
|
||||
if (UPstream::master(comm))
|
||||
{
|
||||
recvOffsets.setSize(nProcs);
|
||||
forAll(recvOffsets, proci)
|
||||
{
|
||||
// Note: truncating long int to int since UPstream::gather limited
|
||||
// to ints
|
||||
recvOffsets[proci] =
|
||||
reinterpret_cast<char*>(&datas[proci])
|
||||
- data0Ptr;
|
||||
int(reinterpret_cast<char*>(&datas[proci]) - data0Ptr);
|
||||
}
|
||||
recvSizes.setSize(nProcs, sizeof(label));
|
||||
}
|
||||
@ -748,7 +749,8 @@ void Foam::decomposedBlockData::gatherSlaveData
|
||||
&& (UPstream::myProcNo(comm) < startProc+nProcs)
|
||||
)
|
||||
{
|
||||
nSend = data.byteSize();
|
||||
// Note: UPstream::gather limited to int
|
||||
nSend = int(data.byteSize());
|
||||
}
|
||||
|
||||
UPstream::gather
|
||||
@ -764,6 +766,46 @@ void Foam::decomposedBlockData::gatherSlaveData
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::decomposedBlockData::calcNumProcs
|
||||
(
|
||||
const label comm,
|
||||
const off_t maxBufferSize,
|
||||
const labelUList& recvSizes,
|
||||
const label startProci
|
||||
)
|
||||
{
|
||||
const label nProcs = UPstream::nProcs(comm);
|
||||
|
||||
label nSendProcs = -1;
|
||||
if (UPstream::master(comm))
|
||||
{
|
||||
off_t totalSize = recvSizes[startProci];
|
||||
label proci = startProci+1;
|
||||
while (proci < nProcs && (totalSize+recvSizes[proci] < maxBufferSize))
|
||||
{
|
||||
totalSize += recvSizes[proci];
|
||||
proci++;
|
||||
}
|
||||
|
||||
nSendProcs = proci-startProci;
|
||||
}
|
||||
|
||||
// Scatter nSendProcs
|
||||
label n;
|
||||
UPstream::scatter
|
||||
(
|
||||
reinterpret_cast<const char*>(&nSendProcs),
|
||||
List<int>(nProcs, sizeof(nSendProcs)),
|
||||
List<int>(nProcs, 0),
|
||||
reinterpret_cast<char*>(&n),
|
||||
sizeof(n),
|
||||
comm
|
||||
);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::decomposedBlockData::writeBlocks
|
||||
(
|
||||
const label comm,
|
||||
@ -772,8 +814,7 @@ bool Foam::decomposedBlockData::writeBlocks
|
||||
const UList<char>& data,
|
||||
|
||||
const labelUList& recvSizes,
|
||||
const bool haveSlaveData,
|
||||
const List<char>& slaveData,
|
||||
const PtrList<SubList<char>>& slaveData,
|
||||
|
||||
const UPstream::commsTypes commsType,
|
||||
const bool syncReturnState
|
||||
@ -784,17 +825,15 @@ bool Foam::decomposedBlockData::writeBlocks
|
||||
Pout<< "decomposedBlockData::writeBlocks:"
|
||||
<< " stream:" << (osPtr.valid() ? osPtr().name() : "invalid")
|
||||
<< " data:" << data.size()
|
||||
<< " haveSlaveData:" << haveSlaveData
|
||||
<< " (master only) slaveData:" << slaveData.size()
|
||||
<< " commsType:" << Pstream::commsTypeNames[commsType] << endl;
|
||||
}
|
||||
|
||||
const label nProcs = UPstream::nProcs(comm);
|
||||
|
||||
|
||||
bool ok = true;
|
||||
|
||||
if (haveSlaveData)
|
||||
if (slaveData.size())
|
||||
{
|
||||
// Already have gathered the slave data. communicator only used to
|
||||
// check who is the master
|
||||
@ -821,8 +860,7 @@ bool Foam::decomposedBlockData::writeBlocks
|
||||
os << nl << nl << "// Processor" << proci << nl;
|
||||
start[proci] = os.stdStream().tellp();
|
||||
|
||||
os << SubList<char>(slaveData, recvSizes[proci], slaveOffset);
|
||||
|
||||
os << slaveData[proci];
|
||||
slaveOffset += recvSizes[proci];
|
||||
}
|
||||
|
||||
@ -897,44 +935,24 @@ bool Foam::decomposedBlockData::writeBlocks
|
||||
// maxMasterFileBufferSize
|
||||
|
||||
// Starting slave processor and number of processors
|
||||
labelPair startAndSize(1, nProcs-1);
|
||||
label startProc = 1;
|
||||
label nSendProcs = nProcs-1;
|
||||
|
||||
while (startAndSize[1] > 0)
|
||||
while (nSendProcs > 0)
|
||||
{
|
||||
labelPair masterData(startAndSize);
|
||||
if (UPstream::master(comm))
|
||||
{
|
||||
label totalSize = recvSizes[masterData[0]];
|
||||
label proci = masterData[0]+1;
|
||||
while
|
||||
(
|
||||
proci < nProcs
|
||||
&& (
|
||||
totalSize+recvSizes[proci]
|
||||
< fileOperations::masterUncollatedFileOperation::
|
||||
maxMasterFileBufferSize
|
||||
)
|
||||
)
|
||||
{
|
||||
totalSize += recvSizes[proci];
|
||||
++proci;
|
||||
}
|
||||
|
||||
masterData[1] = proci-masterData[0];
|
||||
}
|
||||
|
||||
// Scatter masterData
|
||||
UPstream::scatter
|
||||
nSendProcs = calcNumProcs
|
||||
(
|
||||
reinterpret_cast<const char*>(masterData.cdata()),
|
||||
List<int>(nProcs, sizeof(masterData)),
|
||||
List<int>(nProcs, 0),
|
||||
reinterpret_cast<char*>(startAndSize.data()),
|
||||
sizeof(startAndSize),
|
||||
comm
|
||||
comm,
|
||||
off_t
|
||||
(
|
||||
fileOperations::masterUncollatedFileOperation::
|
||||
maxMasterFileBufferSize
|
||||
),
|
||||
recvSizes,
|
||||
startProc
|
||||
);
|
||||
|
||||
if (startAndSize[0] == nProcs || startAndSize[1] == 0)
|
||||
if (startProc == nProcs || nSendProcs == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -949,8 +967,8 @@ bool Foam::decomposedBlockData::writeBlocks
|
||||
data,
|
||||
recvSizes,
|
||||
|
||||
startAndSize[0], // startProc,
|
||||
startAndSize[1], // nProcs,
|
||||
startProc, // startProc,
|
||||
nSendProcs, // nProcs,
|
||||
|
||||
sliceOffsets,
|
||||
recvData
|
||||
@ -963,9 +981,9 @@ bool Foam::decomposedBlockData::writeBlocks
|
||||
// Write slaves
|
||||
for
|
||||
(
|
||||
label proci = startAndSize[0];
|
||||
proci < startAndSize[0]+startAndSize[1];
|
||||
++proci
|
||||
label proci = startProc;
|
||||
proci < startProc+nSendProcs;
|
||||
proci++
|
||||
)
|
||||
{
|
||||
os << nl << nl << "// Processor" << proci << nl;
|
||||
@ -981,7 +999,7 @@ bool Foam::decomposedBlockData::writeBlocks
|
||||
}
|
||||
}
|
||||
|
||||
startAndSize[0] += startAndSize[1];
|
||||
startProc += nSendProcs;
|
||||
}
|
||||
|
||||
if (UPstream::master(comm))
|
||||
@ -1027,7 +1045,7 @@ bool Foam::decomposedBlockData::writeData(Ostream& os) const
|
||||
);
|
||||
|
||||
IOobject io(*this);
|
||||
if (Pstream::master())
|
||||
if (Pstream::master(comm_))
|
||||
{
|
||||
IStringStream is
|
||||
(
|
||||
@ -1043,7 +1061,7 @@ bool Foam::decomposedBlockData::writeData(Ostream& os) const
|
||||
|
||||
// version
|
||||
string versionString(os.version().str());
|
||||
Pstream::scatter(versionString);
|
||||
Pstream::scatter(versionString, Pstream::msgType(), comm_);
|
||||
|
||||
// stream
|
||||
string formatString;
|
||||
@ -1051,21 +1069,21 @@ bool Foam::decomposedBlockData::writeData(Ostream& os) const
|
||||
OStringStream os;
|
||||
os << os.format();
|
||||
formatString = os.str();
|
||||
Pstream::scatter(formatString);
|
||||
Pstream::scatter(formatString, Pstream::msgType(), comm_);
|
||||
}
|
||||
|
||||
//word masterName(name());
|
||||
//Pstream::scatter(masterName);
|
||||
//Pstream::scatter(masterName, Pstream::msgType(), comm_);
|
||||
|
||||
Pstream::scatter(io.headerClassName());
|
||||
Pstream::scatter(io.note());
|
||||
Pstream::scatter(io.headerClassName(), Pstream::msgType(), comm_);
|
||||
Pstream::scatter(io.note(), Pstream::msgType(), comm_);
|
||||
//Pstream::scatter(io.instance(), Pstream::msgType(), comm);
|
||||
//Pstream::scatter(io.local(), Pstream::msgType(), comm);
|
||||
|
||||
fileName masterLocation(instance()/db().dbDir()/local());
|
||||
Pstream::scatter(masterLocation);
|
||||
Pstream::scatter(masterLocation, Pstream::msgType(), comm_);
|
||||
|
||||
if (!Pstream::master())
|
||||
if (!Pstream::master(comm_))
|
||||
{
|
||||
writeHeader
|
||||
(
|
||||
@ -1081,7 +1099,7 @@ bool Foam::decomposedBlockData::writeData(Ostream& os) const
|
||||
|
||||
os.writeQuoted(str, false);
|
||||
|
||||
if (!Pstream::master())
|
||||
if (!Pstream::master(comm_))
|
||||
{
|
||||
IOobject::writeEndDivider(os);
|
||||
}
|
||||
@ -1108,10 +1126,10 @@ bool Foam::decomposedBlockData::writeObject
|
||||
}
|
||||
|
||||
labelList recvSizes;
|
||||
gather(comm_, this->byteSize(), recvSizes);
|
||||
gather(comm_, label(this->byteSize()), recvSizes);
|
||||
|
||||
List<std::streamoff> start;
|
||||
List<char> slaveData; // dummy already received slave data
|
||||
PtrList<SubList<char>> slaveData; // dummy slave data
|
||||
return writeBlocks
|
||||
(
|
||||
comm_,
|
||||
@ -1119,7 +1137,6 @@ bool Foam::decomposedBlockData::writeObject
|
||||
start,
|
||||
*this,
|
||||
recvSizes,
|
||||
false, // don't have slave data
|
||||
slaveData,
|
||||
commsType_
|
||||
);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -66,6 +66,16 @@ protected:
|
||||
|
||||
// Protected member functions
|
||||
|
||||
//- Helper: determine number of processors whose recvSizes fits
|
||||
// ito maxBufferSize
|
||||
static label calcNumProcs
|
||||
(
|
||||
const label comm,
|
||||
const off_t maxBufferSize,
|
||||
const labelUList& recvSizes,
|
||||
const label startProci
|
||||
);
|
||||
|
||||
//- Read data into *this. ISstream is only valid on master.
|
||||
static bool readBlocks
|
||||
(
|
||||
@ -202,12 +212,12 @@ public:
|
||||
const label comm,
|
||||
autoPtr<OSstream>& osPtr,
|
||||
List<std::streamoff>& start,
|
||||
const UList<char>&,
|
||||
const UList<char>& masterData,
|
||||
|
||||
const labelUList& recvSizes,
|
||||
|
||||
const bool haveSlaveData, // does master have slaveData
|
||||
const List<char>& slaveData, // optional slave data (on master)
|
||||
// optional slave data (on master)
|
||||
const PtrList<SubList<char>>& slaveData,
|
||||
|
||||
const UPstream::commsTypes,
|
||||
const bool syncReturnState = true
|
||||
|
||||
@ -372,10 +372,8 @@ public:
|
||||
static void addValidParOptions(HashTable<string>& validParOptions);
|
||||
|
||||
//- Initialisation function called from main
|
||||
// Spawns slave processes and initialises inter-communication.
|
||||
// \note warns if MPI has already been initialized.
|
||||
// Fatal if MPI has already been finalized.
|
||||
static bool init(int& argc, char**& argv);
|
||||
// Spawns slave processes and initialises inter-communication
|
||||
static bool init(int& argc, char**& argv, const bool needsThread);
|
||||
|
||||
//- Special purpose initialisation function.
|
||||
// Performs a basic MPI_Init without any other setup.
|
||||
|
||||
@ -714,6 +714,36 @@ Foam::instantList Foam::Time::times() const
|
||||
}
|
||||
|
||||
|
||||
Foam::word Foam::Time::findInstance
|
||||
(
|
||||
const fileName& dir,
|
||||
const word& name,
|
||||
const IOobject::readOption rOpt,
|
||||
const word& stopInstance
|
||||
) const
|
||||
{
|
||||
IOobject startIO
|
||||
(
|
||||
name, // name might be empty!
|
||||
timeName(),
|
||||
dir,
|
||||
*this,
|
||||
rOpt
|
||||
);
|
||||
|
||||
IOobject io
|
||||
(
|
||||
fileHandler().findInstance
|
||||
(
|
||||
startIO,
|
||||
timeOutputValue(),
|
||||
stopInstance
|
||||
)
|
||||
);
|
||||
return io.instance();
|
||||
}
|
||||
|
||||
|
||||
Foam::word Foam::Time::findInstancePath
|
||||
(
|
||||
const fileName& directory,
|
||||
|
||||
@ -196,9 +196,6 @@ protected:
|
||||
//- Read the control dictionary and set the write controls etc.
|
||||
virtual void readDict();
|
||||
|
||||
//- Find IOobject in the objectPath
|
||||
static bool exists(IOobject& io);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@ -1,236 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Description
|
||||
If "name" is empty: return the location of "directory"
|
||||
If "name" is not empty: return the location of "directory" containing the
|
||||
file "name".
|
||||
Used in reading mesh data.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "Time.H"
|
||||
#include "IOobject.H"
|
||||
#include "IOList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::Time::exists(IOobject& io)
|
||||
{
|
||||
// Generate filename for object
|
||||
fileName objPath(fileHandler().objectPath(io, word::null));
|
||||
|
||||
// Test for either directory or a (valid) file & IOobject
|
||||
bool ok;
|
||||
if (io.name().empty())
|
||||
{
|
||||
ok = fileHandler().isDir(objPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
ok =
|
||||
fileHandler().isFile(objPath)
|
||||
&& io.typeHeaderOk<IOList<label>>(false);// object with local scope
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
// Re-test with raw objectPath. This is for backwards
|
||||
// compatibility
|
||||
fileName originalPath(io.objectPath());
|
||||
if (originalPath != objPath)
|
||||
{
|
||||
// Test for either directory or a (valid) file & IOobject
|
||||
if (io.name().empty())
|
||||
{
|
||||
ok = fileHandler().isDir(originalPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
ok =
|
||||
fileHandler().isFile(originalPath)
|
||||
&& io.typeHeaderOk<IOList<label>>(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
Foam::word Foam::Time::findInstance
|
||||
(
|
||||
const fileName& dir,
|
||||
const word& name,
|
||||
const IOobject::readOption rOpt,
|
||||
const word& stopInstance
|
||||
) const
|
||||
{
|
||||
// Note: - if name is empty, just check the directory itself
|
||||
// - check both for isFile and headerOk since the latter does a
|
||||
// filePath so searches for the file.
|
||||
// - check for an object with local file scope (so no looking up in
|
||||
// parent directory in case of parallel)
|
||||
|
||||
{
|
||||
IOobject io
|
||||
(
|
||||
name, // name might be empty!
|
||||
timeName(),
|
||||
dir,
|
||||
*this
|
||||
);
|
||||
|
||||
if (exists(io))
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction
|
||||
<< "Found exact match for \"" << name
|
||||
<< "\" in " << timeName()/dir
|
||||
<< endl;
|
||||
}
|
||||
|
||||
return timeName();
|
||||
}
|
||||
}
|
||||
|
||||
// Search back through the time directories to find the time
|
||||
// closest to and lower than current time
|
||||
|
||||
instantList ts = times();
|
||||
label instanceI;
|
||||
|
||||
for (instanceI = ts.size()-1; instanceI >= 0; --instanceI)
|
||||
{
|
||||
if (ts[instanceI].value() <= timeOutputValue())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// continue searching from here
|
||||
for (; instanceI >= 0; --instanceI)
|
||||
{
|
||||
IOobject io
|
||||
(
|
||||
name, // name might be empty!
|
||||
ts[instanceI].name(),
|
||||
dir,
|
||||
*this
|
||||
);
|
||||
|
||||
if (exists(io))
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction
|
||||
<< "Found instance match for \"" << name
|
||||
<< "\" in " << ts[instanceI].name()/dir
|
||||
<< endl;
|
||||
}
|
||||
|
||||
return ts[instanceI].name();
|
||||
}
|
||||
|
||||
// Check if hit minimum instance
|
||||
if (ts[instanceI].name() == stopInstance)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
//InfoInFunction
|
||||
Pout<< "findInstance : "
|
||||
<< "Hit stopInstance " << stopInstance
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
rOpt == IOobject::MUST_READ
|
||||
|| rOpt == IOobject::MUST_READ_IF_MODIFIED
|
||||
)
|
||||
{
|
||||
if (name.empty())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot find directory "
|
||||
<< dir << " in times " << timeName()
|
||||
<< " down to " << stopInstance
|
||||
<< exit(FatalError);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot find file \"" << name << "\" in directory "
|
||||
<< dir << " in times " << timeName()
|
||||
<< " down to " << stopInstance
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
return ts[instanceI].name();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// not in any of the time directories, try constant
|
||||
|
||||
// Note. This needs to be a hard-coded constant, rather than the
|
||||
// constant function of the time, because the latter points to
|
||||
// the case constant directory in parallel cases
|
||||
|
||||
IOobject io
|
||||
(
|
||||
name,
|
||||
constant(),
|
||||
dir,
|
||||
*this
|
||||
);
|
||||
|
||||
if (exists(io))
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction
|
||||
<< "Found constant match for \"" << name
|
||||
<< "\" in " << constant()/dir
|
||||
<< endl;
|
||||
}
|
||||
|
||||
return constant();
|
||||
}
|
||||
|
||||
if (rOpt == IOobject::MUST_READ || rOpt == IOobject::MUST_READ_IF_MODIFIED)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot find file \"" << name << "\" in directory "
|
||||
<< dir << " in times " << timeName()
|
||||
<< " down to " << constant()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
return constant();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -236,7 +236,7 @@ void Foam::error::exit(const int errNo)
|
||||
{
|
||||
Perr<< endl << *this << endl
|
||||
<< "\nFOAM exiting\n" << endl;
|
||||
::exit(1);
|
||||
::exit(errNo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation | Copyright (C) 2015-2016 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -183,7 +183,8 @@ void Foam::regIOobject::close()
|
||||
if (IFstream::debug)
|
||||
{
|
||||
Pout<< "regIOobject::close() : "
|
||||
<< "finished reading " << isPtr_().name()
|
||||
<< "finished reading "
|
||||
<< (isPtr_.valid() ? isPtr_().name() : "dummy")
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2013-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -54,7 +54,7 @@ public:
|
||||
// Constructors
|
||||
|
||||
//- Construct given addressing
|
||||
patchFieldSubset(const labelUList& directAddressing)
|
||||
directFieldMapper(const labelUList& directAddressing)
|
||||
:
|
||||
directAddressing_(directAddressing),
|
||||
hasUnmapped_(false)
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -86,6 +86,7 @@ void pow
|
||||
gf.oriented() = pow(gf1.oriented(), r);
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
class Type,
|
||||
@ -181,6 +182,7 @@ void sqr
|
||||
gf.oriented() = sqr(gf1.oriented());
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
tmp
|
||||
<
|
||||
@ -217,6 +219,7 @@ sqr(const GeometricField<Type, PatchField, GeoMesh>& gf)
|
||||
return tSqr;
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
tmp
|
||||
<
|
||||
@ -270,6 +273,7 @@ void magSqr
|
||||
gsf.oriented() = magSqr(gf.oriented());
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
tmp<GeometricField<scalar, PatchField, GeoMesh>> magSqr
|
||||
(
|
||||
@ -343,6 +347,7 @@ void mag
|
||||
gsf.oriented() = mag(gf.oriented());
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
tmp<GeometricField<scalar, PatchField, GeoMesh>> mag
|
||||
(
|
||||
@ -458,6 +463,7 @@ cmptAv(const GeometricField<Type, PatchField, GeoMesh>& gf)
|
||||
return CmptAv;
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
tmp
|
||||
<
|
||||
@ -500,7 +506,7 @@ cmptAv(const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf)
|
||||
}
|
||||
|
||||
|
||||
#define UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(returnType, func, gFunc) \
|
||||
#define UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(returnType, func, binaryOp) \
|
||||
\
|
||||
template<class Type, template<class> class PatchField, class GeoMesh> \
|
||||
dimensioned<returnType> func \
|
||||
@ -512,7 +518,15 @@ dimensioned<returnType> func \
|
||||
( \
|
||||
#func "(" + gf.name() + ')', \
|
||||
gf.dimensions(), \
|
||||
Foam::func(gFunc(gf.primitiveField()), gFunc(gf.boundaryField())) \
|
||||
returnReduce \
|
||||
( \
|
||||
Foam::func \
|
||||
( \
|
||||
Foam::func(gf.primitiveField()), \
|
||||
Foam::func(gf.boundaryField()) \
|
||||
), \
|
||||
binaryOp<Type>() \
|
||||
) \
|
||||
); \
|
||||
} \
|
||||
\
|
||||
@ -527,8 +541,8 @@ dimensioned<returnType> func \
|
||||
return res; \
|
||||
}
|
||||
|
||||
UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(Type, max, gMax)
|
||||
UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(Type, min, gMin)
|
||||
UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(Type, max, maxOp)
|
||||
UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(Type, min, minOp)
|
||||
|
||||
#undef UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -212,7 +212,7 @@ tmp
|
||||
cmptAv(const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf);
|
||||
|
||||
|
||||
#define UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(returnType, func, gFunc) \
|
||||
#define UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(returnType, func, binaryOp) \
|
||||
\
|
||||
template<class Type, template<class> class PatchField, class GeoMesh> \
|
||||
dimensioned<returnType> func \
|
||||
@ -226,8 +226,8 @@ dimensioned<returnType> func \
|
||||
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf1 \
|
||||
);
|
||||
|
||||
UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(Type, max, gMax)
|
||||
UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(Type, min, gMin)
|
||||
UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(Type, max, maxOp)
|
||||
UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(Type, min, minOp)
|
||||
|
||||
#undef UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY
|
||||
|
||||
|
||||
@ -40,8 +40,9 @@ License
|
||||
#include "foamVersion.H"
|
||||
#include "stringOps.H"
|
||||
#include "CStringList.H"
|
||||
#include "uncollatedFileOperation.H"
|
||||
#include "masterUncollatedFileOperation.H"
|
||||
#include "stringListOps.H"
|
||||
#include "fileOperation.H"
|
||||
#include "fileOperationInitialise.H"
|
||||
#include "IOmanip.H"
|
||||
|
||||
#include <cctype>
|
||||
@ -83,6 +84,12 @@ Foam::argList::initValidTables::initValidTables()
|
||||
"decomposeParDict", "file",
|
||||
"read decomposePar dictionary from specified location"
|
||||
);
|
||||
argList::addOption
|
||||
(
|
||||
"hostRoots", "(((host1 dir1) .. (hostN dirN))",
|
||||
"slave root directories (per host) for distributed running"
|
||||
);
|
||||
validParOptions.set("hostRoots", "((host1 dir1) .. (hostN dirN))");
|
||||
|
||||
argList::addBoolOption
|
||||
(
|
||||
@ -324,6 +331,7 @@ void Foam::argList::noParallel()
|
||||
removeOption("parallel");
|
||||
removeOption("roots");
|
||||
removeOption("decomposeParDict");
|
||||
removeOption("hostRoots");
|
||||
validParOptions.clear();
|
||||
}
|
||||
|
||||
@ -687,6 +695,34 @@ Foam::argList::argList
|
||||
options_(argc),
|
||||
distributed_(false)
|
||||
{
|
||||
// Check for fileHandler
|
||||
word handlerType(getEnv("FOAM_FILEHANDLER"));
|
||||
for (int argI = 0; argI < argc; ++argI)
|
||||
{
|
||||
if (argv[argI][0] == '-')
|
||||
{
|
||||
const char *optionName = &argv[argI][1];
|
||||
if (string(optionName) == "fileHandler")
|
||||
{
|
||||
handlerType = argv[argI+1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (handlerType.empty())
|
||||
{
|
||||
handlerType = fileOperation::defaultFileHandler;
|
||||
}
|
||||
|
||||
// Detect any parallel options
|
||||
bool needsThread = fileOperations::fileOperationInitialise::New
|
||||
(
|
||||
handlerType,
|
||||
argc,
|
||||
argv
|
||||
)().needsThreading();
|
||||
|
||||
|
||||
// Check if this run is a parallel run by searching for any parallel option
|
||||
// If found call runPar which might filter argv
|
||||
for (int argi = 1; argi < argc; ++argi)
|
||||
@ -697,7 +733,7 @@ Foam::argList::argList
|
||||
|
||||
if (validParOptions.found(optName))
|
||||
{
|
||||
parRunControl_.runPar(argc, argv);
|
||||
parRunControl_.runPar(argc, argv, needsThread);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -942,6 +978,58 @@ void Foam::argList::parse
|
||||
Foam::fileHandler(handler);
|
||||
}
|
||||
|
||||
|
||||
stringList slaveProcs;
|
||||
stringList slaveMachine;
|
||||
const int writeHostsSwitch = debug::infoSwitch("writeHosts", 1);
|
||||
|
||||
// Collect slave machine/pid, and check that the build is identical
|
||||
if (parRunControl_.parRun())
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
slaveProcs.setSize(Pstream::nProcs() - 1);
|
||||
slaveMachine.setSize(Pstream::nProcs() - 1);
|
||||
label proci = 0;
|
||||
for
|
||||
(
|
||||
int slave = Pstream::firstSlave();
|
||||
slave <= Pstream::lastSlave();
|
||||
slave++
|
||||
)
|
||||
{
|
||||
IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
|
||||
|
||||
string slaveBuild;
|
||||
label slavePid;
|
||||
fromSlave >> slaveBuild >> slaveMachine[proci] >> slavePid;
|
||||
slaveProcs[proci] = slaveMachine[proci] + "." + name(slavePid);
|
||||
proci++;
|
||||
|
||||
// Check build string to make sure all processors are running
|
||||
// the same build
|
||||
if (slaveBuild != Foam::FOAMbuild)
|
||||
{
|
||||
FatalErrorIn(executable())
|
||||
<< "Master is running version " << Foam::FOAMbuild
|
||||
<< "; slave " << proci << " is running version "
|
||||
<< slaveBuild
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OPstream toMaster
|
||||
(
|
||||
Pstream::commsTypes::scheduled,
|
||||
Pstream::masterNo()
|
||||
);
|
||||
toMaster << string(Foam::FOAMbuild) << hostName() << pid();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Case is a single processor run unless it is running parallel
|
||||
int nProcs = 1;
|
||||
|
||||
@ -999,6 +1087,52 @@ void Foam::argList::parse
|
||||
dictNProcs = roots.size()+1;
|
||||
}
|
||||
}
|
||||
else if (options_.found("hostRoots"))
|
||||
{
|
||||
source = "-hostRoots";
|
||||
IStringStream is(options_["hostRoots"]);
|
||||
List<Tuple2<wordRe, fileName>> hostRoots(is);
|
||||
|
||||
roots.setSize(Pstream::nProcs()-1);
|
||||
forAll(hostRoots, i)
|
||||
{
|
||||
const Tuple2<wordRe, fileName>& hostRoot = hostRoots[i];
|
||||
const wordRe& re = hostRoot.first();
|
||||
labelList matchedRoots(findStrings(re, slaveMachine));
|
||||
forAll(matchedRoots, matchi)
|
||||
{
|
||||
label slavei = matchedRoots[matchi];
|
||||
if (roots[slavei] != wordRe())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Slave " << slaveMachine[slavei]
|
||||
<< " has multiple matching roots in "
|
||||
<< hostRoots << exit(FatalError);
|
||||
}
|
||||
else
|
||||
{
|
||||
roots[slavei] = hostRoot.second();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check
|
||||
forAll(roots, slavei)
|
||||
{
|
||||
if (roots[slavei] == wordRe())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Slave " << slaveMachine[slavei]
|
||||
<< " has no matching roots in "
|
||||
<< hostRoots << exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
if (roots.size() != 1)
|
||||
{
|
||||
dictNProcs = roots.size()+1;
|
||||
}
|
||||
}
|
||||
else if (checkProcessorDirectories_)
|
||||
{
|
||||
// Use values from decomposeParDict, the location was already
|
||||
@ -1172,55 +1306,6 @@ void Foam::argList::parse
|
||||
case_ = globalCase_;
|
||||
}
|
||||
|
||||
stringList slaveProcs;
|
||||
const int writeHostsSwitch = debug::infoSwitch("writeHosts", 1);
|
||||
|
||||
// Collect slave machine/pid, and check that the build is identical
|
||||
if (parRunControl_.parRun())
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
slaveProcs.setSize(Pstream::nProcs() - 1);
|
||||
label proci = 0;
|
||||
for
|
||||
(
|
||||
int slave = Pstream::firstSlave();
|
||||
slave <= Pstream::lastSlave();
|
||||
slave++
|
||||
)
|
||||
{
|
||||
IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
|
||||
|
||||
string slaveBuild;
|
||||
string slaveMachine;
|
||||
label slavePid;
|
||||
fromSlave >> slaveBuild >> slaveMachine >> slavePid;
|
||||
|
||||
slaveProcs[proci++] = slaveMachine + "." + name(slavePid);
|
||||
|
||||
// Check build string to make sure all processors are running
|
||||
// the same build
|
||||
if (slaveBuild != Foam::FOAMbuild)
|
||||
{
|
||||
FatalErrorIn(executable())
|
||||
<< "Master is running version " << Foam::FOAMbuild
|
||||
<< "; slave " << proci << " is running version "
|
||||
<< slaveBuild
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OPstream toMaster
|
||||
(
|
||||
Pstream::commsTypes::scheduled,
|
||||
Pstream::masterNo()
|
||||
);
|
||||
toMaster << string(Foam::FOAMbuild) << hostName() << pid();
|
||||
}
|
||||
}
|
||||
|
||||
// Keep or discard slave and root information for reporting:
|
||||
if (Pstream::master() && parRunControl_.parRun())
|
||||
{
|
||||
@ -1412,6 +1497,7 @@ bool Foam::argList::unsetOption(const word& optName)
|
||||
optName == "case"
|
||||
|| optName == "parallel"
|
||||
|| optName == "roots"
|
||||
|| optName == "hostRoots"
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -70,11 +70,11 @@ public:
|
||||
}
|
||||
|
||||
//- Initialize Pstream for a parallel run
|
||||
void runPar(int& argc, char**& argv)
|
||||
void runPar(int& argc, char**& argv, const bool needsThread)
|
||||
{
|
||||
RunPar = true;
|
||||
|
||||
if (!Pstream::init(argc, argv))
|
||||
if (!Pstream::init(argc, argv, needsThread))
|
||||
{
|
||||
Info<< "Failed to start parallel run" << endl;
|
||||
Pstream::exit(1);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -95,21 +95,31 @@ Foam::dictionary& Foam::debug::controlDict()
|
||||
{
|
||||
if (!controlDictPtr_)
|
||||
{
|
||||
fileNameList controlDictFiles = findEtcFiles("controlDict", true);
|
||||
controlDictPtr_ = new dictionary();
|
||||
forAllReverse(controlDictFiles, cdfi)
|
||||
string controlDictString(getEnv("FOAM_CONTROLDICT"));
|
||||
if (!controlDictString.empty())
|
||||
{
|
||||
IFstream ifs(controlDictFiles[cdfi]);
|
||||
|
||||
if (!ifs.good())
|
||||
// Read from environment
|
||||
IStringStream is(controlDictString);
|
||||
controlDictPtr_ = new dictionary(is);
|
||||
}
|
||||
else
|
||||
{
|
||||
fileNameList controlDictFiles = findEtcFiles("controlDict", true);
|
||||
controlDictPtr_ = new dictionary();
|
||||
forAllReverse(controlDictFiles, cdfi)
|
||||
{
|
||||
SafeFatalIOErrorInFunction
|
||||
(
|
||||
ifs,
|
||||
"Cannot open controlDict"
|
||||
);
|
||||
IFstream ifs(controlDictFiles[cdfi]);
|
||||
|
||||
if (!ifs.good())
|
||||
{
|
||||
SafeFatalIOErrorInFunction
|
||||
(
|
||||
ifs,
|
||||
"Cannot open controlDict"
|
||||
);
|
||||
}
|
||||
controlDictPtr_->merge(dictionary(ifs));
|
||||
}
|
||||
controlDictPtr_->merge(dictionary(ifs));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -26,6 +26,7 @@ License
|
||||
#include "OFstreamCollator.H"
|
||||
#include "OFstream.H"
|
||||
#include "decomposedBlockData.H"
|
||||
#include "masterUncollatedFileOperation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
@ -44,8 +45,7 @@ bool Foam::OFstreamCollator::writeFile
|
||||
const fileName& fName,
|
||||
const string& masterData,
|
||||
const labelUList& recvSizes,
|
||||
const bool haveSlaveData, // does master have slaveData
|
||||
const UList<char>& slaveData, // on master: slave data
|
||||
const PtrList<SubList<char>>& slaveData, // optional slave data
|
||||
IOstream::streamFormat fmt,
|
||||
IOstream::versionNumber ver,
|
||||
IOstream::compressionType cmp,
|
||||
@ -54,9 +54,22 @@ bool Foam::OFstreamCollator::writeFile
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "OFstreamCollator : Writing " << masterData.size()
|
||||
Pout<< "OFstreamCollator : Writing master " << masterData.size()
|
||||
<< " bytes to " << fName
|
||||
<< " using comm " << comm << endl;
|
||||
if (slaveData.size())
|
||||
{
|
||||
Pout<< "OFstreamCollator : Slave data" << endl;
|
||||
forAll(slaveData, proci)
|
||||
{
|
||||
if (slaveData.set(proci))
|
||||
{
|
||||
Pout<< " " << proci
|
||||
<< " size:" << slaveData[proci].size()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
autoPtr<OSstream> osPtr;
|
||||
@ -76,17 +89,20 @@ bool Foam::OFstreamCollator::writeFile
|
||||
);
|
||||
|
||||
// We don't have IOobject so cannot use IOobject::writeHeader
|
||||
OSstream& os = osPtr();
|
||||
decomposedBlockData::writeHeader
|
||||
(
|
||||
os,
|
||||
ver,
|
||||
fmt,
|
||||
typeName,
|
||||
"",
|
||||
fName,
|
||||
fName.name()
|
||||
);
|
||||
if (!append)
|
||||
{
|
||||
OSstream& os = osPtr();
|
||||
decomposedBlockData::writeHeader
|
||||
(
|
||||
os,
|
||||
ver,
|
||||
fmt,
|
||||
typeName,
|
||||
"",
|
||||
fName,
|
||||
fName.name()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -109,9 +125,13 @@ bool Foam::OFstreamCollator::writeFile
|
||||
start,
|
||||
slice,
|
||||
recvSizes,
|
||||
haveSlaveData,
|
||||
slaveData,
|
||||
UPstream::commsTypes::nonBlocking, //scheduled,
|
||||
(
|
||||
fileOperations::masterUncollatedFileOperation::
|
||||
maxMasterFileBufferSize == 0
|
||||
? UPstream::commsTypes::scheduled
|
||||
: UPstream::commsTypes::nonBlocking
|
||||
),
|
||||
false // do not reduce return state
|
||||
);
|
||||
|
||||
@ -132,7 +152,11 @@ bool Foam::OFstreamCollator::writeFile
|
||||
{
|
||||
sum += recvSizes[i];
|
||||
}
|
||||
Pout<< " (overall " << sum << ")";
|
||||
// Use ostringstream to display long int (until writing these is
|
||||
// supported)
|
||||
std::ostringstream os;
|
||||
os << sum;
|
||||
Pout<< " (overall " << os.str() << ")";
|
||||
}
|
||||
Pout<< " to " << fName
|
||||
<< " using comm " << comm << endl;
|
||||
@ -151,12 +175,13 @@ void* Foam::OFstreamCollator::writeAll(void *threadarg)
|
||||
{
|
||||
writeData* ptr = nullptr;
|
||||
|
||||
lockMutex(handler.mutex_);
|
||||
if (handler.objects_.size())
|
||||
{
|
||||
ptr = handler.objects_.pop();
|
||||
std::lock_guard<std::mutex> guard(handler.mutex_);
|
||||
if (handler.objects_.size())
|
||||
{
|
||||
ptr = handler.objects_.pop();
|
||||
}
|
||||
}
|
||||
unlockMutex(handler.mutex_);
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
@ -164,6 +189,28 @@ void* Foam::OFstreamCollator::writeAll(void *threadarg)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert storage to pointers
|
||||
PtrList<SubList<char>> slaveData;
|
||||
if (ptr->slaveData_.size())
|
||||
{
|
||||
slaveData.setSize(ptr->slaveData_.size());
|
||||
forAll(slaveData, proci)
|
||||
{
|
||||
if (ptr->slaveData_.set(proci))
|
||||
{
|
||||
slaveData.set
|
||||
(
|
||||
proci,
|
||||
new SubList<char>
|
||||
(
|
||||
ptr->slaveData_[proci],
|
||||
ptr->sizes_[proci]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ok = writeFile
|
||||
(
|
||||
ptr->comm_,
|
||||
@ -171,9 +218,7 @@ void* Foam::OFstreamCollator::writeAll(void *threadarg)
|
||||
ptr->pathName_,
|
||||
ptr->data_,
|
||||
ptr->sizes_,
|
||||
ptr->haveSlaveData_,
|
||||
ptr->slaveData_,
|
||||
|
||||
slaveData,
|
||||
ptr->format_,
|
||||
ptr->version_,
|
||||
ptr->compression_,
|
||||
@ -196,9 +241,10 @@ void* Foam::OFstreamCollator::writeAll(void *threadarg)
|
||||
Pout<< "OFstreamCollator : Exiting write thread " << endl;
|
||||
}
|
||||
|
||||
lockMutex(handler.mutex_);
|
||||
handler.threadRunning_ = false;
|
||||
unlockMutex(handler.mutex_);
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handler.mutex_);
|
||||
handler.threadRunning_ = false;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@ -211,12 +257,13 @@ void Foam::OFstreamCollator::waitForBufferSpace(const off_t wantedSize) const
|
||||
// Count files to be written
|
||||
off_t totalSize = 0;
|
||||
|
||||
lockMutex(mutex_);
|
||||
forAllConstIter(FIFOStack<writeData*>, objects_, iter)
|
||||
{
|
||||
totalSize += iter()->size();
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
forAllConstIter(FIFOStack<writeData*>, objects_, iter)
|
||||
{
|
||||
totalSize += iter()->size();
|
||||
}
|
||||
}
|
||||
unlockMutex(mutex_);
|
||||
|
||||
if (totalSize == 0 || (totalSize+wantedSize) <= maxBufferSize_)
|
||||
{
|
||||
@ -225,13 +272,12 @@ void Foam::OFstreamCollator::waitForBufferSpace(const off_t wantedSize) const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
lockMutex(mutex_);
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
Pout<< "OFstreamCollator : Waiting for buffer space."
|
||||
<< " Currently in use:" << totalSize
|
||||
<< " limit:" << maxBufferSize_
|
||||
<< " files:" << objects_.size()
|
||||
<< endl;
|
||||
unlockMutex(mutex_);
|
||||
}
|
||||
|
||||
sleep(5);
|
||||
@ -244,25 +290,34 @@ void Foam::OFstreamCollator::waitForBufferSpace(const off_t wantedSize) const
|
||||
Foam::OFstreamCollator::OFstreamCollator(const off_t maxBufferSize)
|
||||
:
|
||||
maxBufferSize_(maxBufferSize),
|
||||
mutex_
|
||||
(
|
||||
maxBufferSize_ > 0
|
||||
? allocateMutex()
|
||||
: -1
|
||||
),
|
||||
thread_
|
||||
(
|
||||
maxBufferSize_ > 0
|
||||
? allocateThread()
|
||||
: -1
|
||||
),
|
||||
threadRunning_(false),
|
||||
comm_
|
||||
localComm_(UPstream::worldComm),
|
||||
threadComm_
|
||||
(
|
||||
UPstream::allocateCommunicator
|
||||
(
|
||||
UPstream::worldComm,
|
||||
identity(UPstream::nProcs(UPstream::worldComm))
|
||||
localComm_,
|
||||
identity(UPstream::nProcs(localComm_))
|
||||
)
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
Foam::OFstreamCollator::OFstreamCollator
|
||||
(
|
||||
const off_t maxBufferSize,
|
||||
const label comm
|
||||
)
|
||||
:
|
||||
maxBufferSize_(maxBufferSize),
|
||||
threadRunning_(false),
|
||||
localComm_(comm),
|
||||
threadComm_
|
||||
(
|
||||
UPstream::allocateCommunicator
|
||||
(
|
||||
localComm_,
|
||||
identity(UPstream::nProcs(localComm_))
|
||||
)
|
||||
)
|
||||
{}
|
||||
@ -272,26 +327,19 @@ Foam::OFstreamCollator::OFstreamCollator(const off_t maxBufferSize)
|
||||
|
||||
Foam::OFstreamCollator::~OFstreamCollator()
|
||||
{
|
||||
if (threadRunning_)
|
||||
if (thread_.valid())
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "~OFstreamCollator : Waiting for write thread" << endl;
|
||||
}
|
||||
thread_().join();
|
||||
thread_.clear();
|
||||
}
|
||||
|
||||
joinThread(thread_);
|
||||
}
|
||||
if (thread_ != -1)
|
||||
if (threadComm_ != -1)
|
||||
{
|
||||
freeThread(thread_);
|
||||
}
|
||||
if (mutex_ != -1)
|
||||
{
|
||||
freeMutex(mutex_);
|
||||
}
|
||||
if (comm_ != -1)
|
||||
{
|
||||
UPstream::freeCommunicator(comm_);
|
||||
UPstream::freeCommunicator(threadComm_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,7 +360,8 @@ bool Foam::OFstreamCollator::write
|
||||
// Determine (on master) sizes to receive. Note: do NOT use thread
|
||||
// communicator
|
||||
labelList recvSizes;
|
||||
decomposedBlockData::gather(Pstream::worldComm, data.size(), recvSizes);
|
||||
decomposedBlockData::gather(localComm_, label(data.size()), recvSizes);
|
||||
|
||||
off_t totalSize = 0;
|
||||
label maxLocalSize = 0;
|
||||
{
|
||||
@ -321,8 +370,8 @@ bool Foam::OFstreamCollator::write
|
||||
totalSize += recvSizes[proci];
|
||||
maxLocalSize = max(maxLocalSize, recvSizes[proci]);
|
||||
}
|
||||
Pstream::scatter(totalSize, Pstream::msgType(), Pstream::worldComm);
|
||||
Pstream::scatter(maxLocalSize, Pstream::msgType(), Pstream::worldComm);
|
||||
Pstream::scatter(totalSize, Pstream::msgType(), localComm_);
|
||||
Pstream::scatter(maxLocalSize, Pstream::msgType(), localComm_);
|
||||
}
|
||||
|
||||
if (maxBufferSize_ == 0 || maxLocalSize > maxBufferSize_)
|
||||
@ -330,18 +379,17 @@ bool Foam::OFstreamCollator::write
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "OFstreamCollator : non-thread gather and write of " << fName
|
||||
<< " using worldComm" << endl;
|
||||
<< " using local comm " << localComm_ << endl;
|
||||
}
|
||||
// Direct collating and writing (so master blocks until all written!)
|
||||
const List<char> dummySlaveData;
|
||||
const PtrList<SubList<char>> dummySlaveData;
|
||||
return writeFile
|
||||
(
|
||||
UPstream::worldComm,
|
||||
localComm_,
|
||||
typeName,
|
||||
fName,
|
||||
data,
|
||||
recvSizes,
|
||||
false, // no slave data provided yet
|
||||
dummySlaveData,
|
||||
fmt,
|
||||
ver,
|
||||
@ -360,22 +408,28 @@ bool Foam::OFstreamCollator::write
|
||||
<< fName << endl;
|
||||
}
|
||||
|
||||
if (Pstream::master())
|
||||
if (Pstream::master(localComm_))
|
||||
{
|
||||
waitForBufferSpace(totalSize);
|
||||
}
|
||||
|
||||
// Allocate local buffer for all collated data
|
||||
|
||||
// Receive in chunks of labelMax (2^31-1) since this is the maximum
|
||||
// size that a List can be
|
||||
|
||||
autoPtr<writeData> fileAndDataPtr
|
||||
(
|
||||
new writeData
|
||||
(
|
||||
comm_, // Note: comm not actually used anymore
|
||||
threadComm_, // Note: comm not actually used anymore
|
||||
typeName,
|
||||
fName,
|
||||
data,
|
||||
(
|
||||
Pstream::master(localComm_)
|
||||
? data // Only used on master
|
||||
: string::null
|
||||
),
|
||||
recvSizes,
|
||||
true, // have slave data (collected below)
|
||||
fmt,
|
||||
ver,
|
||||
cmp,
|
||||
@ -384,40 +438,84 @@ bool Foam::OFstreamCollator::write
|
||||
);
|
||||
writeData& fileAndData = fileAndDataPtr();
|
||||
|
||||
// Gather the slave data and insert into fileAndData
|
||||
PtrList<List<char>>& slaveData = fileAndData.slaveData_;
|
||||
|
||||
UList<char> slice(const_cast<char*>(data.data()), label(data.size()));
|
||||
List<int> slaveOffsets;
|
||||
decomposedBlockData::gatherSlaveData
|
||||
(
|
||||
Pstream::worldComm, // Note: using simulation thread
|
||||
slice,
|
||||
recvSizes,
|
||||
|
||||
1, // startProc,
|
||||
Pstream::nProcs()-1, // n procs
|
||||
slaveData.setSize(recvSizes.size());
|
||||
|
||||
slaveOffsets,
|
||||
fileAndData.slaveData_
|
||||
);
|
||||
|
||||
// Append to thread buffer
|
||||
lockMutex(mutex_);
|
||||
objects_.push(fileAndDataPtr.ptr());
|
||||
unlockMutex(mutex_);
|
||||
|
||||
// Start thread if not running
|
||||
lockMutex(mutex_);
|
||||
if (!threadRunning_)
|
||||
// Gather all data onto master. Is done in local communicator since
|
||||
// not in write thread. Note that we do not store in contiguous
|
||||
// buffer since that would limit to 2G chars.
|
||||
label startOfRequests = Pstream::nRequests();
|
||||
if (Pstream::master(localComm_))
|
||||
{
|
||||
createThread(thread_, writeAll, this);
|
||||
if (debug)
|
||||
for (label proci = 1; proci < slaveData.size(); proci++)
|
||||
{
|
||||
Pout<< "OFstreamCollator : Started write thread "
|
||||
<< thread_ << endl;
|
||||
slaveData.set(proci, new List<char>(recvSizes[proci]));
|
||||
UIPstream::read
|
||||
(
|
||||
UPstream::commsTypes::nonBlocking,
|
||||
proci,
|
||||
reinterpret_cast<char*>(slaveData[proci].begin()),
|
||||
slaveData[proci].byteSize(),
|
||||
Pstream::msgType(),
|
||||
localComm_
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if
|
||||
(
|
||||
!UOPstream::write
|
||||
(
|
||||
UPstream::commsTypes::nonBlocking,
|
||||
0,
|
||||
reinterpret_cast<const char*>(slice.begin()),
|
||||
slice.byteSize(),
|
||||
Pstream::msgType(),
|
||||
localComm_
|
||||
)
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot send outgoing message. "
|
||||
<< "to:" << 0 << " nBytes:"
|
||||
<< label(slice.byteSize())
|
||||
<< Foam::abort(FatalError);
|
||||
}
|
||||
}
|
||||
Pstream::waitRequests(startOfRequests);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
|
||||
// Append to thread buffer
|
||||
objects_.push(fileAndDataPtr.ptr());
|
||||
|
||||
// Start thread if not running
|
||||
if (!threadRunning_)
|
||||
{
|
||||
if (thread_.valid())
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "OFstreamCollator : Waiting for write thread"
|
||||
<< endl;
|
||||
}
|
||||
thread_().join();
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "OFstreamCollator : Starting write thread"
|
||||
<< endl;
|
||||
}
|
||||
thread_.reset(new std::thread(writeAll, this));
|
||||
threadRunning_ = true;
|
||||
}
|
||||
threadRunning_ = true;
|
||||
}
|
||||
unlockMutex(mutex_);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -426,57 +524,65 @@ bool Foam::OFstreamCollator::write
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "OFstreamCollator : thread gather and write of " << fName
|
||||
<< " in thread " << thread_
|
||||
<< " using communicator " << comm_ << endl;
|
||||
<< " using communicator " << threadComm_ << endl;
|
||||
}
|
||||
|
||||
if (!UPstream::haveThreads())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "mpi does not seem to have thread support."
|
||||
<< "Please increase the buffer size 'maxThreadFileBufferSize'"
|
||||
<< " Make sure to set buffer size 'maxThreadFileBufferSize'"
|
||||
<< " to at least " << totalSize
|
||||
<< " to be able to do the collating before threading."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
if (Pstream::master())
|
||||
if (Pstream::master(localComm_))
|
||||
{
|
||||
waitForBufferSpace(data.size());
|
||||
}
|
||||
|
||||
lockMutex(mutex_);
|
||||
// Push all file info on buffer. Note that no slave data provided
|
||||
// so it will trigger communication inside the thread
|
||||
objects_.push
|
||||
(
|
||||
new writeData
|
||||
(
|
||||
comm_,
|
||||
typeName,
|
||||
fName,
|
||||
data,
|
||||
recvSizes,
|
||||
false, // Have no slave data; collect in thread
|
||||
fmt,
|
||||
ver,
|
||||
cmp,
|
||||
append
|
||||
)
|
||||
);
|
||||
unlockMutex(mutex_);
|
||||
|
||||
lockMutex(mutex_);
|
||||
if (!threadRunning_)
|
||||
{
|
||||
createThread(thread_, writeAll, this);
|
||||
if (debug)
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
|
||||
// Push all file info on buffer. Note that no slave data provided
|
||||
// so it will trigger communication inside the thread
|
||||
objects_.push
|
||||
(
|
||||
new writeData
|
||||
(
|
||||
threadComm_,
|
||||
typeName,
|
||||
fName,
|
||||
data,
|
||||
recvSizes,
|
||||
fmt,
|
||||
ver,
|
||||
cmp,
|
||||
append
|
||||
)
|
||||
);
|
||||
|
||||
if (!threadRunning_)
|
||||
{
|
||||
Pout<< "OFstreamCollator : Started write thread " << endl;
|
||||
if (thread_.valid())
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "OFstreamCollator : Waiting for write thread"
|
||||
<< endl;
|
||||
}
|
||||
thread_().join();
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "OFstreamCollator : Starting write thread" << endl;
|
||||
}
|
||||
thread_.reset(new std::thread(writeAll, this));
|
||||
threadRunning_ = true;
|
||||
}
|
||||
threadRunning_ = true;
|
||||
}
|
||||
unlockMutex(mutex_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -51,9 +51,12 @@ SourceFiles
|
||||
#ifndef OFstreamCollator_H
|
||||
#define OFstreamCollator_H
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include "IOstream.H"
|
||||
#include "labelList.H"
|
||||
#include "FIFOStack.H"
|
||||
#include "SubList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -77,10 +80,7 @@ class OFstreamCollator
|
||||
const fileName pathName_;
|
||||
const string data_;
|
||||
const labelList sizes_;
|
||||
|
||||
const bool haveSlaveData_;
|
||||
List<char> slaveData_;
|
||||
|
||||
PtrList<List<char>> slaveData_;
|
||||
const IOstream::streamFormat format_;
|
||||
const IOstream::versionNumber version_;
|
||||
const IOstream::compressionType compression_;
|
||||
@ -93,7 +93,6 @@ class OFstreamCollator
|
||||
const fileName& pathName,
|
||||
const string& data,
|
||||
const labelList& sizes,
|
||||
const bool haveSlaveData,
|
||||
IOstream::streamFormat format,
|
||||
IOstream::versionNumber version,
|
||||
IOstream::compressionType compression,
|
||||
@ -105,7 +104,6 @@ class OFstreamCollator
|
||||
pathName_(pathName),
|
||||
data_(data),
|
||||
sizes_(sizes),
|
||||
haveSlaveData_(haveSlaveData),
|
||||
slaveData_(0),
|
||||
format_(format),
|
||||
version_(version),
|
||||
@ -116,27 +114,39 @@ class OFstreamCollator
|
||||
//- (approximate) size of master + any optional slave data
|
||||
off_t size() const
|
||||
{
|
||||
return data_.size() + slaveData_.size();
|
||||
off_t sz = data_.size();
|
||||
forAll(slaveData_, i)
|
||||
{
|
||||
if (slaveData_.set(i))
|
||||
{
|
||||
sz += slaveData_[i].size();
|
||||
}
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Private data
|
||||
|
||||
//- Total amount of storage to use for object stack below
|
||||
const off_t maxBufferSize_;
|
||||
|
||||
//pthread_mutex_t mutex_;
|
||||
label mutex_;
|
||||
mutable std::mutex mutex_;
|
||||
|
||||
//pthread_t thread_;
|
||||
label thread_;
|
||||
autoPtr<std::thread> thread_;
|
||||
|
||||
//- Stack of files to write + contents
|
||||
FIFOStack<writeData*> objects_;
|
||||
|
||||
//- Whether thread is running (and not exited)
|
||||
bool threadRunning_;
|
||||
|
||||
//- Communicator to use for all parallel ops
|
||||
label comm_;
|
||||
//- Communicator to use for all parallel ops (in simulation thread)
|
||||
label localComm_;
|
||||
|
||||
//- Communicator to use for all parallel ops (in write thread)
|
||||
label threadComm_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
@ -149,8 +159,7 @@ class OFstreamCollator
|
||||
const fileName& fName,
|
||||
const string& masterData,
|
||||
const labelUList& recvSizes,
|
||||
const bool haveSlaveData, // (does master) have slave data
|
||||
const UList<char>& slaveData, // (on master) all slave data
|
||||
const PtrList<SubList<char>>& slaveData,
|
||||
IOstream::streamFormat fmt,
|
||||
IOstream::versionNumber ver,
|
||||
IOstream::compressionType cmp,
|
||||
@ -176,6 +185,10 @@ public:
|
||||
//- Construct from buffer size. 0 = do not use thread
|
||||
OFstreamCollator(const off_t maxBufferSize);
|
||||
|
||||
//- Construct from buffer size (0 = do not use thread) and local
|
||||
// thread
|
||||
OFstreamCollator(const off_t maxBufferSize, const label comm);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~OFstreamCollator();
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -57,12 +57,63 @@ namespace fileOperations
|
||||
float,
|
||||
collatedFileOperation::maxThreadFileBufferSize
|
||||
);
|
||||
|
||||
// Mark as needing threaded mpi
|
||||
addNamedToRunTimeSelectionTable
|
||||
(
|
||||
fileOperationInitialise,
|
||||
collatedFileOperationInitialise,
|
||||
word,
|
||||
collated
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::labelList Foam::fileOperations::collatedFileOperation::ioRanks()
|
||||
{
|
||||
labelList ioRanks;
|
||||
|
||||
string ioRanksString(getEnv("FOAM_IORANKS"));
|
||||
if (!ioRanksString.empty())
|
||||
{
|
||||
IStringStream is(ioRanksString);
|
||||
is >> ioRanks;
|
||||
}
|
||||
|
||||
return ioRanks;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::fileOperations::collatedFileOperation::isMasterRank
|
||||
(
|
||||
const label proci
|
||||
)
|
||||
const
|
||||
{
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
return Pstream::master(comm_);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use any IO ranks
|
||||
if (ioRanks_.size())
|
||||
{
|
||||
// Find myself in IO rank
|
||||
return findIndex(ioRanks_, proci) != -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume all in single communicator
|
||||
return proci == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::fileOperations::collatedFileOperation::appendObject
|
||||
(
|
||||
const regIOobject& io,
|
||||
@ -74,14 +125,12 @@ bool Foam::fileOperations::collatedFileOperation::appendObject
|
||||
{
|
||||
// Append to processors/ file
|
||||
|
||||
fileName prefix;
|
||||
fileName postfix;
|
||||
label proci = splitProcessorPath(io.objectPath(), prefix, postfix);
|
||||
label proci = detectProcessorPath(io.objectPath());
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "writeObject:" << " : For local object : "
|
||||
<< io.name()
|
||||
Pout<< "collatedFileOperation::writeObject :"
|
||||
<< " For local object : " << io.name()
|
||||
<< " appending processor " << proci
|
||||
<< " data to " << pathName << endl;
|
||||
}
|
||||
@ -93,12 +142,35 @@ bool Foam::fileOperations::collatedFileOperation::appendObject
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
const bool isMaster = isMasterRank(proci);
|
||||
|
||||
// Determine the local rank if the pathName is a per-rank one
|
||||
label localProci = proci;
|
||||
{
|
||||
fileName path, procDir, local;
|
||||
label groupStart, groupSize, nProcs;
|
||||
splitProcessorPath
|
||||
(
|
||||
pathName,
|
||||
path,
|
||||
procDir,
|
||||
local,
|
||||
groupStart,
|
||||
groupSize,
|
||||
nProcs
|
||||
);
|
||||
if (groupSize > 0 && groupStart != -1)
|
||||
{
|
||||
localProci = proci-groupStart;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Create string from all data to write
|
||||
string buf;
|
||||
{
|
||||
OStringStream os(fmt, ver);
|
||||
if (proci == 0)
|
||||
if (isMaster)
|
||||
{
|
||||
if (!io.writeHeader(os))
|
||||
{
|
||||
@ -112,7 +184,7 @@ bool Foam::fileOperations::collatedFileOperation::appendObject
|
||||
return false;
|
||||
}
|
||||
|
||||
if (proci == 0)
|
||||
if (isMaster)
|
||||
{
|
||||
IOobject::writeEndDivider(os);
|
||||
}
|
||||
@ -121,8 +193,6 @@ bool Foam::fileOperations::collatedFileOperation::appendObject
|
||||
}
|
||||
|
||||
|
||||
bool append = (proci > 0);
|
||||
|
||||
// Note: cannot do append + compression. This is a limitation
|
||||
// of ogzstream (or rather most compressed formats)
|
||||
|
||||
@ -132,7 +202,7 @@ bool Foam::fileOperations::collatedFileOperation::appendObject
|
||||
IOstream::BINARY,
|
||||
ver,
|
||||
IOstream::UNCOMPRESSED, // no compression
|
||||
append
|
||||
!isMaster
|
||||
);
|
||||
|
||||
if (!os.good())
|
||||
@ -142,7 +212,7 @@ bool Foam::fileOperations::collatedFileOperation::appendObject
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
if (proci == 0)
|
||||
if (isMaster)
|
||||
{
|
||||
IOobject::writeBanner(os)
|
||||
<< "FoamFile\n{\n"
|
||||
@ -162,7 +232,7 @@ bool Foam::fileOperations::collatedFileOperation::appendObject
|
||||
const_cast<char*>(buf.data()),
|
||||
label(buf.size())
|
||||
);
|
||||
os << nl << "// Processor" << proci << nl << slice << nl;
|
||||
os << nl << "// Processor" << localProci << nl << slice << nl;
|
||||
|
||||
return os.good();
|
||||
}
|
||||
@ -175,8 +245,23 @@ Foam::fileOperations::collatedFileOperation::collatedFileOperation
|
||||
const bool verbose
|
||||
)
|
||||
:
|
||||
masterUncollatedFileOperation(false),
|
||||
writer_(maxThreadFileBufferSize)
|
||||
masterUncollatedFileOperation
|
||||
(
|
||||
(
|
||||
ioRanks().size()
|
||||
? UPstream::allocateCommunicator
|
||||
(
|
||||
UPstream::worldComm,
|
||||
subRanks(Pstream::nProcs())
|
||||
)
|
||||
: UPstream::worldComm
|
||||
),
|
||||
false
|
||||
),
|
||||
myComm_(comm_),
|
||||
writer_(maxThreadFileBufferSize, comm_),
|
||||
nProcs_(Pstream::nProcs()),
|
||||
ioRanks_(ioRanks())
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
@ -195,12 +280,97 @@ Foam::fileOperations::collatedFileOperation::collatedFileOperation
|
||||
{
|
||||
Info<< " Threading activated "
|
||||
"since maxThreadFileBufferSize > 0." << nl
|
||||
<< " Requires thread support enabled in MPI, "
|
||||
"otherwise the simulation" << nl
|
||||
<< " may \"hang\". If thread support cannot be "
|
||||
"enabled, deactivate threading" << nl
|
||||
<< " by setting maxThreadFileBufferSize to 0 in "
|
||||
"the OpenFOAM etc/controlDict"
|
||||
<< " Requires large enough buffer to collect all data"
|
||||
" or thread support " << nl
|
||||
<< " enabled in MPI. If thread support cannot be "
|
||||
"enabled, deactivate" << nl
|
||||
<< " threading by setting maxThreadFileBufferSize "
|
||||
"to 0 in" << nl
|
||||
<< " $FOAM_ETC/controlDict"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if (ioRanks_.size())
|
||||
{
|
||||
// Print a bit of information
|
||||
stringList ioRanks(Pstream::nProcs());
|
||||
if (Pstream::master(comm_))
|
||||
{
|
||||
ioRanks[Pstream::myProcNo()] = hostName()+"."+name(pid());
|
||||
}
|
||||
Pstream::gatherList(ioRanks);
|
||||
|
||||
Info<< " IO nodes:" << endl;
|
||||
forAll(ioRanks, proci)
|
||||
{
|
||||
if (!ioRanks[proci].empty())
|
||||
{
|
||||
Info<< " " << ioRanks[proci] << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if
|
||||
(
|
||||
regIOobject::fileModificationChecking
|
||||
== regIOobject::inotifyMaster
|
||||
)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Resetting fileModificationChecking to inotify" << endl;
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
regIOobject::fileModificationChecking
|
||||
== regIOobject::timeStampMaster
|
||||
)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Resetting fileModificationChecking to timeStamp" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::fileOperations::collatedFileOperation::collatedFileOperation
|
||||
(
|
||||
const label comm,
|
||||
const labelList& ioRanks,
|
||||
const word& typeName,
|
||||
const bool verbose
|
||||
)
|
||||
:
|
||||
masterUncollatedFileOperation(comm, false),
|
||||
myComm_(-1),
|
||||
writer_(maxThreadFileBufferSize, comm),
|
||||
nProcs_(Pstream::nProcs()),
|
||||
ioRanks_(ioRanks)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
Info<< "I/O : " << typeName
|
||||
<< " (maxThreadFileBufferSize " << maxThreadFileBufferSize
|
||||
<< ')' << endl;
|
||||
|
||||
if (maxThreadFileBufferSize == 0)
|
||||
{
|
||||
Info<< " Threading not activated "
|
||||
"since maxThreadFileBufferSize = 0." << nl
|
||||
<< " Writing may run slowly for large file sizes."
|
||||
<< endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< " Threading activated "
|
||||
"since maxThreadFileBufferSize > 0." << nl
|
||||
<< " Requires large enough buffer to collect all data"
|
||||
" or thread support " << nl
|
||||
<< " enabled in MPI. If thread support cannot be "
|
||||
"enabled, deactivate" << nl
|
||||
<< " threading by setting maxThreadFileBufferSize "
|
||||
"to 0 in the OpenFOAM etc/controlDict" << nl
|
||||
<< endl;
|
||||
}
|
||||
|
||||
@ -227,6 +397,17 @@ Foam::fileOperations::collatedFileOperation::collatedFileOperation
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileOperations::collatedFileOperation::~collatedFileOperation()
|
||||
{
|
||||
if (myComm_ != -1 && myComm_ != UPstream::worldComm)
|
||||
{
|
||||
UPstream::freeCommunicator(myComm_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileName Foam::fileOperations::collatedFileOperation::objectPath
|
||||
@ -238,19 +419,21 @@ Foam::fileName Foam::fileOperations::collatedFileOperation::objectPath
|
||||
// Replacement for objectPath
|
||||
if (io.time().processorCase())
|
||||
{
|
||||
return masterUncollatedFileOperation::objectPath
|
||||
return masterUncollatedFileOperation::localObjectPath
|
||||
(
|
||||
io,
|
||||
fileOperation::PROCESSORSOBJECT,
|
||||
fileOperation::PROCOBJECT,
|
||||
"dummy", // not used for processorsobject
|
||||
io.instance()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return masterUncollatedFileOperation::objectPath
|
||||
return masterUncollatedFileOperation::localObjectPath
|
||||
(
|
||||
io,
|
||||
fileOperation::OBJECT,
|
||||
word::null,
|
||||
io.instance()
|
||||
);
|
||||
}
|
||||
@ -276,8 +459,8 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "writeObject:"
|
||||
<< " : For object : " << io.name()
|
||||
Pout<< "collatedFileOperation::writeObject :"
|
||||
<< " For object : " << io.name()
|
||||
<< " falling back to master-only output to " << io.path()
|
||||
<< endl;
|
||||
}
|
||||
@ -313,7 +496,7 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
|
||||
else
|
||||
{
|
||||
// Construct the equivalent processors/ directory
|
||||
fileName path(processorsPath(io, inst));
|
||||
fileName path(processorsPath(io, inst, processorsDir(io)));
|
||||
|
||||
mkDir(path);
|
||||
fileName pathName(path/io.name());
|
||||
@ -322,7 +505,8 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "writeObject:" << " : For global object : " << io.name()
|
||||
Pout<< "collatedFileOperation::writeObject :"
|
||||
<< " For global object : " << io.name()
|
||||
<< " falling back to master-only output to " << pathName
|
||||
<< endl;
|
||||
}
|
||||
@ -359,11 +543,11 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
|
||||
else if (!Pstream::parRun())
|
||||
{
|
||||
// Special path for e.g. decomposePar. Append to
|
||||
// processors/ file
|
||||
// processorsDDD/ file
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "writeObject:"
|
||||
<< " : For object : " << io.name()
|
||||
Pout<< "collatedFileOperation::writeObject :"
|
||||
<< " For object : " << io.name()
|
||||
<< " appending to " << pathName << endl;
|
||||
}
|
||||
|
||||
@ -373,8 +557,8 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "writeObject:"
|
||||
<< " : For object : " << io.name()
|
||||
Pout<< "collatedFileOperation::writeObject :"
|
||||
<< " For object : " << io.name()
|
||||
<< " starting collating output to " << pathName << endl;
|
||||
}
|
||||
|
||||
@ -386,7 +570,7 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Pstream::master() && !io.writeHeader(os))
|
||||
if (Pstream::master(comm_) && !io.writeHeader(os))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -395,7 +579,7 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Pstream::master())
|
||||
if (Pstream::master(comm_))
|
||||
{
|
||||
IOobject::writeEndDivider(os);
|
||||
}
|
||||
@ -406,4 +590,89 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
|
||||
}
|
||||
|
||||
|
||||
Foam::word Foam::fileOperations::collatedFileOperation::processorsDir
|
||||
(
|
||||
const fileName& fName
|
||||
) const
|
||||
{
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
const List<int>& procs(UPstream::procID(comm_));
|
||||
|
||||
word procDir(processorsBaseDir+Foam::name(Pstream::nProcs()));
|
||||
|
||||
if (procs.size() != Pstream::nProcs())
|
||||
{
|
||||
procDir +=
|
||||
+ "_"
|
||||
+ Foam::name(procs[0])
|
||||
+ "-"
|
||||
+ Foam::name(procs.last());
|
||||
}
|
||||
return procDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
word procDir(processorsBaseDir+Foam::name(nProcs_));
|
||||
|
||||
if (ioRanks_.size())
|
||||
{
|
||||
// Detect current processor number
|
||||
label proci = detectProcessorPath(fName);
|
||||
|
||||
if (proci != -1)
|
||||
{
|
||||
// Find lowest io rank
|
||||
label minProc = 0;
|
||||
label maxProc = nProcs_-1;
|
||||
forAll(ioRanks_, i)
|
||||
{
|
||||
if (ioRanks_[i] >= nProcs_)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (ioRanks_[i] <= proci)
|
||||
{
|
||||
minProc = ioRanks_[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxProc = ioRanks_[i]-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
procDir +=
|
||||
+ "_"
|
||||
+ Foam::name(minProc)
|
||||
+ "-"
|
||||
+ Foam::name(maxProc);
|
||||
}
|
||||
}
|
||||
|
||||
return procDir;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::word Foam::fileOperations::collatedFileOperation::processorsDir
|
||||
(
|
||||
const IOobject& io
|
||||
) const
|
||||
{
|
||||
return processorsDir(io.objectPath());
|
||||
}
|
||||
|
||||
|
||||
void Foam::fileOperations::collatedFileOperation::setNProcs(const label nProcs)
|
||||
{
|
||||
nProcs_ = nProcs;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "collatedFileOperation::setNProcs :"
|
||||
<< " Setting number of processors to " << nProcs_ << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -43,6 +43,7 @@ SourceFiles
|
||||
|
||||
#include "masterUncollatedFileOperation.H"
|
||||
#include "OFstreamCollator.H"
|
||||
#include "fileOperationInitialise.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -59,14 +60,33 @@ class collatedFileOperation
|
||||
:
|
||||
public masterUncollatedFileOperation
|
||||
{
|
||||
// Private data
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Any communicator allocated by me
|
||||
const label myComm_;
|
||||
|
||||
//- Threaded writer
|
||||
mutable OFstreamCollator writer_;
|
||||
|
||||
// For non-parallel operation
|
||||
|
||||
//- Number of processors (overall)
|
||||
label nProcs_;
|
||||
|
||||
//- Ranks of IO handlers
|
||||
const labelList ioRanks_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
static labelList ioRanks();
|
||||
|
||||
//- Is proci master of communicator (in parallel) or master of
|
||||
// the io ranks (non-parallel)
|
||||
bool isMasterRank(const label proci) const;
|
||||
|
||||
//- Append to processors/ file
|
||||
bool appendObject
|
||||
(
|
||||
@ -97,9 +117,18 @@ public:
|
||||
//- Construct null
|
||||
collatedFileOperation(const bool verbose);
|
||||
|
||||
//- Construct from user communicator
|
||||
collatedFileOperation
|
||||
(
|
||||
const label comm,
|
||||
const labelList& ioRanks,
|
||||
const word& typeName,
|
||||
const bool verbose
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~collatedFileOperation() = default;
|
||||
virtual ~collatedFileOperation();
|
||||
|
||||
|
||||
// Member Functions
|
||||
@ -123,6 +152,54 @@ public:
|
||||
IOstream::compressionType compression=IOstream::UNCOMPRESSED,
|
||||
const bool valid = true
|
||||
) const;
|
||||
|
||||
// Other
|
||||
|
||||
//- Actual name of processors dir
|
||||
virtual word processorsDir(const IOobject&) const;
|
||||
|
||||
//- Actual name of processors dir
|
||||
virtual word processorsDir(const fileName&) const;
|
||||
|
||||
//- Set number of processor directories/results. Only used in
|
||||
// decomposePar
|
||||
virtual void setNProcs(const label nProcs);
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class collatedFileOperationInitialise Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class collatedFileOperationInitialise
|
||||
:
|
||||
public masterUncollatedFileOperationInitialise
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
collatedFileOperationInitialise(int& argc, char**& argv)
|
||||
:
|
||||
masterUncollatedFileOperationInitialise(argc, argv)
|
||||
{}
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~collatedFileOperationInitialise()
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Needs threading
|
||||
virtual bool needsThreading() const
|
||||
{
|
||||
return
|
||||
collatedFileOperation::maxThreadFileBufferSize
|
||||
> 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,176 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "hostCollatedFileOperation.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "bitSet.H"
|
||||
|
||||
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace fileOperations
|
||||
{
|
||||
defineTypeNameAndDebug(hostCollatedFileOperation, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
fileOperation,
|
||||
hostCollatedFileOperation,
|
||||
word
|
||||
);
|
||||
|
||||
// Register initialisation routine. Signals need for threaded mpi and
|
||||
// handles command line arguments
|
||||
addNamedToRunTimeSelectionTable
|
||||
(
|
||||
fileOperationInitialise,
|
||||
hostCollatedFileOperationInitialise,
|
||||
word,
|
||||
hostCollated
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::labelList Foam::fileOperations::hostCollatedFileOperation::subRanks
|
||||
(
|
||||
const label n
|
||||
)
|
||||
{
|
||||
DynamicList<label> subRanks(64);
|
||||
|
||||
string ioRanksString(getEnv("FOAM_IORANKS"));
|
||||
if (!ioRanksString.empty())
|
||||
{
|
||||
IStringStream is(ioRanksString);
|
||||
labelList ioRanks(is);
|
||||
|
||||
if (findIndex(ioRanks, 0) == -1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Rank 0 (master) should be in the IO ranks. Currently "
|
||||
<< ioRanks << exit(FatalError);
|
||||
}
|
||||
|
||||
// The lowest numbered rank is the IO rank
|
||||
const bitSet isIOrank(n, ioRanks);
|
||||
|
||||
for (label proci = Pstream::myProcNo(); proci >= 0; --proci)
|
||||
{
|
||||
if (isIOrank[proci])
|
||||
{
|
||||
// Found my master. Collect all processors with same master
|
||||
subRanks.append(proci);
|
||||
for
|
||||
(
|
||||
label rank = proci+1;
|
||||
rank < n && !isIOrank[rank];
|
||||
++rank
|
||||
)
|
||||
{
|
||||
subRanks.append(rank);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal operation: one lowest rank per hostname is the writer
|
||||
const string myHostName(hostName());
|
||||
|
||||
stringList hosts(Pstream::nProcs());
|
||||
hosts[Pstream::myProcNo()] = myHostName;
|
||||
Pstream::gatherList(hosts);
|
||||
Pstream::scatterList(hosts);
|
||||
|
||||
// Collect procs with same hostname
|
||||
forAll(hosts, proci)
|
||||
{
|
||||
if (hosts[proci] == myHostName)
|
||||
{
|
||||
subRanks.append(proci);
|
||||
}
|
||||
}
|
||||
}
|
||||
return subRanks;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileOperations::hostCollatedFileOperation::hostCollatedFileOperation
|
||||
(
|
||||
const bool verbose
|
||||
)
|
||||
:
|
||||
collatedFileOperation
|
||||
(
|
||||
UPstream::allocateCommunicator
|
||||
(
|
||||
UPstream::worldComm,
|
||||
subRanks(Pstream::nProcs())
|
||||
),
|
||||
(Pstream::parRun() ? labelList(0) : ioRanks()), // processor dirs
|
||||
typeName,
|
||||
verbose
|
||||
)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
// Print a bit of information
|
||||
stringList ioRanks(Pstream::nProcs());
|
||||
if (Pstream::master(comm_))
|
||||
{
|
||||
ioRanks[Pstream::myProcNo()] = hostName()+"."+name(pid());
|
||||
}
|
||||
Pstream::gatherList(ioRanks);
|
||||
|
||||
Info<< " IO nodes:" << endl;
|
||||
forAll(ioRanks, proci)
|
||||
{
|
||||
if (!ioRanks[proci].empty())
|
||||
{
|
||||
Info<< " " << ioRanks[proci] << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileOperations::hostCollatedFileOperation::~hostCollatedFileOperation()
|
||||
{
|
||||
if (comm_ != -1 && comm_ != UPstream::worldComm)
|
||||
{
|
||||
UPstream::freeCommunicator(comm_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,134 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::fileOperations::hostCollatedFileOperation
|
||||
|
||||
Description
|
||||
Version of collatedFileOperation with multiple read/write ranks.
|
||||
|
||||
In parallel it will assume ranks are sorted according to hostname
|
||||
and the lowest rank per hostname will be the IO rank. The output directories
|
||||
will get a unique name processors<N>_<low>-<high> where N is the overall
|
||||
number of processors and low and high is the range of ranks contained
|
||||
in the files. Each of these subsets uses its own communicator.
|
||||
|
||||
Instead of using the hostnames the IO ranks can be assigned using the
|
||||
FOAM_IORANKS environment variable (also when running non-parallel), e.g.
|
||||
when decomposing into 4:
|
||||
|
||||
FOAM_IORANKS='(0 2)' decomposePar -fileHandler hostCollated
|
||||
|
||||
will generate
|
||||
|
||||
processors4_0-1/
|
||||
containing data for processors 0 to 1
|
||||
processors4_2-3/
|
||||
containing data for processors 2 to 3
|
||||
|
||||
See also
|
||||
collatedFileOperation
|
||||
|
||||
SourceFiles
|
||||
hostCollatedFileOperation.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fileOperations_hostCollatedFileOperation_H
|
||||
#define fileOperations_hostCollatedFileOperation_H
|
||||
|
||||
#include "collatedFileOperation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace fileOperations
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class hostCollatedFileOperation Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class hostCollatedFileOperation
|
||||
:
|
||||
public collatedFileOperation
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
//- Get the list of processors part of this set
|
||||
static labelList subRanks(const label n);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("hostCollated");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
hostCollatedFileOperation(const bool verbose);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~hostCollatedFileOperation();
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class hostCollatedFileOperationInitialise Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class hostCollatedFileOperationInitialise
|
||||
:
|
||||
public collatedFileOperationInitialise
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
hostCollatedFileOperationInitialise(int& argc, char**& argv)
|
||||
:
|
||||
collatedFileOperationInitialise(argc, argv)
|
||||
{}
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~hostCollatedFileOperationInitialise()
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace fileOperations
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -28,11 +28,11 @@ License
|
||||
#include "regIOobject.H"
|
||||
#include "argList.H"
|
||||
#include "HashSet.H"
|
||||
#include "masterUncollatedFileOperation.H"
|
||||
#include "objectRegistry.H"
|
||||
#include "decomposedBlockData.H"
|
||||
#include "polyMesh.H"
|
||||
#include "registerSwitch.H"
|
||||
#include "Time.H"
|
||||
|
||||
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
|
||||
|
||||
@ -43,6 +43,28 @@ namespace Foam
|
||||
defineTypeNameAndDebug(fileOperation, 0);
|
||||
defineRunTimeSelectionTable(fileOperation, word);
|
||||
|
||||
template<>
|
||||
const char* Foam::NamedEnum
|
||||
<
|
||||
fileOperation::pathType,
|
||||
12
|
||||
>::names[] =
|
||||
{
|
||||
"notFound",
|
||||
"absolute",
|
||||
"objectPath",
|
||||
"writeObject",
|
||||
"uncollatedProc",
|
||||
"globalProc",
|
||||
"localProc",
|
||||
"parentObjectPath",
|
||||
"findInstance",
|
||||
"uncollatedProcInstance",
|
||||
"globalProcInstance",
|
||||
"localProcInstance"
|
||||
};
|
||||
const NamedEnum<fileOperation::pathType, 12> fileOperation::pathTypeNames_;
|
||||
|
||||
word fileOperation::defaultFileHandler
|
||||
(
|
||||
debug::optimisationSwitches().lookupOrAddDefault
|
||||
@ -56,7 +78,7 @@ namespace Foam
|
||||
);
|
||||
}
|
||||
|
||||
Foam::word Foam::fileOperation::processorsDir = "processors";
|
||||
Foam::word Foam::fileOperation::processorsBaseDir = "processors";
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
@ -133,6 +155,80 @@ Foam::instantList Foam::fileOperation::sortTimes
|
||||
}
|
||||
|
||||
|
||||
void Foam::fileOperation::mergeTimes
|
||||
(
|
||||
const instantList& extraTimes,
|
||||
const word& constantName,
|
||||
instantList& times
|
||||
)
|
||||
{
|
||||
if (extraTimes.size())
|
||||
{
|
||||
bool haveConstant =
|
||||
(
|
||||
times.size() > 0
|
||||
&& times[0].name() == constantName
|
||||
);
|
||||
|
||||
bool haveExtraConstant =
|
||||
(
|
||||
extraTimes.size() > 0
|
||||
&& extraTimes[0].name() == constantName
|
||||
);
|
||||
|
||||
// Combine times
|
||||
instantList combinedTimes(times.size()+extraTimes.size());
|
||||
label sz = 0;
|
||||
label extrai = 0;
|
||||
if (haveExtraConstant)
|
||||
{
|
||||
extrai = 1;
|
||||
if (!haveConstant)
|
||||
{
|
||||
combinedTimes[sz++] = extraTimes[0]; // constant
|
||||
}
|
||||
}
|
||||
forAll(times, i)
|
||||
{
|
||||
combinedTimes[sz++] = times[i];
|
||||
}
|
||||
for (; extrai < extraTimes.size(); extrai++)
|
||||
{
|
||||
combinedTimes[sz++] = extraTimes[extrai];
|
||||
}
|
||||
combinedTimes.setSize(sz);
|
||||
times.transfer(combinedTimes);
|
||||
|
||||
// Sort
|
||||
if (times.size() > 1)
|
||||
{
|
||||
label starti = 0;
|
||||
if (times[0].name() == constantName)
|
||||
{
|
||||
starti = 1;
|
||||
}
|
||||
std::sort(×[starti], times.end(), instant::less());
|
||||
|
||||
// Filter out duplicates
|
||||
label newi = starti+1;
|
||||
for (label i = newi; i < times.size(); i++)
|
||||
{
|
||||
if (times[i].value() != times[i-1].value())
|
||||
{
|
||||
if (newi != i)
|
||||
{
|
||||
times[newi] = times[i];
|
||||
}
|
||||
newi++;
|
||||
}
|
||||
}
|
||||
|
||||
times.setSize(newi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::fileOperation::isFileOrDir(const bool isFile, const fileName& f)
|
||||
{
|
||||
return
|
||||
@ -141,8 +237,182 @@ bool Foam::fileOperation::isFileOrDir(const bool isFile, const fileName& f)
|
||||
}
|
||||
|
||||
|
||||
Foam::tmpNrc<Foam::fileOperation::dirIndexList>
|
||||
Foam::fileOperation::lookupProcessorsPath(const fileName& fName) const
|
||||
{
|
||||
// If path is local to a processor (e.g. contains 'processor2')
|
||||
// find the corresponding actual processor directory (e.g. 'processors4')
|
||||
// and index (2)
|
||||
|
||||
fileName path;
|
||||
fileName pDir;
|
||||
fileName local;
|
||||
label gStart;
|
||||
label gSz;
|
||||
label numProcs;
|
||||
label proci =
|
||||
splitProcessorPath(fName, path, pDir, local, gStart, gSz, numProcs);
|
||||
|
||||
if (proci != -1)
|
||||
{
|
||||
const fileName procPath(path/pDir);
|
||||
|
||||
HashTable<dirIndexList>::const_iterator iter =
|
||||
procsDirs_.find(procPath);
|
||||
|
||||
if (iter != procsDirs_.end())
|
||||
{
|
||||
return iter();
|
||||
}
|
||||
|
||||
// Read all directories to see any beginning with processor
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
DynamicList<dirIndex> procDirs;
|
||||
|
||||
// Note: use parallel synchronised reading so cache will be same
|
||||
// order on all processors
|
||||
fileNameList dirNames(readDir(path, fileName::Type::DIRECTORY));
|
||||
|
||||
// Extract info from processorsDDD or processorDDD:
|
||||
// - highest processor number
|
||||
// - directory+offset containing data for proci
|
||||
label maxProc = -1;
|
||||
|
||||
forAll(dirNames, i)
|
||||
{
|
||||
const fileName& dirN = dirNames[i];
|
||||
|
||||
// Analyse directory name
|
||||
fileName rp, rd, rl;
|
||||
label rStart, rSize, rNum;
|
||||
label readProci =
|
||||
splitProcessorPath(dirN, rp, rd, rl, rStart, rSize, rNum);
|
||||
maxProc = max(maxProc, readProci);
|
||||
|
||||
if (proci == readProci)
|
||||
{
|
||||
// Found "processorDDD". No need for index.
|
||||
procDirs.append
|
||||
(
|
||||
dirIndex
|
||||
(
|
||||
dirN,
|
||||
Tuple2<pathType, label>(PROCUNCOLLATED, -1)
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (proci >= rStart && proci < rStart+rSize)
|
||||
{
|
||||
// "processorsDDD_start-end"
|
||||
// Found the file that contains the data for proci
|
||||
procDirs.append
|
||||
(
|
||||
dirIndex
|
||||
(
|
||||
dirN,
|
||||
Tuple2<pathType, label>(PROCOBJECT, proci-rStart)
|
||||
)
|
||||
);
|
||||
}
|
||||
if (rNum != -1)
|
||||
{
|
||||
// Direct detection of processorsDDD
|
||||
maxProc = rNum-1;
|
||||
|
||||
if (rStart == -1)
|
||||
{
|
||||
// "processorsDDD"
|
||||
procDirs.append
|
||||
(
|
||||
dirIndex
|
||||
(
|
||||
dirN,
|
||||
Tuple2<pathType, label>(PROCBASEOBJECT, proci)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!Pstream::parRun())
|
||||
{
|
||||
// If (as a side effect) we found the number of decompositions
|
||||
// use it
|
||||
if (maxProc != -1)
|
||||
{
|
||||
const_cast<fileOperation&>(*this).setNProcs(maxProc+1);
|
||||
}
|
||||
}
|
||||
|
||||
if (returnReduce(procDirs.size(), sumOp<label>()))
|
||||
{
|
||||
procsDirs_.insert(procPath, procDirs);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "fileOperation::lookupProcessorsPath : For:" << procPath
|
||||
<< " detected:" << procDirs << endl;
|
||||
}
|
||||
|
||||
// Make sure to return a reference
|
||||
return procsDirs_[procPath];
|
||||
}
|
||||
}
|
||||
return tmpNrc<dirIndexList>(new dirIndexList(0, dirIndex()));
|
||||
}
|
||||
|
||||
|
||||
bool Foam::fileOperation::exists(IOobject& io) const
|
||||
{
|
||||
// Generate output filename for object
|
||||
fileName objPath(objectPath(io, word::null));
|
||||
|
||||
// Test for either directory or a (valid) file & IOobject
|
||||
bool ok;
|
||||
if (io.name().empty())
|
||||
{
|
||||
ok = isDir(objPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
ok =
|
||||
isFile(objPath)
|
||||
&& io.typeHeaderOk<IOList<label>>(false);// object with local scope
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
// Re-test with searched for objectPath. This is for backwards
|
||||
// compatibility
|
||||
fileName originalPath(filePath(io.objectPath()));
|
||||
if (originalPath != objPath)
|
||||
{
|
||||
// Test for either directory or a (valid) file & IOobject
|
||||
if (io.name().empty())
|
||||
{
|
||||
ok = isDir(originalPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
ok =
|
||||
isFile(originalPath)
|
||||
&& io.typeHeaderOk<IOList<label>>(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileOperation::fileOperation(label comm)
|
||||
:
|
||||
comm_(comm)
|
||||
{}
|
||||
|
||||
|
||||
Foam::autoPtr<Foam::fileOperation> Foam::fileOperation::New
|
||||
(
|
||||
const word& handlerType,
|
||||
@ -238,37 +508,64 @@ bool Foam::fileOperation::writeObject
|
||||
}
|
||||
|
||||
|
||||
//Foam::fileName Foam::fileOperation::objectPath(const fileName& fName) const
|
||||
//{
|
||||
// return fName;
|
||||
//}
|
||||
|
||||
|
||||
Foam::fileName Foam::fileOperation::filePath(const fileName& fName) const
|
||||
{
|
||||
fileName path;
|
||||
fileName local;
|
||||
label proci = fileOperations::masterUncollatedFileOperation::
|
||||
splitProcessorPath
|
||||
(
|
||||
fName,
|
||||
path,
|
||||
local
|
||||
);
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "fileOperation::filePath :" << " fName:" << fName << endl;
|
||||
}
|
||||
|
||||
fileName procsName(path/processorsDir/local);
|
||||
fileName path;
|
||||
fileName pDir;
|
||||
fileName local;
|
||||
label gStart;
|
||||
label gSz;
|
||||
label numProcs;
|
||||
label proci =
|
||||
splitProcessorPath(fName, path, pDir, local, gStart, gSz, numProcs);
|
||||
|
||||
if (numProcs != -1)
|
||||
{
|
||||
WarningInFunction << "Filename is already adapted:" << fName << endl;
|
||||
}
|
||||
|
||||
// Give preference to processors variant
|
||||
if (proci != -1 && exists(procsName))
|
||||
if (proci != -1)
|
||||
{
|
||||
return procsName;
|
||||
}
|
||||
else if (exists(fName))
|
||||
{
|
||||
return fName;
|
||||
// Get all processor directories
|
||||
tmpNrc<dirIndexList> procDirs(lookupProcessorsPath(fName));
|
||||
forAll(procDirs(), i)
|
||||
{
|
||||
const fileName& procDir = procDirs()[i].first();
|
||||
|
||||
fileName collatedName(path/procDir/local);
|
||||
if (exists(collatedName))
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "fileOperation::filePath : " << collatedName << endl;
|
||||
}
|
||||
return collatedName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fileName::null;
|
||||
if (exists(fName))
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "fileOperation::filePath : " << fName << endl;
|
||||
}
|
||||
return fName;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "fileOperation::filePath : Not found" << endl;
|
||||
}
|
||||
return fileName::null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -377,8 +674,8 @@ Foam::instantList Foam::fileOperation::findTimes
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME
|
||||
<< " : Finding times in directory " << directory << endl;
|
||||
Pout<< "fileOperation::findTimes : Finding times in directory "
|
||||
<< directory << endl;
|
||||
}
|
||||
|
||||
// Read directory entries into a list
|
||||
@ -393,103 +690,188 @@ Foam::instantList Foam::fileOperation::findTimes
|
||||
|
||||
instantList times = sortTimes(dirEntries, constantName);
|
||||
|
||||
// Check if directory is processorXXX
|
||||
fileName procsDir
|
||||
(
|
||||
fileOperations::masterUncollatedFileOperation::processorsPath
|
||||
(
|
||||
directory
|
||||
)
|
||||
);
|
||||
|
||||
if (!procsDir.empty() && procsDir != directory)
|
||||
// Get all processor directories
|
||||
tmpNrc<dirIndexList> procDirs(lookupProcessorsPath(directory));
|
||||
forAll(procDirs(), i)
|
||||
{
|
||||
fileNameList extraEntries
|
||||
(
|
||||
Foam::readDir
|
||||
(
|
||||
procsDir,
|
||||
fileName::DIRECTORY
|
||||
)
|
||||
);
|
||||
|
||||
instantList extraTimes = sortTimes(extraEntries, constantName);
|
||||
|
||||
if (extraTimes.size())
|
||||
const fileName& procDir = procDirs()[i].first();
|
||||
fileName collDir(processorsPath(directory, procDir));
|
||||
if (!collDir.empty() && collDir != directory)
|
||||
{
|
||||
bool haveConstant =
|
||||
fileNameList extraEntries
|
||||
(
|
||||
times.size() > 0
|
||||
&& times[0].name() == constantName
|
||||
Foam::readDir
|
||||
(
|
||||
collDir,
|
||||
fileName::DIRECTORY
|
||||
)
|
||||
);
|
||||
|
||||
bool haveExtraConstant =
|
||||
mergeTimes
|
||||
(
|
||||
extraTimes.size() > 0
|
||||
&& extraTimes[0].name() == constantName
|
||||
sortTimes(extraEntries, constantName),
|
||||
constantName,
|
||||
times
|
||||
);
|
||||
|
||||
// Combine times
|
||||
instantList combinedTimes(times.size()+extraTimes.size());
|
||||
label sz = 0;
|
||||
label extrai = 0;
|
||||
if (haveExtraConstant)
|
||||
{
|
||||
extrai = 1;
|
||||
if (!haveConstant)
|
||||
{
|
||||
combinedTimes[sz++] = extraTimes[0]; // constant
|
||||
}
|
||||
}
|
||||
forAll(times, i)
|
||||
{
|
||||
combinedTimes[sz++] = times[i];
|
||||
}
|
||||
for (; extrai < extraTimes.size(); extrai++)
|
||||
{
|
||||
combinedTimes[sz++] = extraTimes[extrai];
|
||||
}
|
||||
combinedTimes.setSize(sz);
|
||||
times.transfer(combinedTimes);
|
||||
|
||||
// Sort
|
||||
if (times.size() > 1)
|
||||
{
|
||||
label starti = 0;
|
||||
if (times[0].name() == constantName)
|
||||
{
|
||||
starti = 1;
|
||||
}
|
||||
std::sort(×[starti], times.end(), instant::less());
|
||||
|
||||
// Filter out duplicates
|
||||
label newi = starti+1;
|
||||
for (label i = newi; i < times.size(); i++)
|
||||
{
|
||||
if (times[i].value() != times[i-1].value())
|
||||
{
|
||||
if (newi != i)
|
||||
{
|
||||
times[newi] = times[i];
|
||||
}
|
||||
newi++;
|
||||
}
|
||||
}
|
||||
|
||||
times.setSize(newi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< FUNCTION_NAME
|
||||
<< " : Found times:" << times << endl;
|
||||
Pout<< "fileOperation::findTimes : Found times:" << times << endl;
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
|
||||
Foam::IOobject Foam::fileOperation::findInstance
|
||||
(
|
||||
const IOobject& startIO,
|
||||
const scalar startValue,
|
||||
const word& stopInstance
|
||||
) const
|
||||
{
|
||||
const Time& time = startIO.time();
|
||||
|
||||
IOobject io(startIO);
|
||||
|
||||
// Note: - if name is empty, just check the directory itself
|
||||
// - check both for isFile and headerOk since the latter does a
|
||||
// filePath so searches for the file.
|
||||
// - check for an object with local file scope (so no looking up in
|
||||
// parent directory in case of parallel)
|
||||
|
||||
if (exists(io))
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction
|
||||
<< "Found exact match for \"" << io.name()
|
||||
<< "\" in " << io.instance()/io.local()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
// Search back through the time directories to find the time
|
||||
// closest to and lower than current time
|
||||
|
||||
instantList ts = time.times();
|
||||
label instanceI;
|
||||
|
||||
for (instanceI = ts.size()-1; instanceI >= 0; --instanceI)
|
||||
{
|
||||
if (ts[instanceI].value() <= startValue)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// continue searching from here
|
||||
for (; instanceI >= 0; --instanceI)
|
||||
{
|
||||
// Shortcut: if actual directory is the timeName we've already tested it
|
||||
if (ts[instanceI].name() == startIO.instance())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
io.instance() = ts[instanceI].name();
|
||||
if (exists(io))
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction
|
||||
<< "Found exact match for \"" << io.name()
|
||||
<< "\" in " << io.instance()/io.local()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
// Check if hit minimum instance
|
||||
if (ts[instanceI].name() == stopInstance)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction
|
||||
<< "Hit stopInstance " << stopInstance << endl;
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
startIO.readOpt() == IOobject::MUST_READ
|
||||
|| startIO.readOpt() == IOobject::MUST_READ_IF_MODIFIED
|
||||
)
|
||||
{
|
||||
if (io.name().empty())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot find directory "
|
||||
<< io.local() << " in times " << startIO.instance()
|
||||
<< " down to " << stopInstance
|
||||
<< exit(FatalError);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot find file \"" << io.name()
|
||||
<< "\" in directory " << io.local()
|
||||
<< " in times " << startIO.instance()
|
||||
<< " down to " << stopInstance
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
return io;
|
||||
}
|
||||
}
|
||||
|
||||
// times() usually already includes the constant() so would have been
|
||||
// checked above. Re-test if
|
||||
// - times() is empty. Sometimes this can happen (e.g. decomposePar with
|
||||
// collated)
|
||||
// - times()[0] is not constant
|
||||
if (!ts.size() || ts[0].name() != time.constant())
|
||||
{
|
||||
// Note. This needs to be a hard-coded constant, rather than the
|
||||
// constant function of the time, because the latter points to
|
||||
// the case constant directory in parallel cases
|
||||
|
||||
io.instance() = time.constant();
|
||||
if (exists(io))
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction
|
||||
<< "Found constant match for \"" << io.name()
|
||||
<< "\" in " << io.instance()/io.local()
|
||||
<< endl;
|
||||
}
|
||||
return io;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if
|
||||
(
|
||||
startIO.readOpt() == IOobject::MUST_READ
|
||||
|| startIO.readOpt() == IOobject::MUST_READ_IF_MODIFIED
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot find file \"" << io.name() << "\" in directory "
|
||||
<< io.local() << " in times " << startIO.instance()
|
||||
<< " down to " << time.constant()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
|
||||
Foam::fileNameList Foam::fileOperation::readObjects
|
||||
(
|
||||
const objectRegistry& db,
|
||||
@ -518,19 +900,9 @@ Foam::fileNameList Foam::fileOperation::readObjects
|
||||
else
|
||||
{
|
||||
// Get processors equivalent of path
|
||||
fileName procsPath(filePath(path));
|
||||
|
||||
fileName prefix;
|
||||
fileName postfix;
|
||||
label proci = fileOperations::masterUncollatedFileOperation::
|
||||
splitProcessorPath
|
||||
(
|
||||
path,
|
||||
prefix,
|
||||
postfix
|
||||
);
|
||||
fileName procsPath(prefix/processorsDir/postfix);
|
||||
|
||||
if (proci != -1 && Foam::isDir(procsPath))
|
||||
if (!procsPath.empty())
|
||||
{
|
||||
newInstance = instance;
|
||||
objectNames = Foam::readDir(procsPath, fileName::FILE);
|
||||
@ -540,46 +912,252 @@ Foam::fileNameList Foam::fileOperation::readObjects
|
||||
}
|
||||
|
||||
|
||||
void Foam::fileOperation::setNProcs(const label nProcs)
|
||||
{}
|
||||
|
||||
|
||||
Foam::label Foam::fileOperation::nProcs
|
||||
(
|
||||
const fileName& dir,
|
||||
const fileName& local
|
||||
) const
|
||||
{
|
||||
if (Foam::isDir(dir/processorsDir))
|
||||
label nProcs = 0;
|
||||
if (Pstream::master(comm_))
|
||||
{
|
||||
fileName pointsFile
|
||||
(
|
||||
dir
|
||||
/processorsDir
|
||||
/"constant"
|
||||
/local
|
||||
/polyMesh::meshSubDir
|
||||
/"points"
|
||||
);
|
||||
fileNameList dirNames(Foam::readDir(dir, fileName::Type::DIRECTORY));
|
||||
|
||||
if (Foam::isFile(pointsFile))
|
||||
// Detect any processorsDDD or processorDDD
|
||||
label maxProc = -1;
|
||||
forAll(dirNames, i)
|
||||
{
|
||||
return decomposedBlockData::numBlocks(pointsFile);
|
||||
const fileName& dirN = dirNames[i];
|
||||
|
||||
fileName path, pDir, local;
|
||||
label start, size, n;
|
||||
maxProc = max
|
||||
(
|
||||
maxProc,
|
||||
splitProcessorPath(dirN, path, pDir, local, start, size, n)
|
||||
);
|
||||
if (n != -1)
|
||||
{
|
||||
// Direct detection of processorsDDD
|
||||
maxProc = n-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
nProcs = maxProc+1;
|
||||
|
||||
|
||||
if (nProcs == 0 && Foam::isDir(dir/processorsBaseDir))
|
||||
{
|
||||
fileName pointsFile
|
||||
(
|
||||
dir
|
||||
/processorsBaseDir
|
||||
/"constant"
|
||||
/local
|
||||
/polyMesh::meshSubDir
|
||||
/"points"
|
||||
);
|
||||
|
||||
if (Foam::isFile(pointsFile))
|
||||
{
|
||||
nProcs = decomposedBlockData::numBlocks(pointsFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
WarningInFunction << "Cannot read file " << pointsFile
|
||||
<< " to determine the number of decompositions."
|
||||
<< " Returning 1" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
Pstream::scatter(nProcs, Pstream::msgType(), comm_);
|
||||
return nProcs;
|
||||
}
|
||||
|
||||
|
||||
Foam::fileName Foam::fileOperation::processorsCasePath
|
||||
(
|
||||
const IOobject& io,
|
||||
const word& procsDir
|
||||
) const
|
||||
{
|
||||
return io.rootPath()/io.time().globalCaseName()/procsDir;
|
||||
}
|
||||
|
||||
|
||||
Foam::fileName Foam::fileOperation::processorsPath
|
||||
(
|
||||
const IOobject& io,
|
||||
const word& instance,
|
||||
const word& procsDir
|
||||
) const
|
||||
{
|
||||
return
|
||||
processorsCasePath(io, procsDir)
|
||||
/instance
|
||||
/io.db().dbDir()
|
||||
/io.local();
|
||||
}
|
||||
|
||||
|
||||
Foam::fileName Foam::fileOperation::processorsPath
|
||||
(
|
||||
const fileName& dir,
|
||||
const word& procsDir
|
||||
) const
|
||||
{
|
||||
// Check if directory is processorDDD
|
||||
word caseName(dir.name());
|
||||
|
||||
std::string::size_type pos = caseName.find("processor");
|
||||
if (pos == 0)
|
||||
{
|
||||
if (caseName.size() <= 9 || caseName[9] == 's')
|
||||
{
|
||||
WarningInFunction << "Directory " << dir
|
||||
<< " does not end in old-style processorDDD" << endl;
|
||||
}
|
||||
|
||||
return dir.path()/procsDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
return fileName::null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::fileOperation::splitProcessorPath
|
||||
(
|
||||
const fileName& objectPath,
|
||||
fileName& path,
|
||||
fileName& procDir,
|
||||
fileName& local,
|
||||
|
||||
label& groupStart,
|
||||
label& groupSize,
|
||||
|
||||
label& nProcs
|
||||
)
|
||||
{
|
||||
path.clear();
|
||||
procDir.clear();
|
||||
local.clear();
|
||||
|
||||
// Potentially detected start of number of processors in local group
|
||||
groupStart = -1;
|
||||
groupSize = 0;
|
||||
|
||||
// Potentially detected number of processors
|
||||
nProcs = -1;
|
||||
|
||||
// Search for processor at start of line or /processor
|
||||
std::string::size_type pos = objectPath.find("processor");
|
||||
if (pos == string::npos)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// "processorDDD"
|
||||
// "processorsNNN"
|
||||
// "processorsNNN_AA-BB"
|
||||
|
||||
|
||||
if (pos > 0 && objectPath[pos-1] != '/')
|
||||
{
|
||||
// Directory not starting with "processor" e.g. "somenamewithprocessor"
|
||||
return -1;
|
||||
}
|
||||
|
||||
procDir = objectPath;
|
||||
|
||||
// Strip leading directory
|
||||
if (pos > 0)
|
||||
{
|
||||
path = objectPath.substr(0, pos-1);
|
||||
procDir = objectPath.substr(pos);
|
||||
}
|
||||
|
||||
// Strip trailing local directory
|
||||
pos = procDir.find('/');
|
||||
if (pos != string::npos)
|
||||
{
|
||||
local = procDir.substr(pos+1);
|
||||
procDir = procDir.substr(0, pos);
|
||||
}
|
||||
|
||||
// Now procDir is e.g.
|
||||
// - processor0
|
||||
// - processors0
|
||||
// - processorBananas
|
||||
|
||||
// Look for number after "processor"
|
||||
|
||||
fileName f(procDir.substr(9));
|
||||
|
||||
if (f.size() && f[0] == 's')
|
||||
{
|
||||
// "processsorsNNN"
|
||||
|
||||
f = f.substr(1);
|
||||
|
||||
// Detect "processorsNNN_AA-BB"
|
||||
{
|
||||
std::string::size_type fromStart = f.find("_");
|
||||
std::string::size_type toStart = f.find("-");
|
||||
if (fromStart != string::npos && toStart != string::npos)
|
||||
{
|
||||
string nProcsName(f.substr(0, fromStart));
|
||||
string fromName(f.substr(fromStart+1, toStart-(fromStart+1)));
|
||||
string toName(f.substr(toStart+1));
|
||||
|
||||
label groupEnd = -1;
|
||||
if
|
||||
(
|
||||
Foam::read(fromName.c_str(), groupStart)
|
||||
&& Foam::read(toName.c_str(), groupEnd)
|
||||
&& Foam::read(nProcsName.c_str(), nProcs)
|
||||
)
|
||||
{
|
||||
groupSize = groupEnd-groupStart+1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Detect "processorsN"
|
||||
label n;
|
||||
if (Foam::read(f.c_str(), n))
|
||||
{
|
||||
nProcs = n;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Detect "processorN"
|
||||
label proci;
|
||||
if (Foam::read(f.c_str(), proci))
|
||||
{
|
||||
return proci;
|
||||
}
|
||||
else
|
||||
{
|
||||
WarningInFunction << "Cannot read file " << pointsFile
|
||||
<< " to determine the number of decompositions."
|
||||
<< " Falling back to looking for processor.*" << endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
label nProcs = 0;
|
||||
while
|
||||
(
|
||||
isDir(dir/(word("processor") + name(nProcs)))
|
||||
)
|
||||
{
|
||||
++nProcs;
|
||||
}
|
||||
|
||||
return nProcs;
|
||||
Foam::label Foam::fileOperation::detectProcessorPath(const fileName& fName)
|
||||
{
|
||||
fileName path, pDir, local;
|
||||
label start, size, nProcs;
|
||||
return splitProcessorPath(fName, path, pDir, local, start, size, nProcs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -45,6 +45,10 @@ Description
|
||||
#include "instantList.H"
|
||||
#include "fileMonitor.H"
|
||||
#include "labelList.H"
|
||||
#include "Switch.H"
|
||||
#include "tmpNrc.H"
|
||||
#include "NamedEnum.H"
|
||||
#include "Tuple2.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -56,16 +60,55 @@ class regIOobject;
|
||||
class objectRegistry;
|
||||
class Time;
|
||||
|
||||
// Description of processor directory naming:
|
||||
// - processor directory naming
|
||||
// - whether directory contains a range (so differs on different processors)
|
||||
// - index in range
|
||||
//typedef Tuple2<fileName, Tuple2<bool, label>> dirIndex;
|
||||
//typedef List<dirIndex> dirIndexList;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class fileOperation Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class fileOperation
|
||||
{
|
||||
public:
|
||||
|
||||
//- Enumeration for the location of an IOobject
|
||||
enum pathType
|
||||
{
|
||||
NOTFOUND, // not found
|
||||
ABSOLUTE, // instance is absolute directory
|
||||
OBJECT, // io.objectPath() exists
|
||||
WRITEOBJECT, // write path exists
|
||||
PROCUNCOLLATED, // objectPath exists in processor0
|
||||
PROCBASEOBJECT, // objectPath exists in specified, constant
|
||||
// processorsDir (usually 'processorsDDD')
|
||||
PROCOBJECT, // objectPath exists in locally differing
|
||||
// processorsDir (e.g. 'processorsDDD_0-1')
|
||||
PARENTOBJECT, // parent of object path
|
||||
FINDINSTANCE, // file found in time directory
|
||||
PROCUNCOLLATEDINSTANCE, // as PROCUNCOLLATED but with instance
|
||||
PROCBASEINSTANCE, // as PROCBASEOBJECT but with instance
|
||||
PROCINSTANCE // as PROCOBJECT but with instance
|
||||
};
|
||||
static const NamedEnum<pathType, 12> pathTypeNames_;
|
||||
|
||||
typedef Tuple2<fileName, Tuple2<pathType, label>> dirIndex;
|
||||
typedef List<dirIndex> dirIndexList;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Communicator to use
|
||||
const label comm_;
|
||||
|
||||
//- Detected processors directories
|
||||
mutable HashTable<dirIndexList> procsDirs_;
|
||||
|
||||
//- file-change monitor for all registered files
|
||||
mutable autoPtr<fileMonitor> monitorPtr_;
|
||||
|
||||
@ -77,15 +120,35 @@ protected:
|
||||
//- Sort directory entries according to time value
|
||||
static instantList sortTimes(const fileNameList&, const word&);
|
||||
|
||||
//- Merge two times
|
||||
static void mergeTimes
|
||||
(
|
||||
const instantList& extraTimes,
|
||||
const word& constantName,
|
||||
instantList& times
|
||||
);
|
||||
|
||||
//- Helper: check for file (isFile) or directory (!isFile)
|
||||
static bool isFileOrDir(const bool isFile, const fileName&);
|
||||
|
||||
//- Detect presence of processorsDDD
|
||||
void cacheProcessorsPath(const fileName& fName) const;
|
||||
|
||||
//- Lookup name of processorsDDD using cache. Return empty fileName
|
||||
// if not found
|
||||
tmpNrc<dirIndexList> lookupProcessorsPath(const fileName&) const;
|
||||
|
||||
//- Does ioobject exist. Is either a directory (empty name()) or
|
||||
// a file
|
||||
bool exists(IOobject& io) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Static data
|
||||
|
||||
//- The processors directory name (usually "processors")
|
||||
static word processorsDir;
|
||||
//- Return the processors directory name (usually "processors")
|
||||
static word processorsBaseDir;
|
||||
|
||||
//- Default fileHandler
|
||||
static word defaultFileHandler;
|
||||
@ -93,19 +156,6 @@ public:
|
||||
|
||||
// Public data types
|
||||
|
||||
//- Enumeration for the location of an IOobject
|
||||
enum pathType
|
||||
{
|
||||
NOTFOUND, // not found
|
||||
ABSOLUTE, // instance is absolute directory
|
||||
OBJECT, // objectPath exists
|
||||
PROCESSORSOBJECT, // objectPath exists in processors/
|
||||
PARENTOBJECT, // parent of object path
|
||||
FINDINSTANCE, // file found in time directory
|
||||
PROCESSORSFINDINSTANCE // as above but in processors/
|
||||
};
|
||||
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("fileOperation");
|
||||
|
||||
@ -116,8 +166,8 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
fileOperation() = default;
|
||||
//- Construct from communicator
|
||||
explicit fileOperation(const label comm);
|
||||
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
@ -413,6 +463,24 @@ public:
|
||||
|
||||
// Other
|
||||
|
||||
//- Actual name of processors dir (for use in mode PROCOBJECT,
|
||||
// PROCINSTANCE)
|
||||
virtual word processorsDir(const IOobject& io) const
|
||||
{
|
||||
return processorsBaseDir;
|
||||
}
|
||||
|
||||
//- Actual name of processors dir (for use in mode PROCOBJECT,
|
||||
// PROCINSTANCE)
|
||||
virtual word processorsDir(const fileName&) const
|
||||
{
|
||||
return processorsBaseDir;
|
||||
}
|
||||
|
||||
//- Set number of processor directories/results. Only used in
|
||||
// decomposePar
|
||||
virtual void setNProcs(const label nProcs);
|
||||
|
||||
//- Get number of processor directories/results. Used for e.g.
|
||||
// reconstructPar, argList checking
|
||||
virtual label nProcs
|
||||
@ -424,9 +492,59 @@ public:
|
||||
//- Get sorted list of times
|
||||
virtual instantList findTimes(const fileName&, const word&) const;
|
||||
|
||||
//- Find instance where IOobject is. Fails if cannot be found
|
||||
// and readOpt() is MUST_READ/MUST_READ_IF_MODIFIED. Otherwise
|
||||
// returns stopInstance.
|
||||
virtual IOobject findInstance
|
||||
(
|
||||
const IOobject& io,
|
||||
const scalar startValue,
|
||||
const word& stopInstance
|
||||
) const;
|
||||
|
||||
//- Callback for time change
|
||||
virtual void setTime(const Time&) const
|
||||
{}
|
||||
|
||||
//- Generate path (like io.path) from root+casename with any
|
||||
// 'processorXXX' replaced by procDir (usually 'processsors')
|
||||
fileName processorsCasePath
|
||||
(
|
||||
const IOobject&,
|
||||
const word& procDir
|
||||
) const;
|
||||
|
||||
//- Generate path (like io.path) with provided instance and any
|
||||
// 'processorXXX' replaced by procDir (usually 'processsors')
|
||||
fileName processorsPath
|
||||
(
|
||||
const IOobject&,
|
||||
const word& instance,
|
||||
const word& procDir
|
||||
) const;
|
||||
|
||||
//- Operating on fileName: replace processorXXX with procDir
|
||||
fileName processorsPath(const fileName&, const word& procDir) const;
|
||||
|
||||
//- Split fileName into part before 'processor' and part after.
|
||||
// Returns -1 or processor number and optionally number
|
||||
// of processors. Use with care.
|
||||
// - path/"processor"+Foam::name(proci)/local reconstructs input
|
||||
// - path/"processors"+Foam::name(nProcs)/local reconstructs
|
||||
// collated processors equivalence
|
||||
static label splitProcessorPath
|
||||
(
|
||||
const fileName&,
|
||||
fileName& path,
|
||||
fileName& procDir,
|
||||
fileName& local,
|
||||
label& groupStart,
|
||||
label& groupSize,
|
||||
label& nProcs
|
||||
);
|
||||
|
||||
//- Detect processor number from '/aa/bb/processorDDD/cc'
|
||||
static label detectProcessorPath(const fileName&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fileOperationInitialise.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "OSspecific.H"
|
||||
|
||||
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace fileOperations
|
||||
{
|
||||
defineTypeNameAndDebug(fileOperationInitialise, 0);
|
||||
defineRunTimeSelectionTable(fileOperationInitialise, word);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileOperations::fileOperationInitialise::fileOperationInitialise
|
||||
(
|
||||
int& argc,
|
||||
char**& argv
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
Foam::autoPtr<Foam::fileOperations::fileOperationInitialise>
|
||||
Foam::fileOperations::fileOperationInitialise::New
|
||||
(
|
||||
const word& type,
|
||||
int& argc,
|
||||
char**& argv
|
||||
)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction << "Constructing fileOperationInitialise" << endl;
|
||||
}
|
||||
|
||||
wordConstructorTable::iterator cstrIter =
|
||||
wordConstructorTablePtr_->find(type);
|
||||
|
||||
if (cstrIter == wordConstructorTablePtr_->end())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Unknown fileOperationInitialise type "
|
||||
<< type << nl << nl
|
||||
<< "Valid fileOperationInitialise types are" << endl
|
||||
<< wordConstructorTablePtr_->sortedToc()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
return autoPtr<fileOperationInitialise>(cstrIter()(argc, argv));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileOperations::fileOperationInitialise::~fileOperationInitialise()
|
||||
{}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,102 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::fileOperationInitialise
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fileOperationInitialise_H
|
||||
#define fileOperationInitialise_H
|
||||
|
||||
#include "runTimeSelectionTables.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace fileOperations
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class fileOperationInitialise Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class fileOperationInitialise
|
||||
{
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("fileOperationInitialise");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct components
|
||||
fileOperationInitialise(int& argc, char**& argv);
|
||||
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
fileOperationInitialise,
|
||||
word,
|
||||
(
|
||||
int& argc, char**& argv
|
||||
),
|
||||
(argc, argv)
|
||||
);
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Select type
|
||||
static autoPtr<fileOperationInitialise> New
|
||||
(
|
||||
const word& type, int& argc, char**& argv
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~fileOperationInitialise();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Needs threading
|
||||
virtual bool needsThreading() const = 0;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace fileOperations
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,84 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::unthreadedInitialise
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef unthreadedInitialise_H
|
||||
#define unthreadedInitialise_H
|
||||
|
||||
#include "fileOperationInitialise.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace fileOperations
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class unthreadedInitialise Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class unthreadedInitialise
|
||||
:
|
||||
public fileOperationInitialise
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
unthreadedInitialise(int& argc, char**& argv)
|
||||
:
|
||||
fileOperationInitialise(argc, argv)
|
||||
{}
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~unthreadedInitialise()
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Needs threading
|
||||
virtual bool needsThreading() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace fileOperations
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,31 @@ Description
|
||||
fileOperations that performs all file operations on the master processor.
|
||||
Requires the calls to be parallel synchronised!
|
||||
|
||||
Limitations: - no /processor in filename
|
||||
- no /uniform/ in the filename
|
||||
|
||||
The main logic is in ::filePath which returns a
|
||||
- same path on all processors. This can either be a global file
|
||||
(system/controlDict, processorXXX/0/uniform/) or a collated file
|
||||
(processors/0/p)
|
||||
- same path on all processors of the local communicator
|
||||
(processors4_0-1/0/p)
|
||||
- different path on all processors (processor0/0/p)
|
||||
|
||||
system/controlDict:
|
||||
filePath worldmaster: <globalRoot>/system/controlDict
|
||||
localmaster: ,,
|
||||
slave : ,,
|
||||
|
||||
processor0/uniform/time
|
||||
filePath worldmaster: <globalRoot>/processorXXX/uniform/time
|
||||
localmaster: ,,
|
||||
slave : ,,
|
||||
|
||||
processors0/0/p
|
||||
processors10/0/p
|
||||
processors10_2-4/0/p
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fileOperations_masterUncollatedFileOperation_H
|
||||
@ -36,6 +61,9 @@ Description
|
||||
#include "fileOperation.H"
|
||||
#include "OSspecific.H"
|
||||
#include "HashPtrTable.H"
|
||||
#include "Switch.H"
|
||||
#include "unthreadedInitialise.H"
|
||||
#include "boolList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -59,6 +87,9 @@ protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Any communicator allocated by me
|
||||
const label myComm_;
|
||||
|
||||
//- Cached times for a given directory
|
||||
mutable HashPtrTable<instantList> times_;
|
||||
|
||||
@ -354,18 +385,29 @@ protected:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Get the list of processors that are part of this communicator
|
||||
static labelList subRanks(const label n);
|
||||
|
||||
template<class Type>
|
||||
Type scatterList(const UList<Type>&) const;
|
||||
Type scatterList(const UList<Type>&, const int, const label comm) const;
|
||||
|
||||
template<class Type, class fileOp>
|
||||
Type masterOp(const fileName&, const fileOp& fop) const;
|
||||
Type masterOp
|
||||
(
|
||||
const fileName&,
|
||||
const fileOp& fop,
|
||||
const int tag,
|
||||
const label comm
|
||||
) const;
|
||||
|
||||
template<class Type, class fileOp>
|
||||
Type masterOp
|
||||
(
|
||||
const fileName&,
|
||||
const fileName&,
|
||||
const fileOp& fop
|
||||
const fileOp& fop,
|
||||
const int tag,
|
||||
const label comm
|
||||
) const;
|
||||
|
||||
//- Equivalent of Time::findInstance
|
||||
@ -375,26 +417,32 @@ protected:
|
||||
const instant& t
|
||||
);
|
||||
|
||||
//- Search for object; return info on how it was found
|
||||
//- Search (locally!) for object; return info on how it was found.
|
||||
// Does not do any parallel communication.
|
||||
// checkGlobal : also check undecomposed case
|
||||
// isFile : true:check for file; false:check for directory
|
||||
fileName filePathInfo
|
||||
// isFile : true:check for file false:check for directory
|
||||
// searchType : how was found
|
||||
// processorsDir : name of processor directory
|
||||
// instance : instance
|
||||
virtual fileName filePathInfo
|
||||
(
|
||||
const bool checkGlobal,
|
||||
const bool isFile,
|
||||
const IOobject& io,
|
||||
const IOobject&,
|
||||
const bool search,
|
||||
pathType&,
|
||||
word&
|
||||
pathType& searchType,
|
||||
word& processorsDir,
|
||||
word& instance
|
||||
) const;
|
||||
|
||||
//- Construct filePath
|
||||
static fileName objectPath
|
||||
fileName localObjectPath
|
||||
(
|
||||
const IOobject&,
|
||||
const pathType&,
|
||||
const word&
|
||||
);
|
||||
const pathType& searchType,
|
||||
const word& processorsDir,
|
||||
const word& instancePath
|
||||
) const;
|
||||
|
||||
//- Read file contents and send to processors
|
||||
static void readAndSend
|
||||
@ -405,6 +453,29 @@ protected:
|
||||
PstreamBuffers& pBufs
|
||||
);
|
||||
|
||||
//- Detect file (possibly compressed), read file contents and send
|
||||
// to processors
|
||||
static void readAndSend
|
||||
(
|
||||
const fileName& fName,
|
||||
const labelUList& procs,
|
||||
PstreamBuffers& pBufs
|
||||
);
|
||||
|
||||
//- Read files on comms master
|
||||
static autoPtr<ISstream> read
|
||||
(
|
||||
IOobject& io,
|
||||
const label comm,
|
||||
const bool uniform, // on comms master only
|
||||
const fileNameList& filePaths, // on comms master only
|
||||
const boolList& procValid // on comms master only
|
||||
);
|
||||
|
||||
//- Helper: check IO for local existence. Like filePathInfo but
|
||||
// without parent searchign and instance searching
|
||||
bool exists(const dirIndexList&, IOobject& io) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
@ -425,9 +496,12 @@ public:
|
||||
//- Construct null
|
||||
masterUncollatedFileOperation(const bool verbose);
|
||||
|
||||
//- Construct from communicator
|
||||
masterUncollatedFileOperation(const label comm, const bool verbose);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~masterUncollatedFileOperation() = default;
|
||||
virtual ~masterUncollatedFileOperation();
|
||||
|
||||
|
||||
// Member Functions
|
||||
@ -682,30 +756,19 @@ public:
|
||||
//- Get sorted list of times
|
||||
virtual instantList findTimes(const fileName&, const word&) const;
|
||||
|
||||
//- Find instance where IOobject is. Fails if cannot be found
|
||||
// and readOpt() is MUST_READ/MUST_READ_IF_MODIFIED. Otherwise
|
||||
// returns stopInstance.
|
||||
virtual IOobject findInstance
|
||||
(
|
||||
const IOobject& io,
|
||||
const scalar startValue,
|
||||
const word& stopInstance
|
||||
) const;
|
||||
|
||||
//- Callback for time change
|
||||
virtual void setTime(const Time&) const;
|
||||
|
||||
//- root+casename with any 'processorXXX' replaced by 'processsors'
|
||||
static fileName processorsCasePath(const IOobject&);
|
||||
|
||||
//- Like io.path with provided instance and any 'processorXXX'
|
||||
// replaced by 'processsors'
|
||||
static fileName processorsPath(const IOobject&, const word&);
|
||||
|
||||
//- Operating on fileName: replace processorXXX with processors
|
||||
static fileName processorsPath(const fileName&);
|
||||
|
||||
//- Split fileName into part before processor and part after.
|
||||
// Returns -1 or processor number. Use with care.
|
||||
// - path/"processor" + Foam::name(proci)/local reconstructs input
|
||||
// - path/"processors"/local reconstructs processors equivalence
|
||||
static label splitProcessorPath
|
||||
(
|
||||
const fileName&,
|
||||
fileName& path,
|
||||
fileName& local
|
||||
);
|
||||
|
||||
//- Return cached times
|
||||
const HashPtrTable<instantList>& times() const
|
||||
{
|
||||
@ -714,6 +777,28 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class masterUncollatedFileOperationInitialise Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class masterUncollatedFileOperationInitialise
|
||||
:
|
||||
public unthreadedInitialise
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
masterUncollatedFileOperationInitialise(int& argc, char**& argv);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~masterUncollatedFileOperationInitialise()
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace fileOperations
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -31,14 +31,16 @@ License
|
||||
template<class Type>
|
||||
Type Foam::fileOperations::masterUncollatedFileOperation::scatterList
|
||||
(
|
||||
const UList<Type>& masterLst
|
||||
const UList<Type>& masterLst,
|
||||
const int tag,
|
||||
const label comm
|
||||
) const
|
||||
{
|
||||
// TBD: more efficient scatter
|
||||
PstreamBuffers pBufs(UPstream::commsTypes::nonBlocking);
|
||||
if (Pstream::master())
|
||||
PstreamBuffers pBufs(UPstream::commsTypes::nonBlocking, tag, comm);
|
||||
if (Pstream::master(comm))
|
||||
{
|
||||
for (label proci = 1; proci < Pstream::nProcs(); proci++)
|
||||
for (label proci = 1; proci < Pstream::nProcs(comm); proci++)
|
||||
{
|
||||
UOPstream os(proci, pBufs);
|
||||
os << masterLst[proci];
|
||||
@ -48,9 +50,9 @@ Type Foam::fileOperations::masterUncollatedFileOperation::scatterList
|
||||
|
||||
Type myResult;
|
||||
|
||||
if (Pstream::master())
|
||||
if (Pstream::master(comm))
|
||||
{
|
||||
myResult = masterLst[Pstream::myProcNo()];
|
||||
myResult = masterLst[Pstream::myProcNo(comm)];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -65,21 +67,25 @@ template<class Type, class fileOp>
|
||||
Type Foam::fileOperations::masterUncollatedFileOperation::masterOp
|
||||
(
|
||||
const fileName& fName,
|
||||
const fileOp& fop
|
||||
const fileOp& fop,
|
||||
const int tag,
|
||||
const label comm
|
||||
) const
|
||||
{
|
||||
if (IFstream::debug)
|
||||
{
|
||||
Pout<< "masterUncollatedFileOperation : Operation on " << fName << endl;
|
||||
Pout<< "masterUncollatedFileOperation::masterOp : Operation "
|
||||
<< typeid(fileOp).name()
|
||||
<< " on " << fName << endl;
|
||||
}
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
List<fileName> filePaths(Pstream::nProcs());
|
||||
filePaths[Pstream::myProcNo()] = fName;
|
||||
Pstream::gatherList(filePaths);
|
||||
List<fileName> filePaths(Pstream::nProcs(comm));
|
||||
filePaths[Pstream::myProcNo(comm)] = fName;
|
||||
Pstream::gatherList(filePaths, tag, comm);
|
||||
|
||||
List<Type> result(Pstream::nProcs());
|
||||
if (Pstream::master())
|
||||
List<Type> result(filePaths.size());
|
||||
if (Pstream::master(comm))
|
||||
{
|
||||
result = fop(filePaths[0]);
|
||||
for (label i = 1; i < filePaths.size(); i++)
|
||||
@ -91,7 +97,7 @@ Type Foam::fileOperations::masterUncollatedFileOperation::masterOp
|
||||
}
|
||||
}
|
||||
|
||||
return scatterList(result);
|
||||
return scatterList(result, tag, comm);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -105,7 +111,9 @@ Type Foam::fileOperations::masterUncollatedFileOperation::masterOp
|
||||
(
|
||||
const fileName& src,
|
||||
const fileName& dest,
|
||||
const fileOp& fop
|
||||
const fileOp& fop,
|
||||
const int tag,
|
||||
const label comm
|
||||
) const
|
||||
{
|
||||
if (IFstream::debug)
|
||||
@ -115,16 +123,16 @@ Type Foam::fileOperations::masterUncollatedFileOperation::masterOp
|
||||
}
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
List<fileName> srcs(Pstream::nProcs());
|
||||
srcs[Pstream::myProcNo()] = src;
|
||||
Pstream::gatherList(srcs);
|
||||
List<fileName> srcs(Pstream::nProcs(comm));
|
||||
srcs[Pstream::myProcNo(comm)] = src;
|
||||
Pstream::gatherList(srcs, tag, comm);
|
||||
|
||||
List<fileName> dests(Pstream::nProcs());
|
||||
dests[Pstream::myProcNo()] = dest;
|
||||
Pstream::gatherList(dests);
|
||||
List<fileName> dests(srcs.size());
|
||||
dests[Pstream::myProcNo(comm)] = dest;
|
||||
Pstream::gatherList(dests, tag, comm);
|
||||
|
||||
List<Type> result(Pstream::nProcs());
|
||||
if (Pstream::master())
|
||||
List<Type> result(Pstream::nProcs(comm));
|
||||
if (Pstream::master(comm))
|
||||
{
|
||||
result = fop(srcs[0], dests[0]);
|
||||
for (label i = 1; i < srcs.size(); i++)
|
||||
@ -136,7 +144,7 @@ Type Foam::fileOperations::masterUncollatedFileOperation::masterOp
|
||||
}
|
||||
}
|
||||
|
||||
return scatterList(result);
|
||||
return scatterList(result, tag, comm);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -27,9 +27,9 @@ License
|
||||
#include "Time.H"
|
||||
#include "Fstream.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "masterUncollatedFileOperation.H"
|
||||
#include "decomposedBlockData.H"
|
||||
#include "dummyISstream.H"
|
||||
#include "unthreadedInitialise.H"
|
||||
|
||||
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
|
||||
|
||||
@ -39,6 +39,15 @@ namespace fileOperations
|
||||
{
|
||||
defineTypeNameAndDebug(uncollatedFileOperation, 0);
|
||||
addToRunTimeSelectionTable(fileOperation, uncollatedFileOperation, word);
|
||||
|
||||
// Mark as not needing threaded mpi
|
||||
addNamedToRunTimeSelectionTable
|
||||
(
|
||||
fileOperationInitialise,
|
||||
unthreadedInitialise,
|
||||
word,
|
||||
uncollated
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,17 +111,20 @@ Foam::fileName Foam::fileOperations::uncollatedFileOperation::filePathInfo
|
||||
// Check if parallel "procesors" directory
|
||||
if (io.time().processorCase())
|
||||
{
|
||||
fileName path = fileOperations::masterUncollatedFileOperation::
|
||||
processorsPath
|
||||
tmpNrc<dirIndexList> pDirs
|
||||
(
|
||||
io,
|
||||
io.instance()
|
||||
lookupProcessorsPath(io.objectPath())
|
||||
);
|
||||
fileName objectPath = path/io.name();
|
||||
|
||||
if (isFileOrDir(isFile, objectPath))
|
||||
forAll(pDirs(), i)
|
||||
{
|
||||
return objectPath;
|
||||
const fileName& pDir = pDirs()[i].first();
|
||||
fileName objPath =
|
||||
processorsPath(io, io.instance(), pDir)
|
||||
/io.name();
|
||||
if (objPath != objectPath && isFileOrDir(isFile, objPath))
|
||||
{
|
||||
return objPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,6 +165,8 @@ Foam::fileOperations::uncollatedFileOperation::uncollatedFileOperation
|
||||
(
|
||||
const bool verbose
|
||||
)
|
||||
:
|
||||
fileOperation(Pstream::worldComm)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
@ -533,15 +547,7 @@ Foam::fileOperations::uncollatedFileOperation::readStream
|
||||
{
|
||||
// Analyse the objectpath to find out the processor we're trying
|
||||
// to access
|
||||
fileName path;
|
||||
fileName local;
|
||||
label proci = fileOperations::masterUncollatedFileOperation::
|
||||
splitProcessorPath
|
||||
(
|
||||
io.objectPath(),
|
||||
path,
|
||||
local
|
||||
);
|
||||
label proci = detectProcessorPath(io.objectPath());
|
||||
|
||||
if (proci == -1)
|
||||
{
|
||||
@ -551,6 +557,26 @@ Foam::fileOperations::uncollatedFileOperation::readStream
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
// Analyse the fileName for any processor subset. Note: this
|
||||
// should really be part of filePath() which should return
|
||||
// both file and index in file.
|
||||
fileName path, procDir, local;
|
||||
label groupStart, groupSize, nProcs;
|
||||
splitProcessorPath
|
||||
(
|
||||
fName,
|
||||
path,
|
||||
procDir,
|
||||
local,
|
||||
groupStart,
|
||||
groupSize,
|
||||
nProcs
|
||||
);
|
||||
if (groupStart != -1 && groupSize > 0)
|
||||
{
|
||||
proci = proci-groupStart;
|
||||
}
|
||||
|
||||
// Read data and return as stream
|
||||
return decomposedBlockData::readBlock(proci, isPtr(), io);
|
||||
}
|
||||
@ -570,8 +596,8 @@ bool Foam::fileOperations::uncollatedFileOperation::read
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "uncollatedFileOperation::read() : "
|
||||
<< "reading object " << io.objectPath()
|
||||
Pout<< "uncollatedFileOperation::read :"
|
||||
<< " Reading object " << io.objectPath()
|
||||
<< " from file " << endl;
|
||||
}
|
||||
|
||||
|
||||
@ -256,33 +256,6 @@ bool dlSymFound(void* handle, const std::string& symbol);
|
||||
fileNameList dlLoaded();
|
||||
|
||||
|
||||
// Thread handling
|
||||
|
||||
//- Allocate a thread
|
||||
label allocateThread();
|
||||
|
||||
//- Start a thread
|
||||
void createThread(const label, void *(*start_routine) (void *), void *arg);
|
||||
|
||||
//- Wait for thread
|
||||
void joinThread(const label);
|
||||
|
||||
//- Delete a thread
|
||||
void freeThread(const label);
|
||||
|
||||
//- Allocate a mutex variable
|
||||
label allocateMutex();
|
||||
|
||||
//- Lock a mutex variable
|
||||
void lockMutex(const label);
|
||||
|
||||
//- Unlock a mutex variable
|
||||
void unlockMutex(const label);
|
||||
|
||||
//- Free a mutex variable
|
||||
void freeMutex(const label);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
@ -67,7 +67,7 @@ class tmpNrc
|
||||
mutable T* ptr_;
|
||||
|
||||
//- The type (managed pointer | const-reference object)
|
||||
refType type_;
|
||||
mutable refType type_;
|
||||
|
||||
|
||||
public:
|
||||
@ -160,6 +160,9 @@ public:
|
||||
//- delete object and set pointer to nullptr
|
||||
inline void clear() const;
|
||||
|
||||
//- Swaps the managed object with other tmpNrc.
|
||||
inline void swap(tmpNrc<T>& other) noexcept;
|
||||
|
||||
|
||||
// Member operators
|
||||
|
||||
|
||||
@ -266,7 +266,7 @@ Foam::faceZone::faceZone
|
||||
(
|
||||
const word& name,
|
||||
const labelUList& addr,
|
||||
const boolList& fm,
|
||||
const boolUList& fm,
|
||||
const label index,
|
||||
const faceZoneMesh& zm
|
||||
)
|
||||
@ -328,7 +328,7 @@ Foam::faceZone::faceZone
|
||||
(
|
||||
const faceZone& origZone,
|
||||
const labelUList& addr,
|
||||
const boolList& fm,
|
||||
const boolUList& fm,
|
||||
const label index,
|
||||
const faceZoneMesh& zm
|
||||
)
|
||||
@ -468,7 +468,7 @@ void Foam::faceZone::resetAddressing
|
||||
void Foam::faceZone::resetAddressing
|
||||
(
|
||||
const labelUList& addr,
|
||||
const boolList& flipMap
|
||||
const boolUList& flipMap
|
||||
)
|
||||
{
|
||||
clearAddressing();
|
||||
|
||||
@ -177,7 +177,7 @@ public:
|
||||
(
|
||||
const word& name,
|
||||
const labelUList& addr,
|
||||
const boolList& fm,
|
||||
const boolUList& fm,
|
||||
const label index,
|
||||
const faceZoneMesh& zm
|
||||
);
|
||||
@ -208,7 +208,7 @@ public:
|
||||
(
|
||||
const faceZone& origZone,
|
||||
const labelUList& addr,
|
||||
const boolList& fm,
|
||||
const boolUList& fm,
|
||||
const label index,
|
||||
const faceZoneMesh& zm
|
||||
);
|
||||
@ -236,7 +236,7 @@ public:
|
||||
virtual autoPtr<faceZone> clone
|
||||
(
|
||||
const labelUList& addr,
|
||||
const boolList& fm,
|
||||
const boolUList& fm,
|
||||
const label index,
|
||||
const faceZoneMesh& zm
|
||||
) const
|
||||
@ -309,7 +309,7 @@ public:
|
||||
virtual void resetAddressing
|
||||
(
|
||||
const labelUList& addr,
|
||||
const boolList& flipMap
|
||||
const boolUList& flipMap
|
||||
);
|
||||
|
||||
//- Move reset addressing - use uniform flip map value
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -42,7 +42,7 @@ bool Foam::UPstream::initNull()
|
||||
}
|
||||
|
||||
|
||||
bool Foam::UPstream::init(int& argc, char**& argv)
|
||||
bool Foam::UPstream::init(int& argc, char**& argv, const bool needsThread)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "The dummy Pstream library cannot be used in parallel mode"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
sinclude $(GENERAL_RULES)/mplib$(WM_MPLIB)
|
||||
sinclude $(RULES)/mplib$(WM_MPLIB)
|
||||
sinclude $(DEFAULT_RULES)/mplib$(WM_MPLIB)
|
||||
|
||||
EXE_INC = $(PFLAGS) $(PINC) $(c++LESSWARN)
|
||||
LIB_LIBS = $(PLIBS)
|
||||
|
||||
@ -101,7 +101,7 @@ bool Foam::UPstream::initNull()
|
||||
}
|
||||
|
||||
|
||||
bool Foam::UPstream::init(int& argc, char**& argv)
|
||||
bool Foam::UPstream::init(int& argc, char**& argv, const bool needsThread)
|
||||
{
|
||||
int flag = 0;
|
||||
|
||||
@ -129,17 +129,16 @@ bool Foam::UPstream::init(int& argc, char**& argv)
|
||||
|
||||
|
||||
//MPI_Init(&argc, &argv);
|
||||
int wanted_thread_support = MPI_THREAD_SINGLE;
|
||||
if (fileOperations::collatedFileOperation::maxThreadFileBufferSize > 0)
|
||||
{
|
||||
wanted_thread_support = MPI_THREAD_MULTIPLE;
|
||||
}
|
||||
int provided_thread_support;
|
||||
MPI_Init_thread
|
||||
(
|
||||
&argc,
|
||||
&argv,
|
||||
wanted_thread_support,
|
||||
(
|
||||
needsThread
|
||||
? MPI_THREAD_MULTIPLE
|
||||
: MPI_THREAD_SINGLE
|
||||
),
|
||||
&provided_thread_support
|
||||
);
|
||||
|
||||
|
||||
@ -571,7 +571,8 @@ void Foam::vtk::vtuSizing::populateArrays
|
||||
if (output == contentType::LEGACY)
|
||||
{
|
||||
// Update size for legacy face stream
|
||||
faceOutput[startLabel] = (faceIndexer - startLabel);
|
||||
// (subtract 1 to avoid counting the storage location)
|
||||
faceOutput[startLabel] = (faceIndexer - 1 - startLabel);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation | Copyright (C) 2015-2018 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -42,6 +42,7 @@ License
|
||||
#include "fvMeshTools.H"
|
||||
#include "labelPairHashes.H"
|
||||
#include "ListOps.H"
|
||||
#include "globalIndex.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
@ -688,25 +689,54 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::repatch
|
||||
// merge those points.
|
||||
Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::mergeSharedPoints
|
||||
(
|
||||
const labelList& pointToGlobalMaster,
|
||||
labelListList& constructPointMap
|
||||
)
|
||||
{
|
||||
// Find out which sets of points get merged and create a map from
|
||||
// mesh point to unique point.
|
||||
Map<label> pointToMaster
|
||||
(
|
||||
fvMeshAdder::findSharedPoints
|
||||
(
|
||||
mesh_,
|
||||
mergeTol_
|
||||
)
|
||||
);
|
||||
|
||||
label nShared = 0;
|
||||
forAll(pointToGlobalMaster, pointi)
|
||||
{
|
||||
if (pointToGlobalMaster[pointi] != -1)
|
||||
{
|
||||
nShared++;
|
||||
}
|
||||
}
|
||||
|
||||
Map<label> globalMasterToLocalMaster(2*nShared);
|
||||
Map<label> pointToMaster(2*nShared);
|
||||
|
||||
forAll(pointToGlobalMaster, pointi)
|
||||
{
|
||||
label globali = pointToGlobalMaster[pointi];
|
||||
if (globali != -1)
|
||||
{
|
||||
Map<label>::const_iterator iter = globalMasterToLocalMaster.find
|
||||
(
|
||||
globali
|
||||
);
|
||||
|
||||
if (iter == globalMasterToLocalMaster.end())
|
||||
{
|
||||
// Found first point. Designate as master
|
||||
globalMasterToLocalMaster.insert(globali, pointi);
|
||||
pointToMaster.insert(pointi, pointi);
|
||||
}
|
||||
else
|
||||
{
|
||||
pointToMaster.insert(pointi, iter());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (returnReduce(pointToMaster.size(), sumOp<label>()) == 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
polyTopoChange meshMod(mesh_);
|
||||
|
||||
fvMeshAdder::mergePoints(mesh_, pointToMaster, meshMod);
|
||||
@ -750,16 +780,19 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::mergeSharedPoints
|
||||
}
|
||||
|
||||
|
||||
// Construct the local environment of all boundary faces.
|
||||
void Foam::fvMeshDistribute::getNeighbourData
|
||||
void Foam::fvMeshDistribute::getCouplingData
|
||||
(
|
||||
const labelList& distribution,
|
||||
labelList& sourceFace,
|
||||
labelList& sourceProc,
|
||||
labelList& sourcePatch,
|
||||
labelList& sourceNewNbrProc
|
||||
labelList& sourceNewNbrProc,
|
||||
labelList& sourcePointMaster
|
||||
) const
|
||||
{
|
||||
// Construct the coupling information for all (boundary) faces and
|
||||
// points
|
||||
|
||||
label nBnd = mesh_.nFaces() - mesh_.nInternalFaces();
|
||||
sourceFace.setSize(nBnd);
|
||||
sourceProc.setSize(nBnd);
|
||||
@ -890,13 +923,62 @@ void Foam::fvMeshDistribute::getNeighbourData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Collect coupled (collocated) points
|
||||
sourcePointMaster.setSize(mesh_.nPoints());
|
||||
sourcePointMaster = -1;
|
||||
{
|
||||
// Assign global master point
|
||||
const globalIndex globalPoints(mesh_.nPoints());
|
||||
|
||||
const globalMeshData& gmd = mesh_.globalData();
|
||||
const indirectPrimitivePatch& cpp = gmd.coupledPatch();
|
||||
const labelList& meshPoints = cpp.meshPoints();
|
||||
const mapDistribute& slavesMap = gmd.globalCoPointSlavesMap();
|
||||
const labelListList& slaves = gmd.globalCoPointSlaves();
|
||||
|
||||
labelList elems(slavesMap.constructSize(), -1);
|
||||
forAll(meshPoints, pointi)
|
||||
{
|
||||
const labelList& slots = slaves[pointi];
|
||||
|
||||
if (slots.size())
|
||||
{
|
||||
// pointi is a master. Assign a unique label.
|
||||
|
||||
label globalPointi = globalPoints.toGlobal(meshPoints[pointi]);
|
||||
elems[pointi] = globalPointi;
|
||||
forAll(slots, i)
|
||||
{
|
||||
label sloti = slots[i];
|
||||
if (sloti >= meshPoints.size())
|
||||
{
|
||||
// Filter out local collocated points. We don't want
|
||||
// to merge these
|
||||
elems[slots[i]] = globalPointi;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Push slave-slot data back to slaves
|
||||
slavesMap.reverseDistribute(elems.size(), elems, false);
|
||||
|
||||
// Extract back onto mesh
|
||||
forAll(meshPoints, pointi)
|
||||
{
|
||||
sourcePointMaster[meshPoints[pointi]] = elems[pointi];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Subset the neighbourCell/neighbourProc fields
|
||||
void Foam::fvMeshDistribute::subsetBoundaryData
|
||||
void Foam::fvMeshDistribute::subsetCouplingData
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const labelList& pointMap,
|
||||
const labelList& faceMap,
|
||||
const labelList& cellMap,
|
||||
|
||||
@ -909,11 +991,13 @@ void Foam::fvMeshDistribute::subsetBoundaryData
|
||||
const labelList& sourceProc,
|
||||
const labelList& sourcePatch,
|
||||
const labelList& sourceNewNbrProc,
|
||||
const labelList& sourcePointMaster,
|
||||
|
||||
labelList& subFace,
|
||||
labelList& subProc,
|
||||
labelList& subPatch,
|
||||
labelList& subNewNbrProc
|
||||
labelList& subNewNbrProc,
|
||||
labelList& subPointMaster
|
||||
)
|
||||
{
|
||||
subFace.setSize(mesh.nFaces() - mesh.nInternalFaces());
|
||||
@ -959,6 +1043,9 @@ void Foam::fvMeshDistribute::subsetBoundaryData
|
||||
subNewNbrProc[newBFacei] = sourceNewNbrProc[oldBFacei];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
subPointMaster = UIndirectList<label>(sourcePointMaster, pointMap);
|
||||
}
|
||||
|
||||
|
||||
@ -1042,9 +1129,9 @@ Foam::labelList Foam::fvMeshDistribute::mapBoundaryData
|
||||
(
|
||||
const primitiveMesh& mesh, // mesh after adding
|
||||
const mapAddedPolyMesh& map,
|
||||
const labelList& boundaryData0, // mesh before adding
|
||||
const labelList& boundaryData0, // on mesh before adding
|
||||
const label nInternalFaces1,
|
||||
const labelList& boundaryData1 // added mesh
|
||||
const labelList& boundaryData1 // on added mesh
|
||||
)
|
||||
{
|
||||
labelList newBoundaryData(mesh.nFaces() - mesh.nInternalFaces());
|
||||
@ -1076,6 +1163,41 @@ Foam::labelList Foam::fvMeshDistribute::mapBoundaryData
|
||||
}
|
||||
|
||||
|
||||
Foam::labelList Foam::fvMeshDistribute::mapPointData
|
||||
(
|
||||
const primitiveMesh& mesh, // mesh after adding
|
||||
const mapAddedPolyMesh& map,
|
||||
const labelList& boundaryData0, // on mesh before adding
|
||||
const labelList& boundaryData1 // on added mesh
|
||||
)
|
||||
{
|
||||
labelList newBoundaryData(mesh.nPoints());
|
||||
|
||||
forAll(boundaryData0, oldPointi)
|
||||
{
|
||||
label newPointi = map.oldPointMap()[oldPointi];
|
||||
|
||||
// Point still exists (is necessary?)
|
||||
if (newPointi >= 0)
|
||||
{
|
||||
newBoundaryData[newPointi] = boundaryData0[oldPointi];
|
||||
}
|
||||
}
|
||||
|
||||
forAll(boundaryData1, addedPointi)
|
||||
{
|
||||
label newPointi = map.addedPointMap()[addedPointi];
|
||||
|
||||
if (newPointi >= 0)
|
||||
{
|
||||
newBoundaryData[newPointi] = boundaryData1[addedPointi];
|
||||
}
|
||||
}
|
||||
|
||||
return newBoundaryData;
|
||||
}
|
||||
|
||||
|
||||
// Remove cells. Add all exposed faces to patch oldInternalPatchi
|
||||
Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::doRemoveCells
|
||||
(
|
||||
@ -1297,6 +1419,7 @@ void Foam::fvMeshDistribute::sendMesh
|
||||
const labelList& sourceProc,
|
||||
const labelList& sourcePatch,
|
||||
const labelList& sourceNewNbrProc,
|
||||
const labelList& sourcePointMaster,
|
||||
Ostream& toDomain
|
||||
)
|
||||
{
|
||||
@ -1433,7 +1556,8 @@ void Foam::fvMeshDistribute::sendMesh
|
||||
<< sourceFace
|
||||
<< sourceProc
|
||||
<< sourcePatch
|
||||
<< sourceNewNbrProc;
|
||||
<< sourceNewNbrProc
|
||||
<< sourcePointMaster;
|
||||
|
||||
|
||||
if (debug)
|
||||
@ -1456,6 +1580,7 @@ Foam::autoPtr<Foam::fvMesh> Foam::fvMeshDistribute::receiveMesh
|
||||
labelList& domainSourceProc,
|
||||
labelList& domainSourcePatch,
|
||||
labelList& domainSourceNewNbrProc,
|
||||
labelList& domainSourcePointMaster,
|
||||
Istream& fromNbr
|
||||
)
|
||||
{
|
||||
@ -1474,7 +1599,8 @@ Foam::autoPtr<Foam::fvMesh> Foam::fvMeshDistribute::receiveMesh
|
||||
>> domainSourceFace
|
||||
>> domainSourceProc
|
||||
>> domainSourcePatch
|
||||
>> domainSourceNewNbrProc;
|
||||
>> domainSourceNewNbrProc
|
||||
>> domainSourcePointMaster;
|
||||
|
||||
// Construct fvMesh
|
||||
auto domainMeshPtr = autoPtr<fvMesh>::New
|
||||
@ -1709,13 +1835,15 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
|
||||
labelList sourceFace;
|
||||
labelList sourceProc;
|
||||
labelList sourceNewNbrProc;
|
||||
getNeighbourData
|
||||
labelList sourcePointMaster;
|
||||
getCouplingData
|
||||
(
|
||||
distribution,
|
||||
sourceFace,
|
||||
sourceProc,
|
||||
sourcePatch,
|
||||
sourceNewNbrProc
|
||||
sourceNewNbrProc,
|
||||
sourcePointMaster
|
||||
);
|
||||
|
||||
|
||||
@ -1924,11 +2052,13 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
|
||||
labelList procSourceProc;
|
||||
labelList procSourcePatch;
|
||||
labelList procSourceNewNbrProc;
|
||||
labelList procSourcePointMaster;
|
||||
|
||||
subsetBoundaryData
|
||||
subsetCouplingData
|
||||
(
|
||||
subsetter.subMesh(),
|
||||
subsetter.faceMap(), // from subMesh to mesh
|
||||
subsetter.pointMap(), // from subMesh to mesh
|
||||
subsetter.faceMap(), // ,, ,,
|
||||
subsetter.cellMap(), // ,, ,,
|
||||
|
||||
distribution, // old mesh distribution
|
||||
@ -1940,15 +2070,16 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
|
||||
sourceProc,
|
||||
sourcePatch,
|
||||
sourceNewNbrProc,
|
||||
sourcePointMaster,
|
||||
|
||||
procSourceFace,
|
||||
procSourceProc,
|
||||
procSourcePatch,
|
||||
procSourceNewNbrProc
|
||||
procSourceNewNbrProc,
|
||||
procSourcePointMaster
|
||||
);
|
||||
|
||||
|
||||
|
||||
// Send to neighbour
|
||||
sendMesh
|
||||
(
|
||||
@ -1963,6 +2094,8 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
|
||||
procSourceProc,
|
||||
procSourcePatch,
|
||||
procSourceNewNbrProc,
|
||||
procSourcePointMaster,
|
||||
|
||||
str
|
||||
);
|
||||
|
||||
@ -2121,10 +2254,12 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
|
||||
labelList domainSourceProc;
|
||||
labelList domainSourcePatch;
|
||||
labelList domainSourceNewNbrProc;
|
||||
labelList domainSourcePointMaster;
|
||||
|
||||
subsetBoundaryData
|
||||
subsetCouplingData
|
||||
(
|
||||
mesh_, // new mesh
|
||||
subMap().pointMap(), // from new to original mesh
|
||||
subMap().faceMap(), // from new to original mesh
|
||||
subMap().cellMap(),
|
||||
|
||||
@ -2137,17 +2272,20 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
|
||||
sourceProc,
|
||||
sourcePatch,
|
||||
sourceNewNbrProc,
|
||||
sourcePointMaster,
|
||||
|
||||
domainSourceFace,
|
||||
domainSourceProc,
|
||||
domainSourcePatch,
|
||||
domainSourceNewNbrProc
|
||||
domainSourceNewNbrProc,
|
||||
domainSourcePointMaster
|
||||
);
|
||||
|
||||
sourceFace.transfer(domainSourceFace);
|
||||
sourceProc.transfer(domainSourceProc);
|
||||
sourcePatch.transfer(domainSourcePatch);
|
||||
sourceNewNbrProc.transfer(domainSourceNewNbrProc);
|
||||
sourcePointMaster.transfer(domainSourcePointMaster);
|
||||
}
|
||||
|
||||
|
||||
@ -2205,6 +2343,7 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
|
||||
labelList domainSourceProc;
|
||||
labelList domainSourcePatch;
|
||||
labelList domainSourceNewNbrProc;
|
||||
labelList domainSourcePointMaster;
|
||||
|
||||
autoPtr<fvMesh> domainMeshPtr;
|
||||
|
||||
@ -2241,6 +2380,7 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
|
||||
domainSourceProc,
|
||||
domainSourcePatch,
|
||||
domainSourceNewNbrProc,
|
||||
domainSourcePointMaster,
|
||||
str
|
||||
);
|
||||
fvMesh& domainMesh = domainMeshPtr();
|
||||
@ -2508,6 +2648,15 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
|
||||
domainMesh.nInternalFaces(),
|
||||
domainSourceNewNbrProc
|
||||
);
|
||||
// Update pointMaster data
|
||||
sourcePointMaster = mapPointData
|
||||
(
|
||||
mesh_,
|
||||
map(),
|
||||
sourcePointMaster,
|
||||
domainSourcePointMaster
|
||||
);
|
||||
|
||||
|
||||
// Update all addressing so xxProcAddressing points to correct
|
||||
// item in masterMesh.
|
||||
@ -2621,6 +2770,10 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
|
||||
}
|
||||
|
||||
|
||||
// See if any originally shared points need to be merged. Note: does
|
||||
// parallel comms. After this points and edges should again be consistent.
|
||||
mergeSharedPoints(sourcePointMaster, constructPointMap);
|
||||
|
||||
|
||||
// Add processorPatches
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
@ -2650,16 +2803,8 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
|
||||
|
||||
// Change patches. Since this might change ordering of coupled faces
|
||||
// we also need to adapt our constructMaps.
|
||||
// NOTE: there is one very particular problem with this structure.
|
||||
// We first create the processor patches and use these to merge out
|
||||
// shared points (see mergeSharedPoints below). So temporarily points
|
||||
// and edges do not match!
|
||||
repatch(newPatchID, constructFaceMap);
|
||||
|
||||
// See if any geometrically shared points need to be merged. Note: does
|
||||
// parallel comms. After this points and edges should again be consistent.
|
||||
mergeSharedPoints(constructPointMap);
|
||||
|
||||
// Bit of hack: processorFvPatchField does not get reset since created
|
||||
// from nothing so explicitly reset.
|
||||
initPatchFields<volScalarField, processorFvPatchField<scalar>>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -163,11 +163,11 @@ class fvMeshDistribute
|
||||
labelListList& constructFaceMap
|
||||
);
|
||||
|
||||
//- Merge any shared points that are geometrically shared. Needs
|
||||
// parallel valid mesh - uses globalMeshData.
|
||||
//- Merge any local points that were remotely coupled.
|
||||
// constructPointMap is adapted for the new point labels.
|
||||
autoPtr<mapPolyMesh> mergeSharedPoints
|
||||
(
|
||||
const labelList& pointToGlobalMaster,
|
||||
labelListList& constructPointMap
|
||||
);
|
||||
|
||||
@ -175,19 +175,21 @@ class fvMeshDistribute
|
||||
// Coupling information
|
||||
|
||||
//- Construct the local environment of all boundary faces.
|
||||
void getNeighbourData
|
||||
void getCouplingData
|
||||
(
|
||||
const labelList& distribution,
|
||||
labelList& sourceFace,
|
||||
labelList& sourceProc,
|
||||
labelList& sourcePatch,
|
||||
labelList& sourceNewProc
|
||||
labelList& sourceNewProc,
|
||||
labelList& sourcePointMaster
|
||||
) const;
|
||||
|
||||
// Subset the neighbourCell/neighbourProc fields
|
||||
static void subsetBoundaryData
|
||||
static void subsetCouplingData
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const labelList& pointMap,
|
||||
const labelList& faceMap,
|
||||
const labelList& cellMap,
|
||||
|
||||
@ -200,11 +202,13 @@ class fvMeshDistribute
|
||||
const labelList& sourceProc,
|
||||
const labelList& sourcePatch,
|
||||
const labelList& sourceNewProc,
|
||||
const labelList& sourcePointMaster,
|
||||
|
||||
labelList& subFace,
|
||||
labelList& subProc,
|
||||
labelList& subPatch,
|
||||
labelList& subNewProc
|
||||
labelList& subNewProc,
|
||||
labelList& subPointMaster
|
||||
);
|
||||
|
||||
//- Find cells on mesh whose faceID/procID match the neighbour
|
||||
@ -237,6 +241,14 @@ class fvMeshDistribute
|
||||
const labelList& boundaryData1 // added mesh
|
||||
);
|
||||
|
||||
//- Map point data to new mesh (resulting from adding two meshes)
|
||||
static labelList mapPointData
|
||||
(
|
||||
const primitiveMesh& mesh, // mesh after adding
|
||||
const mapAddedPolyMesh& map,
|
||||
const labelList& boundaryData0, // on mesh before adding
|
||||
const labelList& boundaryData1 // on added mesh
|
||||
);
|
||||
|
||||
// Other
|
||||
|
||||
@ -276,6 +288,7 @@ class fvMeshDistribute
|
||||
const labelList& sourceProc,
|
||||
const labelList& sourcePatch,
|
||||
const labelList& sourceNewProc,
|
||||
const labelList& sourcePointMaster,
|
||||
Ostream& toDomain
|
||||
);
|
||||
//- Send subset of fields
|
||||
@ -300,6 +313,7 @@ class fvMeshDistribute
|
||||
labelList& domainSourceProc,
|
||||
labelList& domainSourcePatch,
|
||||
labelList& domainSourceNewProc,
|
||||
labelList& domainSourcePointMaster,
|
||||
Istream& fromNbr
|
||||
);
|
||||
|
||||
|
||||
@ -154,6 +154,7 @@ $(derivedFvPatchFields)/flowRateInletVelocity/flowRateInletVelocityFvPatchVector
|
||||
$(derivedFvPatchFields)/flowRateOutletVelocity/flowRateOutletVelocityFvPatchVectorField.C
|
||||
$(derivedFvPatchFields)/fluxCorrectedVelocity/fluxCorrectedVelocityFvPatchVectorField.C
|
||||
$(derivedFvPatchFields)/freestream/freestreamFvPatchFields.C
|
||||
$(derivedFvPatchFields)/freestreamVelocity/freestreamVelocityFvPatchVectorField.C
|
||||
$(derivedFvPatchFields)/freestreamPressure/freestreamPressureFvPatchScalarField.C
|
||||
$(derivedFvPatchFields)/inletOutlet/inletOutletFvPatchFields.C
|
||||
$(derivedFvPatchFields)/inletOutletTotalTemperature/inletOutletTotalTemperatureFvPatchScalarField.C
|
||||
@ -168,6 +169,7 @@ $(derivedFvPatchFields)/noSlip/noSlipFvPatchVectorField.C
|
||||
$(derivedFvPatchFields)/movingWallVelocity/movingWallVelocityFvPatchVectorField.C
|
||||
$(derivedFvPatchFields)/outletInlet/outletInletFvPatchFields.C
|
||||
$(derivedFvPatchFields)/outletMappedUniformInlet/outletMappedUniformInletFvPatchFields.C
|
||||
$(derivedFvPatchFields)/fixedMeanOutletInlet/fixedMeanOutletInletFvPatchFields.C
|
||||
$(derivedFvPatchFields)/partialSlip/partialSlipFvPatchFields.C
|
||||
$(derivedFvPatchFields)/phaseHydrostaticPressure/phaseHydrostaticPressureFvPatchScalarField.C
|
||||
$(derivedFvPatchFields)/pressureDirectedInletOutletVelocity/pressureDirectedInletOutletVelocityFvPatchVectorField.C
|
||||
|
||||
@ -0,0 +1,148 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fixedMeanOutletInletFvPatchField.H"
|
||||
#include "volFields.H"
|
||||
#include "surfaceFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fixedMeanOutletInletFvPatchField<Type>::fixedMeanOutletInletFvPatchField
|
||||
(
|
||||
const fvPatch& p,
|
||||
const DimensionedField<Type, volMesh>& iF
|
||||
)
|
||||
:
|
||||
outletInletFvPatchField<Type>(p, iF),
|
||||
meanValue_()
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fixedMeanOutletInletFvPatchField<Type>::fixedMeanOutletInletFvPatchField
|
||||
(
|
||||
const fvPatch& p,
|
||||
const DimensionedField<Type, volMesh>& iF,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
outletInletFvPatchField<Type>(p, iF),
|
||||
meanValue_(Function1<Type>::New("meanValue", dict))
|
||||
{
|
||||
this->phiName_ = dict.lookupOrDefault<word>("phi", "phi");
|
||||
|
||||
fvPatchField<Type>::operator=
|
||||
(
|
||||
Field<Type>("value", dict, p.size())
|
||||
);
|
||||
|
||||
this->refValue() = *this;
|
||||
this->refGrad() = Zero;
|
||||
this->valueFraction() = 0.0;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fixedMeanOutletInletFvPatchField<Type>::fixedMeanOutletInletFvPatchField
|
||||
(
|
||||
const fixedMeanOutletInletFvPatchField<Type>& ptf,
|
||||
const fvPatch& p,
|
||||
const DimensionedField<Type, volMesh>& iF,
|
||||
const fvPatchFieldMapper& mapper
|
||||
)
|
||||
:
|
||||
outletInletFvPatchField<Type>(ptf, p, iF, mapper),
|
||||
meanValue_(ptf.meanValue_.clone())
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fixedMeanOutletInletFvPatchField<Type>::fixedMeanOutletInletFvPatchField
|
||||
(
|
||||
const fixedMeanOutletInletFvPatchField<Type>& ptf
|
||||
)
|
||||
:
|
||||
outletInletFvPatchField<Type>(ptf),
|
||||
meanValue_(ptf.meanValue_.clone())
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fixedMeanOutletInletFvPatchField<Type>::fixedMeanOutletInletFvPatchField
|
||||
(
|
||||
const fixedMeanOutletInletFvPatchField<Type>& ptf,
|
||||
const DimensionedField<Type, volMesh>& iF
|
||||
)
|
||||
:
|
||||
outletInletFvPatchField<Type>(ptf, iF),
|
||||
meanValue_(ptf.meanValue_.clone())
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::fixedMeanOutletInletFvPatchField<Type>::updateCoeffs()
|
||||
{
|
||||
if (this->updated())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const scalar t = this->db().time().timeOutputValue();
|
||||
Type meanValue = meanValue_->value(t);
|
||||
|
||||
Field<Type> newValues(this->patchInternalField());
|
||||
|
||||
Type meanValuePsi =
|
||||
gSum(this->patch().magSf()*newValues)
|
||||
/gSum(this->patch().magSf());
|
||||
|
||||
if (mag(meanValue) > SMALL && mag(meanValuePsi)/mag(meanValue) > 0.5)
|
||||
{
|
||||
newValues *= mag(meanValue)/mag(meanValuePsi);
|
||||
}
|
||||
else
|
||||
{
|
||||
newValues += (meanValue - meanValuePsi);
|
||||
}
|
||||
|
||||
this->refValue() = newValues;
|
||||
|
||||
outletInletFvPatchField<Type>::updateCoeffs();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::fixedMeanOutletInletFvPatchField<Type>::write(Ostream& os) const
|
||||
{
|
||||
fvPatchField<Type>::write(os);
|
||||
meanValue_->writeData(os);
|
||||
this->writeEntry("value", os);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,185 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::fixedMeanOutletInletFvPatchField
|
||||
|
||||
Group
|
||||
grpInletBoundaryConditions
|
||||
|
||||
Description
|
||||
This boundary condition extrapolates field to the patch using the near-cell
|
||||
values and adjusts the distribution to match the specified, optionally
|
||||
time-varying, mean value. This extrapolated field is applied as a
|
||||
fixedValue for outflow faces but zeroGradient is applied to inflow faces.
|
||||
|
||||
This boundary condition can be applied to pressure when inletOutlet is
|
||||
applied to the velocity so that a zeroGradient condition is applied to the
|
||||
pressure at inflow faces where the velocity is specified to avoid an
|
||||
unphysical over-specification of the set of boundary conditions.
|
||||
|
||||
Usage
|
||||
\table
|
||||
Property | Description | Required | Default value
|
||||
meanValue | mean value Function1 | yes |
|
||||
phi | Flux field name | no | phi
|
||||
\endtable
|
||||
|
||||
Example of the boundary condition specification:
|
||||
\verbatim
|
||||
<patchName>
|
||||
{
|
||||
type fixedMeanOutletInlet;
|
||||
meanValue 1.0;
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
See also
|
||||
Foam::fixedMeanFvPatchField
|
||||
Foam::outletInletFvPatchField
|
||||
Foam::Function1Types
|
||||
|
||||
SourceFiles
|
||||
fixedMeanOutletInletFvPatchField.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fixedMeanOutletInletFvPatchField_H
|
||||
#define fixedMeanOutletInletFvPatchField_H
|
||||
|
||||
#include "outletInletFvPatchFields.H"
|
||||
#include "Function1.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class fixedMeanOutletInletFvPatchField Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class fixedMeanOutletInletFvPatchField
|
||||
:
|
||||
public outletInletFvPatchField<Type>
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- MeanValue value the field is adjusted to maintain
|
||||
autoPtr<Function1<Type>> meanValue_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("fixedMeanOutletInlet");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from patch and internal field
|
||||
fixedMeanOutletInletFvPatchField
|
||||
(
|
||||
const fvPatch&,
|
||||
const DimensionedField<Type, volMesh>&
|
||||
);
|
||||
|
||||
//- Construct from patch, internal field and dictionary
|
||||
fixedMeanOutletInletFvPatchField
|
||||
(
|
||||
const fvPatch&,
|
||||
const DimensionedField<Type, volMesh>&,
|
||||
const dictionary&
|
||||
);
|
||||
|
||||
//- Construct by mapping given fixedMeanOutletInletFvPatchField
|
||||
// onto a new patch
|
||||
fixedMeanOutletInletFvPatchField
|
||||
(
|
||||
const fixedMeanOutletInletFvPatchField<Type>&,
|
||||
const fvPatch&,
|
||||
const DimensionedField<Type, volMesh>&,
|
||||
const fvPatchFieldMapper&
|
||||
);
|
||||
|
||||
//- Construct as copy
|
||||
fixedMeanOutletInletFvPatchField
|
||||
(
|
||||
const fixedMeanOutletInletFvPatchField<Type>&
|
||||
);
|
||||
|
||||
//- Construct and return a clone
|
||||
virtual tmp<fvPatchField<Type>> clone() const
|
||||
{
|
||||
return tmp<fvPatchField<Type>>
|
||||
(
|
||||
new fixedMeanOutletInletFvPatchField<Type>(*this)
|
||||
);
|
||||
}
|
||||
|
||||
//- Construct as copy setting internal field reference
|
||||
fixedMeanOutletInletFvPatchField
|
||||
(
|
||||
const fixedMeanOutletInletFvPatchField<Type>&,
|
||||
const DimensionedField<Type, volMesh>&
|
||||
);
|
||||
|
||||
//- Construct and return a clone setting internal field reference
|
||||
virtual tmp<fvPatchField<Type>> clone
|
||||
(
|
||||
const DimensionedField<Type, volMesh>& iF
|
||||
) const
|
||||
{
|
||||
return tmp<fvPatchField<Type>>
|
||||
(
|
||||
new fixedMeanOutletInletFvPatchField<Type>(*this, iF)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
//- Update the coefficients associated with the patch field
|
||||
virtual void updateCoeffs();
|
||||
|
||||
//- Write
|
||||
virtual void write(Ostream&) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "fixedMeanOutletInletFvPatchField.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,43 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fixedMeanOutletInletFvPatchFields.H"
|
||||
#include "volMesh.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
makePatchFields(fixedMeanOutletInlet);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,49 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fixedMeanOutletInletFvPatchFields_H
|
||||
#define fixedMeanOutletInletFvPatchFields_H
|
||||
|
||||
#include "fixedMeanOutletInletFvPatchField.H"
|
||||
#include "fieldTypes.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
makePatchTypeFieldTypedefs(fixedMeanOutletInlet);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,50 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fixedMeanOutletInletFvPatchFieldsFwd_H
|
||||
#define fixedMeanOutletInletFvPatchFieldsFwd_H
|
||||
|
||||
#include "fieldTypes.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type> class fixedMeanOutletInletFvPatchField;
|
||||
|
||||
makePatchTypeFieldTypedefs(fixedMeanOutletInlet);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -45,7 +45,7 @@ Usage
|
||||
<patchName>
|
||||
{
|
||||
type freestream;
|
||||
phi phi;
|
||||
freestreamValue uniform (300 0 0);
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -24,10 +24,7 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "freestreamPressureFvPatchScalarField.H"
|
||||
#include "freestreamFvPatchFields.H"
|
||||
#include "fvPatchFieldMapper.H"
|
||||
#include "volFields.H"
|
||||
#include "surfaceFields.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
@ -39,10 +36,8 @@ freestreamPressureFvPatchScalarField
|
||||
const DimensionedField<scalar, volMesh>& iF
|
||||
)
|
||||
:
|
||||
zeroGradientFvPatchScalarField(p, iF),
|
||||
UName_("U"),
|
||||
phiName_("phi"),
|
||||
rhoName_("rho")
|
||||
mixedFvPatchScalarField(p, iF),
|
||||
UName_("U")
|
||||
{}
|
||||
|
||||
|
||||
@ -54,11 +49,26 @@ freestreamPressureFvPatchScalarField
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
zeroGradientFvPatchScalarField(p, iF, dict),
|
||||
UName_(dict.lookupOrDefault<word>("U", "U")),
|
||||
phiName_(dict.lookupOrDefault<word>("phi", "phi")),
|
||||
rhoName_(dict.lookupOrDefault<word>("rho", "rho"))
|
||||
{}
|
||||
mixedFvPatchScalarField(p, iF),
|
||||
UName_(dict.lookupOrDefault<word>("U", "U"))
|
||||
{
|
||||
freestreamValue() = scalarField("freestreamValue", dict, p.size());
|
||||
|
||||
if (dict.found("value"))
|
||||
{
|
||||
fvPatchScalarField::operator=
|
||||
(
|
||||
scalarField("value", dict, p.size())
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
fvPatchScalarField::operator=(freestreamValue());
|
||||
}
|
||||
|
||||
refGrad() = Zero;
|
||||
valueFraction() = 0;
|
||||
}
|
||||
|
||||
|
||||
Foam::freestreamPressureFvPatchScalarField::
|
||||
@ -70,10 +80,8 @@ freestreamPressureFvPatchScalarField
|
||||
const fvPatchFieldMapper& mapper
|
||||
)
|
||||
:
|
||||
zeroGradientFvPatchScalarField(ptf, p, iF, mapper),
|
||||
UName_(ptf.UName_),
|
||||
phiName_(ptf.phiName_),
|
||||
rhoName_(ptf.rhoName_)
|
||||
mixedFvPatchScalarField(ptf, p, iF, mapper),
|
||||
UName_(ptf.UName_)
|
||||
{}
|
||||
|
||||
|
||||
@ -83,10 +91,8 @@ freestreamPressureFvPatchScalarField
|
||||
const freestreamPressureFvPatchScalarField& wbppsf
|
||||
)
|
||||
:
|
||||
zeroGradientFvPatchScalarField(wbppsf),
|
||||
UName_(wbppsf.UName_),
|
||||
phiName_(wbppsf.phiName_),
|
||||
rhoName_(wbppsf.rhoName_)
|
||||
mixedFvPatchScalarField(wbppsf),
|
||||
UName_(wbppsf.UName_)
|
||||
{}
|
||||
|
||||
|
||||
@ -97,10 +103,8 @@ freestreamPressureFvPatchScalarField
|
||||
const DimensionedField<scalar, volMesh>& iF
|
||||
)
|
||||
:
|
||||
zeroGradientFvPatchScalarField(wbppsf, iF),
|
||||
UName_(wbppsf.UName_),
|
||||
phiName_(wbppsf.phiName_),
|
||||
rhoName_(wbppsf.rhoName_)
|
||||
mixedFvPatchScalarField(wbppsf, iF),
|
||||
UName_(wbppsf.UName_)
|
||||
{}
|
||||
|
||||
|
||||
@ -113,43 +117,15 @@ void Foam::freestreamPressureFvPatchScalarField::updateCoeffs()
|
||||
return;
|
||||
}
|
||||
|
||||
const freestreamFvPatchVectorField& Up =
|
||||
refCast<const freestreamFvPatchVectorField>
|
||||
const Field<vector>& Up =
|
||||
patch().template lookupPatchField<volVectorField, vector>
|
||||
(
|
||||
patch().lookupPatchField<volVectorField, vector>(UName_)
|
||||
UName_
|
||||
);
|
||||
|
||||
const surfaceScalarField& phi =
|
||||
db().lookupObject<surfaceScalarField>(phiName_);
|
||||
valueFraction() = 0.5 + 0.5*(Up & patch().nf())/mag(Up);
|
||||
|
||||
fvsPatchField<scalar>& phip =
|
||||
const_cast<fvsPatchField<scalar>&>
|
||||
(
|
||||
patch().patchField<surfaceScalarField, scalar>(phi)
|
||||
);
|
||||
|
||||
if (phi.dimensions() == dimVelocity*dimArea)
|
||||
{
|
||||
phip = patch().Sf() & Up.freestreamValue();
|
||||
}
|
||||
else if (phi.dimensions() == dimDensity*dimVelocity*dimArea)
|
||||
{
|
||||
const fvPatchField<scalar>& rhop =
|
||||
patch().lookupPatchField<volScalarField, scalar>(rhoName_);
|
||||
|
||||
phip = rhop*(patch().Sf() & Up.freestreamValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "dimensions of phi are not correct"
|
||||
<< "\n on patch " << this->patch().name()
|
||||
<< " of field " << this->internalField().name()
|
||||
<< " in file " << this->internalField().objectPath()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
zeroGradientFvPatchScalarField::updateCoeffs();
|
||||
mixedFvPatchField<scalar>::updateCoeffs();
|
||||
}
|
||||
|
||||
|
||||
@ -157,8 +133,7 @@ void Foam::freestreamPressureFvPatchScalarField::write(Ostream& os) const
|
||||
{
|
||||
fvPatchScalarField::write(os);
|
||||
os.writeEntryIfDifferent<word>("U", "U", UName_);
|
||||
os.writeEntryIfDifferent<word>("phi", "phi", phiName_);
|
||||
os.writeEntryIfDifferent<word>("rho", "rho", rhoName_);
|
||||
freestreamValue().writeEntry("freestreamValue", os);
|
||||
writeEntry("value", os);
|
||||
}
|
||||
|
||||
|
||||
@ -29,15 +29,16 @@ Group
|
||||
|
||||
Description
|
||||
This boundary condition provides a free-stream condition for pressure.
|
||||
It is a zero-gradient condition that constrains the flux across the patch
|
||||
based on the free-stream velocity.
|
||||
|
||||
It is an outlet-inlet condition that uses the velocity orientation to
|
||||
continuously blend between zero gradient for normal inlet and fixed value
|
||||
for normal outlet flow.
|
||||
|
||||
Usage
|
||||
\table
|
||||
Property | Description | Required | Default value
|
||||
U | velocity field name | no | U
|
||||
phi | flux field name | no | phi
|
||||
rho | density field name | no | none
|
||||
Property | Description | Required | Default value
|
||||
U | velocity field name | no | U
|
||||
freestreamValue | freestream pressure | yes |
|
||||
\endtable
|
||||
|
||||
Example of the boundary condition specification:
|
||||
@ -45,14 +46,15 @@ Usage
|
||||
<patchName>
|
||||
{
|
||||
type freestreamPressure;
|
||||
freestreamValue uniform 1e5;
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Note
|
||||
This condition is designed to operate with a freestream velocity condition
|
||||
This condition is designed to operate with a freestreamVelocity condition
|
||||
|
||||
See also
|
||||
Foam::zeroGradientFvPatchField
|
||||
Foam::mixedFvPatchField
|
||||
Foam::freestreamFvPatchField
|
||||
|
||||
SourceFiles
|
||||
@ -64,7 +66,7 @@ SourceFiles
|
||||
#define freestreamPressureFvPatchScalarField_H
|
||||
|
||||
#include "fvPatchFields.H"
|
||||
#include "zeroGradientFvPatchFields.H"
|
||||
#include "mixedFvPatchFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -77,20 +79,13 @@ namespace Foam
|
||||
|
||||
class freestreamPressureFvPatchScalarField
|
||||
:
|
||||
public zeroGradientFvPatchScalarField
|
||||
public mixedFvPatchScalarField
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Name of the velocity field
|
||||
word UName_;
|
||||
|
||||
//- Name of the flux transporting the field
|
||||
word phiName_;
|
||||
|
||||
//- Name of the density field used to normalise the mass flux
|
||||
//- if necessary
|
||||
word rhoName_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
@ -162,6 +157,17 @@ public:
|
||||
|
||||
// Member functions
|
||||
|
||||
const scalarField& freestreamValue() const
|
||||
{
|
||||
return refValue();
|
||||
}
|
||||
|
||||
scalarField& freestreamValue()
|
||||
{
|
||||
return refValue();
|
||||
}
|
||||
|
||||
|
||||
// Evaluation functions
|
||||
|
||||
//- Update the coefficients associated with the patch field
|
||||
|
||||
@ -0,0 +1,136 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "freestreamVelocityFvPatchVectorField.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::freestreamVelocityFvPatchVectorField::freestreamVelocityFvPatchVectorField
|
||||
(
|
||||
const fvPatch& p,
|
||||
const DimensionedField<vector, volMesh>& iF
|
||||
)
|
||||
:
|
||||
mixedFvPatchVectorField(p, iF)
|
||||
{}
|
||||
|
||||
|
||||
Foam::freestreamVelocityFvPatchVectorField::freestreamVelocityFvPatchVectorField
|
||||
(
|
||||
const fvPatch& p,
|
||||
const DimensionedField<vector, volMesh>& iF,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
mixedFvPatchVectorField(p, iF)
|
||||
{
|
||||
freestreamValue() = vectorField("freestreamValue", dict, p.size());
|
||||
|
||||
if (dict.found("value"))
|
||||
{
|
||||
fvPatchVectorField::operator=
|
||||
(
|
||||
vectorField("value", dict, p.size())
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
fvPatchVectorField::operator=(freestreamValue());
|
||||
}
|
||||
|
||||
refGrad() = Zero;
|
||||
valueFraction() = 1;
|
||||
}
|
||||
|
||||
|
||||
Foam::freestreamVelocityFvPatchVectorField::freestreamVelocityFvPatchVectorField
|
||||
(
|
||||
const freestreamVelocityFvPatchVectorField& ptf,
|
||||
const fvPatch& p,
|
||||
const DimensionedField<vector, volMesh>& iF,
|
||||
const fvPatchFieldMapper& mapper
|
||||
)
|
||||
:
|
||||
mixedFvPatchVectorField(ptf, p, iF, mapper)
|
||||
{}
|
||||
|
||||
|
||||
Foam::freestreamVelocityFvPatchVectorField::freestreamVelocityFvPatchVectorField
|
||||
(
|
||||
const freestreamVelocityFvPatchVectorField& wbppsf
|
||||
)
|
||||
:
|
||||
mixedFvPatchVectorField(wbppsf)
|
||||
{}
|
||||
|
||||
|
||||
Foam::freestreamVelocityFvPatchVectorField::freestreamVelocityFvPatchVectorField
|
||||
(
|
||||
const freestreamVelocityFvPatchVectorField& wbppsf,
|
||||
const DimensionedField<vector, volMesh>& iF
|
||||
)
|
||||
:
|
||||
mixedFvPatchVectorField(wbppsf, iF)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::freestreamVelocityFvPatchVectorField::updateCoeffs()
|
||||
{
|
||||
if (updated())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Field<vector>& Up = *this;
|
||||
|
||||
valueFraction() = 0.5 - 0.5*(Up & patch().nf())/mag(Up);
|
||||
|
||||
mixedFvPatchField<vector>::updateCoeffs();
|
||||
}
|
||||
|
||||
|
||||
void Foam::freestreamVelocityFvPatchVectorField::write(Ostream& os) const
|
||||
{
|
||||
fvPatchVectorField::write(os);
|
||||
freestreamValue().writeEntry("freestreamValue", os);
|
||||
writeEntry("value", os);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
makePatchTypeField
|
||||
(
|
||||
fvPatchVectorField,
|
||||
freestreamVelocityFvPatchVectorField
|
||||
);
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,184 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::freestreamVelocityFvPatchVectorField
|
||||
|
||||
Group
|
||||
grpInletBoundaryConditions grpOutletBoundaryConditions
|
||||
|
||||
Description
|
||||
This boundary condition provides a free-stream condition for velocity.
|
||||
|
||||
It is an inlet-outlet condition that uses the velocity orientation to
|
||||
continuously blend between fixed value for normal inlet and zero gradient
|
||||
for normal outlet flow.
|
||||
|
||||
Usage
|
||||
\table
|
||||
Property | Description | Required | Default value
|
||||
freestreamValue | freestream velocity | yes |
|
||||
\endtable
|
||||
|
||||
Example of the boundary condition specification:
|
||||
\verbatim
|
||||
<patchName>
|
||||
{
|
||||
type freestreamVelocity;
|
||||
freestreamValue uniform (300 0 0);
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Note
|
||||
This condition is designed to operate with the freestreamPressure condition
|
||||
|
||||
See also
|
||||
Foam::mixedFvPatchField
|
||||
Foam::freestreamFvPatchField
|
||||
|
||||
SourceFiles
|
||||
freestreamVelocityFvPatchVectorField.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef freestreamVelocityFvPatchVectorField_H
|
||||
#define freestreamVelocityFvPatchVectorField_H
|
||||
|
||||
#include "fvPatchFields.H"
|
||||
#include "mixedFvPatchFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class freestreamVelocityFvPatchVectorField Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class freestreamVelocityFvPatchVectorField
|
||||
:
|
||||
public mixedFvPatchVectorField
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("freestreamVelocity");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from patch and internal field
|
||||
freestreamVelocityFvPatchVectorField
|
||||
(
|
||||
const fvPatch&,
|
||||
const DimensionedField<vector, volMesh>&
|
||||
);
|
||||
|
||||
//- Construct from patch, internal field and dictionary
|
||||
freestreamVelocityFvPatchVectorField
|
||||
(
|
||||
const fvPatch&,
|
||||
const DimensionedField<vector, volMesh>&,
|
||||
const dictionary&
|
||||
);
|
||||
|
||||
//- Construct by mapping given freestreamVelocityFvPatchVectorField onto
|
||||
// a new patch
|
||||
freestreamVelocityFvPatchVectorField
|
||||
(
|
||||
const freestreamVelocityFvPatchVectorField&,
|
||||
const fvPatch&,
|
||||
const DimensionedField<vector, volMesh>&,
|
||||
const fvPatchFieldMapper&
|
||||
);
|
||||
|
||||
//- Construct as copy
|
||||
freestreamVelocityFvPatchVectorField
|
||||
(
|
||||
const freestreamVelocityFvPatchVectorField&
|
||||
);
|
||||
|
||||
//- Construct and return a clone
|
||||
virtual tmp<fvPatchVectorField> clone() const
|
||||
{
|
||||
return tmp<fvPatchVectorField>
|
||||
(
|
||||
new freestreamVelocityFvPatchVectorField(*this)
|
||||
);
|
||||
}
|
||||
|
||||
//- Construct as copy setting internal field reference
|
||||
freestreamVelocityFvPatchVectorField
|
||||
(
|
||||
const freestreamVelocityFvPatchVectorField&,
|
||||
const DimensionedField<vector, volMesh>&
|
||||
);
|
||||
|
||||
//- Construct and return a clone setting internal field reference
|
||||
virtual tmp<fvPatchVectorField> clone
|
||||
(
|
||||
const DimensionedField<vector, volMesh>& iF
|
||||
) const
|
||||
{
|
||||
return tmp<fvPatchVectorField>
|
||||
(
|
||||
new freestreamVelocityFvPatchVectorField(*this, iF)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
const vectorField& freestreamValue() const
|
||||
{
|
||||
return refValue();
|
||||
}
|
||||
|
||||
vectorField& freestreamValue()
|
||||
{
|
||||
return refValue();
|
||||
}
|
||||
|
||||
|
||||
// Evaluation functions
|
||||
|
||||
//- Update the coefficients associated with the patch field
|
||||
virtual void updateCoeffs();
|
||||
|
||||
|
||||
//- Write
|
||||
virtual void write(Ostream&) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -75,7 +75,7 @@ swirlFlowRateInletVelocityFvPatchVectorField
|
||||
dict.lookupOrDefault
|
||||
(
|
||||
"axis",
|
||||
patch().size()
|
||||
returnReduce(patch().size(), maxOp<label>())
|
||||
? -gSum(patch().Sf())/gSum(patch().magSf())
|
||||
: Zero
|
||||
)
|
||||
@ -145,48 +145,53 @@ void Foam::swirlFlowRateInletVelocityFvPatchVectorField::updateCoeffs()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const scalar t = this->db().time().timeOutputValue();
|
||||
const scalar flowRate = flowRate_->value(t);
|
||||
const scalar rpm = rpm_->value(t);
|
||||
|
||||
const scalar totArea = gSum(patch().magSf());
|
||||
const scalar avgU = -flowRate/totArea;
|
||||
|
||||
const vector axisHat = axis_/mag(axis_);
|
||||
|
||||
// Update angular velocity - convert [rpm] to [rad/s]
|
||||
tmp<vectorField> tangentialVelocity
|
||||
(
|
||||
axisHat ^ (rpm*constant::mathematical::pi/30.0)*(patch().Cf() - origin_)
|
||||
);
|
||||
|
||||
tmp<vectorField> n = patch().nf();
|
||||
|
||||
const surfaceScalarField& phi =
|
||||
db().lookupObject<surfaceScalarField>(phiName_);
|
||||
|
||||
if (phi.dimensions() == dimVelocity*dimArea)
|
||||
if (totArea > ROOTVSMALL && axis_ != vector(Zero))
|
||||
{
|
||||
// volumetric flow-rate
|
||||
operator==(tangentialVelocity + n*avgU);
|
||||
}
|
||||
else if (phi.dimensions() == dimDensity*dimVelocity*dimArea)
|
||||
{
|
||||
const fvPatchField<scalar>& rhop =
|
||||
patch().lookupPatchField<volScalarField, scalar>(rhoName_);
|
||||
const scalar t = this->db().time().timeOutputValue();
|
||||
const scalar flowRate = flowRate_->value(t);
|
||||
const scalar rpm = rpm_->value(t);
|
||||
|
||||
// mass flow-rate
|
||||
operator==(tangentialVelocity + n*avgU/rhop);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "dimensions of " << phiName_ << " are incorrect" << nl
|
||||
<< " on patch " << this->patch().name()
|
||||
<< " of field " << this->internalField().name()
|
||||
<< " in file " << this->internalField().objectPath()
|
||||
<< nl << exit(FatalError);
|
||||
const scalar avgU = -flowRate/totArea;
|
||||
|
||||
const vector axisHat = axis_/mag(axis_);
|
||||
|
||||
// Update angular velocity - convert [rpm] to [rad/s]
|
||||
tmp<vectorField> tangentialVelocity
|
||||
(
|
||||
axisHat
|
||||
^(rpm*constant::mathematical::pi/30.0)
|
||||
*(patch().Cf() - origin_)
|
||||
);
|
||||
|
||||
tmp<vectorField> n = patch().nf();
|
||||
|
||||
const surfaceScalarField& phi =
|
||||
db().lookupObject<surfaceScalarField>(phiName_);
|
||||
|
||||
if (phi.dimensions() == dimVelocity*dimArea)
|
||||
{
|
||||
// volumetric flow-rate
|
||||
operator==(tangentialVelocity + n*avgU);
|
||||
}
|
||||
else if (phi.dimensions() == dimDensity*dimVelocity*dimArea)
|
||||
{
|
||||
const fvPatchField<scalar>& rhop =
|
||||
patch().lookupPatchField<volScalarField, scalar>(rhoName_);
|
||||
|
||||
// mass flow-rate
|
||||
operator==(tangentialVelocity + n*avgU/rhop);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "dimensions of " << phiName_ << " are incorrect" << nl
|
||||
<< " on patch " << this->patch().name()
|
||||
<< " of field " << this->internalField().name()
|
||||
<< " in file " << this->internalField().objectPath()
|
||||
<< nl << exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
fixedValueFvPatchField<vector>::updateCoeffs();
|
||||
|
||||
@ -261,7 +261,7 @@ EulerDdtScheme<Type>::fvcDdt
|
||||
new GeometricField<Type, fvPatchField, volMesh>
|
||||
(
|
||||
ddtIOobject,
|
||||
rDeltaT.value()*
|
||||
rDeltaT*
|
||||
(
|
||||
alpha()
|
||||
*rho()
|
||||
|
||||
@ -0,0 +1,230 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "cellLimitedGrad.H"
|
||||
#include "gaussGrad.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, class Limiter>
|
||||
void Foam::fv::cellLimitedGrad<Type, Limiter>::limitGradient
|
||||
(
|
||||
const Field<scalar>& limiter,
|
||||
Field<vector>& gIf
|
||||
) const
|
||||
{
|
||||
gIf *= limiter;
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class Limiter>
|
||||
void Foam::fv::cellLimitedGrad<Type, Limiter>::limitGradient
|
||||
(
|
||||
const Field<vector>& limiter,
|
||||
Field<tensor>& gIf
|
||||
) const
|
||||
{
|
||||
forAll(gIf, celli)
|
||||
{
|
||||
gIf[celli] = tensor
|
||||
(
|
||||
cmptMultiply(limiter[celli], gIf[celli].x()),
|
||||
cmptMultiply(limiter[celli], gIf[celli].y()),
|
||||
cmptMultiply(limiter[celli], gIf[celli].z())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class Limiter>
|
||||
Foam::tmp
|
||||
<
|
||||
Foam::GeometricField
|
||||
<
|
||||
typename Foam::outerProduct<Foam::vector, Type>::type,
|
||||
Foam::fvPatchField,
|
||||
Foam::volMesh
|
||||
>
|
||||
>
|
||||
Foam::fv::cellLimitedGrad<Type, Limiter>::calcGrad
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& vsf,
|
||||
const word& name
|
||||
) const
|
||||
{
|
||||
const fvMesh& mesh = vsf.mesh();
|
||||
|
||||
tmp
|
||||
<
|
||||
GeometricField
|
||||
<typename outerProduct<vector, Type>::type, fvPatchField, volMesh>
|
||||
> tGrad = basicGradScheme_().calcGrad(vsf, name);
|
||||
|
||||
if (k_ < SMALL)
|
||||
{
|
||||
return tGrad;
|
||||
}
|
||||
|
||||
GeometricField
|
||||
<
|
||||
typename outerProduct<vector, Type>::type,
|
||||
fvPatchField,
|
||||
volMesh
|
||||
>& g = tGrad.ref();
|
||||
|
||||
const labelUList& owner = mesh.owner();
|
||||
const labelUList& neighbour = mesh.neighbour();
|
||||
|
||||
const volVectorField& C = mesh.C();
|
||||
const surfaceVectorField& Cf = mesh.Cf();
|
||||
|
||||
Field<Type> maxVsf(vsf.primitiveField());
|
||||
Field<Type> minVsf(vsf.primitiveField());
|
||||
|
||||
forAll(owner, facei)
|
||||
{
|
||||
label own = owner[facei];
|
||||
label nei = neighbour[facei];
|
||||
|
||||
const Type& vsfOwn = vsf[own];
|
||||
const Type& vsfNei = vsf[nei];
|
||||
|
||||
maxVsf[own] = max(maxVsf[own], vsfNei);
|
||||
minVsf[own] = min(minVsf[own], vsfNei);
|
||||
|
||||
maxVsf[nei] = max(maxVsf[nei], vsfOwn);
|
||||
minVsf[nei] = min(minVsf[nei], vsfOwn);
|
||||
}
|
||||
|
||||
|
||||
const typename GeometricField<Type, fvPatchField, volMesh>::Boundary& bsf =
|
||||
vsf.boundaryField();
|
||||
|
||||
forAll(bsf, patchi)
|
||||
{
|
||||
const fvPatchField<Type>& psf = bsf[patchi];
|
||||
const labelUList& pOwner = mesh.boundary()[patchi].faceCells();
|
||||
|
||||
if (psf.coupled())
|
||||
{
|
||||
const Field<Type> psfNei(psf.patchNeighbourField());
|
||||
|
||||
forAll(pOwner, pFacei)
|
||||
{
|
||||
label own = pOwner[pFacei];
|
||||
const Type& vsfNei = psfNei[pFacei];
|
||||
|
||||
maxVsf[own] = max(maxVsf[own], vsfNei);
|
||||
minVsf[own] = min(minVsf[own], vsfNei);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(pOwner, pFacei)
|
||||
{
|
||||
label own = pOwner[pFacei];
|
||||
const Type& vsfNei = psf[pFacei];
|
||||
|
||||
maxVsf[own] = max(maxVsf[own], vsfNei);
|
||||
minVsf[own] = min(minVsf[own], vsfNei);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
maxVsf -= vsf;
|
||||
minVsf -= vsf;
|
||||
|
||||
if (k_ < 1.0)
|
||||
{
|
||||
const Field<Type> maxMinVsf((1.0/k_ - 1.0)*(maxVsf - minVsf));
|
||||
maxVsf += maxMinVsf;
|
||||
minVsf -= maxMinVsf;
|
||||
}
|
||||
|
||||
|
||||
// Create limiter initialized to 1
|
||||
// Note: the limiter is not permitted to be > 1
|
||||
Field<Type> limiter(vsf.primitiveField().size(), pTraits<Type>::one);
|
||||
|
||||
forAll(owner, facei)
|
||||
{
|
||||
label own = owner[facei];
|
||||
label nei = neighbour[facei];
|
||||
|
||||
// owner side
|
||||
limitFace
|
||||
(
|
||||
limiter[own],
|
||||
maxVsf[own],
|
||||
minVsf[own],
|
||||
(Cf[facei] - C[own]) & g[own]
|
||||
);
|
||||
|
||||
// neighbour side
|
||||
limitFace
|
||||
(
|
||||
limiter[nei],
|
||||
maxVsf[nei],
|
||||
minVsf[nei],
|
||||
(Cf[facei] - C[nei]) & g[nei]
|
||||
);
|
||||
}
|
||||
|
||||
forAll(bsf, patchi)
|
||||
{
|
||||
const labelUList& pOwner = mesh.boundary()[patchi].faceCells();
|
||||
const vectorField& pCf = Cf.boundaryField()[patchi];
|
||||
|
||||
forAll(pOwner, pFacei)
|
||||
{
|
||||
label own = pOwner[pFacei];
|
||||
|
||||
limitFace
|
||||
(
|
||||
limiter[own],
|
||||
maxVsf[own],
|
||||
minVsf[own],
|
||||
((pCf[pFacei] - C[own]) & g[own])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (fv::debug)
|
||||
{
|
||||
Info<< "gradient limiter for: " << vsf.name()
|
||||
<< " max = " << gMax(limiter)
|
||||
<< " min = " << gMin(limiter)
|
||||
<< " average: " << gAverage(limiter) << endl;
|
||||
}
|
||||
|
||||
limitGradient(limiter, g);
|
||||
g.correctBoundaryConditions();
|
||||
gaussGrad<Type>::correctBoundaryConditions(vsf, g);
|
||||
|
||||
return tGrad;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -44,14 +44,13 @@ SourceFiles
|
||||
#define cellLimitedGrad_H
|
||||
|
||||
#include "gradScheme.H"
|
||||
#include "Field.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace fv
|
||||
{
|
||||
|
||||
@ -59,10 +58,11 @@ namespace fv
|
||||
Class cellLimitedGrad Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
template<class Type, class Limiter>
|
||||
class cellLimitedGrad
|
||||
:
|
||||
public fv::gradScheme<Type>
|
||||
public fv::gradScheme<Type>,
|
||||
public Limiter
|
||||
{
|
||||
// Private Data
|
||||
|
||||
@ -74,6 +74,18 @@ class cellLimitedGrad
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
void limitGradient
|
||||
(
|
||||
const Field<scalar>& limiter,
|
||||
Field<vector>& gIf
|
||||
) const;
|
||||
|
||||
void limitGradient
|
||||
(
|
||||
const Field<vector>& limiter,
|
||||
Field<tensor>& gIf
|
||||
) const;
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
cellLimitedGrad(const cellLimitedGrad&);
|
||||
|
||||
@ -93,6 +105,7 @@ public:
|
||||
cellLimitedGrad(const fvMesh& mesh, Istream& schemeData)
|
||||
:
|
||||
gradScheme<Type>(mesh),
|
||||
Limiter(schemeData),
|
||||
basicGradScheme_(fv::gradScheme<Type>::New(mesh, schemeData)),
|
||||
k_(readScalar(schemeData))
|
||||
{
|
||||
@ -110,13 +123,21 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
static inline void limitFace
|
||||
inline void limitFaceCmpt
|
||||
(
|
||||
scalar& limiter,
|
||||
const scalar maxDelta,
|
||||
const scalar minDelta,
|
||||
const scalar extrapolate
|
||||
) const;
|
||||
|
||||
inline void limitFace
|
||||
(
|
||||
Type& limiter,
|
||||
const Type& maxDelta,
|
||||
const Type& minDelta,
|
||||
const Type& extrapolate
|
||||
);
|
||||
) const;
|
||||
|
||||
//- Return the gradient of the given field to the gradScheme::grad
|
||||
// for optional caching
|
||||
@ -134,73 +155,67 @@ public:
|
||||
|
||||
// * * * * * * * * * * * * Inline Member Function * * * * * * * * * * * * * //
|
||||
|
||||
template<>
|
||||
inline void cellLimitedGrad<scalar>::limitFace
|
||||
template<class Type, class Limiter>
|
||||
inline void cellLimitedGrad<Type, Limiter>::limitFaceCmpt
|
||||
(
|
||||
scalar& limiter,
|
||||
const scalar& maxDelta,
|
||||
const scalar& minDelta,
|
||||
const scalar& extrapolate
|
||||
)
|
||||
const scalar maxDelta,
|
||||
const scalar minDelta,
|
||||
const scalar extrapolate
|
||||
) const
|
||||
{
|
||||
if (extrapolate > maxDelta + VSMALL)
|
||||
scalar r = 1;
|
||||
|
||||
if (extrapolate > SMALL)
|
||||
{
|
||||
limiter = min(limiter, maxDelta/extrapolate);
|
||||
r = maxDelta/extrapolate;
|
||||
}
|
||||
else if (extrapolate < minDelta - VSMALL)
|
||||
else if (extrapolate < -SMALL)
|
||||
{
|
||||
limiter = min(limiter, minDelta/extrapolate);
|
||||
r = minDelta/extrapolate;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
limiter = min(limiter, Limiter::limiter(r));
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
inline void cellLimitedGrad<Type>::limitFace
|
||||
template<class Type, class Limiter>
|
||||
inline void cellLimitedGrad<Type, Limiter>::limitFace
|
||||
(
|
||||
Type& limiter,
|
||||
const Type& maxDelta,
|
||||
const Type& minDelta,
|
||||
const Type& extrapolate
|
||||
)
|
||||
) const
|
||||
{
|
||||
for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
|
||||
for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; ++cmpt)
|
||||
{
|
||||
cellLimitedGrad<scalar>::limitFace
|
||||
limitFaceCmpt
|
||||
(
|
||||
limiter.component(cmpt),
|
||||
maxDelta.component(cmpt),
|
||||
minDelta.component(cmpt),
|
||||
extrapolate.component(cmpt)
|
||||
setComponent(limiter, cmpt),
|
||||
component(maxDelta, cmpt),
|
||||
component(minDelta, cmpt),
|
||||
component(extrapolate, cmpt)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * Template Member Function Specialisations * * * * * * * * //
|
||||
|
||||
template<>
|
||||
tmp<volVectorField> cellLimitedGrad<scalar>::calcGrad
|
||||
(
|
||||
const volScalarField& vsf,
|
||||
const word& name
|
||||
) const;
|
||||
|
||||
|
||||
template<>
|
||||
tmp<volTensorField> cellLimitedGrad<vector>::calcGrad
|
||||
(
|
||||
const volVectorField& vsf,
|
||||
const word& name
|
||||
) const;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace fv
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
#ifdef NoRepository
|
||||
#include "cellLimitedGrad.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
@ -24,335 +24,49 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "cellLimitedGrad.H"
|
||||
#include "gaussGrad.H"
|
||||
#include "fvMesh.H"
|
||||
#include "volMesh.H"
|
||||
#include "surfaceMesh.H"
|
||||
#include "volFields.H"
|
||||
#include "fixedValueFvPatchFields.H"
|
||||
#include "minmodGradientLimiter.H"
|
||||
#include "VenkatakrishnanGradientLimiter.H"
|
||||
#include "cubicGradientLimiter.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
makeFvGradScheme(cellLimitedGrad)
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<>
|
||||
Foam::tmp<Foam::volVectorField>
|
||||
Foam::fv::cellLimitedGrad<Foam::scalar>::calcGrad
|
||||
(
|
||||
const volScalarField& vsf,
|
||||
const word& name
|
||||
) const
|
||||
{
|
||||
const fvMesh& mesh = vsf.mesh();
|
||||
|
||||
tmp<volVectorField> tGrad = basicGradScheme_().calcGrad(vsf, name);
|
||||
|
||||
if (k_ < SMALL)
|
||||
{
|
||||
return tGrad;
|
||||
#define makeNamedFvLimitedGradTypeScheme(SS, Type, Limiter, Name) \
|
||||
typedef Foam::fv::SS<Foam::Type, Foam::fv::gradientLimiters::Limiter> \
|
||||
SS##Type##Limiter##_; \
|
||||
\
|
||||
defineTemplateTypeNameAndDebugWithName \
|
||||
( \
|
||||
SS##Type##Limiter##_, \
|
||||
Name, \
|
||||
0 \
|
||||
); \
|
||||
\
|
||||
namespace Foam \
|
||||
{ \
|
||||
namespace fv \
|
||||
{ \
|
||||
gradScheme<Type>::addIstreamConstructorToTable \
|
||||
< \
|
||||
SS<Type, gradientLimiters::Limiter> \
|
||||
> add##SS##Type##Limiter##IstreamConstructorToTable_; \
|
||||
} \
|
||||
}
|
||||
|
||||
volVectorField& g = tGrad.ref();
|
||||
#define makeFvLimitedGradTypeScheme(SS, Type, Limiter) \
|
||||
makeNamedFvLimitedGradTypeScheme(SS##Grad, Type, Limiter, #SS"<"#Limiter">")
|
||||
|
||||
const labelUList& owner = mesh.owner();
|
||||
const labelUList& neighbour = mesh.neighbour();
|
||||
#define makeFvLimitedGradScheme(SS, Limiter) \
|
||||
\
|
||||
makeFvLimitedGradTypeScheme(SS, scalar, Limiter) \
|
||||
makeFvLimitedGradTypeScheme(SS, vector, Limiter)
|
||||
|
||||
const volVectorField& C = mesh.C();
|
||||
const surfaceVectorField& Cf = mesh.Cf();
|
||||
|
||||
scalarField maxVsf(vsf.primitiveField());
|
||||
scalarField minVsf(vsf.primitiveField());
|
||||
|
||||
forAll(owner, facei)
|
||||
{
|
||||
label own = owner[facei];
|
||||
label nei = neighbour[facei];
|
||||
|
||||
scalar vsfOwn = vsf[own];
|
||||
scalar vsfNei = vsf[nei];
|
||||
|
||||
maxVsf[own] = max(maxVsf[own], vsfNei);
|
||||
minVsf[own] = min(minVsf[own], vsfNei);
|
||||
|
||||
maxVsf[nei] = max(maxVsf[nei], vsfOwn);
|
||||
minVsf[nei] = min(minVsf[nei], vsfOwn);
|
||||
}
|
||||
|
||||
|
||||
const volScalarField::Boundary& bsf = vsf.boundaryField();
|
||||
|
||||
forAll(bsf, patchi)
|
||||
{
|
||||
const fvPatchScalarField& psf = bsf[patchi];
|
||||
|
||||
const labelUList& pOwner = mesh.boundary()[patchi].faceCells();
|
||||
|
||||
if (psf.coupled())
|
||||
{
|
||||
const scalarField psfNei(psf.patchNeighbourField());
|
||||
|
||||
forAll(pOwner, pFacei)
|
||||
{
|
||||
label own = pOwner[pFacei];
|
||||
scalar vsfNei = psfNei[pFacei];
|
||||
|
||||
maxVsf[own] = max(maxVsf[own], vsfNei);
|
||||
minVsf[own] = min(minVsf[own], vsfNei);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(pOwner, pFacei)
|
||||
{
|
||||
label own = pOwner[pFacei];
|
||||
scalar vsfNei = psf[pFacei];
|
||||
|
||||
maxVsf[own] = max(maxVsf[own], vsfNei);
|
||||
minVsf[own] = min(minVsf[own], vsfNei);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
maxVsf -= vsf;
|
||||
minVsf -= vsf;
|
||||
|
||||
if (k_ < 1.0)
|
||||
{
|
||||
const scalarField maxMinVsf((1.0/k_ - 1.0)*(maxVsf - minVsf));
|
||||
maxVsf += maxMinVsf;
|
||||
minVsf -= maxMinVsf;
|
||||
|
||||
//maxVsf *= 1.0/k_;
|
||||
//minVsf *= 1.0/k_;
|
||||
}
|
||||
|
||||
|
||||
// create limiter
|
||||
scalarField limiter(vsf.primitiveField().size(), 1.0);
|
||||
|
||||
forAll(owner, facei)
|
||||
{
|
||||
label own = owner[facei];
|
||||
label nei = neighbour[facei];
|
||||
|
||||
// owner side
|
||||
limitFace
|
||||
(
|
||||
limiter[own],
|
||||
maxVsf[own],
|
||||
minVsf[own],
|
||||
(Cf[facei] - C[own]) & g[own]
|
||||
);
|
||||
|
||||
// neighbour side
|
||||
limitFace
|
||||
(
|
||||
limiter[nei],
|
||||
maxVsf[nei],
|
||||
minVsf[nei],
|
||||
(Cf[facei] - C[nei]) & g[nei]
|
||||
);
|
||||
}
|
||||
|
||||
forAll(bsf, patchi)
|
||||
{
|
||||
const labelUList& pOwner = mesh.boundary()[patchi].faceCells();
|
||||
const vectorField& pCf = Cf.boundaryField()[patchi];
|
||||
|
||||
forAll(pOwner, pFacei)
|
||||
{
|
||||
label own = pOwner[pFacei];
|
||||
|
||||
limitFace
|
||||
(
|
||||
limiter[own],
|
||||
maxVsf[own],
|
||||
minVsf[own],
|
||||
(pCf[pFacei] - C[own]) & g[own]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (fv::debug)
|
||||
{
|
||||
Info<< "gradient limiter for: " << vsf.name()
|
||||
<< " max = " << gMax(limiter)
|
||||
<< " min = " << gMin(limiter)
|
||||
<< " average: " << gAverage(limiter) << endl;
|
||||
}
|
||||
|
||||
g.primitiveFieldRef() *= limiter;
|
||||
g.correctBoundaryConditions();
|
||||
gaussGrad<scalar>::correctBoundaryConditions(vsf, g);
|
||||
|
||||
return tGrad;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
Foam::tmp<Foam::volTensorField>
|
||||
Foam::fv::cellLimitedGrad<Foam::vector>::calcGrad
|
||||
(
|
||||
const volVectorField& vsf,
|
||||
const word& name
|
||||
) const
|
||||
{
|
||||
const fvMesh& mesh = vsf.mesh();
|
||||
|
||||
tmp<volTensorField> tGrad = basicGradScheme_().calcGrad(vsf, name);
|
||||
|
||||
if (k_ < SMALL)
|
||||
{
|
||||
return tGrad;
|
||||
}
|
||||
|
||||
volTensorField& g = tGrad.ref();
|
||||
|
||||
const labelUList& owner = mesh.owner();
|
||||
const labelUList& neighbour = mesh.neighbour();
|
||||
|
||||
const volVectorField& C = mesh.C();
|
||||
const surfaceVectorField& Cf = mesh.Cf();
|
||||
|
||||
vectorField maxVsf(vsf.primitiveField());
|
||||
vectorField minVsf(vsf.primitiveField());
|
||||
|
||||
forAll(owner, facei)
|
||||
{
|
||||
label own = owner[facei];
|
||||
label nei = neighbour[facei];
|
||||
|
||||
const vector& vsfOwn = vsf[own];
|
||||
const vector& vsfNei = vsf[nei];
|
||||
|
||||
maxVsf[own] = max(maxVsf[own], vsfNei);
|
||||
minVsf[own] = min(minVsf[own], vsfNei);
|
||||
|
||||
maxVsf[nei] = max(maxVsf[nei], vsfOwn);
|
||||
minVsf[nei] = min(minVsf[nei], vsfOwn);
|
||||
}
|
||||
|
||||
|
||||
const volVectorField::Boundary& bsf = vsf.boundaryField();
|
||||
|
||||
forAll(bsf, patchi)
|
||||
{
|
||||
const fvPatchVectorField& psf = bsf[patchi];
|
||||
const labelUList& pOwner = mesh.boundary()[patchi].faceCells();
|
||||
|
||||
if (psf.coupled())
|
||||
{
|
||||
const vectorField psfNei(psf.patchNeighbourField());
|
||||
|
||||
forAll(pOwner, pFacei)
|
||||
{
|
||||
label own = pOwner[pFacei];
|
||||
const vector& vsfNei = psfNei[pFacei];
|
||||
|
||||
maxVsf[own] = max(maxVsf[own], vsfNei);
|
||||
minVsf[own] = min(minVsf[own], vsfNei);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(pOwner, pFacei)
|
||||
{
|
||||
label own = pOwner[pFacei];
|
||||
const vector& vsfNei = psf[pFacei];
|
||||
|
||||
maxVsf[own] = max(maxVsf[own], vsfNei);
|
||||
minVsf[own] = min(minVsf[own], vsfNei);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
maxVsf -= vsf;
|
||||
minVsf -= vsf;
|
||||
|
||||
if (k_ < 1.0)
|
||||
{
|
||||
const vectorField maxMinVsf((1.0/k_ - 1.0)*(maxVsf - minVsf));
|
||||
maxVsf += maxMinVsf;
|
||||
minVsf -= maxMinVsf;
|
||||
|
||||
//maxVsf *= 1.0/k_;
|
||||
//minVsf *= 1.0/k_;
|
||||
}
|
||||
|
||||
|
||||
// create limiter
|
||||
vectorField limiter(vsf.primitiveField().size(), vector::one);
|
||||
|
||||
forAll(owner, facei)
|
||||
{
|
||||
label own = owner[facei];
|
||||
label nei = neighbour[facei];
|
||||
|
||||
// owner side
|
||||
limitFace
|
||||
(
|
||||
limiter[own],
|
||||
maxVsf[own],
|
||||
minVsf[own],
|
||||
(Cf[facei] - C[own]) & g[own]
|
||||
);
|
||||
|
||||
// neighbour side
|
||||
limitFace
|
||||
(
|
||||
limiter[nei],
|
||||
maxVsf[nei],
|
||||
minVsf[nei],
|
||||
(Cf[facei] - C[nei]) & g[nei]
|
||||
);
|
||||
}
|
||||
|
||||
forAll(bsf, patchi)
|
||||
{
|
||||
const labelUList& pOwner = mesh.boundary()[patchi].faceCells();
|
||||
const vectorField& pCf = Cf.boundaryField()[patchi];
|
||||
|
||||
forAll(pOwner, pFacei)
|
||||
{
|
||||
label own = pOwner[pFacei];
|
||||
|
||||
limitFace
|
||||
(
|
||||
limiter[own],
|
||||
maxVsf[own],
|
||||
minVsf[own],
|
||||
((pCf[pFacei] - C[own]) & g[own])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (fv::debug)
|
||||
{
|
||||
Info<< "gradient limiter for: " << vsf.name()
|
||||
<< " max = " << gMax(limiter)
|
||||
<< " min = " << gMin(limiter)
|
||||
<< " average: " << gAverage(limiter) << endl;
|
||||
}
|
||||
|
||||
tensorField& gIf = g.primitiveFieldRef();
|
||||
|
||||
forAll(gIf, celli)
|
||||
{
|
||||
gIf[celli] = tensor
|
||||
(
|
||||
cmptMultiply(limiter[celli], gIf[celli].x()),
|
||||
cmptMultiply(limiter[celli], gIf[celli].y()),
|
||||
cmptMultiply(limiter[celli], gIf[celli].z())
|
||||
);
|
||||
}
|
||||
|
||||
g.correctBoundaryConditions();
|
||||
gaussGrad<vector>::correctBoundaryConditions(vsf, g);
|
||||
|
||||
return tGrad;
|
||||
}
|
||||
// Default limiter in minmod specified without the limiter name
|
||||
// for backward compatibility
|
||||
makeNamedFvLimitedGradTypeScheme(cellLimitedGrad, scalar, minmod, "cellLimited")
|
||||
makeNamedFvLimitedGradTypeScheme(cellLimitedGrad, vector, minmod, "cellLimited")
|
||||
|
||||
makeFvLimitedGradScheme(cellLimited, Venkatakrishnan)
|
||||
makeFvLimitedGradScheme(cellLimited, cubic)
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -0,0 +1,113 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::fv::gradientLimiters::Venkatakrishnan
|
||||
|
||||
Description
|
||||
Venkatakrishnan gradient limiter
|
||||
|
||||
to be used with the Foam::fv::cellLimitedGrad limited gradient.
|
||||
|
||||
Reference:
|
||||
\verbatim
|
||||
Venkatakrishnan, V. (1993).
|
||||
On the accuracy of limiters and convergence to steady state solutions.
|
||||
In 31st Aerospace Sciences Meeting (p. 880).
|
||||
\endverbatim
|
||||
|
||||
Example:
|
||||
\verbatim
|
||||
gradSchemes
|
||||
{
|
||||
default Gauss linear;
|
||||
limited cellLimited<Venkatakrishnan> Gauss linear 1;
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Note: this limiter formally allows the limiter function to slightly exceed 1
|
||||
which is generally not a good idea and can cause unboundedness. To avoid
|
||||
this problem the limiter function is clipped to 1 which is likely to be
|
||||
better behaved but is then not differentiable and so no longer conforms to
|
||||
the basic principles of this kind of limiter function. All these issues are
|
||||
resolved in a consistent and differentiable manner by the
|
||||
Foam::fv::gradientLimiters::cubic limiter which is recommended in
|
||||
preference to the Foam::fv::gradientLimiters::Venkatakrishnan limiter.
|
||||
|
||||
See also
|
||||
Foam::fv::cellLimitedGrad
|
||||
Foam::fv::gradientLimiters::cubic
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef VenkatakrishnanGradientLimiter_H
|
||||
#define VenkatakrishnanGradientLimiter_H
|
||||
|
||||
#include "Istream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace fv
|
||||
{
|
||||
|
||||
namespace gradientLimiters
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
class Venkatakrishnan
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
Venkatakrishnan(Istream&)
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
inline scalar limiter(const scalar r) const
|
||||
{
|
||||
return (sqr(r) + 2*r)/(sqr(r) + r + 2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace gradientLimiters
|
||||
|
||||
} // End namespace fv
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,146 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::fv::gradientLimiters::minmod
|
||||
|
||||
Description
|
||||
Cubic gradient limiter
|
||||
|
||||
to be used with the Foam::fv::cellLimitedGrad limited gradient. This
|
||||
limiter function is similar to Foam::fv::gradientLimiters::Venkatakrishnan
|
||||
but is a fit to obey the value and gradient constraints and avoids the
|
||||
problem of the limiter exceeding 1 present in the Venkatakrishnan function.
|
||||
|
||||
The transition point at which the limiter function reaches 1 is an input
|
||||
parameter and should be set to a value between 1 and 2 although values
|
||||
larger than 2 are physical but likely to significantly reduce the accuracy
|
||||
of the scheme.
|
||||
|
||||
Reference:
|
||||
\verbatim
|
||||
Michalak, K., & Ollivier-Gooch, C. (2008).
|
||||
Limiters for unstructured higher-order accurate solutions
|
||||
of the Euler equations.
|
||||
In 46th AIAA Aerospace Sciences Meeting and Exhibit (p. 776).
|
||||
\endverbatim
|
||||
|
||||
Example:
|
||||
\verbatim
|
||||
gradSchemes
|
||||
{
|
||||
default Gauss linear;
|
||||
limited cellLimited<cubic> 1.5 Gauss linear 1;
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
See also
|
||||
Foam::fv::cellLimitedGrad
|
||||
Foam::fv::gradientLimiters::Venkatakrishnan
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef cubicGradientLimiter_H
|
||||
#define cubicGradientLimiter_H
|
||||
|
||||
#include "Istream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace fv
|
||||
{
|
||||
|
||||
namespace gradientLimiters
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
class cubic
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Limiter transition point at which the limiter function -> 1
|
||||
// Must be > 1
|
||||
const scalar rt_;
|
||||
|
||||
//- Coefficient of the r^3 term (evaluated from rt)
|
||||
const scalar a_;
|
||||
|
||||
// - Coefficient of the r^2 term (evaluated from rt)
|
||||
const scalar b_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
cubic(Istream& schemeData)
|
||||
:
|
||||
rt_(readScalar(schemeData)),
|
||||
a_(2.0/sqr(rt_) - 2.0/pow3(rt_)),
|
||||
b_(-(3.0/2.0)*a_*rt_)
|
||||
{
|
||||
if (rt_ < 1)
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
schemeData
|
||||
) << "coefficient = " << rt_
|
||||
<< " should be > 1"
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
inline scalar limiter(const scalar r) const
|
||||
{
|
||||
if (r < rt_)
|
||||
{
|
||||
return ((a_*r + b_)*r + 1)*r;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace gradientLimiters
|
||||
|
||||
} // End namespace fv
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,99 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::fv::gradientLimiters::minmod
|
||||
|
||||
Description
|
||||
Minmod gradient limiter
|
||||
|
||||
This is the default gradient limiter which clips the gradient to remove cell
|
||||
to face extrapolation unboundedness. It corresponds to the original
|
||||
cellLimitedGrad implementation before the addition of run-time select-able
|
||||
limiter functions.
|
||||
|
||||
Example:
|
||||
\verbatim
|
||||
gradSchemes
|
||||
{
|
||||
default Gauss linear;
|
||||
limited cellLimited Gauss linear 1;
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
See also
|
||||
Foam::fv::cellLimitedGrad
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef minmodGradientLimiter_H
|
||||
#define minmodGradientLimiter_H
|
||||
|
||||
#include "Istream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace fv
|
||||
{
|
||||
|
||||
namespace gradientLimiters
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
class minmod
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
minmod(Istream&)
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
inline scalar limiter(const scalar r) const
|
||||
{
|
||||
return min(r, 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace gradientLimiters
|
||||
|
||||
} // End namespace fv
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -61,7 +61,8 @@ Foam::functionObjects::turbulenceFields::compressibleFieldNames_
|
||||
{ compressibleField::cfAlphaEff, "alphaEff" },
|
||||
{ compressibleField::cfR, "R" },
|
||||
{ compressibleField::cfDevRhoReff, "devRhoReff" },
|
||||
{ compressibleField::cfL, "L" }
|
||||
{ compressibleField::cfL, "L" },
|
||||
{ compressibleField::cfI, "I" }
|
||||
};
|
||||
|
||||
|
||||
@ -80,6 +81,7 @@ Foam::functionObjects::turbulenceFields::incompressibleFieldNames_
|
||||
{ incompressibleField::ifR, "R" },
|
||||
{ incompressibleField::ifDevReff, "devReff" },
|
||||
{ incompressibleField::ifL, "L" },
|
||||
{ incompressibleField::ifI, "I" }
|
||||
};
|
||||
|
||||
|
||||
@ -236,6 +238,11 @@ bool Foam::functionObjects::turbulenceFields::execute()
|
||||
processField<scalar>(f, L(model));
|
||||
break;
|
||||
}
|
||||
case cfI:
|
||||
{
|
||||
processField<scalar>(f, I(model));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
FatalErrorInFunction
|
||||
@ -298,6 +305,11 @@ bool Foam::functionObjects::turbulenceFields::execute()
|
||||
processField<scalar>(f, L(model));
|
||||
break;
|
||||
}
|
||||
case ifI:
|
||||
{
|
||||
processField<scalar>(f, I(model));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
FatalErrorInFunction
|
||||
|
||||
@ -76,6 +76,7 @@ Usage
|
||||
devReff | Deviatoric part of the effective Reynolds stress
|
||||
devRhoReff | Divergence of the Reynolds stress
|
||||
L | turbulence length scale
|
||||
I | turbulence intensity
|
||||
\endplaintable
|
||||
|
||||
See also
|
||||
@ -125,7 +126,8 @@ public:
|
||||
cfAlphaEff,
|
||||
cfR,
|
||||
cfDevRhoReff,
|
||||
cfL
|
||||
cfL,
|
||||
cfI
|
||||
};
|
||||
static const Enum<compressibleField> compressibleFieldNames_;
|
||||
|
||||
@ -139,7 +141,8 @@ public:
|
||||
ifNuEff,
|
||||
ifR,
|
||||
ifDevReff,
|
||||
ifL
|
||||
ifL,
|
||||
ifI
|
||||
};
|
||||
static const Enum<incompressibleField> incompressibleFieldNames_;
|
||||
|
||||
@ -179,6 +182,10 @@ protected:
|
||||
template<class Model>
|
||||
tmp<volScalarField> L(const Model& model) const;
|
||||
|
||||
//- Return I calculated from k and U
|
||||
template<class Model>
|
||||
tmp<volScalarField> I(const Model& model) const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@ -85,19 +85,16 @@ Foam::functionObjects::turbulenceFields::omega
|
||||
const volScalarField k(model.k());
|
||||
const volScalarField epsilon(model.epsilon());
|
||||
|
||||
return tmp<volScalarField>
|
||||
return tmp<volScalarField>::New
|
||||
(
|
||||
new volScalarField
|
||||
IOobject
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"omega.tmp",
|
||||
k.mesh().time().timeName(),
|
||||
k.mesh()
|
||||
),
|
||||
epsilon/(Cmu*k),
|
||||
epsilon.boundaryField().types()
|
||||
)
|
||||
"omega.tmp",
|
||||
k.mesh().time().timeName(),
|
||||
k.mesh()
|
||||
),
|
||||
epsilon/(Cmu*k),
|
||||
epsilon.boundaryField().types()
|
||||
);
|
||||
}
|
||||
|
||||
@ -109,9 +106,10 @@ Foam::functionObjects::turbulenceFields::nuTilda
|
||||
const Model& model
|
||||
) const
|
||||
{
|
||||
return tmp<volScalarField>
|
||||
return tmp<volScalarField>::New
|
||||
(
|
||||
new volScalarField("nuTilda.tmp", model.k()/omega(model))
|
||||
"nuTilda.tmp",
|
||||
model.k()/omega(model)
|
||||
);
|
||||
}
|
||||
|
||||
@ -130,15 +128,30 @@ Foam::functionObjects::turbulenceFields::L
|
||||
const volScalarField epsilon(model.epsilon());
|
||||
const dimensionedScalar eps0("eps0", epsilon.dimensions(), SMALL);
|
||||
|
||||
return tmp<volScalarField>
|
||||
return tmp<volScalarField>::New
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
"L.tmp",
|
||||
pow(Cmu, 0.75)*pow(k, 1.5)/(epsilon + eps0)
|
||||
)
|
||||
"L.tmp",
|
||||
pow(Cmu, 0.75)*pow(k, 1.5)/(epsilon + eps0)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Model>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::functionObjects::turbulenceFields::I
|
||||
(
|
||||
const Model& model
|
||||
) const
|
||||
{
|
||||
// Assume k is available
|
||||
const volScalarField uPrime(sqrt((2.0/3.0)*model.k()));
|
||||
const dimensionedScalar U0("U0", dimVelocity, SMALL);
|
||||
|
||||
return tmp<volScalarField>::New
|
||||
(
|
||||
"I.tmp",
|
||||
uPrime/max(max(uPrime, mag(model.U())), U0)
|
||||
);
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -353,7 +353,7 @@ Foam::functionObjects::forces::devRhoReff() const
|
||||
const dictionary& transportProperties =
|
||||
lookupObject<dictionary>("transportProperties");
|
||||
|
||||
dimensionedScalar nu(transportProperties.lookup("nu"));
|
||||
dimensionedScalar nu("nu", dimViscosity, transportProperties);
|
||||
|
||||
const volVectorField& U = lookupObject<volVectorField>(UName_);
|
||||
|
||||
|
||||
@ -108,6 +108,7 @@ bool Foam::functionObjects::vtkWrite::read(const dictionary& dict)
|
||||
//
|
||||
dict.readIfPresent("directory", dirName_);
|
||||
|
||||
decompose_ = dict.lookupOrDefault("decompose", false);
|
||||
writeIds_ = dict.lookupOrDefault("writeIds", false);
|
||||
|
||||
|
||||
@ -185,7 +186,7 @@ bool Foam::functionObjects::vtkWrite::write()
|
||||
(
|
||||
mesh_,
|
||||
writeOpts_,
|
||||
true // decompose
|
||||
decompose_
|
||||
);
|
||||
|
||||
// Write mesh
|
||||
|
||||
@ -44,6 +44,7 @@ Description
|
||||
writeInterval 1;
|
||||
format binary;
|
||||
legacy false;
|
||||
decompose false;
|
||||
...
|
||||
fields (U p);
|
||||
}
|
||||
@ -51,14 +52,15 @@ Description
|
||||
|
||||
Usage
|
||||
\table
|
||||
Property | Description | Required | Default value
|
||||
type | Type name: vtkWrite | yes |
|
||||
fields | Fields to output | yes |
|
||||
writeControl | Output control | recommended | timeStep
|
||||
directory | The output directory name | no | "VTK"
|
||||
format | ASCII or binary format | no | binary
|
||||
legacy | Legacy VTK output | no | false
|
||||
writeIds | Write cell ids as field | no | true
|
||||
Property | Description | Required | Default
|
||||
type | Type name: vtkWrite | yes |
|
||||
fields | Fields to output | yes |
|
||||
writeControl | Output control | recommended | timeStep
|
||||
directory | The output directory name | no | "VTK"
|
||||
format | ASCII or binary format | no | binary
|
||||
legacy | Legacy VTK output | no | false
|
||||
decompose | decompose polyhedra | no | false
|
||||
writeIds | Write cell ids as field | no | true
|
||||
\endtable
|
||||
|
||||
See also
|
||||
@ -106,6 +108,9 @@ class vtkWrite
|
||||
//- Output directory name
|
||||
fileName dirName_;
|
||||
|
||||
//- Decompose polyhedra
|
||||
bool decompose_;
|
||||
|
||||
//- Write cell ids field
|
||||
bool writeIds_;
|
||||
|
||||
@ -119,7 +124,11 @@ class vtkWrite
|
||||
|
||||
//- Write selected fields for GeoField type.
|
||||
template<class GeoField>
|
||||
label writeFields(vtk::internalWriter& writer, bool verbose=true) const;
|
||||
label writeFields
|
||||
(
|
||||
vtk::internalWriter& writer,
|
||||
bool verbose=true
|
||||
) const;
|
||||
|
||||
|
||||
//- Write selected fields for GeoField type.
|
||||
@ -131,10 +140,10 @@ class vtkWrite
|
||||
) const;
|
||||
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
//- No copy construct
|
||||
vtkWrite(const vtkWrite&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
//- No copy assignment
|
||||
void operator=(const vtkWrite&) = delete;
|
||||
|
||||
|
||||
@ -150,7 +159,7 @@ public:
|
||||
vtkWrite
|
||||
(
|
||||
const word& name,
|
||||
const Time& t,
|
||||
const Time& runTime,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
@ -57,34 +57,6 @@ registerInfoSwitch
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::particle::stationaryTetGeometry
|
||||
(
|
||||
vector& centre,
|
||||
vector& base,
|
||||
vector& vertex1,
|
||||
vector& vertex2
|
||||
) const
|
||||
{
|
||||
const triFace triIs(currentTetIndices().faceTriIs(mesh_));
|
||||
const vectorField& ccs = mesh_.cellCentres();
|
||||
const pointField& pts = mesh_.points();
|
||||
|
||||
centre = ccs[celli_];
|
||||
base = pts[triIs[0]];
|
||||
vertex1 = pts[triIs[1]];
|
||||
vertex2 = pts[triIs[2]];
|
||||
}
|
||||
|
||||
|
||||
Foam::barycentricTensor Foam::particle::stationaryTetTransform() const
|
||||
{
|
||||
vector centre, base, vertex1, vertex2;
|
||||
stationaryTetGeometry(centre, base, vertex1, vertex2);
|
||||
|
||||
return barycentricTensor(centre, base, vertex1, vertex2);
|
||||
}
|
||||
|
||||
|
||||
void Foam::particle::stationaryTetReverseTransform
|
||||
(
|
||||
vector& centre,
|
||||
@ -114,61 +86,6 @@ void Foam::particle::stationaryTetReverseTransform
|
||||
}
|
||||
|
||||
|
||||
void Foam::particle::movingTetGeometry
|
||||
(
|
||||
const scalar fraction,
|
||||
Pair<vector>& centre,
|
||||
Pair<vector>& base,
|
||||
Pair<vector>& vertex1,
|
||||
Pair<vector>& vertex2
|
||||
) const
|
||||
{
|
||||
const triFace triIs(currentTetIndices().faceTriIs(mesh_));
|
||||
const pointField& ptsOld = mesh_.oldPoints();
|
||||
const pointField& ptsNew = mesh_.points();
|
||||
|
||||
// !!! <-- We would be better off using mesh_.cellCentres() here. However,
|
||||
// we need to put a mesh_.oldCellCentres() method in for this to work. The
|
||||
// values obtained from the mesh and those obtained from the cell do not
|
||||
// necessarily match. See mantis #1993.
|
||||
const vector ccOld = mesh_.cells()[celli_].centre(ptsOld, mesh_.faces());
|
||||
const vector ccNew = mesh_.cells()[celli_].centre(ptsNew, mesh_.faces());
|
||||
|
||||
// Old and new points and cell centres are not sub-cycled. If we are sub-
|
||||
// cycling, then we have to account for the timestep change here by
|
||||
// modifying the fractions that we take of the old and new geometry.
|
||||
const Pair<scalar> s = stepFractionSpan();
|
||||
const scalar f0 = s[0] + stepFraction_*s[1], f1 = fraction*s[1];
|
||||
|
||||
centre[0] = ccOld + f0*(ccNew - ccOld);
|
||||
base[0] = ptsOld[triIs[0]] + f0*(ptsNew[triIs[0]] - ptsOld[triIs[0]]);
|
||||
vertex1[0] = ptsOld[triIs[1]] + f0*(ptsNew[triIs[1]] - ptsOld[triIs[1]]);
|
||||
vertex2[0] = ptsOld[triIs[2]] + f0*(ptsNew[triIs[2]] - ptsOld[triIs[2]]);
|
||||
|
||||
centre[1] = f1*(ccNew - ccOld);
|
||||
base[1] = f1*(ptsNew[triIs[0]] - ptsOld[triIs[0]]);
|
||||
vertex1[1] = f1*(ptsNew[triIs[1]] - ptsOld[triIs[1]]);
|
||||
vertex2[1] = f1*(ptsNew[triIs[2]] - ptsOld[triIs[2]]);
|
||||
}
|
||||
|
||||
|
||||
Foam::Pair<Foam::barycentricTensor> Foam::particle::movingTetTransform
|
||||
(
|
||||
const scalar fraction
|
||||
) const
|
||||
{
|
||||
Pair<vector> centre, base, vertex1, vertex2;
|
||||
movingTetGeometry(fraction, centre, base, vertex1, vertex2);
|
||||
|
||||
return
|
||||
Pair<barycentricTensor>
|
||||
(
|
||||
barycentricTensor(centre[0], base[0], vertex1[0], vertex2[0]),
|
||||
barycentricTensor(centre[1], base[1], vertex1[1], vertex2[1])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void Foam::particle::movingTetReverseTransform
|
||||
(
|
||||
const scalar fraction,
|
||||
@ -1013,47 +930,6 @@ Foam::vector Foam::particle::deviationFromMeshCentre() const
|
||||
}
|
||||
|
||||
|
||||
void Foam::particle::patchData(vector& n, vector& U) const
|
||||
{
|
||||
if (!onBoundaryFace())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Patch data was requested for a particle that isn't on a patch"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
if (mesh_.moving())
|
||||
{
|
||||
Pair<vector> centre, base, vertex1, vertex2;
|
||||
movingTetGeometry(1, centre, base, vertex1, vertex2);
|
||||
|
||||
n = triPointRef(base[0], vertex1[0], vertex2[0]).normal();
|
||||
n /= mag(n);
|
||||
|
||||
// Interpolate the motion of the three face vertices to the current
|
||||
// coordinates
|
||||
U =
|
||||
coordinates_.b()*base[1]
|
||||
+ coordinates_.c()*vertex1[1]
|
||||
+ coordinates_.d()*vertex2[1];
|
||||
|
||||
// The movingTetGeometry method gives the motion as a displacement
|
||||
// across the time-step, so we divide by the time-step to get velocity
|
||||
U /= mesh_.time().deltaTValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
vector centre, base, vertex1, vertex2;
|
||||
stationaryTetGeometry(centre, base, vertex1, vertex2);
|
||||
|
||||
n = triPointRef(base, vertex1, vertex2).normal();
|
||||
n /= mag(n);
|
||||
|
||||
U = Zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::particle::transformProperties(const tensor&)
|
||||
{}
|
||||
|
||||
|
||||
@ -180,7 +180,7 @@ private:
|
||||
// Tetrahedra functions
|
||||
|
||||
//- Get the vertices of the current tet
|
||||
void stationaryTetGeometry
|
||||
inline void stationaryTetGeometry
|
||||
(
|
||||
vector& centre,
|
||||
vector& base,
|
||||
@ -193,7 +193,7 @@ private:
|
||||
// Cartesian position in the global coordinate system. The
|
||||
// conversion is x = A & y, where x is the Cartesian position, y is
|
||||
// the barycentric position and A is the transformation tensor.
|
||||
barycentricTensor stationaryTetTransform() const;
|
||||
inline barycentricTensor stationaryTetTransform() const;
|
||||
|
||||
//- Get the reverse transform associated with the current tet. The
|
||||
// conversion is detA*y = (x - centre) & T. The variables x, y and
|
||||
@ -212,7 +212,7 @@ private:
|
||||
//- Get the vertices of the current moving tet. Two values are
|
||||
// returned for each vertex. The first is a constant, and the
|
||||
// second is a linear coefficient of the track fraction.
|
||||
void movingTetGeometry
|
||||
inline void movingTetGeometry
|
||||
(
|
||||
const scalar endStepFraction,
|
||||
Pair<vector>& centre,
|
||||
@ -225,7 +225,7 @@ private:
|
||||
// This is of the same form as for the static case. As with the
|
||||
// moving geometry, a linear function of the tracking fraction is
|
||||
// returned for each component.
|
||||
Pair<barycentricTensor> movingTetTransform
|
||||
inline Pair<barycentricTensor> movingTetTransform
|
||||
(
|
||||
const scalar endStepFraction
|
||||
) const;
|
||||
@ -625,7 +625,7 @@ public:
|
||||
// Patch data
|
||||
|
||||
//- Get the normal and velocity of the current patch location
|
||||
void patchData(vector& n, vector& U) const;
|
||||
inline void patchData(vector& n, vector& U) const;
|
||||
|
||||
|
||||
// Transformations
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -26,6 +26,91 @@ License
|
||||
#include "polyMesh.H"
|
||||
#include "Time.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::particle::stationaryTetGeometry
|
||||
(
|
||||
vector& centre,
|
||||
vector& base,
|
||||
vector& vertex1,
|
||||
vector& vertex2
|
||||
) const
|
||||
{
|
||||
const triFace triIs(currentTetIndices().faceTriIs(mesh_));
|
||||
const vectorField& ccs = mesh_.cellCentres();
|
||||
const pointField& pts = mesh_.points();
|
||||
|
||||
centre = ccs[celli_];
|
||||
base = pts[triIs[0]];
|
||||
vertex1 = pts[triIs[1]];
|
||||
vertex2 = pts[triIs[2]];
|
||||
}
|
||||
|
||||
|
||||
inline Foam::barycentricTensor Foam::particle::stationaryTetTransform() const
|
||||
{
|
||||
vector centre, base, vertex1, vertex2;
|
||||
stationaryTetGeometry(centre, base, vertex1, vertex2);
|
||||
|
||||
return barycentricTensor(centre, base, vertex1, vertex2);
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::particle::movingTetGeometry
|
||||
(
|
||||
const scalar fraction,
|
||||
Pair<vector>& centre,
|
||||
Pair<vector>& base,
|
||||
Pair<vector>& vertex1,
|
||||
Pair<vector>& vertex2
|
||||
) const
|
||||
{
|
||||
const triFace triIs(currentTetIndices().faceTriIs(mesh_));
|
||||
const pointField& ptsOld = mesh_.oldPoints();
|
||||
const pointField& ptsNew = mesh_.points();
|
||||
|
||||
// !!! <-- We would be better off using mesh_.cellCentres() here. However,
|
||||
// we need to put a mesh_.oldCellCentres() method in for this to work. The
|
||||
// values obtained from the mesh and those obtained from the cell do not
|
||||
// necessarily match. See mantis #1993.
|
||||
const vector ccOld = mesh_.cells()[celli_].centre(ptsOld, mesh_.faces());
|
||||
const vector ccNew = mesh_.cells()[celli_].centre(ptsNew, mesh_.faces());
|
||||
|
||||
// Old and new points and cell centres are not sub-cycled. If we are sub-
|
||||
// cycling, then we have to account for the timestep change here by
|
||||
// modifying the fractions that we take of the old and new geometry.
|
||||
const Pair<scalar> s = stepFractionSpan();
|
||||
const scalar f0 = s[0] + stepFraction_*s[1], f1 = fraction*s[1];
|
||||
|
||||
centre[0] = ccOld + f0*(ccNew - ccOld);
|
||||
base[0] = ptsOld[triIs[0]] + f0*(ptsNew[triIs[0]] - ptsOld[triIs[0]]);
|
||||
vertex1[0] = ptsOld[triIs[1]] + f0*(ptsNew[triIs[1]] - ptsOld[triIs[1]]);
|
||||
vertex2[0] = ptsOld[triIs[2]] + f0*(ptsNew[triIs[2]] - ptsOld[triIs[2]]);
|
||||
|
||||
centre[1] = f1*(ccNew - ccOld);
|
||||
base[1] = f1*(ptsNew[triIs[0]] - ptsOld[triIs[0]]);
|
||||
vertex1[1] = f1*(ptsNew[triIs[1]] - ptsOld[triIs[1]]);
|
||||
vertex2[1] = f1*(ptsNew[triIs[2]] - ptsOld[triIs[2]]);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::Pair<Foam::barycentricTensor> Foam::particle::movingTetTransform
|
||||
(
|
||||
const scalar fraction
|
||||
) const
|
||||
{
|
||||
Pair<vector> centre, base, vertex1, vertex2;
|
||||
movingTetGeometry(fraction, centre, base, vertex1, vertex2);
|
||||
|
||||
return
|
||||
Pair<barycentricTensor>
|
||||
(
|
||||
barycentricTensor(centre[0], base[0], vertex1[0], vertex2[0]),
|
||||
barycentricTensor(centre[1], base[1], vertex1[1], vertex2[1])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline Foam::label Foam::particle::getNewParticleID() const
|
||||
@ -231,4 +316,45 @@ inline Foam::vector Foam::particle::position() const
|
||||
}
|
||||
|
||||
|
||||
void Foam::particle::patchData(vector& n, vector& U) const
|
||||
{
|
||||
if (!onBoundaryFace())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Patch data was requested for a particle that isn't on a patch"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
if (mesh_.moving())
|
||||
{
|
||||
Pair<vector> centre, base, vertex1, vertex2;
|
||||
movingTetGeometry(1, centre, base, vertex1, vertex2);
|
||||
|
||||
n = triPointRef(base[0], vertex1[0], vertex2[0]).normal();
|
||||
n /= mag(n);
|
||||
|
||||
// Interpolate the motion of the three face vertices to the current
|
||||
// coordinates
|
||||
U =
|
||||
coordinates_.b()*base[1]
|
||||
+ coordinates_.c()*vertex1[1]
|
||||
+ coordinates_.d()*vertex2[1];
|
||||
|
||||
// The movingTetGeometry method gives the motion as a displacement
|
||||
// across the time-step, so we divide by the time-step to get velocity
|
||||
U /= mesh_.time().deltaTValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
vector centre, base, vertex1, vertex2;
|
||||
stationaryTetGeometry(centre, base, vertex1, vertex2);
|
||||
|
||||
n = triPointRef(base, vertex1, vertex2).normal();
|
||||
n /= mag(n);
|
||||
|
||||
U = Zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -156,6 +156,8 @@ void Foam::particle::hitFace
|
||||
}
|
||||
else if (onBoundaryFace())
|
||||
{
|
||||
changeToMasterPatch();
|
||||
|
||||
if (!p.hitPatch(cloud, ttd))
|
||||
{
|
||||
const polyPatch& patch = mesh_.boundaryMesh()[p.patch()];
|
||||
@ -212,11 +214,6 @@ void Foam::particle::trackToAndHitFace
|
||||
{
|
||||
trackToFace(direction, fraction);
|
||||
|
||||
if (onBoundaryFace())
|
||||
{
|
||||
changeToMasterPatch();
|
||||
}
|
||||
|
||||
hitFace(direction, cloud, td);
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -34,6 +34,7 @@ License
|
||||
#include "ParticleErosion.H"
|
||||
#include "ParticleTracks.H"
|
||||
#include "ParticleTrap.H"
|
||||
#include "PatchCollisionDensity.H"
|
||||
#include "PatchPostProcessing.H"
|
||||
#include "VoidFraction.H"
|
||||
|
||||
@ -48,6 +49,7 @@ License
|
||||
makeCloudFunctionObjectType(ParticleErosion, CloudType); \
|
||||
makeCloudFunctionObjectType(ParticleTracks, CloudType); \
|
||||
makeCloudFunctionObjectType(ParticleTrap, CloudType); \
|
||||
makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \
|
||||
makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \
|
||||
makeCloudFunctionObjectType(VoidFraction, CloudType);
|
||||
|
||||
|
||||
@ -0,0 +1,168 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "PatchCollisionDensity.H"
|
||||
#include "Pstream.H"
|
||||
#include "stringListOps.H"
|
||||
#include "ListOps.H"
|
||||
#include "ListListOps.H"
|
||||
|
||||
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
|
||||
|
||||
template<class CloudType>
|
||||
void Foam::PatchCollisionDensity<CloudType>::write()
|
||||
{
|
||||
const scalarField z(this->owner().mesh().nCells(), 0);
|
||||
|
||||
volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
this->owner().name() + ":collisionDensity",
|
||||
this->owner().mesh().time().timeName(),
|
||||
this->owner().mesh()
|
||||
),
|
||||
this->owner().mesh(),
|
||||
dimless/dimArea,
|
||||
z,
|
||||
collisionDensity_
|
||||
)
|
||||
.write();
|
||||
|
||||
volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
this->owner().name() + ":collisionDensityRate",
|
||||
this->owner().mesh().time().timeName(),
|
||||
this->owner().mesh()
|
||||
),
|
||||
this->owner().mesh(),
|
||||
dimless/dimArea/dimTime,
|
||||
z,
|
||||
(collisionDensity_ - collisionDensity0_)
|
||||
/(this->owner().mesh().time().value() - time0_)
|
||||
)
|
||||
.write();
|
||||
|
||||
collisionDensity0_ == collisionDensity_;
|
||||
time0_ = this->owner().mesh().time().value();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class CloudType>
|
||||
Foam::PatchCollisionDensity<CloudType>::PatchCollisionDensity
|
||||
(
|
||||
const dictionary& dict,
|
||||
CloudType& owner,
|
||||
const word& modelName
|
||||
)
|
||||
:
|
||||
CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
|
||||
minSpeed_(dict.lookupOrDefault<scalar>("minSpeed", -1)),
|
||||
collisionDensity_
|
||||
(
|
||||
this->owner().mesh().boundary(),
|
||||
volScalarField::Internal::null(),
|
||||
calculatedFvPatchField<scalar>::typeName
|
||||
),
|
||||
collisionDensity0_
|
||||
(
|
||||
this->owner().mesh().boundary(),
|
||||
volScalarField::Internal::null(),
|
||||
calculatedFvPatchField<scalar>::typeName
|
||||
),
|
||||
time0_(this->owner().mesh().time().value())
|
||||
{
|
||||
collisionDensity_ == 0;
|
||||
collisionDensity0_ == 0;
|
||||
|
||||
IOobject io
|
||||
(
|
||||
this->owner().name() + ":collisionDensity",
|
||||
this->owner().mesh().time().timeName(),
|
||||
this->owner().mesh(),
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
);
|
||||
|
||||
if (io.typeHeaderOk<volScalarField>())
|
||||
{
|
||||
const volScalarField collisionDensity(io, this->owner().mesh());
|
||||
collisionDensity_ == collisionDensity.boundaryField();
|
||||
collisionDensity0_ == collisionDensity.boundaryField();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class CloudType>
|
||||
Foam::PatchCollisionDensity<CloudType>::PatchCollisionDensity
|
||||
(
|
||||
const PatchCollisionDensity<CloudType>& ppm
|
||||
)
|
||||
:
|
||||
CloudFunctionObject<CloudType>(ppm),
|
||||
minSpeed_(ppm.minSpeed_),
|
||||
collisionDensity_(ppm.collisionDensity_),
|
||||
collisionDensity0_(ppm.collisionDensity0_),
|
||||
time0_(ppm.time0_)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class CloudType>
|
||||
Foam::PatchCollisionDensity<CloudType>::~PatchCollisionDensity()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class CloudType>
|
||||
void Foam::PatchCollisionDensity<CloudType>::postPatch
|
||||
(
|
||||
const parcelType& p,
|
||||
const polyPatch& pp,
|
||||
bool&
|
||||
)
|
||||
{
|
||||
const label patchi = pp.index();
|
||||
const label patchFacei = p.face() - pp.start();
|
||||
|
||||
vector nw, Up;
|
||||
this->owner().patchData(p, pp, nw, Up);
|
||||
|
||||
const scalar speed = (p.U() - Up) & nw;
|
||||
if (speed > minSpeed_)
|
||||
{
|
||||
collisionDensity_[patchi][patchFacei] +=
|
||||
1/this->owner().mesh().magSf().boundaryField()[patchi][patchFacei];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,152 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::PatchCollisionDensity
|
||||
|
||||
Description
|
||||
Function object which generates fields of the number and rate of collisions
|
||||
per unit area on all patches. Can optionally take a minimum speed below
|
||||
which a collision is not counted.
|
||||
|
||||
Example usage:
|
||||
\verbatim
|
||||
patchCollisionDensity1
|
||||
{
|
||||
type patchCollisionDensity;
|
||||
minSpeed 1e-3;
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
SourceFiles
|
||||
PatchCollisionDensity.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef PatchCollisionDensity_H
|
||||
#define PatchCollisionDensity_H
|
||||
|
||||
#include "CloudFunctionObject.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class PatchCollisionDensity Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class CloudType>
|
||||
class PatchCollisionDensity
|
||||
:
|
||||
public CloudFunctionObject<CloudType>
|
||||
{
|
||||
// Private data
|
||||
|
||||
typedef typename CloudType::particleType parcelType;
|
||||
|
||||
//- The threshold for a collision
|
||||
const scalar minSpeed_;
|
||||
|
||||
//- The field of the number of collisions per unit area
|
||||
volScalarField::Boundary collisionDensity_;
|
||||
|
||||
//- The field of the number of collisions per unit area at the last
|
||||
// output
|
||||
volScalarField::Boundary collisionDensity0_;
|
||||
|
||||
//- The time at the last output
|
||||
scalar time0_;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Write post-processing info
|
||||
void write();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("patchCollisionDensity");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from dictionary
|
||||
PatchCollisionDensity
|
||||
(
|
||||
const dictionary& dict,
|
||||
CloudType& owner,
|
||||
const word& modelName
|
||||
);
|
||||
|
||||
//- Construct copy
|
||||
PatchCollisionDensity(const PatchCollisionDensity<CloudType>& ppm);
|
||||
|
||||
//- Construct and return a clone
|
||||
virtual autoPtr<CloudFunctionObject<CloudType>> clone() const
|
||||
{
|
||||
return autoPtr<CloudFunctionObject<CloudType>>
|
||||
(
|
||||
new PatchCollisionDensity<CloudType>(*this)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~PatchCollisionDensity();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Evaluation
|
||||
|
||||
//- Post-patch hook
|
||||
virtual void postPatch
|
||||
(
|
||||
const parcelType& p,
|
||||
const polyPatch& pp,
|
||||
bool& keepParticle
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "PatchCollisionDensity.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -250,7 +250,7 @@ void Foam::lumpedPointDisplacementPointPatchVectorField::updateCoeffs()
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
movement().writeData(forces, moments);
|
||||
movement().writeData(forces, moments, &(db().time()));
|
||||
|
||||
// Signal external source to execute
|
||||
movement().coupler().useSlave();
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -48,29 +48,65 @@ Foam::lumpedPointMovement::formatNames
|
||||
};
|
||||
|
||||
|
||||
const Foam::Enum
|
||||
<
|
||||
Foam::lumpedPointMovement::scalingType
|
||||
>
|
||||
Foam::lumpedPointMovement::scalingNames
|
||||
{
|
||||
{ scalingType::LENGTH, "plain" },
|
||||
{ scalingType::FORCE, "force" },
|
||||
{ scalingType::MOMENT, "moment" }
|
||||
};
|
||||
|
||||
|
||||
const Foam::word
|
||||
Foam::lumpedPointMovement::dictionaryName("lumpedPointMovement");
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
//! \cond fileScope
|
||||
//- Space-separated vector value (ASCII)
|
||||
static inline Ostream& putPlain(Ostream& os, const vector& val)
|
||||
{
|
||||
os << val.x() << ' ' << val.y() << ' ' << val.z();
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
//! \cond fileScope
|
||||
//- Space-separated vector value (ASCII)
|
||||
static inline Ostream& putTime(Ostream& os, const Time& t)
|
||||
{
|
||||
os <<"Time index=" << t.timeIndex()
|
||||
<< " value=" << t.timeOutputValue();
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
//! \cond fileScope
|
||||
//- Write list content with size, bracket, content, bracket one-per-line.
|
||||
// This makes for consistent for parsing, regardless of the list length.
|
||||
template <class T>
|
||||
static void writeList(Ostream& os, const string& header, const UList<T>& lst)
|
||||
static void writeList(Ostream& os, const string& header, const UList<T>& list)
|
||||
{
|
||||
const label len = list.size();
|
||||
|
||||
// Header string
|
||||
os << header.c_str() << nl;
|
||||
|
||||
// Write size and start delimiter
|
||||
os << lst.size() << nl
|
||||
<< token::BEGIN_LIST << nl;
|
||||
os << len << nl << token::BEGIN_LIST << nl;
|
||||
|
||||
// Write contents
|
||||
forAll(lst, i)
|
||||
for (label i=0; i < len; ++i)
|
||||
{
|
||||
os << lst[i] << nl;
|
||||
os << list[i] << nl;
|
||||
}
|
||||
|
||||
// Write end delimiter
|
||||
@ -165,8 +201,11 @@ Foam::lumpedPointMovement::lumpedPointMovement()
|
||||
coupler_(),
|
||||
inputName_("positions.in"),
|
||||
outputName_("forces.out"),
|
||||
logName_("movement.log"),
|
||||
inputFormat_(lumpedPointState::inputFormatType::DICTIONARY),
|
||||
outputFormat_(outputFormatType::DICTIONARY),
|
||||
scaleInput_(-1.0),
|
||||
scaleOutput_(-1.0),
|
||||
state0_(),
|
||||
state_(),
|
||||
thresholdPtr_(0),
|
||||
@ -198,6 +237,11 @@ Foam::lumpedPointMovement::lumpedPointMovement
|
||||
autoCentre_(true),
|
||||
forcesDict_(),
|
||||
coupler_(),
|
||||
inputName_("positions.in"),
|
||||
outputName_("forces.out"),
|
||||
logName_("movement.log"),
|
||||
scaleInput_(-1.0),
|
||||
scaleOutput_(-1.0),
|
||||
state0_(),
|
||||
state_(),
|
||||
thresholdPtr_(0),
|
||||
@ -262,6 +306,7 @@ void Foam::lumpedPointMovement::readDict(const dictionary& dict)
|
||||
|
||||
commDict.lookup("inputName") >> inputName_;
|
||||
commDict.lookup("outputName") >> outputName_;
|
||||
commDict.readIfPresent("logName", logName_);
|
||||
|
||||
inputFormat_ = lumpedPointState::formatNames.lookup
|
||||
(
|
||||
@ -274,6 +319,47 @@ void Foam::lumpedPointMovement::readDict(const dictionary& dict)
|
||||
"outputFormat",
|
||||
commDict
|
||||
);
|
||||
|
||||
scaleInput_ = -1;
|
||||
scaleOutput_ = -1;
|
||||
|
||||
const dictionary* scaleDict = nullptr;
|
||||
|
||||
if ((scaleDict = commDict.subDictPtr("scaleInput")))
|
||||
{
|
||||
for (int i=0; i < scaleInput_.size(); ++i)
|
||||
{
|
||||
const word& key = scalingNames[scalingType(i)];
|
||||
|
||||
if
|
||||
(
|
||||
scaleDict->readIfPresent(key, scaleInput_[i])
|
||||
&& scaleInput_[i] > 0
|
||||
)
|
||||
{
|
||||
Info<<"Using input " << key << " multiplier: "
|
||||
<< scaleInput_[i] << nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((scaleDict = commDict.subDictPtr("scaleOutput")))
|
||||
{
|
||||
for (int i=0; i < scaleOutput_.size(); ++i)
|
||||
{
|
||||
const word& key = scalingNames[scalingType(i)];
|
||||
|
||||
if
|
||||
(
|
||||
scaleDict->readIfPresent(key, scaleOutput_[i])
|
||||
&& scaleOutput_[i] > 0
|
||||
)
|
||||
{
|
||||
Info<<"Using output " << key << " multiplier: "
|
||||
<< scaleOutput_[i] << nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -638,6 +724,8 @@ bool Foam::lumpedPointMovement::readState()
|
||||
coupler().resolveFile(inputName_)
|
||||
);
|
||||
|
||||
state_.scalePoints(scaleInput_[scalingType::LENGTH]);
|
||||
|
||||
state_.relax(relax_, prev);
|
||||
|
||||
return status;
|
||||
@ -646,45 +734,114 @@ bool Foam::lumpedPointMovement::readState()
|
||||
|
||||
bool Foam::lumpedPointMovement::writeData
|
||||
(
|
||||
const UList<vector>& forces
|
||||
Ostream& os,
|
||||
const UList<vector>& forces,
|
||||
const UList<vector>& moments,
|
||||
const outputFormatType fmt,
|
||||
const Time* timeinfo
|
||||
) const
|
||||
{
|
||||
if (!Pstream::master())
|
||||
const bool writeMoments = (moments.size() == forces.size());
|
||||
|
||||
if (fmt == outputFormatType::PLAIN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const fileName output(coupler().resolveFile(outputName_));
|
||||
OFstream os(output); // ASCII
|
||||
|
||||
if (outputFormat_ == outputFormatType::PLAIN)
|
||||
{
|
||||
os <<"# output from OpenFOAM" << nl
|
||||
<<"# N, points, forces" << nl
|
||||
<< this->size() << nl;
|
||||
|
||||
const char* zeroVector = "0 0 0";
|
||||
|
||||
forAll(locations_, i)
|
||||
os <<"########" << nl;
|
||||
if (timeinfo)
|
||||
{
|
||||
const vector pos = locations_[i] * axis_;
|
||||
os <<"# ";
|
||||
putTime(os, *timeinfo) << nl;
|
||||
}
|
||||
os <<"# size=" << this->size() << nl
|
||||
<<"# columns (points) (forces)";
|
||||
|
||||
os << pos.x() << ' '
|
||||
<< pos.y() << ' '
|
||||
<< pos.z() << ' ';
|
||||
if (writeMoments)
|
||||
{
|
||||
os << " (moments)";
|
||||
}
|
||||
|
||||
if (i < forces.size())
|
||||
os << nl;
|
||||
|
||||
bool report = false;
|
||||
scalar scaleLength = scaleOutput_[scalingType::LENGTH];
|
||||
scalar scaleForce = scaleOutput_[scalingType::FORCE];
|
||||
scalar scaleMoment = scaleOutput_[scalingType::MOMENT];
|
||||
|
||||
if (scaleLength > 0)
|
||||
{
|
||||
report = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
scaleLength = 1.0;
|
||||
}
|
||||
|
||||
if (scaleForce > 0)
|
||||
{
|
||||
report = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
scaleForce = 1.0;
|
||||
}
|
||||
|
||||
if (writeMoments)
|
||||
{
|
||||
if (scaleMoment > 0)
|
||||
{
|
||||
os << forces[i].x() << ' '
|
||||
<< forces[i].y() << ' '
|
||||
<< forces[i].z();
|
||||
report = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
os << zeroVector;
|
||||
scaleMoment = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (report)
|
||||
{
|
||||
os <<"# scaling points=" << scaleLength
|
||||
<<" forces=" << scaleForce;
|
||||
|
||||
if (writeMoments)
|
||||
{
|
||||
os <<" moments=" << scaleMoment;
|
||||
}
|
||||
|
||||
os << nl;
|
||||
os << nl;
|
||||
}
|
||||
|
||||
os <<"########" << nl;
|
||||
|
||||
forAll(locations_, i)
|
||||
{
|
||||
const vector pos = scaleLength * (locations_[i] * axis_);
|
||||
|
||||
putPlain(os, pos) << ' ';
|
||||
|
||||
if (i < forces.size())
|
||||
{
|
||||
const vector val(scaleForce * forces[i]);
|
||||
putPlain(os, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
putPlain(os, vector::zero);
|
||||
}
|
||||
|
||||
if (writeMoments)
|
||||
{
|
||||
os << ' ';
|
||||
if (i < moments.size())
|
||||
{
|
||||
const vector val(scaleMoment * moments[i]);
|
||||
putPlain(os, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
putPlain(os, vector::zero);
|
||||
}
|
||||
}
|
||||
|
||||
os << nl;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -693,10 +850,21 @@ bool Foam::lumpedPointMovement::writeData
|
||||
// - exclude the usual OpenFOAM 'FoamFile' header
|
||||
// - ensure lists have consistent format
|
||||
|
||||
os <<"// output from OpenFOAM" << nl << nl;
|
||||
os <<"////////" << nl;
|
||||
if (timeinfo)
|
||||
{
|
||||
os <<"// ";
|
||||
putTime(os, *timeinfo) << nl;
|
||||
}
|
||||
os << nl;
|
||||
|
||||
writeList(os, "points", (locations_*axis_)());
|
||||
writeList(os, "forces", forces);
|
||||
|
||||
if (writeMoments)
|
||||
{
|
||||
writeList(os, "moments", moments);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -706,7 +874,8 @@ bool Foam::lumpedPointMovement::writeData
|
||||
bool Foam::lumpedPointMovement::writeData
|
||||
(
|
||||
const UList<vector>& forces,
|
||||
const UList<vector>& moments
|
||||
const UList<vector>& moments,
|
||||
const Time* timeinfo
|
||||
) const
|
||||
{
|
||||
if (!Pstream::master())
|
||||
@ -714,60 +883,28 @@ bool Foam::lumpedPointMovement::writeData
|
||||
return false;
|
||||
}
|
||||
|
||||
const fileName output(coupler().resolveFile(outputName_));
|
||||
OFstream os(output); // ASCII
|
||||
|
||||
if (outputFormat_ == outputFormatType::PLAIN)
|
||||
// Regular output
|
||||
{
|
||||
os <<"# output from OpenFOAM" << nl
|
||||
<<"# N, points, forces, moments" << nl
|
||||
<< this->size() << nl;
|
||||
const fileName output(coupler().resolveFile(outputName_));
|
||||
OFstream os(output, IOstream::ASCII);
|
||||
|
||||
const char* zeroVector = "0 0 0";
|
||||
|
||||
forAll(locations_, i)
|
||||
{
|
||||
const vector pos = locations_[i] * axis_;
|
||||
|
||||
os << pos.x() << ' '
|
||||
<< pos.y() << ' '
|
||||
<< pos.z() << ' ';
|
||||
|
||||
if (i < forces.size())
|
||||
{
|
||||
os << forces[i].x() << ' '
|
||||
<< forces[i].y() << ' '
|
||||
<< forces[i].z() << ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
os << zeroVector << ' ';
|
||||
}
|
||||
|
||||
if (i < moments.size())
|
||||
{
|
||||
os << moments[i].x() << ' '
|
||||
<< moments[i].y() << ' '
|
||||
<< moments[i].z();
|
||||
}
|
||||
else
|
||||
{
|
||||
os << zeroVector;
|
||||
}
|
||||
os << nl;
|
||||
}
|
||||
writeData(os, forces, moments, outputFormat_, timeinfo);
|
||||
}
|
||||
else
|
||||
|
||||
// Log output
|
||||
{
|
||||
// Make it easier for external programs to parse
|
||||
// - exclude the usual OpenFOAM 'FoamFile' header
|
||||
// - ensure lists have consistent format
|
||||
const fileName output(coupler().resolveFile(logName_));
|
||||
|
||||
os <<"// output from OpenFOAM" << nl << nl;
|
||||
OFstream os
|
||||
(
|
||||
output,
|
||||
IOstream::ASCII,
|
||||
IOstream::currentVersion,
|
||||
IOstream::UNCOMPRESSED,
|
||||
true // append mode
|
||||
);
|
||||
|
||||
writeList(os, "points", (locations_*axis_)());
|
||||
writeList(os, "forces", forces);
|
||||
writeList(os, "moments", moments);
|
||||
writeData(os, forces, moments, outputFormatType::PLAIN, timeinfo);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -60,8 +60,10 @@ SourceFiles
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declarations
|
||||
class polyMesh;
|
||||
class Time;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class lumpedPointMovement Declaration
|
||||
@ -78,11 +80,22 @@ public:
|
||||
DICTIONARY
|
||||
};
|
||||
|
||||
//- Output format types
|
||||
enum scalingType
|
||||
{
|
||||
LENGTH = 0,
|
||||
FORCE,
|
||||
MOMENT
|
||||
};
|
||||
|
||||
// Static data
|
||||
|
||||
//- Names for the output format types
|
||||
static const Enum<outputFormatType> formatNames;
|
||||
|
||||
//- Names for the scaling types
|
||||
static const Enum<scalingType> scalingNames;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@ -125,9 +138,15 @@ private:
|
||||
//- File io
|
||||
word inputName_;
|
||||
word outputName_;
|
||||
word logName_;
|
||||
|
||||
lumpedPointState::inputFormatType inputFormat_;
|
||||
outputFormatType outputFormat_;
|
||||
|
||||
//- Optional scale factors for input/output files
|
||||
FixedList<scalar, 1> scaleInput_;
|
||||
FixedList<scalar, 3> scaleOutput_;
|
||||
|
||||
|
||||
// Demand-driven private data
|
||||
|
||||
@ -246,6 +265,9 @@ public:
|
||||
//- The output (forces) file name
|
||||
inline const word& outputName() const;
|
||||
|
||||
//- The log file name
|
||||
inline const word& logName() const;
|
||||
|
||||
//- The input (state) file format
|
||||
inline lumpedPointState::inputFormatType inputFormat() const;
|
||||
|
||||
@ -324,21 +346,24 @@ public:
|
||||
//- Write axis, locations, division as a dictionary
|
||||
void writeDict(Ostream& os) const;
|
||||
|
||||
|
||||
//- Write points, forces
|
||||
//- Write points, forces, moments. Only call from the master process
|
||||
bool writeData
|
||||
(
|
||||
const UList<vector>& forces
|
||||
Ostream& os,
|
||||
const UList<vector>& forces,
|
||||
const UList<vector>& moments,
|
||||
const outputFormatType fmt = outputFormatType::PLAIN,
|
||||
const Time* timeinfo = nullptr
|
||||
) const;
|
||||
|
||||
//- Write points, forces, moments
|
||||
bool writeData
|
||||
(
|
||||
const UList<vector>& forces,
|
||||
const UList<vector>& moments
|
||||
const UList<vector>& moments = List<vector>(),
|
||||
const Time* timeinfo = nullptr
|
||||
) const;
|
||||
|
||||
|
||||
//- Read state from file, applying relaxation as requested
|
||||
bool readState();
|
||||
|
||||
|
||||
100
src/lumpedPointMotion/lumpedPointMovement.dict
Normal file
100
src/lumpedPointMotion/lumpedPointMovement.dict
Normal file
@ -0,0 +1,100 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: plus |
|
||||
| \\ / A nd | Web: www.OpenFOAM.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
location "system";
|
||||
object lumpedPointMovement;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Reference axis for the locations
|
||||
axis (0 0 1);
|
||||
|
||||
// Locations of the lumped points
|
||||
locations 11(0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5);
|
||||
|
||||
// Division for pressure forces (0-1)
|
||||
division 0.5;
|
||||
|
||||
//- If present, the offset of patch points compared to the locations
|
||||
// Otherwise determined from the bounding box
|
||||
// centre (0 0 0);
|
||||
|
||||
//- The interpolation scheme
|
||||
interpolationScheme linear;
|
||||
|
||||
//- Relaxation/scaling factor when updating positions
|
||||
relax 1.0;
|
||||
|
||||
|
||||
forces
|
||||
{
|
||||
//- The pressure name (default: p)
|
||||
p p;
|
||||
|
||||
//- Reference pressure [Pa] (default: 0)
|
||||
pRef 0;
|
||||
|
||||
//- Reference density for incompressible calculations (default: 1)
|
||||
rhoRef 1;
|
||||
}
|
||||
|
||||
|
||||
communication
|
||||
{
|
||||
commsDir "comms";
|
||||
|
||||
log on;
|
||||
|
||||
waitInterval 1;
|
||||
|
||||
timeOut 100;
|
||||
|
||||
initByExternal false;
|
||||
|
||||
// Input file of positions/rotation, written by external application
|
||||
inputName positions.in;
|
||||
|
||||
// Output file of forces, written by OpenFOAM
|
||||
outputName forces.out;
|
||||
|
||||
// Log of points/forces/moments during the simulation
|
||||
logName movement.log;
|
||||
|
||||
inputFormat dictionary;
|
||||
outputFormat dictionary;
|
||||
|
||||
debugTable "$FOAM_CASE/output.txt";
|
||||
|
||||
|
||||
// Scaling applied to values read from 'inputName'
|
||||
scaleInput
|
||||
{
|
||||
//- Length multiplier (to metres). Eg 0.001 for [mm] -> [m]
|
||||
length 1;
|
||||
}
|
||||
|
||||
// Scaling applied to values written to 'outputName'
|
||||
scaleOutput
|
||||
{
|
||||
//- Length multiplier (from metres). Eg 1000 for [m] -> [mm]
|
||||
length 1;
|
||||
|
||||
//- Force units multiplier (from Pa)
|
||||
force 1;
|
||||
|
||||
//- Moment units multiplier (from N.m)
|
||||
moment 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -133,6 +133,12 @@ inline const Foam::word& Foam::lumpedPointMovement::outputName() const
|
||||
}
|
||||
|
||||
|
||||
inline const Foam::word& Foam::lumpedPointMovement::logName() const
|
||||
{
|
||||
return logName_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::lumpedPointState::inputFormatType
|
||||
Foam::lumpedPointMovement::inputFormat() const
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user