Нельзя заменить реальные переменные Фортрана переменными двойной точности или большей точностью - PullRequest
1 голос
/ 05 июня 2019

Я использую известный код (CAMB), который генерирует такие значения:

k(h/Mpc) Pk/s8^2(Mpc/h)^3
5.2781500000e-06 1.9477400000e+01
5.5479700000e-06 2.0432300000e+01
5.8315700000e-06 2.1434000000e+01
6.1296700000e-06 2.2484700000e+01
6.4430100000e-06 2.3587000000e+01
6.7723700000e-06 2.4743400000e+01
7.1185600000e-06 2.5956400000e+01
7.4824500000e-06 2.7228900000e+01
7.8649500000e-06 2.8563800000e+01
8.2669900000e-06 2.9964100000e+01

Я хотел бы получить более точные значения для сгенерированных значений, например:

k(h/Mpc) Pk/s8^2(Mpc/h)^3
5.3594794736e-06 1.8529569626e+01
5.6332442000e-06 1.9437295914e+01
5.9209928622e-06 2.0389484405e+01
6.2234403231e-06 2.1388326645e+01
6.5413364609e-06 2.2436098099e+01
6.8754711720e-06 2.3535198212e+01
7.2266739153e-06 2.4688137054e+01
7.5958159869e-06 2.5897554398e+01
7.9838137026e-06 2.7166225433e+01
8.3916311269e-06 2.8497039795e+01
8.8202796178e-06 2.9893053055e+01
9.2708232842e-06 3.1357446670e+01
9.7443817140e-06 3.2893573761e+01

Здесь раздел кода, который производит данные:

Я пытался внести следующие изменения в объявления переменных в начале кода выше:

1) Первая попытка:

!Export files of total  matter power spectra in h^{-1} Mpc units, against k/h.
Type(MatterTransferData), intent(in) :: MTrans
Type(CAMBdata) :: State
character(LEN=Ini_max_string_len), intent(IN) :: FileNames(*)
character(LEN=name_tag_len) :: columns(3)
integer itf, i, unit
integer points
! Added : way of declaring double precision
integer, parameter :: wp = selected_real_kind(15,307)
real(wp), dimension(:,:), allocatable :: outpower

но он не компилируется:

 real(wp), dimension(:,:), allocatable :: outpower
       1
Error: Symbol ‘wp’ at (1) has no IMPLICIT type
../results.f90:3660:25:

             allocate(outpower(points,ncol))
                     1
Error: Allocate-object at (1) is neither a data pointer nor an     allocatable variable
../results.f90:3676:16:

outpower(:,1) = exp(PK_data%matpower(:,1))
            1
Error: Unclassifiable statement at (1)
../results.f90:3679:20:

                 outpower(:,3) = exp(PK_data%vvpower(:,1))
                1
Error: Unclassifiable statement at (1)
compilation terminated due to -fmax-errors=4.
make[1]: *** [results.o] Error 1
make: *** [camb] Error 2

2) Также я попробовал:

!Export files of total  matter power spectra in h^{-1} Mpc units, against k/h.
Type(MatterTransferData), intent(in) :: MTrans
Type(CAMBdata) :: State
character(LEN=Ini_max_string_len), intent(IN) :: FileNames(*)
character(LEN=name_tag_len) :: columns(3)
integer itf, i, unit
integer points
! Added : way of declaring double precision
double precision, dimension(:,:), allocatable :: outpower

но то же самое, компиляция не удалась

call Transfer_GetMatterPowerS(State, MTrans, outpower(1,1), itf,  minkh,dlnkh, points)
                                                                                                      1
Error: Type mismatch in argument ‘outpower’ at (1); passed REAL(8) to    REAL(4)
make[1]: *** [results.o] Error 1
make: *** [camb] Error 2

ОБНОВЛЕНИЕ 1:

с -fmax-errors=1, я получаю следующее:

 call Transfer_GetMatterPowerS(State, MTrans, outpower(1,1), itf,  minkh,dlnkh, points)
                                                                                                      1
