Purpose

Now that we have determined that the land an ocean tempearture does not resolve the issue of S and diff we are going to try using heat flux as comparison data.

Set Up and Define Functions

library(hector)
devtools::load_all("/Users/dorh012/Documents/2019/hectorcal")

Calibrate Hector to CESM1-CAM5 data.

# To make things easy we are going to start out just looking at the rcp 85 + historical results. 
cmip_individual %>% 
    filter(model == 'CESM1-CAM5' & experiment %in% c('historical', 'rcp85')) %>%  
    select(year, model, value) %>% 
    mutate(variable = GLOBAL_TEMP(), experiment = 'rcp85') -> 
    cesm_comp_data
core <- newcore(system.file('input/hector_rcp85.ini', package = 'hector'))
fn   <- minimize_global(core = core, comparison_data = cesm_comp_data)
params <- c(3.5, 1.5, 0.6)
names(params) <- c(ECS(), AERO_SCALE(), VOLCANIC_SCALE())
print(params)
     S  alpha volscl 
   3.5    1.5    0.6 
cesm_temp_fits <- optim(par = params, fn = fn)

What were the best fit params?

cesm_temp_fits$par
       S    alpha   volscl 
3.649249 1.221565 1.033603 


Emulate CESM1-CAM5 Heat Flux Data

Use the best fits to run Hector again and pull out the global temp and the heat flux.

parameterize_core(params = cesm_temp_fits$par, core)
Hector core:    unnamed hector core
Start date: 1745
End date:   2300
Current date:   1745
Input file: /Users/dorh012/Library/R/3.5/library/hector/input/hector_rcp85.ini
reset(core)
Hector core:    unnamed hector core
Start date: 1745
End date:   2300
Current date:   1745
Input file: /Users/dorh012/Library/R/3.5/library/hector/input/hector_rcp85.ini
run(core)
Hector core:    unnamed hector core
Start date: 1745
End date:   2300
Current date:   2300
Input file: /Users/dorh012/Library/R/3.5/library/hector/input/hector_rcp85.ini
fetchvars(core, 1850:2100, c(GLOBAL_TEMP(), HEAT_FLUX())) %>%
    select(year, value, variable) %>%
    mutate(experiment = 'rcp85', model = 'emulated CESM') ->
    emulatedCESM_comp_data

Fit S, alpha, and volscl to CESM1-CAM5 at fixed diff

diff_values <- seq(from = 0.5, to = 15, by = 1)
lapply(diff_values, function(x){
    # Make a new core
    core <- newcore(system.file('input/hector_rcp85.ini', package = 'hector'))
    # Reset the diff value
    dif        <- x
    names(dif) <- DIFFUSIVITY()
    parameterize_core(core = core, params = dif)
    reset(core)
    # The function to minimize
    fn <- minimize_temp_flux(core = core, comparison_data = emulatedCESM_comp_data)
    # Make the inital guess for the parameter
    best_guess        <- c(3.649204, 1.221605, 1.033848)
    names(best_guess) <- c( 'S', 'alpha', 'volscl')
    # Minmize the paramters
    fit_heatFlux_temp <- optim(par = best_guess, fn = fn,  control = list('maxit' = 900))
    # If the optimization was sucessful then use it as hector input.
    if(fit_heatFlux_temp$convergence == 0 ){
        parameterize_core(params = fit_heatFlux_temp$par, core)
        reset(core)
        run(core, runtodate = 2100)
        fetchvars(core, dates = 1750:2100, vars = c(hector::GLOBAL_TEMP(), hector::HEAT_FLUX())) %>%
            mutate(S = fit_heatFlux_temp$par[['S']],
                   diff = x,
                   alpha = fit_heatFlux_temp$par[['alpha']],
                   volscl = fit_heatFlux_temp$par[['volscl']],
                   SE = fit_heatFlux_temp$value)
    }}) %>%
    bind_rows ->
    heatFlux_temp_fits


How do the fits look?

ggplot(data = heatFlux_temp_fits) +
    geom_point(data = cesm_comp_data, aes(year, value, color = 'actual CESM1')) +
    geom_point(data = emulatedCESM_comp_data, aes(year, value, color = 'emulated CESM1')) +
    geom_line(aes(year, value, group = diff)) +
    facet_wrap('variable') +
    coord_cartesian(xlim = c(1850, 2100)) +
    labs(title = 'Hector fits at fixed diff vs comparison data')


