Example #1
0
    def __init__(
        self,
        atmosphere,
        timestep='6h',
        max_duration='500d',
        outfile=None,
        experiment='RCE',
        writeevery='24h',
        delta=0.0,
        delta2=0.0,
        post_count=365,
        radiation=None,
        ozone=None,
        humidity=None,
        surface=None,
        cloud=None,
        convection=None,
        lapserate=None,
        upwelling=None,
        diurnal_cycle=False,
        co2_adjustment_timescale=np.nan,
        logevery=None,
        timestep_adjuster=None,
    ):
        """Set-up a radiative-convective model.

        Parameters:

            atmosphere: :py:class:`konrad.atmosphere.Atmosphere`.

            timestep (float, str or timedelta): Model time step

                * If float, time step in days.
                * If str, a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).
                * A `timedelta` object is directly used as timestep.

            max_duration (float, str or timedelta): Maximum duration.
                The duration is given in model time

                * If float, maximum duration in days.
                * If str, a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).
                * A `timedelta` object is directly used as timestep.

            outfile (str): netCDF4 file to store output.

            experiment (str): Experiment description (stored in netCDF output).

            writeevery (float, str or timedelta): Set output frequency.

                * float: Every nth day in model time
                * str: a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).
                * A `timedelta` object is directly used as timestep.
                * Note: Setting a value of `"0h"` will write after every iteration.

            delta (float): First stop criterion. If the change in top-of-the-atmosphere
                radiative balance is smaller than this threshold,
                skip further iterations. Values are given in W/m^2/day.

            delta2 (float): Second stop criterion. If the second-derivative of the
                top-of-the-atmosphere radiative balance is smaller than this threshold,
                skip further iterations. Values are given in W/m^2/day^2.

            post_count (float): Numbers of days that the convergence criterion
                (see `delta` and `delta2`) has to be fulfilled to stop the simulation.

            radiation (konrad.radiation): Radiation model.
                Defaults to :class:`konrad.radiation.RRTMG`.

            ozone (konrad.ozone): Ozone model.
                Defaults to :class:`konrad.ozone.OzonePressure`.

            humidity (konrad.humidity): Humidity model.
                Defaults to :class:`konrad.humidity.FixedRH`.

            surface (konrad.surface): Surface model.
                Defaults to :class:`konrad.surface.SlabOcean`.

            cloud (konrad.cloud): Cloud model.
                Defaults to :class:`konrad.cloud.ClearSky`.

            convection (konrad.convection): Convection scheme.
                Defaults to :class:`konrad.convection.HardAdjustment`.

            lapserate (konrad.lapserate): Lapse rate handler.
                Defaults to :class:`konrad.lapserate.MoistLapseRate`.

            upwelling (konrad.upwelling): Upwelling model.
                Defaults to :class:`konrad.upwelling.NoUpwelling`.

            diurnal_cycle (bool): Toggle diurnal cycle of solar angle.

            co2_adjustment_timescale (int/float): Adjust CO2 concentrations
                towards an equilibrium state following Romps 2020.
                To be used with :class:`konrad.surface.FixedTemperature`.
                Recommended value is 7 (1 week).
                Defaults to no CO2 adjustment, with `np.nan`.

            logevery (int): Log the model progress at every nth iteration.
                Default is no logging.

                This keyword only affects the frequency with which the
                log messages are generated. You have to enable the logging
                by using the :py:mod:`logging` standard library or
                the `konrad.enable_logging()` convenience function.

            timestep_adjuster (callable): A callable object, that takes the
                current timestep and the temperature change as input
                to calculate a new timestep (`f(timestep, deltaT)`).

                Default (`None`) is keeping the given timestep fixed.
        """
        # Sub-model initialisation

        # Atmosphere
        self.atmosphere = atmosphere

        # Radiation
        if radiation is None:
            self.radiation = RRTMG()
        else:
            self.radiation = radiation

        # Ozone
        self.ozone = utils.return_if_type(ozone, 'ozone', Ozone,
                                          OzonePressure())

        # Humidity
        self.humidity = FixedRH() if humidity is None else humidity

        # Surface
        self.surface = utils.return_if_type(surface, 'surface', Surface,
                                            SlabOcean())

        # Cloud
        self.cloud = utils.return_if_type(
            cloud, 'cloud', Cloud, ClearSky(self.atmosphere['plev'].size))

        # Convection
        self.convection = utils.return_if_type(convection, 'convection',
                                               Convection, HardAdjustment())

        # Critical lapse-rate
        self.lapserate = utils.return_if_type(lapserate, 'lapserate',
                                              LapseRate, MoistLapseRate())

        # Stratospheric upwelling
        self.upwelling = utils.return_if_type(upwelling, 'upwelling',
                                              Upwelling, NoUpwelling())

        # Diurnal cycle
        self.diurnal_cycle = diurnal_cycle

        # Time, timestepping and duration attributes
        self.timestep = utils.parse_fraction_of_day(timestep)
        self.time = datetime.datetime(1, 1, 1)  # Start model run at 0001/1/1
        self.max_duration = utils.parse_fraction_of_day(max_duration)
        self.niter = 0
        self.timestep_adjuster = timestep_adjuster

        # Output writing attributes
        self.writeevery = utils.parse_fraction_of_day(writeevery)
        self.last_written = self.time
        self.outfile = outfile
        self.nchandler = None
        self.experiment = experiment

        # Logging attributes
        self.logevery = logevery

        # Attributes used by the is_converged() method
        self.delta = delta
        if delta != 0.0 and delta2 == 0.0:
            self.delta2 = delta / 100
        else:
            self.delta2 = delta2
        self.oldN = 0
        self.oldDN = 0
        self.newDN = 0
        self.newDDN = 0
        self.counteq = datetime.timedelta(microseconds=0)
        self.post_count = utils.parse_fraction_of_day(post_count)
        self.converged = False

        # Attributes used by the time-step adjuster
        self.oldT = 0
        self.deltaT = 0

        # Attributes for experiments with varying carbon dioxide following
        # Romps (2020)
        self.co2_adjustment_timescale = co2_adjustment_timescale
        if not np.isnan(co2_adjustment_timescale) and not isinstance(
                surface, FixedTemperature):
            raise TypeError("Runs with adjusting CO2 concentration "
                            "require a fixed surface temperature.")

        logging.info('Created Konrad object:\n{}'.format(self))
