Skip to content

Commit

Permalink
improved vector and test_vector
Browse files Browse the repository at this point in the history
  • Loading branch information
mariomerinomartinez committed Aug 7, 2018
1 parent d1c1a14 commit 31f1432
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 93 deletions.
38 changes: 19 additions & 19 deletions +anakin/@vector/vector.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,22 @@
The class constructor accepts the following call types:
- a0 = anakin.vector(); % where: a0 is the null vector
- a = anakin.vector(a); % (convert to vector class)
- a = anakin.basis(c); % where: c are column components in B0
- a = anakin.basis(rc,B1); % where: rc are relative column components,
% and B1 is a vector basis
- a = anakin.basis(c); % where: c are components in canonical basis B0
- a = anakin.basis(rc,B1); % where: rc are relative components in B1
- a = anakin.basis(x,y,z); % where: x,y,z are components in B0
- a = anakin.basis(rx,ry,rz,B1); % where: rx,rc,rz are relative column
% components, and B1 is a vector basis
- a = anakin.basis(rx,ry,rz,B1); % where: rx,rc,rz are relative components
METHODS:
* components: returns the components of the vector in a chosen basis
* x,y,z: returns individual components in a chosen basis
* dir, magnitude: returns the unit vector and magnitude of a vector
* isunitary, isperpendicular, isparallel: checks for the corresponding
property and returns true or false
* plot: plots the vector with quiver, at a chosen position
* dt: returns the time derivative of a vector wrt a chosen basis
(symbolic variables must be used)
* subs: takes values of the symbolic unknowns and returns a vector with
purely numeric coordinates (symbolic variables must be used)
* isunitary, isperpendicular, isparallel: checks for the corresponding
property and returns true or false
* plot: plots the vector with quiver, at a chosen position
MMM20180802
%}
Expand Down Expand Up @@ -62,6 +60,17 @@ purely numeric coordinates (symbolic variables must be used)
end
end
methods % overloads
function value = eq(a,b) % overload ==
if isa(a.c,'sym') || isa(b.c,'sym') % symbolic inputs
value = isAlways(a.c==b.c,'Unknown','false'); % In case of doubt, false
else % numeric input
value = (abs(a.c - b.c)<eps(max(abs(a.c(:))))+eps(max(abs(b.c(:)))));
end
value = all(value(:));
end
function value = ne(a,b) % overload ~=
value = ~eq(a,b);
end
function a = plus(a,b) % overloaded + operator
a.c = a.c + b.c;
end
Expand Down Expand Up @@ -102,17 +111,6 @@ purely numeric coordinates (symbolic variables must be used)
function a = mldivide(x,a) % overloaded \ (division by scalar or matrix)
a.c = x\a.c;
end
function value = eq(a,b) % overload ==
if isa(a.c,'sym') || isa(b.c,'sym') % symbolic inputs
value = isAlways(a.c==b.c,'Unknown','false'); % In case of doubt, false
else % numeric input
value = (abs(a.c - b.c)<eps(max(abs(a.c(:))))+eps(max(abs(b.c(:)))));
end
value = all(value(:));
end
function value = ne(a,b) % overload ~=
value = ~eq(a,b);
end
function value = dot(a,b) % dot product of two real vectors
value = dot(a.c,b.c);
if isa(value,'sym')
Expand Down Expand Up @@ -168,6 +166,8 @@ purely numeric coordinates (symbolic variables must be used)
function magnitude = magnitude(a) % returns magnitude of a (alias for norm)
magnitude = norm(a);
end
end
methods % symbolic
function da = dt(a,B) % time derivative with respect to basis B. Requires sym vector that utlimately depends on a single variable t
if ~exist('B','var')
B = anakin.basis; % canonical vector basis
Expand Down
212 changes: 138 additions & 74 deletions tests/test_vector.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,108 +19,172 @@

function test_creator(~) % Call creator without arguments
import anakin.*
B1 = basis([0,1,0],[-1,0,0],[0,0,1]);

a = vector;
end

function test_creator2(~) % Call creator with numeric arguments
import anakin.*
B1 = basis([0,-1,0],[0,1,0],[0,0,1]);

a = vector; % null vector
a = vector([1;2;0]); % components in canonical vector basis, column array form
a = vector([1,2,0]); % components in canonical vector basis, row array form
a = vector([1;2;0],B1); % components in another basis, column array form
a = vector([1,2,0],B1); % components in another basis, row array form
a = vector(1,2,0); % components in canonical vector basis, independently given
a = vector(1,2,0,B1); % components in another basis, independently given

if license('test','symbolic_toolbox')
syms t theta(t) phi(t);
assume([in(t, 'real'), in(theta(t), 'real'), in(phi(t), 'real')]);
B1 = basis([1,0,0],[0,cos(phi),sin(phi)],[0,-sin(phi),cos(phi)]);

a = vector([cos(theta);sin(theta);0]); % components in canonical vector basis, column array form
a = vector([cos(theta),sin(theta),0]); % components in canonical vector basis, row array form
a = vector([cos(theta);sin(theta);0],B1); % components in another basis, column array form
a = vector([cos(theta),sin(theta),0],B1); % components in another basis, row array form
a = vector(cos(theta),sin(theta),0); % components in canonical vector basis, independently given
a = vector(cos(theta),sin(theta),0,B1); % components in another basis, independently given
end
end

