0

水分子の速度のシミュレーション データがあります。データのフォーマットは以下の通りです。わかりやすくするために、データの形式を説明したいと思います。これにより、計算したいことが簡単にわかります。

水分子は、酸素 (O) と 2 つの水素 (H) の 3 つの原子で構成されています。ここでは、O、H1、H2 と名前を付けます。

以下のデータは線title 0と数字4335で始まり、4335 個の原子 (4335/3 = 1445 個の水分子) が含まれていることを示しています。

3 行目 ( ) から始まる最初の 3 つの数値は、30.0923365 0.0341984 -0.1248516つのデカルト方向 Ox、Oy、Oz での酸素 (O) 原子の速度を表します。水素の速度を表す同じ行の次の 3 つの数値 (H1) ==> H1x、H1y、H1z。最後に、水素の速度を表す 4 行目の最初の 3 つの数値 (H2) ==> H2x、H2y、H2z。最後に、酸素原子の速度を表す同じ 4 行目の次の 3 つの数値。

これらのシーケンスは、データ ファイルの最初の 2 行を含む 2170 行の 4335 個の原子すべてに対して行われ、次のセクションで から始まりtitle 1ます。

title 0
4335  2.0001000e+04
 0.0923365   0.0341984  -0.1248516  -0.8946258   1.6688854   0.8259304
 0.2890579   0.8051153  -1.5612963   0.0625492  -0.1361579   0.2869132
 0.2343408  -0.0665305   1.0745378  -0.8375892   0.6953992   0.5149021
-0.1628550   0.0131844   0.0688080   0.2429340   0.2168210  -0.0289806
-0.3677613   0.2054004  -0.1511643  -0.3487551  -0.1454157   0.0801884
-0.9039297  -0.0682939  -0.2337404  -0.5605327  -0.0369157   0.2243892
-0.3100274  -0.2673132  -0.2093299   0.1975043  -0.4572202  -0.8410826
-0.6995287  -0.4123909   0.0649209  -0.1910519   0.2289656   0.2443295
-0.0279093   0.5790939  -0.0104249  -1.1961776  -0.5387340   0.1445187
-0.3188485   0.3789352  -0.0112114   0.7831523   0.6043882  -0.7131590
-0.7214440  -0.5358508  -0.3035673  -0.1549275  -0.1402387  -0.0101964
-0.2027608   1.5107149   0.2963312  -1.5104872  -0.1554981  -1.3323215
 0.1097982  -0.1553742   0.3803437   0.0816858   0.0265007   0.4215823
 0.1157368   0.2100116   0.4712551   0.1799426  -0.1260255  -0.2131755
 0.1811777  -0.9442581  -0.6036636   0.9681703  -0.1523646  -0.3502441
 0.0976771   0.0019619  -0.1832204  -0.0055989   0.2701100  -0.4416720
 0.8496723   0.4070951  -0.0819204   0.1156806  -0.1619873  -0.0016126
-0.4051959   0.4263505  -0.9460036   0.4412067   0.1002270   0.5864405
-0.3831136   0.3240860  -0.0005143  -0.5667163   0.2618876   0.0103317
-0.6442209   0.3965833  -0.0778050  -0.2404238  -0.1339887  -0.1662417
 0.3421198   0.7480828  -1.8316993  -0.4454920  -0.0499657  -0.1951254
-0.2895359  -0.1934811  -0.2674928   0.1255802   1.3522828  -0.2829485
-0.4129106  -0.6842645  -1.0147657  -0.1278501  -0.0597648  -0.1478294
-0.2519974   0.0665314  -0.0690079  -0.0480210  -0.1179547  -0.2091919
-0.1942484   0.2583650  -0.0734658  -0.1216313   0.5158040  -0.0676843
-0.3063602   0.8148463  -0.1959571  -0.1009838  -0.3394633  -0.0866587
 .
 .     (goes on until line 2170)
 .
 0.1028815  -0.0844088  -0.2156557  -0.1698745  -0.2018967  -0.3863209
 0.1793070  -0.1005802   0.1800752  -0.1404713   0.2216020   0.2236271
 0.5192825  -0.7398186   0.0418758   0.0347715  -0.3457840  -0.1300237
-0.3089482   1.1125441  -0.4020403   0.2739744  -0.9062766   0.0012294
 0.1498538   0.0883857  -0.0094638   0.0963565  -1.1027019   0.0115313
