"""
Package which defines a large set of variables and functions to process them.
The variables defined are divided into three types:
*Running variables: they store information which is overwritten in each following iteration step
*Static variables: they are non-changing system properties
*Storage variables: these are lists filled with system properties during a model run
The centre piece of this package is the class ``Variables.Vars``:
.. autosummary::
:toctree:
:nosignatures:
Vars
All variables defined in ``Variable.Vars`` can be read and written with::
from lowEBMs.Packages.Variable import Vars
Vars.x #returns the current value of variable x in Vars
Vars.x = y #variable x in Vars is permanently set to value y
Functions to process variables before a simulation run are, for single simulations
.. autosummary::
:toctree:
:nosignatures:
variable_importer
builtin_importer
initial_importer
output_importer
and for parallelized ensemble simulations
.. autosummary::
:toctree:
:nosignatures:
variable_importer_parallelized
builtin_importer_parallelized
initial_importer_parallelized
output_importer_parallelized
.. Important::
``Variables.variable_importer`` and executes the in the list following processing functions which has to be executed before a simulation can be run for more information see :doc:`How to use <howtouse>`). For parallelized simulations this can be swapped to ``Variables.variable_importer_parallelized``.
Functions to process variables during or after a simulation run are:
.. autosummary::
:toctree:
:nosignatures:
reset
datareset
"""
import builtins
import numpy as np
from qualname import qualname
#import xarray as xr
[docs]class Vars():
"""
``Variables.Vars`` defines any variable desired to store and access from another module's functions.
There are three different types of variables defined.
**Running variables:**
+---------------+-----------------------------------------------------------------------+
| t | The time in the simulation (in steps of the builtins.stepsize_of_integration) |
+---------------+-----------------------------------------------------------------------+
| T | The ZMT temperature |
+---------------+-----------------------------------------------------------------------+
| T_global | The GMT temperature |
+---------------+-----------------------------------------------------------------------+
| orbitals | The orbital parameters for the current simulation time t |
+---------------+-----------------------------------------------------------------------+
| noise | The noise factor on the solar insolation term |
+---------------+-----------------------------------------------------------------------+
| ForcingTracker| The current index and value of the external forcing's input list |
+---------------+-----------------------------------------------------------------------+
| CO2Tracker | The current index and value of the CO2 forcing's input list |
+---------------+-----------------------------------------------------------------------+
| meridional | The meridional wind pattern (from ``earthsystem.meridionalwind_sel``) |
+---------------+-----------------------------------------------------------------------+
| tempdif | The temperature difference between entries of the ZMT |
+---------------+-----------------------------------------------------------------------+
**Static variables:**
+-----------------------+-----------------------------------------------------------------------+
| Lat | The latitudes of the gridpoints (or ZMT) |
+-----------------------+-----------------------------------------------------------------------+
| Lat2 | The latitudes of the centres between gridpoints (or centered ZMT) |
+-----------------------+-----------------------------------------------------------------------+
| solar | The distribution of solar insolation |
+-----------------------+-----------------------------------------------------------------------+
| orbtable | The lookup-table for orbital parameters (from ``climlab``) |
+-----------------------+-----------------------------------------------------------------------+
| area | The area of a latitudinal belt |
+-----------------------+-----------------------------------------------------------------------+
| bounds | The boundary latitudes used to calculate **Area** |
+-----------------------+-----------------------------------------------------------------------+
| latlength | The circumference of a latitudinal circle |
+-----------------------+-----------------------------------------------------------------------+
| External_time_start | The simulation time when the external forcing sets in |
+-----------------------+-----------------------------------------------------------------------+
| CO2_time_start | The simulation time when the CO2 forcing sets in |
+-----------------------+-----------------------------------------------------------------------+
| start_time | The real clock time when the simulation was started |
+-----------------------+-----------------------------------------------------------------------+
**Storage variables:**
+---------------+-----------------------------------------------------------------------+
| cL | The sellers watervapour energy transfer |
+---------------+-----------------------------------------------------------------------+
| C | The sellers atmospheric sensible heat energy transfer |
+---------------+-----------------------------------------------------------------------+
| F | The sellers oceanic sensible heat energy transfer |
+---------------+-----------------------------------------------------------------------+
| P | The total energy transfer , P=cL+C+F (non-weighted, one direction) |
+---------------+-----------------------------------------------------------------------+
| Transfer | The total sellers energy transfer for a latitudinal belt |
+---------------+-----------------------------------------------------------------------+
| BudTransfer | The budyko energy transfer for a latitudinal belt |
+---------------+-----------------------------------------------------------------------+
| alpha | The alpha value distribution |
+---------------+-----------------------------------------------------------------------+
| Rdown | The downward radiative energy flux |
+---------------+-----------------------------------------------------------------------+
| Rup | The upward radiative energy flux |
+---------------+-----------------------------------------------------------------------+
| ExternalOutput| List of radiative forcings |
+---------------+-----------------------------------------------------------------------+
| CO2Output | The CO2 radiative forcing |
+---------------+-----------------------------------------------------------------------+
| ExternalInput | List of the raw input to calculate the radiative forcing |
+---------------+-----------------------------------------------------------------------+
| CO2Input | The raw CO2 input |
+---------------+-----------------------------------------------------------------------+
"""
###Running variables -- RK4###
t=float
T=float
T_global=float
###Running variables###
orbitals=float
solar=list
alpha=list
noise=float
ForcingTracker=[0,0]
CO2Tracker=[0,0]
SolarTracker=[0,0]
AODTracker=[0,0]
OrbitalTracker=[0,{'ecc': 0, 'long_peri': 0, 'obliquity': 0}]
meridional=list
tempdif=list
TSI=float
AOD=float
###Static variables###
Lat=float
Lat2=float
orbtable=float
area=list
bounds=list
latlength=list
External_time_start=float
CO2_time_start=float
ExternalOrbitals_time_start=float
Solar_time_start=float
AOD_time_start=float
start_time=float
###Storage variables###
cL=list
C=list
F=list
P=list
Transfer=list
BudTransfer=list
Rdown=list
Rup=list
ExternalOutput=list
ExternalInput=list
CO2Output=list
CO2Input=list
ExternalOrbitals=list
SolarInput=list
SolarOutput=list
AODInput=list
AODOutput=list
Read=dict #{'cL':cL, 'C': C, 'F': F,'P': P,'Transfer': Transfer,'alpha': alpha,'BudTransfer': BudTransfer,'Solar':,Noise,Rdown,Rup,ExternalOutput,CO2Forcing]
###Variables initial values### (for reset)
def __init__(self):
self.t=float
self.T=float
self.T_global=float
self.Lat=float
self.Lat2=float
self.start_time=float
self.orbitals=float
self.orbtable=float
self.noise=float
self.ForcingTracker=[0,0]
self.CO2Tracker=[0,0]
self.SolarTracker=[0,0]
self.AODTracker=[0,0]
self.OrbitalTracker=[0,{'ecc': 0, 'long_peri': 0, 'obliquity': 0}]
self.meridional=list
self.tempdif=list
self.TSI=float
self.AOD=float
self.solar=list
self.area=list
self.bounds=list
self.latlength=list
self.External_time_start=float
self.CO2_time_start=float
self.ExternalOrbitals_time_start=float
self.Solar_time_start=float
self.AOD_time_start=float
self.start_time=float
self.cL=list
self.C=list
self.F=list
self.P=list
self.Transfer=list
self.BudTransfer=list
self.alpha=list
self.Rin=list
self.Rout=list
self.ExternalOutput=list
self.ExternalInput=list
self.CO2Output=list
self.CO2Input=list
self.ExternalOrbitals=list
self.SolarInput=list
self.SolarOutput=list
self.AODInput=list
self.AODOutput=list
self.Read=dict #[self.cL,self.C,self.F,self.P,self.Transfer,self.alpha,self.BudTransfer,self.Solar,self.Noise,self.Rin,self.Rout,self.ExternalOutput,self.CO2Forcing]
def trackerreset():
reset('ForcingTracker')
Vars.ForcingTracker=np.array([Vars.ForcingTracker for i in range(int(builtins.number_of_externals))],dtype=object)
reset('CO2Tracker')
reset('SolarTracker')
reset('OrbitalTracker')
reset('AODTracker')
[docs]def reset(x):
"""
Resets the given variable to the initial value specified in Vars.__init__.
**Function-call arguments** \n
:param float/list x: The variable which shall be reset to the initial value
:returns: No return
"""
classreset=Vars()
exec("Vars.%s=classreset.%s" % (x,x))
[docs]def datareset():
"""
Resets the *primary variables* to their initial values. The *primary variables* are variables defined under the``[initials]``-section in the *configuration.ini-file*. These are:
+---------------+-----------------------------------------------------------------------+
| t | The time in the simulation (in steps of the builtins.stepsize_of_integration) |
+---------------+-----------------------------------------------------------------------+
| T | The ZMT temperature |
+---------------+-----------------------------------------------------------------------+
| T_global | The GMT temperature |
+---------------+-----------------------------------------------------------------------+
| Lat | The latitudes of the gridpoints (or ZMT) |
+---------------+-----------------------------------------------------------------------+
| Lat2 | The latitudes of the centres between gridpoints (or centered ZMT) |
+---------------+-----------------------------------------------------------------------+
"""
classreset=Vars()
Vars.t=classreset.t
Vars.T=classreset.T
Vars.T_global=classreset.T_global
Vars.Lat=classreset.Lat
Vars.Lat2=classreset.Lat2
[docs]def variable_importer(config,initialZMT=True,control=False,parallel=False,parallel_config=0,accuracy=1e-3,accuracy_number=1000):
"""
Executes all relevant functions to import variables for a single simulation run. From the *configuration* dictionary, returned by ``Configuration.importer``, the relevant information is extracted and the specific importer functions are executed in the following order:
.. math::
buliltin \_ importer \quad \\rightarrow \quad initial \_ importer \quad \\rightarrow \quad output \_ importer
.. Note::
When doing this manually, maintain the order!
**Function-call arguments** \n
:param dict config: The configuration dictionary returned by ``Configuration.importer``
:returns: No return
"""
builtin_importer(config['rk4input'],control=control,parallel=parallel,parallel_config=parallel_config,accuracy=accuracy,accuracy_number=accuracy_number)
trackerreset()
initial_importer(config['initials'],initialZMT=initialZMT,control=control,parallel=parallel)
output_importer(config['funccomp']['funclist'])
[docs]def builtin_importer(rk4input,control=False,parallel=False,parallel_config=0,accuracy=1e-3,accuracy_number=1000):
"""
Adds the most important variables to the python-builtin functions which are globally accessible. This enables calling and writing variables globally and across different files.
Variables added to the builtin-functions are all arguments of the ``[rk4input]``-section from the *configuration* dictionary, returned by ``Configuration.importer``, and three additional ones.
.. Important::
Variables from the ``[rk4input]``-section are added with their key given in the *configuration.ini-file* and can be called by the same one later.
Here all added variables (``[rk4input]``-variables + additional ones):
+---------------------------+-----------------------------------------------------------------------+
| builtins.number_of_integration | Number of iterations to perfom |
+---------------------------+-----------------------------------------------------------------------+
| builtins.stepsize_of_integration | Time steps of one iteration steps |
+---------------------------+-----------------------------------------------------------------------+
| builtins.spatial_resolution | Grid resolution (width of one latitudinal band in degree) |
+---------------------------+-----------------------------------------------------------------------+
| builtins.both_hemispheres | Indicates if both hemispheres or northern hemisphere is modeled |
+---------------------------+-----------------------------------------------------------------------+
| builtins.latitudinal_circle | Indicates that the temperature is defined on latitudinal circles |
+---------------------------+-----------------------------------------------------------------------+
| builtins.latitudinal_belt | Indicates that the temperature is defined on latitudinal belts |
+---------------------------+-----------------------------------------------------------------------+
| eq_condition | Activation/Deactivation of stop criterion (equilibrium condition) |
+---------------------------+-----------------------------------------------------------------------+
| eq_condition_length | The number of last datapoints to be compared with the predefined limit|
+---------------------------+-----------------------------------------------------------------------+
| eq_condition_amplitude | The predefined limiting value which defines the stop criterion |
+---------------------------+-----------------------------------------------------------------------+
| builtins.data_readout | The number of iterations between data-readout |
+---------------------------+-----------------------------------------------------------------------+
| builtins.number_of_externals | The number of external forcings are used |
+---------------------------+-----------------------------------------------------------------------+
+---------------------------+-----------------------------------------------------------------------+
| Runtime_Tracker | Tracks the iteration and cycle step (builtins.number_of_integration*4) |
+---------------------------+-----------------------------------------------------------------------+
| Noise_Tracker | Tracks the value of solar noise |
+---------------------------+-----------------------------------------------------------------------+
| parallelization | Indicates if parallelized simulations are enabled |
+---------------------------+-----------------------------------------------------------------------+
**Function-call arguments** \n
:param dict rk4input: The ``[rk4input]``-section from the configuration dictionary returned by ``Configuration.importer``
:returns: No return
"""
#Writing systemparameters into builtin-module to make them globally callable
#Overview given in Readme.txt
keys=list(rk4input.keys())
values=list(rk4input.values())
for i in range(len(keys)):
exec("builtins.%s=%f" % (keys[i],values[i]))
builtins.Runtime_Tracker=0
builtins.Readout_Tracker=0
builtins.Noise_Tracker=0
if parallel==True:
builtins.parallelization=True
if parallel_config==0:
print('Specify the parallelization configuration file!')
keys_parallel=list(parallel_config.keys())
values_parallel=list(parallel_config.values())
for i in range(len(keys_parallel)):
exec("builtins.%s=%i" % (keys_parallel[i],values_parallel[i]))
else:
builtins.parallelization=False
if control==True:
builtins.control=True
builtins.eq_condition=True
builtins.number_of_integration=100000
builtins.data_readout=1
builtins.eq_condition_length=accuracy_number
builtins.eq_condition_amplitude=accuracy
print('Starting controlrun with a temperature accuracy of %s K on the GMT over %s datapoints.' %(accuracy,accuracy_number))
else:
builtins.control=False
[docs]def initial_importer(initials,initialZMT=True,control=False,parallel=False):
"""
Calculates the initial conditions of the *primary variables* from the ``initials``-section.
The initial conditions are directly written to their entry in ``Variable.Vars``.
**Function-call arguments** \n
:param dict initials: The ``[initials]``-section from the configuration dictionary returned by ``Configuration.importer``
:returns: No return
"""
from lowEBMs.Packages.Functions import cosd, lna
###filling the running variables with values depending on the systemconfiguration in rk4input###
if builtins.spatial_resolution==0:
dim=0
print('0D')
Vars.T=initials['zmt']
else:
dim=1
#NS==True corresponds to southpole to northpole representation (180 Degrees)
if builtins.both_hemispheres==True:
Latrange=180
#Checking if Temperature and Latitude is set on a latitudal circle (0°,10°,..if step=10)
#or on a latitudinal belt and therefore between the boundaries (5°,15°,..if step=10)
#circle==True and belt==False says on the latitudinal circle
if builtins.latitudinal_circle==True and builtins.latitudinal_belt==False:
Vars.Lat=np.linspace(-90+builtins.spatial_resolution,90-builtins.spatial_resolution,int(Latrange/builtins.spatial_resolution-1))
Vars.Lat2=np.linspace(-90,90-builtins.spatial_resolution,int(Latrange/builtins.spatial_resolution))+builtins.spatial_resolution/2
if initialZMT==True:
Vars.T=np.array([initials['zmt']]*int(Latrange/builtins.spatial_resolution-1))
#Checking if the Temperature for each latitude starts with the same value or a
#cosine shifted value range
if initials['initial_temperature_cosine']==True:
Vars.T=Vars.T+initials['initial_temperature_amplitude']*(cosd(Vars.Lat)-1)
#circle==False and belt==True say on the latitudinal belt
if builtins.latitudinal_circle==False and builtins.latitudinal_belt==True:
Vars.Lat2=np.linspace(-90+builtins.spatial_resolution,90-builtins.spatial_resolution,int(Latrange/builtins.spatial_resolution-1))
Vars.Lat=np.linspace(-90,90-builtins.spatial_resolution,int(Latrange/builtins.spatial_resolution))+builtins.spatial_resolution/2
if initialZMT==True:
Vars.T=np.array([initials['zmt']]*int(Latrange/builtins.spatial_resolution))
if initials['initial_temperature_cosine']==True:
if initials['initial_temperature_noise']==True:
z=[0]*len(Vars.Lat)
for k in range(len(Vars.Lat)):
z[k]=np.random.normal(0,initials['initial_temperature_noise_amplitude'])
else:
z=0
Vars.T=Vars.T+initials['initial_temperature_amplitude']*(cosd(Vars.Lat)-1)+lna(z)
#Not from southpole to northpole rather equator to pole
else:
Latrange=90
if builtins.latitudinal_circle==True and builtins.latitudinal_belt==False:
Vars.Lat=np.linspace(0,90-builtins.spatial_resolution,int(Latrange/builtins.spatial_resolution))
Vars.Lat2=np.linspace(0,90-builtins.spatial_resolution,int(Latrange/builtins.spatial_resolution))+builtins.spatial_resolution/2
if initialZMT==True:
Vars.T=np.array([initials['zmt']]*int(Latrange/builtins.spatial_resolution))
if initials['initial_temperature_cosine']==True:
Vars.T=Vars.T+initials['initial_temperature_amplitude']*(cosd(Vars.Lat)-1)
if builtins.latitudinal_circle==False and builtins.latitudinal_belt==True:
Vars.Lat2=np.linspace(0,90-builtins.spatial_resolution,int(Latrange/builtins.spatial_resolution))
Vars.Lat=np.linspace(0,90-builtins.spatial_resolution,int(Latrange/builtins.spatial_resolution))+builtins.spatial_resolution/2
if initialZMT==True:
Vars.T=np.array([initials['zmt']]*int(Latrange/builtins.spatial_resolution))
if initials['initial_temperature_cosine']==True:
Vars.T=Vars.T+initials['initial_temperature_amplitude']*(cosd(Vars.Lat)-1)
Vars.t=initials['time']
if parallel==True:
if initialZMT==True:
Vars.T=np.array([Vars.T]*number_of_parallels)
Vars.T_global=np.array([initials['gmt']]*number_of_parallels)
else:
Vars.T_global=initials['gmt']
[docs]def output_importer(functiondict):
functionlist=list(functiondict.values())
"""
Creates empty lists for the storage-variables which will be filled during the simulation.
The lists are directly written to their entry in ``Variable.Vars`` and can be returned after the simulation is finished.
"""
if (builtins.number_of_integration) % builtins.data_readout == 0:
#Assigning dynamical variables in Variables Package with initial values from var
for func in functionlist:
if qualname(func)=='transfer.sellers':
Vars.cL=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
Vars.C=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
Vars.F=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
Vars.P=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
Vars.Transfer=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
if qualname(func)=='transfer.budyko':
Vars.BudTransfer=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
if qualname(func)=='forcing.co2_myhre':
Vars.CO2Output=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
if qualname(func)=='forcing.solar':
Vars.SolarOutput=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
if qualname(func)=='forcing.aod':
Vars.AODOutput==np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
Vars.ExternalOutput=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
Vars.alpha=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
Vars.solar=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
Vars.noise=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
Vars.Rdown=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
#Vars.Rup=np.reshape(np.zeros(int(builtins.number_of_integration/builtins.data_readout)*len(Vars.Lat)),(int(builtins.number_of_integration/builtins.data_readout),len(Vars.Lat)))
Vars.Rup=np.array([0]*int(builtins.number_of_integration/builtins.data_readout),dtype=object)
else:
for func in functionlist:
if qualname(func)=='transfer.sellers':
Vars.cL=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
Vars.C=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
Vars.F=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
Vars.P=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
Vars.Transfer=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
if qualname(func)=='transfer.budyko':
Vars.BudTransfer=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
if qualname(func)=='forcing.co2_myhre':
Vars.CO2Output=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
if qualname(func)=='forcing.solar':
Vars.SolarOutput=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
if qualname(func)=='forcing.aod':
Vars.AODOutput==np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
Vars.ExternalOutput=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
Vars.alpha=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
Vars.solar=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
Vars.noise=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
Vars.Rdown=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
#Vars.Rup=np.reshape(np.zeros(int(builtins.number_of_integration/builtins.data_readout)*len(Vars.Lat)),(int(builtins.number_of_integration/builtins.data_readout),len(Vars.Lat)))
Vars.Rup=np.array([0]*int(builtins.number_of_integration/builtins.data_readout+1),dtype=object)
Vars.ExternalOutput=np.array([Vars.ExternalOutput for i in range(int(builtins.number_of_externals))],dtype=object)
Vars.External_time_start=np.array([0 for i in range(int(builtins.number_of_externals))],dtype=object)
Vars.ForcingTracker=np.array([[0,0] for i in range(int(builtins.number_of_externals))],dtype=object)
Vars.ExternalInput=np.array([0 for i in range(int(builtins.number_of_externals))],dtype=object)
Vars.Read={'cL': Vars.cL,'C': Vars.C,'F': Vars.F,'P': Vars.P,'Transfer': Vars.Transfer,'alpha': Vars.alpha,'BudTransfer': Vars.BudTransfer, 'solar': Vars.solar,'noise': Vars.noise,'Rdown': Vars.Rdown,'Rup': Vars.Rup, 'ExternalOutput': Vars.ExternalOutput,'CO2Output': Vars.CO2Output,'SolarOutput':Vars.SolarOutput,'AODOutput':Vars.AODOutput}