Create an initial model setup for Chmy and run it in parallel
Aim
In this tutorial, your will learn how to use Chmy to perform a 2D diffusion simulation on one or multiple CPU's or GPU's. Chmy
is a package that allows you to specify grids and fields and create finite difference simulations, by applying stencil-based kernels in an efficient manner.
1. Load Chmy and required packages
using Chmy, Chmy.Architectures, Chmy.Grids, Chmy.Fields, Chmy.BoundaryConditions, Chmy.GridOperators, Chmy.KernelLaunch
using KernelAbstractions
using Printf
using CairoMakie
using GeophysicalModelGenerator
In case you want to use GPU's, you need to sort out whether you have AMD or NVIDIA GPU's and load the package accordingly: using AMDGPU AMDGPU.allowscalar(false) using CUDA CUDA.allowscalar(false)
To run this in parallel you need to load this:
using Chmy.Distributed
using MPI
MPI.Init()
2. Define computational routines
You need to specify compute kernel for the gradients:
@kernel inbounds = true function compute_q!(q, C, χ, g::StructuredGrid, O)
I = @index(Global, NTuple)
I = I + O
q.x[I...] = -χ * ∂x(C, g, I...)
q.y[I...] = -χ * ∂y(C, g, I...)
end
You need to specify a compute kernel to update the concentration
@kernel inbounds = true function update_C!(C, q, Δt, g::StructuredGrid, O)
I = @index(Global, NTuple)
I = I + O
C[I...] -= Δt * divg(q, g, I...)
end
And the main function is:
@views function main(backend=CPU(); nxy_l=(126, 126))
arch = Arch(backend, MPI.COMM_WORLD, (0, 0))
topo = topology(arch)
me = global_rank(topo)
# geometry
dims_l = nxy_l
dims_g = dims_l .* dims(topo)
grid = UniformGrid(arch; origin=(-2, -2), extent=(4, 4), dims=dims_g)
launch = Launcher(arch, grid, outer_width=(16, 8))
##@info "mpi" me grid
nx, ny = dims_g
# physics
χ = 1.0
# numerics
Δt = minimum(spacing(grid))^2 / χ / ndims(grid) / 2.1
# allocate fields
C = Field(backend, grid, Center())
P = Field(backend, grid, Center(), Int32) # phases
q = VectorField(backend, grid)
C_v = (me==0) ? KernelAbstractions.zeros(CPU(), Float64, size(interior(C)) .* dims(topo)) : nothing
# Use the `GeophysicalModelGenerator` to set the initial conditions. Note that
# you have to call this for a `Phases` and a `Temp` grid, which we call `C` here.
add_box!(P,C,grid, xlim=(-1.0,1.0), zlim=(-1.0,1.0), phase=ConstantPhase(4), T=ConstantTemp(400))
# set BC's and updates the halo:
bc!(arch, grid, C => Neumann(); exchange=C)
# visualisation
fig = Figure(; size=(400, 320))
ax = Axis(fig[1, 1]; aspect=DataAspect(), xlabel="x", ylabel="y", title="it = 0")
plt = heatmap!(ax, centers(grid)..., interior(C) |> Array; colormap=:turbo)
Colorbar(fig[1, 2], plt)
# action
nt = 100
for it in 1:nt
(me==0) && @printf("it = %d/%d \n", it, nt)
launch(arch, grid, compute_q! => (q, C, χ, grid))
launch(arch, grid, update_C! => (C, q, Δt, grid); bc=batch(grid, C => Neumann(); exchange=C))
end
KernelAbstractions.synchronize(backend)
gather!(arch, C_v, C)
if me == 0
fig = Figure(; size=(400, 320))
ax = Axis(fig[1, 1]; aspect=DataAspect(), xlabel="x", ylabel="y", title="it = 0")
plt = heatmap!(ax, C_v; colormap=:turbo) # how to get the global grid for axes?
Colorbar(fig[1, 2], plt)
save("out_gather_$nx.png", fig)
end
return
end
In the code above, the part that calls GMG
is:
add_box!(P,C,grid, xlim=(-1.0,1.0), zlim=(-1.0,1.0), phase=ConstantPhase(4), T=ConstantTemp(400))
which works just like any of the other GMG function, except that you pass Chmy Scalar Fields and a Chmy grid object. Note that this also works in MPI-parallel.
3. Run the simulation on one CPU machine or GPU card:
Running the code on the CPU is done with this:
n = 128
main(; nxy_l=(n, n) .- 2)
If you instead want to run this on AMD or NVIDIA GPU's do this:
# main(ROCBackend(); nxy_l=(n, n) .- 2)
# main(CUDABackend(); nxy_l=(n, n) .- 2)
And we need to finalize the simulation with
MPI.Finalize()
4. Run the simulation on an MPI-parallel machine
If you want to run this on multiple cores, you will need to setup the MPI.jl package, such that mpiexecjl
is created on the command line.
You can than run it with:
mpiexecjl -n 4 --project=. julia Tutorial_Chmy_MPI.jl
The full file can be downloaded here
This page was generated using Literate.jl.