Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Distributed module #41

Merged
merged 132 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from 106 commits
Commits
Show all changes
132 commits
Select commit Hold shift + click to select a range
5eaf613
Remove MPIPreferences
utkinis Oct 5, 2023
9e18317
Add pipelines
utkinis Oct 5, 2023
0d17d8d
Fix bug
utkinis Oct 5, 2023
8fb6c0f
Fix test
utkinis Oct 5, 2023
96c5819
Simplify pipelines
utkinis Oct 6, 2023
fed5458
Add `.JuliaFormatter.toml`
utkinis Oct 13, 2023
2c7df43
Add device selection by id
utkinis Oct 13, 2023
ba35fd9
Rename files
utkinis Oct 13, 2023
c8b4992
Remove leftover file
utkinis Oct 13, 2023
39d6128
Add distributed boundary conditions
utkinis Oct 13, 2023
a02f9ce
Move stuff to Utils
utkinis Oct 13, 2023
1732f7e
Add boundary hiding
utkinis Oct 13, 2023
5e4199b
Add field boundary conditions
utkinis Oct 13, 2023
04cfe22
Refactor pipelines
utkinis Oct 13, 2023
34919ed
Format tests
utkinis Oct 13, 2023
86ed354
Add tests for utils
utkinis Oct 13, 2023
8382ce3
Fix formatting
utkinis Oct 13, 2023
2a0f9d1
Fix tests
utkinis Oct 13, 2023
379d9b6
Rename files
utkinis Oct 13, 2023
82b17c6
Fix tests
utkinis Oct 13, 2023
684e406
Refactor boundary hiding
utkinis Oct 16, 2023
7090c4f
Fix tests
utkinis Oct 16, 2023
b923d74
Fix synchronize
utkinis Oct 16, 2023
c82e676
Remove commented code and direct field accesses
utkinis Oct 16, 2023
bc14df7
Re-order using statements
utkinis Oct 16, 2023
bac648d
Remove unused import
utkinis Oct 16, 2023
bdff8b9
Add type info
utkinis Oct 16, 2023
413e651
Add supporn for variable locations for Distributed
utkinis Oct 16, 2023
3b73154
Fix last name
utkinis Oct 16, 2023
daf36d1
Add some docs
utkinis Oct 16, 2023
a482e33
Add comment
utkinis Oct 16, 2023
ee28515
Add empty bc handling
utkinis Oct 16, 2023
bbf60c7
Remove extra lines
utkinis Oct 16, 2023
bcb1bb6
Remove empty lines
utkinis Oct 16, 2023
23b9ed3
Remove commented code
utkinis Oct 16, 2023
2c59a56
Re-arrange the inclusion order
utkinis Oct 16, 2023
237ce07
Update fields
utkinis Oct 17, 2023
fba369b
Update boudary condition
utkinis Oct 18, 2023
fad55da
Update diffusion benchmarks
utkinis Oct 18, 2023
8f888ae
Update benchmark
utkinis Oct 18, 2023
bb2a5d1
Change formatting
utkinis Oct 18, 2023
97f5c8f
Fix kwargs passing
luraess Oct 23, 2023
38310e8
WIP diffusion
utkinis Oct 23, 2023
f1528fc
Update failing benchmark
utkinis Oct 23, 2023
6d76cae
Fix gather for 2D
utkinis Oct 27, 2023
56a9947
Update gather
utkinis Nov 1, 2023
3eb4cad
Fix bug in boundary condition application
utkinis Nov 6, 2023
d8ef378
Bump GPU ext compat
luraess Nov 6, 2023
b94686e
Update README
luraess Nov 6, 2023
d591b6a
Add usage doc
luraess Nov 6, 2023
eab0977
Update usage docs
luraess Nov 6, 2023
646fb71
Fix bug with device selection
utkinis Nov 9, 2023
f463269
Add `get_device` for CPU
utkinis Nov 9, 2023
bdd03d8
Add missing imports
utkinis Nov 9, 2023
72425f6
Update `Project.toml`
utkinis Nov 9, 2023
50f3793
Fix typo
utkinis Nov 9, 2023
e2ac734
Try fix
utkinis Nov 9, 2023
73b7e3f
Rename extensions
utkinis Nov 9, 2023
9805eb9
Fix typo
utkinis Nov 9, 2023
fb5e1ff
Update project
luraess Nov 10, 2023
e0a3339
Bump version
luraess Nov 10, 2023
de6c7b4
Add wip script
luraess Nov 10, 2023
07bf739
Fix sync call
luraess Nov 10, 2023
b262aeb
Add global_grid to benchs
luraess Nov 10, 2023
a607dc6
Remove arch sync
luraess Nov 11, 2023
52263f3
Homogenise API calls
luraess Nov 11, 2023
8583c21
Pass through kwargs
utkinis Nov 12, 2023
1ce6599
WIP Stokes
utkinis Nov 13, 2023
e603e0d
Fix deps
utkinis Nov 13, 2023
aac257a
WIP model
utkinis Nov 13, 2023
4f263d7
WIP MPI models (don't run me plz I'm broken)
utkinis Nov 13, 2023
4341258
Add bench scripts
luraess Nov 13, 2023
3dea798
Update scripts
luraess Nov 13, 2023
6a9eb27
Gather on CPU
utkinis Nov 14, 2023
8a032bf
Change A_eff calculation
utkinis Nov 14, 2023
0a0db0a
Fix Stokes model
utkinis Nov 14, 2023
61e4b91
Update scripts
utkinis Nov 15, 2023
f951314
Add docs
utkinis Nov 15, 2023
d7995c0
Add `Distributed` module to docs
utkinis Nov 15, 2023
42323c4
Merge branch 'main' into iu/distributed
utkinis Nov 15, 2023
8c5ca90
Change problem size
utkinis Nov 15, 2023
2351d3a
Remove setup from a script
utkinis Nov 15, 2023
7f547fc
Fix merge issues
utkinis Nov 15, 2023
7ecc7c7
Update model
utkinis Nov 16, 2023
635ed1e
Update model
utkinis Nov 16, 2023
4c12cc5
Update kernels
utkinis Nov 16, 2023
9cc002a
Change resolution
utkinis Nov 17, 2023
d492320
WIP residuals
utkinis Nov 17, 2023
cb85e4a
Cleanup
luraess Nov 17, 2023
63b0f52
WIP
luraess Nov 17, 2023
52469fd
Fix benchmark
utkinis Nov 17, 2023
a745e8b
Update `Fields` API
utkinis Nov 19, 2023
c367c0b
Add helper functions
utkinis Nov 19, 2023
593e238
Update scripts WIP
utkinis Nov 19, 2023
212a396
Remove verbose flag
utkinis Nov 19, 2023
9ee2a3f
Move Architecture constructor
utkinis Nov 19, 2023
75c61e4
Update for changes in API
utkinis Nov 19, 2023
71ecc7b
Add tests
utkinis Nov 19, 2023
ebeed72
Delete old files
utkinis Nov 19, 2023
57064ed
Fix test runner
utkinis Nov 19, 2023
92e97ae
Fix tests
utkinis Nov 20, 2023
9a90435
Improve distributed tests
luraess Nov 20, 2023
01a82b2
Fixup
luraess Nov 20, 2023
bf45584
Add error message display for failed commands
utkinis Nov 20, 2023
48b7692
Refactor Stokes non MPI
luraess Nov 20, 2023
2ed80e6
Try luraess CI runnner
luraess Nov 21, 2023
c8a8096
Fixup
luraess Nov 21, 2023
9d9a38d
Define `outer_width` in model
luraess Nov 21, 2023
b5830af
Update
luraess Nov 21, 2023
1d37038
Add non-distributed manufactured solution
utkinis Nov 22, 2023
1a7800a
Fix forcing
utkinis Nov 22, 2023
2a13c19
Add FunctionFields
utkinis Nov 22, 2023
b7df5e8
Add field forcings
utkinis Nov 22, 2023
e6076fe
Fix 2D setup
utkinis Nov 22, 2023
28254db
Add doc for `KernelLaunch`
utkinis Nov 22, 2023
cb22b3e
Fix typo
utkinis Nov 22, 2023
fe1fbfc
Fix indent
utkinis Nov 22, 2023
7ef3dea
Turn example into a jldoctest
utkinis Nov 22, 2023
504793e
WIP (not running!)
luraess Nov 22, 2023
dcc50d8
Fix typo
luraess Nov 22, 2023
09fa1db
BC WIP (not working)
luraess Nov 22, 2023
937ff7e
Add error check WIP
luraess Nov 23, 2023
5c04757
Add TODOs
luraess Nov 23, 2023
81966af
Update model
utkinis Nov 23, 2023
6983769
Add missing sync
utkinis Nov 23, 2023
5c3f0df
Play with script
utkinis Nov 23, 2023
03537f5
Remove async
utkinis Nov 23, 2023
22618c4
Add latest changes to MPI script. Needs GPU test
luraess Nov 23, 2023
8f6cc96
LUMI setup
utkinis Nov 24, 2023
866c055
LUMI setup
luraess Nov 24, 2023
580e439
LUMI wip
luraess Nov 24, 2023
38305fb
Add intro
utkinis Nov 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .JuliaFormatter.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
style = "yas"
margin = 140
align_assignment = true
whitespace_ops_in_indices = false
import_to_using = false
pipe_to_function_call = false
always_use_return = false
3 changes: 2 additions & 1 deletion .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ steps:
agents:
queue: "juliagpu"
rocm: "*"
rocmgpu: "gfx1101"
timeout_in_minutes: 120
soft_fail:
- exit_status: 3
env:
JULIA_NUM_THREADS: 4
env:
SECRET_CODECOV_TOKEN: "0IoqMRJlTdzvkxpJfv/d4uQBzH0u5Odph6JiQLEASjdh7OPCxmy8ADN7tRPYECguthAFTVnsKeIWpgCyvaJcLY6+sFqlYraL0XOGGX/BCrBQfRvMNKfY8WRf6Hc3NFCyHqFkONFYbxYnFbpXYtdZKbfWDkRHB0bu2JqCbzhN2Yk29dmj2PZPAtUkM+0Uab7cDEzfM/FDwOEssm8bnR/HQRe02DASAyxQGVxcnSZJGZr9IWiPLq6a5qyvN7tkk6FnkMbobwkA48L2fffZQCQF/jlIxc4/yOk9r7P9RVTjWIoSxA59mfuUbKlVHokvXwlVvNS9gXbGOf9gqabfyjcqUA==;U2FsdGVkX19S+m5lHSaFCpYeyDqSxPrqJ9OGWCWUTNDao2X1lzTtCEYQG7YI4abf+9pMnp2msk8JAuw2W7ugQQ=="
SECRET_CODECOV_TOKEN: "0IoqMRJlTdzvkxpJfv/d4uQBzH0u5Odph6JiQLEASjdh7OPCxmy8ADN7tRPYECguthAFTVnsKeIWpgCyvaJcLY6+sFqlYraL0XOGGX/BCrBQfRvMNKfY8WRf6Hc3NFCyHqFkONFYbxYnFbpXYtdZKbfWDkRHB0bu2JqCbzhN2Yk29dmj2PZPAtUkM+0Uab7cDEzfM/FDwOEssm8bnR/HQRe02DASAyxQGVxcnSZJGZr9IWiPLq6a5qyvN7tkk6FnkMbobwkA48L2fffZQCQF/jlIxc4/yOk9r7P9RVTjWIoSxA59mfuUbKlVHokvXwlVvNS9gXbGOf9gqabfyjcqUA==;U2FsdGVkX19S+m5lHSaFCpYeyDqSxPrqJ9OGWCWUTNDao2X1lzTtCEYQG7YI4abf+9pMnp2msk8JAuw2W7ugQQ=="
utkinis marked this conversation as resolved.
Show resolved Hide resolved
16 changes: 12 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "FastIce"
uuid = "e0de9f13-a007-490e-b696-b07d031015ca"
authors = ["Ludovic Raess <ludovic.rass@gmail.com>, Ivan Utkin <utkin@hey.com> and contributors"]
version = "0.1.0"
version = "0.2.0"