Example #2
0
    def __init__(
        self,
        atmosphere,
        timestep='6h',
        max_duration='500d',
        outfile=None,
        experiment='RCE',
        writeevery='24h',
        writefor=None,
        delta=0.0,
        radiation=None,
        ozone=None,
        humidity=None,
        surface=None,
        cloud=None,
        convection=None,
        lapserate=None,
        upwelling=None,
        diurnal_cycle=False,
        co2_adjustment_timescale=np.nan,
        logevery=None,
        timestep_adjuster=None,
    ):
        """Set-up a radiative-convective model.

        Parameters:

            atmosphere: :py:class:`konrad.atmosphere.Atmosphere`.

            timestep (float, str or timedelta): Model time step

                * If float, time step in days.
                * If str, a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).
                * A `timedelta` object is directly used as timestep.

            max_duration (float, str or timedelta): Maximum duration.
                The duration is given in model time

                * If float, maximum duration in days.
                * If str, a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).
                * A `timedelta` object is directly used as timestep.

            outfile (str): netCDF4 file to store output.

            experiment (str): Experiment description (stored in netCDF output).

            writeevery (float, str or timedelta): Set output frequency.

                * float: Every nth day in model time
                * str: a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).
                * A `timedelta` object is directly used as timestep.
                * Note: Setting a value of `"0h"` will write after every iteration.

            writefor (None, float, str or timedelta): whenever the writing
                function is triggered because of 'writeevery', it will also be
                triggered for the next 'writefor' days

                * None: disable this functionality
                * float: for n days
                * str: a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).
                * A `timedelta` object is directly used as timestep.
                Defaults to None

            delta (float): Stop criterion. If the heating rate is below this
                threshold for all levels, skip further iterations. Values
                are given in K/day.

            radiation (konrad.radiation): Radiation model.
                Defaults to :class:`konrad.radiation.RRTMG`.

            ozone (konrad.ozone): Ozone model.
                Defaults to :class:`konrad.ozone.OzonePressure`.

            humidity (konrad.humidity): Humidity model.
                Defaults to :class:`konrad.humidity.FixedRH`.

            surface (konrad.surface): Surface model.
                Defaults to :class:`konrad.surface.SlabOcean`.

            cloud (konrad.cloud): Cloud model.
                Defaults to :class:`konrad.cloud.ClearSky`.

            convection (konrad.convection): Convection scheme.
                Defaults to :class:`konrad.convection.HardAdjustment`.

            lapserate (konrad.lapserate): Lapse rate handler.
                Defaults to :class:`konrad.lapserate.MoistLapseRate`.

            upwelling (konrad.upwelling): Upwelling model.
                Defaults to :class:`konrad.upwelling.NoUpwelling`.

            diurnal_cycle (bool): Toggle diurnal cycle of solar angle.

            co2_adjustment_timescale (int/float): Adjust CO2 concentrations
                towards an equilibrium state following Romps 2020.
                To be used with :class:`konrad.surface.FixedTemperature`.
                Recommended value is 7 (1 week).
                Defaults to no CO2 adjustment, with `np.nan`.

            logevery (int): Log the model progress at every nth iteration.
                Default is no logging.

                This keyword only affects the frequency with which the
                log messages are generated. You have to enable the logging
                by using the :py:mod:`logging` standard library or
                the `konrad.enable_logging()` convenience function.

            timestep_adjuster (callable): A callable object, that takes the
                current timestep and the temperature change as input
                to calculate a new timestep (`f(timestep, deltaT)`).

                Default (`None`) is keeping the given timestep fixed.
        """
        # Sub-models.
        self.atmosphere = atmosphere
        if radiation is None:
            self.radiation = RRTMG()
        else:
            self.radiation = radiation

        self.ozone = utils.return_if_type(ozone, 'ozone',
                                          Ozone, OzonePressure())

        self.humidity = FixedRH() if humidity is None else humidity
        self.surface = utils.return_if_type(surface, 'surface',
                                            Surface, SlabOcean())
        self.cloud = utils.return_if_type(cloud, 'cloud',
                                          Cloud,
                                          ClearSky(self.atmosphere['plev'].size)
                                          )

        self.convection = utils.return_if_type(convection, 'convection',
                                               Convection, HardAdjustment())

        self.lapserate = utils.return_if_type(lapserate, 'lapserate',
                                              LapseRate, MoistLapseRate())

        self.upwelling = utils.return_if_type(upwelling, 'upwelling',
                                              Upwelling, NoUpwelling())

        self.diurnal_cycle = diurnal_cycle

        self.timestep = utils.parse_fraction_of_day(timestep)
        self.time = datetime.datetime(1, 1, 1)  # Start model run at 0001/1/1
        self.max_duration = utils.parse_fraction_of_day(max_duration)
        self.niter = 0

        self.writeevery = utils.parse_fraction_of_day(writeevery)
        self.last_written = self.time

        self.writefor = utils.parse_fraction_of_day(writefor)

        self.logevery = logevery

        self.delta = delta
        self.deltaT = None
        self.converged = False

        self.outfile = outfile
        self.nchandler = None
        self.experiment = experiment

        self.co2_adjustment_timescale = co2_adjustment_timescale
        if not np.isnan(co2_adjustment_timescale) and not isinstance(
                surface, FixedTemperature):
            raise TypeError(
                "Runs with adjusting CO2 concentration "
                "require a fixed surface temperature."
                )

        self.timestep_adjuster = timestep_adjuster

        logging.info('Created Konrad object:\n{}'.format(self))
