-
Notifications
You must be signed in to change notification settings - Fork 195
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
Zero result when using pressure derivatives in KernelComputedFields #1401
Comments
What is the type of the object |
It's a binary operation, which I guess is what we expect, right? julia> p = sum(model.pressures)
BinaryOperation at (Center, Center, Center)
├── grid: RegularRectilinearGrid{Float64, Periodic, Bounded, Bounded}(Nx=1, Ny=512, Nz=8)
│ └── domain: x ∈ [0.0, 150.0], y ∈ [0.0, 6000.0], z ∈ [-80.0, 0.0]
└── tree:
+ at (Center, Center, Center) via identity
├── Field located at (Center, Center, Center)
└── Field located at (Center, Center, Center)
julia> typeof(p)
Oceananigans.AbstractOperations.BinaryOperation{Center,Center,Center,typeof(+),Field{Center,Center,Center,OffsetArrays.OffsetArray{Float64,3,Array{Float64,3}},RegularRectilinearGrid{Float64,Periodic,Bounded,Bounded,OffsetArrays.OffsetArray{Float64,1,StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}}},NamedTuple{(:x, :y, :z),Tuple{CoordinateBoundaryConditions{BoundaryCondition{Oceananigans.BoundaryConditions.Periodic,Nothing},BoundaryCondition{Oceananigans.BoundaryConditions.Periodic,Nothing}},CoordinateBoundaryConditions{BoundaryCondition{Flux,Nothing},BoundaryCondition{Flux,Nothing}},CoordinateBoundaryConditions{BoundaryCondition{Flux,Nothing},BoundaryCondition{Flux,Nothing}}}}},Field{Center,Center,Center,OffsetArrays.OffsetArray{Float64,3,Array{Float64,3}},RegularRectilinearGrid{Float64,Periodic,Bounded,Bounded,OffsetArrays.OffsetArray{Float64,1,StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}}},NamedTuple{(:x, :y, :z),Tuple{CoordinateBoundaryConditions{BoundaryCondition{Oceananigans.BoundaryConditions.Periodic,Nothing},BoundaryCondition{Oceananigans.BoundaryConditions.Periodic,Nothing}},CoordinateBoundaryConditions{BoundaryCondition{Flux,Nothing},BoundaryCondition{Flux,Nothing}},CoordinateBoundaryConditions{BoundaryCondition{Flux,Nothing},BoundaryCondition{Flux,Nothing}}}}},typeof(identity),typeof(identity),typeof(identity),RegularRectilinearGrid{Float64,Periodic,Bounded,Bounded,OffsetArrays.OffsetArray{Float64,1,StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}}}} |
Pressure is different from other variables because it doesn't have a dedicated More on the top of this issue, there is a small difference between the two kernels: in one the reference density (which is otherwise arbitrary?) appears to be But otherwise I don't see why it wouldn't work and I am a bit stumped. |
Sorry that was a typo. Just fixed it.
Yes, I've dedicated several hours to investigating this issue also and got nothing. The issue also is that I'm actually depending on that result for research, and it's pretty expensive to calculate that offline. Do you have any suggested workarounds? |
Does the order in which you call You could try making |
Just tested it and no.
I'd tried that already and the results are the same :/ Something interesting is that the code below works: @kernel function pressure_correlation_z_ccc!(wp, grid, w, p)
i, j, k = @index(Global, NTuple)
@inbounds wp[i, j, k] = ℑzᵃᵃᶠ(i, j, k, grid, p) * w[i, j, k] # C, C, C → C, C, F
end
wp = KernelComputedField(Center, Center, Center, pressure_correlation_z_ccc!, model;
field_dependencies=(w, p))
wp_2 = ComputedField(w*p)
compute!(wp)
compute!(wp_2) The outputs are correct in this case. So apparently what's causing the problem is the term CC'ing @ali-ramadhan to see if he has any ideas. |
Oh I see the problem. In this code @kernel function pressure_distribution_z_ccc!(dwpdz_ρ, grid, w, p, ρ₀)
i, j, k = @index(Global, NTuple)
wp = ℑzᵃᵃᶠ(i, j, k, grid, p) * w[i, j, k] # C, C, C → C, C, F
@inbounds dwpdz_ρ[i, j, k] = (1/ρ₀) * ∂zᵃᵃᶜ(i, j, k, grid, wp) # C, C, F → C, C, C
end the object It might work to instead pass the |
Hmm... indeed when I do it like you suggest it seems to work: @kernel function pressure_correlation_z_ccc!(dwpdz, grid, wp, ρ₀)
i, j, k = @index(Global, NTuple)
@inbounds dwpdz[i, j, k] = (1/ρ₀) * ∂zᵃᵃᶜ(i, j, k, grid, wp) # C, C, F → C, C, C
end
dwpdz_3 = KernelComputedField(Center, Center, Center, pressure_correlation_z_ccc!, model;
field_dependencies=(w*p), parameters=1024) But I don't understand why the other case doesn't work. You mentioned that Also I remember using this approach before in kernels with other properties and it seems to work in other cases. So why not here? |
This: wp = ℑzᵃᵃᶠ(i, j, k, grid, p) * w[i, j, k] is a number (the result of interpolating
|
If we take a look at those other kernels, maybe we can get to the bottom of it? |
Actually now that I'm checking my scripts, I have always differentiated arguments passed as a For my application this already solves the issue, as I can just define a vertical derivative kernel and pass the abstract operation |
Also another thought. When re-writing the script based on your suggestion I found myself writing: @kernel function ∂zᶜ!(result, grid, operand)
i, j, k = @index(Global, NTuple)
@inbounds result[i, j, k] = ∂zᵃᵃᶜ(i, j, k, grid, operand) # C, C, F → C, C, C
end
vw = @at (Center, Center, Face) w*v
dvwdz = KernelComputedField(Center, Center, Center, ∂zᶜ!, model;
field_dependencies=(vw,)) After which I immediately thought: "I thought re-wrote the operation Oceananigans.AbstractOperations.∂z!" So this to me begs the question: can these operations be generalized using |
Ahh hmm... I think you can get more diagnostics to work this way. The reason complex diagnostics fail, as discussed on #1241, is because of the recursive calls to This can be seen in the code in the crucial
I believe in this case that the function I think we could avoid some calls to |
What is the limitation you're referring to? |
I gotta be honest that whole discussion went right over my head, haha. I think mostly because I don't really understand what's the exact use of Am I correct in assuming that if I specify where each calculation is performed (by using |
I'm referring to the fact that if you calculate a new quantity inside the kernel and then try to differentiate it the differentiation will fail because the new quantity will be a number and not a field. At least that's what I understood is happening in the piece of code below based on your feedback: wp = ℑzᵃᵃᶠ(i, j, k, grid, p) * w[i, j, k] Also I'm closing the issue since my I've found a workaround to it based on your comments. |
Great! Just to clear up the conversation, I think its incorrect to refer to what we've discovered as a "limitation". Instead, we found a bug in the kernel function. The "workaround" is not a work around in the usual sense --- its just one correct way to express the intent with code. There are several other ways to write this relatively simple kernel, which may be illuminating to explore. Exploiting the fact the the derivative function can be applied to functions of the form @inline wpᵃᵃᶠ(i, j, k, grid, w, p) = @inbounds ℑzᵃᵃᶠ(i, j, k, grid, p) * w[i, j, k]
@kernel function pressure_distribution_z_ccc!(dwpdz_ρ, grid, w, p, ρ₀)
i, j, k = @index(Global, NTuple)
@inbounds dwpdz_ρ[i, j, k] = (1/ρ₀) * ∂zᵃᵃᶜ(i, j, k, grid, wpᵃᵃᶠ, w, p) # C, C, F → C, C, C
end An even more mundane to express our intent is to manually difference the product @kernel function pressure_distribution_z_ccc!(dwpdz_ρ, grid, w, p, ρ₀)
i, j, k = @index(Global, NTuple)
@inbounds wpᵃᵃᶠ_above = ℑzᵃᵃᶠ(i, j, k+1, grid, p) * w[i, j, k+1]
@inbounds wpᵃᵃᶠ_below = ℑzᵃᵃᶠ(i, j, k, grid, p) * w[i, j, k]
@inbounds dwpdz_ρ[i, j, k] = (1/ρ₀) * (wpᵃᵃᶠ_above - wpᵃᵃᶠ_below) / Δzᵃᵃᶜ(i, j, k, grid) # C, C, F → C, C, C
end Using the differencing function is probably better (its what we do in the source) because it ensures that the indexing convection is treated correctly. |
I'm encountering a weird behavior that I can't really understand. I'm trying to calculate the pressure redistribution terms for an LES using a KernelComputedField. Everything else I use a KernelComputedField in that script works. Since this is the only diagnostic that uses the pressure field I'm thinking that's the source of the problem, but I really can't understand why.
Below is a MWE:
After running this I get that the result from
dwpdz_2
is correct (which is aComputedField
), but the result fromdwpdz
(aKernelComputedField
) is not. Output from the REPL:Am I missing something here? Is computation for pressure somehow different from other variables?
Notes:
p = sum(model.pressures)
forp = model.pressures.pNHS
the result is the same.w * p
term in the kernel the result is correct! So apparently it has to do with the derivative of the pressure, not just the pressure itself.The text was updated successfully, but these errors were encountered: