A cooling coffee cup model with dependent parameters

Here we show an example (found in examples/coffee_cup_dependent/uq_coffee_dependent_function.py) where we examine a cooling coffee cup model with dependent parameters. We modify the simple cooling coffee cup model by introducing two auxillary variables \(\alpha\) and \(\hat{\kappa}\):

\[\kappa = \alpha\hat{\kappa}\]

to get:

\[\frac{dT(t)}{dt} = -\alpha\hat{\kappa}\left(T(t) - T_{env}\right).\]

The auxillary variables are made dependent by requiring that the model should be identical to the original model. We assume that \(\alpha\) is an uncertain scaling factor:

\[\alpha = \mathrm{Uniform}(0.5, 1.5),\]

and set:

\[\hat{\kappa} = \frac{\kappa}{\alpha}.\]

Which gives us the following distributions:

\[ \begin{align}\begin{aligned}\alpha &= \mathrm{Uniform}(0.5, 1.5)\\\hat{\kappa} &= \frac{\mathrm{Uniform}(0.025, 0.075)}{\alpha}\\T_{env} &= \mathrm{Uniform}(15, 25).\end{aligned}\end{align} \]

With Chaospy we can create these dependencies using arithmetic operators:

# Create the distributions
T_env_dist = cp.Uniform(15, 25)
alpha_dist = cp.Uniform(0.5, 1.5)
kappa_hat_dist = cp.Uniform(0.025, 0.075)/alpha_dist

# Define the parameters dictionary
parameters = {"alpha": alpha_dist,
              "kappa_hat": kappa_hat_dist,
              "T_env": T_env_dist}

We can use this parameters dictionary directly when we set up the uncertainty quantification

# We can use the parameters dictionary directly
# when we set up the uncertainty quantification
UQ = un.UncertaintyQuantification(model=model, parameters=parameters)

The Rosenblatt transformation is by default automatically used we have the parameters that are dependent. We also set the seed to easier be able to reproduce the result.

# We can use the parameters dictionary directly
# when we set up the uncertainty quantification
UQ = un.UncertaintyQuantification(model=model, parameters=parameters)

# Perform the uncertainty quantification,
# which automatically use the Rosenblatt transformation
# We set the seed to easier be able to reproduce the result
data = UQ.quantify(seed=10)

The complete code example become:

import uncertainpy as un
import chaospy as cp
import numpy as np
from scipy.integrate import odeint


# Create the coffee cup model function
def coffee_cup_dependent(kappa_hat, T_env, alpha):
    # Initial temperature and time
    time = np.linspace(0, 200, 150)            # Minutes
    T_0 = 95                                   # Celsius

    # The equation describing the model
    def f(T, time, alpha, kappa_hat, T_env):
        return -alpha*kappa_hat*(T - T_env)

    # Solving the equation by integration.
    temperature = odeint(f, T_0, time, args=(alpha, kappa_hat, T_env))[:, 0]

    # Return time and model results
    return time, temperature


# Create a model from the coffee_cup_dependent function and add labels
model = un.Model(coffee_cup_dependent, labels=["Time (s)", "Temperature (C)"])

# Create the distributions
T_env_dist = cp.Uniform(15, 25)
alpha_dist = cp.Uniform(0.5, 1.5)
kappa_hat_dist = cp.Uniform(0.025, 0.075)/alpha_dist

# Define the parameters dictionary
parameters = {"alpha": alpha_dist,
              "kappa_hat": kappa_hat_dist,
              "T_env": T_env_dist}

# We can use the parameters dictionary directly
# when we set up the uncertainty quantification
UQ = un.UncertaintyQuantification(model=model, parameters=parameters)

# Perform the uncertainty quantification,
# which automatically use the Rosenblatt transformation
# We set the seed to easier be able to reproduce the result
data = UQ.quantify(seed=10)

In this case, the distribution we assign to \(\alpha\) does not matter for the end result, as the distribution for \(\hat{\kappa}\) will be scaled accordingly. Using the Rosenblatt transformation, an uncertainty quantification and sensitivity analysis of the dependent coffee cup model therefore returns the same results as seen in the simple coffee cup model, where the role of the original \(\kappa\) is taken over by \(\hat{\kappa}\), while the sensitivity to the additional parameter \(\alpha\) becomes strictly zero.