library('hector')
library('ggplot2')
library('ggthemes')
What we want to know is, how individually identifiable are the climate sensitivity \(S\) and the ocean thermal diffusivity \(\kappa\), given just temperature data over the 21st century. To do this, we will look at a range of \(\kappa\) values, and for each one we will find the \(S\) value that best reproduces the 21st century temperatures for the baseline run. Then we will look at how different those runs are over the 21st century, and whether they diverge with longer runs.
Here is our function to return output data for a single \(\kappa\) value.
compyears <- 2001:2100
kopt <- function(hcore, kappa, temp2100)
{
setvar(hcore, NA, DIFFUSIVITY(), kappa, 'cm2/s')
optfun <- function(S) {
hfail <- function(e) {1e6*(S-2)} # return a large value on parameter out of range
tryCatch({
setvar(hcore, NA, ECS(), S, 'degC')
reset(hcore)
run(hcore, max(compyears))
sum((fetchvars(hcore, compyears, GLOBAL_TEMP())$value - temp2100)^2)
}, error=hfail)
}
op <- optimize(optfun, c(0.1, 50))
# if(op$objective > 1e-4) {
# warning('Optimization failed. kappa= ', kappa, ' val= ', op$objective)
# }
## Have the location of the optimum, now get the data
setvar(hcore, NA, ECS(), op$minimum, 'degC')
runtodate <- function(date) {
reset(hcore)
run(hcore,date)
df <- fetchvars(hcore, 2000:date, GLOBAL_TEMP())
df$kappa <- kappa
df$S <- op$minimum
df
}
## Some models won't be able to run to 2300, so back those down as necessary
rslt <- NULL
date <- 2301
hfail2 <- function(e) {NULL}
while(is.null(rslt)) {
date <- date-10
rslt <- tryCatch({
runtodate(date)
}, error=hfail2)
}
rslt
}
To run this we’ll need a Hector core. My hunch is that the high emissions scenario will give us the best discriminatory power, so we’ll use that. We also need the 21st century temperatures.
inifile <- system.file('input/hector_rcp85.ini', package='hector')
hc <- newcore(inifile)
invisible(run(hc, max(compyears)))
temps <- fetchvars(hc, compyears, GLOBAL_TEMP())$value
kvals <- c(0.01, 2.3, 10.0, 20.0)
rslts <- lapply(kvals,
function(k) {
r <- kopt(hc, k, temps)
message('k= ', k, ' S= ', r$S[1])
r
})
k= 0.01 S= 2.00909721511787
k= 2.3 S= 2.99999511064658
k= 10 S= 6.83593956125711
k= 20 S= 49.9999397962838
Now, let’s take a look at these runs. We’ll first plot only out to 2100, then we’ll plot everything.
pltdata <- dplyr::bind_rows(rslts)
pltdata$kappa <- factor(pltdata$kappa, ordered=TRUE)
pltdata2100 <- dplyr::filter(pltdata, year<=2100)
ggplot(data=pltdata2100, aes(x=year, y=value, color=kappa)) + geom_line(size=1.1) +
ylab('Temperature') + theme_solarized_2(light=FALSE) + scale_color_solarized()

ggplot(data=pltdata, aes(x=year, y=value, color=kappa)) + geom_line(size=1.1) +
ylab('Temperature') + theme_solarized_2(light=FALSE) + scale_color_solarized()

