Matlab: implementing sum of exponentials using function handles - matlab

I need to implement the following formula using function handles in Matlab
where t is the time vector and n is large. Also, Sk and fk are constant for each k. Any efficient way to implement this is appreciated.
Edit:
For the first harmonic, I could write
y=#(t) s(1)*exp(i*2*pi*f(1)*t);
However, I can not use this in a for loop to generate f(t). Is there a vector approach for doing this?

Assuming you have a data vector s, a frequency vector f of the same length, and a time vector t of a (potentially) different length, you can compute the given equation using
result = sum( s(:) .* exp( i*2*pi * f(:) .* t(:).' ), 1 );
What is happening here is s(:) forces s to be a column vector. We make f into a column vector in the same way. t(:).' is a row vector. MATLAB does implicit singleton expansion, so that f(:) .* t(:).' returns a 2D matrix. The other .* also does singleton expansion for s. Finally sum(.,1) sums over the fist dimension, which is over all values of f. The result is a row vector of the same length as t.
If you need a function handle that computes this, simply turn the one-liner into an anonymous function:
y = #(t) sum( s(:) .* exp( i*2*pi * f(:) .* t(:).' ), 1 );
This anonymous function will capture s and f as they exist when defining it. t can be supplied later:
result = y(t);
But do note that ifft does the same computation but much more efficiently.

Related

Efficient Manipulation of Cell Array of Gridded Data Interpolant in Matlab

I have vectors Ll, Lh, x, and alp of sizes NL, NL, Nx, and Nalp, respectively. I also have a matrix G of size NL * NL * Nx * Nalp. G is a function of Ll, Lh, x, and alp. Together, I have gridded arrays and sample values in G.
For each x and alp, I create an interpolant and store in a cell array. See below code snippet:
for ixs=1:Nx
for ias=1:Nalp
Gn(:,:,ixs, ias)={griddedInterpolant({Ll, Lh}, G(:,:,ixs, ias),'linear', 'none')};
end
end
Pros: Compared to interp2, this is very fast especially because I have to evaluate Gn by a great number of times.
Cons: (1) Requires a great deal of memory, and (2) Cannot be easily vectorized so as to avoid an additional loop of the following kind (which is again evaluated many many times)
for ixs=1:Nx
for ias=1:Nalp
GGn=Gn{:,:, ixs, ias};
SomeVector(ixs, ias)*GGn(Llnx, Lhnx);
end
end
(a) If I could somehow vectorize the whole class of griddedInterpolant named Gn, I could optimize on the last loop, and (b) If I could store the vector Ll, and Lh only once, I could use memory more efficiently.
I need your help. Precisely, how can I do this more efficiently? Thank you.
Best,
BK
EDIT:
A solution would be to generate a function Gn which takes Ll and Lh as arguments, given x and alp. Gn returns an array of functional handles, one for each (x, alph). Then, calling Gn(Llnx, Lhnx, x, alp) returns the interpolated value. Now, (Llnx, Lhnx, x, alp) can each be arrays of the same number of elements. Any efficient way that uses professional's code?
Using the method provided here you can pre-compute weights for multidimensional linear interpolation. So you don't need griddedInterpolant and use bsxfun to vectorize computation of interpolation using the precomputed weights.
[W I]=lininterpnw(Ll, Lh, Llnx, Lhnx);
GGn = reshape(G,NL* NL,[]);
result = squeeze(sum(bsxfun(#times, W, reshape(GGn(I(:),:),size(G)))));
bsxfun(#times, reshape(SomeVector,1,[]), result);
Each column in the result matrix is the output of the interpolation of each 2D matrix.
Here assumed that 1Ll, Lh, Llnx, Lhnx are row vectors.

Octave: For-loop error says A(I) = X: X must have the same size as I

I need to evaluate the integral from x=-1 to x=1 for the function x*e^(x)*sin(pi*x). To do so, I'm using the Gaussian Quadrature method. This method can be summarized as the summation of the (weights)*(function evaluated at given roots) from k=1 to k=n where n=30.
In my code below, the roots are found in the column vector LegendreGaussQuadratureConstants(n).x. I'm taking the transpose because I want to perform element by element multiplication on the weights, which are stored in the row vector LegendreGaussQuadratureConstants(n).w
My code:
fx = #(x) x .* e.^(-x) .* sin(pi .* x);
for k = 1:50
Leg(k) = (fx(LegendreGaussQuadratureConstants(k).x))' .* LegendreGaussQuadratureConstants(k).w;
endfor
The problem is that it's giving me the error in the title, implying that there is some problem with using a scalar value of k and that it should match up with the size of values being multiplied, but that makes no sense...
You said it yourself in your question
the roots are found in the column vector LegendreGaussQuadratureConstants(n).x. I'm taking the transpose because I want to perform element by element multiplication on the weights, which are stored in the row vector LegendreGaussQuadratureConstants(n).w.
You're taking the element-wise product of two vectors and the result is also going to be a vector. However, you then try to assign it to a scalar, Leg(k) which produces your error.
You either need to store these vectors in a 2D version of Leg
for k = 1:50
Leg(k,:) = (fx(LegendreGaussQuadratureConstants(k).x))' .* LegendreGaussQuadratureConstants(k).w;
endfor
or perform some other operation on the element-wise multiplication result to get it to be a scalar.
for k = 1:50
Leg(k) = sum((fx(LegendreGaussQuadratureConstants(k).x))' .* LegendreGaussQuadratureConstants(k).w);
endfor

Square wave function for Matlab

I'm new to programming in Matlab. I'm trying to figure out how to calculate the following function:
I know my code is off, I just wanted to start with some form of the function. I have attempted to write out the sum of the function in the program below.
function [g] = square_wave(n)
g = symsum(((sin((2k-1)*t))/(2k-1)), 1,n);
end
Any help would be much appreciated.
Update:
My code as of now:
function [yout] = square_wave(n)
syms n;
f = n^4;
df = diff(f);
syms t k;
f = 1; %//Define frequency here
funcSum = (sin(2*pi*(2*k - 1)*f*t) / (2*k - 1));
funcOut = symsum(func, v, start, finish);
xsquare = (4/pi) * symsum(funcSum, k, 1, Inf);
tVector = 0 : 0.01 : 4*pi; %// Choose a step size of 0.01
yout = subs(xsquare, t, tVector);
end
Note: This answer was partly inspired by a previous post I wrote here: How to have square wave in Matlab symbolic equation - However, it isn't quite the same, which is why I'm providing an answer here.
Alright, so it looks like you got the first bit of the question right. However, when you're multiplying things together, you need to use the * operator... and so 2k - 1 should be 2*k - 1. Ignoring this, you are symsuming correctly given that square wave equation. The input into this function is only one parameter only - n. What you see in the above equation is a Fourier Series representation of a square wave. A bastardized version of this theory is that you can represent a periodic function as an infinite summation of sinusoidal functions with each function weighted by a certain amount. What you see in the equation is in fact the Fourier Series of a square wave.
n controls the total number of sinusoids to add into the equation. The more sinusoids you have, the more the function is going to look like a square wave. In the question, they want you to play around with the value of n. If n becomes very large, it should start approaching what looks like to be a square wave.
The symsum will represent this Fourier Series as a function with respect to t. What you need to do now is you need to substitute values of t into this expression to get the output amplitude for each value t. They define that for you already where it's a vector from 0 to 4*pi with 1001 points in between.
Define this vector, then you'll need to use subs to substitute the time values into the symsum expression and when you're done, cast them back to double so that you actually get a numeric vector.
As such, your function should simply be this:
function [g] = square_wave(n)
syms t k; %// Define t and k
f = sin((2*k-1)*t)/(2*k-1); %// Define function
F = symsum(f, k, 1, n); %// Define Fourier Series
tVector = linspace(0, 4*pi, 1001); %// Define time points
g = double(subs(F, t, tVector)); %// Get numeric output
end
The first line defines t and k to be symbolic because t and k are symbolic in the expression. Next, I'll define f to be the term inside the summation with respect to t and k. The line after that defines the actual sum itself. We use f and sum with respect to k as that is what the summation calls for and we sum from 1 up to n. Last but not least, we define a time vector from 0 to 4*pi with 1001 points in between and we use subs to substitute the value of t in the Fourier Series with all values in this vector. The result should be a 1001 vector which I then cast to double to get a numerical result and we get your desired output.
To show you that this works, we can try this with n = 20. Do this in the command prompt now:
>> g = square_wave(20);
>> t = linspace(0, 4*pi, 1001);
>> plot(t, g);
We get:
Therefore, if you make n go higher... so 200 as they suggest, you'll see that the wave will eventually look like what you expect from a square wave.
If you don't have the Symbolic Math Toolbox, which symsum, syms and subs relies on, we can do it completely numerically. What you'll have to do is define a meshgrid of points for pairs of t and n, substitute each pair into the sequence equation for the Fourier Series and sum up all of the results.
As such, you'd do something like this:
function [g] = square_wave(n)
tVector = linspace(0, 4*pi, 1001); %// Define time points
[t,k] = meshgrid(tVector, 1:n); %// Define meshgrid
f = sin((2*k-1).*t)./(2*k-1); %// Define Fourier Series
g = sum(f, 1); %// Sum up for each time point
end
The first line of code defines our time points from 0 to 4*pi. The next line of code defines a meshgrid of points. How this works is that for t, each column defines a unique time point, so the first column is 200 zeroes, up to the last column which is a column of 200 4*pi values. Similarly for k, each row denotes a unique n value so the first row is 1001 1s, followed by 1001 2s, up to 1001 1s. The implications with this is now each column of t and k denotes the right (t,n) pairs to compute the output of the Fourier series for each time that is unique to that column.
As such, you'd simply use the sequence equation and do element-wise multiplication and division, then sum along each individual column to finally get the square wave output. With the above code, you will get the same result as above, and it'll be much faster than symsum because we're doing it numerically now and not doing it symbolically which has a lot more computational overhead.
Here's what we get when n = 200:
This code with n=200 ran in milliseconds whereas the symsum equivalent took almost 2 minutes on my machine - Mac OS X 10.10.3 Yosemite, 16 GB RAM, Intel Core i7 2.3 GHz.

Matlab: definite integral of numerical vectors

i'm looking for to solve a definite integral of two vectors, I try to explain.
I know: z vector of numbers and G(z) vector of numbers.
The limits of integration are zmin and zmax
I should to calculate:
Integral between zmin,zmax of [G(z) * z^(7/6)] dz
Could I solve with the following code?
For i = zmin:zmax
myresult = G(z(i))*z(i)^(7/6)
end
(wrote before)
You can use numerical integral.
Define G(z) as a function handle, and the function to be integrated as
another one. You can find an example in my other answer.
So your goal is to calculate the sum of [G(z) * z^(7/6)] * dz, where G(z) and z are pre-calculated numerical vectors, dz a small increment value.
dz = (zmax - zmin) / length(G(z));
S = G * z' * dz;
S should be the result. Let me explain.
First of all, I messed up with G(z) previously (apologize for that). You have already evaluated (partially) the function to integrate, namely G(z) and z.
G(z) and z are number arrays. Arrays are indexed by integer, starting from 1. So G(z(i)) may not be a valid expression, as z(i) haven't been guaranteed to be integers. The code above only works correctly if you have defined G(z) in this way - G(i) = some_function (z(i));. By so each element of the same index in two arrays have a meaningful relation.
There are several ways to evaluate the product of two arrays (vectors), generating a single-value sum. A for loop works, but is inefficient. G * z' is the way to calc vector dot product.

'Multiplying' arrays in MATLAB

First off, I didn't know what to put as title, since the question is not easy to formulate shortly.
I need to convolve a matrix-valued function (k) with a vector-valued function (X), each of which is defined on R^3. I need to to this in MATLAB, so naturally I will do the discretized version. I plan on representing k and X by 5- and 4-dimensional arrays, respectively. This seems a bit heavy though. Do you know if there are any better ways to do it?
Instead of doing the convolution directly, I will go to Fourier space by fft'ing both k and X, pad with zeros, multiply them and then use ifft. That should produce the same result and run much, much faster.
My question here is whether there is any way to multiply these arrays/matrices easily? I.e. is there any way to do k(i,j,k,:,:)*X(i,j,k,:) for all i,j,k, without using three nested loops?
Do you need to discretize? Matlab is perfectly capable of taking functions as input and output. For examples, you could define a convolution function:
>> convolve = #(fm,fv) #(x) fm(x) * fv(x); %fm matrix valued, fv vector valued
and define some matrix-valued and vector-valued functions (this assumes the input is a column vector)
>> f = #(x) [x x x];
>> g = #(x) cos(x);
now their convolution:
>> h = convolve(f,g);
and try applying it to a vector:
>> h([1;2;3])
ans =
-0.8658
-1.7317
-2.5975
You get the same answer as if you did the operation manually:
>> f([1;2;3]) * g([1;2;3])
ans =
-0.8658
-1.7317
-2.5975
You perform element-by-element operation by using . together with the operator of choice. For example:
Element-by-element multiplication: .*
Element-by-element division: ./
and so on... is that what you mean?