├── .gitignore
├── 404.html
├── CNAME
├── Gemfile
├── Gemfile.lock
├── _config.yml
├── _posts
├── 2020-06-12-3-ways-to-run-tutorials-in-OpenFOAM.markdown
├── 2020-12-20-openfoam-docker-workflow.markdown
├── 2020-12-29-minimizing-docker-images.markdown
└── 2020-12-29-running-pytorch-models-in-openfoam.markdown
├── about.markdown
├── assets
├── img
│ ├── andre_weiner_reduced-edited.jpg
│ ├── boxes_post_crop-1024x915.png
│ ├── cavity_crop-1024x698.png
│ ├── cpp_intellisense.png
│ ├── cylinder_post-1024x576.png
│ ├── multi_stage_docker.png
│ ├── pytorch_download_selection.png
│ └── vscode_edit_setting.png
└── main.scss
└── index.markdown
/.gitignore:
--------------------------------------------------------------------------------
1 | _site
2 | .sass-cache
3 | .jekyll-cache
4 | .jekyll-metadata
5 | vendor
6 |
--------------------------------------------------------------------------------
/404.html:
--------------------------------------------------------------------------------
1 | ---
2 | permalink: /404.html
3 | layout: default
4 | ---
5 |
6 |
19 |
20 |
21 |
404
22 |
23 |
Page not found :(
24 |
The requested page could not be found.
25 |
26 |
--------------------------------------------------------------------------------
/CNAME:
--------------------------------------------------------------------------------
1 | ml-cfd.com
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 | # Hello! This is where you manage which Jekyll version is used to run.
3 | # When you want to use a different version, change it below, save the
4 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
5 | #
6 | # bundle exec jekyll serve
7 | #
8 | # This will help ensure the proper Jekyll version is running.
9 | # Happy Jekylling!
10 | # gem "jekyll", "~> 4.2.2"
11 | # This is the default theme for new Jekyll sites. You may change this to anything you like.
12 | gem "minima", "~> 2.5"
13 | # If you want to use GitHub Pages, remove the "gem "jekyll"" above and
14 | # uncomment the line below. To upgrade, run `bundle update github-pages`.
15 | gem "github-pages", "~> 225", group: :jekyll_plugins
16 | # If you have any plugins, put them here!
17 | group :jekyll_plugins do
18 | gem "jekyll-feed", "~> 0.12"
19 | end
20 |
21 | # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
22 | # and associated library.
23 | platforms :mingw, :x64_mingw, :mswin, :jruby do
24 | gem "tzinfo", "~> 1.2"
25 | gem "tzinfo-data"
26 | end
27 |
28 | # Performance-booster for watching directories on Windows
29 | gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
30 |
31 | # Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
32 | # do not have a Java counterpart.
33 | gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]
34 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | activesupport (6.0.4.6)
5 | concurrent-ruby (~> 1.0, >= 1.0.2)
6 | i18n (>= 0.7, < 2)
7 | minitest (~> 5.1)
8 | tzinfo (~> 1.1)
9 | zeitwerk (~> 2.2, >= 2.2.2)
10 | addressable (2.8.0)
11 | public_suffix (>= 2.0.2, < 5.0)
12 | coffee-script (2.4.1)
13 | coffee-script-source
14 | execjs
15 | coffee-script-source (1.11.1)
16 | colorator (1.1.0)
17 | commonmarker (0.23.4)
18 | concurrent-ruby (1.1.9)
19 | dnsruby (1.61.9)
20 | simpleidn (~> 0.1)
21 | em-websocket (0.5.3)
22 | eventmachine (>= 0.12.9)
23 | http_parser.rb (~> 0)
24 | ethon (0.15.0)
25 | ffi (>= 1.15.0)
26 | eventmachine (1.2.7)
27 | execjs (2.8.1)
28 | faraday (1.10.0)
29 | faraday-em_http (~> 1.0)
30 | faraday-em_synchrony (~> 1.0)
31 | faraday-excon (~> 1.1)
32 | faraday-httpclient (~> 1.0)
33 | faraday-multipart (~> 1.0)
34 | faraday-net_http (~> 1.0)
35 | faraday-net_http_persistent (~> 1.0)
36 | faraday-patron (~> 1.0)
37 | faraday-rack (~> 1.0)
38 | faraday-retry (~> 1.0)
39 | ruby2_keywords (>= 0.0.4)
40 | faraday-em_http (1.0.0)
41 | faraday-em_synchrony (1.0.0)
42 | faraday-excon (1.1.0)
43 | faraday-httpclient (1.0.1)
44 | faraday-multipart (1.0.3)
45 | multipart-post (>= 1.2, < 3)
46 | faraday-net_http (1.0.1)
47 | faraday-net_http_persistent (1.2.0)
48 | faraday-patron (1.0.0)
49 | faraday-rack (1.0.0)
50 | faraday-retry (1.0.3)
51 | ffi (1.15.5)
52 | forwardable-extended (2.6.0)
53 | gemoji (3.0.1)
54 | github-pages (225)
55 | github-pages-health-check (= 1.17.9)
56 | jekyll (= 3.9.0)
57 | jekyll-avatar (= 0.7.0)
58 | jekyll-coffeescript (= 1.1.1)
59 | jekyll-commonmark-ghpages (= 0.2.0)
60 | jekyll-default-layout (= 0.1.4)
61 | jekyll-feed (= 0.15.1)
62 | jekyll-gist (= 1.5.0)
63 | jekyll-github-metadata (= 2.13.0)
64 | jekyll-include-cache (= 0.2.1)
65 | jekyll-mentions (= 1.6.0)
66 | jekyll-optional-front-matter (= 0.3.2)
67 | jekyll-paginate (= 1.1.0)
68 | jekyll-readme-index (= 0.3.0)
69 | jekyll-redirect-from (= 0.16.0)
70 | jekyll-relative-links (= 0.6.1)
71 | jekyll-remote-theme (= 0.4.3)
72 | jekyll-sass-converter (= 1.5.2)
73 | jekyll-seo-tag (= 2.8.0)
74 | jekyll-sitemap (= 1.4.0)
75 | jekyll-swiss (= 1.0.0)
76 | jekyll-theme-architect (= 0.2.0)
77 | jekyll-theme-cayman (= 0.2.0)
78 | jekyll-theme-dinky (= 0.2.0)
79 | jekyll-theme-hacker (= 0.2.0)
80 | jekyll-theme-leap-day (= 0.2.0)
81 | jekyll-theme-merlot (= 0.2.0)
82 | jekyll-theme-midnight (= 0.2.0)
83 | jekyll-theme-minimal (= 0.2.0)
84 | jekyll-theme-modernist (= 0.2.0)
85 | jekyll-theme-primer (= 0.6.0)
86 | jekyll-theme-slate (= 0.2.0)
87 | jekyll-theme-tactile (= 0.2.0)
88 | jekyll-theme-time-machine (= 0.2.0)
89 | jekyll-titles-from-headings (= 0.5.3)
90 | jemoji (= 0.12.0)
91 | kramdown (= 2.3.1)
92 | kramdown-parser-gfm (= 1.1.0)
93 | liquid (= 4.0.3)
94 | mercenary (~> 0.3)
95 | minima (= 2.5.1)
96 | nokogiri (>= 1.12.5, < 2.0)
97 | rouge (= 3.26.0)
98 | terminal-table (~> 1.4)
99 | github-pages-health-check (1.17.9)
100 | addressable (~> 2.3)
101 | dnsruby (~> 1.60)
102 | octokit (~> 4.0)
103 | public_suffix (>= 3.0, < 5.0)
104 | typhoeus (~> 1.3)
105 | html-pipeline (2.14.0)
106 | activesupport (>= 2)
107 | nokogiri (>= 1.4)
108 | http_parser.rb (0.8.0)
109 | i18n (0.9.5)
110 | concurrent-ruby (~> 1.0)
111 | jekyll (3.9.0)
112 | addressable (~> 2.4)
113 | colorator (~> 1.0)
114 | em-websocket (~> 0.5)
115 | i18n (~> 0.7)
116 | jekyll-sass-converter (~> 1.0)
117 | jekyll-watch (~> 2.0)
118 | kramdown (>= 1.17, < 3)
119 | liquid (~> 4.0)
120 | mercenary (~> 0.3.3)
121 | pathutil (~> 0.9)
122 | rouge (>= 1.7, < 4)
123 | safe_yaml (~> 1.0)
124 | jekyll-avatar (0.7.0)
125 | jekyll (>= 3.0, < 5.0)
126 | jekyll-coffeescript (1.1.1)
127 | coffee-script (~> 2.2)
128 | coffee-script-source (~> 1.11.1)
129 | jekyll-commonmark (1.4.0)
130 | commonmarker (~> 0.22)
131 | jekyll-commonmark-ghpages (0.2.0)
132 | commonmarker (~> 0.23.4)
133 | jekyll (~> 3.9.0)
134 | jekyll-commonmark (~> 1.4.0)
135 | rouge (>= 2.0, < 4.0)
136 | jekyll-default-layout (0.1.4)
137 | jekyll (~> 3.0)
138 | jekyll-feed (0.15.1)
139 | jekyll (>= 3.7, < 5.0)
140 | jekyll-gist (1.5.0)
141 | octokit (~> 4.2)
142 | jekyll-github-metadata (2.13.0)
143 | jekyll (>= 3.4, < 5.0)
144 | octokit (~> 4.0, != 4.4.0)
145 | jekyll-include-cache (0.2.1)
146 | jekyll (>= 3.7, < 5.0)
147 | jekyll-mentions (1.6.0)
148 | html-pipeline (~> 2.3)
149 | jekyll (>= 3.7, < 5.0)
150 | jekyll-optional-front-matter (0.3.2)
151 | jekyll (>= 3.0, < 5.0)
152 | jekyll-paginate (1.1.0)
153 | jekyll-readme-index (0.3.0)
154 | jekyll (>= 3.0, < 5.0)
155 | jekyll-redirect-from (0.16.0)
156 | jekyll (>= 3.3, < 5.0)
157 | jekyll-relative-links (0.6.1)
158 | jekyll (>= 3.3, < 5.0)
159 | jekyll-remote-theme (0.4.3)
160 | addressable (~> 2.0)
161 | jekyll (>= 3.5, < 5.0)
162 | jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
163 | rubyzip (>= 1.3.0, < 3.0)
164 | jekyll-sass-converter (1.5.2)
165 | sass (~> 3.4)
166 | jekyll-seo-tag (2.8.0)
167 | jekyll (>= 3.8, < 5.0)
168 | jekyll-sitemap (1.4.0)
169 | jekyll (>= 3.7, < 5.0)
170 | jekyll-swiss (1.0.0)
171 | jekyll-theme-architect (0.2.0)
172 | jekyll (> 3.5, < 5.0)
173 | jekyll-seo-tag (~> 2.0)
174 | jekyll-theme-cayman (0.2.0)
175 | jekyll (> 3.5, < 5.0)
176 | jekyll-seo-tag (~> 2.0)
177 | jekyll-theme-dinky (0.2.0)
178 | jekyll (> 3.5, < 5.0)
179 | jekyll-seo-tag (~> 2.0)
180 | jekyll-theme-hacker (0.2.0)
181 | jekyll (> 3.5, < 5.0)
182 | jekyll-seo-tag (~> 2.0)
183 | jekyll-theme-leap-day (0.2.0)
184 | jekyll (> 3.5, < 5.0)
185 | jekyll-seo-tag (~> 2.0)
186 | jekyll-theme-merlot (0.2.0)
187 | jekyll (> 3.5, < 5.0)
188 | jekyll-seo-tag (~> 2.0)
189 | jekyll-theme-midnight (0.2.0)
190 | jekyll (> 3.5, < 5.0)
191 | jekyll-seo-tag (~> 2.0)
192 | jekyll-theme-minimal (0.2.0)
193 | jekyll (> 3.5, < 5.0)
194 | jekyll-seo-tag (~> 2.0)
195 | jekyll-theme-modernist (0.2.0)
196 | jekyll (> 3.5, < 5.0)
197 | jekyll-seo-tag (~> 2.0)
198 | jekyll-theme-primer (0.6.0)
199 | jekyll (> 3.5, < 5.0)
200 | jekyll-github-metadata (~> 2.9)
201 | jekyll-seo-tag (~> 2.0)
202 | jekyll-theme-slate (0.2.0)
203 | jekyll (> 3.5, < 5.0)
204 | jekyll-seo-tag (~> 2.0)
205 | jekyll-theme-tactile (0.2.0)
206 | jekyll (> 3.5, < 5.0)
207 | jekyll-seo-tag (~> 2.0)
208 | jekyll-theme-time-machine (0.2.0)
209 | jekyll (> 3.5, < 5.0)
210 | jekyll-seo-tag (~> 2.0)
211 | jekyll-titles-from-headings (0.5.3)
212 | jekyll (>= 3.3, < 5.0)
213 | jekyll-watch (2.2.1)
214 | listen (~> 3.0)
215 | jemoji (0.12.0)
216 | gemoji (~> 3.0)
217 | html-pipeline (~> 2.2)
218 | jekyll (>= 3.0, < 5.0)
219 | kramdown (2.3.1)
220 | rexml
221 | kramdown-parser-gfm (1.1.0)
222 | kramdown (~> 2.0)
223 | liquid (4.0.3)
224 | listen (3.7.1)
225 | rb-fsevent (~> 0.10, >= 0.10.3)
226 | rb-inotify (~> 0.9, >= 0.9.10)
227 | mercenary (0.3.6)
228 | minima (2.5.1)
229 | jekyll (>= 3.5, < 5.0)
230 | jekyll-feed (~> 0.9)
231 | jekyll-seo-tag (~> 2.1)
232 | minitest (5.15.0)
233 | multipart-post (2.1.1)
234 | nokogiri (1.13.3-x86_64-linux)
235 | racc (~> 1.4)
236 | octokit (4.22.0)
237 | faraday (>= 0.9)
238 | sawyer (~> 0.8.0, >= 0.5.3)
239 | pathutil (0.16.2)
240 | forwardable-extended (~> 2.6)
241 | public_suffix (4.0.6)
242 | racc (1.6.0)
243 | rb-fsevent (0.11.1)
244 | rb-inotify (0.10.1)
245 | ffi (~> 1.0)
246 | rexml (3.2.5)
247 | rouge (3.26.0)
248 | ruby2_keywords (0.0.5)
249 | rubyzip (2.3.2)
250 | safe_yaml (1.0.5)
251 | sass (3.7.4)
252 | sass-listen (~> 4.0.0)
253 | sass-listen (4.0.0)
254 | rb-fsevent (~> 0.9, >= 0.9.4)
255 | rb-inotify (~> 0.9, >= 0.9.7)
256 | sawyer (0.8.2)
257 | addressable (>= 2.3.5)
258 | faraday (> 0.8, < 2.0)
259 | simpleidn (0.2.1)
260 | unf (~> 0.1.4)
261 | terminal-table (1.8.0)
262 | unicode-display_width (~> 1.1, >= 1.1.1)
263 | thread_safe (0.3.6)
264 | typhoeus (1.4.0)
265 | ethon (>= 0.9.0)
266 | tzinfo (1.2.9)
267 | thread_safe (~> 0.1)
268 | unf (0.1.4)
269 | unf_ext
270 | unf_ext (0.0.8)
271 | unicode-display_width (1.8.0)
272 | zeitwerk (2.5.4)
273 |
274 | PLATFORMS
275 | x86_64-linux
276 |
277 | DEPENDENCIES
278 | github-pages (~> 225)
279 | http_parser.rb (~> 0.6.0)
280 | jekyll-feed (~> 0.12)
281 | minima (~> 2.5)
282 | tzinfo (~> 1.2)
283 | tzinfo-data
284 | wdm (~> 0.1.1)
285 |
286 | BUNDLED WITH
287 | 2.3.8
288 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | # Welcome to Jekyll!
2 | #
3 | # This config file is meant for settings that affect your whole blog, values
4 | # which you are expected to set up once and rarely edit after that. If you find
5 | # yourself editing this file very often, consider using Jekyll's data files
6 | # feature for the data you need to update frequently.
7 | #
8 | # For technical reasons, this file is *NOT* reloaded automatically when you use
9 | # 'bundle exec jekyll serve'. If you change this file, please restart the server process.
10 | #
11 | # If you need help with YAML syntax, here are some quick references for you:
12 | # https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
13 | # https://learnxinyminutes.com/docs/yaml/
14 | #
15 | # Site settings
16 | # These are used to personalize your new site. If you look in the HTML files,
17 | # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
18 | # You can create any custom variable you would like, and they will be accessible
19 | # in the templates via {{ site.myvariable }}.
20 |
21 | title: ML-CFD
22 | email: andre.weiner@yahoo.de
23 | description: >- # this means to ignore newlines until "baseurl:"
24 | Blog about machine learning and computational fluid dynamics
25 | baseurl: "" # the subpath of your site, e.g. /blog
26 | url: "https://ml-cfd.com" # the base hostname & protocol for your site, e.g. http://example.com
27 | # twitter_username: jekyllrb
28 | github_username: AndreWeiner
29 | linkedin_username: andre-weiner-a79752133
30 |
31 | # Build settings
32 | theme: minima
33 | plugins:
34 | - jekyll-feed
35 |
36 | # Exclude from processing.
37 | # The following items will not be processed, by default.
38 | # Any item listed under the `exclude:` key here will be automatically added to
39 | # the internal "default list".
40 | #
41 | # Excluded items can be processed by explicitly listing the directories or
42 | # their entries' file path in the `include:` list.
43 | #
44 | # exclude:
45 | # - .sass-cache/
46 | # - .jekyll-cache/
47 | # - gemfiles/
48 | # - Gemfile
49 | # - Gemfile.lock
50 | # - node_modules/
51 | # - vendor/bundle/
52 | # - vendor/cache/
53 | # - vendor/gems/
54 | # - vendor/ruby/
55 |
--------------------------------------------------------------------------------
/_posts/2020-06-12-3-ways-to-run-tutorials-in-OpenFOAM.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: "3 ways to run tutorials in OpenFOAM"
4 | date: 2020-06-12 12:00:00 +0100
5 | categories: OpenFOAM basic
6 | ---
7 |
8 | ### Tutorials - The starting point of almost every simulation
9 |
10 | Tutorials are an interactive way of transferring knowledge. They are a kind of recipe that provides you with the necessary steps to complete a particular task. The maintainers of OpenFOAM deliver an extensive collection of tutorials together with the library. For OpenFOAM users, the supplied case setups are the most useful information provided for free. Reading this post to the end will enable you to run all these tutorials, avoiding some pitfalls.
11 |
12 | Tutorials are essential because to start your project in most cases you will:
13 |
14 | 1. Select a solver implementing all necessary physics
15 | 2. Check the available tutorials for the solver
16 | 3. Copy, rename, and modify the most similar tutorial
17 | 4. Test and run your simulation
18 |
19 | The tutorial collection contains a variety of different case setups. In the following, you will learn three different ways to run OpenFOAM tutorials. To get started, open a terminal window and copy the tutorial collection into your run directory.
20 |
21 | ```bash
22 | cp -r $FOAM_TUTORIALS $FOAM_RUN
23 | ```
24 |
25 | ### 1. Simple *blockMesh/mySolverFoam* tutorials
26 |
27 | The [lid-driven cavity](https://www.cfd-online.com/Wiki/Lid-driven_cavity_problem) flow is a common test case for validation. It is also one of the cases thoroughly explained in the [OpenFOAM tutorial guide](https://openfoam.com/documentation/tutorial-guide/tutorialse2.php#x6-60002.1) (section 2.1). The way how you create and run simulations in OpenFOAM may seem a bit strange to users who come from a Microsoft-Windows environment or who are used to have a [GUI](https://en.wikipedia.org/wiki/Graphical_user_interface). Instead, solvers, utilities, or scripts in OpenFOAM require a certain directory structure containing control files. Navigate to the cavity folder and type `ls -R` or `tree` to get an overview.
28 |
29 | ```bash
30 | cd $FOAM_RUN/tutorials/incompressible/icoFoam/cavity/
31 | tree
32 | .
33 | ├── 0
34 | │ ├── p
35 | │ └── U
36 | ├── constant
37 | │ └── transportProperties
38 | └── system
39 | ├── blockMeshDict
40 | ├── controlDict
41 | ├── fvSchemes
42 | └── fvSolution
43 | ```
44 |
45 | All tutorials have a **system** (control files for solvers and utilities), a **constant** (mesh, material properties), and a **0** (zero; technically, the initial time folder could have any value/name but *0* is the most common scenario) directory (initial values, boundary conditions). If no further execution scripts are provided, you will always have to run `blockMesh`, for the mesh creation, and afterward your solver of choice, in our case `icoFoam`. In rare cases, there are one or two more dictionaries for preprocessing in the system folder (pre - they are executed before the solver). A possible scenario is an additional **setFieldsDict** to set initial field values. The corresponding utility to run after `blockMesh` would be `setFields`. The applications will give some output which should be saved in log files for later use (and to avoid that the terminal window is overflowing with solver output). `&>` redirects the standard output and error messages of, for example, *blockMesh* to the file *log.blockMesh*. Now it’s time to run our first tutorial:
46 |
47 | ```bash
48 | blockMesh &> log.blockMesh
49 | # ... maybe some more preprocessing utilities
50 | icoFoam &> log.icoFoam
51 | ```
52 |
53 | |  |
54 | |:--:|
55 | |*Vector plot of cell-centered velocity colored by its magnitude.*|
56 |
57 | ### 2. Tutorials with *Allrun/Allclean* scripts
58 |
59 | The `reactingParcelFilmFoam` solver is, as one can guess from the name, a fairly complex application involving many physical models. Pre- and post-processing tasks for such simulations are correspondingly extensive. At this point, running every single application with its options would be too time (and nerve) consuming. Luckily, automating processes comes naturally within a Linux environment via **Shell** scripts. Basically, all necessary commands are written into a file which is then executed. In the tutorial collection, these scripts are usually called `Allrun`. For convenience, different scripts can be created for subtasks, e.q. meshing or parallel execution. After the setup is complete, you may want to run a variety of simulations with different parameters. Here it comes in handy to have an `Allclean` script, which resets the case to its initial state. All of this you can find in the **hotBoxes** tutorial.
60 |
61 | ```bash
62 | cd $FOAM_RUN/tutorials/lagrangian/reactingParcelFilmFoam/hotBoxes
63 | tree -L 1
64 | .
65 | ├── 0.org
66 | ├── Allclean
67 | ├── Allrun
68 | ├── Allrun-parallel
69 | ├── Allrun.pre
70 | ├── constant
71 | ...
72 | └── system
73 | ```
74 |
75 | Running the tutorial in serial takes about 24h. So it's wise to run it overnight or/and to use the `Allrun-parallel` script, which runs the solver with four processes in parallel (about 9h to complete on my office laptop).
76 |
77 | ```bash
78 | ./Allrun
79 | ```
80 |
81 | |  |
82 | |:--:|
83 | |*The surface color indicates the thickness of the cooling film. The Lagrangian particles' diameters scale with the mass they carry.*|
84 |
85 | ### 3. Tutorials that require system operations
86 |
87 | The last type of tutorials I want to introduce here need system operations. *System operations* basically means that an application (e.g., a solver) compiles and (hopefully) runs user-supplied C++ source code at runtime. Examples are the [#codeStream](http://openfoam.org/release/2-0-0/run-time-control-code-compilation/) directive or the **codedFixedValue** boundary condition (same link as before). Since the [OpenFOAM 2.3.1 release](http://openfoam.org/release/2-3-1/), system calls are allowed by default. If you run an older version or you want to check your configuration, open the system-wide **controlDict** and set the **allowSystemOperations** switch to 1.
88 |
89 | ```bash
90 | # for a system-wide installation root privileges are required
91 | # e.g on Ubuntu run
92 | sudo gedit $FOAM_ETC/controlDict
93 | ```
94 |
95 | ```cpp
96 | // and set the allowSystemOperations switch to 1
97 | InfoSwitches
98 | {
99 | ...
100 | // Allow case-supplied C++ code (#codeStream, codedFixedValue)
101 | allowSystemOperations 1;
102 | }
103 | ```
104 |
105 | Now we are ready to simulate the potential flow around a cylinder. This case is very charming because it allows us to validate our numerical results with an [analytical solution](https://en.wikipedia.org/wiki/Potential_flow_around_a_circular_cylinder). Within the case’s **controlDict** a coded function object is supplied which later on calculates the numerical error as defined in the picture below. So let’s run the simulation!
106 |
107 | ```
108 | cd $FOAM_RUN/tutorials/basic/potentialFoam/cylinder
109 | blockMesh &>log.blockMesh
110 | potentialFoam &>log.potentialFoam
111 | ```
112 |
113 | Here is a task for **you**:
114 |
115 | 1. Take a close look at the streamlines in the picture below. First, check the alignment between mesh and streamlines. Can you spot under which conditions the highest deviations occur?
116 | 2. Open the **fvSolution** file located in the system directory, set different values for the **nNonOrthogonalCorrectors** (0, 1, 2, …), and re-run the simulation. How does the error behave?
117 |
118 | |  |
119 | |:--:|
120 | |*The color of the streamlines indicates the relative difference between numerical and analytical solution.*|
121 |
122 | That’s it for this tutorial! With the above information, you are prepared to explore all the tutorials coming with OpenFOAM.
123 |
124 | Cheers, Andre
--------------------------------------------------------------------------------
/_posts/2020-12-20-openfoam-docker-workflow.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: "A detailed look at the OpenFOAM docker workflow"
4 | date: 2020-12-20 12:00:00 +0100
5 | categories: OpenFOAM Docker
6 | ---
7 |
8 | **Update (Mar 5 2022)**: the workflow described in this article has been revised at the end of 2022. Have a look at the [updated workflow](https://develop.openfoam.com/Development/openfoam/-/wikis/precompiled/docker). Nonetheless, if you are new to working with Docker and OpenFOAM, you will still learn the essentials from this article.
9 |
10 | ---
11 |
12 | This article is all about
13 |
14 | - what the installOpenFOAM script does,
15 | - what the startOpenFOAM script does, and
16 | - ways to ship your OpenFOAM/solvers/utilities using Docker.
17 |
18 | The quickest way to get a running OpenFOAM installation on any Linux distribution (or even Mac and Windows) is probably via a Docker image. In case you have never heard of Docker, and you are wondering why you should bother to use it, Robin Knowles from [CFD Engine](https://www.cfdengine.com/) wrote a fantastic article entitled [The complete guide to Docker & OpenFOAM](https://www.cfdengine.com/blog/how-to-install-openfoam-anywhere-with-docker/), which I really recommend to read before continuing with this post. If you are not in the mood to read another article, here is why you should care about Docker in a nutshell:
19 |
20 | - Docker allows creating isolated, standardized software images.
21 | - An image contains the software itself and all its dependencies, which is why you can share and run your app (almost) without limit.
22 | - This flexibility makes your app executable even if you do not know the hardware or operating system (OS) it is going to run on. You can run your app in the cloud, or you can share it quickly with a co-worker who uses a different OS, or you can conserve a solver and it will be still runnable in five years from now and it will still give the exact same results.
23 |
24 | If you followed the [installation instructions](https://openfoam.com/download/install-binary-linux.php) provided on the ESI OpenFOAM website, you installed Docker and executed two scripts, namely installOpenFOAM, and startOpenFOAM. Afterward, you were magically presented with a running OpenFOAM installation without having had to worry about any dependencies besides Docker. And there is more: in the isolated container environment, you still have the same username as on the Linux host and use the same credentials to run sudo commands. There is also a fully-fledged version of paraFoam available. You may be wondering why this should be a big deal?! Well, Docker is great for creating standardized, isolated, and minimalistic environments. Isolation means that Docker only uses few core components of the host system’s Linux kernel (Cgroups, Namespaces, etc. - [learn more](https://docs.docker.com/engine/security/security/)), but it doesn’t depend on or interact with any other applications, libraries, or configuration files of the host. To work in a Docker container feels a bit like working on a remote server, with the difference being only that this remote server is an isolated fraction of your workstation. Still, with the OpenFOAM-plus workflow, the OpenFOAM container integrates seamlessly into your system, and you can run simulations just as well as with the native installation. But how and when does the mapping of username, password, or permissions happen? And how does it become possible to access your simulation data if created in an isolated environment? It all happens with the execution of two short scripts. Understanding these scripts will enable you to modify them according to your needs. If you are curious to learn more, read on.
25 |
26 | ### *installOpenFOAM*
27 |
28 | Let’s start with the first script that was executed: `installOpenFOAM`. The name suggests that this script installs OpenFOAM on your computer, but as you will learn in the next paragraphs, there is no classical installation process when working with images/containers. A more suitable name might be `initOpenFOAMContainer` or even better `runOpenFOAMContainer`, but I guess such naming could confuse users new to Docker and containerization. The script may be divided into two logical parts: first, some useful environment variables are defined, and then the Docker run command is executed.
29 |
30 | ```bash
31 | username="$USER"
32 | user="$(id -u)"
33 | home="${1:-$HOME}"
34 | imageName="openfoamplus/of_v1812_centos73"
35 | containerName="of_v1812"
36 | displayVar="$DISPLAY"
37 | ```
38 |
39 | Line 1 and 2 define variables for username and user id. The username will be your login name as in the command line prompt, e. g. **username**`@workstation:~$`. The id is an integer value associated with the user, most likely 1001. The next line is of great importance because it defines where (in which path) you will interact with the OpenFOAM container. The syntax of the right-hand-side works as follows: `${defined_path:-default_path}`. The default path is simply your home directory `HOME`. The default path is used if no other valid path was given as the first command-line argument to the `installOpenFOAM` script. To change the default path, one would execute `./installOpenFOAM /absolute/alternative/path`. The imageName is the name of the OpenFOAM image hosted on [Dockerhub](https://hub.docker.com/r/openfoamplus/of_v1812_centos73). The part of the image name before the front slash corresponds to the Dockerhub user, here **openfoamplus**. The second part gives more information about the image. For example, the present image is built on CentOS 7.3 and contains version 1812 of OpenFOAM-plus. Last but not least, there is the `DISPLAY` variable, which tells an application with a graphical user interface (GUI) where to display the interface. On my laptop, the value of `DISPLAY` is simply `:0` (zero), which is my primary (and only) screen. Remember, Docker containers are a bit like remote servers, so you have to provide some additional information to use GUI applications. With all the information gathered up to this point, we are ready to move on to the actual container creation.
40 |
41 | The syntax to create and execute a container is `docker run [options] IMAGE [command] [args]` ([read more](https://docs.docker.com/engine/reference/run/)). The image name is stored in the variable `imageName` and appears only in the twelfth line of the command in the code box below. Every item between docker run and ${imageName} starting with `-` or `--` is an option. The command to be executed after the container was created is /bin/bash, which is why you are presented with a command-line prompt when starting the OpenFOAM container. Bash is run with the `-rcfile` argument to execute additional commands from the file specified thereafter (line 13). The content of `setImage.sh` is shown in the last code box of this article for completeness.
42 |
43 | {% highlight bash linenos %}
44 | docker run -it -d --name ${containerName} --user=${user} \
45 | -e USER=${username} \
46 | -e QT_X11_NO_MITSHM=1 \
47 | -e DISPLAY=${displayVar} \
48 | -e QT_XKB_CONFIG_ROOT=/usr/share/X11/xkb \
49 | --workdir="${home}" \
50 | --volume="${home}:${home}" \
51 | --volume="/etc/group:/etc/group:ro" \
52 | --volume="/etc/passwd:/etc/passwd:ro" \
53 | --volume="/etc/shadow:/etc/shadow:ro" \
54 | --volume="/etc/sudoers.d:/etc/sudoers.d:ro" \
55 | -v=/tmp/.X11-unix:/tmp/.X11-unix ${imageName} \
56 | /bin/bash --rcfile /opt/OpenFOAM/setImage_v1812.sh
57 | {% endhighlight %}
58 |
59 | Let’s take a closer look at all the container options displayed above because this is where the magic happens.
60 |
61 | | option | description |
62 | |:--:|:--|
63 | | `-i` or `--interactive` | keeps the standard input open even if you detach from the container, e.g., if you close the terminal |
64 | | `-t` or `--tty` | allocates a virtual console to interact with the container |
65 | | `-d` or `--detach` | allows running a container in the background; the container will not stop after you exit from the container |
66 | | `--name` | sets a container name |
67 | | `-u` or `--user` | creates an additional user within the container; the default user is `root` |
68 | | `-e` or `--env` | sets environment variables in the container |
69 | | `-w` or `--workdir` | sets the working directory inside the container, e.g., the default directory after attaching (logging in) to the container |
70 | | `-v` or `--volume` | binds a source from the host to the container; such a source might be a file, a directory, or a Docker volume |
71 |
72 | The first interesting option is the `--user` flag, which is used to create a new user inside the container with the same id as the user creating the container. Additionally, in line 2, the `-e` option sets the corresponding username. More environment variables are set in lines 3-5 to enable a GUI (mainly ParaView) to be forwarded to the host system. In line 6 the working directory is set to `home`. The home directory will be the same as on the host system since we first mapped the user to the container (unless a different directory was specified). The syntax to [bind volumes](https://docs.docker.com/storage/bind-mounts/) to the container is `--volume path_on_host:path_in_container:options`. The last argument is optional, for example, to make a file or directory read-only with the `ro` option. The first and most important directory-mount happens in line 7, where the home directory of the container is bound to the host’s home. If you use the `FOAM_RUN` directory to run test cases, then all the solver/utility output will be accessible from the home directory of the host. Likewise, data can be made accessible to the container by moving it to the home directory. After mounting home, there are three more single files and two folders that are bound to the container:
73 |
74 | - the `/etc/group` file contains a list of groups and their members
75 | - `/etc/passwd` contains further user attributes like id or password
76 | - `/etc/shadow` is a file with the same content as `/etc/passwd` but only root has read access (this is some safety feature of modern Linux systems)
77 | - the `sudoers.d` folder sometimes contains sudoers (users with root privileges) information that has to stay unchanged whenever the system is upgraded
78 | - the `.X11-unix` folder contains an endpoint (a Unix socket) for the Xserver to communicate with clients (applications like ParaView)
79 |
80 | ### *startOpenFOAM*
81 |
82 | The `installOpenFOAM` will be only run once to create the OpenFOAM container. `startOpenFOAM` is the script to execute whenever you need to login to the container. The first line in the scripts grants the container access to the Xserver of the host (to draw GUIs). After that follow two common Docker commands. `docker start CONTAINER_NAME` will start the container in case it was stopped, for example, after rebooting the host system. It is important to note, however, that the container must exist. Finally, an interactive bash shell is executed in the running container using the Docker `exec` command: `docker exec [options] CONTAINER_NAME command [args]`.
83 |
84 | ```bash
85 | xhost +local:of_v1812
86 | docker start of_v1812
87 | docker exec -it of_v1812 /bin/bash -rcfile /opt/OpenFOAM/setImage_v1812.sh
88 | ```
89 |
90 | The content of the `rcfile` loaded when you execute bash in the container is included in the code box below. First, all the OpenFOAM-specific variables and commands are sourced (made available). After that, some third-party binaries and libraries are added to `PATH` and `LD_LIBRARY_PATH` to have them system-wide available for execution or for compiling new applications (in the container). The last exported variable is again a dependency of `paraFoam`, which is built with [Qt](https://en.wikipedia.org/wiki/Qt_(software)).
91 |
92 | ```bash
93 | source /opt/OpenFOAM/OpenFOAM-v1812/etc/bashrc
94 | export LD_LIBRARY_PATH=$WM_THIRD_PARTY_DIR/platforms/linux64Gcc/ParaView-5.6.0/lib/mesa:$LD_LIBRARY_PATH
95 | export LD_LIBRARY_PATH=$WM_THIRD_PARTY_DIR/platforms/linux64Gcc/ParaView-5.6.0/lib/paraview-5.6/plugins:$LD_LIBRARY_PATH
96 | export LD_LIBRARY_PATH=$WM_THIRD_PARTY_DIR/platforms/linux64Gcc/qt-5.9.0/lib:$LD_LIBRARY_PATH
97 | export LD_LIBRARY_PATH=$WM_THIRD_PARTY_DIR/platforms/linux64/zlib-1.2.11/lib:$LD_LIBRARY_PATH
98 | export PATH=$WM_THIRD_PARTY_DIR/platforms/linux64Gcc/qt-5.9.0/bin:$PATH
99 | export QT_PLUGIN_PATH=$WM_THIRD_PARTY_DIR/platforms/linux64Gcc/qt-5.9.0/plugins
100 | ```
101 |
102 | ### Shipping OpenFOAM using Docker
103 |
104 | If you have your own modified version of OpenFOAM or some solver/utility you have written, here are approaches to preserve and ship your work using Docker:
105 |
106 | - Large modifications to OpenFOAM itself require to build a new OpenFOAM Docker image. For that you can base your image on a Linux distribution close to your development environment, e.g. Ubuntu or CentOS, you install all dependencies needed to compile OpenFOAM from scratch, you copy your modified version to the image, and compile it.
107 | - A new solver/utility can be built on top of the official OpenFOAM Docker image. You will copy the new sources to the image, compile them, and voilà.
108 | - If you only need a runnable binary of your app, it is possible to build an image from scratch and to copy only the binary and the dynamically-linked libraries to the image. That’s the most minimalistic way to ship an app.
109 |
110 | I will describe each of these approaches in more detail in follow-up articles.
111 |
112 | Cheers, Andre
--------------------------------------------------------------------------------
/_posts/2020-12-29-minimizing-docker-images.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: "Minimizing the size of Docker images using multi-stage builds"
4 | date: 2020-12-29 12:00:00 +0100
5 | categories: OpenFOAM Docker
6 | ---
7 |
8 | **Update (Mar 6 2022)**: there are now different official [OpenFOAM images](https://develop.openfoam.com/Development/openfoam/-/wikis/precompiled/docker) available, which are tailored to development or application. The images are also build in multiple stages and have increasing features/size with each stage.
9 |
10 | ---
11 |
12 | 1. A multi-stage build version of hello world
13 | 2. Single-stage build of dummyFoam
14 | 3. Analyzing library dependencies
15 | 4. Multi-stage build of dummyFoam
16 | 5. Summary
17 |
18 | When compiling a new high-level application or utility that will be shipped as a container, ideally, you want to start from a base image that comes as close as possible to the build-environment you need to compile your application. For example, if you’re going to create and build a custom OpenFOAM® solver, it makes perfect sense to start with the [OpenFOAM Docker image](https://develop.openfoam.com/Development/openfoam/-/wikis/precompiled/docker) as a base. You may install additional third-party libraries, copy your sources to the image, and compile. This workflow is really convenient since it allows, for example, to compile your application against a variety of OpenFOAM versions or flavors at lighting speed while keeping all dependencies nicely separated. One disadvantage, however, is the quickly increasing storage demand since every newly created image contains both the build-environment and the application. Moreover, sending the image over the network will take longer and cause significantly more traffic. Of course, there is an established way to overcome these disadvantages called **multi-stage builds**, and this article tells you how to apply it to OpenFOAM applications.
19 |
20 | The idea behind multi-stage builds is simple: first, you prepare one or more build-environments with all dependencies (typically called builder(s)), then you build your application, and finally, you extract only what is really needed from the builder and discard the rest. The simplest multi-stage build is a two-stage build as depicted in the image below. However, you could also merge applications from multiple different builders into one final image, or you could combine different builders to create a new builder. The first scenario may be relevant to merge several binaries needed to run a simulation into a single image (e. g. third-party meshing tool + custom OpenFOAM solver + third-party post-processing tool). The latter scenario may occur if OpenFOAM is combined with another custom library to build the final app. In the early days of Docker, users would define individual Dockerfiles for each step in the build process, and write wrapper scripts to execute them in order. Since the introduction of [multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/), Docker handles the execution and copy processes for the user, and the entire build can be defined in a single Dockerfile.
21 |
22 | |  |
23 | |:--:|
24 | |*Multi-stage build with two stages: in the first stage, the environment is set up and the application is compiled; in the second stage, the compiled application and its dependencies are isolated.*|
25 |
26 | ### A multi-stage build version of *hello world*
27 |
28 | Let’s start with the probably simplest app we can build in a multi-stage process as outlined before: `hello_world.cpp`. If you want to follow along:
29 |
30 | 1. `mkdir hello_world`
31 | 2. `cd hello_world`
32 | 3. `touch hello_world.cpp`
33 | 4. copy & paste the source code from the box below into `hello_world.cpp`
34 |
35 | ```cpp
36 | #include
37 | using std::cout;
38 |
39 | int main(){
40 | cout << "Hello World - multi-stage edition\n";
41 | return 0;
42 | }
43 | ```
44 |
45 | To build the app, we start with the official Ubuntu 18.04 Docker image, update the list of available software packages, and install a C++ compiler. Note that the ~120MB Docker image of Ubuntu is not comparable to the richly packaged desktop version you may use on your workstation, so you’ll probably have to install more dependencies than you’re used to. The actual compile command to build the program follows in line 5. Compiling the app concludes the first stage.
46 |
47 | In the second stage, we start with an empty Docker image (basically `FROM` scratch) and copy only the binary called hello from the first stage over to the final image. The possibility to name different stages makes it easy to write comprehensible Dockerfiles. In the example below, our base image is simply called builder. This name is then used in the second stage to run the `COPY` command. By default, the `hello` program is executed whenever we run a container.
48 |
49 | ```docker
50 | # first stage
51 | FROM ubuntu:18.04 AS builder
52 | RUN apt-get update && apt-get install -y g++
53 | COPY hello_world.cpp /
54 | RUN g++ -static -o hello hello_world.cpp
55 |
56 | # second stage
57 | FROM scratch
58 | COPY --from=builder hello /
59 | CMD ["/hello"]
60 | ```
61 |
62 | To build and run the hello world multi-stage version,
63 |
64 | 1. create a new Dockerfile `touch Dockerfile`,
65 | 2. copy & paste the content of the code box above into the Dockerfile, and
66 | 3. execute the Docker commands provided in the code box below.
67 |
68 | ```bash
69 | docker build -t hello_world:multi_stage .
70 | docker run hello_world:multi_stage
71 | # output ...
72 | Hello World - multi-stage edition
73 | ```
74 |
75 | I hope you’ll agree at this point that Docker multi-stage builds enable us to create streamlined build processes. The same overall two-step structure can be applied to build OpenFOAM apps, too. However, there are some technicalities that require a couple of intermediate steps to create a runnable and isolated binary. Therefore, we’ll first take a look at how dummyFoam is built in a single-stage process.
76 |
77 | ### Single-stage build of *dummyFoam*
78 |
79 | `dummyFoam` consists only of the basic app structure that the `foamNewApp` utility creates. The app does nothing more than setting up a root-case and creating a (run)time object. In case you want to follow along, I have set up two Github repositories to make your life easier:
80 |
81 | ```bash
82 | git clone https://github.com/AndreWeiner/of_app_isolation.git
83 | cd of_app_isolation
84 | git clone https://github.com/AndreWeiner/dummyFoam.git
85 | ```
86 |
87 | With the commands above, we have downloaded one repository into another. The commands issued later on require precisely this folder structure. The first repository contains the Dockerfiles for single and multi-stage builds. The second one comprises a version-controlled form of dummyFoam. Let’s now have a look at the single-stage build.
88 |
89 | ```docker
90 | FROM openfoamplus/of_v1912_centos73
91 | # copy app source code to base image
92 | COPY dummyFoam /opt/OpenFOAM/OpenFOAM-v1912/applications/solvers/dummyFoam
93 | # change working directory
94 | WORKDIR /opt/OpenFOAM/OpenFOAM-v1912/applications/solvers/dummyFoam
95 | # source environment variables, compile, and create execution script
96 | RUN source /opt/OpenFOAM/OpenFOAM-v1912/etc/bashrc && \
97 | wmake && \
98 | mkdir /case && \
99 | echo "source /opt/OpenFOAM/OpenFOAM-v1912/etc/bashrc &> /dev/null; dummyFoam -case /case" > /runDummyFoam.sh
100 | ```
101 |
102 | We start with version 1912 of the OpenFOAM-plus release as a base image. The image comes with all dependencies needed to build `dummyFoam`. Next, we copy the app sources to the image and make the app folder our work-directory. The `RUN` command sources the OpenFOAM environment variables, builds the app using `wmake`, and creates a new folder in the root directory. The case folder serves as a mount point to attach simulation cases.
103 |
104 | Commands to build the dummyFoam image and to create a container are provided in the code box below. We use the latest commit on the master branch of the `dummyFoam` repository (the default state after cloning the repository). One could also checkout another branch before copying the sources and building the image. To track the branch/commit used, it is good practice to tag the image with the commit hash (or at least a unique portion of it).
105 |
106 | ```bash
107 | # build the image
108 | docker build -t andreweiner/dummy_foam:$(git --git-dir dummyFoam/.git log -1 --format=%h) -f Dockerfile.single .
109 | # create a container
110 | docker container run -it andreweiner/dummy_foam_single:06ff344 /bin/bash
111 | # now we are inside the container
112 | # let's see where the dummyFoam binary file is located
113 | which dummyFoam
114 | # output ...
115 | /root/OpenFOAM/-v1912/platforms/linux64GccDPInt32Opt/bin/dummyFoam
116 | ```
117 |
118 | With the latter two commands in the code box above, we can see where in the image the `dummyFoam` binary is located. However, this time it is not as easy as copying the binary over to the second stage. A little twist I didn’t comment on earlier in the `hello_world.cpp` example is the flag `-static`. Even though the hello world program is relatively simple, it already has quite some dependencies on other libraries. An obvious example is `iostream` from the C++ standard library. But the standard library links against other C libraries which will be therefore also needed in the hello program. If one of these dependencies is missing in the second stage, the linker (a tool provided by the operating system to handle library dependencies) will complain and crash as soon as we try to execute the binary. So why did it work in the first example? The answer is that the flag `-static` tells the compiler to create a static version of the program. A static program is one that does not dynamically load any other libraries at runtime. In other words, the compiler packages all the dependencies into a single executable binary file. The reason why not every program is compiled statically is the subsequent massive redundancy of binary code. Each and every C++ program, for example, would very likely contain the entire C++ standard library.
119 |
120 | Coming back to the compilation of `dummyFoam`, unfortunately, it is not as easy as adding a flag to the `wmake` options. We would have to tinker around with the base image, and presumably create a new one. Here, we follow another path. In theory, we just have to find all the libraries dummyFoam loads at runtime and copy them over to the second stage together with the `dummyFoam` binary itself. This workflow may sound cumbersome, but, luckily, it can be automated to a large extent as you’ll see in the next section.
121 |
122 | ### Analyzing library dependencies
123 |
124 | [ldd](http://man7.org/linux/man-pages/man1/ldd.1.html) is a tool that invokes the (dynamic) linker and allows us to trace dynamic library dependencies. The output of `ldd` is formatted as `shared_library.so => /path/to/shared_library.so (address in memory)` ([learn more](https://stackoverflow.com/questions/34428037/how-to-interpret-the-output-of-the-ldd-program)). `dummyFoam` loads several OpenFOAM-specific and some system libraries, as can be seen in the code box below. Note that you have to be inside the container created after the single-stage build to invoke to command in line 1 of the code box.
125 |
126 | ```bash
127 | ldd $(which dummyFoam)
128 | # output ...
129 | linux-vdso.so.1 => (0x00007fff811f7000)
130 | libfiniteVolume.so => /opt/OpenFOAM/OpenFOAM-v1912/platforms/linux64GccDPInt32Opt/lib/libfiniteVolume.so (0x00007f1220154000)
131 | libmeshTools.so => /opt/OpenFOAM/OpenFOAM-v1912/platforms/linux64GccDPInt32Opt/lib/libmeshTools.so (0x00007f121f930000)
132 | libOpenFOAM.so => /opt/OpenFOAM/OpenFOAM-v1912/platforms/linux64GccDPInt32Opt/lib/libOpenFOAM.so (0x00007f121ecc1000)
133 | libdl.so.2 => /lib64/libdl.so.2 (0x00007f121eabd000)
134 | libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f121e7b4000)
135 | ...
136 | ```
137 |
138 | What we actually need from the `ldd`-output are the paths to all shared object libraries (`*.so` files). To extract the path from each line, we pipe the output to `cut`, split the line at every whitespace, and keep only the third element/field. The output of cut can be piped again to `xargs`, which converts the line-wise output of `cut` into a single line containing all paths (basically, an argument list that can be used by yet another program).
139 |
140 | ```bash
141 | ldd $(which dummyFoam) | cut -d" " -f3
142 | # output ...
143 | /opt/OpenFOAM/OpenFOAM-v1912/platforms/linux64GccDPInt32Opt/lib/libfiniteVolume.so
144 | /opt/OpenFOAM/OpenFOAM-v1912/platforms/linux64GccDPInt32Opt/lib/libmeshTools.so
145 | /opt/OpenFOAM/OpenFOAM-v1912/platforms/linux64GccDPInt32Opt/lib/libOpenFOAM.so
146 | /lib64/libdl.so.2
147 | /lib64/libstdc++.so.6
148 | ...
149 | ldd $(which dummyFoam) | cut -d" " -f3 | xargs
150 | # output ...
151 | /opt/OpenFOAM/OpenFOAM-v1912/platforms/linux64GccDPInt32Opt/lib/libfiniteVolume.so /opt/OpenFOAM/OpenFOAM-v1912/platforms/linux64GccDPInt32Opt/lib/libmeshTools.so /opt/OpenFOAM/OpenFOAM-v1912/platforms/linux64GccDPInt32Opt/lib/libOpenFOAM.so /lib64/libdl.so.2 /lib64/libstdc++.so.6 ...
152 | ```
153 |
154 | Did this single-line command seem too easy to work? It sometimes is because there is another stumbling block you may encounter. Many operating systems, like Ubuntu, allow having multiple versions of the same library. To manage these dependencies internally, there is usually a symbolic link pointing to the default version of the library. One example in the case of dummyFoam is the C++ standard library. If we inspect the path returned by ldd using `ls -al`, we find that `/lib64/libstdc++.so.6` is actually pointing to the specific version `libstdc++.so.6.0.19` in the same directory. The tracing of `ldd` does not follow symbolic links, so we have to keep that in mind when copying the library files. You’ll read in the next section to overcome this issue.
155 |
156 | ```bash
157 | ls -al /lib64/libstdc++.so.6
158 | # output ...
159 | lrwxrwxrwx 1 root root 19 Jun 5 2017 /lib64/libstdc++.so.6 -> libstdc++.so.6.0.19
160 | ```
161 |
162 | ### Multi-stage build of *dummyFoam*
163 |
164 | Finally, we are ready for the multi-stage build of `dummyFoam`! In the builder stage, we package the libraries required by `dummyFoam` into a tar-archive. In the `tar` command, it is essential to add the `--dereference` flag. This option tells `tar` to follow symbolic links and to archive the actual file and not the link pointing to it. In the last step of the first stage, another file not captured by the `cut` command is added to the archive, and a second archive containing OpenFOAM configuration files is created.
165 |
166 | ```docker
167 | # step 1: build application using base image with build environment
168 | FROM openfoamplus/of_v1912_centos73 AS builder
169 | COPY dummyFoam /opt/OpenFOAM/OpenFOAM-v1912/applications/solvers/dummyFoam
170 | WORKDIR /opt/OpenFOAM/OpenFOAM-v1912/applications/solvers/dummyFoam
171 | RUN source /opt/OpenFOAM/OpenFOAM-v1912/etc/bashrc && \
172 | wmake && \
173 | ldd $(which dummyFoam) | cut -d" " -f3 | xargs tar --dereference -cf libs.tar && \
174 | tar --dereference -rvf libs.tar /lib64/ld-linux-x86-64.so.2 && \
175 | tar -cf etc.tar /opt/OpenFOAM/OpenFOAM-v1912/etc
176 | ```
177 |
178 | The base image for the second stage is Alpine, a minimalistic operating system specifically designed for Docker images. Alpine has a package manager and enables us to install basic command-line tools like `bash` and `tar`. Next, we copy the `dummyFoam` binary, the required dynamic libraries, and the configuration files from the builder and extract the archives. Note that the absolute paths of all files will be the same in the second stage. The remainder of the Dockerfile configures environment variables and creates an execution script that runs `dummyFoam` in the `/case` folder (similar to the single-stage build).
179 |
180 | ```docker
181 | # step 2: isolate application and dependencies
182 | FROM alpine:latest
183 | RUN apk add --no-cache bash tar
184 | COPY --from=builder /opt/OpenFOAM/OpenFOAM-v1912/applications/solvers/dummyFoam/libs.tar \
185 | /root/OpenFOAM/-v1912/platforms/linux64GccDPInt32Opt/bin/dummyFoam \
186 | /opt/OpenFOAM/OpenFOAM-v1912/applications/solvers/dummyFoam/etc.tar \
187 | /
188 | RUN tar -xf libs.tar && \
189 | tar -xf etc.tar && \
190 | rm *.tar && \
191 | sed -i '/projectDir=\"\$HOME\/OpenFOAM\/OpenFOAM-\$WM_PROJECT_VERSION\"/c\projectDir=\"\/opt\/OpenFOAM\/OpenFOAM-\$WM_PROJECT_VERSION\"' /opt/OpenFOAM/OpenFOAM-v1912/etc/bashrc && \
192 | mkdir case && \
193 | echo "source /opt/OpenFOAM/OpenFOAM-v1912/etc/bashrc &> /dev/null; /dummyFoam -case /case" > runDummyFoam.sh
194 | ENV LD_LIBRARY_PATH=\
195 | lib:\
196 | lib64:\
197 | /opt/OpenFOAM/OpenFOAM-v1912/platforms/linux64GccDPInt32Opt/lib:\
198 | /opt/OpenFOAM/ThirdParty-v1912/platforms/linux64Gcc/openmpi-1.10.4/lib64/lib:\
199 | /opt/OpenFOAM/OpenFOAM-v1912/platforms/linux64GccDPInt32Opt/lib/openmpi-1.10.4:\
200 | /opt/OpenFOAM/ThirdParty-v1912/platforms/linux64Gcc/openmpi-1.10.4/lib64
201 | ```
202 |
203 | To perform the multi-stage build, run `docker build -t andreweiner/dummy_foam:$(git --git-dir dummyFoam/.git log -1 --format=%h)`. If the image build succeeds, you should be presented with a teeny-tiny but executable version of the custom solver. You can test the image as follows:
204 |
205 | 1. on the host, `cd` into any valid OpenFOAM test case; if you have a local installation, you may run `cd $FOAM_TUTORIALS/basic/laplacianFoam/flange/`
206 | 2. run `dummyFoam` in the test case using `docker container run -it -v"$PWD:/case" andreweiner/dummy_foam:06ff344 /bin/bash /runDummyFoam.sh > log.dummyFoam`
207 |
208 | The solver output in the log-file should look as follows:
209 |
210 | ```bash
211 | ...
212 | Create time
213 |
214 |
215 | ExecutionTime = 0 s ClockTime = 0 s
216 |
217 | End
218 | ```
219 |
220 | ### Summary
221 |
222 | To conclude this somewhat lengthy post, let’s see how much space we actually gained thanks to the multi-stage build. To get the precise image size in bytes, run `docker image inspect IMAGE_ID --format='{{.Size}}'`. When sending an image over the network, e. g. to Dockerhub, the image is typically compressed using `gzip`. So, the important numbers are the size of the image on our system and the size of the compressed archive. To save the single and multi-stage build outcomes as compressed archives, check out the code box below.
223 |
224 | ```bash
225 | ## OpenFOAM base image
226 | docker save openfoamplus/of_v1912_centos73:latest | gzip > of_base.tar.gz
227 | du -h of_base.tar.gz
228 | # output ...
229 | 653M of_base.tar.gz
230 | ## isolated dummyFoam app
231 | docker save andreweiner/dummy_foam:06ff344 | gzip > dummy_foam.tar.gz
232 | du -h dummy_foam.tar.gz
233 | # output ...
234 | 42M dummy_foam.tar.gz
235 | ```
236 |
237 | The table below displays the final numbers. The difference between the base image and the result of the single-stage build is less than 1 MB. The multi-stage build yields an image that is about **15 times** smaller than the one resulting in the single-stage build. Another interesting idea is that adding more apps to the multi-stage build would presumably lead to a marginal increase of the final image size since other apps access mostly the same shared objects libraries as dummyFoam does.
238 |
239 | | version | image size | compressed |
240 | |:--:|--:|--:|
241 | | OpenFOAM-v1912 | 2481 MB | 653 MB |
242 | | dummyFoam + OpenFOAM-v1912 | 2481 MB | 653 MB |
243 | | dummyFoam | 160 MB | 42 MB|
244 |
245 | I hope you found some useful code snippets or ideas while reading the post.
246 |
247 | Cheers, Andre
--------------------------------------------------------------------------------
/_posts/2020-12-29-running-pytorch-models-in-openfoam.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: "Running PyTorch models in OpenFOAM - basic setup and examples"
4 | date: 2020-12-29 12:00:00 +0100
5 | categories: OpenFOAM PyTorch Docker
6 | ---
7 |
8 | 1. Why PyTorch
9 | 2. Docker image with OpenFOAM and PyTorch
10 | 3. Local installation of LibTorch
11 | 4. Setting up Visual Studio Code
12 | 5. Compiling examples using wmake and CMake
13 | 6. Additional links to resources
14 | 7. Summary
15 |
16 | Incorporating data-driven workflows in computational fluid dynamics (CFD) is currently a hot topic, and it will undoubtedly gain even more traction over the months and years to come. The main idea is to use available datasets to make simulation-based workflows faster or more accurate. In the field of machine learning (ML) applied to CFD, deep learning (DL) algorithms allow us to tackle high-dimensional problems more effectively and promise significant progress in fields like turbulence modeling, flow control, or shape optimization. If you found your way to this article, chances are high that you don’t need to be convinced of the potential of ML/DL + CFD. So let’s skip the prose and get started with the nitty-gritty of this article: **how to set up PyTorch to run DL models in OpenFOAM apps**.
17 |
18 | ### Why PyTorch
19 |
20 | Why should you consider using PyTorch instead of Tensorflow/Keras? The short answer is because **PyTorch is easy and fast**. Both PyTorch and Tensorflow provide C++ and Python frontend APIs. However, at the time of writing, my arguments in favor of PyTorch when it comes to incorporating DL models in OpenFOAM are:
21 |
22 | - it is easy to set up the C++ libraries because there are pre-compiled packages ([libtorch](https://pytorch.org/cppdocs/installing.html))
23 | - it is easy to move data and models between the Python and C++ interface thanks to [TorchScript](https://pytorch.org/docs/stable/jit.html)
24 | - the C++ API is closely aligned with its Python counterpart; once you know how to do something in one frontend, you have at least an idea what to look for in the other frontend
25 |
26 | Of course, these arguments only capture my current impression, and DL frameworks are improving at lightning speed. If you had a different experience with Tensorflow or PyTorch, let me know! I would love to see workflows that make it as easy as possible for users and developers to switch between both frameworks according to their needs.
27 |
28 | ### Docker image with OpenFOAM and PyTorch
29 |
30 | If you have read some of my previous blog posts, you know that I am a fan of software containers as a means to make workflows reproducible and shareable. If you’re not much of a Docker user, you should still read this section because it also explains some details needed for local installations. So here is how to create a Docker image based on:
31 |
32 | - Ubuntu 20.04 LTS
33 | - OpenFOAM-v2006; pre-compiled Debian/Ubuntu package by ESI-OpenCFD
34 | - PyTorch 1.6; pre-compiled C++ API package (LibTorch)
35 |
36 | The Dockerfile and instructions on how to build and use an image can be found in [this repository](https://github.com/AndreWeiner/of_pytorch_docker) (I try to keep it up to date with the current versions of PyTorch and OpenFOAM). Here, I only want to focus on some of the details.
37 |
38 | ```docker
39 | # some commands to install required packages
40 | # ...
41 | # install OpenFOAM via Debian package
42 | ARG FOAM_PATH=/usr/lib/openfoam/openfoam2006
43 | RUN apt-get update && apt-get install --no-install-recommends -y \
44 | openfoam2006-default && \
45 | echo ". ${FOAM_PATH}/etc/bashrc" >> /etc/bash.bashrc && \
46 | sed -i "s/-std=c++11/-std=c++14/g" ${FOAM_PATH}/wmake/rules/General/Gcc/c++ && \
47 | sed -i "s/-Wold-style-cast/-Wno-old-style-cast/g" ${FOAM_PATH}/wmake/rules/General/Gcc/c++
48 |
49 |
50 | ## download and extract the PyTorch C++ libraries (libtorch)
51 | RUN wget -q -O libtorch.zip https://download.pytorch.org/libtorch/cpu/libtorch-cxx11-abi-shared-with-deps-1.6.0%2Bcpu.zip && \
52 | unzip libtorch.zip -d opt/ && \
53 | rm *.zip
54 |
55 | ## set libtorch enironment variable
56 | ENV TORCH_LIBRARIES /opt/libtorch
57 | ```
58 |
59 | The Dockerfile contains two modifications to the OpenFOAM compiler flags. First, the C++ standard is set from C++11 to C++14. This change is necessary because otherwise, PyTorch C++ code will not compile. It would be proper to re-compile OpenFOAM after changing the standard, however, there are only minor differences between both standards, and so far I haven’t had any trouble without recompiling the sources. Still, you can also change the standard and re-compile OpenFOAM with C++14 without any trouble (at least the core library; I didn’t test any third-party packages).
60 |
61 | The second modification switches off old-style-cast warnings being displayed when compiling PyTorch code. This change is only for convenience and helps to spot truly important warning and error messages more easily.
62 |
63 | “Installing” LibTorch is as easy as downloading and extracting a zip file. The shared object and header files are located under `/opt/libtorch` on the image. Moreover, it makes your life easier if you define an environment variable pointing to the LibTorch directory (e.g. to switch between Docker and local installation, to switch between different library versions, or to set up your code editor).
64 |
65 | ### Local installation of LibTorch
66 |
67 | The local installation of LibTorch is very similar to the Docker recipe. First, go to the [PyTorch website](https://pytorch.org/) and select the C++ API package as indicated in the picture below. **Important:** use the download link containing **-abi-shared-with-deps-** (cxx11 ABI). Then extract the archive to a location of your choice.
68 |
69 | |  |
70 | |:--:|
71 | |*Selection to download libtorch without GPU support.*|
72 |
73 | As in the Dockerfile, I recommend to set up an environment variable pointing to the LibTorch installation, e.g., add `export TORCH_LIBRARIES=/path/to/libtorch` to your `~/.bashrc` file.
74 |
75 | ### Setting up Visual Studio Code
76 |
77 | Powerful code editors can make your life much easier when learning to use a large library with little documentation. Over the last couple of months, I have started using [Visual Studio Code](https://code.visualstudio.com/) (vscode) for more and more of my projects. The main reason for me is the easy setup for a variety of different programming languages and tools (e.g., support for CMake and Docker is available). There are extensions for almost everything, and **they are easy to install and manage**. With very little effort, you can configure linting, code-completion, automatic code-formatting, or quickly jump to the definition of functions and classes. Setting up vscode for your C++/libtorch project requires only a couple of steps.
78 |
79 | #### Installing vscode
80 |
81 | On the [download page](https://code.visualstudio.com/Download) of vscode, you find plenty of options to get vscode. There are `.deb` and `.rpm` packages for the most popular Linux distributions, but also installers for Windows and MacOS. For C++ projects, you also want to install the official C/C++ extension. After staring vscode (simply type `code .` in the command line), open the extension manager by pressing *Crtl+Shift+X*, search for C/C++, and click on install.
82 |
83 | |  |
84 | |:--:|
85 | |*C/C++ extension for vscode.*|
86 |
87 | #### Configuring Intellisense
88 |
89 | If you open up one of the PyTorch C++ [examples](https://github.com/AndreWeiner/of_pytorch_docker/tree/master/test) in the repository with vscode, you will notice that Intellisense (the vscode engine doing all the magic in the background) is not able to find the torch.h header file. To fix this issue, some of the Intellisense settings have to be changed. In vscode, open the command palette by pressing *Ctrl+Shift+P*, search for C/C++, and select *C/C++: Edit Configurations (JSON)* as in the image below.
90 |
91 | |  |
92 | |:--:|
93 | |*Opening C/C++ configurations in vscode.*|
94 |
95 | Assuming that you have defined an environment variable called `TORCH_LIBRARIES` as described above, the following settings allow Intellisense to find the LibTorch header files. Tip: you may also want to add the path to the OpenFOAM sources when programming with components from both libraries. If the OpenFOAM environment variables were available in the shell in which you opened vscode, add `"${FOAM_SRC}/**"` to the `includePath` section of the Intellisense configuration file. Otherwise, it is also possible to add the full path to the OpenFOAM source folder.
96 |
97 | ```js
98 | {
99 | "configurations": [
100 | {
101 | "name": "Linux",
102 | "includePath": [
103 | "${workspaceFolder}/**",
104 | "${TORCH_LIBRARIES}/**",
105 | "${FOAM_SRC}/**"
106 | ],
107 | "defines": [],
108 | "compilerPath": "/usr/bin/g++",
109 | "cStandard": "c11",
110 | "cppStandard": "c++14",
111 | "intelliSenseMode": "gcc-x64"
112 | }
113 | ],
114 | "version": 4
115 | }
116 | ```
117 |
118 | ### Compiling examples using wmake and CMake
119 |
120 | By default, LibTorch applications are compiled using CMake, and dependencies are defined in `CMakeLists.txt` files. In contrast, OpenFOAM applications are typically compiled using `wmake`. Therefore, you are confronted with the following dilemma: you can either try to figure out how to compile OpenFOAM apps with CMake or you learn how to build LibTorch programs with `wmake`. I decided some time ago for the latter approach and haven’t changed my workflow since then. This [repository](https://github.com/AndreWeiner/of_pytorch_docker) currently contains two examples and instructions on how to run them:
121 |
122 | - `tensorCreation`: basics of PyTorch tensors and Autograd; compiled using wmake
123 | - `simpleMLP`: implementation of a simple neural network (multilayer perceptron - MLP); compiled using CMake
124 |
125 | Instead of checking all the CMake files contained in LibTorch, I found it much easier to simply look at the final compile command created by CMake and then to add PyTorch-related options to the `wmake` options file. The simpleMLP example in the [repository](https://github.com/AndreWeiner/of_pytorch_docker) mentioned above contains the implementation of a simple neural network in LibTorch and a CMake configuration file that enables [verbose output](https://stackoverflow.com/questions/2670121/using-cmake-with-gnu-make-how-can-i-see-the-exact-commands) during the compilation. The output of make should look similar to the content of the code box below.
126 |
127 | ```bash
128 | # step 1: using cmake to create a makefile
129 | cmake ..
130 | # step 2: compiling the application using make
131 | make
132 | # verbose output
133 | ...
134 | [ 50%] Building CXX object CMakeFiles/simpleMLP.dir/simpleMLP.C.o
135 | /usr/bin/c++ -DAT_PARALLEL_OPENMP=1 -isystem /opt/libtorch/include -isystem /opt/libtorch/include/torch/csrc/api/include -D_GLIBCXX_USE_CXX11_ABI=1 -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-write-strings -Wno-unknown-pragmas -Wno-missing-braces -fopenmp -std=gnu++14 -o CMakeFiles/simpleMLP.dir/simpleMLP.C.o -c /home/andre/pyTorchCmake/simpleMLP.C
136 | [100%] Linking CXX executable simpleMLP
137 | /usr/bin/cmake -E cmake_link_script CMakeFiles/simpleMLP.dir/link.txt --verbose=1
138 | /usr/bin/c++ -rdynamic CMakeFiles/simpleMLP.dir/simpleMLP.C.o -o pyTorchOnes -Wl,-rpath,/opt/libtorch/lib /opt/libtorch/lib/libtorch.so /opt/libtorch/lib/libc10.so -Wl,--no-as-needed,/opt/libtorch/lib/libtorch_cpu.so -Wl,--as-needed /opt/libtorch/lib/libc10.so -lpthread -Wl,--no-as-needed,/opt/libtorch/lib/libtorch.so -Wl,--as-needed
139 | make[2]: Leaving directory '/home/andre/simpleMLP/build'
140 | [100%] Built target simpleMLP
141 | ...
142 | ```
143 |
144 | Now you can add the paths to header and shared object files to the `wmake` options and simplify the paths using the `TORCH_LIBRARIES` environment variable. The following box shows the options file of the [tensorCreation](https://github.com/AndreWeiner/of_pytorch_docker#tensorcreation) example, compiled with `wmake`. Note that the last three lines are optional.
145 |
146 | ```bash
147 | EXE_INC = \
148 | -I$(TORCH_LIBRARIES)/include \
149 | -I$(TORCH_LIBRARIES)/include/torch/csrc/api/include
150 |
151 | EXE_LIBS = \
152 | -Wl,-rpath,$(TORCH_LIBRARIES)/lib $(TORCH_LIBRARIES)/lib/libtorch.so $(TORCH_LIBRARIES)/lib/libc10.so \
153 | -Wl,--no-as-needed,$(TORCH_LIBRARIES)/lib/libtorch_cpu.so \
154 | -Wl,--as-needed $(TORCH_LIBRARIES)/lib/libc10.so \
155 | -Wl,--no-as-needed,$(TORCH_LIBRARIES)/lib/libtorch.so
156 | ```
157 |
158 | ### Additional links to resources
159 |
160 | - PyTorch [Python API](https://pytorch.org/docs/stable/torch.html) and [C++ API](https://pytorch.org/cppdocs/) documentation
161 | - [Autograd](https://pytorch.org/tutorials/advanced/cpp_autograd.html) in the PyTorch C++ frontend
162 | - plethora of [PyTorch C++ examples](https://github.com/prabhuomkar/pytorch-cpp) by Omkar Prabhu
163 | - creating a [Docker image](https://github.com/AndreWeiner/of_pytorch_docker) with OpenFOAM and PyTorch
164 | - examples for [ML applied to CFD](https://github.com/AndreWeiner/machine-learning-applied-to-cfd) problems
165 |
166 | ### Summary
167 |
168 | Getting started in a new, huge field like ML and DL can be hard for CFD people, but I strongly believe it is worth the trouble. I hope that this article saves you some time and maybe motivates you to give ML+CFD a try in case you’re undecided. Should you have follow-up questions or suggestions for future articles related to this topic, let me know! Finally, I would like to thank **Chiara Pesci** for her early feedback on this blog post and [Tomislav Maric](https://tmaric.gitlab.io/posts/) for our ongoing discussions about OpenFOAM and PyTorch, which have significantly influenced and improved the content of this post.
169 |
170 | Cheers, Andre
--------------------------------------------------------------------------------
/about.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: About
4 | permalink: /about/
5 | ---
6 |
7 | Hi there! My name is Andre Weiner. I am a research scientist working on computational fluid dynamics (CFD) and machine learning (ML). Besides ML and CFD, I am also interested in making research reproducible by employing containerization and version control (Docker, Singularity, Git, Github). Reproducibility also implies full transparency regarding source code and workflows, which is why my work as well as the work of students I supervise is available on [Github](https://github.com/AndreWeiner). I am also an advocate for self-determined, lifelong learning.
8 |
9 | |
|
10 | |:--:|
11 | |*That's me in 2017.*|
12 |
13 | ### Profile pages
14 |
15 | If you are interested in my academic curriculum, have a look at the following profile pages:
16 |
17 | - [Google Scholar](https://scholar.google.de/citations?user=wCmTgzgAAAAJ&hl=de) (journal articles)
18 | - [Technical University of Dresden](https://tu-dresden.de/ing/maschinenwesen/ism/psm/die-professur/beschaeftigte/weiner-andre) (since Sep 2023)
19 | - [Technical University of Braunschweig](https://www.tu-braunschweig.de/ism/forschung/modellierung-und-regelung-von-stroemungen/mitarbeiter/weiner) (May 2020 - Jul 2023)
20 | - [Technical University of Darmstadt](https://www.mma.tu-darmstadt.de/index/mitarbeiter_3/mitarbeiter_details_mma_45120.en.jsp) (Oct 2014 - Apr 2020)
21 |
22 | ### Scientific software packages
23 |
24 | - **flowTorch** - a Python library for analysis and reduced-order modeling of fluid flows, [Github](https://github.com/FlowModelingControl/flowtorch)
25 | - **drlFoam** - Deep Reinforcement Learning with OpenFOAM, [Github](https://github.com/OFDataCommittee/drlfoam)
26 |
27 | ### University courses
28 |
29 | - [Machine learning in computational fluid dynamics](https://github.com/AndreWeiner/ml-cfd-lecture), TU Braunschweig and TU Dresden, since winter term 2021/2022; I designed this course from scratch; lecture notes, slides, exercises, and datasets are freely available
30 | - [Modeling and simulation of turbulent flows](https://github.com/AndreWeiner/turbulence_modelling_lecture), TU Braunschweig, summer term 2023; I designed this course mostly from scratch (syllabus, lecture slides, exercises)
31 |
32 | ### Presentation and training slides
33 |
34 | - [Model-based DRL for accelerated learning from flow simulations](https://andreweiner.github.io/slides/mbdrl-2025-2.html), seminar talk ILR TU Berlin, **Feb 2025**, Berlin
35 | - [Data-driven modeling, optimization, and control in CFD](https://andreweiner.github.io/slides/ml-cfd-2025.html), invited talk automotive industry, **Feb 2025**
36 | - [A brief introduction to Bayesian optimization](https://andreweiner.github.io/reveal.js/bayesopt_intro.html#/), PSM seminar, **Oct 2024**, Dresden
37 | - Best practice guidelines for the modal analysis of numerical and experimental data, DLRK 2024, **Sep 2024**, Hamburg
38 | - [An optimized dynamic mode decomposition for flow analysis and forecasting](https://andreweiner.github.io/reveal.js/ofw2024_optdmd.html#/), 19th OpenFOAM workshop, **June 2024**, Beijing
39 | - Machine learning in computational fluid dynamics - an overview, invited talk, automotive industry, **July 2024**
40 | - Combining machine learning with computational fluid dynamics using OpenFOAM and SmartSim, 19th OpenFOAM workshop, **June 2024**, Beijing
41 | - Analyse turbulenter Strömungen - wie man Ordnung im Chaos findet, Lange Nacht der Wissenschaft, **June 2024**, Dresden
42 | - Modal analysis of fluid flows - best practices, ISM seminar - invited talk, **May 2024**, Braunschweig
43 | - [Model-based reinforcement learning for active flow control](https://andreweiner.github.io/reveal.js/gamm_2024.html#/), 94th GAMM, **Mar 2024**, Magdeburg
44 | - Extracting coherent structures and reduced-order models from flows, Bosch - invited talk, **Jan 2024**, Stuttgart
45 | - DMD analysis of the XRF-1 wing undergoing transonic shock buffet, DLRK 2023, **Sep 2023**, Stuttgart
46 | - [Advances in the application of DRL to flow control](https://andreweiner.github.io/reveal.js/ofw_talk_2023.html#/), 18th OpenFOAM workshop, **Jul 2023**, Genoa
47 | - [Setting up a new flow control problem in drlFoam](https://andreweiner.github.io/reveal.js/ofw_training_2023.html#/), 18th OpenFOAM workshop, **Jul 2023**, Genoa
48 | - [Model-based deep reinforcement learning for flow control](https://andreweiner.github.io/reveal.js/cfc2023.html#/), 22nd Computer Fluids Conference, **Apr 2023**, Cannes
49 | - [Data-driven modeling and validation of reactive mass transfer at rising bubbles](https://andreweiner.github.io/reveal.js/ofmf_short_course_mar2023.html#/), OpenFoam multiphase short course - invited talk, **Mar 2023**, Darmstadt
50 | - [ProDiGI - Machine learning in computational fluid dynamics lecture](https://andreweiner.github.io/reveal.js/prodigi_final.html#/), [ProDiGI](https://www.tu-braunschweig.de/en/teaching-and-media-education/our-services/international-teaching/prodigi) event, **Feb 2023**, Braunschweig
51 | - Analysis of shock buffet PSP measurements by means of dynamic mode decomposition, Airbus XRF-1 workshop, **Dec 2022**, virtual
52 | - [Activities of the data-driven modeling special interest group](https://andreweiner.github.io/reveal.js/release_webinar_2206.html#/), OpenFOAM-v2206 release webinar, **Jul 2022**, virtual
53 | - [Modal analysis of transonic shock buffets on a NACA-0012 airfoil](https://andreweiner.github.io/reveal.js/ofw2022_naca_dmd.html#/), 17th OpenFOAM workshop, **Jul 2022**, Cambridge
54 | - [Analyzing coherent structures by means of dynamic mode decomposition](https://andreweiner.github.io/reveal.js/ofw2022_dmd_training.html#/), 17th OpenFOAM workshop, **Jul 2022**, Cambridge
55 | - [Active flow control via deep reinforcement learning implemented in OpenFOAM](https://andreweiner.github.io/reveal.js/combustion_seminar_may2022.html#/), OpenFOAM combustion seminar - invited talk, **May 2022**, Singapore, virtual
56 | - [Simulation and modal analysis of transonic shock buffets on a NACA-0012 airfoil](https://andreweiner.github.io/reveal.js/euromech2022_buffet.html#/), Euromech Colloquium 612, **Mar 2022**, Aachen, virtual
57 | - [Machine learning in computational fluid dynamics - an overview](https://andreweiner.github.io/reveal.js/mlcfd_overview_feb2022.html#/), keynote lecture chemical industry, **Feb 2022**
58 | - [Simulation and modal analysis of transonic shock buffets on a NACA-0012 airfoil](https://andreweiner.github.io/reveal.js/aiaa2022_buffet.html#/), AIAA SciTech Forum, **Jan 2022**, San Diego, virtual
59 | - [Active control of the flow past a cylinder using deep reinforcement learning](https://andreweiner.github.io/reveal.js/of_conf_2021.html#/), OpenFOAM conference, **Oct 2021**, virtual
60 | - [flowTorch - A platform for analysis and reduced-order modeling of high-speed stall flow phenomena](https://andreweiner.github.io/reveal.js/DLRK_2021.html#/), DLRK 2021, **Aug 2021**, Bremen, virtual
61 | - [Machine learning-aided CFD with OpenFOAM and PyTorch](https://andreweiner.github.io/reveal.js/ofw_training_2021.html#/), training at 16th OpenFOAM Workshop, **Jun 2021**, Dublin, virtual
62 | - [Machine learning-aided CFD with OpenFOAM and PyTorch](https://andreweiner.github.io/reveal.js/ssd_seminar_2021.html#/), SSD Seminar - invited talk, **Jun 2021**, RWTH Aachen, virtual
63 | - [Sparse Spatial Samling - S³](https://wp-ml-cfd.s3.eu-central-1.amazonaws.com/wp-content/uploads/2020/12/29173309/aiaa_2021_fernex_weiner_noack_semaan.pdf), AIAA SciTech Forum, **Jan 2021**, Nashville, virtual
64 | - [Creating data-driven workflows with OpenFOAM and PyTorch](https://andreweiner.github.io/reveal.js/of_conf_2020.html#/), 8th ESI OpenFOAM conference, **Oct 2020**, Berlin, virtual
65 | - [An introduction to supervised learning by example: path regime classification](https://andreweiner.github.io/reveal.js/path_regime_classification_2020.html#/), internal training, **Aug 2020**, Braunschweig, virtual
66 | - [A hybrid approach to compute convection-dominated mass transfer at rising bubbles](https://andreweiner.github.io/reveal.js/gofun2020.html#/), 4th GOFUN, **Apr 2020**, Braunschweig, virtual
67 | - [Modeling and simulation of convection-dominated species transfer at rising bubbles](https://andreweiner.github.io/reveal.js/phd_defence.html#/), Ph.D. defense, **Jan 2020**, Darmstadt
68 | - [A brief introduction to machine learning and its potential application to CFD](https://andreweiner.github.io/reveal.js/ofw2019_slides.html#/), 14th OpenFOAM workshop, **Jul 2019**, Duisburg
69 | - [Data-driven subgrid-scale modeling for convection-dominated concentration boundary layers](https://andreweiner.github.io/reveal.js/ofw2019_sgs_modeling.html#/), 14th OpenFOAM workshop, **Jul 2019**, Duisburg
70 |
71 | ### Supervised student projects
72 |
73 | - [Learning of optimized multigrid solver settings for CFD applications](https://doi.org/10.5281/zenodo.10361535), Master thesis, **Janis Geise**, 2023, [Github](https://github.com/JanisGeise/learning_of_optimized_multigrid_solver_settings_for_CFD_applications)
74 | - [A comparison of reduced-order models for wing buffet predictions](https://zenodo.org/records/10255520), course project, **Anton Schreiber**, 2023, [Github](https://github.com/AntonSchreiber/ROM-buffet-forecasting)
75 | - Prediction of ice formation on heat exchanger surfaces and defrost control using machine learning, master project, together with [Coldsense](https://www.cold-sense.com/en/), **Tom Krogmann**, 2023
76 | - [Robust model-based deep reinforcement learning for flow control](https://zenodo.org/record/7642927#.ZEqIt41Bxkg), course project, **Janis Geise**, 2023, [Github](https://github.com/JanisGeise/robust_MB_DRL_for_flow_control)
77 | - [Optimal sensor placement for active flow control with deep reinforcement learning](https://zenodo.org/record/7636959#.Y-qTLcbMJkg), course project, **Tom Krogmann**, 2022, [Github](https://github.com/TomKrogmann/Optimal_Sensor_Placement_for_Active_Flow_Control_in_Deep_Reinforcement_Learning)
78 | - [Design and implementation of a data-driven wall function for the velocity in RANS simulations](https://zenodo.org/record/6590747), master project, **Jihoo Kang**, 2022, [Github](https://github.com/JihooKang-KOR/Data_driven_wall_modeling)
79 | - POD-based parametric reduced-order models for time-dependent fluid flows, course project, **Jan Schlüter**, 2022
80 | - [Model-based reinforcement learning for accelerated learning from CFD simulations](https://doi.org/10.5281/zenodo.6375574), course project, **Jan Erik Schulze**, 2022, [Github](https://github.com/ErikSchulze1796/Active_flow_control_past_cylinder_using_DRL)
81 | - Reduced-order modeling based on cluster-based network modeling applied to the latent variables of an autoencoder, course project, **Niels Formella**, 2021, [Github](https://github.com/nformella/Cluster-based-network-modeling-using-auto-encoders)
82 | - [Active control of the flow past a cylinder under Reynolds number variation using deep reinforcement learning](https://zenodo.org/record/5634050#.YaumMrso9hE), Bachelor thesis, **Fabian Gabriel**, 2021, [Github](https://github.com/FabianGabriel/Active_flow_control_past_cylinder_using_DRL)
83 | - Numerical investigation of 2D transonic shock-buffet around a NACA 0012-34 airfoil using OpenFOAM and flowTorch, course project, **Tushar Anil Gholap**, 2021, [Github](https://github.com/Tushargh29/transonic_shock_buffet)
84 | - [Active flow control in simulations of fluid flows based on deep reinforcement learning](https://zenodo.org/record/4897961#.YL58_TqxVhE), course project, **Darshan Thummar**, 2021, [Github](https://github.com/darshan315/flow_past_cylinder_by_DRL)
85 | - [Simulation of Fluid Flows based on the Data-driven Evolution of Vortex Particles](https://publikationsserver.tu-braunschweig.de/receive/dbbs_mods_00069386), Master thesis, **Vemburaj Chockalingam Yadav**, 2021, [Github](https://github.com/VemburajYadav/DeepLearningLagrangainVortexDynamics)
86 | - [Datenbasierte Subgridskalen-Modellierung reaktiver Konzentrationsgrenzschichten an freiaufsteigenden Einzelblasen](https://tuprints.ulb.tu-darmstadt.de/11667/), Master thesis, **Alexander Kiefer**, 2020
87 | - [A comparative study of different mesh types for transport processes near gas bubbles regarding accuracy, stability, and run time](https://tuprints.ulb.tu-darmstadt.de/7321/), Bachelor thesis, **Jan-Alexander Kleikemper**, 2018
88 | - [Numerical simulation of single rising bubbles influenced by soluble surfactant in the spherical and ellipsoidal regime](https://tuprints.ulb.tu-darmstadt.de/8296/), Master thesis, **Matthias Steinhausen**, 2018
89 | - [Numerical simulation of reactive species transfer at a spherical gas bubble](https://tuprints.ulb.tu-darmstadt.de/6940/), Bachelor thesis, **Tim Jeremy Patrick Karpowski**, 2017
90 |
--------------------------------------------------------------------------------
/assets/img/andre_weiner_reduced-edited.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreWeiner/ml-cfd/71d03d25835cd979e8f07bc35e4a11c1859a301e/assets/img/andre_weiner_reduced-edited.jpg
--------------------------------------------------------------------------------
/assets/img/boxes_post_crop-1024x915.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreWeiner/ml-cfd/71d03d25835cd979e8f07bc35e4a11c1859a301e/assets/img/boxes_post_crop-1024x915.png
--------------------------------------------------------------------------------
/assets/img/cavity_crop-1024x698.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreWeiner/ml-cfd/71d03d25835cd979e8f07bc35e4a11c1859a301e/assets/img/cavity_crop-1024x698.png
--------------------------------------------------------------------------------
/assets/img/cpp_intellisense.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreWeiner/ml-cfd/71d03d25835cd979e8f07bc35e4a11c1859a301e/assets/img/cpp_intellisense.png
--------------------------------------------------------------------------------
/assets/img/cylinder_post-1024x576.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreWeiner/ml-cfd/71d03d25835cd979e8f07bc35e4a11c1859a301e/assets/img/cylinder_post-1024x576.png
--------------------------------------------------------------------------------
/assets/img/multi_stage_docker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreWeiner/ml-cfd/71d03d25835cd979e8f07bc35e4a11c1859a301e/assets/img/multi_stage_docker.png
--------------------------------------------------------------------------------
/assets/img/pytorch_download_selection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreWeiner/ml-cfd/71d03d25835cd979e8f07bc35e4a11c1859a301e/assets/img/pytorch_download_selection.png
--------------------------------------------------------------------------------
/assets/img/vscode_edit_setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreWeiner/ml-cfd/71d03d25835cd979e8f07bc35e4a11c1859a301e/assets/img/vscode_edit_setting.png
--------------------------------------------------------------------------------
/assets/main.scss:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 |
4 | @import "minima";
5 |
6 | .page-content { padding: 30px 0; flex: 1; text-align: justify;}
--------------------------------------------------------------------------------
/index.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | layout: home
3 | ---
4 |
--------------------------------------------------------------------------------