-0.0432824   0.3330713   0.0304943
title 1
4335  2.0002000e+04
-0.2082078   0.1774843  -0.1023302  -0.1100437   0.5973607   1.0627041
-0.2216015   0.0448885  -0.8415924   0.1691296   0.6008261  -0.0373434
 0.9387534  -0.3642305   0.6756270  -0.6000357   0.6632088   1.0567899
-0.3234407  -0.1781680  -0.1936070  -0.4799916  -0.1522612  -0.2347461
 0.1045985   0.1999704  -0.1482928  -0.0439331   0.0413923   0.1605458
 0.3403952  -0.2012104   0.4851457  -0.9665228   0.2202362   0.0046218
 .
 .   (goes on until line 2170)
 .   

私が計算したいのは、各分子の合成速度であり、Perl を使用してこれを実行したいと考えています。アルゴリズムはこのようになります。

まず、酸素 (O) と水素 (H1 & H2) の速度をそれぞれ Ox、Oy、Oz、H1x、H1y、H1z、H2x、H2y、H2z に保存します。

次に定義します:

    velocity_x = Ox + Hx + Hx
    velocity_y = Oy + Hy + Hy
    velocity_z = Oz + Hz + Hz

最後に計算する

  resultant_velocity = sqrt(velocity_x**2 + velocity_y**2  + velocity_z**2)

「resultant_velocity」を新しいファイルに保存します (ファイルは title_0.dat である必要があります)。そして、プログラムはファイル内のから始まる速度を計算しtitle 1ますtitle 200

私は Perl の初心者ですが、非常に興味深いので、Perl でこの操作を実行したいと考えています。Perl で単純な「読み書き」操作を記述できますが、計算は高校の標準ですが、値を分割して変数に代入し、計算を実行する方法がわかりません。

#!/usr/bin/perl -w

$data_file="malto.dat";
open(DAT, $data_file) || die("Could not open file!");
@raw_data=<DAT>;
close(DAT);

while(<@raw_data>){
@columns=split /\s+/,$_; 
if($columns[0]=~ m/ATOM/){ 
print "$columns[5], $columns[6], $columns[7]\n";
    }
}

コードの作業中に Perl の理解を深めるために、専門家からのガイダンスを得たいと考えています。

どんな助けにも感謝します。よろしく

4

3 に答える 3

1

おそらく、次のことが役に立ちます。

use strict;
use warnings;
use Math::Complex;

my $dataFile = 'malto.dat';

{
    local $/ = 'title ';
    open my $fh, '<', $dataFile or die $!;

    while (<$fh>) {
        chomp;

        my @data = split or next;

        my $titleNum     = 'Title ' . shift @data;
        my $atom         = shift(@data) . ' ' . shift @data;
        my $resultantVel = calcResultantVel( \@data );

        print $titleNum, "\n";
        print $atom,     "\n";
        print 'ResultantVel: ' . $resultantVel, "\n\n";
    }

    close $fh;
}

sub calcResultantVel {
    my ($dataRef) = @_;

    my ($velocity_x, $velocity_y, $velocity_z);

    while ( my @nums = splice( @$dataRef, 0, 9 ) ) {
        $velocity_x += $nums[0] + $nums[3] + $nums[6];
        $velocity_y += $nums[1] + $nums[4] + $nums[7];
        $velocity_z += $nums[2] + $nums[5] + $nums[8];
    }

    return sqrt( $velocity_x**2 + $velocity_y**2 + $velocity_z**2 );
}

単語とスペースtitleはレコードの区切り記号として使用されるため、各読み取りでは で区切られたデータのチャンクが取り込まれtitleます。はchompレコード セパレータを削除し、レコードはsplit空白になります。

0 番目の要素はタイトル番号で、shifted off@dataです。の 1 番目と 2 番目の要素は@data原子数で、これshiftも省略されています。残りの配列要素はデカルト方向であり、その配列への参照がサブルーチンに送信されcalcResultantVelます。

サブルーチンは、一度に 9 つの要素のチャンクを受け取ります。O アトムに 3 つ、最初の H アトムに 3 つ、2 番目の H アトムに 3 つです。実行中の合計は、指定した定義に基づいて保持されます。最後に、結果の速度が返されます。

出力例を次に示します。

Title 0
4335 2.0001000e+04
ResultantVel: 13.2945751170603

