How can I construct the matrices G and D if I have h and w?
Please pay attention that in G there are some 0 rows and in D there are some 0 columns...
Even though i am very late with my solution for this, here it is for anybody wanting to implement it:
function g = gradientMat(w,h)
one = [-ones(w*h,1) ones(w*h,1)];
d = [0 1];
dx = spdiags(one,d,w*h,w*h);
dx(1:h:end,:) = zeros(w,w*h);
d = [0 h];
dy = spdiags(one,d,w*h,w*h);
dy(h*(w-1)+1:end,:) = zeros(h,w*h);
g = [dx;dy];
end
This solution has the advantage to use matlabs sparse diagonal matrices, which allow you to create the gradient matrix for large images and make calculation with these faster.
To obtain the divergence, simpley use:
g = gradientMat(size(image)(1),size(image)(2));
div = (-g')*g;
this is how I did it now, but there must be a more elegant way, right?!
%% construct G
% upper half
firstDiagG = ones(h, 1);
firstDiagG(h) = 0;
firstDiagG = -firstDiagG;
firstDiagG = repmat(firstDiagG,w,1);
% first = diag(firstDiagG);
firstG = spdiags(firstDiagG,0,n,n);
secondDiagG = ones(h, 1);
secondDiagG(h) = 0;
secondDiagG = repmat(secondDiagG,w,1);
% second = diag(secondDiagG);
secondG = spdiags(secondDiagG,0,n,n);
secondG = [zeros(size(secondG,1),1) secondG];
secondG = secondG(:,1:end-1);
upperHalf = firstG + secondG;
% lower half
thirdDiagG = ones(n-h, 1);
thirdDiagG = [thirdDiagG; zeros(h, 1)];
thirdDiagG = -thirdDiagG;
% thirdG = diag(thirdDiagG);
thirdG = spdiags(thirdDiagG,0,n,n);
fourthDiagG = [ones(n-2*h, 1); zeros(n-2*h, 1)];
% fourthG = diag(fourthDiagG);
fourthG = spdiags(fourthDiagG,0,n,n);
fourthG = [zeros(size(fourthG,1), h) fourthG];
fourthG = fourthG(:,1:end-h);
% fourthG = [fourthG zeros(size(fourthG,1),h)];
% fourthG = [fourthG; zeros(size(fourthG,1), size(fourthG,2))];
lowerHalf = thirdG + fourthG;
G = [upperHalf; lowerHalf];
%% construct D
% left half
firstD = firstG; % is the same as in G
secondDiagD = secondDiagG; % is the same as in G
% secondD = diag(secondDiagD);
secondD = spdiags(secondDiagD,0,n,n);
secondD = [zeros(1, size(secondD,1)); secondD];
secondD = secondD(1:end-1,:);
leftHalf = firstD + secondD;
% right half
thrirdDiagD = flip(thirdDiagG);
% thirdD = diag(thrirdDiagD);
thirdD = spdiags(thrirdDiagD,0,n,n);
fourthDiagD = ones(n, 1);
% fourthD = diag(fourthDiagD);
fourthD = spdiags(fourthDiagD,0,n,n);
fourthD = [zeros(h, size(fourthD,1)); fourthD];
fourthD = fourthD(1:end-h,:);
rightHalf = thirdD + fourthD;
D = [leftHalf rightHalf];
Related
The following is my implementation of a paper for cauchy noise removal.
The psnr value of the noisy image is 19 as the paper but when I compute the psnr value for the restored image un, it returns 17 which is even smaller than the psnr value of the noisy image. I guess there is something wrong in psnr computation with my code.
%%
clear memory;
clear all
close all
clc;
%% Initialization
refimg = im2double(imread('cameraman256.png')); % original image
img_height = size(refimg,1);
img_width = size(refimg,2);
refimg = refimg(1:img_height,1:img_width);
padNum = 5;
refimg = padarray(refimg,[padNum,padNum],'symmetric');
[mm,nn]=size(refimg);
img_height = size(refimg,1);
img_width = size(refimg,2);
%% Producing the degraded image
A = 1; % A =1 for image denoising
sz = size(refimg);
rng(0);
r1 = randn(sz); % (using randn because I don't have the statistics toolbox)
r2 = randn(sz);
n = 0.02; % the noise level
u0 = refimg + n.*(r1./r2);
u0 = min(u0,1); % clamp large values to 1
u0 = max(u0,0); % clamp small values to 0
figure(1); imshow(u0(padNum+1:mm-padNum,padNum+1:nn-padNum),'border','tight');
%% Initial values for the primal-dual algorithm
tol = 1e-3;
nIter = 1e3;
options.order = 1; options.bound = 'sym';
un = u0;
wn = u0;
bun = un;
bwn = wn;
pxn = zeros(ny,nx);
pyn = zeros(ny,nx);
q = zeros(ny,nx);
[gxn,gyn] = grad(u0,options);
bgxn = gxn;
bgyn = gyn;
gamma = sqrt(2)/10;
lambda = 0.7;
mu = 6.25;
tau = 0.3;
sigma = 0.3;
%% Primal-dual Algorithm
for j = 1:nIter
%%%%%%%%%%solve the subproblem p
[ux,uy]=grad(bun,options);
pxn = pxn+sigma*(bgxn-ux);
pyn = pyn+sigma*(bgyn-uy);
%%%%%%%%%%%solve the subproblem q
AUk = Au(bun);
q = q+sigma*(bwn-AUk);
%%%%%%%%%%solve the subproblem g
goldxn = gxn;
goldyn = gyn;
txn = gxn-tau*pxn;
tyn = gyn-tau*pyn;
sn = max(1e-6,sqrt(txn.^2+tyn.^2));
gxn = txn./sn.*max(0,sn-tau);
gyn = tyn./sn.*max(0,sn-tau);
%%%%%%%%%%%solve the subproblem wn
u_medfilter = medfilt2(u0);
wold = wn;
a = mu.*lambda.*tau+1;
b = -(mu.*lambda.*tau.*(2.*u0+u_medfilter)-tau.*q+2.*u0+wold);
c = tau.*lambda+mu.*lambda.*tau.*(gamma.^2+u0.^2+2.*u_medfilter.*u0)-2.*tau.*q.*u0+...
gamma.^2+u0.^2+2.*wold.*u0;
d = -tau.*lambda.*u0-mu.*lambda.*tau.*u_medfilter.*(gamma.^2+u0.^2)+tau.*q.*(gamma.^2+u0.^2)...
-wold.*(gamma.^2+u0.^2);
qval = (3.*a.*c-(b.^2))./(9.*(a.^2));
rval = (9.*a.*b.*c-27.*(a.^2).*d-2.*(b.^3))./(54.*(a.^3));
deltaval = qval.^3+rval.^2;
wn = nthroot(rval+real(sqrt(deltaval)),3)+nthroot(rval-real(sqrt(deltaval)),3)-((b)./(3.*a));
%%%%%%%%%%%solve the subproblem un
uold = un;
Asqk = Atu(q);
un = un+tau*(Asqk-div(pxn,pyn,options)); % the restored image
% un = min(1,max(0.01,un));
if (norm(un-uold, 'fro')/norm(uold,'fro')<tol)
break;
end
bun = 2*un-uold;
bwn = 2*wn-wold;
bgxn = 2*gxn-goldxn;
bgyn = 2*gyn-goldyn;
% PSNR_restoredimage = psnr(refimg(padNum+1:mm-padNum,padNum+1:nn-b
padNum),un(padNum+1:mm-padNum,padNum+1:nn-padNum))
end
%% Dispaly results
New_un = un;
refimg = refimg(padNum+1:mm-padNum,padNum+1:nn-padNum);
u0 = u0(padNum+1:mm-padNum,padNum+1:nn-padNum);
u_medfilter = u_medfilter(padNum+1:mm-padNum,padNum+1:nn-padNum);
New_un = New_un(padNum+1:mm-padNum,padNum+1:nn-padNum);
PSNR_noisy = psnr(refimg,u0)
PSNR_med = psnr(refimg,u_medfilter)
PSNR_restoredimage = psnr(New_un,refimg)
figure(2); imshow([refimg,u_medfilter,New_un],'border','tight');
%%
The problem was not in psnr computation. The problem with my code in this question was that I was considering the denoising case but I had forgotten to omit the blur kernel in primal-dual algorithm. Also, the initial parameters corresponding to the deblurring case must be zero. The following is the corrected code. Now the psnr value is 28 similar to the paper.
%%
clear;
%% Initialization
refimg = im2double(imread('cameraman256.png')); % original image
img_height = size(refimg,1);
img_width = size(refimg,2);
refimg = refimg(1:img_height,1:img_width);
%% Producing the noisy image
sz = size(refimg);
rng(0);
r1 = randn(sz); % (using randn because I don't have the statistics toolbox)
r2 = randn(sz);
n = 0.02; % the noise level
u0 = refimg + n.*(r1./r2);
u0 = min(u0,1); % clamp large values to 1
u0 = max(u0,0); % clamp small values to 0
figure(1); imshow(u0,'border','tight');
%% Initial values for the primal-dual algorithm
init = u0;
[ny,nx] = size(init);
tol = 1e-3;
nIter = 1e3;
options.order = 1; options.bound = 'sym';
un = u0;
wn = zeros(ny,nx);
bun = un;
bwn = zeros(ny,nx);
pxn = zeros(ny,nx);
pyn = zeros(ny,nx);
q = zeros(ny,nx);
[gxn,gyn] = grad(u0,options);
bgxn = gxn;
bgyn = gyn;
gamma = sqrt(2)/10;
lambda = 0.7;
mu = 6.25;
tau = 0.3;
sigma = 0.3;
%% Primal-dual Algorithm
for j = 1:nIter
%%%%%%%%%%solve the subproblem p
[ux,uy]=grad(bun,options);
pxn = pxn+sigma*(bgxn-ux);
pyn = pyn+sigma*(bgyn-uy);
%%%%%%%%%%%solve the subproblem q
AUk = bun;
q = q+sigma*(bwn-AUk);
%%%%%%%%%%solve the subproblem g
goldxn = gxn;
goldyn = gyn;
txn = gxn-tau*pxn;
tyn = gyn-tau*pyn;
sn = max(1e-6,sqrt(txn.^2+tyn.^2));
gxn = txn./sn.*max(0,sn-tau);
gyn = tyn./sn.*max(0,sn-tau);
%%%%%%%%%%%solve the subproblem wn
u_medfilter = medfilt2(u0);
wold = wn;
a = mu.*lambda.*tau+1;
b = -(mu.*lambda.*tau.*(2.*u0+u_medfilter)-tau.*q+2.*u0+wold);
c = tau.*lambda+mu.*lambda.*tau.*(gamma.^2+u0.^2+2.*u_medfilter.*u0)-2.*tau.*q.*u0+...
gamma.^2+u0.^2+2.*wold.*u0;
d = -tau.*lambda.*u0-mu.*lambda.*tau.*u_medfilter.*(gamma.^2+u0.^2)+tau.*q.*(gamma.^2+u0.^2)...
-wold.*(gamma.^2+u0.^2);
qval = (3.*a.*c-(b.^2))./(9.*(a.^2));
rval = (9.*a.*b.*c-27.*(a.^2).*d-2.*(b.^3))./(54.*(a.^3));
deltaval = qval.^3+rval.^2;
wn = nthroot(rval+real(sqrt(deltaval)),3)+nthroot(rval-real(sqrt(deltaval)),3)-((b)./(3.*a));
%%%%%%%%%%%solve the subproblem un
uold = un;
Asqk = q;
un = un+tau*(Asqk-div(pxn,pyn,options)); % the restored image
if (norm(un-uold, 'fro')/norm(uold,'fro')<tol)
break;
end
bun = 2*un-uold;
bwn = 2*wn-wold;
bgxn = 2*gxn-goldxn;
bgyn = 2*gyn-goldyn;
end
%% Dispaly results
PSNR_noisy = psnr(u0,refimg)
PSNR_med = psnr(u_medfilter,refimg)
PSNR_restoredimage = psnr(un,refimg)
figure(2); imshow([refimg,u_medfilter,un],'border','tight');
%%
I am writing a for loop to calculate the value of four different variables. The first variable is M. M increases from 10^2 to 10^5,
M = [10^2,10^3,10^4,10^5];
The other three variables needed for the table are shown in the code below.
confmc
confcv
confmcSize/confcvSize
I first create a for loop to iterate through the four different values of M. I then create the table outside of the for loop.
How could I adjust the implementation so that the table displays all four values of M?
randn('state',100)
%%%%%% Problem and method parameters %%%%%%%%%
S = 5; E = 6; sigma = 0.3; r = 0.05; T = 1;
Dt = 1e-2; N = T/Dt; M = [10^2,10^3,10^4,10^5];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for k=1:numel(M)
%%%%%%%%% Geom Asian exact mean %%%%%%%%%%%%
sigsqT= sigma^2*T*(N+1)*(2*N+1)/(6*N*N);
muT = 0.5*sigsqT + (r - 0.5*sigma^2)*T*(N+1)/(2*N);
d1 = (log(S/E) + (muT + 0.5*sigsqT))/(sqrt(sigsqT));
d2 = d1 - sqrt(sigsqT);
N1 = 0.5*(1+erf(d1/sqrt(2)));
N2 = 0.5*(1+erf(d2/sqrt(2)));
geo = exp(-r*T)*( S*exp(muT)*N1 - E*N2 );
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Spath = S*cumprod(exp((r-0.5*sigma^2)*Dt+sigma*sqrt(Dt)*randn(M(k),N)),2);
% Standard Monte Carlo
arithave = mean(Spath,2);
Parith = exp(-r*T)*max(arithave-E,0); % payoffs
Pmean = mean(Parith);
Pstd = std(Parith);
confmc = [Pmean-1.96*Pstd/sqrt(M(k)), Pmean+1.96*Pstd/sqrt(M(k))];
confmcSize = [(Pmean+1.96*Pstd/sqrt(M(k)))-(Pmean-1.96*Pstd/sqrt(M(k)))];
% Control Variate
geoave = exp((1/N)*sum(log(Spath),2));
Pgeo = exp(-r*T)*max(geoave-E,0); % geo payoffs
Z = Parith + geo - Pgeo; % control variate version
Zmean = mean(Z);
Zstd = std(Z);
confcv = [Zmean-1.96*Zstd/sqrt(M(k)), Zmean+1.96*Zstd/sqrt(M(k))];
confcvSize = [(Zmean+1.96*Zstd/sqrt(M(k)))-(Zmean-1.96*Zstd/sqrt(M(k)))];
end
T = table(M,confmc,confcv,confmcSize/confcvSize)
The current code returns
T =
1×4 table
M confmc confcv Var4
_____ ____________________ ____________________ ______
1e+05 0.096756 0.1007 0.097306 0.097789 8.1622
How could I change my implementation so that all four values of M are computed?
I just modified few things.Take a look at the following code.
randn('state',100)
%%%%%% Problem and method parameters %%%%%%%%%
S = 5; E = 6; sigma = 0.3; r = 0.05; T = 1;
Dt = 1e-2; N = T/Dt; M = [10^2,10^3,10^4,10^5];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
confmc = zeros(numel(M), 2);
confcv = zeros(numel(M), 2);
confmcSize = zeros(numel(M), 1);
confcvSize = zeros(numel(M), 1);
for k=1:numel(M)
%%%%%%%%% Geom Asian exact mean %%%%%%%%%%%%
sigsqT= sigma^2*T*(N+1)*(2*N+1)/(6*N*N);
muT = 0.5*sigsqT + (r - 0.5*sigma^2)*T*(N+1)/(2*N);
d1 = (log(S/E) + (muT + 0.5*sigsqT))/(sqrt(sigsqT));
d2 = d1 - sqrt(sigsqT);
N1 = 0.5*(1+erf(d1/sqrt(2)));
N2 = 0.5*(1+erf(d2/sqrt(2)));
geo = exp(-r*T)*( S*exp(muT)*N1 - E*N2 );
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Spath = S*cumprod(exp((r-0.5*sigma^2)*Dt+sigma*sqrt(Dt)*randn(M(k),N)),2);
% Standard Monte Carlo
arithave = mean(Spath,2);
Parith = exp(-r*T)*max(arithave-E,0); % payoffs
Pmean = mean(Parith);
Pstd = std(Parith);
confmc(k,:) = [Pmean-1.96*Pstd/sqrt(M(k)), Pmean+1.96*Pstd/sqrt(M(k))];
confmcSize(k,1) = [(Pmean+1.96*Pstd/sqrt(M(k)))-(Pmean-1.96*Pstd/sqrt(M(k)))];
% Control Variate
geoave = exp((1/N)*sum(log(Spath),2));
Pgeo = exp(-r*T)*max(geoave-E,0); % geo payoffs
Z = Parith + geo - Pgeo; % control variate version
Zmean = mean(Z);
Zstd = std(Z);
confcv(k,:) = [Zmean-1.96*Zstd/sqrt(M(k)), Zmean+1.96*Zstd/sqrt(M(k))];
confcvSize(k,1) = [(Zmean+1.96*Zstd/sqrt(M(k)))-(Zmean-1.96*Zstd/sqrt(M(k)))];
end
T = table(M',confmc,confcv,confmcSize./confcvSize)
In short, I just used a matrix instead of a vector or scalar as the members of the table. In your code, the variables (confmc, confcv, confmcSize, confcvSize) were getting overwritten.
My question this time concerns the obtention of the degree distribution of a LDPC matrix through linear programming, under the following statement:
My code is the following:
function [v] = LP_Irr_LDPC(k,Ebn0)
options = optimoptions('fmincon','Display','iter','Algorithm','interior-point','MaxIter', 4000, 'MaxFunEvals', 70000);
fun = #(v) -sum(v(1:k)./(1:k));
A = [];
b = [];
Aeq = [0, ones(1,k-1)];
beq = 1;
lb = zeros(1,k);
ub = [0, ones(1,k-1)];
nonlcon = #(v)DensEv_SP(v,Ebn0);
l0 = [0 rand(1,k-1)];
l0 = l0./sum(l0);
v = fmincon(fun,l0,A,b,Aeq,beq,lb,ub,nonlcon,options)
end
Definition of nonlinear constraints:
function [c, ceq] = DensEv_SP(v,Ebn0)
% It is also needed to modify this function, as you cannot pass parameters from others to it.
h = [0 rand(1,19)];
h = h./sum(h); % This is where h comes from
syms x;
X = x.^(0:(length(h)-1));
R = h*transpose(X);
ebn0 = 10^(Ebn0/10);
Rm = 1;
LLR = (-50:50);
p03 = 0.3;
LLR03 = log((1-p03)/p03);
r03 = 1 - p03;
noise03 = (2*r03*Rm*ebn0)^-1;
pf03 = normpdf(LLR, LLR03, noise03);
sumpf03 = sum(pf03(1:length(pf03)/2));
divisions = 100;
Aj = zeros(1, divisions);
rho = zeros(1, divisions);
xj = zeros(1, divisions);
k = 10; % Length(v) -> Same value as in 'Complete.m'
for j=1:1:divisions
xj(j) = sumpf03*j/divisions;
rho(j) = subs(R,x,1-xj(j));
Aj(j) = 1 - rho(j);
end
c = zeros(1, length(xj));
lambda = zeros(1, length(Aj));
for j = 1:1:length(xj)
lambda(j) = sum(v(2:k).*(Aj(j).^(1:(k-1))));
c(j) = sumpf03*lambda(j) - xj(j);
end
save Almacen
ceq = [];
%ceq = sum(v)-1;
end
This question is linked to the one posted here. My problem is that I need that each element from vectors v and h resulting from this optimization problem is a fraction of x/N and x/(N(1-r) respectively.
How could I ensure that condition without losing convergence capability?
I came up with one possible solution, at least for vector h, within the function DensEv_SP:
function [c, ceq] = DensEv_SP(v,Ebn0)
% It is also needed to modify this function, as you cannot pass parameters from others to it.
k = 10; % Same as in Complete.m, desired sum of h
M = 19; % Number of integers
h = [0 diff([0,sort(randperm(k+M-1,M-1)),k+M])-ones(1,M)];
h = h./sum(h);
syms x;
X = x.^(0:(length(h)-1));
R = h*transpose(X);
ebn0 = 10^(Ebn0/10);
Rm = 1;
LLR = (-50:50);
p03 = 0.3;
LLR03 = log((1-p03)/p03);
r03 = 1 - p03;
noise03 = (2*r03*Rm*ebn0)^-1;
pf03 = normpdf(LLR, LLR03, noise03);
sumpf03 = sum(pf03(1:length(pf03)/2));
divisions = 100;
Aj = zeros(1, divisions);
rho = zeros(1, divisions);
xj = zeros(1, divisions);
N = 20; % Length(v) -> Same value as in 'Complete.m'
for j=1:1:divisions
xj(j) = sumpf03*j/divisions;
rho(j) = subs(R,x,1-xj(j));
Aj(j) = 1 - rho(j);
end
c = zeros(1, length(xj));
lambda = zeros(1, length(Aj));
for j = 1:1:length(xj)
lambda(j) = sum(v(2:k).*(Aj(j).^(1:(k-1))));
c(j) = sumpf03*lambda(j) - xj(j);
end
save Almacen
ceq = (N*v)-floor(N*v);
%ceq = sum(v)-1;
end
As above stated, there is no longer any problem with vector h; nevertheless the way I defined ceq value seemed to be insufficient to make the optimization work out (the problems with v have not diminished at all). Does anybody know how to find the solution?
I am trying to reconstruct an image using the projections from the Neutron image scanner. I am using the following code. I am not able to obtain a meaningful reconstructed image.
Can anybody advise me on where I am going wrong.
much appreciated,
Vani
filename = strcat(' Z:\NIST_Data\2016\SEPT\example reconstructed\carboxylic\carboxylic reconstructed part 3\Coral\',srcFiles(i).name);
I=imread(filename);
P = im2double(I);
if i == 1
array3d = P;
else
array3d = cat(3, array3d, P);
end
end
num = size(array3d,3);
for p = 1:num
PR = double(squeeze(array3d(p,:,:)));
[L,C]=size(PR);
w = [-pi : (2*pi)/L : pi-(2*pi)/L];
Filt = abs(sin(w));
Filt = Filt(1:463);
for i = 1:C,
IMG = fft(PR(:,i));
end
FiltIMG = IMG*Filt; %FiltIMG = filter (b, a, IMG);
% Remove any remaining imaginary parts
FIL = real(FiltIMG);
% filter the projections
%filtPR = projfilter(PR);
%filtPR = filterplus(PR);
filtPR = FIL;
THETA=0:180;
% figure out how big our picture is going to be.
n = size(filtPR,1);
sideSize = n;
% convert THETA to radians
th = (pi/180)*THETA;
% set up the image
m = length(THETA);
BPI = zeros(sideSize,sideSize);
% find the middle index of the projections
midindex = (n+1)/2;
% set up x and y matrices
x = 1:sideSize;
y = 1:sideSize;
[X,Y] = meshgrid(x,y);
xpr = X - (sideSize+1)/2;
ypr = Y - (sideSize+1)/2;
% loop over each projection
%figure
%colormap(jet)
%M = moviein(m);
for i = 1:m
tic
disp(['On angle ', num2str(THETA(i))]);
% figure out which projections to add to which spots
filtIndex = round(midindex + xpr*sin(th(i)) - ypr*cos(th(i)));
% if we are "in bounds" then add the point
BPIa = zeros(sideSize,sideSize);
spota = find((filtIndex > 0) & (filtIndex <= n));
newfiltIndex = filtIndex(spota);
BPIa(spota) = filtPR(newfiltIndex(:),i);
%keyboard
BPI = BPI + BPIa;
toc
%imagesc(BPI)
%M(:,i) = getframe;
%figure(2)
%plot(filtPR(:,i));
%keyboard
end
BPI = BPI./m;
h=figure
imagesc(BPI)
saveas(h,sprintf('filtsli-FIG%d.tif',p));end
I'm solving a system of ODEs using RK4. I'm generating a straight line plot that seems to be due to the fact that k3_1 is capped at -3.1445e+24. I don't understand why it is capped.
function RK4system_MNModel()
parsec = 3.08*10^18;
r_1 = 8.5*1000.0*parsec; % in cm
z_1 = 0.0; % in cm also
theta_1 = 0.0;
grav = 6.6720*10^-8;
amsun = 1.989*10^33; % in grams
amg = 1.5d11*amsun; % in grams
gm = grav*amg; % constant
q = 0.9; % axial ratio
u_1 = 130.0; % in cm/sec
w_1 = 95*10^4.0; % in cm/sec
v = 180*10^4.0; % in cm/sec
vcirc = sqrt(gm/r_1); % circular speed (constant)
nsteps = 50000;
deltat = 5.0*10^11; % in seconds
angmom = r_1*v; % these are the same
angmom2 = angmom^2.0;
e = -gm/r_1+u_1*u_1/2.0+angmom2/(2.0*r_1*r_1);
time=0.0;
for i=1:nsteps
k3_1 = deltat*u_1 %%%%% THIS LINE
k4_1 = deltat*(-gm*r_1/((r_1^2.0+(1+sqrt(1+z_1^2.0))^2.0)^1.5) + angmom2/(r_1^3.0)); % u'=-dphi_dr+lz^2/(r^3.0) with lz=vi*ri this gives deltau
k5_1 = deltat*(angmom/(r_1^2.0)); % theta'=lz/r^2 this gives deltatheta
k6_1 = deltat*w_1;
k7_1 = deltat*(-gm*z_1*(1+sqrt(1+z_1^2.0))/(sqrt(1+z_1^2.0)*(r_1^2.0+(1+sqrt(1+z_1^2.0))^2.0)^1.5));
r_2 = r_1+k3_1/2.0;
u_2 = u_1+k4_1/2.0;
theta_2 = theta_1+k5_1/2.0;
z_2 = z_1 + k6_1/2.0;
w_2 = w_1 + k7_1/2.0;
k3_2 = deltat*u_2;
k4_2 = deltat*(-gm*r_2/((r_2^2.0+(1+sqrt(1+z_2^2.0))^2.0)^1.5)+angmom2/(r_2^3.0));
k5_2 = deltat*(angmom/(r_2^2.0)); % theta'=lz/r^2 =====> deltatheta
k6_2 = deltat*w_2;
k7_2 = deltat*(-gm*z_2*(1+sqrt(1+z_2^2.0))/(sqrt(1+z_2^2.0)*(r_2^2.0+(1+sqrt(1+z_2^2.0))^2.0)^1.5));
r_3 = r_1+k3_2/2.0;
u_3 = u_1+k4_2/2.0;
theta_3 = theta_1+k5_2/2.0;
z_3 = z_1 + k6_2/2.0;
w_3 = w_1 + k7_2/2.0;
k3_3 = deltat*u_3; % r'=u
k4_3 = deltat*(-gm*r_3/((r_3^2.0+(1+sqrt(1+z_3^2.0))^2.0)^1.5)+angmom2/(r_3^3.0));% u'=-dphi_dr+lz^2/(r^3.0)
k5_3 = deltat*(angmom/(r_3^2.0)); % theta'=lz/r^2
k6_3 = deltat*w_3;
k7_3 = deltat*(-gm*z_3*(1+sqrt(1+z_3^2.0))/(sqrt(1+z_3^2.0)*(r_3^2.0+(1+sqrt(1+z_3^2.0))^2.0)^1.5));
r_4 = r_1+k3_2;
u_4 = u_1+k4_2;
theta_4 = theta_1+k5_2;
z_4 = z_1 + k6_2;
w_4 = w_1 + k7_2;
k3_4 = deltat*u_4; % r'=u
k4_4 = deltat*(-gm*r_4/((r_4^2.0+(1+sqrt(1+z_4^2.0))^2.0)^1.5)+angmom2/(r_4^3.0)); % u'=-dphi_dr+lz^2/(r^3.0)
k5_4 = deltat*(angmom/(r_4^2.0)); % theta'=lz/r^2
k6_4 = deltat*w_4;
k7_4 = deltat*(-gm*z_4*(1+sqrt(1+z_4^2.0))/(sqrt(1+z_4^2.0)*(r_4^2.0+(1+sqrt(1+z_4^2.0))^2.0)^1.5));
r_1 = r_1+(k3_1+2.0*k3_2+2.0*k3_3+k3_4)/6.0; % New value of R for next step
u_1 = u_1+(k4_1+2.0*k4_2+2.0*k4_3+k4_4)/6.0; % New value of U for next step
theta_1 = theta_1+(k5_1+2.0*k5_2+2.0*k5_3+k5_4)/6.0; % New value of theta
z_1 = z_1+(k6_1+2.0*k6_2+2.0*k6_3+k6_4)/6.0;
w_1 = w_1+(k7_1+2.0*k7_2+2.0*k7_3+k7_4)/6.0;
e = -gm/r_1+u_1*u_1/2.0+angmom2/(2.0*r_1*r_1); % energy
ecc = (1.0+(2.0*e*angmom2)/(gm^2.0))^0.5; % eccentricity
x(i) = r_1*cos(theta_1)/(1000.0*parsec); % X for plotting orbit
y(i) = r_1*sin(theta_1)/(1000.0*parsec); % Y for plotting orbit
time = time+deltat;
r(i) = r_1;
z(i) = z_1;
time1(i)= time;
end
Note that the anomally occurs on the indicated line.
It's not k3_1 that's capped, it's the calculation of u_1 that returns a value of -3.1445e+24 / deltat (deltat is constant).
u_1 is calculated in the line:
u_1 = u_1+(k4_1+2.0*k4_2+2.0*k4_3+k4_4)/6.0;
After the first iteration, this returns:
u_1(1) = 6.500e+13 % Hard coded before the loop
u_1(2) = -1.432966614767040e+04 % Calculated using the equation above
u_1(3) = -2.878934017859105e+04 % Calculated using the equation above
u_1(4) = -4.324903004768405e+04
Based on the equation u_1(n+1) = u_1(n) + du it looks like du represents a relatively small difference. The difference between the two first values is very large, so I'm assuming it is this calculation that's incorrect.
If you find that that calculation is correct, then your error is in one of these lines:
k4_1 = deltat*(-gm*r_1/((r_1^2.0+(1+sqrt(1+z_1^2.0))^2.0)^1.5)+angmom2/(r_1^3.0)); % u'=-dphi_dr+lz^2/(r^3.0) with lz=vi*ri this gives delta
k4_2 = deltat*(-gm*r_2/((r_2^2.0+(1+sqrt(1+z_2^2.0))^2.0)^1.5)+angmom2/(r_2^3.0));
k4_3 = deltat*(-gm*r_3/((r_3^2.0+(1+sqrt(1+z_3^2.0))^2.0)^1.5)+angmom2/(r_3^3.0));% u'=-dphi_dr+lz^2/(r^3.0)
k4_4 = deltat*(-gm*r_4/((r_4^2.0+(1+sqrt(1+z_4^2.0))^2.0)^1.5)+angmom2/(r_4^3.0)); % u'=-dphi_dr+lz^2/(r^3.0)