Defining a Differential Equation in Octave - octave

I am attempting to use Octave to solve for a differential equation using Euler's method.
The Euler method was given to me (and is correct), which works for the given Initial Value Problem,
y*y'' + (y')^2 + 1 = 0; y(1) = 1;
That initial value problem is defined in the following Octave function:
function [YDOT] = f(t, Y)
YDOT(1) = Y(2);
YDOT(2) = -(1 + Y(2)^2)/Y(1);
The question I have is about this function definition. Why is YDOT(1) != 1? What is Y(2)?
I have not found any documentation on the definition of a function using function [YDOT] instead of simply function YDOT, and I would appreciate any clarification on what the Octave code is doing.

First things first: You have a (non linear) differential equation of order two which will require you to have two initial conditions. Thus the given information from above is not enough.
The following is defined for further explanations: A==B means A is identical to B; A=>B means B follows from A.
It seems you are mixing a few things. The guy who gave you the files rewrote the equation in the following way:
y*y'' + (y')^2 + 1 = 0; y(1) = 1; | (I) y := y1 & (II) y' := y2
(I) & (II)=>(III): y' = y2 = y1' | y2==Y(2) & y1'==YDOT(1)
Ocatve is "matrix/vector oriented" so we are writing everything in vectors or matrices. Rather writing y1=alpha and y2=beta we are writing y=[alpha; beta] where y(1)==y1=alpha and y(2)==y2=beta. You will soon realize the tremendous advantage of using especially this mathematical formalization for ALL of your problems.
(III) & f(t,Y)=>(IV): y2' == YDOT(2) = y'' = (-1 -(y')^2) / y
Now recall what is y' and y from the definitions in (I) and (II)!
y' = y2 == Y(2) & y = y1 == Y(1)
So we can rewrite equation (IV)
(IV): y2' == YDOT(2) = (-1 -(y')^2) / y == -(1 + Y(2)^2)/Y(1)
So from equation (III) and (IV) we can derive what you already know:
YDOT(1) = Y(2)
YDOT(2) = -(1 + Y(2)^2)/Y(1)
These equations are passed to the solver. Differential equations of all types are solved numerically by retrieving the "next" value in a near neighborhood to some "previously known" value. (The step size inside this neighborhood is one of the key questions when writing solvers!) So your solver uses your initial condition Y(1)==y(1)=1 to make the next step and calculate the "next" value. So right at the start YDOT(1)=Y(2)==y(2) but you didn't tell us this value! But from then on YDOT(1) is varied by the solver in dependency to the function shape to solve your problem and give you ONE unique y(t) solution.
It seems you are using Octave for the first time so let's make a last comment on function [YDOT] = f(t, Y). In general a function is defined in this way:
function[retVal1, retVal2, ...] = myArbitraryName(arg1, arg2, ...)
Where retVal is the return value or output and arg is the argument or input.

Related

Duplicating functions in Julia

I need to overwrite a function based on its previous definition, and this leads to a stackoverflow error.
I have tried with deepcopy(f), but it just returns a reference to f, so this doesn't work.
What I need to be able to do over and over is:
Old(x) = pdf(Uniform(),x)
New(x) = updating_function(Old, Y1)
Old(x) = deepcopy(New(x))
New(x) = updating_function(Old, Y2)
[...]
EDIT:
My overall goal is to have a function that takes a prior distribution and spits out a posterior with an unusual signal structure due to my application.
A simple running example of this would be
Old_pdf(x)= pdf(Uniform(),x)
Old_mean=0.5
function BU(d,low)
value, tol = quadgk(Old_pdf, Old_λ, 1)
truncated(λ)=d(λ)/value
end
Newpdf=BU(Old_pdf,Old_mean)
Old_mean, tol= quadgk(x -> Newpdf(x)*x, Old_mean, 1)
Old_pdf=BU(Old_pdf,Old_mean)
I know that this example could be addressed with functions from the Distributions package. It's not the case for my application.
I have found this question and read the documentation of the IRTools package, but I am unable to make this work. In particular when I try
Old(x) = pdf(Uniform(),x)
New(x) = updating_function(Old, Y1)
const Old_ir= IRTools.Inner.code_ir(New, Tuple{Int})
Old(x) = IRTools.func(Old_ir)
I obtain an object that doesn't behave like a function, hence generates methods error in the rest of the code. I made several attempts at this, and it is entirely possible that I am missing something trivial.
Y1 = 5.0
Y2 = 7.0
updating_function(f1,c) = x -> 2.0 * f1(x) + c
Old = x->sqrt(x)
New = updating_function(Old, Y1)
Old = New
New = updating_function(Old, Y2)
I think you just need anonymous functions:
function BU(f, λ, y)
# I guess here you would use the observations `y` in some way?
z, _ = quadgk(f, λ, 1)
return λ -> f(λ) / z
end
mean(f, λ) = quadgk(x -> f(x) * x, λ, 1)[1]
original_pdf(x) = pdf(Uniform(), x)
f = original_pdf
λ = 0.5
for y in Y
f = BU(f, λ, y)
λ = mean(f, λ)
end
Now I tried very hard, and I think I understand what you're doing, but the example you gave wasn't very clear. Consider this conceptual.
Such things make nice folds, by the way.

