Plot function in TikZ from an array of functions - tikz

I am trying to create a code that automatically draws splines (parametric curves of arbitrary degree—not only cubic—defined as piecewise functions of the variable \t) in 2D. I will compute those functions within an .Rnw file and I’d want my TikZ code to plot the different pieces within a for loop. My problem is that I don’t know how to create (and access) an array of such functions.
I provide a very simplified MWE here
\documentclass{article}
\usepackage{tikz}
\usepackage{ifthen}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\def\npcs{2}
% Functions defined separately
% 1st section
\def\fxa{-2* \t^0 + 2* \t^1 + 0* \t^2}
\def\fya{2* \t^0 + 2* \t^1 -1* \t^2}
% 2nd section
\def\fxb{-2* \t^0 + 2* \t^1 + 0* \t^2}
\def\fyb{1* \t^0 + 4* \t^1 -2* \t^2}
% ... as many times as sections in the piecewise functions
% Functions defined with an array
\def\fxall{{-2* \t^0 + 2* \t^1 + 0* \t^2}, {-2* \t^0 + 2* \t^1 + 0* \t^2}} % ... as many elements as sections in the piecewise functions
\def\fyall{{2* \t^0 + 2* \t^1 -1* \t^2}, {1* \t^0 + 4* \t^1 -2* \t^2}} % ... as many elements as sections in the piecewise functions
\draw[thick, domain = 0:1, smooth, variable = \t, color = red!60]
plot (\fxa, \fya);
\draw[thick, domain = 1:2, smooth, variable = \t, color = red!20]
plot (\fxb, \fyb);
% This is the part that is not working!!
\foreach \n [evaluate = \n as \tstart using int(\n - 1), evaluate = \n as \color using int(100 - 40*\n)] in {1,...,\npcs}
{
\draw[thick, domain = \tstart:\n, smooth, variable = \t, color = red!\color]
plot (\fxall[\tstart], \fyall[\tstart]);
}
\end{tikzpicture}
\end{document}
If I define the functions by hand: \fxa, \fxb, etc, \fya, \fyb, etc… then I would have no problem in plotting all of them, but that obviously does not automatize the problem.
However, when I try to automatize the plotting with a \foreach loop, I get an error. I have tried different ways of declaring the variables \fxall and \fyall (with double braces, with parentheses…) but nothing worked. I get a cascade of massage errors like
Missing $ inserted. }
Extra }, or forgotten $. }
Any ideas on how to fix this?
Thanks in advance!!

Related

Suggestion to solve 'NaN' in matlab. Dealing with large and small numbers in Matlab

