2017-04-20 10 views
1

私はさまざまな構成の2つのベンゼン分子間のファンデルワールス相互作用を研究しようとしています。これを行うために、私は2つの分子のうちの1つを回転させるbashスクリプトを書いています(現在x軸の周りのみ)。2.コードはバグなく実行されるようですが、完全に間違った結果をもたらします。私は何度もチェックして、何か「数学的な」エラーが見つからなかったので、おそらくどこかで構文エラーを起こしたでしょうか? 私はbash(とlinux)の初心者ですので、どんな助けもありがとう!:) ...あなたは私が間違って何をしたか知っていればbashスクリプトでローテーションをコーディングする

C 0.00000000000000000E+00 1.39600002765655495E+00 12.25 
C 1.20899999141693093E+00 6.98000013828277699E-01 12.25 
C 1.20899999141693093E+00 -6.98000013828277699E-01 12.25 
C 0.00000000000000000E+00 -1.39600002765655495E+00 12.25 
C -1.20899999141693093E+00 -6.98000013828277699E-01 12.25 
C -1.20899999141693093E+00 6.98000013828277699E-01 12.25 
H 0.00000000000000000E+00 2.47900009155273393E+00 12.25 
H 2.14700007438659712E+00 1.24000000953674294E+00 12.25 
H 2.14700007438659712E+00 -1.24000000953674294E+00 12.25 
H 0.00000000000000000E+00 -2.47900009155273393E+00 12.25 
H -2.14700007438659712E+00 -1.24000000953674294E+00 12.25 
H -2.14700007438659712E+00 1.24000000953674294E+00 12.25 

事前のおかげ:

#!/bin/bash 

echo "Angle of rotation (in rad:" 
read angle 
echo "File or path to file :" 
read fichier 
echo "Your file:" 
cat $fichier 
echo "Give the line numbers which contain the atoms you want to rotate :" 
read ligneDebut 
read ligneFin 

# creation of an associative array playing the role of the rotation matrix 
declare -A Rx 
Rx=([1,1]=1 [1,2]=0 [1,3]=0 [2,1]=0 [2,2]=`echo "c($angle)" | bc -l` [2,3]=`echo "-s($angle)" | bc -l` [3,1]=0 [3,2]=`echo "s($angle)" | bc -l` [3,3]=`echo "c($angle)" | bc -l`) 

#storage of the atomic positions in an array 
declare -A posAtomes 
for((i=$ligneDebut; i<=$ligneFin; i++)) do 
    for((j=1; j<4; j++)) do 
     posAtomes[$i,$j]=`awk -v ligne=$i -v colonne=$j '{if(NR==ligne) print $(colonne+1)}' $fichier` 
    done 
done 

#computation of the new positions after rotation 
declare -A newPos 
for((i=$ligneDebut; i<=$ligneFin; i++)) do 
    for((j=1; j<4; j++)) do 
     newPos[$i,$j]=`echo "${posAtomes[$i,1]} * ${Rx[$j,1]} + ${posAtomes[$i,2]} * ${Rx[$j,2]} + ${posAtomes[$i,3]} * ${Rx[$j,3]}" | bc -l` 
    done 
done 

#writing the new positions in the original file 
for ((i=$ligneDebut; i<=$ligneFin; i++)) do 
    for ((j=1;j<4;j++)) do 
     awk -v ligne=$i -v colonne=$j -v val=${newPos[$i,$j]} '{if(NR==ligne) {$(colonne+1)=val; print $0} else print $0}' $fichier > tmp && mv tmp $fichier 
    done 
done 

位置ファイルこの(ここでの唯一の1分子である)のようになります。ここでは は、コードがあります!

+0

あなたは「bash」の初心者だと言っているので、私はあなたにそのようなタスクに別の言語を使用するよう助言する機会を与えます。 'bash'には多くの利点がありますが、算術演算の実装が容易ではありません。すべてのLinuxマシンで利用できる汎用言語を探しているなら、 'python'が良い選択だと思います。より特殊化された言語には、MathematicaとMatlab/Octaveが含まれます。 – Aaron

答えて

0

正確な計算には慣れていませんが、いくつかの基本的なトラブルシューティング手順を提供できます。

0)さらに詳しいヘルプを表示するには、入力された入力例(回転角と行番号)、期待する結果、および見ている結果を投稿してみてください。また、実装しようとしている数式を追加すると便利です。

1)多くの単純なecho文を追加して、さまざまなステップで進捗状況を表示してみてください。たとえば、

echo "Angle of rotation (in rad:" 
read angle 
echo "OK, operating with angle: "${angle} 

echo "File or path to file :" 
read fichier 
echo "OK, input file is: "${fichier} 

これらの2つの手順は、プログラムで正しいと思われます。しかし、このアプローチではさらにデバッグの手順が示唆されています。これらのデバッグエコーステートメントをコード全体に追加して中間値を出力し、意図したとおりに動作していることを確認します。

ハッピーハッキング。また、bashでこれを実装する特別な理由はありますか?おそらく、別の言語、例えば組み込みのベクトル数学ライブラリ(Python、R、Matlab ...)を持つ言語などが適しています。

+0

スクリプトを 'bash -x'で起動する(またはスクリプト内で' set -x'コマンドを追加する)ことは、 'echo'をたくさん追加する方が簡単ですが、非常に冗長な出力はオフにすることができます – Aaron

+0

どのラインが走っているのですか?私は、変数の値など、各ステップの出力を表示することを提案していました。基本的にステップスルー・デバッグ。 ;-) – nshiff

+0

これは、どのコマンドが実行されているかを示しています。これは、作成されたコマンドを複数のステップで分解し、それぞれのステップを前の結果で表示するため、ステップバイステップに非常に近くなります。私はそれが 'read'でうまく動作しないことに気付きましたが、標準の変数の影響では、式の代わりに変数の実効値が表示されます。これは、そのステップの後にエコーを追加するのと同じ効果があります。 – Aaron

0

返信いただきありがとうございます!私は "私はどこにでもエコーを置く"と思っていましたが、私はそれを正しくしませんでした。私は間違いを見つけました:bcは10^01ですべてのE + 01を返すためにsedまたはawkを使用しなければならないので、bcは科学的表記法を扱うことができません。こんにちは私はこれで多くの時間を失った!次回はPythonを使用しますhaha

関連する問題