gpt4 book ai didi

fortran - if 语句确定稳态

转载 作者:行者123 更新时间:2023-12-02 18:35:04 25 4
gpt4 key购买 nike

下面的代码正确求解了函数 u(x,t) 的一维热方程。我现在想要找到稳态解,该解不再随时间变化,因此它应该满足 u(t+1)-u(t) = 0。找到稳态解的最有效方法是什么?我在下面展示了三种不同的尝试,但我不确定其中任何一个是否真正在做我想要的事情。第一个和第三个方法的语法正确,第二个方法由于 if 语句而存在语法错误。每种方法由于if结构的变化而有所不同。

方法一:

program parabolic1
integer, parameter :: n = 10, m = 20
real, parameter :: h = 0.1, k = 0.005 !step sizes
real, dimension (0:n) :: u,v
integer:: i,j
real::pi,pi2

u(0) = 0.0; v(0) = 0.0; u(n) = 0.0; v(n) =0.0
pi = 4.0*atan(1.0)
pi2 = pi*pi

do i=1, n-1
u(i) = sin( pi*real(i)*h)
end do

do j = 1,m

do i = 1, n-1
v(i) = 0.5*(u(i-1)+u(i+1))
end do
t = real(j)*k !increment in time, now check for steady-state

!steady-state check: this checks the solutions at every space point which I don't think is correct.
do i = 1,n-1
if ( v(i) - u(i) .LT. 1.0e-7 ) then
print*, 'steady-state condition reached'
exit
end if
end do

do i = 1, n-1 !updating solution
u(i) = v(i)
end do

end do
end program parabolic1

方法2:

program parabolic1
integer, parameter :: n = 10, m = 20
real, parameter :: h = 0.1, k = 0.005 !step sizes
real, dimension (0:n) :: u,v
integer:: i,j
real::pi,pi2

u(0) = 0.0; v(0) = 0.0; u(n) = 0.0; v(n) =0.0
pi = 4.0*atan(1.0)
pi2 = pi*pi

do i=1, n-1
u(i) = sin( pi*real(i)*h)
end do

do j = 1,m

do i = 1, n-1
v(i) = 0.5*(u(i-1)+u(i+1))
end do
t = real(j)*k !increment in time, now check for steady-state

!steady-state check: (This gives an error message since the if statement doesn't have a logical scalar expression, but I want to compare the full arrays v and u as shown.
if ( v - u .LT. 1.0e-7 ) then
print*, 'steady-state condition reached'
exit
end if

do i = 1, n-1 !updating solution
u(i) = v(i)
end do

end do
end program parabolic1

方法3:

program parabolic1
integer, parameter :: n = 10, m = 20
real, parameter :: h = 0.1, k = 0.005 !step sizes
real, dimension (0:n) :: u,v
integer:: i,j
real::pi,pi2

u(0) = 0.0; v(0) = 0.0; u(n) = 0.0; v(n) =0.0
pi = 4.0*atan(1.0)
pi2 = pi*pi

do i=1, n-1
u(i) = sin( pi*real(i)*h)
end do

do j = 1,m

do i = 1, n-1
v(i) = 0.5*(u(i-1)+u(i+1))
end do
t = real(j)*k !increment in time, now check for steady-state

!steady-state check: Perhaps this is the correct expression I want to use
if( norm2(v) - norm2(u) .LT. 1.0e-7 ) then
print*, 'steady-state condition reached'
exit
end if

do i = 1, n-1 !updating solution
u(i) = v(i)
end do

end do
end program parabolic1

最佳答案

无需讨论哪种方法来确定“接近度”是最好的或正确的(不是真正的编程问题),我们可以专注于方法的 Fortran 部分正在做什么。

方法 1 和方法 2 的想法相似(但在执行过程中被破坏),而方法 3 则不同(并以另一种方式被破坏)。

另请注意,通常人们想要比较差异的大小 abs(v-u) 而不是(带符号的)差异 v-u。由于迭代中的非单调变化,这些是完全不同的。

方法3使用norm2(v) -norm2(u)来测试数组uv是否相似。这是不正确的。考虑一下

norm2([1.,0.])-norm2([0.,1.])

而不是更正确的

norm2([1.,0.]-[0.,1.])

方法2

if ( v - u .LT. 1.0e-7 ) then

存在数组表达式无效的问题,但是“所有点都接近吗?”可以适本地写为

if ( ALL( v - u .LT. 1.0e-7 )) then

(您会在这里找到有关此类数组缩减的其他问题)。

方法 1 尝试类似的操作,但错误:

    do i = 1,n-1
if ( v(i) - u(i) .LT. 1.0e-7 ) then
print*, 'steady-state condition reached'
exit
end if
end do

这在一方面是不正确的,另一方面是在微妙方面。

首先,当条件第一次测试为真时,循环将退出,并显示一条消息,表明已达到稳定状态。这是不正确的:您需要所有值接近,而这是测试任何值接近。

其次,当满足条件时,您退出。但是您不会退出时间迭代循环,而是退出紧密度测试循环。 (没有构造名称的 exit 会留下最里面的 do 构造)。您将处于完全相同的情况,在最内部的构造之后立即再次运行,无论测试条件是否满足(如果满足,您也会收到消息)。您将需要在时间循环上使用构造名称。

我不会展示如何做到这一点(这里还有其他相关问题),因为您还需要修复测试条件,此时您最好使用 if(all( ...(更正方法 2),无需额外的 do 构造。

对于方法 1 和 2,您将得到如下内容:

if (all(v-u .lt 1e-7)) then
print *, "Converged"
exit
end if

对于方法 3:

if (norm2(v-u) .lt. 1e-7) then
print *, "Converged"
exit
end if

关于fortran - if 语句确定稳态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68911978/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com