# Drinking water disinfection efficiency

## Question

What is the efficiency of drinking water disinfection methods, reported in log-clearance?

 ```library(OpasnetUtils) objects.latest("Op_en7955", code_name = "variable") ```

## Rationale

### Data

References of efficiency of disinfection methods
Method Campylobacter E.coli O157:H7 Rotavirus Norovirus Cryptosporidium Giardia
UV      
Ozonization  ,    

#### UV

The CT-values for UV are mW/cm2 * seconds

Drinking water UV disinfection efficiency(mJ/cm^2)
ObsPathogen012345
1campylobacter0 3 7 10 14 NA
2E.coli O157:H70 5 9 14 19 NA
3rotavirus0 10 20 29 39 NA
4norovirus0 10 21 36 NA NA
5cryptosporidium0 3 6 12 NA NA
6giardia0 2 5 11 NA NA
• E.coli and Campylobacter jejuni corrected for environmental spp.
• Cryptosporidium and giardia: no correction for environmental spp. (research needed).
• Rotavirus SA-11
• For noro: 0.8 log inactivation was estimated for a UV fluence of 20mJ/cm2. At higher fluences (40 and 70mJ/cm^2) all samples were negative. However, it is uncertain to which degree inactivation assessed with RT-PCR is representative for inactivation assessed with infectivity assays.
• For water with low turbidity and high UV transmission?

The log decreases follow the formula 

log10(Nt/N) = -k * Fluence

where Nt is the microbial concentration after contact time t. Fluence is the product of the UV fluence rate (mW/cm2) and the exposure t (mWs/cm2 = mJ/cm2).

OR

log10(Nt/N) = -k * Fluence - b

where b is the y-intercept. This is used in cases where small amounts of UV don't have an effect, and the log linear decrease only begins at a certain level of UV. For some microbes there is also an upper limit to log decrease, after which adding fluence doesn't decrease the microbe concentration.

#### Ozone

Ozone decay model:

C = (C0 - D)exp(-k*t)

Where D is instantaneous demand, k is decay constant, t is time and C is residual

Ozone has a half-life in pure distilled water of approximately 40 min at pH 7.6, but this decreases to 10 min at pH 8.5 at 14.6°C. Rising temperatures increase the rate of decomposition. 

Drinking water ozonization efficiency(mg/min l^-1)
ObsPathogen012345
1campylobacter0 NA NA NA NA NA
2E.coli O157:H70 NA 0.02 NA NA NA
3rotavirus0 NA 0.5 0.8 1 NA
4norovirus0 NA 0.5 0.8 1 NA
5cryptosporidium0 4 11 22 NA NA
6giardia0 NA 1.8-2 NA NA NA
• E.coli, rota, Giardia muris cysts: temperature 5°C and pH 6-7 
• Giardia: in 15°C demand free buffer water ct required for log-2 0.075-0.9 min*mg/l (50000 cysts - 100 cysts) 
• Crypto: in 1°C tap water ct required for log-2 40 min*mg/l, in 20°C tap water 2 min*mg/l
• Cryptosporidium temperature 13°C, also available for 1°C and 22°C

### Calculations

CT-value = concentration * time (min)

 ``` #This is code "Op_en7955/doses" on page [[Drinking water disinfection efficiency]] library(OpasnetUtils) UVdose = Ovariable("UVdose", data = data.frame(Result = 0)) UVtime <- Ovariable("UVtime", data = data.frame(Result = 0)) OzoneDose = Ovariable("OzoneDose", data = data.frame(Result = 0)) objects.store(UVdose, UVtime, OzoneDose) cat("Ovariables UVdose, UVtime and OzoneDose saved.\n") ```

 ```#This is code "Op_en7955/sensitivity" on page [[Drinking water disinfection efficiency]] library(OpasnetUtils) UVSensitivity <- Ovariable("UVSensitivity", ddata = "Op_en7955", subset="Drinking water UV disinfection efficiency") OzSensitivity <- Ovariable("OzSensitivity", ddata = "Op_en7955", subset="Drinking water ozonization efficiency") objects.store(UVSensitivity, OzSensitivity) cat("Ovariables UVSensitivity and OzSensitivity saved.\n") ```

The code below saves the constant for immediate demand and decay constant as well as the time used as the time ozone affects the water. The current constants are from Haas & Kaymak 2003, the averages of the constants they found for different experiments. Their water temperature in all experiments was 15°C and pH approximately 8. The value on time is based on nothing, but a value is needed for the model to run

 ``` #This is code "Op_en7955/constants" on page [[Drinking water chlorination efficiency]] library(OpasnetUtils) D <- 0.25 # immediate demand k.oz <- 0.54 # decay constant t <- 60 # the time the ozone affects, min objects.store(D, k.oz, t) cat("Constants D, k.oz and t saved.\n") ```

 ```# This is code "Op_en7955/CT_ozone" on page [[Drinking water disinfection efficiency]] library(OpasnetUtils) library(reshape2) CTOzone <- Ovariable( "CTOzone", dependencies = data.frame( Name = c("OzoneDose", "k.oz", "D", "t"), Ident = c("Op_en7955/doses", "Op_en7955/constants", "Op_en7955/constants", "Op_en7955/constants")), formula = function(...){ # Integral of concentration along Times: # Int(OzoneDose*D*exp(-k*t)) = OzoneDose*D*(-1/k)*exp(-k*t) # Definite integral from 0 to t = OzoneDose*D*(-1/k)*exp(-k*t) - OzoneDose*D(-1/k) = OzoneDose*D/k (1-exp(-k*t)) CTOzone <- (D/k.oz)*(1-exp(-1*k.oz*t))*OzoneDose return(CTOzone) } ) objects.store(CTOzone) cat("Ovariable CTOzone saved.\n") ```

 ```# This is code "Op_en7955/CT_UV" on page [[Drinking water disinfection efficiency]] library(OpasnetUtils) library(reshape2) UVCT <- Ovariable( "UVCT", dependencies = data.frame( Name = c("UVdose", "UVtime"), Ident = c("Op_en7955/doses", "Op_en7955/doses")), formula = function(...){ return(UVdose*UVtime) } ) objects.store(UVCT) cat("Ovariable UVCT saved.\n") ```

 ```# This is code "Op_en7955/ozefficiency" on page [[Drinking water chlorination efficiency]] library(OpasnetUtils) library(reshape2) OzoneEfficiency <- Ovariable("OzoneEfficiency", dependencies = data.frame( Name = c("CTOzone", "OzSensitivity"), Ident = c("Op_en7955/CT_ozone", "Op_en7955/sensitivity")), formula = function(...){ OzSensitivity <- EvalOutput(OzSensitivity) # make CTOzone into an Ovariable, if it's not already if(!"ovariable" %in% class(CTOzone)) CTOzone <- Ovariable(name="CTOzone", output=data.frame(Result=CTOzone)) CTOzone <- EvalOutput(CTOzone) sensname <- paste0(OzSensitivity@name,"Result") # put "OzSensitivityResult" into sensname ctname <- paste0(CTOzone@name,"Result") # put "CTOzoneResult" into ctname ova <- merge(OzSensitivity, CTOzone) # merge to get the variables into the same table ova\$Logdecrease <- as.numeric(as.character(ova\$Logdecrease)) # make sure Logdecrease-column is numeric out <- aggregate( 1:nrow(ova@output), #take a set of row numbers included in ova... by = ova@output[ova@marginal & colnames(ova@output)!="Logdecrease"], #...that has a unique combination of values in the # index-columns, except Logdecrease. It takes the row numbers with different values of Logdecrease, with the # combination of other indices unique. FUN = function(x) { tmp <- ova@output[x,] # actually takes those rows whose numbers were selected above from ova ord <- order(tmp\$Logdecrease) # saves the order of rows ordered based on Logdecrease, smallest first. if(sum(tmp[[sensname]], na.rm=TRUE)==0) return(0) # if all the ct:s in this set of rows are 0, return 0 out <- approx( # Otherwise use approx to interpolate the log-decrease for the ct value(s) from earlier x=tmp[[sensname]][ord], y=tmp\$Logdecrease[ord], xout=tmp[[ctname]], rule=1:2 )\$y return(out) } ) colnames(out)[colnames(out)=="x"] <- "Result" return(out) } ) objects.store(OzoneEfficiency) cat("Ovariable OzoneEfficiency saved.\n") ```

 ```# This is code "Op_en7955/uvefficiency" on page [[Drinking water chlorination efficiency]] library(OpasnetUtils) library(reshape2) UVEfficiency <- Ovariable("UVEfficiency", dependencies = data.frame( Name = c("UVCT", "UVSensitivity"), Ident = c("Op_en7955/CT_UV", "Op_en7955/sensitivity")), formula = function(...){ UVSensitivity <- EvalOutput(UVSensitivity) # make UVCT into an Ovariable, if it's not already if(!"ovariable" %in% class(UVCT)) UVCT <- Ovariable(name="UVCT", output=data.frame(Result=UVCT)) UVCT <- EvalOutput(UVCT) sensname <- paste0(UVSensitivity@name,"Result") # put "UVSensitivityResult" into sensname ctname <- paste0(UVCT@name,"Result") # put "UVCTResult" into ctname ova <- merge(UVSensitivity, UVCT) # merge to get the variables into the same table ova\$Logdecrease <- as.numeric(as.character(ova\$Logdecrease)) # make sure Logdecrease-column is numeric out <- aggregate( 1:nrow(ova@output), #take a set of row numbers included in ova... by = ova@output[ova@marginal & colnames(ova@output)!="Logdecrease"], #...that has a unique combination of values in the # index-columns, except Logdecrease. It takes the row numbers with different values of Logdecrease, with the # combination of other indices unique. FUN = function(x) { tmp <- ova@output[x,] # actually takes those rows whose numbers were selected above from ova ord <- order(tmp\$Logdecrease) # saves the order of rows ordered based on Logdecrease, smallest first. if(sum(tmp[[sensname]], na.rm=TRUE)==0) return(0) # if all the ct:s in this set of rows are 0, return 0 out <- approx( # Otherwise use approx to interpolate the log-decrease for the ct value(s) from earlier x=tmp[[sensname]][ord], y=tmp\$Logdecrease[ord], xout=tmp[[ctname]], rule=1:2 )\$y return(out) } ) colnames(out)[colnames(out)=="x"] <- "Result" return(out) } ) objects.store(UVEfficiency) cat("Ovariable UVEfficiency saved.\n") ```