As expected, \(S\) and \(\kappa\) can to some extent trade off against one another, but the tradeoff isn’t perfect. They look wildly different for the longer runs, of course. What matters is how this partial tradeoff compares to our ability to fit the ESMs. We know the ESMs have noise that we won’t ever be able to fit. If the magnitude of that noise is comparable to or larger than the difference (in Hector temperatures) between the largest and smallest \(\kappa\) runs, then all the \(\kappa\), \(S\) pairings effectively look the same, and the parameters are not going to be identifiable. Therefore, we’ll calculate the mean squared error relative to the \(\kappa = 2.3\) run for each of the other runs.
sapply(rslts,
function(r){
r2100 <- dplyr::filter(r, year<=2100)
cmp2100 <- dplyr::filter(rslts[[2]], year<=2100)
mean(
(r2100$value - cmp2100$value)^2
)
}) -> mse
names(mse) <- kvals
mse
0.01 2.3 10 20
0.009771107 0.000000000 0.006692442 0.022865701
The MSE for the total range of \(\kappa\) values is only about 0.033. That’s pretty small. I bet the noise in the ESMs is already higher than that. We can estimate that noise by calculating the MSE between the ESM data and a smoothed version. We’ll use loess smoothing to make it easy on ourselves.
esmnoise <- function(mod) {
dd <- dplyr::filter(cmip_individual, model==mod, experiment=='rcp85')
ll <- loess(data=dd, value~year, span=0.5)
mean((predict(ll) - dd$value)^2)
}
mods <- unique(dplyr::filter(cmip_individual, experiment=='rcp85')$model)
n <- sapply(mods, esmnoise)
n
ACCESS1-0 ACCESS1-3 CanESM2 CCSM4 CESM1-BGC CESM1-CAM5 CESM1-WACCM
7.218283e-03 5.839079e-03 1.302654e-02 7.927348e-03 5.569663e-03 1.141015e-02 1.114608e-02
CMCC-CESM CMCC-CM CMCC-CMS CNRM-CM5 CSIRO-Mk3-6-0 EC-EARTH FGOALS-g2
3.857231e-02 8.656464e-03 1.597073e-02 5.739298e-03 1.798573e-02 1.019948e-02 4.136632e-03
GFDL-CM3 GFDL-ESM2G GISS-E2-H-CC GISS-E2-H GISS-E2-R-CC GISS-E2-R inmcm4
9.435532e-03 9.271329e+04 2.819891e-03 1.150993e-01 2.735334e-03 1.454114e-01 2.602672e-03
IPSL-CM5A-MR IPSL-CM5B-LR MIROC5 MIROC-ESM-CHEM MIROC-ESM MPI-ESM-LR MPI-ESM-MR
7.553371e-03 1.092388e-02 3.148565e-02 5.838751e-03 6.169950e-03 2.025255e-02 1.304763e-02
MRI-CGCM3 NorESM1-ME
5.150667e-03 6.506770e-03
summary(n)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.00 0.01 0.01 3090.00 0.02 92710.00
Something clearly went wrong for GFDL-ESM2G. Other than that the results look interesting, though not good for identifiability. The smallest MSE is 0.003 for inmcm4. If the true value of \(\kappa\) were near the Hector canonical value of 2.3, we would have at least a fighting chance of ruling out \(\kappa \approx 0\) or \(\kappa \ge 10\), assuming that high-frequency variability is the only source of error (i.e, no fitting error and no compromise between experiments).
For 3/4 of the models the MSE is above 0.006, which is comparable to the difference between \(\kappa \approx 2.3\) and \(\kappa \approx 10\). The range of allowable \(\kappa\) values covers essentially all physically plausible values.
By way of example, here’s CESM1-CAM5 overlaid on the \(\kappa\) plots.
cesm_all <- dplyr::filter(cmip_individual, model=='CESM1-CAM5', experiment=='rcp85')
ggplot(data=pltdata2100, aes(x=year, y=value, color=kappa)) + geom_line(size=1.1) +
ylab('Temperature') + theme_solarized_2(light=FALSE) + scale_color_solarized() +
geom_point(data=cesm_all, color='lightgrey')

