Module: NumRu::GAnalysis::Planet

Defined in:
lib/numru/ganalysis/planet.rb

Overview

Library for spherical planets (thin spherical shell; default: Earth)

ASSUMPTIONS

  • longitude is assumed to increase in the eastward direction.

  • latitude is assumed to increase in the northward direction, and it is zero at the equator.

Constant Summary collapse

Earth =

< Pre-defined planets >

"Earth"
@@lonbc =

< Class variables regarding lon & lat >

GPhys::Derivative::CYCLIC_OR_LINEAR
@@lam =

@@latbc = GPhys::Derivative::LINEAR_EXT # this should be always fine

nil
@@phi =

lambda (lon in radian) obtaiend lately (see get_lambda_phi)

nil

Class Method Summary collapse

Class Method Details

.absvor_s(u, v) ⇒ Object



105
106
107
108
109
110
# File 'lib/numru/ganalysis/planet.rb', line 105

def absvor_s(u,v)
  avor = vor_s(u,v) + @@phi.sin * (2*@@Ome)
  avor.long_name = "Absolute Vorticity"
  avor.name = "avor"
  avor
end

.ave_s(s) ⇒ Object

horizontal averaging considering the spherical geometry



66
67
68
69
70
71
72
73
74
# File 'lib/numru/ganalysis/planet.rb', line 66

def ave_s(s)
  lam, phi, lond, latd  = get_lambda_phi(s)
  xmean = s.mean(lond)
  cos_phi = phi.cos

  lond,latd = find_lon_lat_dims(xmean)  # find latd again
  wgt = cos_phi / cos_phi.sum
  (xmean * wgt).sum(latd)
end

.div_s(u, v) ⇒ Object



87
88
89
90
91
92
93
94
95
96
# File 'lib/numru/ganalysis/planet.rb', line 87

def div_s(u,v)
  lam, phi, lond, latd  = get_lambda_phi(u)
  cos_phi = phi.cos
  du_dlam = u.cderiv(lond,@@lonbc,lam)
  dvc_dphi  = (v*cos_phi).cderiv(latd,latbc(phi),phi)
  rot = (du_dlam + dvc_dphi) / (@@R*cos_phi)
  rot.long_name = "div(#{u.name},#{v.name})"
  rot.name = "div"
  rot
end

.find_lon_lat_dims(gp, err_raise = false) ⇒ Object

Find longitude and latitude coordinates.

ARGUMENTS

  • gp : GPhys to inspect

  • err_raise (OPTIONAL; default:false) : if true, exception is raised if longitude or latitude coordinate is not found.

SEARCH CRITERIA (1) Find coord having units “degrees_east” (lon) or

"degrees_north" (lat)

(2) Investigate coordinate name matches (to find a lonitude coord,

/longitude/i for long_name or standard_name, or /^lon/ for name)
and match units compatible with "degrees".

RETURN VALUE

  • lond,latd
    • lond: dimension number of longitude (0,1,..) if found / nil if not found

    • latd: dimension number of latitude (0,1,..) if found / nil if not found



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/numru/ganalysis/planet.rb', line 221

def find_lon_lat_dims(gp, err_raise=false)
  lond = nil
  latd = nil
  (0...gp.rank).each do |dim|
    crd = gp.coord(dim)
    if /^degrees?_east$/i =~ crd.get_att("units")
      lond = dim
      break
    elsif ( ( /longitude/i =~ crd.long_name || 
              /^lon/i =~ crd.name ||
              (nm=crd.get_att("standard_name") && /longitude/i =~ nm ) &&
              (crd.units =~ Units["degrees_east"]) ) )
      lond = dim
      break
    end
  end
  (0...gp.rank).each do |dim|
    next if dim == lond
    crd = gp.coord(dim)
    if /^degrees?_north$/i =~ crd.get_att("units")
      latd = dim
      break
    elsif ( ( /latitude/i =~ crd.long_name || 
              /^lat/i =~ crd.name ||
              (nm=crd.get_att("standard_name") && /latitude/i =~ nm ) &&
              (crd.units =~ Units["degrees_north"]) ) )
      latd = dim
      break
    end
  end
  if err_raise
    raise("Longitude dimension was not found") if !lond
    raise("Latitude dimension was not found") if !latd
  end
  [lond,latd]
end

.get_lambda_phi(gp, err_raise = true) ⇒ Object

Find longitude and latitude coordinates and convert into radian.

RETURN VALUE

  • lam, phi, lond, latd
    • lam (GPhys): longitude in radian (lambda). (nil if not found && !err_raise)

    • phi (GPhys): latitude in radian (lambda). (nil if not found && !err_raise)

    • lond : Interger to show that longitude is the lon-th dim if found; (nil if not found && !err_raise)

    • latd : Interger to show that latitude is the lat-th dim iffound; (nil if not found && !err_raise)



188
189
190
191
192
193
194
195
196
197
# File 'lib/numru/ganalysis/planet.rb', line 188

def get_lambda_phi(gp, err_raise=true)
  lond, latd = find_lon_lat_dims(gp, err_raise)
  lam = lond && gp.axis(lond).to_gphys.convert_units("rad") # lon in rad
  lam.units = "" if lond                            # treat as non-dim
  phi = latd && gp.axis(latd).to_gphys.convert_units("rad") # lat in rad
  phi.units = "" if latd                            # treat as non-dim
  @@lam = lam
  @@phi = phi
  [lam, phi, lond, latd]
end

.grad_s(s) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
# File 'lib/numru/ganalysis/planet.rb', line 112