I am trying to make a model of planets' movement plot it in 3d using Matlab.
I used Newton's law with the gravitational force between two objects and I got the differential equation below:
matlab code:
function dy=F(t,y,CurrentPos,j)
m=[1.98854E+30 3.302E+23 4.8685E+24 5.97219E+24 6.4185E+23 1.89813E+27 5.68319E+26 8.68103E+25 1.0241E+26 1.307E+22];
G=6.67E-11;
dy = zeros(6,1);
dy(1) = y(4);
dy(2) = y(5);
dy(3) = y(6);
for i=1:10
if i~=j
deltaX=(CurrentPos(j,1)-CurrentPos(i,1));
deltaY=(CurrentPos(j,2)-CurrentPos(i,2));
deltaZ=(CurrentPos(j,3)-CurrentPos(i,3));
ray=sqrt((deltaX^2)+(deltaY^2)+(deltaZ^2));
dy(4) = dy(4) + G*m(i)*(deltaX/(ray^3));
dy(5) = dy(5) + G*m(i)*(deltaY/(ray^3));
dy(6) = dy(6) + G*m(i)*(deltaZ/(ray^3));
end
end
where the 'm' array is the planet masses.
then I used the numerical method Runge-Kutta-4 to solve it, and here's the code:
function [y,t]=RK4(F,intPos,a,b,N)
h=(b-a)/N;
t=zeros(N,1);
y = zeros(10*N,6);
y(1,:)=intPos(1,:);
y(2,:)=intPos(2,:);
y(3,:)=intPos(3,:);
y(4,:)=intPos(4,:);
y(5,:)=intPos(5,:);
y(6,:)=intPos(6,:);
y(7,:)=intPos(7,:);
y(8,:)=intPos(8,:);
y(9,:)=intPos(9,:);
y(10,:)=intPos(10,:);
t(1)=a;
for i=1:N
t(i+1)=a+i*h;
CurrentPos=y((i*10)-9:i*10,:);
% CurrentPos(1,:)=intPos(1,:);
y((i*10)+1,:)=intPos(1,:);
for j=2:10
k1=F(t(i),y(((i-1)*10)+j,:),CurrentPos,j);
k2=F(t(i)+h/2,y(((i-1)*10)+j,:)+(h/2).*k1',CurrentPos,j);
k3=F(t(i)+h/2,y(((i-1)*10)+j,:)+(h/2).*k2',CurrentPos,j);
k4=F(t(i)+h,y(((i-1)*10)+j,:)+h.*k3',CurrentPos,j);
y((i*10)+j,:)=y(((i-1)*10)+j,:)+(h/6)*(k1+2*k2+2*k3+k4)';
end
end
Finally applied the function for the Initial States from JPL HORIZONS System:
format short
intPos=zeros(10,6);
intPos(1,:)=[1.81899E+08 9.83630E+08 -1.58778E+07 -1.12474E+01 7.54876E+00 2.68723E-01];
intPos(2,:)=[-5.67576E+10 -2.73592E+10 2.89173E+09 1.16497E+04 -4.14793E+04 -4.45952E+03];
intPos(3,:)=[4.28480E+10 1.00073E+11 -1.11872E+09 -3.22930E+04 1.36960E+04 2.05091E+03];
intPos(4,:)=[-1.43778E+11 -4.00067E+10 -1.38875E+07 7.65151E+03 -2.87514E+04 2.08354E+00];
intPos(5,:)=[-1.14746E+11 -1.96294E+11 -1.32908E+09 2.18369E+04 -1.01132E+04 -7.47957E+02];
intPos(6,:)=[-5.66899E+11 -5.77495E+11 1.50755E+10 9.16793E+03 -8.53244E+03 -1.69767E+02];
intPos(7,:)=[8.20513E+10 -1.50241E+12 2.28565E+10 9.11312E+03 4.96372E+02 -3.71643E+02];
intPos(8,:)=[2.62506E+12 1.40273E+12 -2.87982E+10 -3.25937E+03 5.68878E+03 6.32569E+01];
intPos(9,:)=[4.30300E+12 -1.24223E+12 -7.35857E+10 1.47132E+03 5.25363E+03 -1.42701E+02];
intPos(10,:)=[1.65554E+12 -4.73503E+12 2.77962E+10 5.24541E+03 6.38510E+02 -1.60709E+03];
[yy,t]=RK4(#F,intPos,0,1e8,1e3);
x=zeros(101,1);
y=zeros(101,1);
z=zeros(101,1);
for i=1:1e3
x(i,:)=yy((i-1)*10+4,1);
y(i,:)=yy((i-1)*10+4,2);
z(i,:)=yy((i-1)*10+4,3);
end
plot3(x,y,z)
Finally, the result wasn't satisfying at all and I got many 'NAN', then I did some adjustment on the RK4 method and started to get numbers, but when I plotted them it turned out I'm plotting a line instead of an orbit.
Any help would be appreciated.
Thanks in advance.
Two errors: One physical: The alpha in the formula is the j in the code, the running index j in the formulas is the loop index i in the formula. In total this makes a sign error, transforming the attracting gravity force into a repelling force like between electrons. Thus the physics dictates that the bodies move away from each other almost linearly, as long as their paths don't cross.
Second, you are applying the RK4 method in such a way that in total it is an order 1 method. These also tend to behave un-physically rather quickly. You need to update first all positions to the first stage in a temporary StagePos variable, then use that to compute all position updates for the second stage etc. The difference to the current implementation may be small in each step, but such systematic errors quickly sum up.

How to get algebraic solution and symbolic Jacobian of this simple equation?

(Crossposted from Matlab Answers) I am trying to simplify this set of algebraic equations. Then, I would like to have Matlab calculate the Jacobian for me. But it does not seem to work as I expect.
Consider this simple MWE:
% State Variables
syms x_0 x_1 x_2 x_3
% Input Variables
syms u_1 u_2 u_3
% Constants
syms k_1 V_liq dvs
% 3 Algebraic Equations
stateEquations = [...
x_1 == (x_0*(V_liq - u_1/dvs*1e3)*1e-3 + u_1)*1e3/V_liq*exp(-k_1), ...
x_2 == (x_1*(V_liq - u_2/dvs*1e3)*1e-3 + u_2)*1e3/V_liq*exp(-k_1), ...
x_3 == (x_2*(V_liq - u_3/dvs*1e3)*1e-3 + u_3)*1e3/V_liq*exp(-k_1)];
dstate_x3 = solve(stateEquations, x_3)
dstate_du = jacobian(dstate_x3, [u_1 u_2 u_3])
Since dstate_x3 is empty, the Jacobian is also empty. But I simply want Matlab to replace x_2 in eq. 3 by its right-hand side, and x_1 by its right-hand side...
Could you please give me a hint on how to achieve this with Symbolic Math Toolbox? (Deriving it manually would be very time-consuming, especially with x_i, i > 3)
Since your system has 3 equations, you must solve it for 3 variables, not just for the variable x_3. Because solve doesn't know which variables you want so solve your system for, then it returns an empty solution.
You want to solve for x_1, x_2 and x_3, so replace the penultimate line of your code by
dstate = solve(stateEquations, [x_1 x_2 x_3])
Now dstate is an 1x1 struct with 3  sym fields: x_1, x_2 and x_3. Hence, replace the last line of your code by
dstate_du = jacobian(dstate.x_3, [u_1 u_2 u_3])
Eventually, you might want to  simplify(dstate_du).

spurious lines using fimplicit on a modular function

I want to plot collections of repeating circular arcs and am having trouble with spurious lines showing up in the plots. For example, one of the plots I want is given by
a = #(x,y) ((mod(x,1) + 0.5).^2 + (mod(y,1) - 0.5).^2 - 1)
fimplicit(a,[-1,1],'MeshDensity',500)
but the output is incorrect as far as I can tell:
The implicit function is decidedly not zero on the verticle lines. I assume something funny is happening with the fimplicit algorithm and modular arithmetic. Any ideas how to get around this? Thanks!
That probably happens because your function is discontinuous at the lines x = k with k integer, as a surface plot reveals:
fsurf(a, [-2 2])
To verify that the discontinuity is the likely reason, consider the simpler example
f = #(x,y) (2*(x>=0)-1).*(2*(y>=0)-1);
This function is discontinuous at x = 0 and at y = 0. It jumps from 1 to −1 at x = 0 and at y = 0, but it never equals 0.
fsurf(f, [-2 2])
It can be seen that fimplicit is confused by the discontinuity, and thinks the function is 0 there:
fimplicit(f,[-2,2],'MeshDensity',500)
Looking at the source code of fimplicit, the actual work is seen to be done (on R2017b at least) by the class matlab.graphics.function.ImplicitFunctionLine in the second to last line. That class is a .p file, and is thus obfuscated, which means that unfortunately its source code cannot be seen.

How may I use cellfun or arrayfun in place of this loop?

I implemented the following function in Matlab.
function [x y] = cloud(a,b,phi,x0,y0,N)
phi=phi*2*pi/360;
m=ceil(5*N/pi);
x=a*(-1+2*rand(m,1));
y=b*(-1+2*rand(m,1));
f=sqrt(a^2 - b^2);
indexMatrix=zeros(m,3);
indexMatrix(:,1)=x;
indexMatrix(:,2)=y;
insidePointsMatrix=zeros(1,2);
j=1;
for i=1:m
insidePoint=sqrt(((x(i)+f).^2) + (y(i))^2) + sqrt(((x(i)-f).^2) + (y(i))^2);
if (insidePoint<=2*a)
indexMatrix(i,3)=1;
%insidePointsMatrix(j,:)=indexMatrix(i,1:2);
if j<=N
insidePointsMatrix(j,1:2)=indexMatrix(i,1:2);
j=j+1;
end
end
end
I am reading about arrayfun and cellfun, and I am wondering if it is possible to shorten the function I already implemented using it. Given a 2 x n matrix A where (u,v) are the entries for any given row, how can I return a matrix listing the output of the following formula for each row?
sqrt((u+f).^2+v.^2) + sqrt((u-v)^2+v^2)
The variables f and a are defined above. I am trying to transform a series of points into an ellipse.
using find should give you the u,v coordinates:
cond=sqrt(((x+f).^2) + y.^2) + sqrt(((x-f).^2) + y.^2) ;
ind=find(cond<=2*a);
u=x(ind);
v=y(ind);

Linear combination of a string vector (w/functions) and number vector (coefficients)

I'm really new at matlab, and am trying to fit a line or curve to data points for homework (that part is actually done). Now, I want to take this a little further than the homework asked, I have constructed a function that takes in a text file with coordinates and any number of functions (1,x,x^2... e.g.) and determines the coefficients.
So in the end I'm left with two vectors: one with the coefficients: C = [a,b,c] and another one with functions: F = {'1','x','x^2'}, and I'd like to create a linear combination of them: l = a + b*x + c*x^2, to plot the curve on a graph, and for some reason I can't figure out how to get that to work. Is there something obvious I'm overlooking, or do I have to rethink this in some way?
a=1; b=2; c=3;
C=[a,b,c];
CS = cellfun(#num2str,num2cell(C),'uniformoutput',0)
M={'*','*','*'};
F={'1','x','x^2'};
P={' + ',' + ',''};
S=reshape([CS; M; F; P],1,[]);
cat(2,S{:})
Output:
ans =
1*1 + 2*x + 3*x^2
Are you sure you want to print 'a', 'b' and 'c' as chars?