Esempio n. 1
0
def column_state(num_lev=30, num_lat=1, lev=None, lat=None, water_depth=1.0):
    '''Set up a state variable dictionary consisting of temperatures
    for atmospheric column (`Tatm`) and surface mixed layer (`Ts`).
    '''
    if lat is not None:
        num_lat = np.array(lat).size
    if lev is not None:
        num_lev = np.array(lev).size

    if num_lat is 1:
        sfc, atm = domain.single_column(water_depth=water_depth,
                                        num_lev=num_lev,
                                        lev=lev)
    else:
        sfc, atm = domain.zonal_mean_column(water_depth=water_depth,
                                            num_lev=num_lev,
                                            lev=lev,
                                            num_lat=num_lat,
                                            lat=lat)
    num_lev = atm.lev.num_points
    Ts = Field(288. * np.ones(sfc.shape), domain=sfc)
    Tinitial = np.tile(np.linspace(200., 288. - 10., num_lev), sfc.shape)
    Tatm = Field(Tinitial, domain=atm)
    state = AttrDict()
    state['Ts'] = Ts
    state['Tatm'] = Tatm
    return state
Esempio n. 2
0
 def _compute(self):
     #lapse_rate = self.param['adj_lapse_rate']
     if self.adj_lapse_rate is None:
         #self.adjustment = self.state * 0.
         self.adjustment['Ts'] = self.Ts * 0.
         self.adjustment['Tatm'] = self.Tatm * 0.
     else:
         #  For now, let's assume that the vertical axis is the last axis
         unstable_Tatm = self.Tatm
         if 'Ts' in self.state:
             unstable_Ts = np.atleast_1d(self.Ts)
             #Tcol = np.concatenate((unstable_Ts, unstable_Tatm),axis=-1)
             Tcol = np.concatenate((unstable_Tatm, unstable_Ts),axis=-1)
         else:
             Tcol = unstable_Tatm
         #  convective adjustment routine expect reversered vertical axis
         pflip = self.pnew[..., ::-1]
         Tflip = Tcol[..., ::-1]
         cflip = self.cnew[..., ::-1]
         Tadj_flip = convective_adjustment_direct(pflip, Tflip, cflip, lapserate=self.adj_lapse_rate)
         Tadj = Tadj_flip[..., ::-1]
         if 'Ts' in self.state:
             Ts = Field(Tadj[...,-1], domain=self.Ts.domain)
             Tatm = Field(Tadj[...,:-1], domain=self.Tatm.domain)
             self.adjustment['Ts'] = Ts - self.Ts
         else:
             Tatm = Field(Tadj, domain=self.Tatm.domain)
         self.adjustment['Tatm'] = Tatm - self.Tatm
     #  return the adjustment, independent of timestep
     #  because the parent process might have set a different timestep!
     return self.adjustment
Esempio n. 3
0
 def _compute(self):
     if self.adj_lapse_rate is None:
         self.adjustment['Ts'] = self.Ts * 0.
         self.adjustment['Tatm'] = self.Tatm * 0.
     else:
         #  convective adjustment routine expect reversered vertical axis
         pflip = self.pcol[..., ::-1]
         Tflip = self.Tcol[..., ::-1]
         cflip = self.ccol[..., ::-1]
         lapseflip = np.atleast_1d(self.adj_lapse_rate)[..., ::-1]
         Tadj_flip = convective_adjustment_direct(pflip,
                                                  Tflip,
                                                  cflip,
                                                  lapserate=lapseflip)
         Tadj = Tadj_flip[..., ::-1]
         if 'Ts' in self.state:
             Ts = Field(Tadj[..., -1], domain=self.Ts.domain)
             Tatm = Field(Tadj[..., :-1], domain=self.Tatm.domain)
             self.adjustment['Ts'] = Ts - self.Ts
         else:
             Tatm = Field(Tadj, domain=self.Tatm.domain)
         self.adjustment['Tatm'] = Tatm - self.Tatm
     #  return the adjustment, independent of timestep
     #  because the parent process might have set a different timestep!
     return self.adjustment
Esempio n. 4
0
 def _compute_flux(self):
     #  specific humidity at lowest model level
     #  assumes pressure is the last axis
     q = Field(self.q[..., -1, np.newaxis], domain=self.Ts.domain)
     Ta = Field(self.Tatm[..., -1, np.newaxis], domain=self.Ts.domain)
     qs = qsat(self.Ts, self.ps)
     Deltaq = Field(qs - q, domain=self.Ts.domain)
     rho = self._air_density(Ta)
     #  flux from bulk formula
     self._flux = const.Lhvap * rho * self.Cd * self.U * Deltaq
     self.LHF = self._flux
Esempio n. 5
0
def test_float():
    '''Check that we can step forward the model after setting the state
    variable with an ndarray of integers through 2 different methods'''
    from climlab.domain import initial
    from climlab.domain.field import Field
    state = initial.surface_state()
    sfc = climlab.domain.zonal_mean_surface(num_lat=4)
    state.Ts = Field([10, 15, 15, 10], domain=sfc)
    m = climlab.EBM(state=state)
    m.step_forward()
    k = climlab.EBM(num_lat=4)
    k.set_state('Ts', Field([10, 15, 15, 10], domain=k.domains['Ts']))
    k.step_forward()
Esempio n. 6
0
 def _compute_flux(self):
     #  specific humidity at lowest model level
     #  assumes pressure is the last axis
     q = Field(self.q[..., -1, np.newaxis], domain=self.Ts.domain)
     Ta = Field(self.Tatm[..., -1, np.newaxis], domain=self.Ts.domain)
     qs = qsat(self.Ts, self.ps)
     Deltaq = Field(qs - q, domain=self.Ts.domain)
     rho = self._air_density(Ta)
     #  flux from bulk formula
     self._flux = self.resistance * const.Lhvap * rho * self.Cd * self.U * Deltaq
     self.LHF[:] = self._flux
     # evporation rate, convert from W/m2 to kg/m2/s (or mm/s)
     self.evaporation[:] = self.LHF / const.Lhvap
Esempio n. 7
0
 def compute(self):
     #lapse_rate = self.param['adj_lapse_rate']
     if self.adj_lapse_rate is None:
         self.adjusted_state = self.state
     else:
         #  For now, let's assume that the vertical axis is the last axis
         unstable_Ts = np.atleast_1d(self.Ts)
         unstable_Tatm = self.Tatm
         Tcol = np.concatenate((unstable_Ts, unstable_Tatm),axis=-1)
         Tadj = convective_adjustment_direct(self.pnew, Tcol, self.cnew, lapserate=self.adj_lapse_rate)            
         Ts = Field(Tadj[...,0], domain=self.Ts.domain)
         Tatm = Field(Tadj[...,1:], domain=self.Tatm.domain)
         self.adjustment['Ts'] = Ts - self.Ts
         self.adjustment['Tatm'] = Tatm - self.Tatm
Esempio n. 8
0
 def __init__(self, S0=const.S0, **kwargs):
     super(_Insolation, self).__init__(**kwargs)
     #  initialize diagnostics with correct shape
     self.add_diagnostic('insolation')
     self.add_diagnostic('coszen')
     try:
         domain = self.domains['sfc']
     except:
         domain = self.domains['default']
     self.insolation = Field(np.zeros(domain.shape), domain=domain)
     self.coszen = Field(np.zeros(domain.shape), domain=domain)
     self.declare_diagnostics(['insolation', 'coszen'])
     self.S0 = S0
     #  Now that we have a value for self.S0 we can compute the correct coszen
     self.coszen = self._coszen_from_insolation()
     self.declare_input(['S0'])
