R:矢量化有限差分方程

R:矢量化有限差分方程,r,fortran95,R,Fortran95,我正试图将一些Fortran代码移到R中,用于与化学动力学相关的有限差分 Fortran循环示例: DOUBLE PRECISION, DIMENSION (2000,2) :: data=0.0 DOUBLE PRECISION :: k1=5.0, k2=20.0, dt=0.0005 DO i=2, 2000 data(i,1) = data(i-1,1) + data(i-1,1)*(-k1)*dt data(i,2) = data(i-1,2) + ( data(i-1,1)*

我正试图将一些Fortran代码移到R中,用于与化学动力学相关的有限差分

Fortran循环示例:

DOUBLE PRECISION, DIMENSION (2000,2) :: data=0.0
DOUBLE PRECISION :: k1=5.0, k2=20.0, dt=0.0005
DO i=2, 2000
  data(i,1) = data(i-1,1) + data(i-1,1)*(-k1)*dt
  data(i,2) = data(i-1,2) + ( data(i-1,1)*k1*dt - data(i-1,2)*k2*dt )
  ...
END DO
类似的R代码:

k1=5
k2=20
dt=0.0005
data=data.frame(cbind(c(500,rep(0,1999)),rep(0,2000)))
a.fun=function(y){
     y2=y-k1*y*dt
     return(y2)
 }
apply(data,2,a.fun)
这将覆盖数据帧中的第一个值,并在其他位置保留零。我想运行这个矢量化的,不使用for循环,因为它们在R中非常慢。而且,我的函数到目前为止只计算第一列。在第一列语法正确之前,我无法使第二列正常工作。

这可能会有所帮助

我认为您需要有
数据[1,2]
的初始条件。在初始条件下,我假设
数据[1,1]
为500,而
数据[1,2
为0

代码如下所示:

> ## Define two vectors x and y
> x <- seq(from=0,length=2000,by=0)
> y <- seq(from=0,length=2000,by=0)
> 
> ## Constants
> k1 = 5.0
> dt = 0.0005
> k2 = 20.0
> 
> ## Initialize x[1]=500 and y[1]=0
> x[1]=500
> y[1] = 0
> 
> for (i in 2:2000){
+   x[i]=x[i-1]+x[i-1]*-k1*dt
+   y[i] = y[i-1]+x[i-1]*k1*dt-y[i-1]*k2*dt
+ }
> 
> finaldata <- data.frame(x,y)
> head(finaldata)
         x        y
1 500.0000 0.000000
2 498.7500 1.250000
3 497.5031 2.484375
4 496.2594 3.703289
5 495.0187 4.906905
6 493.7812 6.095382
定义两个向量x和y >xy >##常数 >k1=5.0 >dt=0.0005 >k2=20.0 > >##初始化x[1]=500和y[1]=0 >x[1]=500 >y[1]=0 > >(i在2:2000中){ +x[i]=x[i-1]+x[i-1]*-k1*dt +y[i]=y[i-1]+x[i-1]*k1*dt-y[i-1]*k2*dt + } > >最终数据头(最终数据) xy 1 500.0000 0.000000 2 498.7500 1.250000 3 497.5031 2.484375 4 496.2594 3.703289 5 495.0187 4.906905 6 493.7812 6.095382
我希望这能有所帮助。

R不一定不擅长循环。这在很大程度上取决于你在做什么。使用问题中的
k1
k2
dt
data
(即以
k1=5开始的四行)用迭代矩阵来描述问题,下面最后一行中的循环在我的电脑上几乎瞬间返回:

z <- as.matrix(data)
m <- matrix(c(1-k1*dt, k1*dt, 0, 1-k2*dt), 2)

for(i in 2:nrow(z)) z[i, ] <- m %*% z[i-1, ]

两条注释:1:如果这在Fortran中工作,为什么不使用它呢?2:您的代码返回一个错误:
error in FUN(newX[,i],…):对象“k1”未找到1
谢谢您捕获错误。我已编辑了代码。我知道我的函数到目前为止还不完整。我现在的重点是如何将引用转换到上一次迭代。
data[1,2]=data[1,1]-data[1,1]*k1*dt
这有意义吗?Fortran在Linux上也很方便,但在Windows上就没有那么方便了。好吧,我不能告诉你你想要什么,因为
数据有两列,第2列都是零,这可以通过
任何(data$X2!=0)看到
。更多注释:您的R代码没有定义
k1
dt
。此外,不要使用
data
dt
作为变量名。这些是R函数的名称。数据(1,1)和数据(1,2)的初始值是什么?我还没有计算出第二列,因为它取决于第一列,我无法工作。我添加了k1和dt变量。
data[1,]=500 0
。它使用相同的循环结构将Fortran代码直接转换为R,并使数字起作用,但它的伸缩性非常差,因为R不善于快速计算循环。我希望使用*apply()有一个合适的函数定义。
for
实际上并不比
apply
差多少。它们都是循环。你想在行上循环,在列之间进行交互。
apply
不适合这项工作。我想在这里使用apply会变得更复杂。我放弃了。我试着使用
apply
,但确实如此似乎没有做这项工作。这是我想到的最好的方法。希望有人能为你提供应用功能。祝你好运。Jdbaba,谢谢你的努力。我认为问题在于
a.fun
函数没有做它应该做的事情。你能提供
head(z)
?我得到
z[1,]=500
z[2,]=0 0
。另外,我不太明白您第二行代码中的列表。请您详细说明一下好吗?
m
中有4项,但
z
中只有2列
m
是2x2,
z[I-1,]
是长度为2的向量(在矩阵乘法中可以视为2x1)因此矩阵积是2x1,我们将其分配给长度为2的
z[i,]
。我添加了
标题
输出,并添加了需要输入问题行的讨论。
> head(z)
           X1       X2
[1,] 500.0000 0.000000
[2,] 498.7500 1.250000
[3,] 497.5031 2.484375
[4,] 496.2594 3.703289
[5,] 495.0187 4.906905
[6,] 493.7812 6.095382