# Master dictionary containing all field identifiers known to CliMT # with corresponding long names, units and nominal rank KnownFields = {} KnownFields['ps'] = ['surface pressure', 'mb', '2D'] KnownFields['Ts'] = ['surface temperature', 'K', '2D'] KnownFields['zen'] = ['solar zenith angle', 'deg', '2D'] KnownFields['solin'] = ['insolation', 'W m-2', '2D'] KnownFields['flus'] = ['surface upwelling LW', 'W m-2', '2D'] KnownFields['asdif'] = ['diffuse SW albedo', '-', '2D'] KnownFields['asdir'] = ['direct SW albedo', '-', '2D'] KnownFields['aldif'] = ['diffuse LW albedo', '-', '2D'] KnownFields['aldir'] = ['diffuse LW albedo', '-', '2D'] KnownFields['SrfSenFlx'] = ['surface sensible heat flux', 'W m-2', '2D'] KnownFields['SrfLatFlx'] = ['surface latent heat flux', 'W m-2', '2D'] KnownFields['taux'] = ['surface zonal windstress', 'Pa', '2D'] KnownFields['tauy'] = ['surface merid windstress', 'Pa', '2D'] KnownFields['SrfRadFlx'] = ['net surface radiative flux', 'W m-2', '2D'] KnownFields['SwToa'] = ['net top-of-atmos SW flux', 'W m-2', '2D'] KnownFields['LwToa'] = ['net top-of-atmos LW flux', 'W m-2', '2D'] KnownFields['SwSrf'] = ['net surface SW flux', 'W m-2', '2D'] KnownFields['LwSrf'] = ['net surface LW flux', 'W m-2', '2D'] KnownFields['SwToaCf'] = ['top-of-atmos SW cloud forc', 'W m-2', '2D'] KnownFields['LwToaCf'] = ['top-of-atmos LW cloud forc', 'W m-2', '2D'] KnownFields['SwSrfCf'] = ['surface SW cloud forc', 'W m-2', '2D'] KnownFields['LwSrfCf'] = ['surface LW cloud forc', 'W m-2', '2D'] KnownFields['cbmf'] = ['cloud base mass flux', 'kg s-1', '2D'] KnownFields['precc'] = ['convective precip rate', 'mm day-1', '2D'] KnownFields['Tsdot'] = ['surface heating rate', 'K s-1', '2D'] KnownFields['p'] = ['atmospheric pressure', 'mb', '3D'] KnownFields['dp'] = ['level thickness', 'mb', '3D'] KnownFields['T'] = ['atmospheric temperature', 'K', '3D'] KnownFields['theta'] = ['potential temperature', 'K', '3D'] KnownFields['Te'] = ['target temp, Newt. cooling', 'K', '3D'] KnownFields['q'] = ['specific humidity', 'g kg-1', '3D'] KnownFields['U'] = ['zonal wind', 'm s-1', '3D'] KnownFields['V'] = ['meridional wind', 'm s-1', '3D'] KnownFields['W'] = ['pressure velocity', 'Pa s-', '3D'] KnownFields['psi'] = ['streamfunction', 'm Pa s-1', '3D'] KnownFields['cldf'] = ['cloud fraction', '-', '3D'] KnownFields['ciwp'] = ['cloud liquid water path', 'g m-2', '3D'] KnownFields['clwp'] = ['cloud liquid water path', 'g m-2', '3D'] KnownFields['r_liq'] = ['Effective radius, liquid drop','micron', '3D'] KnownFields['r_ice'] = ['Effective radius, ice drop','micron', '3D'] KnownFields['o3'] = ['ozone mass mix. ratio', 'kg kg-1', '3D'] KnownFields['swflx'] = ['SW radiative flux', 'W m-2', '3D'] KnownFields['lwflx'] = ['LW radiative flux', 'W m-2', '3D'] KnownFields['lwup'] = ['upward LW radiative flux', 'W m-2', '3D'] KnownFields['lwdown'] = ['downward LW radiative flux', 'W m-2', '3D'] KnownFields['swhr'] = ['SW heating rate', 'K day-1', '3D'] KnownFields['lwhr'] = ['LW heating rate', 'K day-1', '3D'] KnownFields['lwtau'] = ['Broadband LW optical depth', '-', '3D'] KnownFields['TdotDyn'] = ['dynamical heating rate', 'K day-1', '3D'] KnownFields['TdotRad'] = ['net radiative heating rate', 'K day-1', '3D'] KnownFields['TdotTurb'] = ['turbulent heating rate', 'K day-1', '3D'] KnownFields['TdotConv'] = ['convective heating rate', 'K day-1', '3D'] KnownFields['qdotDyn'] = ['dynamical moistening rate', 'g kg-1 day-1', '3D'] KnownFields['qdotTurb'] = ['turbulent moistening rate', 'g kg-1 day-1', '3D'] KnownFields['qdotConv'] = ['convective moistening rate','g kg-1 day-1', '3D'] KnownFields['UdotDyn'] = ['dynamical zonal accn', 'm s-1 day-1', '3D'] KnownFields['UdotTurb'] = ['turbulent zonal drag', 'm s-1 day-', '3D'] KnownFields['VdotDyn'] = ['dynamical merid accn', 'm s-1 day-1', '3D'] KnownFields['VdotTurb'] = ['turbulent merid drag', 'm s-1 day-1', '3D'] import os from numpy import * from grid import Grid class State: ''' Contains all 2D and 3D fields used/produced by component. ''' def __init__(self, Component, **kwargs): # Initialize dicts self.Now = {} # Current time level (n) self.New = {} # n+1 self.Old = {} # n-1 # Initialize time counter (keeps track of 'age' of a time-marched State) if 'ElapsedTime' in kwargs: self.ElapsedTime = kwargs.pop('ElapsedTime') else: self.ElapsedTime = 0. # Initialize grid self.Grid = Grid(Component, **kwargs) # Initialize Required fields self._initializeFields(Component, **kwargs) # Initialize previous time level of prognostic fields for key in Component.Prognostic: self.Old[key] = self.Now[key].copy() def advance(self, Component): ''' Advances State one timestep. ''' return def _initializeFields(self, Component, **kwargs): """ Sets initial values of requested fields """ FieldNames = Component.Required LevType = Component.LevType for Field in FieldNames: if Field not in KnownFields: raise KeyError, \ '\n\n ++++ CliMT.State.init: Field %s unknown' % Field # Set fields' values to input or default Shape3D = self.Grid.Shape3D Shape2D = Shape3D[1:] for Field in FieldNames: exec('Shape = Shape%s' % KnownFields[Field][2]) if Field in kwargs: try: self.Now[Field] = reshape( array(kwargs[Field]), Shape ) except: raise \ '\n\n ++++ CliMT.State.init: Input %s incorrectly dimensioned' % Field else: self.Now[Field] = self._getDefault(Field, Shape, **kwargs) # Catch some anomalous cases if 'p' in FieldNames and 'p' not in kwargs and LevType == 'p': self.Now['p'] = transpose(resize(self.Grid['lev'],Shape3D[::-1])) if 'ps' in FieldNames and 'ps' not in kwargs: if 'p' in self.Now: dp = self.Now['p'][-1] - self.Now['p'][-2] self.Now['ps'] = self.Now['p'][-1] + dp/2. elif LevType == 'p': dp = self.Grid['lev'][-1] - self.Grid['lev'][-2] self.Now['ps'] = zeros(Shape2D,'d') + self.Grid['lev'][-1] + dp/2. if 'Ts' in FieldNames and 'Ts' not in kwargs and 'T' in self.Now: self.Now['Ts'] = reshape( self.Now['T'][-1], Shape2D ) def _getDefault(self, Field, Shape, **kwargs): """ Get default value of Field """ # This routine instantiates ozone and insolation classes to get # default values. To do this correctly, we reset lat, lon in kwargs. # Also, we pop OutputFile and MonitorFields from kwargs to prevent # those instances from creating output and monitor instances. for key in ['lat','lon']: kwargs[key]=self.Grid[key] if 'OutputFile' in kwargs: kwargs.pop('OutputFile') if 'MonitorFields' in kwargs: kwargs.pop('MonitorFields') # Pressure if 'p' == Field: nlev = Shape[0] lev = (arange(nlev)+0.5) * 1000./nlev return transpose(resize(lev,Shape[::-1])) # Level thickness if 'dp' == Field: return zeros(Shape,'d') -99. # set as missing # Surface pressure if 'ps' == Field: return zeros(Shape,'d') + 1000. # Zonal wind if 'U' == Field: return zeros(Shape,'d') # Meridional wind if 'V' == Field: return zeros(Shape,'d') # Meridional streamfunc if 'psi' == Field: return zeros(Shape,'d') # Temperature if 'T' == Field: return zeros(Shape,'d') + 283.15 # Potential temperature if 'theta' == Field: return zeros(Shape,'d') + 283.15 # Surface temperature if 'Ts' == Field: return zeros(Shape,'d') + 283.15 # Moisture if 'q' == Field: return zeros(Shape,'d') + 1.e-5 # Ozone if 'o3' == Field: # create ozone instance to provide default ozone values # note that values will NOT evolve unless ozone explicitly # federated from ozone import ozone ozone = ozone(**kwargs) return ozone.State['o3'] # Cloud frac if 'cldf' == Field: return zeros(Shape,'d') # Cloud water path if 'clwp' == Field: return zeros(Shape,'d') if 'ciwp' == Field: return zeros(Shape,'d') -99. # set as missing by default # Effective radius cloud drops if 'r_liq' == Field: return zeros(Shape,'d') + 10. if 'r_ice' == Field: return zeros(Shape,'d') + 30. # Insolation if 'zen' == Field or 'solin' == Field: # create insolation instance to provide default zen and solin # values for radiation # note that values will NOT evolve unless insolation explicitly # federated with radiation from insolation import insolation insolation = insolation(**kwargs) if 'zen' == Field: return insolation.State['zen'] if 'solin' == Field: return insolation.State['solin'] # Surface upwelling LW if 'flus' == Field: return zeros(Shape,'d') -99. # set to missing as default # Albedos if 'asdir' == Field: return zeros(Shape,'d') + 0.07 if 'asdif' == Field: return zeros(Shape,'d') + 0.07 if 'aldir' == Field: return zeros(Shape,'d') + 0.07 if 'aldif' == Field: return zeros(Shape,'d') + 0.07 # Surface fluxes if 'SrfRadFlx' == Field: return zeros(Shape,'d') if 'SrfLatFlx' == Field: return zeros(Shape,'d') if 'SrfSenFlx' == Field: return zeros(Shape,'d') # Cloud-base mass flux (required for Emanuel convection scheme) if 'cbmf' == Field: return zeros(Shape,'d') # The following methods allow a State instance to be treated as a dictionary def __getitem__(self,key): try: return self.Now[key] except: raise IndexError,'\n\n CliMT.State: %s not in State' % str(key) def __setitem__(self,key,value): self.Now[key] = value def __iter__(self): return self.Now.__iter__() def keys(self): return self.Now.keys() def update(self, dict): self.Now.update(dict)