initial version
This commit is contained in:
		
						commit
						8e602ca6bf
					
				
					 26 changed files with 3306 additions and 0 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
venv
 | 
			
		||||
							
								
								
									
										556
									
								
								AnalyticLC/AnalyticLC.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										556
									
								
								AnalyticLC/AnalyticLC.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,556 @@
 | 
			
		|||
function [LC,RV_o_r,Y_o_r,Z_o_r,O] = AnalyticLC(P,Tmid0,ror,aor,mu,ex0,ey0,I0,Omega0,t,u1,u2,varargin)
 | 
			
		||||
% AnalyticLC: generate an analytic light-curve, and optionally RV and astrometry data, from a set of initial (free) orbital
 | 
			
		||||
% elements.
 | 
			
		||||
 | 
			
		||||
% The full logic of AnalyticLC and the model derivation are described in the paper "An Accurate 3D
 | 
			
		||||
% Analytic Model for Exoplanetary Photometry, Radial Velocity and
 | 
			
		||||
% Astrometry" by Judkovsky, Ofir and Aharonson (2021), please cite this
 | 
			
		||||
% paper upon usage. Model and enjoy :)
 | 
			
		||||
 | 
			
		||||
%Inputs: 
 | 
			
		||||
% P - vector of orbital periods, 
 | 
			
		||||
% Tmid0 - vector of refernce times-of-mid-transit, 
 | 
			
		||||
% ror - vector of planets/star radii ratio, 
 | 
			
		||||
% aor - semi-major-axis in stellar radius of innermost planet, 
 | 
			
		||||
% mu - vector of planets/star mass ratio, 
 | 
			
		||||
% ex0 and ey0 - vectors of initial FREE eccentricities components of planets
 | 
			
		||||
% I0 = vector of initial FREE inclinations (radians), 
 | 
			
		||||
% Omega0 - vector of initial FREE longiudes of ascending nodes (radians), 
 | 
			
		||||
% t - time vector to calculate light curve model at, 
 | 
			
		||||
% u1,u2 - limb darkening coefficients. 
 | 
			
		||||
% Eccentricity components and inclination are defined with respect to the system plane, and NOT with respect to the sky plane. The system plane is
 | 
			
		||||
% defined such that the x axis points from the star to the observer, and y
 | 
			
		||||
% is on the sky plane such that the inclinations are measured with respect
 | 
			
		||||
% to the xy plane. Transits are expected to occur for small
 | 
			
		||||
% values of sin(I0)*sin(Omega), which is equal to the cosine of the
 | 
			
		||||
% sky-plane inclination.
 | 
			
		||||
% The time units are to the user's choice, and should be consistent in all
 | 
			
		||||
% parameters (t,P,Tmid etc.).
 | 
			
		||||
 | 
			
		||||
% Examples for usage:
 | 
			
		||||
% LC = AnalyticLC(P,Tmid0,ror,aor,mu,ex0,ey0,I0,Omega0,t,u1,u2,'OutputList','');
 | 
			
		||||
% LC = AnalyticLC(P,Tmid0,ror,aor,mu,ex0,ey0,I0,Omega0,t,u1,u2,'BinningTime',BinningTime,'OutputList','all');
 | 
			
		||||
% [LC,RV_o_r,Y_o_r,Z_o_r,O] = AnalyticLC(P,Tmid0,ror,aor,mu,ex0,ey0,I0,Omega0,t,u1,u2,'tRV',tRV);
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
BinningTime = range(t); %rough time steps for performing the binning to construct the light curve. A value per cadence type is allowed, or a single value for all cadence types. For cadences shorter the the binning time, no binning will be introcued.
 | 
			
		||||
CadenceType = ones(size(t)); %cadence type should label each time stamp. values must be consecutive natural integers: 1, 2,...
 | 
			
		||||
MaxTTV = inf(1,length(P)); %maximal TTV amplitude allowed for each planet. A value per planet is allowed, or a single value for all planets.
 | 
			
		||||
tRV = []; %times to evaluate radial velocity at
 | 
			
		||||
ExtraIters = 0; %extra iterations for the TTV calculations
 | 
			
		||||
OrdersAll = []; %orders for calculating the forced elements; see function ForcedElements1.
 | 
			
		||||
OutputList = 'all'; %a list of parameters to give as an additional output in the structure O. Upon "all", a default list is returned.
 | 
			
		||||
Calculate3PlanetsCrossTerms = 0; %Should the 3-planets cross terms be incorporated.
 | 
			
		||||
MaxPower = 4; %maximal (joint) power of eccentricities and inclinations used in the expansion
 | 
			
		||||
OrbitalElementsAsCellArrays = 0; %an option to return (within the structure O) cell arrays including the orbital elements variations. Each such cell array will contain one cell per planet.
 | 
			
		||||
 | 
			
		||||
%read optional inputs for the parameters above
 | 
			
		||||
for i=1:2:numel(varargin)
 | 
			
		||||
    switch lower(varargin{i})
 | 
			
		||||
        case 'binningtime'
 | 
			
		||||
            BinningTime=varargin{i+1};
 | 
			
		||||
        case 'cadencetype'
 | 
			
		||||
            CadenceType=varargin{i+1};
 | 
			
		||||
        case 'maxttv'
 | 
			
		||||
            MaxTTV=varargin{i+1};
 | 
			
		||||
        case 'trv'
 | 
			
		||||
            tRV=vertical(varargin{i+1});
 | 
			
		||||
        case 'extraiters'
 | 
			
		||||
            ExtraIters=(varargin{i+1});
 | 
			
		||||
        case 'ordersall'
 | 
			
		||||
            OrdersAll=(varargin{i+1});
 | 
			
		||||
        case 'maxpower'
 | 
			
		||||
            MaxPower=(varargin{i+1});
 | 
			
		||||
        case 'outputlist'
 | 
			
		||||
            OutputList=(varargin{i+1});
 | 
			
		||||
        case 'calculate3planetscrossterms'
 | 
			
		||||
            Calculate3PlanetsCrossTerms=(varargin{i+1});
 | 
			
		||||
        case 'orbitalelementsascellarrays'
 | 
			
		||||
            OrbitalElementsAsCellArrays=(varargin{i+1});
 | 
			
		||||
        otherwise
 | 
			
		||||
            fprintf('WARNING: Parameter %s is unknown and therefore ignored.\n',varargin{i})
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%number of planets and number of time stamps and number of cadence types
 | 
			
		||||
Npl = length(P);
 | 
			
		||||
Nt = length(t);
 | 
			
		||||
Ncad = max(CadenceType);
 | 
			
		||||
Nrv = length(tRV);
 | 
			
		||||
 | 
			
		||||
%prepare a time axis of one point per transit for the calculation of the
 | 
			
		||||
%orbital dynamics
 | 
			
		||||
[tT,BeginIdx,EndIdx,Ntr] = DynamicsTimeAxis(P,Tmid0,t);
 | 
			
		||||
NtT = length(tT);
 | 
			
		||||
 | 
			
		||||
%make sure that each cadence type is characterized by its own binning time
 | 
			
		||||
if length(BinningTime)==1, BinningTime = BinningTime*ones(1,Ncad); end
 | 
			
		||||
 | 
			
		||||
%make sure that each planet receives a maximal TTV value
 | 
			
		||||
if length(MaxTTV)==1, MaxTTV = MaxTTV*ones(1,Npl); end
 | 
			
		||||
 | 
			
		||||
%calculate mean motion
 | 
			
		||||
n = 2*pi./P;
 | 
			
		||||
 | 
			
		||||
%calculate time relative to first mid-transit
 | 
			
		||||
t0_T = vertical(tT)-Tmid0;
 | 
			
		||||
t0_RV = vertical(tRV)-Tmid0;
 | 
			
		||||
 | 
			
		||||
%calculate mean longitudes
 | 
			
		||||
Lambda_T = t0_T.*repmat(n,NtT,1);
 | 
			
		||||
 | 
			
		||||
%calculate period ratio
 | 
			
		||||
PeriodRatio = P(2:end)./P(1);
 | 
			
		||||
 | 
			
		||||
%calculate semi-major axis of outer planets, deduced from Period Ratio
 | 
			
		||||
if length(aor)==1
 | 
			
		||||
    aor(2:Npl) = aor(1)*PeriodRatio.^(2/3).*(((1+mu(2:end))/(1+mu(1))).^(1/3));
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%calculate the secular motion of the eccentricities and inclinations
 | 
			
		||||
[A,B] = SecularInteractionsMatrix(n,mu);
 | 
			
		||||
free_e_0 = ex0+1i*ey0;
 | 
			
		||||
free_I_0 = I0.*exp(1i.*Omega0);
 | 
			
		||||