Esempio n. 9
0
    def __init__(self,
                 num_lev=30,
                 num_lat=1,
                 lev=None,
                 lat=None,
                 water_depth=1.0,
                 albedo_sfc=0.299,
                 timestep=1. * const.seconds_per_day,
                 Q=341.3,
                 # absorption coefficient in m**2 / kg
                 abs_coeff=1.229E-4,
                 **kwargs):
        # Check to see if an initial state is already provided
        #  If not, make one
        if 'state' not in kwargs:
            state = column_state(num_lev, num_lat, lev, lat, water_depth)
            kwargs.update({'state': state})
        super(GreyRadiationModel, self).__init__(timestep=timestep, **kwargs)
        self.param['water_depth'] = water_depth
        self.param['albedo_sfc'] = albedo_sfc
        self.param['Q'] = Q
        self.param['abs_coeff'] = abs_coeff

        sfc = self.Ts.domain
        atm = self.Tatm.domain
        # create sub-models for longwave and shortwave radiation
        dp = self.Tatm.domain.lev.delta
        absorbLW = compute_layer_absorptivity(self.param['abs_coeff'], dp)
        absorbLW = Field(np.tile(absorbLW, sfc.shape), domain=atm)
        absorbSW = np.zeros_like(absorbLW)
        longwave = GreyGas(state=self.state, absorptivity=absorbLW,
                             albedo_sfc=0)
        shortwave = GreyGasSW(state=self.state, absorptivity=absorbSW,
                                albedo_sfc=self.param['albedo_sfc'])
        # sub-model for insolation ... here we just set constant Q
        thisQ = self.param['Q']*np.ones_like(self.Ts)
        Q = FixedInsolation(S0=thisQ, domains=sfc, **self.param)
        self.add_subprocess('LW', longwave)
        self.add_subprocess('SW', shortwave)
        self.add_subprocess('insolation', Q)
        newdiags = ['OLR',
                    'LW_down_sfc',
                    'LW_up_sfc',
                    'LW_absorbed_sfc',
                    'LW_absorbed_atm',
                    'LW_emission',
                    'ASR',
                    'SW_absorbed_sfc',
                    'SW_absorbed_atm',
                    'SW_up_sfc',
                    'SW_up_TOA',
                    'SW_down_TOA',
                    'planetary_albedo']
        for name in newdiags:
            self.init_diagnostic(name)
        # This process has to handle the coupling between
        # insolation and column radiation
        self.subprocess['SW'].flux_from_space = \
            self.subprocess['insolation'].diagnostics['insolation']
Esempio n. 10
0
def initial_state(num_lev, num_lat, lev, lat, water_depth):
    if num_lat is 1:
        sfc, atm = domain.single_column(water_depth=water_depth,
                                        num_lev=num_lev,
                                        lev=lev)
    else:
        sfc, atm = domain.zonal_mean_column(water_depth=water_depth,
                                            num_lev=num_lev,
                                            lev=lev,
                                            num_lat=num_lat,
                                            lat=lat)
    num_lev = atm.lev.num_points
    Ts = Field(288. * np.ones(sfc.shape), domain=sfc)
    Tinitial = np.tile(np.linspace(288. - 10., 200., num_lev), sfc.shape)
    Tatm = Field(Tinitial, domain=atm)
    state = {'Ts': Ts, 'Tatm': Tatm}
    return state
Esempio n. 11
0
 def _get_current_insolation(self):
     #  this probably only works for 1D (latitude) domains
     insolation_array = self.insolation_array
     # make sure that the diagnostic has the correct field dimensions.
     dom = self.domains['default']
     time_index = self.time['day_of_year_index']   # THIS ONLY WORKS IF self IS THE MASTER PROCESS
     insolation = insolation_array[..., time_index]
     self.diagnostics['insolation'] = Field(insolation, domain=dom)