Error: Type mismatch in argument ‘outpower’ at (1); passed REAL(8) to REAL(4)
compilation terminated due to -fmax-errors=1.

За исключением решения, данного @Steve с опцией компиляции -freal-4-real-8, разве нет другого решения, которое я мог бы включить непосредственно в код, т.е. раздел, который я дал?

ОБНОВЛЕНИЕ 2: здесь ниже 3 соответствующих подпрограмм Transfer_GetMatterPowerS, Transfer_GetMatterPowerData и Transfer_SaveMatterPower, которые выдают ошибку при попытке получить двойную точность:


subroutine Transfer_GetMatterPowerS(State, MTrans, outpower, itf, minkh, dlnkh, npoints, var1, var2)
class(CAMBdata) :: state
Type(MatterTransferData), intent(in) :: MTrans
integer, intent(in) :: itf, npoints
integer, intent(in), optional :: var1, var2
real, intent(out) :: outpower(*)
real, intent(in) :: minkh, dlnkh
real(dl) :: outpowerd(npoints)
real(dl):: minkhd, dlnkhd

minkhd = minkh; dlnkhd = dlnkh
call Transfer_GetMatterPowerD(State, MTrans,  outpowerd, itf, minkhd, dlnkhd, npoints,var1, var2)
outpower(1:npoints) = outpowerd(1:npoints)

end subroutine Transfer_GetMatterPowerS

subroutine Transfer_GetMatterPowerData(State, MTrans, PK_data, itf_only, var1, var2)
!Does *NOT* include non-linear corrections
!Get total matter power spectrum in units of (h Mpc^{-1})^3 ready for interpolation.
!Here there definition is < Delta^2(x) > = 1/(2 pi)^3 int d^3k P_k(k)
!We are assuming that Cls are generated so any baryonic wiggles are well sampled and that matter power
!spectrum is generated to beyond the CMB k_max
class(CAMBdata) :: State
Type(MatterTransferData), intent(in) :: MTrans
Type(MatterPowerData) :: PK_data
integer, intent(in), optional :: itf_only
integer, intent(in), optional :: var1, var2
double precision :: h, kh, k, power
integer :: ik, nz, itf, itf_start, itf_end, s1, s2

s1 = PresentDefault (transfer_power_var, var1)
s2 = PresentDefault (transfer_power_var, var2)

if (present(itf_only)) then
    itf_start=itf_only
    itf_end = itf_only
    nz = 1
else
    itf_start=1
    nz= size(MTrans%TransferData,3)
    itf_end = nz
end if
PK_data%num_k = MTrans%num_q_trans
PK_Data%num_z = nz

allocate(PK_data%matpower(PK_data%num_k,nz))
allocate(PK_data%ddmat(PK_data%num_k,nz))
allocate(PK_data%nonlin_ratio(PK_data%num_k,nz))
allocate(PK_data%log_kh(PK_data%num_k))
allocate(PK_data%redshifts(nz))
PK_data%redshifts = State%Transfer_Redshifts(itf_start:itf_end)

h = State%CP%H0/100

do ik=1,MTrans%num_q_trans
    kh = MTrans%TransferData(Transfer_kh,ik,1)
    k = kh*h
    PK_data%log_kh(ik) = log(kh)
    power = State%CP%InitPower%ScalarPower(k)
    if (global_error_flag/=0) then
        call MatterPowerdata_Free(PK_data)
        return
    end if
    do itf = 1, nz
        PK_data%matpower(ik,itf) = &
            log(MTrans%TransferData(s1,ik,itf_start+itf-1)*&
            MTrans%TransferData(s2,ik,itf_start+itf-1)*k &
            *const_pi*const_twopi*h**3*power)
    end do
end do

call MatterPowerdata_getsplines(PK_data)

end subroutine Transfer_GetMatterPowerData

subroutine Transfer_SaveMatterPower(MTrans, State,FileNames, all21cm)
use constants