Octave, finding the maximum of a numeric function

I am trying to compute the maximum value of the solution of a system with two ODEs using Octave. I have firstly solved the system itself:
function xdot = f (x,t)
a1=0.00875;
a2=0.075;
b1=7.5;
b2=2.5;
d1=0.0001;
d2=0.0001;
g=4*10^(-8);
K1=5000;
K2=2500;
n=2;
m=2;
xdot = zeros(2,1);
xdot(1) = a1+b1*x(1)^n/(K1^n+x(1)^n)-g*x(1)*x(2)-d1*x(1);
xdot(2) = a2+b2*x(1)^m/(K2^m+x(1)^m)-d2*x(2);
endfunction
t = linspace(0, 5000, 200)';
x0 = [1000; 1000];
x = lsode ("f", x0, t);
set term dumb;
plot(t,x);
But now I do not know how to compute the maximum value of the two functions (numerical ones) obtained as solutions of the system. I have searched in the Internet but I haven't found what I want... I only have found the function fminbnd for the minimum of a function on an interval...
Is it possible to compute the maximum value of a numeric function with Octave?
Generally, if you know how to find the minimum of a function, you also know how to find its maximum: just look for the minimum of -f.
However, fminbnd is designed for functions that can be evaluated at any given point. What you have is just a vector of 200 points. In principle, you could use interpolation to get a function and then maximize that. But this is not really needed, because all the information you have is in that matrix x anyway, so it makes sense to just take the maximum value there. Like this:
[x1m, i1] = max(x(:,1));
[x2m, i2] = max(x(:,2));
disp(sprintf('Maximum of x1 is %f attained at t = %f', x1m, t(i1)));
disp(sprintf('Maximum of x1 is %f attained at t = %f', x2m, t(i2)));

administer drug dose at certain time step in octave