Esempio n. 12
0
    def set_state(self, name, value):
        """Sets the variable ``name`` to a new state ``value``.

        :param string name:     name of the state
        :param value:           state variable
        :type value:            :class:`~climlab.domain.field.Field` or *array*
        :raises: :exc:`ValueError`
                                if state variable ``value`` is not having a domain.
        :raises: :exc:`ValueError`
                                if shape mismatch between existing domain and
                                new state variable.

        :Example:

            Resetting the surface temperature of an EBM to
            :math:`-5 ^{\circ} \\textrm{C}` on all latitues::

                >>> import climlab
                >>> from climlab import Field
                >>> import numpy as np

                >>> # setup model
                >>> model = climlab.EBM(num_lat=36)

                >>> # create new temperature distribution
                >>> initial = -5 * ones(size(model.lat))
                >>> model.set_state('Ts', Field(initial, domain=model.domains['Ts']))

                >>> np.squeeze(model.Ts)
                Field([-5., -5., -5., -5., -5., -5., -5., -5., -5., -5., -5., -5., -5.,
                       -5., -5., -5., -5., -5., -5., -5., -5., -5., -5., -5., -5., -5.,
                       -5., -5., -5., -5., -5., -5., -5., -5., -5., -5.])

        """
        if isinstance(value, Field):
            # populate domains dictionary with domains from state variables
            self.domains.update({name: value.domain})
        else:
            try:
                thisdom = self.state[name].domain
                domshape = thisdom.shape
            except:
                raise ValueError('State variable needs a domain.')
            value = np.atleast_1d(value)
            if value.shape == domshape:
                value = Field(value, domain=thisdom)
            else:
                raise ValueError(
                    'Shape mismatch between existing domain and new state variable.'
                )
        # set the state dictionary
        self.state[name] = value
        for name, value in self.state.items():
            #convert int dtype to float
            if np.issubdtype(self.state[name].dtype, np.dtype('int').type):
                value = self.state[name].astype(float)
                self.state[name] = value
        setattr(self, name, value)
Esempio n. 13
0
 def _compute_fixed(self):
     try:
         temp_array = self._daily_insolation_array()
         insolation = np.mean(temp_array, axis=1)
         # make sure that the diagnostic has the correct field dimensions.
         dom = self.domains['default']
         self.insolation[:] = Field(insolation, domain=dom)
     except:
         pass
Esempio n. 14
0
 def compute(self):
     #lapse_rate = self.param['adj_lapse_rate']
     Tadj = convective_adjustment_direct(self.pnew,
                                         Tcol,
                                         self.cnew,
                                         lapserate=self.adj_lapse_rate)
     Tatm = Field(Tadj[..., 1:], domain=self.Tatm.domain)
     self.adjustment['Ts'] = Ts - self.Ts
     self.adjustment['Tatm'] = Tatm - self.Tatm
Esempio n. 15
0
 def _get_current_albedo(self):
     '''Simple step-function albedo based on ice line at temperature Tf.'''
     ice = self.subprocess['iceline'].ice
     # noice = self.subprocess['iceline'].diagnostics['noice']
     cold_albedo = self.subprocess['cold_albedo'].albedo
     warm_albedo = self.subprocess['warm_albedo'].albedo
     albedo = Field(np.where(ice, cold_albedo, warm_albedo),
                    domain=self.domains['Ts'])
     return albedo
Esempio n. 16
0
 def _compute_fixed(self):
     '''Recompute any fixed quantities after a change in parameters'''
     phi = np.deg2rad(self.lat)
     try:
         albedo = self.a0 + self.a2 * P2(np.sin(phi))
     except:
         albedo = np.zeros_like(phi)
     # make sure that the diagnostic has the correct field dimensions.
     dom = self.domains['default']
     self.albedo = Field(albedo, domain=dom)
Esempio n. 17
0
def make_column(lev=None, ps=1013, tmp=None, ts=None):
    state = climlab.column_state(lev=lev)
    num_lev = np.array(lev).size
    lev = state.Tatm.domain.lev

    lev_values = lev.points
    lev_dfs = np.zeros(num_lev)
    lev_dfs[1:] = np.diff(lev_values)
    lev_dfs[0] = lev_values[0]
    lev_dfs = lev_dfs / 2.

    lev.bounds = np.full(num_lev + 1, ps)
    lev.bounds[:-1] = lev_values - lev_dfs
    lev.delta = np.abs(np.diff(lev.bounds))
    sfc, atm = domain.single_column(lev=lev)
    state['Ts'] = Field(ts, domain=sfc)
    state['Tatm'] = Field(tmp, domain=atm)

    return state