free_e_T = Vector1stOrderDE(A,free_e_0.',horizontal(tT)-t(1)); 
 | 
			
		||||
free_I_T = Vector1stOrderDE(B,free_I_0.',horizontal(tT)-t(1));
 | 
			
		||||
 | 
			
		||||
%calculate the near-resonant interactions and their resulting TTV's
 | 
			
		||||
[dz,dLambda,du,da_oa,dTheta,zT,uT,TTV] = ResonantInteractions2(P,mu,Lambda_T,free_e_T,free_I_T,tT,BeginIdx,EndIdx,ExtraIters,OrdersAll,Calculate3PlanetsCrossTerms,MaxPower);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
%check if the solution is invalid. Reasons for invalidity:
 | 
			
		||||
%if the TTV's do not exceed the maximal value, and if it does - return nans
 | 
			
		||||
%innermost planet hits star: a(1-e)<Rs
 | 
			
		||||
%e>1 are invalid
 | 
			
		||||
if any( max(abs(TTV))>MaxTTV ) || any((1-abs(zT(:,1))).*aor(1)<1) || any(abs(zT(:))>1)
 | 
			
		||||
    LC = nan(size(t));
 | 
			
		||||
    O = [];
 | 
			
		||||
    RV_o_r = nan(size(tRV));
 | 
			
		||||
    Y_o_r = nan(size(tRV));
 | 
			
		||||
    Z_o_r = nan(size(tRV));
 | 
			
		||||
    return
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%translate the orbital elements to transits properties
 | 
			
		||||
CalcDurations = nargout>=5;
 | 
			
		||||
[D,D1,Tau,Tau1,w,w1,d,d1,b,b1,AssociatedTmid,AssociatedInd,dbdt,b0] = TransitsProperties(Nt,Npl,BeginIdx,EndIdx,t,tT,TTV,P,n,da_oa,aor,zT,uT,ror,CalcDurations);
 | 
			
		||||
 | 
			
		||||
%construct the light-curve for each planet
 | 
			
		||||
AllLC = GenerateLightCurve(Nt,Npl,Ncad,CadenceType,t,BinningTime,AssociatedTmid,w,d,b,ror,u1,u2);
 | 
			
		||||
 | 
			
		||||
%sum all planets light-curves to get the total light curve. The possibility of mutual transits is neglected.
 | 
			
		||||
LC = sum(AllLC,2)-Npl+1;
 | 
			
		||||
 | 
			
		||||
%calculate the forced elements of the RV time stamps if the output requires doing so
 | 
			
		||||
if Nrv>0 
 | 
			
		||||
    
 | 
			
		||||
    Lambda_RV = t0_RV.*repmat(n,Nrv,1);
 | 
			
		||||
    
 | 
			
		||||
    %secular interactions at the RV time stamps
 | 
			
		||||
    free_e_RV = Vector1stOrderDE(A,free_e_0.',horizontal(tRV));
 | 
			
		||||
    free_I_RV = Vector1stOrderDE(B,free_I_0.',horizontal(tRV));
 | 
			
		||||
    
 | 
			
		||||
    %near-resonant interactions at the RV time stamps
 | 
			
		||||
    [forced_e_RV,dLambda_RV,forced_I_RV] = ForcedElements1(P,Lambda_RV,mu,free_e_RV,free_I_RV,OrdersAll,MaxPower);
 | 
			
		||||
    
 | 
			
		||||
    zRV = free_e_RV+forced_e_RV;
 | 
			
		||||
    uRV = free_I_RV+forced_I_RV;
 | 
			
		||||
    Lambda_RV = Lambda_RV+dLambda_RV;
 | 
			
		||||
    
 | 
			
		||||
    %calculate the radial velocity/astrometry model
 | 
			
		||||
    [RV_o_r,Y_o_r,Z_o_r] = CalcRV(Lambda_RV,zRV,uRV,mu,aor,n,nargout>2);
 | 
			
		||||
    
 | 
			
		||||
else
 | 
			
		||||
    
 | 
			
		||||
    forced_e_RV = zeros(Nrv,Npl);
 | 
			
		||||
    Lambda_RV = zeros(Nrv,Npl);
 | 
			
		||||
    free_e_RV = zeros(Nrv,Npl);
 | 
			
		||||
    free_I_RV = zeros(Nrv,Npl);
 | 
			
		||||
    forced_I_RV = zeros(Nrv,Npl); 
 | 
			
		||||
    zRV = free_e_RV+forced_e_RV;
 | 
			
		||||
    uRV = free_I_RV+forced_I_RV;
 | 
			
		||||
    RV_o_r = [];
 | 
			
		||||
    Y_o_r = [];
 | 
			
		||||
    Z_o_r  = [];
 | 
			
		||||
    
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%if required, give more outputs then just the light-curve and the RV
 | 
			
		||||
%values. These outputs are specified in the optinal input variable
 | 
			
		||||
%OutputList.
 | 
			
		||||
if nargout>4
 | 
			
		||||
    
 | 
			
		||||
    %upon the value of "all", set OutputList to include a default list of
 | 
			
		||||
    %variables
 | 
			
		||||
    if strcmp(OutputList,'all')
 | 
			
		||||
        OutputList = {'tT','tRV','zT','zRV','uT','uRV','D','Tau','w','d','b','AssociatedTmid','AssociatedInd','AllLC','TmidActualCell','free_e_T','free_I_T','free_e_RV','free_I_RV','TTVCell','dzCell','duCell','dLambdaCell','zfreeCell','dbdt','b0','Lambda_T','P','BeginIdx','EndIdx','Ntr'}; %a list of parameters to give as an additional output, if required
 | 
			
		||||
        OrbitalElementsAsCellArrays = 1;
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    %generate cell arrays for the orbital elements
 | 
			
		||||
    if OrbitalElementsAsCellArrays 
 | 
			
		||||
        
 | 
			
		||||
        TmidActualCell = cell(1,Npl);
 | 
			
		||||
        TTVCell = cell(1,Npl);
 | 
			
		||||
        dzCell = cell(1,Npl);
 | 
			
		||||
        duCell = cell(1,Npl);
 | 
			
		||||
        dLambdaCell = cell(1,Npl);
 | 
			
		||||
        zfreeCell = cell(1,Npl);
 | 
			
		||||
        ufreeCell = cell(1,Npl);
 | 
			
		||||
        da_oaCell = cell(1,Npl);
 | 
			
		||||
        
 | 
			
		||||
        for j = 1:Npl
 | 
			
		||||
            TmidActualCell{j} = (tT(BeginIdx(j):EndIdx(j)))'+TTV(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
            TTVCell{j} = TTV(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
            dzCell{j} = dz(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
            duCell{j} = du(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
            dLambdaCell{j} = dLambda(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
            zfreeCell{j} = free_e_T(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
            ufreeCell{j} = free_I_T(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
            da_oaCell{j} = da_oa(BeginIdx(j):EndIdx(j),j).';         
 | 
			
		||||
        end
 | 
			
		||||
        
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    %move all variables specified in OutputList to a single structure
 | 
			
		||||
    %variable O
 | 
			
		||||
    for j = 1:length(OutputList)
 | 
			
		||||
        try
 | 
			
		||||
            eval(['O.',OutputList{j},'=',OutputList{j},';']);
 | 
			
		||||
        catch
 | 
			
		||||
            fprintf('Requested variable %s does not exist \n',OutputList{j});
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function [AA,BB] = SecularInteractionsMatrix(n,mu)
 | 
			
		||||
%calculate the interaction matrix that will describe the equation dz/dt=Az
 | 
			
		||||
%where z is a vector of the complex eccentricities and for the similar
 | 
			
		||||
%equation for I*exp(i*Omega) using the matrix BB
 | 
			
		||||
 | 
			
		||||
Npl = length(n);
 | 
			
		||||
 | 
			
		||||
AA = ones(Npl);
 | 
			
		||||
BB = ones(Npl);
 | 
			
		||||
 | 
			
		||||
for j1 = 1:Npl
 | 
			
		||||
    for j2 = j1:Npl
 | 
			
		||||
        
 | 
			
		||||
        if j1~=j2
 | 
			
		||||
            alph = (n(j2)/n(j1))^(2/3)*((1+mu(j1))/(1+mu(j2)))^(1/3);
 | 
			
		||||
            A1 = LaplaceCoeffs(alph,1/2,1);
 | 
			
		||||
            
 | 
			
		||||
            
 | 
			
		||||
            DA1 = LaplaceCoeffs(alph,1/2,1,1);
 | 
			
		||||
            D2A1 = LaplaceCoeffs(alph,1/2,1,2);
 | 
			
		||||
            
 | 
			
		||||
            f10 = 0.5*A1-0.5*alph*DA1-0.25*alph^2*D2A1; %calculate f2 and f10 for j=0
 | 
			
		||||
            AA(j1,j2) = n(j1)*mu(j2)/(1+mu(j1))*alph*f10;
 | 
			
		||||
            AA(j2,j1) = n(j2)*mu(j1)/(1+mu(j2))*f10;
 | 
			
		||||
            
 | 
			
		||||
            B1 = LaplaceCoeffs(alph,3/2,1);
 | 
			
		||||
            f14 = alph*B1;
 | 
			
		||||
            BB(j1,j2) = 0.25*n(j1)*mu(j2)/(1+mu(j1))*alph*f14;
 | 
			
		||||
            BB(j2,j1) = 0.25*n(j2)*mu(j1)/(1+mu(j2))*f14;
 | 
			
		||||
            
 | 
			
		||||
        else
 | 
			
		||||
            alphvec = zeros(1,Npl);
 | 
			
		||||
            alphvec(1:j1) = (n(1:j1)/n(j1)).^(-2/3).*((1+mu(1:j1))./(1+mu(j1))).^(1/3);
 | 
			
		||||
            alphvec(j1+1:end) = (n(j1+1:end)/n(j1)).^(2/3).*((1+mu(j1+1:end))./(1+mu(j1))).^(-1/3);
 | 
			
		||||
            DA0 = LaplaceCoeffs(alphvec,1/2,0,1);
 | 
			
		||||
            D2A0 = LaplaceCoeffs(alphvec,1/2,0,2);
 | 
			
		||||
            f2 = 0.25*alphvec.*DA0+1/8*alphvec.^2.*D2A0;
 | 
			
		||||
            InnerVec = mu(1:(j1-1))/(1+mu(j1)).*f2(1:(j1-1));
 | 
			
		||||
            OuterVec = alphvec((j1+1):end).*mu((j1+1):end)/(1+mu(j1)).*f2((j1+1):end);
 | 
			
		||||
            
 | 
			
		||||
            AA(j1,j2) = n(j1)*2*(sum(InnerVec)+sum(OuterVec));
 | 
			
		||||
            
 | 
			
		||||
            B1 = LaplaceCoeffs(alphvec,3/2,1);
 | 
			
		||||
            f3 = -0.5*alphvec.*B1;
 | 
			
		||||
            InnerVec = mu(1:(j1-1)).*f3(1:(j1-1));
 | 
			
		||||
            OuterVec = alphvec((j1+1):end).*mu((j1+1):end).*f3((j1+1):end);
 | 
			
		||||
            BB(j1,j2) = 0.25*n(j1)*2*(sum(InnerVec)+sum(OuterVec));
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
AA = 1i*AA;
 | 
			
		||||
BB = 1i*BB;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function [TmidActualCell,TTVCell,dzCell,duCell,da_oaCell,dLambdaCell,zfreeCell] = ResonantInteractions1(P,mu,Lambda,free_all,free_i,tT,BeginIdx,EndIdx,ExtraIters,OrdersAll,Calculate3PlanetsCrossTerms,MaxPower)
 | 
			
		||||
%calculate the near-resonant interactions arising from the appropriate
 | 
			
		||||
%disturbing function terms
 | 
			
		||||
 | 
			
		||||
%calculate mean motions
 | 
			
		||||
n = 2*pi./P;
 | 
			
		||||
 | 
			
		||||
% [dz,dLambda] = ForcedEccentricitiesAndMeanLongitudes1(P,Lambda,mu,free_all,OrdersAll);
 | 
			
		||||
% [dz,dLambda] = ForcedElements(P,Lambda,mu,free_all,free_i,OrdersAll);
 | 
			
		||||
[dz,dLambda,du,da_oa] = ForcedElements1(P,Lambda,mu,free_all,free_i,OrdersAll,MaxPower);
 | 
			
		||||
 | 
			
		||||
if Calculate3PlanetsCrossTerms
 | 
			
		||||
    dLambda = dLambda+ForcedMeanLongitudes3PlanetsCrossTerms(P,Lambda,mu,free_all);
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
for jj = 1:ExtraIters
 | 
			
		||||
    %     [dz,dLambda] = ForcedEccentricitiesAndMeanLongitudes1(P,Lambda+dLambda,mu,free_all+dz,OrdersAll);
 | 
			
		||||
    %     [dz,dLambda] = ForcedElements(P,Lambda+dLambda,mu,free_all+dz,free_i,OrdersAll);
 | 
			
		||||
    [dz,dLambda,du,da_oa] = ForcedElements1(P,Lambda+dLambda,mu,free_all+dz,free_i+du,OrdersAll,MaxPower);
 | 
			
		||||
   
 | 
			
		||||
    %add the 3-planets cross terms
 | 
			
		||||
    if Calculate3PlanetsCrossTerms
 | 
			
		||||
        dLambda = dLambda+ForcedMeanLongitudes3PlanetsCrossTerms(P,Lambda+dLambda,mu,free_all+dz);
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%calculate the total eccentricity for each nominal transit time
 | 
			
		||||
z = free_all+dz;
 | 
			
		||||
 | 
			
		||||
%calculate the true longitude variations
 | 
			
		||||
dTheta = dLambda+2*real((conj(z).*dLambda+conj(dz)/1i).*(1+5/4*conj(dz)));
 | 
			
		||||
 | 
			
		||||
%translate the variations in true longitude to variations in time via the
 | 
			
		||||
%planetary angular velocity
 | 
			
		||||
% TTV = -dTheta./repmat(n,size(z,1),1).*((1-abs(z).^2).^(3/2))./((1+real(z)).^2);
 | 
			
		||||
TTV = -dTheta./(repmat(n,size(z,1),1).*(1-1.5*da_oa)).*((1-abs(z).^2).^(3/2))./((1+real(z)).^2); %taking into account the variations in n - 8.2.2021
 | 
			
		||||
 | 
			
		||||
Npl = length(P);
 | 
			
		||||
%pre allocation
 | 
			
		||||
TmidActualCell = cell(1,Npl);
 | 
			
		||||
TTVCell = cell(1,Npl);
 | 
			
		||||
dzCell = cell(1,Npl);
 | 
			
		||||
dLambdaCell = cell(1,Npl);
 | 
			
		||||
zfreeCell = cell(1,Npl);
 | 
			
		||||
ufreeCell = cell(1,Npl);
 | 
			
		||||
da_oaCell = cell(1,Npl);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
for j = 1:Npl
 | 
			
		||||
    %     TmidActualCell{j} = TmidActualCell{j}+TTV(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
    TmidActualCell{j} = (tT(BeginIdx(j):EndIdx(j)))'+TTV(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
    TTVCell{j} = TTV(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
    dzCell{j} = dz(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
    duCell{j} = du(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
    dLambdaCell{j} = dLambda(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
    zfreeCell{j} = free_all(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
    ufreeCell{j} = free_i(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
    da_oaCell{j} = da_oa(BeginIdx(j):EndIdx(j),j).';
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function [dz,dLambda,du,da_oa,dTheta,z,u,TTV] = ResonantInteractions2(P,mu,Lambda,free_all,free_i,tT,BeginIdx,EndIdx,ExtraIters,OrdersAll,Calculate3PlanetsCrossTerms,MaxPower)
 | 
			
		||||
%calculate the forced orbital elements due to near-resonant interactions
 | 
			
		||||
 | 
			
		||||
n = 2*pi./P;
 | 
			
		||||
 | 
			
		||||
%pair-wise interactions
 | 
			
		||||
[dz,dLambda,du,da_oa] = ForcedElements1(P,Lambda,mu,free_all,free_i,OrdersAll,MaxPower);
 | 
			
		||||
 | 
			
		||||
%triplets interactions
 | 
			
		||||
if Calculate3PlanetsCrossTerms
 | 
			
		||||
    dLambda = dLambda+ForcedMeanLongitudes3PlanetsCrossTerms(P,Lambda,mu,free_all);
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%iterative solution to the equations, if desired
 | 
			
		||||
for jj = 1:ExtraIters    
 | 
			
		||||
    [dz,dLambda,du,da_oa] = ForcedElements1(P,Lambda+dLambda,mu,free_all+dz,free_i+du,OrdersAll,MaxPower);
 | 
			
		||||
    if Calculate3PlanetsCrossTerms
 | 
			
		||||
        dLambda = dLambda+ForcedMeanLongitudes3PlanetsCrossTerms(P,Lambda+dLambda,mu,free_all+dz);
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%calculate the total eccentricity and inclination for each nominal transit time
 | 
			
		||||
z = free_all+dz;
 | 
			
		||||
u = free_i+du;
 | 
			
		||||
 | 
			
		||||
%translate to true longitude
 | 
			
		||||
dTheta = dLambda+...
 | 
			
		||||
2*real( conj(z).*dLambda+conj(dz)/1i )...
 | 
			
		||||
+5/2*real( conj(z).^2.*dLambda+conj(z).*conj(dz).*conj(z)/1i )...
 | 
			
		||||
+13/4*real( conj(z).^3.*dLambda+conj(z).^2.*conj(dz)/1i )...
 | 
			
		||||
-1/4*real( (conj(z).*dz+z.*conj(dz)).*conj(z)/1i + z.*conj(z).*(conj(z).*dLambda+conj(dz)/1i) )...
 | 
			
		||||
+103/24*real( conj(z).^4.*dLambda+conj(z).^3.*conj(dz)/1i )...
 | 
			
		||||
-11/24*real( (conj(z).*dz+z.*conj(dz)).*conj(z).^2/1i + 2*z.*conj(z).*(conj(z).^2.*dLambda+conj(z).*conj(dz)/1i) );
 | 
			
		||||
 | 
			
		||||
%translate the variations in true longitude to variations in time using the
 | 
			
		||||
%planetary angular velocity, taking into account the variations in n
 | 
			
		||||
TTV = -dTheta./(repmat(n,size(z,1),1).*(1-1.5*da_oa)).*((1-abs(z).^2).^(3/2))./((1+real(z)).^2); 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function [RV_o_r,Y_o_r,Z_o_r] = CalcRV(Lambda,z,u,mu,aor,n,CalcAstrometry)
 | 
			
		||||
%calculate the RV at the desired time stamps
 | 
			
		||||
 | 
			
		||||
Nt = size(z,1);
 | 
			
		||||
Pom = angle(z);
 | 
			
		||||
Om = angle(u);
 | 
			
		||||
e = abs(z);
 | 
			
		||||
I = abs(u);
 | 
			
		||||
om = Pom-Om;
 | 
			
		||||
M = Lambda-Pom;
 | 
			
		||||
 | 
			
		||||
%calculate sin(f) and cos(f) to 2nd order in e, Solar System Dynamics eq.
 | 
			
		||||
%2.84 and 2.85, page 40
 | 
			
		||||
sinf = sin(M)+e.*sin(2*M)+e.^2.*(9/8*sin(3*M)-7/8*sin(M));
 | 
			
		||||
cosf = cos(M)+e.*(cos(2*M)-1)+9/8*e.^2.*(cos(3*M)-cos(M));
 | 
			
		||||
 | 
			
		||||
%calculate the planets astrocentric velocities on the x axis
 | 
			
		||||
Xdot_o_r = -repmat(n,Nt,1).*repmat(aor,Nt,1)./sqrt(1-e.^2).*((cos(om).*cos(Om)-sin(om).*sin(Om).*cos(I)).*sinf+(sin(om).*cos(Om)+cos(om).*sin(Om).*cos(I)).*(e+cosf));
 | 
			
		||||
 | 
			
		||||
%sum the astrocentric velocities along x axis to get stellar
 | 
			
		||||
%barycentric velocity along x axis
 | 
			
		||||
Xsdot_o_r = -sum(repmat(mu,Nt,1).*Xdot_o_r,2)/(1+sum(mu));
 | 
			
		||||
 | 
			
		||||
%the radial velocity is defined positive when the star moves away from the
 | 
			
		||||
%observer, i.e. it is positive then Xsdot is negative and vice versa.
 | 
			
		||||
RV_o_r = -Xsdot_o_r;
 | 
			
		||||
 | 
			
		||||
if CalcAstrometry
 | 
			
		||||
    %calculate the planets astrocentric positions on the y and z axes
 | 
			
		||||
    y = repmat(aor,Nt,1).*(1-e.^2)./(1+e.*cosf).*(sin(Om).*(cos(om).*cosf-sin(om).*sinf)+cos(Om).*cos(I).*(sin(om).*cosf+cos(om).*sinf));
 | 
			
		||||
    z = repmat(aor,Nt,1).*(1-e.^2)./(1+e.*cosf).*sin(I).*(sin(om).*cosf+cos(om).*sinf);
 | 
			
		||||
    
 | 
			
		||||
    %sum the astrocentric positions along x axis to get the
 | 
			
		||||
    %stellar barycentric position along y and z axes
 | 
			
		||||
    Y_o_r = -sum(repmat(mu,Nt,1).*y,2)/(1+sum(mu));
 | 
			
		||||
    Z_o_r = -sum(repmat(mu,Nt,1).*z,2)/(1+sum(mu));
 | 
			
		||||
else
 | 
			
		||||
    Y_o_r = [];
 | 
			
		||||
    Z_o_r = [];
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function [td,BeginIdx,EndIdx,Ntr] = DynamicsTimeAxis(P,Tmid0,t)
 | 
			
		||||
%generate a time axis that includes one point per transit event
 | 
			
		||||
td = [];
 | 
			
		||||
BeginIdx = zeros(1,length(P));
 | 
			
		||||
EndIdx = zeros(1,length(P));
 | 
			
		||||
Ntr = zeros(1,length(P));
 | 
			
		||||
 | 
			
		||||
for j = 1:length(P)
 | 
			
		||||
 | 
			
		||||
    td0 = ((min(t)+mod(Tmid0(j)-min(t),P(j))):P(j):max(t))'; %new version, taking into account the possibility that Tmid0 is not within the range of t
 | 
			
		||||
    td = [td;td0];
 | 
			
		||||
    EndIdx(j) = length(td);
 | 
			
		||||
    if j==1, BeginIdx(j) = 1; else, BeginIdx(j) = EndIdx(j-1)+1; end
 | 
			
		||||
    Ntr(j) = length(td0);
 | 
			
		||||
    
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function [D,D1,Tau,Tau1,w,w1,d,d1,b,b1,AssociatedTmid,AssociatedInd,dbdt,b0] = TransitsProperties(Nt,Npl,BeginIdx,EndIdx,t,tT,TTV,P,n,da_oa,aor,zT,uT,ror,CalcDurations)
 | 
			
		||||
%translate orbital elements at transits to transits parameters
 | 
			
		||||
 | 
			
		||||
%pre-allocate memory for transit properties: duration, ingress/egress,
 | 
			
		||||
%angular velocity, planet-star separation, impact parameter.
 | 
			
		||||
D = zeros(Nt,Npl);
 | 
			
		||||
Tau = zeros(Nt,Npl);
 | 
			
		||||
w = zeros(Nt,Npl);
 | 
			
		||||
d = zeros(Nt,Npl);
 | 
			
		||||
b = zeros(Nt,Npl);
 | 
			
		||||
 | 
			
		||||
D1 = cell(1,Npl);
 | 
			
		||||
Tau1 = cell(1,Npl);
 | 
			
		||||
w1 = cell(1,Npl);
 | 
			
		||||
d1 = cell(1,Npl);
 | 
			
		||||
b1 = cell(1,Npl);
 | 
			
		||||
 | 
			
		||||
AssociatedTmid = zeros(Nt,Npl);
 | 
			
		||||
AssociatedInd = zeros(Nt,Npl);
 | 
			
		||||
 | 
			
		||||
dbdt = zeros(1,Npl);
 | 
			
		||||
b0 = zeros(1,Npl);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
for j = 1:Npl
 | 
			
		||||
    
 | 
			
		||||
    %indices
 | 
			
		||||
    Idx = BeginIdx(j):EndIdx(j);    
 | 
			
		||||
 | 
			
		||||
    %Associate time-of-mid-transit to each time stamp
 | 
			
		||||
    [AssociatedTmid(:,j),AssociatedInd(:,j)] = AssociateTmid(t,tT(Idx)+TTV(Idx,j),P(j));
 | 
			
		||||
             
 | 
			
		||||
    %based on the presumed orbital elements as a function of time, calculate
 | 
			
		||||
    %the transit parameters - Duration, Ingress-Egress, angular velocity,
 | 
			
		||||
    %planet-star distance and impact parameter, and translate them to
 | 
			
		||||
    %light-curve
 | 
			
		||||
    if ~CalcDurations
 | 
			
		||||
        [w1{j},d1{j},b1{j}] = OrbitalElements2TransitParams(n(j)*(1-1.5*da_oa(Idx,j)),aor(j)*(1+da_oa(Idx,j)),real(zT(Idx,j)),imag(zT(Idx,j)),abs(uT(Idx,j)),angle(uT(Idx,j)),ror(j)); %treating I, Omega, aor, n as varying
 | 
			
		||||
        w(:,j) = w1{j}(AssociatedInd(:,j));
 | 
			
		||||
        d(:,j) = d1{j}(AssociatedInd(:,j));
 | 
			
		||||
        b(:,j) = b1{j}(AssociatedInd(:,j));
 | 
			
		||||
        
 | 
			
		||||
    else
 | 
			
		||||
        [w1{j},d1{j},b1{j},D1{j},Tau1{j}] = OrbitalElements2TransitParams(n(j)*(1-1.5*da_oa(Idx,j)),aor(j)*(1+da_oa(Idx,j)),real(zT(Idx,j)),imag(zT(Idx,j)),abs(uT(Idx,j)),angle(uT(Idx,j)),ror(j)); %treating I, Omega, aor, n as varying
 | 
			
		||||
        w(:,j) = w1{j}(AssociatedInd(:,j));
 | 
			
		||||
        d(:,j) = d1{j}(AssociatedInd(:,j));
 | 
			
		||||
        b(:,j) = b1{j}(AssociatedInd(:,j));
 | 
			
		||||
        D(:,j) = D1{j}(AssociatedInd(:,j));
 | 
			
		||||
        Tau(:,j) = Tau1{j}(AssociatedInd(:,j));
 | 
			
		||||
        
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    %calculate db_dt and b0
 | 
			
		||||
    [dbdt(j),b0(j)] = fit_linear(tT(Idx),b1{j});    
 | 
			
		||||
        
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function AllLC = GenerateLightCurve(Nt,Npl,Ncad,CadenceType,t,BinningTime,AssociatedTmid,w,d,b,ror,u1,u2)
 | 
			
		||||
%construct the light-curve for each planet based on the transit properties
 | 
			
		||||
%of each individual event
 | 
			
		||||
 | 
			
		||||
%pre-allocate
 | 
			
		||||
AllLC = zeros(Nt,Npl);
 | 
			
		||||
 | 
			
		||||
%go over cadence types
 | 
			
		||||
for jc = 1:Ncad
 | 
			
		||||
    
 | 
			
		||||
    %index of data corresponding to the cadence type
 | 
			
		||||
    indc = CadenceType==jc;
 | 
			
		||||
    
 | 
			
		||||
    %construct the integration vector based on half integration time and number
 | 
			
		||||
    %of neighbors on each side, which is a function of the binning time
 | 
			
		||||
    dtHalfIntegration = median(diff(t(indc)))/2;
 | 
			
		||||
    nNeighbors = round(dtHalfIntegration/BinningTime(jc));
 | 
			
		||||
    IntegrationStep = 2*dtHalfIntegration/(2*nNeighbors+1);
 | 
			
		||||
    IntegrationVector = -dtHalfIntegration+IntegrationStep*(0.5:(2*nNeighbors+1));
 | 
			
		||||
    NI = length(IntegrationVector);
 | 
			
		||||
    
 | 
			
		||||
    %create a table of times around the original times
 | 
			
		||||
    t1 = vertical(t(indc))+IntegrationVector;
 | 
			
		||||
        
 | 
			
		||||
    %go over planets one by one and generate planetary light curve
 | 
			
		||||
    for j = 1:Npl
 | 
			
		||||
        
 | 
			
		||||
        %calculate the phase (for the specific cadence type jc)
 | 
			
		||||
        Phi = (t1-repmat(AssociatedTmid(indc,j),1,NI)).*repmat(w(indc,j),1,NI);
 | 
			
		||||
        
 | 
			
		||||
        %calculate position on the sky with respect to the stellar center in units
 | 
			
		||||
        %of stellar radii and using its own w, a, b (for the specific cadence type jc)
 | 
			
		||||
        x = repmat(d(indc,j),1,NI).*sin(Phi);
 | 
			
		||||
        y = repmat(b(indc,j),1,NI).*cos(Phi);
 | 
			
		||||
        
 | 
			
		||||
        %calculate the distance from stellar disk center. For phases larger than
 | 
			
		||||
        %0.25 null the Mandel-Agol model by using Rsky>1+Rp (for the specific cadence type jc)
 | 
			
		||||
        Rsky = sqrt(x.^2+y.^2);
 | 
			
		||||
        Rsky(abs(Phi)>0.25) = 5;
 | 
			
		||||
        
 | 
			
		||||
        %calculate the instanteneous Mandel-Agol model for each time stamp
 | 
			
		||||
        %in the binned time vector (for the specific cadence type jc)        
 | 
			
		||||
        %lc = occultquadVec(ror(j),Rsky(:),u1,u2);
 | 
			
		||||
        lc = MALookupTable(ror(j),Rsky(:),u1,u2);
 | 
			
		||||
                
 | 
			
		||||
        %bin the light-curve by averaging, and assign in the relevant
 | 
			
		||||
        %positions of AllLC
 | 
			
		||||
        AllLC(indc,j) = mean(reshape(lc,size(Rsky)),2);
 | 
			
		||||
        
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										44
									
								
								AnalyticLC/AssociateTmid.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								AnalyticLC/AssociateTmid.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
function [AssociatedTmid,AssociatedInd] = AssociateTmid(t,Tmid,P)
 | 
			
		||||
% AssociateTmid: Associate a time-of-mid-transit to each time stamp t.
 | 
			
		||||
 | 
			
		||||
%Inputs: t - list of times
 | 
			
		||||
%           Tmid - list of times of mid transit
 | 
			
		||||
%           P - orbital period (optional input)
 | 
			
		||||
 | 
			
		||||
% Yair Judkovsky, 2.5.2020
 | 
			
		||||
 | 
			
		||||
%estimate the period if it is not given
 | 
			
		||||
if ~exist('P','var')
 | 
			
		||||
P = median(diff(Tmid));
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%transit indices - the first transit in the data is one, and going up
 | 
			
		||||
try
 | 
			
		||||
    Tr_Ind = 1+round((Tmid-Tmid(1))/P);
 | 
			
		||||
catch
 | 
			
		||||
    AssociatedTmid = nan(size(t));
 | 
			
		||||
    AssociatedInd = nan(size(t));
 | 
			
		||||
    return
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%associate an index of transit per time stamp. Any event before the first
 | 
			
		||||
%Tmid will be associated with the first Tmid. Any event after the last Tmid
 | 
			
		||||
%will be associated with the last Tmid.
 | 
			
		||||
AssociatedInd = 1+round((t-Tmid(1))/P);
 | 
			
		||||
AssociatedInd(AssociatedInd<1) = 1;
 | 
			
		||||
AssociatedInd(AssociatedInd>Tr_Ind(end)) = Tr_Ind(end);
 | 
			
		||||
 | 
			
		||||
%Associated transit index
 | 
			
		||||
try
 | 
			
		||||
Tmid_Of_Tr_Ind = inf(1,max(Tr_Ind));
 | 
			
		||||
Tmid_Of_Tr_Ind(Tr_Ind) = Tmid;
 | 
			
		||||
%next few lines for debugging purposes
 | 
			
		||||
catch
 | 
			
		||||
    save('debug_tmid');
 | 
			
		||||
    AssociatedTmid = nan(size(t));
 | 
			
		||||
    AssociatedInd = nan(size(t));
 | 
			
		||||
    return
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%associate a value of Tmid for each time stamp
 | 
			
		||||
AssociatedTmid = Tmid_Of_Tr_Ind(AssociatedInd);
 | 
			
		||||
							
								
								
									
										154
									
								
								AnalyticLC/DisturbingFunctionMultiTermVariations.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								AnalyticLC/DisturbingFunctionMultiTermVariations.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,154 @@
 | 
			
		|||
function [dLambda1,dLambda2,dz1,dz2,du1,du2,da_oa1,da_oa2] = DisturbingFunctionMultiTermVariations(n1,n2,alph,Lambda1,Lambda2,mu1,mu2,j,k,e1,e2,Pom1,Pom2,I1,I2,s1,s2,Om1,Om2,A,Ap,B,Bp,C,Cp,D,Dp,f,fE,fI,Df,DfE,DfI)
 | 
			
		||||
 | 
			
		||||
%get the number of time stamps and number of terms, in order to replicate
 | 
			
		||||
%the vectors and perform the calculation once for all terms
 | 
			
		||||
% Ntime = length(Lambda1);
 | 
			
		||||
% Nterm = length(k);
 | 
			
		||||
% 
 | 
			
		||||
% 
 | 
			
		||||
% Lambda1 = repmat(Lambda1,1,Nterm);
 | 
			
		||||
% Lambda2 = repmat(Lambda2,1,Nterm);
 | 
			
		||||
% e1 = repmat(e1,1,Nterm);
 | 
			
		||||
% e2 = repmat(e2,1,Nterm);
 | 
			
		||||
% Pom1 = repmat(Pom1,1,Nterm);
 | 
			
		||||
% Pom2 = repmat(Pom2,1,Nterm);
 | 
			
		||||
% I1 = repmat(I1,1,Nterm);
 | 
			
		||||
% I2 = repmat(I2,1,Nterm);
 | 
			
		||||
% s1 = repmat(s1,1,Nterm);
 | 
			
		||||
% s2 = repmat(s2,1,Nterm);
 | 
			
		||||
% Om1 = repmat(Om1,1,Nterm);
 | 
			
		||||
% Om2 = repmat(Om2,1,Nterm);
 | 
			
		||||
% 
 | 
			
		||||
% if length(j)==length(k)
 | 
			
		||||
%     j = repmat(j,Ntime,1);
 | 
			
		||||
% end
 | 
			
		||||
% k = repmat(k,Ntime,1);
 | 
			
		||||
% A = repmat(A,Ntime,1);
 | 
			
		||||
% Ap = repmat(Ap,Ntime,1);
 | 
			
		||||
% B = repmat(B,Ntime,1);
 | 
			
		||||
% Bp = repmat(Bp,Ntime,1);
 | 
			
		||||
% C = repmat(C,Ntime,1);
 | 
			
		||||
% Cp = repmat(Cp,Ntime,1);
 | 
			
		||||
% D = repmat(D,Ntime,1);
 | 
			
		||||
% Dp = repmat(Dp,Ntime,1);
 | 
			
		||||
 | 
			
		||||
f_inner = f+fE;
 | 
			
		||||
f_outer = f+fI;
 | 
			
		||||
Df_inner = Df+DfE;
 | 
			
		||||
Df_outer = Df+DfI;
 | 
			
		||||
 | 
			
		||||
% f = repmat(f,Ntime,1);
 | 
			
		||||
% fE = repmat(fE,Ntime,1);
 | 
			
		||||
% fI = repmat(fI,Ntime,1);
 | 
			
		||||
% Df = repmat(Df,Ntime,1);
 | 
			
		||||
% DfE = repmat(DfE,Ntime,1);
 | 
			
		||||
% DfI = repmat(DfI,Ntime,1);
 | 
			
		||||
 | 
			
		||||
% f_inner = repmat(f_inner,Ntime,1);
 | 
			
		||||
% f_outer = repmat(f_outer,Ntime,1);
 | 
			
		||||
% Df_inner = repmat(Df_inner,Ntime,1);
 | 
			
		||||
% Df_outer = repmat(Df_outer,Ntime,1);
 | 
			
		||||
 | 
			
		||||
SQ1 = sqrt(1-e1.^2);
 | 
			
		||||
SQ2 = sqrt(1-e2.^2);
 | 
			
		||||
 | 
			
		||||
%calculate the cosine argument
 | 
			
		||||
Phi = j.*Lambda2+(k-j).*Lambda1-C.*Pom1-Cp.*Pom2-D.*Om1-Dp.*Om2;
 | 
			
		||||
 | 
			
		||||
%calculate Cjk and Sjk
 | 
			
		||||
PowersFactor = e1.^A.*e2.^Ap.*s1.^B.*s2.^Bp;
 | 
			
		||||
Cjk = PowersFactor.*cos(Phi);
 | 
			
		||||
Sjk = PowersFactor.*sin(Phi);
 | 
			
		||||
 | 
			
		||||
%calculate the mean-motion of the longitude of conjunction
 | 
			
		||||
njk = j*n2+(k-j)*n1;
 | 
			
		||||
 | 
			
		||||
%orbital elements variations - inner planet
 | 
			
		||||
da_oa1 = 2*mu2/(1+mu1)*alph*(f_inner).*(k-j)*n1./njk.*Cjk;
 | 
			
		||||
 | 
			
		||||
dLambda1 = mu2/(1+mu1)*alph*n1./njk.*Sjk...
 | 
			
		||||
    .*(...
 | 
			
		||||
    3.*(f_inner).*(j-k)*n1./njk...
 | 
			
		||||
    -2*alph*(Df_inner)...
 | 
			
		||||
    +(f_inner).*A.*(SQ1.*(1-SQ1))./(e1.^2)...
 | 
			
		||||
    +(f_inner).*B/2./SQ1...
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
de1 = mu2/(1+mu1)*alph*(f_inner).*SQ1./e1*n1./njk.*Cjk...
 | 
			
		||||
    .*((j-k).*(1-SQ1)+C);
 | 
			
		||||
 | 
			
		||||
dPom1 = mu2/(1+mu1)*alph*(f_inner)*n1./njk.*Sjk...
 | 
			
		||||
    .*(A.*SQ1./(e1.^2)+B/2./SQ1);
 | 
			
		||||
 | 
			
		||||
dI1 = mu2/(1+mu1)*alph*(f_inner)./SQ1*n1./njk.*Cjk...
 | 
			
		||||
    .*((j-k+C).*tan(I1/2)+D./sin(I1));
 | 
			
		||||
 | 
			
		||||
dOm1 = mu2/(1+mu1)*alph*(f_inner).*B/2.*cot(I1/2)./(SQ1.*sin(I1))*n1./njk.*Sjk;
 | 
			
		||||
 | 
			
		||||
% dI1 = 0; dOm1 = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
%orbital elements variations - outer planet
 | 
			
		||||
da_oa2 = 2*mu1/(1+mu2)*(f_outer).*j*n2./njk.*Cjk;
 | 
			
		||||
 | 
			
		||||
dLambda2 = mu1/(1+mu2)*n2./njk.*Sjk.*...
 | 
			
		||||
    (...
 | 
			
		||||
  -3*(f_outer).*j*n2./njk...
 | 
			
		||||
  +2*(f_outer+alph*Df_outer)...
 | 
			
		||||
  +(f_outer).*Ap.*SQ2.*(1-SQ2)./(e2.^2)...
 | 
			
		||||
  +(f_outer).*Bp/2./SQ2...
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
de2 = mu1/(1+mu2)*(f_outer).*SQ2./e2*n2./njk.*Cjk.*...
 | 
			
		||||
    (...
 | 
			
		||||
    -j.*(1-SQ2)+Cp...
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
dPom2 = mu1/(1+mu2)*(f_outer)*n2./njk.*Sjk.*...
 | 
			
		||||
    (...
 | 
			
		||||
  Ap.*SQ2./(e2.^2)+Bp/2./SQ2...  
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
dI2 = mu1/(1+mu2)*(f_outer)./SQ2*n2./njk.*Cjk.*...
 | 
			
		||||
    (...
 | 
			
		||||
  (Cp-j).*tan(I2/2)+Dp./sin(I2)...  
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
dOm2 = mu1/(1+mu2)*(f_outer).*Bp/2.*cot(I2/2)./(SQ2.*sin(I2))*n2./njk.*Sjk;
 | 
			
		||||
 | 
			
		||||
% dI2 = 0; dOm2 = 0;
 | 
			
		||||
 | 
			
		||||
NewVersion = 1;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if ~NewVersion
 | 
			
		||||
%translate to the complex form
 | 
			
		||||
dz1 = (de1+1i*dPom1.*e1).*exp(1i*Pom1);
 | 
			
		||||
dz2 = (de2+1i*dPom2.*e2).*exp(1i*Pom2);
 | 
			
		||||
 | 
			
		||||
du1 = (dI1+1i*dOm1.*I1).*exp(1i*Om1);
 | 
			
		||||
du2 = (dI2+1i*dOm2.*I2).*exp(1i*Om2);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
%sum the distribution of all terms to get the total effect
 | 
			
		||||
dz1 = sum(dz1,2);
 | 
			
		||||
dz2 = sum(dz2,2);
 | 
			
		||||
du1 = sum(du1,2);
 | 
			
		||||
du2 = sum(du2,2);
 | 
			
		||||
da_oa1 = sum(da_oa1,2);
 | 
			
		||||
da_oa2 = sum(da_oa2,2);
 | 
			
		||||
dLambda1 = sum(dLambda1,2);
 | 
			
		||||
dLambda2 = sum(dLambda2,2);
 | 
			
		||||
 | 
			
		||||
else
 | 
			
		||||
   %translate to the complex form
 | 
			
		||||
dz1 = (sum(de1,2)+1i*sum(dPom1,2).*e1).*exp(1i*Pom1);
 | 
			
		||||
dz2 = (sum(de2,2)+1i*sum(dPom2,2).*e2).*exp(1i*Pom2); 
 | 
			
		||||
du1 = (sum(dI1,2)+1i*sum(dOm1,2).*I1).*exp(1i*Om1);
 | 
			
		||||
du2 = (sum(dI2,2)+1i*sum(dOm2,2).*I2).*exp(1i*Om2);
 | 
			
		||||
da_oa1 = sum(da_oa1,2);
 | 
			
		||||
da_oa2 = sum(da_oa2,2);
 | 
			
		||||
dLambda1 = sum(dLambda1,2);
 | 
			
		||||
dLambda2 = sum(dLambda2,2);
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										1230
									
								
								AnalyticLC/ForcedElements1.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1230
									
								
								AnalyticLC/ForcedElements1.m
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										82
									
								
								AnalyticLC/ForcedMeanLongitudes3PlanetsCrossTerms.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								AnalyticLC/ForcedMeanLongitudes3PlanetsCrossTerms.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,82 @@
 | 
			
		|||
function dLambda = ForcedMeanLongitudes3PlanetsCrossTerms(P,Lambda,mu,z)
 | 
			
		||||
% ForcedMeanLongitudes3Planets: calculate the forced mean longitudes of a set of
 | 
			
		||||
% planets due to the cross-terms among different resonances.
 | 
			
		||||
 | 
			
		||||
%Inputs: P - orbital periods, Lambda - mean longitudes, mu - planets/star
 | 
			
		||||
%mass ratio, z - free eccentricities (if they are not given, zero values
 | 
			
		||||
%are assumed). Labmda and z can be given as columns of multiple values.
 | 
			
		||||
 | 
			
		||||
% Yair Judkovsky, 2.11.2020
 | 
			
		||||
 | 
			
		||||
if ~exist('z','var')
 | 
			
		||||
    z = zeros(size(P));
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%mean motions
 | 
			
		||||
n = 2*pi./P;
 | 
			
		||||
 | 
			
		||||
%absolute values and angles of eccentricities
 | 
			
		||||
pom = angle(z);
 | 
			
		||||
e = abs(z);
 | 
			
		||||
zx = real(z);
 | 
			
		||||
zy = imag(z);
 | 
			
		||||
 | 
			
		||||
%allocate space for 3d matrices that will hold the values of dLambda
 | 
			
		||||
%according to these dimensios: orders, data points, number of planets
 | 
			
		||||
dLambda = zeros(size(z,1),length(P));
 | 
			
		||||
 | 
			
		||||
%go over all possible planets triplets
 | 
			
		||||
for j1 = 1:length(P)
 | 
			
		||||
    for j2 = (j1+1):length(P)
 | 
			
		||||
        for j3 = (j2+1):length(P)
 | 
			
		||||
            
 | 
			
		||||
            %calculate the nearest 1st order MMR for each pair in the
 | 
			
		||||
            %triplet
 | 
			
		||||
            j = round(P(j2)/(P(j2)-P(j1)));
 | 
			
		||||
            k = round(P(j3)/(P(j3)-P(j2)));
 | 
			
		||||
            nj = j*n(j2)+(1-j)*n(j1);
 | 
			
		||||
            nk = k*n(j3)+(1-k)*n(j2);
 | 
			
		||||
            alph12 = (n(j2)/n(j1))^(2/3)*((1+mu(j1))/(1+mu(j2)))^(1/3);
 | 
			
		||||
            alph23 = (n(j3)/n(j2))^(2/3)*((1+mu(j2))/(1+mu(j3)))^(1/3);
 | 
			
		||||
            
 | 
			
		||||
            %longitudes of conjunction
 | 
			
		||||
            Lambda_j = j*Lambda(:,j2)+(1-j)*Lambda(:,j1);
 | 
			
		||||
            Lambda_k = k*Lambda(:,j3)+(1-k)*Lambda(:,j2);
 | 
			
		||||
            
 | 
			
		||||
            %laplace coefficients
 | 
			
		||||
            Ak = LaplaceCoeffs(alph23,0.5,k,0);
 | 
			
		||||
            DAk = LaplaceCoeffs(alph23,0.5,k,1);
 | 
			
		||||
            Ajm1 = LaplaceCoeffs(alph12,0.5,j-1,0);
 | 
			
		||||
            DAjm1 = LaplaceCoeffs(alph12,0.5,j-1,1);
 | 
			
		||||
            D2Ajm1 = LaplaceCoeffs(alph12,0.5,j-1,2);
 | 
			
		||||
            f27k = -k*Ak-0.5*alph23*DAk;
 | 
			
		||||
            f31j = (j-0.5)*Ajm1+0.5*alph12*DAjm1;
 | 
			
		||||
            
 | 
			
		||||
            Df31j = (j-0.5)*DAjm1+0.5*DAjm1+0.5*alph12*D2Ajm1;
 | 
			
		||||
            
 | 
			
		||||
             F=sqrt(1);            
 | 
			
		||||
            %calculate and add to the dlambda of the intermediate planet
 | 
			
		||||
            AlphaFactor = -3/2*f27k*(f31j-(j==2)/(2*alph12^2))*alph23;
 | 
			
		||||
            MassFactor = mu(j1)*mu(j3)/(1+mu(j2))^2;            
 | 
			
		||||
            SinTerm1 = (j/nk+(1-k)/nj)*sin(Lambda_j+Lambda_k-2*pom(:,j2))/(nj+nk)^2;
 | 
			
		||||
            SinTerm2 = (j/nk-(1-k)/nj)*sin(Lambda_j-Lambda_k)/(nj-nk)^2;                       
 | 
			
		||||
            dLambda(:,j2) = dLambda(:,j2)+F*AlphaFactor*MassFactor*n(j2)^3*(SinTerm1+SinTerm2);
 | 
			
		||||
        
 | 
			
		||||
            %calculate and add to the dlambda of the innermost planet
 | 
			
		||||
            AlphaFactor = 3/2*f27k*(f31j-2*alph12*(j==2))*alph12*alph23;
 | 
			
		||||
            MassFactor = mu(j2)*mu(j3)/(1+mu(j1))/(1+mu(j2));
 | 
			
		||||
            SinTerm1 = sin(Lambda_j+Lambda_k-2*pom(:,j2))/(nj+nk)^2;
 | 
			
		||||
            SinTerm2 = sin(Lambda_j-Lambda_k)/(nj-nk)^2;
 | 
			
		||||
            dLambda(:,j1) = dLambda(:,j1)+F*AlphaFactor*MassFactor*n(j1)^2*n(j2)*(j-1)/nk*(SinTerm1+SinTerm2);
 | 
			
		||||
              
 | 
			
		||||
            %calculate and add to the dlambda of the outermost planet
 | 
			
		||||
            AlphaFactor = -3/2*f27k*(f31j-(j==2)/(2*alph12^2));
 | 
			
		||||
            MassFactor = mu(j1)*mu(j2)/(1+mu(j2))/(1+mu(j3));
 | 
			
		||||
            SinTerm1 = sin(Lambda_j+Lambda_k-2*pom(:,j2))/(nj+nk)^2;
 | 
			
		||||
            SinTerm2 = -sin(Lambda_j-Lambda_k)/(nj-nk)^2;
 | 
			
		||||
            dLambda(:,j3) = dLambda(:,j3)+F*AlphaFactor*MassFactor*n(j3)^2*n(j2)*k/nj*(SinTerm1+SinTerm2);
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										166
									
								
								AnalyticLC/LaplaceCoeffs.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								AnalyticLC/LaplaceCoeffs.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,166 @@
 | 
			
		|||
function Output = LaplaceCoeffs(varargin)
 | 
			
		||||
% LaplaceCoeff: get a Laplace coefficient (definition: Solar System
 | 
			
		||||
% Dynamics, eq. 6.67)
 | 
			
		||||
 | 
			
		||||
%Inputs: 'init' - calculate a table of the laplace coefficients and save it
 | 
			
		||||
%           in ~/Matlab/Data/LaplaceCoeffs.mat
 | 
			
		||||
%           'load' = return all the table and the row/col values in a
 | 
			
		||||
%           structure
 | 
			
		||||
%           alph,s,j = return the laplace coefficient for the given alph,s,j.
 | 
			
		||||
%           alph can be a vector
 | 
			
		||||
%           alph,s,j,D = return the D order derivative of the laplace
 | 
			
		||||
%           coefficient for the given alph, s, j.
 | 
			
		||||
 | 
			
		||||
% Yair Judkovsky, 6.4.2020
 | 
			
		||||
 | 
			
		||||
persistent jVec sVec DVec alphaVec bTable Nj Ns ND
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
%return a specific laplace coeff
 | 
			
		||||
if isnumeric(varargin{1})
 | 
			
		||||
    
 | 
			
		||||
    alph = varargin{1};
 | 
			
		||||
    s = varargin{2};
 | 
			
		||||
    j = abs(varargin{3}); %b_s_j = b_s__-j, Solar System Dynamics eq. 6.69
 | 
			
		||||
    
 | 
			
		||||
    %a recursive path of the function for the case there's a 4th input -
 | 
			
		||||
    %the laplace coeff derivative.
 | 
			
		||||
    if length(varargin)>3
 | 
			
		||||
        D = varargin{4}; %derivative order
 | 
			
		||||
    else
 | 
			
		||||
        D = 0;
 | 
			
		||||
    end          
 | 
			
		||||
              
 | 
			
		||||
    jInd = j+1;
 | 
			
		||||
    sInd = s+0.5;
 | 
			
		||||
    DInd = D+1;
 | 
			
		||||
    
 | 
			
		||||
    %if the requested derivative is too high, calculate by recursive method
 | 
			
		||||
    if DInd>ND
 | 
			
		||||
        %2nd and higher derivatives of the coeff, Solar System Dynamics eq. 6.71
 | 
			
		||||
        Output = s*(LaplaceCoeffs(alph,s+1,j-1,D-1)-2*alph.*LaplaceCoeffs(alph,s+1,j,D-1)+LaplaceCoeffs(alph,s+1,j+1,D-1)-2*(D-1)*LaplaceCoeffs(alph,s+1,j,D-2));
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    row = sub2ind([Nj,Ns,ND],jInd,sInd,DInd);
 | 
			
		||||
    
 | 
			
		||||
    %find the column corresponding to the alpha given, currently by finding the
 | 
			
		||||
    %closest value in the table
 | 
			
		||||
    F = (length(alphaVec));
 | 
			
		||||
    col = round(alph*F);
 | 
			
		||||
    if col==0
 | 
			
		||||
        col = 1;
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    %return the value from the table
 | 
			
		||||
    Output = bTable(row,col);
 | 
			
		||||
    return
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%perform the calculation. Table will be made such that each row
 | 
			
		||||
%corresponds to some j,s combination, and each column corresponds to an
 | 
			
		||||
%alpha value.
 | 
			
		||||
if isequal(varargin{1},'init')
 | 
			
		||||
    
 | 
			
		||||
    %define the integrand function
 | 
			
		||||
    laplace_integrand=@(j1,s1,alph1) (@(phi) (cos(j1.*phi)./(1-2.*alph1.*cos(phi)+alph1.^2).^s1));
 | 
			
		||||
    
 | 
			
		||||
    warning off
 | 
			
		||||
    
 | 
			
		||||
    %set range of j, s, D, alpha. Can also be read from varargin if
 | 
			
		||||
    %exists, where the 2,3,4,5 arguments will be Ns, Nj,ND and dalpha
 | 
			
		||||
    Ns =3;
 | 
			
		||||
    Nj = 5;
 | 
			
		||||
    ND = 4;
 | 
			
		||||
    dalpha = 1e-2;
 | 
			
		||||
    %set integration tolerance
 | 
			
		||||
    AbsTol = 1e-5;
 | 
			
		||||
    Path = '~/Matlab/Data/LaplaceCoeffs.mat';
 | 
			
		||||
    
 | 
			
		||||
    %read inputs from varargin, if they exist
 | 
			
		||||
    if length(varargin)==5
 | 
			
		||||
        Ns = varargin{2};
 | 
			
		||||
        Nj = varargin{3};
 | 
			
		||||
        ND = varargin{4};
 | 
			
		||||
        dalpha = varargin{5};
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    if length(varargin)>5
 | 
			
		||||
        AbsTol = varargin{6};
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    if length(varargin)>6
 | 
			
		||||
        Path = varargin{7};
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    %set a vector of s and j values
 | 
			
		||||
    sVec = (1:Ns)-0.5;
 | 
			
		||||
    jVec = (1:Nj)-1;
 | 
			
		||||
    DVec = (1:ND)-1;
 | 
			
		||||
      
 | 
			
		||||
    %define the alpha vector from dalpha
 | 
			
		||||
    alphaVec = dalpha:dalpha:1;
 | 
			
		||||
      
 | 
			
		||||
    %pre-allocate
 | 
			
		||||
    bTable = zeros(Nj*Ns*ND,length(alphaVec));
 | 
			
		||||
    
 | 
			
		||||
    for jInd = 1:length(jVec)
 | 
			
		||||
        for sInd = 1:length(sVec)
 | 
			
		||||
            for DInd = 1:length(DVec)
 | 
			
		||||
                for alphaInd = 1:length(alphaVec)
 | 
			
		||||
                    
 | 
			
		||||
                    row = sub2ind([Nj,Ns,ND],jInd,sInd,DInd);
 | 
			
		||||
                    
 | 
			
		||||
                    val = CalculateSingleCoeff(jVec(jInd),sVec(sInd),alphaVec(alphaInd),DVec(DInd),AbsTol,laplace_integrand);
 | 
			
		||||
                    
 | 
			
		||||
                    bTable(row,alphaInd)=val;
 | 
			
		||||
                    
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    save(Path,'jVec','sVec','alphaVec','DVec','bTable','Nj','Ns','ND');
 | 
			
		||||
    disp('calculated laplace coeffs');
 | 
			
		||||
    Output = [];
 | 
			
		||||
    return
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%load the table including the persistent variables for future use. Also
 | 
			
		||||
%return the persistent variables in a structure as an output.
 | 
			
		||||
if isequal(varargin{1},'load')
 | 
			
		||||
    Path = '~/Matlab/Data/LaplaceCoeffs.mat';
 | 
			
		||||
    if nargin>1
 | 
			
		||||
        Path = varargin{2};
 | 
			
		||||
    end
 | 
			
		||||
    load(Path);
 | 
			
		||||
    Output = load(Path);
 | 
			
		||||
    return
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
%         if D==0
 | 
			
		||||
%             Output = LaplaceCoeffs(alph,s,j);
 | 
			
		||||
%         elseif D==1 %first derivative of the coeff, Solar System Dynamics eq. 6.70
 | 
			
		||||
%             Output = s*(LaplaceCoeffs(alph,s+1,j-1)-2*alph.*LaplaceCoeffs(alph,s+1,j)+LaplaceCoeffs(alph,s+1,j+1));
 | 
			
		||||
%         else %2nd and higher derivatives of the coeff, Solar System Dynamics eq. 6.71
 | 
			
		||||
%             Output = s*(LaplaceCoeffs(alph,s+1,j-1,D-1)-2*alph.*LaplaceCoeffs(alph,s+1,j,D-1)+LaplaceCoeffs(alph,s+1,j+1,D-1)-2*(D-1)*LaplaceCoeffs(alph,s+1,j,D-2));
 | 
			
		||||
%         end
 | 
			
		||||
%         return
 | 
			
		||||
        
 | 
			
		||||
function val = CalculateSingleCoeff(j,s,alph,D,AbsTol,laplace_integrand)
 | 
			
		||||
 | 
			
		||||
% %define the integrand function
 | 
			
		||||
% laplace_integrand=@(j1,s1,alph1) (@(phi) (cos(j1.*phi)./(1-2.*alph1.*cos(phi)+alph1.^2).^s1));
 | 
			
		||||
 | 
			
		||||
if D==0
 | 
			
		||||
    val = 1/pi*integral(laplace_integrand(j,s,alph),0,2*pi,'AbsTol',AbsTol);
 | 
			
		||||
elseif D==1 %first derivative of the coeff, Solar System Dynamics eq. 6.70
 | 
			
		||||
    val = s*(CalculateSingleCoeff(j-1,s+1,alph,D-1,AbsTol,laplace_integrand)...
 | 
			
		||||
            -2*alph.*CalculateSingleCoeff(j,s+1,alph,D-1,AbsTol,laplace_integrand)...
 | 
			
		||||
            +CalculateSingleCoeff(j+1,s+1,alph,D-1,AbsTol,laplace_integrand));
 | 
			
		||||
else %2nd and higher derivatives of the coeff, Solar System Dynamics eq. 6.71
 | 
			
		||||
    val = s*(CalculateSingleCoeff(j-1,s+1,alph,D-1,AbsTol,laplace_integrand)...
 | 
			
		||||
            -2*alph.*CalculateSingleCoeff(j,s+1,alph,D-1,AbsTol,laplace_integrand)...
 | 
			
		||||
            +CalculateSingleCoeff(j+1,s+1,alph,D-1,AbsTol,laplace_integrand)...
 | 
			
		||||
            -2*(D-1)*CalculateSingleCoeff(j,s+1,alph,D-2,AbsTol,laplace_integrand));
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										105
									
								
								AnalyticLC/MALookupTable.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								AnalyticLC/MALookupTable.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,105 @@
 | 
			
		|||
function Output = MALookupTable(varargin)
 | 
			
		||||
% MALookupTable: generate a look-up table for Mandel-Agol model values, or
 | 
			
		||||
% use the table and read from it
 | 
			
		||||
 | 
			
		||||
%Inputs: 'init' - calculate a table of the MA values for the given rVec,
 | 
			
		||||
%zVec, u1, u2
 | 
			
		||||
%           'load' = return all the table and the row/col values in a
 | 
			
		||||
%           structure
 | 
			
		||||
%           r,z = return the Mandel-Agol model values for the given r,z.
 | 
			
		||||
%           u1 and u2 which will be used are the ones that were used for
 | 
			
		||||
%           generating the table. z can be a vector, r must be a scalar.
 | 
			
		||||
 | 
			
		||||
% Yair Judkovsky, 25.10.2020
 | 
			
		||||
 | 
			
		||||
persistent rVec zVec u1 u2 R Z MATable
 | 
			
		||||
 | 
			
		||||
%return a specific Mandel-Agol model value
 | 
			
		||||
if isnumeric(varargin{1})
 | 
			
		||||
    
 | 
			
		||||
    %get r, z values from the input
 | 
			
		||||
    r = varargin{1};
 | 
			
		||||
    z = varargin{2};
 | 
			
		||||
    Requested_u1 = varargin{3};
 | 
			
		||||
    Requested_u2 = varargin{4};
 | 
			
		||||
    
 | 
			
		||||
    %if no table exists, or if the requested u1,u2 do not match the table, just calculate the values
 | 
			
		||||
    if isempty(MATable) || Requested_u1~=u1 || Requested_u2~=u2
 | 
			
		||||
        Output = occultquadVec(r,z,Requested_u1,Requested_u2);
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    Output = ones(size(z));
 | 
			
		||||
    
 | 
			
		||||
    %old method - plug in "1" wherever outside the planet radius range
 | 
			
		||||
%     Output(z<1+r) = interp2(R,Z,MATable,z(z<1+r),r,'linear',1);
 | 
			
		||||
    
 | 
			
		||||
    %new method - outside the radius range calculate using occultquadVec. This
 | 
			
		||||
    %is useful because now the radius range can be reduce, yielding a fast
 | 
			
		||||
    %calculation for most of the points
 | 
			
		||||
    ind = r>min(rVec) & r<max(rVec);
 | 
			
		||||
    Output(z<1+r & ind) = interp2(R,Z,MATable,z(z<1+r & ind),r,'linear');
 | 
			
		||||
    Output(z<1+r & ~ind) = occultquadVec(r,z(z<1+r & ~ind),u1,u2);
 | 
			
		||||
    
 | 
			
		||||
    return
 | 
			
		||||
    
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%perform the calculation. Table will be made such that each row represents
 | 
			
		||||
%a value of r, and each column represents a value of z
 | 
			
		||||
if isequal(varargin{1},'init')
 | 
			
		||||
    
 | 
			
		||||
    %set range of r, z, u1, u2. Can also be read from varargin if
 | 
			
		||||
    %exists, where the 2,3,4,5 arguments will be rVec, zVec, u1, u2.
 | 
			
		||||
    rVec = 0.5e-2:2e-3:0.2;
 | 
			
		||||
    zVec = 0:2e-3:1.25;
 | 
			
		||||
    u1 = 0.36;
 | 
			
		||||
    u2 = 0.28;
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    %read inputs from varargin, if they exist
 | 
			
		||||
    if length(varargin)==5
 | 
			
		||||
        rVec = varargin{2};
 | 
			
		||||
        zVec = varargin{3};
 | 
			
		||||
        u1 = varargin{4};
 | 
			
		||||
        u2 = varargin{5};
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    %generate a table of r and z values
 | 
			
		||||
    [R,Z] = meshgrid(zVec,rVec);
 | 
			
		||||
    
 | 
			
		||||
    %set a table of model values for r and z
 | 
			
		||||
    MATable = zeros(length(rVec),length(zVec));
 | 
			
		||||
    for j = 1:length(rVec)
 | 
			
		||||
        MATable(j,:) = occultquadVec(rVec(j),zVec,u1,u2);
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    fprintf('calculated Mandel-Agol values \n');
 | 
			
		||||
    
 | 
			
		||||
    Output = [];
 | 
			
		||||
    return
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%load the table
 | 
			
		||||
if isequal(varargin{1},'load')
 | 
			
		||||
    Output.rVec = rVec;
 | 
			
		||||
    Output.zVec = zVec;
 | 
			
		||||
    Output.u1 = u1;
 | 
			
		||||
    Output.u2 = u2;
 | 
			
		||||
    Output.R = R;
 | 
			
		||||
    Output.Z = Z;
 | 
			
		||||
    Output.MATable = MATable;
 | 
			
		||||
    return
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
%clear the values
 | 
			
		||||
if isequal(varargin{1},'clear')
 | 
			
		||||
    clear rVec zVec u1 u2 R Z MATable
 | 
			
		||||
    Output = [];
 | 
			
		||||
    return
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										24
									
								
								AnalyticLC/OrbitalElements2TransitParams.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								AnalyticLC/OrbitalElements2TransitParams.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
function [w,d,b,T,Tau] = OrbitalElements2TransitParams(n,aor,ex,ey,I,Omega,r)
 | 
			
		||||
%OrbitalElements2TransitParams: returns the duration, ingress-egress time and angular velocity as a
 | 
			
		||||
%function of the orbital properties.
 | 
			
		||||
 | 
			
		||||
%inputs: n - mean motion, aor - semi-major axis over stellar radius, ex,ey - eccentricity vector components, x
 | 
			
		||||
%pointing at observer, I,Omega - inclination with respect to the planet xy,
 | 
			
		||||
%r - planetary radius in units of stellar radii.
 | 
			
		||||
%where x points at observer. Outputs: T=Duration, Tau=ingress/egress time,
 | 
			
		||||
%w = angular velocity at mid-transit, d = planet-star distance at
 | 
			
		||||
%mid-transit, b = impact parameter
 | 
			
		||||
 | 
			
		||||
%Yair Judkovsky, 9.9.2020
 | 
			
		||||
 | 
			
		||||
w = n.*(1+ex).^2./(1-ex.^2-ey.^2).^(3/2);
 | 
			
		||||
d = aor.*(1-ex.^2-ey.^2)./(1+ex);
 | 
			
		||||
b = d.*sin(I).*sin(Omega);
 | 
			
		||||
 | 
			
		||||
if nargout>3
 | 
			
		||||
asin0 = asin(sqrt(((1+ex).^2./(aor.^2.*(1-ex.^2-ey.^2).^2)-sin(I).^2.*sin(Omega).^2)./(1-sin(I).^2.*sin(Omega).^2)));
 | 
			
		||||
T=1./n*2.*((1-ex.^2-ey.^2).^(3/2))./((1+ex).^2).*asin0;
 | 
			
		||||
asin2 = asin(sqrt(((1+r).^2.*(1+ex).^2./(aor.^2.*(1-ex.^2-ey.^2).^2)-sin(I).^2.*sin(Omega).^2)./(1-sin(I).^2.*sin(Omega).^2)));
 | 
			
		||||
asin1 = asin(sqrt(((1-r).^2.*(1+ex).^2./(aor.^2.*(1-ex.^2-ey.^2).^2)-sin(I).^2.*sin(Omega).^2)./(1-sin(I).^2.*sin(Omega).^2)));
 | 
			
		||||
Tau=1./n.*((1-ex.^2-ey.^2).^(3/2))./((1+ex).^2).*(asin2-asin1);
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										1
									
								
								AnalyticLC/fooo.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								AnalyticLC/fooo.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
t = 0:100:0.02
 | 
			
		||||
							
								
								
									
										16
									
								
								AnalyticLC/fooo.octave
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								AnalyticLC/fooo.octave
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
P = [9, 19, 32]
 | 
			
		||||
Tmid0 = [0, 10, 15]
 | 
			
		||||
ror = [0.03, 0.12, 0.05]
 | 
			
		||||
aor = 25
 | 
			
		||||
mu = [0.02, 0.05, 0.01]
 | 
			
		||||
ex0 = [0, 0, 0]
 | 
			
		||||
ey0 = [0, 0, 0]
 | 
			
		||||
I0 = [90, 90, 90]
 | 
			
		||||
Omega0 = [0, 0, 0]
 | 
			
		||||
t = [0, 9, 19, 22, 32]
 | 
			
		||||
u1 = 0.27
 | 
			
		||||
u2 = 0.13
 | 
			
		||||
 | 
			
		||||
LC = AnalyticLC(P, Tmid0, ror, aor, mu, ex0, ey0, I0, Omega0, t, u1, u2)
 | 
			
		||||
 | 
			
		||||
print LC
 | 
			
		||||
							
								
								
									
										16
									
								
								AnalyticLC/test.octave
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								AnalyticLC/test.octave
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
P = [9, 19, 32]
 | 
			
		||||
Tmid0 = [0, 10, 15]
 | 
			
		||||
ror = [0.03, 0.12, 0.05]
 | 
			
		||||
aor = 25
 | 
			
		||||
mu = [0.02, 0.05, 0.01]
 | 
			
		||||
ex0 = [0, 0, 0]
 | 
			
		||||
ey0 = [0, 0, 0]
 | 
			
		||||
I0 = [90, 90, 90]
 | 
			
		||||
Omega0 = [0, 0, 0]
 | 
			
		||||
t = [0, 9, 19, 22, 32]
 | 
			
		||||
u1 = 0.27
 | 
			
		||||
u2 = 0.13
 | 
			
		||||
 | 
			
		||||
LC = AnalyticLC(P, Tmid0, ror, aor, mu, ex0, ey0, I0, Omega0, t, u1, u2)
 | 
			
		||||
 | 
			
		||||
print LC
 | 
			
		||||
							
								
								
									
										6
									
								
								FittingAndMath/CatStructFields.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								FittingAndMath/CatStructFields.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
function S = CatStructFields(S, T, dim)
 | 
			
		||||
fields = fieldnames(S);
 | 
			
		||||
for k = 1:numel(fields)
 | 
			
		||||
  aField     = fields{k}; % EDIT: changed to {}
 | 
			
		||||
  S.(aField) = cat(dim, S.(aField), T.(aField));
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										37
									
								
								FittingAndMath/Vector1stOrderDE.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								FittingAndMath/Vector1stOrderDE.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
function xt = Vector1stOrderDE(A,x0,t)
 | 
			
		||||
%Vector1stOrderDE: - solves the vector equation dx/dt=Ax
 | 
			
		||||
 | 
			
		||||
%inputs: A - matrix of the equation, x0 - x for t=0, t - time axis to
 | 
			
		||||
%evaluate values at. derivation is given at:
 | 
			
		||||
%https://www.unf.edu/~mzhan/chapter4.pdf
 | 
			
		||||
 | 
			
		||||
%Yair Judkovsky, 3.10.2020
 | 
			
		||||
 | 
			
		||||
if nargin==0
 | 
			
		||||
A=[.1,.01;-.002,-.002].*i;
 | 
			
		||||
x0=[.3,0.0001];
 | 
			
		||||
t=linspace(0,100,100000);
 | 
			
		||||
end
 | 
			
		||||
nt=length(t);
 | 
			
		||||
if any(~isfinite(A(:))), xt = 123.123; return, end
 | 
			
		||||
[ev,lam]=eig(A);
 | 
			
		||||
nev=length(diag(lam));
 | 
			
		||||
phi0i=inv(ev);
 | 
			
		||||
% add singleton dimension as the first (time) index and replicate
 | 
			
		||||
% eigenvectors along that dimension.
 | 
			
		||||
evp=repmat(reshape(ev,[1,nev,nev]),[length(t),1,1]);
 | 
			
		||||
 | 
			
		||||
lamt=reshape(exp(diag(lam)*t).',length(t),1,nev);
 | 
			
		||||
lamt=repmat(lamt,1,nev,1);
 | 
			
		||||
phit=lamt.*evp;
 | 
			
		||||
 | 
			
		||||
xt=reshape(reshape(phit,nev*nt,nev)*(phi0i*x0),nt,nev);
 | 
			
		||||
 | 
			
		||||
if nargin==0
 | 
			
		||||
figure;
 | 
			
		||||
plot(xt);
 | 
			
		||||
hold on
 | 
			
		||||
plot(real(x0),imag(x0),'o');
 | 
			
		||||
axis equal
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								FittingAndMath/fit_linear.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								FittingAndMath/fit_linear.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
function [a,b,da,db]=fit_linear(x,y,varargin)
 | 
			
		||||
%fit_linear: 1st order linear regression.
 | 
			
		||||
 | 
			
		||||
%This function fits a dataset of x and y values to the linear equation
 | 
			
		||||
%y=ax+b. it is optional for the user to insert also y error values for the
 | 
			
		||||
%estimation of a and b errors.
 | 
			
		||||
%
 | 
			
		||||
 | 
			
		||||
%Yair Judkovsky, 21.8.2013
 | 
			
		||||
 | 
			
		||||
if nargin==2     %case of no error input - assuming that all errors are equal
 | 
			
		||||
 dy = ones(size(y));
 | 
			
		||||
else
 | 
			
		||||
 dy = varargin{1};
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
dy2=dy.^2;
 | 
			
		||||
x2=x.^2;
 | 
			
		||||
xy=x.*y;
 | 
			
		||||
 | 
			
		||||
S=sum(1./dy2);
 | 
			
		||||
Sx=sum(x./dy2);
 | 
			
		||||
Sy=sum(y./dy2);
 | 
			
		||||
Sxx=sum(x2./dy2);
 | 
			
		||||
Sxy=sum(xy./dy2);
 | 
			
		||||
D=S*Sxx-Sx^2;
 | 
			
		||||
 | 
			
		||||
a=(S*Sxy-Sx*Sy)/D;
 | 
			
		||||
b=(Sxx*Sy-Sxy*Sx)/D;
 | 
			
		||||
 | 
			
		||||
if nargin==2    %no error given - need to estimate it
 | 
			
		||||
    Ytheo=a*x+b;
 | 
			
		||||
    dy2=mean((Ytheo-y).^2)*ones(size(y));    
 | 
			
		||||
    S=sum(1./dy2);
 | 
			
		||||
    Sx=sum(x./dy2);
 | 
			
		||||
    Sxx=sum(x2./dy2);
 | 
			
		||||
    D=S*Sxx-Sx^2;
 | 
			
		||||
    da=sqrt(S/D);
 | 
			
		||||
    db=sqrt(Sxx/D);
 | 
			
		||||
else
 | 
			
		||||
    da=sqrt(S/D);
 | 
			
		||||
    db=sqrt(Sxx/D);
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return
 | 
			
		||||
							
								
								
									
										9
									
								
								FittingAndMath/horizontal.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								FittingAndMath/horizontal.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
function horzvec=horizontal(vec)
 | 
			
		||||
%reshape input vector into row vector
 | 
			
		||||
    
 | 
			
		||||
if min(size(vec))>1
 | 
			
		||||
    horzvec=[];
 | 
			
		||||
    return
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
horzvec=reshape(vec,1,length(vec));
 | 
			
		||||
							
								
								
									
										3
									
								
								FittingAndMath/range.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								FittingAndMath/range.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
function res = range(X)
 | 
			
		||||
res=max(X(:))-min(X(:));
 | 
			
		||||
return
 | 
			
		||||
							
								
								
									
										9
									
								
								FittingAndMath/vertical.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								FittingAndMath/vertical.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
function vertvec=vertical(vec)
 | 
			
		||||
%reshape input vector into row vector
 | 
			
		||||
    
 | 
			
		||||
if min(size(vec))>1
 | 
			
		||||
    vertvec=[];
 | 
			
		||||
    return
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
vertvec=reshape(vec,length(vec),1);
 | 
			
		||||
							
								
								
									
										17
									
								
								FluxCalculation/ellecVec.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								FluxCalculation/ellecVec.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
function ellec=ellecVec(k)
 | 
			
		||||
% Computes polynomial approximation for the complete elliptic
 | 
			
		||||
% integral of the second kind (Hasting's approximation):
 | 
			
		||||
m1=1-k.*k;
 | 
			
		||||
m1(m1<eps)=eps;
 | 
			
		||||
a1=0.44325141463;
 | 
			
		||||
a2=0.06260601220;
 | 
			
		||||
a3=0.04757383546;
 | 
			
		||||
a4=0.01736506451;
 | 
			
		||||
b1=0.24998368310;
 | 
			
		||||
b2=0.09200180037;
 | 
			
		||||
b3=0.04069697526;
 | 
			
		||||
b4=0.00526449639;
 | 
			
		||||
ee1=1+m1.*(a1+m1.*(a2+m1.*(a3+m1*a4)));
 | 
			
		||||
%ee2=m1.*(b1+m1.*(b2+m1.*(b3+m1.*b4))).*log(1./m1);
 | 
			
		||||
ee2=m1.*(b1+m1.*(b2+m1.*(b3+m1.*b4))).*(-1*log(m1));
 | 
			
		||||
ellec=ee1+ee2;
 | 
			
		||||
							
								
								
									
										18
									
								
								FluxCalculation/ellkVec.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								FluxCalculation/ellkVec.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
function ellk=ellkVec(k)
 | 
			
		||||
% Computes polynomial approximation for the complete elliptic
 | 
			
		||||
% integral of the first kind (Hasting's approximation):
 | 
			
		||||
m1=1-k.*k;
 | 
			
		||||
m1(m1<eps)=eps;
 | 
			
		||||
a0=1.38629436112;
 | 
			
		||||
a1=0.09666344259;
 | 
			
		||||
a2=0.03590092383;
 | 
			
		||||
a3=0.03742563713;
 | 
			
		||||
a4=0.01451196212;
 | 
			
		||||
b0=0.5;
 | 
			
		||||
b1=0.12498593597;
 | 
			
		||||
b2=0.06880248576;
 | 
			
		||||
b3=0.03328355346;
 | 
			
		||||
b4=0.00441787012;
 | 
			
		||||
ek1=a0+m1.*(a1+m1.*(a2+m1.*(a3+m1*a4)));
 | 
			
		||||
ek2=(b0+m1.*(b1+m1.*(b2+m1.*(b3+m1*b4)))).*log(m1);
 | 
			
		||||
ellk=ek1-ek2;
 | 
			
		||||
							
								
								
									
										438
									
								
								FluxCalculation/occultquadVec.m
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										438
									
								
								FluxCalculation/occultquadVec.m
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,438 @@
 | 
			
		|||
function [muo1, mu0]=occultquadVec(p,z,u1,u2,ToPlot,varargin)
 | 
			
		||||
% Aviv Comments
 | 
			
		||||
% ==================================================
 | 
			
		||||
% v.0.32 - vectorize rc,rj,rf
 | 
			
		||||
%        - Allow correcting behaviour near z==p, z=1-p
 | 
			
		||||
%        - Added optinal parameter TolFactor for tolerances control
 | 
			
		||||
%        - Removed all "CloseToOne" and added ToSmooth Parameter
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%% - Mandel Agol comments
 | 
			
		||||
%
 | 
			
		||||
%   This routine computes the lightcurve for occultation
 | 
			
		||||
%   of a quadratically limb-darkened source without microlensing.
 | 
			
		||||
%   Please cite Mandel & Agol (2002) if you make use of this routine
 | 
			
		||||
%   in your research.  Please report errors or bugs to agol@tapir.caltech.edu
 | 
			
		||||
%       implicit none
 | 
			
		||||
%       integer i,nz
 | 
			
		||||
%       double precision z0(nz),u1,u2,p,muo1(nz),mu0(nz),
 | 
			
		||||
%      &       mu(nz),lambdad(nz),etad(nz),lambdae(nz),lam,
 | 
			
		||||
%      &       pi,x1,x2,x3,z,omega,kap0,kap1,q,Kk,Ek,Pk,n,ellec,ellk,rj
 | 
			
		||||
% 
 | 
			
		||||
%  Input:
 | 
			
		||||
% 
 | 
			
		||||
%  rs   radius of the source (set to unity)
 | 
			
		||||
%  z    impact parameter in units of rs
 | 
			
		||||
%  p    occulting star radius in units of rs
 | 
			
		||||
%  u1   linear    limb-darkening coefficient (gamma_1 in paper)
 | 
			
		||||
%  u2   quadratic limb-darkening coefficient (gamma_2 in paper)
 | 
			
		||||
% 
 | 
			
		||||
%  Optional input:
 | 
			
		||||
%
 | 
			
		||||
%  ToPlot:   Graphical output [default=false];
 | 
			
		||||
%  Tols:     A factor controling the three "ERRTOL" parameters for the three helper functions. If given, all three default ERRTOLs wil be scaled by it: [Default =1 ]
 | 
			
		||||
%  ToSmooth: if true, smooths the original Mandel-Agol model around z=p and around abs(z-p)=1 to produce better-behaving derivative. The value themselves are virtually unchanged. [default=true]
 | 
			
		||||
%
 | 
			
		||||
%  Output:
 | 
			
		||||
% 
 | 
			
		||||
%  muo1 fraction of flux at each z for a limb-darkened source
 | 
			
		||||
%  mu0  fraction of flux at each z for a uniform source
 | 
			
		||||
% 
 | 
			
		||||
%  Limb darkening has the form:
 | 
			
		||||
%   I(r)=[1-u1*(1-sqrt(1-(r/rs)^2))-u2*(1-sqrt(1-(r/rs)^2))^2]/(1-u1/3-u2/6)/pi
 | 
			
		||||
%  
 | 
			
		||||
%  To use this routine
 | 
			
		||||
% 
 | 
			
		||||
%  Now, compute pure occultation curve:
 | 
			
		||||
 | 
			
		||||
% Setting the extra inputs for the case in which only p,z,u1,u2 are given
 | 
			
		||||
if nargin<5
 | 
			
		||||
    ToPlot=false;
 | 
			
		||||
end;
 | 
			
		||||
TolFactor=1;
 | 
			
		||||
ToSmooth=true;
 | 
			
		||||
for i=1:2:numel(varargin)
 | 
			
		||||
    switch lower(varargin{i})
 | 
			
		||||
        case 'tolfactor'
 | 
			
		||||
            TolFactor=varargin{i+1};
 | 
			
		||||
        case 'tosmooth'
 | 
			
		||||
            ToSmooth=varargin{i+1};
 | 
			
		||||
        otherwise
 | 
			
		||||
            fprintf('WARNING: parameter %s is unknown, and so ignored.\n',varargin{i});
 | 
			
		||||
    end;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
%make z a column vector
 | 
			
		||||
if size(z,2)>size(z,1) % z is a column vector
 | 
			
		||||
    z=z.';
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
%set zeros to lambdad, lambda3, 3tad, kap0, kap1
 | 
			
		||||
lambdad=zeros(size(z));
 | 
			
		||||
lambdae=lambdad;
 | 
			
		||||
etad=lambdad;
 | 
			
		||||
kap0=lambdad;
 | 
			
		||||
kap1=lambdad;
 | 
			
		||||
 | 
			
		||||
%if p is close to 0.5, make it 0.5
 | 
			
		||||
if abs(p-0.5)<1e-3
 | 
			
		||||
	p=0.5;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
omega=1-u1/3-u2/6;
 | 
			
		||||
x1=(p-z).^2;
 | 
			
		||||
x2=(p+z).^2;
 | 
			
		||||
x3=p.^2-z.^2;
 | 
			
		||||
 | 
			
		||||
% the source is unocculted:
 | 
			
		||||
% Table 3, I.
 | 
			
		||||
i=z>=1+p;
 | 
			
		||||
if any(i)
 | 
			
		||||
    lambdad(i)=0;
 | 
			
		||||
    etad(i)=0;
 | 
			
		||||
    lambdae(i)=0;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
% the source is partly occulted and the occulting object crosses the limb:
 | 
			
		||||
% Equation (26):
 | 
			
		||||
i=z>=abs(1-p) & z<=1+p;
 | 
			
		||||
if any(i)
 | 
			
		||||
    kap1(i)=acos(min((1-p^2+z(i).^2)/2./z(i),1));
 | 
			
		||||
    kap0(i)=acos(min((p*p+z(i).^2-1)/2/p./z(i),1));
 | 
			
		||||
    lambdae(i)=p^2*kap0(i)+kap1(i);
 | 
			
		||||
    lambdae(i)=(lambdae(i)-0.5*sqrt(max(4*z(i).^2-(1+z(i).^2-p^2).^2,0)))/pi;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
% the occulting object transits the source star (but doesn't
 | 
			
		||||
% completely cover it):
 | 
			
		||||
i=z<=1-p;
 | 
			
		||||
if any(i)
 | 
			
		||||
    lambdae(i)=p^2;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
% the edge of the occulting star lies at the origin- special 
 | 
			
		||||
% expressions in this case:
 | 
			
		||||
 | 
			
		||||
i=find(abs(z-p)<1e-4*(z+p));
 | 
			
		||||
if ~isempty(i)
 | 
			
		||||
% Table 3, Case V.:
 | 
			
		||||
    j=z(i)>=0.5;
 | 
			
		||||
    if any(j)
 | 
			
		||||
        %lam=0.5*pi;
 | 
			
		||||
        q=0.5/p;
 | 
			
		||||
        Kk=ellkVec(q);
 | 
			
		||||
        Ek=ellecVec(q);
 | 
			
		||||
% Equation 34: lambda_3
 | 
			
		||||
        lambdad(i(j))=1/3+16*p/9/pi*(2*p^2-1)*Ek-(32*p^4-20*p^2+3)/9/pi/p*Kk;
 | 
			
		||||
% Equation 34: eta_1
 | 
			
		||||
        etad(i(j))=1/2/pi*(kap1(i(j))+p^2*(p^2+2*z(i(j))).*kap0(i(j))-(1+5*p^2+z(i(j)).^2)./4.*sqrt((1-x1(i(j))).*(x2(i(j))-1)));
 | 
			
		||||
        if p==0.5
 | 
			
		||||
% Case VIII: p=1/2, z=1/2
 | 
			
		||||
            lambdad(i(j))=1/3-4/pi/9;
 | 
			
		||||
            etad(i(j))=3/32;
 | 
			
		||||
        end;
 | 
			
		||||
    end;
 | 
			
		||||
    j=~j;
 | 
			
		||||
    if any(j)
 | 
			
		||||
% Table 3, Case VI.:
 | 
			
		||||
        %lam=0.5*pi;
 | 
			
		||||
        q=2*p;
 | 
			
		||||
        Kk=ellkVec(q);
 | 
			
		||||
        Ek=ellecVec(q);
 | 
			
		||||
% Equation 34: lambda_4
 | 
			
		||||
        lambdad(i(j))=1/3+2/9/pi*(4*(2*p^2-1)*Ek+(1-4*p^2)*Kk);
 | 
			
		||||
% Equation 34: eta_2
 | 
			
		||||
        etad(i(j))=p^2/2*(p^2+2*z(i(j)).^2);
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
% the occulting star partly occults the source and crosses the limb:
 | 
			
		||||
% Table 3, Case III:
 | 
			
		||||
i=find(z>=0.5+abs(p-0.5) & z<1+p | (p>0.5 & z>abs(1-p)*(1+10*eps(1)) & z<p));
 | 
			
		||||
if any(i)
 | 
			
		||||
    %lam=0.5*pi;
 | 
			
		||||
    q=sqrt((1-(p-z(i)).^2)/4./z(i)/p);
 | 
			
		||||
    Kk=ellkVec(q);
 | 
			
		||||
    Ek=ellecVec(q);
 | 
			
		||||
    n=1./x1(i)-1;
 | 
			
		||||
    Pk=Kk-n/3.*rj(0,1-q.^2,1,1+n,TolFactor);
 | 
			
		||||
% Equation 34, lambda_1:
 | 
			
		||||
    lambdad(i)=1/9/pi./sqrt(p*z(i)).*(((1-x2(i)).*(2*x2(i)+x1(i)-3)-3*x3(i).*(x2(i)-2)).*Kk+4*p*z(i).*(z(i).^2+7*p^2-4).*Ek-3*x3(i)./x1(i).*Pk);
 | 
			
		||||
    j=z(i)<p;
 | 
			
		||||
    if any(j)
 | 
			
		||||
        lambdad(i(j))=lambdad(i(j))+2/3;
 | 
			
		||||
    end;
 | 
			
		||||
% Equation 34, eta_1:
 | 
			
		||||
    etad(i)=1/2/pi*(kap1(i)+p^2*(p^2+2*z(i).^2).*kap0(i)-(1+5*p^2+z(i).^2)/4.*sqrt((1-x1(i)).*(x2(i)-1)));
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
% the occulting star transits the source:
 | 
			
		||||
% Table 3, Case IV.:
 | 
			
		||||
%i=find(p<=1 & z<=(1-p)*1.0001);
 | 
			
		||||
i=find(p<=1 & z<=(1-p)*1.0001 & abs(z-p)>10*eps);
 | 
			
		||||
if any(i)
 | 
			
		||||
    %lam=0.5*pi;
 | 
			
		||||
    q=sqrt((x2(i)-x1(i))./(1-x1(i)));
 | 
			
		||||
    Kk=ellkVec(q);
 | 
			
		||||
    Ek=ellecVec(q);
 | 
			
		||||
    n=x2(i)./x1(i)-1;
 | 
			
		||||
    Pk=Kk-n/3.*rj(0,1-q.^2,1,1+n,TolFactor);
 | 
			
		||||
    % Equation 34, lambda_2:
 | 
			
		||||
    lambdad(i)=2/9/pi./sqrt(1-x1(i)).*((1-5*z(i).^2+p^2+x3(i).^2).*Kk+(1-x1(i)).*(z(i).^2+7*p^2-4).*Ek-3*x3(i)./x1(i).*Pk);
 | 
			
		||||
    j=z(i)<p;
 | 
			
		||||
    if any(j)
 | 
			
		||||
        lambdad(i(j))=lambdad(i(j))+2/3;
 | 
			
		||||
    end
 | 
			
		||||
    j=abs(p+z(i)-1)<=1e-8;
 | 
			
		||||
    if any(j)
 | 
			
		||||
        lambdad(i(j))=2/3/pi*acos(1-2*p)-4/9/pi*sqrt(p*(1-p))*(3+2*p-8*p*p);
 | 
			
		||||
    end
 | 
			
		||||
    % Equation 34, eta_2:
 | 
			
		||||
    etad(i)=p^2/2.*(p^2+2*z(i).^2);
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
% Now, using equation (33):
 | 
			
		||||
muo1=1-((1-u1-2*u2)*lambdae+(u1+2*u2)*lambdad+u2.*etad)/omega;
 | 
			
		||||
% Equation 25:
 | 
			
		||||
mu0=1-lambdae;
 | 
			
		||||
 | 
			
		||||
% the  source is completely occulted:
 | 
			
		||||
% Table 3, II.
 | 
			
		||||
if p>=1
 | 
			
		||||
  i=z<=p-1;
 | 
			
		||||
  if any(i)
 | 
			
		||||
      %lambdad(i)=1;
 | 
			
		||||
      %etad(i)=1;
 | 
			
		||||
      %lambdae(i)=1;
 | 
			
		||||
      muo1(i)=0;
 | 
			
		||||
      mu0(i)=0;
 | 
			
		||||
  end;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
if ToSmooth>0
 | 
			
		||||
    deg=2;
 | 
			
		||||
    CorrectionRange=2e-4;
 | 
			
		||||
    FitRange=5*CorrectionRange;
 | 
			
		||||
%     i=find(z>=1-p-CorrectionRange & z<=1-p+CorrectionRange); % inner than II/III contact
 | 
			
		||||
%     if ~isempty(i)
 | 
			
		||||
%         if p<1
 | 
			
		||||
%             tmpz=1-p+[linspace(-FitRange,-CorrectionRange,deg*10).'; linspace(CorrectionRange,FitRange,deg*10).'];
 | 
			
		||||
%         else
 | 
			
		||||
%             tmpz=p-1+[linspace(-FitRange,-CorrectionRange,deg*10).'; linspace(CorrectionRange,FitRange,deg*10).'];
 | 
			
		||||
%         end
 | 
			
		||||
%         tmpz(tmpz<0)=[];
 | 
			
		||||
%         tmp_muo1=occultquadVec(p,tmpz,u1,u2,0,'ToSmooth',false);
 | 
			
		||||
%         if ~isempty(tmpz)
 | 
			
		||||
%             pol=IterativePolyfit(tmpz,tmp_muo1,deg,3);
 | 
			
		||||
%             muo1(i)=polyval(pol,z(i));
 | 
			
		||||
%         end
 | 
			
		||||
%     end;
 | 
			
		||||
 | 
			
		||||
    % inner than II/III contact
 | 
			
		||||
    i=z>=1-p-CorrectionRange & z<=1-p; 
 | 
			
		||||
    if ~isempty(i)
 | 
			
		||||
        %if p<1
 | 
			
		||||
        %    tmpz=1-p+linspace(-FitRange,-CorrectionRange,deg*10).';
 | 
			
		||||
        %else
 | 
			
		||||
        %    tmpz=p-1+linspace(-FitRange,-CorrectionRange,deg*10).';
 | 
			
		||||
        %end
 | 
			
		||||
        tmpz=abs(1-p)+linspace(-FitRange,-CorrectionRange,deg*10).';
 | 
			
		||||
        tmpz(tmpz<0)=[];
 | 
			
		||||
        tmp_muo1=occultquadVec(p,tmpz,u1,u2,0,'ToSmooth',false);
 | 
			
		||||
        if ~isempty(tmpz)
 | 
			
		||||
            pol=polyfit(tmpz,tmp_muo1,deg);
 | 
			
		||||
            muo1(i)=polyval(pol,z(i));
 | 
			
		||||
        end
 | 
			
		||||
    end;
 | 
			
		||||
    
 | 
			
		||||
    % outer than II/III contact
 | 
			
		||||
    j=z>=1-p & z<=1-p+CorrectionRange; 
 | 
			
		||||
    if ~isempty(j)
 | 
			
		||||
        %if p<1
 | 
			
		||||
        %    tmpz=1-p+linspace(CorrectionRange,FitRange,deg*10).';
 | 
			
		||||
        %else
 | 
			
		||||
        %    tmpz=p-1+linspace(CorrectionRange,FitRange,deg*10).';
 | 
			
		||||
        %end
 | 
			
		||||
        tmpz=abs(1-p)+linspace(CorrectionRange,FitRange,deg*10).';
 | 
			
		||||
        tmpz(tmpz<0)=[];
 | 
			
		||||
        tmp_muo1=occultquadVec(p,tmpz,u1,u2,0,'ToSmooth',false);
 | 
			
		||||
        if ~isempty(tmpz)
 | 
			
		||||
            pol=polyfit(tmpz,tmp_muo1,deg);
 | 
			
		||||
            muo1(j)=polyval(pol,z(j));
 | 
			
		||||
        end
 | 
			
		||||
    end;
 | 
			
		||||
 | 
			
		||||
    % close to z=p
 | 
			
		||||
    if p>0.5
 | 
			
		||||
        deg=3;
 | 
			
		||||
    end;
 | 
			
		||||
    CorrectionRange=1e-2;
 | 
			
		||||
    FitRange=5*CorrectionRange;
 | 
			
		||||
    if p<0.5  
 | 
			
		||||
        i=find(z-p>-CorrectionRange & z-p<min(CorrectionRange,1-2*p)); % near z~p
 | 
			
		||||
    else
 | 
			
		||||
        i=find(z-p>max(-CorrectionRange,1-2*p) & z-p<CorrectionRange); % near z~p
 | 
			
		||||
    end
 | 
			
		||||
    if ~isempty(i)
 | 
			
		||||
        if p<0.5
 | 
			
		||||
            tmpz=p+linspace(-FitRange,min(FitRange,1-2*p),deg*10).';
 | 
			
		||||
        else
 | 
			
		||||
            tmpz=p+linspace(max(-FitRange,1-2*p),FitRange,deg*10).';
 | 
			
		||||
        end
 | 
			
		||||
        tmpz(abs(tmpz-p)<CorrectionRange | tmpz<0)=[];
 | 
			
		||||
        tmp_muo1=occultquadVec(p,tmpz,u1,u2,0,'ToSmooth',false);
 | 
			
		||||
        if ~isempty(tmpz)
 | 
			
		||||
            pol=polyfit(tmpz,tmp_muo1,deg);
 | 
			
		||||
            muo1(i)=polyval(pol,z(i));
 | 
			
		||||
        end;
 | 
			
		||||
    end;
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if ToPlot
 | 
			
		||||
    plot([flipud(-z); z],[flipud(mu0); mu0],'.',[flipud(-z); z],[flipud(muo1); muo1],'.r');
 | 
			
		||||
    a=axis;
 | 
			
		||||
    axis([a(1) a(2) a(3) 1+(1-a(3))*0.1]);
 | 
			
		||||
    title({'Uniform source (blue) and quadratic model for the limb darkening (red)';sprintf('p=%g, u1=%g, u2=%g',p,u1,u2)});
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function rc=rc(x,y,ERRTOL)
 | 
			
		||||
xt=zeros(size(x)); yt=xt;
 | 
			
		||||
w=xt; s=xt;
 | 
			
		||||
alamb=xt; ave=xt;
 | 
			
		||||
 | 
			
		||||
ERRTOL=.04*ERRTOL;
 | 
			
		||||
THIRD=1/3;
 | 
			
		||||
C1=.3;
 | 
			
		||||
C2=1/7;
 | 
			
		||||
C3=.375;
 | 
			
		||||
C4=9/22;
 | 
			
		||||
i=y>0;
 | 
			
		||||
if any(i)
 | 
			
		||||
    xt(i)=x(i);
 | 
			
		||||
    yt(i)=y(i);
 | 
			
		||||
    w(i)=1;
 | 
			
		||||
end;
 | 
			
		||||
i=~i;
 | 
			
		||||
if any(i)
 | 
			
		||||
    xt(i)=x(i)-y(i);
 | 
			
		||||
    yt(i)=-y(i);
 | 
			
		||||
    w(i)=sqrt(x(i))./sqrt(xt(i));
 | 
			
		||||
end
 | 
			
		||||
i=true(size(x));
 | 
			
		||||
while any(i)
 | 
			
		||||
    alamb(i)=2*sqrt(xt(i)).*sqrt(yt(i))+yt(i);
 | 
			
		||||
    xt(i)=.25*(xt(i)+alamb(i));
 | 
			
		||||
    yt(i)=.25*(yt(i)+alamb(i));
 | 
			
		||||
    ave(i)=THIRD*(xt(i)+yt(i)+yt(i));
 | 
			
		||||
    s(i)=(yt(i)-ave(i))./ave(i);
 | 
			
		||||
    i(i)=abs(s(i))>ERRTOL;
 | 
			
		||||
end;
 | 
			
		||||
rc=w.*(1+s.^2.*(C1+s.*(C2+s.*(C3+s.*C4))))./sqrt(ave);
 | 
			
		||||
%  (C) Copr. 1986-92 Numerical Recipes Software
 | 
			
		||||
 | 
			
		||||
function rj=rj(x,y,z,p,ERRTOL)
 | 
			
		||||
% built for x,z scalars and y,p vectors
 | 
			
		||||
fac=ones(size(y));
 | 
			
		||||
x=x*fac; z=z*fac; rj=0*fac;
 | 
			
		||||
xt=rj; yt=rj; zt=rj; pt=rj; a=rj; b=rj; rho=rj; tau=rj; rcx=rj;
 | 
			
		||||
sqrtx=rj; sqrty=rj; sqrtz=rj; alamb=rj; alpha=rj; beta=rj; Sum=rj; ave=rj;
 | 
			
		||||
ave4=ave*ones(1,4);
 | 
			
		||||
 | 
			
		||||
ERRTOL=.05*ERRTOL;
 | 
			
		||||
C1=3/14;
 | 
			
		||||
C2=1/3;
 | 
			
		||||
C3=3/22;
 | 
			
		||||
C4=3/26;
 | 
			
		||||
C5=.75*C3;
 | 
			
		||||
C6=1.5*C4;
 | 
			
		||||
C7=.5*C2;
 | 
			
		||||
C8=C3+C3;
 | 
			
		||||
i=p>0;
 | 
			
		||||
if any(i)
 | 
			
		||||
    xt(i)=x(i);
 | 
			
		||||
    yt(i)=y(i);
 | 
			
		||||
    zt(i)=z(i);
 | 
			
		||||
    pt(i)=p(i);
 | 
			
		||||
end;
 | 
			
		||||
i=~i;
 | 
			
		||||
if any(i)
 | 
			
		||||
    xt(i)=min([x(i),y(i),z(i)],[],2);
 | 
			
		||||
    zt(i)=max([x(i),y(i),z(i)],[],2);
 | 
			
		||||
    yt(i)=x(i)+y(i)+z(i)-xt(i)-zt(i);
 | 
			
		||||
    a(i)=1./(yt(i)-p(i));
 | 
			
		||||
    b(i)=a(i).*(zt(i)-yt(i)).*(yt(i)-xt(i));
 | 
			
		||||
    pt(i)=yt(i)+b(i);
 | 
			
		||||
    rho(i)=xt(i).*zt(i)./yt(i);
 | 
			
		||||
    tau(i)=p(i).*pt(i)./yt(i);
 | 
			
		||||
    rcx(i)=rc(rho(i),tau(i),ERRTOL);
 | 
			
		||||
end
 | 
			
		||||
%continue                      % ************** 1 ***************
 | 
			
		||||
i=true(size(y));
 | 
			
		||||
while any(i)
 | 
			
		||||
    sqrtx(i)=sqrt(xt(i));
 | 
			
		||||
    sqrty(i)=sqrt(yt(i));
 | 
			
		||||
    sqrtz(i)=sqrt(zt(i));
 | 
			
		||||
    alamb(i)=sqrtx(i).*(sqrty(i)+sqrtz(i))+sqrty(i).*sqrtz(i);
 | 
			
		||||
    alpha(i)=(pt(i).*(sqrtx(i)+sqrty(i)+sqrtz(i))+sqrtx(i).*sqrty(i).*sqrtz(i)).^2;
 | 
			
		||||
    beta(i)=pt(i).*(pt(i)+alamb(i)).^2;
 | 
			
		||||
    Sum(i)=Sum(i)+fac(i).*rc(alpha(i),beta(i),ERRTOL);
 | 
			
		||||
    fac(i)=.25*fac(i);
 | 
			
		||||
    xt(i)=.25*(xt(i)+alamb(i));
 | 
			
		||||
    yt(i)=.25*(yt(i)+alamb(i));
 | 
			
		||||
    zt(i)=.25*(zt(i)+alamb(i));
 | 
			
		||||
    pt(i)=.25*(pt(i)+alamb(i));
 | 
			
		||||
    ave(i)=.2*(xt(i)+yt(i)+zt(i)+pt(i)+pt(i));
 | 
			
		||||
    ave4(i,:)=ave(i)*ones(1,4);
 | 
			
		||||
    %delx=(ave-xt)/ave;
 | 
			
		||||
    %dely=(ave-yt)/ave;
 | 
			
		||||
    %delz=(ave-zt)/ave;
 | 
			
		||||
    %delp=(ave-pt)/ave;
 | 
			
		||||
    del4=(ave4-[xt yt zt pt])./ave4;
 | 
			
		||||
    i=max(abs(del4),[],2)>ERRTOL;
 | 
			
		||||
end;
 | 
			
		||||
ea=del4(:,1).*(del4(:,2)+del4(:,3))+del4(:,2).*del4(:,3);
 | 
			
		||||
eb=del4(:,1).*del4(:,2).*del4(:,3);
 | 
			
		||||
ec=del4(:,4).^2;
 | 
			
		||||
ed=ea-3*ec;
 | 
			
		||||
ee=eb+2*del4(:,4).*(ea-ec);
 | 
			
		||||
rj=3*Sum+fac.*(1+ed.*(-C1+C5*ed-C6*ee)+eb.*(C7+del4(:,4).*(-C8+del4(:,4).*C4))+del4(:,4).*ea.*(C2-del4(:,4)*C3)-C2*del4(:,4).*ec)./(ave.*sqrt(ave));
 | 
			
		||||
i=p<=0;
 | 
			
		||||
if any(i)
 | 
			
		||||
    rj(i)=a.*(b.*rj(i)+3*(rcx(i)-rf(xt(i),yt(i),zt(i),ERRTOL)));
 | 
			
		||||
end;
 | 
			
		||||
%  (C) Copr. 1986-92 Numerical Recipes Software
 | 
			
		||||
 | 
			
		||||
function rf=rf(x,y,z,ERRTOL)
 | 
			
		||||
xyz=[x y z];
 | 
			
		||||
sqrtxyz=zeros(size(xyz));
 | 
			
		||||
alamb=sqrtxyz;
 | 
			
		||||
ave=sqrtxyz;
 | 
			
		||||
ave3=sqrtxyz;
 | 
			
		||||
del3=sqrtxyz;
 | 
			
		||||
 | 
			
		||||
ERRTOL=.08*ERRTOL;
 | 
			
		||||
THIRD=1/3;
 | 
			
		||||
C1=1/24;
 | 
			
		||||
C2=.1;
 | 
			
		||||
C3=3/44;
 | 
			
		||||
C4=1/14;
 | 
			
		||||
xyzt=xyz;
 | 
			
		||||
%continue                  % **************** 1 *****************
 | 
			
		||||
i=true(size(x));
 | 
			
		||||
while any(i)
 | 
			
		||||
    sqrtxyz(i,:)=sqrt(xyz(i,:));
 | 
			
		||||
   %alamb(i,:)=sqrtxyz(i,1).*(sqrtxyz(i,2)+sqrtxy(i,3))+sqrtxyz(i,2).*sqrtxyz(i,3);
 | 
			
		||||
    alamb(i,:)=sqrtxyz(i,1).*(sqrtxyz(i,2)+sqrtxyz(i,3))+sqrtxyz(i,2).*sqrtxyz(i,3);
 | 
			
		||||
    xyzt(i,:)=.25*(xyzt(i,:)+alamb(i,:)*ones(1,3));
 | 
			
		||||
    ave(i)=THIRD*(sum(xyzt(i,:),2));
 | 
			
		||||
    ave3(i,:)=ave(i)*ones(1,3);
 | 
			
		||||
    del3(i,:)=(ave3(i,:)-xyzt(i,:))./ave3(i,:);
 | 
			
		||||
    i(i)=max(abs(del3(i,:)),[],2)>ERRTOL;
 | 
			
		||||
end;
 | 
			
		||||
e2=del3(:,1).*del3(:,2)-del3(:,3)^2;
 | 
			
		||||
e3=del3(:,1).*del3(:,2).*del3(:,3);
 | 
			
		||||
rf=(1+(C1*e2-C2-C3*e3).*e2+C4*e3)./sqrt(ave);
 | 
			
		||||
%  (C) Copr. 1986-92 Numerical Recipes Software 0NL&WR2.
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								LaplaceCoeffs.mat
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								LaplaceCoeffs.mat
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										287
									
								
								anac_2_2p.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										287
									
								
								anac_2_2p.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,287 @@
 | 
			
		|||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
"""
 | 
			
		||||
abgewandelt von:
 | 
			
		||||
Created on Fri Dec  3 08:49:07 2021
 | 
			
		||||
 | 
			
		||||
@author: dreizler
 | 
			
		||||
"""
 | 
			
		||||
import pdb
 | 
			
		||||
 | 
			
		||||
from scipy.stats import gamma,norm,beta,truncnorm
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
from types import SimpleNamespace
 | 
			
		||||
 | 
			
		||||
import dynesty
 | 
			
		||||
from dynesty.utils import resample_equal
 | 
			
		||||
 | 
			
		||||
# system functions that are always useful to have
 | 
			
		||||
import time, sys, os
 | 
			
		||||
 | 
			
		||||
# basic numeric setup
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
from dynesty import plotting as dyplot
 | 
			
		||||
 | 
			
		||||
from oct2py import Oct2Py
 | 
			
		||||
 | 
			
		||||
from multiprocessing import Pool
 | 
			
		||||
 | 
			
		||||
# plotting
 | 
			
		||||
import matplotlib
 | 
			
		||||
from matplotlib import pyplot as plt
 | 
			
		||||
# inline plotting
 | 
			
		||||
#%matplotlib inline
 | 
			
		||||
 | 
			
		||||
import csv
 | 
			
		||||
import json
 | 
			
		||||
import pickle
 | 
			
		||||
 | 
			
		||||
def parse_parameters(settings):
 | 
			
		||||
    p = []
 | 
			
		||||
    fix = {}
 | 
			
		||||
    for planet in settings["planets"]:
 | 
			
		||||
        for key, value in planet.items():
 | 
			
		||||
            fix[key] = [(None, None)] * len(settings["planets"])
 | 
			
		||||
 | 
			
		||||
    i = 0
 | 
			
		||||
    for planet in settings["planets"]:
 | 
			
		||||
        for key, value in planet.items():
 | 
			
		||||
            if value["type"] != "fixed":
 | 
			
		||||
                p += [(i, key, value["type"], value["values"])]
 | 
			
		||||
            else:
 | 
			
		||||
                fix[key][i] = value["values"]
 | 
			
		||||
        i += 1
 | 
			
		||||
 | 
			
		||||
    for key, value in settings["parameters"].items():
 | 
			
		||||
        if value["type"] != "fixed":
 | 
			
		||||
            p += [(-1, key, value["type"], value["values"])]
 | 
			
		||||
        else:
 | 
			
		||||
            fix[key] = value["values"]
 | 
			
		||||
 | 
			
		||||
    return p, fix
 | 
			
		||||
 | 
			
		||||
def parse_settings():
 | 
			
		||||
    settings = json.load(open("parameter.json"))
 | 
			
		||||
 | 
			
		||||
    p, fix = parse_parameters(settings)
 | 
			
		||||
 | 
			
		||||
    return p, fix, settings["nkern"], settings["nlivepoints"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def generate_mockdata():
 | 
			
		||||
    np.random.seed(56101)
 | 
			
		||||
 | 
			
		||||
    P_true=[12.3456, 29.3]
 | 
			
		||||
    Tmid0_true=[9.8765432, 15.4029]
 | 
			
		||||
    ror_true=[0.021, 0.027]
 | 
			
		||||
    aor_true=30
 | 
			
		||||
    mu_true=[1.24e-5, 3e-5]
 | 
			
		||||
    ex0_true=[0.01234, 0.00998]
 | 
			
		||||
    ey0_true=[0.02345, 0.0189]
 | 
			
		||||
    I0_true=[0.01745329, 0.0203]
 | 
			
		||||
    Omega0_true=[0.4014257, 0.369]
 | 
			
		||||
    sig_true = np.log(0.000084) 
 | 
			
		||||
 | 
			
		||||
    #t_mock = np.linspace(0,100,500)
 | 
			
		||||
    u1=0.5;
 | 
			
		||||
    u2=0.3;
 | 
			
		||||
    t=np.linspace(0,100,2) #0:0.002:100;
 | 
			
		||||
    tRV=np.linspace(0,100,1000)
 | 
			
		||||
 | 
			
		||||
    init_octpy()
 | 
			
		||||
    LC,RV_o_r,Y_o_r,Z_o_r,O = octave.feval("AnalyticLC",P_true, Tmid0_true, ror_true, aor_true, mu_true, ex0_true, ey0_true, I0_true, Omega0_true, t, u1, u2,'tRV',tRV, nout=5)
 | 
			
		||||
 | 
			
		||||
    #y_old = octave.AnalyticLC(P_true, Tmid0_true, ror_true, aor_true, mu_true, ex0_true, ey0_true, I0_true, Omega0_true, t, u1, u2)
 | 
			
		||||
    y_true2 = [] 
 | 
			
		||||
    for i in RV_o_r:
 | 
			
		||||
        y_true2.append(i[0])
 | 
			
		||||
    y_true2 = np.array(y_true2)
 | 
			
		||||
    y_true = y_true2[(np.isfinite(y_true2))]
 | 
			
		||||
 | 
			
		||||
    y = y_true + 0.0001*np.random.randn(len(y_true)) #0.0001
 | 
			
		||||
    yerr = 0.00005 + np.zeros(len(y)) #0.00005
 | 
			
		||||
 | 
			
		||||
    # plot results
 | 
			
		||||
    plt.figure(figsize=(10, 5))
 | 
			
		||||
    plt.errorbar(tRV, y, yerr=yerr, fmt='ko', ecolor='red')
 | 
			
		||||
    plt.plot(tRV, y_true, color='blue', lw=3)
 | 
			
		||||
    plt.xlabel(r'$t$')
 | 
			
		||||
    plt.ylabel(r'$y_true$')
 | 
			
		||||
    plt.tight_layout()
 | 
			
		||||
    plt.show()
 | 
			
		||||
    plt.close()
 | 
			
		||||
 | 
			
		||||
    return y, yerr, y_true
 | 
			
		||||
 | 
			
		||||
def calculate(nkern, nlivepoints, parameters, fixed_parameters):
 | 
			
		||||
    ndim = len(parameters)
 | 
			
		||||
    p = Pool(nkern, init, [parameters, fixed_parameters])
 | 
			
		||||
 | 
			
		||||
    #P, Tmid0, ror, aor, mu, ex0, ey0, I0, Omega0, sig
 | 
			
		||||
    dsampler = dynesty.NestedSampler(loglike, prior_transform, ndim=ndim, periodic=None,
 | 
			
		||||
            bound='multi', sample='auto',nlive=nlivepoints,pool=p, queue_size=nkern) #n*n/2 live points mind.
 | 
			
		||||
    dsampler.run_nested(dlogz=0.001)
 | 
			
		||||
    dres = dsampler.results
 | 
			
		||||
    with open('data_4dim.pickle', 'wb') as f:
 | 
			
		||||
        pickle.dump(dres, f, pickle.HIGHEST_PROTOCOL)
 | 
			
		||||
 | 
			
		||||
    return dres
 | 
			
		||||
 | 
			
		||||
def create_plot(dres):
 | 
			
		||||
    P_true=[12.3456, 29.3]
 | 
			
		||||
    Tmid0_true=[9.8765432, 15.4029]
 | 
			
		||||
    ror_true=[0.021, 0.027]
 | 
			
		||||
    aor_true=30
 | 
			
		||||
    mu_true=[1.24e-5, 3e-5]
 | 
			
		||||
    ex0_true=[0.01234, 0.00998]
 | 
			
		||||
    ey0_true=[0.02345, 0.0189]
 | 
			
		||||
    I0_true=[0.01745329, 0.0203]
 | 
			
		||||
    Omega0_true=[0.4014257, 0.369]
 | 
			
		||||
    sig_true = np.log(0.000084) 
 | 
			
		||||
 | 
			
		||||
    truths = [P_true[0], P_true[1], sig_true]
 | 
			
		||||
    labels = [r'P $d$',r'P $d$', r'T $d$',r'T $d$',  r'ex0', r'ex0', r'ey0', r'ey0',r'$\sigma \log(m/s)$']
 | 
			
		||||
    fig, axes = dyplot.traceplot(dres, truths=truths, truth_color='black', labels=labels, connect=True,
 | 
			
		||||
            fig=plt.subplots(ndim, 2, constrained_layout=True))
 | 
			
		||||
    fig.tight_layout()
 | 
			
		||||
    plt.savefig("tmp_2p/plot_test1.png")
 | 
			
		||||
    fig, axes = dyplot.cornerplot(dres, truths=truths, show_titles=True, 
 | 
			
		||||
            title_kwargs={'y': 1.04}, labels=labels,
 | 
			
		||||
            fig=plt.subplots(ndim, ndim,constrained_layout=True))
 | 
			
		||||
 | 
			
		||||
    fig.tight_layout()
 | 
			
		||||
    plt.savefig("tmp_2p/plot_test2.png")
 | 
			
		||||
    #lt.close()
 | 
			
		||||
 | 
			
		||||
def init(parameters, fixed_parameters):
 | 
			
		||||
    global p 
 | 
			
		||||
    p = parameters
 | 
			
		||||
    global fix
 | 
			
		||||
    fix = fixed_parameters
 | 
			
		||||
    init_octpy()
 | 
			
		||||
 | 
			
		||||
def init_octpy():
 | 
			
		||||
    global octave
 | 
			
		||||
    octave = Oct2Py()
 | 
			
		||||
    BaseDir='/home/end/anal/endsversion/'
 | 
			
		||||
    octave.addpath(BaseDir)
 | 
			
		||||
    octave.addpath(BaseDir + 'AnalyticLC/')
 | 
			
		||||
    octave.addpath(BaseDir + 'FittingAndMath/')
 | 
			
		||||
    octave.addpath(BaseDir + 'FluxCalculation/')
 | 
			
		||||
    octave.LaplaceCoeffs('load',BaseDir + 'LaplaceCoeffs.mat')
 | 
			
		||||
 | 
			
		||||
# Prior transforms for nested samplers:
 | 
			
		||||
def transform_uniform(x, hyperparameters):
 | 
			
		||||
    a, b = hyperparameters
 | 
			
		||||
    return a + (b-a)*x
 | 
			
		||||
 | 
			
		||||
def transform_loguniform(x, hyperparameters):
 | 
			
		||||
    a, b = hyperparameters
 | 
			
		||||
    la = np.log(a)
 | 
			
		||||
    lb = np.log(b)
 | 
			
		||||
    return np.exp(la + x * (lb - la))
 | 
			
		||||
 | 
			
		||||
def transform_normal(x, hyperparameters):
 | 
			
		||||
    mu, sigma = hyperparameters
 | 
			
		||||
    return norm.ppf(x, loc=mu, scale=sigma)
 | 
			
		||||
 | 
			
		||||
def transform_beta(x, hyperparameters):
 | 
			
		||||
    a, b = hyperparameters
 | 
			
		||||
    return beta.ppf(x, a, b)
 | 
			
		||||
 | 
			
		||||
def transform_exponential(x, hyperparameters):
 | 
			
		||||
    a = hyperparameters
 | 
			
		||||
    return gamma.ppf(x, a)
 | 
			
		||||
 | 
			
		||||
def transform_truncated_normal(x, hyperparameters):
 | 
			
		||||
    mu, sigma, a, b = hyperparameters
 | 
			
		||||
    ar, br = (a - mu) / sigma, (b - mu) / sigma
 | 
			
		||||
    return truncnorm.ppf(x, ar, br, loc=mu, scale=sigma)
 | 
			
		||||
 | 
			
		||||
def transform_modifiedjeffreys(x, hyperparameters):
 | 
			
		||||
    turn, hi = hyperparameters
 | 
			
		||||
    return turn * (np.exp( (x + 1e-10) * np.log(hi/turn + 1)) - 1)
 | 
			
		||||
 | 
			
		||||
# prior transform
 | 
			
		||||
def prior_transform(utheta):
 | 
			
		||||
    global p;
 | 
			
		||||
    global fix;
 | 
			
		||||
    
 | 
			
		||||
    transforms = [x[2] for x in p]
 | 
			
		||||
    hyperparams = [x[3] for x in p]
 | 
			
		||||
    transformed_priors = np.zeros(len(utheta))
 | 
			
		||||
    for k,param in enumerate(utheta):
 | 
			
		||||
        if transforms[k] == 'uniform':
 | 
			
		||||
            transformed_priors[k] = transform_uniform(param,hyperparams[k])
 | 
			
		||||
        elif transforms[k] == 'loguniform':
 | 
			
		||||
            transformed_priors[k] = transform_loguniform(param,hyperparams[k])
 | 
			
		||||
        elif transforms[k] == 'normal':
 | 
			
		||||
            transformed_priors[k] = transform_normal(param,hyperparams[k])
 | 
			
		||||
        else:
 | 
			
		||||
            raise ValueError("Transform not known")
 | 
			
		||||
 | 
			
		||||
    return transformed_priors
 | 
			
		||||
 | 
			
		||||
# log-likelihood
 | 
			
		||||
def loglike(theta):
 | 
			
		||||
    global octave;
 | 
			
		||||
    global p;
 | 
			
		||||
    global fix;
 | 
			
		||||
    parameters = fix.copy()
 | 
			
		||||
 | 
			
		||||
    for i in range(len(theta)):
 | 
			
		||||
        planetid = p[i][0]
 | 
			
		||||
        keyname = p[i][1]
 | 
			
		||||
        if planetid == -1:
 | 
			
		||||
            parameters[keyname] = theta[i]
 | 
			
		||||
        else:
 | 
			
		||||
            parameters[keyname][planetid] = theta[i]
 | 
			
		||||
 | 
			
		||||
    n = SimpleNamespace(**parameters)
 | 
			
		||||
    
 | 
			
		||||
    u1=0.5;
 | 
			
		||||
    u2=0.3;
 | 
			
		||||
    t=np.linspace(0,100,2) #0:0.002:100;
 | 
			
		||||
    tRV=np.linspace(0,100,1000)
 | 
			
		||||
    
 | 
			
		||||
    try:
 | 
			
		||||
        LC,RV_o_r,Y_o_r,Z_o_r,O = octave.feval("AnalyticLC",n.P, n.Tmid0, n.ror, n.aor, n.mu, n.ex0, n.ey0, n.I0, n.Omega0, t, u1, u2,'tRV',tRV, nout=5)
 | 
			
		||||
 | 
			
		||||
        model =[]
 | 
			
		||||
        for i in RV_o_r:
 | 
			
		||||
            model.append(i[0])
 | 
			
		||||
            model = np.array(model)
 | 
			
		||||
            model23 = model[~(np.isnan(model))]
 | 
			
		||||
            model2 = model23[~(np.iscomplex(model23))]
 | 
			
		||||
            #print("Model:")
 | 
			
		||||
            #print(model2)
 | 
			
		||||
            #print("y:")
 | 
			
		||||
            #print(y)
 | 
			
		||||
            if (model2.size == 0):
 | 
			
		||||
                #print("error")
 | 
			
		||||
                return -np.inf
 | 
			
		||||
            inv_sigma2 = 1.0 / (n.yerr**2 + np.exp(2 * n.sig))
 | 
			
		||||
            ret = -0.5 * (np.sum((n.y-model2)**2 * inv_sigma2 - np.log(inv_sigma2)))
 | 
			
		||||
            #if np.imag(ret)!=0:
 | 
			
		||||
            #    return -np.inf
 | 
			
		||||
            #print(ret)
 | 
			
		||||
            return ret
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        print(e)
 | 
			
		||||
        return -np.inf
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    parameters, fixed, nkern, nlivepoints = parse_settings()
 | 
			
		||||
 | 
			
		||||
    y, yerr, y_true = generate_mockdata()
 | 
			
		||||
 | 
			
		||||
    fixed["y"] = y
 | 
			
		||||
    fixed["yerr"] = yerr
 | 
			
		||||
    fixed["y_true"] = y_true
 | 
			
		||||
 | 
			
		||||
    results = calculate(nkern, nlivepoints, parameters, fixed)
 | 
			
		||||
    create_plot(results)
 | 
			
		||||
 | 
			
		||||
main()
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								octave-workspace
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								octave-workspace
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										39
									
								
								parameter.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								parameter.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
{
 | 
			
		||||
	"planets": [
 | 
			
		||||
		{
 | 
			
		||||
			"P": {"type": "uniform", "values": [11,13]},
 | 
			
		||||
			"Tmid0": {"type": "fixed", "values": 9.876},
 | 
			
		||||
			"ex0": {"type": "fixed", "values": 0.01234},
 | 
			
		||||
			"ey0": {"type": "fixed", "values": 0.02345},
 | 
			
		||||
			"ror": {"type": "fixed", "values": 0.021},
 | 
			
		||||
			"mu": {"type": "fixed", "values": 1.24e-5},
 | 
			
		||||
			"I0": {"type": "fixed", "values": 0.01745},
 | 
			
		||||
			"Omega0": {"type": "fixed", "values": 0.4014257}
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"P": {"type": "uniform", "values": [29,31]},
 | 
			
		||||
			"Tmid0": {"type": "fixed", "values": 15.4029},
 | 
			
		||||
			"ex0": {"type": "fixed", "values": 0.00998},
 | 
			
		||||
			"ey0": {"type": "fixed", "values": 0.0189},
 | 
			
		||||
			"ror": {"type": "fixed", "values": 0.027},
 | 
			
		||||
			"mu": {"type": "fixed", "values": 3e-5},
 | 
			
		||||
			"I0": {"type": "fixed", "values": 0.0203},
 | 
			
		||||
			"Omega0": {"type": "fixed", "values": 0.369}
 | 
			
		||||
		}
 | 
			
		||||
	],
 | 
			
		||||
	"parameters": {
 | 
			
		||||
		"sig": {"type": "uniform", "values": [-10000,100]},
 | 
			
		||||
		"aor": {"type": "fixed", "values": 30},
 | 
			
		||||
		"u1" : {"type": "fixed", "values": 0.5},
 | 
			
		||||
		"u2" : {"type": "fixed", "values": 0.3}
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	"LC_datapath": "/dev/null", 
 | 
			
		||||
	"RV_datapath": "/dev/null", 
 | 
			
		||||
	"AnalyticLC_datapath": "/dev/null", 
 | 
			
		||||
	"atrometry_datapath": "/dev/null", 
 | 
			
		||||
 | 
			
		||||
	"nlivepoints": 1000,
 | 
			
		||||
	"nkern": 16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								requirements.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								requirements.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
oct2py
 | 
			
		||||
dynesty
 | 
			
		||||
matplotlib
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue