我正在使用一个名为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.txt
和avg.txt
。我还修复了您的代码中的一些错误做法;特别是,您应该在每个Perl程序的顶部都有use strict
和use 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