% Northern Treeline Temperature Response simulation and comparison
%
% (C) Michael Mann, 2011.
%
% specify NH temperature simulation options
%
% ioption=0: EBM simulation; AJSBT07 natural forcings + anthro
% ioption=1:   " AJSBT07 but with reduced AD 1258 forcing magnitude
% ioption=2:   " use Gao et al Volcanic series in place of AJSBT07
% ioption=3:   " use Crowley et al Volcanic series in place of AJSBT07
% ioption=4: use AJSBT07 simulated NH temperature series AD 850-1999
ioption=4;
%
% specify volcanic optical depth scaling
%
% iscaling=0: Assume optical depth scales linearly with loading
% iscaling=1: assume 2/3 power law scaling
iscaling=0;
%
% specify solar scaling
%
% isolar=0: Assume 0.1% Maunder Min-Present change in solar output
% isolar=1: Assume 0.25% Maunder Min-Present change in solar output
isolar=0;
%
% specify equilibrium 2XCO2 sensitivity for EBM 
% standard value is mid-range IPCC sensitivity of 3C/2xCO2
sens=3.0;
%
% specify growth model version (variants on Vaganov-Shashkin model)
% igrowth=0: default is quadratic side-ramps in peak function
% igrowth=1: alternatively, use linear side-ramps in peak function (see Evans et al '06)
% igrowth=2: use simple growing degree model (linear response above Tmin
% threshhold, zero below)
igrowth=2;
%
% specify parameters of temperature-limited tree growth model (from Evans et al '06)
T1=6.0; % minimum daily mean temp for growth, default is 10C (note: Evans uses 5C, but range 3-10C is cited elsewhere)
T2=18.0; % lower end of optimal temperature range, default is 18C
T3=21.0; % upper end of optimal temperature range, default is 21C
T4=24.0; % maximum daily mean temp for growth, default is 24C
%
% specify parameters of annual temperature cycle at treeline
tmax = 11.8; % peak summer daily mean temp, default is 11.8C (mid-pointed of cited treeline range)
tmin = -27.0; % minimum winter daily mean temp, default is -27C (Churchill MB)
%
% whether or not employing stochastic white noise weather forcing
istoch=1; % default is no forcing (istoch=0)
%
% amplitude of white noise daily temperature forcing (if istoch=1)
ampnoise=3.0; % default is zero;  estimate from Churchill (for July-August) is s.d. = 3.0C
%
% number of spatial degrees of freedom assumed in tree=ring sampling
ndofs=20; % D'Arrigo et al use composite of 20 distinct regions
%
% minimum number of growth days in season to constitute a 'non-missing' ring
nmin=7; % reasonable default is between 3 and 4 weeks (take 26 days)
%
% reseed random number generator? (if so, choose non-zero integer)
iseed=0;
%reseed(1:iseed)=rand;
%
%
%
%
%
%
%
%
%%%%%%%%%%%%%%%%%%%%
%
year=(850:1999)'; % full analysis interval is AD 850-1999
nyears=1150;
%
% read in AJSBT07 NCAR CSM 1.4 NH Mean temperature series (AD 850-1999)
%
load Data/nh_csm.dat % Read in AJSBT07 NCAR CSM simulated NH series
%
% read in D'Arrigo et al '06 summer NH (20-90 deg) tree-ring temperature
% reconstruction (AD 713-1995)
% uses RCS version standardized to best retain low-frequency variability
% we will use AD 1200-1980 interval over which validation statistics
% suggest greatest reconstruction skill (see D'Arrigo et al)
%
load Data/nh_darrigo.dat
year_rcs=nh_darrigo(:,1);
nhem_rcs_raw=nh_darrigo(:,2);
%
%
% Get forcing series AD 850-1999
[volc,solar,aer,forcingcotwo] = getforcings(ioption,iscaling,isolar);
% Run EBM simulation 
% (or alternatively use AJSBT07 NH simulated series if indicated)
if (ioption==4) 
   surftemp=nh_csm;
else
[surftemp]  = EBM(volc,solar,aer,forcingcotwo,sens); 
end
%
% define temperature anomalies relative to modern instrumental (1961-1990)
% base period
%
load Data/hadcrut3nh.dat % load HadCRUT3 instrumental NH mean temp record
yearinstr=hadcrut3nh(:,1);
nhinstr=hadcrut3nh(:,14);
%
% center model NH series w.r.t. 1961-1990  instrumental base period
%
nhmodel=surftemp-mean(surftemp(1112:1141)); % EBM simulation
nhcsm=nh_csm-mean(nh_csm(1112:1141)); % NCAR CSM simulation
%
% compare EBM and NCAR CSM simulation NH series over AD 850-1999
%
figure(1);
hold
plot(year,nhmodel,'r'); 
plot(year,nhcsm,'g');
%
% calculate residual variance (estimated of unforced variability)resid
%
if (not(ioption==4))
residmodel=nhmodel-nhcsm;
stdresmodel=std(residmodel);
[smoothedmodeldiff,w0,w1,w2,msebest] = lowpassadaptive(residmodel,0.1);
stdsmoothedmodeldiff=std(smoothedmodeldiff);
end

%
% compare simulated and observed NH series over historical era
%
figure(2);
hold
plot(year(1001:1150),nhmodel(1001:1150),'r'); 
plot(yearinstr(1:150),nhinstr(1:150),'k');
%
% apply daily tree growth model to simulated temperature series 
%
% plot growth response function
%
temprange=35.0;
nbinsper=10;
nbins=round(temprange*nbinsper);
binwidth=1.0/nbinsper;
for i=1:nbins+1;
    temp(i)=(i-1)*binwidth;
    [response]=tresponse(temp(i),T1,T2,T3,T4,igrowth);
    growthfunction(i)=response;
end
figure(3);
hold
plot(temp,growthfunction); 
ndays=365;
%
if (istoch==0) % if no stochastic weather forcing, there is just one noise-free realization
[annual,grow,ngrowing,diffuse,total] = treegrowth(nhmodel,volc,T1,T2,T3,T4,tmax,tmin,igrowth,0.0);
else % otherwise form composite of ensemble of weather-forced regional series
    annualsum(1:ndays)=0.0;
    growsum(1:nyears)=0.0;
    ngrowingsum(1:nyears)=0.0;
    diffusesum(1:nyears)=0.0;
    totalsum(1:nyears)=0.0;
    nmiss(1:nyears)=0;
    for i=1:ndofs
    [annual0,grow0,ngrowing0,diffuse0,total0] = treegrowth(nhmodel,volc,T1,T2,T3,T4,tmax,tmin,igrowth,ampnoise);
    ngrowingsum=ngrowingsum+ngrowing0;
    iflagmissany=0;  % check for 'missing rings' now
    nmisstot(i)=0;
    for j=1:nyears
        iflagmiss(j)=0;
        if (ngrowing0(j)<nmin) 
            iflagmiss(j)=1;
            iflagmissany=1;
            nmiss(j)=nmiss(j)+1; % record there was a 'missing ring' for this year
            nmisstot(i)=nmisstot(i)+1; % total missing 'rings' for each record
        end
    end
    nmissmax=max(nmisstot);
    % shift tree-ring growth series forward for each missing ring encountered back in time
    if (iflagmissany)
    diffuse1=diffuse0;
    grow1=grow0;
    total1=total0;
    for k=1:nmissmax
    for j=nyears:-1:1
        if (iflagmiss(j))
            iflagmiss(j)=0;
            grow1(2:j)=grow0(1:j-1); % shift series forward one
            grow1(1)=grow1(2); % use persistence for year 0
            grow0=grow1;
            diffuse1(2:j)=diffuse0(1:j-1); % shift series forward one
            diffuse1(1)=diffuse1(2); % use persistence for year 0
            diffuse0=diffuse1;
            total1(2:j)=total0(1:j-1); % shift series forward one
            total1(1)=total1(2); % use persistence for year 0
            total0=total1;
        end
    end
    end
    end
    growsum=growsum+grow0;
    diffusesum=diffusesum+diffuse0;
    totalsum=totalsum+total0;
    end
    annual=annual0; % this is the annual cycle for a typical location
    annualcomp=(1.0/ndofs)*annualsum; % this is annual cycle of the composite
    ngrowing=round((1.0/ndofs)*ngrowingsum);
    grow=(1.0/ndofs)*growsum;
    diffuse=(1.0/ndofs)*diffusesum;
    total=(1.0/ndofs)*totalsum;
    fracmiss=round(nmiss)/round(ndofs);
    % plot fraction of estimated 'missing' rings in sample as a function of year
    figure(11)
    hold
    plot(year,fracmiss,'g')
end
%
% plot sample annual temperature cycle (including stochastic forcing)
%
thresh(1:ndays)=T1;
figure(4);
hold
plot(annual); 
plot(thresh,'k--')
%
% standardize tree-ring response series to have same mean and variance as EBM-simulated temp series over
% sub-intervals not impacted by large volcanic forcing events (estimates of long-term
% means and variances are otherwise biased by absence of major volcanic cooling episodes in tree-ring response) 
%
%
notvolc=not(abs(volc)>1);
% optional rescaling of variance--commented out
%series0=nhmodel.*notvolc;
%series1=grow'.*notvolc;
%series2=total'.*notvolc;
series0=nhmodel;
series1=grow';
series2=total';
sd0=std(series0);
sd1=std(series1);
sd2=std(series2);
%
% if using stochastic white noise forcing, multidecadally smooth series 
% before variance matching to reduce effect of variance inflation by noise
zerro=1.0e-6;
if (istoch)
    [smoothed0,w0,w1,w2,msebest] = lowpassadaptive(series0,0.015);
    [smoothed1,w0,w1,w2,msebest] = lowpassadaptive(series1,0.015);
    [smoothed2,w0,w1,w2,msebest] = lowpassadaptive(series2,0.015);
    sd0=std(smoothed0);
    sd1=std(smoothed1);
    sd2=std(smoothed2);
end
%
stdshift1=sd0/sd1;
stdshift2=sd0/sd2;
growcomp=grow*stdshift1;
totalcomp=total*stdshift2;
growcomp=growcomp+mean(series0)-mean(growcomp);
totalcomp=totalcomp+mean(series0)-mean(totalcomp);
%
% re-align RCS series to have same **non-volcanic** mean as simulated
% series over AD 1200-1980 (for same reason as indicated above for
% simulated tree-growth indices)
%
nhem_rcs=nhem_rcs_raw+mean(series0(351:1131))-mean(nhem_rcs_raw(488:1268));
%
% compare EBM-simulated NH series, simulated tree-ring series, 
% and actual tree-ring series over AD 1200-1980 interval
%
figure(5);
hold
plot(year(351:1131),nhmodel(351:1131),'r'); 
plot(year_rcs(488:1268),nhem_rcs(488:1268));
plot(year(351:1131),growcomp(351:1131),'g'); 
%
% same comparison as figure 3, but use total growth estimate
% including estimated volcanic diffuse radiation effect
%
figure(6);
hold
plot(year(351:1131),nhmodel(351:1131),'r'); 
plot(year_rcs(488:1268),nhem_rcs(488:1268));
plot(year(351:1131),totalcomp(351:1131),'g'); 
%
% plot growth index and growing day length statistic
%
figure(7);
hold
plot(year(351:1131),grow(351:1131),'k'); 
figure(8);
hold
plot(year(351:1131),ngrowing(351:1131),'g'); 
%
% plot residual between NH mean temperature simulation and tree-ring series over AD 1200-1980
%
yearshort=year_rcs(488:1268);
nshort=length(yearshort);
%
resid=nhem_rcs(488:1268)-nhmodel(351:1131);
centerplot=zeros(nshort);
uppertwosigma=centerplot+2.0*std(resid);
uppersigma=centerplot+std(resid);
lowertwosigma=centerplot-2.0*std(resid);
lowersigma=centerplot-std(resid);
lowerthreesigma=centerplot-3.0*std(resid);
upperthreesigma=centerplot+3.0*std(resid);
figure(9)
hold
plot(yearshort,resid);
plot(yearshort,centerplot,'k--');
plot(yearshort,uppertwosigma,'k--');
plot(yearshort,uppersigma,'k--');
plot(yearshort,lowersigma,'k--');
plot(yearshort,lowertwosigma,'k--');
%
% calculate decadal residual variance over segment between 15th century and
% 19th century eruptions (1500-1800)
%
[smoothedbest,w0,w1,w2,msebest] = lowpassadaptive(resid(301:601),0.1);
stdsmoothed=std(smoothedbest);
%
% flag years where growing season length is found to be less than nmin days 
% as a potentially 'compromised' tree-ring year and plot
% 
figure(10)
hold
nhem_rcs_nomiss=nhem_rcs(488:1268);
shortseason=ngrowing(351:1131)<nmin;
for i=1:nshort
    if (shortseason(i))
        plot(yearshort(i),nhem_rcs_nomiss(i),'o')
        nhem_rcs_nomiss(i)=NaN;
    end
end
plot(yearshort,nhem_rcs_nomiss,'k')
%
% done
%


















      