diff --git a/applications/utilities/mesh/manipulation/createNonConformalCouples/createNonConformalCouples.C b/applications/utilities/mesh/manipulation/createNonConformalCouples/createNonConformalCouples.C index c56b3b7093..c3a5a97b12 100644 --- a/applications/utilities/mesh/manipulation/createNonConformalCouples/createNonConformalCouples.C +++ b/applications/utilities/mesh/manipulation/createNonConformalCouples/createNonConformalCouples.C @@ -75,17 +75,140 @@ using namespace Foam; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -void createNonConformalCouples -( - fvMesh& mesh, - const List>& patchNames, - const wordList& cyclicNames, - const List& transforms -) +int main(int argc, char *argv[]) { + #include "addOverwriteOption.H" + #include "addRegionOption.H" + #include "addDictOption.H" + + const bool haveArgs = argList::hasArgs(argc, argv); + if (haveArgs) + { + argList::validArgs.append("patch1"); + argList::validArgs.append("patch2"); + argList::addBoolOption + ( + "fields", + "add non-conformal boundary conditions to the fields" + ); + } + + #include "setRootCase.H" + #include "createTime.H" + runTime.functionObjects().off(); + + // Flag to determine whether or not patches are added to fields + bool fields; + + // Patch names between which to create couples, field dictionaries, the + // associated cyclic name prefix and transformation (if any) + List> patchNames; + List> patchFieldDicts; + wordList cyclicNames; + List transforms; + + // If there are patch name arguments, then we assume fields are not being + // changed, the cyclic name is just the cyclic typename, and that there is + // no transformation. If there are no arguments then get all this + // information from the system dictionary. + if (haveArgs) + { + fields = args.optionFound("fields"); + + patchNames.append(Pair(args[1], args[2])); + patchFieldDicts.append(Pair()); + cyclicNames.append(nonConformalCyclicPolyPatch::typeName); + transforms.append(cyclicTransform(true)); + } + else + { + static const word dictName("createNonConformalCouplesDict"); + + IOdictionary dict(systemDict(dictName, args, runTime)); + + fields = dict.lookupOrDefault("fields", false); + + const dictionary& couplesDict = + dict.optionalSubDict("nonConformalCouples"); + + forAllConstIter(dictionary, couplesDict, iter) + { + if (!iter().isDict()) continue; + + const dictionary& subDict = iter().dict(); + + const bool havePatches = subDict.found("patches"); + const bool haveOwnerNeighbour = + subDict.found("owner") || subDict.found("neighbour"); + + if (havePatches == haveOwnerNeighbour) + { + FatalIOErrorInFunction(subDict) + << "Patches should be specified with either a single " + << "\"patches\" entry with a pair of patch names, or with " + << "two sub-dictionaries named \"owner\" and " + << "\"neighbour\"." << exit(FatalIOError); + } + + if (havePatches) + { + patchNames.append(subDict.lookup>("patches")); + patchFieldDicts.append(Pair()); + } + + if (haveOwnerNeighbour) + { + const dictionary& ownerDict = subDict.subDict("owner"); + const dictionary& neighbourDict = subDict.subDict("neighbour"); + + patchNames.append + ( + Pair + ( + ownerDict["patch"], + neighbourDict["patch"] + ) + ); + patchFieldDicts.append + ( + Pair + ( + ownerDict.subOrEmptyDict("patchFields"), + neighbourDict.subOrEmptyDict("patchFields") + ) + ); + } + + cyclicNames.append(subDict.dictName()); + transforms.append(cyclicTransform(subDict, true)); + } + } + + Foam::word meshRegionName = polyMesh::defaultRegion; + args.optionReadIfPresent("region", meshRegionName); + + #include "createNamedMesh.H" + const polyBoundaryMesh& patches = mesh.boundaryMesh(); + const bool overwrite = args.optionFound("overwrite"); + + const word oldInstance = mesh.pointsInstance(); + + // Read the fields + IOobjectList objects(mesh, runTime.timeName()); + if (fields) Info<< "Reading geometric fields" << nl << endl; + #include "readVolFields.H" + #include "readSurfaceFields.H" + #include "readPointFields.H" + if (fields) Info<< endl; + + // Make sure the mesh is not connected before couples are added + mesh.conform(); + + // Start building lists of patches and patch-fields to add List newPatches; + List newPatchFieldDicts; // Find the first processor patch and face label firstProcPatchi = patches.size(), firstProcFacei = mesh.nFaces(); @@ -116,6 +239,10 @@ void createNonConformalCouples ( pp.clone(patches, patchi, pp.size(), pp.start()).ptr() ); + newPatchFieldDicts.append + ( + dictionary() + ); } // Convenience function to generate patch names for the owner or neighbour @@ -157,6 +284,10 @@ void createNonConformalCouples transforms[i] ) ); + newPatchFieldDicts.append + ( + patchFieldDicts[i][0] + ); newPatches.append ( new nonConformalCyclicPolyPatch @@ -172,6 +303,10 @@ void createNonConformalCouples inv(transforms[i]) ) ); + newPatchFieldDicts.append + ( + patchFieldDicts[i][1] + ); } // Add the error patches. Note there is only one for each source patch, @@ -198,6 +333,10 @@ void createNonConformalCouples iter.key() ) ); + newPatchFieldDicts.append + ( + dictionary() + ); } }; appendErrorPatches(true); @@ -212,6 +351,10 @@ void createNonConformalCouples ( pp.clone(patches, newPatches.size(), pp.size(), pp.start()).ptr() ); + newPatchFieldDicts.append + ( + dictionary() + ); } // Add the processor cyclic patches @@ -278,6 +421,10 @@ void createNonConformalCouples patchNames[i][!owner] ) ); + newPatchFieldDicts.append + ( + patchFieldDicts[i][!owner] + ); } } } @@ -291,7 +438,8 @@ void createNonConformalCouples } // Re-patch the mesh. Note that new patches are all constraints, so the - // dictionary and patch type do not get used. + // dictionary and patch type do not get used. Overrides will be handled + // later, once all patches have been added and the mesh has been stitched. forAll(newPatches, newPatchi) { fvMeshTools::addPatch @@ -303,104 +451,24 @@ void createNonConformalCouples false ); } -} - - -int main(int argc, char *argv[]) -{ - #include "addOverwriteOption.H" - #include "addRegionOption.H" - #include "addDictOption.H" - - const bool haveArgs = argList::hasArgs(argc, argv); - if (haveArgs) - { - argList::validArgs.append("patch1"); - argList::validArgs.append("patch2"); - argList::addBoolOption - ( - "fields", - "add non-conformal boundary conditions to the fields" - ); - } - - #include "setRootCase.H" - #include "createTime.H" - runTime.functionObjects().off(); - - // Flag to determine whether or not patches are added to fields - bool fields; - - // Patch names between which to create couples, the associated cyclic name - // prefix and transformation (if any) - List> patchNames; - wordList cyclicNames; - List transforms; - - // If there are patch name arguments, then we assume fields are not being - // changed, the cyclic name is just the cyclic typename, and that there is - // no transformation. If there are no arguments then get all this - // information from the system dictionary. - if (haveArgs) - { - fields = args.optionFound("fields"); - - patchNames.append(Pair(args[1], args[2])); - cyclicNames.append(nonConformalCyclicPolyPatch::typeName); - transforms.append(cyclicTransform(true)); - } - else - { - static const word dictName("createNonConformalCouplesDict"); - - IOdictionary dict(systemDict(dictName, args, runTime)); - - fields = dict.lookupOrDefault("fields", false); - - const dictionary& couplesDict = - dict.optionalSubDict("nonConformalCouples"); - - forAllConstIter(dictionary, couplesDict, iter) - { - if (!iter().isDict()) continue; - - patchNames.append(iter().dict().lookup>("patches")); - cyclicNames.append(iter().dict().dictName()); - transforms.append(cyclicTransform(iter().dict(), true)); - } - } - - Foam::word meshRegionName = polyMesh::defaultRegion; - args.optionReadIfPresent("region", meshRegionName); - - const bool overwrite = args.optionFound("overwrite"); - - #include "createNamedMesh.H" - - // Read the fields - IOobjectList objects(mesh, runTime.timeName()); - if (fields) Info<< "Reading geometric fields" << nl << endl; - #include "readVolFields.H" - #include "readSurfaceFields.H" - #include "readPointFields.H" - if (fields) Info<< endl; - - const word oldInstance = mesh.pointsInstance(); - - // Make sure the mesh is not connected before couples are added - fvMeshStitchers::stationary stitcher(mesh); - stitcher.disconnect(false, false); - - createNonConformalCouples - ( - mesh, - patchNames, - cyclicNames, - transforms - ); // Connect the mesh so that the new stitching topology gets written out - stitcher.connect(false, false, false); + fvMeshStitchers::stationary(mesh).connect(false, false, false); + + // Set the fields on the new patches. All new patches are constraints, so + // this should only be creating overrides; e.g., jump cyclics. + forAll(newPatches, newPatchi) + { + if (!newPatchFieldDicts[newPatchi].empty()) + { + fvMeshTools::setPatchFields + ( + mesh, + newPatchi, + newPatchFieldDicts[newPatchi] + ); + } + } mesh.setInstance(runTime.timeName()); diff --git a/src/finiteVolume/fields/fvPatchFields/derived/fixedJump/fixedJumpFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/derived/fixedJump/fixedJumpFvPatchField.C index 0bba0af294..a6c2d07b19 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/fixedJump/fixedJumpFvPatchField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/fixedJump/fixedJumpFvPatchField.C @@ -158,7 +158,6 @@ template void Foam::fixedJumpFvPatchField::write(Ostream& os) const { fvPatchField::write(os); - writeEntry(os, "patchType", this->interfaceFieldType()); if (this->cyclicPatch().owner()) { diff --git a/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcher.C b/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcher.C index 0f08877001..e6ee9734f3 100644 --- a/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcher.C +++ b/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcher.C @@ -1206,12 +1206,15 @@ bool Foam::fvMeshStitcher::disconnect Info<< indent << typeName << ": Disconnecting" << incrIndent << endl; } - // Pre-conform surface fields. This splits the original and cyclic parts of - // the interface fields into separate boundary fields, with both sets of - // values store on the original faces. The original field overwrites the - // existing boundary values, whilst the cyclic field is stored as a - // separate field for use later. - preConformSurfaceFields(); + if (changing) + { + // Pre-conform surface fields. This splits the original and cyclic + // parts of the interface fields into separate boundary fields, with + // both sets of values store on the original faces. The original field + // overwrites the existing boundary values, whilst the cyclic field is + // stored as a separate field for use later. + preConformSurfaceFields(); + } // Undo all non-conformal changes and clear all geometry and topology mesh_.conform(); @@ -1382,20 +1385,23 @@ bool Foam::fvMeshStitcher::connect correctMeshPhi(polyFacesBf, Sf, Cf); } - // Post-non-conform surface fields. This reconstructs the original and - // cyclic parts of the interface fields from separate original and cyclic - // parts. The original part was store in the same field, whilst the cyclic - // part was separately registered. - postNonConformSurfaceFields(); + if (changing) + { + // Post-non-conform surface fields. This reconstructs the original and + // cyclic parts of the interface fields from separate original and + // cyclic parts. The original part was store in the same field, whilst + // the cyclic part was separately registered. + postNonConformSurfaceFields(); - // Volume fields are assumed to be intensive. So, the value on a face which - // has changed in size can be retained without modification. New faces need - // values to be set. This is done by evaluating all the nonConformalCoupled - // patch fields. - evaluateVolFields(); + // Volume fields are assumed to be intensive. So, the value on a face + // which has changed in size can be retained without modification. New + // faces need values to be set. This is done by evaluating all the + // nonConformalCoupled patch fields. + evaluateVolFields(); - // Do special post-non-conformation for surface velocities. - postNonConformSurfaceVelocities(); + // Do special post-non-conformation for surface velocities. + postNonConformSurfaceVelocities(); + } // Prevent hangs caused by processor cyclic patches using mesh geometry mesh_.deltaCoeffs(); diff --git a/src/thermophysicalModels/basic/basicThermo/basicThermo.C b/src/thermophysicalModels/basic/basicThermo/basicThermo.C index da8d95727d..bacda86636 100644 --- a/src/thermophysicalModels/basic/basicThermo/basicThermo.C +++ b/src/thermophysicalModels/basic/basicThermo/basicThermo.C @@ -205,12 +205,9 @@ Foam::wordList Foam::basicThermo::heBoundaryBaseTypes() forAll(tbf, patchi) { - if (isA(tbf[patchi])) + if (tbf[patchi].overridesConstraint()) { - const fixedJumpFvPatchScalarField& pf = - dynamic_cast(tbf[patchi]); - - hbt[patchi] = pf.interfaceFieldType(); + hbt[patchi] = tbf[patchi].patch().type(); } else if (isA(tbf[patchi])) { diff --git a/tutorials/modules/incompressibleFluid/TJunctionFan/Allrun b/tutorials/modules/incompressibleFluid/TJunctionFan/Allrun index 1b6d6dcf99..260e3001c3 100755 --- a/tutorials/modules/incompressibleFluid/TJunctionFan/Allrun +++ b/tutorials/modules/incompressibleFluid/TJunctionFan/Allrun @@ -11,7 +11,7 @@ runApplication blockMesh # Create faceZones for baffles and fan runApplication topoSet -# Create wall and cyclic baffles and the fields on them +# Create baffles and the fields on them runApplication createBaffles -overwrite runApplication $application diff --git a/tutorials/modules/incompressibleFluid/TJunctionFan/Allrun-NCC b/tutorials/modules/incompressibleFluid/TJunctionFan/Allrun-NCC new file mode 100755 index 0000000000..bb0894a872 --- /dev/null +++ b/tutorials/modules/incompressibleFluid/TJunctionFan/Allrun-NCC @@ -0,0 +1,20 @@ +#!/bin/sh + +# Source tutorial run functions +. $WM_PROJECT_DIR/bin/tools/RunFunctions + +# Get application name +application=$(getApplication) + +runApplication blockMesh + +# Create faceZones for baffles and fan +runApplication topoSet + +# Create baffles and the fields on them +runApplication createBaffles -overwrite -dict system/createBafflesDict.NCC + +# Create non-conformal couplings +runApplication createNonConformalCouples -overwrite + +runApplication $application diff --git a/tutorials/modules/incompressibleFluid/TJunctionFan/system/createBafflesDict b/tutorials/modules/incompressibleFluid/TJunctionFan/system/createBafflesDict index b896f00cca..5f0716b00d 100644 --- a/tutorials/modules/incompressibleFluid/TJunctionFan/system/createBafflesDict +++ b/tutorials/modules/incompressibleFluid/TJunctionFan/system/createBafflesDict @@ -19,10 +19,10 @@ fields true; baffles { - baffleFaces + baffle { type faceZone; - zoneName baffleFaces; + zoneName baffle; owner { @@ -80,18 +80,16 @@ baffles } } - cyclicFaces + fan { - type searchableSurface; - surface searchablePlate; - origin (0.099 -0.006 0.004); - span (0 0.012 0.012); + type faceZone; + zoneName fan; owner { - name cyclic0; + name fan0; type cyclic; - neighbourPatch cyclic1; + neighbourPatch fan1; patchFields { @@ -108,9 +106,9 @@ baffles neighbour { - name cyclic1; + name fan1; type cyclic; - neighbourPatch cyclic0; + neighbourPatch fan0; patchFields { diff --git a/tutorials/modules/incompressibleFluid/TJunctionFan/system/createBafflesDict.NCC b/tutorials/modules/incompressibleFluid/TJunctionFan/system/createBafflesDict.NCC new file mode 100644 index 0000000000..7a94c6df88 --- /dev/null +++ b/tutorials/modules/incompressibleFluid/TJunctionFan/system/createBafflesDict.NCC @@ -0,0 +1,113 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object createBafflesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +internalFacesOnly true; + +fields true; + +baffles +{ + baffle + { + type faceZone; + zoneName baffle; + + owner + { + name baffle0; + type wall; + + patchFields + { + epsilon + { + type epsilonWallFunction; + Cmu 0.09; + kappa 0.41; + E 9.8; + value uniform 0; + } + k + { + type kqRWallFunction; + value uniform 0; + } + nut + { + type nutkWallFunction; + Cmu 0.09; + kappa 0.41; + E 9.8; + value uniform 0; + } + nuTilda + { + type zeroGradient; + } + p + { + type zeroGradient; + } + U + { + type fixedValue; + value uniform (0 0 0); + } + } + } + + neighbour + { + name baffle1; + type wall; + + patchFields + { + $../../owner/patchFields; + } + } + } + + fan + { + type faceZone; + zoneName fan; + + owner + { + name fan0; + type wall; + + patchFields + { + $../../../baffle/owner/patchFields; + } + } + + neighbour + { + name fan1; + type wall; + + patchFields + { + $../../owner/patchFields; + } + } + } +} + + +// ************************************************************************* // diff --git a/tutorials/modules/incompressibleFluid/TJunctionFan/system/createNonConformalCouplesDict b/tutorials/modules/incompressibleFluid/TJunctionFan/system/createNonConformalCouplesDict new file mode 100644 index 0000000000..6bf64bcbc2 --- /dev/null +++ b/tutorials/modules/incompressibleFluid/TJunctionFan/system/createNonConformalCouplesDict @@ -0,0 +1,55 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object createNonConformalCouplesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +fields yes; + +nonConformalCouples +{ + fan + { + owner + { + patch fan0; + + patchFields + { + p + { + type fanPressureJump; + patchType nonConformalCyclic; + jump uniform 0; + value uniform 0; + jumpTable polynomial 1((100 0)); + } + } + } + + neighbour + { + patch fan1; + + patchFields + { + $../../owner/patchFields; + } + } + + transform none; + } +} + + +// ************************************************************************* // diff --git a/tutorials/modules/incompressibleFluid/TJunctionFan/system/topoSetDict b/tutorials/modules/incompressibleFluid/TJunctionFan/system/topoSetDict index 95a53023da..133af1b1da 100644 --- a/tutorials/modules/incompressibleFluid/TJunctionFan/system/topoSetDict +++ b/tutorials/modules/incompressibleFluid/TJunctionFan/system/topoSetDict @@ -17,52 +17,28 @@ FoamFile actions ( { - name cyclicFacesFaceSet; - type faceSet; - action new; - source boxToFace; - box (0.099 -0.006 0.004)(0.101 0.006 0.016); - } - - { - name cyclicFacesSlaveCells; - type cellSet; - action new; - source boxToCell; - box (-10 -10 -10)(0.1 10 10); - } - - { - name cyclicFaces; + name baffle; type faceZoneSet; action new; - source setsToFaceZone; - faceSet cyclicFacesFaceSet; - cellSet cyclicFacesSlaveCells; + source planeToFaceZone; + point (0.1 0 0); + normal (1 0 0); } - { - name baffleFaceSet; - type faceSet; + name fan; + type faceZoneSet; action new; - source boxToFace; - box (0.099 -10 -10)(0.101 10 10); + source searchableSurfaceToFaceZone; + surface searchablePlate; + origin (0.1 -0.006 0.004); + span (0 0.012 0.012); } - { - name baffleFaceSet; - type faceSet; + name baffle; + type faceZoneSet; action delete; - source boxToFace; - box (0.099 -0.006 0.004)(0.101 0.006 0.016); - } - - { - name baffleFaces; - type faceZoneSet; - action new; - source setToFaceZone; - faceSet baffleFaceSet; + source faceZoneToFaceZone; + zone fan; } );