def find_icelines(self): """Finds iceline according to the surface temperature. This method is called by the private function :func:`~climlab.surface.albedo.Iceline._compute` and updates following attributes according to the freezing temperature ``self.param['Tf']`` and the surface temperature ``self.param['Ts']``: **Object attributes** \n :ivar Field noice: a Field of booleans which are ``True`` where :math:`T_s \\ge T_f` :ivar Field ice: a Field of booleans which are ``True`` where :math:`T_s < T_f` :ivar array icelat: an array with two elements indicating the ice-edge latitudes :ivar float ice_area: fractional area covered by ice (0 - 1) :ivar dict diagnostics: keys ``'icelat'`` and ``'ice_area'`` are updated """ Tf = self.param['Tf'] Ts = self.state['Ts'] lat_bounds = self.domains['Ts'].axes['lat'].bounds self.noice = np.where(Ts >= Tf, True, False) self.ice = np.where(Ts < Tf, True, False) # Ice cover in fractional area self.ice_area = global_mean(self.ice * np.ones_like(self.Ts)) # Express ice cover in terms of ice edge latitudes if self.ice.all(): # 100% ice cover self.icelat = np.array([-0., 0.]) elif self.noice.all(): # zero ice cover self.icelat = np.array([-90., 90.]) else: # there is some ice edge # Taking np.diff of a boolean array gives True at the boundaries between True and False boundary_indices = np.where(np.diff(self.ice.squeeze()))[0] + 1 # check for asymmetry case: [-90,x] or [x,90] # -> boundary_indices hold only one value for icelat if boundary_indices.size == 1: if self.ice[0] == True: # case: [x,90] # extend indice array by missing value for northpole boundary_indices = np.append(boundary_indices, self.ice.size) elif self.ice[-1] == True: # case: [-90,x] # extend indice array by missing value for northpole boundary_indices = np.insert(boundary_indices, 0, 0) # check for asymmetry case: [-90,x] or [x,90] # -> boundary_indices hold only one value for icelat if boundary_indices.size == 1: if self.ice[0] == True: # case: [x,90] # extend indice array by missing value for northpole boundary_indices = np.append(boundary_indices, self.ice.size) elif self.ice[-1] == True: # case: [-90,x] # extend indice array by missing value for northpole boundary_indices = np.insert(boundary_indices, 0, 0) self.icelat = lat_bounds[ boundary_indices] # an array of boundary latitudes
def find_icelines(self): """Finds iceline according to the surface temperature. This method is called by the private function :func:`~climlab.surface.albedo.Iceline._compute` and updates following attributes according to the freezing temperature ``self.param['Tf']`` and the surface temperature ``self.param['Ts']``: **Object attributes** \n :ivar Field noice: a Field of booleans which are ``True`` where :math:`T_s \\ge T_f` :ivar Field ice: a Field of booleans which are ``True`` where :math:`T_s < T_f` :ivar array icelat: an array with two elements indicating the ice-edge latitudes :ivar float ice_area: fractional area covered by ice (0 - 1) :ivar dict diagnostics: keys ``'icelat'`` and ``'ice_area'`` are updated """ Tf = self.param['Tf'] Ts = self.state['Ts'] lat_bounds = self.domains['Ts'].axes['lat'].bounds self.noice = np.where(Ts >= Tf, True, False) self.ice = np.where(Ts < Tf, True, False) # Ice cover in fractional area self.ice_area = global_mean(self.ice * np.ones_like(self.Ts)) # Express ice cover in terms of ice edge latitudes if self.ice.all(): # 100% ice cover self.icelat = np.array([-0., 0.]) elif self.noice.all(): # zero ice cover self.icelat = np.array([-90., 90.]) else: # there is some ice edge # Taking np.diff of a boolean array gives True at the boundaries between True and False boundary_indices = np.where(np.diff(self.ice.squeeze()))[0]+1 # check for asymmetry case: [-90,x] or [x,90] # -> boundary_indices hold only one value for icelat if boundary_indices.size == 1: if self.ice[0] == True: # case: [x,90] # extend indice array by missing value for northpole boundary_indices = np.append(boundary_indices, self.ice.size) elif self.ice[-1] == True: # case: [-90,x] # extend indice array by missing value for northpole boundary_indices = np.insert(boundary_indices,0 ,0) # check for asymmetry case: [-90,x] or [x,90] # -> boundary_indices hold only one value for icelat if boundary_indices.size == 1: if self.ice[0] == True: # case: [x,90] # extend indice array by missing value for northpole boundary_indices = np.append(boundary_indices, self.ice.size) elif self.ice[-1] == True: # case: [-90,x] # extend indice array by missing value for northpole boundary_indices = np.insert(boundary_indices,0 ,0) self.icelat = lat_bounds[boundary_indices] # an array of boundary latitudes
def global_mean_temperature(self): """Convenience method to compute global mean surface temperature. Calls :func:`~climlab.domain.field.global_mean` method which for the object attriute ``Ts`` which calculates the latitude weighted global mean of a field. :Example: Calculating the global mean temperature of initial EBM temperature:: >>> import climlab >>> model = climlab.EBM(T0=14., T2=-25) >>> model.global_mean_temperature() Field(13.99873037400856) """ return global_mean(self.Ts)
def __init__(self, model, kyear_start=-20., kyear_stop=0., segment_length_years=100., orbital_year_factor=1., verbose=True ): """Automatically integrate a process through changes in orbital parameters. model is an instance of climlab.time_dependent_process segment_length_years is the length of each integration with fixed orbital parameters. orbital_year_factor is an optional speed-up to the orbital cycles. """ self.model = model self.kyear_start = kyear_start self.kyear_stop = kyear_stop self.segment_length_years = segment_length_years self.orbital_year_factor = orbital_year_factor self.verbose = verbose self.num_segments = int(-(kyear_start - kyear_stop) * 1000. / segment_length_years / orbital_year_factor) kyear_before_present = kyear_start if verbose: print("--------- OrbitalCycles START ----------") print("Beginning integration for the model from " + str(kyear_start) + " to " + str(kyear_stop) + " kyears before present.") print("Integration time for each set of orbital parameters is " + str(segment_length_years) + " years.") print("Orbital cycles will be sped up by a factor " + str(orbital_year_factor)) print("Total number of segments is " + str(self.num_segments)) # initialize storage arrays self.T_segments_global = np.empty( self.num_segments ) self.T_segments = np.empty( (self.model.Ts.size, self.num_segments) ) self.T_segments_annual = np.empty_like( self.T_segments ) self.orb_kyear = np.empty( self.num_segments ) # Get orbital data table orbtable = OrbitalTable() for n in range(self.num_segments): if verbose: print("-------------------------") print("Segment " + str(n) + " out of " + str(self.num_segments) ) print( "Using orbital parameters from " + str(kyear_before_present) + " kyears before present." ) self.orb = orbtable.lookup_parameters(kyear_before_present) #self.model.make_insolation_array( orb ) self.model.subprocess['insolation'].orb = self.orb self.model.integrate_years(segment_length_years-1., verbose=False) # Run one final year to characterize the current equilibrated state self.model.integrate_years(1.0, verbose=False) self.T_segments_annual[:, n] = np.squeeze(self.model.timeave['Ts']) self.T_segments[:, n] = np.squeeze(self.model.Ts) self.T_segments_global[n] = global_mean(self.model.timeave['Ts']) self.orb_kyear[n] = kyear_before_present kyear_before_present += segment_length_years / 1000. * orbital_year_factor if verbose: print( "Global mean temperature from the final year of integration is " + str(self.T_segments_global[n]) + " degrees C." ) if verbose: print("--------- OrbitalCycles END ----------")
def global_mean_temperature(self): '''Convenience method to compute global mean surface temperature.''' return global_mean(self.state['Ts'])
def _compute_heating_rates(self): '''Compute energy flux convergences to get heating rates in W / m**2.''' for varname, value in self.state.iteritems(): self.heating_rate[varname] = - self.b * (value - global_mean(value))
def global_mean_temperature(self): '''Convenience method to compute global mean surface temperature.''' return global_mean(self.Ts)
def __init__(self, model, kyear_start=-20., kyear_stop=0., segment_length_years=100., orbital_year_factor=1., verbose=True): """Automatically integrates a process through changes in orbital parameters. OrbitalCycles is a module for setting up long integrations of climlab processes over orbital cycles. The duration between integration start and end time is partitioned in time segments over which the orbital parameters are held constant. The process is integrated over every time segment and the process state ``Ts`` is stored for each segment. The storage arrays are saving: * **current model state** at end of each segment * **model state averaged** over last integrated year of each segment * **global mean** of averaged model state over last integrated year of each segment .. note:: Input ``kyear`` is thousands of years after present. For years before present, use ``kyear < 0``. **Initialization parameters** \n :param model: a time dependent process :type model: :class:`~climlab.process.time_dependent_process.TimeDependentProcess` :param float kyear_start: integration start time. \n As time reference is present, argument should be :math:`<0` for time before present. * *unit:* kiloyears \n * *default value:* ``-20.`` :param float kyear_stop: integration stop time. \n As time reference is present, argument should be :math:`\\le 0` for time before present. * *unit:* kiloyears \n * *default value:* ``0.`` :param float segment_length_years: is the length of each integration with fixed orbital parameters. [default: 100.] :param float orbital_year_factor: is an optional speed-up to the orbital cycles. [default: 1.] :param bool verbose: prints product of calculation and information about computation progress [default: True] **Object attributes** \n Following object attributes are generated during initialization: :ivar model: timedependent process to be integrated :vartype model: :class:`~climlab.process.time_dependent_process.TimeDependentProcess` :ivar float kyear_start: integration start time :ivar float kyear_stop: integration stop time :ivar float segment_length_years: length of each integration with fixed orbital parameters :ivar float orbital_year_factor: speed-up factor to the orbital cycles :ivar bool verbose: print flag :ivar int num_segments: number of segments with fixed oribtal parameters, calculated through: .. math:: num_{seg} = \\frac{-(kyear_{start}-kyear_{stop})*1000}{seg_{length} * orb_{factor}} :ivar array T_segments_global: storage for global mean temperature for final year of each segment :ivar array T_segments: storage for actual temperature at end of each segment :ivar array T_segments_annual: storage for timeaveraged temperature over last year of segment \n dimension: (size(Ts), num_segments) :ivar array orb_kyear: integration start time of all segments :ivar dict orb: orbital parameters for last integrated segment :Example: Integration of an energy balance model for 10,000 years with corresponding orbital parameters:: from climlab.model.ebm import EBM_seasonal from climlab.solar.orbital_cycles import OrbitalCycles from climlab.surface.albedo import StepFunctionAlbedo ebm = EBM_seasonal() print ebm # add an albedo feedback albedo = StepFunctionAlbedo(state=ebm.state, **ebm.param) ebm.add_subprocess('albedo', albedo) # start the integration # run for 10,000 orbital years, but only 1,000 model years experiment = OrbitalCycles(ebm, kyear_start=-20, kyear_stop=-10, orbital_year_factor=10.) """ self.model = model self.kyear_start = kyear_start self.kyear_stop = kyear_stop self.segment_length_years = segment_length_years self.orbital_year_factor = orbital_year_factor self.verbose = verbose self.num_segments = int(-(kyear_start - kyear_stop) * 1000. / segment_length_years / orbital_year_factor) kyear_before_present = kyear_start if verbose: print("--------- OrbitalCycles START ----------") print("Beginning integration for the model from " + str(kyear_start) + " to " + str(kyear_stop) + " kyears before present.") print("Integration time for each set of orbital parameters is " + str(segment_length_years) + " years.") print("Orbital cycles will be sped up by a factor " + str(orbital_year_factor)) print("Total number of segments is " + str(self.num_segments)) # initialize storage arrays self.T_segments_global = np.empty(self.num_segments) self.T_segments = np.empty((self.model.Ts.size, self.num_segments)) self.T_segments_annual = np.empty_like(self.T_segments) self.orb_kyear = np.empty(self.num_segments) # Get orbital data table #orbtable = OrbitalTable() for n in range(self.num_segments): if verbose: print("-------------------------") print("Segment " + str(n) + " out of " + str(self.num_segments)) print("Using orbital parameters from " + str(kyear_before_present) + " kyears before present.") self.orb = OrbitalTable.interp(kyear=kyear_before_present) #self.model.make_insolation_array( orb ) self.model.subprocess['insolation'].orb = self.orb self.model.integrate_years(segment_length_years - 1., verbose=False) # Run one final year to characterize the current equilibrated state self.model.integrate_years(1.0, verbose=False) self.T_segments_annual[:, n] = np.squeeze(self.model.timeave['Ts']) self.T_segments[:, n] = np.squeeze(self.model.Ts) self.T_segments_global[n] = global_mean(self.model.timeave['Ts']) self.orb_kyear[n] = kyear_before_present kyear_before_present += segment_length_years / 1000. * orbital_year_factor if verbose: print( "Global mean temperature from the final year of integration is " + str(self.T_segments_global[n]) + " degrees C.") if verbose: print("--------- OrbitalCycles END ----------")
def _compute_heating_rates(self): """Computes energy flux convergences to get heating rates in :math:`W/m^2`. """ for varname, value in self.state.items(): self.heating_rate[varname] = - self.b * (value - global_mean(value))
def __init__(self, model, kyear_start=-20., kyear_stop=0., segment_length_years=100., orbital_year_factor=1., verbose=True ): """Automatically integrates a process through changes in orbital parameters. OrbitalCycles is a module for setting up long integrations of climlab processes over orbital cycles. The duration between integration start and end time is partitioned in time segments over which the orbital parameters are held constant. The process is integrated over every time segment and the process state ``Ts`` is stored for each segment. The storage arrays are saving: * **current model state** at end of each segment * **model state averaged** over last integrated year of each segment * **global mean** of averaged model state over last integrated year of each segment .. note:: Input ``kyear`` is thousands of years after present. For years before present, use ``kyear < 0``. **Initialization parameters** \n :param model: a time dependent process :type model: :class:`~climlab.process.time_dependent_process.TimeDependentProcess` :param float kyear_start: integration start time. \n As time reference is present, argument should be :math:`<0` for time before present. * *unit:* kiloyears \n * *default value:* ``-20.`` :param float kyear_stop: integration stop time. \n As time reference is present, argument should be :math:`\\le 0` for time before present. * *unit:* kiloyears \n * *default value:* ``0.`` :param float segment_length_years: is the length of each integration with fixed orbital parameters. [default: 100.] :param float orbital_year_factor: is an optional speed-up to the orbital cycles. [default: 1.] :param bool verbose: prints product of calculation and information about computation progress [default: True] **Object attributes** \n Following object attributes are generated during initialization: :ivar model: timedependent process to be integrated :vartype model: :class:`~climlab.process.time_dependent_process.TimeDependentProcess` :ivar float kyear_start: integration start time :ivar float kyear_stop: integration stop time :ivar float segment_length_years: length of each integration with fixed orbital parameters :ivar float orbital_year_factor: speed-up factor to the orbital cycles :ivar bool verbose: print flag :ivar int num_segments: number of segments with fixed oribtal parameters, calculated through: .. math:: num_{seg} = \\frac{-(kyear_{start}-kyear_{stop})*1000}{seg_{length} * orb_{factor}} :ivar array T_segments_global: storage for global mean temperature for final year of each segment :ivar array T_segments: storage for actual temperature at end of each segment :ivar array T_segments_annual: storage for timeaveraged temperature over last year of segment \n dimension: (size(Ts), num_segments) :ivar array orb_kyear: integration start time of all segments :ivar dict orb: orbital parameters for last integrated segment :Example: Integration of an energy balance model for 10,000 years with corresponding orbital parameters:: from climlab.model.ebm import EBM_seasonal from climlab.solar.orbital_cycles import OrbitalCycles from climlab.surface.albedo import StepFunctionAlbedo ebm = EBM_seasonal() print ebm # add an albedo feedback albedo = StepFunctionAlbedo(state=ebm.state, **ebm.param) ebm.add_subprocess('albedo', albedo) # start the integration # run for 10,000 orbital years, but only 1,000 model years experiment = OrbitalCycles(ebm, kyear_start=-20, kyear_stop=-10, orbital_year_factor=10.) """ self.model = model self.kyear_start = kyear_start self.kyear_stop = kyear_stop self.segment_length_years = segment_length_years self.orbital_year_factor = orbital_year_factor self.verbose = verbose self.num_segments = int(-(kyear_start - kyear_stop) * 1000. / segment_length_years / orbital_year_factor) kyear_before_present = kyear_start if verbose: print("--------- OrbitalCycles START ----------") print("Beginning integration for the model from " + str(kyear_start) + " to " + str(kyear_stop) + " kyears before present.") print("Integration time for each set of orbital parameters is " + str(segment_length_years) + " years.") print("Orbital cycles will be sped up by a factor " + str(orbital_year_factor)) print("Total number of segments is " + str(self.num_segments)) # initialize storage arrays self.T_segments_global = np.empty( self.num_segments ) self.T_segments = np.empty( (self.model.Ts.size, self.num_segments) ) self.T_segments_annual = np.empty_like( self.T_segments ) self.orb_kyear = np.empty( self.num_segments ) # Get orbital data table #orbtable = OrbitalTable() for n in range(self.num_segments): if verbose: print("-------------------------") print("Segment " + str(n) + " out of " + str(self.num_segments) ) print( "Using orbital parameters from " + str(kyear_before_present) + " kyears before present." ) self.orb = OrbitalTable.interp(kyear=kyear_before_present) #self.model.make_insolation_array( orb ) self.model.subprocess['insolation'].orb = self.orb self.model.integrate_years(segment_length_years-1., verbose=False) # Run one final year to characterize the current equilibrated state self.model.integrate_years(1.0, verbose=False) self.T_segments_annual[:, n] = np.squeeze(self.model.timeave['Ts']) self.T_segments[:, n] = np.squeeze(self.model.Ts) self.T_segments_global[n] = global_mean(self.model.timeave['Ts']) self.orb_kyear[n] = kyear_before_present kyear_before_present += segment_length_years / 1000. * orbital_year_factor if verbose: print( "Global mean temperature from the final year of integration is " + str(self.T_segments_global[n]) + " degrees C." ) if verbose: print("--------- OrbitalCycles END ----------")