[deps]
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
Expand All @@ -13,19 +13,27 @@ LightXML = "9c8b4983-aa76-5018-a973-4c85ecc9e179"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195"
MPIPreferences = "3da0fdf6-3ccc-4f1b-acd9-58baa6c99267"
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
Preferences = "21216c6a-2e73-6563-6e65-726566657250"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[compat]
Adapt = "3"
AMDGPU = "0.7"
CUDA = "5"
ElasticArrays = "1"
GeometryBasics = "0.4"
HDF5 = "0.17"
KernelAbstractions = "0.9"
LightXML = "0.9"
MPI = "0.20"
MPIPreferences = "0.1"
OffsetArrays = "1"
Preferences = "1"
Preferences = "1"

[weakdeps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"

[extensions]
FastIceCUDAExt = "CUDA"
FastIceAMDGPUExt = "AMDGPU"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ Parallel multi-xPU iterative **FastIce** flow solvers

FastIce is currently under active development in order to run at scale on the LUMI AMD-powered GPU supercomputer within the EuroHPC [**STREAM** project](https://ptsolvers.github.io/GPU4GEO/stream/).

Checkout the non-existing [documentation](https://PTsolvers.github.io/FastIce.jl/dev).
Checkout the [documentation](https://PTsolvers.github.io/FastIce.jl/dev) for API reference and usage.
4 changes: 3 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ push!(LOAD_PATH,"../src/")

makedocs(
sitename = "FastIce",
authors="Ludovic Räss, Ivan utkin and contributors",
authors="Ludovic Räss, Ivan Utkin and contributors",
format = Documenter.HTML(; prettyurls=get(ENV, "CI", nothing) == "true"), # easier local build
modules = [FastIce],
pages=[
"Home" => "index.md",
"Usage" => "usage.md",
"Library" => "library.md"
]
)

Expand Down
10 changes: 10 additions & 0 deletions docs/src/library.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Library

## Modules

### Grids

```@autodocs
Modules = [FastIce.Grids, FastIce.Distributed]
Order = [:type, :function]
```
29 changes: 29 additions & 0 deletions docs/src/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Library

## Running tests

### CPU tests

To run the FastIce test suite on the CPU, simple run `test` from within the package mode or using `Pkg`:
```julia-repl
using Pkg
Pkg.test("FastIce")
```

### GPU tests

To run the FastIce test suite on CUDA or ROC Backend (Nvidia or AMD GPUs), respectively, run the tests using `Pkg` adding following `test_args`:

#### For CUDA backend (Nvidia GPU):

```julia-repl
using Pkg
Pkg.test("FastIce"; test_args=["--backend=CUDA"])
```

#### For ROC backend (AMD GPU):

```julia-repl
using Pkg
Pkg.test("FastIce"; test_args=["--backend=AMDGPU"])
```
14 changes: 0 additions & 14 deletions ext/AMDGPUExt/AMDGPUExt.jl

This file was deleted.

14 changes: 0 additions & 14 deletions ext/CUDAExt/CUDAExt.jl

This file was deleted.

14 changes: 14 additions & 0 deletions ext/FastIceAMDGPUExt/FastIceAMDGPUExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module FastIceAMDGPUExt

using FastIce, AMDGPU, AMDGPU.ROCKernels
import FastIce.Architectures: heuristic_groupsize, set_device!, get_device

set_device!(dev::HIPDevice) = AMDGPU.device!(dev)

get_device(::ROCBackend, id::Integer) = HIPDevice(id)

heuristic_groupsize(::HIPDevice, ::Val{1}) = (256, )
heuristic_groupsize(::HIPDevice, ::Val{2}) = (128, 2, )
heuristic_groupsize(::HIPDevice, ::Val{3}) = (128, 2, 1, )

end
15 changes: 15 additions & 0 deletions ext/FastIceCUDAExt/FastIceCUDAExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module FastIceCUDAExt

using FastIce, CUDA, CUDA.CUDAKernels

import FastIce.Architectures: heuristic_groupsize, set_device!, get_device

set_device!(dev::CuDevice) = CUDA.device!(dev)

get_device(::CUDABackend, id::Integer) = CuDevice(id - 1)

heuristic_groupsize(::CuDevice, ::Val{1}) = (256,)
heuristic_groupsize(::CuDevice, ::Val{2}) = (32, 8)
heuristic_groupsize(::CuDevice, ::Val{3}) = (32, 8, 1)

end
3 changes: 2 additions & 1 deletion scripts_future_API/Project.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
FastIce = "e0de9f13-a007-490e-b696-b07d031015ca"
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195"
MPIPreferences = "3da0fdf6-3ccc-4f1b-acd9-58baa6c99267"
56 changes: 56 additions & 0 deletions scripts_future_API/benchmark_dbc.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using FastIce.Architectures
using FastIce.Distributed
using FastIce.Fields
using FastIce.Grids
using FastIce.BoundaryConditions
using FastIce.KernelLaunch

using KernelAbstractions
using MPI

@kernel function fill_field!(f, val, offset=nothing)
I = @index(Global, Cartesian)
if !isnothing(offset)
I += offset
end
f[I] = val
end

MPI.Init()

arch = Architecture(CPU(), (2, 2, 2))
grid = CartesianGrid(; origin=(0.0, 0.0, 0.0), extent=(1.0, 1.0, 1.0), size=(5, 7, 5))
field = Field(backend(arch), grid, (Center(), Center(), Center()); halo=1)

me = global_rank(details(arch))

fill!(parent(field), Inf)

bc = BoundaryConditionsBatch((field,), (DirichletBC{FullCell}(-me-10),))

boundary_conditions = override_boundary_conditions(arch, ((bc, bc), (bc, bc), (bc, bc)); exchange=true)

hide_boundaries = HideBoundaries{3}(arch)

outer_width = (2, 2, 2)

launch!(arch, grid, fill_field! => (field, me); location=location(field), hide_boundaries, boundary_conditions, outer_width)

# sleep(0.25me)
# @show coordinates(details(arch))
# display(parent(field))

field_g = if global_rank(details(arch)) == 0
KernelAbstractions.allocate(Architectures.backend(arch), eltype(field), dimensions(details(arch)) .* size(field))
else
nothing
end

gather!(arch, field_g, field)

if global_rank(details(arch)) == 0
println("global matrix:")
display(field_g)
end

MPI.Finalize()
109 changes: 109 additions & 0 deletions scripts_future_API/benchmark_diffusion_2D.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using FastIce.Grids
using FastIce.GridOperators
using FastIce.Fields
using FastIce.Architectures
using FastIce.BoundaryConditions
using FastIce.Distributed
using FastIce.KernelLaunch

using KernelAbstractions
using MPI

using Plots

@kernel function update_C!(C, qC, dt, Δ, offset=nothing)
I = @index(Global, Cartesian)
isnothing(offset) || (I += offset)
@inbounds if checkbounds(Bool, C, I)
C[I] -= dt * (∂ᶜx(qC.x, I) / Δ.x +
∂ᶜy(qC.y, I) / Δ.y)
end
end

@kernel function update_qC!(qC, C, dc, Δ, offset=nothing)
I = @index(Global, Cartesian)
isnothing(offset) || (I += offset)
@inbounds if checkbounds(Bool, qC.x, I)
qC.x[I] = -dc * ∂ᵛx(C, I) / Δ.x
end
@inbounds if checkbounds(Bool, qC.y, I)
qC.y[I] = -dc * ∂ᵛy(C, I) / Δ.y
end
end

function diffusion_2D(ka_backend=CPU())
# setup arch
arch = Architecture(ka_backend, (0, 0))
topo = details(arch)
# physics
lx, ly = 10.0, 10.0
dc = 1
# numerics
size_g = (32, 32)
nt = 1000
# preprocessing
size_g = global_grid_size(topo, size_g)
global_grid = CartesianGrid(; origin=(-0.5lx, -0.5ly),
extent=(lx, ly),
size=size_g)
grid = local_grid(global_grid, topo)
Δ = NamedTuple{(:x, :y)}(spacing(global_grid))
dt = minimum(Δ)^2 / dc / ndims(grid) / 2.1
hide_boundaries = HideBoundaries{ndims(grid)}(arch)
outer_width = (4, 4)
# fields
C = Field(arch, grid, Center(); halo=1)
qC = (x = Field(arch, grid, (Vertex(), Center()); halo=1),
y = Field(arch, grid, (Center(), Vertex()); halo=1))
C_g = if global_rank(topo) == 0
KernelAbstractions.allocate(Architectures.backend(arch), eltype(C), size_g)
else
nothing
end
# initial condition
foreach(comp -> fill!(parent(comp), 0.0), qC)
# fill!(parent(C), me)
set!(C, grid, (x, y) -> exp(-x^2 - y^2))
# set!(C, me)
# boundary conditions
zero_flux_bc = DirichletBC{FullCell}(0.0)
bc_q = (x = BoundaryConditionsBatch((qC.x, qC.y), (zero_flux_bc, nothing)),
y = BoundaryConditionsBatch((qC.x, qC.y), (nothing, zero_flux_bc)))
# zero flux at physical boundaries and nothing at MPI boundaries
bc_q = override_boundary_conditions(arch, ((bc_q.x, bc_q.x), (bc_q.y, bc_q.y)); exchange=true)
# nothing at physical boundaries and communication at MPI boundaries
bc_c = BoundaryConditionsBatch((C,), nothing)
bc_c = override_boundary_conditions(arch, ((bc_c, bc_c), (bc_c, bc_c)); exchange=true)
for D in ndims(grid):-1:1
apply_boundary_conditions!(Val(1), Val(D), arch, grid, bc_c[D][1])
apply_boundary_conditions!(Val(2), Val(D), arch, grid, bc_c[D][2])
apply_boundary_conditions!(Val(1), Val(D), arch, grid, bc_q[D][1])
apply_boundary_conditions!(Val(2), Val(D), arch, grid, bc_q[D][2])
end
# time loop
if global_rank(topo) == 0
anim = Animation()
end
for it in 1:nt
(global_rank(topo) == 0) && println("it = $it")
launch!(arch, grid, update_qC! => (qC, C, dc, Δ); location=Vertex(), hide_boundaries, boundary_conditions=bc_q, outer_width)
launch!(arch, grid, update_C! => (C, qC, dt, Δ); location=Center(), expand=1)
synchronize(Architectures.backend(arch))
if it % 5 == 0
gather!(arch, C_g, C)
if global_rank(topo) == 0
heatmap(C_g; aspect_ratio=1, size=(600, 600), clims=(0, 1))
frame(anim)
end
end
end
if global_rank(topo) == 0
gif(anim, "C.gif")
end

return
end

MPI.Init()
diffusion_2D()
MPI.Finalize()
Loading