I'm trying to plot the boundaries of Arnold tongues (the regions were periodic solutions exist) for the circle map, f(x) = 2x + a + b*sin(2*pi*x)/pi mod 1. These are defined when f^n(x)=x and d/dx(f^n(x)) = 1, where f^n(x) represents iterating the function n times, i.e. f^2(x) = f(f(x)), n is the period of the periodic point.
I would like to able to take the two equations and write an equation for the boundary of the Arnold tongues in terms of b, so I will get x = g(b) and a = h(b) which satisfies the equation. I then want to plot a against b.
Analytically I can solve this in this way for the period 1 boundary by rearrange d/dx(f(x)) = 1 for x which gives x in terms of b then substituting this value into f(x) = x to give a in terms of b. I've also managed to do this in MATLAB using symbolic equations in the following way.
clear;
syms x a b
f = 2*x + a + (b/pi)*sin(2*pi*x);
g = diff(f,x);
solx = solve(g==1,x);
fnox = subs(f,x,solx);
solb(1) = solve(fnox(1)==solx(1), a);
solb(2) = solve(fnox(2)==solx(2),a);
[xval1,yval1] = fplot(matlabFunction(solb(1)),[0 1]);
[xval2,yval2] = fplot(matlabFunction(solb(2)),[0 1]);
A1 = [xval1,yval1];
A2 = [xval2,yval2];
A1 = A1(imag(A1(:,2))==0,:);
A2 = A2(imag(A2(:,2))==0,:);
figure(1)
hold on;
plot(A1(:,2),A1(:,1),'b')
plot(A2(:,2),A2(:,1),'b')
hold off;
The question is this, is there a way for me to solve for period 2 or higher boundary? I've tried the following,
f2 = subs(f,x,f)
g2 = diff(f2,x)
solx2 = solve(g2==1,x);
However I get a 'cannot find explicit solution' warning. I think perhaps the equation is too complicated for MATLAB to solve symbolically. Is there a way I can get it to work using symbolic equations? If not is there a suitable numeric method to perform the above?
Any help is much appreciated, thanks in advance.
Related
In the integral
I want to optimize the function Dt, as I know the end result of the integral. I have expressions for k1 and k0 in terms of k2 and N, and it is k2 and N that I would like to optimize. They have constraints, needing to be between certain values. I have it all setup in my code, but I am just unaware of how to tell the genetic alogrithm to optimize an integral function? Is there something I'm missing here? The integral is usually evaluated numerically but I am trying to go backwards, and assuming I know an answer find the input parameters
EDIT:
All right, so here's my code. I know the integral MUST add up to a known value, and I know the value, so I need to optimize the variables with that given parameter. I have created an objective function y= integral - DT. I kept theta as syms because it is the thing being integrated to give DT.
function y = objective(k)
% Define constants
AU = astroConstants(2);
mu = astroConstants(4);
% Define start and finish parameters for the exponential sinusoid.
r1 = AU; % Initial radius
psi = pi/2; % Final polar angle of Mars/finish transfer
phi = pi/2;
r2 = 1.5*AU;
global k1
k1 = sqrt( ( (log(r1/r2) + sin(k(1)*(psi + 2*pi*k(2)))*tan(0)/k(1)) / (1-
cos(k(1)*(psi+2*pi*k(2)))) )^2 + tan(0)^2/k(1)^2 );
k0 = r1/exp(k1*sin(phi));
syms theta
R = k0*exp(k1*sin(k(1)*theta + phi));
syms theta
theta_dot = sqrt((mu/(R^3))*1/((tan(0))^2 + k1*(k(1))^2*sin(k(1)*theta +
phi) + 1));
z = 1/theta_dot;
y = int(z, theta, 0,(psi+2*pi*k(2))) - 1.3069e08;
global x
x=y;
end
my k's are constrained, and the following is the constraint function. I'm hoping what I have done here is tell it that the function MUST = 0.
function [c,c_eq] = myconstraints(k)
global k1 x
c = [norm(k1*(k(1)^2))-1 -norm(k1*(k(1)^2))];
c_eq =[x];
end
And finally, my ga code looks like this. Honestly, I've been playing with it all night and getting error messages after error messages - ranging from "constraint function must return real value" to "error in fcnvectorizer" and "unable to convert expression into double array", with the last two coming after i've removed the constraints.
clc; clear;
ObjFcn = #objective;
nvars = 2
LB = [0 2];
UB = [1 7];
ConsFcn = #myconstraints;
[k,fval] = ga(ObjFcn,nvars,[],[],[],[],LB,UB,ConsFcn);
I've been stuck on this problem for weeks and have gotten nowhere, even with searching through literature.
The GMRES algorithm and its matlab implementation are supposed to solve linear equations system, such as
%Ax = b
A = rand(4);
b = rand(4,1);
x = gmres(A,b);
One can also use a function handle
foo = #(x) A*x + conj(A)*5*x;
y = gmres(foo,b);
What I want is to solve the following
B = rand(4);
H = rand(4);
foo2 = H*B + B*H;
X = gmres(foo2, B) %Will not run!
--Error using gmres (line 94)
--Right hand side must be a column vector of length 30 to match the coefficient matrix.
Mathematically speaking I don't see why gmres couldn't apply to this problem as well.
Note: What I'm really trying to solve is an implicit euler method for a PDE dB/dt = B_xx + B_yy, so H is in fact a second derivative matrix using finite difference.
Thank you
Amir
If I've understood right you want to use GMRES to solve an a sylvester equation
A*X + X*A = C
for n-by-n matrices A, X and C.
(I asked a related question yesterday over at SciComp and got this great answer.)
To use GMRES you can express this matrix-matrix equation as a size n^2 matrix-vector equation. For convenience we can use the Kronecker product, implemented in MATLAB with kron:
A = randn(5);
X = randi(3,[5 5]);
C = A*X + X*A;
% Use the Kronecker product to form an n^2-by-n^2 matrix
% A*X + X*A
bigA = (kron(eye(5),A) + kron(A.',eye(5)));
% Quick check that we're getting the same answer
norm(bigA*X(:) - C(:))
% Use GMRES to calculate X from A and C.
vec_X_gmres = gmres(bigA,C(:));
X_gmres = reshape(vec_X_gmres,5,5);
We were asked to define our own differential operators on MATLAB, and I did it following a series of steps, and then we should use the differential operators to solve a boundary value problem:
-y'' + 2y' - y = x, y(0) = y(1) =0
my code was as follows, it was used to compute this (first and second derivative)
h = 2;
x = 2:h:50;
y = x.^2 ;
n=length(x);
uppershift = 1;
U = diag(ones(n-abs(uppershift),1),uppershift);
lowershift = -1;
L= diag(ones(n-abs(lowershift),1),lowershift);
% the code above creates the upper and lower shift matrix
D = ((U-L))/(2*h); %first differential operator
D2 = (full (gallery('tridiag',n)))/ -(h^2); %second differential operator
d1= D*y.'
d2= ((D2)*y.')
then I changed it to this after posting it here and getting one response that encouraged the usage of Identity Matrix, however I still seem to be getting no where.
h = 2;
n=10;
uppershift = 1;
U = diag(ones(n-abs(uppershift),1),uppershift);
lowershift = -1;
L= diag(ones(n-abs(lowershift),1),lowershift);
D = ((U-L))/(2*h); %first differential operator
D2 = (full (gallery('tridiag',n)))/ -(h^2); %second differential operator
I= eye(n);
eqn=(-D2 + 2*D - I)*y == x
solve(eqn,y)
I am not sure how to proceed with this, like should I define y and x, or what exactly? I am clueless!
Because this is a numerical approximation to the solution of the ODE, you are seeking to find a numerical vector that is representative of the solution to this ODE from time x=0 to x=1. This means that your boundary conditions make it so that the solution is only valid between 0 and 1.
Also this is now the reverse problem. In the previous post we did together, you know what the input vector was, and doing a matrix-vector multiplication produced the output derivative operation on that input vector. Now, you are given the output of the derivative and you are now seeking what the original input was. This now involves solving a linear system of equations.
Essentially, your problem is now this:
YX = F
Y are the coefficients from the matrix derivative operators that you derived, which is a n x n matrix, X would be the solution to the ODE, which is a n x 1 vector and F would be the function you are associating the ODE with, also a n x 1 vector. In our case, that would be x. To find Y, you've pretty much done that already in your code. You simply take each matrix operator (first and second derivative) and you add them together with the proper signs and scales to respect the left-hand side of the ODE. BTW, your first derivative and second derivative matrices are correct. What's left is adding the -y term to the mix, and that is accomplished by -eye(n) as you have found out in your code.
Once you formulate your Y and F, you can use the mldivide or \ operator and solve for X and get the solution to this linear system via:
X = Y \ F;
The above essentially solves the linear system of equations formed by Y and F and will be stored in X.
The first thing you need to do is define a vector of points going from x=0 to x=1. linspace is probably the most suitable where you can specify how many points we want. Let's assume 100 points for now:
x = linspace(0,1,100);
Therefore, h in our case is just 1/100. In general, if you want to solve from the starting point x = a up to the end point x = b, the step size h is defined as h = (b - a)/n where n is the total number of points you want to solve for in the ODE.
Now, we have to include the boundary conditions. This simply means that we know the beginning and ending of the solution of the ODE. This means that y(0) = y(1) = 0. As such, we make sure that the first row of Y has only the first column set to 1 and the last row of Y has only the last column set to 1, and we'll set the output position in F to both be 0. This symbolizes that we already know the solution at these points.
Therefore, your final code to solve is just:
%// Setup
a = 0; b = 1; n = 100;
x = linspace(a,b,n);
h = (b-a)/n;
%// Your code
uppershift = 1;
U = diag(ones(n-abs(uppershift),1),uppershift);
lowershift = -1;
L= diag(ones(n-abs(lowershift),1),lowershift);
D = ((U-L))/(2*h); %first differential operator
D2 = (full (gallery('tridiag',n)))/ -(h^2);
%// New code - Create differential equation matrix
Y = (-D2 + 2*D - eye(n));
%// Set boundary conditions on system
Y(1,:) = 0; Y(1,1) = 1;
Y(end,:) = 0; Y(end,end) = 1;
%// New code - Create F vector and set boundary conditions
F = x.';
F(1) = 0; F(end) = 0;
%// Solve system
X = Y \ F;
X should now contain your numerical approximation to the ODE in steps of h = 1/100 starting from x=0 up to x=1.
Now let's see what this looks like:
figure;
plot(x, X);
title('Solution to ODE');
xlabel('x'); ylabel('y');
You can see that y(0) = y(1) = 0 as per the boundary conditions.
Hope this helps, and good luck!
I have a Matlab function that returns a polynomial of the form:
poly = ax^2 + bx*y + cy^2
where a, b, and c are constants, and x and y are symbolic (class sym).
I want to get the coefficients of the polynomial in the form [a b c], but I'm running into the following problem. If the function returns poly = y^2, then coeffs(poly) = 1. I don't want this – I want it to return [0 0 1].
How can I create a function that will give me the coefficients of a symbolic polynomial in the form that I want?
You can use sym2poly if your polynomial is a function of a single variable like your example y^2:
syms y
p = 2*y^2+3*y+4;
c = sym2poly(p)
which returns
c =
2 3 4
Use fliplr(c) if you really want the coefficients in the other order. If you're going to be working with polynomials it would probably also be a good idea not to create a variable called poly, which is the name of a function you might want to use.
If you actually need to handle polynomials in multiple variables, you can use MuPAD functions from within Matlab. Here is how you can use MuPAD's coeff to get the coefficients in terms of the order of variable they precede (x or y):
syms x y
p = 2*x^2+3*x*y+4*y;
v = symvar(p);
c = eval(feval(symengine,'coeff',p,v))
If you want to extract all of the information from the polynomial, the poly2list function is quite helpful:
syms x y
p = 2*x^2+3*x*y+4*y;
v = symvar(p);
m = eval(feval(symengine,'poly2list',p,v));
c = m(:,1); % Coefficients
degs = m(:,2:end); % Degree of each variable in each term
The polynomial can then be reconstructed via:
sum(c.*prod(repmat(v,[size(m,1) 1]).^degs,2))
By the way, good choice on where you go to school. :-)
There is also an alternative to this problem. For a given degree, this function returns a polynomial of that degree and its coefficients altogether.
function [polynomial, coefficeint] = makePoly(degree)
syms x y
previous = 0 ;
for i=0:degree
current = expand((x+y)^i);
previous= current + previous ;
end
[~,poly] = coeffs(previous);
for j= 1:length(poly)
coefficeint(j) = sym(strcat('a', int2str(j)) );
end
polynomial = fliplr(coefficeint)* poly.' ;
end
Hope this helps.
I am trying to implement the crank nicolson method in matlab and have managed to get an implementation working without boundary conditions (ie u(0,t)=u(N,t)=0). The problem I am having is with adding boundary conditions. It seems that the boundary conditions are not being considered in my current implementation.
Here is my current implementation:
C-N method:
function [ x, t, U ] = Crank_Nicolson( vString, fString, a, N, M,g1,g2 )
%The Crank Nicolson provides a solution to the parabolic equation provided
% The Crank Nicolson method uses linear system of equations to solve the
% parabolic equation.
%Prepare the grid and grid spacing variables.
dt = 1/M;
t = dt * [0:M];
h = 1/N;
x = 2 + h * [0:N]';%Shift x by 2 that way we have 2 <= x <= 3
%Prepare the matrix that will store the solutions over the grid
U = zeros(N+1, M+1);
%This will fill the first column with the initial condition. feval will
%evaluate the initial condition at all values of x
U(:,1) = feval(vString, x);
%This fills the boundary conditions. One boundary condition goes on the
%first row the other boundary condition goes on the last row
U(1,:) = feval(g1, t);
U(end,:) = feval(g2, t);
%The loop that will populate the matrix with the solution
n = 1:N+1;%Start at 2 since n=1 is the initial condition
e = ones(N+1,1);
B = spdiags([-1*e 2*e -1*e],-1:1, N+1, N+1)*(1/h^2);
A = (speye(N+1)+((a*dt)/2)*B);
X = (speye(N+1)-((a*dt)/2)*B);
R = chol(A);%Choleski decomposition
for m=2:M+1
%The linear system is solved.
b = X*U(n,m-1) + dt * feval(fString, x(n), (t(m)+t(m-1))*0.5);
b = R'\b;
U(n,m) = R\b;
end
end
I know that this implementation works when boundary conditions are not an issue. Is there something I am missing? Also, I'd be happy to hear if there are any general matlab format suggestions, since I am relatively new to matlab.
If you are interested in the entire project, download this