I've experienced when using OpenFOAM when making bash scripts and on trying to compile new things, and also happened to me when working only with Python scripts, my machine didn't know which path to use or was chosing the wrong path and not performing as expected. In those scenarios I have the need to manually handle the task or find a way to isolate the environment (virtualize) to ensure my application worked as expected.
Docker is a way to virtualize a whole machine and make it portable via an << Image >>. There, you will have with an operative system, the software you need and other features you may want for your project, all of them already compiled, ready to use and packed into a single file. You can upload to or download from a remote repository and be able to run a instance of that image on any machine in something called << Container >>.
Think on this another scenario: you are currently working on your personal machine, you have developed new tools, turbulence model, source terms or any other class-related feature on openfoam ---> you have made YOUR openfoam, and you may need more resources than the ones you own to do a simulation (or to shorten its execution time). You would want a procedure that eases the set-up of your project's environment on the higher-resources machine you found, and here is where Docker is a nice solution.
Key things about the structure of your Dockerfile:
In YouTube there are a lot of good videos that better explain what is Docker, how to install it, use it in general and what is the << Dockerfile >>. I'll provide some recommendations based on my own experience of the moment to structure your Dockerfile for openfoam and to integrate there your-own-built features:
Go for INSTALLING & CLONING from repos and make later final compilations per sector, rather than a fully COPY your local files.
My first trials where to copy fully my openfoam2012 source folder (the one you have in usr/lib/openfoam/...) and this approach worked for that version ONLY, I succesfully built an image based on the folders of that openfoam that I've modified however took hours the image to be built. Here a snipped part where I commanded to copy my local folder:
# Copy your customized OpenFOAM directory to the image
COPY . /opt/OpenFOAMv2012
But for newer ESI versions of openfoam, that approach did not work, Docker always crashed after hours of execution and I could not gather enough information of the error nor identify what happened. It was pretty frustrating.
What worked? Making a step-by-step instalation: first download and install openfoam, then get from a repository your own-built-features as this:
# Install OpenFOAM
RUN curl -s https://dl.openfoam.com/add-debian-repo.sh | bash && \
wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | bash && \
apt-get -y update && apt-get install -y openfoam2312-default
.
.
.
# Clone the repository
WORKDIR "/home/user"
RUN git clone https://github.com/ManuelaRC/TestingOF2312.git
RUN echo "Cloned respository ManuelaRC/TestingOF2312"
WORKDIR "/home/user/TestingOF2312"
Pack your tool to be compiled inside existing libraries and save the task to call an external-user library in controlDict.
Find a suitable location for the files you have developed and rewrite the Make/files or those directories. An example of a new fvOption, you copy the folder of the new class into derived/ directory and rewrite the inner content fvOption/Make/files with 'sed' command:
# Copy calibratedActuatorDisk to the fvOption folder
RUN cp -r calibratedActuatorDisk /usr/lib/openfoam/openfoam2312/src/fvOptions/sources/derived/
# Modify turbulentTransportModels.C
RUN sed -i '\|$(derivedSources)/actuationDiskSource/actuationDiskSource.C|a $(derivedSources)/calibratedActuatorDisk/calibratedActuatorDisk.C' \
/usr/lib/openfoam/openfoam2312/src/fvOptions/Make/files
RUN sed -i '\|$(derivedSources)/actuationDiskSource/actuationDiskSource.C|a $(derivedSources)/calibratedActuatorDisk/myLookupTable4Turbines/myLookupTable4Turbines.C' \
/usr/lib/openfoam/openfoam2312/src/fvOptions/Make/files
WORKDIR "/usr/lib/openfoam/openfoam2312/src/fvOptions"
RUN source /usr/lib/openfoam/openfoam2312/etc/bashrc && wclean .
Calling again via 'source' and executing in the same line 'wmake' you can compile only the fvOptions library, saving time on not compiling the entire openfoam, again.
If you want to know about the fvOption compiled in this example, visit here.
Consider to incorporate a tutorial case that carries the dictionaries and/or bash scripts that uses your own-built features.
This way, you can ensure to have packed all the suplementary content (dictionaries, external files, case-file structure) required to set a new simulation using your workflow design. You can achieve this by also downloading from the repo an unsolved case (so it's a light-weight folder) and copy it to the tutorial path you consider fits best (according to the physics and solver used).
#### COPYING TUTORIALS
WORKDIR "/home/user/TestingOF2312"
RUN cp -r tutorials /usr/lib/openfoam/openfoam2312/tutorials/incompressible/simpleFoam/
# Confirmation message
RUN echo "tutorials of calibratedActuatorDisk copied to tutorials/incompressible/simpleFoam/"
Build the image:
Place the terminal where your Dockerfile is and run:
docker build -t openfoam2312_wind:v1 .
If you had issues while building, and practically you redid the content of the Dockerfile, you might need to run '--no-cache' flag next time in order to make a refresh building:
docker build --no-cache -t openfoam2312_wind:v1 .
Test it
You can do trials in your own machine and mount your local volume so the case and output files are stored in your local machine and eases the inspection how your application is performing.
I built the image 'openfoam2312_wind:v1' on a fully ubuntu machine and upload it to my dockerHub repository, to later download into a different physical machine, an Ubuntu in WSL, that did not have any OpenFOAM version installed, and could verify that I could run my customized openfoam fast without having to locally install it.
docker run -it --name openfoam_container -v ~/RUNS:/home/user/RUNS openfoam2312_wind:v1 bash
Here, a local directory ~/RUNS in the host machine will be created (if it does not exist already) and it will too in the virtual machine. There will be stored data that will be accesiable to the user at both machines in the same time.
You can take a look at my repo to get more details of the workflow I followed.
Final comments
Doing COPY may be a good choice if you have developed another type of project, like an application of different nature than openfoam. I suspect that my docker-crashing experience was related to long-name paths of files, which is a curious and not so often source of error when copying files.
In the past, I ran simulations in third-party machines where I didn't have the media to compile my own sources-terms, so went using codedSource class. If your mesh is high in cell count or the number of source terms is significant, it can be noticeable the time consumed in the compilation of the codedSource from running a built-in feature. Runing a container is like opening an application ready to use.
If you will run your simulations in parallel, remember to ensure that your host machine (either physical or virtual) has MPI library already installed.