MatLab - How to solve an indefinite integral and then define the limits? - matlab

I have an model to evaluate a thermodinamical process, it is made with Mathcad and I need it in MatLab.
It is a big equation that uses an integral thousand of times, each temperature uses an definite integral.
If I solve each time, the result is the same as Mathcad, but it takes hours, if I solve only once, it takes less than a second, but the result is wrong.
I split the equation and found that the error is in the part that is in the code.
How should I write my code to solve only one time the and get the right result?
clc
clear
FrCrist = FCrystFastWrong();
FrCrist = FCrystSlowRight();
function [Fvpa] = FCrystSlowRight()
tic;
syms T;
Part4 = (10^(-4.27+(3961/(T-751))));
i = 0;
for TempN = 996:1100
i = i+1;
TC(i) = TempN;
FintDef = int(Part4,T,[1000 TempN]);
Fvpa(i) = double(vpa(FintDef));
end
toc
plot(TC,Fvpa)
end
function [Fvpa] = FCrystFastWrong()
tic;
syms T;
Part4 = (10^(-4.27+(3961/(T-751))));
Fint = int(Part4,T);
qc = arrayfun(#char, Fint, 'uniform', 0);
qc = erase(qc,"int");
qc = erase(qc,", T");
qc = str2sym(qc);
f = inline(qc,'T');
i = 0;
for TempN = 996:1667
i = i+1;
TC(i) = TempN;
Solve(i) = f(TempN)-f(1000);
Fvpa(i) = Solve(i);
end
toc
plot(TC,Fvpa)
end

Related

Why does this not correctly evaluate e^x using the Taylor series?

I am attempting to write a function called expSeries which uses another function factFunc to evaluate e^x. I have already written the function factFunc, as shown below:
function fact = factFunc(n)
f = 1;
for a = 1:b
f = f*a;
end
fact = f;
end
I am now attempting to write the function expSeries which evaulates e^x using the Taylor series. This is what I have so far:
function expo = exponentialFunc(x)
terms = input('Enter the number of terms');
b = 0;
for i = 1:terms
b = x/factFunc(terms);
end
expo = b;
end
And in the main program, I have
n = exponentialFunc(4);
disp(n);
Where in this instance I am trying to find e^4. However, the output is not what expected. Does anyone have any idea where I am going wrong?
Fix to factFunc:
function fact = factFunc(n)
f = 1;
for a = 1:n
f = f*a;
end
fact = f;
end
Fix to exponentialFunc
function expo = exponentialFunc(x)
terms = input('Enter the number of terms');
b = 0;
for i = 0:terms-1
b = b + x^i/factFunc(i);
end
expo = b;
end
Example
>> exponentialFunc(4)
Enter the number of terms10
ans =
54.1541
Note exp(4) = 54.59815...

MATLAB plot failing due to Index exceeding matrix dimensions

I was wondering if someone could point out why I keep failing Test 1 and 2 despite my plot appearing as it should be.
My goal is to plot a bacteria population using three different K values on the same plot however I am failing due to the Index Exceeding Matrix Dimensions.
I am unsure what this means and how it relates to the plot.
I appreciate any help.
Thank you.
`function [bacteria_plot] = BacteriaPop(K,BacteriaPop)
C = 100;
r = 1;
t = 0:20;
K = 1000;
Kk = 3000;
kK = 5000;
BacteriaPop = (C.*exp(r.*t))./(1+(C./K).*exp(r.*t));
BacteriaPop = (C.*exp(r.*t))./(1+(C./Kk).*exp(r.*t));
BacteriaPop = (C.*exp(r.*t))./(1+(C./kK).*exp(r.*t));
hold on
plot(t,BacteriaPop)
end
`
[![Code, Plot and Error][2]][2]
Thanks to some help I have changed my code to
function [bacteria_plot] = bacteria_growth(K,Kk,kK,Y)
C = 100;
r = 1;
t = 0:20;
K = 1000;
Kk = 3000;
kK = 5000;
y(:,1) = (C.*exp(r.*t))./(1+(C./K).*exp(r.*t));
y(:,2) = (C.*exp(r.*t))./(1+(C./Kk).*exp(r.*t));
y(:,3) = (C.*exp(r.*t))./(1+(C./kK).*exp(r.*t));
hold on
plot(t,y)
hold off
end
It is still not perfect but it passed all the tests.
Any constructive criticism to streamline this code will be welcomed.

Matlab 2016b: looping with structures is much slower than with variables

I am computing a list of error statistics of a variable u. Whenever I put the structures in the loop, Matlab becomes superslow, while it is pretty fast with standard variables. I have heard that with Matlab 2016b one can either use loops or use vectorized notation, the speed should be the same. It looks like it does not work for structures. Do you know why? Best suggestion here? This is a minimal example ( I just used trivial "if" clauses, mine are more complex and that's the main reason why I don't vectorize):
n = 1000,
m = 1000;
uMODEL = rand(n,m);
uOBS = rand(n,m);
%
%
%
tic
ERRORS = struct('Emedio',0,'MAE',0,'sigma',0,'Emax',0,'Emin',0);
Nerr(1:max(n,1),1) = 0; %Nerr at most it contains n
fields = fieldnames(ERRORS);
for i = 1:numel(fields)
ERRORS.(fields{i}) = zeros(max(n,1),1);
end
for i=1:m
for j=1:n
if (1000>2 && 2000<343532)
diff = uMODEL(j,i)-uOBS(j,i);
ERRORS.Emedio(j) = ERRORS.Emedio(j) + diff;
ERRORS.MAE(j) = ERRORS.MAE(j) + abs(diff);
ERRORS.sigma(j) = ERRORS.sigma(j) + diff^2;
ERRORS.Emax(j) = max(ERRORS.Emax(j),diff);
ERRORS.Emin(j) = min(ERRORS.Emin(j),diff);
Nerr(n) = Nerr(n) + 1;
end
end
end
ERRORS.Emedio(:) = ERRORS.Emedio(:)./Nerr(:);
ERRORS.MAE(:) = ERRORS.MAE(:)./Nerr(:);
ERRORS.sigma(:) = sqrt(ERRORS.sigma(:)./(Nerr(:)-1));
toc
clear ERRORS
tic
%
% here instead I define variables, I fill them up and then I throw them in structures, cause loops with structures are strangely slow...
Emedio = zeros(max(n,1),1);
MAE = zeros(max(n,1),1);
sigma = zeros(max(n,1),1);
Nerr = zeros(max(n,1),1);
Emax = zeros(max(n,1),1);
Emin = zeros(max(n,1),1);
for i=1:m
for j=1:n
if (1000>2 && 2000<343532)
diff = uMODEL(j,i)-uOBS(j,i);
Emedio(j) = Emedio(j) + diff;
MAE(j) = MAE(j) + abs(diff);
sigma(j) = sigma(j) + diff^2;
Emax(j) = max(Emax(j),diff);
Emin(j) = min(Emin(j),diff);
Nerr(n) = Nerr(n) + 1;
end
end
end
Emedio(:) = Emedio(:)./Nerr(:);
MAE(:) = MAE(:)./Nerr(:);
sigma(:) = sqrt(sigma(:)./(Nerr(:)-1));
ERRORS.Emedio(:) = Emedio(:);
ERRORS.MAE(:) = MAE(:);
ERRORS.sigma(:) = sigma(:);
ERRORS.Emax(:) = Emax(:);
ERRORS.Emin(:) = Emin(:);
toc
the output is:
Elapsed time is 2.372765 seconds.
Elapsed time is 0.057719 seconds.

Fast rolling correlation in Matlab

I am trying to derive a function for calculating a moving/rolling correlation for two vectors and speed is a high priority, since I need to apply this function in an array function. What I have (which is too slow) is this:
Data1 = rand(3000,1);
Data2 = rand(3000,1);
function y = MovCorr(Data1,Data2)
[N,~] = size(Data1);
correlationTS = nan(N, 1);
for t = 20+1:N
correlationTS(t, :) = corr(Data1(t-20:t, 1),Data2(t-20:t,1),'rows','complete');
end
y = correlationTS;
end
I am thinking that the for loop could be done more efficiently if I knew how to generate the roling window indices and then applying accumarray. Any suggestions?
Following the advice from #knedlsepp, and using filter as in the movingstd, I found the following solution, which is quite fast:
function Cor = MovCorr1(Data1,Data2,k)
y = zscore(Data2);
n = size(y,1);
if (n<k)
Cor = NaN(n,1);
else
x = zscore(Data1);
x2 = x.^2;
y2 = y.^2;
xy = x .* y;
A=1;
B = ones(1,k);
Stdx = sqrt((filter(B,A,x2) - (filter(B,A,x).^2)*(1/k))/(k-1));
Stdy = sqrt((filter(B,A,y2) - (filter(B,A,y).^2)*(1/k))/(k-1));
Cor = (filter(B,A,xy) - filter(B,A,x).*filter(B,A,y)/k)./((k-1)*Stdx.*Stdy);
Cor(1:(k-1)) = NaN;
end
end
Comparing with my original solution the execution times are:
tic
MovCorr(Data1,Data2);
toc
Elapsed time is 1.017552 seconds.
tic
MovCorr1(Data1,Data2,21);
toc
Elapsed time is 0.019400 seconds.

use nested functions in matlab M-file

i have question,about which i am too much interested,suppose that i have two M-file in matlab, in the first one i have described following function for calculating peaks and peaks indeces
function [peaks,peak_indices] = find_peaks(row_vector)
A = [0 row_vector 0];
j = 1;
for i=1:length(A)-2
temp=A(i:i+2);
if(max(temp)==temp(2))
peaks(j) = row_vector(i);
peak_indices(j) = i;
j = j+1;
end
end
end
and in second M-file i have code for describing sinusoidal model for given data sample
function [ x ]=generate(N,m,A3)
f1 = 100;
f2 = 200;
T = 1./f1;
t = (0:(N*T/m):(N*T))';
wn = rand(length(t),1).*2 - 1;
x = 20.*sin(2.*pi.*f1.*t) + 30.*cos(2.*pi.*f2.*t) + A3.*wn;
end
my question is how to combine it together?one solution would be just create two M-file into folder,then call function from one M-file and made operation on given vector and get result,and then call second function from another M file on given result and finally get what we want,but i would like to build it in one big M-file,in c++,in java,we can create classes,but i am not sure if we can do same in matlab too,please help me to clarify everything and use find_peaks function into generate function
UPDATED:
ok now i would like to show simple change what i have made in my code
function [ x ] = generate(N,m,A3)
f1 = 100;
f2 = 200;
T = 1./f1;
t = (0:(N*T/m):(N*T))'; %'
wn = rand(length(t),1).*2 - 1;
x = 20.*sin(2.*pi.*f1.*t) + 30.*cos(2.*pi.*f2.*t) + A3.*wn;
[pks,locs] = findpeaks(x);
end
i used findpeaks built-in function in matlab,but i am getting following error
generate(1000,50,50)
Undefined function 'generate' for input arguments of type 'double'.
also i am interested what would be effective sampling rate to avoid alliasing?
You can simply put both in one file. The file must have the same name as the first function therein, and you will not be able to access subsequently defined functions from outside that file. See the MATLAB documentation on functions http://www.mathworks.co.uk/help/matlab/ref/function.html (particularly the examples section).
Also note that MATLAB has a built-in function findpeaks().
(By the way, you're still sampling at too low a frequency and will most certainly get aliasing - see http://en.wikipedia.org/wiki/Aliasing#Sampling_sinusoidal_functions )
Edit: As you requested it, here is some more information on the sampling theorem. A good and simple introduction to these basics is http://www.dspguide.com/ch3/2.htm and for further reading you should search for the Shannon/Nyquist sampling theorem.
Try with this, within a single MATLAB script
function test()
clc, clear all, close all
x = generate(1000,50,50);
[p,i] = find_peaks(x)
end
function x = generate(N,m,A3)
f1 = 100;
f2 = 200;
T = 1./f1;
t = (0:(N*T/m):(N*T))'; %'
wn = rand(length(t),1).*2 - 1;
x = 20.*sin(2.*pi.*f1.*t) + 30.*cos(2.*pi.*f2.*t) + A3.*wn;
end
function [peaks,peak_indices] = find_peaks(row_vector)
A = [0;row_vector;0];
j = 1;
for i=1:length(A)-2
temp=A(i:i+2);
if(max(temp)==temp(2))
peaks(j) = row_vector(i);
peak_indices(j) = i;
j = j+1;
end
end
end