function test_creator3(~) % Call creator with arguments of type sym

function test_overloads(~) % components, x,y,z
import anakin.*
syms t;
syms theta(t) phi(t);
assume([in(t, 'real'), in(theta(t), 'real'), in(phi(t), 'real')]);
B1 = basis([1,0,0],[0,cos(phi),sin(phi)],[0,-sin(phi),cos(phi)]);

a = vector([cos(theta);sin(theta);0]); % components in canonical vector basis, column array form
a = vector([cos(theta),sin(theta),0]); % components in canonical vector basis, row array form
a = vector([cos(theta);sin(theta);0],B1); % components in another basis, column array form
a = vector([cos(theta),sin(theta),0],B1); % components in another basis, row array form
a = vector(cos(theta),sin(theta),0); % components in canonical vector basis, independently given
a = vector(cos(theta),sin(theta),0,B1); % components in another basis, independently given
a = vector([1.1,2.2,3.3]);
b = vector([4.4,5.5,6.6]);

assert(a==a);
assert(a~=b);
assert(a + b == vector([5.5;7.7;9.9]));
assert(a - b == vector([-3.3;-3.3;-3.3]));
assert(+a == a);
assert(-a == vector([-1.1,-2.2,-3.3]));
assert(2 * a == vector([2.2;4.4;6.6]));
assert(a * 2 == vector([2.2;4.4;6.6]));
assert(2 .* a == vector([2.2;4.4;6.6]));
assert(a .* 2 == vector([2.2;4.4;6.6]));
assert(2 \ a == vector([0.55;1.1;1.65]));
assert(a / 2 == vector([0.55;1.1;1.65]));
assert(2 .\ a == vector([0.55;1.1;1.65]));
assert(a ./ 2 == vector([0.55;1.1;1.65]));
assert(dot(a,b) == 38.72);
assert(norm(a) == sqrt(16.94));
assert(cross(a,b) == vector([-3.63,7.26,-3.63]));
assert(dir(a) == vector([1.1,2.2,3.3]/sqrt(16.94)));
assert(magnitude(a) == sqrt(16.94));

if license('test','symbolic_toolbox')
syms t x1(t) y1(t) z1(t) x2(t) y2(t) z2(t);
assume([in(t, 'real'), ...
in(x1(t), 'real'), in(y1(t), 'real'), in(z1(t), 'real'),...
in(x2(t), 'real'), in(y2(t), 'real'), in(z2(t), 'real')]);

a = vector([x1,y1,z1]);
b = vector([x2,y2,z2]);

assert(a==a);
assert(a~=b);
assert(a + b == vector([x1+x2;y1+y2;z1+z2]));
assert(a - b == vector([x1-x2;y1-y2;z1-z2]));
assert(+a == a);
assert(-a == vector([-x1,-y1,-z1]));
assert(2 * a == vector(2*[x1,y1,z1]));
assert(a * 2 == vector(2*[x1,y1,z1]));
assert(2 .* a == vector(2*[x1,y1,z1]));
assert(a .* 2 == vector(2*[x1,y1,z1]));
assert(2 \ a == vector([x1,y1,z1]/2));
assert(a / 2 == vector([x1,y1,z1]/2));
assert(2 .\ a == vector([x1,y1,z1]/2));
assert(a ./ 2 == vector([x1,y1,z1]/2));
assert(isAlways(dot(a,b) == x1*x2+y1*y2+z1*z2));
assert(isAlways(norm(a) == sqrt(x1^2+y1^2+z1^2)));
assert(cross(a,b) == vector([y1*z2-z1*y2,z1*x2-x1*z2,x1*y2-y1*x2]));
assert(dir(a) == vector([x1,y1,z1]/sqrt(x1^2+y1^2+z1^2)));
assert(isAlways(magnitude(a) == sqrt(x1^2+y1^2+z1^2)));
end
end

function test_components(~) % Call components, x,y,z
import anakin.*
syms t;
syms theta(t) phi(t);
assume([in(t, 'real'), in(theta(t), 'real'), in(phi(t), 'real')]);
B1 = basis([1,0,0],[0,cos(phi),sin(phi)],[0,-sin(phi),cos(phi)]);
a = vector([cos(theta),sin(theta),0],B1);
B1 = basis([0,1,0],[-1,0,0],[0,0,1]);
a = vector([1,2,3],B1);

assert(isAlways(all(a.components(B1) == [cos(theta);sin(theta);0])));
assert(isAlways(a.x(B1) == cos(theta)));
assert(isAlways(a.y(B1) == sin(theta)));
assert(isAlways(a.z(B1) == 0));
end

