简体   繁体   中英

Plotting an 'n' sized vector between a given function with given interval in R

Let me make my question clear because I don't know how to ask it properly (therefore I don't know if it was answered already or not), I will go through my whole problem:

There is a given function (which is the right side of an explicit first order differential equation if it matters):

f = function(t,y){
-2*y+3*t
}

Then there's a given interval from 'a' to 'b', this is the range the function is calculated in with 'n' steps, so the step size in the interval (dt) is:

 dt=abs(a-b)/n 

In this case 'a' is always 0 and 'b' is always positive, so 'b' is always greater than 'a' but I tried to be generic.

The initial condition:

yt0=y0

The calculation that determines the vector:

yt=vector("numeric",n)


for (i in 1:(n-1)) 
{

yt[1]=f(0,yt0)*dt+yt0

yt[i+1]=(f(dt*i,yt[i]))*dt+yt[i] 
} 

The created vector is 'n' long, but this is an approximate solution to the differential equation between the interval ranging from 'a' to 'b'. And here comes my problem:

When I try plotting it alongside the exact solution (using deSolve), it is not accurate. The values of the vector are accurate, but it does not know that these values belong to an approximate function that's between the interval range 'a' to 'b'.

That's why the graphs of the exact and approximate solution are not matching at all. I feel pretty burnt out, so I might not describe my issue properly, but is there a solution to this? To make it realise that its values are between 'a' and 'b' on the 'x' axis and not between '1' and 'n'? I thank you all for the answers in advance!

The deSolve lines I used (regarding 'b' is greater than 'a'):

df = function(t, y, params) list(-2*y+3*t)

t = seq(a, b, length.out = n)

ddf = as.data.frame(ode(yt0, t, df, parms=NULL))

I tried to reconstruct the comparison between an "approximate" solution using a loop (that is in fact the Euler method), and a solution with package deSolve . It uses the lsoda solver by default that is more precise than Euler'S method, but it is of course also an approximation (default relative and absolute tolerance set to 1e-6).

As the question missed some concrete values and the plot functions, it was not clear where the original problem was, but the following example may help to re-formulate the question. I assume that the problem may be confusion between t (absolute time) and dt between the two approaches. Compare the lines marked as "original code" with the "suggestion":

library(deSolve)

f = function(t, y){
  -2 * y + 3 * t
}

## some values
y0 <- 0.1
a  <- 3
b  <- 5
n  <- 100

## Euler method using a loop
dt <- abs(a-b)/n
yt <- vector("numeric", n)
yt[1] <- f(0, y0) * dt + y0 # written before the loop
for (i in 1:(n-1)) {
  #yt[i+1] = (f(    dt * i, yt[i])) * dt + yt[i] # original code
  yt[i+1] <- (f(a + dt * i, yt[i])) * dt + yt[i] # suggestion
}

## Lsoda integration wit package deSolve
df <- function(t, y, params) list(-2*y + 3*t)
t <- seq(a, b, length.out = n)
ddf = as.data.frame(ode(y0, t, df, parms=NULL))

## Plot of both solutions
plot(ddf, type="l", lwd=5, col="orange", ylab="y", las=1)
lines(t, yt, lwd=2, lty="dashed", col="blue")
legend("topleft", c("deSolve", "for loop"),
       lty=c("solid", "dashed"), lwd=c(5, 2), col=c("orange", "blue"))

for循环和deSolve之间的比较

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM