Find rotation matrix with two vectors - matlab

I want to find the rotation matrix between two vectors.
[0;0;1] = R * [0.0023;0.0019;0.9899]
How do I find the 3*3 rotation matrix?

This is a simple rearrangement
% [0;0;1] = R * [0.0023;0.0019;0.9899];
% So ...
% [0;0;1] / [0.0023;0.0019;0.9899] = R
% This is a valid MATLAB command
R = [0;0;1] / [0.0023;0.0019;0.9899];
>> R =
[ 0 0 0
0 0 0
0 0 1.0102 ]
We can validate this result
R * [0.0023;0.0019;0.9899]
>> ans =
[0; 0; 1]

Your problem can be defined as a linear equation, say,
y = mx
where, y and x are matrices. Find m.
Solution:
m = x\y or m = mldivide(x,y)
Notice the backslash. It is not a forward slash / as Wolfie mentioned in his answer. For details see https://www.mathworks.com/help/matlab/ref/mldivide.html
Additional Details:
If x is a singular matrix, use pinv. See https://www.mathworks.com/help/matlab/ref/pinv.html for reference.

Related

Programming Finite Element Method

I am trying to teach myself how about Finite Element Methods.
All of my code is adapted from the following link pages 16-20
http://homepages.cae.wisc.edu/~suresh/ME964Website/M964Notes/Notes/introfem.pdf
I am programming along in Matlab to perform a finite element analysis on a single 8 node cube element. I have defined the xi,eta,zeta local axes (we can think about this as x, y, z for now), so I get the following shape functions:
%%shape functions
zeta = 0:.01:1;
eta = 0:.01:1;
xi = 0:.01:1;
N1 = 1/8*(1-xi).*(1-eta).*(1-zeta);
N2 = 1/8*(1+xi).*(1-eta).*(1-zeta);
N3 = 1/8*(1+xi).*(1+eta).*(1-zeta);
N4 = 1/8*(1-xi).*(1+eta).*(1-zeta);
N5 = 1/8*(1-xi).*(1-eta).*(1+zeta);
N6 = 1/8*(1+xi).*(1-eta).*(1+zeta);
N7 = 1/8*(1+xi).*(1+eta).*(1+zeta);
N8 = 1/8*(1-xi).*(1+eta).*(1+zeta);
The [N] Matrix is to be arranged like this according to the text I am reading:
%N Matrix
N= [N1 0 0 N2 0 0 N3 0 0 N4 0 0 N5 0 0 N6 0 0 N7 0 0 N8 0 0;
0 N1 0 0 N2 0 0 N3 0 0 N4 0 0 N5 0 0 N6 0 0 N7 0 0 N8 0;
0 0 N1 0 0 N2 0 0 N3 0 0 N4 0 0 N5 0 0 N6 0 0 N7 0 0 N8];
To find the [B] matrix i have to use the following [D] matrix:
%%Del Matrix for node i
%[ d/dx 0 0
% 0 d/dy 0
% 0 0 d/dz . . .
% d/dy d/dx 0
% 0 d/dz d/dy
% d/dz 0 d/dx ]
which is an operator to go on [N]. (B=DN)
Later on, as the text shows, I will be making calculations involving integrals of this [B] matrix over the volume of this element.
So, my question is, how can I store these polynomial shape functions in a matrix, operate on them with differentiation, and then integrate them numerically. I can tell with the way I have this set up right now, that it wont work because I have defined the functions as a vector over an interval [0,1] and then storing these vectors in the [N] matrix. Then using diff() function to differentiate appropriately to find the [B] matrix.
But since the matrix elements of [B] are now vectors over an interval [0,1] I think that is going to cause problems. How would you guys go about these calculations described in the textbook I posted above?
Solved my problem using anonymous functions and storing the polynomials in a symbolic matrix. example:
syms xi eta zeta
N1= ... %type out in terms of xi eta and zeta
.
.
.
dN1dXi = diff(N1,xi) %symbolic differentiation with respect to xi
can also perform symbolic integration when needed:
intN1 = int(N1,xi,lowerLimit,upperLimit) %symbolic integration with respect to xi
and when ready to substitute in actual values to evaluate the symbolic functions:
subs(N1,{xi,eta,zeta},{value1,value2,value3})
You should check page 24 about how to map from a parametric domain ([0,1]^) to the physical domain.
Although I think you can do as you said, using symbolic. I think symbolic calculation in Matlab is very time-consuming.
I would go for derivate N manually and store as dN, and use it when need it.
Regards,
German
after you have the shape functions you need to substitute it in the stiffness matrix, the stiffness matrix should be 24x24 as you have 24 degrees of freedom. to solve you need to build a linear system (Ax=b), the right hand side is based on the PDE you are solving and you have to include neuman boundary conditions in the right hand side plus the source term. In python for 2d element (4 DOF) will be like:
def shapefxncoef (Valxy):
#creating a temporary metrix to store zeros and get the size of the shape
#function matrix.
n_temp = np.zeros((4,4))
#filling the values of the matrix with a loop.
for i in range(4):
#the values used in the matrix are from the Valxy x and y components.
xi = Valxy [0, i];
yi = Valxy [1, i];
n_temp[i, 0] = 1;
n_temp[i, 1] = xi;
n_temp[i, 2] = yi;
n_temp[i, 3] = xi*yi;
#this gives an identity matrix and the stiffness matric can be derived
#if we take the inverse.
n = np.linalg.inv(n_temp);
return n;
def N (Valxy, x, y):
n = shapefxncoef (Valxy);
res = n[0, :] + n[1, :]*x + n[2, :]*y + n[3, :]*x*y;
return res;
def Be (Valxy, x, y):
res = np.zeros ((2,4));
res_temp = shapefxncoef (Valxy);
for i in range (4):
res_tempi = res_temp[:, i];
dNix = res_tempi[1] + res_tempi[3]*y;
dNiy = res_tempi[2] + res_tempi[3]*x;
res[0, i] = dNix;
res[1, i] = dNiy;
return res;
def Ke (Valxy, conduct):
a = lambda x, y: conduct * np.dot ((Be(Valxy, x, y)).T, Be(Valxy, x, y));
k = intr.integrateOnQuadrangle (Valxy.T, a, np.zeros((4,4)));
return k;

