代码之家  ›  专栏  ›  技术社区  ›  Emma

Perl和CFD Post:使用Perl计算动态输出文件中数字序列的平均值

  •  -1
  • Emma  · 技术社区  · 8 年前

    Im使用一个名为CFD Post的软件来处理模拟结果。软件命令语言基于Perl。因此,我编写了一个简单的代码,其中除了Perl命令外,还包含软件自己的命令,以输出一个数据文件,其中包含不同位置和时间间隔的压力最大值。简化的代码示例如下所示:

    # Output file for storing the pressure values from the software. The file is opened here to insert headings.
    !   $outputfile = "pressure.txt";
    !   open(FH,">> $outputfile");
    #   Print headings
    !   print FH "time [s]  location    distance [mm]   Max Pressure [Pa]\n";
    #########################################################################
    #   Loop for creating locations
    !   for ($i = 0; $i < 101; $i += 10) {
    !   $location = "x${i}"; 
    #   ......
    #   Code within CFD-Post software for creating the locations for 
        extracting 
        spatial data 
    #   ......
    #   Code within CFD-Post software for loading different timesteps and 
        looping 
        over them at each location
    #   Get the timestep values from the current results file
    !   $timestepList = getValue("DATA READER", "Timestep List");
    !   @timesteps = split(/, /, $timestepList );
    #   Loop over timesteps
    !   foreach $ts ( @timesteps ) {
    #   Load current timestep, 
    >   load timestep=$ts
    !   $time = getValue( "DATA READER", "Current Timevalue");
    #   ......
    #   Code within CFD-Post software for retrieving the pressure value at each 
        location
    !   $MaxPressure = maxVal(“Pressure” , "$location");
        ######################################################################
    #
    #   Perl code of concern in the current question 
        #   Tab delimited output
    !   print FH "$time $location   $i  $MaxPressure\n";
    !   };
    !   };
    #   Close the output file 
    !   close FH;
    

    文本文件中的输出如下:

    time [s]    location    distance [mm]   Max Pressure [Pa]
    1           x0          0               3.531e5
    2           x0          0               7.795e5
    3           x0          0               5.265e5
    ..          ..          ..              ..
    ..          ..          ..              ..
    10          x0          0               ..e5
    1           x10         10              4.267e5
    2           x10         10              9.987e5
    3           x10         10              1.443e5
    ..          ..          ..              ..
    ..          ..          ..              ..
    10          x10         10              ..e5
    

    我想要的是另一个输出文本文件(在运行中),该文件 平均压力 结束 每个固定位置

    Distance [mm]   Avg Pressure [Pa]
    0               x.xxxe5
    10              x.xxxe5
    20              x.xxxe5 
    ..              ..e5
    

    实现这一点的Perl代码是什么(不使用模块?),因为我不确定它们是否与软件中使用的命令语言兼容。当然可以使用Matlab来完成这项任务,但我想这在Perl中应该不是一个大问题?注意,我不熟悉Perl,这是我第一周使用它:)


    使现代化

    这是上面的代码,删除了干扰性注释并添加了适当的缩进

    $outputfile = "pressure.txt";
    
    open( FH, ">> $outputfile" );
    
    print FH "time [s]  location    distance [mm]   Max Pressure [Pa]\n";
    
    for ( $i = 0; $i < 101; $i += 10 ) {
    
        $location = "x${i}";
    
        $timestepList = getValue( "DATA READER", "Timestep List" );
        @timesteps    = split( /, /, $timestepList );
    
        foreach $ts ( @timesteps ) {
    
            $time        = getValue( "DATA READER", "Current Timevalue" );
            $MaxPressure = maxVal( "Pressure", "$location" );
    
            print FH "$time $location   $i  $MaxPressure\n";
        }
    }
    
    close FH;
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   Borodin    8 年前

    使现代化

    这是你的代码更新,我认为你想做什么。它写入两个输出文件而不是一个: pressure.txt avg.txt . 我还修复了代码中的一些不良实践;特别是你应该 use strict use warnings 'all' 在每个Perl程序的顶部(我把它们放在这里,因为我不知道程序的顶部是什么样子),您需要在第一个使用点声明所有变量 my

    我还从append更改了输出文件的打开模式。我想你不希望每个输出都添加到文件的末尾?

    我希望这有帮助

    my ( $outputfile, $avg_file ) = qw/ pressure.txt avg.txt /;
    
    open my $out_fh, '>', $outputfile" or die qq{Unable to open "$outputfile" for output: $!};;
    open my $avg_fh, '>', $avg_file"   or die qq{Unable to open "$avg_file" for output: $!};;
    
    print $out_fh "time [s]  location    distance [mm]   Max Pressure [Pa]\n";
    print $avg_fh "Distance [mm]   Avg Pressure [Pa]\n";
    
    for ( 0 .. 10 ) {
    
        my $i = $_ * 10;  # $i = 0, 10, 20, ... 100
    
        my $location = "x$i";
    
        my $timestep_list = getValue( 'DATA READER', 'Timestep List' );
        my @timesteps    = split /,\s*/, $timestep_list;
    
        my ($n, $total_maxp) = (0, 0);
    
        for my $ts ( @timesteps ) {
    
            my $time         = getValue( 'DATA READER', 'Current Timevalue' );
            my $max_pressure = maxVal( 'Pressure', $location );
    
            print $out_fh "$time $location   $i  $max_pressure\n";
    
            ++$n;
            $total_maxp += $max_pressure;
        }
    
        printf $avg_fh "%-16d%-.3e\n", $i, $total_maxp / $n;
    }
    
    close $out_fh or die $!;
    close $avg_fh or die $!;
    


    use strict;
    use warnings 'all';
    
    use Scalar::Util 'looks_like_number';
    use List::Util 'sum';
    
    my %data;
    
    while ( <DATA> ) {
        my ($t, $loc, $dist, $maxp) = split;
        next unless looks_like_number($maxp);
        push @{ $data{$dist} }, $maxp;
    }
    
    for my $dist ( sort { $a <=> $b } keys %data ) {
        my $maxp = $data{$dist};
        $maxp = sum(@$maxp) / @$maxp;
        printf "%-16d%-.3E\n", $dist, $maxp;
    }
    
    __DATA__
    time [s]    location    distance [mm]   Max Pressure [Pa]
    1           x0          0               3.531e5
    2           x0          0               7.795e5
    3           x0          0               5.265e5
    ..          ..          ..              ..
    ..          ..          ..              ..
    10          x0          0               ..e5
    1           x10         10              4.267e5
    2           x10         10              9.987e5
    3           x10         10              1.443e5
    ..          ..          ..              ..
    ..          ..          ..              ..
    10          x10         10              ..e5
    

    输出

    0               5.530E+005
    10              5.232E+005