Well, ok, not quite the illustration I’d hoped because these model runs weren’t optimized to that CESM run, but hopefully it’s clear that when you include all the ensemble members, the band easily spans a width comparable to the width of the band of \(\kappa\) values.
What next?
One thing that might help would be to smooth the ESMs so that we have Hector trying to fit their smooth trend, which is all it can really hope to do anyhow. I’m curious to see if doing the fits in principal component space might accomplish this in a less ad-hoc way than using something like loess (more about the principal components angle tomorrow). Of course, the discrepancies between experiments and ensemble members may still lead to non-identifiability between \(S\) and \(\kappa\). Even if it doesn’t, the fact that one \(\kappa\) is favored doesn’t mean it’s the right value, so I’m not sure how much stock we should put in fits done with smoothed results. However, I do think we want to know what happens when we try those other methods so that we can plan our next move, as well as so we can start to figure out what our findings are going to be for this paper.
LS0tCnRpdGxlOiAiUmVmbGVjdGlvbnMgb24gSWRlbnRpZmlhYmlsaXR5IG9mIENsaW1hdGUgU2Vuc2l0aXZpdHkgYW5kIERpZmZ1c2l2aXR5IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7ciBzZXR1cH0KbGlicmFyeSgnaGVjdG9yJykKbGlicmFyeSgnZ2dwbG90MicpCmxpYnJhcnkoJ2dndGhlbWVzJykKYGBgCgpXaGF0IHdlIHdhbnQgdG8ga25vdyBpcywgaG93IGluZGl2aWR1YWxseSBpZGVudGlmaWFibGUgYXJlIHRoZSBjbGltYXRlIHNlbnNpdGl2aXR5CiRTJCBhbmQgdGhlIG9jZWFuIHRoZXJtYWwgZGlmZnVzaXZpdHkgJFxrYXBwYSQsIGdpdmVuIF9qdXN0XyB0ZW1wZXJhdHVyZSBkYXRhIG92ZXIKdGhlIDIxc3QgY2VudHVyeS4gIFRvIGRvIHRoaXMsIHdlIHdpbGwgbG9vayBhdCBhIHJhbmdlIG9mICRca2FwcGEkIHZhbHVlcywgYW5kIGZvcgplYWNoIG9uZSB3ZSB3aWxsIGZpbmQgdGhlICRTJCB2YWx1ZSB0aGF0IGJlc3QgcmVwcm9kdWNlcyB0aGUgMjFzdCBjZW50dXJ5IHRlbXBlcmF0dXJlcyBmb3IgCnRoZSBiYXNlbGluZSBydW4uICBUaGVuIHdlIHdpbGwgbG9vayBhdCBob3cgZGlmZmVyZW50IHRob3NlIHJ1bnMgYXJlIG92ZXIgdGhlIDIxc3QKY2VudHVyeSwgYW5kIHdoZXRoZXIgdGhleSBkaXZlcmdlIHdpdGggbG9uZ2VyIHJ1bnMuCgpIZXJlIGlzIG91ciBmdW5jdGlvbiB0byByZXR1cm4gb3V0cHV0IGRhdGEgZm9yIGEgc2luZ2xlICRca2FwcGEkIHZhbHVlLgoKYGBge3Iga29wdH0KY29tcHllYXJzIDwtIDIwMDE6MjEwMAprb3B0IDwtIGZ1bmN0aW9uKGhjb3JlLCBrYXBwYSwgdGVtcDIxMDApCnsKICAgIHNldHZhcihoY29yZSwgTkEsIERJRkZVU0lWSVRZKCksIGthcHBhLCAnY20yL3MnKQogICAgb3B0ZnVuIDwtIGZ1bmN0aW9uKFMpIHsKICAgICAgICBoZmFpbCA8LSBmdW5jdGlvbihlKSB7MWU2KihTLTIpfSAgIyByZXR1cm4gYSBsYXJnZSB2YWx1ZSBvbiBwYXJhbWV0ZXIgb3V0IG9mIHJhbmdlCiAgICAgICAgdHJ5Q2F0Y2goewogICAgICAgICAgICBzZXR2YXIoaGNvcmUsIE5BLCBFQ1MoKSwgUywgJ2RlZ0MnKQogICAgICAgICAgICByZXNldChoY29yZSkKICAgICAgICAgICAgcnVuKGhjb3JlLCBtYXgoY29tcHllYXJzKSkKICAgICAgICAgICAgc3VtKChmZXRjaHZhcnMoaGNvcmUsIGNvbXB5ZWFycywgR0xPQkFMX1RFTVAoKSkkdmFsdWUgLSB0ZW1wMjEwMCleMikKICAgICAgICB9LCBlcnJvcj1oZmFpbCkgCiAgICB9CiAgICBvcCA8LSBvcHRpbWl6ZShvcHRmdW4sIGMoMC4xLCA1MCkpCiAgICAjIGlmKG9wJG9iamVjdGl2ZSA+IDFlLTQpIHsKICAgICMgICAgIHdhcm5pbmcoJ09wdGltaXphdGlvbiBmYWlsZWQuIGthcHBhPSAnLCBrYXBwYSwgJyB2YWw9ICcsIG9wJG9iamVjdGl2ZSkKICAgICMgfQogICAgIyMgSGF2ZSB0aGUgbG9jYXRpb24gb2YgdGhlIG9wdGltdW0sIG5vdyBnZXQgdGhlIGRhdGEKICAgIHNldHZhcihoY29yZSwgTkEsIEVDUygpLCBvcCRtaW5pbXVtLCAnZGVnQycpCiAgICBydW50b2RhdGUgPC0gZnVuY3Rpb24oZGF0ZSkgewogICAgICAgIHJlc2V0KGhjb3JlKQogICAgICAgIHJ1bihoY29yZSxkYXRlKQogICAgICAgIGRmIDwtIGZldGNodmFycyhoY29yZSwgMjAwMDpkYXRlLCBHTE9CQUxfVEVNUCgpKQogICAgICAgIGRmJGthcHBhIDwtIGthcHBhCiAgICAgICAgZGYkUyA8LSBvcCRtaW5pbXVtCiAgICAgICAgZGYKICAgIH0KICAgICMjIFNvbWUgbW9kZWxzIHdvbid0IGJlIGFibGUgdG8gcnVuIHRvIDIzMDAsIHNvIGJhY2sgdGhvc2UgZG93biBhcyBuZWNlc3NhcnkKICAgIHJzbHQgPC0gTlVMTAogICAgZGF0ZSA8LSAyMzAxCiAgICBoZmFpbDIgPC0gZnVuY3Rpb24oZSkge05VTEx9CiAgICB3aGlsZShpcy5udWxsKHJzbHQpKSB7CiAgICAgICAgZGF0ZSA8LSBkYXRlLTEwCiAgICAgICAgcnNsdCA8LSB0cnlDYXRjaCh7CiAgICAgICAgICAgIHJ1bnRvZGF0ZShkYXRlKQogICAgICAgIH0sIGVycm9yPWhmYWlsMikKICAgIH0KICAgIHJzbHQKfQpgYGAKClRvIHJ1biB0aGlzIHdlJ2xsIG5lZWQgYSBIZWN0b3IgY29yZS4gIE15IGh1bmNoIGlzIHRoYXQgdGhlIGhpZ2ggZW1pc3Npb25zIHNjZW5hcmlvIAp3aWxsIGdpdmUgdXMgdGhlIGJlc3QgZGlzY3JpbWluYXRvcnkgcG93ZXIsIHNvIHdlJ2xsIHVzZSB0aGF0LiAgV2UgYWxzbyBuZWVkIHRoZSAyMXN0CmNlbnR1cnkgdGVtcGVyYXR1cmVzLgpgYGB7ciBoZWN0b3J9CmluaWZpbGUgPC0gc3lzdGVtLmZpbGUoJ2lucHV0L2hlY3Rvcl9yY3A4NS5pbmknLCBwYWNrYWdlPSdoZWN0b3InKQpoYyA8LSBuZXdjb3JlKGluaWZpbGUpCmludmlzaWJsZShydW4oaGMsIG1heChjb21weWVhcnMpKSkKdGVtcHMgPC0gZmV0Y2h2YXJzKGhjLCBjb21weWVhcnMsIEdMT0JBTF9URU1QKCkpJHZhbHVlCmt2YWxzIDwtIGMoMC4wMSwgMi4zLCAxMC4wLCAyMC4wKQpyc2x0cyA8LSBsYXBwbHkoa3ZhbHMsCiAgICAgICAgICAgICAgICBmdW5jdGlvbihrKSB7CiAgICAgICAgICAgICAgICAgICAgciA8LSBrb3B0KGhjLCBrLCB0ZW1wcykKICAgICAgICAgICAgICAgICAgICBtZXNzYWdlKCdrPSAnLCBrLCAnIFM9ICcsIHIkU1sxXSkKICAgICAgICAgICAgICAgICAgICByCiAgICAgICAgICAgICAgICB9KQpgYGAKCk5vdywgbGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlc2UgcnVucy4gIFdlJ2xsIGZpcnN0IHBsb3Qgb25seSBvdXQgdG8gMjEwMCwgdGhlbiB3ZSdsbCBwbG90CmV2ZXJ5dGhpbmcuCmBgYHtyIHBsb3RydW5zfQpwbHRkYXRhIDwtIGRwbHlyOjpiaW5kX3Jvd3MocnNsdHMpCnBsdGRhdGEka2FwcGEgPC0gZmFjdG9yKHBsdGRhdGEka2FwcGEsIG9yZGVyZWQ9VFJVRSkKcGx0ZGF0YTIxMDAgPC0gZHBseXI6OmZpbHRlcihwbHRkYXRhLCB5ZWFyPD0yMTAwKQpnZ3Bsb3QoZGF0YT1wbHRkYXRhMjEwMCwgYWVzKHg9eWVhciwgeT12YWx1ZSwgY29sb3I9a2FwcGEpKSArIGdlb21fbGluZShzaXplPTEuMSkgKwogICAgeWxhYignVGVtcGVyYXR1cmUnKSArIHRoZW1lX3NvbGFyaXplZF8yKGxpZ2h0PUZBTFNFKSArIHNjYWxlX2NvbG9yX3NvbGFyaXplZCgpCmdncGxvdChkYXRhPXBsdGRhdGEsIGFlcyh4PXllYXIsIHk9dmFsdWUsIGNvbG9yPWthcHBhKSkgKyBnZW9tX2xpbmUoc2l6ZT0xLjEpICsKICAgIHlsYWIoJ1RlbXBlcmF0dXJlJykgKyB0aGVtZV9zb2xhcml6ZWRfMihsaWdodD1GQUxTRSkgKyBzY2FsZV9jb2xvcl9zb2xhcml6ZWQoKQpgYGAKCkFzIGV4cGVjdGVkLCAkUyQgYW5kICRca2FwcGEkIGNhbiB0byBzb21lIGV4dGVudCB0cmFkZSBvZmYgYWdhaW5zdCBvbmUgYW5vdGhlciwgYnV0IAp0aGUgdHJhZGVvZmYgaXNuJ3QgcGVyZmVjdC4gIFRoZXkgbG9vayB3aWxkbHkgZGlmZmVyZW50IGZvciB0aGUgbG9uZ2VyIHJ1bnMsIG9mIGNvdXJzZS4KV2hhdCBtYXR0ZXJzIGlzIGhvdyB0aGlzIHBhcnRpYWwgdHJhZGVvZmYgY29tcGFyZXMgdG8gb3VyIGFiaWxpdHkgdG8gZml0IHRoZSBFU01zLiAgV2UKa25vdyB0aGUgRVNNcyBoYXZlIG5vaXNlIHRoYXQgd2Ugd29uJ3QgZXZlciBiZSBhYmxlIHRvIGZpdC4gIElmIHRoZSBtYWduaXR1ZGUgb2YgdGhhdApub2lzZSBpcyBjb21wYXJhYmxlIHRvIG9yIGxhcmdlciB0aGFuIHRoZSBkaWZmZXJlbmNlIChpbiBIZWN0b3IgdGVtcGVyYXR1cmVzKSBiZXR3ZWVuIAp0aGUgbGFyZ2VzdCBhbmQgc21hbGxlc3QgJFxrYXBwYSQgcnVucywgdGhlbiBhbGwgdGhlICRca2FwcGEkLCAkUyQgcGFpcmluZ3MgZWZmZWN0aXZlbHkKbG9vayB0aGUgc2FtZSwgYW5kIHRoZSBwYXJhbWV0ZXJzIGFyZSBub3QgZ29pbmcgdG8gYmUgaWRlbnRpZmlhYmxlLiAgVGhlcmVmb3JlLCB3ZSdsbApjYWxjdWxhdGUgdGhlIG1lYW4gc3F1YXJlZCBlcnJvciByZWxhdGl2ZSB0byB0aGUgJFxrYXBwYSA9IDIuMyQgcnVuIGZvciBlYWNoIG9mIHRoZQpvdGhlciBydW5zLgoKYGBge3IgbXNlfQpzYXBwbHkocnNsdHMsIAogICAgICAgZnVuY3Rpb24ocil7CiAgICAgICAgICAgcjIxMDAgPC0gZHBseXI6OmZpbHRlcihyLCB5ZWFyPD0yMTAwKQogICAgICAgICAgIGNtcDIxMDAgPC0gZHBseXI6OmZpbHRlcihyc2x0c1tbMl1dLCB5ZWFyPD0yMTAwKQogICAgICAgICAgIG1lYW4oCiAgICAgICAgICAgICAgIChyMjEwMCR2YWx1ZSAtIGNtcDIxMDAkdmFsdWUpXjIKICAgICAgICAgICApCiAgICAgICB9KSAtPiBtc2UKbmFtZXMobXNlKSA8LSBrdmFscwptc2UKYGBgClRoZSBNU0UgZm9yIHRoZSB0b3RhbCByYW5nZSBvZiAkXGthcHBhJCB2YWx1ZXMgaXMgb25seSBhYm91dCBgciBzaWduaWYobXNlWzFdK21zZVs0XSwyKWAuICBUaGF0J3MgCnByZXR0eSBzbWFsbC4gIEkgYmV0IHRoZSBub2lzZSBpbiB0aGUgRVNNcyBpcyBhbHJlYWR5IGhpZ2hlciB0aGFuIHRoYXQuICBXZSBjYW4gZXN0aW1hdGUKdGhhdCBub2lzZSBieSBjYWxjdWxhdGluZyB0aGUgTVNFIGJldHdlZW4gdGhlIEVTTSBkYXRhIGFuZCBhIHNtb290aGVkIHZlcnNpb24uICBXZSdsbAp1c2UgbG9lc3Mgc21vb3RoaW5nIHRvIG1ha2UgaXQgZWFzeSBvbiBvdXJzZWx2ZXMuCmBgYHtyIGVzbW5vaXNlfQplc21ub2lzZSA8LSBmdW5jdGlvbihtb2QpIHsKICAgIGRkIDwtIGRwbHlyOjpmaWx0ZXIoY21pcF9pbmRpdmlkdWFsLCBtb2RlbD09bW9kLCBleHBlcmltZW50PT0ncmNwODUnKQogICAgbGwgPC0gbG9lc3MoZGF0YT1kZCwgdmFsdWV+eWVhciwgc3Bhbj0wLjUpCiAgICBtZWFuKChwcmVkaWN0KGxsKSAtIGRkJHZhbHVlKV4yKQp9Cm1vZHMgPC0gdW5pcXVlKGRwbHlyOjpmaWx0ZXIoY21pcF9pbmRpdmlkdWFsLCBleHBlcmltZW50PT0ncmNwODUnKSRtb2RlbCkKbiA8LSBzYXBwbHkobW9kcywgZXNtbm9pc2UpCm4Kc3VtbWFyeShuKQpgYGAKU29tZXRoaW5nIGNsZWFybHkgd2VudCB3cm9uZyBmb3IgYHIgbmFtZXMobilbd2hpY2gubWF4KG4pXWAuICBPdGhlciB0aGFuIHRoYXQKdGhlIHJlc3VsdHMgbG9vayBpbnRlcmVzdGluZywgdGhvdWdoIG5vdCBnb29kIGZvciBpZGVudGlmaWFiaWxpdHkuICBUaGUgc21hbGxlc3QgTVNFCmlzIGByIHNpZ25pZihtaW4obiksIDEpYCBmb3IgYHIgbmFtZXMobilbd2hpY2gubWluKG4pXWAuICBJZiB0aGUgdHJ1ZSB2YWx1ZSBvZiAkXGthcHBhJAp3ZXJlIG5lYXIgdGhlIEhlY3RvciBjYW5vbmljYWwgdmFsdWUgb2YgMi4zLCB3ZSB3b3VsZCBoYXZlIGF0IGxlYXN0IGEgZmlnaHRpbmcgY2hhbmNlCm9mIHJ1bGluZyBvdXQgJFxrYXBwYSBcYXBwcm94IDAkIG9yICRca2FwcGEgXGdlIDEwJCwgX2Fzc3VtaW5nXyB0aGF0IGhpZ2gtZnJlcXVlbmN5IHZhcmlhYmlsaXR5CmlzIHRoZSBfb25seV8gc291cmNlIG9mIGVycm9yIChpLmUsIG5vIGZpdHRpbmcgZXJyb3IgYW5kIG5vIGNvbXByb21pc2UgYmV0d2VlbiBleHBlcmltZW50cykuICAKRm9yIDMvNCBvZiB0aGUgbW9kZWxzIHRoZSBNU0UgaXMgYWJvdmUgYHIgc2lnbmlmKHN1bW1hcnkobilbMl0sIDEpYCwgd2hpY2ggaXMgY29tcGFyYWJsZSAKdG8gdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiAkXGthcHBhIFxhcHByb3ggMi4zJCBhbmQgJFxrYXBwYSBcYXBwcm94IDEwJC4gIFRoZSByYW5nZSBvZiAKYWxsb3dhYmxlICRca2FwcGEkIHZhbHVlcyBjb3ZlcnMgZXNzZW50aWFsbHkgX2FsbF8gcGh5c2ljYWxseSBwbGF1c2libGUgdmFsdWVzLgoKQnkgd2F5IG9mIGV4YW1wbGUsIGhlcmUncyBDRVNNMS1DQU01IG92ZXJsYWlkIG9uIHRoZSAkXGthcHBhJCBwbG90cy4KYGBge3Igb3ZseXBsb3R9CmNlc21fYWxsIDwtIGRwbHlyOjpmaWx0ZXIoY21pcF9pbmRpdmlkdWFsLCBtb2RlbD09J0NFU00xLUNBTTUnLCBleHBlcmltZW50PT0ncmNwODUnKQpnZ3Bsb3QoZGF0YT1wbHRkYXRhMjEwMCwgYWVzKHg9eWVhciwgeT12YWx1ZSwgY29sb3I9a2FwcGEpKSArIGdlb21fbGluZShzaXplPTEuMSkgKwogICAgeWxhYignVGVtcGVyYXR1cmUnKSArIHRoZW1lX3NvbGFyaXplZF8yKGxpZ2h0PUZBTFNFKSArIHNjYWxlX2NvbG9yX3NvbGFyaXplZCgpICsKICAgIGdlb21fcG9pbnQoZGF0YT1jZXNtX2FsbCwgY29sb3I9J2xpZ2h0Z3JleScpCmBgYApXZWxsLCBvaywgbm90IHF1aXRlIHRoZSBpbGx1c3RyYXRpb24gSSdkIGhvcGVkIGJlY2F1c2UgdGhlc2UgbW9kZWwgcnVucyB3ZXJlbid0IApvcHRpbWl6ZWQgdG8gdGhhdCBDRVNNIHJ1biwgYnV0IGhvcGVmdWxseSBpdCdzIGNsZWFyIHRoYXQgd2hlbiB5b3UgaW5jbHVkZSBhbGwKdGhlIGVuc2VtYmxlIG1lbWJlcnMsIHRoZSBiYW5kIGVhc2lseSBzcGFucyBhIHdpZHRoIGNvbXBhcmFibGUgdG8gdGhlIHdpZHRoIG9mCnRoZSBiYW5kIG9mICRca2FwcGEkIHZhbHVlcy4gIAoKIyMjIFdoYXQgbmV4dD8KCk9uZSB0aGluZyB0aGF0IF9taWdodF8gaGVscCB3b3VsZCBiZSB0byBzbW9vdGggdGhlIEVTTXMgc28gdGhhdCB3ZSBoYXZlIEhlY3Rvcgp0cnlpbmcgdG8gZml0IHRoZWlyIHNtb290aCB0cmVuZCwgd2hpY2ggaXMgYWxsIGl0IGNhbiByZWFsbHkgaG9wZSB0byBkbyBhbnlob3cuCkknbSBjdXJpb3VzIHRvIHNlZSBpZiBkb2luZyB0aGUgZml0cyBpbiBwcmluY2lwYWwgY29tcG9uZW50IHNwYWNlIG1pZ2h0IGFjY29tcGxpc2gKdGhpcyBpbiBhIGxlc3MgYWQtaG9jIHdheSB0aGFuIHVzaW5nIHNvbWV0aGluZyBsaWtlIGxvZXNzIChtb3JlIGFib3V0IHRoZSBwcmluY2lwYWwKY29tcG9uZW50cyBhbmdsZSB0b21vcnJvdykuICBPZiBjb3Vyc2UsIHRoZSBkaXNjcmVwYW5jaWVzCmJldHdlZW4gZXhwZXJpbWVudHMgYW5kIGVuc2VtYmxlIG1lbWJlcnMgbWF5IHN0aWxsIGxlYWQgdG8gbm9uLWlkZW50aWZpYWJpbGl0eSBiZXR3ZWVuCiRTJCBhbmQgJFxrYXBwYSQuICBFdmVuIGlmIGl0IGRvZXNuJ3QsIHRoZSBmYWN0IHRoYXQgb25lICRca2FwcGEkIGlzIGZhdm9yZWQgCmRvZXNuJ3QgbWVhbiBpdCdzIHRoZSBfcmlnaHRfIHZhbHVlLCBzbyBJJ20gbm90IHN1cmUgaG93IG11Y2ggc3RvY2sgd2Ugc2hvdWxkIHB1dCBpbgpmaXRzIGRvbmUgd2l0aCBzbW9vdGhlZCByZXN1bHRzLiAgSG93ZXZlciwgSSBkbyB0aGluayB3ZSB3YW50IHRvIGtub3cgd2hhdCBoYXBwZW5zCndoZW4gd2UgdHJ5IHRob3NlIG90aGVyIG1ldGhvZHMgc28gdGhhdCB3ZSBjYW4gcGxhbiBvdXIgbmV4dCBtb3ZlLCBhcyB3ZWxsIGFzIHNvIHdlCmNhbiBzdGFydCB0byBmaWd1cmUgb3V0IHdoYXQgb3VyIGZpbmRpbmdzIGFyZSBnb2luZyB0byBiZSBmb3IgdGhpcyBwYXBlci4gIAo=