Compute

Now that we have datasets added to our Bundle, our next step is to run the forward model and compute a synthetic model for each of these datasets.

Setup

Let's first make sure we have the latest version of PHOEBE 2.3 installed (uncomment this line if running in an online notebook session such as colab).


In [ ]:
#!pip install -I "phoebe>=2.3,<2.4"

In [1]:
import phoebe
from phoebe import u # units
import numpy as np
import matplotlib.pyplot as plt

logger = phoebe.logger()

b = phoebe.default_binary()

And we'll attach some dummy datasets. See the datasets tutorial for more details.


In [2]:
b.add_dataset('orb', 
              compute_times=phoebe.linspace(0,10,10), 
              dataset='orb01')

b.add_dataset('lc', 
              compute_times=phoebe.linspace(0,1,101),
              dataset='lc01')


Out[2]:
<ParameterSet: 43 parameters | contexts: dataset, compute, figure, constraint>

Default Compute Options

Any default Bundle already has a set of default compute options to run the backend for PHOEBE 2. In most cases, you can just edit the options in this default set of compte options.


In [3]:
print(b.computes)


['phoebe01']

In [4]:
print(b.filter(context='compute'))


ParameterSet: 18 parameters
  dynamics_method@phoebe01@co...: keplerian
           ltte@phoebe01@compute: False
   irrad_method@phoebe01@compute: horvat
  boosting_method@phoebe01@co...: none
  eclipse_method@phoebe01@com...: native
  horizon_method@phoebe01@com...: boolean
  mesh_method@primary@phoebe0...: marching
  mesh_method@secondary@phoeb...: marching
  ntriangles@primary@phoebe01...: 1500
  ntriangles@secondary@phoebe...: 1500
  distortion_method@primary@p...: roche
  distortion_method@secondary...: roche
    atm@primary@phoebe01@compute: ck2004
  atm@secondary@phoebe01@compute: ck2004
  enabled@orb01@phoebe01@compute: True
   enabled@lc01@phoebe01@compute: True
      lc_method@phoebe01@compute: numerical
     fti_method@phoebe01@compute: none

In [5]:
b.set_value('irrad_method', 'none')

Adding Compute Options

In other cases, we may want to manually add additional sets of compute options. This syntax should look very familiar by now, it takes a function (or the name of a recognized function in phoebe.parameters.compute) and then any kwargs to set in that ParameterSet, passed to b.add_compute.

