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

Perl&;CFD Post:使用Perl动态计算输出文件中数字序列的平均值,perl,printf,average,Perl,Printf,Average,我正在使用一个叫做CFD Post的软件来处理模拟结果。软件命令语言基于Perl。因此,我正在编写一个简单的代码,其中除了Perl命令外,还包含软件自己的命令,以输出一个数据文件,其中包含不同位置和时间间隔的压力最大值。简化的代码示例如下所示: # Output file for storing the pressure values from the software. The file is opened here to insert headings. ! $outputfile =

我正在使用一个叫做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;
我想要的是另一个输出文本文件(在运行中),它在每个固定位置时间上的压力进行平均,这样输出将如下所示:

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;
$outputfile=“pressure.txt”;
打开(FH,“>>$outputfile”);
打印FH“时间[s]位置距离[mm]最大压力[Pa]\n”;
对于($i=0;$i<101;$i+=10){
$location=“x${i}”;
$timestepList=getValue(“数据读取器”、“timestepList”);
@timesteps=拆分(/,/,$timestepList);
foreach$ts(@timesteps){
$time=getValue(“数据读取器”、“当前时间值”);
$MaxPressure=maxVal(“压力”,“位置”);
打印FH“$time$location$i$maxpression\n”;
}
}
关闭FH;
更新 这是您的代码更新,可以执行我认为您需要的操作。它写入两个输出文件,而不是一个:
pressure.txt
avg.txt
。我还修复了代码中的一些错误实践;特别是,您应该在每个Perl程序的顶部设置
use strict
use warning'all'
(我把它们放在这里,因为我不知道程序的顶部是什么样子),并且您需要在第一次使用
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 $!;

原始答案
堆栈溢出在这里帮助您使代码正常工作。如果你没有任何代码,那么你就错过了一个重要的步骤!我知道我误解了你的问题,但我还是不明白。你说“我想要的是另一个输出文本文件(在运行中)”,听起来像是想要实时输出。但你的模拟肯定不能实时工作吗?即使是这样,请求文本文件中的实时数据也是非常奇怪的,因为文本文件通常只能附加到。此外,您的代码仅从
数据读取器
中获取11个值,而且想要从如此小的样本中获取实时数据似乎有些奇怪。如果您可以保证数据将以
距离
的顺序到达,那么也许可以采取一些措施。请告知。@Borodin非常感谢您的回复,对于造成的混乱我感到非常抱歉。我所说的“动态”是指我想计算平均值,然后保存在代码本身的一个新文件中,而不需要导入数据文件并为平均值编写单独的代码。我几乎没有Perl方面的经验。我曾尝试运行您提供的代码,并将平均值的输出写入一个新文件
OUT2
,但由于某些原因,它无法工作!我得到一个空文件…(续)我使用了
OUT1
而不是
数据
,因为它包含了软件生成的数据(不知道这是否正确使用?
使用严格;使用“全部”警告;使用Scalar::Util“看起来像数字”;使用列表::Util'sum';我的%数据;while(){my($t,$loc,$dist,$maxp)=split;next除非看起来像数字($maxp);push{$data{$dist}},$maxp;}为我的$dist(sort{$a$b}keys%data){my$maxp=$data{$dist};$maxp=sum(@$maxp)/$maxp;printfout2'-16d%-.3E\n',$dist maxp;}
(续)我猜软件不理解所使用的模块,但它不会产生任何错误。也许有更直接的方法来避免使用模块?我有几百个这样的数据点,我现在正在使用其中的一个示例,看看代码是否有效:)干杯!发布的原始答案效果良好。它只需要在开始处理应答中发布的代码之前打开包含计算输出值的文件。此外,这也证实了模块在CFD会后文件中工作。我发现使用的Perl版本是Perl-5.9.5-vs2k12(随ANSYS 17.0提供)
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