GithubHelp home page GithubHelp logo

Comments (7)

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

it should also work to just extend ∇²! shouldn't it?

function ∇²!(   ∇²alms::LowerTriangularMatrix{Complex{NF}}, # Output: Laplacian of alms
                alms::LowerTriangularMatrix{Complex{NF}},   # Input: spectral coefficients
                S::SpectralTransform{NF};                   # precomputed eigenvalues
                add::Bool=false,                            # add to output array or overwrite
                flipsign::Bool=false,                       # -∇² or ∇²
                inverse::Bool=false                        # ∇⁻² or ∇²
                ) where {NF<:AbstractFloat}

    @boundscheck size(alms) == size(∇²alms) || throw(BoundsError)
    lmax,mmax = size(alms) .- (2,1)     # degree l, order m of the Legendre polynomials
    
    @unpack eigenvalues = S
    eigenvalues = inverse ? inv.(eigenvalues) : eigenvalues 
    @boundscheck length(eigenvalues) >= lmax+1 || throw(BoundsError)

    kernel(o,a) = flipsign ? (add ? (o-a) : -a) :
                             (add ? (o+a) :  a)    

    lm = 0
    @inbounds for m in 1:mmax+1     # order m = 0:mmax but 1-based
        for l in m:lmax+1           # degree l = m:lmax but 1-based
            lm += 1
            ∇²alms[lm] = kernel(∇²alms[lm],alms[lm]*eigenvalues[l])
        end
        lm += 1
    end

    return ∇²alms
end

I didn't test it, though

from speedyweather.jl.

milankl avatar milankl commented on July 28, 2024

Yes, we can make that functional again. UV_from_vor! or UV_from_vordiv! invert the Laplacian and take the gradients (nabla in the former, rotated nabla + nabla in the latter) in one go (which is faster and more memory efficient). In the following diagram you basically jump directly from vor (,div) to U,V without explicitly calculating stream function or velocity potential.

image

I don't think it's necessary to use precalculated eigenvalues, as they are so simple, so I'd probably drop ::SpectralTransform as an argument. Which methods do you need

  • ∇⁻²(::AbstractMatrix)
  • ∇⁻²(::LowerTriangularMatrix)
  • ∇⁻²!(::AbstractMatrix,::AbstractMatrix)
  • ∇⁻²!(::LowerTriangularMatrix,::LowerTriangularMatrix)
  • ...?

from speedyweather.jl.

milankl avatar milankl commented on July 28, 2024

I know the documentation is far from up to date, but at least that is already described

https://milankl.github.io/SpeedyWeather.jl/dev/spectral_transform/#U,V-from-vorticity-and-divergence

from speedyweather.jl.

milankl avatar milankl commented on July 28, 2024

Yes, good idea, I didn't realise I had already written ∇²! with a kernel. With #142 I decided to externalise the kernel such that we can also define ∇⁻² which might be nice to avoid confusion? And I didn't like the inv.(eigenvalues) as it would allocate memory ;)

from speedyweather.jl.

milankl avatar milankl commented on July 28, 2024

Oh we could also leave the kernel inside and define ∇⁻²!(...) = ∇²!(....;inverse=true) true yeah I don't know whether it makes a difference

from speedyweather.jl.

milankl avatar milankl commented on July 28, 2024

Internalised kernel is committed now, interestingly for 3x ?-clauses in a function you need to @inline them otherwise you get a 10x performance penalty...

    @inline kernel(o,a,b) = inverse ?   (flipsign ? (add ? (o - a/b) : -a/b)  :
                                                    (add ? (o + a/b) :  a/b)) :
                                        (flipsign ? (add ? (o - a*b) : -a*b)  :
                                                    (add ? (o + a*b) :  a*b))

from speedyweather.jl.

milankl avatar milankl commented on July 28, 2024

For the record, writing a kernel like this

    # use eigenvalues⁻¹/eigenvalues for ∇⁻²/∇² based but name both eigenvalues
    eigenvalues = inverse ? S.eigenvalues⁻¹ : S.eigenvalues
    @boundscheck length(eigenvalues) >= lmax+1 || throw(BoundsError)

    @inline kernel(o,a) = flipsign ? (add ? (o-a) : -a)  :
                                     (add ? (o+a) :  a)

    lm = 0
    @inbounds for m in 1:mmax+1     # order m = 0:mmax but 1-based
        for l in m:lmax+1           # degree l = m:lmax but 1-based
            lm += 1
            ∇²alms[lm] = kernel(∇²alms[lm],alms[lm]*eigenvalues[l])
        end
    end

Gives the same speed as hardcoding +=, -=, = +, = - (and same for inverse). The @inline is technically not necessary, but using 3x ? will not inline that function automatically. I suspect as the speed is the same, this is actually directly compiled to the same code -- at least on my hardware.

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.