Purpose
During the concentration driven experiments we saw that \(S\) and \(\kappa\) were able to trade off with one another, making it impossible for the optimization routine to identify unique solutions of \(S\) and \(\kappa\) for the different model fits. We are also concerned that something similar is occurring with carbon cycle parameters in the emission driven calibration. Which is why we opted to apply a penalty to constrain the carbon cycle parameters. Here are the “symmetry tests”, where we fix one of the symmetrical parameters and solve for the remaining Hector parameters for the concentration and emission driven run.
Set Up
library(dplyr)
library(tidyr)
library(ggplot2)
library(knitr)
BASE_DIR <- "/Users/dorh012/Documents/2019/hectorcal/analysis/paper_1"
# Import the data from the carbon cycle symetry results and add info about the pentaly.
beta_q10 <- read.csv(list.files(file.path(BASE_DIR, 'output', 'emiss_beta_q10'), '.csv', full.name = TRUE),
stringsAsFactors = FALSE)
beta_q10_penalty <- read.csv(list.files(file.path(BASE_DIR, 'output', 'emiss_beta_q10_penalty2'), '.csv',
full.name = TRUE), stringsAsFactors = FALSE)
beta_q10$penalty <- 'no penalty'
beta_q10_penalty$penalty <- 'penalty'
beta_q10_df <- bind_rows(beta_q10, beta_q10_penalty)
# Import the data for the cliamte system symetry test runs.
S_kappa <- read.csv(list.files(file.path(BASE_DIR, 'output', 'conc_S_kappa_temp'), '.csv', full.name = TRUE),
stringsAsFactors = FALSE)
S_kappa_HF <- read.csv(list.files(file.path(BASE_DIR, 'output', 'conc_S_kappa_tempHF'), '.csv',
full.name = TRUE), stringsAsFactors = FALSE)
S_kappa_df <- bind_rows(S_kappa, S_kappa_HF)
Concentration Driven Tests
For the concentration driven symmetry tests \(\kappa\) was fixed at values ranging from 0 to 5, the remaining climate variables were optimized by our calibration protocol that uses temp-only or a combination of temp and heat flux. The first plot compares the \(\kappa\) values vs the minimized temperature MSE. The second plot shows how the relationship between \(\kappa\) and \(S\) change when the ocean heat flux constraint it added.
ggplot(data = S_kappa_df,
aes(kappa, min, color = model))+
geom_line() +
geom_point() +
facet_wrap('comp_data') +
labs(x = expression(kappa),
y = 'minmized temp MSE')

The relationship between \(\kappa\) and temp MSE changes from being constant in the temperature-only run to having a defined minimum in the temperature-heat flux set up.
ggplot(data = S_kappa_df,
aes(kappa, S, color = model))+
geom_line() +
geom_point() +
facet_wrap('comp_data') +
labs(x = expression(kappa),
y = 'S')

