Skip to content

Conversation

@navidcy
Copy link
Member

@navidcy navidcy commented Jun 10, 2025

This PR adds FFTBasedPoisonSolve method for AMDGPU.

Closes #4591

@navidcy navidcy added GPU 👾 Where Oceananigans gets its powers from extensions 🧬 labels Jun 10, 2025
@navidcy navidcy requested review from amontoison and simone-silvestri and removed request for simone-silvestri June 10, 2025 10:52

function plan_backward_transform(A::ROCArray, ::Union{Bounded, Periodic}, dims, planner_flag)
length(dims) == 0 && return nothing
return AMDGPU.rocFFT.plan_bfft!(A, dims)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the plan_bfft!, not the plan_ifft!
do we need to add a normalisation or something?

@navidcy navidcy marked this pull request as ready for review June 10, 2025 10:53
@navidcy
Copy link
Member Author

navidcy commented Jun 10, 2025

With the current modifications I can create an FFTBasedPoissonSolver with a uniformly-spaced grid.

julia> using Oceananigans, AMDGPU

julia> grid = RectilinearGrid(GPU(AMDGPU.ROCBackend()), size=(8, 8, 8), extent=(1, 2, 3))
8×8×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on ROCGPU with 3×3×3 halo
├── Periodic x  [0.0, 1.0)  regularly spaced with Δx=0.125
├── Periodic y  [0.0, 2.0)  regularly spaced with Δy=0.25
└── Bounded  z  [-3.0, 0.0] regularly spaced with Δz=0.375

julia> pressure_solver = Oceananigans.Solvers.FFTBasedPoissonSolver(grid)
FFTBasedPoissonSolver on GPU{ROCBackend}: 
├── grid: 8×8×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on ROCGPU with 3×3×3 halo
├── storage: ROCArray{ComplexF64, 3, AMDGPU.Runtime.Mem.HIPBuffer}
├── buffer: ROCArray{ComplexF64, 3, AMDGPU.Runtime.Mem.HIPBuffer}
└── transforms:
    ├── forward: Oceananigans.Solvers.DiscreteTransform, Oceananigans.Solvers.DiscreteTransform
    └── backward: Oceananigans.Solvers.DiscreteTransform, Oceananigans.Solvers.DiscreteTransform

julia> model = NonhydrostaticModel(; grid, pressure_solver)
NonhydrostaticModel{GPU, RectilinearGrid}(time = 0 seconds, iteration = 0)
├── grid: 8×8×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on ROCGPU with 3×3×3 halo
├── timestepper: RungeKutta3TimeStepper
├── advection scheme: Centered(order=2)
├── tracers: ()
├── closure: Nothing
├── buoyancy: Nothing
└── coriolis: Nothing

julia> simulation = Simulation(model, Δt=10, stop_iteration=3)
Simulation of NonhydrostaticModel{GPU, RectilinearGrid}(time = 0 seconds, iteration = 0)
├── Next time step: 10 seconds
├── Elapsed wall time: 0 seconds
├── Wall time per iteration: NaN days
├── Stop time: Inf days
├── Stop iteration: 3.0
├── Wall time limit: Inf
├── Minimum relative step: 0.0
├── Callbacks: OrderedDict with 4 entries:
│   ├── stop_time_exceeded => Callback of stop_time_exceeded on IterationInterval(1)
│   ├── stop_iteration_exceeded => Callback of stop_iteration_exceeded on IterationInterval(1)
│   ├── wall_time_limit_exceeded => Callback of wall_time_limit_exceeded on IterationInterval(1)
│   └── nan_checker => Callback of NaNChecker for u on IterationInterval(100)
├── Output writers: OrderedDict with no entries
└── Diagnostics: OrderedDict with no entries