Esempio n. 18
0
 def _compute_fixed(self):
     phi = np.deg2rad(self.lat)
     #  Why is there a silent fail here? Should get rid of this.
     try:
         insolation = self.S0 / 4 * (1. + self.s2 * P2(np.sin(phi)))
         dom = self.domains['default']
         try:
             insolation = to_latlon(insolation, domain=dom)
             self.insolation[:] = insolation
         except:
             self.insolation[:] = Field(insolation, domain=dom)
         # make sure that the diagnostic has the correct field dimensions.
         #self.insolation = Field(insolation, domain=dom)
         self.insolation[:] = Field(insolation, domain=dom)
         self.coszen[:] = self._coszen_from_insolation()
     #  Silent fail only for attribute error: _s2 is not an attribute of self
     #  but s2 parameter is being stored in self._s2
     except AttributeError:
         pass
Esempio n. 19
0
def init_interface(field):
    '''Return a Field object defined at the vertical interfaces of the input Field object.'''
    interface_shape = np.array(field.shape)
    interface_shape[-1] += 1
    interfaces = np.tile(False, len(interface_shape))
    interfaces[-1] = True
    interface_zero = Field(np.zeros(interface_shape),
                           domain=field.domain,
                           interfaces=interfaces)
    return interface_zero
Esempio n. 20
0
 def _compute_flux(self):
     # this ensure same dimensions as Ts
     #  (and use only the lowest model level)
     Ta = Field(self.Tatm[..., -1, np.newaxis], domain=self.Ts.domain)
     Ts = self.Ts
     DeltaT = Ts - Ta
     rho = self._air_density(Ta)
     #  flux from bulk formula
     self._flux = self.resistance * const.cp * rho * self.Cd * self.U * DeltaT
     self.SHF = self._flux
Esempio n. 21
0
 def _compute_fixed(self):
     #lat = self.domains['default'].axes['lat'].points 
     lat = self.lat
     phi = np.deg2rad(lat)
     try:
         insolation = self.S0 / 4 * (1. + self.s2 * P2(np.sin(phi)))
         # make sure that the diagnostic has the correct field dimensions.
         dom = self.domains['default']
         self.diagnostics['insolation'] = Field(insolation, domain=dom)
     except:
         pass
Esempio n. 22
0
 def _compute_fixed(self):
     phi = np.deg2rad(self.lat)
     #  Why is there a silent fail here? Should get rid of this.
     try:
         insolation = self.S0 / 4 * (1. + self.s2 * P2(np.sin(phi)))
         # make sure that the diagnostic has the correct field dimensions.
         dom = self.domains['default']
         #self.insolation = Field(insolation, domain=dom)
         self.insolation[:] = Field(insolation, domain=dom)
     except:
         pass
Esempio n. 23
0
def surface_state(num_lat=90, water_depth=10., T0=12., T2=-40.):
    '''Set up a state variable dictionary for a zonal-mean surface model
    (e.g. basic EBM). There is a single state variable `Ts`, the temperature
    of the surface mixed layer.
    '''
    sfc = domain.zonal_mean_surface(num_lat=num_lat, water_depth=water_depth)
    sinphi = np.sin(np.deg2rad(sfc.axes['lat'].points))
    initial = T0 + T2 * legendre.P2(sinphi)
    Ts = Field(initial, domain=sfc)
    state = AttrDict()
    state['Ts'] = Ts
    return state