Let's say that we want to create two sets of compute options - in this example, we'll create one called 'preview' which will cut some corners to quickly get us a model, and one called 'detailed' which will get a much more precise model but likely take longer. As with other tags, the string you provide for the compute tag is up to you (so long as it doesn't raise an error because it conflicts with other tags).


In [6]:
b.add_compute(phoebe.compute.phoebe, compute='preview', irrad_method='none')


Out[6]:
<ParameterSet: 30 parameters | datasets: _default, orb01, lc01>

In [7]:
print(b['preview@compute'])


ParameterSet: 18 parameters
  dynamics_method@preview@com...: keplerian
            ltte@preview@compute: False
    irrad_method@preview@compute: none
  boosting_method@preview@com...: none
  eclipse_method@preview@compute: native
  horizon_method@preview@compute: boolean
   enabled@orb01@preview@compute: True
    enabled@lc01@preview@compute: True
  mesh_method@primary@preview...: marching
  mesh_method@secondary@previ...: marching
  ntriangles@primary@preview@...: 1500
  ntriangles@secondary@previe...: 1500
  distortion_method@primary@p...: roche
  distortion_method@secondary...: roche
     atm@primary@preview@compute: ck2004
   atm@secondary@preview@compute: ck2004
       lc_method@preview@compute: numerical
      fti_method@preview@compute: none

In [8]:
b.add_compute('phoebe', compute='detailed', irrad_method='wilson')


Out[8]:
<ParameterSet: 30 parameters | datasets: _default, orb01, lc01>

In [9]:
print(b.get_compute('detailed'))


ParameterSet: 18 parameters
  dynamics_method@detailed@co...: keplerian
           ltte@detailed@compute: False
   irrad_method@detailed@compute: wilson
  boosting_method@detailed@co...: none
  eclipse_method@detailed@com...: native
  horizon_method@detailed@com...: boolean
  enabled@orb01@detailed@compute: True
   enabled@lc01@detailed@compute: True
  mesh_method@primary@detaile...: marching
  mesh_method@secondary@detai...: marching
  ntriangles@primary@detailed...: 1500
  ntriangles@secondary@detail...: 1500
  distortion_method@primary@d...: roche
  distortion_method@secondary...: roche
    atm@primary@detailed@compute: ck2004
  atm@secondary@detailed@compute: ck2004
      lc_method@detailed@compute: numerical
     fti_method@detailed@compute: none

Editing Compute Options

Backend-Specific Compute Options

Most of the parameters in the compute options are specific to the backend being used. Here, of course, we're using the PHOEBE 2.0 backend - but for details on other backends see the Advanced: Alternate Backends Tutorial.

The PHOEBE 2.0 compute options are described in the tutorial on their relevant dataset types:

Enabling/Disabling Datasets

By default, synthetic models will be created for all datasets in the Bundle when run_compute is called. But you can disable a dataset to have run_compute ignore that dataset. This is handled by a BoolParameter with the qualifier 'enabled' - and has a copy that lives in each set of compute options

Let's say we wanted to compute the orbit but not light curve - so we want to set enabled@lc01:


In [10]:
print(b['enabled@lc01'])


ParameterSet: 3 parameters
   enabled@lc01@phoebe01@compute: True
    enabled@lc01@preview@compute: True
   enabled@lc01@detailed@compute: True

as you can see, there is a copy for both of our compute options ('preview' and 'detailed').

If we know which set of compute options we'll be using, or only want to enable/disable for a given set, then we can do that:


In [11]:
b['enabled@lc01@preview'] = False
print(b['enabled@lc01'])


ParameterSet: 3 parameters
   enabled@lc01@phoebe01@compute: True
    enabled@lc01@preview@compute: False
   enabled@lc01@detailed@compute: True

or to enable/disable a dataset for all sets of compute options, we can use the set_value_all method:


In [12]:
b.set_value_all('enabled@lc01', True)
print(b['enabled@lc01'])


ParameterSet: 3 parameters
   enabled@lc01@phoebe01@compute: True
    enabled@lc01@preview@compute: True
   enabled@lc01@detailed@compute: True

If the enabled parameter is missing for a set of compute options - it is likely that that particular backend does not support that dataset type.

Running Compute

run_compute takes arguments for the compute tag as well as the model tag for the resulting synthetic model(s).

You do not need to provide the compute tag if only 0 or 1 set of compute options exist in the Bundle. If there are no compute options, the default PHOEBE 2 options will be added on your behalf and used. If there is a single set of compute options, those will be assumed. In our case, we have two compute options in the Bundle (with tags 'preview' and 'detailed') so we must provide an argument for compute.

If you do not provide a tag for the model, one will be created for you called 'latest'. Note that the 'latest' model will be overwritten without throwing any errors, whereas other named models can only be overwritten if you pass overwrite=True (see the run_compute API docs for details). In general, though, if you want to maintain the results from previous calls to run_compute, you must provide a NEW model tag.


In [13]:
b.run_compute(compute='preview')


Out[13]:
<ParameterSet: 18 parameters | contexts: model, figure>

In [14]:
print(b.models)


['latest']

Storing/Tagging Models

Now let's compute models for three different 'versions' of parameters. By providing a model tag, we can keep the synthetics for each of these different runs in the bundle - which will be handy later on for plotting and comparing models.


In [15]:
b.set_value('incl@orbit', 90)
b.run_compute(compute='preview', model='run_with_incl_90')


Out[15]:
<ParameterSet: 18 parameters | contexts: model, figure>

In [16]:
b.set_value('incl@orbit', 85)
b.run_compute(compute='preview', model='run_with_incl_85')


Out[16]:
<ParameterSet: 18 parameters | contexts: model, figure>

In [17]:
b.set_value('incl@orbit', 80)
b.run_compute(compute='preview', model='run_with_incl_80')


Out[17]:
<ParameterSet: 18 parameters | contexts: model, figure>

We will now have three new sets of synthetics which can be compared, plotted, or removed.


In [18]:
print(b.models)


['latest', 'run_with_incl_90', 'run_with_incl_85', 'run_with_incl_80']

To remove a model, call remove_model.


In [19]:
b.remove_model('latest')


Out[19]:
<ParameterSet: 16 parameters | kinds: orb, lc>

In [20]:
print(b.models)


['latest', 'run_with_incl_90', 'run_with_incl_85', 'run_with_incl_80']

Accessing Synthetics from Models

The synthetics can be accessed by their dataset and model tags.


In [32]:
b['run_with_incl_90']


Out[32]:
<ParameterSet: 18 parameters | contexts: model, figure>

In [33]:
b['primary@run_with_incl_90']


Out[33]:
<ParameterSet: 7 parameters | qualifiers: vvs, us, times, vs, ws, vus, vws>

In [34]:
b['us@primary@run_with_incl_90']


Out[34]:
<Parameter: us=[ 1.62265701e-16 -1.70338717e+00 -2.60974055e+00 ...
  2.60974055e+00  1.70338717e+00  2.07569028e-14] solRad | keys: description, value, default_unit, visible_if, copy_for, allow_none>

or of course through method access:


In [35]:
print(b.get_value(qualifier='us', dataset='orb01', component='primary', model='run_with_incl_90')[:10])


[ 1.62265701e-16 -1.70338717e+00 -2.60974055e+00 -2.29496732e+00
 -9.06353380e-01  9.06353380e-01  2.29496732e+00  2.60974055e+00
  1.70338717e+00  2.07569028e-14]

For more details about the resulting Parameters in the model context, see the tutorial on the relevant dataset types:

Next

Next up: let's start plotting our synthetic model.

Or look at any of these advanced topics related to computing observables: