Sandbox flow configuration: A rapid prototyping tool inside XCompact3d

Flow Visualization with Passive Scalar Field

Felipe N. Schuch, LaSET, School of Technology, PUCRS.

Motivation

  • How can we speed up our workflow?

    alt text

  • Can we improve the learning curve for beginners in our code?

Identifying the main challenges

  • Using parallel computation in a distributed-memory system and Message Passing Interface;

Illustration of the 2D domain decomposition from 2DECOMP&FFT.

  • Coding, compiling, testing, debugging and handling I/O in Fortran.

Methodology

Sandbox Flow Configuration (BC-Sandbox.f90)

alt text

  • The initial set-up is imported from external files;
  • The choice of the external tool is up to the user:
  • It adds no extra dependency to the workflow.

Variables handled by Sandbox

  • Initial condition for velocity and scalar field(s);
  • Inflow profiles for velocity and scalar field(s) (if nclx1=nclxS1=2);
  • Top and bottom boundary values for scalar field(s) (if nclyS1=2 or nclySn=2);
  • Customized operator for the imposition of constant flow rate (if nclx1=nclxn=0);
  • $\epsilon$ array, describing the solid geometry for IBM (if iibm $\ne$ 0).

See README for more details.

An example using Python and Numpy

import numpy as np

ux = np.zeros(shape=(nx, ny, nz), dtype=np.float64)
uy = np.zeros_like(ux)
uz = np.zeros_like(ux)
phi = np.zeros(shape=(nx, ny, nz, numscalar), dtype=np.float64)

# Sequence of operations to set the initial condition

ux.T.tofile('./data/ux.bin')
uy.T.tofile('./data/uy.bin')
uz.T.tofile('./data/uz.bin')
for n in range(numscalar):
    phi[:,:,:,n].T.tofile('./data/phi{}.bin'.format(n+1))

Note: The initial set-up can be provided from any other language, as long as the files are written as raw binaries (compatible with 2DECOMP&FFT) and the filenames are correct.

Cases Covered by Sandbox

CaseICBCFRCIBMLMN
Channel-Flow✔️✔️
Cylinder✔️✔️✔️
Lock-exchange✔️✔️⚠️
Periodic Hill✔️✔️✔️
Taylor–Green vortex✔️
TBL✔️⚠️⚠️

Note: Initial Condition (IC); Boundary Conditions (BC); Flow rate Control (FRC); Immersed Boundary Method (IBM); Low Mach Number (LMN).

Case Study

Periodic Heat Exchanger

Flow Visualization with Passive Scalar Field
  • Periodic boundary conditions in x and z;
  • A cylinder at the center with low temperature;
  • No-slip conditions for velocity at top and bottom, besides, high temperature at the walls.

Initialization

>>> import xcompact3d_toolbox as x3d
>>> import xcompact3d_toolbox.sandbox
>>> prm = x3d.Parameters(loadfile='input.i3d')
>>> dataset = x3d.sandbox.init_dataset(prm)
>>> dataset
<xarray.Dataset>
Dimensions:  (n: 1, x: 128, y: 129, z: 8)
Coordinates:
  * x        (x) float64 0.0 0.04688 0.09375 0.1406 ... 5.812 5.859 5.906 5.953
  * y        (y) float64 0.0 0.04688 0.09375 0.1406 ... 5.859 5.906 5.953 6.0
  * z        (z) float64 0.0 0.04688 0.09375 0.1406 0.1875 0.2344 0.2812 0.3281
  * n        (n) int32 0
Data variables:
    byphi1   (n, x, z) float64 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0
    byphin   (n, x, z) float64 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0
    ux       (x, y, z) float64 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0
    uy       (x, y, z) float64 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0
    uz       (x, y, z) float64 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0
    phi      (n, x, y, z) float64 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0
    vol_frc  (x, y, z) float64 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0

Boundary Conditions

High temperature at the bottom and top walls:

$$ \Theta(x,y=0,z,t) = 1 $$

$$ \Theta(x,y=L_y,z,t) = 1 $$

>>> dataset["byphi1"] += 1.0
>>> dataset["byphin"] += 1.0

Initial Condition

>>> dataset["ux"] += velocity_profile + random_noise
>>> dataset["uy"] += random_noise
>>> dataset["uz"] += random_noise
>>> dataset["phi"] += 1.0

Note: Part of the code was not presented, for simplicity.

Geometry

>>> epsi = x3d.sandbox.init_epsi(prm)
>>> for array in epsi.values():
...     array = array.geo.cylinder(x=prm.xlx / 2.0, y=prm.yly / 2.0)
...
>>> epsi["epsi"].isel(z=0).plot()

Flow rate Control

>>> dataset["vol_frc"] += prm.dy / prm.yly / prm.nx / prm.nz
>>> dataset["vol_frc"][dict(y=0)] *= 0.5
>>> dataset["vol_frc"][dict(y=-1)] *= 0.5
>>> dataset["vol_frc"] = dataset.vol_frc.where(epsi == False, 0.0)
>>> dataset.vol_frc.isel(z=0).plot()

Note: The code will compute the stream-wise flow rate as int = sum(vol_frc * ux), and correct the stream-wise velocity as ux = ux / int.

  • Now we save the arrays to the disk:
    >>> dataset.x3d.write(prm)
    >>> x3d.gene_epsi_3D(epsi, prm)
    
  • And run the simulation:
    mpirun -n [number of cores] ./xcompact3d |tee log.out
    
  • There is no need to recompile the code every time;
  • We can code, test, plot and debug the initial set-up interactively in a Jupyter Notebook (or any other computational tool).

Periodic Heat Exchanger

Flow Visualization with Passive Scalar Field

View the code online.

Flow Visualization with Passive Scalar Field

View the code online.

Flow Visualization with Passive Scalar Field

View the code online.

Bonus

User Interface with IPywidgets (try it online)

Flow Visualization with Passive Scalar Field

Conclusion

The outcome of this work benefits users from different levels:

  • For students in CFD, it provides direct hands-on experience and a safe place for practising and learning;
  • For advanced users and code developers, it works as a rapid prototyping tool;
  • Furthermore, it is a useful advance in terms of research reproducibility.

Note: module sandbox is still in pre-release (fschuch/Xcompact3d).

Questions?

Felipe N. Schuch, LaSET, School of Technology, PUCRS.
🏠 fschuch.comfelipe.schuch@edu.pucrs.br