Perl & CFD-Post:使用 Perl 计算一系列数字的平均值,即时计算输出文件的平均值



我正在使用一个名为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  $MaxPressuren";
!   };
!   };
#   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

我想要的是另一个输出文本文件(动态),每个固定位置时间//strong>上对压力进行平均,这样输出将显示为:

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  $MaxPressuren";
}
}
close FH;

更新

这是您的代码更新,以执行我认为您想要的操作。它写入两个输出文件,而不是一个:pressure.txtavg.txt。我还修复了您的代码中的一些错误做法;特别是,您应该在每个Perl程序的顶部都有use strictuse warnings 'all'(我在这里省略了它们,因为我不知道程序的顶部是什么样子),并且您需要在my的第一个使用点声明所有变量

我还将输出文件的打开模式从append更改为open。我想你不想把每个输出都添加到文件的末尾吗?

我希望这能帮助

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_pressuren";
++$n;
$total_maxp += $max_pressure;
}
printf $avg_fh "%-16d%-.3en", $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%-.3En", $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

最新更新