julia> run!(simulation)
[ Info: Initializing simulation...
[ Info:     ... simulation initialization complete (416.478 μs)
[ Info: Executing initial time step...
[ Info:     ... initial time step complete (3.048 ms).
[ Info: Simulation is stopping after running for 6.118 ms.
[ Info: Model iteration 3 equals or exceeds stop iteration 3.

@navidcy
Copy link
Member Author

navidcy commented Jun 10, 2025

With AMDGPU, scalar operations need AMDGPU.@allowscalar, right?
But all the code is sprinkled with CUDA.@allowscalar. What do we do about that?

@amontoison
Copy link
Collaborator

We have a generic @allowscalar in GPUArraysCore.jl if I remember well.

@navidcy
Copy link
Member Author

navidcy commented Jun 10, 2025

This is ready to review.
The only thing I'm not sure about is the use of bfft instead of ifft.

@glwagner
Copy link
Member

@allowscalar does not belong to CUDA and it is wrong that we use CUDA.@allowscalar. This is addressed by #4499

@michel2323 , I feel that with AMDGPU starting to get some use, we should try to merge #4499. What do you think? If we wait too long we may get some conflicts.

@glwagner
Copy link
Member

glwagner commented Jun 10, 2025

This is ready to review. The only thing I'm not sure about is the use of bfft instead of ifft.

Can you please test this? An empirical test should reveal whether this code is correct and also will show what the normalization needs to be (if documentation is insufficient, which I am not surprised that it is).

@michel2323
Copy link
Collaborator

@michel2323 , I feel that with AMDGPU starting to get some use, we should try to merge #4499. What do you think? If we wait too long we may get some conflicts.

@glwagner I continuously rebased, so it shouldn't be too far off. However, while the majority of tests pass, there are still a few that fail. I'll do another pass tomorrow morning and give you a short summary. I might need some help.

@navidcy
Copy link
Member Author

navidcy commented Jun 10, 2025

Can you please test this? An empirical test should reveal whether this code is correct and also will show what the normalization needs to be (if documentation is insufficient, which I am not surprised that it is).

Yes, I wanted an idea of how to test. I know that ifft and bfft differ by a factor, e.g.,

julia> Nx, Ny = 3, 4
(3, 4)

julia> a = rand(Nx, Ny)
3×4 Matrix{Float64}:
 0.453795  0.778266  0.499822    0.749407
 0.646126  0.855627  0.00391171  0.158878
 0.307381  0.898621  0.453264    0.604466

julia> ah = fft(a)
3×4 Matrix{ComplexF64}:
  6.40956+0.0im        0.450305-1.01976im    -1.68096+0.0im        0.450305+1.01976im
 0.517153+0.518913im   -0.64285-0.21592im  -0.0206029-0.327336im  0.0544652-1.14911im
 0.517153-0.518913im  0.0544652+1.14911im  -0.0206029+0.327336im   -0.64285+0.21592im

julia> ifft(ah)
3×4 Matrix{ComplexF64}:
 0.453795+0.0im  0.778266+0.0im    0.499822+0.0im  0.749407+0.0im
 0.646126+0.0im  0.855627+0.0im  0.00391171+0.0im  0.158878+0.0im
 0.307381+0.0im  0.898621+0.0im    0.453264+0.0im  0.604466+0.0im

julia> bfft(ah) / (Nx * Ny)
3×4 Matrix{ComplexF64}:
 0.453795+0.0im  0.778266+0.0im    0.499822+0.0im  0.749407+0.0im
 0.646126+0.0im  0.855627+0.0im  0.00391171+0.0im  0.158878+0.0im
 0.307381+0.0im  0.898621+0.0im    0.453264+0.0im  0.604466+0.0im

But I don't know exactly how to incorporate this function in the plans so that it's the same as elsewhere in the pressure solver.

@navidcy
Copy link
Member Author

navidcy commented Jun 10, 2025

Hm... If I understand correctly we need to manually apply the scaling after the inverse transform. How do I do that best way? The normalization should be

N = prod(size(A, d) for d in dims)

function backward_transform!(x)
    p * x           # in-place inverse FFT
    @. x = x / N    # in-place normalization
    return x
end

@glwagner
Copy link
Member

What prevents you from using that exact code?

@navidcy
Copy link
Member Author

navidcy commented Jun 11, 2025

I tried and failed. I need help perhaps?
I don't know exactly how to make the pressure solver use this rescaling only if it's a ROCArray

@navidcy
Copy link
Member Author

navidcy commented Jun 11, 2025

I tried doing this in the AMD extension:

function plan_backward_transform(A::ROCArray, ::Union{Bounded, Periodic}, dims, planner_flag)
    length(dims) == 0 && return nothing

    p = AMDGPU.rocFFT.plan_bfft!(A, dims)
    N = prod(size(A, d) for d in dims)

    function backward_transform!(x, y)
        @. x = p * y           # in-place inverse FFT
        @. x = x / N    # in-place normalization
        return x
    end
    return backward_transform!
end

but I got an error related with binary operations... The pressure_solver is constructed but while time stepping I get:

julia> using Oceananigans, AMDGPU
[ Info: Precompiling OceananigansAMDGPUExt [8da284e0-aa90-5603-9506-0dba59ddb112]

julia> grid = RectilinearGrid(GPU(AMDGPU.ROCBackend()), size=(16, 8, 4), x=(0, 16), y=(0, 1), z=[0, 1, 2, 3, 4])
16×8×4 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on ROCGPU with 3×3×3 halo
├── Periodic x  [0.0, 16.0) regularly spaced with Δx=1.0
├── Periodic y  [0.0, 1.0)  regularly spaced with Δy=0.125
└── Bounded  z  [0.0, 4.0]  variably spaced with min(Δz)=1.0, max(Δz)=1.0

julia> pressure_solver = Oceananigans.Solvers.FFTBasedPoissonSolver(grid)
FFTBasedPoissonSolver on GPU{ROCBackend}: 
├── grid: 16×8×4 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on ROCGPU with 3×3×3 halo
├── storage: ROCArray{ComplexF64, 3, AMDGPU.Runtime.Mem.HIPBuffer}
├── buffer: ROCArray{ComplexF64, 3, AMDGPU.Runtime.Mem.HIPBuffer}
└── transforms:
    ├── forward: Oceananigans.Solvers.DiscreteTransform
    └── backward: Oceananigans.Solvers.DiscreteTransform

julia> model = NonhydrostaticModel(; grid, pressure_solver)
NonhydrostaticModel{GPU, RectilinearGrid}(time = 0 seconds, iteration = 0)
├── grid: 16×8×4 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on ROCGPU with 3×3×3 halo
├── timestepper: RungeKutta3TimeStepper
├── advection scheme: Centered(order=2)
├── tracers: ()
├── closure: Nothing
├── buoyancy: Nothing
└── coriolis: Nothing

julia> simulation = Simulation(model, Δt=10, stop_iteration=3)
Simulation of NonhydrostaticModel{GPU, RectilinearGrid}(time = 0 seconds, iteration = 0)
├── Next time step: 10 seconds
├── Elapsed wall time: 0 seconds
├── Wall time per iteration: NaN days
├── Stop time: Inf days
├── Stop iteration: 3.0
├── Wall time limit: Inf
├── Minimum relative step: 0.0
├── Callbacks: OrderedDict with 4 entries:
│   ├── stop_time_exceeded => Callback of stop_time_exceeded on IterationInterval(1)
│   ├── stop_iteration_exceeded => Callback of stop_iteration_exceeded on IterationInterval(1)
│   ├── wall_time_limit_exceeded => Callback of wall_time_limit_exceeded on IterationInterval(1)
│   └── nan_checker => Callback of NaNChecker for u on IterationInterval(100)
├── Output writers: OrderedDict with no entries
└── Diagnostics: OrderedDict with no entries

julia> run!(simulation)
[ Info: Initializing simulation...
[ Info:     ... simulation initialization complete (4.818 seconds)
[ Info: Executing initial time step...
ERROR: MethodError: no method matching *(::OceananigansAMDGPUExt.var"#backward_transform!#3"{}, ::ROCArray{…})

Closest candidates are:
  *(::Any, ::Any, ::Any, ::Oceananigans.Grids.AbstractGrid, ::Any, ::Any, ::Number, ::Oceananigans.AbstractOperations.BinaryOperation)
   @ Oceananigans ~/Oceananigans.jl/src/AbstractOperations/binary_operations.jl:91
  *(::Any, ::Any, ::Any, ::Oceananigans.Grids.AbstractGrid, ::Any, ::Any, ::Oceananigans.AbstractOperations.BinaryOperation, ::Oceananigans.AbstractOperations.BinaryOperation)
   @ Oceananigans ~/Oceananigans.jl/src/AbstractOperations/binary_operations.jl:70
  *(::Any, ::Any, ::Any, ::Oceananigans.Grids.AbstractGrid, ::Any, ::Any, ::Oceananigans.AbstractOperations.BinaryOperation, ::Oceananigans.Fields.AbstractField)
   @ Oceananigans ~/Oceananigans.jl/src/AbstractOperations/binary_operations.jl:76
  ...

Stacktrace:
  [1] apply_transform!(A::ROCArray{…}, B::ROCArray{…}, plan::Function, ::Nothing)
    @ Oceananigans.Solvers ~/Oceananigans.jl/src/Solvers/discrete_transforms.jl:142
  [2] (::Oceananigans.Solvers.DiscreteTransform{…})(A::ROCArray{…}, buffer::ROCArray{…})
    @ Oceananigans.Solvers ~/Oceananigans.jl/src/Solvers/discrete_transforms.jl:118
  [3] solve!::Field{…}, solver::Oceananigans.Solvers.FFTBasedPoissonSolver{…}, b::ROCArray{…}, m::Int64)
    @ Oceananigans.Solvers ~/Oceananigans.jl/src/Solvers/fft_based_poisson_solver.jl:119
  [4] solve!::Field{…}, solver::Oceananigans.Solvers.FFTBasedPoissonSolver{…})
    @ Oceananigans.Solvers ~/Oceananigans.jl/src/Solvers/fft_based_poisson_solver.jl:96
  [5] solve_for_pressure!(pressure::Field{…}, solver::Oceananigans.Solvers.FFTBasedPoissonSolver{…}, Δt::Float64, args::@NamedTuple{})
    @ Oceananigans.Models.NonhydrostaticModels ~/Oceananigans.jl/src/Models/NonhydrostaticModels/solve_for_pressure.jl:85
  [6] compute_pressure_correction!(model::NonhydrostaticModel{…}, Δt::Float64)
    @ Oceananigans.Models.NonhydrostaticModels ~/Oceananigans.jl/src/Models/NonhydrostaticModels/pressure_correction.jl:13
  [7] time_step!(model::NonhydrostaticModel{…}, Δt::Float64; callbacks::Tuple{})
    @ Oceananigans.TimeSteppers ~/Oceananigans.jl/src/TimeSteppers/runge_kutta_3.jl:114
  [8] time_step!(sim::Simulation{…})
    @ Oceananigans.Simulations ~/Oceananigans.jl/src/Simulations/run.jl:149
  [9] run!(sim::Simulation{…}; pickup::Bool)
    @ Oceananigans.Simulations ~/Oceananigans.jl/src/Simulations/run.jl:105
 [10] run!(sim::Simulation{…})
    @ Oceananigans.Simulations ~/Oceananigans.jl/src/Simulations/run.jl:92
 [11] top-level scope
    @ REPL[6]:1
Some type information was truncated. Use `show(err)` to see complete types.

@glwagner
Copy link
Member

glwagner commented Jun 11, 2025

The stack trace shows that the error originates from here:

function apply_transform!(A, B, plan, ::Nothing)
plan * A
return nothing
end

You need to extend apply_transform! (or extend * for the plan you are creating if you want to reuse the apply_transform! function itself, but I don't see the value in that)

@glwagner
Copy link
Member

although the DiscreteTransform interface already includes a normalization options which is applied here

maybe_normalize!(A, transform.normalization)

@glwagner
Copy link
Member

struct DiscreteTransform{P, D, G, Δ, Ω, N, T, Σ}
plan :: P
grid :: G
direction :: D
dims :: Δ
topology :: Ω
normalization :: N
twiddle_factors :: T # # https://en.wikipedia.org/wiki/Twiddle_factor
transpose_dims :: Σ
end

@navidcy
Copy link
Member Author

navidcy commented Jun 11, 2025

Yes. I am confused though because the Fourier transforms don't include a normalisation factor but then it seems that the DiscreteTransforms method were called. (Is the Fourier transforms <: DiscreteTransforms)?

Perhaps I have a lack of understanding of how things work in general with the transforms and that's where the essence of my difficulty lies... :(

@glwagner
Copy link
Member

Yes but nobody understands this so the only solution is to figure it out

@glwagner
Copy link
Member

this file organizes the transforms:

backward_transforms = (

it looks like plans are made and then inserted into DiscreteTransform.

@navidcy
Copy link
Member Author

navidcy commented Jun 11, 2025

Yes but nobody understands this so the only solution is to figure it out

:D

OK! Will try to penetrate this!

@navidcy
Copy link
Member Author

navidcy commented Jun 11, 2025

(it's helpful to hear that we are at the same denominator)

@glwagner
Copy link
Member

The constructor for DiscreteTransform is here:

function DiscreteTransform(plan, direction, grid, dims)

this builds normalization factors here:

normalization = prod(normalization_factor(arch, topo[d](), direction, N[d]) for d in dims)

The normalization_factor takes the architecture as first argument, eg

normalization_factor(arch, topo, direction, N) = 1

for fallback and

normalization_factor(::CPU, ::Bounded, ::Backward, N) = 1 / 2N

on CPU.

You can try extending normalization_factor for AMDGPU?

It is a little dirty, because it makes an assumption that every architecture is tied to a particular transform implementation. Nevertheless, this is the case for all existing code and also here as well.

@glwagner
Copy link
Member

glwagner commented Jun 11, 2025

The normalization factor is applied here

function (transform::DiscreteTransform{P, <:Forward})(A, buffer) where P
maybe_permute_indices!(A, buffer, architecture(transform), transform.grid, transform.dims, transform.topology)
apply_transform!(A, buffer, transform.plan, transform.transpose_dims)
maybe_twiddle_forward!(A, transform.twiddle_factors)
maybe_normalize!(A, transform.normalization)
return nothing
end
function (transform::DiscreteTransform{P, <:Backward})(A, buffer) where P
maybe_twiddle_backward!(A, transform.twiddle_factors)
apply_transform!(A, buffer, transform.plan, transform.transpose_dims)
maybe_unpermute_indices!(A, buffer, architecture(transform), transform.grid, transform.dims, transform.topology)
maybe_normalize!(A, transform.normalization)
return nothing
end

via functions maybe_normalize which are defined here

function maybe_normalize!(A, normalization)
# Avoid a tiny kernel launch if possible.
if normalization != 1
@. A *= normalization
end
return nothing
end

if this fits your use case, you can try it.

It is all a little overengineered and therefore overcomplex.

@navidcy
Copy link
Member Author

navidcy commented Jul 16, 2025

OK, if I understand correctly the FFT-related methods were already included in #4499, right @michel2323? So perhaps this PR is not needed? Or it might be a good idea to add a NonhydrostaticModel test; perhaps this is what the PR should do.

@navidcy
Copy link
Member Author

navidcy commented Jul 16, 2025

Hm... I seem to be getting an error that plan_ifft! is not defined?

https://buildkite.com/julialang/oceananigans-dot-jl/builds/1788#0198152b-f0c3-432f-9372-6ee7d06a56a0/122-1089

@giordano
Copy link
Collaborator

giordano commented Jan 1, 2026

Hm... I seem to be getting an error that plan_ifft! is not defined?

I just came across this. The FFT stuff in the AMDGPU extension is simply broken: NumericalEarth/Breeze.jl#369 (comment). Oceananigans shouldn't call AMDGPU.rocFFT.plan_ifft!, but AbstractFFTs.plan_ifft! on an ROCArray{<:Complex}, similarly for all the other FFT functions. This error would have been avoided if ExplicitImports.jl was enforced in the entirety of Oceananigans (we are still a long way from that goal).

@glwagner
Copy link
Member

glwagner commented Jan 2, 2026

Makes sense, so we don’t have to figure out how to do this translation from ifft to bfft ourselves

@giordano
Copy link
Collaborator

giordano commented Jan 4, 2026

New errors, but the undefined plan_fft!/plan_ifft! errors are resolved: https://buildkite.com/julialang/oceananigans-dot-jl/builds/4986#019b8a21-ade7-487e-9248-0a15db839156/L2086

AMDGPU on RectilinearGrids: Error During Test at /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/test_amdgpu.jl:22
  Got exception outside of a @test
  MethodError: no method matching plan_transforms(::RectilinearGrid{Float32, Periodic, Periodic, Bounded, Oceananigans.Grids.StaticVerticalDiscretization{OffsetVector{Float32, ROCArray{Float32, 1, AMDGPU.Runtime.Mem.HIPBuffer}}, OffsetVector{Float32, ROCArray{Float32, 1, AMDGPU.Runtime.Mem.HIPBuffer}}, OffsetVector{Float32, ROCArray{Float32, 1, AMDGPU.Runtime.Mem.HIPBuffer}}, OffsetVector{Float32, ROCArray{Float32, 1, AMDGPU.Runtime.Mem.HIPBuffer}}}, Float32, Float32, OffsetVector{Float32, StepRangeLen{Float32, Float64, Float64, Int64}}, OffsetVector{Float32, StepRangeLen{Float32, Float64, Float64, Int64}}, GPU{ROCBackend}}, ::ROCArray{ComplexF32, 3, AMDGPU.Runtime.Mem.HIPBuffer}, ::UInt32)
  The function `plan_transforms` exists, but no method is defined for this combination of argument types.
  Closest candidates are:
    plan_transforms(::Any, ::Any, ::Any, ::Any)
     @ Oceananigans /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/src/Solvers/plan_transforms.jl:139
    plan_transforms(::RectilinearGrid{<:Any, <:Any, <:Any, <:Any, <:Union{MutableVerticalDiscretization{<:Any, <:Any, <:Number}, Oceananigans.Grids.StaticVerticalDiscretization{<:Any, <:Any, <:Number}}, <:Number, <:Number}, ::Any, ::Any)
     @ Oceananigans /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/src/Solvers/plan_transforms.jl:68
  Stacktrace:
    [1] FFTBasedPoissonSolver(grid::RectilinearGrid{Float32, Periodic, Periodic, Bounded, Oceananigans.Grids.StaticVerticalDiscretization{OffsetVector{Float32, ROCArray{Float32, 1, AMDGPU.Runtime.Mem.HIPBuffer}}, OffsetVector{Float32, ROCArray{Float32, 1, AMDGPU.Runtime.Mem.HIPBuffer}}, OffsetVector{Float32, ROCArray{Float32, 1, AMDGPU.Runtime.Mem.HIPBuffer}}, OffsetVector{Float32, ROCArray{Float32, 1, AMDGPU.Runtime.Mem.HIPBuffer}}}, Float32, Float32, OffsetVector{Float32, StepRangeLen{Float32, Float64, Float64, Int64}}, OffsetVector{Float32, StepRangeLen{Float32, Float64, Float64, Int64}}, GPU{ROCBackend}}, planner_flag::UInt32)
      @ Oceananigans.Solvers /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/src/Solvers/fft_based_poisson_solver.jl:67
    [2] FFTBasedPoissonSolver(grid::RectilinearGrid{Float32, Periodic, Periodic, Bounded, Oceananigans.Grids.StaticVerticalDiscretization{OffsetVector{Float32, ROCArray{Float32, 1, AMDGPU.Runtime.Mem.HIPBuffer}}, OffsetVector{Float32, ROCArray{Float32, 1, AMDGPU.Runtime.Mem.HIPBuffer}}, OffsetVector{Float32, ROCArray{Float32, 1, AMDGPU.Runtime.Mem.HIPBuffer}}, OffsetVector{Float32, ROCArray{Float32, 1, AMDGPU.Runtime.Mem.HIPBuffer}}}, Float32, Float32, OffsetVector{Float32, StepRangeLen{Float32, Float64, Float64, Int64}}, OffsetVector{Float32, StepRangeLen{Float32, Float64, Float64, Int64}}, GPU{ROCBackend}})
      @ Oceananigans.Solvers /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/src/Solvers/fft_based_poisson_solver.jl:53
    [3] macro expansion
      @ /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/test_amdgpu.jl:69 [inlined]
    [4] macro expansion
      @ ~/.cache/julia-buildkite-plugin/julia_installs/bin/linux/x64/1.12/julia-1.12-latest-linux-x86_64/share/julia/stdlib/v1.12/Test/src/Test.jl:1776 [inlined]
    [5] top-level scope
      @ /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/test_amdgpu.jl:23
[...]
AMDGPU on LatitudeLongitudeGrid with HydrostaticFreeSurfaceModel: Error During Test at /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/test_amdgpu.jl:96
  Test threw exception
  Expression: parent(grid.Δyᶠᶜᵃ) isa ROCArray
  MethodError: no method matching parent(::Float32)
  The function `parent` exists, but no method is defined for this combination of argument types.
  Closest candidates are:
    parent(::DataFrames.SubDataFrame)
     @ DataFrames ~/.cache/julia-buildkite-plugin/depots/01962b57-ae40-45a7-b229-560c2d4f6b07/packages/DataFrames/b4w9K/src/subdataframe/subdataframe.jl:137
    parent(::SubArray)
     @ Base subarray.jl:80
    parent(::DataFrames.AbstractDataFrame)
     @ DataFrames ~/.cache/julia-buildkite-plugin/depots/01962b57-ae40-45a7-b229-560c2d4f6b07/packages/DataFrames/b4w9K/src/abstractdataframe/abstractdataframe.jl:1914
    ...
  Stacktrace:
   [1] macro expansion
     @ ~/.cache/julia-buildkite-plugin/julia_installs/bin/linux/x64/1.12/julia-1.12-latest-linux-x86_64/share/julia/stdlib/v1.12/Test/src/Test.jl:677 [inlined]
   [2] macro expansion
     @ /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/test_amdgpu.jl:96 [inlined]
   [3] macro expansion
     @ ~/.cache/julia-buildkite-plugin/julia_installs/bin/linux/x64/1.12/julia-1.12-latest-linux-x86_64/share/julia/stdlib/v1.12/Test/src/Test.jl:1776 [inlined]
   [4] top-level scope
     @ /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/test_amdgpu.jl:84
AMDGPU on LatitudeLongitudeGrid with HydrostaticFreeSurfaceModel: Error During Test at /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/test_amdgpu.jl:97
  Test threw exception
  Expression: parent(grid.Δyᶜᶠᵃ) isa ROCArray
  MethodError: no method matching parent(::Float32)
  The function `parent` exists, but no method is defined for this combination of argument types.
  Closest candidates are:
    parent(::DataFrames.SubDataFrame)
     @ DataFrames ~/.cache/julia-buildkite-plugin/depots/01962b57-ae40-45a7-b229-560c2d4f6b07/packages/DataFrames/b4w9K/src/subdataframe/subdataframe.jl:137
    parent(::SubArray)
     @ Base subarray.jl:80
    parent(::DataFrames.AbstractDataFrame)
     @ DataFrames ~/.cache/julia-buildkite-plugin/depots/01962b57-ae40-45a7-b229-560c2d4f6b07/packages/DataFrames/b4w9K/src/abstractdataframe/abstractdataframe.jl:1914
    ...
  Stacktrace:
   [1] macro expansion
     @ ~/.cache/julia-buildkite-plugin/julia_installs/bin/linux/x64/1.12/julia-1.12-latest-linux-x86_64/share/julia/stdlib/v1.12/Test/src/Test.jl:677 [inlined]
   [2] macro expansion
     @ /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/test_amdgpu.jl:97 [inlined]
   [3] macro expansion
     @ ~/.cache/julia-buildkite-plugin/julia_installs/bin/linux/x64/1.12/julia-1.12-latest-linux-x86_64/share/julia/stdlib/v1.12/Test/src/Test.jl:1776 [inlined]
   [4] top-level scope
     @ /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/test_amdgpu.jl:84
AMDGPU on LatitudeLongitudeGrid with HydrostaticFreeSurfaceModel: Error During Test at /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/test_amdgpu.jl:83
  Got exception outside of a @test
  UndefVarError: `build_and_time_step_simulation` not defined in `Main`
  Suggestion: check for spelling errors or missing imports.
  Stacktrace:
    [1] macro expansion
      @ /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/test_amdgpu.jl:115 [inlined]
    [2] macro expansion
      @ ~/.cache/julia-buildkite-plugin/julia_installs/bin/linux/x64/1.12/julia-1.12-latest-linux-x86_64/share/julia/stdlib/v1.12/Test/src/Test.jl:1776 [inlined]
    [3] top-level scope
      @ /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/test_amdgpu.jl:84
    [4] include(mapexpr::Function, mod::Module, _path::String)
      @ Base ./Base.jl:307
    [5] IncludeInto
      @ ./Base.jl:308 [inlined]
    [6] macro expansion
      @ /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/runtests.jl:303 [inlined]
    [7] macro expansion
      @ ~/.cache/julia-buildkite-plugin/julia_installs/bin/linux/x64/1.12/julia-1.12-latest-linux-x86_64/share/julia/stdlib/v1.12/Test/src/Test.jl:1776 [inlined]
    [8] macro expansion
      @ /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/runtests.jl:303 [inlined]
    [9] macro expansion
      @ ~/.cache/julia-buildkite-plugin/julia_installs/bin/linux/x64/1.12/julia-1.12-latest-linux-x86_64/share/julia/stdlib/v1.12/Test/src/Test.jl:1776 [inlined]
   [10] (::var"#6#7")()
      @ Main /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/runtests.jl:25
   [11] task_local_storage(body::var"#6#7", key::Symbol, val::GPUArraysCore.ScalarIndexing)
      @ Base ./task.jl:298
   [12] allowscalar(f::Function)
      @ GPUArraysCore ~/.cache/julia-buildkite-plugin/depots/01962b57-ae40-45a7-b229-560c2d4f6b07/packages/GPUArraysCore/aNaXo/src/GPUArraysCore.jl:179
   [13] top-level scope
      @ /var/lib/buildkite-agent/builds/amdgpu1-luraess-com/julialang/oceananigans-dot-jl/test/runtests.jl:21
   [14] include(mapexpr::Function, mod::Module, _path::String)
      @ Base ./Base.jl:307
   [15] top-level scope
      @ none:6
   [16] eval(m::Module, e::Any)
      @ Core ./boot.jl:489
   [17] exec_options(opts::Base.JLOptions)
      @ Base ./client.jl:283
   [18] _start()
      @ Base ./client.jl:550


@test iteration(simulation) == 3
@test time(simulation) == 3minutes
build_and_time_step_simulation(model)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@glwagner you added this line in f835c0d, but this function doesn't exist anywhere as far as I can tell.

@giordano
Copy link
Collaborator

giordano commented Jan 4, 2026

Remaining errors are the method error with plan_transforms (see full error in #4593 (comment)) and #4593 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extensions 🧬 GPU 👾 Where Oceananigans gets its powers from

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AMDGPU with NonhydrostaticModel?

6 participants