GithubHelp home page GithubHelp logo

Comments (13)

giordano avatar giordano commented on July 28, 2024 1

It's currently implemented solely with spherical harmonics coefficients in mind and for those prod(A) then returns the product of the coefficients, I actually like that. Or in more general terms: it does return the product of the lower triangular of the matrix. This could also be intended.

But that's a different operation than the product of all the elements of an array. Changing the semantic of a function can cause surprising and confusing results.

from speedyweather.jl.

maximilian-gelbrecht avatar maximilian-gelbrecht commented on July 28, 2024 1

I give up. No helpful replies on Slack and I tried a lot of different variations of what's given in the manual. Doesn't seem to work.

So I'd change it to AbstractVector

@milankl The printing / show will be no problem to adjust. There are one or two routines that need slight adjustment that assume LowerTriangularMatrix <: AbstractMatrix, but not many. Are there any other things that might need adjustment as soon as all tests pass?

Overall there a few routines that allow spectral input to be an AbstractMatrix. Personally, I would just require that all spectral input needs to be LowerTriangularMatrix. What do you think?

from speedyweather.jl.

maximilian-gelbrecht avatar maximilian-gelbrecht commented on July 28, 2024 1

In case we ever come back to this, to remind myself and archive it, this was my best effort so far:

# Broadcasting 

import Base.BroadcastStyle, Base.similar

struct LowerTriangularStyle <: Broadcast.AbstractArrayStyle{1} end

Base.BroadcastStyle(::Type{<:LowerTriangularMatrix}) = LowerTriangularStyle()

Base.similar(bc::Broadcast.Broadcasted{LowerTriangularStyle}, ::Type{ElType}) where ElType = similar(LowerTriangularMatrix{Eltype}, axes(bc))

LowerTriangularStyle(::Val{0}) = LowerTriangularStyle()
LowerTriangularStyle(::Val{1}) = LowerTriangularStyle()
LowerTriangularStyle(::Val{2}) = LowerTriangularStyle()

No errors, just the same wrong results

from speedyweather.jl.

milankl avatar milankl commented on July 28, 2024

@giordano just raised another related issue

julia> A = LowerTriangularMatrix(rand(3,3))
3×3 LowerTriangularMatrix{Float64}:
 0.382579  0.0       0.0
 0.554634  0.779331  0.0
 0.453919  0.236713  0.559563

julia> sum(A)
2.966738421294002

julia> prod(A)
0.009942566052321158

The sum is correct, but the product should obviously be zero.

from speedyweather.jl.

maximilian-gelbrecht avatar maximilian-gelbrecht commented on July 28, 2024

@giordano just raised another related issue

julia> A = LowerTriangularMatrix(rand(3,3))
3×3 LowerTriangularMatrix{Float64}:
 0.382579  0.0       0.0
 0.554634  0.779331  0.0
 0.453919  0.236713  0.559563

julia> sum(A)
2.966738421294002

julia> prod(A)
0.009942566052321158

The sum is correct, but the product should obviously be zero.

Is it a bug or a feature?

It's currently implemented solely with spherical harmonics coefficients in mind and for those prod(A) then returns the product of the coefficients, I actually like that. Or in more general terms: it does return the product of the lower triangular of the matrix. This could also be intended.

If the product of the full matrix is meant, yes of course that's always zero, but then one could also just add

Base.prod(A::LowerTriangularMatrix{T}) where T = zero(T)

from speedyweather.jl.

maximilian-gelbrecht avatar maximilian-gelbrecht commented on July 28, 2024

To original problem: I never customised broadcast before. But something like broadcast!(*,A,....) = broadcast!(*,A.data,..) could maybe work. So "forwarding" all critical broadcast operations to the actual vector with the data. I had no time to test this (yet)

from speedyweather.jl.

maximilian-gelbrecht avatar maximilian-gelbrecht commented on July 28, 2024

There are also BroadcastStyles and more specifically, ArrayStyle and DefaultArrayStyle{N}. Because essentially, we have a 2D array that should broadcast like a 1D Array.

