#!/usr/bin/env bash # Generic external-flow OpenFOAM case for an arbitrary STL body (normalized L=1, # centred at origin). Steady RANS k-omega-SST, matching EZFlow non-dim (U=1, # rho=1, nu=1/Re). snappyHexMesh with feature capture + boundary layers. # Usage: of_external.sh source /usr/lib/openfoam/openfoam2512/etc/bashrc STL="$1"; RE="$2"; AREF="$3"; NAME="$4" NU=$(awk "BEGIN{printf \"%.8g\", 1.0/$RE}") K0=0.00375; OMEGA0=1.6 CASE=/root/of_ext/${NAME}_re${RE} MB="$FOAM_TUTORIALS/incompressible/simpleFoam/motorBike" echo "=== build $CASE (Re=$RE nu=$NU Aref=$AREF stl=$STL) ===" rm -rf "$CASE"; mkdir -p "$CASE/0" "$CASE/constant/triSurface" "$CASE/system" cp "$MB/system/fvSchemes" "$CASE/system/fvSchemes" cp "$MB/system/fvSolution" "$CASE/system/fvSolution" cp "$STL" "$CASE/constant/triSurface/body.stl" hdr(){ echo "FoamFile{version 2.0;format ascii;class $1;object $2;}"; } { hdr dictionary transportProperties; echo "transportModel Newtonian;"; echo "nu [0 2 -1 0 0 0 0] $NU;"; } > "$CASE/constant/transportProperties" { hdr dictionary turbulenceProperties; echo "simulationType RAS;"; echo "RAS{ RASModel kOmegaSST; turbulence on; printCoeffs on; }"; } \ > "$CASE/constant/turbulenceProperties" cat > "$CASE/system/controlDict" < "$CASE/system/blockMeshDict" <<'EOF' FoamFile{version 2.0;format ascii;class dictionary;object blockMeshDict;} scale 1; vertices ( (-6 -6 -6) (18 -6 -6) (18 6 -6) (-6 6 -6) (-6 -6 6) (18 -6 6) (18 6 6) (-6 6 6) ); blocks ( hex (0 1 2 3 4 5 6 7) (48 24 24) simpleGrading (1 1 1) ); edges (); boundary ( inlet { type patch; faces ((0 4 7 3)); } outlet { type patch; faces ((1 5 6 2)); } farfield { type patch; faces ((1 5 4 0)(3 7 6 2)(0 3 2 1)(4 5 6 7)); } ); mergePatchPairs (); EOF cat > "$CASE/system/surfaceFeatureExtractDict" <<'EOF' FoamFile{version 2.0;format ascii;class dictionary;object surfaceFeatureExtractDict;} body.stl { extractionMethod extractFromSurface; extractFromSurfaceCoeffs { includedAngle 150; } writeObj no; } EOF cat > "$CASE/system/snappyHexMeshDict" <<'EOF' FoamFile{version 2.0;format ascii;class dictionary;object snappyHexMeshDict;} castellatedMesh true; snap true; addLayers true; geometry { body { type triSurfaceMesh; file "body.stl"; } } castellatedMeshControls { maxLocalCells 2000000; maxGlobalCells 8000000; minRefinementCells 10; nCellsBetweenLevels 3; resolveFeatureAngle 30; allowFreeStandingZoneFaces true; features ( { file "body.eMesh"; level 4; } ); refinementSurfaces { body { level (3 4); patchInfo { type wall; } } } refinementRegions { body { mode distance; levels ((0.5 3) (1.5 2) (3.0 1)); } } locationInMesh (-5 0.013 0.027); } snapControls { nSmoothPatch 3; tolerance 2.0; nSolveIter 50; nRelaxIter 8; nFeatureSnapIter 10; implicitFeatureSnap false; explicitFeatureSnap true; } addLayersControls { relativeSizes true; expansionRatio 1.2; finalLayerThickness 0.5; minThickness 0.05; layers { body { nSurfaceLayers 4; } } nGrow 0; featureAngle 80; nRelaxIter 5; nSmoothSurfaceNormals 1; nSmoothNormals 3; nSmoothThickness 10; maxFaceThicknessRatio 0.5; maxThicknessToMedialRatio 0.3; minMedialAxisAngle 90; nBufferCellsNoExtrude 0; nLayerIter 50; } meshQualityControls { maxNonOrtho 65; maxBoundarySkewness 20; maxInternalSkewness 4; maxConcave 80; minVol 1e-13; minTetQuality 1e-15; minArea -1; minTwist 0.02; minDeterminant 0.001; minFaceWeight 0.05; minVolRatio 0.01; minTriangleTwist -1; nSmoothScale 4; errorReduction 0.75; relaxed { maxNonOrtho 75; } } mergeTolerance 1e-6; EOF # 0/ fields (flow +x; wall patch = body) cat > "$CASE/0/U" < "$CASE/0/p" < "$CASE/0/nut" < "$CASE/0/k" < "$CASE/0/omega" < log.blockMesh 2>&1; echo "rc=$?" echo "=== surfaceFeatureExtract ==="; surfaceFeatureExtract > log.sfe 2>&1; echo "rc=$?" echo "=== snappyHexMesh ==="; t=$(date +%s) snappyHexMesh -overwrite > log.snappy 2>&1; echo "snappy rc=$? in $(( $(date +%s)-t ))s" grep -iE "Added .*cells|Layer mesh|Final" log.snappy | tail -3 echo "=== checkMesh ==="; checkMesh > log.checkMesh 2>&1 grep -iE "cells:|Mesh OK|\*\*\*" log.checkMesh | tail -4 echo "=== simpleFoam ==="; t=$(date +%s) simpleFoam > log.simpleFoam 2>&1; echo "simpleFoam rc=$? in $(( $(date +%s)-t ))s" grep -E "SIMPLE solution converged|Time =" log.simpleFoam | tail -2 F=$(find postProcessing -name 'coefficient*.dat' 2>/dev/null | head -1) echo "OF_EXT_DONE name=$NAME Re=$RE Cd_Cl:"; tail -1 "$F" EOF_GUARD=1