浮点运算的 Fortran 舍入误差

计算科学 计算几何 正则 浮点
2021-12-14 12:22:09

我有简单的代码,它用圆柱体包围的区域标记节点。的情况下观察到的圆柱体轻微倾斜θ=90

检查任意方向圆柱内任意点的算法如下。为连接中心和任意点的向量,且对于方向向量在其上 的投影为 因此,垂直向量为 对于长度为、半径的圆柱体,检查 rco

r=co.
or
u=ro.
p=ruo.
2la
p.p<a2for lul.

实际问题: 上述算法是在 Fortran 中实现的。如果在圆柱体内,代码会检查笛卡尔网格中的点。以下是测试用例:圆柱在 yz 平面上相对于 y 轴因此,方向向量为 (0, 1, 0)。θ=90o

情况 1: 方向向量直接用分配。这导致了具有o=(0.0,1.0,0.0)θ=90.

情况 2: 方向向量是用具有双精度精度的内在 Fortran 函数dsin\指定的,其中值指定为超过 20 位有效小数点。由此产生的圆柱体导致轻微倾斜。dcoso=(0.0,sin(π/2.0),cos(π/2.0))π

突出显示的区域表示由于圆柱体相对于笛卡尔轴倾斜而产生的额外材料。我还尝试了架构特定的最大精度“pi”值。这也会导致同样的问题。

这表明圆柱体的实际角度不是任何人都可以为这个问题提出有效的解决方案。我需要对任意角度使用内置三角函数并寻找准确的单元格标记方法。90

注意:所有操作均以双精度精度执行。

1个回答

查看代码、您正在使用的编译器和编译器选项会非常好。但是,我可以建议立即测试几件事:

  1. 无论何时使用任何常量,都不要在文本中指定 0.0 和 2.0,而是使用 0.0_dp 和 2.0_dp。这将确保对它们使用双精度。(dp=kind(0.0d0)) 此外,我会说乘以 0.5_dp 优于除以 2.0_dp。说,

    tmp_sin=dsin(pid*0.5_dp)
    tmp_cos=dcos(pid*0.5_dp)
    o=/0.0_dp,tmp_sin,tmp_cos/
    
  2. 另一件要尝试的事情是创建一个双精度变量 pid_over_two ,其值为 pi/2 且有效数字大于 20,并在其上尝试您的代码(使用您的编译器设置)。

  3. 确保不要使用允许非 IEEE 标准划分的 -no-prec-div 选项编译此代码。

  4. 确保在输出可视化数据时使用正确的格式说明符

这些是我可以在不查看代码内部的情况下提出的基本建议。此外,看看您的代码(在您的编译器/平台/设置下)产生什么输出是很有价值的:

dsin(pid/2.0)
dsin(pid/2.0_dp)
dsin(0.5_dp*pid)
dcos(pid/2.0)
dcos(pid/2.0_dp)
dcos(0.5_dp*pid)