The correlation between \(\kappa\) and \(S\) reverses when we add the ocean heat flux constraint. This is similar to what we are seeing in the mcmc runs which is dope.
The symmetry about \(S\) and \(\kappa\) is fairly obvious in this experiment. I would hope for something similar in the set up for the emission driven runs with vs without the penalty.
Shout out to BBL
So I talked to BBL about observational values of \(\beta\) and \(Q_{10}\). And this is what he passed along.
Q10 global scale papers:
* Mahecha et al. 2010, found convergence around 1.5. http://dx.doi.org/10.1126/science.1189587
* Bond-Lamberty and Thomson 2010, global soil respiration Q10 of 1.4 http://dx.doi.org/10.1038/nature08930
* Johnston and Sibly 2018, latitudinal gradient of 2.3 to 2.7. http://dx.doi.org/10.1038/s41559-018-0648-6
* The E3SM team has found that a global Q10 of 1.5 leads to best performance vis-a-vis ILAMB benchmarks and observational records.
The CO2 fertilization literature is more scattered (or maybe I just don’t know it as well). Tree rings, satellites, greenhouse studies, FACE studies–they seem to all give wildly divergent estimates of possible beta strength.
When I spent some time looking at the \(\beta\) literature what I could find didn’t report values, if it did it was rarely a global value and since Hector’s beta is unit less it was hard to get a sense of what values would be comparable to one another.
New constraint, the following is pulled from BBL’s nature paper.
These data suggest a moderate response of global RS to temperature: a Q10 (rate of change of RS with an increase in temperature of 10 °C) of 1.5. This value matches, within confidence limits, global Q10 values for RS (2.1 ± 0.7 and 1.9 ± 0.4) constrained by the observed interannual variability in atmospheric CO2 using the UK Met Office Hadley Centre coupled global model11.
Emission Driven Tests
Now we suspect that there is trade off occurring between \(\beta\) and \(Q_{10}\). So now we fix \(\beta\) values and solve for the remaining climate and carbon cycle parameters. Not all of the sampled values of \(\beta\) converged, it took a lot more iterations to get the emission driven runs to converge. In the penalty set up \(Q_{10}\) was set constrained using the log mesa function where a = 1.5, b = 2.8, dig = 0.10 from BBL’s paper. This range is very different from the range we found from the DOE PI meeting MCMC.
ggplot(data = beta_q10_df,
aes(beta, min_value, color = model))+
geom_line() +
geom_point() +
facet_wrap('penalty') +
labs(x = expression(beta),
y = 'MSE')

As we were expecting without the penalty the MSE is constant across the fixed \(\beta\) values however it does look like CanESM2 has a bit of a trend in it. I don’t really have a sense of what sort of slope in the parameter vs MSE line would mean that optim would be able to solve for a unique solution. My gut says that the gradient of the line is not enough for optim to identify unique solutions but what do you guys think? And that even with the penalty applied there is some un-identifiablity with \(\beta\) less than 0.25.
Pay attention to the scales on these!
ggplot(data = beta_q10_df,
aes(beta, q10_rh, color = model))+
geom_line() +
geom_point() +
facet_wrap('penalty', scales = 'free') +
labs(x = expression(beta),
y = expression(Q[10]))

