Title: | Simulate Rehabilitation Strategies for Water Distribution Systems |
---|---|
Description: | The outcome of various rehabilitation strategies for water distribution systems can be modeled with the Water Management Simulator (WaMaSim). Pipe breaks and the corresponding damage and rehabilitation costs are simulated. It is mainly intended to be used as educational tool for the Water Infrastructure Experimental and Computer Laboratory at ETH Zurich, Switzerland. |
Authors: | Andreas Scheidegger [aut], Rachel Barrett [aut], Christian Foerster [cre] |
Maintainer: | Christian Foerster <[email protected]> |
License: | GPL-3 |
Version: | 1.0.0 |
Built: | 2024-11-20 06:21:18 UTC |
Source: | https://github.com/scheidan/wamasim |
Convenient functions to extract the time or budget.
## S3 method for class 'statelist' x$name
## S3 method for class 'statelist' x$name
x |
a state list |
name |
name of the element to extract |
a vector of the time or budget, or a state
Andreas Scheidegger
## Not run: str(result) # result is a 'statelist' returned from simulate_network result$budget # vector of budget result$time # vector of time result$time.22 # state list of time 22 ## End(Not run)
## Not run: str(result) # result is a 'statelist' returned from simulate_network result$budget # vector of budget result$time # vector of time result$time.22 # state list of time 22 ## End(Not run)
The annual total costs are calculated. The total costs consist of damage, failure and rehabilitation costs.
costs.per.year(statelist, income)
costs.per.year(statelist, income)
statelist |
a state list |
income |
the same values as passed to
|
a vector of the total cost per year
Andreas Scheidegger
Dummy strategy to model no rehabilitation at all.
do.nothing(state)
do.nothing(state)
state |
a state list |
a state list
Andreas Scheidegger
replace.n.highest.risk
,
replace.n.oldest
, replace.n.random
, replace.older.than
,
replace.more.failures.than
## define a strategy function that can be passed to simulate_network(): mystrategy <- . %>% do.nothing
## define a strategy function that can be passed to simulate_network(): mystrategy <- . %>% do.nothing
Expand the network with additional pipes. The diameter of these pipes is sampled.
expand(state, n.new, separate.budget = FALSE)
expand(state, n.new, separate.budget = FALSE)
state |
a state object |
n.new |
|
separate.budget |
boolean, if |
the expanded inventory
Andreas Scheidegger
Allows pipes to randomly fail. If a failure occurs, the failure costs (repair + damage) are calculated and subtracted from the budget. Note, that this may result in a negative budget.
fail(state, prob.failure)
fail(state, prob.failure)
state |
a state object |
prob.failure |
function returning the annual failure rate; i.e. the probability of a
pipe failing in the current year of simulation.
|
inventory with new failures
Andreas Scheidegger
Calculate the costs caused by a failure according to Section 7.1 in "The Water Network Management Challenge", Max Maurer 2017.
failure.cost(diameter, mean = FALSE)
failure.cost(diameter, mean = FALSE)
diameter |
diameter [mm] |
mean |
boolean. Should the expected cost be returned? Random otherwise. |
if mean=FALSE
, the failure costs [CHF] are sampled
randomly. If mean=TRUE
, the expected average costs are returned.
Andreas Scheidegger
The number of failures per year is calculated
from a state list produced by simulate_network
.
failures.per.year(statelist)
failures.per.year(statelist)
statelist |
a state list |
vector containing the number of failures per year
Andreas Scheidegger
Creates the initial network that can be used with simulate_network
.
initiate.network(inventory = 0, budget = Inf)
initiate.network(inventory = 0, budget = Inf)
inventory |
if |
budget |
initial budget |
a state list
Andreas Scheidegger
The number of newly built pipes per year is calculated
from a state list produced by simulate_network
.
pipes.built.per.year(statelist)
pipes.built.per.year(statelist)
statelist |
a state list |
vector containing the number of newly built pipes for each year
Andreas Scheidegger
The number of pipes in service is calculated for every year
based on a state list produced by simulate_network
.
pipes.inservice.per.year(statelist)
pipes.inservice.per.year(statelist)
statelist |
a state list |
vector containing the number of pipes in service
Andreas Scheidegger
Replace pipes with a high number of failures. Pipes are only replaced if the budget remains positive.
replace.more.failures.than(state, failures, max.costs = Inf)
replace.more.failures.than(state, failures, max.costs = Inf)
state |
a state list |
failures |
maximal allowed number of failures |
max.costs |
maximal amount of money allowed to be spent on this strategy |
a state list
Andreas Scheidegger
replace.n.highest.risk
,
replace.n.oldest
, replace.n.random
, replace.older.than
,
do.nothing
## define a strategy function that can be passed to simulate_network(): mystrategy <- . %>% replace.more.failures.than(max.failure=3, max.costs=20000) ## or define a more complex strategy by combining multiple strategies ## into a prioritized sequence: mystrategy <- . %>% replace.more.failures.than(failures=2) %>% replace.n.oldest(n=3) %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.older.than(age=8) %>% replace.n.random(n=4)
## define a strategy function that can be passed to simulate_network(): mystrategy <- . %>% replace.more.failures.than(max.failure=3, max.costs=20000) ## or define a more complex strategy by combining multiple strategies ## into a prioritized sequence: mystrategy <- . %>% replace.more.failures.than(failures=2) %>% replace.n.oldest(n=3) %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.older.than(age=8) %>% replace.n.random(n=4)
n
pipes with the highest riskStrategy to prioritize pipes with the highest risk. Pipes are only replaced if the budget remains positive.
replace.n.highest.risk(state, n, prob.failure, max.costs = Inf)
replace.n.highest.risk(state, n, prob.failure, max.costs = Inf)
state |
a state list |
n |
number of highest risk pipes to replace |
prob.failure |
failure rate function. Typically the same as passed to |
max.costs |
maximal amount of money allowed to be spent on this strategy |
The risk is defined as the product of the failure probability in the next year and the expected failure costs.
a state list
Andreas Scheidegger
replace.n.oldest
, replace.n.random
,
replace.older.than
,
replace.more.failures.than
, do.nothing
## define a strategy function that can be passed to simulate_network(): mystrategy <- . %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp, max.costs=30000) ## or define a more complex strategy by combining multiple strategies ## into a prioritized sequence: mystrategy <- . %>% replace.more.failures.than(failures=2) %>% replace.n.oldest(n=3) %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.older.than(age=8) %>% replace.n.random(n=4)
## define a strategy function that can be passed to simulate_network(): mystrategy <- . %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp, max.costs=30000) ## or define a more complex strategy by combining multiple strategies ## into a prioritized sequence: mystrategy <- . %>% replace.more.failures.than(failures=2) %>% replace.n.oldest(n=3) %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.older.than(age=8) %>% replace.n.random(n=4)
n
oldest pipesPrioritize the oldest pipes for replacement. Pipes are only replaced if the budget remains positive.
replace.n.oldest(state, n, max.costs = Inf)
replace.n.oldest(state, n, max.costs = Inf)
state |
a state list |
n |
number of oldest pipes to replace |
max.costs |
maximal amount of money allowed to be spent on this strategy |
a state list
Andreas Scheidegger
replace.n.highest.risk
,
replace.n.random
, replace.older.than
,
replace.more.failures.than
, do.nothing
## define a strategy function that can be passed to simulate_network(): mystrategy <- . %>% replace.n.oldest(n=10) ## or define a more complex strategy by combining multiple strategies ## into a prioritized sequence: mystrategy <- . %>% replace.more.failures.than(failures=2) %>% replace.n.oldest(n=3) %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.older.than(age=8) %>% replace.n.random(n=4)
## define a strategy function that can be passed to simulate_network(): mystrategy <- . %>% replace.n.oldest(n=10) ## or define a more complex strategy by combining multiple strategies ## into a prioritized sequence: mystrategy <- . %>% replace.more.failures.than(failures=2) %>% replace.n.oldest(n=3) %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.older.than(age=8) %>% replace.n.random(n=4)
n
randomly selected pipesReplace a certain number of randomly chosen pipes. Pipes are only replaced if the budget remains positive.
replace.n.random(state, n, max.costs = Inf)
replace.n.random(state, n, max.costs = Inf)
state |
a state list |
n |
number of random pipes to replace |
max.costs |
maximal amount of money allowed to be spent on this strategy |
a state list
Andreas Scheidegger
replace.n.highest.risk
,
replace.n.oldest
, replace.older.than
,
replace.more.failures.than
, do.nothing
## define a strategy function that can be passed to simulate_network(): mystrategy <- . %>% replace.n.random(n=10) ## or define a more complex strategy by combining multiple strategies ## into a prioritized sequence: mystrategy <- . %>% replace.more.failures.than(failures=2) %>% replace.n.oldest(n=3) %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.older.than(age=8) %>% replace.n.random(n=4)
## define a strategy function that can be passed to simulate_network(): mystrategy <- . %>% replace.n.random(n=10) ## or define a more complex strategy by combining multiple strategies ## into a prioritized sequence: mystrategy <- . %>% replace.more.failures.than(failures=2) %>% replace.n.oldest(n=3) %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.older.than(age=8) %>% replace.n.random(n=4)
age
Strategy to replace pipes older than a given age. Pipes are only replaced if the budget remains positive.
replace.older.than(state, age, max.costs = Inf)
replace.older.than(state, age, max.costs = Inf)
state |
a state list |
age |
pipes older than age are replaced |
max.costs |
maximal amount of money allowed to be spent on this strategy |
a state list
Andreas Scheidegger
replace.n.highest.risk
,
replace.n.oldest
, replace.n.random
,
replace.more.failures.than
, do.nothing
## define a strategy function that can be passed to simulate_network(): mystrategy <- . %>% replace.older.than(age=85, max.costs=20000) ## or define a more complex strategy by combining multiple strategies ## into a prioritized sequence: mystrategy <- . %>% replace.more.failures.than(failures=2) %>% replace.n.oldest(n=3) %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.older.than(age=8) %>% replace.n.random(n=4)
## define a strategy function that can be passed to simulate_network(): mystrategy <- . %>% replace.older.than(age=85, max.costs=20000) ## or define a more complex strategy by combining multiple strategies ## into a prioritized sequence: mystrategy <- . %>% replace.more.failures.than(failures=2) %>% replace.n.oldest(n=3) %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.older.than(age=8) %>% replace.n.random(n=4)
Based on Eq(14) of "The Water Network Management Challenge, Max Maurer 2017", assuming a pipe length of 100m.
replacement.value(diameter)
replacement.value(diameter)
diameter |
diameter of the pipe [mm] |
replacement value [CHF]
Andreas Scheidegger
The diameter distribution is based on a real data set from Lisa Scholten (pipe_data.csv). Refer to the old exercise on watermain break modelling in the ETH Infrastructure Systems course by Max Maurer.
sample.diameter(n = 1)
sample.diameter(n = 1)
n |
number of samples |
a vector of diameters
Andreas Scheidegger
Simulates failures, expansion, rehabilitation, and costs of a water supply pipe network. The simulation is stochastic.
simulate_network(n.years, expansion, rehabilitation, prob.failure, income = 0, initial.budget = Inf, initial.inventory = NULL, free.expansion = TRUE)
simulate_network(n.years, expansion, rehabilitation, prob.failure, income = 0, initial.budget = Inf, initial.inventory = NULL, free.expansion = TRUE)
n.years |
number of years to simulate |
expansion |
either a scalar describing the number of pipes added
every year to expand the pipe network, or a vector of length |
rehabilitation |
a (combination of) rehabilitation strategy function(s). See details below. |
prob.failure |
a function describing the probability of a pipe failing in the next year given its age, number of previous failures, and the age at the last failure (if any). |
income |
either a scalar describing the annual income, or a vector of length |
initial.budget |
initial budget |
initial.inventory |
if it is an integer it specifies the
number of initial pipes, or alternatively it can be a |
free.expansion |
if |
The rehabilitation is defined by combining different simple replacement strategies.
See the example for how this can be done using the mystrategy
function input.
If the strategies vary over time, see initiate.network
and
simulate_network.period
.
The failure behavior is defined by the function prob.failure
.
It calculates the probability of a pipe failing within the next year based on pipe age,
pipe age at the last failure, and the number of failures. Note, the model
makes the assumption that a pipe cannot fail more than once per year.
The costs are calculated as a function of the pipe diameter, assuming all pipes have a length of 100 meters.
an updated state list
Andreas Scheidegger
For more fine-grained control see initiate.network
and simulate_network.period
. Different replacement strategies
are implemented: replace.n.highest.risk
,
replace.n.oldest
, replace.n.random
, replace.older.than
,
replace.more.failures.than
, do.nothing
.
## ----------- ## define model parameters ## Define the annual probability of a failure prob.failure.exp <- function(age, age.last.failure, n.failure) { if(n.failure==0){ return(1/30) } else { return(1/10) } } ## define a complicated (and probably useless) rehabilitation strategy mystrategy <- . %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.more.failures.than(failures=5) %>% replace.older.than(age=70, max.cost=2e6) %>% replace.n.oldest(n=3) %>% replace.n.random(n=2) ## This means: every year (if we have enough budget!), replace first the 2 pipes ## with the highest risk, then all pipes with more than 5 failures, ## then all pipes older then 70 years (up to costs of 2e6), then the 3 ## oldest pipes remaining, and finally replace 2 randomly selected pipes. ## ----------- ## run the simulation result <- simulate_network( n.years = 100, # run it for 100 years expansion = 10, # build 10 pipes per year (if money is available) rehabilitation = mystrategy, # use the strategy defined above prob.failure = prob.failure.exp, # use the probability function defined above income = 1e6, # the annual income initial.budget = 1e7, initial.inventory = 50, # start the simulation with 50 new pipes free.expansion = FALSE ) ## look at some results ## str(result) ## str(result$time.100)
## ----------- ## define model parameters ## Define the annual probability of a failure prob.failure.exp <- function(age, age.last.failure, n.failure) { if(n.failure==0){ return(1/30) } else { return(1/10) } } ## define a complicated (and probably useless) rehabilitation strategy mystrategy <- . %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.more.failures.than(failures=5) %>% replace.older.than(age=70, max.cost=2e6) %>% replace.n.oldest(n=3) %>% replace.n.random(n=2) ## This means: every year (if we have enough budget!), replace first the 2 pipes ## with the highest risk, then all pipes with more than 5 failures, ## then all pipes older then 70 years (up to costs of 2e6), then the 3 ## oldest pipes remaining, and finally replace 2 randomly selected pipes. ## ----------- ## run the simulation result <- simulate_network( n.years = 100, # run it for 100 years expansion = 10, # build 10 pipes per year (if money is available) rehabilitation = mystrategy, # use the strategy defined above prob.failure = prob.failure.exp, # use the probability function defined above income = 1e6, # the annual income initial.budget = 1e7, initial.inventory = 50, # start the simulation with 50 new pipes free.expansion = FALSE ) ## look at some results ## str(result) ## str(result$time.100)
Simulates failures, expansion, rehabilitation, and costs of a water supply pipe network. The simulation is stochastic.
simulate_network.period(statelist, n.years, expansion, rehabilitation, prob.failure, income = 0, free.expansion = TRUE)
simulate_network.period(statelist, n.years, expansion, rehabilitation, prob.failure, income = 0, free.expansion = TRUE)
statelist |
a state list |
n.years |
number of years to simulate |
expansion |
either a scalar describing the number of pipes added
every year to expand the pipe network, or a vector of length |
rehabilitation |
a (combination of) rehabilitation strategy function(s). See details below. |
prob.failure |
a function describing the probability of a pipe failing in the next year given its age, number of previous failures, and the age at the last failure (if any). |
income |
either a scalar describing the annual income, or a vector of length |
free.expansion |
if |
The rehabilitation is defined by combining different simple replacement strategies.
See the example for how this can be done using the mystrategy
function input.
The failure behavior is defined by the function prob.failure
.
It calculates the probability of a pipe failing within the next year based on pipe age,
pipe age at the last failure, and the number of failures. Note, the model
makes the assumption that a pipe cannot fail more than once per year.
The costs are calculated as a function of the pipe diameter, assuming all pipes have a length of 100 meters.
an updated state list
Andreas Scheidegger
simulate_network
provides a slightly more convenient interface.
## ----------- ## define model parameters ## Define the annual probability of a failure prob.failure.exp <- function(age, age.last.failure, n.failure) { if(n.failure==0){ return(1/30) } else { return(1/10) } } ## define a complicated (and probably useless) rehabilitation strategy mystrategy <- . %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.more.failures.than(failures=5) %>% replace.older.than(age=70, max.cost=2e6) %>% replace.n.oldest(n=3) %>% replace.n.random(n=2) ## This means: every year (if we have enough budget!), replace first the 2 pipes ## with the highest risk, then all pipes with more than 5 failures, ## then all pipes older then 70 years (up to costs of 2e6), then the 3 ## oldest pipes remaining, and finally replace 2 randomly selected pipes. ## ----------- ## run the simulation in steps statelist <- initiate.network(inventory = 50, budget = 1e7) statelist <- simulate_network.period( statelist, # state list to update n.years = 20, # run it for 20 years expansion = 10, # build 10 pipes per year (if money is available) rehabilitation = mystrategy, # use the strategy defined above prob.failure = prob.failure.exp, # use the probability function defined above income = 1e6 # the annual income ) statelist <- simulate_network.period( statelist, # state list to update n.years = 10, # run it for 10 more years expansion = 2, # now, build only 2 pipes per year (if money is available) rehabilitation = mystrategy, # use the strategy defined above prob.failure = prob.failure.exp, # use the probability function defined above income = 1e6 # the annual income ) ## look at some results ## str(statelist) ## str(statelist$time.30)
## ----------- ## define model parameters ## Define the annual probability of a failure prob.failure.exp <- function(age, age.last.failure, n.failure) { if(n.failure==0){ return(1/30) } else { return(1/10) } } ## define a complicated (and probably useless) rehabilitation strategy mystrategy <- . %>% replace.n.highest.risk(n=2, prob.failure=prob.failure.exp) %>% replace.more.failures.than(failures=5) %>% replace.older.than(age=70, max.cost=2e6) %>% replace.n.oldest(n=3) %>% replace.n.random(n=2) ## This means: every year (if we have enough budget!), replace first the 2 pipes ## with the highest risk, then all pipes with more than 5 failures, ## then all pipes older then 70 years (up to costs of 2e6), then the 3 ## oldest pipes remaining, and finally replace 2 randomly selected pipes. ## ----------- ## run the simulation in steps statelist <- initiate.network(inventory = 50, budget = 1e7) statelist <- simulate_network.period( statelist, # state list to update n.years = 20, # run it for 20 years expansion = 10, # build 10 pipes per year (if money is available) rehabilitation = mystrategy, # use the strategy defined above prob.failure = prob.failure.exp, # use the probability function defined above income = 1e6 # the annual income ) statelist <- simulate_network.period( statelist, # state list to update n.years = 10, # run it for 10 more years expansion = 2, # now, build only 2 pipes per year (if money is available) rehabilitation = mystrategy, # use the strategy defined above prob.failure = prob.failure.exp, # use the probability function defined above income = 1e6 # the annual income ) ## look at some results ## str(statelist) ## str(statelist$time.30)
WaMaSim is a package that simulates the effect of different
rehabilitation strategies for water distribution systems. It is an education tool
used for the Water Infrastructure Experimental and Computer Laboratory at ETH Zurich, Switzerland.
See the documentation for simulate_network
to get started.
Andreas Scheidegger