diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml index a978849..cd77db2 100644 --- a/.github/workflows/sphinx.yml +++ b/.github/workflows/sphinx.yml @@ -1,54 +1,69 @@ -# From: https://github.com/rkdarst/sphinx-actions-test/blob/master/.github/workflows/sphinx-build.yml +# Deploy Sphinx. This could be shorter, but we also do some extra +# stuff. +# +# License: CC-0. This is the canonical location of this file, which +# you may want to link to anyway: +# https://github.com/coderefinery/sphinx-lesson-template/blob/main/.github/workflows/sphinx.yml +# https://raw.githubusercontent.com/coderefinery/sphinx-lesson-template/main/.github/workflows/sphinx.yml + name: sphinx on: [push, pull_request] -# If these SPHINXOPTS are enabled, then be strict about the builds and -# fail on any warnings -#env: -# SPHINXOPTS: "-W --keep-going -T" env: - DEFAULT_BRANCH: main + DEFAULT_BRANCH: "main" + # If these SPHINXOPTS are enabled, then be strict about the + # builds and fail on any warnings. + #SPHINXOPTS: "-W --keep-going -T" + GENERATE_PDF: false # to enable, must be 'true' lowercase + GENERATE_SINGLEHTML: false # to enable, must be 'true' lowercase + PDF_FILENAME: lesson.pdf + MULTIBRANCH: false # to enable, must be 'true' lowercase jobs: - build-and-deploy: - name: Build and gh-pages + build: + name: Build runs-on: ubuntu-latest + permissions: + contents: read + steps: # https://github.com/marketplace/actions/checkout - uses: actions/checkout@v4 with: fetch-depth: 0 lfs: true + # https://github.com/marketplace/actions/setup-python # ^-- This gives info on matrix testing. - name: Install Python uses: actions/setup-python@v4 with: - python-version: "3.12" - # https://docs.github.com/en/actions/guides/building-and-testing-python#caching-dependencies - # ^-- How to set up caching for pip on Ubuntu - - name: Cache pip - uses: actions/cache@v2 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - ${{ runner.os }}- + python-version: '3.11' + cache: 'pip' + # https://docs.github.com/en/actions/guides/building-and-testing-python#installing-dependencies # ^-- This gives info on installing dependencies with pip - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt + + # Debug - name: Debugging information + env: + ref: ${{github.ref}} + event_name: ${{github.event_name}} + head_ref: ${{github.head_ref}} + base_ref: ${{github.base_ref}} run: | - echo "github.ref:" ${{github.ref}} - echo "github.event_name:" ${{github.event_name}} - echo "github.head_ref:" ${{github.head_ref}} - echo "github.base_ref:" ${{github.base_ref}} + echo "github.ref: ${ref}" + echo "github.event_name: ${event_name}" + echo "github.head_ref: ${head_ref}" + echo "github.base_ref: ${base_ref}" + echo "GENERATE_PDF: ${GENERATE_PDF}" + echo "GENERATE_SINGLEHTML: ${GENERATE_SINGLEHTML}" set -x git rev-parse --abbrev-ref HEAD git branch @@ -61,7 +76,8 @@ jobs: # Build - uses: ammaraskar/sphinx-problem-matcher@master - - name: Build Sphinx docs + - name: Build Sphinx docs (dirhtml) + # SPHINXOPTS used via environment variables run: | make dirhtml # This fixes broken copy button icons, as explained in @@ -73,60 +89,38 @@ jobs: # https://github.com/readthedocs/sphinx_rtd_theme/pull/1025 sed -i 's/url_root="#"/url_root=""/' _build/dirhtml/index.html || true + # singlehtml + - name: Generate singlehtml + if: ${{ env.GENERATE_SINGLEHTML == 'true' }} + run: | + make singlehtml + mv _build/singlehtml/ _build/dirhtml/singlehtml/ - # The following supports building all branches and combining on - # gh-pages + # PDF if requested + - name: Generate PDF + if: ${{ env.GENERATE_PDF == 'true' }} + run: | + pip install https://github.com/rkdarst/sphinx_pyppeteer_builder/archive/refs/heads/main.zip + make pyppeteer + mv _build/pyppeteer/*.pdf _build/dirhtml/${PDF_FILENAME} - # Clone and set up the old gh-pages branch - - name: Clone old gh-pages + # Stage all deployed assets in _gh-pages/ for simplicity, and to + # prepare to do a multi-branch deployment. + - name: Copy deployment data to _gh-pages/ if: ${{ github.event_name == 'push' }} - run: | - set -x - git fetch - ( git branch gh-pages remotes/origin/gh-pages && git clone . --branch=gh-pages _gh-pages/ ) || mkdir _gh-pages - rm -rf _gh-pages/.git/ - mkdir -p _gh-pages/branch/ - # If a push and default branch, copy build to _gh-pages/ as the "main" - # deployment. - - name: Copy new build (default branch) - if: | - contains(github.event_name, 'push') && - contains(github.ref, env.DEFAULT_BRANCH) - run: | - set -x - # Delete everything under _gh-pages/ that is from the - # primary branch deployment. Eicludes the other branches - # _gh-pages/branch-* paths, and not including - # _gh-pages itself. - find _gh-pages/ -mindepth 1 ! -path '_gh-pages/branch*' -delete + run: rsync -a _build/dirhtml/ _gh-pages/ - # If a push and not on default branch, then copy the build to - # _gh-pages/branch/$brname (transforming '/' into '--') - - name: Copy new build (branch) - if: | - contains(github.event_name, 'push') && - !contains(github.ref, env.DEFAULT_BRANCH) - run: | - set -x - #brname=$(git rev-parse --abbrev-ref HEAD) - brname="${{github.ref}}" - brname="${brname##refs/heads/}" - brdir=${brname//\//--} # replace '/' with '--' - rm -rf _gh-pages/branch/${brdir} - rsync -a _build/dirhtml/ _gh-pages/branch/${brdir} - # Go through each branch in _gh-pages/branch/, if it's not a - # ref, then delete it. - - name: Delete old feature branches - if: ${{ github.event_name == 'push' }} - run: | - set -x - for brdir in `ls _gh-pages/branch/` ; do - brname=${brdir//--/\/} # replace '--' with '/' - if ! git show-ref remotes/origin/$brname ; then - echo "Removing $brdir" - rm -r _gh-pages/branch/$brdir/ - fi - done + + # Use gh-pages-multibranch to multiplex different branches into + # one deployment. See + # https://github.com/coderefinery/gh-pages-multibranch + - name: gh-pages multibranch + uses: coderefinery/gh-pages-multibranch@main + if: ${{ github.event_name == 'push' && env.MULTIBRANCH == 'true' }} + with: + directory: _gh-pages/ + default_branch: ${{ env.DEFAULT_BRANCH }} + publish_branch: gh-pages # Add the .nojekyll file - name: nojekyll @@ -134,15 +128,43 @@ jobs: run: | touch _gh-pages/.nojekyll + # Save artifact for the next step. + - uses: actions/upload-artifact@v4 + if: ${{ github.event_name == 'push' }} + with: + name: gh-pages-build + path: _gh-pages/ + + # Deploy in a separate job so that write permissions are restricted + # to the minimum steps. + deploy: + name: Deploy + runs-on: ubuntu-latest + needs: build + # This if can't use the env context - find better way later. + if: ${{ github.event_name == 'push' }} + permissions: + contents: write + + steps: + - uses: actions/download-artifact@v4 + if: ${{ github.event_name == 'push' && ( env.MULTIBRANCH == 'true' || github.ref == format('refs/heads/{0}', env.DEFAULT_BRANCH )) }} + with: + name: gh-pages-build + path: _gh-pages/ + + # As of 2023, we could publish to pages via a Deployment. This + # isn't done yet to give it time to stabilize (out of beta), and + # also having a gh-pages branch to check out is rather + # convenient. + # Deploy # https://github.com/peaceiris/actions-gh-pages - name: Deploy uses: peaceiris/actions-gh-pages@v3 - if: ${{ github.event_name == 'push' }} - #if: ${{ success() && github.event_name == 'push' && github.ref == 'refs/heads/${{ env.DEFAULT_BRANCH }}' }} + if: ${{ github.event_name == 'push' && ( env.MULTIBRANCH == 'true' || github.ref == format('refs/heads/{0}', env.DEFAULT_BRANCH )) }} with: publish_branch: gh-pages github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: _gh-pages/ force_orphan: true - diff --git a/content/handson.rst b/content/handson.rst index 14a7fbf..165a58d 100644 --- a/content/handson.rst +++ b/content/handson.rst @@ -5,12 +5,17 @@ Case Study .. questions:: - - What is - - What problem do + - How do I set up a case with an OpenFOAM-native mesher? + - How do I set up boundary conditions and turbulence modelling? + - How do I run the case in parallel? + - How do I postprocess the results? .. objectives:: - - introduce the basics of OpenFOAM + - Learn how to create a block-structured mesh with ``blockMesh``; + - Set up boundary conditions and turbulence modelling, if any; + - Run the case either in serial or parallel; + - Learn how to visualise and postprocess results in Paraview. .. instructor-note:: @@ -21,77 +26,57 @@ Case Study Lid-driven cavity flow ---------------------------- -This case uses OpenFOAM to calculate the incompressible flow in a two-dimensional square domain, see the Figure blow +This case uses OpenFOAM to calculate the incompressible flow in a two-dimensional square domain, see the Figure below: .. image:: img/cavity2D_geometry.png +You can copy it from the OpenFOAM tutorial folder: -Here are some suggestions for this hands-on session. +.. code:: console -- Write questions on `Hackmd `_. + $ cp -r $FOAM_TUTORIALS/incompressibleFluid/cavity /path/where/you/want/to/run -- Follow the instructions below to recap what we learned during th lecture. - The material is written for the Tegner cluster, but you can start on your laptop for maximum interactivity. -- Although post-processing with Paraview is listed as optional (see last section in the hands-on), it is very highly recommended that - you install Paraview on your machine and inspect the results of the OpenFOAM simulations. - Of course, you can use another post-processor of your liking. +The structure of the case is the following: -- At some point, do login to Tegner, and get comfortable with running on iteractive nodes. - For that, follow the instructions in the `slides by Arash `_. - - -- Use the case as a sandbox to change various settings and play with the parameters. Use the "banana-trick" to learn about - possible options: change any dictionary keyword to "banana", the case will crash showing possible valid options for the keyword. - -- If you have CFD experience, ask yourself: what settings would I typically need to change? - Then try to figure out what dictionaries and keywords correspond to that. The teachers are there to help! - Try also to dig online a little bit yourself: one of the course outcomes is that you should be able to continue develop your skills - on your own. - -To use OpenFOAM on Tegner, we first need to load the appropriate module. -This is followed by sourcing *$FOAM_BASHRC* to activate the OpenFOAM environment. -The *$FOAM_TUTORIALS* will then store the path to the tutorial collection shipped with OpenFOAM. -Note, you can also use the *tut* command to jump to the tutorial directory and look around. -**Important:** Always copy the tutorial to a folder where you have full write permission, never execute tutorials inside *$FOAM_TUTORIALS*. -Also, as OpenFOAM cases are not always backward-compatible, please make sure to always copy cases from *$FOAM_TUTORIALS* of the current version you are using. - -.. code:: bash - - $ module add openfoam/1912 # Using OpenFOAM v1912 - $ echo $FOAM_BASHRC - /pdc/vol/openfoam/v1912/OpenFOAM-v1912/etc/bashrc - $ source $FOAM_BASHRC - $ cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavity . - -- The structure of the case is shown in the following - -.. code:: bash +.. code:: console $ cd cavity $ ls 0 constant system $ tree - - ├── 0 (time directory starting with T=0, initial conditions) - │   ├── p (pressure) - │   └── U (flow velocity) - ├── Allrun (precanned run file) - ├── constant (hard static stuff i.e. physical properties) - │   ├── transportProperties (Transport Model e.g. Newtonian) - └── system - ├── blockMeshDict - ├── controlDict (the main dictionary for controlling the simulation) - ├── fvSchemes - ├── fvSolution - ├── PDRblockMeshDict - -- The default setting is to run the application *simpleFoam* in serial on a two-dimensional square mesh of size (20×20×1). - Note that all OpenFOAM cases are three-dimensional. For a two-dimensional case the third dimension has a single computational cell, - and special boundary conditions are employed. - The case will run up to time *0.5* with *0.005* per step, i.e. a total of 100 time steps. The simulation results are stored every 20 time steps. - + . + ├── 0 + │   ├── epsilon + │   ├── k + │   ├── nut + │   ├── nuTilda + │   ├── omega + │   ├── p + │   └── U + ├── constant + │   ├── momentumTransport + │   └── physicalProperties + ├── r.foam + └── system + ├── blockMeshDict + ├── controlDict + ├── fvSchemes + └── fvSolution + +The default setting is to run the solver in serial on a two-dimensional square +mesh of size (20×20×1). Note that all OpenFOAM cases are three-dimensional. For +a two-dimensional case the third dimension has a single computational cell, and +special boundary conditions are employed. The case will run up to time *0.5* +with *0.005* non-dimensional time units per step, i.e. a total of 100 time +steps. The simulation results are stored every 20 time steps. + + +- Use the case as a sandbox to change various settings and play with the + parameters. Use the "banana-trick" to learn about possible options: + change any dictionary keyword to "banana", the case will crash showing possible + valid options for the keyword. Run the case by default +++++++++++++++++++++++ @@ -99,20 +84,21 @@ Run the case by default .. code:: bash $ blockMesh # create the equivalent mesh of (20x20x1) - $ icoFoam > log.icoFoam + $ foamRun | tee log $ ls 0 0.1 0.2 0.3 0.4 0.5 constant system -Congratulations, you were able to run your first OpenFOAM case on a PDC cluster! +Congratulations, you were able to run your first OpenFOAM case! Inspecting the log file +++++++++++++++++++++++ To make sure everything is OK we can look at the output logs from the OpenFOAM run. This will show us if the run actually worked as intended. -To do this, inspect *log.icoFoam* with your favorite editor or simply use commands like *tail*. +To do this, inspect *log.icoFoam* with your favorite editor or simply use commands +like ``tail``. -.. code:: bash +.. code:: console $ tail -n 50 log.icoFoam Time = 0.5 @@ -128,17 +114,18 @@ To do this, inspect *log.icoFoam* with your favorite editor or simply use comman End -There is quite a bit of information to be extracted from the logs, such as residuals of the iterative solvers and the Courant number. -Depending on the simulation options, the logs may become more expressive, monitoring additional simulation aspects. +There is quite a bit of information to be extracted from the logs, such as residuals of the iterative +solvers and the Courant number. +Depending on the simulation options, the logs may become more expressive, monitoring additional +simulation aspects. Creating the finer mesh +++++++++++++++++++++++ The cavity case is too tiny to make running in parallel a reasonable alternative. We will therefore make the mesh denser. -An overview of OpenFOAM meshing will be given during day 2 of the workshop. For now, we just provide the instruction for refining without much explaination. -In *system/blockMeshDict*, the default mesh size is set by the triple *(20 20 1)*, +In ``system/blockMeshDict``, the default mesh size is set by the triple *(20 20 1)*, in the following lines. .. code:: bash @@ -159,13 +146,14 @@ So, to refine we can change it to e.g. *(100 100 1)*, And then rerun the command *blockMesh*. -.. code:: bash +.. code:: console $ blockMesh -If you now run *icoFoam* you will notice that the solver is slow and that the Courant number is very high! +If you now run ``foamRun`` you will notice that the solver is slow and that +the Courant number is very high! -.. code:: bash +.. code:: text Time = 0.01 @@ -178,7 +166,8 @@ If you now run *icoFoam* you will notice that the solver is slow and that the Co time step continuity errors : sum local = 2.39948e-08, global = -4.25067e-19, cumulative = -1.89512e-18 ExecutionTime = 0.54 s ClockTime = 0 s -This makes sense: we decreased the cell size, so to keep the Courant number reasonable we also need to change the time step. +This makes sense: we decreased the cell size, so to keep the Courant +number reasonable we also need to change the time step. This is done by changing the value of the *deltaT* keyword in the *controlDict*. We can set the time-step to 0.0005. @@ -192,28 +181,31 @@ Running in parallel Let us now run the case in parallel. Inspecting *system/decomposeParDict*, we see that the case is set to be decomposed into 4 subdomains. -.. code:: bash +.. code:: cpp numberOfSubdomains 4; We will leave this as is and now we can decompose the case and run in parallel. -.. code:: bash +.. code:: console - $ decomposePar + $ decomposePar -fileHandler collated -This will create directories *processor0* to *processor3*, containing the subdomains. +This will create a ``processors4`` directory which contains, for each writed step and field, +a single file that can be accessed by all ranks in parallel. The default ``uncollated`` +format would create one file per field and rank, which can quickly amount to millions +of files for massively parallel simulations. To run the case, execute the following command. -.. code:: bash +.. code:: console - $ mpirun -np 4 icoFoam -parallel > logfile.icoFoamParallel + $ mpirun -np 4 foamRun -parallel -fileHandler collated | tee logParallel -Upon completion we can reconstruct the solution on the whole domain: +Upon completion we can reconstruct the solution over the whole domain: -.. code:: bash +.. code:: console - $ reconstructPar -latestTime + $ reconstructPar -latestTime -fileHandler collated Here, the *-latestTime* flag tells the program to only reconstruct the last time-step. @@ -224,56 +216,58 @@ To do yourself: - Play around with mesh sizes and change *decomposeParDict* to run on a larger number of processors. -- Go through https://www.pdc.kth.se/support/documents/run_jobs/job_scheduling.html#how-to-submit-jobs to learn how to - submit jobs to the cluster queue. Try to submit your cavity case as a short queued job. - A simple jobs script example is available in the `slides by Arash `_. - Increasing the Reynolds number ++++++++++++++++++++++++++++++ -We will now increase the Reynolds number to *100*, at which point the solution takes a noticeably longer time to converge. +We will now increase the Reynolds number to *100*, at which point the solution takes a noticeably +longer time to converge. -.. code:: bash +.. code:: console $ cp -r cavity cavityHighRe -and then edit *transportProperties* dictionary to reduce the kinematic viscosity to *0.001* +and then edit *physicalProperties* dictionary to reduce the kinematic viscosity to *0.001* -.. code:: bash +.. code:: console nu 0.01; to -.. code:: bash +.. code:: console nu 0.001; -Increase the *endTime* from *0.5* to *2* so that *icoFoam* run upto 2 seconds. +Increase the *endTime* from *0.5* to *2* so that ``foamRun`` runs up to 2 seconds. -.. code:: bash +.. code:: console - $ icoFoam + $ foamRun Turbulence modelling (optional) +++++++++++++++++++++++++++++++ -The need to increase spatial and temporal resolution then becomes impractical as the flow moves into the turbulent regime, where problems of solution stability may also occur. -Instead Reynolds-averaged simulation (RAS) turbulence models are used to solve for the mean -flow behaviour and calculate the statistics of the fluctuations. -The standard k-epsilon model with wall functions will be used in this tutorial to solve the lid-driven cavity case with a Reynolds number of 10^4. -Two extra variables are solved for: k, the turbulent kinetic energy, and epsilon, the turbulent dissipation rate. -The additional equations and models for turbulent flow are implemented into a OpenFOAM solver called *pisoFoam*. -To setup the model you will need three additional files in the 0 directory: *nut*, *k*, *epsilon*. -Create them by making a copy of the *p* file, and then modify them as needed. - -A range of wall function models is available in OpenFOAM that are applied as boundary conditions on individual patches. -This enables different wall function models to be applied to different wall regions. -The choice of wall function models are specified through the turbulent viscosity field, nut, in the *0/nut* file: - -.. code:: bash +The need to increase spatial and temporal resolution becomes impractical +as the flow moves into the turbulent regime, where problems of solution +stability may also occur. Instead, Reynolds-averaged simulation (RAS) turbulence +models are used to solve for the mean flow behaviour and calculate the +statistics of the fluctuations. The standard k-epsilon model with wall +functions will be used in this tutorial to solve the lid-driven cavity case +with a Reynolds number of :math:`10^4`. Two extra variables are solved for: k, the +turbulent kinetic energy, and :math:`\varepsilon`, the turbulent dissipation rate. +To setup the model you will need three additional files in the 0 directory: *nut*, +*k*, *epsilon*. Create them by making a copy of the *p* file, and then modify them +as needed. + +A range of wall function models is available in OpenFOAM that are applied as +boundary conditions on individual patches. This enables different wall function +models to be applied to different wall regions. The choice of wall function +models are specified through the turbulent viscosity field, nut, in the *0/nut* +file: + +.. code:: cpp dimensions [0 2 -1 0 0 0 0]; @@ -298,14 +292,19 @@ The choice of wall function models are specified through the turbulent viscosity } -You should should now open the field files for *k* and *epsilon* ( in *0/k* and *0/epsilon*) and set their boundary conditions. -For a wall boundary condition wall, *epsilon* is assigned an *epsilonWallFunction* boundary condition and a *kqRwallFunction* boundary condition is assigned to *k*. -The latter is a generic boundary condition that can be applied to any field that are of a turbulent kinetic energy type, e.g. *k*, *q* or Reynolds Stress *R* +You should should now open the field files for *k* and *epsilon* ( in *0/k* and *0/epsilon*) +and set their boundary conditions. For a wall boundary condition wall, *epsilon* is assigned +an *epsilonWallFunction* boundary condition and a *kqRwallFunction* boundary condition is assigned to *k*. +The latter is a generic boundary condition that can be applied to any field that are of a turbulent kinetic +energy type, e.g. *k*, *q* or Reynolds Stress *R*. -Turbulence modelling includes a range of methods, e.g. *RAS* or large-eddy simulation (*LES*), that are provided in OpenFOAM. In most transient solvers, the choice of turbulence modelling method is selectable at run-time through the simulationType keyword in turbulenceProperties dictionary. The user can view this file in the constant directory: +Turbulence modelling includes a range of methods, e.g. *RAS* or large-eddy simulation (*LES*), that are +provided in OpenFOAM. In most transient solvers, the choice of turbulence modelling method is selectable +at run-time through the simulationType keyword in momentumTransport dictionary. The user can view this +file in the constant directory: -.. code:: bash +.. code:: cpp simulationType RAS; @@ -319,7 +318,7 @@ Turbulence modelling includes a range of methods, e.g. *RAS* or large-eddy simul } The options for *simulationType* are *laminar*, *RAS* and *LES*. -More informaton on turbulence models can be found in the Extended Code Guide +More informaton on turbulence models can be found in the Extended Code Guide. With RAS selected in this case, the choice of *RAS* modelling is specified in a turbulenceProperties subdictionary, also in the constant directory. The turbulence model is selected by the *RASModel* entry from a long list of @@ -329,72 +328,65 @@ the user should also ensure that turbulence calculation is switched on. Finally, you can run the case with commands: -.. code:: bash +.. code:: console $ blockMesh - $ pisoFoam + $ foamRun Post-processing (optional) ++++++++++++++++++++++++++ -The post-processing tool supplied with OpenFOAM is *paraFoam*, which is a wrapper of *paraview* (www.paraview.org). -The *paraFoam* post-processing is started by typing in the terminal from within the case directory with loading *paraview* module. - -.. code:: bash - - $ module add paraview/5.8.1-gcc-7.2 - $ paraFoam - -Alternatively, if you can add an empty file inside the case directory. +The post-processing tool supplied with OpenFOAM is *paraFoam*, which is a +wrapper of `Paraview `__. Compared to vanilla +Paraview, it has an additional reader for ``blockMesh`` dictionaries and can +visualise patch names. To open an OpenFOAM case with native Paraview, you can +add an empty file inside the case directory. -.. code:: bash +.. code:: console $ touch case.foam -You can now open this file with regular Paraview, and not *paraFoam*. +You can now open this file with regular Paraview. .. image:: img/cavity2D_mesh.png .. image:: img/cavity2D_pressure.png - - - - - - - - - - MotorBike --------- -This case uses OpenFOAM to calculate the steady flow around a motorbike and rider using RAS turbulence modelling with wall functions. -The initialization of flow velocity is to 20 m/s. -The box includes the bike and ride are approximately 2.0x0.8x1.3m and the estimated characteristic length scale L=0.5m, see the Figure below. +This case uses OpenFOAM to calculate the steady flow around a motorbike and +rider using RAS turbulence modelling with wall functions. The initialization of +the velocity field is to 20 m/s. The box includes both bike and rider and +its size is approximately 2.0x0.8x1.3m. The estimated characteristic length scale +is L=0.5m. .. image:: img/motorbike_overall.png -As you will see, this is a more advanced case than the cavity, involving *snappyHexMesh* to generate the mesh, RANS modelling, -and using several function objects. -The idea is to further strengthen the familiarity with OpenFOAM input and have a more fun case to play around with than the cavity. +This is a more advanced case than the cavity, involving *snappyHexMesh* to +generate the mesh, RANS modelling, and using several function objects. In +OpenFOAM-speak, function objects are forms of computation or data manipulation +that can be executed "online" while the solver is running or in a separate +post-processing step; common function objects are, for example: +- Sample a quantity on a point/line/plane/patch/cloud and save it on disk; +- Solve an additional transport equation (e.g. temperature in an incompressible + flow) +- Seed the flow with Lagrangian particles (one-way LPT); +- Streamlines; +- ... -Notice that OpenFOAM cases are not backward compatible, please always copy cases from *$FOAM_TUTORIALS* of current version +Notice that OpenFOAM cases are not backwards-compatible, so a tutorial from the +current OpenFOAM version is needed. -.. code:: bash +.. code:: console - $ module add openfoam/1912 - $ echo $FOAM_BASHRC - /pdc/vol/openfoam/v1912/OpenFOAM-v1912/etc/bashrc - $ source $FOAM_BASHRC $ cp -r $FOAM_TUTORIALS/incompressible/simpleFoam/motorBike . -- The structure of the case is shown in the following +- The structure of the case is as follows: -.. code:: bash +.. code:: console $ cd motorBike $ ls @@ -402,117 +394,107 @@ Notice that OpenFOAM cases are not backward compatible, please always copy cases $ tree -d 1 . - ├── 0.orig (time directory starting with T=0, initial conditions) - │   ├── include - │   │   ├── fixedInlet - │   │   ├── frontBackUpperPatches - │   │   └── initialConditions - │   ├── k (turbulence kenetic energy) - │   ├── nut (turbulence viscosity) - │   ├── omega (turbulence specific dissipation rate) - │   ├── p (pressure) - │   └── U (flow velocity) - ├── Allclean (precanned clean file) - ├── Allrun (precanned run file) - ├── constant (hard static stuff i.e. physical properties) - |-- RASProperties (Reynolds-Averaged Simulation Model to use e.g. kOmegaSST) - │   ├── polyMesh - │   │   ├── blockMeshDict - │   │   ├── boundary - │   ├── transportProperties (Transport Model e.g. Newtonian) - │   ├── triSurface - │   │   ├── motorBike.obj.gz (actual motorbike model) - │   └── turbulenceProperties - └── system - ├── blockMeshDict - ├── controlDict (the main dictionary for controlling the simulation) - ├── decomposeParDict (dictionary for partitioning up the space into smaller chunks) - ├── fvSchemes - ├── fvSolution - ├── snappyHexMeshDict (the dictionary for adding a mesh for simulating surface interactions) - -- The default setting is to run the application simpleFoam on 6 MPI-rank with background mesh block - of size (20×8×8). The results are stored in 5 time steps 100, 200, 300, 400 and 500. - - -The following tasks are suggested during the hands-on session. - -- Try to change some parameters in the snappyHexMeshDict, can you see what happens? - -- Try to figure out what each fucntion object does. Search for documentation in the user guide. - If you are brave, look at the source code, that is the big plus of open-source! - -- Think about what you typically look at in your CFD simulations. See if you can find a suitable function object. - (Suggestions: inlet-outlet mass flow balance, y+ values, Co-number, velocity min/max, residuals, etc.) - - -Run the case by default -+++++++++++++++++++++++ - -.. code:: bash + . + ├── 0 + │   ├── include + │   │   ├── fixedInlet + │   │   ├── frontBackUpperPatches + │   │   └── initialConditions + │   ├── k + │   ├── nut + │   ├── nuTilda + │   ├── p + │   └── U + ├── Allclean + ├── Allrun + ├── constant + │   ├── geometry + │   │   └── README + │   ├── momentumTransport + │   └── physicalProperties + └── system + ├── blockMeshDict + ├── controlDict + ├── cutPlane + ├── decomposeParDict + ├── forceCoeffs + ├── functions + ├── fvSchemes + ├── fvSolution + ├── snappyHexMeshDict + └── streamlines + +The default setting is to run the application simpleFoam on 6 MPI-rank with +background mesh block of size (20×8×8). The results are stored in 5 time steps +100, 200, 300, 400 and 500. + +Run the case with default parameters +++++++++++++++++++++++++++++++++++++ + +.. code:: console - $ source $FOAM_BASHRC $ ./Allrun # run the workflow -The script *Allrun* is a script to collect all commands for whole workflow. -You can use it, but it is not very pedagogical. Better to manually go through each command to remember what it does. +The script *Allrun* is a script to collect all the commands for whole workflow. +You can use it, but it is not very pedagogical. Better to manually go through +each command to remember what it does. -.. code:: bash +.. code:: console # Copy motorbike surface from resources directory - cp $FOAM_TUTORIALS/resources/geometry/motorBike.obj.gz constant/triSurface/ - - # Restore the 0 directory - cp -r 0.orig 0 - - # Extracts and writes surface features to file - surfaceFeatureExtract + cp $FOAM_TUTORIALS/resources/geometry/motorBike.obj.gz constant/geometry/ # Create a block mesh, which will be the background mesh for snappy blockMesh # Decompose a mesh for parallelization - decomposePar -copyZero + decomposePar -copyZero -fileHandler collated # Run the snappyHexMesh in parallel! - mpirun -np 6 snappyHexMesh -parallel -overwrite > log.snappyHexMesh + mpirun -np 6 snappyHexMesh -parallel -fileHandler collated -overwrite | tee log.snappyHexMesh - # Run a potential flow solver - mpirun -np 6 potentialFoam -parallel -writephi > log.potentialFoam + # Run a potential flow solver to get a good initial condition + mpirun -np 6 potentialFoam -parallel -fileHandler collated -initialiseUBCs | tee log.potentialFoam # Run the steady-state solver for incompressible flow - mpirun -np 6 simpleFoam -parallel > log.simpleFoam + mpirun -np 6 foamRun -parallel -fileHandler collated | tee log.foamRun # Reconstruct the mesh using geometric information - reconstructParMesh -constant + reconstructParMesh -constant -fileHandler collated # Reconstruct fields of the parallel case - reconstructPar -latestTime + reconstructPar -fileHandler collated -latestTime -Some stuff worth noting here: +Some points worth noting here: -- We want to generate the mesh in parallel and this introduces some extra shenanigans into the workflow. - This is not really needed for this case, but can be good to know. +- Mesh generation is performed in parallel; -- We generate the background mesh with *blockMesh* and then decompose that into subdomains with *decomposePar*. - Here, we have to provide the *-copyZero* flag, so that the *0* folder is simply copied to the *processor* directories - without change. Otherwise, some stuff will be "optimized away", for example entries for boundaries that are not found in the mesh. - Since the background mesh generate by *blockMesh* does not contain the motorbike, this would completely ruin the *0* folder. +- We generate the background mesh with *blockMesh* and then decompose that into + subdomains with ``decomposePar``. Here, we have to provide the ``-copyZero`` + flag, so that the *0* folder is simply copied to the *processor* directories + without change. Otherwise, some stuff will be "optimized away", for example + entries for boundaries that are not found in the mesh. Since the background + mesh generate by ``blockMesh`` does not contain the motorbike, this would + completely ruin the *0* folder. -- We run *potentialFoam* to solve potential flow equations to get a better initial condition. Note a corresponding entry in *system/fvSolution*. +- We run ``potentialFoam`` to solve potential flow equations to get a better + initial condition. Note a corresponding entry in ``system/fvSolution``. -- After running the case we need to reconstruct not only the data but also the mesh, which was generated in parallel. For that, we use *reconstructParMesh*. - The *-constant* flag makes it put the mesh directly into *constant/polyMesh*. +- After running the case we need to reconstruct not only the data but also the + mesh, which was generated in parallel. For that, we use + ``reconstructParMesh``. The ``-constant`` flag makes it put the mesh directly + into ``constant/polyMesh``. -Validating the model +Inspecting the run ++++++++++++++++++++ To make sure everything is OK we can the output logs from the OpenFOAM run, -this will show if the run actually worked or not. For each stage there is a log.[stage] -output. For example, in the *log.simpleFoam* file the coefficients should be likes +this will show if the run actually worked or not. For each stage there is a +log.[stage] output. For example, in the *log.foamRun* file the coefficients +should be likes -.. code:: bash +.. code:: console $ tail -n 50 ./log.simpleFoam ... @@ -535,43 +517,55 @@ Here you can see that function objects add new stuff to the log! Parallelization +++++++++++++++ -we can change the MPI rank and the decomposition method in file *system/decomposeParDict*, for example, change the default +We can change the number of MPI ranks and the decomposition method in file +*system/decomposeParDict*, for example, change the default. -.. code:: bash +.. code:: cpp numberOfSubdomains 6; method hierarchical; to -.. code:: bash +.. code:: cpp numberOfSubdomains 24; // MPI-rank method scotch; // using scotch for partition -(Note: If you still used *method hierarchical*, the *hierarchicalCoeffs* in the file -should be coordinately changed) +(Note: If you still used *method hierarchical*, the *hierarchicalCoeffs* in the +file should be coordinately changed) -.. code:: bash +.. code:: cpp hierarchicalCoeffs { n (4 3 2); // 4x3x2 = 24 !! } -The script *Allclean* can be used to delete the log files and remove the results from +The script ``Allclean`` can be used to delete the log files and remove the results from motorBike run and then rerun again. Mesh refinement +++++++++++++++ -- For scalability tests, the default mesh of 350 k cells may be small, (you can check the mesh information in *log.snappyHexMesh* +Information about cell count and other quality parameters can be inspected with +the ``checkMesh`` command. -.. code:: bash +.. code:: text - Layer mesh : cells:353548 faces:1107696 points:405989 + Mesh stats + points: 3889958 + faces: 10253758 + internal faces: 9645402 + cells: 3215663 + faces per cell: 6.1882 + boundary patches: 76 + point zones: 0 + face zones: 0 + cell zones: 0 -We need to increase the block mesh size and change the settings in file *system/blockMeshDict*, for example, from +We need to increase the block mesh size and change the settings in file +*system/blockMeshDict*, for example, from .. code:: bash @@ -582,32 +576,28 @@ We need to increase the block mesh size and change the settings in file *system/ to -.. code:: bash +.. code:: cpp blocks ( hex (0 1 2 3 4 5 6 7) (40 16 16) simpleGrading (1 1 1) ); -i.e. the mesh size in x, y, and z-directory increases twice. The script *Allclean* can be used to delete the log files and remove the results from motorBike run and then rerun again. +i.e. the mesh size in x, y, and z-directory increases twice. The script +*Allclean* can be used to delete the log files and remove the results from +motorBike run and then rerun again. -(Notice: Please do not refine the mesh too much. Otherwise execution time becomes very long) -.. code :: bash +.. code :: console $ ./Allclean $ ./Allrun -The total number of cells is around 1.8 M (check it the log.snappyHexMesh) - -.. code:: bash - - Layer mesh : cells:1892612 faces:5875533 points:2112502 - snappyHexMesh +++++++++++++ -The mesher performs three steps to create the mesh from the background mesh and the stl surface of the motorbike. +The mesher performs three steps to create the mesh from the background mesh and +the stl surface of the motorbike. .. code:: bash @@ -618,19 +608,20 @@ The mesher performs three steps to create the mesh from the background mesh and snap true; addLayers true; -Try running snappyHexMesh without the *-overwrite* flag and take a look at the three produced meshes in the consecutive -time directories written. -Can you see the difference from step to step? -Note that *addLayers* can be removed, and the produced mesh will still conform to the geometry. +Try running snappyHexMesh without the *-overwrite* flag and take a look at the +three produced meshes in the consecutive time directories written. Can you see +the difference from step to step? Note that *addLayers* can be removed, and the +produced mesh will still conform to the geometry. -There are many settings which can be modified to refine and improve the mesh quality. For example, +There are many settings which can be modified to refine and improve the mesh +quality. For example, .. code:: bash $ less system/snappyHexMeshDict ... - // Geometry refinement for wak region + // Geometry refinement for wake region geometry { refinementBox @@ -655,28 +646,29 @@ There are many settings which can be modified to refine and improve the mesh qua ... -refines the mesh in a predifined box. Try changing the parameters of the box and look at the effect. -You could also try creating a new geometric primitve and refining it. As usual, to see what is there set *type* to *banana*, -let the mesher crash and write out available valid options. +refines the mesh in a predifined box. Try changing the parameters of the box +and look at the effect. You could also try creating a new geometric primitve +and refining it. As usual, to see what is there set *type* to *banana*, let the +mesher crash and write out available valid options. Function objects ++++++++++++++++ -The motorbike case contains several function objects distributed among respective files in *system*. -Take a look at them, try to understand what they do. Consult the User guide on openfoam.com. +The motorbike case contains several function objects distributed among +respective files in *system*. Take a look at them, try to understand what they +do. To add the execution to a function object to a case, it has to be added +to the ``system/functions`` dictionary (from OF 12). -.. code:: bash +.. code:: console ... - $ less system/controlDict + $ less system/functions functions { #include "streamLines" - #include "wallBoundedStreamLines" - #include "cuttingPlane" + #include "cutPlane" #include "forceCoeffs" - #include "ensightWrite" } $ ls system @@ -728,23 +720,23 @@ The solvers are selected in the *system/fvSolution* smoother GaussSeidel; ... -More details about the OpenFOAM schemes and solvers can be found at `OpenFOAM: User Guide `_ -Feel free to horse around with the settings even if it kills the solver. -Use the banana trick to see what solvers are available e.g. for pressure and try to change to a different solver? -Is the case running faster or slower? You can always look at the execution time in the log file. +More details about the OpenFOAM schemes and solvers can be found at `OpenFOAM: +User Guide +`_ Feel +free to horse around with the settings even if it kills the solver. Use the +banana trick to see what solvers are available e.g. for pressure and try to +change to a different solver? Is the case running faster or slower? You can +always look at the execution time in the log file. Post-processing +++++++++++++++ -As already mentioned multiple times, Paraview can be used to inspect the case: mesh, flow variable, function object output. -The motorbike case is great for a fancy visualization, so if you have the time and desire, try to produce something interesting! -It is easiest to work with Paraview on your own machine, but you can also use Tegner. - -.. code:: bash +As already mentioned multiple times, Paraview can be used to inspect the case: +mesh, flow variable, function object output. The motorbike case is great for a +fancy visualization, so if you have the time and desire, try to produce +something interesting! - $ module add paraview - $ paraFoam .. image:: img/motorbike_result.png diff --git a/content/img/cavity2D_mesh.png b/content/img/cavity2D_mesh.png index 1be4e3b..2213196 100644 Binary files a/content/img/cavity2D_mesh.png and b/content/img/cavity2D_mesh.png differ diff --git a/content/index.rst b/content/index.rst index 3f2c5f5..e32cbce 100644 --- a/content/index.rst +++ b/content/index.rst @@ -36,6 +36,15 @@ who would like to get started with OpenFOAM using a HPC resource. Basic knowledge of using Linux will be required. Participants are expected to know basic numerical analysis and have CFD theoretical background. +About the course +---------------- + +This workshop will provide an introduction to OpenFOAM, its different versions and how it differs from commercial CFD solvers. +This will be followed by an overview of the OpenFOAM case structure, meshing tools, run in serial and parallel of some example cases +and an introduction to postprocessing in Paraview. Emphasis will be placed on numerics considerations and solution schemes available +in OpenFOAM. +The workshop will assume OpenFOAM foundation version, at least 11. + Schedule -------- @@ -84,8 +93,6 @@ Schedule - Hands-on session -About the course ----------------- See also -------- diff --git a/content/introduction.rst b/content/introduction.rst index 43be27b..2927538 100644 --- a/content/introduction.rst +++ b/content/introduction.rst @@ -21,7 +21,7 @@ OpenFOAM Introduction What is OpenFOAM ? ------------------ -- OpenFOAM® (for “Open-source Field Operation And Manipulation”) is an open source Computation Fluid Dynamics (CFD) solve released and developed primarily by OpenCFD Ltd since 2004. +- OpenFOAM® (for “Open-source Field Operation And Manipulation”) is an open source general solver of Partial differential equations (PDEs) via the finite volume method. It is particularly popular in the computational fluid dynamics (CFD) community. - It has a large user base across most areas of engineering and science, from both commercial and academic organizations. @@ -33,60 +33,60 @@ Different variants of OpenFOAM There are two main variants of OpenFOAM: - OpenCFD Ltd version (`www.openfoam.com `_): + OpenCFD Ltd aka ESI version (`www.openfoam.com `_): - New versions released twice a year (June-December) - Versions are named as (vYYMM) e.g. v1912 - Website: https://www.openfoam.com OpenFOAM foundation version (`www.openfoam.org `_): - No defined date for new release - - Versions are named with with two digits like 4.1 + - Semantic versioning is used. The most recent version is 12. - Website: https://openfoam.org One can read the history if interested: -https://www.openfoam.com/news/history +https://www.openfoam.com/news/history. + +Moreover, another fork exists called `foam-extend`, a community-driven effort currently at version 5.0. This project, while being on a generally slower development +cycle, is more open to contributions from other actors and provides some experimental features not found in the other flavours, such as +turbomachinery toolboxes, immersed boundary method and tooling for reduced order models such as POD. Which version to use? --------------------- -It depends on the features you want to use +It depends on the features you want to use: - - Check the website and release notes to see which one fits better to your framework - - If both include the features you need, do some performance and accuracy benchmarks to see which one is better + - Check the website and release notes to see which one fits better to your framework; + - If both include the features you need, do some performance and accuracy benchmarks to see which one is better; - Otherwise it is just matter of taste! -We will be using the OpenCFD Ltd version with vXXXXXX for the training +Some features are only available in one flavour (e.g. overset meshes only implemented in ESI), while others have been introduced in one and +then ported to the other. The foundation version is more prone to breaking changes (see e.g. the modular solvers below), whereas the ESI version +tends to require minor modifications across subsequent versions. foam-extend offers some features that neither of the other two have; while it +generally strives to have some degree of compatibility with the foundation version, some porting effort is probably required. OpenFOAM executables -------------------- -Unlike many other software, OpenFOAM does not have a unique executable. -Once compiled, a large number of excutebles is generated and they fall into two categories: +Historically, unlike many other software, OpenFOAM does not have a unique executable. +Once compiled, a large number of executables is generated, which fall into two categories: - **solver**: that is designed to solve a specific continuum mechanics problem - - **utility**: that is designed to perform tasks that involve data manipulation. - -For every solver, mesh generation etc. there is a separate executable! -You should run the right executable according to the solver you are using! -Check the documentation to see recommended solvers for different cases. - -- ‘simpleFoam’: if you use SIMPLE algorithm -- ‘icoFoam’: if you use PISO algorithm for laminar flow -- ... + - **utility**: that is designed to perform tasks that involve data manipulation, mesh generation/conversion, etc. +This is the case for the ESI version of OpenFOAM and used to be for OpenFOAM foundation until version 10. +From OpenFOAM 11 onwards, a radical shift of paradigm has taken place: so-called `modular `__ +solvers have been introduced. This approach consists in each solver being a *class* (in the OOP sense) and having one single executable (``foamRun``) +which launches the solver. This makes it easier to include multiple physics in the solution strategy, as well as adding additional equations to be solved. +While this makes for much cleaner and maintainable code, it also means that a wealth of older tutorial cases/learning materials (such as blog and forum posts) +cannot immediately be reused on OpenFOAM :math:`\geq` 11. OpenFOAM vs commercial software ------------------------------- -Being an open source software, the advantages of OpenFOAM is quite obvious: - - - free to use - - a strong focus on customization and flexibility - - full control over the simulation - -All these nice features come with a price: very deep learning curve. -For example, contrary to the commercial CFD softwares, there are no default values in OpenFOAM. -It is up to the user to set those values which means the user has to know what he/she is doing. +OpenFOAM is open-source and it has a degree of focus on customisability and flexibility. The possibility of having full control on the simulation +and the fact that it is free make it very appealing for research use, but it is also widely used in industry (e.g. some automakers and F1 teams, pharma, chemical engineering...). +The costs lie in its steeper learning curve, as users need to have some solid theoretical understanding of CFD, and the absence of bells and whistles that come with +commercial software like friendly GUIs (even though some `commercial `__ and `free `__ efforts are underway). diff --git a/content/mesh.rst b/content/mesh.rst index 7a04d1a..d0513a4 100644 --- a/content/mesh.rst +++ b/content/mesh.rst @@ -1,16 +1,24 @@ .. _mesh: -Mesh -==== +Meshing +======= .. questions:: - What is a mesher? + - What are the choices we have for native OpenFOAM meshing? + - How do we visualise the generated mesh(es)? + - Can we import meshes from other CFD packages into OpenFOAM? + - What are the tools we can use to evaluate mesh metrics and quality? + .. objectives:: - Understand the basics of blockMesh and snappyHexMesh - Know how to use blockMesh and snappyHexMesh + - Learn to inspect a mesh in Paraview + - Learn to use checkMesh to summarise statistics and metrics of mesh quality + .. instructor-note:: @@ -22,18 +30,21 @@ Mesh Mesh generation --------------- -There are a couple of mesher available: +A few meshers that generate OF-native meshes are available: - blockMesh – Block-structured hexahedral mesher - snappyHexMesh – Unstructured hexa-dominated mesher -- cfMesh – Unstructured mesher with different available meshing strategies -- makeFaMesh - Create finite-area meshes from volume-mesh patches -- Other commercial mesh generation +- cfMesh – Unstructured mesher with different available meshing strategies. Works on recent OF versions with some tweeking +- Pointwise - commercial (and paid), has native OF export capabilities + +Moreover, a plethora of conversion tools exist to import meshes from both free and commercial meshers, as outlined :ref:`here`. + + blockMesh +++++++++ -blockMesh is a structured hexahedral mesh generator: +blockMesh is a structured hexahedral mesh generator, meaning that it can generate several blocks with a structured topology: - Key features: @@ -48,57 +59,126 @@ blockMesh is a structured hexahedral mesh generator: - ordering of points is important -It is well suited to simple geometries that can be described by a few blocks, but challenging to apply to cases with a large number of blocks due to book-keeping requirements, i.e. the need to manage point connectivity and ordering. +It is well suited to simple geometries that can be described by a few blocks, but challenging to apply to cases with a large number of blocks due to book-keeping requirements, i.e. +the need to manage point connectivity and ordering. The utility is controlled using a ``blockMeshDict`` dictionary, located in the case **system** directory. -It manually define everything: vertices, blocks, curved edges, boundaries and is split into the following sections: +The user has to manually define all topological entities (points, edges, blocks, etc.) and is split into the following sections: - points - edges - blocks - patches -An example of the ``blockMeshDict`` dictionary is provided below: - - -Boundary types are listed here: - - - "patch": generic type used for most boundary boundaries - - "wall": for walls - - "empty": for a 2D case, defining the side boundaries parallel to the 2D plane in which the solution is obtained - - "cyclic", "cyclicAMI": for periodic boundary conditions. Come in pairs - - "symmetry": symmetry boundary - -Boundary types vs boundary conditions: +An example of ``blockMeshDict`` dictionary for a 2D cavity is provided below: + +.. code-block:: cpp + + /*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 12 + \\/ M anipulation | + \*---------------------------------------------------------------------------*/ + FoamFile + { + format ascii; + class dictionary; + object blockMeshDict; + } + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + convertToMeters 0.1; + + vertices + ( + (0 0 0) + (1 0 0) + (1 1 0) + (0 1 0) + (0 0 0.1) + (1 0 0.1) + (1 1 0.1) + (0 1 0.1) + ); + + blocks + ( + hex (0 1 2 3 4 5 6 7) (20 20 1) simpleGrading (1 1 1) + ); + + boundary + ( + movingWall + { + type wall; + faces + ( + (3 7 6 2) + ); + } + fixedWalls + { + type wall; + faces + ( + (0 4 7 3) + (2 6 5 1) + (1 5 4 0) + ); + } + frontAndBack + { + type empty; + faces + ( + (0 3 2 1) + (4 5 6 7) + ); + } + ); + + + // ************************************************************************* // + + + +The types a boundary can have are listed here: + + - `patch`: generic type used for most boundary boundaries; + - `wall`: for walls; + - `empty`: for a 2D case, defining the side boundaries parallel to the 2D plane + in which the solution is obtained; + - `cyclic`, "cyclicAMI": for periodic boundary conditions. Come in pairs; + - `symmetry`: symmetry boundary; + + A distinction has to be made between boundary types and boundary conditions: - Boundary conditions for fields are set in the **0** folder! - But some boundary types essentially define the condition, e.g. cyclic. - - In this case, the conditions in the **0** folder must match the boundary type, e.g. cyclic boundary condition for the cyclic boundary type. Same with "empty" + - In this case, the conditions in the **0** folder must match the boundary type, + e.g. cyclic boundary condition for the cyclic boundary type. Same with "empty" snappyHexMesh +++++++++++++ -snappyHexMesh is a fully parallel, split hex, mesh generator that guarantees a minimum mesh quality. Controlled using OpenFOAM dictionaries, it is particularly well suited to batch driven operation. +snappyHexMesh is a fully parallel, split hex mesh generator that guarantees a +minimum (user-defined) mesh quality. Controlled using OpenFOAM dictionaries, it +is particularly well suited to batch driven operation. -Some of the key features are listed here:: +Some of the key features are listed here: - - starts from any pure hex mesh (structured or unstructured) - - reads geometry in triangulated formats, e.g. in stl, obj, vtk - - no limit on the number of input surfaces - - can use simple analytically-defined geometry, e.g. box, sphere, cone - - generates prismatic layers - - scales well when meshing in parallel - - can work with dirty surfaces, i.e. non-watertight surfaces +- starts from any pure hex mesh (structured or unstructured), e.g. as generated + by ``blockMesh`` +- reads geometry in triangulated formats, e.g. in stl, obj, vtk +- no limit on the number of input surfaces +- can use simple analytically-defined geometry, e.g. box, sphere, cone +- generates prismatic layers +- scales well when meshing in parallel +- can work with dirty surfaces, i.e. non-watertight surfaces -Meshing controls are set in the ``snappyHexMeshDict`` located in the case **system** directory, which contains the following sections: - - - Geometry: specification of the input surfaces - - Castellation: starting from any pure hex mesh, refine and optionally load balance when running in parallel. The refinement is specified both according to surfaces, volumes and gaps - - Snapping: guaranteed mesh quality whilst morphing to geometric surfaces and features - - Layers: prismatic layers are inserted by shrinking an existing mesh and creating an infill, subject to the same mesh quality constraints - - Mesh quality: mesh quality settings enforced during the snapping and layer addition phases - - Global setting The overall meshing process is summarised by the figure below: @@ -107,8 +187,22 @@ The overall meshing process is summarised by the figure below: Figure source: OpenFOAM documentation `Meshing process `__. +The process starts with a "background" mesh (usually generated with ``blockMesh``), which is then +*castellated* (i.e. the cells are split close to the body). Then the *snapping* steps takes place, +during which the cells are "clipped" to fit the body. Further steps like growth of boundary +layers and other refinements can follow. +Meshing controls are set in the ``snappyHexMeshDict`` located in the case +**system** directory, which contains the following sections: +- Geometry: specification of the input surfaces +- Castellation: starting from any pure hex mesh, refine and optionally load balance when + running in parallel. The refinement is specified both according to surfaces, volumes and gaps +- Snapping: guaranteed mesh quality whilst morphing to geometric surfaces and features +- Layers: prismatic layers are inserted by shrinking an existing mesh and creating an infill, + subject to the same mesh quality constraints +- Mesh quality: mesh quality settings enforced during the snapping and layer addition phases +- Global settings This includes: @@ -123,35 +217,50 @@ This includes: Note: -- Running ``snappyHexMesh`` will produce a separate directory for each step of the meshing process. The mesh in **constant** folder will be intact. +- Running ``snappyHexMesh`` will produce a separate directory for each step of the meshing process. The + mesh in **constant** folder will be intact. - Running ``snappyHexMesh –overwrite`` to write only the final mesh directly to **constant** folder -Mesh manipulation ------------------ +Mesh visualisation +------------------ + +The computational mesh can be inspected with Paraview. Starting from an OF case folder, a file +(historically named ``r.foam``) has to be created (this will also be needed to visualise +simulation results). After that, Paraview can be opened and you can click on File->Open and +select the newly created ``r.foam``. Once the case is loaded, be sure to select +"Surface with edges" as visualisation type. An example visualisation for a 2D cavity +is shown below. -The following tools are useful when manipulating the mesh, e.g. scaling the geometry, identifying patches and creating sets and zones for physical models and post-processing:: - - surfaceTransformPoints - - topoSet +.. figure:: img/cavity2D_mesh.png + :align: center + + +.. _Mesh conversion: + Mesh conversion --------------- -Quite a few tools exist for mesh conversion:: - - - ccmToFoam - - fireToFoam - - fluentMeshToFoam, fluent3DMeshToFoam - - gmshToFoam - - ansysfoam +Several meshers exist, both commercial and free/open source, which can be used indirectly +with OpenFOAM by importing the produced meshes with some conversion tool. + +- ccm26ToFoam - can be used to import Star-CCM+ meshes. The original mesh cannot contain + interfaces; +- fluentMeshToFoam - can be used to import meshes from ANSYS Fluent; +- gmshToFoam - can be used to import meshes from the open source tool Gmsh; +- ideasToFoam - can be used to convert meshes generated by I-DEAS and Salome; +- gambitToFoam - can be used to import meshes generated by GAMBIT; +- starToFoam - can be used to import meshes generated by STAR-CD meshers, such + as PROSTAR. Summary ------- - - OpenFOAM has several meshing tools, suitable for both simple and complex geometries - - It’s possible to do a lot with snappyHexMesh, including industrial flows - - It requires a lot of parameter tweeking and one has to know the tool well - - Generally, speciallized commercial meshers are still a bit better + - OpenFOAM has several meshing tools, suitable for both simple and complex geometries; + - It’s possible to do a lot with snappyHexMesh, including industrial flows; + - It requires a lot of parameter tweaking and one has to know the tool well; + - Generally, specialised commercial meshers are still a bit better. diff --git a/content/numerics.rst b/content/numerics.rst index d11f5b3..751b8cb 100644 --- a/content/numerics.rst +++ b/content/numerics.rst @@ -5,12 +5,15 @@ Numerics .. questions:: - - What is - - What problem do + - What is the general form of the equations we are trying to solve? + - Which discretisation schemes are available in OpenFOAM and how do we prescribe them? + - Which linear solvers are available in OpenFOAM and how do we prescribe them? .. objectives:: - - Explain + - Know in which files discretisation schemes and linear solvers are prescribed + - Know which schemes are available for each term + - Use some rule of thumb to decide which schemes are more suitable for each term .. instructor-note:: @@ -128,30 +131,9 @@ Interpolation schemes are specified in the ``fvSchemes`` file under the interpol } -A wide variety of interpolation schemes are available, ranging from those that are based solely on geometry, and others, e.g. convection schemes that are functions of the local flow: +A wide variety of interpolation schemes are available; some of them only depend on the geometry, while others are mainly used with convection (divergence) fluxes. +For non-convective fluxes, the ``linear`` scheme is the most used. - - Linear scheme: The most obvious option is linear interpolation, 2nd order accurate. However, for convective fluxes it introduces oscillations - - Convection scheme: Many options for interpolating the convective flux exist. Often it is the most important numerical choice in the simulation. Many of the convection schemes available in OpenFOAM are based on the TVD and NVD: - - - NVD/TVD convection schemes:: - - - Limited linear divergence scheme - - Linear divergence scheme - - Linear-upwind divergence scheme - - MUSCL divergence scheme - - Mid-point divergence scheme - - Minmod divergence scheme - - QUICK divergence scheme - - UMIST divergence scheme - - Upwind divergence scheme - - Van Leer divergence scheme - - - Non-NVD/TVD convection schemes:: - - - Courant number blended divergence scheme - - DES hybrid divergence scheme - - Filtered Linear (2) divergence scheme - - LUST divergence scheme @@ -173,7 +155,7 @@ Now it is the time to choose a time integration scheme. Temporal schemes define } -Available **