Esempio n. 24
0
    def __init__(
            self,
            num_lev=30,
            num_lat=1,
            lev=None,
            lat=None,
            water_depth=1.0,
            albedo_sfc=0.299,
            timestep=1. * const.seconds_per_day,
            Q=341.3,
            # absorption coefficient in m**2 / kg
            abs_coeff=1.229E-4,
            **kwargs):
        if lat is not None:
            num_lat = np.array(lat).size
        if lev is not None:
            num_lev = np.array(lev).size
        # Check to see if an initial state is already provided
        #  If not, make one
        if 'state' not in kwargs:
            state = self.initial_state(num_lev, num_lat, lev, lat, water_depth)
            kwargs.update({'state': state})
        super(GreyRadiationModel, self).__init__(timestep=timestep, **kwargs)
        self.param['water_depth'] = water_depth
        self.param['albedo_sfc'] = albedo_sfc
        self.param['Q'] = Q
        self.param['abs_coeff'] = abs_coeff

        sfc = self.Ts.domain
        atm = self.Tatm.domain
        # create sub-models for longwave and shortwave radiation
        dp = self.Tatm.domain.lev.delta
        absorbLW = compute_layer_absorptivity(self.param['abs_coeff'], dp)
        absorbLW = Field(np.tile(absorbLW, sfc.shape), domain=atm)
        absorbSW = np.zeros_like(absorbLW)
        longwave = Radiation(state=self.state,
                             absorptivity=absorbLW,
                             albedo_sfc=0)
        shortwave = RadiationSW(state=self.state,
                                absorptivity=absorbSW,
                                albedo_sfc=self.param['albedo_sfc'])
        # sub-model for insolation ... here we just set constant Q
        thisQ = self.param['Q'] * np.ones_like(self.Ts)
        Q = FixedInsolation(S0=thisQ, domain=sfc, **self.param)
        #  surface sub-model
        surface = SurfaceRadiation(state=self.state, **self.param)
        self.add_subprocess('LW', longwave)
        self.add_subprocess('SW', shortwave)
        self.add_subprocess('insolation', Q)
        self.add_subprocess('surface', surface)
Esempio n. 25
0
 def _compute(self):
     #lapse_rate = self.param['adj_lapse_rate']
     if self.adj_lapse_rate is None:
         self.adjustment = self.state * 0.
     else:
         #  For now, let's assume that the vertical axis is the last axis
         unstable_Tatm = self.Tatm
         if 'Ts' in self.state:
             unstable_Ts = np.atleast_1d(self.Ts)
             #Tcol = np.concatenate((unstable_Ts, unstable_Tatm),axis=-1)
             Tcol = np.concatenate((unstable_Tatm, unstable_Ts), axis=-1)
         else:
             Tcol = unstable_Tatm
         #  convective adjustment routine expect reversered vertical axis
         pflip = self.pnew[..., ::-1]
         Tflip = Tcol[..., ::-1]
         cflip = self.cnew[..., ::-1]
         Tadj_flip = convective_adjustment_direct(
             pflip, Tflip, cflip, lapserate=self.adj_lapse_rate)
         Tadj = Tadj_flip[..., ::-1]
         if 'Ts' in self.state:
             Ts = Field(Tadj[..., -1], domain=self.Ts.domain)
             Tatm = Field(Tadj[..., :-1], domain=self.Tatm.domain)
             self.adjustment['Ts'] = Ts - self.Ts
         else:
             Tatm = Field(Tadj, domain=self.Tatm.domain)
         self.adjustment['Tatm'] = Tatm - self.Tatm
     # # express the adjustment (already accounting for the finite time step)
     # #  as a tendency per unit time, so that it can be applied along with explicit
     # tendencies = {}
     # for name, adj in self.adjustment.iteritems():
     #     tendencies[name] = adj / self.param['timestep']
     # return tendencies
     #  go back to just returning the adjustment, independent of timestep
     #  because the parent process might have set a different timestep!
     return self.adjustment
Esempio n. 26
0
 def _compute_fixed(self):
     try:
         temp_array = self._daily_insolation_array()
         insolation = np.mean(temp_array, axis=1)
         # make sure that the diagnostic has the correct field dimensions.
         dom = self.domains['default']
         try:
             insolation = to_latlon(insolation, domain=dom)
             self.insolation[:] = insolation
         except:
             self.insolation[:] = Field(insolation, domain=dom)
         self.coszen[:] = self._coszen_from_insolation()
     #  Silent fail only for attribute error: _orb is not an attribute of self
     #  but orb parameter is being stored in self._orb
     except AttributeError:
         pass