Example #3
0
    def __init__(self,
                 atmosphere,
                 timestep='3h',
                 max_duration='5000d',
                 outfile=None,
                 experiment='RCE',
                 writeevery='1d',
                 delta=1e-4,
                 radiation=None,
                 ozone=None,
                 humidity=None,
                 surface=None,
                 cloud=None,
                 convection=None,
                 lapserate=None,
                 upwelling=None,
                 diurnal_cycle=False,
                 co2_adjustment_timescale=np.nan):
        """Set-up a radiative-convective model.

        Parameters:

            atmosphere: :py:class:`konrad.atmosphere.Atmosphere`.

            timestep (float or str): Model time step (per iteration)

                * If float, time step in days.
                * If str, a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).

            max_duration (float or str): Maximum duration of the simulation
                The duration is given in model time

                * If float, maximum duration in days.
                * If str, a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).

            outfile (str): netCDF4 file to store output.

            experiment (str): Experiment description (stored in netCDF output).

            writeevery (int, float or str): Set output frequency.

                * int: Every nth iteration
                * float: Every nth day in model time
                * str: a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).

            delta (float): Stop criterion. If the heating rate is below this
                threshold for all levels, skip further iterations. Values
                are given in K/day.

            radiation (konrad.radiation): Radiation model.
                Defaults to :class:`konrad.radiation.RRTMG`.

            ozone (konrad.ozone): Ozone model.
                Defaults to :class:`konrad.ozone.OzonePressure`.

            humidity (konrad.humidity): Humidity model.
                Defaults to :class:`konrad.humidity.FixedRH`.

            surface (konrad.surface): Surface model.
                Defaults to :class:`konrad.surface.SurfaceHeatCapacity`.

            cloud (konrad.cloud): Cloud model.
                Defaults to :class:`konrad.cloud.ClearSky`.

            convection (konrad.convection): Convection scheme.
                Defaults to :class:`konrad.convection.HardAdjustment`.

            lapserate (konrad.lapserate): Lapse rate handler.
                Defaults to :class:`konrad.lapserate.MoistLapseRate`.

            upwelling (konrad.upwelling): Upwelling model.
                Defaults to :class:`konrad.upwelling.NoUpwelling`.

            diurnal_cycle (bool): Toggle diurnal cycle of solar angle.

            co2_adjustment_timescale (int/float): Adjust CO2 concentrations
                towards an equilibrium state following Romps 2020.
                To be used with :class:`konrad.surface.FixedTemperature`.
                Recommended value is 7 (1 week).
                Defaults to no CO2 adjustment, with `np.nan`.
        """
        # Sub-models.
        self.atmosphere = atmosphere
        if radiation is None:
            self.radiation = RRTMG()
        else:
            self.radiation = radiation

        self.ozone = utils.return_if_type(ozone, 'ozone', Ozone,
                                          OzonePressure())

        self.humidity = FixedRH() if humidity is None else humidity
        self.surface = utils.return_if_type(surface, 'surface', Surface,
                                            SlabOcean())
        self.cloud = utils.return_if_type(
            cloud, 'cloud', Cloud, ClearSky(self.atmosphere['plev'].size))

        self.convection = utils.return_if_type(convection, 'convection',
                                               Convection, HardAdjustment())

        self.lapserate = utils.return_if_type(lapserate, 'lapserate',
                                              LapseRate, MoistLapseRate())

        self.upwelling = utils.return_if_type(upwelling, 'upwelling',
                                              Upwelling, NoUpwelling())

        self.diurnal_cycle = diurnal_cycle
        self.max_duration = utils.parse_fraction_of_day(max_duration)
        self.timestep = utils.parse_fraction_of_day(timestep)
        self.writeevery = utils.parse_fraction_of_day(writeevery)

        self.max_iterations = np.ceil(self.max_duration / self.timestep)
        self.niter = 0

        self.delta = delta
        self.deltaT = None
        self.converged = False

        self.outfile = outfile
        self.nchandler = None
        self.experiment = experiment

        self.co2_adjustment_timescale = co2_adjustment_timescale
        if not np.isnan(co2_adjustment_timescale) and not isinstance(
                surface, FixedTemperature):
            raise TypeError("Runs with adjusting CO2 concentration "
                            "require a fixed surface temperature.")

        logging.info('Created Konrad object:\n{}'.format(self))