function test_overloads(~) % components, x,y,z
import anakin.*
syms t;
syms theta(t) phi(t);
assume([in(t, 'real'), in(theta(t), 'real'), in(phi(t), 'real')]);
a = vector([cos(theta),sin(theta),0]);
b = vector([0,cos(phi),sin(phi)]);
assert(all(a.components(B1) == [1;2;3]));
assert(a.x(B1) == 1);
assert(a.y(B1) == 2);
assert(a.z(B1) == 3);
assert(all(a.components == [-2;1;3]));
assert(a.x == -2);
assert(a.y == 1);
assert(a.z == 3);

a+b;a-b;+a;-a;2*a;a*2; 2.1 .*a;a.*2;a/2;2\a;a./2;21.2 .\a; % many overloaded operators
dot(a,b);
norm(a);
cross(a,b);
dir(a);
magnitude(a);
assert(a==a);
assert(a~=b);
if license('test','symbolic_toolbox')
syms t theta(t) phi(t);
assume([in(t, 'real'), in(theta(t), 'real'), in(phi(t), 'real')]);
B1 = basis([1,0,0],[0,cos(phi),sin(phi)],[0,-sin(phi),cos(phi)]);
a = vector([cos(theta),sin(theta),0],B1);

assert(isAlways(all(a.components(B1) == [cos(theta);sin(theta);0])));
assert(isAlways(a.x(B1) == cos(theta)));
assert(isAlways(a.y(B1) == sin(theta)));
assert(isAlways(a.z(B1) == 0));
end
end

function test_isa(~) % isunitary, isparallel, isperpendicular
import anakin.*
syms t;
syms theta(t) phi(t);
assume([in(t, 'real'), in(theta(t), 'real'), in(phi(t), 'real')]);
a = vector([cos(theta),sin(theta),0]);
b = vector([0,0,sin(phi)]);
c = 2*a;

assert(isunitary(a));
assert(~isunitary(c));
assert(isperpendicular(a,b));
assert(~isperpendicular(a,c));
assert(~isparallel(a,b));
assert(isparallel(a,c));
if license('test','symbolic_toolbox')
ii = 2;
else
ii = 1;
end

for i = 1:ii

if i == 1
a = vector(cos(pi/6),sin(pi/6),0);
b = vector(0,0,2.1);
elseif i == 2
syms t theta(t) phi(t);
assume([in(t, 'real'), in(theta(t), 'real'), in(phi(t), 'real')]);
a = vector([cos(theta),sin(theta),0]);
b = vector([0,0,sin(phi)]);
end
c = 2*a;

assert(isunitary(a));
assert(~isunitary(c));
assert(isperpendicular(a,b));
assert(~isperpendicular(a,c));
assert(~isparallel(a,b));
assert(isparallel(a,c));
end
end

function test_subs(~) % Particularize a symbolic vector
import anakin.*
syms t;
syms theta(t) phi(t) xi(t);
assume([in(t, 'real'), in(theta(t), 'real'), in(phi(t), 'real'),in(xi(t), 'real')]);
a = vector([cos(theta),sin(theta)+xi^2*sin(phi),xi*cos(phi)]);

c = a.subs({t,theta,phi,xi},{1,t^2-4,2*t+3,-2}); % call with cell arrays
c = a.subs([t,theta,phi,xi],[1,t^2-4,2*t+3,-2]); % call with arrays
if license('test','symbolic_toolbox')
import anakin.*
syms t;
syms theta(t) phi(t) xi(t);
assume([in(t, 'real'), in(theta(t), 'real'), in(phi(t), 'real'),in(xi(t), 'real')]);
a = vector([cos(theta),sin(theta)+xi^2*sin(phi),xi*cos(phi)]);

c = a.subs({t,theta,phi,xi},{1,t^2-4,2*t+3,-2}); % call with cell arrays
c = a.subs([t,theta,phi,xi],[1,t^2-4,2*t+3,-2]); % call with arrays
end
end

function test_timediff(~) % Time derivative wrt a given basis calling dt
import anakin.*
syms t;
syms theta(t) phi(t);
assume([in(t, 'real'), in(theta(t), 'real'), in(phi(t), 'real')]);
B0 = basis;
B1 = basis([1,0,0],[0,cos(phi),sin(phi)],[0,-sin(phi),cos(phi)]);
a = vector([cos(theta),sin(theta),0],B1);

assert(a.dt(B1) == vector(diff(theta,1)*[-sin(theta),cos(theta),0],B1)); % time derivative of a wrt B1
assert(a.dt(B0) == a.dt(B1) + cross(omega(B1,B0),a)); % time derivative of a wrt B0
if license('test','symbolic_toolbox')
import anakin.*
syms t;
syms theta(t) phi(t);
assume([in(t, 'real'), in(theta(t), 'real'), in(phi(t), 'real')]);
B0 = basis;
B1 = basis([1,0,0],[0,cos(phi),sin(phi)],[0,-sin(phi),cos(phi)]);
a = vector([cos(theta),sin(theta),0],B1);

assert(a.dt(B1) == vector(diff(theta,1)*[-sin(theta),cos(theta),0],B1)); % time derivative of a wrt B1
assert(a.dt(B0) == a.dt(B1) + cross(omega(B1,B0),a)); % time derivative of a wrt B0
end
end

function test_plot(~) % vector plotting
Expand Down

0 comments on commit 31f1432

Please sign in to comment.