如何在MatLAB中获取Fortran精度

Bil*_*ean 0 matlab fortran double-precision

我有一段用Fortran和Matlab编写的代码.他们做了完全相同的计算,即

  1. 构造一个tanh-field并找到它的拉普拉斯算子
  2. 将一些术语相乘

该乘法的结果产生矩阵,其中(4,4)和(6,6)I减去.

  • 在Fortran他们的差异是~1e-20
  • 在Matlab中,它们的差异完全相同.

这个问题非常关键,因为我测试这个数字是否小于零. 问题:有没有办法执行计算,以便在Matlab中获得与Fortran相同的精度?

我列出以下代码:


MATLAB

clear all

weights = [4./9, 1./9,1./9,1./9,1./9, 1./36,1./36,1./36,1./36];
dir_x   = [  0,   1,  0, -1,  0,    1,  -1,  -1,   1];
dir_y   = [  0,   0,  1,  0, -1,    1,   1,  -1,  -1];



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CONSTANTS
length_y = 11; length_x = length_y;
y_center = 5; x_center  = y_center;


densityHigh = 1.0;
densityLow  = 0.1;
radius  = 3.0;
c_width = 1.0;

average_density = 0.5*(densityHigh+densityLow);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%





for x=1:length_x
    for y=1:length_y
        for i=1:9
            fIn(i, x, y) = weights(i)*densityHigh;
            test_radius = sqrt((x-x_center)*(x-x_center) + (y-y_center)*(y-y_center));
            if(test_radius <= (radius+c_width))
                fIn(i, x, y) = weights(i)*( average_density - 0.5*(densityHigh-densityLow)*tanh(2.0*(radius-sqrt((x-x_center)*(x-x_center) + (y-y_center)*(y-y_center))/c_width)) );
            end
        end
    end
end 

ref_density_2d = ones(length_x)*average_density;
for i=1:length_x
    ref_density(:,:,i) = abs(ref_density_2d(:, i)');
end


          rho = sum(fIn);
laplacian_rho = (+1.0*(circshift(rho(1,:,:), [0, -1, -1]) + circshift(rho(1,:,:), [0, +1, -1]) + circshift(rho(1,:,:), [0, -1, +1]) + circshift(rho(1,:,:), [0, +1, +1])) + ...
                 +4.0*(circshift(rho(1,:,:), [0, -1, +0]) + circshift(rho(1,:,:), [0, +1, +0]) + circshift(rho(1,:,:), [0, +0, -1]) + circshift(rho(1,:,:), [0, +0, +1])) + ...
                -20.0*rho(1,:,:));

psi   = 4.0*0.001828989483310*(rho-densityLow).*(rho-densityHigh).*(rho-ref_density) - laplacian_rho*(1.851851851851852e-04)/6.0;

psi(1,4,4)-psi(1,6,6) 
Run Code Online (Sandbox Code Playgroud)

Fortran语言

 PROGRAM main

 IMPLICIT NONE

 INTEGER, PARAMETER :: DBL = KIND(1.D0)
 REAL(KIND = DBL), DIMENSION(1:11,1:11) :: psi, rho
 INTEGER :: i, j, m, ie, iw, jn, js
 REAL(KIND = DBL) :: R, rhon, lapRho

 INTEGER, DIMENSION(1:11,1:11,1:4) :: ni

 REAL(KIND = DBL) :: kappa, kappa_6, kappa_12, kappaEf, beta, beta4



 beta     = 12.D0*0.0001/(1.D0*( (1.0 - 0.1)**4 ))
 kappa    = 1.5D0*0.0001*1.D0/( (1.0 - 0.1)**2 ) 


!-------- Define near neighbours and initialize the density rho ----------------
 DO j = 1, 11
   DO i = 1, 11

! Initialize density
      rho(i,j) = 1.D0
        R =  DSQRT( ( DBLE(i)-5.0 )**2 + ( DBLE(j)-5.0 )**2 )
        IF (R <= (DBLE(3.0) + 1.D0)) THEN
          rho(i,j) = 0.55D0 - 0.5*0.9*TANH(2.D0*(DBLE(3.0) - R)/1.D0)
        END IF

 !Generate neighbors array
      ni(i,j,1) = i + 1
      ni(i,j,2) = j + 1
      ni(i,j,3) = i - 1
      ni(i,j,4) = j - 1
   END DO
 END DO


! Fix neighbours at edges
 ni(1,:,3) = 11
 ni(11,:,1) = 1
 ni(:,1,4) = 11
 ni(:,11,2) = 1



!--------- Differential terms for the stress form of the interfacial force -----
 DO j = 1, 11
   DO i = 1, 11

! Identify neighbors
     ie = ni(i,j,1)
     jn = ni(i,j,2)
     iw = ni(i,j,3)
     js = ni(i,j,4)

! Laplacian of the density rho
     lapRho = 4.D0*( rho(ie,j ) + rho(iw,j ) + rho(i ,jn) + rho(i ,js) )       &
             + rho(ie,jn) + rho(ie,js) + rho(iw,jn) + rho(iw,js) - 20.D0*rho(i,j)

! Define the chemical potential Psi
     psi(i,j) = 4.D0*beta*( rho(i,j) - 0.55 )*( rho(i,j) - 0.1 )*( rho(i,j) - 1.0 ) &
              - kappa*lapRho/6.D0
   END DO
 END DO


write(*,*) psi(6,6)-psi(4,4)


 END PROGRAM
Run Code Online (Sandbox Code Playgroud)

Ale*_*ogt 6

因此,您仍然没有在整个代码中使用双精度,例如:

beta     = 12.D0*0.0001/(1.D0*( (1.0 - 0.1)**4 ))
Run Code Online (Sandbox Code Playgroud)

还有很多.如果我强制编译器使用双精度作为浮点数的默认值(对于gfortran编译选项是-fdefault-real-8),代码的结果是:

0.00000000000000000000000000000000000

所以你需要修复你的代码.例如,引用的行应为:

beta     = 12.D0*0.0001D0/(1.D0*( (1.0D0 - 0.1D0)**4 ))
Run Code Online (Sandbox Code Playgroud)

[虽然我鄙视这种符号D0,但这是一个不同的故事]