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

How can we speed up our workflow?

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

- 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.

Sandbox Flow Configuration (BC-Sandbox.f90)

- The initial set-up is imported from external files;
- The choice of the external tool is up to the user:
- Fortran, Matlab, Octave, R, Julia;
- Python with just Numpy or more specific tools (Py4Incompact3D or Xcompact3d-toolbox);

- It adds no extra dependency to the workflow.

`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.

```
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.

`Sandbox`

Case | IC | BC | FRC | IBM | LMN |
---|---|---|---|---|---|

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**).

- 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.

```
>>> 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
```

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
```

```
>>> 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.

```
>>> 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()
```

```
>>> 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

User Interface with IPywidgets (try it online)

**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).

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

🏠 fschuch.com ✉ felipe.schuch@edu.pucrs.br