Title 1
4335 2.0001000e+04
ResultantVel: 12.7696611061461

正しく機能していることを視覚的に確認できます。「... Perl で簡単な '読み取りおよび書き込み' 操作を作成できる...」ので、次のステップは、必要な結果をファイルに書き込むことです。

お役に立てれば!

于 2012-12-14T22:12:51.783 に答える
1

私のアドバイスは次のとおりです。ジョブを小さなコンポーネントに分割し、作業の意味のある部分ごとにメソッドを記述します。ウィット:

use strict;
use warnings;

main(@ARGV); # Pass data file name on command line. Don't hard-code it.

sub main {
    my $data_f = shift;
    open(my $data_h, '<', $data_f) or die "$!: $data_f";
    while (my $section = get_section($data_h)){
        # Also write methods that can be called here to make 
        # desired computations, print output, etc.
    }
}

sub get_section {
    # Takes a file handle.
    # Returns a hash reference containing all of the data
    # for an entire section of the file.
    my $h = shift;
    return if eof($h);
    chomp (my $title = <$h>);
    my ($n_atoms) = <$h> =~ /^(\d+)/;
    return {
        'title'     => $title,
        'n_atoms'   => $n_atoms,
        'molecules' => get_molecules($h, $n_atoms / 3),
    };
}

sub get_molecules {
    my @molecules;
    return \@molecules;
}

方法は書いていませんget_molecules()。ファイル ハンドルと整数 (分子の N) を取ります。配列の配列またはハッシュの配列への参照を返すことができ、各内部配列/ハッシュは単一の分子の情報を保持します。

于 2012-12-14T15:57:09.880 に答える
0

あなたの助けとガイドをありがとう。以下のようにコードを変更しようとしました。少なくとも私のニーズには対応しています。

#!/usr/bin/perl
###############

#use strict;
#use warnings;
use Math::Complex;

open    OUTPUT, '>', "velocityOnly.dat" or die "Can't create filehandle: $!";

my $dataFile = 'velF1F2.vel';

{
local $/ = 'title ';
open my $FH, '<', $dataFile or die $!;

while (<$FH>) {
    chomp;

    my @data = split or next;

    my $titleNum     = 'Title ' . shift(@data);
    my $atom         = shift(@data) . ' ' . shift(@data);
    #my $resultantVel = calcResultantVel( \@data );

    #print OUTPUT "$titleNum", "\n";
print "$titleNum", "\n";

for my $i (1..1445)
{
    $j=(9*($i-1));  

   $velocity_x = $data[($j+0)] + $data[($j+3)] + $data[($j+6)];
   $velocity_y = $data[($j+1)] + $data[($j+4)] + $data[($j+7)];
   $velocity_z = $data[($j+2)] + $data[($j+5)] + $data[($j+8)];

   $velo = sprintf '%.3f',sqrt( $velocity_x**2 + $velocity_y**2 + $velocity_z**2 );
        chomp $velo;
        print   "$velo","\n";
        print   OUTPUT  "$velo\n";

    }

    #print 'ResultantVel: ' . $resultantVel, "\n\n";
    }

   close $FH;
   }

しかし、複雑な計算を行うための他の機能を追加して、さらに拡張したいと考えています。コード

その前に、以下のコードをサブルーチンにするためのガイドが必要です。私はここで少し迷っています。コードは実際にすべての X、Y、Z を追加し、最終的に速度を見つけます。しかし、私が欲しいのはそうではありません。続いて、9 個の値のそれぞれが、3 つの原子を含む水分子の座標を表します。

(数字 1445 は分子の数です。各分子には 3 つの原子が含まれ、各原子には 3 つの座標があります。したがって、水の分子には 9 つのデカルト座標があります。)

ここの i は水分子の数を表します

for my $i (1..1445)
{
    $j=(9*($i-1));  

   $velocity_x = $data[($j+0)] + $data[($j+3)] + $data[($j+6)];
   $velocity_y = $data[($j+1)] + $data[($j+4)] + $data[($j+7)];
   $velocity_z = $data[($j+2)] + $data[($j+5)] + $data[($j+8)];

   $velo = sprintf '%.3f',sqrt( $velocity_x**2 + $velocity_y**2 + $velocity_z**2 );
        chomp $velo;
        print   "$velo","\n";
        print   OUTPUT  "$velo\n";

    }
于 2012-12-17T12:45:06.950 に答える