diff --git a/applications/solvers/compressible/rhoPorousSimpleFoam/UEqn.H b/applications/solvers/compressible/rhoPorousSimpleFoam/UEqn.H index 00a6f39bf468159df59e8de6983c4452be65c5ef..4150cd7503f41d781ce066ae50ee9acfd915e00c 100644 --- a/applications/solvers/compressible/rhoPorousSimpleFoam/UEqn.H +++ b/applications/solvers/compressible/rhoPorousSimpleFoam/UEqn.H @@ -35,7 +35,12 @@ { pZones.addResistance(UEqn()); - solve(UEqn() == -fvc::grad(p)); + eqnResidual = solve + ( + UEqn() == -fvc::grad(p) + ). initialResidual(); + + maxResidual = max(eqnResidual, maxResidual); trAU = 1.0/UEqn().A(); trAU().rename("rAU"); diff --git a/applications/solvers/compressible/rhoPorousSimpleFoam/convergenceCheck.H b/applications/solvers/compressible/rhoPorousSimpleFoam/convergenceCheck.H new file mode 100644 index 0000000000000000000000000000000000000000..8958063193af348a058fd8f3baecb2547c00da3c --- /dev/null +++ b/applications/solvers/compressible/rhoPorousSimpleFoam/convergenceCheck.H @@ -0,0 +1,9 @@ +// check convergence + +if (maxResidual < convergenceCriterion) +{ + Info<< "reached convergence criterion: " << convergenceCriterion << endl; + runTime.writeAndEnd(); + Info<< "latestTime = " << runTime.timeName() << endl; +} + diff --git a/applications/solvers/compressible/rhoPorousSimpleFoam/hEqn.H b/applications/solvers/compressible/rhoPorousSimpleFoam/hEqn.H index e5d60199fe7638498a04749a6e3d9d9f38384de3..8eb03f95eb46b687a79f9f68c09152bbd269224a 100644 --- a/applications/solvers/compressible/rhoPorousSimpleFoam/hEqn.H +++ b/applications/solvers/compressible/rhoPorousSimpleFoam/hEqn.H @@ -11,7 +11,8 @@ hEqn.relax(); - hEqn.solve(); + eqnResidual = hEqn.solve().initialResidual(); + maxResidual = max(eqnResidual, maxResidual); thermo->correct(); } diff --git a/applications/solvers/compressible/rhoPorousSimpleFoam/initConvergenceCheck.H b/applications/solvers/compressible/rhoPorousSimpleFoam/initConvergenceCheck.H new file mode 100644 index 0000000000000000000000000000000000000000..b56197f22a50cfd07b04fc14d40b9a5454da8c5b --- /dev/null +++ b/applications/solvers/compressible/rhoPorousSimpleFoam/initConvergenceCheck.H @@ -0,0 +1,7 @@ +// initialize values for convergence checks + + scalar eqnResidual = 1, maxResidual = 0; + scalar convergenceCriterion = 0; + + simple.readIfPresent("convergence", convergenceCriterion); + diff --git a/applications/solvers/compressible/rhoPorousSimpleFoam/pEqn.H b/applications/solvers/compressible/rhoPorousSimpleFoam/pEqn.H index 558a57c86bed684ed2c4d46e194c746a485d2509..ae41da9e36fd7af8dd172b163b16dd8829a93b8b 100644 --- a/applications/solvers/compressible/rhoPorousSimpleFoam/pEqn.H +++ b/applications/solvers/compressible/rhoPorousSimpleFoam/pEqn.H @@ -26,7 +26,16 @@ for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++) } tpEqn().setReference(pRefCell, pRefValue); - tpEqn().solve(); + // retain the residual from the first iteration + if (nonOrth == 0) + { + eqnResidual = tpEqn().solve().initialResidual(); + maxResidual = max(eqnResidual, maxResidual); + } + else + { + tpEqn().solve(); + } if (nonOrth == nNonOrthCorr) { diff --git a/applications/solvers/compressible/rhoPorousSimpleFoam/rhoPorousSimpleFoam.C b/applications/solvers/compressible/rhoPorousSimpleFoam/rhoPorousSimpleFoam.C index 4042dc43f140d34a3bc7aaf49b1293a2409f5cf1..cba0c2dce171dcef9122ced75c5c9c3e1ad35c10 100644 --- a/applications/solvers/compressible/rhoPorousSimpleFoam/rhoPorousSimpleFoam.C +++ b/applications/solvers/compressible/rhoPorousSimpleFoam/rhoPorousSimpleFoam.C @@ -56,6 +56,7 @@ int main(int argc, char *argv[]) Info<< "Time = " << runTime.timeName() << nl << endl; # include "readSIMPLEControls.H" +# include "initConvergenceCheck.H" p.storePrevIter(); rho.storePrevIter(); @@ -70,10 +71,11 @@ int main(int argc, char *argv[]) turbulence->correct(); runTime.write(); - Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" << " ClockTime = " << runTime.elapsedClockTime() << " s" << nl << endl; + +# include "convergenceCheck.H" } Info<< "End\n" << endl; diff --git a/applications/solvers/compressible/rhoSimpleFoam/UEqn.H b/applications/solvers/compressible/rhoSimpleFoam/UEqn.H index f1bed4d071e985d92c9057c777ca9e216b174c54..c41bc9b6c7b93cab65751d97b441f519e4b3d05f 100644 --- a/applications/solvers/compressible/rhoSimpleFoam/UEqn.H +++ b/applications/solvers/compressible/rhoSimpleFoam/UEqn.H @@ -9,4 +9,9 @@ UEqn().relax(); - solve(UEqn() == -fvc::grad(p)); + eqnResidual = solve + ( + UEqn() == -fvc::grad(p) + ).initialResidual(); + + maxResidual = max(eqnResidual, maxResidual); diff --git a/applications/solvers/compressible/rhoSimpleFoam/convergenceCheck.H b/applications/solvers/compressible/rhoSimpleFoam/convergenceCheck.H new file mode 100644 index 0000000000000000000000000000000000000000..8958063193af348a058fd8f3baecb2547c00da3c --- /dev/null +++ b/applications/solvers/compressible/rhoSimpleFoam/convergenceCheck.H @@ -0,0 +1,9 @@ +// check convergence + +if (maxResidual < convergenceCriterion) +{ + Info<< "reached convergence criterion: " << convergenceCriterion << endl; + runTime.writeAndEnd(); + Info<< "latestTime = " << runTime.timeName() << endl; +} + diff --git a/applications/solvers/compressible/rhoSimpleFoam/hEqn.H b/applications/solvers/compressible/rhoSimpleFoam/hEqn.H index e5d60199fe7638498a04749a6e3d9d9f38384de3..8eb03f95eb46b687a79f9f68c09152bbd269224a 100644 --- a/applications/solvers/compressible/rhoSimpleFoam/hEqn.H +++ b/applications/solvers/compressible/rhoSimpleFoam/hEqn.H @@ -11,7 +11,8 @@ hEqn.relax(); - hEqn.solve(); + eqnResidual = hEqn.solve().initialResidual(); + maxResidual = max(eqnResidual, maxResidual); thermo->correct(); } diff --git a/applications/solvers/compressible/rhoSimpleFoam/initConvergenceCheck.H b/applications/solvers/compressible/rhoSimpleFoam/initConvergenceCheck.H new file mode 100644 index 0000000000000000000000000000000000000000..b56197f22a50cfd07b04fc14d40b9a5454da8c5b --- /dev/null +++ b/applications/solvers/compressible/rhoSimpleFoam/initConvergenceCheck.H @@ -0,0 +1,7 @@ +// initialize values for convergence checks + + scalar eqnResidual = 1, maxResidual = 0; + scalar convergenceCriterion = 0; + + simple.readIfPresent("convergence", convergenceCriterion); + diff --git a/applications/solvers/compressible/rhoSimpleFoam/pEqn.H b/applications/solvers/compressible/rhoSimpleFoam/pEqn.H index 87f82991efab27ed09108b586047497f87fc18ba..9f7e576919221f54f8286fa1bf0cad6ab7366c44 100644 --- a/applications/solvers/compressible/rhoSimpleFoam/pEqn.H +++ b/applications/solvers/compressible/rhoSimpleFoam/pEqn.H @@ -12,7 +12,16 @@ for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++) ); pEqn.setReference(pRefCell, pRefValue); - pEqn.solve(); + // retain the residual from the first iteration + if (nonOrth == 0) + { + eqnResidual = pEqn.solve().initialResidual(); + maxResidual = max(eqnResidual, maxResidual); + } + else + { + pEqn.solve(); + } if (nonOrth == nNonOrthCorr) { diff --git a/applications/solvers/compressible/rhoSimpleFoam/rhoSimpleFoam.C b/applications/solvers/compressible/rhoSimpleFoam/rhoSimpleFoam.C index b5b2aeb152c206980769de73809320f30ce6e144..edfe32990257558342f2fd34ec326ac365b09e0a 100644 --- a/applications/solvers/compressible/rhoSimpleFoam/rhoSimpleFoam.C +++ b/applications/solvers/compressible/rhoSimpleFoam/rhoSimpleFoam.C @@ -26,8 +26,7 @@ Application rhoSimpleFoam Description - Steady-state solver for turbulent flow of compressible fluids for - ventilation and heat-transfer. + Steady-state solver for turbulent flow of compressible fluids \*---------------------------------------------------------------------------*/ @@ -56,6 +55,7 @@ int main(int argc, char *argv[]) Info<< "Time = " << runTime.timeName() << nl << endl; # include "readSIMPLEControls.H" +# include "initConvergenceCheck.H" p.storePrevIter(); rho.storePrevIter(); @@ -74,6 +74,8 @@ int main(int argc, char *argv[]) Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" << " ClockTime = " << runTime.elapsedClockTime() << " s" << nl << endl; + +# include "convergenceCheck.H" } Info<< "End\n" << endl; diff --git a/applications/solvers/heatTransfer/buoyantSimpleFoam/UEqn.H b/applications/solvers/heatTransfer/buoyantSimpleFoam/UEqn.H index d58a70a54e4f3a533ee3f149a757ed68c0438f14..5bc4c4738ccc963dadfa1666a1886deb56cd5b5b 100644 --- a/applications/solvers/heatTransfer/buoyantSimpleFoam/UEqn.H +++ b/applications/solvers/heatTransfer/buoyantSimpleFoam/UEqn.H @@ -9,4 +9,10 @@ UEqn().relax(); - solve(UEqn() == -fvc::grad(pd) - fvc::grad(rho)*gh); + eqnResidual = solve + ( + UEqn() == -fvc::grad(pd) - fvc::grad(rho)*gh + ).initialResidual(); + + maxResidual = max(eqnResidual, maxResidual); + diff --git a/applications/solvers/heatTransfer/buoyantSimpleFoam/buoyantSimpleFoam.C b/applications/solvers/heatTransfer/buoyantSimpleFoam/buoyantSimpleFoam.C index 932deb1fed6013dee7da3d3ddcf4bea8a9347989..3beb759bd717a875dc0fe8b98221a636f1d8daeb 100644 --- a/applications/solvers/heatTransfer/buoyantSimpleFoam/buoyantSimpleFoam.C +++ b/applications/solvers/heatTransfer/buoyantSimpleFoam/buoyantSimpleFoam.C @@ -26,8 +26,7 @@ Application buoyantSimpleFoam Description - Steady-state solver for buoyant, turbulent flow of compressible fluids for - ventilation and heat-transfer. + Steady-state solver for buoyant, turbulent flow of compressible fluids \*---------------------------------------------------------------------------*/ @@ -57,6 +56,7 @@ int main(int argc, char *argv[]) Info<< "Time = " << runTime.timeName() << nl << endl; # include "readSIMPLEControls.H" +# include "initConvergenceCheck.H" pd.storePrevIter(); rho.storePrevIter(); @@ -64,9 +64,7 @@ int main(int argc, char *argv[]) // Pressure-velocity SIMPLE corrector { # include "UEqn.H" - # include "hEqn.H" - # include "pEqn.H" } @@ -77,6 +75,8 @@ int main(int argc, char *argv[]) Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" << " ClockTime = " << runTime.elapsedClockTime() << " s" << nl << endl; + +# include "convergenceCheck.H" } Info<< "End\n" << endl; diff --git a/applications/solvers/heatTransfer/buoyantSimpleFoam/convergenceCheck.H b/applications/solvers/heatTransfer/buoyantSimpleFoam/convergenceCheck.H new file mode 100644 index 0000000000000000000000000000000000000000..8958063193af348a058fd8f3baecb2547c00da3c --- /dev/null +++ b/applications/solvers/heatTransfer/buoyantSimpleFoam/convergenceCheck.H @@ -0,0 +1,9 @@ +// check convergence + +if (maxResidual < convergenceCriterion) +{ + Info<< "reached convergence criterion: " << convergenceCriterion << endl; + runTime.writeAndEnd(); + Info<< "latestTime = " << runTime.timeName() << endl; +} + diff --git a/applications/solvers/heatTransfer/buoyantSimpleFoam/hEqn.H b/applications/solvers/heatTransfer/buoyantSimpleFoam/hEqn.H index 5ff3394ac0ae9efa6878bc14da8839702b42a81e..dad078c2193a6797d2f08ed9751cdac4ca4ff157 100644 --- a/applications/solvers/heatTransfer/buoyantSimpleFoam/hEqn.H +++ b/applications/solvers/heatTransfer/buoyantSimpleFoam/hEqn.H @@ -11,7 +11,8 @@ hEqn.relax(); - hEqn.solve(); + eqnResidual = hEqn.solve().initialResidual(); + maxResidual = max(eqnResidual, maxResidual); thermo->correct(); } diff --git a/applications/solvers/heatTransfer/buoyantSimpleFoam/initConvergenceCheck.H b/applications/solvers/heatTransfer/buoyantSimpleFoam/initConvergenceCheck.H new file mode 100644 index 0000000000000000000000000000000000000000..b56197f22a50cfd07b04fc14d40b9a5454da8c5b --- /dev/null +++ b/applications/solvers/heatTransfer/buoyantSimpleFoam/initConvergenceCheck.H @@ -0,0 +1,7 @@ +// initialize values for convergence checks + + scalar eqnResidual = 1, maxResidual = 0; + scalar convergenceCriterion = 0; + + simple.readIfPresent("convergence", convergenceCriterion); + diff --git a/applications/solvers/heatTransfer/buoyantSimpleFoam/pEqn.H b/applications/solvers/heatTransfer/buoyantSimpleFoam/pEqn.H index 6f7aa582f078a471d7db384fd5d3729416277e6d..4c8d0939a8b53526a4ee07d4f91d6a5b3692a821 100644 --- a/applications/solvers/heatTransfer/buoyantSimpleFoam/pEqn.H +++ b/applications/solvers/heatTransfer/buoyantSimpleFoam/pEqn.H @@ -13,7 +13,16 @@ for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++) ); pdEqn.setReference(pdRefCell, pdRefValue); - pdEqn.solve(); + // retain the residual from the first iteration + if (nonOrth == 0) + { + eqnResidual = pdEqn.solve().initialResidual(); + maxResidual = max(eqnResidual, maxResidual); + } + else + { + pdEqn.solve(); + } if (nonOrth == nNonOrthCorr) { diff --git a/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/UEqn.H b/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/UEqn.H index d58a70a54e4f3a533ee3f149a757ed68c0438f14..5bc4c4738ccc963dadfa1666a1886deb56cd5b5b 100644 --- a/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/UEqn.H +++ b/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/UEqn.H @@ -9,4 +9,10 @@ UEqn().relax(); - solve(UEqn() == -fvc::grad(pd) - fvc::grad(rho)*gh); + eqnResidual = solve + ( + UEqn() == -fvc::grad(pd) - fvc::grad(rho)*gh + ).initialResidual(); + + maxResidual = max(eqnResidual, maxResidual); + diff --git a/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/buoyantSimpleRadiationFoam.C b/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/buoyantSimpleRadiationFoam.C index 034134eeb55773e5ff440cde7824068a6274db4a..4bb432d53ea832e69b95492f41fc2bef80b06ee5 100644 --- a/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/buoyantSimpleRadiationFoam.C +++ b/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/buoyantSimpleRadiationFoam.C @@ -58,6 +58,7 @@ int main(int argc, char *argv[]) Info<< "Time = " << runTime.timeName() << nl << endl; # include "readSIMPLEControls.H" +# include "initConvergenceCheck.H" pd.storePrevIter(); rho.storePrevIter(); @@ -65,9 +66,7 @@ int main(int argc, char *argv[]) // Pressure-velocity SIMPLE corrector { # include "UEqn.H" - # include "hEqn.H" - # include "pEqn.H" } @@ -78,6 +77,8 @@ int main(int argc, char *argv[]) Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" << " ClockTime = " << runTime.elapsedClockTime() << " s" << nl << endl; + +# include "convergenceCheck.H" } Info<< "End\n" << endl; diff --git a/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/convergenceCheck.H b/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/convergenceCheck.H new file mode 100644 index 0000000000000000000000000000000000000000..8958063193af348a058fd8f3baecb2547c00da3c --- /dev/null +++ b/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/convergenceCheck.H @@ -0,0 +1,9 @@ +// check convergence + +if (maxResidual < convergenceCriterion) +{ + Info<< "reached convergence criterion: " << convergenceCriterion << endl; + runTime.writeAndEnd(); + Info<< "latestTime = " << runTime.timeName() << endl; +} + diff --git a/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/hEqn.H b/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/hEqn.H index 88094369d4107068cf0fc9eeb788322a7f0158da..31462927b94bdd60bba71db3718e6d98a7e9defb 100644 --- a/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/hEqn.H +++ b/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/hEqn.H @@ -12,7 +12,8 @@ hEqn.relax(); - hEqn.solve(); + eqnResidual = hEqn.solve().initialResidual(); + maxResidual = max(eqnResidual, maxResidual); thermo->correct(); diff --git a/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/initConvergenceCheck.H b/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/initConvergenceCheck.H new file mode 100644 index 0000000000000000000000000000000000000000..b56197f22a50cfd07b04fc14d40b9a5454da8c5b --- /dev/null +++ b/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/initConvergenceCheck.H @@ -0,0 +1,7 @@ +// initialize values for convergence checks + + scalar eqnResidual = 1, maxResidual = 0; + scalar convergenceCriterion = 0; + + simple.readIfPresent("convergence", convergenceCriterion); + diff --git a/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/pEqn.H b/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/pEqn.H index 6f7aa582f078a471d7db384fd5d3729416277e6d..4c8d0939a8b53526a4ee07d4f91d6a5b3692a821 100644 --- a/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/pEqn.H +++ b/applications/solvers/heatTransfer/buoyantSimpleRadiationFoam/pEqn.H @@ -13,7 +13,16 @@ for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++) ); pdEqn.setReference(pdRefCell, pdRefValue); - pdEqn.solve(); + // retain the residual from the first iteration + if (nonOrth == 0) + { + eqnResidual = pdEqn.solve().initialResidual(); + maxResidual = max(eqnResidual, maxResidual); + } + else + { + pdEqn.solve(); + } if (nonOrth == nNonOrthCorr) { diff --git a/applications/solvers/incompressible/simpleFoam/UEqn.H b/applications/solvers/incompressible/simpleFoam/UEqn.H new file mode 100644 index 0000000000000000000000000000000000000000..9f9d9f6dd41457397ce54c3b69901d33b27a21c1 --- /dev/null +++ b/applications/solvers/incompressible/simpleFoam/UEqn.H @@ -0,0 +1,17 @@ + // Solve the Momentum equation + + tmp<fvVectorMatrix> UEqn + ( + fvm::div(phi, U) + + turbulence->divDevReff(U) + ); + + UEqn().relax(); + + eqnResidual = solve + ( + UEqn() == -fvc::grad(p) + ).initialResidual(); + + maxResidual = max(eqnResidual, maxResidual); + diff --git a/applications/solvers/incompressible/simpleFoam/convergenceCheck.H b/applications/solvers/incompressible/simpleFoam/convergenceCheck.H new file mode 100644 index 0000000000000000000000000000000000000000..8958063193af348a058fd8f3baecb2547c00da3c --- /dev/null +++ b/applications/solvers/incompressible/simpleFoam/convergenceCheck.H @@ -0,0 +1,9 @@ +// check convergence + +if (maxResidual < convergenceCriterion) +{ + Info<< "reached convergence criterion: " << convergenceCriterion << endl; + runTime.writeAndEnd(); + Info<< "latestTime = " << runTime.timeName() << endl; +} + diff --git a/applications/solvers/incompressible/simpleFoam/initConvergenceCheck.H b/applications/solvers/incompressible/simpleFoam/initConvergenceCheck.H new file mode 100644 index 0000000000000000000000000000000000000000..b56197f22a50cfd07b04fc14d40b9a5454da8c5b --- /dev/null +++ b/applications/solvers/incompressible/simpleFoam/initConvergenceCheck.H @@ -0,0 +1,7 @@ +// initialize values for convergence checks + + scalar eqnResidual = 1, maxResidual = 0; + scalar convergenceCriterion = 0; + + simple.readIfPresent("convergence", convergenceCriterion); + diff --git a/applications/solvers/incompressible/simpleFoam/pEqn.H b/applications/solvers/incompressible/simpleFoam/pEqn.H new file mode 100644 index 0000000000000000000000000000000000000000..dd9cae30a9c3a94d4be9c1bd3d5ab2df2d65f998 --- /dev/null +++ b/applications/solvers/incompressible/simpleFoam/pEqn.H @@ -0,0 +1,43 @@ + p.boundaryField().updateCoeffs(); + + volScalarField AU = UEqn().A(); + U = UEqn().H()/AU; + UEqn.clear(); + phi = fvc::interpolate(U) & mesh.Sf(); + adjustPhi(phi, U, p); + + // Non-orthogonal pressure corrector loop + for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++) + { + fvScalarMatrix pEqn + ( + fvm::laplacian(1.0/AU, p) == fvc::div(phi) + ); + + pEqn.setReference(pRefCell, pRefValue); + // retain the residual from the first iteration + if (nonOrth == 0) + { + eqnResidual = pEqn.solve().initialResidual(); + maxResidual = max(eqnResidual, maxResidual); + } + else + { + pEqn.solve(); + } + + if (nonOrth == nNonOrthCorr) + { + phi -= pEqn.flux(); + } + } + +# include "continuityErrs.H" + + // Explicitly relax pressure for momentum corrector + p.relax(); + + // Momentum corrector + U -= fvc::grad(p)/AU; + U.correctBoundaryConditions(); + diff --git a/applications/solvers/incompressible/simpleFoam/simpleFoam.C b/applications/solvers/incompressible/simpleFoam/simpleFoam.C index c604d95870610e1df5217879f0ba5f30fd2cc77b..7c378fe8ff714f44ddb56f898968fa607d986850 100644 --- a/applications/solvers/incompressible/simpleFoam/simpleFoam.C +++ b/applications/solvers/incompressible/simpleFoam/simpleFoam.C @@ -26,8 +26,7 @@ Application simpleFoam Description - Steady-state solver for incompressible, turbulent flow of non-Newtonian - fluids. + Steady-state solver for incompressible, turbulent flow \*---------------------------------------------------------------------------*/ @@ -41,14 +40,11 @@ int main(int argc, char *argv[]) { # include "setRootCase.H" - # include "createTime.H" # include "createMesh.H" # include "createFields.H" # include "initContinuityErrs.H" - //mesh.clearPrimitives(); - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Info<< "\nStarting time loop\n" << endl; @@ -58,55 +54,14 @@ int main(int argc, char *argv[]) Info<< "Time = " << runTime.timeName() << nl << endl; # include "readSIMPLEControls.H" +# include "initConvergenceCheck.H" p.storePrevIter(); // Pressure-velocity SIMPLE corrector { - // Momentum predictor - - tmp<fvVectorMatrix> UEqn - ( - fvm::div(phi, U) - + turbulence->divDevReff(U) - ); - - UEqn().relax(); - - solve(UEqn() == -fvc::grad(p)); - - p.boundaryField().updateCoeffs(); - volScalarField AU = UEqn().A(); - U = UEqn().H()/AU; - UEqn.clear(); - phi = fvc::interpolate(U) & mesh.Sf(); - adjustPhi(phi, U, p); - - // Non-orthogonal pressure corrector loop - for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++) - { - fvScalarMatrix pEqn - ( - fvm::laplacian(1.0/AU, p) == fvc::div(phi) - ); - - pEqn.setReference(pRefCell, pRefValue); - pEqn.solve(); - - if (nonOrth == nNonOrthCorr) - { - phi -= pEqn.flux(); - } - } - -# include "continuityErrs.H" - - // Explicitly relax pressure for momentum corrector - p.relax(); - - // Momentum corrector - U -= fvc::grad(p)/AU; - U.correctBoundaryConditions(); +# include "UEqn.H" +# include "pEqn.H" } turbulence->correct(); @@ -116,6 +71,8 @@ int main(int argc, char *argv[]) Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" << " ClockTime = " << runTime.elapsedClockTime() << " s" << nl << endl; + +# include "convergenceCheck.H" } Info<< "End\n" << endl; diff --git a/applications/utilities/mesh/conversion/foamToStarMesh/Make/files b/applications/utilities/mesh/conversion/foamToStarMesh/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..72c388a0b8cbce1e7541433983f3418c93c47d2c --- /dev/null +++ b/applications/utilities/mesh/conversion/foamToStarMesh/Make/files @@ -0,0 +1,3 @@ +foamToStarMesh.C + +EXE = $(FOAM_APPBIN)/foamToStarMesh diff --git a/applications/utilities/mesh/conversion/foamToStarMesh/Make/options b/applications/utilities/mesh/conversion/foamToStarMesh/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..15672901703919f27df1928dd6c4aa1b7d5f879b --- /dev/null +++ b/applications/utilities/mesh/conversion/foamToStarMesh/Make/options @@ -0,0 +1,6 @@ +EXE_INC = \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/conversion/lnInclude + +EXE_LIBS = \ + -lconversion diff --git a/applications/utilities/mesh/conversion/foamToStarMesh/foamToStarMesh.C b/applications/utilities/mesh/conversion/foamToStarMesh/foamToStarMesh.C new file mode 100644 index 0000000000000000000000000000000000000000..fc970cd7486551dafbf08cf1d6fa760ea1565911 --- /dev/null +++ b/applications/utilities/mesh/conversion/foamToStarMesh/foamToStarMesh.C @@ -0,0 +1,171 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Application + foamToStarMesh + +Description + Reads an OpenFOAM mesh and writes a pro-STAR (v4) bnd/cel/vrt format. + +Usage + - foamToStarMesh [OPTION] \n + Reads an OpenFOAM mesh and writes a pro-STAR (v4) bnd/cel/vrt format. + + @param -noBnd \n + Suppress writing the @c .bnd file + + @param -scale \<factor\>\n + Specify an alternative geometry scaling factor. + The default is @b 1000 (scale @em [m] to @em [mm]). + + @param -surface \n + Extract the surface of the volume mesh only. + This can be useful, for example, for surface morphing in an external + package. + + @param -tri \n + Extract a triangulated surface. + The @b -surface options is implicitly selected. + + +Note + The cellTable information available in the files + @c constant/cellTable and @c constant/polyMesh/cellTableId + will be used if available. Otherwise the cellZones are used when + creating the cellTable information. + +See Also + Foam::cellTable, Foam::meshWriter and Foam::meshWriters::STARCD + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "Time.H" +#include "polyMesh.H" +#include "STARCDMeshWriter.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + argList::noParallel(); + argList::validOptions.insert("scale", "scale"); + argList::validOptions.insert("noBnd", ""); + argList::validOptions.insert("tri", ""); + argList::validOptions.insert("surface", ""); + +# include "addTimeOptions.H" +# include "setRootCase.H" +# include "createTime.H" + // Get times list + instantList Times = runTime.times(); + + // set startTime and endTime depending on -time and -latestTime options +# include "checkTimeOptions.H" + runTime.setTime(Times[startTime], startTime); + + bool surfaceOnly = false; + if (args.options().found("surface") or args.options().found("tri")) + { + surfaceOnly = true; + } + + fileName exportName = meshWriter::defaultMeshName; + if (surfaceOnly) + { + exportName = meshWriter::defaultSurfaceName; + } + + if (args.options().found("case")) + { + exportName += '-' + args.globalCaseName(); + } + + // default: rescale from [m] to [mm] + scalar scaleFactor = 1000; + if (args.options().found("scale")) + { + scaleFactor = readScalar(IStringStream(args.options()["scale"])()); + if (scaleFactor <= 0) + { + scaleFactor = 1; + } + } + +# include "createPolyMesh.H" + + // bool firstCheck = true; + + for (label timeI = startTime; timeI < endTime; ++timeI) + { + runTime.setTime(Times[timeI], timeI); + +# include "getTimeIndex.H" + + polyMesh::readUpdateState state = mesh.readUpdate(); + + if (timeI == startTime || state != polyMesh::UNCHANGED) + { + meshWriters::STARCD writer(mesh, scaleFactor); + + if (args.options().found("noBnd")) + { + writer.noBoundary(); + } + + fileName meshName(exportName); + if (state != polyMesh::UNCHANGED) + { + meshName += '_' + runTime.timeName(); + } + + if (surfaceOnly) + { + if (args.options().found("tri")) + { + writer.writeSurface(meshName, true); + } + else + { + writer.writeSurface(meshName); + } + } + else + { + writer.write(meshName); + } + } + + Info<< nl << endl; + } + + Info<< "End\n" << endl; + + return 0; +} + +// ************************************************************************* // diff --git a/applications/utilities/mesh/conversion/foamToStarMesh/getTimeIndex.H b/applications/utilities/mesh/conversion/foamToStarMesh/getTimeIndex.H new file mode 100644 index 0000000000000000000000000000000000000000..85a92405dda760fbbfc5931102afe41aa602b2e6 --- /dev/null +++ b/applications/utilities/mesh/conversion/foamToStarMesh/getTimeIndex.H @@ -0,0 +1,51 @@ +// Read time index from */uniform/time, but treat 0 and constant specially + + word timeName = "0"; + + if + ( + runTime.timeName() != "constant" + && runTime.timeName() != "0" + ) + { + IOobject io + ( + "time", + runTime.timeName(), + "uniform", + runTime, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE, + false + ); + + if (io.headerOk()) + { + IOdictionary timeObject + ( + IOobject + ( + "time", + runTime.timeName(), + "uniform", + runTime, + IOobject::MUST_READ, + IOobject::NO_WRITE, + false + ) + ); + + label index; + timeObject.lookup("index") >> index; + timeName = Foam::name(index); + } + else + { + timeName = runTime.timeName(); + // Info<< "skip ... missing entry " << io.objectPath() << endl; + // continue; + } + } + + Info<< "\nTime [" << timeName << "] = " << runTime.timeName() << nl; + diff --git a/applications/utilities/mesh/conversion/star4ToFoam/Make/files b/applications/utilities/mesh/conversion/star4ToFoam/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..19355fafdd91ea78bcac3331e81d5ebb0859ace8 --- /dev/null +++ b/applications/utilities/mesh/conversion/star4ToFoam/Make/files @@ -0,0 +1,3 @@ +star4ToFoam.C + +EXE = $(FOAM_APPBIN)/star4ToFoam diff --git a/applications/utilities/mesh/conversion/star4ToFoam/Make/options b/applications/utilities/mesh/conversion/star4ToFoam/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..15672901703919f27df1928dd6c4aa1b7d5f879b --- /dev/null +++ b/applications/utilities/mesh/conversion/star4ToFoam/Make/options @@ -0,0 +1,6 @@ +EXE_INC = \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/conversion/lnInclude + +EXE_LIBS = \ + -lconversion diff --git a/applications/utilities/mesh/conversion/star4ToFoam/star4ToFoam.C b/applications/utilities/mesh/conversion/star4ToFoam/star4ToFoam.C new file mode 100644 index 0000000000000000000000000000000000000000..a92e70913f78595c7e57bad6b9ebc45969ad8020 --- /dev/null +++ b/applications/utilities/mesh/conversion/star4ToFoam/star4ToFoam.C @@ -0,0 +1,113 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Application + star4ToFoam + +Description + Converts a Star-CD (v4) pro-STAR mesh into OpenFOAM format. + +Usage + - star4ToFoam [OPTION] ccmMesh\n + convert pro-STAR mesh to OpenFOAM + + @param -ascii \n + Write in ASCII format instead of binary + + @param -scale \<factor\>\n + Specify an alternative geometry scaling factor. + The default is @b 0.001 (scale @em [mm] to @em [m]). + + @param -solids \n + Treat any solid cells present just like fluid cells. + The default is to discard them. + +Note + - baffles are written as interfaces for later use + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "Time.H" +#include "STARCDMeshReader.H" +#include "OFstream.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + argList::noParallel(); + argList::validArgs.append("pro-STAR prefix"); + argList::validOptions.insert("ascii", ""); + argList::validOptions.insert("scale", "scale"); + argList::validOptions.insert("solids", ""); + + argList args(argc, argv); + Time runTime(args.rootPath(), args.caseName()); + stringList const& params = args.additionalArgs(); + + // default rescale from [mm] to [m] + scalar scaleFactor = 0.001; + if (args.options().found("scale")) + { + scaleFactor = readScalar(IStringStream(args.options()["scale"])()); + if (scaleFactor <= 0) + { + scaleFactor = 1; + } + } + + if (args.options().found("solids")) + { + meshReaders::STARCD::keepSolids = true; + } + + // default to binary output, unless otherwise specified + IOstream::streamFormat format = IOstream::BINARY; + if (args.options().found("ascii")) + { + format = IOstream::ASCII; + } + + // increase the precision of the points data + IOstream::defaultPrecision(10); + + // remove extensions and/or trailing '.' + fileName prefix = fileName(params[0]).lessExt(); + + meshReaders::STARCD reader(prefix, runTime, scaleFactor); + + autoPtr<polyMesh> mesh = reader.mesh(runTime); + reader.writeMesh(mesh, format); + + + Info<< "\nEnd\n" << endl; + + return 0; +} + +// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options index 0652ffc64694c7223ea4b2c990aa047362987804..823dae1ba76b6aafff9d4d7275878f6526e92f08 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options @@ -5,5 +5,5 @@ EXE_INC = \ EXE_LIBS = \ -lfiniteVolume \ - -llagrangian \ - + -llagrangian + diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C index 3fa1495a909862cb4c26f90d0d1ff9ee331d5f26..7dac6294e6d6614337583d1f24021738424f151f 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C @@ -24,6 +24,15 @@ License Description Translates FOAM data to EnSight format + +Usage + - foamToEnsight [OPTION] \n + Translates OpenFOAM data to Ensight format + + @param -ascii \n + Write Ensight data in ASCII format instead of "C Binary" + +Note Parallel support for cloud data is not supported \*---------------------------------------------------------------------------*/ @@ -74,16 +83,16 @@ bool inFileNameList int main(int argc, char *argv[]) { argList::validOptions.insert("patches", "patch list"); - argList::validOptions.insert("binary", "" ); + argList::validOptions.insert("ascii", "" ); # include "addTimeOptions.H" # include "setRootCase.H" // Check options - bool binary = false; - if (args.options().found("binary")) + bool binary = true; + if (args.options().found("ascii")) { - binary = true; + binary = false; } # include "createTime.H" diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/files b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..739c971551520b88f08aac2001229792eb1031c5 --- /dev/null +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/files @@ -0,0 +1,3 @@ +foamToEnsightParts.C + +EXE = $(FOAM_APPBIN)/foamToEnsightParts diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/options b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..518c2a009922089cdff4de6dc662f0bb67321ce2 --- /dev/null +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/options @@ -0,0 +1,9 @@ +EXE_INC = \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/lagrangian/basic/lnInclude \ + -I$(LIB_SRC)/conversion/lnInclude + +EXE_LIBS = \ + -lfiniteVolume \ + -llagrangian \ + -lconversion diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkHasLagrangian.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkHasLagrangian.H new file mode 100644 index 0000000000000000000000000000000000000000..18f9ddf805919f9d7c1cecae9fc5daa511098aaf --- /dev/null +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkHasLagrangian.H @@ -0,0 +1,19 @@ +// check for lagrangian/positions information in the final directory + +bool hasLagrangian = false; +if (timeDirs.size() > 1) +{ + IOobject io + ( + "positions", + timeDirs[timeDirs.size() - 1].name(), + "lagrangian", + mesh, + IOobject::NO_READ + ); + + if (io.headerOk()) + { + hasLagrangian = true; + } +} diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkHasMovingMesh.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkHasMovingMesh.H new file mode 100644 index 0000000000000000000000000000000000000000..a9367daf8eb9870b055ecb1f5a2025eb39d3cee5 --- /dev/null +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkHasMovingMesh.H @@ -0,0 +1,20 @@ +// check for "points" in all of the result directories + +bool hasMovingMesh = false; +if (timeDirs.size() > 1) +{ + hasMovingMesh = true; + for (label i=0; i < timeDirs.size() && hasMovingMesh; ++i) + { + IOobject io + ( + "points", + timeDirs[i].name(), + polyMesh::meshSubDir, + mesh, + IOobject::NO_READ + ); + + hasMovingMesh = io.headerOk(); + } +} diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkHasSprayField.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkHasSprayField.H new file mode 100644 index 0000000000000000000000000000000000000000..e6601f71911eb1abdc58d80933832c5a40e45429 --- /dev/null +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkHasSprayField.H @@ -0,0 +1,15 @@ +// check that the spray variable is present for this time +// +bool hasSprayField = true; +{ + IOobject ioHeader + ( + fieldName, + mesh.time().timeName(), + "lagrangian", + mesh, + IOobject::NO_READ + ); + + hasSprayField = ioHeader.headerOk(); +} diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkHasValidField.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkHasValidField.H new file mode 100644 index 0000000000000000000000000000000000000000..9973a7a5fbb682531938b5e719487ae025761325 --- /dev/null +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkHasValidField.H @@ -0,0 +1,23 @@ +// check that the variable is present for all times +// +bool hasValidField = true; +{ + for (label i=0; i < timeDirs.size() && hasValidField; ++i) + { + if (fieldName.size() > 2 && fieldName(fieldName.size() - 2, 2) == "_0") + { + hasValidField = false; + break; + } + + IOobject ioHeader + ( + fieldName, + timeDirs[i].name(), + mesh, + IOobject::NO_READ + ); + + hasValidField = ioHeader.headerOk(); + } +} diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/ensightCaseTimes.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/ensightCaseTimes.H new file mode 100644 index 0000000000000000000000000000000000000000..ab7f4de5312a1cd8b7ec15e765637e17cbb16498 --- /dev/null +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/ensightCaseTimes.H @@ -0,0 +1,91 @@ +// write time values to case file +{ + scalar timeCorrection = 0; + if (timeDirs[0].value() < 0) + { + timeCorrection = - timeDirs[0].value(); + Info<< "Correcting time values. Adding " << timeCorrection << endl; + } + + caseFile.setf(ios_base::scientific, ios_base::floatfield); + caseFile.precision(5); + + // time set 1 - geometry and volume fields + if (fieldFileNumbers.size()) + { + caseFile + << "time set: " << 1 << nl + << "number of steps: " << fieldFileNumbers.size() << nl + << "filename numbers:" << nl; + + label count = 0; + forAll (fieldFileNumbers, i) + { + caseFile + << " " << setw(12) << fieldFileNumbers[i]; + + if (++count % 6 == 0) + { + caseFile << nl; + } + } + + caseFile + << nl << "time values:" << nl; + + count = 0; + forAll (fieldFileNumbers, i) + { + caseFile + << " " << setw(12) + << timeIndices[fieldFileNumbers[i]] + timeCorrection; + + if (++count % 6 == 0) + { + caseFile << nl; + } + } + caseFile << nl << nl; + } + + // time set 2 - lagrangian fields + if (hasLagrangian && sprayFileNumbers.size()) + { + caseFile + << "time set: " << 2 << nl + << "number of steps: " << sprayFileNumbers.size() << nl + << "filename numbers:" << nl; + + label count = 0; + forAll (sprayFileNumbers, i) + { + caseFile + << " " << setw(12) << sprayFileNumbers[i]; + + if (++count % 6 == 0) + { + caseFile << nl; + } + } + + caseFile + << nl << "time values:" << nl; + + count = 0; + forAll (sprayFileNumbers, i) + { + caseFile + << " " << setw(12) + << timeIndices[sprayFileNumbers[i]] + timeCorrection; + + if (++count % 6 == 0) + { + caseFile << nl; + } + } + caseFile << nl << nl; + } + + + caseFile << "# end" << nl; +} diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/ensightOutputFunctions.C b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/ensightOutputFunctions.C new file mode 100644 index 0000000000000000000000000000000000000000..a1b459c4a18b7c5d5840d0d7fbfbcffed56c278f --- /dev/null +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/ensightOutputFunctions.C @@ -0,0 +1,233 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + $Date: 2008/04/02 11:37:10 $ +\*---------------------------------------------------------------------------*/ + +#include "ensightOutputFunctions.H" + +#include "passiveParticle.H" +#include "Cloud.H" +#include "IOField.H" +#include "volFields.H" +#include "surfaceFields.H" + +#include "OFstream.H" +#include "IOmanip.H" + +namespace Foam +{ + +// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // + +template<class Type> +void ensightCaseEntry +( + OFstream& caseFile, + const IOobject& fieldObject, + const fileName& dataMask, + bool measured +) +{ + caseFile.setf(ios_base::left); + + if (measured) + { + caseFile + << pTraits<Type>::typeName + << " per measured node: 2 " + << setw(15) + << ("s" + fieldObject.name()).c_str() + << " " + << (dataMask/"lagrangian"/fieldObject.name()).c_str() + << nl; + } + else + { + caseFile + << pTraits<Type>::typeName + << " per element: " + << setw(15) << fieldObject.name() + << " " + << (dataMask/fieldObject.name()).c_str() + << nl; + } +} + + +void ensightParticlePositions +( + const polyMesh& mesh, + const fileName& dataDir, + const fileName& subDir, + IOstream::streamFormat format +) +{ + Cloud<passiveParticle> parcels(mesh); + + fileName lagrangianDir = subDir/"lagrangian"; + fileName postFileName = lagrangianDir/"positions"; + + // the ITER/lagrangian subdirectory must exist + mkDir(dataDir/lagrangianDir); + ensightFile os(dataDir/postFileName, format); + + // tag binary format (just like geometry files) + os.writeBinaryHeader(); + os.write(postFileName); + os.newline(); + os.write("particle coordinates"); + os.newline(); + os.write(parcels.size(), 8); // unusual width + os.newline(); + + // binary write is Ensight6 - first ids, then positions + if (format == IOstream::BINARY) + { + forAll (parcels, i) + { + os.write(i+1); + } + + forAllIter(Cloud<passiveParticle>, parcels, elmnt) + { + const vector& p = elmnt().position(); + + os.write(p.x()); + os.write(p.y()); + os.write(p.z()); + } + } + else + { + label nParcels = 0; + + forAllIter(Cloud<passiveParticle>, parcels, elmnt) + { + const vector& p = elmnt().position(); + + os.write(++nParcels, 8); // unusual width + os.write(p.x()); + os.write(p.y()); + os.write(p.z()); + os.newline(); + } + } +} + + + +template<class Type> +void ensightSprayField +( + const IOobject& fieldObject, + const fileName& dataDir, + const fileName& subDir, + IOstream::streamFormat format +) +{ + Info<< " " << fieldObject.name() << flush; + + fileName lagrangianDir = subDir/"lagrangian"; + fileName postFileName = lagrangianDir/fieldObject.name(); + + string title = postFileName + " with " + pTraits<Type>::typeName + " values"; + + ensightFile os(dataDir/postFileName, format); + os.write(title); + os.newline(); + + IOField<Type> field(fieldObject); + + // 6 values per line + label count = 0; + + forAll(field, i) + { + Type val = field[i]; + + if (mag(val) < 1.0e-90) + { + val = pTraits<Type>::zero; + } + + for (direction cmpt=0; cmpt < pTraits<Type>::nComponents; cmpt++) + { + os.write( component(val, cmpt) ); + } + + count += pTraits<Type>::nComponents; + + if (count % 6 == 0) + { + os.newline(); + } + } + + // add final newline if required + if (count % 6) + { + os.newline(); + } +} + + +//- write generalized field components +template <class Type> +void ensightVolField +( + const ensightParts& partsList, + const IOobject& fieldObject, + const fvMesh& mesh, + const fileName& dataDir, + const fileName& subDir, + IOstream::streamFormat format +) +{ + Info<< " " << fieldObject.name() << flush; + + fileName postFileName = subDir/fieldObject.name(); + + ensightFile os(dataDir/postFileName, format); + os.write(postFileName); + os.newline(); + + // ie, volField<Type> + partsList.writeField + ( + os, + GeometricField<Type, fvPatchField, volMesh> + ( + fieldObject, + mesh + ) + ); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // end namespace Foam + +// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/ensightOutputFunctions.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/ensightOutputFunctions.H new file mode 100644 index 0000000000000000000000000000000000000000..e2f5ef2860102d50ef6dbe39ccbad8951a2d0f3c --- /dev/null +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/ensightOutputFunctions.H @@ -0,0 +1,100 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Description + + miscellaneous collection of functions and template related + to Ensight data + +SourceFiles + ensightOutputFunctions.C + +\*---------------------------------------------------------------------------*/ + +#ifndef ensightOutputFunctions_H +#define ensightOutputFunctions_H + +#include "ensightFile.H" +#include "polyMesh.H" +#include "IOobject.H" + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template<class Type> +void ensightCaseEntry +( + OFstream& caseFile, + const IOobject& fieldObject, + const fileName& dataMask, + bool measured = false +); + + +void ensightParticlePositions +( + const polyMesh& mesh, + const fileName& dataDir, + const fileName& subDir, + IOstream::streamFormat format +); + + +//- write spray parcels +template<class Type> +void ensightSprayField +( + const IOobject& fieldObject, + const fileName& dataDir, + const fileName& subDir, + IOstream::streamFormat format +); + +//- write generalized field components +template<class Type> +void ensightVolField +( + const ensightParts& partsList, + const IOobject& fieldObject, + const fvMesh& mesh, + const fileName& dataDir, + const fileName& subDir, + IOstream::streamFormat format +); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // end namespace Foam + +#ifdef NoRepository +# include "ensightOutputFunctions.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/foamToEnsightParts.C b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/foamToEnsightParts.C new file mode 100644 index 0000000000000000000000000000000000000000..65588d7dc87e54e3489d9a207e1829dbac1d54dc --- /dev/null +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/foamToEnsightParts.C @@ -0,0 +1,499 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Application + foamToEnsightParts + +Description + Translates OpenFOAM data to Ensight format. + An Ensight part is created for each cellZone and patch. + +Usage + - foamToEnsightParts [OPTION] \n + Translates OpenFOAM data to Ensight format + + @param -ascii \n + Write Ensight data in ASCII format instead of "C Binary" + + @param -zeroTime \n + Include the often incomplete initial conditions. + +Note + - no parallel data. + - writes to @a Ensight directory to avoid collisions with foamToEnsight. + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "timeSelector.H" + +#include "volFields.H" +#include "OFstream.H" +#include "IOmanip.H" +#include "IOobjectList.H" +#include "scalarIOField.H" +#include "tensorIOField.H" + +#include "ensightParts.H" +#include "ensightOutputFunctions.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Main program: + +int main(int argc, char *argv[]) +{ + // with -constant and -zeroTime + timeSelector::addOptions(true, false); + argList::noParallel(); + argList::validOptions.insert("ascii", ""); + + const label nTypes = 2; + const word fieldTypes[] = + { + volScalarField::typeName, + volVectorField::typeName + }; + + const label nSprayFieldTypes = 2; + const word sprayFieldTypes[] = + { + scalarIOField::typeName, + vectorIOField::typeName + }; + +# include "setRootCase.H" +# include "createTime.H" + + // get times list + instantList timeDirs = timeSelector::select0(runTime, args); + + // default to binary output, unless otherwise specified + IOstream::streamFormat format = IOstream::BINARY; + if (args.options().found("ascii")) + { + format = IOstream::ASCII; + } + + fileName ensightDir = args.rootPath()/args.globalCaseName()/"Ensight"; + fileName dataDir = ensightDir/"data"; + fileName caseFileName = "Ensight.case"; + fileName dataMask = fileName("data")/ensightFile::mask(); + + // Ensight and Ensight/data directories must exist + if (dir(ensightDir)) + { + rmDir(ensightDir); + } + mkDir(ensightDir); + mkDir(dataDir); + +# include "createMesh.H" + // Construct the list of ensight parts for the entire mesh + ensightParts partsList(mesh); + + // write summary information + { + OFstream partsInfoFile(ensightDir/"partsInfo"); + + partsInfoFile + << "// summary of ensight parts" << nl << nl; + partsList.writeSummary(partsInfoFile); + } + +# include "checkHasMovingMesh.H" +# include "checkHasLagrangian.H" + + // only take the objects that exists at the end of the calculation + IOobjectList objects(mesh, timeDirs[timeDirs.size()-1].name()); + IOobjectList sprayObjects(mesh, timeDirs[timeDirs.size()-1].name(), "lagrangian"); + + // write single geometry or one per time step + fileName geometryFileName("geometry"); + if (hasMovingMesh) + { + geometryFileName = dataMask/geometryFileName; + } + + // the case file is always ASCII + Info << "write case: " << caseFileName.c_str() << endl; + + OFstream caseFile(ensightDir/caseFileName, IOstream::ASCII); + caseFile.setf(ios_base::left); + caseFile + << "FORMAT" << nl + << setw(16) << "type:" << "ensight gold" << nl << nl + << "GEOMETRY" << nl + << setw(16) << "model: 1" << geometryFileName.c_str() << nl; + + if (hasLagrangian) + { + caseFile + << setw(16) << "measured: 2" + << fileName(dataMask/"lagrangian"/"positions").c_str() << nl; + } + caseFile + << nl << "VARIABLE" << nl; + + label nFieldTime = timeDirs.size(); + if (nFieldTime < 0) + { + nFieldTime = 0; + } + + List<label> fieldFileNumbers(nFieldTime); + List<label> sprayFileNumbers(nFieldTime); + + // map used times used + Map<scalar> timeIndices; + + nFieldTime = 0; + label nSprayTime = 0; + + forAll(timeDirs, timeI) + { + runTime.setTime(timeDirs[timeI], timeI); + +# include "getTimeIndex.H" + + fieldFileNumbers[nFieldTime++] = timeIndex; + + // the data/ITER subdirectory must exist + fileName subDir = ensightFile::subDir(timeIndex); + mkDir(dataDir/subDir); + + // place a timestamp in the directory for future reference + { + OFstream timeStamp(dataDir/subDir/"time"); + timeStamp + << "# timestep time" << nl + << subDir.c_str() << " " << runTime.timeName() << nl; + } + +# include "moveMesh.H" + + if (nFieldTime == 1 || mesh.moving()) + { + if (hasMovingMesh) + { + geometryFileName = dataDir/subDir/"geometry"; + } + if (mesh.moving()) + { + partsList.recalculate(mesh); + } + + ensightGeoFile geoFile(ensightDir/geometryFileName, format); + partsList.writeGeometry(geoFile); + Info << nl; + } + + Info<< "write volume field: " << flush; + + for (label i=0; i < nTypes; i++) + { + wordList fieldNames = objects.names(fieldTypes[i]); + + forAll (fieldNames, fieldI) + { + word fieldName = fieldNames[fieldI]; + +# include "checkHasValidField.H" + + if (!hasValidField) + { + continue; + } + + IOobject fieldObject + ( + fieldName, + mesh.time().timeName(), + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ); + + if (fieldTypes[i] == volScalarField::typeName) + { + if (nFieldTime == 1) + { + ensightCaseEntry<scalar> + ( + caseFile, + fieldObject, + dataMask + ); + } + + ensightVolField<scalar> + ( + partsList, + fieldObject, + mesh, + dataDir, + subDir, + format + ); + + } + else if (fieldTypes[i] == volVectorField::typeName) + { + if (nFieldTime == 1) + { + ensightCaseEntry<vector> + ( + caseFile, + fieldObject, + dataMask + ); + } + + ensightVolField<vector> + ( + partsList, + fieldObject, + mesh, + dataDir, + subDir, + format + ); + + } + else if (fieldTypes[i] == volSphericalTensorField::typeName) + { + if (nFieldTime == 1) + { + ensightCaseEntry<sphericalTensor> + ( + caseFile, + fieldObject, + dataMask + ); + } + + ensightVolField<sphericalTensor> + ( + partsList, + fieldObject, + mesh, + dataDir, + subDir, + format + ); + + } + else if (fieldTypes[i] == volSymmTensorField::typeName) + { + if (nFieldTime == 1) + { + ensightCaseEntry<symmTensor> + ( + caseFile, + fieldObject, + dataMask + ); + } + + ensightVolField<symmTensor> + ( + partsList, + fieldObject, + mesh, + dataDir, + subDir, + format + ); + + } + else if (fieldTypes[i] == volTensorField::typeName) + { + if (nFieldTime == 1) + { + ensightCaseEntry<tensor> + ( + caseFile, + fieldObject, + dataMask + ); + } + + ensightVolField<tensor> + ( + partsList, + fieldObject, + mesh, + dataDir, + subDir, + format + ); + + } + } + } + Info<< endl; + + + if (hasLagrangian) + { + // check that the positions field is present for this time + { + IOobject ioHeader + ( + "positions", + mesh.time().timeName(), + "lagrangian", + mesh, + IOobject::NO_READ + ); + + if (ioHeader.headerOk()) + { + sprayFileNumbers[nSprayTime++] = timeIndex; + } + } + + Info<< "write spray field: " << flush; + + ensightParticlePositions + ( + mesh, + dataDir, + subDir, + format + ); + + for (label i=0; i < nSprayFieldTypes; i++) + { + wordList fieldNames = sprayObjects.names(sprayFieldTypes[i]); + + forAll (fieldNames, fieldI) + { + word fieldName = fieldNames[fieldI]; + +# include "checkHasSprayField.H" + + if (!hasSprayField) + { + continue; + } + + IOobject fieldObject + ( + fieldName, + mesh.time().timeName(), + "lagrangian", + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ); + + if (sprayFieldTypes[i] == scalarIOField::typeName) + { + if (nSprayTime == 1) + { + ensightCaseEntry<scalar> + ( + caseFile, + fieldObject, + dataMask, + true + ); + } + + ensightSprayField<scalar> + ( + fieldObject, + dataDir, + subDir, + format + ); + + } + else if (sprayFieldTypes[i] == vectorIOField::typeName) + { + if (nSprayTime == 1) + { + ensightCaseEntry<vector> + ( + caseFile, + fieldObject, + dataMask, + true + ); + } + + ensightSprayField<vector> + ( + fieldObject, + dataDir, + subDir, + format + ); + + } + else if (sprayFieldTypes[i] == tensorIOField::typeName) + { + if (nSprayTime == 1) + { + ensightCaseEntry<tensor> + ( + caseFile, + fieldObject, + dataMask, + true + ); + } + + ensightSprayField<tensor> + ( + fieldObject, + dataDir, + subDir, + format + ); + + } + } + } + Info<< endl; + } + } + + fieldFileNumbers.setSize(nFieldTime); + sprayFileNumbers.setSize(nSprayTime); + + // add time values + caseFile << nl << "TIME" << nl; +# include "ensightCaseTimes.H" + + Info<< "\nEnd\n"<< endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/getTimeIndex.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/getTimeIndex.H new file mode 100644 index 0000000000000000000000000000000000000000..297131d1a01c1d2011cd9a6cbb2946e157b7f563 --- /dev/null +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/getTimeIndex.H @@ -0,0 +1,50 @@ +// Read time index from */uniform/time, +// but treat 0 and constant specially + + label timeIndex = 0; + + if + ( + runTime.timeName() != "constant" + && runTime.timeName() != "0" + ) + { + IOobject io + ( + "time", + runTime.timeName(), + "uniform", + runTime, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE, + false + ); + + if (io.headerOk()) + { + IOdictionary timeObject + ( + IOobject + ( + "time", + runTime.timeName(), + "uniform", + runTime, + IOobject::MUST_READ, + IOobject::NO_WRITE, + false + ) + ); + + timeObject.lookup("index") >> timeIndex; + } + else + { + Info<< "skip ... missing entry " << io.objectPath() << endl; + continue; + } + } + + timeIndices.insert(timeIndex, timeDirs[timeI].value()); + Info<< "\nTime [" << timeIndex << "] = " << runTime.timeName() << nl; + diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/moveMesh.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/moveMesh.H new file mode 100644 index 0000000000000000000000000000000000000000..f2ca3a1a658309e723029e759bd186ee2af36331 --- /dev/null +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/moveMesh.H @@ -0,0 +1,28 @@ +{ + IOobject ioPoints + ( + "points", + runTime.timeName(), + polyMesh::meshSubDir, + mesh + ); + + if (ioPoints.headerOk()) + { + // Reading new points + pointIOField newPoints + ( + IOobject + ( + "points", + mesh.time().timeName(), + polyMesh::meshSubDir, + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ); + + mesh.movePoints(newPoints); + } +} diff --git a/bin/foamCheckSourceDeps b/bin/foamCheckSourceDeps new file mode 100755 index 0000000000000000000000000000000000000000..5653f050d162fe41f2ffab142176f7f57501df12 --- /dev/null +++ b/bin/foamCheckSourceDeps @@ -0,0 +1,70 @@ +#!/bin/sh +#------------------------------------------------------------------------------ +# ========= | +# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox +# \\ / O peration | +# \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. +# \\/ M anipulation | +#------------------------------------------------------------------------------- +# License +# This file is part of OpenFOAM. +# +# OpenFOAM is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# OpenFOAM is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License +# along with OpenFOAM; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# Script +# foamCheckSourceDeps +# +# Description +# Usage: foamCheckSourceDeps [dir1 .. dirN] +# +# Search for *.dep files that are without a corresponding .C or .L file. +# These could indicate a directory that has been moved. +# - print questionable directory and dep file +#------------------------------------------------------------------------------ +if [ "$1" = "-h" -o "$1" = "-help" ] +then + cat <<USAGE 1>&2 +Usage: ${0##*/} [dir1 .. dirN] + + Search for .dep files that are without a corresponding .C or .L file. + This could indicate a directory that has been moved. + - print questionable directory and file +USAGE + exit 1 +fi + +if [ "$#" -eq 0 ] +then + set -- . +fi + +for checkDir +do + if [ -d $checkDir ] + then + find $checkDir -name '*.dep' -print | while read depFile; + do + Cfile=$(echo $depFile | sed -e 's/\.dep$/.C/') + # also check flex files + Lfile=$(echo $depFile | sed -e 's/\.C$/.L/') + if [ ! -f $Cfile -a ! -f $Lfile ] + then + echo "$(dirname $Cfile) ${depFile##*/}" + fi + done + fi +done + +# ----------------------------------------------------------------------------- diff --git a/bin/foamSystemCheck b/bin/foamSystemCheck index 27b7242d797e31fa0ec4cc33ca2288ea01020d98..5b8d33574a74d31c7bc75c6dd1ba84f633bac397 100755 --- a/bin/foamSystemCheck +++ b/bin/foamSystemCheck @@ -1,4 +1,4 @@ -#!/bin/sh -u +#!/bin/sh #------------------------------------------------------------------------------ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox @@ -28,37 +28,35 @@ # # Description # Checks the machine system and the user's -# personal configuration for running FOAM. +# personal configuration for running OpenFOAM. # #------------------------------------------------------------------------------ -TMPTAB=tmptab.$$ -LOG=log.$0 -HLINE="-----------------------------------------------------------------------" +# STATIC VARIABLES +# ~~~~~~~~~~~~~~~~ +FOAM_VERSION=1.5 -FATALERROR=0 -SSHRSHOK=0 -WIDTH=20 -FOAM_VERSION=1.4.1 -OS=`uname -s` +HLINE="-----------------------------------------------------------------------" +WIDTH=16 +unset FATALERROR -#FUNCTIONS -#~~~~~~~~~ +# FUNCTIONS +# ~~~~~~~~~ heading () { - echo "" echo "" echo "$1" echo "$HLINE" } lenBase () { -echo $1 | tr -d " " | wc -m | tr -d " " + echo $1 | tr -d " " | wc -m | tr -d " " } length () { - NOCHAR=`lenBase $1` - NOCHAR=`expr $NOCHAR - 1` - if [ $NOCHAR -eq -1 ]; then + NOCHAR=$(lenBase $1) + NOCHAR=$(expr $NOCHAR - 1) + if [ $NOCHAR -eq -1 ] + then NOCHAR=0 fi echo $NOCHAR @@ -66,197 +64,106 @@ length () { fixlen () { WORD=$1 - ONELEN=`length "$1"` - LDIFF=`expr $ONELEN - $2` - if [ $LDIFF -le 1 ]; then - while [ $LDIFF -lt 0 ] ; do + ONELEN=$(length "$1") + LDIFF=$(expr $ONELEN - $2) + if [ $LDIFF -le 1 ] + then + while [ $LDIFF -lt 0 ] + do WORD="$WORD " - LDIFF=`expr $LDIFF + 1` + LDIFF=$(expr $LDIFF + 1) done echo "$WORD" else - LDIFF=`expr $LDIFF + 4` - WORD=`echo "$WORD" | cut -c${LDIFF}-` + LDIFF=$(expr $LDIFF + 4) + WORD=$(echo "$WORD" | cut -c${LDIFF}-) echo "...${WORD}" fi } +# MAIN CODE +# ~~~~~~~~~ +heading "Checking basic system..." -checkSetup () { -cat <<EOF -Host: $HOST_NAME -OS: $OS -OS_version: $OS_VERSION -Shell: $USER_SHELL -User: $USER_NAME -EOF -} - -checkNetworking () { -pingTest $HOST_NAME -pingTest localHost -checkRsh -checkSsh -} - -pingTest () { -case $OS in - SunOS) - if [ -x '/usr/sbin/ping' ] ; then - PINGTEST=`/usr/sbin/ping $1 2>&1` - if [ -n "`echo $PINGTEST | grep 'alive'`" ] ; then - RESULT="Successful" - elif [ -n "`echo $PINGTEST | grep 'unknown host'`" ] ; then - RESULT="Unknown_host" - else - RESULT="Networking_not_set" - fi - else - RESULT="Ping_not_installed_in_usual_path" - fi - ;; - *) - if [ -x '/bin/ping' ] ; then - PINGTEST=`/bin/ping -w 3 -c 1 $1 2>&1` - if [ -n "`echo $PINGTEST | grep '1 received'`" ] ; then - RESULT="Successful" - elif [ -n "`echo $PINGTEST | grep 'unknown host'`" ] ; then - RESULT='Unknown host' - else - RESULT='Networking not set' - fi - else - RESULT="Ping_not_installed_in_usual_path" - fi - ;; +# check shell +echo "$(fixlen "Shell:" $WIDTH) $SHELL" +case "$SHELL" in +*/csh | */tcsh) + USER_CONFIG_TYPE=cshrc + ;; +*/bash | */ksh) + USER_CONFIG_TYPE=bashrc + ;; +*) + USER_CONFIG_TYPE="" + echo "FATALERROR: Cannot identify the current shell." + echo " OpenFOAM ${FOAM_VERSION} is compatible" + echo " with csh, tcsh, ksh and bash." + echo + FATALERROR=yes + ;; esac -echo "`fixlen "Ping_$1:" $WIDTH` $RESULT" -if [ "$RESULT" != 'Successful' ]; then - FATALERROR=`expr $FATALERROR + 1` -fi - -} - -telnetPortTest () { -telnet -e A $1 $2 <<EOF -A -quit -EOF -} - -checkTelnetPort () { -if [ -x "/usr/bin/telnet" ] || [ -x "/bin/telnet" ] ; then - RESULT=`telnetPortTest $1 $2 2>&1 | egrep "onnect.* [t|r]"` - if [ "`echo $RESULT | grep 'Connected to'`" ] ; then - RESULT='Successful' - elif [ "`echo $RESULT | grep 'Connection refused'`" ] ; - then - RESULT='Unsuccessful, connection refused*' - else - RESULT="Not active*" - fi -else - RESULT='No_telnet_running:_cannot_check*' -fi -} - -checkRsh () { -checkTelnetPort $HOST_NAME 222 -echo "`fixlen "Test_rsh:" $WIDTH` $RESULT" -if [ "$RESULT" != 'Successful' ]; then - SSHRSHOK=`expr $SSHRSHOK + 1` -fi -} - -checkSsh () { -checkTelnetPort $HOST_NAME 22 -echo "`fixlen "Test_ssh:" $WIDTH` $RESULT" -if [ "$RESULT" != 'Successful' ]; then - SSHRSHOK=`expr $SSHRSHOK + 1` -fi -} - -expenv () { - eval "echo $1" -} - -#MAIN CODE -#~~~~~~~~~ -HOST_NAME=`uname -n` -OS=`uname -s` -OS_VERSION=`uname -r` -USER_SHELL=`basename $SHELL` -USER_NAME=$LOGNAME -# -if [ `length $USER_NAME` -eq 0 ] ; then - USER_NAME=$USER -fi -# -WIDTH=20 -heading "Checking basic system..." -case $USER_SHELL in - csh|tcsh) USER_CONFIG_TYPE=cshrc - echo "`fixlen "Shell:" $WIDTH` $USER_SHELL" - ;; - bash|ksh) USER_CONFIG_TYPE=bashrc - echo "`fixlen "Shell:" $WIDTH` $USER_SHELL" - ;; - *) USER_CONFIG_TYPE="" - echo "`fixlen "Shell:" $WIDTH` $USER_SHELL" - echo "FATALERROR: Cannot identify the current shell." - echo " Foam ${FOAM_VERSION} is compatible" - echo " with csh, tcsh, ksh and bash." - echo - FATALERROR=`expr $FATALERROR + 1`;; -esac -# -if [ `length $HOST_NAME` -eq 0 ]; then - echo "`fixlen "Host:" $WIDTH` ${HOST_NAME}" +# check hostname +HOST=$(uname -n) +echo "$(fixlen "Host:" $WIDTH) $HOST" +if [ $(length $HOST) -eq 0 ] +then echo "FATALERROR: Cannot stat hostname." - echo " Foam ${FOAM_VERSION} needs a valid hostname to function." + echo " OpenFOAM ${FOAM_VERSION} needs a valid hostname to function." echo " Contact your system administrator. " echo - FATALERROR=`expr $FATALERROR + 1` -else - echo "`fixlen "Host:" $WIDTH` ${HOST_NAME}" + FATALERROR=yes fi -# -if [ "$OS" = "Linux" ] || [ "$OS" = "LinuxAMD64" ] || [ "$OS" = "SunOS" ]; then - echo "`fixlen "OS:" $WIDTH` ${OS} version ${OS_VERSION}" -else + +# check os +OS=$(uname -s) +case "$OS" in +Linux | LinuxAMD64 | SunOS ) + echo "$(fixlen "OS:" $WIDTH) ${OS} version $(uname -r)" + ;; +*) echo "FATALERROR: Incompatible operating system \"$OS\"." - echo " Foam${FOAM_VERSION} is currently available for " + echo " OpenFOAM ${FOAM_VERSION} is currently available for " echo " Linux, LinuxAMD64 and SunOS only." echo - FATALERROR=`expr $FATALERROR + 1` + FATALERROR=yes + ;; +esac + + +# check user name +USER_NAME=$LOGNAME +if [ $(length $USER_NAME) -eq 0 ] +then + USER_NAME=$USER fi -# -if [ `length $USER_NAME` -eq 0 ]; then - echo "`fixlen "User:" $WIDTH` ${USER_NAME}" + +echo "$(fixlen "User:" $WIDTH) ${USER_NAME}" +if [ $(length $USER_NAME) -eq 0 ] +then echo "FATALERROR: Cannot stat user name ${USER_NAME}." - echo " Foam${FOAM_VERSION} needs a valid user name." + echo " OpenFOAM ${FOAM_VERSION} needs a valid user name." echo " Contact your system administrator. " echo "" - FATALERROR=`expr $FATALERROR + 1` -else - echo "`fixlen "User:" $WIDTH` ${USER_NAME}" + FATALERROR=yes fi -# + echo "" echo "" -if [ $FATALERROR -gt 0 ]; then +if [ -n "$FATALERROR" ] +then echo "System check: FAIL" echo "==================" - echo "Your system is not currently compatible with Foam installation " + echo "Your system is not currently compatible with OpenFOAM installation " echo "requirements. Review the error messages and consult the documentation" echo "for further instructions." echo else echo "System check: PASS" echo "==================" - echo "Continue Foam installation." + echo "Continue OpenFOAM installation." echo fi diff --git a/src/OpenFOAM/fields/pointPatchFields/derived/timeVaryingUniformFixedValue/timeVaryingUniformFixedValuePointPatchField.C b/src/OpenFOAM/fields/pointPatchFields/derived/timeVaryingUniformFixedValue/timeVaryingUniformFixedValuePointPatchField.C index 2ce7ada7ea1ce5445da016c0e5f064d13322df43..9b81fa90f8716dacdd5f5e4fe1f3d04cd9175d85 100644 --- a/src/OpenFOAM/fields/pointPatchFields/derived/timeVaryingUniformFixedValue/timeVaryingUniformFixedValuePointPatchField.C +++ b/src/OpenFOAM/fields/pointPatchFields/derived/timeVaryingUniformFixedValue/timeVaryingUniformFixedValuePointPatchField.C @@ -70,7 +70,7 @@ timeVaryingUniformFixedValuePointPatchField ) : fixedValuePointPatchField<Type>(p, iF), - timeSeries_(this->db(), dict) + timeSeries_(dict) { updateCoeffs(); } diff --git a/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.C b/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.C index bfb0ce9f128d21032c08b5bb3f73163bc73bf500..946041c6c3d71eb423ca02bff32a022de58b5cd9 100644 --- a/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.C +++ b/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.C @@ -32,20 +32,23 @@ License template<class Type> void Foam::interpolationTable<Type>::readTable() { - fileName_.expand(); + // preserve the original (unexpanded) fileName to avoid absolute paths + // appearing subsequently in the write() method + fileName fName(fileName_); + + fName.expand(); // Read data from file - IFstream(fileName_)() >> *this; + IFstream(fName)() >> *this; - // Check that the data is okay + // Check that the data are okay check(); if (this->size() == 0) { FatalErrorIn ( - "Foam::interpolationTable<Type>::interpolationTable" - "(const dictionary& dict)" + "Foam::interpolationTable<Type>::readTable()" ) << "table is empty" << nl << exit(FatalError); } @@ -58,8 +61,8 @@ template<class Type> Foam::interpolationTable<Type>::interpolationTable() : List<Tuple2<scalar, Type> >(), - boundAction_(interpolationTable::WARN), - fileName_("undefined_fileName") + boundsHandling_(interpolationTable::WARN), + fileName_("fileNameIsUndefined") {} @@ -67,7 +70,7 @@ template<class Type> Foam::interpolationTable<Type>::interpolationTable(const fileName& fn) : List<Tuple2<scalar, Type> >(), - boundAction_(interpolationTable::WARN), + boundsHandling_(interpolationTable::WARN), fileName_(fn) { readTable(); @@ -78,7 +81,7 @@ template<class Type> Foam::interpolationTable<Type>::interpolationTable(const dictionary& dict) : List<Tuple2<scalar, Type> >(), - boundAction_(wordToBoundAction(dict.lookup("boundAction"))), + boundsHandling_(wordToBoundsHandling(dict.lookup("outOfBounds"))), fileName_(dict.lookup("fileName")) { readTable(); @@ -92,7 +95,7 @@ Foam::interpolationTable<Type>::interpolationTable ) : List<Tuple2<scalar, Type> >(interpTable), - boundAction_(interpTable.boundAction_), + boundsHandling_(interpTable.boundsHandling_), fileName_(interpTable.fileName_) {} @@ -101,9 +104,9 @@ Foam::interpolationTable<Type>::interpolationTable // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template<class Type> -Foam::word Foam::interpolationTable<Type>::boundActionToWord +Foam::word Foam::interpolationTable<Type>::boundsHandlingToWord ( - const boundActions& bound + const boundsHandling& bound ) const { word enumName("warn"); @@ -137,8 +140,8 @@ Foam::word Foam::interpolationTable<Type>::boundActionToWord template<class Type> -typename Foam::interpolationTable<Type>::boundActions -Foam::interpolationTable<Type>::wordToBoundAction +typename Foam::interpolationTable<Type>::boundsHandling +Foam::interpolationTable<Type>::wordToBoundsHandling ( const word& bound ) const @@ -163,14 +166,27 @@ Foam::interpolationTable<Type>::wordToBoundAction { WarningIn ( - "Foam::interpolationTable<Type>::wordToBoundAction(const word&)" - ) << "bad bounding specifier " << bound << " using 'warn'" << endl; + "Foam::interpolationTable<Type>::wordToBoundsHandling(const word&)" + ) << "bad outOfBounds specifier " << bound << " using 'warn'" << endl; return interpolationTable::WARN; } } +template<class Type> +typename Foam::interpolationTable<Type>::boundsHandling +Foam::interpolationTable<Type>::outOfBounds +( + const boundsHandling& bound +) +{ + boundsHandling prev = boundsHandling_; + boundsHandling_ = bound; + return prev; +} + + template<class Type> void Foam::interpolationTable<Type>::check() const { @@ -197,26 +213,13 @@ void Foam::interpolationTable<Type>::check() const } -template<class Type> -typename Foam::interpolationTable<Type>::boundActions -Foam::interpolationTable<Type>::boundAction -( - const boundActions& bound -) -{ - boundActions prev = boundAction_; - boundAction_ = bound; - return prev; -} - - template<class Type> void Foam::interpolationTable<Type>::write(Ostream& os) const { os.writeKeyword("fileName") << fileName_ << token::END_STATEMENT << nl; - os.writeKeyword("boundAction") - << boundActionToWord(boundAction_) << token::END_STATEMENT << nl; + os.writeKeyword("outOfBounds") + << boundsHandlingToWord(boundsHandling_) << token::END_STATEMENT << nl; } @@ -235,7 +238,7 @@ Foam::interpolationTable<Type>::operator[](const label i) const } else if (ii < 0) { - switch (boundAction_) + switch (boundsHandling_) { case interpolationTable::ERROR: { @@ -275,7 +278,7 @@ Foam::interpolationTable<Type>::operator[](const label i) const } else if (ii >= n) { - switch (boundAction_) + switch (boundsHandling_) { case interpolationTable::ERROR: { @@ -334,7 +337,7 @@ Type Foam::interpolationTable<Type>::operator()(const scalar value) const if (lookupValue < minLimit) { - switch (boundAction_) + switch (boundsHandling_) { case interpolationTable::ERROR: { @@ -375,7 +378,7 @@ Type Foam::interpolationTable<Type>::operator()(const scalar value) const } else if (lookupValue >= maxLimit) { - switch (boundAction_) + switch (boundsHandling_) { case interpolationTable::ERROR: { diff --git a/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.H b/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.H index 77b944cda083f420ef5ff8ccf7b68080aae02345..8e00d9f5b3f92562a8dce8051f51db238a301f83 100644 --- a/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.H +++ b/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.H @@ -29,15 +29,15 @@ Description A list of times and values. The time values must be positive and monotonically increasing. - The treatment of out-of-bounds values depends on the current setting - of bounding. + The handling of out-of-bounds values depends on the current setting + of @a outOfBounds. - If @a REPEAT bounding is in effect, the final time value is treated - as being equivalent to time=0 for the following periods. + If @a REPEAT is chosen for the out-of-bounds handling, the final time + value is treated as being equivalent to time=0 for the following periods. Note - - Accessing an empty list will result in an error. - - Accessing a list with a single element will always return the same value. + - Accessing an empty list results in an error. + - Accessing a list with a single element always returns the same value. SourceFiles interpolationTable.C @@ -55,10 +55,8 @@ SourceFiles namespace Foam { -class objectRegistry; - /*---------------------------------------------------------------------------*\ - Class interpolationTable Declaration + Class interpolationTable Declaration \*---------------------------------------------------------------------------*/ template<class Type> @@ -71,7 +69,7 @@ public: // Public data types //- Enumeration for handling out-of-bound values - enum boundActions + enum boundsHandling { ERROR, /*!< Exit with a FatalError */ WARN, /*!< Issue warning and clamp value (default) */ @@ -85,7 +83,7 @@ private: // Private data //- Enumeration for handling out-of-bound values - boundActions boundAction_; + boundsHandling boundsHandling_; //- File name fileName fileName_; @@ -107,7 +105,7 @@ public: //- Construct given the name of the file containing the table of data interpolationTable(const fileName& fn); - //- Construct by reading the fileName and boundAction from dictionary + //- Construct by reading the fileName and boundsHandling from dictionary // and read the table from that file. // This is a specialised constructor used by patchFields interpolationTable(const dictionary& dict); @@ -118,20 +116,19 @@ public: // Member Functions - //- Return the out-of-bounds treatment as a word - word boundActionToWord(const boundActions& bound) const; + //- Return the out-of-bounds handling as a word + word boundsHandlingToWord(const boundsHandling& bound) const; + + //- Return the out-of-bounds handling as an enumeration + boundsHandling wordToBoundsHandling(const word& bound) const; - //- Return the out-of-bounds treatment as an enumeration - boundActions wordToBoundAction(const word& bound) const; + //- Set the out-of-bounds handling from enum, return previous setting + boundsHandling outOfBounds(const boundsHandling& bound); //- Check that list is monotonically increasing // Exit with a FatalError if there is a problem void check() const; - //- Set the out-of-bounds treatment from enum, return previous - // setting - boundActions boundAction(const boundActions& bound); - //- Write void write(Ostream& os) const; diff --git a/src/conversion/Make/files b/src/conversion/Make/files index 435c341cd3c800a2db6c43d24d560631c58afb43..7c5a0aa91c070a5903667e22ed7a76f864bfee0e 100644 --- a/src/conversion/Make/files +++ b/src/conversion/Make/files @@ -1,3 +1,24 @@ +ensight/file/ensightFile.C +ensight/file/ensightGeoFile.C +ensight/part/ensightPart.C +ensight/part/ensightPartIO.C +ensight/part/ensightPartCells.C +ensight/part/ensightPartFaces.C +ensight/part/ensightParts.C + +meshTables/boundaryRegion.C +meshTables/cellTable.C + +meshReader/meshReader.C +meshReader/meshReaderAux.C +meshReader/calcPointCells.C +meshReader/createPolyCells.C +meshReader/createPolyBoundary.C +meshReader/starcd/STARCDMeshReader.C + +meshWriter/meshWriter.C +meshWriter/starcd/STARCDMeshWriter.C + polyDualMesh/polyDualMesh.C LIB = $(FOAM_LIBBIN)/libconversion diff --git a/src/conversion/Make/options b/src/conversion/Make/options index 4b2f0a059fbac055ee17d31b510b95445907d34c..a3ae8da833177387e9eecf75b5e2675fc7b481f5 100644 --- a/src/conversion/Make/options +++ b/src/conversion/Make/options @@ -1,5 +1,7 @@ EXE_INC = \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/meshTools/lnInclude LIB_LIBS = \ + -lfiniteVolume \ -lmeshTools diff --git a/src/conversion/ensight/file/ensightFile.C b/src/conversion/ensight/file/ensightFile.C new file mode 100644 index 0000000000000000000000000000000000000000..88357ba435acd05896294ae6eaf1968c01b8fadf --- /dev/null +++ b/src/conversion/ensight/file/ensightFile.C @@ -0,0 +1,298 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "ensightFile.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// allow undef in results +bool Foam::ensightFile::allowUndef_ = false; + +// value to represent undef in results +Foam::scalar Foam::ensightFile::undefValue_ = Foam::floatScalarVGREAT; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from pathname +Foam::ensightFile::ensightFile +( + const fileName& pathname, + IOstream::streamFormat format +) +: + OFstream(pathname, format) +{ + // ascii formatting specs + setf + ( + ios_base::scientific, + ios_base::floatfield + ); + precision(5); +} + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::ensightFile::~ensightFile() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::ensightFile::allowUndef() +{ + return allowUndef_; +} + + +bool Foam::ensightFile::allowUndef(bool value) +{ + bool old = allowUndef_; + allowUndef_ = value; + return old; +} + + +Foam::scalar Foam::ensightFile::undefValue(const scalar& value) +{ + // enable its use too + allowUndef_ = true; + + scalar old = undefValue_; + undefValue_ = value; + return old; +} + + +// binary write +Foam::Ostream& Foam::ensightFile::write +( + const char* buf, + std::streamsize count +) +{ + stream().write(buf, count); + return *this; +} + + +// write string as "%80s" or as binary +Foam::Ostream& Foam::ensightFile::write +( + const string& value +) +{ + char buf[80]; + + for (string::size_type i = 0; i < 80; ++i) + { + buf[i] = 0; + } + + string::size_type n = value.size(); + if (n >= 80) + { + n = 79; + } + + for (string::size_type i = 0; i < n; ++i) + { + buf[i] = value[i]; + } + + if (format() == IOstream::BINARY) + { + write + ( + reinterpret_cast<char const *>(buf), + sizeof(buf) + ); + } + else + { + stream() << buf; + } + + return *this; +} + + +// write integer as "%10d" or as binary +Foam::Ostream& Foam::ensightFile::write +( + const label& value +) +{ + if (format() == IOstream::BINARY) + { + unsigned int ivalue(value); + + write + ( + reinterpret_cast<char const *>(&ivalue), + sizeof(ivalue) + ); + } + else + { + stream().width(10); + stream() << value; + } + + return *this; +} + + +// write integer with specified width or as binary +Foam::Ostream& Foam::ensightFile::write +( + const label& value, + const label fieldWidth +) +{ + if (format() == IOstream::BINARY) + { + unsigned int ivalue(value); + + write + ( + reinterpret_cast<char const *>(&ivalue), + sizeof(ivalue) + ); + } + else + { + stream().width(fieldWidth); + stream() << value; + } + + return *this; +} + + +// write float as "%12.5e" or as binary +Foam::Ostream& Foam::ensightFile::write +( + const scalar& value +) +{ + if (format() == IOstream::BINARY) + { + float fvalue(value); + + write + ( + reinterpret_cast<char const *>(&fvalue), + sizeof(fvalue) + ); + } + else + { + stream().width(12); + stream() << value; + } + + return *this; +} + + +// Add carriage return to ascii stream +void Foam::ensightFile::newline() +{ + if (format() == IOstream::ASCII) + { + stream() << nl; + } +} + + +// write undef value +Foam::Ostream& Foam::ensightFile::writeUndef() +{ + write(undefValue_); + return *this; +} + + +// write element keyword with trailing newline, optionally with undef +Foam::Ostream& Foam::ensightFile::writeKeyword +( + const string& key +) +{ + if (allowUndef_) + { + write(key + " undef"); + newline(); + write(undefValue_); + newline(); + } + else + { + write(key); + newline(); + } + return *this; +} + + +// write "C Binary" for binary files +Foam::Ostream& Foam::ensightFile::writeBinaryHeader() +{ + if (format() == IOstream::BINARY) + { + write("C Binary"); + } + + return *this; +} + + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + + +// '*' mask appropriate for subDir +Foam::string Foam::ensightFile::mask() +{ + char buf[16] = "********"; + return buf; +} + + +// consistent zero-padded numbers for subdirectories +Foam::string Foam::ensightFile::subDir(const label n) +{ + char buf[16]; + + sprintf(buf, "%08d", n); + return buf; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/ensight/file/ensightFile.H b/src/conversion/ensight/file/ensightFile.H new file mode 100644 index 0000000000000000000000000000000000000000..9e0271dbf4a44fffa0d4c154b93265c2f519f6fa --- /dev/null +++ b/src/conversion/ensight/file/ensightFile.H @@ -0,0 +1,130 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::ensightFile + +Description + Ensight output with specialized write() for strings, integers and floats. + Correctly handles binary write as well. + +\*---------------------------------------------------------------------------*/ +#ifndef ensightFile_H +#define ensightFile_H + +#include "OFstream.H" +#include "IOstream.H" + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class ensightFile Declaration +\*---------------------------------------------------------------------------*/ + +class ensightFile +: + public OFstream +{ + //- allow undef in results + static bool allowUndef_; + + //- value to represent undef in results + static scalar undefValue_; + + //- Disallow default bitwise assignment + void operator=(const ensightFile&); + + //- Disallow default copy constructor + ensightFile(const ensightFile&); + +public: + // Constructors + + //- Construct from pathname + ensightFile + ( + const fileName& pathname, + IOstream::streamFormat format=IOstream::BINARY + ); + + // Destructor + ~ensightFile(); + + // Access + //- Return setting for whether 'undef' values are allowed in results + static bool allowUndef(); + + //- '*' mask appropriate for subDir + static string mask(); + + //- consistent zero-padded numbers for subdirectories + static string subDir(const label); + + // Edit + static bool allowUndef(bool); + + //- Assign the value to represent undef in the results + // Returns the previous value + // NB: do not use values larger than floatScalarVGREAT + static scalar undefValue(const scalar&); + + // Output + + //- binary write + virtual Ostream& write(const char* buf, std::streamsize count); + + //- write element keyword with trailing newline, optionally with undef + virtual Ostream& writeKeyword(const string& key); + + //- write "C Binary" for binary files (eg, geometry/measured) + Ostream& writeBinaryHeader(); + + //- write undef value + Ostream& writeUndef(); + + //- write string as "%80s" or as binary + Ostream& write(const string& value); + + //- write integer as "%10d" or as binary + Ostream& write(const label& value); + + //- write integer with specified width or as binary + Ostream& write(const label& value, const label fieldWidth); + + //- write float as "%12.5e" or as binary + Ostream& write(const scalar& value); + + //- Add carriage return to ascii stream + void newline(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ensight/file/ensightGeoFile.C b/src/conversion/ensight/file/ensightGeoFile.C new file mode 100644 index 0000000000000000000000000000000000000000..72805f553c5eda67bf782ac23a41d0859dddc514 --- /dev/null +++ b/src/conversion/ensight/file/ensightGeoFile.C @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "ensightGeoFile.H" + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + + +// Construct from pathname +Foam::ensightGeoFile::ensightGeoFile +( + const fileName& pathname, + IOstream::streamFormat format +) +: + ensightFile(pathname, format) +{ + writeBinaryHeader(); + write("Ensight Geometry File"); newline(); + write("====================="); newline(); + write("node id assign"); newline(); + write("element id assign"); newline(); +} + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::ensightGeoFile::~ensightGeoFile() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +// write keyword with trailing newline +Foam::Ostream& Foam::ensightGeoFile::writeKeyword +( + const string& key +) +{ + write(key); + newline(); + + return *this; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/ensight/file/ensightGeoFile.H b/src/conversion/ensight/file/ensightGeoFile.H new file mode 100644 index 0000000000000000000000000000000000000000..1c91fa3218e79cf93830a1590b8fce9b35b1e6e9 --- /dev/null +++ b/src/conversion/ensight/file/ensightGeoFile.H @@ -0,0 +1,80 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::ensightGeoFile + +Description + Specialized Ensight output with extra geometry file header + +\*---------------------------------------------------------------------------*/ +#ifndef ensightGeoFile_H +#define ensightGeoFile_H + +#include "ensightFile.H" + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class ensightGeoFile Declaration +\*---------------------------------------------------------------------------*/ +class ensightGeoFile +: + public ensightFile +{ + //- Disallow default bitwise assignment + void operator=(const ensightGeoFile&); + + //- Disallow default copy constructor + ensightGeoFile(const ensightGeoFile&); + +public: + // Constructors + + //- Construct from pathname + ensightGeoFile + ( + const fileName& pathname, + IOstream::streamFormat format=IOstream::BINARY + ); + + // Destructor + ~ensightGeoFile(); + + // Output + + //- write keyword with trailing newline + virtual Ostream& writeKeyword(const string& key); + +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +} // End namespace Foam + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ensight/part/ensightPart.C b/src/conversion/ensight/part/ensightPart.C new file mode 100644 index 0000000000000000000000000000000000000000..7d2fab6483790a6502d7f6ee4f7699b40df564eb --- /dev/null +++ b/src/conversion/ensight/part/ensightPart.C @@ -0,0 +1,231 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*----------------------------------------------------------------------------*/ + +#include "ensightPart.H" +#include "addToRunTimeSelectionTable.H" +#include "dictionary.H" +#include "ListOps.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // +namespace Foam +{ + defineTypeNameAndDebug(ensightPart, 0); + defineTemplateTypeNameAndDebug(IOPtrList<ensightPart>, 0); + defineRunTimeSelectionTable(ensightPart, istream); +} + +Foam::List<Foam::word> Foam::ensightPart::elemTypes_(0); + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +//- check for fully defined fields +bool Foam::ensightPart::isFieldDefined +( + const List<scalar>& field +) const +{ + forAll(elemLists_, elemI) + { + const labelList& idList = elemLists_[elemI]; + + forAll(idList, i) + { + label id = idList[i]; + + if (id >= field.size() || isnan(field[id])) + { + return false; + } + } + } + return true; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Null constructor +Foam::ensightPart::ensightPart +() +: + number_(0), + name_(""), + elemLists_(0), + offset_(0), + size_(0), + isCellData_(true), + matId_(0), + meshPtr_(0) +{} + + +// Construct empty part with number and description +Foam::ensightPart::ensightPart +( + label partNumber, + const string& partDescription +) +: + number_(partNumber), + name_(partDescription), + elemLists_(0), + offset_(0), + size_(0), + isCellData_(true), + matId_(0), + meshPtr_(0) +{} + + +// Construct empty part with number and description +Foam::ensightPart::ensightPart +( + label partNumber, + const string& partDescription, + const polyMesh& pMesh +) +: + number_(partNumber), + name_(partDescription), + elemLists_(0), + offset_(0), + size_(0), + isCellData_(true), + matId_(0), + meshPtr_(&pMesh) +{} + + +// Construct as copy +Foam::ensightPart::ensightPart +( + const ensightPart& part +) +: + number_(part.number_), + name_(part.name_), + elemLists_(part.elemLists_), + offset_(part.offset_), + size_(part.size_), + isCellData_(part.isCellData_), + matId_(part.matId_), + meshPtr_(part.meshPtr_) +{} + + +// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * // + +// runtime selection +Foam::autoPtr<Foam::ensightPart> Foam::ensightPart::New(Istream& is) +{ + word partType(is); + + istreamConstructorTable::iterator cstrIter = + istreamConstructorTablePtr_->find(partType); + + if (cstrIter == istreamConstructorTablePtr_->end()) + { + FatalIOErrorIn + ( + "ensightPart::New(Istream&)", + is + ) << "unknown ensightPart type " << partType << endl << endl + << "Valid ensightPart types are :" << endl + << istreamConstructorTablePtr_->toc() + << exit(FatalIOError); + } + + return autoPtr<ensightPart>(cstrIter()(is)); +} + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::ensightPart::~ensightPart() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +// reconstruct from Istream +void Foam::ensightPart::reconstruct(Istream& is) +{ + dictionary dict(is); + dict.lookup("id") >> number_; + dict.lookup("name") >> name_; + dict.readIfPresent("offset", offset_); + + // populate elemLists_ + elemLists_.setSize(elementTypes().size()); + + forAll(elementTypes(), elemI) + { + word key(elementTypes()[elemI]); + if (dict.found(key)) + { + dict.lookup(key) >> elemLists_[elemI]; + } + else + { + elemLists_[elemI].clear(); + } + size_ += elemLists_[elemI].size(); + } + + is.check("ensightPart::reconstruct(Istream&)"); +} + + +// renumber elements +void Foam::ensightPart::renumber(labelList const& origId) +{ + // transform to global values first + if (offset_) + { + forAll(elemLists_, elemI) + { + labelList& idList = elemLists_[elemI]; + forAll(idList, i) + { + idList[i] += offset_; + } + } + + offset_ = 0; + } + + if (origId.size()) + { + forAll(elemLists_, elemI) + { + inplaceRenumber(origId, elemLists_[elemI]); + } + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/ensight/part/ensightPart.H b/src/conversion/ensight/part/ensightPart.H new file mode 100644 index 0000000000000000000000000000000000000000..b3186eb3a1281f5b077025bef305dacb8c60dcb7 --- /dev/null +++ b/src/conversion/ensight/part/ensightPart.H @@ -0,0 +1,353 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::ensightPart + +Description + Base class for ensightPartCells and ensightPartFaces + +SourceFiles + ensightPart.C + ensightPartIO.C + ensightPartI.H + +\*---------------------------------------------------------------------------*/ + +#ifndef ensightPart_H +#define ensightPart_H + +#include "ensightFile.H" +#include "ensightGeoFile.H" +#include "typeInfo.H" +#include "labelList.H" +#include "polyMesh.H" +#include "Field.H" +#include "IOPtrList.H" +#include "IOstream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class ensightPart Declaration +\*---------------------------------------------------------------------------*/ + +class ensightPart +{ + // Private data + + // Static data members + static List<word> elemTypes_; + + // Private Member Functions + +protected: + // Protected data + + //- part number + label number_; + + //- part name (or description) + string name_; + + //- simple labelList with a name + labelListList elemLists_; + + //- start offset for elemLists_ + label offset_; + + //- number of elements in this part + label size_; + + //- cell or face data + bool isCellData_; + + //- material id (numeric) + label matId_; + + //- mesh reference used + const polyMesh* meshPtr_; + + // Protected Classes + + //- track the points used by the part and map global to local indices + class localPoints + { + public: + //- number of points used + label nPoints; + + //- map global to local indices + labelList list; + + // null constructor + localPoints() + : + nPoints(0), + list(0) + {} + + // construct for mesh points + localPoints(const polyMesh& pMesh) + : + nPoints(0), + list(pMesh.points().size(), -1) + {} + }; + + + // Protected Member Functions + + //- reconstruct contents from Istream + void reconstruct(Istream&); + + //- check for fully defined fields + bool isFieldDefined(const List<scalar>&) const; + + //- write the part header + void writeHeader(ensightFile&, bool withDescription=false) const; + + //- write a scalar field for idList + void writeFieldList + ( + ensightFile& os, + const List<scalar>& field, + const labelList& idList + ) const; + + //- track points used + virtual localPoints calcLocalPoints() const + { + return localPoints(); + } + + //- write connectivities + virtual void writeConnectivity + ( + ensightGeoFile& os, + const string& key, + const labelList& idList, + const labelList& pointMap + ) const + {} + +public: + + //- Runtime type information + TypeName("ensightPart"); + + // Public data + + // Constructors + + //- Construct null + ensightPart(); + + //- Construct empty part with number and description + ensightPart(label partNumber, const string& partDescription); + + //- Construct empty part with number and description + ensightPart + ( + label partNumber, + const string& partDescription, + const polyMesh& pMesh + ); + + //- Construct as copy + ensightPart(const ensightPart&); + + + // Selectors + + // Declare run-time constructor selection table + declareRunTimeSelectionTable + ( + autoPtr, + ensightPart, + istream, + ( + Istream& is + ), + (is) + ); + + //- Construct and return clone + autoPtr<ensightPart> clone() const + { + return autoPtr<ensightPart>(new ensightPart(*this)); + }; + + //- Construct on freestore from Istream + static autoPtr<ensightPart> New(Istream& is); + + + // Destructor + + virtual ~ensightPart(); + + // Static members + + virtual List<word> const& elementTypes() const + { + return elemTypes_; + } + + // Access + + //- number of elements in this part + label size() const + { + return size_; + } + + //- represents cell data + bool isCellData() const + { + return isCellData_; + } + + //- represents face data + bool isFaceData() const + { + return !isCellData_; + } + + //- part number + label number() const + { + return number_; + } + + //- part name or description + const string& name() const + { + return name_; + } + + //- material id + label materialId() const + { + return matId_; + } + + //- non-const access + void name(const string& value) + { + name_ = value; + } + + void materialId(const label value) + { + matId_ = value; + } + + //- offset for element ids + label offset() const + { + return offset_; + } + + // Edit + + //- renumber elements + void renumber(labelList const&); + + //- write summary information about the object + bool writeSummary(Ostream&) const; + + //- write reconstruction information for the object + bool writeData(Ostream&) const; + + //- write geometry + void writeGeometry(ensightGeoFile&) const; + + //- write scalar field + void writeScalarField + ( + ensightFile&, + const List<scalar>& field + ) const; + + //- write vector field components + void writeVectorField + ( + ensightFile&, + const List<scalar>& field0, + const List<scalar>& field1, + const List<scalar>& field2 + ) const; + + + //- write generalized field components + template <class Type> + void writeField + ( + ensightFile&, + const Field<Type>& + ) const; + + + // Member Operators + + //- Disallow default bitwise assignment + void operator=(const ensightPart&) + { + notImplemented("ensightPart::operator=(const ensightPart&)"); + } + + + // IOstream Operators + + //- write data (reconstruction information) + friend Ostream& operator<<(Ostream&, const ensightPart&); + + //- write geometry + friend ensightGeoFile& operator<< + ( + ensightGeoFile&, + const ensightPart& + ); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository +# include "ensightPartI.H" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ensight/part/ensightPartCells.C b/src/conversion/ensight/part/ensightPartCells.C new file mode 100644 index 0000000000000000000000000000000000000000..acbc02665e6b3c48f20eecfdc0022e97f4d7cf70 --- /dev/null +++ b/src/conversion/ensight/part/ensightPartCells.C @@ -0,0 +1,454 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*----------------------------------------------------------------------------*/ + +#include "ensightPartCells.H" +#include "addToRunTimeSelectionTable.H" +#include "IOstream.H" +#include "IStringStream.H" +#include "dictionary.H" +#include "cellModeller.H" + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(ensightPartCells, 0); + addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream); +} + +// names for addressable ensight element types +Foam::List<Foam::word> Foam::ensightPartCells::elemTypes_ +( + IStringStream + ( + "(tetra4 pyramid5 penta6 hexa8 nfaced)" + )() +); + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +// classify the cell types, track the points used +void Foam::ensightPartCells::classify +( + const labelList& idList +) +{ + // References to cell shape models + const cellModel& tet = *(cellModeller::lookup("tet")); + const cellModel& pyr = *(cellModeller::lookup("pyr")); + const cellModel& prism = *(cellModeller::lookup("prism")); + const cellModel& hex = *(cellModeller::lookup("hex")); + + const polyMesh& mesh = *meshPtr_; + const cellShapeList& cellShapes = mesh.cellShapes(); + + offset_ = 0; + size_ = mesh.nCells(); + + bool limited = false; + if (&idList) + { + limited = true; + size_ = idList.size(); + } + + // count the shapes + label nTet = 0; + label nPyr = 0; + label nPrism = 0; + label nHex = 0; + label nPoly = 0; + + + // TODO: allow tet-decomposition of polyhedral cells +#if 0 + label nTetDecomp = 0; + label nPyrDecomp = 0; +#endif + + for (label listI = 0; listI < size_; ++listI) + { + label cellId = listI; + if (limited) + { + cellId = idList[listI]; + } + + const cellShape& cellShape = cellShapes[cellId]; + const cellModel& cellModel = cellShape.model(); + + if (cellModel == tet) + { + nTet++; + } + else if (cellModel == pyr) + { + nPyr++; + } + else if (cellModel == prism) + { + nPrism++; + } + else if (cellModel == hex) + { + nHex++; + } + else + { + nPoly++; + + // TODO: allow tet-decomposition of polyhedral cells +#if 0 + const cell& cFaces = mesh.cells()[cellI]; + + forAll(cFaces, cFaceI) + { + const face& f = mesh.faces()[cFaces[cFaceI]]; + + label nQuads = 0; + label nTris = 0; + f.nTrianglesQuads(mesh.points(), nTris, nQuads); + + nTetDecomp += nTris; + nPyrDecomp += nQuads; + } + + nAddCells--; + nAddPoints++; +#endif + } + } + + + // we can avoid double looping, but at the cost of allocation + labelList tetCells(nTet); + labelList pyramidCells(nPyr); + labelList prismCells(nPrism); + labelList hexCells(nHex); + labelList polyCells(nPoly); + + nTet = 0, + nPyr = 0; + nPrism = 0; + nHex = 0; + nPoly = 0; + + // classify the shapes + for (label listI = 0; listI < size_; ++listI) + { + label cellId = listI; + if (limited) + { + cellId = idList[listI]; + } + + const cellShape& cellShape = cellShapes[cellId]; + const cellModel& cellModel = cellShape.model(); + + if (cellModel == tet) + { + tetCells[nTet++] = cellId; + } + else if (cellModel == pyr) + { + pyramidCells[nPyr++] = cellId; + } + else if (cellModel == prism) + { + prismCells[nPrism++] = cellId; + } + else if (cellModel == hex) + { + hexCells[nHex++] = cellId; + } + else + { + polyCells[nPoly++] = cellId; + + // TODO: allow tet-decomposition of polyhedral cells +#if 0 + // Mapping from additional point to cell + addPointCellLabels_[api] = cellId; + + const cell& cFaces = mesh.cells()[cellId]; + + forAll(cFaces, cFaceI) + { + const face& f = mesh.faces()[cFaces[cFaceI]]; + + label nQuads = 0; + label nTris = 0; + f.nTrianglesQuads(mesh.points(), nTris, nQuads); + + nTetDecomp += nTris; + nPyrDecomp += nQuads; + } + + nAddCells--; + nAddPoints++; +#endif + } + } + + + // MUST match with elementTypes + elemLists_.setSize(elementTypes().size()); + + elemLists_[tetra4Elements].transfer( tetCells ); + elemLists_[pyramid5Elements].transfer( pyramidCells ); + elemLists_[penta6Elements].transfer( prismCells ); + elemLists_[hexa8Elements].transfer( hexCells ); + elemLists_[nfacedElements].transfer( polyCells ); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct empty part with number and description +Foam::ensightPartCells::ensightPartCells +( + label partNumber, + const string& partDescription +) +: + ensightPart(partNumber, partDescription) +{} + + +// Construct from polyMesh without zones +Foam::ensightPartCells::ensightPartCells +( + label partNumber, + const polyMesh& pMesh +) +: + ensightPart(partNumber, "cells", pMesh) +{ + classify(); +} + + +// Construct from polyMesh and list of (non-zoned) cells +Foam::ensightPartCells::ensightPartCells +( + label partNumber, + const polyMesh& pMesh, + const labelList& idList +) +: + ensightPart(partNumber, "cells", pMesh) +{ + classify(idList); +} + + +// Construct from polyMesh and cellZone +Foam::ensightPartCells::ensightPartCells +( + label partNumber, + const polyMesh& pMesh, + const cellZone& cZone +) +: + ensightPart(partNumber, cZone.name(), pMesh) +{ + classify(cZone); +} + + +// Construct as copy +Foam::ensightPartCells::ensightPartCells +( + const ensightPartCells& part +) +: + ensightPart(part) +{} + + +// Construct from Istream +Foam::ensightPartCells::ensightPartCells +( + Istream& is +) +: + ensightPart() +{ + reconstruct(is); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + + +Foam::ensightPartCells::~ensightPartCells() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + + +// track the points used +Foam::ensightPart::localPoints Foam::ensightPartCells::calcLocalPoints() const +{ + const polyMesh& mesh = *meshPtr_; + + localPoints ptList(mesh); + labelList& usedPoints = ptList.list; + label nPoints = 0; + + forAll(elemLists_, typeI) + { + const labelList& idList = elemLists_[typeI]; + + // add all points from cells + forAll(idList, i) + { + label id = idList[i] + offset_; + const labelList& cFaces = mesh.cells()[id]; + + forAll(cFaces, cFaceI) + { + const face& f = mesh.faces()[cFaces[cFaceI]]; + + forAll(f, fp) + { + if (usedPoints[f[fp]] == -1) + { + usedPoints[f[fp]] = nPoints++; + } + } + } + } + } + + // this is not absolutely necessary, but renumber anyhow + nPoints = 0; + forAll(usedPoints, ptI) + { + if (usedPoints[ptI] > -1) + { + usedPoints[ptI] = nPoints++; + } + } + + ptList.nPoints = nPoints; + return ptList; +} + + +// write cell connectivities +void Foam::ensightPartCells::writeConnectivity +( + ensightGeoFile& os, + const string& key, + const labelList& idList, + const labelList& pointMap +) const +{ + os.writeKeyword(key); + os.write(idList.size()); + os.newline(); + + const polyMesh& mesh = *meshPtr_; + + // write polyhedral + if (word(key) == "nfaced") + { + const faceList& meshFaces = mesh.faces(); + + // write the number of faces per element + forAll(idList, i) + { + label id = idList[i] + offset_; + const labelList& cFace = mesh.cells()[id]; + + os.write( cFace.size() ); + os.newline(); + } + + // write the number of points per element face + forAll(idList, i) + { + label id = idList[i] + offset_; + const labelList& cFace = mesh.cells()[id]; + + forAll(cFace, faceI) + { + const face& cf = meshFaces[cFace[faceI]]; + + os.write( cf.size() ); + os.newline(); + } + } + + // write the points describing each element face + forAll(idList, i) + { + label id = idList[i] + offset_; + const labelList& cFace = mesh.cells()[id]; + + forAll(cFace, faceI) + { + const face& cf = meshFaces[cFace[faceI]]; + + forAll(cf, ptI) + { + // convert global -> local index + // (note: Ensight indices start with 1) + os.write( pointMap[cf[ptI]] + 1); + } + os.newline(); + } + } + } + else + { + // write primitive + const cellShapeList& cellShapes = mesh.cellShapes(); + + forAll(idList, i) + { + label id = idList[i] + offset_; + const cellShape& cellPoints = cellShapes[id]; + + // convert global -> local index + // (note: Ensight indices start with 1) + forAll(cellPoints, ptI) + { + os.write( pointMap[cellPoints[ptI]] + 1 ); + } + os.newline(); + } + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/ensight/part/ensightPartCells.H b/src/conversion/ensight/part/ensightPartCells.H new file mode 100644 index 0000000000000000000000000000000000000000..a85b2778098c3951a368ca1ab87c65aeff85a97f --- /dev/null +++ b/src/conversion/ensight/part/ensightPartCells.H @@ -0,0 +1,162 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::ensightPartCells + +Description + An implementation of ensightPart to hold volume mesh cells. + +SourceFiles + ensightPartCells.C + +\*---------------------------------------------------------------------------*/ + +#ifndef ensightPartCells_H +#define ensightPartCells_H + +#include "ensightPart.H" +#include "typeInfo.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class ensightPartCells Declaration +\*---------------------------------------------------------------------------*/ + +class ensightPartCells +: + public ensightPart +{ + // Private data + + // Private Member Functions + + //- Disallow default bitwise assignment + void operator=(const ensightPartCells&); + + //- classify the cell types + void classify(const labelList& idLabels = labelList::null()); + + //- track points used + virtual localPoints calcLocalPoints() const; + + //- track the points used + // virtual void makeLocalPointMap(); + + //- element connectivity + virtual void writeConnectivity + ( + ensightGeoFile& os, + const string& key, + const labelList& idList, + const labelList& pointMap + ) const; + +protected: + + //- addressable Ensight element types + enum elemType + { + tetra4Elements, + pyramid5Elements, + penta6Elements, + hexa8Elements, + nfacedElements + }; + + // Static data members + static List<word> elemTypes_; + + +public: + + //- Runtime type information + TypeName("ensightCells"); + + // Constructors + + //- Construct empty part with number and description + ensightPartCells(label partNumber, const string& partDescription); + + //- Construct from polyMesh without zones + ensightPartCells(label partNumber, const polyMesh&); + + //- Construct from polyMesh and list of (non-zoned) cells + ensightPartCells + ( + label partNumber, + const polyMesh&, + const labelList& + ); + + //- Construct from polyMesh and cellZone + ensightPartCells + ( + label partNumber, + const polyMesh&, + const cellZone& + ); + + //- Construct as copy + ensightPartCells(const ensightPartCells&); + + //- Construct from Istream + ensightPartCells(Istream&); + + //- Construct on freestore from Istream + static autoPtr<ensightPartCells> New(Istream& is) + { + return autoPtr<ensightPartCells>(new ensightPartCells(is)); + } + + + // Destructor + + virtual ~ensightPartCells(); + + + // Member Functions + + //- static listing of the element types + virtual List<word> const& elementTypes() const + { + return elemTypes_; + } + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ensight/part/ensightPartFaces.C b/src/conversion/ensight/part/ensightPartFaces.C new file mode 100644 index 0000000000000000000000000000000000000000..79fd6ceed0b7a204fbaebd2b49b1b8c87bff08bc --- /dev/null +++ b/src/conversion/ensight/part/ensightPartFaces.C @@ -0,0 +1,263 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*----------------------------------------------------------------------------*/ + +#include "ensightPartFaces.H" +#include "addToRunTimeSelectionTable.H" +#include "IOstreams.H" +#include "IStringStream.H" +#include "dictionary.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // +namespace Foam +{ + defineTypeNameAndDebug(ensightPartFaces, 0); + addToRunTimeSelectionTable(ensightPart, ensightPartFaces, istream); +} + +// names for addressable ensight element types +Foam::List<Foam::word> Foam::ensightPartFaces::elemTypes_ +( + IStringStream + ( + "(tria3 quad4 nsided)" + )() +); + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct empty part with number and description +Foam::ensightPartFaces::ensightPartFaces +( + label partNumber, + const string& partDescription +) +: + ensightPart(partNumber, partDescription) +{ + isCellData_ = false; +} + + +// Construct from polyMesh and polyPatch +Foam::ensightPartFaces::ensightPartFaces +( + label partNumber, + const polyMesh& pMesh, + const polyPatch& pPatch +) +: + ensightPart(partNumber, pPatch.name(), pMesh) +{ + isCellData_ = false; + offset_ = pPatch.start(); + size_ = pPatch.size(); + + // count the shapes + label nTri = 0; + label nQuad = 0; + label nPoly = 0; + + forAll (pPatch, patchfaceI) + { + const face& f = pMesh.faces()[patchfaceI + offset_]; + + if (f.size() == 3) + { + nTri++; + } + else if (f.size() == 4) + { + nQuad++; + } + else + { + nPoly++; + } + } + + // we can avoid double looping, but at the cost of allocation + + labelList triCells(nTri); + labelList quadCells(nQuad); + labelList polygonCells(nPoly); + + nTri = 0; + nQuad = 0; + nPoly = 0; + + // classify the shapes + forAll(pPatch, patchfaceI) + { + const face& f = pMesh.faces()[patchfaceI + offset_]; + + if (f.size() == 3) + { + triCells[nTri++] = patchfaceI; + } + else if (f.size() == 4) + { + quadCells[nQuad++] = patchfaceI; + } + else + { + polygonCells[nPoly++] = patchfaceI; + } + } + + + // MUST match with elementTypes + elemLists_.setSize(elementTypes().size()); + + elemLists_[tria3Elements].transfer( triCells ); + elemLists_[quad4Elements].transfer( quadCells ); + elemLists_[nsidedElements].transfer( polygonCells ); +} + + + +// Construct as copy +Foam::ensightPartFaces::ensightPartFaces +( + const ensightPartFaces &part +) +: + ensightPart(part) +{} + + +// Construct from Istream +Foam::ensightPartFaces::ensightPartFaces +( + Istream& is +) +: + ensightPart() +{ + isCellData_ = false; + reconstruct(is); +} + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::ensightPartFaces::~ensightPartFaces() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +// track the points used +Foam::ensightPart::localPoints Foam::ensightPartFaces::calcLocalPoints() const +{ + const polyMesh& mesh = *meshPtr_; + + localPoints ptList(mesh); + labelList& usedPoints = ptList.list; + label nPoints = 0; + + forAll(elemLists_, typeI) + { + const labelList& idList = elemLists_[typeI]; + + // add all points from faces + forAll(idList, i) + { + label id = idList[i] + offset_; + const face& f = mesh.faces()[id]; + + forAll(f, fp) + { + if (usedPoints[f[fp]] == -1) + { + usedPoints[f[fp]] = nPoints++; + } + } + } + } + + // this is not absolutely necessary, but renumber anyhow + nPoints = 0; + forAll(usedPoints, ptI) + { + if (usedPoints[ptI] > -1) + { + usedPoints[ptI] = nPoints++; + } + } + + ptList.nPoints = nPoints; + return ptList; +} + + +// write face connectivities +void Foam::ensightPartFaces::writeConnectivity +( + ensightGeoFile& os, + const string& key, + const labelList& idList, + const labelList& pointMap +) const +{ + os.writeKeyword(key); + os.write(idList.size()); + os.newline(); + + const faceList& meshFaces = meshPtr_->faces(); + + // write (polygon) face sizes + if (word(key) == "nsided") + { + // write the number of points per face + forAll(idList, i) + { + label id = idList[i] + offset_; + const face& f = meshFaces[id]; + + os.write( f.size() ); + os.newline(); + } + } + + // write the points describing the face + forAll(idList, i) + { + label id = idList[i] + offset_; + const face& f = meshFaces[id]; + + // convert global -> local index + // (note: Ensight indices start with 1) + forAll(f, fp) + { + os.write( pointMap[f[fp]] + 1 ); + } + os.newline(); + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/ensight/part/ensightPartFaces.H b/src/conversion/ensight/part/ensightPartFaces.H new file mode 100644 index 0000000000000000000000000000000000000000..6f00e0fb567e2815078b1ebbfa6b03d4b88d9dc3 --- /dev/null +++ b/src/conversion/ensight/part/ensightPartFaces.H @@ -0,0 +1,142 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::ensightPartFaces + +Description + An implementation of ensightPart to hold volume mesh faces. + +SourceFiles + ensightPartFaces.C + +\*---------------------------------------------------------------------------*/ + +#ifndef ensightPartFaces_H +#define ensightPartFaces_H + +#include "ensightPart.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class ensightPartFaces Declaration +\*---------------------------------------------------------------------------*/ + +class ensightPartFaces +: + public ensightPart +{ + // Private data + + // Private Member Functions + + //- Disallow default bitwise assignment + void operator=(const ensightPartFaces&); + + //- track points used + virtual localPoints calcLocalPoints() const; + + //- element connectivity + virtual void writeConnectivity + ( + ensightGeoFile& os, + const string& key, + const labelList& idList, + const labelList& pointMap + ) const; + +protected: + + //- addressable ensight element types + enum elemType + { + tria3Elements, + quad4Elements, + nsidedElements + }; + + // Static data members + static List<word> elemTypes_; + + +public: + + //- Runtime type information + TypeName("ensightFaces"); + + // Constructors + + //- Construct empty part with number and description + ensightPartFaces(label partNumber, const string& partDescription); + + //- Construct from polyMesh and polyPatch + ensightPartFaces + ( + label partNumber, + const polyMesh&, + const polyPatch& + ); + + //- Construct as copy + ensightPartFaces(const ensightPartFaces&); + + //- Construct from Istream + ensightPartFaces(Istream&); + + //- Construct on freestore from Istream + static autoPtr<ensightPartFaces> New(Istream& is) + { + return autoPtr<ensightPartFaces>(new ensightPartFaces(is)); + } + + + // Destructor + + virtual ~ensightPartFaces(); + + + // Member Functions + + //- static listing of the element types + virtual List<word> const& elementTypes() const + { + return elemTypes_; + } + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ensight/part/ensightPartI.H b/src/conversion/ensight/part/ensightPartI.H new file mode 100644 index 0000000000000000000000000000000000000000..6252fdc6baad339df61749ba05885c8d1035ff3a --- /dev/null +++ b/src/conversion/ensight/part/ensightPartI.H @@ -0,0 +1,71 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Description + Template to write generalized field components + +\*---------------------------------------------------------------------------*/ + +#include "ensightPart.H" + +// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // + +// write generalized field components +template <class Type> +void Foam::ensightPart::writeField +( + ensightFile& os, + const Field<Type>& field +) const +{ + if (size() && field.size()) + { + writeHeader(os); + + forAll(elementTypes(), elemI) + { + const labelList& idList = elemLists_[elemI]; + + if (idList.size()) + { + os.writeKeyword( elementTypes()[elemI] ); + + for + ( + direction cmpt=0; + cmpt < pTraits<Type>::nComponents; + cmpt++ + ) + { + writeFieldList(os, field.component(cmpt), idList); + } + } + } + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/ensight/part/ensightPartIO.C b/src/conversion/ensight/part/ensightPartIO.C new file mode 100644 index 0000000000000000000000000000000000000000..7bb6b3961aa36268990c37bddedcc747dafbce5f --- /dev/null +++ b/src/conversion/ensight/part/ensightPartIO.C @@ -0,0 +1,264 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Description + Output for ensightPart + +\*---------------------------------------------------------------------------*/ + +#include "ensightPart.H" +#include "dictionary.H" +#include "IOstreams.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +// write the part header +void Foam::ensightPart::writeHeader +( + ensightFile& os, + bool withDescription +) const +{ + os.write("part"); + os.newline(); + + os.write(number() + 1); // Ensight starts with 1 + os.newline(); + + if (withDescription) + { + os.write(name()); + os.newline(); + } +} + + +// write scalar field for idList +void Foam::ensightPart::writeFieldList +( + ensightFile& os, + const List<scalar>& field, + const List<label>& idList +) const +{ + forAll(idList, i) + { + if (idList[i] >= field.size() || isnan(field[idList[i]])) + { + os.writeUndef(); + } + else + { + os.write(field[idList[i]]); + } + + os.newline(); + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + + +// write summary information about the object +bool Foam::ensightPart::writeSummary +( + Ostream& os +) const +{ + os << indent << type() << nl + << indent << token::BEGIN_BLOCK << incrIndent << nl; + + // Ensight starts with 1 + os.writeKeyword("id") << (number() + 1) << token::END_STATEMENT << nl; + os.writeKeyword("name") << name() << token::END_STATEMENT << nl; + os.writeKeyword("offset") << offset() << token::END_STATEMENT << nl; + os.writeKeyword("size") << size() << token::END_STATEMENT << nl; + + os << decrIndent << indent << token::END_BLOCK << nl << endl; + + return true; +} + + +// write reconstruction information for the object +bool Foam::ensightPart::writeData +( + Ostream& os +) const +{ + os << indent << type() << nl + << indent << token::BEGIN_BLOCK << incrIndent << nl; + + os.writeKeyword("id") << number() << token::END_STATEMENT << nl; + os.writeKeyword("name") << name() << token::END_STATEMENT << nl; + os.writeKeyword("offset") << offset() << token::END_STATEMENT << nl; + + forAll(elementTypes(), typeI) + { + word key(elementTypes()[typeI]); + if (elemLists_[typeI].size()) + { + elemLists_[typeI].writeEntry(key, os); + } + } + + os << decrIndent << indent << token::END_BLOCK << nl << endl; + + return true; +} + + + +// write geometry by components +void Foam::ensightPart::writeGeometry +( + ensightGeoFile& os +) const +{ + if (size() && meshPtr_) + { + const polyMesh& mesh = *meshPtr_; + const pointField& meshPoints = mesh.points(); + + localPoints ptList = calcLocalPoints(); + labelList& pointMap = ptList.list; + + writeHeader(os, true); + + // write points + os.writeKeyword("coordinates"); + os.write(ptList.nPoints); + os.newline(); + + for (direction cmpt=0; cmpt < vector::nComponents; cmpt++) + { + forAll(pointMap, ptI) + { + if (pointMap[ptI] > -1) + { + os.write( meshPoints[ptI].component(cmpt) ); + os.newline(); + } + } + } + + // write parts + forAll(elementTypes(), elemI) + { + if (elemLists_[elemI].size()) + { + writeConnectivity + ( + os, + elementTypes()[elemI], + elemLists_[elemI], + pointMap + ); + } + } + } +} + + +// write scalar field +void Foam::ensightPart::writeScalarField +( + ensightFile& os, + const List<scalar>& field +) const +{ + if (size() && field.size() && (os.allowUndef() || isFieldDefined(field))) + { + writeHeader(os); + + forAll(elementTypes(), elemI) + { + const labelList& idList = elemLists_[elemI]; + + if (idList.size()) + { + os.writeKeyword( elementTypes()[elemI] ); + writeFieldList(os, field, idList); + } + } + } +} + + +// write vector field components +void Foam::ensightPart::writeVectorField +( + ensightFile& os, + const List<scalar>& field0, + const List<scalar>& field1, + const List<scalar>& field2 +) const +{ + if (size() && field0.size() && (os.allowUndef() || isFieldDefined(field0))) + { + writeHeader(os); + + forAll(elementTypes(), elemI) + { + const labelList& idList = elemLists_[elemI]; + + if (idList.size()) + { + os.writeKeyword( elementTypes()[elemI] ); + writeFieldList(os, field0, idList); + writeFieldList(os, field1, idList); + writeFieldList(os, field2, idList); + } + } + } +} + + +// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // + +Foam::Ostream& Foam::operator<< +( + Ostream& os, + const ensightPart& part +) +{ + part.writeData(os); + return os; +} + + +Foam::ensightGeoFile& Foam::operator<< +( + ensightGeoFile& os, + const ensightPart& part +) +{ + part.writeGeometry(os); + return os; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/ensight/part/ensightParts.C b/src/conversion/ensight/part/ensightParts.C new file mode 100644 index 0000000000000000000000000000000000000000..464205a9c85df77749453b21caa1d74320b43e6c --- /dev/null +++ b/src/conversion/ensight/part/ensightParts.C @@ -0,0 +1,342 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*----------------------------------------------------------------------------*/ + +#include "ensightParts.H" + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from polyMesh +Foam::ensightParts::ensightParts +( + const polyMesh& pMesh +) +: + partsList_() +{ + recalculate(pMesh); +} + + +// Construct from IOobject +Foam::ensightParts::ensightParts +( + const IOobject& ioObj +) +: + partsList_() +{ + IOPtrList<ensightPart> ioList(ioObj); + partsList_.transfer(ioList); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::ensightParts::~ensightParts() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + + +// clear old information and construct anew from polyMesh +void Foam::ensightParts::recalculate +( + const polyMesh& pMesh +) +{ + partsList_.clear(); + + // extra space for unzoned cells + label nPart = + ( + pMesh.cellZones().size() + + pMesh.boundaryMesh().size() + + 1 + ); + + partsList_.setSize(nPart); + nPart = 0; + + label nZoneCells = 0; + + // do cell zones + forAll(pMesh.cellZones(), zoneI) + { + const cellZone& cZone = pMesh.cellZones()[zoneI]; + nZoneCells += cZone.size(); + + if (cZone.size()) + { + partsList_.set + ( + nPart, + new ensightPartCells + ( + nPart, + pMesh, + cZone + ) + ); + + nPart++; + } + } + + // collect unzoned cells + + // special case: no zones at all - do entire mesh + if (nZoneCells == 0) + { + partsList_.set + ( + nPart, + new ensightPartCells + ( + nPart, + pMesh + ) + ); + + nPart++; + } + else if (pMesh.nCells() > nZoneCells) + { + // determine which cells are not in a cellZone + labelList unzoned(pMesh.nCells(), -1); + + forAll(pMesh.cellZones(), zoneI) + { + const labelList& idList = pMesh.cellZones()[zoneI]; + + forAll(idList, i) + { + unzoned[idList[i]] = idList[i]; + } + } + + label nUnzoned = 0; + forAll(unzoned, i) + { + if (unzoned[i] < 0) + { + unzoned[nUnzoned] = i; + nUnzoned++; + } + } + unzoned.setSize(nUnzoned); + + if (unzoned.size()) + { + partsList_.set + ( + nPart, + new ensightPartCells + ( + nPart, + pMesh, + unzoned + ) + ); + + nPart++; + } + } + + + // do boundaries, skipping empty and processor patches + forAll(pMesh.boundaryMesh(), patchI) + { + const polyPatch& pPatch = pMesh.boundaryMesh()[patchI]; + if + ( + pPatch.size() + && typeid(pPatch) != typeid(processorPolyPatch) + ) + { + partsList_.set + ( + nPart, + new ensightPartFaces + ( + nPart, + pMesh, + pPatch + ) + ); + + nPart++; + } + } + + // truncate to correct size + partsList_.setSize(nPart); +} + + +// renumber elements +void Foam::ensightParts::renumber +( + const labelList& origCellId, + const labelList& origFaceId +) +{ + forAll(partsList_, partI) + { + if (partsList_[partI].isCellData()) + { + partsList_[partI].renumber(origCellId); + } + else + { + partsList_[partI].renumber(origFaceId); + } + } +} + + +// write the geometry +void Foam::ensightParts::writeGeometry +( + ensightGeoFile& os +) const +{ + // with some feedback + Info<< "write geometry part:" << nl << flush; + + forAll(partsList_, partI) + { + Info<< " " << partI << flush; + partsList_[partI].writeGeometry(os); + } +} + + +// write summary information about the objects +bool Foam::ensightParts::writeSummary +( + Ostream& os +) const +{ + forAll(partsList_, partI) + { + partsList_[partI].writeSummary(os); + } + + return true; +} + + +void Foam::ensightParts::writeData +( + Ostream& os +) const +{ + // Write size of list + os << nl << partsList_.size(); + + // Write beginning of contents + os << nl << token::BEGIN_LIST; + + // Write list contents + forAll(partsList_, i) + { + os << nl << partsList_[i]; + } + + // Write end of contents + os << nl << token::END_LIST << nl; + + // Check state of IOstream + os.check("Ostream& operator<<(Ostream&, const PtrList&)"); +} + + +// write scalar field +void Foam::ensightParts::writeScalarField +( + ensightFile& os, + const List<scalar>& field, + bool useFaceData +) const +{ + forAll(partsList_, partI) + { + if + ( + useFaceData + ? partsList_[partI].isFaceData() + : partsList_[partI].isCellData() + ) + { + partsList_[partI].writeScalarField(os,field); + } + } +} + + +// write vector field components +void Foam::ensightParts::writeVectorField +( + ensightFile& os, + const List<scalar>& field0, + const List<scalar>& field1, + const List<scalar>& field2, + bool useFaceData +) const +{ + forAll(partsList_, partI) + { + if + ( + useFaceData + ? partsList_[partI].isFaceData() + : partsList_[partI].isCellData() + ) + { + partsList_[partI].writeVectorField(os, field0, field1, field2); + } + } +} + +// * * * * * * * * * * * * * * * Member operators * * * * * * * * * * * * * // + + +// * * * * * * * * * * * * * * * * IOStream operators * * * * * * * * * * * // + +Foam::ensightGeoFile& Foam::operator<< +( + ensightGeoFile& os, + const ensightParts& parts +) +{ + parts.writeGeometry(os); + return os; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/ensight/part/ensightParts.H b/src/conversion/ensight/part/ensightParts.H new file mode 100644 index 0000000000000000000000000000000000000000..f4ca32d6ff80231db1fb64378668c4be29ed553d --- /dev/null +++ b/src/conversion/ensight/part/ensightParts.H @@ -0,0 +1,158 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::ensightParts + +Description + A collection of several ensightPart elements + +SourceFiles + ensightParts.C + ensightPartsI.H + +\*---------------------------------------------------------------------------*/ + +#ifndef ensightParts_H +#define ensightParts_H + +#include "ensightPart.H" +#include "ensightPartFaces.H" +#include "ensightPartCells.H" +#include "volFields.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class ensightParts Declaration +\*---------------------------------------------------------------------------*/ + +class ensightParts +{ + // Private Data + + //- list of parts + PtrList<ensightPart> partsList_; + + // Private Member Functions + + //- Disallow default bitwise copy construct + ensightParts(const ensightParts&); + + //- Disallow default bitwise assignment + void operator=(const ensightParts&); + +public: + + // Constructors + + //- Construct from polyMesh + ensightParts(const polyMesh&); + + //- Construct from IOobject + ensightParts(const IOobject&); + + // Destructor + + ~ensightParts(); + + //- clear old information and construct anew from polyMesh + void recalculate(const polyMesh&); + + //- renumber elements + void renumber + ( + const labelList& origCellId, + const labelList& origFaceId + ); + + //- number of parts + label size() const + { + return partsList_.size(); + } + + //- write the geometry + void writeGeometry(ensightGeoFile&) const; + + //- write summary information about the objects + bool writeSummary(Ostream&) const; + + //- write the lists + void writeData(Ostream&) const; + + //- write scalar field + void writeScalarField + ( + ensightFile&, + const List<scalar>& field, + bool useFaceData = false + ) const; + + //- write vector field components + void writeVectorField + ( + ensightFile&, + const List<scalar>& field0, + const List<scalar>& field1, + const List<scalar>& field2, + bool useFaceData = false + ) const; + + + //- write generalized field components + template <class Type> + void writeField + ( + ensightFile&, + const GeometricField<Type, fvPatchField, volMesh>& + ) const; + + // Friend Operators + + friend ensightGeoFile& operator<< + ( + ensightGeoFile&, + const ensightParts& + ); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository +# include "ensightPartsI.H" +#endif + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ensight/part/ensightPartsI.H b/src/conversion/ensight/part/ensightPartsI.H new file mode 100644 index 0000000000000000000000000000000000000000..bb5a915dec678a2099b066a9053fe75ba3ec6533 --- /dev/null +++ b/src/conversion/ensight/part/ensightPartsI.H @@ -0,0 +1,77 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Description + Template to write generalized field components + +\*---------------------------------------------------------------------------*/ +#include "ensightParts.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// write generalized field components +template <class Type> +void Foam::ensightParts::writeField +( + ensightFile& os, + const GeometricField<Type, fvPatchField, volMesh>& field +) const +{ + // find offset to patch parts (ie, the first face data) + label patchOffset = 0; + forAll(partsList_, partI) + { + if (partsList_[partI].isFaceData()) + { + patchOffset = partI; + break; + } + } + + forAll(partsList_, partI) + { + label patchI = partI - patchOffset; + + if (partsList_[partI].isCellData()) + { + partsList_[partI].writeField + ( + os, + field + ); + } + else if (patchI < field.boundaryField().size()) + { + partsList_[partI].writeField + ( + os, + field.boundaryField()[patchI] + ); + } + } +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/meshReader/README b/src/conversion/meshReader/README new file mode 100644 index 0000000000000000000000000000000000000000..bf24eb65a181fa838c6dd9313813480f4b0439be --- /dev/null +++ b/src/conversion/meshReader/README @@ -0,0 +1,95 @@ +With pro-STAR version v4, the input formats have changed radically. + * Easier to parse space-delimited input formats + * No arbitrary or integral couples + * No trimmed or degenerate cells + * Support for polyhedral cells + * Boundaries are directly connected to cell and faces + +Since the boundaries are now connected directly to the faces, +we now must be concerned with cell face notation otherwise we perform the +incorrect lookup. +Fortunately, there are only 4 primitive shapes to be concerned with. + +Hexa: + Foam pro-STAR + ~~~~~~~~~~~~~~ ~~~~~~~~~~~ + Face 0 (0 4 7 3) -> F5: (0 4 7 3) + Face 1 (1 2 6 5) -> F6: (1 2 6 5) + Face 2 (0 1 5 4) -> F3: (0 1 5 4) + Face 3 (3 7 6 2) -> F4: (2 3 7 6) + Face 4 (0 3 2 1) -> F1: (0 3 2 1) + Face 5 (4 5 6 7) -> F2: (4 5 6 7) + + +Prism: + Foam pro-STAR + ~~~~~~~~~~~~~~ ~~~~~~~~~~~ + Face 0 (0 2 1) -> F1: (0 2 1) + Face 1 (3 4 5) -> F2: (3 4 5) + Face 2 (0 3 5 2) -> F5: (0 3 5 2) + Face 3 (1 2 5 4) -> F6: (1 2 5 4) + Face 4 (0 1 4 3) -> F3: (0 1 4 3) + + +Tetra: + Foam pro-STAR + ~~~~~~~~~~~~~~ ~~~~~~~~~~~ + Face 0 (1 2 3) -> F6: (1 2 3) + Face 1 (0 3 2) -> F5: (0 3 2) + Face 2 (0 1 3) -> F3: (0 1 3) + Face 3 (0 2 1) -> F1: (0 2 1) + + +Pyramid: + Foam pro-STAR + ~~~~~~~~~~~~~~ ~~~~~~~~~~~ + Face 0 (0 3 2 1) -> F1: (0 3 2 1) + Face 1 (0 4 3) -> F5: (0 4 3) + Face 2 (3 4 2) -> F4: (2 3 4) + Face 3 (1 2 4) -> F6: (1 2 4) + Face 4 (0 1 4) -> F3: (0 1 4) + +Noting that several faces are skipped over in the pro-STAR definitions, +simply introducing a new cell modeller will be a problem. +Instead, subtract 1 from the pro-STAR faces and use lookup tables. + + +Here are the pro-STAR macro snippets used for creating the primitive cells: + +! hexa +v 10 0 0 0 +v 11 1 0 0 +v 12 1 1 0 +v 13 0 1 0 +v 14 0 0 1 +v 15 1 0 1 +v 16 1 1 1 +v 17 0 1 1 +c hexa 10 11 12 13 14 15 16 17 + +! prism +v 20 0 0 0 +v 21 1 0 0 +v 22 1 1 0 +v 23 0 0 1 +v 24 1 0 1 +v 25 1 1 1 +c prism 20 21 22 23 24 25 + +! tet +v 30 0 0 0 +v 31 1 0 0 +v 32 1 1 0 +v 33 0.75 0.75 1 +c tetra 30 31 32 33 + +! pyramid +v 40 0 0 0 +v 41 1 0 0 +v 42 1 1 0 +v 43 0 1 0 +v 44 0.5 0.5 1 +c pyra 40 41 42 43 44 + +! list faces +flist all diff --git a/src/conversion/meshReader/calcPointCells.C b/src/conversion/meshReader/calcPointCells.C new file mode 100644 index 0000000000000000000000000000000000000000..1b9c673d0eb4bdd63799e4ab1faea281b5edea04 --- /dev/null +++ b/src/conversion/meshReader/calcPointCells.C @@ -0,0 +1,183 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Description + calculate point cells - ie, the cells attached to each point + + - remove unused points, adjust pointCells and cellFaces accordingly +\*---------------------------------------------------------------------------*/ + +#include "meshReader.H" + +// for transition - in case someone really relied on the old behaviour +#undef LEAVE_UNUSED_POINTS + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void Foam::meshReader::calcPointCells() const +{ + const static label UNIT_POINT_CELLS = 12; + + if (pointCellsPtr_) + { + FatalErrorIn("meshReader::calcPointCells() const") + << "pointCells already calculated" + << abort(FatalError); + } + + label nPoints = points().size(); + + pointCellsPtr_ = new labelListList(nPoints); + labelListList& ptCells = *pointCellsPtr_; + + forAll(ptCells, i) + { + ptCells[i].setSize(UNIT_POINT_CELLS); + } + + // Initialize the list of labels which will hold the count of the + // actual number of cells per point during the analysis + labelList cellCount(nPoints, 0); + + // Note. Unlike the standard point-cell algorithm, which asks the cell for + // the supporting point labels, we need to work based on the cell faces. + // This is because some of the faces do not come from the cell shape. + // It is also advantageous to remove duplicates from the point-cell + // addressing, because this removes a lot of waste later. + + faceListList& cFaces = cellFaces(); + + // For each cell + forAll(cFaces, cellI) + { + const faceList& faces = cFaces[cellI]; + + forAll(faces, i) + { + // For each vertex + const labelList& labels = faces[i]; + + forAll(labels, j) + { + // Set working point label + label curPoint = labels[j]; + labelList& curPointCells = ptCells[curPoint]; + label curCount = cellCount[curPoint]; + + // check if the cell has been added before + bool found = false; + + for (label f = 0; f < curCount; f++) + { + if (curPointCells[f] == cellI) + { + found = true; + break; + } + } + + if (!found) + { + // If the list of pointCells is not big enough, double it + if (curPointCells.size() <= curCount) + { + curPointCells.setSize(curPointCells.size()*2); + } + + // Enter the cell label in the point's cell list + curPointCells[curCount] = cellI; + + // Increment the cell count for the point addressed + cellCount[curPoint]++; + } + } + } + } + + // report and remove unused points + // - adjust points, pointCells, and cellFaces accordingly + label pointI = 0; + labelList oldToNew(nPoints, -1); + + forAll(ptCells, i) + { + ptCells[i].setSize(cellCount[i]); + if (cellCount[i] > 0) + { + oldToNew[i] = pointI++; + } + } + + // report unused points + if (nPoints > pointI) + { +#ifdef LEAVE_UNUSED_POINTS + FatalErrorIn("meshReader::calcPointCells() const") + << "mesh has " << (nPoints - pointI) + << " points that were declared but not used" << endl; +#else + + Info<< "removing " << (nPoints - pointI) << " unused points" << endl; + + nPoints = pointI; + + // adjust points and truncate + inplaceReorder(oldToNew, points()); + points().setSize(nPoints); + + // adjust pointCells and truncate + inplaceReorder(oldToNew, ptCells); + ptCells.setSize(nPoints); + + // adjust cellFaces - this could be faster + // For each cell + forAll(cFaces, cellI) + { + faceList& faces = cFaces[cellI]; + + // For each face + forAll(faces, i) + { + inplaceRenumber(oldToNew, faces[i]); + } + } +#endif + } +} + + +const Foam::labelListList& Foam::meshReader::pointCells() const +{ + if (!pointCellsPtr_) + { + calcPointCells(); + } + + return *pointCellsPtr_; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// ************************************************************************* // diff --git a/src/conversion/meshReader/createPolyBoundary.C b/src/conversion/meshReader/createPolyBoundary.C new file mode 100644 index 0000000000000000000000000000000000000000..e25ead64c4e680b703edf30c25b74a82a4b30810 --- /dev/null +++ b/src/conversion/meshReader/createPolyBoundary.C @@ -0,0 +1,450 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Description + boundary faces + - use pointCells when searching for connectivity + - initialize the cell connectivity with '-1' + - find both cell faces corresponding to the baffles and mark them + to prevent a connection + - standard connectivity checks + + - added baffle and monitoring support + +\*---------------------------------------------------------------------------*/ + +#include "meshReader.H" +#include "Time.H" +#include "polyPatch.H" +#include "emptyPolyPatch.H" +#include "preservePatchTypes.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// add in boundary face +void Foam::meshReader::addPolyBoundaryFace +( + const label cellId, + const label cellFaceId, + const label nCreatedFaces +) +{ +#ifdef DEBUG_BOUNDARY + Info<< nCreatedFaces + << " add bnd for cell " << cellId + << " face " << cellFaceId + << " (original cell " << origCellId_[cellId] << ")" + << endl; +#endif + + // standard case: volume cells + const face& thisFace = cellFaces_[cellId][cellFaceId]; + + // Debugging + if (cellPolys_[cellId][cellFaceId] > nInternalFaces_) + { + Info<< "meshReader::createPolyBoundary(): " + << "Problem with face: " << thisFace << endl + << "Probably multiple definitions " + << "of a single boundary face." << endl + << endl; + } + else if (cellPolys_[cellId][cellFaceId] >= 0) + { + Info<< "meshReader::createPolyBoundary(): " + << "Problem with face: " << thisFace << endl + << "Probably trying to define a boundary face " + << "on a previously matched internal face." << endl + << "Internal face: " + << meshFaces_[cellPolys_[cellId][cellFaceId]] + << endl; + } + + meshFaces_[nCreatedFaces] = thisFace; + cellPolys_[cellId][cellFaceId] = nCreatedFaces; +} + + +// add in boundary face +void Foam::meshReader::addPolyBoundaryFace +( + const cellFaceIdentifier& identifier, + const label nCreatedFaces +) +{ + addPolyBoundaryFace(identifier.cell, identifier.face, nCreatedFaces); +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void Foam::meshReader::createPolyBoundary() +{ + label nBoundaryFaces = 0; + label nMissingFaces = 0; + label nInterfaces = 0; + + const faceListList& cFaces = cellFaces(); + + // determine number of non-patched faces: + forAll(cellPolys_, cellI) + { + cell& curCell = cellPolys_[cellI]; + + forAll(curCell, fI) + { + if (curCell[fI] < 0) + { + nMissingFaces++; + } + } + } + + forAll(boundaryIds_, patchI) + { + nBoundaryFaces += boundaryIds_[patchI].size(); + } + + Info<< nl + << "There are " << nMissingFaces + << " faces to be patched and " << nBoundaryFaces + << " specified - collect missed boundaries to final patch" << endl; + + patchStarts_.setSize(boundaryIds_.size()); + patchSizes_.setSize(boundaryIds_.size()); + + label nCreatedFaces = nInternalFaces_; + label baffleOffset = cFaces.size(); + interfaces_.setSize(baffleIds_.size()); + nBoundaryFaces = 0; + + forAll(boundaryIds_, patchI) + { + const List<cellFaceIdentifier>& idList = boundaryIds_[patchI]; + + patchStarts_[patchI] = nCreatedFaces; + + // write each baffle side separately + if (patchPhysicalTypes_[patchI] == "baffle") + { + label count = 0; + + for (label side = 0; side < 2; ++side) + { + label position = nInterfaces; + + forAll(idList, bndI) + { + label baffleI = idList[bndI].cell - baffleOffset; + + if + ( + baffleI >= 0 + && baffleI < baffleFaces_.size() + && baffleIds_[baffleI].size() + ) + { + addPolyBoundaryFace + ( + baffleIds_[baffleI][side], + nCreatedFaces + ); + + // remove applied boundaries (2nd pass) + if (side == 1) + { + baffleIds_[baffleI].clear(); + } + + interfaces_[position][side] = nCreatedFaces; + + nBoundaryFaces++; + nCreatedFaces++; + position++; + count++; + } + } + } + + nInterfaces += (count - (count % 2)) / 2; + } + else if (patchPhysicalTypes_[patchI] == "monitoring") + { + // translate the "monitoring" pseudo-boundaries to face sets + List<label> monitoring(idList.size()); + + label monitorI = 0; + forAll(idList, bndI) + { + label cellId = idList[bndI].cell; + label faceId = idList[bndI].face; + + // standard case: volume cells + if (cellId < baffleOffset) + { + label faceNr = cellPolys_[cellId][faceId]; + if (faceNr >= 0) + { + monitoring[monitorI++] = faceNr; + } + } + } + + monitoringSets_.insert(patchNames_[patchI], monitoring); + } + else + { + forAll(idList, bndI) + { + // standard case: volume cells + if (idList[bndI].cell < baffleOffset) + { + addPolyBoundaryFace + ( + idList[bndI], + nCreatedFaces + ); + + nBoundaryFaces++; + nCreatedFaces++; + } + } + } + + patchSizes_[patchI] = nCreatedFaces - patchStarts_[patchI]; + } + + // add in missing faces + Info<< "Missing faces added to patch after face " + << nCreatedFaces << ":" <<endl; + nMissingFaces = 0; + + // look for baffles first - keep them together at the start of the patch + for (label side = 0; side < 2; ++side) + { + label position = nInterfaces; + + forAll(baffleIds_, baffleI) + { + if (baffleIds_[baffleI].size()) + { + // add each side for each baffle + addPolyBoundaryFace + ( + baffleIds_[baffleI][side], + nCreatedFaces + ); + + interfaces_[position][side] = nCreatedFaces; + + // remove applied boundaries (2nd pass) + if (side == 1) + { + baffleIds_[baffleI].clear(); + } + + nMissingFaces++; + nCreatedFaces++; + position++; + } + } + } + + nInterfaces += (nMissingFaces - (nMissingFaces % 2)) / 2; + + // scan for any other missing faces + forAll(cellPolys_, cellI) + { + const labelList& curFaces = cellPolys_[cellI]; + + forAll(curFaces, cellFaceI) + { + if (curFaces[cellFaceI] < 0) + { + // just report the first few + if (nMissingFaces < 4) + { + const face& thisFace = cFaces[cellI][cellFaceI]; + + Info<< " cell " << cellI << " face " << cellFaceI + << " (original cell " << origCellId_[cellI] << ")" + << " face: " << thisFace + << endl; + } + else if (nMissingFaces == 5) + { + Info<< " ..." << nl << endl; + } + + addPolyBoundaryFace(cellI, cellFaceI, nCreatedFaces); + nMissingFaces++; + nCreatedFaces++; + } + } + } + + Info<< "Added " << nMissingFaces << " unmatched faces" << endl; + + if (nMissingFaces > 0) + { + patchSizes_[patchSizes_.size() - 1] = nMissingFaces; + } + else + { + patchStarts_.setSize(patchStarts_.size() - 1); + } + + // reset the size of the face list + meshFaces_.setSize(nCreatedFaces); + + // check the mesh for face mismatch + // (faces addressed once or more than twice) + labelList markupFaces(meshFaces_.size(), 0); + + forAll(cellPolys_, cellI) + { + const labelList& curFaces = cellPolys_[cellI]; + + forAll(curFaces, faceI) + { + markupFaces[curFaces[faceI]]++; + } + } + + for (label i = nInternalFaces_; i < markupFaces.size(); i++) + { + markupFaces[i]++; + } + + label nProblemFaces = 0; + + forAll(markupFaces, faceI) + { + if (markupFaces[faceI] != 2) + { + const face& problemFace = meshFaces_[faceI]; + + Info<< "meshReader::createPolyBoundary() : " + << "problem with face " << faceI << ": addressed " + << markupFaces[faceI] << " times (should be 2!). Face: " + << problemFace << endl; + + nProblemFaces++; + } + } + + if (nProblemFaces > 0) + { + Info<< "Number of incorrectly matched faces: " + << nProblemFaces << endl; + } + + // adjust for missing members + if (nInterfaces < interfaces_.size()) + { + interfaces_.setSize(nInterfaces); + } + + Info<< "Number of boundary faces: " << nBoundaryFaces << nl + << "Total number of faces: " << nCreatedFaces << nl + << "Number of interfaces: " << nInterfaces << endl; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +Foam::List<Foam::polyPatch*> +Foam::meshReader::polyBoundaryPatches(const polyMesh& mesh) +{ + label nUsed = 0, nEmpty = 0; + label nPatches = patchStarts_.size(); + + // avoid empty patches - move to the end of the lists and truncate + labelList oldToNew = identity(nPatches); + forAll(patchSizes_, patchI) + { + if (patchSizes_[patchI] > 0) + { + oldToNew[patchI] = nUsed++; + } + else + { + nEmpty++; + oldToNew[patchI] = nPatches - nEmpty; + } + } + + nPatches = nUsed; + + if (nEmpty) + { + Info<< "Removing " << nEmpty << " empty patches" << endl; + + inplaceReorder(oldToNew, patchTypes_); + inplaceReorder(oldToNew, patchNames_); + inplaceReorder(oldToNew, patchStarts_); + inplaceReorder(oldToNew, patchSizes_); + } + + patchTypes_.setSize(nPatches); + patchNames_.setSize(nPatches); + patchStarts_.setSize(nPatches); + patchSizes_.setSize(nPatches); + + + List<polyPatch*> p(nPatches); + + // Default boundary patch types + word defaultFacesType(emptyPolyPatch::typeName); + + // we could consider dropping this entirely + preservePatchTypes + ( + mesh, + mesh.instance(), + mesh.meshDir(), + patchNames_, + patchTypes_, + "defaultFaces", + defaultFacesType, + patchPhysicalTypes_ + ); + + forAll(patchStarts_, patchI) + { + p[patchI] = polyPatch::New + ( + patchTypes_[patchI], + patchNames_[patchI], + patchSizes_[patchI], + patchStarts_[patchI], + patchI, + mesh.boundaryMesh() + ).ptr(); + } + + return p; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/meshReader/createPolyCells.C b/src/conversion/meshReader/createPolyCells.C new file mode 100644 index 0000000000000000000000000000000000000000..ca9622cbf2e14cf6358bc610cb902dd0e62af3e0 --- /dev/null +++ b/src/conversion/meshReader/createPolyCells.C @@ -0,0 +1,330 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Description + create cellPolys + - use pointCells when searching for connectivity + - initialize the cell connectivity with '-1' + - find both cell faces corresponding to the baffles and mark them + to prevent a connection + - standard connectivity checks + + - added baffle support +\*---------------------------------------------------------------------------*/ + +#include "meshReader.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void Foam::meshReader::createPolyCells() +{ + // loop through all cell faces and create connectivity. This will produce + // a global face list and will describe all cells as lists of face labels + + const faceListList& cFaces = cellFaces(); + + // count the maximum number of faces and set the size of the cellPolys_ + cellPolys_.setSize(cFaces.size()); + + label maxFaces = 0; + + forAll(cellPolys_, cellI) + { + cellPolys_[cellI].setSize(cFaces[cellI].size(), -1); + + maxFaces += cFaces[cellI].size(); + } + + Info<< "Maximum possible number of faces in mesh: " << maxFaces << endl; + + meshFaces_.setSize(maxFaces); + + // set reference to point-cell addressing + const labelListList& ptCells = pointCells(); + + // size the baffle lists and initialize to -1 + baffleIds_.setSize(baffleFaces_.size()); + forAll(baffleIds_, baffleI) + { + baffleIds_[baffleI].setSize(2); + } + + // block off baffles first + // + // To prevent internal faces, we'll mark the cell faces + // with negative cell ids (offset by nCells). + // eg, + // cellI = -(nCells + baffleI) + // + // To distinguish these from the normal '-1' marker, we require + // cellI = -(nCells + baffleI) < -1 + // + // This condition is met provided that nCells > 1. + // ie., baffles require at least 2 volume cells + + label baffleOffset = cFaces.size(); + forAll(baffleFaces_, baffleI) + { + label cellI = -(baffleOffset + baffleI); + const face& curFace = baffleFaces_[baffleI]; + + // get the list of labels + const labelList& curPoints = curFace; + + // a baffle is a single face - only need to match one face + // get the list of cells sharing this point + const labelList& curNeighbours = ptCells[curPoints[0]]; + + label nNeighbours = 0; + + // For all neighbours + forAll(curNeighbours, neiI) + { + label curNei = curNeighbours[neiI]; + + // get the list of search faces + const faceList& searchFaces = cFaces[curNei]; + + forAll(searchFaces, neiFaceI) + { + int cmp = face::compare(curFace, searchFaces[neiFaceI]); + + if (cmp) + { + // maintain baffle orientation + // side0: baffle normal same as attached face + // side1: baffle normal opposite from attached face + // + label side = 0; + if (cmp < 0) + { + side = 1; + } + +#ifdef DEBUG_FACE_ORDERING + Info<< "cmp " << cmp << " matched " << curFace + << " with " << searchFaces[neiFaceI] + << endl; + + + Info<< "match " << baffleI + << " (" << origCellId_[baffleOffset+baffleI] << ")" + << " side " << side + << " against cell " << curNei + << " face " << neiFaceI + << " curFace " << curFace[1] + << " neiFace " << searchFaces[neiFaceI][1] + << endl; +#endif + + if (baffleIds_[baffleI][side].unused()) + { + baffleIds_[baffleI][side] = cellFaceIdentifier + ( + curNei, + neiFaceI + ); + + nNeighbours++; + } + else + { + Info<< "multiple matches for side " << side + << " of baffle " << baffleI + << " (original cell " + << origCellId_[baffleOffset+baffleI] << ")" + << endl; + } + break; + } + } + if (nNeighbours >= 2) break; + } + + if (nNeighbours == 2) + { + for (label side = 0; side < nNeighbours; ++side) + { + label neiCell = baffleIds_[baffleI][side].cell; + label neiFace = baffleIds_[baffleI][side].face; + + if (baffleIds_[baffleI][side].used()) + { + cellPolys_[neiCell][neiFace] = cellI; + } + } + } + else + { + Info<< "drop baffle " << baffleI + << " (original cell " + << origCellId_[baffleOffset+baffleI] << ")" + << " with " << nNeighbours << " neighbours" << endl; + + baffleFaces_[baffleI].clear(); + baffleIds_[baffleI].clear(); + } + } + +#ifdef DEBUG_CELLPOLY + Info<< "cellPolys_" << cellPolys_ << endl; + Info<< "baffleFaces_" << baffleFaces_ << endl; + Info<< "baffleIds_" << baffleIds_ << endl; +#endif + + bool found = false; + + nInternalFaces_ = 0; + + forAll(cFaces, cellI) + { + // Note: + // Insertion cannot be done in one go as the faces need to be + // added into the list in the increasing order of neighbour + // cells. Therefore, all neighbours will be detected first + // and then added in the correct order. + + const faceList& curFaces = cFaces[cellI]; + + // Record the neighbour cell + labelList neiCells(curFaces.size(), -1); + + // Record the face of neighbour cell + labelList faceOfNeiCell(curFaces.size(), -1); + + label nNeighbours = 0; + + // For all faces ... + forAll(curFaces, faceI) + { + // Skip already matched faces or those tagged by baffles + if (cellPolys_[cellI][faceI] != -1) continue; + + found = false; + + const face& curFace = curFaces[faceI]; + + // get the list of labels + const labelList& curPoints = curFace; + + // For all points + forAll(curPoints, pointI) + { + // get the list of cells sharing this point + const labelList& curNeighbours = ptCells[curPoints[pointI]]; + + // For all neighbours + forAll(curNeighbours, neiI) + { + label curNei = curNeighbours[neiI]; + + // reject neighbours with the lower label. This should + // also reject current cell. + if (curNei > cellI) + { + // get the list of search faces + const faceList& searchFaces = cFaces[curNei]; + + forAll(searchFaces, neiFaceI) + { + if (searchFaces[neiFaceI] == curFace) + { + // Record the neighbour cell and face + neiCells[faceI] = curNei; + faceOfNeiCell[faceI] = neiFaceI; + nNeighbours++; +#ifdef DEBUG_FACE_ORDERING + Info<< " cell " << cellI + << " face " << faceI + << " point " << pointI + << " nei " << curNei + << " neiFace " << neiFaceI + << endl; +#endif + found = true; + break; + } + } + if (found) break; + } + if (found) break; + } + if (found) break; + } // End of current points + } // End of current faces + + // Add the faces in the increasing order of neighbours + for (label neiSearch = 0; neiSearch < nNeighbours; neiSearch++) + { + // Find the lowest neighbour which is still valid + label nextNei = -1; + label minNei = cellPolys_.size(); + + forAll(neiCells, ncI) + { + if (neiCells[ncI] > -1 && neiCells[ncI] < minNei) + { + nextNei = ncI; + minNei = neiCells[ncI]; + } + } + + if (nextNei > -1) + { + // Add the face to the list of faces + meshFaces_[nInternalFaces_] = curFaces[nextNei]; + + // Mark for owner + cellPolys_[cellI][nextNei] = nInternalFaces_; + + // Mark for neighbour + cellPolys_[neiCells[nextNei]][faceOfNeiCell[nextNei]] = + nInternalFaces_; + + // Stop the neighbour from being used again + neiCells[nextNei] = -1; + + // Increment number of faces counter + nInternalFaces_++; + } + else + { + FatalErrorIn("meshReader::createPolyCells()") + << "Error in internal face insertion" + << abort(FatalError); + } + } + } + +#ifdef DEBUG_CELLPOLY + Info<< "cellPolys = " << cellPolys_ << endl; +#endif + + // don't reset the size of internal faces, because more faces will be + // added in createPolyBoundary() +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/meshReader/meshReader.C b/src/conversion/meshReader/meshReader.C new file mode 100644 index 0000000000000000000000000000000000000000..08a8a9886abf74a05898c90b7fbf4df2c052a800 --- /dev/null +++ b/src/conversion/meshReader/meshReader.C @@ -0,0 +1,254 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "meshReader.H" +#include "Time.H" +#include "polyMesh.H" +#include "faceSet.H" +#include "emptyPolyPatch.H" +#include "cellModeller.H" +#include "demandDrivenData.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// Pointers to cell shape models +const Foam::cellModel* Foam::meshReader::unknownModel = Foam::cellModeller:: +lookup +( + "unknown" +); + +const Foam::cellModel* Foam::meshReader::tetModel = Foam::cellModeller:: +lookup +( + "tet" +); + +const Foam::cellModel* Foam::meshReader::pyrModel = Foam::cellModeller:: +lookup +( + "pyr" +); + +const Foam::cellModel* Foam::meshReader::prismModel = Foam::cellModeller:: +lookup +( + "prism" +); + +const Foam::cellModel* Foam::meshReader::hexModel = Foam::cellModeller:: +lookup +( + "hex" +); + +// * * * * * * * * * * * * * * Static Functions * * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +// attach cellZones based on the cellTable Id +// - any other values can be extracted later from the cellTable dictionary +void Foam::meshReader::addCellZones +( + polyMesh& mesh +) const +{ + cellTable_.addCellZones(mesh, cellTableId_); + warnDuplicates("cellZones", mesh.cellZones().names()); +} + + +// attach faceZones based on the monitoring boundary conditions +void Foam::meshReader::addFaceZones +( + polyMesh& mesh +) const +{ + label nZone = monitoringSets_.size(); + mesh.faceZones().setSize(nZone); + + if (!nZone) + { + return; + } + + nZone = 0; + for + ( + HashTable<List<label>, word, string::hash>::const_iterator + iter = monitoringSets_.begin(); + iter != monitoringSets_.end(); + ++iter + ) + { + Info<< "faceZone " << nZone + << " (size: " << iter().size() << ") name: " + << iter.key() << endl; + + mesh.faceZones().set + ( + nZone, + new faceZone + ( + iter.key(), + iter(), + List<bool>(iter().size(), false), + nZone, + mesh.faceZones() + ) + ); + + nZone++; + } + mesh.faceZones().writeOpt() = IOobject::AUTO_WRITE; + warnDuplicates("faceZones", mesh.faceZones().names()); +} + + +// create and access the polyMesh +Foam::autoPtr<Foam::polyMesh> Foam::meshReader::mesh +( + const objectRegistry& registry +) +{ + readGeometry(); + + Info<< "Creating a polyMesh" << endl; + createPolyCells(); + + Info<< "Number of internal faces: " << nInternalFaces_ << endl; + + createPolyBoundary(); + clearExtraStorage(); + + autoPtr<polyMesh> mesh + ( + new polyMesh + ( + IOobject + ( + polyMesh::defaultRegion, + "constant", + registry + ), + points(), + meshFaces_, + cellPolys_ + ) + ); + + // adding patches also checks the mesh + mesh().addPatches(polyBoundaryPatches(mesh)); + + warnDuplicates("boundaries", mesh().boundaryMesh().names()); + + addCellZones(mesh()); + addFaceZones(mesh()); + + return mesh; +} + + +//- write the polyMesh +void Foam::meshReader::writeMesh +( + const polyMesh& mesh, + IOstream::streamFormat fmt +) const +{ + fileName meshDir = mesh.objectRegistry::path()/mesh.meshDir(); + + // remove some directories and files - this should be easier + mesh.removeFiles(mesh.instance()); + if (dir(meshDir/"sets")) + { + rmDir(meshDir/"sets"); + } + + Info<< "Writing polyMesh" << endl; + mesh.writeObject + ( + fmt, + IOstream::currentVersion, + IOstream::UNCOMPRESSED + ); + writeAux(mesh); +} + + +// Clear extra storage before creation of the mesh to reduce the memory usage +void Foam::meshReader::clearExtraStorage() +{ + cellFaces_.clear(); + baffleFaces_.clear(); + boundaryIds_.clear(); + baffleIds_.clear(); + + deleteDemandDrivenData(pointCellsPtr_); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::meshReader::meshReader +( + const fileName& fileOrPrefix, + const scalar scaleFactor +) + : + pointCellsPtr_(NULL), + nInternalFaces_(0), + patchStarts_(0), + patchSizes_(0), + interfaces_(0), + baffleIds_(0), + meshFaces_(0), + cellPolys_(0), + geometryFile_(fileOrPrefix), + scaleFactor_(scaleFactor), + points_(0), + origCellId_(0), + boundaryIds_(0), + patchTypes_(0), + patchNames_(0), + patchPhysicalTypes_(0), + cellFaces_(0), + baffleFaces_(0), + cellTableId_(0), + cellTable_() +{} + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::meshReader::~meshReader() +{ + deleteDemandDrivenData(pointCellsPtr_); +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// ************************************************************************* // diff --git a/src/conversion/meshReader/meshReader.H b/src/conversion/meshReader/meshReader.H new file mode 100644 index 0000000000000000000000000000000000000000..171c547756db7cde3c09b2783059ea5115d8b83a --- /dev/null +++ b/src/conversion/meshReader/meshReader.H @@ -0,0 +1,319 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Namespace + Foam::meshReaders + +Description + A namespace for holding various types of mesh readers. + + +Class + Foam::meshReader + +Description + This class supports creating polyMeshes with baffles. + + The derived classes are responsible for providing the protected data. + This implementation is somewhat messy, but could/should be restructured + to provide a more generalized reader (at the moment it has been written + for converting pro-STAR data). + + The meshReader supports cellTable information (see new user's guide entry). + +Note + The boundary definitions are given as cell/face. + +SourceFiles + calcPointCells.C + createPolyBoundary.C + createPolyCells.C + meshReader.C + meshReaderAux.C +\*---------------------------------------------------------------------------*/ + +#ifndef meshReader_H +#define meshReader_H + +#include "polyMesh.H" +#include "HashTable.H" +#include "IOstream.H" + +#include "cellTable.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class meshReader Declaration +\*---------------------------------------------------------------------------*/ + +class meshReader +{ +protected: + //- identify cell faces in terms of cell Id and face Id + class cellFaceIdentifier + { + public: + //- cell Id + label cell; + + //- face Id + label face; + + //- Construct null + cellFaceIdentifier() : cell(-1), face(-1) {} + + //- Construct from cell/face components + cellFaceIdentifier(label c, label f) : cell(c), face(f) {} + + // Check + + //- used if cell or face are non-negative + bool used() const + { + return (cell >= 0 && face >= 0); + } + + //- unsed if cell or face are negative + bool unused() const + { + return (cell < 0 || face < 0); + } + + // Member Operators + bool operator!=(const cellFaceIdentifier& cf) const + { + return (cell != cf.cell || face != cf.face); + } + + bool operator==(const cellFaceIdentifier& cf) const + { + return (cell == cf.cell && face == cf.face); + } + + // IOstream Operators + friend Ostream& operator<<(Ostream& os, const cellFaceIdentifier& cf) + { + os << "(" << cf.cell << "/" << cf.face << ")"; + return os; + } + }; + +private: + + // Private data + + //- Point-cell addressing. Used for topological analysis + // Warning. This point cell addressing list potentially contains + // duplicate cell entries. Use additional checking + mutable labelListList* pointCellsPtr_; + + //- Number of internal faces for polyMesh + label nInternalFaces_; + + //- Polyhedral mesh boundary patch start indices and dimensions + labelList patchStarts_; + labelList patchSizes_; + + //- association between two faces + List<labelPair> interfaces_; + + //- list of cells/faces id pairs for each baffle + List<List<cellFaceIdentifier> > baffleIds_; + + //- Global face list for polyMesh + faceList meshFaces_; + + //- Cells as polyhedra for polyMesh + cellList cellPolys_; + + //- Face sets for monitoring + HashTable<List<label>, word, string::hash> monitoringSets_; + + // Private Member Functions + + //- Disallow default bitwise copy construct + meshReader(const meshReader&); + + //- Disallow default bitwise assignment + void operator=(const meshReader&); + + //- Calculate pointCells + void calcPointCells() const; + + const labelListList& pointCells() const; + + //- Make polyhedral cells and global faces if the mesh is polyhedral + void createPolyCells(); + + //- add in boundary face + void addPolyBoundaryFace + ( + const label cellId, + const label cellFaceId, + const label nCreatedFaces + ); + + //- add in boundary face + void addPolyBoundaryFace + ( + const cellFaceIdentifier& identifier, + const label nCreatedFaces + ); + + //- add cellZones based on cellTable Id + void addCellZones(polyMesh&) const; + + //- add faceZones based on monitoring boundary conditions + void addFaceZones(polyMesh&) const; + + //- Make polyhedral boundary from shape boundary + // (adds more faces to the face list) + void createPolyBoundary(); + + //- Add polyhedral boundary + List<polyPatch*> polyBoundaryPatches(const polyMesh&); + + //- Clear extra storage before creation of the mesh to remove + // a memory peak + void clearExtraStorage(); + + void writeInterfaces(const objectRegistry&) const; + + // write List<label> in constant/polyMesh + void writeMeshLabelList + ( + const objectRegistry& registry, + const word& propertyName, + const labelList& list, + IOstream::streamFormat fmt = IOstream::ASCII + ) const; + + //- Return list of faces for every cell + faceListList& cellFaces() const + { + return const_cast<faceListList&>(cellFaces_); + } + +protected: + // Protected data + + //- Pointers to cell shape models + static const cellModel* unknownModel; + static const cellModel* tetModel; + static const cellModel* pyrModel; + static const cellModel* prismModel; + static const cellModel* hexModel; + + //- referenced filename + fileName geometryFile_; + + //- geometry scaling + scalar scaleFactor_; + + //- Points supporting the mesh + pointField points_; + + //- lookup original Cell number for a given cell + labelList origCellId_; + + //- identify boundary faces by cells and their faces + // for each patch + List<List<cellFaceIdentifier> > boundaryIds_; + + //- Boundary patch types + wordList patchTypes_; + + //- Boundary patch names + wordList patchNames_; + + //- Boundary patch physical types + wordList patchPhysicalTypes_; + + //- List of faces for every cell + faceListList cellFaces_; + + //- List of each baffle face + faceList baffleFaces_; + + // cell table id for each cell + labelList cellTableId_; + + // cell table persistent data saved as a dictionary + cellTable cellTable_; + + // Member Functions + + //- subclasses are required to supply this information + virtual bool readGeometry + ( + const scalar scaleFactor = 1.0 + ) = 0; + + //- Return mesh points + pointField& points() const + { + return const_cast<pointField&>(points_); + } + +public: + // Static Members + + //- warn about repeated names + static void warnDuplicates(const word& context, const wordList&); + + // Constructors + + //- Construct from fileName + meshReader(const fileName&, const scalar scaleFactor = 1.0); + + // Destructor + virtual ~meshReader(); + + // Member Functions + + //- create and return polyMesh + virtual autoPtr<polyMesh> mesh(const objectRegistry&); + + //- Write auxiliary information + void writeAux(const objectRegistry&) const; + + //- Write mesh + void writeMesh + ( + const polyMesh&, + IOstream::streamFormat fmt = IOstream::BINARY + ) const; +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +#endif + +// ************************************************************************* // diff --git a/src/conversion/meshReader/meshReaderAux.C b/src/conversion/meshReader/meshReaderAux.C new file mode 100644 index 0000000000000000000000000000000000000000..286092594595c5136aae72332969bc1643d72728 --- /dev/null +++ b/src/conversion/meshReader/meshReaderAux.C @@ -0,0 +1,188 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*----------------------------------------------------------------------------*/ +#include "meshReader.H" +#include "IOMap.H" +#include "OFstream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * Static Functions * * * * * * * * * * * * * // + +// warn about duplicate names +void Foam::meshReader::warnDuplicates +( + const word& context, + const wordList& list +) +{ + HashTable<label> hashed(list.size()); + bool duplicates = false; + + forAll(list, listI) + { + // check duplicate name + HashTable<label>::iterator iter = hashed.find(list[listI]); + if (iter != hashed.end()) + { + (*iter)++; + duplicates = true; + } + else + { + hashed.insert(list[listI], 1); + } + } + + // warn about duplicate names + if (duplicates) + { + Info << nl << "WARNING: " << context << " with identical names:"; + forAllConstIter(HashTable<label>, hashed, iter) + { + if (*iter > 1) + { + Info << " " << iter.key(); + } + } + Info << nl << endl; + } +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + + +// write interface (baffle) mapping +void Foam::meshReader::writeInterfaces(const objectRegistry& registry) const +{ + // write constant/polyMesh/interface + IOList<labelList> ioObj + ( + IOobject + ( + "interfaces", + "constant", + polyMesh::meshSubDir, + registry, + IOobject::NO_READ, + IOobject::NO_WRITE, + false + ) + ); + + ioObj.note() = "as yet unsupported interfaces (baffles)"; + + Info<< "Writing " << ioObj.name() << " to " << ioObj.objectPath() << endl; + + OFstream os(ioObj.objectPath()); + ioObj.writeHeader(os); + + os << interfaces_ + << "// ************************************************************************* //" + << endl; + +} + + +// write List<label> in constant/polyMesh +// this is crucial for later conversion back to ccm/starcd +void Foam::meshReader::writeMeshLabelList +( + const objectRegistry& registry, + const word& propertyName, + const labelList& list, + IOstream::streamFormat fmt +) const +{ + // write constant/polyMesh/propertyName + IOList<label> ioObj + ( + IOobject + ( + propertyName, + "constant", + polyMesh::meshSubDir, + registry, + IOobject::NO_READ, + IOobject::AUTO_WRITE, + false + ), + list + ); + + + ioObj.note() = "persistent data for star-cd <-> foam translation"; + Info<< "Writing " << ioObj.name() << " to " << ioObj.objectPath() << endl; + + // NOTE: + // the cellTableId is an integer and almost always < 1000, thus ASCII + // will be compacter than binary and makes external scripting easier + // + ioObj.writeObject + ( + fmt, + IOstream::currentVersion, + IOstream::UNCOMPRESSED + ); +} + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::meshReader::writeAux(const objectRegistry& registry) const +{ + cellTable_.writeDict(registry); + writeInterfaces(registry); + + // write origCellId as List<label> + writeMeshLabelList + ( + registry, + "origCellId", + origCellId_, + IOstream::BINARY + ); + + // write cellTableId as List<label> + // this is crucial for later conversion back to ccm/starcd + writeMeshLabelList + ( + registry, + "cellTableId", + cellTableId_, + IOstream::ASCII + ); +} + + +// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/meshReader/starcd/STARCDMeshReader.C b/src/conversion/meshReader/starcd/STARCDMeshReader.C new file mode 100644 index 0000000000000000000000000000000000000000..aaabca6740ecedaaef0080d0907784abab9d0ca8 --- /dev/null +++ b/src/conversion/meshReader/starcd/STARCDMeshReader.C @@ -0,0 +1,1105 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "STARCDMeshReader.H" +#include "cyclicPolyPatch.H" +#include "emptyPolyPatch.H" +#include "wallPolyPatch.H" +#include "symmetryPolyPatch.H" +#include "cellModeller.H" +#include "SortableList.H" +#include "IFstream.H" +#include "IOMap.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// special boundary regions +const char* Foam::meshReaders::STARCD::defaultBoundaryName = + "Default_Boundary_Region"; + +const char* Foam::meshReaders::STARCD::defaultSolidBoundaryName = + "Default_Boundary_Solid"; + +// keep solids +bool Foam::meshReaders::STARCD::keepSolids = false; + +// face addressing from pro-STAR faces -> foam faces +const int Foam::meshReaders::STARCD::starToFoamFaceAddr[4][6] = +{ + { 4, 5, 2, 3, 0, 1 }, // 11 = pro-STAR hex + { 0, 1, 4, -1, 2, 3 }, // 12 = pro-STAR prism + { 3, -1, 2, -1, 1, 0 }, // 13 = pro-STAR tetra + { 0, -1, 4, 2, 1, 3 } // 14 = pro-STAR pyramid +}; + +// * * * * * * * * * * * * * * Static Functions * * * * * * * * * * * * * * // + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// read and discard to newline +void Foam::meshReaders::STARCD::readToNewline(IFstream& is) +{ + char ch = '\n'; + do + { + (is).get(ch); + } + while ((is) && ch != '\n'); +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// read header +bool Foam::meshReaders::STARCD::readHeader +( + IFstream& is, + word fileSignature +) +{ + if (!is.good()) + { + FatalErrorIn("meshReaders::STARCD::readHeader()") + << "cannot read " << fileSignature << " " << is.name() + << abort(FatalError); + } + + word header; + label majorVersion; + + is >> header; + is >> majorVersion; + + // skip the rest of the line + readToNewline(is); + + // add other checks ... + if (header != fileSignature) + { + Info<< "header mismatch " << fileSignature << " " << is.name() + << endl; + } + + return true; +} + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +// read boundaryRegion names and the cellTable information from +// dictionaries that have been extracted from the .inp file +void Foam::meshReaders::STARCD::readAux +( + const objectRegistry& registry +) +{ + boundaryRegion_.readDict(registry); + cellTable_.readDict(registry); +} + +// read in the points from the .vrt file +// +/*---------------------------------------------------------------------------*\ +Line 1: + PROSTAR_VERTEX [newline] + +Line 2: + <version> 0 0 0 0 0 0 0 [newline] + +Body: + <vertexId> <x> <y> <z> [newline] + +\*---------------------------------------------------------------------------*/ +void Foam::meshReaders::STARCD::readPoints +( + const fileName& inputName, + const scalar scaleFactor +) +{ + const word fileSignature = "PROSTAR_VERTEX"; + label nPoints = 0, maxId = 0; + + // Pass 1: + // get # points and maximum vertex label + { + IFstream is(inputName); + readHeader(is, fileSignature); + + label lineLabel; + scalar x, y, z; + + while ((is >> lineLabel).good()) + { + nPoints++; + maxId = max(maxId, lineLabel); + is >> x >> y >> z; + } + } + + Info<< "Number of points = " << nPoints << endl; + + // set sizes and reset to invalid values + + points_.setSize(nPoints); + mapToFoamPointId_.setSize(maxId+1); + + //- original Point number for a given vertex + // might need again in the future + //// labelList origPointId(nPoints); + //// origPointId = -1; + + mapToFoamPointId_ = -1; + + // Pass 2: + // construct pointList and conversion table + // from Star vertex numbers to Foam point labels + if (nPoints > 0) + { + IFstream is(inputName); + readHeader(is, fileSignature); + + label lineLabel; + + label pointI = 0; + while ((is >> lineLabel).good()) + { + is >> points_[pointI].x() + >> points_[pointI].y() + >> points_[pointI].z(); + + // might need again in the future + //// origPointId[pointI] = lineLabel; + mapToFoamPointId_[lineLabel] = pointI; + pointI++; + } + + if (nPoints > pointI) + { + nPoints = pointI; + points_.setSize(nPoints); + // might need again in the future + //// origPointId.setSize(nPoints); + } + + if (scaleFactor > 1.0 + SMALL || scaleFactor < 1.0 - SMALL) + { + points_ *= scaleFactor; + } + } + else + { + FatalErrorIn("meshReaders::STARCD::readPoints()") + << "no points in file " << inputName + << abort(FatalError); + } + +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// read in the cells from the .cel file +// +/*---------------------------------------------------------------------------*\ +Line 1: + PROSTAR_CELL [newline] + +Line 2: + <version> 0 0 0 0 0 0 0 [newline] + +Body: + <cellId> <shapeId> <nLabels> <cellTableId> <typeId> [newline] + <cellId> <int1> .. <int8> + <cellId> <int9> .. <int16> + + with shapeId: + * 1 = point + * 2 = line + * 3 = shell + * 11 = hexa + * 12 = prism + * 13 = tetra + * 14 = pyramid + * 255 = polyhedron + + with typeId + * 1 = fluid + * 2 = solid + * 3 = baffle + * 4 = shell + * 5 = line + * 6 = point + +For primitive cell shapes, the number of vertices will never exceed 8 (hexa) +and corresponds to <nLabels>. +For polyhedral, <nLabels> includess an index table comprising beg/end pairs +for each cell face. + +Strictly speaking, we only need the cellModeller for adding boundaries. +\*---------------------------------------------------------------------------*/ + +void Foam::meshReaders::STARCD::readCells +( + const fileName& inputName +) +{ + const word fileSignature = "PROSTAR_CELL"; + label nFluids = 0, nSolids = 0, nBaffles = 0, nShells = 0; + label maxId = 0; + + bool unknownVertices = false; + + + // Pass 1: + // count nFluids, nSolids, nBaffle, nShell and maxId + // also see if polyhedral cells were used + { + IFstream is(inputName); + readHeader(is, fileSignature); + + label lineLabel, shapeId, nLabels, cellTableId, typeId; + + while ((is >> lineLabel).good()) + { + label starCellId = lineLabel; + is >> shapeId + >> nLabels + >> cellTableId + >> typeId; + + // skip the rest of the line + readToNewline(is); + + // max 8 indices per line + while (nLabels > 0) + { + readToNewline(is); + nLabels -= 8; + } + + if (typeId == starcdFluidType) + { + nFluids++; + maxId = max(maxId, starCellId); + + if (!cellTable_.found(cellTableId)) + { + cellTable_.setName(cellTableId); + cellTable_.setMaterial(cellTableId, "fluid"); + } + } + else if (typeId == starcdSolidType) + { + nSolids++; + if (keepSolids) + { + maxId = max(maxId, starCellId); + } + + if (!cellTable_.found(cellTableId)) + { + cellTable_.setName(cellTableId); + cellTable_.setMaterial(cellTableId, "solid"); + } + + } + else if (typeId == starcdBaffleType) + { + // baffles have no cellTable entry + nBaffles++; + maxId = max(maxId, starCellId); + } + else if (typeId == starcdShellType) + { + nShells++; + if (!cellTable_.found(cellTableId)) + { + cellTable_.setName(cellTableId); + cellTable_.setMaterial(cellTableId, "shell"); + } + } + + } + } + + Info<< "Number of fluids = " << nFluids << nl + << "Number of baffles = " << nBaffles << nl; + if (keepSolids) + { + Info<< "Number of solids = " << nSolids << nl; + } + else + { + Info<< "Ignored solids = " << nSolids << nl; + } + Info<< "Ignored shells = " << nShells << endl; + + + label nCells; + if (keepSolids) + { + nCells = nFluids + nSolids; + } + else + { + nCells = nFluids; + } + + cellFaces_.setSize(nCells); + cellShapes_.setSize(nCells); + cellTableId_.setSize(nCells); + + // information for the interfaces + baffleFaces_.setSize(nBaffles); + + // extra space for baffles + origCellId_.setSize(nCells + nBaffles); + mapToFoamCellId_.setSize(maxId+1); + mapToFoamCellId_ = -1; + + + // avoid undefined shapes for polyhedra + cellShape genericShape(*unknownModel, labelList(0)); + + // Pass 2: + // construct cellFaces_ and possibly cellShapes_ + if (nCells <= 0) + { + FatalErrorIn("meshReaders::STARCD::readCells()") + << "no cells in file " << inputName + << abort(FatalError); + } + else + { + IFstream is(inputName); + readHeader(is, fileSignature); + + labelList starLabels(64); + label lineLabel, shapeId, nLabels, cellTableId, typeId; + + label cellI = 0; + label baffleI = 0; + + while ((is >> lineLabel).good()) + { + label starCellId = lineLabel; + is >> shapeId + >> nLabels + >> cellTableId + >> typeId; + + if (nLabels > starLabels.size()) + { + starLabels.setSize(nLabels); + } + starLabels = -1; + + // read indices - max 8 per line + for (label i = 0; i < nLabels; ++i) + { + if ((i % 8) == 0) + { + is >> lineLabel; + } + is >> starLabels[i]; + } + + // skip solid cells + if (typeId == starcdSolidType && !keepSolids) + { + continue; + } + + // determine the foam cell shape + const cellModel* curModelPtr = NULL; + + // fluid/solid cells + switch (shapeId) + { + case starcdHex: + curModelPtr = hexModel; + break; + case starcdPrism: + curModelPtr = prismModel; + break; + case starcdTet: + curModelPtr = tetModel; + break; + case starcdPyr: + curModelPtr = pyrModel; + break; + } + + if (curModelPtr) + { + // primitive cell - use shapes + + // convert orig vertex Id to point label + bool isBad = false; + for (label i=0; i < nLabels; ++i) + { + label pointId = mapToFoamPointId_[starLabels[i]]; + if (pointId < 0) + { + Info<< "Cells inconsistent with vertex file. " + << "Star vertex " << starLabels[i] + << " does not exist" << endl; + isBad = true; + unknownVertices = true; + } + starLabels[i] = pointId; + } + + if (isBad) + { + continue; + } + + // record original cell number and lookup + origCellId_[cellI] = starCellId; + mapToFoamCellId_[starCellId] = cellI; + + cellTableId_[cellI] = cellTableId; + cellShapes_[cellI] = cellShape + ( + *curModelPtr, + SubList<label>(starLabels, nLabels) + ); + + cellFaces_[cellI] = cellShapes_[cellI].faces(); + cellI++; + } + else if (shapeId == starcdPoly) + { + // polyhedral cell + label nFaces = starLabels[0] - 1; + + // convert orig vertex id to point label + // start with offset (skip the index table) + bool isBad = false; + for (label i=starLabels[0]; i < nLabels; ++i) + { + label pointId = mapToFoamPointId_[starLabels[i]]; + if (pointId < 0) + { + Info<< "Cells inconsistent with vertex file. " + << "Star vertex " << starLabels[i] + << " does not exist" << endl; + isBad = true; + unknownVertices = true; + } + starLabels[i] = pointId; + } + + if (isBad) + { + continue; + } + + // traverse beg/end indices + faceList faces(nFaces); + label faceI = 0; + for (label i=0; i < nFaces; ++i) + { + label beg = starLabels[i]; + label n = starLabels[i+1] - beg; + + face f + ( + SubList<label>(starLabels, n, beg) + ); + + f.collapse(); + + // valid faces only + if (f.size() >= 3) + { + faces[faceI++] = f; + } + } + + if (nFaces > faceI) + { + Info<< "star cell " << starCellId << " has " + << (nFaces - faceI) + << " empty faces - could cause boundary addressing problems" + << endl; + + nFaces = faceI; + faces.setSize(nFaces); + } + + if (nFaces < 4) + { + FatalErrorIn("meshReaders::STARCD::readCells()") + << "star cell " << starCellId << " has " << nFaces + << abort(FatalError); + } + + // record original cell number and lookup + origCellId_[cellI] = starCellId; + mapToFoamCellId_[starCellId] = cellI; + + cellTableId_[cellI] = cellTableId; + cellShapes_[cellI] = genericShape; + cellFaces_[cellI] = faces; + cellI++; + } + else if (typeId == starcdBaffleType) + { + // baffles + + // convert orig vertex id to point label + bool isBad = false; + for (label i=0; i < nLabels; ++i) + { + label pointId = mapToFoamPointId_[starLabels[i]]; + if (pointId < 0) + { + Info<< "Baffles inconsistent with vertex file. " + << "Star vertex " << starLabels[i] + << " does not exist" << endl; + isBad = true; + unknownVertices = true; + } + starLabels[i] = pointId; + } + + if (isBad) + { + continue; + } + + + face f + ( + SubList<label>(starLabels, nLabels) + ); + + f.collapse(); + + // valid faces only + if (f.size() >= 3) + { + baffleFaces_[baffleI] = f; + // insert lookup addressing in normal list + mapToFoamCellId_[starCellId] = nCells + baffleI; + origCellId_[nCells + baffleI] = starCellId; + baffleI++; + } + } + } + + baffleFaces_.setSize(baffleI); + } + + if (unknownVertices) + { + FatalErrorIn("meshReaders::STARCD::readCells()") + << "cells with unknown vertices" + << abort(FatalError); + } + + // truncate lists + +#ifdef DEBUG_READING + Info<< "CELLS READ" << endl; +#endif + + // cleanup + mapToFoamPointId_.clear(); +} + +// read in the boundaries from the .bnd file +// +/*---------------------------------------------------------------------------*\ +Line 1: + PROSTAR_BOUNDARY [newline] + +Line 2: + <version> 0 0 0 0 0 0 0 [newline] + +Body: + <boundId> <cellId> <cellFace> <regionId> 0 <boundaryType> [newline] + +where boundaryType is truncated to 4 characters from one of the following: +INLET +PRESSSURE +OUTLET +BAFFLE +etc, +\*---------------------------------------------------------------------------*/ + +void Foam::meshReaders::STARCD::readBoundary +( + const fileName& inputName +) +{ + const word fileSignature = "PROSTAR_BOUNDARY"; + label nPatches = 0, nFaces = 0, nBafflePatches = 0, maxId = 0; + label lineLabel, starCellId, cellFaceId, starRegion, configNumber; + word patchType; + + labelList mapToFoamPatchId(1000, -1); + labelList nPatchFaces(1000, 0); + labelList origRegion(1000, 0); + patchTypes_.setSize(1000); + + // this is what we seem to need + // these MUST correspond to starToFoamFaceAddr + // + Map<label> faceLookupIndex; + + faceLookupIndex.insert(hexModel->index(), 0); + faceLookupIndex.insert(prismModel->index(), 1); + faceLookupIndex.insert(tetModel->index(), 2); + faceLookupIndex.insert(pyrModel->index(), 3); + + // Pass 1: + // collect + // no. of faces (nFaces), no. of patches (nPatches) + // and for each of these patches the number of faces + // (nPatchFaces[patchLabel]) + // + // and a conversion table from Star regions to (Foam) patchLabels + // + // additionally note the no. of baffle patches (nBafflePatches) + // so that we sort these to the end of the patch list + // - this makes it easier to transfer them to an adjacent patch if reqd + { + IFstream is(inputName); + + if (is.good()) + { + readHeader(is, fileSignature); + + while ((is >> lineLabel).good()) + { + nFaces++; + is >> starCellId + >> cellFaceId + >> starRegion + >> configNumber + >> patchType; + + // Build translation table to convert star patch to foam patch + label patchLabel = mapToFoamPatchId[starRegion]; + if (patchLabel == -1) + { + patchLabel = nPatches; + mapToFoamPatchId[starRegion] = patchLabel; + origRegion[patchLabel] = starRegion; + patchTypes_[patchLabel] = patchType; + + maxId = max(maxId, starRegion); + + if (patchType == "BAFF") // should actually be case-insensitive + { + nBafflePatches++; + } + nPatches++; + } + + nPatchFaces[patchLabel]++; + } + + if (nPatches == 0) + { + Info<< "No boundary faces in file " << inputName << endl; + } + } + else + { + Info<< "Could not read boundary file " << inputName << endl; + } + } + + // keep empty patch region in reserve + nPatches++; + Info<< "Number of patches = " << nPatches + << " (including extra for missing)" << endl; + + // resize + origRegion.setSize(nPatches); + patchTypes_.setSize(nPatches); + patchNames_.setSize(nPatches); + nPatchFaces.setSize(nPatches); + + // add our empty patch + origRegion[nPatches-1] = 0; + nPatchFaces[nPatches-1] = 0; + patchTypes_[nPatches-1] = "none"; + + // create names + // - use 'Label' entry from "constant/boundaryRegion" dictionary + forAll(patchTypes_, patchI) + { + bool foundName = false, foundType = false; + + Map<dictionary>::const_iterator + iter = boundaryRegion_.find(origRegion[patchI]); + + if + ( + iter != boundaryRegion_.end() + ) + { + if (iter().found("BoundaryType")) + { + iter().lookup("BoundaryType") >> patchTypes_[patchI]; + foundType = true; + } + + if (iter().found("Label")) + { + iter().lookup("Label") >> patchNames_[patchI]; + foundName = true; + } + } + + // consistent names, in long form and in lowercase + if (!foundType) + { + // transform + forAllIter(string, patchTypes_[patchI], i) + { + *i = tolower(*i); + } + + if (patchTypes_[patchI] == "symp") + { + patchTypes_[patchI] = "symplane"; + } + else if (patchTypes_[patchI] == "cycl") + { + patchTypes_[patchI] = "cyclic"; + } + else if (patchTypes_[patchI] == "baff") + { + patchTypes_[patchI] = "baffle"; + } + else if (patchTypes_[patchI] == "moni") + { + patchTypes_[patchI] = "monitoring"; + } + } + + // create a name if needed + if (!foundName) + { + patchNames_[patchI] = + patchTypes_[patchI] + "_" + name(origRegion[patchI]); + } + } + + // enforce name "Default_Boundary_Region" + patchNames_[nPatches-1] = defaultBoundaryName; + + // sort according to ascending region numbers, but leave + // Default_Boundary_Region as the last patch + { + SortableList<label> sortedOrder(SubList<label>(origRegion, nPatches-1)); + + labelList oldToNew = identity(nPatches); + forAll(sortedOrder, i) + { + oldToNew[sortedOrder.indices()[i]] = i; + } + + inplaceReorder(oldToNew, origRegion); + inplaceReorder(oldToNew, patchTypes_); + inplaceReorder(oldToNew, patchNames_); + inplaceReorder(oldToNew, nPatchFaces); + } + + // re-sort to have baffles near the end + nBafflePatches = 1; + if (nBafflePatches) + { + labelList oldToNew = identity(nPatches); + label newIndex = 0; + label baffleIndex = (nPatches-1 - nBafflePatches); + + for (label i=0; i < oldToNew.size()-1; ++i) + { + if (patchTypes_[i] == "baffle") + { + oldToNew[i] = baffleIndex++; + } + else + { + oldToNew[i] = newIndex++; + } + } + + inplaceReorder(oldToNew, origRegion); + inplaceReorder(oldToNew, patchTypes_); + inplaceReorder(oldToNew, patchNames_); + inplaceReorder(oldToNew, nPatchFaces); + } + + mapToFoamPatchId.setSize(maxId+1, -1); + forAll(origRegion, patchI) + { + mapToFoamPatchId[origRegion[patchI]] = patchI; + } + + boundaryIds_.setSize(nPatches); + forAll(boundaryIds_, patchI) + { + boundaryIds_[patchI].setSize(nPatchFaces[patchI]); + nPatchFaces[patchI] = 0; + } + + + // Pass 2: + // + if (nPatches > 1 && mapToFoamCellId_.size() > 1) + { + IFstream is(inputName); + readHeader(is, fileSignature); + + while ((is >> lineLabel).good()) + { + is + >> starCellId + >> cellFaceId + >> starRegion + >> configNumber + >> patchType; + + label patchI = mapToFoamPatchId[starRegion]; + + // zero-based indexing + cellFaceId--; + + label cellId = -1; + + // convert to FOAM cell number + if (starCellId < mapToFoamCellId_.size()) + { + cellId = mapToFoamCellId_[starCellId]; + } + + if (cellId < 0) + { + Info + << "Boundaries inconsistent with cell file. " + << "Star cell " << starCellId << " does not exist" + << endl; + } + else + { + // restrict lookup to volume cells (no baffles) + if (cellId < cellShapes_.size()) + { + label index = cellShapes_[cellId].model().index(); + if (faceLookupIndex.found(index)) + { + index = faceLookupIndex[index]; + cellFaceId = starToFoamFaceAddr[index][cellFaceId]; + } + } + else + { + // we currently use cellId >= nCells to tag baffles, + // we can also use a negative face number + cellFaceId = -1; + } + + boundaryIds_[patchI][nPatchFaces[patchI]] = + cellFaceIdentifier(cellId, cellFaceId); + +#ifdef DEBUG_BOUNDARY + Info<< "bnd " << cellId << " " << cellFaceId << endl; +#endif + // increment counter of faces in current patch + nPatchFaces[patchI]++; + } + } + } + + // retain original information in patchPhysicalTypes_ - overwrite latter + patchPhysicalTypes_.setSize(patchTypes_.size()); + + + forAll(boundaryIds_, patchI) + { + // resize - avoid invalid boundaries + if (nPatchFaces[patchI] < boundaryIds_[patchI].size()) + { + boundaryIds_[patchI].setSize(nPatchFaces[patchI]); + } + + word origType = patchTypes_[patchI]; + patchPhysicalTypes_[patchI] = origType; + + if (origType == "symplane") + { + patchTypes_[patchI] = symmetryPolyPatch::typeName; + patchPhysicalTypes_[patchI] = patchTypes_[patchI]; + } + else if (origType == "wall") + { + patchTypes_[patchI] = wallPolyPatch::typeName; + patchPhysicalTypes_[patchI] = patchTypes_[patchI]; + } + else if (origType == "cyclic") + { + // incorrect. should be cyclicPatch but this + // requires info on connected faces. + patchTypes_[patchI] = cyclicPolyPatch::typeName; + patchPhysicalTypes_[patchI] = patchTypes_[patchI]; + } + else if (origType == "baffle") + { + // incorrect. tag the patch until we get proper support. + // set physical type to a canonical "baffle" + patchTypes_[patchI] = emptyPolyPatch::typeName; + patchPhysicalTypes_[patchI] = "baffle"; + } + else + { + patchTypes_[patchI] = polyPatch::typeName; + } + + Info<< "patch " << patchI + << " (region " << origRegion[patchI] + << ": " << origType << ") type: '" << patchTypes_[patchI] + << "' name: " << patchNames_[patchI] << endl; + } + + // cleanup + mapToFoamCellId_.clear(); + cellShapes_.clear(); +} + + +// +// remove unused points +// +void Foam::meshReaders::STARCD::cullPoints() +{ + label nPoints = points_.size(); + labelList oldToNew(nPoints, -1); + + // loop through cell faces and note which points are being used + forAll(cellFaces_, cellI) + { + const faceList& faces = cellFaces_[cellI]; + forAll(faces, i) + { + const labelList& labels = faces[i]; + forAll(labels, j) + { + oldToNew[labels[j]]++; + } + } + } + + // the new ordering and the count of unused points + label pointI = 0; + forAll(oldToNew, i) + { + if (oldToNew[i] >= 0) + { + oldToNew[i] = pointI++; + } + } + + // report unused points + if (nPoints > pointI) + { + Info<< "Unused points = " << (nPoints - pointI) << endl; + nPoints = pointI; + + // adjust points and truncate + inplaceReorder(oldToNew, points_); + points_.setSize(nPoints); + + // adjust cellFaces - with mesh shapes this might be faster + forAll(cellFaces_, cellI) + { + faceList& faces = cellFaces_[cellI]; + forAll(faces, i) + { + inplaceRenumber(oldToNew, faces[i]); + } + } + + // adjust baffles + forAll(baffleFaces_, faceI) + { + inplaceRenumber(oldToNew, baffleFaces_[faceI]); + } + } +} + + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +bool Foam::meshReaders::STARCD::readGeometry +( + const scalar scaleFactor +) +{ + // Info<< "called meshReaders::STARCD::readGeometry" << endl; + + readPoints(geometryFile_ + ".vrt", scaleFactor); + readCells(geometryFile_ + ".cel"); + cullPoints(); + readBoundary(geometryFile_ + ".bnd"); + + return true; +} + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from reading a file +Foam::meshReaders::STARCD::STARCD +( + const fileName& prefix, + const objectRegistry& registry, + const scalar scaleFactor +) +: + meshReader(prefix, scaleFactor), + cellShapes_(0), + mapToFoamPointId_(0), + mapToFoamCellId_(0) +{ + readAux(registry); +} + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::meshReaders::STARCD::~STARCD() +{} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/meshReader/starcd/STARCDMeshReader.H b/src/conversion/meshReader/starcd/STARCDMeshReader.H new file mode 100644 index 0000000000000000000000000000000000000000..ce8873360875cd584f86154dcc6ac8b1985776e4 --- /dev/null +++ b/src/conversion/meshReader/starcd/STARCDMeshReader.H @@ -0,0 +1,176 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::meshReaders::STARCD + +Description + Read pro-STAR vrt/cel/bnd files. + The protected data in meshReader are filled. + + Starting with pro-STAR version 4, the files have become easier to read. + - vertices are space-delimited. + - the cell format is logical. + - trimmed and degenerate cells are saved as polyhedral. + - the boundaries corresponds to cells and their faces. + +SourceFiles + STARCDMeshReader.C + +\*---------------------------------------------------------------------------*/ + +#ifndef STARCDMeshReader_H +#define STARCDMeshReader_H + +# include "meshReader.H" +# include "boundaryRegion.H" +# include "cellShape.H" +# include "IFstream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace meshReaders +{ + +/*---------------------------------------------------------------------------*\ + Class meshReaders::STARCD Declaration +\*---------------------------------------------------------------------------*/ + +class STARCD +: + public meshReader +{ + +protected: + + // Private Data + static const char* defaultBoundaryName; + static const char* defaultSolidBoundaryName; + + //- Face addressing from pro-STAR faces -> OpenFOAM faces + static const int starToFoamFaceAddr[4][6]; + + //- Cell shapes + cellShapeList cellShapes_; + + //- Point labels (imported Point numbering not necessarily contiguous) + labelList mapToFoamPointId_; + + //- Cell labels (imported Cell numbering not necessarily contiguous) + labelList mapToFoamCellId_; + + //- boundary region data + boundaryRegion boundaryRegion_; + + // Private Member Functions + + //- Disallow default bitwise copy construct + STARCD(const STARCD&); + + //- Disallow default bitwise assignment + void operator=(const STARCD&); + + //- Read the mesh from the file(s) + virtual bool readGeometry(const scalar scaleFactor = 1.0); + + //- read points from file + void readPoints(const fileName&, const scalar scaleFactor); + + //- read cell connectivities from file + virtual void readCells(const fileName&); + + //- remove unused points + void cullPoints(); + + //- read boundary (cell/face) definitions + void readBoundary(const fileName&); + + //- read auxiliary data from constant/{boundaryRegion,cellTable} + void readAux(const objectRegistry&); + + //- read and discard to newline + static void readToNewline(IFstream&); + + //- read header + static bool readHeader(IFstream&, word fileSignature); + +protected: + + enum cellType + { + starcdFluidType = 1, + starcdSolidType = 2, + starcdBaffleType = 3, + starcdShellType = 4, + starcdLineType = 5, + starcdPointType = 6 + }; + + enum shapeType + { + starcdPoint = 1, + starcdLine = 2, + starcdShell = 3, + starcdHex = 11, + starcdPrism = 12, + starcdTet = 13, + starcdPyr = 14, + starcdPoly = 255 + }; + + +public: + + //- keep solids (default false) + static bool keepSolids; + + // Constructors + + //- Construct from case name + STARCD + ( + const fileName& prefix, + const objectRegistry&, + const scalar scaleFactor = 1.0 + ); + + // Destructor + virtual ~STARCD(); + + // Member Functions + +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace meshReaders + +} // End namespace Foam + +#endif + +// ************************************************************************* // diff --git a/src/conversion/meshTables/README b/src/conversion/meshTables/README new file mode 100644 index 0000000000000000000000000000000000000000..56c47002412921408f0c178af6c4693bbf502ca8 --- /dev/null +++ b/src/conversion/meshTables/README @@ -0,0 +1,25 @@ +Star-CD uses a so-called 'cell table' to organize properties. The ccm and +star4 converters preserve this information as a Map of dictionaries under +"constant/cellTable" and as cell data under "constant/polyMesh/cellTableId". + +The combination of both files allows subsequent creating of cellSets and +cellZones for any combination of properties (eg, porosities and solids). + +Additionally, the reverse converters can use this information when +converting foam meshes back to the Star-CD formats. + +The names of the dictionary elements (eg, Label, MaterialType, etc) are +chosen to match those used by the ccm-format. + +Here is a sample dictionary entry: + +<int> // unique positive int +{ + Label <word>; // optional + MaterialType <word>; // optional (fluid|solid) + MaterialId <int>; // optional + PorosityId <int>; // optional + GroupId <int>; // optional + SpinId <int>; // optional +} + diff --git a/src/conversion/meshTables/boundaryRegion.C b/src/conversion/meshTables/boundaryRegion.C new file mode 100644 index 0000000000000000000000000000000000000000..8af5a0e1664e060bbc8b364b31917e19785a6463 --- /dev/null +++ b/src/conversion/meshTables/boundaryRegion.C @@ -0,0 +1,268 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "boundaryRegion.H" +#include "IOMap.H" +#include "OFstream.H" + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::boundaryRegion::boundaryRegion() +: + Map<dictionary>() +{} + + +// read constant/boundaryRegion (IOMap<dictionary>) +Foam::boundaryRegion::boundaryRegion +( + const objectRegistry& registry, + const word& name, + const fileName& instance +) +: + Map<dictionary>() +{ + readDict(registry, name, instance); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::boundaryRegion::~boundaryRegion() +{} + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +Foam::label Foam::boundaryRegion::append(const dictionary& dict) +{ + label maxId = -1; + forAllConstIter(Map<dictionary>, *this, iter) + { + if (maxId < iter.key()) + { + maxId = iter.key(); + } + } + + insert(++maxId, dict); + return maxId; +} + + +Foam::Map<Foam::word> +Foam::boundaryRegion::names() const +{ + Map<word> lookup; + + forAllConstIter(Map<dictionary>, *this, iter) + { + word value = "boundaryRegion_" + Foam::name(iter.key()); + iter().readIfPresent("Label", value); + + lookup.insert(iter.key(), value); + } + + return lookup; +} + + +Foam::Map<Foam::word> +Foam::boundaryRegion::boundaryTypes() const +{ + Map<word> lookup; + + forAllConstIter(Map<dictionary>, *this, iter) + { + word value = "patch"; + iter().readIfPresent("BoundaryType", value); + lookup.insert(iter.key(), value); + } + + return lookup; +} + + +Foam::label Foam::boundaryRegion::findIndex(const word& name) const +{ + forAllConstIter(Map<dictionary>, *this, iter) + { + word theName; + if (iter().readIfPresent("Label", theName)) + { + if (theName == name) + { + return iter.key(); + } + } + } + + return -1; +} + + +Foam::word Foam::boundaryRegion::boundaryType(const word& name) const +{ + word bndType = "patch"; + + label id = this->findIndex(name); + if (id >= 0) + { + const dictionary& dict = operator[](id); + dict.readIfPresent("BoundaryType", bndType); + } + + return bndType; +} + + +// read constant/boundaryRegion (IOMap<dictionary>) +void Foam::boundaryRegion::readDict +( + const objectRegistry& registry, + const word& name, + const fileName& instance +) +{ + clear(); + + // read constant/dictName + IOMap<dictionary> ioObj + ( + IOobject + ( + name, + instance, + registry, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE, + false + ) + ); + + if (ioObj.headerOk()) + { + *this = ioObj; + } + else + { + Info<< "no constant/boundaryRegion information available" << endl; + } +} + + +// write constant/boundaryRegion for later reuse +void Foam::boundaryRegion::writeDict +( + const objectRegistry& registry, + const word& name, + const fileName& instance +) const +{ + // write constant/dictName + IOMap<dictionary> ioObj + ( + IOobject + ( + name, + instance, + registry, + IOobject::NO_READ, + IOobject::NO_WRITE, + false + ) + ); + + ioObj.note() = "persistent data for thirdParty mesh <-> OpenFOAM translation"; + + Info<< "Writing " << ioObj.name() << " to " << ioObj.objectPath() << endl; + + OFstream os(ioObj.objectPath()); + ioObj.writeHeader(os); + os << *this; +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + + +void Foam::boundaryRegion::operator=(const boundaryRegion& rhs) +{ + Map<dictionary>::operator=(rhs); +} + +void Foam::boundaryRegion::operator=(const Map<dictionary>& rhs) +{ + Map<dictionary>::operator=(rhs); +} + + +// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * // + +void Foam::boundaryRegion::rename(const dictionary& dict) +{ + if (!dict.size()) + { + return; + } + + Map<word> mapping; + + forAllConstIter(dictionary, dict, iter) + { + word oldName(iter().stream()); + + label id = this->findIndex(oldName); + if (id >= 0) + { + mapping.insert(id, iter().keyword()); + } + } + + if (mapping.size()) + { + forAllConstIter(Map<word>, mapping, iter) + { + label id = iter.key(); + word oldName(operator[](id).lookup("Label")); + word newName(iter()); + + dictionary newDict(operator[](id)); + newDict.remove("Label"); + newDict.add("Label", newName); + + this->set(id, newDict); + Info<< "rename patch: " << newName << " <- " << oldName << endl; + } + } +} + +// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/meshTables/boundaryRegion.H b/src/conversion/meshTables/boundaryRegion.H new file mode 100644 index 0000000000000000000000000000000000000000..ba5976d4a5e7cb2c441135ff3cf94afca17d3965 --- /dev/null +++ b/src/conversion/meshTables/boundaryRegion.H @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::boundaryRegion + +Description + The boundaryRegion persistent data saved as a Map<dictionary>. + + The meshReader supports boundaryRegion information. + + The <tt>constant/boundaryRegion</tt> file is an @c IOMap<dictionary> + that is used to save the information persistently. + It contains the boundaryRegion information of the following form: + + @verbatim + ( + INT + { + BoundaryType WORD; + Label WORD; + } + ... + ) + @endverbatim + +SourceFiles + boundaryRegion.C + +\*---------------------------------------------------------------------------*/ + +#ifndef boundaryRegion_H +#define boundaryRegion_H + +#include "polyMesh.H" +#include "Map.H" +#include "dictionary.H" +#include "labelList.H" +#include "wordList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class boundaryRegion Declaration +\*---------------------------------------------------------------------------*/ + +class boundaryRegion +: + public Map<dictionary> +{ + // Private data + + // Private Member Functions + + //- Disallow default bitwise copy construct + boundaryRegion(const boundaryRegion&); + +public: + // Static Members + + // Constructors + + //- Construct null + boundaryRegion(); + + //- Construct read from registry, name. instance + boundaryRegion + ( + const objectRegistry&, + const word& name = "boundaryRegion", + const fileName& instance = "constant" + ); + + + // Destructor + ~boundaryRegion(); + + + // Member Functions + + //- Append to the end, return index + label append(const dictionary&); + + //- Return index corresponding to patch 'name' + // returns -1 if not found + label findIndex(const word& name) const; + + //- Return a Map of (id => name) + Map<word> names() const; + + //- Return a Map of (id => type) + Map<word> boundaryTypes() const; + + //- Return BoundaryType corresponding to patch 'name' + word boundaryType(const word& name) const; + + //- Read constant/boundaryRegion + void readDict + ( + const objectRegistry&, + const word& name = "boundaryRegion", + const fileName& instance = "constant" + ); + + + //- Write constant/boundaryRegion for later reuse + void writeDict + ( + const objectRegistry&, + const word& name = "boundaryRegion", + const fileName& instance = "constant" + ) const; + + + // Member Operators + + //- Assignment + void operator=(const boundaryRegion&); + + //- Assign from Map<dictionary> + void operator=(const Map<dictionary>&); + + + // Friend Functions + + //- Rename regions + // each dictionary entry is a single word: + // @verbatim + // newPatchName originalName; + // @endverbatim + void rename(const dictionary&); + +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +#endif + +// ************************************************************************* // diff --git a/src/conversion/meshTables/cellTable.C b/src/conversion/meshTables/cellTable.C new file mode 100644 index 0000000000000000000000000000000000000000..66e39a4cb9f8d15838049c0acd65d12c6b34f94b --- /dev/null +++ b/src/conversion/meshTables/cellTable.C @@ -0,0 +1,587 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Description + +\*---------------------------------------------------------------------------*/ + +#include "cellTable.H" +#include "IOMap.H" +#include "OFstream.H" +#include "wordList.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const char* const Foam::cellTable::defaultMaterial_ = "fluid"; + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +//- map from cellTable Id -> zone number (unmapped = -1) +Foam::labelList Foam::cellTable::zoneMap() const +{ + label maxId = 0; + forAllConstIter(Map<dictionary>, *this, iter) + { + if (maxId < iter.key()) + { + maxId = iter.key(); + } + } + + label zoneI = 0; + labelList list(maxId+1, -1); + + forAllConstIter(Map<dictionary>, *this, iter) + { + list[iter.key()] = zoneI++; + } + + return list; +} + + +Foam::wordList Foam::cellTable::namesList() const +{ + Map<word> lookup = names(); + wordList lst(lookup.size()); + + label n = 0; + forAllConstIter(Map<word>, lookup, iter) + { + lst[n] = iter(); + } + + lst.setSize(n); + + return lst; +} + + +// add required entries - MaterialType +void Foam::cellTable::addDefaults() +{ + forAllIter(Map<dictionary>, *this, iter) + { + if (!iter().found("MaterialType")) + { + iter().add("MaterialType", defaultMaterial_); + } + } +} + + +void Foam::cellTable::setEntry +( + const label& id, + const word& keyWord, + const word& value +) +{ + dictionary dict; + dict.add(keyWord, value); + + iterator iter = find(id); + if (iter != end()) + { + iter().merge(dict); + } + else + { + insert(id, dict); + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + + +Foam::cellTable::cellTable() +: + Map<dictionary>() +{} + + +// read constant/cellTable (IOMap<dictionary>) +Foam::cellTable::cellTable +( + const objectRegistry& registry, + const word& name, + const fileName& instance +) +: + Map<dictionary>() +{ + readDict(registry, name, instance); +} + + +// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::cellTable::~cellTable() +{} + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +Foam::label Foam::cellTable::append(const dictionary& dict) +{ + label maxId = -1; + forAllConstIter(Map<dictionary>, *this, iter) + { + if (maxId < iter.key()) + { + maxId = iter.key(); + } + } + + insert(++maxId, dict); + return maxId; +} + + +Foam::Map<Foam::word> +Foam::cellTable::names() const +{ + Map<word> lookup; + + forAllConstIter(Map<dictionary>, *this, iter) + { + word theName = "cellTable_" + Foam::name(iter.key()); + + iter().readIfPresent("Label", theName); + + lookup.insert(iter.key(), theName); + } + + return lookup; +} + + +Foam::word Foam::cellTable::name(const label& id) const +{ + const_iterator iter = find(id); + + word theName = "cellTable_" + Foam::name(id); + if (iter != end()) + { + iter().readIfPresent("Label", theName); + } + + return theName; +} + + +Foam::label Foam::cellTable::findIndex(const word& name) const +{ + forAllConstIter(Map<dictionary>, *this, iter) + { + word theName; + if (iter().readIfPresent("Label", theName)) + { + if (theName == name) + { + return iter.key(); + } + } + } + + return -1; +} + + +Foam::Map<Foam::word> +Foam::cellTable::selectType(const word& materialType) const +{ + Map<word> lookup; + + forAllConstIter(Map<dictionary>, *this, iter) + { + word matl(defaultMaterial_); + + iter().readIfPresent("MaterialType", matl); + + if (matl == materialType) + { + word theName = "cellTable_" + Foam::name(iter.key()); + + iter().readIfPresent("Label", theName); + + lookup.insert(iter.key(), theName); + } + } + + return lookup; +} + + +Foam::Map<Foam::word> +Foam::cellTable::fluids() const +{ + return selectType("fluid"); +} + + +Foam::Map<Foam::word> +Foam::cellTable::solids() const +{ + return selectType("solid"); +} + + +Foam::Map<Foam::word> +Foam::cellTable::shells() const +{ + return selectType("shell"); +} + + +Foam::Map<Foam::word> +Foam::cellTable::materialTypes() const +{ + Map<word> lookup; + + forAllConstIter(Map<dictionary>, *this, iter) + { + word matlType(defaultMaterial_); + + iter().readIfPresent("MaterialType", matlType); + + lookup.insert(iter.key(), matlType); + } + + return lookup; +} + + +//- assign material Type +void Foam::cellTable::setMaterial(const label& id, const word& matlType) +{ + setEntry(id, "MaterialType", matlType); +} + + +void Foam::cellTable::setName(const label& id, const word& name) +{ + setEntry(id, "Label", name); +} + + +void Foam::cellTable::setName(const label& id) +{ + iterator iter = find(id); + + if (iter == end() || !iter().found("Label")) + { + setName(id, "cellTable_" + ::Foam::name(id)); + } +} + + +// read constant/cellTable (IOMap<dictionary>) +void Foam::cellTable::readDict +( + const objectRegistry& registry, + const word& name, + const fileName& instance +) +{ + clear(); + + // read constant/dictName + IOMap<dictionary> ioObj + ( + IOobject + ( + name, + instance, + registry, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE, + false + ) + ); + + if (ioObj.headerOk()) + { + *this = ioObj; + addDefaults(); + } + else + { + Info<< "no constant/cellTable information available" << endl; + } +} + + +// write constant/cellTable for later reuse +void Foam::cellTable::writeDict +( + const objectRegistry& registry, + const word& name, + const fileName& instance +) const +{ + // write constant/dictName + IOMap<dictionary> ioObj + ( + IOobject + ( + name, + instance, + registry, + IOobject::NO_READ, + IOobject::NO_WRITE, + false + ) + ); + + ioObj.note() = "persistent data for thirdParty mesh <-> OpenFOAM translation"; + + Info<< "Writing " << ioObj.name() << " to " << ioObj.objectPath() << endl; + + OFstream os(ioObj.objectPath()); + ioObj.writeHeader(os); + os << *this; +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + + +void Foam::cellTable::operator=(const cellTable& rhs) +{ + Map<dictionary>::operator=(rhs); + addDefaults(); +} + +void Foam::cellTable::operator=(const Map<dictionary>& rhs) +{ + Map<dictionary>::operator=(rhs); + addDefaults(); +} + +void Foam::cellTable::operator=(const polyMesh& mesh) +{ + Map<dictionary> zoneDict; + + // create cellTableId and cellTable based on cellZones + label nZoneCells = 0; + + wordList zoneNames = mesh.cellZones().names(); + label unZonedType = zoneNames.size() + 1; + + // do cell zones + forAll(mesh.cellZones(), zoneI) + { + const cellZone& cZone = mesh.cellZones()[zoneI]; + nZoneCells += cZone.size(); + + dictionary dict; + dict.add("Label", zoneNames[zoneI]); + zoneDict.insert(zoneI + 1, dict); + } + + // collect unzoned cells + // special case: no zones at all - do entire mesh + if (nZoneCells == 0) + { + zoneDict.clear(); + unZonedType = 1; + } + + if (mesh.nCells() > nZoneCells) + { + zoneDict.insert + ( + unZonedType, + dictionary + ( + IStringStream("Label cells;")() + ) + ); + } + + Map<dictionary>::operator=(zoneDict); + addDefaults(); +} + + +// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * // + + +// attach cellZones based on the cellTable Id +// - any other values can be extracted later from the cellTable dictionary +void Foam::cellTable::addCellZones +( + polyMesh& mesh, + const labelList& tableIds +) const +{ + labelList typeToZone = zoneMap(); + wordList zoneNames = namesList(); + + List<DynamicList<label> > zoneCells(size()); + + forAll(tableIds, cellI) + { + label zoneI = typeToZone[tableIds[cellI]]; + if (zoneI >= 0) + { + zoneCells[zoneI].append(cellI); + } + } + + // avoid empty zones + labelList zoneUsed(zoneCells.size()); + + label nZone = 0; + forAll(zoneCells, zoneI) + { + zoneCells[zoneI].shrink(); + if (zoneCells[zoneI].size() > 0) + { + zoneUsed[nZone++] = zoneI; + } + } + zoneUsed.setSize(nZone); + + mesh.cellZones().clear(); + if (nZone <= 1) + { + Info<< "cellZones not used" << endl; + return; + } + mesh.cellZones().setSize(nZone); + + forAll(zoneUsed, zoneI) + { + const label origZoneI = zoneUsed[zoneI]; + + Info<< "cellZone " << zoneI + << " (size: " << zoneCells[origZoneI].size() << ") name: " + << zoneNames[origZoneI] << endl; + + mesh.cellZones().set + ( + zoneI, + new cellZone + ( + zoneNames[origZoneI], + zoneCells[origZoneI], + zoneI, + mesh.cellZones() + ) + ); + } + mesh.cellZones().writeOpt() = IOobject::AUTO_WRITE; +} + + +void Foam::cellTable::combine(const dictionary& dict, labelList& tableIds) +{ + if (!dict.size()) + { + return; + } + + bool remap = false; + labelList mapping(identity(max(this->toc()) + 1)); + + forAllConstIter (dictionary, dict, iter) + { + wordList zoneNames(iter().stream()); + labelList zoneIndex(zoneNames.size()); + + label nElem = 0; + forAll (zoneNames, zoneI) + { + zoneIndex[nElem] = this->findIndex(zoneNames[zoneI]); + if (zoneIndex[nElem] >= 0) + { + if (zoneI != nElem) + { + zoneNames[nElem] = zoneNames[zoneI]; + } + ++nElem; + } + } + + zoneIndex.setSize(nElem); + zoneNames.setSize(nElem); + + if (nElem) + { + remap = true; + label targetId = this->findIndex(iter().keyword()); + + Info<< "combine cellTable: " << iter().keyword(); + if (targetId >= 0) + { + Info<< " += ("; + } + else + { + Info<< " = ("; + } + forAll (zoneNames, zoneI) + { + Info<< " " << zoneNames[zoneI]; + } + Info<< " )" << endl; + + // re-use the first element if possible + if (targetId < 0) + { + targetId = min(zoneIndex); + dictionary newDict(operator[](targetId)); + + newDict.remove("Label"); + newDict.add("Label", iter().keyword()); + this->set(targetId, newDict); + } + + forAll (zoneIndex, zoneI) + { + label idx = zoneIndex[zoneI]; + if (idx != targetId && idx >= 0) + { + mapping[idx] = targetId; + this->erase(idx); + } + } + } + } + + if (remap) + { + inplaceRenumber(mapping, tableIds); + } +} + +// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/meshTables/cellTable.H b/src/conversion/meshTables/cellTable.H new file mode 100644 index 0000000000000000000000000000000000000000..a0e092c7eec6c481871d8fb811ba787051a30836 --- /dev/null +++ b/src/conversion/meshTables/cellTable.H @@ -0,0 +1,207 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::cellTable + +Description + The cellTable persistent data saved as a Map<dictionary>. + + The meshReader supports cellTable information. + + The <tt>constant/cellTable</tt> file is an @c IOMap<dictionary> that is + used to save the information persistently. It contains the cellTable + information of the following form: + + @verbatim + ( + ID + { + Label WORD; + MaterialType WORD; + MaterialId INT; + PorosityId INT; + ColorIdx INT; + ... + } + ... + ) + @endverbatim + + If the @a Label is missing, a value <tt>cellTable_{ID}</tt> will be + inferred. If the @a MaterialType is missing, the value @a fluid will + be inferred. + +SourceFiles + cellTable.C + +\*---------------------------------------------------------------------------*/ + +#ifndef cellTable_H +#define cellTable_H + +#include "polyMesh.H" +#include "Map.H" +#include "dictionary.H" +#include "labelList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class cellTable Declaration +\*---------------------------------------------------------------------------*/ + +class cellTable +: + public Map<dictionary> +{ + // Private data + static const char* const defaultMaterial_; + + // Private Member Functions + + //- Map from cellTable ID => zone number (unmapped = -1) + labelList zoneMap() const; + + //- A contiguous list of cellTable names + List<word> namesList() const; + + //- Add required entries - MaterialType + void addDefaults(); + + void setEntry(const label& id, const word& keyWord, const word& value); + + //- Disallow default bitwise copy construct + cellTable(const cellTable&); + +public: + // Static Members + + // Constructors + + //- Construct null + cellTable(); + + //- Construct read from registry, name. instance + cellTable + ( + const objectRegistry&, + const word& name = "cellTable", + const fileName& instance = "constant" + ); + + + // Destructor + ~cellTable(); + + + // Member Functions + + //- Append to the end, return index + label append(const dictionary&); + + //- Return index corresponding to name + // returns -1 if not found + label findIndex(const word& name) const; + + //- Return the name corresponding to id + // returns cellTable_ID if not otherwise defined + word name(const label& id) const; + + //- Return a Map of (id => name) + Map<word> names() const; + + //- Return a Map of (id => name) for materialType (fluid | solid | shell) + Map<word> selectType(const word& materialType) const; + + //- Return a Map of (id => name) for fluids + Map<word> fluids() const; + + //- Return a Map of (id => name) for shells + Map<word> shells() const; + + //- Return a Map of (id => name) for solids + Map<word> solids() const; + + //- Return a Map of (id => fluid|solid|shell) + Map<word> materialTypes() const; + + //- Assign material Type + void setMaterial(const label&, const word&); + + //- Assign name + void setName(const label&, const word&); + + //- Assign default name if not already set + void setName(const label&); + + //- Read constant/cellTable + void readDict + ( + const objectRegistry&, + const word& name = "cellTable", + const fileName& instance = "constant" + ); + + //- write constant/cellTable for later reuse + void writeDict + ( + const objectRegistry&, + const word& name = "cellTable", + const fileName& instance = "constant" + ) const; + + // Member Operators + + //- Assignment + void operator=(const cellTable&); + + //- Assign from Map<dictionary> + void operator=(const Map<dictionary>&); + + //- Assign from cellZones + void operator=(const polyMesh&); + + + // Friend Functions + + //- Classify tableIds into cellZones according to the cellTable + void addCellZones(polyMesh&, const labelList& tableIds) const; + + //- Combine tableIds together + // each dictionary entry is a wordList + void combine(const dictionary&, labelList& tableIds); + +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +#endif + +// ************************************************************************* // diff --git a/src/conversion/meshWriter/meshWriter.C b/src/conversion/meshWriter/meshWriter.C new file mode 100644 index 0000000000000000000000000000000000000000..ca9eeb019026d2756ad5b90832394503990a7798 --- /dev/null +++ b/src/conversion/meshWriter/meshWriter.C @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*----------------------------------------------------------------------------*/ + +#include "meshWriter.H" +#include "cellModeller.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// Pointers to cell shape models +const Foam::cellModel* Foam::meshWriter::unknownModel = Foam::cellModeller:: +lookup +( + "unknown" +); +const Foam::cellModel* Foam::meshWriter::tetModel = Foam::cellModeller:: +lookup +( + "tet" +); +const Foam::cellModel* Foam::meshWriter::pyrModel = Foam::cellModeller:: +lookup +( + "pyr" +); +const Foam::cellModel* Foam::meshWriter::prismModel = Foam::cellModeller:: +lookup +( + "prism" +); +const Foam::cellModel* Foam::meshWriter::hexModel = Foam::cellModeller:: +lookup +( + "hex" +); + + +Foam::string Foam::meshWriter::defaultMeshName = "meshExport"; +Foam::string Foam::meshWriter::defaultSurfaceName = "surfExport"; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::meshWriter::meshWriter +( + const polyMesh& mesh, + const scalar scaleFactor +) +: + mesh_(mesh), + scaleFactor_(scaleFactor), + writeBoundary_(true), + boundaryRegion_(), + cellTable_(), + cellTableId_() +{} + + +// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * // + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::meshWriter::~meshWriter() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + + +// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * // + + +// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// ************************************************************************* // diff --git a/src/conversion/meshWriter/meshWriter.H b/src/conversion/meshWriter/meshWriter.H new file mode 100644 index 0000000000000000000000000000000000000000..866bd0072ffe4fb2671d8493b7c5c539410c827e --- /dev/null +++ b/src/conversion/meshWriter/meshWriter.H @@ -0,0 +1,218 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Namespace + Foam::meshWriters + +Description + A namespace for holding various types of mesh writers. + + +Class + Foam::meshWriter + +Description + write OpenFOAM meshes and/or results to another CFD format + - currently just STAR-CD + +@par Files + + "constant/boundaryRegion" is an IOMap<dictionary> that contains + the boundary type and names. eg, + @verbatim + ( + 0 + { + BoundaryType wall; + Label Default_Boundary_Region; + } + + 1 + { + BoundaryType inlet; + Label inlet_1; + } + + ... + + 4 + { + BoundaryType pressure; + Label outlet; + } + ) + @endverbatim + + +SourceFiles + meshWriterI.H + meshWriter.C + meshWriterIO.C + +\*---------------------------------------------------------------------------*/ + +#ifndef meshWriter_H +#define meshWriter_H + +#include "polyMesh.H" +#include "boundaryRegion.H" +#include "cellTable.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class meshWriter Declaration +\*---------------------------------------------------------------------------*/ + +class meshWriter +{ + // Private data + + // Private Member Functions + + //- Disallow default bitwise copy construct + meshWriter(const meshWriter&); + + //- Disallow default bitwise assignment + void operator=(const meshWriter&); + +protected: + // Protected data + + //- mesh reference + const polyMesh& mesh_; + + //- scaling factor for points (eg, [m] -> [mm]) + scalar scaleFactor_; + + //- write bnd file + bool writeBoundary_; + + //- boundaryRegion persistent data saved as a dictionary + boundaryRegion boundaryRegion_; + + //- cellTable persistent data saved as a dictionary + cellTable cellTable_; + + // cellTable IDs for each cell + labelList cellTableId_; + + //- Pointers to cell shape models + static const cellModel* unknownModel; + static const cellModel* tetModel; + static const cellModel* pyrModel; + static const cellModel* prismModel; + static const cellModel* hexModel; + +public: + + // Static data members + + static string defaultMeshName; + static string defaultSurfaceName; + + + // Constructors + + //- create a writer obejct + meshWriter + ( + const polyMesh&, + const scalar scaleFactor = 1.0 + ); + + + // Selectors + + // Destructor + + virtual ~meshWriter(); + + + // Member Functions + + // Access + + // Check + + // Edit + + //- set points scaling + void scaleFactor(const scalar scaling) + { + scaleFactor_ = scaling; + } + + //- suppress writing bnd file + void noBoundary() + { + writeBoundary_ = false; + } + + // Write + + //- write volume mesh + // subclass must to supply this method + virtual bool write + ( + const fileName& timeName = fileName::null + ) const = 0; + + //- write surface mesh with optional triangulation + // subclass could supply this information + virtual bool writeSurface + ( + const fileName& timeName = fileName::null, + const bool& triangulate = false + ) const + { + return false; + } + + // Member Operators + + // Friend Functions + + // Friend Operators + + // IOstream Operators +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// #include "meshWriterI.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/meshWriter/starcd/STARCDMeshWriter.C b/src/conversion/meshWriter/starcd/STARCDMeshWriter.C new file mode 100644 index 0000000000000000000000000000000000000000..f382f096060ab953c91032a8a20686d0bc16495a --- /dev/null +++ b/src/conversion/meshWriter/starcd/STARCDMeshWriter.C @@ -0,0 +1,757 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "STARCDMeshWriter.H" + +#include "Time.H" +#include "SortableList.H" +#include "OFstream.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// special boundary regions +const char* Foam::meshWriters::STARCD::defaultBoundaryName = + "Default_Boundary_Region"; + +// face addressing from foam faces -> pro-STAR faces for primitive shapes +const Foam::label Foam::meshWriters::STARCD::foamToStarFaceAddr[4][6] = +{ + { 4, 5, 2, 3, 0, 1 }, // 11 = pro-STAR hex + { 0, 1, 4, 5, 2, -1 }, // 12 = pro-STAR prism + { 5, 4, 2, 0, -1, -1 }, // 13 = pro-STAR tetra + { 0, 4, 3, 5, 2, -1 } // 14 = pro-STAR pyramid +}; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::label Foam::meshWriters::STARCD::findDefaultBoundary() const +{ + const polyBoundaryMesh& patches = mesh_.boundaryMesh(); + + label id = -1; + + // find Default_Boundary_Region if it exists + forAll(patches, patchI) + { + if (defaultBoundaryName == patches[patchI].name()) + { + id = patchI; + break; + } + } + return id; +} + + +void Foam::meshWriters::STARCD::getCellTable() +{ + // read constant/polyMesh/propertyName + IOList<label> ioList + ( + IOobject + ( + "cellTableId", + "constant", + polyMesh::meshSubDir, + mesh_, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE, + false + ) + ); + + bool useCellZones = false; + cellTableId_.setSize(mesh_.nCells(), -1); + + // get information from constant/polyMesh/cellTableId if possible + if (ioList.headerOk()) + { + if (ioList.size() == mesh_.nCells()) + { + cellTableId_.transfer(ioList); + + if (!cellTable_.size()) + { + Info<< "no cellTable information available" << endl; + } + } + else + { + WarningIn("STARCD::getCellTable()") + << ioList.objectPath() << " has incorrect number of cells " + << " - use cellZone information" + << endl; + + ioList.clear(); + useCellZones = true; + } + } + else + { + useCellZones = true; + } + + + if (useCellZones) + { + if (!cellTable_.size()) + { + Info<< "created cellTable from cellZones" << endl; + cellTable_ = mesh_; + } + + // track if there are unzoned cells + label nUnzoned = mesh_.nCells(); + + // get the cellZone <-> cellTable correspondence + Info<< "matching cellZones to cellTable" << endl; + + forAll (mesh_.cellZones(), zoneI) + { + const cellZone& cZone = mesh_.cellZones()[zoneI]; + if (cZone.size()) + { + nUnzoned -= cZone.size(); + + label tableId = cellTable_.findIndex(cZone.name()); + if (tableId < 0) + { + dictionary dict; + + dict.add("Label", cZone.name()); + dict.add("MaterialType", "fluid"); + tableId = cellTable_.append(dict); + } + + forAll (cZone, i) + { + cellTableId_[cZone[i]] = tableId; + } + } + } + + if (nUnzoned) + { + dictionary dict; + + dict.add("Label", "__unZonedCells__"); + dict.add("MaterialType", "fluid"); + label tableId = cellTable_.append(dict); + + forAll (cellTableId_, i) + { + if (cellTableId_[i] < 0) + { + cellTableId_[i] = tableId; + } + } + } + } +} + + +// Prostar 4+ header format +void Foam::meshWriters::STARCD::writeHeader +( + Ostream& os, + const char* filetype +) +{ + os << "PROSTAR_" << filetype << nl + << 4000 + << " " << 0 + << " " << 0 + << " " << 0 + << " " << 0 + << " " << 0 + << " " << 0 + << " " << 0 + << endl; +} + + +void Foam::meshWriters::STARCD::writePoints +( + const fileName& prefix +) const +{ + OFstream os(prefix + ".vrt"); + writeHeader(os, "VERTEX"); + + // Set the precision of the points data to 10 + os.precision(10); + + // force decimal point for Fortran input + os.setf(std::ios::showpoint); + + const pointField& points = mesh_.points(); + + Info<< "Writing " << os.name() << " : " + << points.size() << " points" << endl; + + forAll(points, ptI) + { + // convert [m] -> [mm] + os + << ptI + 1 << " " + << scaleFactor_ * points[ptI].x() << " " + << scaleFactor_ * points[ptI].y() << " " + << scaleFactor_ * points[ptI].z() << nl; + } + os.flush(); + +} + + +void Foam::meshWriters::STARCD::writeCells +( + const fileName& prefix +) const +{ + OFstream os(prefix + ".cel"); + writeHeader(os, "CELL"); + + // this is what we seem to need + // map foam cellModeller index -> star shape + Map<label> shapeLookupIndex; + shapeLookupIndex.insert(hexModel->index(), 11); + shapeLookupIndex.insert(prismModel->index(), 12); + shapeLookupIndex.insert(tetModel->index(), 13); + shapeLookupIndex.insert(pyrModel->index(), 14); + + const cellShapeList& shapes = mesh_.cellShapes(); + const cellList& cells = mesh_.cells(); + const faceList& faces = mesh_.faces(); + const labelList& owner = mesh_.faceOwner(); + + Info<< "Writing " << os.name() << " : " + << cells.size() << " cells" << endl; + + forAll(cells, cellId) + { + label tableId = cellTableId_[cellId]; + label materialType = 1; // 1(fluid) + if (cellTable_.found(tableId)) + { + const dictionary& dict = cellTable_[tableId]; + if (dict.found("MaterialType")) + { + word matType; + dict.lookup("MaterialType") >> matType; + if (matType == "solid") + { + materialType = 2; + } + + } + } + + const cellShape& shape = shapes[cellId]; + label mapIndex = shape.model().index(); + + // a registered primitive type + if (shapeLookupIndex.found(mapIndex)) + { + label shapeId = shapeLookupIndex[mapIndex]; + const labelList& vrtList = shapes[cellId]; + + os << cellId + 1 + << " " << shapeId + << " " << vrtList.size() + << " " << tableId + << " " << materialType; + + // primitives have <= 8 vertices, but prevent overrun anyhow + // indent following lines for ease of reading + label count = 0; + forAll(vrtList, i) + { + if ((count % 8) == 0) + { + os << nl + << " " << cellId + 1; + } + os << " " << vrtList[i] + 1; + count++; + } + os << endl; + + } + else + { + label shapeId = 255; // treat as general polyhedral + const labelList& cFaces = cells[cellId]; + + // create (beg,end) indices + List<label> indices(cFaces.size() + 1); + indices[0] = indices.size(); + + label count = indices.size(); + // determine the total number of vertices + forAll(cFaces, faceI) + { + count += faces[cFaces[faceI]].size(); + indices[faceI+1] = count; + } + + os << cellId + 1 + << " " << shapeId + << " " << count + << " " << tableId + << " " << materialType; + + // write indices - max 8 per line + // indent following lines for ease of reading + count = 0; + forAll(indices, i) + { + if ((count % 8) == 0) + { + os << nl + << " " << cellId + 1; + } + os << " " << indices[i]; + count++; + } + + // write faces - max 8 per line + forAll(cFaces, faceI) + { + label meshFace = cFaces[faceI]; + face f; + + if (owner[meshFace] == cellId) + { + f = faces[meshFace]; + } + else + { + f = faces[meshFace].reverseFace(); + } + + forAll(f, i) + { + if ((count % 8) == 0) + { + os << nl + << " " << cellId + 1; + } + + os << " " << f[i] + 1; + count++; + } + } + + os << endl; + } + } +} + + +void Foam::meshWriters::STARCD::writeBoundary +( + const fileName& prefix +) const +{ + OFstream os(prefix + ".bnd"); + writeHeader(os, "BOUNDARY"); + + const cellShapeList& shapes = mesh_.cellShapes(); + const cellList& cells = mesh_.cells(); + const faceList& faces = mesh_.faces(); + const labelList& owner = mesh_.faceOwner(); + const polyBoundaryMesh& patches = mesh_.boundaryMesh(); + + // this is what we seem to need + // these MUST correspond to foamToStarFaceAddr + // + Map<label> faceLookupIndex; + faceLookupIndex.insert(hexModel->index(), 0); + faceLookupIndex.insert(prismModel->index(), 1); + faceLookupIndex.insert(tetModel->index(), 2); + faceLookupIndex.insert(pyrModel->index(), 3); + + Info<< "Writing " << os.name() << " : " + << (mesh_.nFaces() - patches[0].start()) << " boundaries" << endl; + + + label defaultId = findDefaultBoundary(); + + // + // write boundary faces - skip Default_Boundary_Region entirely + // + label boundId = 0; + forAll(patches, patchI) + { + label regionId = patchI; + if (regionId == defaultId) + { + continue; // skip - already written + } + else if (defaultId == -1 || regionId < defaultId) + { + regionId++; + } + + label patchStart = patches[patchI].start(); + label patchSize = patches[patchI].size(); + word bndType = boundaryRegion_.boundaryType(patches[patchI].name()); + + for + ( + label faceI = patchStart; + faceI < (patchStart + patchSize); + ++faceI + ) + { + label cellId = owner[faceI]; + const labelList& cFaces = cells[cellId]; + const cellShape& shape = shapes[cellId]; + label cellFaceId = findIndex(cFaces, faceI); + + // Info<< "cell " << cellId + 1 << " face " << faceI + // << " == " << faces[faceI] + // << " is index " << cellFaceId << " from " << cFaces; + + // Unfortunately, the order of faces returned by + // primitiveMesh::cells() is not necessarily the same + // as defined by primitiveMesh::cellShapes() + // Thus, for registered primitive types, do the lookup ourselves. + // Finally, the cellModel face number is re-mapped to the + // STAR-CD local face number + + label mapIndex = shape.model().index(); + + // a registered primitive type + if (faceLookupIndex.found(mapIndex)) + { + const faceList sFaces = shape.faces(); + forAll(sFaces, sFaceI) + { + if (faces[faceI] == sFaces[sFaceI]) + { + cellFaceId = sFaceI; + break; + } + } + + mapIndex = faceLookupIndex[mapIndex]; + cellFaceId = foamToStarFaceAddr[mapIndex][cellFaceId]; + } + // Info<< endl; + + boundId++; + + os + << boundId + << " " << cellId + 1 + << " " << cellFaceId + 1 + << " " << regionId + << " " << 0 + << " " << bndType.c_str() + << endl; + } + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::meshWriters::STARCD::STARCD +( + const polyMesh& mesh, + const scalar scaleFactor +) +: + meshWriter(mesh, scaleFactor) +{ + boundaryRegion_.readDict(mesh_); + cellTable_.readDict(mesh_); + getCellTable(); +} + + +// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * // + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::meshWriters::STARCD::~STARCD() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::meshWriters::STARCD::rmFiles +( + const fileName& baseName +) const +{ + rm(baseName + ".vrt"); + rm(baseName + ".cel"); + rm(baseName + ".bnd"); + rm(baseName + ".inp"); +} + + +bool Foam::meshWriters::STARCD::write +( + const fileName& meshName +) const +{ + fileName baseName(meshName); + + if (!baseName.size()) + { + baseName = meshWriter::defaultMeshName; + + if + ( + mesh_.time().timeName() != "0" + && mesh_.time().timeName() != "constant" + ) + { + baseName += "_" + mesh_.time().timeName(); + } + } + + rmFiles(baseName); + writePoints(baseName); + writeCells(baseName); + + if (writeBoundary_) + { + writeBoundary(baseName); + } + + return true; +} + + +bool Foam::meshWriters::STARCD::writeSurface +( + const fileName& meshName, + const bool& triangulate +) const +{ + fileName baseName(meshName); + + if (!baseName.size()) + { + baseName = meshWriter::defaultSurfaceName; + + if + ( + mesh_.time().timeName() != "0" + && mesh_.time().timeName() != "constant" + ) + { + baseName += "_" + mesh_.time().timeName(); + } + } + + rmFiles(baseName); + + OFstream celFile(baseName + ".cel"); + writeHeader(celFile, "CELL"); + + Info << "Writing " << celFile.name() << endl; + + // mesh and patch info + const pointField& points = mesh_.points(); + const labelList& owner = mesh_.faceOwner(); + const faceList& meshFaces = mesh_.faces(); + const polyBoundaryMesh& patches = mesh_.boundaryMesh(); + + label shapeId = 3; // shell/baffle element + label typeId = 4; // 4(shell) + + // remember which points need to be written + labelHashSet pointHash; + + // write boundary faces as normal STAR-CD mesh + if (triangulate) + { + // cell Id has no particular meaning - just increment + // use the cellTable id from the patch Number + label cellId = 0; + + forAll(patches, patchI) + { + label patchStart = patches[patchI].start(); + label patchSize = patches[patchI].size(); + + label ctableId = patchI + 1; + + for + ( + label faceI = patchStart; + faceI < (patchStart + patchSize); + ++faceI + ) + { + const face& f = meshFaces[faceI]; + + label nTri = f.nTriangles(points); + faceList triFaces; + + // triangulate polygons, but not quads + if (nTri <= 2) + { + triFaces.setSize(1); + triFaces[0] = f; + } + else + { + triFaces.setSize(nTri); + nTri = 0; + f.triangles(points, nTri, triFaces); + } + + forAll(triFaces, faceI) + { + const labelList& vrtList = triFaces[faceI]; + + celFile + << cellId + 1 << " " + << shapeId << " " + << vrtList.size() << " " + << ctableId << " " + << typeId; + + // must be 3 (triangle) but could be quad + label count = 0; + forAll(vrtList, i) + { + if ((count % 8) == 0) + { + celFile + << nl + << " " << cellId + 1; + } + // remember which points we'll need to write + pointHash.insert(vrtList[i]); + celFile << " " << vrtList[i] + 1; + count++; + } + celFile << endl; + + cellId++; + } + } + } + } + else + { + // cell Id is the OpenFOAM face Id + // use the cellTable id from the face owner + // - allows separation of parts + forAll(patches, patchI) + { + label patchStart = patches[patchI].start(); + label patchSize = patches[patchI].size(); + + for + ( + label faceI = patchStart; + faceI < (patchStart + patchSize); + ++faceI + ) + { + const labelList& vrtList = meshFaces[faceI]; + label cellId = faceI; + + celFile + << cellId + 1 << " " + << shapeId << " " + << vrtList.size() << " " + << cellTableId_[owner[faceI]] << " " + << typeId; + + // likely <= 8 vertices, but prevent overrun anyhow + label count = 0; + forAll(vrtList, i) + { + if ((count % 8) == 0) + { + celFile + << nl + << " " << cellId + 1; + } + // remember which points we'll need to write + pointHash.insert(vrtList[i]); + celFile << " " << vrtList[i] + 1; + count++; + } + celFile << endl; + } + } + } + + OFstream vrtFile(baseName + ".vrt"); + writeHeader(vrtFile, "VERTEX"); + + vrtFile.precision(10); + vrtFile.setf(std::ios::showpoint); // force decimal point for Fortran + + Info << "Writing " << vrtFile.name() << endl; + + // build sorted table of contents + SortableList<label> toc(pointHash.size()); + { + label i = 0; + forAllConstIter(labelHashSet, pointHash, iter) + { + toc[i++] = iter.key(); + } + } + toc.sort(); + pointHash.clear(); + + // write points in sorted order + forAll(toc, i) + { + label vrtId = toc[i]; + vrtFile + << vrtId + 1 + << " " << scaleFactor_ * points[vrtId].x() + << " " << scaleFactor_ * points[vrtId].y() + << " " << scaleFactor_ * points[vrtId].z() + << endl; + } + + return true; +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/src/conversion/meshWriter/starcd/STARCDMeshWriter.H b/src/conversion/meshWriter/starcd/STARCDMeshWriter.H new file mode 100644 index 0000000000000000000000000000000000000000..1bbdf7dd455642c9d294721ad2889035daba84dd --- /dev/null +++ b/src/conversion/meshWriter/starcd/STARCDMeshWriter.H @@ -0,0 +1,167 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::meshWriters::STARCD + +Description + Writes polyMesh in pro-STAR (v4) bnd/cel/vrt format + + Alternatively, extracts the surface of the FOAM mesh into + pro-STAR (v4) .cel/.vrt/ format. + This can be useful, for example, for surface morphing in an external + package. + + The cellTableId and cellTable information are used (if available). + Otherwise the cellZones are used (if available). + +SourceFiles + STARCDMeshWriter.C + +\*---------------------------------------------------------------------------*/ + +#ifndef STARCDMeshWriter_H +#define STARCDMeshWriter_H + +#include "meshWriter.H" +#include "IOstream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace meshWriters +{ + +/*---------------------------------------------------------------------------*\ + Class meshWriters::STARCD Declaration +\*---------------------------------------------------------------------------*/ + +class STARCD +: + public meshWriter +{ + // Private Data + static const char* defaultBoundaryName; + + // Private Member Functions + + //- Disallow default bitwise copy construct + STARCD(const STARCD&); + + //- Disallow default bitwise assignment + void operator=(const STARCD&); + + //- pro-STAR 4+ header format + static void writeHeader(Ostream&, const char* filetype); + + //- write points + void writePoints(const fileName& baseName) const; + + //- write cells + void writeCells(const fileName& baseName) const; + + //- write boundary + void writeBoundary(const fileName& baseName) const; + + void getCellTable(); + + label findDefaultBoundary() const; + +public: + + // Static data members + + //- Face addressing from OpenFOAM faces -> pro-STAR faces + static const label foamToStarFaceAddr[4][6]; + + + // Constructors + + //- open a file for writing + STARCD + ( + const polyMesh&, + const scalar scaleFactor = 1.0 + ); + + // Selectors + + // Destructor + + virtual ~STARCD(); + + + // Member Functions + + // Access + + // Check + + // Edit + + // Write + + + //- Remove STAR-CD files for the baseName + void rmFiles(const fileName& baseName) const; + + //- write volume mesh + virtual bool write + ( + const fileName& meshName = fileName::null + ) const; + + //- write surface mesh with optional triangulation + virtual bool writeSurface + ( + const fileName& meshName = fileName::null, + const bool& triangulate = false + ) const; + + + // Member Operators + + // Friend Functions + + // Friend Operators + + // IOstream Operators +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace meshWriters + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/fields/fvPatchFields/derived/flowRateInletVelocity/flowRateInletVelocityFvPatchVectorField.C b/src/finiteVolume/fields/fvPatchFields/derived/flowRateInletVelocity/flowRateInletVelocityFvPatchVectorField.C index c3427b4bded0a4c28ae931f79021ee374d885ddd..2d2f6f204c49d2e26b6f09f888bd72f3b5bf58a8 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/flowRateInletVelocity/flowRateInletVelocityFvPatchVectorField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/flowRateInletVelocity/flowRateInletVelocityFvPatchVectorField.C @@ -156,8 +156,8 @@ void Foam::flowRateInletVelocityFvPatchVectorField::updateCoeffs() FatalErrorIn ( "flowRateInletVelocityFvPatchVectorField::updateCoeffs()" - ) << "dimensions of phi are incorrect" - << "\n on patch " << this->patch().name() + ) << "dimensions of " << phiName_ << " are incorrect" << nl + << " on patch " << this->patch().name() << " of field " << this->dimensionedInternalField().name() << " in file " << this->dimensionedInternalField().objectPath() << nl << exit(FatalError); diff --git a/src/finiteVolume/fields/fvPatchFields/derived/flowRateInletVelocity/flowRateInletVelocityFvPatchVectorField.H b/src/finiteVolume/fields/fvPatchFields/derived/flowRateInletVelocity/flowRateInletVelocityFvPatchVectorField.H index b0c8de9b2f018be80b6060eb2d87eba3214d2060..ff5b0e4afc09f4d06163fc2ca9de41a080f45b6c 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/flowRateInletVelocity/flowRateInletVelocityFvPatchVectorField.H +++ b/src/finiteVolume/fields/fvPatchFields/derived/flowRateInletVelocity/flowRateInletVelocityFvPatchVectorField.H @@ -26,12 +26,13 @@ Class Foam::flowRateInletVelocityFvPatchVectorField Description - Describes an volumetric/mass flow normal vector boundary condition by its + Describes a volumetric/mass flow normal vector boundary condition by its magnitude as an integral over its area. + The basis of the patch (volumetric or mass) is determined by the dimensions of the flux, phi. - The current density is used to correct the velocity when applying the mass - basis. + The current density is used to correct the velocity when applying the + mass basis. Example of the boundary condition specification: @verbatim diff --git a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingFlowRateInletVelocity/timeVaryingFlowRateInletVelocityFvPatchVectorField.H b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingFlowRateInletVelocity/timeVaryingFlowRateInletVelocityFvPatchVectorField.H index cbacacb4c545b205afe14eeffc82412729b7ad38..21198d936eaff29ec63932bf956f79abd57aa5af 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingFlowRateInletVelocity/timeVaryingFlowRateInletVelocityFvPatchVectorField.H +++ b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingFlowRateInletVelocity/timeVaryingFlowRateInletVelocityFvPatchVectorField.H @@ -46,7 +46,7 @@ Note - strange behaviour with potentialFoam since the U equation is not solved See Also - Foam::timeSeries and Foam::flowRateInletVelocityFvPatchVectorField + Foam::interpolationTable and Foam::flowRateInletVelocityFvPatchVectorField SourceFiles timeVaryingFlowRateInletVelocityFvPatchVectorField.C diff --git a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingUniformFixedValue/timeVaryingUniformFixedValueFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingUniformFixedValue/timeVaryingUniformFixedValueFvPatchField.H index bd073c24b1ce638b8c4d8307f4ccba9609bb3a07..b6ce246cc6d92dbfa4c2234abe7642823badb0f2 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingUniformFixedValue/timeVaryingUniformFixedValueFvPatchField.H +++ b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingUniformFixedValue/timeVaryingUniformFixedValueFvPatchField.H @@ -43,7 +43,7 @@ Note a uniformFixedValue patch. See Also - Foam::timeSeries and Foam::fixedValueFvPatchField + Foam::interpolationTable and Foam::fixedValueFvPatchField SourceFiles timeVaryingUniformFixedValueFvPatchField.C diff --git a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingUniformTotalPressure/timeVaryingUniformTotalPressureFvPatchScalarField.H b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingUniformTotalPressure/timeVaryingUniformTotalPressureFvPatchScalarField.H index 4bfead28d1cbd105ca4cbf6753f8a463e8147be7..8d02bcefeb872cdc2906e224de235591b8295d1c 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingUniformTotalPressure/timeVaryingUniformTotalPressureFvPatchScalarField.H +++ b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingUniformTotalPressure/timeVaryingUniformTotalPressureFvPatchScalarField.H @@ -26,8 +26,11 @@ Class Foam::timeVaryingUniformTotalPressureFvPatchScalarField Description - See timeVaryingUniformFixedValueFvPatchField.H - and totalPressureFvPatchScalarField.H + A time-varying form of a uniform total pressure boundary condition. + +See Also + Foam::timeVaryingUniformFixedValueFvPatchField + and Foam::totalPressureFvPatchScalarField.H SourceFiles timeVaryingUniformTotalPressureFvPatchScalarField.C diff --git a/tutorials/rhoPimpleFoam/angledDuct/0/U b/tutorials/rhoPimpleFoam/angledDuct/0/U index f18de82fff1381139696e2a69a48a5128a71e068..54bfd05ea9389f3d0f9782ef24163eb49cdf8d6e 100644 --- a/tutorials/rhoPimpleFoam/angledDuct/0/U +++ b/tutorials/rhoPimpleFoam/angledDuct/0/U @@ -42,8 +42,8 @@ boundaryField } inlet { - type massFlowRateInletVelocity; - massFlowRate 0.1; + type flowRateInletVelocity; + flowRate 0.1; value uniform (0 0 0); } outlet diff --git a/tutorials/rhoPorousSimpleFoam/angledDuctImplicit/0/U b/tutorials/rhoPorousSimpleFoam/angledDuctImplicit/0/U index e6ded2df85a075c0f57c3d5ddde201a2509a9509..afea1eb58d696c9239afc01401fc420db42598eb 100644 --- a/tutorials/rhoPorousSimpleFoam/angledDuctImplicit/0/U +++ b/tutorials/rhoPorousSimpleFoam/angledDuctImplicit/0/U @@ -42,8 +42,8 @@ boundaryField } inlet { - type massFlowRateInletVelocity; - massFlowRate 0.1; + type flowRateInletVelocity; + flowRate 0.1; value uniform (0 0 0); } outlet