How to vectorize the evaluation of a quadratic form (x' * A * x)?

If I have a matrix A and I want to evaluate x' * A * x for multiple values of x, how can I vectorize this?
(I could do X' * A * X and take the diagonal, but this is clearly inefficient.)
One way to think about it is that you are trying to take a bunch of dot products between the vectors in X and the vectors in AX. Matlab has a function for that:
N = 10; % number of x's
M = 100; % length of x's
X = rand(M,N);
A = rand(M, M);
% way 1
way1 = diag(X' * A * X);
% way 2
way2 = dot(X, A*X)';
% compare
[way1 way2]
How about this?
sum((A*X).*X,1)
Or, if you are dealing with complex values,
sum((A*X).*conj(X),1)
Check:
>> A = rand(4,4);
>> X = rand(4,3);
>> sum((A*X).*X,1)
ans =
5.4755 2.6205 3.4803
>> diag(X'*A*X)
ans =
5.4755
2.6205
3.4803
This could be one approach, though not sure if this would be more efficient than the direct matrix multiplication + diag based approach -
%// Perform X'*A equivalent multiplication
mult1 = bsxfun(#times,permute(X,[1 3 2]),A)
%// Perform rest of the equivalent multiplication
mult2 = bsxfun(#times,mult1,permute(X,[3 1 2]))
%// Perform the summations required to reduce to desired output's size
out = sum(reshape(mult2,[],size(X,2)),1)
You can re-arrange the multiplications a bit -
mult1 = bsxfun(#times,permute(X,[1 3 2]),permute(X,[3 1 2]))
mult2 = bsxfun(#times,mult1,A)
out = sum(reshape(mult2,[],size(X,2)),1)
Or merge the ending bsxfun(#times and sum with a bit more simplified and maybe more efficient version -
mult1 = bsxfun(#times,permute(X,[1 3 2]),permute(X,[3 1 2]))
out = reshape(permute(mult1,[3 1 2]),size(X,2),[])*A(:)
Or simplify it further to make it a one-liner that uses minimal of tools and could be the most efficient of the lot! -
out = reshape(bsxfun(#times,X.',permute(X,[2 3 1])),[],numel(A))*A(:)
In numpy, you can do np.einsum('ij,jk,ki->i',np.transpose(X),A,X).

Finding sub-matrix with minimum elementwise sum

I have a symmetric m-by-m matrix A. Each element has a value between 0 and 1. I now want to choose n rows / columns of A which form an n-by-n sub-matrix B.
The criteria for choosing these elements, is that the sum of all elements of B must be the minimum out of all possible n-by-n sub-matrices of A.
For example, suppose that A is a 4-by-4 matrix:
A = [0 0.5 1 0; 0.5 0 0.5 0; 1 0.5 1 1; 0 0 1 0.5]
And n is set to 3. Then, the best B is the one taking the first, second and fourth rows / columns of A:
B = [0 0.5 0; 0.5 0 0; 0 0 0.5]
Where the sum of these elements is 0 + 0.5 + 0 + 0.5 + 0 + 0 + 0 + 0 + 0.5 = 1.5, which is smaller than another other possible 3-by-3 sub-matrices (e.g. using the first, third and fourth rows / columns).
How can I do this?
This is partly a mathematics question, and partly a Matlab one. Any help with either would be great!
Do the following:
m = size(A,1);
n=3;
sub = nchoosek(1:m,n); % (numCombinations x n)
subR = permute(sub,[2,3,1]); % (n x 1 x numCombinations), row indices
subC = permute(sub,[3,2,1]); % (1 x n x numCombinations), column indices
lin = bsxfun(#plus,subR,m*(subC-1)); % (n x n x numCombinations), linear indices
allB = A(lin); % (n x n x numCombinations), all possible Bs
sumB = sum(sum(allB,1),2); % (1 x 1 x numCombinations), sum of Bs
sumB = squeeze(sumB); % (numCombinations x 1), sum of Bs
[minB,minBInd] = min(sumB);
fprintf('Indices for minimum B: %s\n',mat2str(sub(minBInd,:)))
fprintf('Minimum B: %s (Sum: %g)\n',mat2str(allB(:,:,minBInd)),minB)
This looks only for submatrices where the row indices are the same as the column indices, and not necessarily consecutive. That is how I understood the question.
This is a bit brute force, but should work
A = [0 0.5 1 0; 0.5 0 0.5 0; 1 0.5 1 1; 0 0 1 0.5];
sizeA = size(A,1);
size_sub=3;
idx_combs = nchoosek(1:sizeA, size_sub);
for ii=1:size(idx_combs,1)
sub_temp = A(idx_combs(ii,:),:);
sub = sub_temp(:,idx_combs(ii,:));
sum_temp = sum(sub);
sums(ii) = sum(sum_temp);
end
[min_set, idx] = min(sums);
sub_temp = A(idx_combs(idx,:),:);
sub = sub_temp(:,idx_combs(idx,:))
Try to convolve the matrix A with a smaller matrix M. Eg if you is interested in finding the 3x3 submatrix then let M be ones(3). This code shows how it works.
A = toeplitz(10:-1:1) % Create a to eplitz matrix (example matrix)
m = 3; % Submatrix size
mC = ceil(m/2); % Distance to center of submatrix
M = ones(m);
Aconv = conv2(A,M); % Do the convolution.
[~,minColIdx] = min(min(Aconv(1+mC:end-mC,1+mC:end-mC))); % Find column center with smallest sum
[~,minRowIdx] = min(min(Aconv(1+mC:end-mC,minColIdx+mC),[],2)); % Find row center with smlest sum
minRowIdx = minRowIdx+mC-1 % Convoluted matrix is larger than A
minColIdx = minColIdx+mC-1 % Convoluted matrix is larger than A
range = -mC+1:mC-1
B = A(minRowIdx+range, minColIdx+range)
The idea is to imitate a fir filter y(n) = 1*x(n-1)+1*x(n)+1*x(n+1). For now it only finds the first smallest matrix though. Notice the +1 adjustment because first matrix element is 1. Then notice the the restoration right below.

Solving a difference equation with initial condition

Consider a difference equation with its initial conditions.
5y(n) + y(n-1) - 3y(n-2) = (1/5^n) u(n), n>=0
y(n-1) = 2, y(n-2) = 0
How can I determine y(n) in Matlab?
Use an approach similar to this (using filter), but specifying initial conditions as done here (using filtic).
I'm assuming your initial conditions are: y(-1)=2, y(-2)=0.
num = 1; %// numerator of transfer function (from difference equation)
den = [5 1 -3]; %// denominator of transfer function (from difference equation)
n = 0:100; %// choose as desired
x = (1/5).^n; %// n is >= 0, so u(n) is 1
y = filter(num, den, x, filtic(num, den, [2 0], [0 0]));
%// [2 0] reflects initial conditions on y, and [0 0] those on x.
Here's a plot of the result, obtained with stem(n,y).
The second line of your code does not give initial conditions, because it refers to the index variable n. Since Matlab only allows positive integer indices, I'll assume that you mean y(1) = 0 and y(2) = 2.
You can get an iteration rule out of your first equation by simple algebra:
y(n) = ( (1/5^n) u(n) - y(n-1) + 3y(n-2) ) / 5
Code to apply this rule in Matlab:
n_max = 100;
y = nan(n_max, 1);
y(1) = 0;
y(2) = 2;
for n = 3 : n_max
y(n) = ( (1/5^n) * u(n) - y(n-1) + 3 * y(n-2) ) / 5;
end
This code assumes that the array u is already defined. n_max specifies how many elements of y to compute.

What's wrong here and how can I calculate autocorrelation?

f1 = 1 ;
N = 1024 ;
fs = 200 ;
ts = 1/fs ;
t = -(N/(2*fs)):ts:(N/(2*fs)) ;
theta=rand(0:2*pi);
X = sin(2*pi*f1*t+theta) ;
plot(t,x)
grid
Error using +
Matrix dimensions must agree.
And how can i calculate the autocorrelation of x function Rxx(n) ?
Replace the theta line by
theta = 2*pi*rand; %// generates a random number between 0 and 2*pi
and the plot line by
plot(t, X); %// capital "X", as you have defined previously
For the autocorrelation, you can use conv (correlation for real signals is equivalent to convolution with a time-reversal):
c = conv(X,fliplr(X));
plot(-(N/fs):ts:(N/fs), c)
To add to what Luis Mendo has answered, the reason for the error message is that:
>> size(t)
ans =
1 1025
>> size(theta)
ans =
0 1 2 3 4 5 6
So you are trying to add two things which are not the same dimension in X = sin(2*pi*f1*t+theta), hence the error message.
Use Luis's suggestions to fix your code.