def grad_s(s)
  lam, phi, lond, latd  = get_lambda_phi(s)
  cos_phi = phi.cos
  xs = s.cderiv(lond,@@lonbc,lam) / (@@R*cos_phi)
  ys = s.cderiv(latd,latbc(phi),phi) / @@R
  xs.long_name = "xgrad(#{s.name})"
  xs.name = "xgrad"
  ys.long_name = "ygrad(#{s.name})"
  ys.name = "ygrad"
  [xs,ys]
end

.grad_sx(s) ⇒ Object



124
125
126
127
128
129
130
131
# File 'lib/numru/ganalysis/planet.rb', line 124

def grad_sx(s)
  lam, phi, lond, latd  = get_lambda_phi(s)
  cos_phi = phi.cos
  xs = s.cderiv(lond,@@lonbc,lam) / (@@R*cos_phi)
  xs.long_name = "xgrad(#{s.name})"
  xs.name = "xgrad"
  xs
end

.grad_sy(s) ⇒ Object



133
134
135
136
137
138
139
140
# File 'lib/numru/ganalysis/planet.rb', line 133

def grad_sy(s)
  lam, phi, lond, latd  = get_lambda_phi(s)
  cos_phi = phi.cos
  ys = s.cderiv(latd,latbc(phi),phi) / @@R
  ys.long_name = "ygrad(#{s.name})"
  ys.name = "ygrad"
  ys
end

.grad_sy_cosphifact(s, cosphi_exponent) ⇒ Object



142
143
144
145
146
147
148
149
150
# File 'lib/numru/ganalysis/planet.rb', line 142

def grad_sy_cosphifact(s,cosphi_exponent)
  lam, phi, lond, latd  = get_lambda_phi(s)
  cos_phi = phi.cos
  cos_phi_factor = cos_phi**cosphi_exponent
  ys = (s*cos_phi_factor).cderiv(latd,latbc(phi),phi)/cos_phi_factor / @@R
  ys.long_name = "ygrad(#{s.name})"
  ys.name = "ygrad"
  ys
end

.init(planet) ⇒ Object



19
20
21
22
23
24
25
26
27
# File 'lib/numru/ganalysis/planet.rb', line 19

def init(planet)
  case planet
  when Earth
    @@R = UNumeric[6.37e6, "m"]
    @@Ome = UNumeric[2*Math::PI/8.64e4,"s-1"]
  else
    raise "Unsupported predefined planet: #{planet}."
  end
end

.latbc(phi) ⇒ Object

< Differentian at the planets’s near surface. With suffix “_s” >



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/numru/ganalysis/planet.rb', line 48

def latbc(phi)
=begin
  # not so good
  pi2 = Math::PI/2
  eps = 0.1
  xs = phi[0..1].val 
  xe = phi[-2..-1].val
  if (pi2-xs[0].abs) / (xs[0]-xs[1]).abs < eps and
     (pi2-xe[-1].abs) / (xe[-1]-xe[-2]).abs < eps 
    GPhys::Derivative::MIRROR_B
  else
    GPhys::Derivative::LINEAR_EXT
  end
=end
  GPhys::Derivative::LINEAR_EXT
end

.omegaObject



36
# File 'lib/numru/ganalysis/planet.rb', line 36

def omega; @@Ome; end

.omega=(o) ⇒ Object



34
# File 'lib/numru/ganalysis/planet.rb', line 34

def omega=(o);  @@Ome = o; end

.radiusObject



35
# File 'lib/numru/ganalysis/planet.rb', line 35

def radius; @@R; end

.radius=(r) ⇒ Object

< Adjustable planetary settings >



33
# File 'lib/numru/ganalysis/planet.rb', line 33

def radius=(r); @@R = r; end

.rot_s(u, v) ⇒ Object



76
77
78
79
80
81
82
83
84
85
# File 'lib/numru/ganalysis/planet.rb', line 76

def rot_s(u,v)
  lam, phi, lond, latd  = get_lambda_phi(u)
  cos_phi = phi.cos
  dv_dlam = v.cderiv(lond,@@lonbc,lam)
  duc_dphi  = (u*cos_phi).cderiv(latd,latbc(phi),phi)
  rot = (dv_dlam - duc_dphi) / (@@R*cos_phi)
  rot.long_name = "rot(#{u.name},#{v.name})"
  rot.name = "rot"
  rot
end

.vor_s(u, v) ⇒ Object



98
99
100
101
102
103
# File 'lib/numru/ganalysis/planet.rb', line 98

def vor_s(u,v)
  vor = rot_s(u,v)
  vor.long_name = "Relative Vorticity"
  vor.name = "vor"
  vor
end

.weight_cosphi(s, cos_exp, r_exp) ⇒ Object



159
160
161
162
163
164
# File 'lib/numru/ganalysis/planet.rb', line 159

def weight_cosphi(s, cos_exp, r_exp)
  lam, phi, lond, latd  = get_lambda_phi(s)
  cos_phi = phi.cos
  ys = s * (cos_phi**cos_exp * @@R**r_exp)
  ys
end

.weight_sinphi(s, sin_exp, r_exp) ⇒ Object



166
167
168
169
170
171
# File 'lib/numru/ganalysis/planet.rb', line 166

def weight_sinphi(s, sin_exp, r_exp)
  lam, phi, lond, latd  = get_lambda_phi(s)
  sin_phi = phi.sin
  ys = s * (sin_phi**sin_exp * @@R**r_exp)
  ys
end

.weight_tanphi(s, tan_exp, r_exp) ⇒ Object



152
153
154
155
156
157
# File 'lib/numru/ganalysis/planet.rb', line 152

def weight_tanphi(s, tan_exp, r_exp)
  lam, phi, lond, latd  = get_lambda_phi(s)
  tan_phi = phi.tan
  ys = s * (tan_phi**tan_exp * @@R**r_exp)
  ys
end