diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/Make/options b/applications/solvers/heatTransfer/chtMultiRegionFoam/Make/options index 2fcfff4126..c896f86d16 100644 --- a/applications/solvers/heatTransfer/chtMultiRegionFoam/Make/options +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/Make/options @@ -8,7 +8,9 @@ EXE_INC = \ -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \ -I$(LIB_SRC)/thermophysicalModels/basicSolidThermo/lnInclude \ -I$(LIB_SRC)/turbulenceModels/compressible/turbulenceModel/lnInclude \ - -I$(LIB_SRC)/thermophysicalModels/radiationModels/lnInclude + -I$(LIB_SRC)/thermophysicalModels/radiationModels/lnInclude \ + -I$(LIB_SRC)/parallel/decompose/decompose/lnInclude \ + -I$(LIB_SRC)/parallel/reconstruct/reconstruct/lnInclude EXE_LIBS = \ -lbasicThermophysicalModels \ @@ -19,4 +21,6 @@ EXE_LIBS = \ -lcompressibleLESModels \ -lmeshTools \ -lfiniteVolume \ - -lradiationModels + -lradiationModels \ + -ldecompose \ + -lreconstruct diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/allhEqn.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/allhEqn.H new file mode 100644 index 0000000000..cfe2e84a0f --- /dev/null +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/allhEqn.H @@ -0,0 +1,84 @@ + +// Get mapped alpha (surfaceScalarField) +tmp tallAlpha = procToAllMapper().reconstructFvSurfaceField + ( + IOobject + ( + "alpha", + allMesh().time().timeName(), + allMesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + procAlpha + ); + +// Get alpha from harmonic interpolation of vol quantities +// (Note: really only needed at internal faces originating patches +// inbetween regions) +tmp allHarmonicAlpha +( + harmonic(allMesh()).interpolate(allVolAlpha()) +); + +// Loop over all fluid and solid regions to transfer +// allHarmonicAlpha to allAlpha +surfaceScalarField& allAlpha = tallAlpha(); +forAll(boundaryProcAddressing, procI) +{ + forAll(boundaryProcAddressing[procI], patchI) + { + if (boundaryProcAddressing[procI][patchI] == -1) + { + // Interface patch + const labelList::subList cp = + procMeshes[procI].boundary()[patchI].patchSlice + ( + faceProcAddressing[procI] + ); + + forAll(cp, faceI) + { + label curF = mag(cp[faceI])-1; + if (curF < allMesh().nInternalFaces()) + { + allAlpha[curF] = allHarmonicAlpha()[curF]; + } + } + } + } +} + + +tmp allPhi +( + procToAllMapper().reconstructFvSurfaceField + ( + IOobject + ( + "phi", + allMesh().time().timeName(), + allMesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + procPhi + ) +); + +// So we have nNonOrthCorr +//#include "readSolidMultiRegionPIMPLEControls.H" +//for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++) +{ + fvScalarMatrix hEqn + ( + fvm::ddt(allRho(), allh()) + + fvm::div(allPhi(), allh()) + - fvm::laplacian(allAlpha, allh()) + == + allSource() + ); + + hEqn.relax(); + hEqn.solve(allMesh().solver(allh().select(finalIter))); +} diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C index b65ecf5118..927562c144 100644 --- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C @@ -39,6 +39,11 @@ Description #include "solidRegionDiffNo.H" #include "basicSolidThermo.H" #include "radiationModel.H" +#include "fvFieldReconstructor.H" +#include "mixedFvPatchFields.H" +#include "fvFieldDecomposer.H" +#include "harmonic.H" +#include "rmap.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -49,12 +54,40 @@ int main(int argc, char *argv[]) regionProperties rp(runTime); + const label nAllRegions = + rp.fluidRegionNames().size() + + rp.solidRegionNames().size(); + PtrList cellProcAddressing(nAllRegions); + PtrList faceProcAddressing(nAllRegions); + PtrList boundaryProcAddressing(nAllRegions); + PtrList procMeshes(nAllRegions); + + // Load meshes, fluid first + labelList fluidToProc(identity(rp.fluidRegionNames().size())); + labelList solidToProc(rp.solidRegionNames().size()); + forAll(solidToProc, i) + { + solidToProc[i] = fluidToProc.size()+i; + } + + // Get the coupled solution flag + #include "readPIMPLEControls.H" + + if (temperatureCoupled) + { + Info<< "Solving single enthalpy for all equations" << nl << endl; + } + #include "createFluidMeshes.H" #include "createSolidMeshes.H" #include "createFluidFields.H" #include "createSolidFields.H" + // Temperature solved on single mesh + #include "createAllMesh.H" + #include "createAllFields.H" + #include "initContinuityErrs.H" #include "readTimeControls.H" @@ -81,9 +114,10 @@ int main(int argc, char *argv[]) Info<< "Time = " << runTime.timeName() << nl << endl; + if (nOuterCorr != 1) { - forAll(fluidRegions, i) + forAll(fluidToProc, i) { #include "setRegionFluidFields.H" #include "storeOldFluidFields.H" @@ -96,22 +130,133 @@ int main(int argc, char *argv[]) { bool finalIter = oCorr == nOuterCorr-1; - forAll(fluidRegions, i) + if (finalIter) { - Info<< "\nSolving for fluid region " - << fluidRegions[i].name() << endl; - #include "setRegionFluidFields.H" - #include "readFluidMultiRegionPIMPLEControls.H" - #include "solveFluid.H" + forAll(procMeshes, procI) + { + procMeshes[procI].data::add("finalIteration", true); + } } - forAll(solidRegions, i) + + PtrList procPhi(nAllRegions); + PtrList procAlpha(nAllRegions); + + + // Solve (uncoupled) or set up (coupled) the temperature equation + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + forAll(solidToProc, i) { - Info<< "\nSolving for solid region " - << solidRegions[i].name() << endl; + label procI = solidToProc[i]; + + Info<< "\nSolving temperature for solid region " + << procMeshes[procI].name() << endl; #include "setRegionSolidFields.H" #include "readSolidMultiRegionPIMPLEControls.H" - #include "solveSolid.H" + + if (temperatureCoupled) + { + // Map my properties to overall h equation + #include "rmapSolid.H" + } + else + { + #include "solveSolid.H" + } + } + + + forAll(fluidToProc, i) + { + label procI = fluidToProc[i]; + + Info<< "\nSolving temperature for fluid region " + << procMeshes[procI].name() << endl; + #include "setRegionFluidFields.H" + #include "readFluidMultiRegionPIMPLEControls.H" + + if (oCorr == 0) + { + #include "rhoEqn.H" + } + + if (temperatureCoupled) + { + // Map my properties to overall h equation + #include "rmapFluid.H" + } + else + { + #include "hEqn.H" + } + } + + + // Solve combined h equation + // ~~~~~~~~~~~~~~~~~~~~~~~~~ + + if (temperatureCoupled) + { + Info<< "\nSolving single enthalpy for all regions" + << endl; + + // Solve combined h + #include "allhEqn.H" + + forAll(solidToProc, i) + { + label procI = solidToProc[i]; + #include "setRegionSolidFields.H" + #include "readSolidMultiRegionPIMPLEControls.H" + + #include "mapSolid.H" + } + + forAll(fluidToProc, i) + { + label procI = fluidToProc[i]; + #include "setRegionFluidFields.H" + #include "readFluidMultiRegionPIMPLEControls.H" + + #include "mapFluid.H" + } + } + + + // Update thermos + // ~~~~~~~~~~~~~~ + + forAll(fluidToProc, i) + { + Info<< "\nUpdating thermo for fluid region " + << procMeshes[fluidToProc[i]].name() << endl; + + #include "setRegionFluidFields.H" + #include "readFluidMultiRegionPIMPLEControls.H" + + thermo.correct(); + rad.correct(); + #include "solvePressureVelocityFluid.H" + } + + forAll(solidToProc, i) + { + Info<< "\nUpdating thermo for solid region " + << procMeshes[solidToProc[i]].name() << endl; + #include "setRegionSolidFields.H" + #include "readSolidMultiRegionPIMPLEControls.H" + + thermo.correct(); + } + + + if (finalIter) + { + forAll(procMeshes, procI) + { + procMeshes[procI].data::remove("finalIteration"); + } } } diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/createAllFields.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/createAllFields.H new file mode 100644 index 0000000000..faa8eaac58 --- /dev/null +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/createAllFields.H @@ -0,0 +1,64 @@ + autoPtr allRho; + autoPtr allh; + autoPtr allVolAlpha; + autoPtr allSource; + + if (temperatureCoupled) + { + allRho.reset + ( + new volScalarField + ( + IOobject + ( + "rho", + runTime.timeName(), + allMesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + allMesh(), + dimensionedScalar("rho", dimDensity, 0.0) + ) + ); + + allh.reset + ( + new volScalarField + ( + IOobject + ( + "h", + runTime.timeName(), + allMesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + allMesh(), + dimensionedScalar("h", dimEnergy/dimMass, 0.0), + mixedFvPatchScalarField::typeName + ) + ); + + allVolAlpha.reset + ( + new volScalarField + ( + IOobject + ( + "volAlpha", + runTime.timeName(), + allMesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + allMesh(), + dimensionedScalar("volAlpha", dimMass/dimLength/dimTime, 0.0) + ) + ); + + allSource.reset + ( + new fvMatrix(allh(), allh().dimensions()*dimMass/dimTime) + ); + } diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/createAllMesh.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/createAllMesh.H new file mode 100644 index 0000000000..8bff40e48a --- /dev/null +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/createAllMesh.H @@ -0,0 +1,63 @@ +// +// createAllMesh.H +// ~~~~~~~~~~~~~~~ + + autoPtr allMesh; + autoPtr procToAllMapper; + PtrList allToProcMappers; + + if (temperatureCoupled) + { + Foam::Info + << "Create mesh for time = " + << runTime.timeName() << Foam::nl << Foam::endl; + + allMesh.reset + ( + new Foam::fvMesh + ( + Foam::IOobject + ( + Foam::fvMesh::defaultRegion, + runTime.timeName(), + runTime, + Foam::IOobject::MUST_READ + ) + ) + ); + + procToAllMapper.reset + ( + new fvFieldReconstructor + ( + allMesh(), + procMeshes, + faceProcAddressing, + cellProcAddressing, + boundaryProcAddressing + ) + ); + + + allToProcMappers.setSize + ( + rp.fluidRegionNames().size() + + rp.solidRegionNames().size() + ); + + forAll(allToProcMappers, i) + { + allToProcMappers.set + ( + i, + new fvFieldDecomposer + ( + allMesh(), + procMeshes[i], + faceProcAddressing[i], + cellProcAddressing[i], + boundaryProcAddressing[i] + ) + ); + } + } diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/compressibleMultiRegionCourantNo.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/compressibleMultiRegionCourantNo.H index b5db5078f1..61b7b10340 100644 --- a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/compressibleMultiRegionCourantNo.H +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/compressibleMultiRegionCourantNo.H @@ -1,12 +1,12 @@ scalar CoNum = -GREAT; - forAll(fluidRegions, regionI) + forAll(fluidToProc, regionI) { CoNum = max ( compressibleCourantNo ( - fluidRegions[regionI], + procMeshes[fluidToProc[regionI]], runTime, rhoFluid[regionI], phiFluid[regionI] diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/createFluidFields.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/createFluidFields.H index f6788d26eb..667b39d646 100644 --- a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/createFluidFields.H +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/createFluidFields.H @@ -1,30 +1,36 @@ // Initialise fluid field pointer lists - PtrList thermoFluid(fluidRegions.size()); - PtrList rhoFluid(fluidRegions.size()); - PtrList KFluid(fluidRegions.size()); - PtrList UFluid(fluidRegions.size()); - PtrList phiFluid(fluidRegions.size()); - PtrList gFluid(fluidRegions.size()); - PtrList turbulence(fluidRegions.size()); - PtrList p_rghFluid(fluidRegions.size()); - PtrList ghFluid(fluidRegions.size()); - PtrList ghfFluid(fluidRegions.size()); - PtrList radiation(fluidRegions.size()); - PtrList DpDtFluid(fluidRegions.size()); + PtrList thermoFluid(rp.fluidRegionNames().size()); + PtrList rhoFluid(rp.fluidRegionNames().size()); + PtrList KFluid(rp.fluidRegionNames().size()); + PtrList UFluid(rp.fluidRegionNames().size()); + PtrList phiFluid(rp.fluidRegionNames().size()); + PtrList gFluid(rp.fluidRegionNames().size()); + PtrList turbulence + ( + rp.fluidRegionNames().size() + ); + PtrList p_rghFluid(rp.fluidRegionNames().size()); + PtrList ghFluid(rp.fluidRegionNames().size()); + PtrList ghfFluid(rp.fluidRegionNames().size()); + PtrList radiation(rp.fluidRegionNames().size()); + PtrList DpDtFluid(rp.fluidRegionNames().size()); - List initialMassFluid(fluidRegions.size()); + List initialMassFluid(rp.fluidRegionNames().size()); // Populate fluid field pointer lists - forAll(fluidRegions, i) + forAll(rp.fluidRegionNames(), i) { Info<< "*** Reading fluid mesh thermophysical properties for region " - << fluidRegions[i].name() << nl << endl; + << rp.fluidRegionNames()[i] << nl << endl; + + label procI = fluidToProc[i]; + Info<< " Adding to thermoFluid\n" << endl; thermoFluid.set ( i, - basicRhoThermo::New(fluidRegions[i]).ptr() + basicRhoThermo::New(procMeshes[procI]).ptr() ); Info<< " Adding to rhoFluid\n" << endl; @@ -37,7 +43,7 @@ ( "rho", runTime.timeName(), - fluidRegions[i], + procMeshes[procI], IOobject::NO_READ, IOobject::AUTO_WRITE ), @@ -55,7 +61,7 @@ ( "K", runTime.timeName(), - fluidRegions[i], + procMeshes[procI], IOobject::NO_READ, IOobject::NO_WRITE ), @@ -73,11 +79,11 @@ ( "U", runTime.timeName(), - fluidRegions[i], + procMeshes[procI], IOobject::MUST_READ, IOobject::AUTO_WRITE ), - fluidRegions[i] + procMeshes[procI] ) ); @@ -91,12 +97,12 @@ ( "phi", runTime.timeName(), - fluidRegions[i], + procMeshes[procI], IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE ), linearInterpolate(rhoFluid[i]*UFluid[i]) - & fluidRegions[i].Sf() + & procMeshes[procI].Sf() ) ); @@ -110,7 +116,7 @@ ( "g", runTime.constant(), - fluidRegions[i], + procMeshes[procI], IOobject::MUST_READ, IOobject::NO_WRITE ) @@ -137,14 +143,14 @@ ghFluid.set ( i, - new volScalarField("gh", gFluid[i] & fluidRegions[i].C()) + new volScalarField("gh", gFluid[i] & procMeshes[procI].C()) ); Info<< " Adding to ghfFluid\n" << endl; ghfFluid.set ( i, - new surfaceScalarField("ghf", gFluid[i] & fluidRegions[i].Cf()) + new surfaceScalarField("ghf", gFluid[i] & procMeshes[procI].Cf()) ); p_rghFluid.set @@ -156,11 +162,11 @@ ( "p_rgh", runTime.timeName(), - fluidRegions[i], + procMeshes[procI], IOobject::MUST_READ, IOobject::AUTO_WRITE ), - fluidRegions[i] + procMeshes[procI] ) ); diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/createFluidMeshes.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/createFluidMeshes.H index 30a2e1089f..73b533b0d9 100644 --- a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/createFluidMeshes.H +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/createFluidMeshes.H @@ -1,13 +1,13 @@ - PtrList fluidRegions(rp.fluidRegionNames().size()); - forAll(rp.fluidRegionNames(), i) { Info<< "Create fluid mesh for region " << rp.fluidRegionNames()[i] << " for time = " << runTime.timeName() << nl << endl; - fluidRegions.set + label procI = fluidToProc[i]; + + procMeshes.set ( - i, + procI, new fvMesh ( IOobject @@ -19,4 +19,58 @@ ) ) ); + + if (temperatureCoupled) + { + cellProcAddressing.set + ( + procI, + new labelIOList + ( + IOobject + ( + "cellRegionAddressing", + procMeshes[procI].facesInstance(), + procMeshes[procI].meshSubDir, + procMeshes[procI], + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ) + ); + + faceProcAddressing.set + ( + procI, + new labelIOList + ( + IOobject + ( + "faceRegionAddressing", + procMeshes[procI].facesInstance(), + procMeshes[procI].meshSubDir, + procMeshes[procI], + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ) + ); + + boundaryProcAddressing.set + ( + procI, + new labelIOList + ( + IOobject + ( + "boundaryRegionAddressing", + procMeshes[procI].facesInstance(), + procMeshes[procI].meshSubDir, + procMeshes[procI], + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ) + ); + } } diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/initContinuityErrs.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/initContinuityErrs.H index 1a7f5a3262..8cc47b1ca0 100644 --- a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/initContinuityErrs.H +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/initContinuityErrs.H @@ -1 +1 @@ -List cumulativeContErr(fluidRegions.size(), 0.0); +List cumulativeContErr(fluidToProc.size(), 0.0); diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/mapFluid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/mapFluid.H new file mode 100644 index 0000000000..75d83afd09 --- /dev/null +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/mapFluid.H @@ -0,0 +1,3 @@ +h = allToProcMappers[procI].decomposeField(allh(), true); +h.oldTime().timeIndex() = allh().oldTime().timeIndex(); +h.correctBoundaryConditions(); diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/rmapFluid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/rmapFluid.H new file mode 100644 index 0000000000..576d883f01 --- /dev/null +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/rmapFluid.H @@ -0,0 +1,56 @@ +// Note:Map rho and rho.oldTime() since fluid rho assigned to at +// end of iteration. +rmap +( + allRho(), + rho, + faceProcAddressing[procI], + cellProcAddressing[procI], + boundaryProcAddressing[procI] +); +rmap +( + allRho().oldTime(), + rho.oldTime(), + faceProcAddressing[procI], + cellProcAddressing[procI], + boundaryProcAddressing[procI] +); + +// Necessary? Probably only for boundary values since bcs on +// h are not the same as those on allh + +rmap +( + allh(), + h, + faceProcAddressing[procI], + cellProcAddressing[procI], + boundaryProcAddressing[procI] +); + +procAlpha.set(procI, fvc::interpolate(turb.alphaEff())); + +rmap +( + allVolAlpha(), + turb.alphaEff()(), + faceProcAddressing[procI], + cellProcAddressing[procI], + boundaryProcAddressing[procI] +); + +rmap +( + allSource(), + (DpDt + rad.Sh(thermo))(), + faceProcAddressing[procI], + cellProcAddressing[procI], + boundaryProcAddressing[procI] +); + +procPhi.set +( + procI, + new surfaceScalarField(phi) +); diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/setRegionFluidFields.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/setRegionFluidFields.H index 81c6d25bb0..5bc0fffa40 100644 --- a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/setRegionFluidFields.H +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/setRegionFluidFields.H @@ -1,4 +1,4 @@ - fvMesh& mesh = fluidRegions[i]; + fvMesh& mesh = procMeshes[fluidToProc[i]]; basicRhoThermo& thermo = thermoFluid[i]; volScalarField& rho = rhoFluid[i]; diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/solvePressureVelocityFluid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/solvePressureVelocityFluid.H new file mode 100644 index 0000000000..d04a301112 --- /dev/null +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/fluid/solvePressureVelocityFluid.H @@ -0,0 +1,11 @@ +#include "UEqn.H" + +// --- PISO loop +for (int corr=0; corr("nOuterCorrectors", 1); + + const Switch temperatureCoupled = + pimple.lookupOrDefault("temperatureCoupled", false); diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/rmap.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/rmap.H new file mode 100644 index 0000000000..d9c8e35060 --- /dev/null +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/rmap.H @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011 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 . + +Global + rmap + +Description + map field on subset of mesh onto overall field. Rewrites boundary + conditions to be mixed. + + The source fields can have different patch types for the same destination + patch. To work around this it attempts to convert all patch fields into + mixed type since this can accomodate anything from fixedValue to + fixedGradient. + +SourceFiles + rmap.C + +\*---------------------------------------------------------------------------*/ + +#ifndef rmap_H +#define rmap_H + +#include "volFields.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//- Map patchField +template +static void rmap +( + fvPatchField& destBC, + const labelList& reverseAddressing, + const fvPatchField& sourceBC +); + +//- Map volField +template +static void rmap +( + GeometricField& dest, + const GeometricField& source, + const labelList& faceProcAddressing, + const labelList& cellProcAddressing, + const labelList& boundaryProcAddressing +); + +//- Map fvMatrix +template +static void rmap +( + fvMatrix& dest, + const fvMatrix& source, + const labelList& faceProcAddressing, + const labelList& cellProcAddressing, + const labelList& boundaryProcAddressing +); + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository +# include "rmapTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/rmapTemplates.C b/applications/solvers/heatTransfer/chtMultiRegionFoam/rmapTemplates.C new file mode 100644 index 0000000000..6dbf50a81c --- /dev/null +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/rmapTemplates.C @@ -0,0 +1,309 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011 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 . + +\*---------------------------------------------------------------------------*/ + +#include "rmap.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template +void Foam::rmap +( + fvPatchField& destBC, + const labelList& reverseAddressing, + const fvPatchField& sourceBC +) +{ + // Assign value + destBC.Field::rmap(sourceBC, reverseAddressing); + + // Assign other properties + if (isA >(destBC)) + { + mixedFvPatchField& mp = + refCast >(destBC); + + if (isA >(sourceBC)) + { + const mixedFvPatchField& Tp = + refCast >(sourceBC); + + mp.refValue().rmap(Tp.refValue(), reverseAddressing); + mp.refGrad().rmap(Tp.refGrad(), reverseAddressing); + mp.valueFraction().rmap(Tp.valueFraction(), reverseAddressing); + } + else if (isA >(sourceBC)) + { + const fixedGradientFvPatchField& Tp = + refCast > + ( + sourceBC + ); + // Make pure fixedGradient + mp.refValue().rmap(Tp, reverseAddressing); // unused + mp.refGrad().rmap(Tp.gradient(), reverseAddressing); + mp.valueFraction().rmap + ( + Field(reverseAddressing.size(), 0.0), + reverseAddressing + ); + } + else if (isA >(sourceBC)) + { + // Make pure fixedGradient with gradient = 0 + mp.refValue().rmap(sourceBC, reverseAddressing); // unused + mp.refGrad().rmap + ( + Field(reverseAddressing.size(), 0.0), + reverseAddressing + ); + mp.valueFraction().rmap + ( + Field(reverseAddressing.size(), 0.0), + reverseAddressing + ); + } + else if (isA >(sourceBC)) + { + // Make pure fixedValue + mp.refValue().rmap(sourceBC, reverseAddressing); + mp.refGrad().rmap + ( + Field(reverseAddressing.size(), 0.0), + reverseAddressing + ); // unused + mp.valueFraction().rmap + ( + Field(reverseAddressing.size(), 1.0), + reverseAddressing + ); + } + else if (isA >(sourceBC)) + { + // Make pure fixedValue + mp.refValue().rmap(sourceBC, reverseAddressing); + mp.refGrad().rmap + ( + Field(reverseAddressing.size(), 0.0), + reverseAddressing + ); // unused + mp.valueFraction().rmap + ( + Field(reverseAddressing.size(), 1.0), + reverseAddressing + ); + } + else + { + FatalErrorIn("rmap(..)") + << "Don't know how to map source bc " + << sourceBC.type() + << " into a mixed boundary condition at " + << destBC.patch().name() + << exit(FatalError); + } + } + else if (isA >(destBC)) + { + fixedGradientFvPatchField& mp = + refCast >(destBC); + + if (isA >(sourceBC)) + { + const fixedGradientFvPatchField& Tp = + refCast > + ( + sourceBC + ); + mp.gradient().rmap(Tp.gradient(), reverseAddressing); + } + else if (isA >(sourceBC)) + { + const mixedFvPatchField& Tp = + refCast >(sourceBC); + mp.gradient().rmap(Tp.snGrad(), reverseAddressing); + } + else if (isA >(sourceBC)) + { + mp.gradient().rmap + ( + Field(reverseAddressing.size(), 0.0), + reverseAddressing + ); + } + else + { + FatalErrorIn("rmap(..)") + << "Don't know how to map source bc " + << sourceBC.type() + << " into a fixedGradient boundary condition at " + << destBC.patch().name() + << exit(FatalError); + } + } +} + + +template +void Foam::rmap +( + GeometricField& dest, + const GeometricField& source, + const labelList& faceProcAddressing, + const labelList& cellProcAddressing, + const labelList& boundaryProcAddressing +) +{ + if (dest.dimensions() != source.dimensions()) + { + FatalErrorIn("rmap(..)") + << "Different dimensions for = for fields " << dest.name() + << " and " << source.name() << endl + << " dimensions : " << dest.dimensions() + << " = " << source.dimensions() << endl + << exit(FatalError); + } + + // Copy internal field + dest.internalField().rmap(source.internalField(), cellProcAddressing); + + // Copy boundary properties as mixed + forAll(source.boundaryField(), patchI) + { + label curBPatch = boundaryProcAddressing[patchI]; + + if (curBPatch == -1) + { + // Unknown patch. Do not change any values. + } + else + { + // Get addressing slice for this patch + const labelList::subList cp = + source.mesh().boundary()[patchI].patchSlice + ( + faceProcAddressing + ); + + const label curPatchStart = + dest.mesh().boundaryMesh()[curBPatch].start(); + + labelList reverseAddressing(cp.size()); + + forAll(cp, faceI) + { + // Subtract one to take into account offsets for + // face direction. + if (cp[faceI] <= 0) + { + FatalErrorIn("rmap(..)") + << "Problem:" + << " patch:" << source.mesh().boundary()[patchI].name() + << " field:" << source.name() + << " local face:" << faceI + << " mapped to:" << cp[faceI] << exit(FatalError); + } + + reverseAddressing[faceI] = cp[faceI] - 1 - curPatchStart; + } + + // Map curBPatch from source patch. Is like rmap but also + // copies non-value properties from alike patchFields. + rmap + ( + dest.boundaryField()[curBPatch], + reverseAddressing, + source.boundaryField()[patchI] + ); + } + } + + // Copy timeIndex + dest.timeIndex() = source.timeIndex(); +} + + +template +void Foam::rmap +( + fvMatrix& dest, + const fvMatrix& source, + const labelList& faceProcAddressing, + const labelList& cellProcAddressing, + const labelList& boundaryProcAddressing +) +{ + dest.source().rmap(source.source(), cellProcAddressing); + + FieldField& sourceInternal = + const_cast&>(source).internalCoeffs(); + FieldField& sourceBoundary = + const_cast&>(source).boundaryCoeffs(); + + forAll(sourceInternal, patchI) + { + label curBPatch = boundaryProcAddressing[patchI]; + + if (curBPatch == -1) + { + // Unknown patch. Do not change any values. + } + else + { + // Get addressing slice for this patch + const fvMesh& sourceMesh = source.psi().mesh(); + + const labelList::subList cp = + sourceMesh.boundary()[patchI].patchSlice + ( + faceProcAddressing + ); + + const label curPatchStart = + dest.psi().mesh().boundaryMesh()[curBPatch].start(); + + labelList reverseAddressing(cp.size()); + + forAll(cp, faceI) + { + // Subtract one to take into account offsets for + // face direction. + reverseAddressing[faceI] = cp[faceI] - 1 - curPatchStart; + } + dest.internalCoeffs()[curBPatch].rmap + ( + sourceInternal[patchI], + reverseAddressing + ); + dest.boundaryCoeffs()[curBPatch].rmap + ( + sourceBoundary[patchI], + reverseAddressing + ); + } + } +} + + +// ************************************************************************* // diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/createSolidFields.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/createSolidFields.H index 837305659e..ab58752d80 100644 --- a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/createSolidFields.H +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/createSolidFields.H @@ -1,12 +1,36 @@ // Initialise solid field pointer lists - PtrList thermos(solidRegions.size()); + PtrList thermoSolid(rp.solidRegionNames().size()); + PtrList hSolid(rp.solidRegionNames().size()); // Populate solid field pointer lists - forAll(solidRegions, i) + forAll(rp.solidRegionNames(), i) { Info<< "*** Reading solid mesh thermophysical properties for region " - << solidRegions[i].name() << nl << endl; + << rp.solidRegionNames()[i] << nl << endl; - Info<< " Adding to thermos\n" << endl; - thermos.set(i, basicSolidThermo::New(solidRegions[i])); + label procI = solidToProc[i]; + + Info<< " Adding to thermoSolid\n" << endl; + thermoSolid.set(i, basicSolidThermo::New(procMeshes[procI])); + + if (temperatureCoupled) + { + Info<< " Adding to hSolid\n" << endl; + hSolid.set + ( + i, + new volScalarField + ( + IOobject + ( + "h", + runTime.timeName(), + procMeshes[procI], + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + procMeshes[procI] + ) + ); + } } diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/createSolidMeshes.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/createSolidMeshes.H index eb50be2380..10b5f4160c 100644 --- a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/createSolidMeshes.H +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/createSolidMeshes.H @@ -1,13 +1,13 @@ - PtrList solidRegions(rp.solidRegionNames().size()); - forAll(rp.solidRegionNames(), i) { Info<< "Create solid mesh for region " << rp.solidRegionNames()[i] << " for time = " << runTime.timeName() << nl << endl; - solidRegions.set + label procI = solidToProc[i]; + + procMeshes.set ( - i, + procI, new fvMesh ( IOobject @@ -20,8 +20,57 @@ ) ); - // Force calculation of geometric properties to prevent it being done - // later in e.g. some boundary evaluation - //(void)solidRegions[i].weights(); - //(void)solidRegions[i].deltaCoeffs(); + if (temperatureCoupled) + { + cellProcAddressing.set + ( + procI, + new labelIOList + ( + IOobject + ( + "cellRegionAddressing", + procMeshes[procI].facesInstance(), + procMeshes[procI].meshSubDir, + procMeshes[procI], + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ) + ); + + faceProcAddressing.set + ( + procI, + new labelIOList + ( + IOobject + ( + "faceRegionAddressing", + procMeshes[procI].facesInstance(), + procMeshes[procI].meshSubDir, + procMeshes[procI], + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ) + ); + + boundaryProcAddressing.set + ( + procI, + new labelIOList + ( + IOobject + ( + "boundaryRegionAddressing", + procMeshes[procI].facesInstance(), + procMeshes[procI].meshSubDir, + procMeshes[procI], + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ) + ); + } } diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/mapSolid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/mapSolid.H new file mode 100644 index 0000000000..ca6e506347 --- /dev/null +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/mapSolid.H @@ -0,0 +1,15 @@ +{ + volScalarField& h = hSolid[i]; + + h = allToProcMappers[procI].decomposeField(allh(), true); + h.oldTime().timeIndex() = allh().oldTime().timeIndex(); + + T += (h-h.oldTime())/cp; + // Correct T boundary conditions and update h boundary + // conditions accordingly. + volScalarField::GeometricBoundaryField Told = T.boundaryField(); + T.correctBoundaryConditions(); + h.boundaryField() += + cp.boundaryField() + * (T.boundaryField()-Told); +} diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/rmapSolid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/rmapSolid.H new file mode 100644 index 0000000000..b36474a531 --- /dev/null +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/rmapSolid.H @@ -0,0 +1,90 @@ +{ + volScalarField& h = hSolid[i]; + + procPhi.setSize(nAllRegions); + procAlpha.setSize(nAllRegions); + + rmap + ( + allRho(), + rho, + faceProcAddressing[procI], + cellProcAddressing[procI], + boundaryProcAddressing[procI] + ); + + // Necessary? Probably only for boundary values since bcs on + // h are not the same as those on allh + rmap + ( + allh(), + h, + faceProcAddressing[procI], + cellProcAddressing[procI], + boundaryProcAddressing[procI] + ); + + + tmp Kcp(K/cp); + + rmap + ( + allVolAlpha(), + Kcp(), + faceProcAddressing[procI], + cellProcAddressing[procI], + boundaryProcAddressing[procI] + ); + + procAlpha.set(procI, fvc::interpolate(Kcp)); + + // allSource is initialised to zero already + //rmap + //( + // allSource(), + // volScalarField + // ( + // IOobject + // ( + // "procSource", + // runTime.timeName(), + // mesh, + // IOobject::NO_READ, + // IOobject::AUTO_WRITE + // ), + // mesh, + // dimensionedScalar + // ( + // "procSource", + // allh().dimensions()*dimDensity/dimTime, + // 0.0 + // ) + // ), + // faceProcAddressing[procI], + // cellProcAddressing[procI], + // boundaryProcAddressing[procI] + //); + + procPhi.set + ( + procI, + new surfaceScalarField + ( + IOobject + ( + "phi", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar + ( + "phi", + dimDensity*dimVelocity*dimArea, + 0.0 + ) + ) + ); +} diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/setRegionSolidFields.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/setRegionSolidFields.H index a843ed8bd7..a1dbe88c0a 100644 --- a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/setRegionSolidFields.H +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/setRegionSolidFields.H @@ -1,5 +1,5 @@ - fvMesh& mesh = solidRegions[i]; - basicSolidThermo& thermo = thermos[i]; + fvMesh& mesh = procMeshes[solidToProc[i]]; + basicSolidThermo& thermo = thermoSolid[i]; tmp trho = thermo.rho(); const volScalarField& rho = trho(); diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffusionNo.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffusionNo.H index 77dc6f04bf..5564d3bd3a 100644 --- a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffusionNo.H +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffusionNo.H @@ -1,6 +1,6 @@ scalar DiNum = -GREAT; - forAll(solidRegions, i) + forAll(solidToProc, i) { # include "setRegionSolidFields.H" @@ -8,7 +8,7 @@ ( solidRegionDiffNo ( - solidRegions[i], + procMeshes[solidToProc[i]], runTime, rho*cp, K diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solveSolid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solveSolid.H index d8aa03283b..96cd32ddb3 100644 --- a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solveSolid.H +++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solveSolid.H @@ -1,8 +1,3 @@ -if (finalIter) -{ - mesh.data::add("finalIteration", true); -} - { for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++) { @@ -17,10 +12,3 @@ if (finalIter) Info<< "Min/max T:" << min(T) << ' ' << max(T) << endl; } - -thermo.correct(); - -if (finalIter) -{ - mesh.data::remove("finalIteration"); -} diff --git a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/extrudeToRegionMesh.C b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/extrudeToRegionMesh.C index f6214c8e62..0a085485f1 100644 --- a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/extrudeToRegionMesh.C +++ b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/extrudeToRegionMesh.C @@ -936,12 +936,6 @@ int main(int argc, char *argv[]) const word dictName (args.optionLookupOrDefault("dict", "extrudeToRegionMeshDict")); - mappedPatchBase::sampleMode sampleMode = mappedPatchBase::NEARESTPATCHFACE; - if (args.optionFound("AMI")) - { - sampleMode = mappedPatchBase::NEARESTPATCHFACEAMI; - } - IOdictionary dict ( IOobject @@ -966,6 +960,9 @@ int main(int argc, char *argv[]) dict.lookup("faceZonesShadow") >> zoneShadowNames; } + mappedPatchBase::sampleMode sampleMode = + mappedPatchBase::sampleModeNames_[dict.lookup("sampleMode")]; + const Switch oneD(dict.lookup("oneD")); const Switch adaptMesh(dict.lookup("adaptMesh")); diff --git a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/extrudeToRegionMeshDict b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/extrudeToRegionMeshDict index 7aa652fb79..b5f14db5d6 100644 --- a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/extrudeToRegionMeshDict +++ b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/extrudeToRegionMeshDict @@ -15,10 +15,10 @@ FoamFile // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Name of region to create -region liquidFilm; +region liquidFilm; // FaceZones to extrude -faceZones (f0); +faceZones (f0); // FaceZone shadow //faceZonesShadow (fBaffleShadow); @@ -30,10 +30,13 @@ faceZones (f0); // - extruding boundary faces: repatched to be on mapped patches // If false: leave original mesh intact. Extruded mesh will still have // mapped patch which might need to be adapted. -adaptMesh true; +adaptMesh true; + +// Sample mode for inter-region communication +sampleMode nearestPatchFace; // Extrude 1D-columns of cells? -oneD false; +oneD false; // If oneD is true. Specify which boundary is wanted between the layers //oneDPolyPatchType emptyPolyPatch; //wedgePolyPatch @@ -42,23 +45,23 @@ oneD false; //- Extrusion model to use. The only logical choice is linearNormal? //- Linear extrusion in normal direction -extrudeModel linearNormal; +extrudeModel linearNormal; //- Linear extrusion in specified direction -//extrudeModel linearDirection; +// extrudeModel linearDirection; //- Wedge extrusion. If nLayers is 1 assumes symmetry around plane. -// extrudeModel wedge; +// extrudeModel wedge; //- Extrudes into sphere around (0 0 0) -//extrudeModel linearRadial; +// extrudeModel linearRadial; //- Extrudes into sphere with grading according to pressure (atmospherics) -//extrudeModel sigmaRadial; +// extrudeModel sigmaRadial; -nLayers 10; +nLayers 10; -expansionRatio 0.9; +expansionRatio 0.9; linearNormalCoeffs { diff --git a/applications/utilities/parallelProcessing/decomposePar/Make/files b/applications/utilities/parallelProcessing/decomposePar/Make/files index 125f6b81e7..cad5ac1ce3 100644 --- a/applications/utilities/parallelProcessing/decomposePar/Make/files +++ b/applications/utilities/parallelProcessing/decomposePar/Make/files @@ -3,7 +3,6 @@ domainDecomposition.C domainDecompositionMesh.C domainDecompositionDistribute.C dimFieldDecomposer.C -fvFieldDecomposer.C pointFieldDecomposer.C lagrangianFieldDecomposer.C diff --git a/applications/utilities/parallelProcessing/decomposePar/Make/options b/applications/utilities/parallelProcessing/decomposePar/Make/options index 7a9f1df3f5..7194eb1bce 100644 --- a/applications/utilities/parallelProcessing/decomposePar/Make/options +++ b/applications/utilities/parallelProcessing/decomposePar/Make/options @@ -1,4 +1,5 @@ EXE_INC = \ + -I$(LIB_SRC)/parallel/decompose/decompose/lnInclude \ -I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \ -I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude \ @@ -6,6 +7,7 @@ EXE_INC = \ EXE_LIBS = \ -lfiniteVolume \ + -ldecompose \ -lgenericPatchFields \ -ldecompositionMethods -L$(FOAM_LIBBIN)/dummy -lmetisDecomp -lscotchDecomp \ -llagrangian \ diff --git a/etc/config/settings.csh b/etc/config/settings.csh index 93f3e506ab..fbb9f04270 100644 --- a/etc/config/settings.csh +++ b/etc/config/settings.csh @@ -487,9 +487,31 @@ case QSMPI: breaksw case SGIMPI: - setenv FOAM_MPI ${MPI_ROOT##*/} + if ( ! $?MPI_ROOT) setenv MPI_ROOT /dummy + + if ( ! -d "$MPI_ROOT" ) then + echo "Warning in $WM_PROJECT_DIR/etc/config/settings.csh:" + echo " MPI_ROOT not a valid mpt installation directory." + echo " Please set MPI_ROOT to the mpt installation directory." + echo " (usually done by loading the mpt module)" + echo " MPI_ROOT currently set to '$MPI_ROOT'" + endif + + if ( "${MPI_ROOT:h}/" == $MPI_ROOT ) then + setenv MPI_ROOT ${MPI_ROOT:h} + endif + + setenv FOAM_MPI ${MPI_ROOT:t} setenv MPI_ARCH_PATH $MPI_ROOT + + if ($?FOAM_VERBOSE && $?prompt) then + echo "Using SGI MPT:" + echo " MPI_ROOT : $MPI_ROOT" + echo " FOAM_MPI : $FOAM_MPI" + endif + + _foamAddPath $MPI_ARCH_PATH/bin _foamAddLib $MPI_ARCH_PATH/lib breaksw diff --git a/etc/config/settings.sh b/etc/config/settings.sh index 5111ef405a..bf8f58a34a 100644 --- a/etc/config/settings.sh +++ b/etc/config/settings.sh @@ -511,9 +511,30 @@ QSMPI) ;; SGIMPI) + lastCharID=$(( ${#MPI_ROOT} - 1 )) + if [ "${MPI_ROOT:$lastCharID:1}" == '/' ] + then + MPI_ROOT=${MPI_ROOT:0:$lastCharID} + fi + export FOAM_MPI=${MPI_ROOT##*/} export MPI_ARCH_PATH=$MPI_ROOT + if [ ! -d "$MPI_ROOT" -o -z "$MPI_ARCH_PATH" ] + then + echo "Warning in $WM_PROJECT_DIR/etc/config/settings.sh:" 1>&2 + echo " MPI_ROOT not a valid mpt installation directory or ending in a '/'." 1>&2 + echo " Please set MPI_ROOT to the mpt installation directory." 1>&2 + echo " MPI_ROOT currently set to '$MPI_ROOT'" 1>&2 + fi + + if [ "$FOAM_VERBOSE" -a "$PS1" ] + then + echo "Using SGI MPT:" + echo " MPI_ROOT : $MPI_ROOT" + echo " FOAM_MPI : $FOAM_MPI" + fi + _foamAddPath $MPI_ARCH_PATH/bin _foamAddLib $MPI_ARCH_PATH/lib ;; diff --git a/etc/controlDict b/etc/controlDict index c367f5d853..7a14e9036c 100644 --- a/etc/controlDict +++ b/etc/controlDict @@ -58,6 +58,11 @@ OptimisationSwitches commsType nonBlocking; //scheduled; //blocking; floatTransfer 0; nProcsSimpleSum 0; + + // Force dumping (at next timestep) upon signal (-1 to disable) + writeNowSignal -1; //10; + // Force dumping (at next timestep) upon signal (-1 to disable) and exit + stopAtWriteNowSignal -1; } diff --git a/src/OSspecific/POSIX/Make/files b/src/OSspecific/POSIX/Make/files index c7396b6345..90dc5bc92e 100644 --- a/src/OSspecific/POSIX/Make/files +++ b/src/OSspecific/POSIX/Make/files @@ -2,6 +2,8 @@ signals/sigFpe.C signals/sigSegv.C signals/sigInt.C signals/sigQuit.C +signals/sigStopAtWriteNow.C +signals/sigWriteNow.C regExp.C timer.C fileStat.C diff --git a/src/OSspecific/POSIX/POSIX.C b/src/OSspecific/POSIX/POSIX.C index 7ab46939cd..e214e7eeca 100644 --- a/src/OSspecific/POSIX/POSIX.C +++ b/src/OSspecific/POSIX/POSIX.C @@ -123,7 +123,7 @@ bool Foam::setEnv } -Foam::word Foam::hostName(bool full) +Foam::string Foam::hostName(bool full) { char buf[128]; ::gethostname(buf, sizeof(buf)); @@ -142,7 +142,7 @@ Foam::word Foam::hostName(bool full) } -Foam::word Foam::domainName() +Foam::string Foam::domainName() { char buf[128]; ::gethostname(buf, sizeof(buf)); @@ -159,11 +159,11 @@ Foam::word Foam::domainName() } } - return word::null; + return string::null; } -Foam::word Foam::userName() +Foam::string Foam::userName() { struct passwd* pw = ::getpwuid(::getuid()); @@ -173,7 +173,7 @@ Foam::word Foam::userName() } else { - return word::null; + return string::null; } } @@ -209,7 +209,7 @@ Foam::fileName Foam::home() } -Foam::fileName Foam::home(const word& userName) +Foam::fileName Foam::home(const string& userName) { struct passwd* pw; @@ -1069,7 +1069,7 @@ void Foam::fdClose(const int fd) bool Foam::ping ( - const word& destName, + const string& destName, const label destPort, const label timeOut ) @@ -1083,7 +1083,7 @@ bool Foam::ping { FatalErrorIn ( - "Foam::ping(const word&, ...)" + "Foam::ping(const string&, ...)" ) << "gethostbyname error " << h_errno << " for host " << destName << abort(FatalError); } @@ -1097,7 +1097,7 @@ bool Foam::ping { FatalErrorIn ( - "Foam::ping(const word&, const label)" + "Foam::ping(const string&, const label)" ) << "socket error" << abort(FatalError); } @@ -1149,7 +1149,7 @@ bool Foam::ping } -bool Foam::ping(const word& hostname, const label timeOut) +bool Foam::ping(const string& hostname, const label timeOut) { return ping(hostname, 222, timeOut) || ping(hostname, 22, timeOut); } diff --git a/src/OSspecific/POSIX/signals/sigStopAtWriteNow.C b/src/OSspecific/POSIX/signals/sigStopAtWriteNow.C new file mode 100644 index 0000000000..09d862ca5d --- /dev/null +++ b/src/OSspecific/POSIX/signals/sigStopAtWriteNow.C @@ -0,0 +1,140 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011 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 . + +\*---------------------------------------------------------------------------*/ + +#include "sigStopAtWriteNow.H" +#include "error.H" +#include "JobInfo.H" +#include "IOstreams.H" +#include "Time.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// Signal number to catch +int Foam::sigStopAtWriteNow::signal_ +( + debug::optimisationSwitch("stopAtWriteNowSignal", -1) +); + +static Foam::Time const* runTimePtr_ = NULL; + + +struct sigaction Foam::sigStopAtWriteNow::oldAction_; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::sigStopAtWriteNow::sigHandler(int) +{ + // Reset old handling + if (sigaction(signal_, &oldAction_, NULL) < 0) + { + FatalErrorIn + ( + "Foam::sigStopAtWriteNow::sigHandler(int)" + ) << "Cannot reset " << signal_ << " trapping" + << abort(FatalError); + } + + // Update jobInfo file + jobInfo.signalEnd(); + + Info<< "sigStopAtWriteNow :" + << " setting up write and stop at end of the next iteration" + << nl << endl; + runTimePtr_->stopAt(Time::saWriteNow); + + //// Throw signal (to old handler) + //raise(signal_); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sigStopAtWriteNow::sigStopAtWriteNow(){} + + +Foam::sigStopAtWriteNow::sigStopAtWriteNow +( + const bool verbose, + const Time& runTime +) +{ + if (signal_ > 0) + { + // Store runTime + runTimePtr_ = &runTime; + + struct sigaction newAction; + newAction.sa_handler = sigHandler; + newAction.sa_flags = SA_NODEFER; + sigemptyset(&newAction.sa_mask); + if (sigaction(signal_, &newAction, &oldAction_) < 0) + { + FatalErrorIn + ( + "Foam::sigStopAtWriteNow::sigStopAtWriteNow" + "(const bool, const Time&)" + ) << "Cannot set " << signal_ << " trapping" + << abort(FatalError); + } + + if (verbose) + { + Info<< "sigStopAtWriteNow :" + << " Enabling writing and stopping upon signal " << signal_ + << endl; + } + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::sigStopAtWriteNow::~sigStopAtWriteNow() +{ + // Reset old handling + if (signal_ > 0) + { + if (sigaction(signal_, &oldAction_, NULL) < 0) + { + FatalErrorIn + ( + "Foam::sigStopAtWriteNow::~sigStopAtWriteNow()" + ) << "Cannot reset " << signal_ << " trapping" + << abort(FatalError); + } + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::sigStopAtWriteNow::active() const +{ + return signal_ > 0; +} + + +// ************************************************************************* // diff --git a/src/OSspecific/POSIX/signals/sigStopAtWriteNow.H b/src/OSspecific/POSIX/signals/sigStopAtWriteNow.H new file mode 100644 index 0000000000..4c07248eb2 --- /dev/null +++ b/src/OSspecific/POSIX/signals/sigStopAtWriteNow.H @@ -0,0 +1,99 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011 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 . + +Class + Foam::sigStopAtWriteNow + +Description + Signal handler for interupt defined by + OptimisationSwitches::stopAtWriteNowSignal + + Write and stop the job. + +SourceFiles + sigStopAtWriteNow.C + +\*---------------------------------------------------------------------------*/ + +#ifndef sigStopAtWriteNow_H +#define sigStopAtWriteNow_H + +#include + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +class Time; + +/*---------------------------------------------------------------------------*\ + Class sigStopAtWriteNow Declaration +\*---------------------------------------------------------------------------*/ + +class sigStopAtWriteNow +{ + // Private data + + //- number of signal to use + static int signal_; + + //- Saved old signal trapping setting + static struct sigaction oldAction_; + + // Private Member Functions + + static void sigHandler(int); + + +public: + + // Constructors + + //- Construct null + sigStopAtWriteNow(); + + //- Construct from components + sigStopAtWriteNow(const bool verbose, const Time& runTime); + + + //- Destructor + ~sigStopAtWriteNow(); + + + // Member functions + + //- Is active? + bool active() const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/POSIX/signals/sigWriteNow.C b/src/OSspecific/POSIX/signals/sigWriteNow.C new file mode 100644 index 0000000000..6ad98a6190 --- /dev/null +++ b/src/OSspecific/POSIX/signals/sigWriteNow.C @@ -0,0 +1,122 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011 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 . + +\*---------------------------------------------------------------------------*/ + +#include "sigWriteNow.H" +#include "error.H" +#include "JobInfo.H" +#include "IOstreams.H" +#include "Time.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// Signal number to catch +int Foam::sigWriteNow::signal_ +( + debug::optimisationSwitch("writeNowSignal", -1) +); + +static Foam::Time* runTimePtr_ = NULL; + + +struct sigaction Foam::sigWriteNow::oldAction_; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::sigWriteNow::sigHandler(int) +{ + Info<< "sigWriteNow :" + << " setting up write at end of the next iteration" << nl << endl; + runTimePtr_->writeOnce(); + + //// Throw signal (to old handler) + //raise(signal_); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sigWriteNow::sigWriteNow() +{} + + +Foam::sigWriteNow::sigWriteNow(const bool verbose, Time& runTime) +{ + if (signal_ >= 0) + { + // Store runTime + runTimePtr_ = &runTime; + + struct sigaction newAction; + newAction.sa_handler = sigHandler; + newAction.sa_flags = SA_NODEFER; + sigemptyset(&newAction.sa_mask); + if (sigaction(signal_, &newAction, &oldAction_) < 0) + { + FatalErrorIn + ( + "Foam::sigWriteNow::sigWriteNow(const bool, const Time&)" + ) << "Cannot set " << signal_ << " trapping" + << abort(FatalError); + } + + if (verbose) + { + Info<< "sigWriteNow :" + << " Enabling writing upon signal " << signal_ + << endl; + } + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::sigWriteNow::~sigWriteNow() +{ + // Reset old handling + if (signal_ > 0) + { + if (sigaction(signal_, &oldAction_, NULL) < 0) + { + FatalErrorIn + ( + "Foam::sigWriteNow::~sigWriteNow()" + ) << "Cannot reset " << signal_ << " trapping" + << abort(FatalError); + } + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::sigWriteNow::active() const +{ + return signal_ > 0; +} + + +// ************************************************************************* // diff --git a/src/OSspecific/POSIX/signals/sigWriteNow.H b/src/OSspecific/POSIX/signals/sigWriteNow.H new file mode 100644 index 0000000000..871b980edd --- /dev/null +++ b/src/OSspecific/POSIX/signals/sigWriteNow.H @@ -0,0 +1,99 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011 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 . + +Class + Foam::sigWriteNow + +Description + Signal handler for interupt defined by OptimisationSwitches::writeNowSignal + + Write once and continue. + +SourceFiles + sigWriteNow.C + +\*---------------------------------------------------------------------------*/ + +#ifndef sigWriteNow_H +#define sigWriteNow_H + +#include + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +class Time; + +/*---------------------------------------------------------------------------*\ + Class sigWriteNow Declaration +\*---------------------------------------------------------------------------*/ + +class sigWriteNow +{ + // Private data + + //- number of signal to use + static int signal_; + + //- Saved old signal trapping setting + static struct sigaction oldAction_; + + // Private Member Functions + + static void sigHandler(int); + + +public: + + // Constructors + + //- Construct null + sigWriteNow(); + + //- Construct from components + sigWriteNow(const bool verbose, Time& runTime); + + + //- Destructor + ~sigWriteNow(); + + + // Member functions + + //- Is active? + bool active() const; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/Time/Time.C b/src/OpenFOAM/db/Time/Time.C index 727f21c98c..0051d23153 100644 --- a/src/OpenFOAM/db/Time/Time.C +++ b/src/OpenFOAM/db/Time/Time.C @@ -81,10 +81,17 @@ void Foam::Time::adjustDeltaT() { if (writeControl_ == wcAdjustableRunTime) { + scalar interval = writeInterval_; + if (secondaryWriteControl_ == wcAdjustableRunTime) + { + interval = min(interval, secondaryWriteInterval_); + } + + scalar timeToNextWrite = max ( 0.0, - (outputTimeIndex_ + 1)*writeInterval_ - (value() - startTime_) + (outputTimeIndex_ + 1)*interval - (value() - startTime_) ); scalar nSteps = timeToNextWrite/deltaT_ - SMALL; @@ -252,8 +259,13 @@ Foam::Time::Time stopAt_(saEndTime), writeControl_(wcTimeStep), writeInterval_(GREAT), + secondaryWriteControl_(wcTimeStep), + secondaryWriteInterval_(labelMax), purgeWrite_(0), + writeOnce_(false), subCycling_(false), + sigWriteNow_(true, *this), + sigStopAtWriteNow_(true, *this), writeFormat_(IOstream::ASCII), writeVersion_(IOstream::currentVersion), @@ -339,8 +351,13 @@ Foam::Time::Time stopAt_(saEndTime), writeControl_(wcTimeStep), writeInterval_(GREAT), + secondaryWriteControl_(wcTimeStep), + secondaryWriteInterval_(labelMax), purgeWrite_(0), + writeOnce_(false), subCycling_(false), + sigWriteNow_(true, *this), + sigStopAtWriteNow_(true, *this), writeFormat_(IOstream::ASCII), writeVersion_(IOstream::currentVersion), @@ -429,8 +446,13 @@ Foam::Time::Time stopAt_(saEndTime), writeControl_(wcTimeStep), writeInterval_(GREAT), + secondaryWriteControl_(wcTimeStep), + secondaryWriteInterval_(labelMax), purgeWrite_(0), + writeOnce_(false), subCycling_(false), + sigWriteNow_(true, *this), + sigStopAtWriteNow_(true, *this), writeFormat_(IOstream::ASCII), writeVersion_(IOstream::currentVersion), @@ -521,7 +543,10 @@ Foam::Time::Time stopAt_(saEndTime), writeControl_(wcTimeStep), writeInterval_(GREAT), + secondaryWriteControl_(wcTimeStep), + secondaryWriteInterval_(labelMax), purgeWrite_(0), + writeOnce_(false), subCycling_(false), writeFormat_(IOstream::ASCII), @@ -944,6 +969,35 @@ Foam::Time& Foam::Time::operator++() if (!subCycling_) { + if (sigStopAtWriteNow_.active() || sigWriteNow_.active()) + { + // A signal might have been sent on one processor only + // Reduce so all decide the same. + + label flag = 0; + if (sigStopAtWriteNow_.active() && stopAt_ == saWriteNow) + { + flag += 1; + } + if (sigWriteNow_.active() && writeOnce_) + { + flag += 2; + } + reduce(flag, maxOp