Esempio n. 27
0
 def _compute_fixed(self):
     '''Recompute any fixed quantities after a change in parameters'''
     try:
         lon, lat = np.meshgrid(self.lon, self.lat)
     except:
         lat = self.lat
     phi = np.deg2rad(lat)
     try:
         albedo = self.a0 + self.a2 * P2(np.sin(phi))
     except:
         albedo = np.zeros_like(phi)
     # make sure that the diagnostic has the correct field dimensions.
     #dom = self.domains['default']
     #  this is a more robust way to get the single value from dictionary:
     dom = next(iter(self.domains.values()))
     self.albedo = Field(albedo, domain=dom)
Esempio n. 28
0
 def _get_current_insolation(self):
     insolation_array = self.insolation_array
     # make sure that the diagnostic has the correct field dimensions.
     dom = self.domains['default']
     time_index = self.time[
         'day_of_year_index']  # THIS ONLY WORKS IF self IS THE MASTER PROCESS
     insolation = insolation_array[..., time_index]
     if 'lon' in dom.axes:
         # insolation is latitude-only, need to broadcast across longitude
         #  assumption is axes are ordered (lat, lon, depth)
         #  NOTE this is a clunky hack and all this will go away
         #  when we use xarray structures for these internals
         insolation = np.tile(insolation[..., np.newaxis],
                              dom.axes['lon'].num_points)
     self.insolation[:] = Field(insolation, domain=dom)
     self.coszen[:] = self._coszen_from_insolation()
Esempio n. 29
0
 def __init__(
         self,
         num_lat=90,
         S0=const.S0,
         A=210.,
         B=2.,
         D=0.555,  # in W / m^2 / degC, same as B
         water_depth=10.0,
         Tf=-10.,
         a0=0.3,
         a2=0.078,
         ai=0.62,
         timestep=const.seconds_per_year / 90.,
         T_init_0=12.,
         T_init_P2=-40.,
         **kwargs):
     super(EBM, self).__init__(timestep=timestep, **kwargs)
     if not self.domains and not self.state:  # no state vars or domains yet
         sfc = domain.zonal_mean_surface(num_lat=num_lat,
                                         water_depth=water_depth)
         lat = sfc.axes['lat'].points
         initial = T_init_0 + T_init_P2 * legendre.P2(
             np.sin(np.deg2rad(lat)))
         self.set_state('Ts', Field(initial, domain=sfc))
     self.param['S0'] = S0
     self.param['A'] = A
     self.param['B'] = B
     self.param['D'] = D
     self.param['Tf'] = Tf
     self.param['water_depth'] = water_depth
     self.param['a0'] = a0
     self.param['a2'] = a2
     self.param['ai'] = ai
     # create sub-models
     self.add_subprocess('LW', AplusBT(state=self.state, **self.param))
     self.add_subprocess('insolation',
                         P2Insolation(domains=sfc, **self.param))
     self.add_subprocess(
         'albedo', albedo.StepFunctionAlbedo(state=self.state,
                                             **self.param))
     # diffusivity in units of 1/s
     K = self.param['D'] / self.domains['Ts'].heat_capacity
     self.add_subprocess(
         'diffusion',
         MeridionalDiffusion(state=self.state, K=K, **self.param))
     self.topdown = False  # call subprocess compute methods first
Esempio n. 30
0
 def set_state(self, name, value):
     if isinstance(value, Field):
         # populate domains dictionary with domains from state variables
         self.domains.update({name: value.domain})
     else:
         try:
             thisdom = self.state[name].domain
             domshape = thisdom.shape
         except:
             raise ValueError('State variable needs a domain.')
         value = np.atleast_1d(value)
         if value.shape == domshape:
             value = Field(value, domain=thisdom)
         else:
             raise ValueError(
                 'Shape mismatch between existing domain and new state variable.'
             )
     # set the state dictionary
     self.state[name] = value
     setattr(self, name, value)