Source code for epygram.geometries.V1DGeometry

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
V1DGeometry:

Contains the classe for Vertical 1D geometry of fields.
"""

from footprints import FootprintBase, FPDict

from epygram import profiles, epygramError, config
from epygram.util import RecursiveObject



[docs]class V1DGeometry(RecursiveObject, FootprintBase): """ Handles the geometry for a Vertical 1-Dimension Field (column). Here, the grid defines the vertical position of each level between a bottom and a top positions. The position of points w/r to the vertical grid (mass or flux points), is interpreted as:\n - mass: points are located on same levels as the grid points. - flux: points are located on half-levels, hence are N+1. """ _collector = ('geometry',) _footprint = dict( attr=dict( structure=dict( values=set(['V1D'])), coordinate=dict( values=set(['hybrid_pressure', 'hybrid_height', 'pressure', 'altitude', 'height', 'potential_vortex'])), grid=dict( type=FPDict, info="Handles description of the vertical grid."), hlocation=dict( type=FPDict, optional=True, info="Handles horizontal location of the column."), position_on_grid=dict( optional=True, info="Position of points w/r to the vertical grid.", values=set(['mass', 'flux']), default='mass') ) )
[docs] def hybridP2pressure(self, Psurf, gridposition=None): """ Converts a hybrid_pressure coordinate grid into pressure. *Psurf* is the surface pressure, needed for integration of Ai and Bi. If *gridposition* is given ('mass' or 'flux'), the target grid is computed accordingly. If not, the pressures are computed at the hybrid-pressure gridposition (i.e. flux generally). """ if self.grid['gridposition'] != 'flux': raise NotImplementedError('A and B must define flux levels') if gridposition == None: gridposition = self.grid['gridposition'] # compute pressures A = self.grid['levels']['Ai'] B = self.grid['levels']['Bi'] if gridposition == 'mass': P = profiles.hybridpressureAB2masspressure(A, B, Psurf) elif gridposition == 'flux': P = profiles.hybridpressureAB2fluxpressure(A, B, Psurf) else: raise epygramError("gridposition != 'mass' or 'flux'.") # and update info self._attributes['coordinate'] = 'pressure' self._attributes['grid']['gridposition'] = gridposition self._attributes['grid']['levels'] = tuple(P)
[docs] def hybridP2altitude(self, R, T, Psurf, Pdep=0., Phi_surf=0.): """ Converts a hybrid_pressure coordinate grid into altitude of mass levels. - *R* is the profile of specific gas constant (J/kg/K). - *T* is the profile of temperature (K). - *Psurf* is the surface pressure, needed for integration of Ai and Bi. - *Pdep* is the optional profile of NH pressure departures. - *Phi_surf* is the optional surface geopotential. If given, the final coordinate is altitude above sea level, else height above ground surface. """ A = self.grid['levels']['Ai'] B = self.grid['levels']['Bi'] if self.grid['gridposition'] == 'flux': # compute alt alt = profiles.hybridpressureAB2altitude(A, B, R, T, Psurf=Psurf, Pdep=Pdep, Phi_surf=Phi_surf, Ptop=config.default_Ptop) # and update info if abs(Phi_surf) < config.epsilon: self._attributes['coordinate'] = 'height' self._attributes['grid']['levels'] = tuple(alt) else: self._attributes['coordinate'] = 'altitude' self._attributes['grid']['levels'] = tuple(alt) self._attributes['grid']['gridposition'] = 'mass' elif self.grid['gridposition'] == 'mass': raise NotImplementedError("hybrid-pressure grid at mass-levels.")
[docs] def hybridH2altitude(self, Zsurf, gridposition=None, conv2height=False): """ Converts a hybrid_height coordinate grid into altitude. *Zsurf* is the surface pressure, needed for integration of Ai and Bi. If *gridposition* is given ('mass' or 'flux'), the target grid is computed accordingly. If not, the altitudes are computed at the hybrid-height gridposition (i.e. flux generally). If conv2height is True, conversion into height is performed instead of altitude. """ if self.grid['gridposition'] != 'flux': raise NotImplementedError('A and B must define flux levels') if gridposition == None: gridposition = self.grid['gridposition'] # compute altitudes A = self.grid['levels']['Ai'] B = self.grid['levels']['Bi'] if gridposition == 'mass': Z = profiles.hybridheightAB2massheight(A, B, Zsurf, conv2height=conv2height) elif gridposition == 'flux': Z = profiles.hybridheightAB2fluxheight(A, B, Zsurf, conv2height=conv2height) else: raise epygramError("gridposition != 'mass' or 'flux'.") # and update info self._attributes['coordinate'] = 'height' if conv2height else 'altitude' self._attributes['grid']['gridposition'] = gridposition self._attributes['grid']['levels'] = tuple(Z)
[docs] def pressure2altitude(self, R, T, Pdep=0., Phi_surf=0.): """ Converts a pressure coordinate grid (on mass or flux levels) to altitude on mass levels). - *R* is the profile of specific gas constant (J/kg/K). - *T* is the profile of temperature (K). - *Pdep* is the optional profile of NH pressure departures. - *Phi_surf* is the optional surface geopotential. If given, the final coordinate is altitude above sea level, else height above ground surface. """ if self.grid['gridposition'] == 'flux': # compute alt alt = profiles.pressure2altitude(R, T, pi_tilde=self.grid['levels'], Pdep=Pdep, Phi_surf=Phi_surf) elif self.grid['gridposition'] == 'mass': # compute alt alt = profiles.pressure2altitude(R, T, pi=self.grid['levels'], Pdep=Pdep, Phi_surf=Phi_surf) # and update info if abs(Phi_surf) < config.epsilon: self._attributes['coordinate'] = 'height' self._attributes['grid']['levels'] = tuple(alt) else: self._attributes['coordinate'] = 'altitude' self._attributes['grid']['levels'] = tuple(alt) self.grid['gridposition'] = 'mass' del self._attributes['grid']['levels']