!Export files of total  matter power spectra in h^{-1} Mpc units, against k/h.
Type(MatterTransferData), intent(in) :: MTrans
Type(CAMBdata) :: State
character(LEN=Ini_max_string_len), intent(IN) :: FileNames(*)
character(LEN=name_tag_len) :: columns(3)
integer itf, i, unit
integer points
! Added : way of declaring double precision
!integer, parameter :: wp = selected_real_kind(15,307)
!real(wp), dimension(:,:), allocatable :: outpower
double precision, dimension(:,:), allocatable :: outpower
real minkh,dlnkh
Type(MatterPowerData) :: PK_data
integer ncol
logical, intent(in), optional :: all21cm
logical all21
!JD 08/13 Changes in here to PK arrays and variables
integer itf_PK

all21 = DefaultFalse(all21cm)
if (all21) then
    ncol = 3
else
    ncol = 1
end if

do itf=1, State%CP%Transfer%PK_num_redshifts
    if (FileNames(itf) /= '') then
        if (.not. transfer_interp_matterpower ) then
            itf_PK = State%PK_redshifts_index(itf)

            points = MTrans%num_q_trans
            allocate(outpower(points,ncol))

            !Sources
            if (all21) then
                call Transfer_Get21cmPowerData(MTrans, State, PK_data, itf_PK)
            else
                call Transfer_GetMatterPowerData(State, MTrans, PK_data, itf_PK)
                !JD 08/13 for nonlinear lensing of CMB + LSS compatibility
                !Changed (CP%NonLinear/=NonLinear_None) to CP%NonLinear/=NonLinear_none .and. CP%NonLinear/=NonLinear_Lens)
                if(State%CP%NonLinear/=NonLinear_none .and. State%CP%NonLinear/=NonLinear_Lens) then
                    call State%CP%NonLinearModel%GetNonLinRatios(State, PK_data)
                    PK_data%matpower = PK_data%matpower +  2*log(PK_data%nonlin_ratio)
                    call MatterPowerdata_getsplines(PK_data)
                end if
            end if

            outpower(:,1) = exp(PK_data%matpower(:,1))
            !Sources
            if (all21) then
                outpower(:,3) = exp(PK_data%vvpower(:,1))
                outpower(:,2) = exp(PK_data%vdpower(:,1))

                outpower(:,1) = outpower(:,1)/1d10*const_pi*const_twopi/MTrans%TransferData(Transfer_kh,:,1)**3
                outpower(:,2) = outpower(:,2)/1d10*const_pi*const_twopi/MTrans%TransferData(Transfer_kh,:,1)**3
                outpower(:,3) = outpower(:,3)/1d10*const_pi*const_twopi/MTrans%TransferData(Transfer_kh,:,1)**3
            end if

            call MatterPowerdata_Free(PK_Data)
            columns = ['P   ', 'P_vd','P_vv']
            unit = open_file_header(FileNames(itf), 'k/h', columns(:ncol), 15)
            do i=1,points
                write (unit, '(*(E15.6))') MTrans%TransferData(Transfer_kh,i,1),outpower(i,:)
            end do
            close(unit)
        else
            if (all21) stop 'Transfer_SaveMatterPower: if output all assume not interpolated'
            minkh = 1e-4
            dlnkh = 0.02
            points = log(MTrans%TransferData(Transfer_kh,MTrans%num_q_trans,itf)/minkh)/dlnkh+1
            !             dlnkh = log(MTrans%TransferData(Transfer_kh,MTrans%num_q_trans,itf)/minkh)/(points-0.999)
            allocate(outpower(points,1))
            call Transfer_GetMatterPowerS(State, MTrans, outpower(1,1), itf,  minkh,dlnkh, points)

            columns(1) = 'P'
            unit = open_file_header(FileNames(itf), 'k/h', columns(:1), 15)

            do i=1,points
                write (unit, '(*(E15.6))') minkh*exp((i-1)*dlnkh),outpower(i,1)
            end do
            close(unit)
        end if

        deallocate(outpower)
    end if
end do

end subroutine Transfer_SaveMatterPower
...