aboutsummaryrefslogtreecommitdiff
path: root/template
diff options
context:
space:
mode:
authorAdrian Kummerlaender2019-07-23 23:20:24 +0200
committerAdrian Kummerlaender2019-07-23 23:20:24 +0200
commit6e6624e5f90565e6b022f26fca1f32c5b28abed9 (patch)
tree708e186d9bcaf7dc87901f6d8fe0b5aeda759079 /template
parentb71608dd58d8ce38bc9f56615d7c2da1606975d1 (diff)
downloadsymlbm_playground-6e6624e5f90565e6b022f26fca1f32c5b28abed9.tar
symlbm_playground-6e6624e5f90565e6b022f26fca1f32c5b28abed9.tar.gz
symlbm_playground-6e6624e5f90565e6b022f26fca1f32c5b28abed9.tar.bz2
symlbm_playground-6e6624e5f90565e6b022f26fca1f32c5b28abed9.tar.lz
symlbm_playground-6e6624e5f90565e6b022f26fca1f32c5b28abed9.tar.xz
symlbm_playground-6e6624e5f90565e6b022f26fca1f32c5b28abed9.tar.zst
symlbm_playground-6e6624e5f90565e6b022f26fca1f32c5b28abed9.zip
Generate basic example in plain C++
An attempt to produce a minimal LBM implementation to benchmark various memory and vectorization schemes on the CPU.
Diffstat (limited to 'template')
-rw-r--r--template/standalone.mako109
1 files changed, 109 insertions, 0 deletions
diff --git a/template/standalone.mako b/template/standalone.mako
new file mode 100644
index 0000000..6750de9
--- /dev/null
+++ b/template/standalone.mako
@@ -0,0 +1,109 @@
+#include <array>
+#include <cstdint>
+#include <memory>
+
+<%
+def pop_offset(i):
+ return i * geometry.volume
+%>
+
+void equilibrilize(${float_type}* f_next,
+ ${float_type}* f_prev,
+ const std::size_t gid)
+{
+ ${float_type}* preshifted_f_next = f_next + gid;
+ ${float_type}* preshifted_f_prev = f_prev + gid;
+
+% for i, w_i in enumerate(descriptor.w):
+ preshifted_f_next[${pop_offset(i)}] = ${w_i}.f;
+ preshifted_f_prev[${pop_offset(i)}] = ${w_i}.f;
+% endfor
+}
+
+<%
+def neighbor_offset(c_i):
+ return {
+ 2: lambda: c_i[1]*geometry.size_x + c_i[0],
+ 3: lambda: c_i[2]*geometry.size_x*geometry.size_y + c_i[1]*geometry.size_x + c_i[0]
+ }.get(descriptor.d)()
+
+%>
+
+void collide_and_stream( ${float_type}* f_next,
+ const ${float_type}* f_prev,
+ const int* material,
+ const std::size_t gid)
+{
+ const int m = material[gid];
+
+ if ( m == 0 ) {
+ return;
+ }
+
+ ${float_type}* preshifted_f_next = f_next + gid;
+ const ${float_type}* preshifted_f_prev = f_prev + gid;
+
+% for i, c_i in enumerate(descriptor.c):
+ const ${float_type} f_curr_${i} = preshifted_f_prev[${pop_offset(i) + neighbor_offset(-c_i)}];
+% endfor
+
+% for i, expr in enumerate(moments_subexpr):
+ const ${float_type} ${expr[0]} = ${ccode(expr[1])};
+% endfor
+
+% for i, expr in enumerate(moments_assignment):
+ ${float_type} ${ccode(expr)}
+% endfor
+
+% for i, expr in enumerate(collide_subexpr):
+ const ${float_type} ${expr[0]} = ${ccode(expr[1])};
+% endfor
+
+% for i, expr in enumerate(collide_assignment):
+ const ${float_type} ${ccode(expr)}
+% endfor
+
+% for i in range(0,descriptor.q):
+ preshifted_f_next[${pop_offset(i)}] = f_next_${i};
+% endfor
+}
+
+int main()
+{
+ auto f_a = std::make_unique<${float_type}[]>(${geometry.volume*descriptor.q});
+ auto f_b = std::make_unique<${float_type}[]>(${geometry.volume*descriptor.q});
+ auto material = std::make_unique<int[]>(${geometry.volume});
+
+ ${float_type}* f_prev = f_a.get();
+ ${float_type}* f_next = f_b.get();
+
+ for (int iX = 0; iX < ${geometry.size_x}; ++iX) {
+ for (int iY = 0; iY < ${geometry.size_x}; ++iY) {
+ if (iX == 0 || iY == 0 || iX == ${geometry.size_x-1} || iY == ${geometry.size_y-1}) {
+ material[iY*${geometry.size_x} + iX] = 0;
+ } else {
+ material[iY*${geometry.size_x} + iX] = 1;
+ }
+ }
+ }
+
+ for (std::size_t iCell = 0; iCell < ${geometry.volume}; ++iCell) {
+ equilibrilize(f_prev, f_next, iCell);
+ }
+
+ for (std::size_t iStep = 0; iStep < ${steps}; ++iStep) {
+ if (iStep % 2 == 0) {
+ f_next = f_a.get();
+ f_prev = f_b.get();
+ } else {
+ f_next = f_b.get();
+ f_prev = f_a.get();
+ }
+
+ for (std::size_t iCell = 0; iCell < ${geometry.volume}; ++iCell) {
+ collide_and_stream(f_next, f_prev, material.get(), iCell);
+ }
+ }
+
+ return 0;
+}