HenryDane / climlab

Python package for process-oriented climate modeling
MIT License
1 stars 0 forks source link

`AplusBT` breaks if its the only process. #3

Open HenryDane opened 1 year ago

HenryDane commented 1 year ago

Code to reproduce:

    state = climlab.column_state(num_lev=10)
    model = climlab.TimeDependentProcess(state=state)
    model.add_subprocess(climlab.radiation.aplusbt.AplusBT())

Resulting error:

AttributeError                            Traceback (most recent call last)
Cell In[7], line 2
      1 model = climlab.TimeDependentProcess(state=state)
----> 2 model.add_subprocess(climlab.radiation.aplusbt.AplusBT(state=state['Ts']))

File ~/Documents/_Feldl/climlab/climlab/radiation/aplusbt.py:90, in AplusBT.__init__(self, A, B, **kwargs)
     88 self.A = A
     89 self.B = B
---> 90 self.add_diagnostic('OLR', 0. * self.Ts)

AttributeError: 'AplusBT' object has no attribute 'Ts'
HenryDane commented 1 year ago

It also breaks if you do the setup with volume_state()

model = climlab.TimeDependentProcess(state=state)
model.add_subprocess('Sun', climlab.radiation.insolation.DailyInsolation(state=state.Ts))
model.add_subprocess('ABT', climlab.radiation.aplusbt.AplusBT(state={'Ts': state['Ts']}))

and reports this error when calling model.integrate_years():

KeyError                                  Traceback (most recent call last)
Cell In[26], line 1
----> 1 model.integrate_years()

File ~/Documents/_Feldl/climlab/climlab/process/time_dependent_process.py:419, in TimeDependentProcess.integrate_years(self, years, verbose)
    416 #  begin time loop
    417 for count in range(numsteps):
    418     # Compute the timestep
--> 419     self.step_forward()
    420     if count == 0:
    421         # on first step only...
    422         #  This implements a generic time-averaging feature
    423         # using the list of model state variables
    424         self.timeave = self.state.copy()

File ~/Documents/_Feldl/climlab/climlab/process/time_dependent_process.py:333, in TimeDependentProcess.step_forward(self)
    307 def step_forward(self):
    308     """Updates state variables with computed tendencies.
    309 
    310     Calls the :func:`compute` method to get current tendencies for all
   (...)
    331 
    332     """
--> 333     tenddict = self.compute()
    334     #  Total tendency is applied as an explicit forward timestep
    335     # (already accounting properly for order of operations in compute() )
    336     for varname, tend in tenddict.items():

File ~/Documents/_Feldl/climlab/climlab/process/time_dependent_process.py:212, in TimeDependentProcess.compute(self)
    210     self._build_process_type_list()
    211 tendencies = {}
--> 212 ignored = self._compute_type('diagnostic')
    213 tendencies['explicit'] = self._compute_type('explicit')
    214 #  Tendencies due to implicit and adjustment processes need to be
    215 #  calculated from a state that is already adjusted after explicit stuff
    216 #  So apply the tendencies temporarily and then remove them again

File ~/Documents/_Feldl/climlab/climlab/process/time_dependent_process.py:267, in TimeDependentProcess._compute_type(self, proctype)
    265     tenddict = proc.tendencies
    266 for name, tend in tenddict.items():
--> 267     tendencies[name] += tend
    268 for diagname, value in proc.diagnostics.items():
    269     self.__setattr__(diagname, value)

KeyError: 'default'
HenryDane commented 1 year ago

The AplusBT process needs to have a state supplied (e.g. AplusBT(state=state)).

HenryDane commented 1 year ago

This does work:

state = volume_state()
fstate = {'Ts' : state['Ts']} # "flatten" state (to only have surface stuff)
model = climlab.TimeDependentProcess(state=fstate)
model.add_subprocess('ABT', climlab.radiation.Boltzmann(state=fstate))
model.integrate_years()

but including the DailyInsolation breaks stuff.