Module: NumRu::GAnalysis::SphHarmonicIsoG
- Defined in:
- lib/numru/ganalysis/sph_harmonic_iso_g.rb
Overview
Spherical harmonics library for equally spaced lon-lat grids using SHTLIB in DCL
REQUIREMENT
-
This module can handle grid data that satisfy the following
-
dimension 0 (first dim) is longitude, dimension 1 is latitude.
-
must be equally spaced and cover the globe such as lon = 0, 2,.., 358 [,360], or -180, -170,..,170 [,180]. etc (in increasing order; cyclic extension is applied internally) and lat = -90,-88,..,90. (or 90, 98,..,-90; pole to pole)
-
-
Data missig is not allowed
Constant Summary collapse
- @@work =
@@im = @@jm = @@mm = nil
Class Method Summary collapse
- .__factor_n_m(&factor_n_m) ⇒ Object
-
.check_and_init(gphys, mm) ⇒ Object
Check the valdity of the lon-lat grid.
-
.div_h(u, v, mm, radius = 1.0, &factor_n_m) ⇒ Object
Horizontal divergence on the sphere.
-
.filt(gp, mm, deriv = nil, lap = nil, &factor_n_m) ⇒ Object
Spherical harmonics filter.
-
.lapla_h(gp, mm, radius = 1.0, order = 1) ⇒ Object
Horizontal Laplacian on the sphere.
- .loop_for_3rd_or_greater_dim(shape, &block) ⇒ Object
-
.rot_h(u, v, mm, radius = 1.0, &factor_n_m) ⇒ Object
Horizontal rotation on the sphere.
- .xgrad(gp, mm, &factor_n_m) ⇒ Object (also: xdiv)
- .ydiv(gp, mm, &factor_n_m) ⇒ Object
- .ygrad(gp, mm, &factor_n_m) ⇒ Object
Class Method Details
.__factor_n_m(&factor_n_m) ⇒ Object
195 196 197 198 199 200 201 202 203 204 |
# File 'lib/numru/ganalysis/sph_harmonic_iso_g.rb', line 195 def __factor_n_m( &factor_n_m ) ms = DCLExt.sht_get_m(@@mm) ns = DCLExt.sht_get_n(@@mm) len = ms.length f = NArray.float(len) for i in 0...len f[i] = factor_n_m.call(ns[i],ms[i]) end f end |
.check_and_init(gphys, mm) ⇒ Object
Check the valdity of the lon-lat grid.
This method raises an exception if the data is not acceptable
ARGUMENTS
-
gp [GPhys] : data to check its grid
-
mm [Integer] : truncation wavenumber
RETURN VALUE
-
gphys [GPhys] : same as input, but for the 1st dim is cyclically extended if needed.
-
np2sp [true or false] : true if data is N.pole to S.pole, false if data is S.pole to N.pole
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/numru/ganalysis/sph_harmonic_iso_g.rb', line 36 def check_and_init(gphys, mm) raise(ArgumentError, "Invalid rank (#{gphys.rank})") if gphys.rank < 2 lon = gphys.coord(0).val if lon[0] > lon[-1] raise ArgumentError, "Longitude must be in the increasing order." end gphys = gphys.cyclic_ext(0) lat = gphys.coord(1).convert_units("degrees").val eps = 0.1 if (lat[0]-90.0).abs < eps && (lat[-1]+90.0).abs < eps # N.pole to S.pole np2sp = true elsif (lat[0]+90.0).abs > eps || (lat[-1]-90.0).abs > eps raise ArgumentError, "Not pole to pole: #{lat[0]..lat[-1]}." else np2sp = false end nx, ny, = gphys.shape im = (nx-1)/2 jm = (ny-1)/2 if (mm+1)/2 > jm || mm+1 > im raise(ArgumentError,"mm=#{mm} is too big for im=#{im} & jm=#{jm}") end if @@work.nil? || @@mm != mm || @@jm != jm || @@im != im @@work = DCL.shtint(mm,jm,im) @@mm = mm @@jm = jm @@im = im end [gphys, np2sp] end |
.div_h(u, v, mm, radius = 1.0, &factor_n_m) ⇒ Object
Horizontal divergence on the sphere
ARGUMENTS
-
u,v [GPhys] : the x and y components to take divergence
-
mm [Integer] : truncation wavenumber
-
radius (optional; defaut=1.0) [Numeric(if non-dim) or UNumeric] radius of the sphere
173 174 175 176 177 178 179 |
# File 'lib/numru/ganalysis/sph_harmonic_iso_g.rb', line 173 def div_h(u,v, mm, radius=1.0, &factor_n_m ) gp = xdiv(u, mm, &factor_n_m) + ydiv(v, mm, &factor_n_m) gp *= radius**(-1) if radius != 1.0 gp.long_name = "div_h(#{u.name},#{v.name})" gp.name = "div_h" gp end |
.filt(gp, mm, deriv = nil, lap = nil, &factor_n_m) ⇒ Object
Spherical harmonics filter
ARGUMENTS
-
gp [GPhys] : grid data to filter (lon,lat,…: rank >= 2)
-
mm [Integer] : truncation wavenumber
-
deriv (optional) [nil(default) or Symbol] (let lambda be longitude and phi be latitude) if :xgrad (or :xdiv), applies del / cosphi dellambda, if :ygrad, applies del / delphi, if :ydiv, applies del cosphi / cosphi delphi.
-
lap (optional) [nil(default) or Integer] If 1, laplacian is taken; if -1 inverserser laplacian is taken – note that you can also explitly take laplacian by using the factor_n_m block (see below).
-
factor_n_m (optional block) spectral filter in the form of {|n,m| } that returns the factor if n and m are integers. Example {|n,m| -n*(n+1)} to take laplacian.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/numru/ganalysis/sph_harmonic_iso_g.rb', line 92 def filt( gp, mm, deriv=nil, lap=nil, &factor_n_m ) iswg2s = isws2g = 0 case deriv when :xgrad, :xdiv isws2g = -1 #when :xderiv ##(horinout, developpers memo: just multiply with cos\phi afterward) # iswg2s = -1 # don't know if isws2g is better # raise("Under development: need cos_phi factor") when :ygrad isws2g = 1 when :ydiv iswg2s = 1 when nil # do nothing else raise ArgumentError,"Unsupported operation #{deriv}" end nlon = gp.shape[0] gp, np2sp = check_and_init(gp, mm) # sets @@work, @@mm, @@im & @@jm na = gp.val na = na.to_na if na.respond_to?(:to_na) # for NArrayMiss shape = na.shape naf = NArray.float( *shape ) # output variable (filtered NArray) f = __factor_n_m( &factor_n_m ) if factor_n_m loop_for_3rd_or_greater_dim(shape){|sel| w,s = DCL.shtg2s(@@mm,iswg2s,na[*sel],@@work) s = DCL.shtlap(@@mm,lap,s) if lap s = s * f if factor_n_m s = -s if np2sp && (isws2g==1 || iswg2s==1 ) # y-reversed --> *(-1) w,g = DCL.shts2g(@@mm,@@jm,@@im,isws2g,s,@@work) naf[*sel] = g } vaf = VArray.new(naf, gp.data, gp.name) gp = GPhys.new( gp.grid, vaf) if gp.shape[0] != nlon # cyclically extended --> trim it to the original shape gp = gp[0...nlon,false] end gp end |
.lapla_h(gp, mm, radius = 1.0, order = 1) ⇒ Object
Horizontal Laplacian on the sphere
-
gp [GPhys] : grid data (lon,lat,…: rank >= 2)
-
mm [Integer] : truncation wavenumber
-
radius (optional; defaut=1.0) [Numeric(if non-dim) or UNumeric] radius of the sphere
153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/numru/ganalysis/sph_harmonic_iso_g.rb', line 153 def lapla_h( gp, mm, radius=1.0, order=1 ) if order==-1 || order==1 gp = filt( gp, mm, nil, order ) elsif order > 0 gp = filt( gp, mm ){|n,m| (-n*(n+1))**order } else # negative --> avoid zero division gp = filt( gp, mm ){|n,m| n==0 ? 0 : (-n*(n+1))**order } end gp *= radius**(-2) if radius != 1.0 gp end |
.loop_for_3rd_or_greater_dim(shape, &block) ⇒ Object
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/numru/ganalysis/sph_harmonic_iso_g.rb', line 206 def loop_for_3rd_or_greater_dim(shape,&block) raise(ArgumentError, "block not given") if !block sh3 = shape[2..-1] rank3 = sh3.length csh3 = [1] (1...rank3).each{|d| csh3[d] = sh3[d-1]*csh3[d-1]} len = 1 sh3.each{|n| len *= n} for i in 0...len sel = [true,true] (0...rank3).each do |d| sel.push( (i/csh3[d]) % sh3[d] ) end block.call(sel) end end |
.rot_h(u, v, mm, radius = 1.0, &factor_n_m) ⇒ Object
Horizontal rotation on the sphere
-
u,v [GPhys] : the x and y components to take rotation
-
mm [Integer] : truncation wavenumber
-
radius (optional; defaut=1.0) [Numeric(if non-dim) or UNumeric] radius of the sphere
187 188 189 190 191 192 193 |
# File 'lib/numru/ganalysis/sph_harmonic_iso_g.rb', line 187 def rot_h(u,v, mm, radius=1.0, &factor_n_m ) gp = xdiv(v, mm, &factor_n_m) - ydiv(u, mm, &factor_n_m) gp *= radius**(-1) if radius != 1.0 gp.long_name = "rot_h(#{u.name},#{v.name})" gp.name = "rot_h" gp end |
.xgrad(gp, mm, &factor_n_m) ⇒ Object Also known as: xdiv
134 135 136 |
# File 'lib/numru/ganalysis/sph_harmonic_iso_g.rb', line 134 def xgrad( gp, mm, &factor_n_m ) filt( gp, mm, :xgrad, &factor_n_m ) end |
.ydiv(gp, mm, &factor_n_m) ⇒ Object
143 144 145 |
# File 'lib/numru/ganalysis/sph_harmonic_iso_g.rb', line 143 def ydiv( gp, mm, &factor_n_m ) filt( gp, mm, :ydiv, &factor_n_m ) end |
.ygrad(gp, mm, &factor_n_m) ⇒ Object
140 141 142 |
# File 'lib/numru/ganalysis/sph_harmonic_iso_g.rb', line 140 def ygrad( gp, mm, &factor_n_m ) filt( gp, mm, :ygrad, &factor_n_m ) end |