Here's the manual on it

PS: It's still fascinating to me how customizable Julia is

I made a quick attempt and just added

Base.BroadcastStyle(::Type{<:LowerTriangularMatrix}) = Broadcast.DefaultArrayStyle{1}

but that's not working, we'll have to look a bit deeper into that.

Your suspicion about the created Matrix should be correct though, as the manual states, this is indeed the default fallback. But the Base.similar(bc::Broadcasted{DestStyle}, ::Type{ElType}) is also customizable.

from speedyweather.jl.

maximilian-gelbrecht avatar maximilian-gelbrecht commented on July 28, 2024

Rename LowerTriangularMatrix to SphericalHarmonicsCoefficients and the current product would be correct ;)

But whatever, I have no strong feelings about this. Add

Base.prod(A::LowerTriangularMatrix{T}) where T = zero(T)

and you have the correct answer for the full 2D matrix that's consistent with using them for general purposes.

I'll have a bit further look in the broadcasting issue in the next days.

from speedyweather.jl.

maximilian-gelbrecht avatar maximilian-gelbrecht commented on July 28, 2024

So, a hacky way to fix it, is just to make LowerTriangularMatrix a subtype of AbstractVector instead of AbstractMatrix. Then, the MWE in the OP works. The 2D indexing also still works, obviously it is not a subtype of AbstractMatrix in this case, so functions that assume that would need to be changed.

For a way how to fix this and keep it a subtype of AbstractMatrix, one would need to specialise

Base.BroadcastStyle(::Type{SrcType}) = SrcStyle()
and
Base.similar(bc::Broadcasted{DestStyle}, ::Type{ElType})

The manual gives one concrete example for this, but especially for the Base.similar I don't quite get it how to generalise this.

from speedyweather.jl.

milankl avatar milankl commented on July 28, 2024

Thanks for looking into this!

So, a hacky way to fix it, is just to make LowerTriangularMatrix a subtype of AbstractVector instead of AbstractMatrix.

I tried that earlier, and thought it was a good idea as 2D indexing then comes as a bonus rather than assumed to exist. However, I ran into even more problems down the line, which gave me the feeling that <:AbstractMatrix is better. I don't have hard feelings on this and believe both is possible; both will come with advantages and disadvantages, but it's hard to foresee the consequences.

I'd suggest to try first changing the broadcasting and if that imposes even bigger obstacles then we can try <:AbstractVector again?!

from speedyweather.jl.

milankl avatar milankl commented on July 28, 2024

I've added a method like

function gridded(   alms::AbstractMatrix,       # spectral coefficients
                    S::SpectralTransform{NF},   # struct for spectral transform parameters
                    ) where NF                  # number format NF
 
    map = zeros(S.Grid{NF},S.nresolution)               # preallocate output
    almsᴸ = LowerTriangularMatrix{Complex{NF}}(alms)    # drop the upper triangle and convert to NF
    gridded!(map,almsᴸ,S)                               # now execute the in-place version
    return map
end

So that someone can also come with a Matrix of coefficients without the need to do LowerTriangularMatrix(::Matrix) first. So the ::AbstractMatrix here isn't an issue and we'd only need to do vec(alms) inside the function body.

from speedyweather.jl.

milankl avatar milankl commented on July 28, 2024

Thanks for trying!! Then let's do <:AbstractVector and proceed. I feel like we've already spent too much time on this ;)

from speedyweather.jl.

milankl avatar milankl commented on July 28, 2024

The only request I have it that we retain show similar to this

julia> rand(LowerTriangularMatrix,4,4)
4×4 LowerTriangularMatrix{Float64}:
 0.0025516  0.0        0.0        0.0
 0.2128     0.906056   0.0        0.0
 0.589329   0.0822436  0.0122374  0.0
 0.865687   0.838233   0.741264   0.685711

As otherwise troubleshooting with spectral fields isn't easy...

from speedyweather.jl.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.