What is the relationship between S and diff?

heatFlux_temp_fits %>%
    select(S, diff, 'minimized squared error' = SE) %>%
    distinct %>%
    ggplot(aes(diff, S, color = `minimized squared error`)) +
    geom_point(size = 3) +
    coord_cartesian(ylim = c(0, 6)) +
    theme(legend.position = 'bottom') +
    labs(title = 'Best fit S vs diff')

The darker the blue the better the fit is. The dark blue dots are over the range of diff values that we expect to be reasonable.

What happens if we fit for alpha and S?

# Inital parameter guesses
inital_guess        <- c(3.5, 1.6,  0.6, 2.3)
names(inital_guess) <- c(ECS(), AERO_SCALE(), VOLCANIC_SCALE(), DIFFUSIVITY())
# Make the function to minimize and optmize the fit.
fn_heatF_tmep <- minimize_temp_flux(core = core, comparison_data = emulatedCESM_comp_data)
fit_S_diff    <- optim(par = inital_guess, fn = fn_heatF_tmep)

What do the parameter values look like?

fit_S_diff$par
       S    alpha   volscl     diff 
3.649284 1.221651 1.033753 2.299885 

Other than the alpha value, the other parameter values are pretty realistic.


What does the fit look like?

# Run hector with parameter values
parameterize_core(fit_S_diff$par, core)
Hector core:    unnamed hector core
Start date: 1745
End date:   2300
Current date:   1745
Input file: /Users/dorh012/Library/R/3.5/library/hector/input/hector_rcp85.ini
run(core)
Hector core:    unnamed hector core
Start date: 1745
End date:   2300
Current date:   2300
Input file: /Users/dorh012/Library/R/3.5/library/hector/input/hector_rcp85.ini
hector_output <- fetchvars(core = core, dates = 1850:2100, vars = c(GLOBAL_TEMP()))
ggplot(data = hector_output, aes(year, value, color = 'hector output')) +
    geom_point(data = cesm_comp_data, aes(year, value, color = 'CESM1-CAM5')) +
    geom_line(size = 1)

Looks pretty good to me!

Conclusions

Using heat flux as comparison data resolved the problem of S and diff! whoot whoot!

Next Steps

  1. Get heat flux scale and center results? (do we want it from the PCA or I could just get it from the ensemble)
  2. Test with the actual CESM1-CAM5 data
  3. Download/process the CMIP5 results for the heat flux data
LS0tCnRpdGxlOiAiRG9lcyBoZWF0IGZsdXggc29sdmUgdGhlIFMgYW5kIGRpZmYgcHJvYmxlbT8iCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCgojIyBQdXJwb3NlIAoKTm93IHRoYXQgd2UgaGF2ZSBkZXRlcm1pbmVkIHRoYXQgdGhlIGxhbmQgYW4gb2NlYW4gdGVtcGVhcnR1cmUgZG9lcyBub3QgcmVzb2x2ZSB0aGUgaXNzdWUgb2YgUyBhbmQgZGlmZiB3ZSBhcmUgZ29pbmcgdG8gdHJ5IHVzaW5nIGhlYXQgZmx1eCBhcyBjb21wYXJpc29uIGRhdGEuIAoKCiMjIyBTZXQgVXAgYW5kIERlZmluZSBGdW5jdGlvbnMgCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpsaWJyYXJ5KGhlY3RvcikKZGV2dG9vbHM6OmxvYWRfYWxsKCIvVXNlcnMvZG9yaDAxMi9Eb2N1bWVudHMvMjAxOS9oZWN0b3JjYWwiKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCgptaW5pbWl6ZV9nbG9iYWwgPC0gZnVuY3Rpb24oY29yZSwgY29tcGFyaXNvbl9kYXRhKXsKCiAgICBmdW5jdGlvbihwYXJhbSl7CgogICAgICAgIG9wdGlvbnMoc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKICAgICAgICB0cnlDYXRjaChleHByID0gewogICAgICAgICAgICBwYXJhbWV0ZXJpemVfY29yZShwYXJhbXMgPSBwYXJhbSwgY29yZSA9IGNvcmUpCiAgICAgICAgICAgIHJlc2V0KGNvcmUpCiAgICAgICAgICAgIHJ1bihjb3JlKQoKICAgICAgICAgICAgZmV0Y2h2YXJzKGNvcmUsIGRhdGVzID0gMTg1MToyMTAwLCB2YXJzID0gR0xPQkFMX1RFTVAoKSkgJT4lCiAgICAgICAgICAgICAgICByZW5hbWUoaGVjdG9yX3ZhbHVlID0gdmFsdWUpICU+JQogICAgICAgICAgICAgICAgbGVmdF9qb2luKGNvbXBhcmlzb25fZGF0YSwgYnkgPSBjKCJ5ZWFyIiwgInZhcmlhYmxlIikpICU+JQogICAgICAgICAgICAgICAgbXV0YXRlKGRpZiA9ICh2YWx1ZSAtIGhlY3Rvcl92YWx1ZSkgXiAyKSAlPiUKICAgICAgICAgICAgICAgIHB1bGwoZGlmKSAlPiUKICAgICAgICAgICAgICAgIHN1bX0sIGVycm9yPWZ1bmN0aW9uKGUpe0luZn0pCgogICAgfQoKfQoKbWluaW1pemVfdGVtcF9mbHV4IDwtIGZ1bmN0aW9uKGNvcmUsIGNvbXBhcmlzb25fZGF0YSl7CgogICAgZnVuY3Rpb24ocGFyYW0pewoKICAgICAgICBvcHRpb25zKHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCiAgICAgICAgdHJ5Q2F0Y2goZXhwciA9IHsKICAgICAgICAgICAgcGFyYW1ldGVyaXplX2NvcmUocGFyYW1zID0gcGFyYW0sIGNvcmUgPSBjb3JlKQogICAgICAgICAgICByZXNldChjb3JlKQogICAgICAgICAgICBydW4oY29yZSkKCiAgICAgICAgICAgIGZldGNodmFycyhjb3JlLCBkYXRlcyA9IDE4NTA6MjEwMCwgdmFycyA9IGMoR0xPQkFMX1RFTVAoKSwgSEVBVF9GTFVYKCkpKSAlPiUKICAgICAgICAgICAgICAgIHJlbmFtZShoZWN0b3JfdmFsdWUgPSB2YWx1ZSkgJT4lCiAgICAgICAgICAgICAgICBsZWZ0X2pvaW4oY29tcGFyaXNvbl9kYXRhLCBieSA9IGMoInllYXIiLCAidmFyaWFibGUiKSkgJT4lCiAgICAgICAgICAgICAgICBtdXRhdGUoZGlmID0gKHZhbHVlIC0gaGVjdG9yX3ZhbHVlKSBeIDIpICU+JQogICAgICAgICAgICAgICAgcHVsbChkaWYpICU+JQogICAgICAgICAgICAgICAgc3VtfSwgZXJyb3I9ZnVuY3Rpb24oZSl7SW5mfSkKCiAgICB9Cn0KYGBgCgoKIyMgQ2FsaWJyYXRlIEhlY3RvciB0byBDRVNNMS1DQU01IGRhdGEuIAoKYGBge3J9CiMgVG8gbWFrZSB0aGluZ3MgZWFzeSB3ZSBhcmUgZ29pbmcgdG8gc3RhcnQgb3V0IGp1c3QgbG9va2luZyBhdCB0aGUgcmNwIDg1ICsgaGlzdG9yaWNhbCByZXN1bHRzLiAKY21pcF9pbmRpdmlkdWFsICU+JSAKICAgIGZpbHRlcihtb2RlbCA9PSAnQ0VTTTEtQ0FNNScgJiBleHBlcmltZW50ICVpbiUgYygnaGlzdG9yaWNhbCcsICdyY3A4NScpKSAlPiUgIAogICAgc2VsZWN0KHllYXIsIG1vZGVsLCB2YWx1ZSkgJT4lIAogICAgbXV0YXRlKHZhcmlhYmxlID0gR0xPQkFMX1RFTVAoKSwgZXhwZXJpbWVudCA9ICdyY3A4NScpIC0+IAogICAgY2VzbV9jb21wX2RhdGEKCmNvcmUgPC0gbmV3Y29yZShzeXN0ZW0uZmlsZSgnaW5wdXQvaGVjdG9yX3JjcDg1LmluaScsIHBhY2thZ2UgPSAnaGVjdG9yJykpCmZuICAgPC0gbWluaW1pemVfZ2xvYmFsKGNvcmUgPSBjb3JlLCBjb21wYXJpc29uX2RhdGEgPSBjZXNtX2NvbXBfZGF0YSkKCnBhcmFtcyA8LSBjKDMuNSwgMS41LCAwLjYpCm5hbWVzKHBhcmFtcykgPC0gYyhFQ1MoKSwgQUVST19TQ0FMRSgpLCBWT0xDQU5JQ19TQ0FMRSgpKQpwcmludChwYXJhbXMpCmNlc21fdGVtcF9maXRzIDwtIG9wdGltKHBhciA9IHBhcmFtcywgZm4gPSBmbikKYGBgCgoKV2hhdCB3ZXJlIHRoZSBiZXN0IGZpdCBwYXJhbXM/CgpgYGB7cn0KY2VzbV90ZW1wX2ZpdHMkcGFyCmBgYAoKPGJyPgoKIyMgRW11bGF0ZSBDRVNNMS1DQU01IEhlYXQgRmx1eCBEYXRhCgpVc2UgdGhlIGJlc3QgZml0cyB0byBydW4gSGVjdG9yIGFnYWluIGFuZCBwdWxsIG91dCB0aGUgZ2xvYmFsIHRlbXAgYW5kIHRoZSBoZWF0IGZsdXguCgpgYGB7cn0KcGFyYW1ldGVyaXplX2NvcmUocGFyYW1zID0gY2VzbV90ZW1wX2ZpdHMkcGFyLCBjb3JlKQpyZXNldChjb3JlKQpydW4oY29yZSkKCmZldGNodmFycyhjb3JlLCAxODUwOjIxMDAsIGMoR0xPQkFMX1RFTVAoKSwgSEVBVF9GTFVYKCkpKSAlPiUKICAgIHNlbGVjdCh5ZWFyLCB2YWx1ZSwgdmFyaWFibGUpICU+JQogICAgbXV0YXRlKGV4cGVyaW1lbnQgPSAncmNwODUnLCBtb2RlbCA9ICdlbXVsYXRlZCBDRVNNJykgLT4KICAgIGVtdWxhdGVkQ0VTTV9jb21wX2RhdGEKYGBgCgoKIyMgRml0IFMsIGFscGhhLCBhbmQgdm9sc2NsIHRvIENFU00xLUNBTTUgYXQgZml4ZWQgZGlmZgoKCmBgYHtyfQpkaWZmX3ZhbHVlcyA8LSBzZXEoZnJvbSA9IDAuNSwgdG8gPSAxNSwgYnkgPSAxKQoKbGFwcGx5KGRpZmZfdmFsdWVzLCBmdW5jdGlvbih4KXsKCiAgICAjIE1ha2UgYSBuZXcgY29yZQogICAgY29yZSA8LSBuZXdjb3JlKHN5c3RlbS5maWxlKCdpbnB1dC9oZWN0b3JfcmNwODUuaW5pJywgcGFja2FnZSA9ICdoZWN0b3InKSkKCiAgICAjIFJlc2V0IHRoZSBkaWZmIHZhbHVlCiAgICBkaWYgICAgICAgIDwtIHgKICAgIG5hbWVzKGRpZikgPC0gRElGRlVTSVZJVFkoKQogICAgcGFyYW1ldGVyaXplX2NvcmUoY29yZSA9IGNvcmUsIHBhcmFtcyA9IGRpZikKICAgIHJlc2V0KGNvcmUpCgogICAgIyBUaGUgZnVuY3Rpb24gdG8gbWluaW1pemUKICAgIGZuIDwtIG1pbmltaXplX3RlbXBfZmx1eChjb3JlID0gY29yZSwgY29tcGFyaXNvbl9kYXRhID0gZW11bGF0ZWRDRVNNX2NvbXBfZGF0YSkKCiAgICAjIE1ha2UgdGhlIGluaXRhbCBndWVzcyBmb3IgdGhlIHBhcmFtZXRlcgogICAgYmVzdF9ndWVzcyAgICAgICAgPC0gYygzLjY0OTIwNCwgMS4yMjE2MDUsIDEuMDMzODQ4KQogICAgbmFtZXMoYmVzdF9ndWVzcykgPC0gYyggJ1MnLCAnYWxwaGEnLCAndm9sc2NsJykKCiAgICAjIE1pbm1pemUgdGhlIHBhcmFtdGVycwogICAgZml0X2hlYXRGbHV4X3RlbXAgPC0gb3B0aW0ocGFyID0gYmVzdF9ndWVzcywgZm4gPSBmbiwgIGNvbnRyb2wgPSBsaXN0KCdtYXhpdCcgPSA5MDApKQoKICAgICMgSWYgdGhlIG9wdGltaXphdGlvbiB3YXMgc3VjZXNzZnVsIHRoZW4gdXNlIGl0IGFzIGhlY3RvciBpbnB1dC4KICAgIGlmKGZpdF9oZWF0Rmx1eF90ZW1wJGNvbnZlcmdlbmNlID09IDAgKXsKCiAgICAgICAgcGFyYW1ldGVyaXplX2NvcmUocGFyYW1zID0gZml0X2hlYXRGbHV4X3RlbXAkcGFyLCBjb3JlKQogICAgICAgIHJlc2V0KGNvcmUpCiAgICAgICAgcnVuKGNvcmUsIHJ1bnRvZGF0ZSA9IDIxMDApCgogICAgICAgIGZldGNodmFycyhjb3JlLCBkYXRlcyA9IDE3NTA6MjEwMCwgdmFycyA9IGMoaGVjdG9yOjpHTE9CQUxfVEVNUCgpLCBoZWN0b3I6OkhFQVRfRkxVWCgpKSkgJT4lCiAgICAgICAgICAgIG11dGF0ZShTID0gZml0X2hlYXRGbHV4X3RlbXAkcGFyW1snUyddXSwKICAgICAgICAgICAgICAgICAgIGRpZmYgPSB4LAogICAgICAgICAgICAgICAgICAgYWxwaGEgPSBmaXRfaGVhdEZsdXhfdGVtcCRwYXJbWydhbHBoYSddXSwKICAgICAgICAgICAgICAgICAgIHZvbHNjbCA9IGZpdF9oZWF0Rmx1eF90ZW1wJHBhcltbJ3ZvbHNjbCddXSwKICAgICAgICAgICAgICAgICAgIFNFID0gZml0X2hlYXRGbHV4X3RlbXAkdmFsdWUpCiAgICB9fSkgJT4lCiAgICBiaW5kX3Jvd3MgLT4KICAgIGhlYXRGbHV4X3RlbXBfZml0cwpgYGAKCjxicj4KCkhvdyBkbyB0aGUgZml0cyBsb29rPwoKYGBge3J9CgpnZ3Bsb3QoZGF0YSA9IGhlYXRGbHV4X3RlbXBfZml0cykgKwogICAgZ2VvbV9wb2ludChkYXRhID0gY2VzbV9jb21wX2RhdGEsIGFlcyh5ZWFyLCB2YWx1ZSwgY29sb3IgPSAnYWN0dWFsIENFU00xJykpICsKICAgIGdlb21fcG9pbnQoZGF0YSA9IGVtdWxhdGVkQ0VTTV9jb21wX2RhdGEsIGFlcyh5ZWFyLCB2YWx1ZSwgY29sb3IgPSAnZW11bGF0ZWQgQ0VTTTEnKSkgKwogICAgZ2VvbV9saW5lKGFlcyh5ZWFyLCB2YWx1ZSwgZ3JvdXAgPSBkaWZmKSkgKwogICAgZmFjZXRfd3JhcCgndmFyaWFibGUnKSArCiAgICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMTg1MCwgMjEwMCkpICsKICAgIGxhYnModGl0bGUgPSAnSGVjdG9yIGZpdHMgYXQgZml4ZWQgZGlmZiB2cyBjb21wYXJpc29uIGRhdGEnKQoKYGBgCgo8YnI+CgpXaGF0IGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBTIGFuZCBkaWZmPwoKYGBge3J9CgpoZWF0Rmx1eF90ZW1wX2ZpdHMgJT4lCiAgICBzZWxlY3QoUywgZGlmZiwgJ21pbmltaXplZCBzcXVhcmVkIGVycm9yJyA9IFNFKSAlPiUKICAgIGRpc3RpbmN0ICU+JQogICAgZ2dwbG90KGFlcyhkaWZmLCBTLCBjb2xvciA9IGBtaW5pbWl6ZWQgc3F1YXJlZCBlcnJvcmApKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAzKSArCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgNikpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nKSArCiAgICBsYWJzKHRpdGxlID0gJ0Jlc3QgZml0IFMgdnMgZGlmZicpCgpgYGAKClRoZSBkYXJrZXIgdGhlIGJsdWUgdGhlIGJldHRlciB0aGUgZml0IGlzLiBUaGUgZGFyayBibHVlIGRvdHMgYXJlIG92ZXIgdGhlIHJhbmdlIG9mIGRpZmYgdmFsdWVzIHRoYXQgd2UgZXhwZWN0IHRvIGJlIHJlYXNvbmFibGUuCgojIyBXaGF0IGhhcHBlbnMgaWYgd2UgZml0IGZvciBhbHBoYSBhbmQgUz8KCmBgYHtyfQojIEluaXRhbCBwYXJhbWV0ZXIgZ3Vlc3Nlcwppbml0YWxfZ3Vlc3MgICAgICAgIDwtIGMoMy41LCAxLjYsICAwLjYsIDIuMykKbmFtZXMoaW5pdGFsX2d1ZXNzKSA8LSBjKEVDUygpLCBBRVJPX1NDQUxFKCksIFZPTENBTklDX1NDQUxFKCksIERJRkZVU0lWSVRZKCkpCgojIE1ha2UgdGhlIGZ1bmN0aW9uIHRvIG1pbmltaXplIGFuZCBvcHRtaXplIHRoZSBmaXQuCmZuX2hlYXRGX3RtZXAgPC0gbWluaW1pemVfdGVtcF9mbHV4KGNvcmUgPSBjb3JlLCBjb21wYXJpc29uX2RhdGEgPSBlbXVsYXRlZENFU01fY29tcF9kYXRhKQpmaXRfU19kaWZmICAgIDwtIG9wdGltKHBhciA9IGluaXRhbF9ndWVzcywgZm4gPSBmbl9oZWF0Rl90bWVwKQpgYGAKCgpXaGF0IGRvIHRoZSBwYXJhbWV0ZXIgdmFsdWVzIGxvb2sgbGlrZT8KCmBgYHtyfQpmaXRfU19kaWZmJHBhcgpgYGAKCk90aGVyIHRoYW4gdGhlIGFscGhhIHZhbHVlLCB0aGUgb3RoZXIgcGFyYW1ldGVyIHZhbHVlcyBhcmUgcHJldHR5IHJlYWxpc3RpYy4KCjxicj4KCldoYXQgZG9lcyB0aGUgZml0IGxvb2sgbGlrZT8KCmBgYHtyfQojIFJ1biBoZWN0b3Igd2l0aCBwYXJhbWV0ZXIgdmFsdWVzCnBhcmFtZXRlcml6ZV9jb3JlKGZpdF9TX2RpZmYkcGFyLCBjb3JlKQpydW4oY29yZSkKaGVjdG9yX291dHB1dCA8LSBmZXRjaHZhcnMoY29yZSA9IGNvcmUsIGRhdGVzID0gMTg1MDoyMTAwLCB2YXJzID0gYyhHTE9CQUxfVEVNUCgpKSkKCmdncGxvdChkYXRhID0gaGVjdG9yX291dHB1dCwgYWVzKHllYXIsIHZhbHVlLCBjb2xvciA9ICdoZWN0b3Igb3V0cHV0JykpICsKICAgIGdlb21fcG9pbnQoZGF0YSA9IGNlc21fY29tcF9kYXRhLCBhZXMoeWVhciwgdmFsdWUsIGNvbG9yID0gJ0NFU00xLUNBTTUnKSkgKwogICAgZ2VvbV9saW5lKHNpemUgPSAxKQpgYGAKCkxvb2tzIHByZXR0eSBnb29kIHRvIG1lIQoKIyMgQ29uY2x1c2lvbnMKClVzaW5nIGhlYXQgZmx1eCBhcyBjb21wYXJpc29uIGRhdGEgcmVzb2x2ZWQgdGhlIHByb2JsZW0gb2YgUyBhbmQgZGlmZiEgd2hvb3Qgd2hvb3QhCgojIyBOZXh0IFN0ZXBzCgoxLiBHZXQgaGVhdCBmbHV4IHNjYWxlIGFuZCBjZW50ZXIgcmVzdWx0cz8gKGRvIHdlIHdhbnQgaXQgZnJvbSB0aGUgUENBIG9yIEkgY291bGQganVzdCBnZXQgaXQgZnJvbSB0aGUgZW5zZW1ibGUpCjIuIFRlc3Qgd2l0aCB0aGUgYWN0dWFsIENFU00xLUNBTTUgZGF0YQozLiBEb3dubG9hZC9wcm9jZXNzIHRoZSBDTUlQNSByZXN1bHRzIGZvciB0aGUgaGVhdCBmbHV4IGRhdGEKCgo=