Based off of these two plots I am inclined to say that the penalty function does help resolve some of the the Identifiability issues we are seeing with \(\beta\) and \(Q_{10}\) but I suspect that optim is still going to be used to really low values of \(\beta\).
Conclusions
Apply the penalty function to the calibration set up somewhat works but I am not sure if it works entirely.
LS0tCnRpdGxlOiAiU3ltbWV0cnkgYmV0YSBhbmQgcTEwIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIyBQdXJwb3NlIAoKRHVyaW5nIHRoZSBjb25jZW50cmF0aW9uIGRyaXZlbiBleHBlcmltZW50cyB3ZSBzYXcgdGhhdCAkUyQgYW5kICRca2FwcGEkIHdlcmUgYWJsZSB0byB0cmFkZSBvZmYgd2l0aCBvbmUgYW5vdGhlciwgbWFraW5nIGl0IGltcG9zc2libGUgZm9yIHRoZSBvcHRpbWl6YXRpb24gcm91dGluZSB0byBpZGVudGlmeSB1bmlxdWUgc29sdXRpb25zIG9mICRTJCBhbmQgJFxrYXBwYSQgZm9yIHRoZSBkaWZmZXJlbnQgbW9kZWwgZml0cy4gV2UgYXJlIGFsc28gY29uY2VybmVkIHRoYXQgc29tZXRoaW5nIHNpbWlsYXIgaXMgb2NjdXJyaW5nIHdpdGggY2FyYm9uIGN5Y2xlIHBhcmFtZXRlcnMgaW4gdGhlIGVtaXNzaW9uIGRyaXZlbiBjYWxpYnJhdGlvbi4gV2hpY2ggaXMgd2h5IHdlIG9wdGVkIHRvIGFwcGx5IGEgcGVuYWx0eSB0byBjb25zdHJhaW4gdGhlIGNhcmJvbiBjeWNsZSBwYXJhbWV0ZXJzLiBIZXJlIGFyZSB0aGUg4oCcc3ltbWV0cnkgdGVzdHPigJ0sIHdoZXJlIHdlIGZpeCBvbmUgb2YgdGhlIHN5bW1ldHJpY2FsIHBhcmFtZXRlcnMgYW5kIHNvbHZlIGZvciB0aGUgcmVtYWluaW5nIEhlY3RvciBwYXJhbWV0ZXJzIGZvciB0aGUgY29uY2VudHJhdGlvbiBhbmQgZW1pc3Npb24gZHJpdmVuIHJ1bi4gCgojIyBTZXQgVXAgCgpgYGB7cn0KbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGtuaXRyKQoKQkFTRV9ESVIgPC0gIi9Vc2Vycy9kb3JoMDEyL0RvY3VtZW50cy8yMDE5L2hlY3RvcmNhbC9hbmFseXNpcy9wYXBlcl8xIgpgYGAKCmBgYHtyfQojIEltcG9ydCB0aGUgZGF0YSBmcm9tIHRoZSBjYXJib24gY3ljbGUgc3ltZXRyeSByZXN1bHRzIGFuZCBhZGQgaW5mbyBhYm91dCB0aGUgcGVudGFseS4gCmJldGFfcTEwIDwtIHJlYWQuY3N2KGxpc3QuZmlsZXMoZmlsZS5wYXRoKEJBU0VfRElSLCAnb3V0cHV0JywgJ2VtaXNzX2JldGFfcTEwJyksICcuY3N2JywgZnVsbC5uYW1lID0gVFJVRSksIAogICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCmJldGFfcTEwX3BlbmFsdHkgPC0gcmVhZC5jc3YobGlzdC5maWxlcyhmaWxlLnBhdGgoQkFTRV9ESVIsICdvdXRwdXQnLCAnZW1pc3NfYmV0YV9xMTBfcGVuYWx0eTInKSwgJy5jc3YnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVsbC5uYW1lID0gVFJVRSksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKYmV0YV9xMTAkcGVuYWx0eSAgICAgICAgIDwtICdubyBwZW5hbHR5JwpiZXRhX3ExMF9wZW5hbHR5JHBlbmFsdHkgPC0gJ3BlbmFsdHknCmJldGFfcTEwX2RmIDwtIGJpbmRfcm93cyhiZXRhX3ExMCwgYmV0YV9xMTBfcGVuYWx0eSkKCiMgSW1wb3J0IHRoZSBkYXRhIGZvciB0aGUgY2xpYW10ZSBzeXN0ZW0gc3ltZXRyeSB0ZXN0IHJ1bnMuIApTX2thcHBhIDwtIHJlYWQuY3N2KGxpc3QuZmlsZXMoZmlsZS5wYXRoKEJBU0VfRElSLCAnb3V0cHV0JywgJ2NvbmNfU19rYXBwYV90ZW1wJyksICcuY3N2JywgZnVsbC5uYW1lID0gVFJVRSksIAogICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpClNfa2FwcGFfSEYgPC0gcmVhZC5jc3YobGlzdC5maWxlcyhmaWxlLnBhdGgoQkFTRV9ESVIsICdvdXRwdXQnLCAnY29uY19TX2thcHBhX3RlbXBIRicpLCAnLmNzdicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdWxsLm5hbWUgPSBUUlVFKSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQpTX2thcHBhX2RmIDwtIGJpbmRfcm93cyhTX2thcHBhLCBTX2thcHBhX0hGKQpgYGAKCiMjIENvbmNlbnRyYXRpb24gRHJpdmVuIFRlc3RzCgpGb3IgdGhlIGNvbmNlbnRyYXRpb24gZHJpdmVuIHN5bW1ldHJ5IHRlc3RzICRca2FwcGEkIHdhcyBmaXhlZCBhdCB2YWx1ZXMgcmFuZ2luZyBmcm9tIDAgdG8gNSwgdGhlIHJlbWFpbmluZyAKY2xpbWF0ZSB2YXJpYWJsZXMgd2VyZSBvcHRpbWl6ZWQgYnkgb3VyIGNhbGlicmF0aW9uIHByb3RvY29sIHRoYXQgdXNlcyB0ZW1wLW9ubHkgb3IgYSBjb21iaW5hdGlvbiBvZiB0ZW1wIGFuZCAKaGVhdCBmbHV4LiBUaGUgZmlyc3QgcGxvdCBjb21wYXJlcyB0aGUgJFxrYXBwYSQgdmFsdWVzIHZzIHRoZSBtaW5pbWl6ZWQgdGVtcGVyYXR1cmUgTVNFLiBUaGUgc2Vjb25kIHBsb3Qgc2hvd3MgaG93IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiAkXGthcHBhJCBhbmQgJFMkIGNoYW5nZSB3aGVuIHRoZSBvY2VhbiBoZWF0IGZsdXggY29uc3RyYWludCBpdCBhZGRlZC4gCgoKYGBge3J9CmdncGxvdChkYXRhID0gU19rYXBwYV9kZiwgCiAgICAgICBhZXMoa2FwcGEsIG1pbiwgY29sb3IgPSBtb2RlbCkpKyAKICAgIGdlb21fbGluZSgpICsgCiAgICBnZW9tX3BvaW50KCkgKyAKICAgIGZhY2V0X3dyYXAoJ2NvbXBfZGF0YScpICArIAogICAgbGFicyh4ID0gZXhwcmVzc2lvbihrYXBwYSksIAogICAgICAgICB5ID0gJ21pbm1pemVkIHRlbXAgTVNFJykKYGBgCgoKVGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuICRca2FwcGEkIGFuZCB0ZW1wIE1TRSBjaGFuZ2VzIGZyb20gYmVpbmcgY29uc3RhbnQgaW4gdGhlIHRlbXBlcmF0dXJlLW9ubHkgcnVuIHRvIGhhdmluZyBhIGRlZmluZWQgbWluaW11bSBpbiB0aGUgdGVtcGVyYXR1cmUtaGVhdCBmbHV4IHNldCB1cC4gCgo8YnI+CgoKYGBge3J9CmdncGxvdChkYXRhID0gU19rYXBwYV9kZiwgCiAgICAgICBhZXMoa2FwcGEsIFMsIGNvbG9yID0gbW9kZWwpKSsgCiAgICBnZW9tX2xpbmUoKSArIAogICAgZ2VvbV9wb2ludCgpICsgCiAgICBmYWNldF93cmFwKCdjb21wX2RhdGEnKSArIAogICAgICAgIGxhYnMoeCA9IGV4cHJlc3Npb24oa2FwcGEpLCAKICAgICAgICAgeSA9ICdTJykKYGBgCgpUaGUgY29ycmVsYXRpb24gYmV0d2VlbiAkXGthcHBhJCBhbmQgJFMkIHJldmVyc2VzIHdoZW4gd2UgYWRkIHRoZSBvY2VhbiBoZWF0IGZsdXggY29uc3RyYWludC4gVGhpcyBpcyBzaW1pbGFyIHRvIHdoYXQgd2UgYXJlIHNlZWluZyBpbiB0aGUgbWNtYyBydW5zIHdoaWNoIGlzIGRvcGUuICAKCjxicj4KClRoZSBzeW1tZXRyeSBhYm91dCAkUyQgYW5kICRca2FwcGEkIGlzIGZhaXJseSBvYnZpb3VzIGluIHRoaXMgZXhwZXJpbWVudC4gSSB3b3VsZCBob3BlIGZvciBzb21ldGhpbmcgc2ltaWxhciBpbiB0aGUgc2V0IHVwIGZvciB0aGUgZW1pc3Npb24gZHJpdmVuIHJ1bnMgd2l0aCB2cyB3aXRob3V0IHRoZSBwZW5hbHR5LiAKCgojIyBTaG91dCBvdXQgdG8gQkJMIAoKU28gSSB0YWxrZWQgdG8gQkJMIGFib3V0IG9ic2VydmF0aW9uYWwgdmFsdWVzIG9mICRcYmV0YSQgYW5kICRRX3sxMH0kLiBBbmQgdGhpcyBpcyB3aGF0IGhlIHBhc3NlZCBhbG9uZy4gCgpgYGAKUTEwIGdsb2JhbCBzY2FsZSBwYXBlcnM6CiogTWFoZWNoYSBldCBhbC4gMjAxMCwgZm91bmQgY29udmVyZ2VuY2UgYXJvdW5kIDEuNS4gaHR0cDovL2R4LmRvaS5vcmcvMTAuMTEyNi9zY2llbmNlLjExODk1ODcKKiBCb25kLUxhbWJlcnR5IGFuZCBUaG9tc29uIDIwMTAsIGdsb2JhbCBzb2lsIHJlc3BpcmF0aW9uIFExMCBvZiAxLjQgaHR0cDovL2R4LmRvaS5vcmcvMTAuMTAzOC9uYXR1cmUwODkzMAoqIEpvaG5zdG9uIGFuZCBTaWJseSAyMDE4LCBsYXRpdHVkaW5hbCBncmFkaWVudCBvZiAyLjMgdG8gMi43LiBodHRwOi8vZHguZG9pLm9yZy8xMC4xMDM4L3M0MTU1OS0wMTgtMDY0OC02CiogVGhlIEUzU00gdGVhbSBoYXMgZm91bmQgdGhhdCBhIGdsb2JhbCBRMTAgb2YgMS41IGxlYWRzIHRvIGJlc3QgcGVyZm9ybWFuY2UgdmlzLWEtdmlzIElMQU1CIGJlbmNobWFya3MgYW5kIG9ic2VydmF0aW9uYWwgcmVjb3Jkcy4KCgpUaGUgQ08yIGZlcnRpbGl6YXRpb24gbGl0ZXJhdHVyZSBpcyBtb3JlIHNjYXR0ZXJlZCAob3IgbWF5YmUgSSBqdXN0IGRvbuKAmXQga25vdyBpdCBhcyB3ZWxsKS4gVHJlZSByaW5ncywgc2F0ZWxsaXRlcywgZ3JlZW5ob3VzZSBzdHVkaWVzLCBGQUNFIHN0dWRpZXPigJN0aGV5IHNlZW0gdG8gYWxsIGdpdmUgd2lsZGx5IGRpdmVyZ2VudCBlc3RpbWF0ZXMgb2YgcG9zc2libGUgYmV0YSBzdHJlbmd0aC4KYGBgCgpXaGVuIEkgc3BlbnQgc29tZSB0aW1lIGxvb2tpbmcgYXQgdGhlICRcYmV0YSQgbGl0ZXJhdHVyZSB3aGF0IEkgY291bGQgZmluZCBkaWRuJ3QgcmVwb3J0IHZhbHVlcywgaWYgaXQgZGlkIGl0IHdhcyByYXJlbHkgYSBnbG9iYWwgdmFsdWUgYW5kIHNpbmNlIEhlY3RvcidzIGJldGEgaXMgdW5pdCBsZXNzIGl0IHdhcyBoYXJkIHRvIGdldCBhIHNlbnNlIG9mIHdoYXQgdmFsdWVzIHdvdWxkIGJlIGNvbXBhcmFibGUgdG8gb25lIGFub3RoZXIuIAoKCk5ldyBjb25zdHJhaW50LCB0aGUgZm9sbG93aW5nIGlzIHB1bGxlZCBmcm9tIEJCTCdzIG5hdHVyZSBwYXBlci4gCgpgYGAKVGhlc2UgZGF0YSBzdWdnZXN0IGEgbW9kZXJhdGUgcmVzcG9uc2Ugb2YgZ2xvYmFsIFJTIHRvIHRlbXBlcmF0dXJlOiBhIFExMCAocmF0ZSBvZiBjaGFuZ2Ugb2YgUlMgd2l0aCBhbiBpbmNyZWFzZSBpbiB0ZW1wZXJhdHVyZSBvZiAxMOKAicKwQykgb2YgMS41LiBUaGlzIHZhbHVlIG1hdGNoZXMsIHdpdGhpbiBjb25maWRlbmNlIGxpbWl0cywgZ2xvYmFsIFExMCB2YWx1ZXMgZm9yIFJTICgyLjHigInCseKAiTAuNyBhbmQgMS454oCJwrHigIkwLjQpIGNvbnN0cmFpbmVkIGJ5IHRoZSBvYnNlcnZlZCBpbnRlcmFubnVhbCB2YXJpYWJpbGl0eSBpbiBhdG1vc3BoZXJpYyBDTzIgdXNpbmcgdGhlIFVLIE1ldCBPZmZpY2UgSGFkbGV5IENlbnRyZSBjb3VwbGVkIGdsb2JhbCBtb2RlbDExLiAKYGBgCgoKCgojIyBFbWlzc2lvbiBEcml2ZW4gVGVzdHMKCk5vdyB3ZSBzdXNwZWN0IHRoYXQgdGhlcmUgaXMgdHJhZGUgb2ZmIG9jY3VycmluZyBiZXR3ZWVuICRcYmV0YSQgYW5kICRRX3sxMH0kLiBTbyBub3cgd2UgZml4ICRcYmV0YSQgdmFsdWVzIGFuZCBzb2x2ZSBmb3IgdGhlIHJlbWFpbmluZyBjbGltYXRlIGFuZCBjYXJib24gY3ljbGUgcGFyYW1ldGVycy4gTm90IGFsbCBvZiB0aGUgc2FtcGxlZCB2YWx1ZXMgb2YgJFxiZXRhJCBjb252ZXJnZWQsIGl0IHRvb2sKYSBsb3QgbW9yZSBpdGVyYXRpb25zIHRvIGdldCB0aGUgZW1pc3Npb24gZHJpdmVuIHJ1bnMgdG8gY29udmVyZ2UuIEluICB0aGUgcGVuYWx0eSAgc2V0IHVwICRRX3sxMH0kIHdhcyBzZXQgY29uc3RyYWluZWQgdXNpbmcgdGhlIGxvZyBtZXNhIGZ1bmN0aW9uIHdoZXJlIGEgPSAxLjUsIGIgPSAyLjgsIGRpZyA9IDAuMTAgZnJvbSBCQkwncyBwYXBlci4gVGhpcyByYW5nZSBpcyB2ZXJ5IGRpZmZlcmVudCAgZnJvbSB0aGUgcmFuZ2Ugd2UgZm91bmQgIGZyb20gdGhlIERPRSBQSSBtZWV0aW5nIE1DTUMuIAo8YnI+CgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBiZXRhX3ExMF9kZiwgCiAgICAgICBhZXMoYmV0YSwgbWluX3ZhbHVlLCBjb2xvciA9IG1vZGVsKSkrIAogICAgZ2VvbV9saW5lKCkgKyAKICAgIGdlb21fcG9pbnQoKSArIAogICAgZmFjZXRfd3JhcCgncGVuYWx0eScpICArIAogICAgbGFicyh4ID0gZXhwcmVzc2lvbihiZXRhKSwgCiAgICAgICAgIHkgPSAnTVNFJykKYGBgCgpBcyB3ZSB3ZXJlIGV4cGVjdGluZyB3aXRob3V0IHRoZSBwZW5hbHR5IHRoZSBNU0UgaXMgY29uc3RhbnQgYWNyb3NzIHRoZSBmaXhlZCAkXGJldGEkIHZhbHVlcyBob3dldmVyIGl0IGRvZXMKbG9vayBsaWtlIENhbkVTTTIgaGFzIGEgYml0IG9mIGEgdHJlbmQgaW4gaXQuIEkgZG9uJ3QgcmVhbGx5IGhhdmUgYSBzZW5zZSBvZiB3aGF0IHNvcnQgb2Ygc2xvcGUgaW4gdGhlIHBhcmFtZXRlciB2cyBNU0UgbGluZSB3b3VsZCBtZWFuIHRoYXQgb3B0aW0gd291bGQgYmUgYWJsZSB0byBzb2x2ZSBmb3IgYSB1bmlxdWUgc29sdXRpb24uIE15IGd1dCBzYXlzIHRoYXQgdGhlIGdyYWRpZW50IG9mIHRoZSBsaW5lIGlzIG5vdCBlbm91Z2ggZm9yIG9wdGltIHRvIGlkZW50aWZ5IHVuaXF1ZSBzb2x1dGlvbnMgYnV0IHdoYXQgZG8geW91IGd1eXMgdGhpbms/IEFuZCB0aGF0IGV2ZW4gd2l0aCB0aGUgcGVuYWx0eSBhcHBsaWVkIHRoZXJlIGlzIHNvbWUgdW4taWRlbnRpZmlhYmxpdHkgd2l0aCAkXGJldGEkIGxlc3MgdGhhbiAwLjI1LiAgCgo8YnI+CgpQYXkgYXR0ZW50aW9uIHRvIHRoZSBzY2FsZXMgb24gdGhlc2UhIAoKYGBge3J9CmdncGxvdChkYXRhID0gYmV0YV9xMTBfZGYsIAogICAgICAgYWVzKGJldGEsIHExMF9yaCwgY29sb3IgPSBtb2RlbCkpKyAKICAgIGdlb21fbGluZSgpICsgCiAgICBnZW9tX3BvaW50KCkgKyAKICAgIGZhY2V0X3dyYXAoJ3BlbmFsdHknLCBzY2FsZXMgPSAnZnJlZScpICArIAogICAgbGFicyh4ID0gZXhwcmVzc2lvbihiZXRhKSwgCiAgICAgICAgIHkgPSBleHByZXNzaW9uKFFbMTBdKSkKYGBgCgpCYXNlZCBvZmYgb2YgdGhlc2UgdHdvIHBsb3RzIEkgYW0gaW5jbGluZWQgdG8gc2F5IHRoYXQgdGhlIHBlbmFsdHkgZnVuY3Rpb24gZG9lcyBoZWxwIHJlc29sdmUgc29tZSBvZiB0aGUgdGhlIElkZW50aWZpYWJpbGl0eSBpc3N1ZXMgd2UgYXJlIHNlZWluZyB3aXRoICRcYmV0YSQgYW5kICRRX3sxMH0kIGJ1dCBJIHN1c3BlY3QgdGhhdCBvcHRpbSBpcyBzdGlsbCBnb2luZyB0byBiZSB1c2VkIHRvIHJlYWxseSBsb3cgdmFsdWVzIG9mICRcYmV0YSQuIAoKCiMjIENvbmNsdXNpb25zIAoKQXBwbHkgdGhlIHBlbmFsdHkgZnVuY3Rpb24gdG8gdGhlIGNhbGlicmF0aW9uIHNldCB1cCBzb21ld2hhdCB3b3JrcyBidXQgSSBhbSBub3Qgc3VyZSBpZiBpdCB3b3JrcyBlbnRpcmVseS4gCgoKCgoKCgoKCgoKCg==