Example #4
0
    def __init__(self,
                 atmosphere,
                 timestep='3h',
                 max_duration='5000d',
                 outfile=None,
                 experiment='RCE',
                 writeevery='1d',
                 delta=1e-4,
                 radiation=None,
                 ozone=None,
                 humidity=None,
                 surface=None,
                 cloud=None,
                 convection=None,
                 lapserate=None,
                 upwelling=None):
        """Set-up a radiative-convective model.

        Parameters:

            atmosphere: :py:class:`konrad.atmosphere.Atmosphere`.

            timestep (float or str): Model time step (per iteration)

                * If float, time step in days.
                * If str, a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).

            max_duration (float or str): Maximum duration of the simulation
                The duration is given in model time

                * If float, maximum duration in days.
                * If str, a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).

            outfile (str): netCDF4 file to store output.

            experiment (str): Experiment description (stored in netCDF output).

            writeevery (int, float or str): Set output frequency.

                * int: Every nth iteration
                * float: Every nth day in model time
                * str: a timedelta string (see :func:`konrad.utils.parse_fraction_of_day`).

            delta (float): Stop criterion. If the heating rate is below this
                threshold for all levels, skip further iterations. Values
                are given in K/day.

            radiation (konrad.radiation): Radiation model.
                Defaults to :class:`konrad.radiation.RRTMG`.

            ozone (konrad.ozone): Ozone model.
                Defaults to :class:`konrad.ozone.OzonePressure`.

            humidity (konrad.humidity): Humidity model.
                Defaults to :class:`konrad.humidity.FixedRH`.

            surface (konrad.surface): Surface model.
                Defaults to :class:`konrad.surface.SurfaceHeatCapacity`.

            cloud (konrad.cloud): Cloud model.
                Defaults to :class:`konrad.cloud.ClearSky`.

            convection (konrad.convection): Convection scheme.
                Defaults to :class:`konrad.convection.HardAdjustment`.

            lapserate (konrad.lapserate): Lapse rate handler.
                Defaults to :class:`konrad.lapserate.MoistLapseRate`.

            upwelling (konrad.upwelling): Upwelling model.
                Defaults to :class:`konrad.upwelling.NoUpwelling`.

        """
        # Sub-models.
        self.atmosphere = atmosphere
        if radiation is None:
            self.radiation = RRTMG()
        else:
            self.radiation = radiation

        self.ozone = utils.return_if_type(ozone, 'ozone', Ozone,
                                          OzonePressure())

        self.humidity = FixedRH() if humidity is None else humidity
        self.surface = utils.return_if_type(surface, 'surface', Surface,
                                            SurfaceHeatCapacity())
        self.cloud = utils.return_if_type(
            cloud, 'cloud', Cloud, ClearSky(self.atmosphere['plev'].size))

        self.convection = utils.return_if_type(convection, 'convection',
                                               Convection, HardAdjustment())

        self.lapserate = utils.return_if_type(lapserate, 'lapserate',
                                              LapseRate, MoistLapseRate())

        self.upwelling = utils.return_if_type(upwelling, 'upwelling',
                                              Upwelling, NoUpwelling())

        self.max_duration = utils.parse_fraction_of_day(max_duration)
        self.timestep = utils.parse_fraction_of_day(timestep)
        self.writeevery = utils.parse_fraction_of_day(writeevery)

        self.max_iterations = np.ceil(self.max_duration / self.timestep)
        self.niter = 0

        self.delta = delta
        self.deltaT = None
        self.converged = False

        self.outfile = outfile
        self.nchandler = None
        self.experiment = experiment

        logging.info('Created Konrad object:\n{}'.format(self))