I am doing a simple task on ocatve.
I have to administer drug dose at day 1,7,21 and 28..
i wrote a function like that:
function xdot = f (x,t)
a=[1;7;21;28]
drug=0; ### initially drug is zero
if (t==a)
drug=drug+57.947;
else
drug=drug+0;
endif
xdot=(-0.4077)*(x)+ drug; passing the value of drug to differential equation
endfunction
In the main file i called this function in lsode:
t=linspace(0,30,30);
x0=0;
y=lsode(#ex,x0,t); ### ex is the file name where function is written
plot(t,y,'o')
This program doesn't work.. it displays all the time zero value for drug. Can anybody help me that how to administer dug dose with certain time step by manipulating linspace function.
It looks like you have a simple clearance model, and at each time in a, you want the dose to be delivered instantaneously. That is, at each time in a, the amount of drug in the subject increases by 57.947.
If that is the model that you have in mind, implementing it in the formula for xdot will not work well. You would actually need to implement it as a "delta function", and lsode won't work with that.
Instead, I recommend solving the problem in stages, corresponding to the time intervals [0, 1], [1, 7], [7, 21], and [21, 28]. During one stage, the differental equation is simply xdot = -0.4077*x. In the first stage, the initial condition is 0. In the next stage, the initial condition is the final value of the previous stage plus the dosage amount 57.947.
Here's a script:
dose = 57.947;
a = [1 7 21 28 30];
x0 = 0.0;
t0 = 0;
t = [];
y = [];
for t1 = a
tinterval = linspace(t0, t1, 2*(t1 - t0) + 1);
yinterval = lsode(#(x, t) -0.4077*x, x0, tinterval);
t = [t tinterval];
y = [y yinterval'];
t0 = t1;
x0 = yinterval(end) + dose;
end
plot(t, y, "linewidth", 2);
The script creates this plot:
Note that the differential equation xdot = -k*x has the solution x0*exp(-k*(t-t0)), so the call to lsode could be replaced with
yinterval = x0*exp(-0.4077*(tinterval - t0));
If you do this, also remove the transpose from yinterval two lines below:
y = [y yinterval];
If you want to keep the implementation of the administration of the drug dose within the formula for xdot, you'll need to distribute it over a small time interval. It could be implemented as a short rectangular pulse of width w and height 57.974/w. You'll also need to ensure that lsode takes sufficiently small internal time steps (less than w) so that it "sees" the drug dose.
You probably want replace t==a by ismember (t, a). Also, you should erase the else clause as it has no effect on the answer.
UPDATE
Consider rewriting your function as:
function xdot = f (x,t)
xdot = -0.4077*x + 57.947*ismember (t, [1 7 21 28])
endfunction

Creating a function from a 2D array in MATLAB (For use in ode45)

I am a first time MATLAB user. I have a 2d array of t vs f in MATLAB. This 2d array correponds to a function, say f(t). I am using ode45 to solve a set of differential equations and f(t) is one of the coefficients i.e. I have a set of equations of the form x'(t)=f(t)x(t) or variations thereof. How do I proceed?
I need a way to convert my array of t vs f into a function that can be used in the ode45 method. Presumably, the conversion will do some linear interpolation and give me the equation of the best fit curve.
Or if there is another approach, I'm all ears!
Thank you!
This is a simple example with passing function as a parameter to right hand side of the ODE. Create files in the same directory and run main
main.m
t = 0:0.2:10; f = sin(t);
fun = #(xc) interp1(t, f, xc);
x0=0.5
% solve diff(x, t)=sin(t)
% pass function as parameter
[tsol, xsol] = ode45(#(t, x) diff_rhs(t, x, fun),[0.0 8.0], 0.5);
% we solve equation dx/dt = sin(x), x(0)=x0
% exact solution is x(t) = - cos(t) + x(0) + 1
plot(tsol, xsol, 'x');
hold on
plot(tsol, -cos(tsol) + x0 + 1, '-');
legend('numerical', 'exact');
diff_rhs.m
function dx = diff_rhs(t, x, fun)
dx = fun(t);
end
References in the documentation: interp1 and anonymous Functions.

summing functions handles in matlab

Hi
I am trying to sum two function handles, but it doesn't work.
for example:
y1=#(x)(x*x);
y2=#(x)(x*x+3*x);
y3=y1+y2
The error I receive is "??? Undefined function or method 'plus' for input arguments of type 'function_handle'."
This is just a small example, in reality I actually need to iteratively sum about 500 functions that are dependent on each other.
EDIT
The solution by Clement J. indeed works but I couldn't manage to generalize this into a loop and ran into a problem. I have the function s=#(x,y,z)((1-exp(-x*y)-z)*exp(-x*y)); And I have a vector v that contains 536 data points and another vector w that also contains 536 data points. My goal is to sum up s(v(i),y,w(i)) for i=1...536 Thus getting one function in the variable y which is the sum of 536 functions. The syntax I tried in order to do this is:
sum=#(y)(s(v(1),y,z2(1)));
for i=2:536
sum=#(y)(sum+s(v(i),y,z2(i)))
end
The solution proposed by Fyodor Soikin works.
>> y3=#(x)(y1(x) + y2(x))
y3 =
#(x) (y1 (x) + y2 (x))
If you want to do it on multiple functions you can use intermediate variables :
>> f1 = y1;
>> f2 = y2;
>> y3=#(x)(f1(x) + f2(x))
EDIT after the comment:
I'm not sure to understand the problem. Can you define your vectors v and w like that outside the function :
v = [5 4]; % your 536 data
w = [4 5];
y = 8;
s=#(y)((1-exp(-v*y)-w).*exp(-v*y))
s_sum = sum(s(y))
Note the dot in the multiplication to do it element-wise.
I think the most succinct solution is given in the comment by Mikhail. I'll flesh it out in more detail...
First, you will want to modify your anonymous function s so that it can operate on vector inputs of the same size as well as scalar inputs (as suggested by Clement J.) by using element-wise arithmetic operators as follows:
s = #(x,y,z) (1-exp(-x.*y)-z).*exp(-x.*y); %# Note the periods
Then, assuming that you have vectors v and w defined in the given workspace, you can create a new function sy that, for a given scalar value of y, will sum across s evaluated at each set of values in v and w:
sy = #(y) sum(s(v,y,w));
If you want to evaluate this function using an array of values for y, you can add a call to the function ARRAYFUN like so:
sy = #(y) arrayfun(#(yi) sum(s(v,yi,w)),y);
Note that the values for v and w that will be used in the function sy will be fixed to what they were when the function was created. In other words, changing v and w in the workspace will not change the values used by sy. Note also that I didn't name the new anonymous function sum, since there is already a built-in function with that name.