1

シミュレーターの 1 つの出力を読み取り、値を保存する必要があります。ファイル名はforces.dat、次のようなものが含まれています。

# Forces     
# CofR       : (4.750000e-01 3.500000e-02 2.000000e-02)
# Time       forces(pressure viscous porous) moment(pressure viscous porous)
2.633022e-02    ((6.268858e-02 -1.468850e+01 1.542745e-20) (1.000906e-03 8.405854e-06 -5.657665e-17) (0.000000e+00 0.000000e+00 0.000000e+00)) ((-8.779466e-18 8.442993e-19 -3.225599e-03) (-2.082489e-18 4.435609e-18 -1.572485e-03) (0.000000e+00 0.000000e+00 0.000000e+00))
8.095238e-02    ((1.781333e-01 -1.468455e+01 -3.545427e-19) (2.362118e-03  2.014609e-05 1.691584e-16) (0.000000e+00 0.000000e+00 0.000000e+00))  ((-3.344781e-18 -5.448339e-19 2.227502e-02) (5.092628e-18 -3.538718e-18  -1.203074e-03) (0.000000e+00 0.000000e+00 0.000000e+00))
1.600000e-01    ((3.204471e-01 -1.467482e+01 -4.599174e-18) (6.936764e-03 1.303800e-04 4.836650e-17) (0.000000e+00 0.000000e+00 0.000000e+00)) ((-1.123589e-17 -4.344967e-19 5.591623e-02) (1.532415e-18 -1.345592e-18  -9.550750e-04) (0.000000e+00 0.000000e+00 0.000000e+00))

最初の 3 行を無視し、次の行数と各行の値を読み取る Fortran サブルーチンを作成する方法を知りたいです。

4

2 に答える 2

1

コマンドライン ツール (例: ) でファイルを前処理する方が簡単だと思いますが、各行sed -e 's/(/ /g' -e 's/)/ /g' input.datを長い文字列に読み込んで不要な括弧をすべて削除することで、Fortran を直接使用することもできます。

program main
    implicit none
    integer, parameter :: mxline = 5000  !! choose appropriately
    integer i, ios, finp, nl
    character(500) str
    real, save :: time( mxline )
    real, dimension( 3, mxline ), save :: &
            frc_pres, frc_visc, frc_poro, &
            mom_pres, mom_visc, mom_poro

    finp = 10
    open( finp, file="input.dat", status="old" )

    nl = 0
    do
        read( finp, "(a)", iostat=ios ) str
        if ( ios /= 0 ) exit
        str = trim( adjustL( str ) )

        !! Skip comment or blank lines.
        if ( str(1:1) == "#" .or. str == "" ) cycle

        !! Replace parentheses with space.
        do i = 1, len_trim( str )
            if ( str(i:i) == "(" .or. str(i:i) == ")" ) str(i:i) = " "
        enddo

        !! Read data from the string.
        nl = nl + 1
        read( str, * ) time( nl ), &
                       frc_pres( :, nl ), frc_visc( :, nl ), frc_poro( :, nl ), &
                       mom_pres( :, nl ), mom_visc( :, nl ), mom_poro( :, nl )
    enddo

    close( finp )

    !! Check.
    do i = 1, nl
        print *
        print *, "time = ", time( i )
        print *, "frc_pres = ", frc_pres( :, i )
        print *, "frc_visc = ", frc_visc( :, i )
        print *, "frc_poro = ", frc_poro( :, i )
        print *, "mom_pres = ", mom_pres( :, i )
        print *, "mom_visc = ", mom_visc( :, i )
        print *, "mom_poro = ", mom_poro( :, i )
    enddo

end program

データ値が非常に大きくなる可能性がある場合 (たとえば、1.0e100)、必要な精度を失わないように、倍精度実数の使用を検討してください。

于 2016-08-12T20:31:05.273 に答える
1

行番号を追跡するこのスニペットを使用できます。要件とファイルの性質に基づいて、それぞれの行の値を取得し、必要な操作を実行できます。

string CurrentLine; 
int LastLineNumber;   
void NextLine() 
{
// using will make sure the file is closed
using(System.IO.StreamReader file = new System.IO.StreamReader ("c:\\forces.dat"))
{
    // Skip lines
    for (int i=0;i<LastLineNumber;++i)
        file.ReadLine();

    // Store your line
    CurrentLine = file.ReadLine();
    LastLineNumber++;
}
}

上記のコードでは、forループ内に、読み取りたい行に基づいてファイル処理のロジックを入れることができます。

于 2016-08-12T08:51:28.460 に答える