如何在MatLAB中获取Fortran精度

时间:2015-04-27 15:41:15

标签: matlab fortran double-precision

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

  1. 构建tanh -field并找到其拉普拉斯
  2. 将一些术语加在一起
  3. 这种乘法的结果产生一个矩阵,其中(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) 
    

    的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
    

1 个答案:

答案 0 :(得分:6)

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

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

还有更多。如果我强制编译器使用double precision作为浮点数的默认值(对于gfortran,编译选项为-fdefault-real-8),则代码的结果为:

  

0.00000000000000000000000000000000000

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

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

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