Tutorial 15: Variable Retirement and Servicing
How to specify variable hazard rates for complex retirement and servicing patterns.Contents
Motivation
In prior tutorials, we mentioned that a 5% retirement rate corresponds to a 20 year expected lifespan. However, in practice some equipment will retire before 20 years and some after. That in mind, how does Kigali Sim actually interpret that 5% directive? In survivor analysis, we specifically say that this is a constant "hazards rate" meaning that, each year, each unit of equipment has a 5% chance of retiring. In practice, this makes sense for many countries which may not know the specific age of equipment already in service or might not have a good estimate for how the rate of failure changes over time. With few assumptions, we still get realistic dynamics like a long tail of equipment on phase out and some retirement prior to the amortized lifespan estimate.
All that said, Kigali Sim can take in more sophisticated estimates if available. The simplest option is to give an average equipment lifetime and let Kigali Sim apply a Weibull survival curve whose hazard rises with age, which is what empirical studies of refrigeration and air-conditioning equipment tend to find. In this tutorial, we will build a simulation that reaches back to 1990 which we assume to be the first year in which the equipment we are studying appeared within the country. Then, for those with just a little extra modeling background, we will optionally make a more sophisticated model to fit some information one might have about equipment even if maybe you don't know the exact hazard function.
This tutorial will use the QubecTalk code-based editor in parts. However, the mean lifetime form can be entered through the UI-based editor as well by choosing "year old (mean life, Weibull)" as the retirement units, and formulas can be typed into any numeric retirement field in the UI-based editor.
Using default assumptions
Before we consider the complex lifecycle, let's set up a simplier simulation in which we model HFC-134a (1 kg / unit initial charge and no servicing). In order to observe how retirement works, let's have 1990 with one million (1,000,000) units of equipment sales but no sales in 1991 onwards. Let's assume a 5% retirement rate and simulate a business as usual scenario from 1990 to 2020.
We see that equipment does drop. However, if we took the 5% as 20 year lifespan seriously, we wouldn't have any population (see bank and set to units of equipment) after 2010. Instead, we see that some equipment keeps "getting lucky" and surviving that annual retirement probability (hazard rate) of 5%. This is like how you aren't guaranteed to have a heads on a coin after two flips.
Note that what we have written here is a survival model with a constant hazard. Mathematically, this is the Weibull distribution with shape (k) of 1. Every unit faces the same 5% chance each year no matter its age. The average lifetime is 20 years, but the median unit retires after only 13.9.
To see this effect, please have bank selected with units of equipment.
Retirement with a mean lifetime
Many studies, surveys, and emissions models report equipment lifetime as a single number. For example, a 20 year mean life for commercial refrigeration. Kigali Sim can use that number directly. Give the mean lifetime in years and it can apply a Weibull survival curve (shape or k of 2) whose hazard rises with age:
uses substance "HFC-134a"
enable import
initial charge with 0 kg / unit for domestic
initial charge with 1 kg / unit for import
initial charge with 0 kg / unit for export
equals 1430 kgCO2e / kg
equals 1 kwh / unit
set import to 1,000,000 units during year 1990
set import to 0 units during year 1991
retire 20 year old mean weibull
end substance
Running this from 1990 to 2020 shows retirement concentrated around the middle of the distribution instead of the long "getting lucky" tail of the flat rate: 61% of the cohort is still in service at age 16 and 17% at age 30. With a 20 year mean, the annual hazard is 0.2% in a unit's first year of service, 3.7% at age 10, and 7.4% at age 20. Comparing the two shapes at the same 20 year mean lifetime:
| Shape 1 (flat 5% / year) | Shape 2 (Weibull mean) | |
|---|---|---|
| Median retirement age | 13.9 years | 18.8 years |
| Still in service at 10 years | 61% | 82% |
| Most likely retirement age | 1 (never rises) | 16 years |
Under constant sales, both shapes reach the same steady state: annual sales multiplied by the mean lifetime. The difference is in the transients and in growing markets. In a fleet growing 5% per year with a 20 year mean life, the flat 5% hazard keeps retiring 5% of the stock each year. Meanwhile, the Weibull model retires only about 3.5% because a growing fleet is a young fleet and young cohorts face low hazard.
This approach is very effective. However, note that, because Kigali Sim derives equipment ages from simulated sales so we have to begin the simulation earlier. In other words, we have to have ages for all of the equipment. If a model instead enters existing stock directly with set priorEquipment, combining that with a Weibull retire raises an error at validation time since the ages of those units are unknown. You might do this because you don't know the equipment age distribution. In that situation, it's often best to fall back to a flat rate such as retire 5 % / year. However, you can also add the assuming new modifier (code-based editor only) which treats the existing stock as a single cohort of typical age.
Other shapes
You can use other shapes of this distribution through a custom formula using "get new equipment" which is further described in the exact retirement schedule section. We offer this k = 1 and k = 2 as common but not exhaustive options.
To try this in the UI-based editor, choose "year old (mean life, Weibull)" from the units dropdown next to the retirement value and enter the mean lifetime as the number. Otherwise, see the code below:
retire 20 year old mean weibull assuming new
Increasing hazard rates with age
If you want a specific hazard function rather than a fitted mean lifetime, you can also write the hazard yourself as a formula of equipment age. Let's change the hazard rate such that the probability of failure is 1% multiplied by the age of the equipment in years. So, 1% at 1 year, 2% at 2 years, and so on. To do this, modify the simulation using QubecTalk code like follows:
uses substance "HFC-134a"
enable import
initial charge with 0 kg / unit for domestic
initial charge with 1 kg / unit for import
initial charge with 0 kg / unit for export
equals 1430 kgCO2e / kg
equals 1 kwh / unit
set priorEquipment to 1,000,000,000 units during year 1990
retire (get age as years) * 1 % / year
end substance
By the time we get to 2000, much of the equipment is already a few years old so its hazard rate is already higher than the 5% we previously assumed. This rate keeps going up as our population of equipment ages, causing us to hit zero units much sooner.
More about get age
One caveat: get age is the average age across the whole equipment population. This is why the mean lifetime form from the previous section is generally preferred when you have a mean life estimate: it tracks each sales cohort's age through the simulation history.
Download the completed tutorial: tutorial_15.qta which contains the complete variable retirement model with age-dependent hazard rates. If you are using the UI-based editor, you can instead enter "(get age as years) * 1" into the text box for retirement (without quotes)!
Exact retirement schedule
It is somewhat uncommon for countries to know the exact equipment in service duration. So, it is typically not ideal to, for example, retire all equipment at exactly 10 years of service.
Even so, sometimes you may know the exact age of equipment already in service and want to model a precise hazard rate per year of equipment age instead of a continuous hazard function. For example, you might have data showing that a specific percentage of equipment retires at specific ages.
Let's consider an example for HFC-134a in commercial refrigeration where the retirement schedule is: 20% of equipment retires at 9 years, 60% at 10 years, and 20% at 11 years. This pattern means equipment has a 10-year expected lifespan but with a narrow window of retirement concentrated around that age. In the UI-based editor, choose "year old (exact)" from the retirement units dropdown and enter the age as the value. To model this in code, you use the `retire year old exact` syntax to retrieve the equipment population from N years ago (when those units were sold) and apply the retirement fraction:
retire 5 year old exact
This approach only works if the user knows the exact age of equipment. If you are uncertain about equipment ages, it may be more appropriate to use a mean lifetime (the Weibull form from earlier), a continuous hazard function (like the age-dependent approach from the previous section), or a constant percentage retirement rate.
The single-age 100%-retirement case above (all of a cohort retiring in one specific year) comes up often enough that Kigali Sim provides a shortcut for it. However, instead of writing that abbreviation, you can write something like:
start default
define application "Commercial Refrigeration"
uses substance "HFC-134a"
enable domestic
initial charge with 1 kg / unit for domestic
equals 1430 kgCO2e / kg
set sales to 1000 units during year 1
set sales to 0 units during year 2
retire (0.2 * (get newEquipment 9 years ago as units)) units / year
retire (0.6 * (get newEquipment 10 years ago as units)) units / year
retire (0.2 * (get newEquipment 11 years ago as units)) units / year
end substance
end application
end default
start simulations
simulate "BAU"
from years 1 to 20
end simulations
The shortcut just saves typing when the retirement fraction is 100% and the age is fixed. It shares the same age-from-sales-history behavior as the full form, so a cohort sold before the simulation start still counts as zero. However, the shortcut only covers the 100%-at-one-age case. In other words, it cannot express the 20%/60%/20% split above. That is because each year old exact line always looks up the full 100% original sales record for its age.
When exact retirement is an option
As with the Weibull form, an exact-age retire needs equipment ages, which come from simulated sales history. Entering existing stock directly with set priorEquipment for the same substance raises an error at validation time instead of silently never retiring that stock, since it has no sales record for the shortcut's cohort lookup to find. As with Weibull retirement, the assuming new modifier (code-based editor only) suppresses this: it treats the existing stock as a single cohort assumed to have entered service when the simulation began, so retire 5 year old exact assuming new retires that stock in full once the simulation reaches year 5. The with replacement modifier works with the exact-age form the same way it does for the other retirement forms, maintaining equipment population.
Fitting a function (optional)
In our earlier examples, we either used a mean lifetime or assumed we already knew the hazard function: a specific estimate of how much we expect the probability of retirement (or servicing) to change with equipment age. This captures some important real-world dynamics! However, some users might not have that detailed information.
For those who have neither a mean lifetime, a precise hazard function, nor exact age data but do have some aggregate observations, let's consider a final optional example. For those with just a little calculus or maybe some background in operations research or reliability engineering, let's address a slightly more messy situation where maybe we have some basic data about equipment but not an exact hazard function. Specifically, let's assume:
- We have about an average 10 year lifespan or, more precisely, we find that a unit has about a 50% chance of having retired by the end of 10 years of service.
- We believe that the probability of retirement increases exponentially with age.
- Equipment leak about 6% of initial charge over 10 years or, more precisely, equipment still in service at year 10 will have leaked around 6% of their initial charge.
- We service to top up to original charge.
- We believe that leakage increases linearly with age.
With these constraints in mind, we can approximate using the following:
start default
define application "MAC"
uses substance "HFC-134a"
enable import
assume only recharge sales
initial charge with 0 kg / unit for domestic
initial charge with 1 kg / unit for import
initial charge with 0 kg / unit for export
equals 1430 kgCO2e / kg
equals 1 kwh / unit
set priorEquipment to 100 units during year 2020
retire (get age as years) ^ 2 * 0.228 % / year
recharge (get age as years) * 3 / 2500 * 100 % with 1 kg / unit
end substance
end application
end default
start simulations
simulate "BAU"
from years 2020 to 2040
end simulations
How did we arrive at those formulas? Here, we need that tiny bit of calculus. For retirement, we want half of a cohort retired by the end of year 10, which means the cumulative hazard must reach ln(2) because a cumulative hazard of 0.5 leaves 61% of units surviving. For leakage, the 6% is itself a cumulative fraction (so we can integrate it directly). We can integrate over the first ten years of life such that we have 50% retirement and 6% recharge. With this operation, we derive a hazard function to fit observed data! Consider the following short code snippets runnable at Wolfram Alpha:
- Solve for retirement rate: integrate x*t^2 from t=0 to 10 equals ln(2), solve for x.
- Solve for servicing: integrate x*t from t=0 to 10 equals 0.06, solve for x
These are provided in Wolfram Alpha for brevity but can be adapted easily to Python (using numpy) or other languages. The continuous solution for retirement is x = 3·ln(2)/1000 ≈ 0.208% per year. However, Kigali Sim applies calculations once per year as we don't know the exact time during the year that equipment comes into service. Therefore, the discrete stepping needs a slightly larger coefficient: 0.228% gives half of a 100 unit cohort retired at the end of its tenth year in service (2030 in this simulation). The leakage solution x = 0.0012, written as 3/2500 above, needs no such correction because it is a cumulative top-up rather than a compounding survival.
Note that we are providing a very direct interpretation of the input assumptions. For some alternative types of input, consider using numpy / Python and an iterative solver. Also, remember from the previous section that the age stream is the fleet's average age, so this quadratic hazard is exact for a single cohort (as here, where all 100 units enter in 2020) and approximate for mixed-age fleets.
Conclusion
If all you have is an average equipment lifetime, the mean lifetime form (retire 20 year old mean weibull) is the recommended path: it needs no other parameter and reproduces the rising hazard that real equipment populations show.
If you have survival analysis data and detailed information on the age of equipment, specifying variable retirement through formulas or exact schedules may lead to higher accuracy in predictions. Additionally, though we looked at hazard rates for retirement, the same approach can apply to servicing as well.
Even so, consider if you really know the likely age of existing equipment or a specific schedule for retirement. If not, it may still be best to stick to a flat percentage retirement per year. This simple approach is often most honest when those detailed data aren't available or perhaps the estimates might be less reliable. There is no shame in going with a flat percentage, especially early in modeling.
Finally, please note that, in this tutorial, we still specify hazard rates (rates of retirement) as a percentage. However, you can also specify an absolute number of units of equipment or volume equivalent (kg, mt, CO2e) to retire each year.
Next Steps
You've learned how to leverage sophisticated features like variable retirement rates, bank-based modeling, and advanced sales assumptions. In the next step, we look at Monte Carlo.
Previous: Tutorial 14 | Return to Guide Index | Next: Tutorial 16