1 | #! @PERL@ -w
|
---|
2 | #
|
---|
3 | # Evaluates total energy and forces for a given bond dissection
|
---|
4 | #
|
---|
5 | # We assume to have the following, an $Inputdir with the following contents:
|
---|
6 | # - For each Atomic Fragment
|
---|
7 | # - A directory with results, especially pcp.energy.all and pcp.forces.all
|
---|
8 | # - Files called AtomicFragmentTE-Factors.dat and AtomicFragmentForces-Factors.dat
|
---|
9 | # - For Each Bond Fragment
|
---|
10 | # - A directory with results, especially pcp.energy.all and pcp.forces.all
|
---|
11 | # - Files called BondFragmentTE-Factors.dat and BondFragmentForces-Factors.dat
|
---|
12 |
|
---|
13 | use strict;
|
---|
14 |
|
---|
15 | my ($Help, $Prefix, $Inputdir);
|
---|
16 | my ($i, $j, $k, $l);
|
---|
17 | use Getopt::Long;
|
---|
18 | use File::Copy;
|
---|
19 |
|
---|
20 | GetOptions("help" => \$Help,
|
---|
21 | "prefix=s", => \$Prefix,
|
---|
22 | "inputdir=s" => \$Inputdir);
|
---|
23 |
|
---|
24 | if ($Help) { usage(); }
|
---|
25 |
|
---|
26 | sub usage {
|
---|
27 | print STDERR <<"EOF";
|
---|
28 | Usage: $0 [OPTIONS]
|
---|
29 | Evaluates the approximate expression of a many-body bond order dissection and writes pcp.energy and pcp.forces files in the inputdir
|
---|
30 | --prefix <prefix> prefix in front of .forces.all and .energy.all
|
---|
31 | --inputdir <inputdir> read data from this directory
|
---|
32 | --help this help
|
---|
33 | EOF
|
---|
34 | exit 1;
|
---|
35 | }
|
---|
36 |
|
---|
37 | if ((!defined $Inputdir) || (!defined $Prefix)) {
|
---|
38 | print "Inputdir and/or Prefix not specified! See --help.\n";
|
---|
39 | exit 1;
|
---|
40 | }
|
---|
41 |
|
---|
42 | # Total energy
|
---|
43 | my @TotalEnergy;
|
---|
44 | my @TotalForce;
|
---|
45 | my $energy;
|
---|
46 | my $forces;
|
---|
47 | my @tmp;
|
---|
48 |
|
---|
49 | # Parse in total energy factors (1d array: Fragment)
|
---|
50 | open(TEFactors, "<$Inputdir/BondFragmentTE-Factors.dat") or die "could not open $Inputdir/BondFragmentTE-Factors.dat: $!";
|
---|
51 | my $line = <TEFactors>;
|
---|
52 | chomp($line);
|
---|
53 | close(TEFactors);
|
---|
54 | my @Factors = split(/[ \t]+/, $line);
|
---|
55 | my $lasttime = 0;
|
---|
56 |
|
---|
57 | # Print parsed total energy factors
|
---|
58 | print "TEFactors:\n";
|
---|
59 | foreach $energy (@Factors) {
|
---|
60 | print $energy."\t";
|
---|
61 | }
|
---|
62 | print "\n";
|
---|
63 |
|
---|
64 | # Parse in Force factors (3d array: AtomPerFragment,AtomPerWholeMolecule,Fragment )
|
---|
65 | my @ForceFactors;
|
---|
66 | open(FORCEFactors, "<$Inputdir/BondFragmentForces-Factors.dat") or die "could not open $Inputdir/BondFragmentForces-Factors.dat: $!";
|
---|
67 | do {
|
---|
68 | my @FragmentFactors;
|
---|
69 | do {
|
---|
70 | $line = <FORCEFactors>;
|
---|
71 | chomp $line;
|
---|
72 | my @tmp = split(/[ \t]+/, $line);
|
---|
73 | if ( $#tmp ) {
|
---|
74 | push @FragmentFactors, [ @tmp ]; # push a copy of the parsed line
|
---|
75 | }
|
---|
76 | #foreach $forces ( @tmp ) {
|
---|
77 | # print "\t [ $forces ]";
|
---|
78 | #}
|
---|
79 | $energy = $#tmp;
|
---|
80 | #print "\t: ".$#tmp." atoms.\n";
|
---|
81 | } until ( $energy == -1 ); # next fragment
|
---|
82 | #print "Next Fragment!\n";
|
---|
83 | # read over next line
|
---|
84 | push @ForceFactors, [ @FragmentFactors ]; # push a copy of the parsed Fragment
|
---|
85 | $line = <FORCEFactors>;
|
---|
86 | } while(<FORCEFactors>);
|
---|
87 | close(FORCEFactors);
|
---|
88 |
|
---|
89 | # Print parsed Force Factors
|
---|
90 | print "\nForce Factors:\n";
|
---|
91 | for $i ( 0 .. $#ForceFactors ) {
|
---|
92 | print "Fragment $i\n";
|
---|
93 | for $j ( 0 .. $#{$ForceFactors[$i]} ) {
|
---|
94 | for $k ( 0 .. $#{${$ForceFactors[$i]}[$j]} ) {
|
---|
95 | print $ForceFactors[$i][$j][$k]."\t";
|
---|
96 | }
|
---|
97 | print "\n";
|
---|
98 | }
|
---|
99 | print "\n";
|
---|
100 | }
|
---|
101 |
|
---|
102 | # check on the number of digits
|
---|
103 | my $format = "-1";
|
---|
104 | for($i=1;$i<10;$i++)
|
---|
105 | {
|
---|
106 | my $test = "%0".$i."s";
|
---|
107 | my $filename = sprintf($test,$i);
|
---|
108 | if ( -e "$Inputdir/BondFragment$filename" )
|
---|
109 | {
|
---|
110 | $format = $test;
|
---|
111 | }
|
---|
112 | }
|
---|
113 | print "Recognized format for BondFragment filename is: $format\n";
|
---|
114 |
|
---|
115 |
|
---|
116 | # Parse local energy and forces from the various FragmentDirs
|
---|
117 | for ($i=0;$i<=$#Factors;$i++)
|
---|
118 | {
|
---|
119 | my $filename = sprintf($format, $i);
|
---|
120 | my @LocalEnergy;
|
---|
121 | open(TE, "<$Inputdir/BondFragment".$filename."/$Prefix.energy.all") or die "could not open $Inputdir/BondFragment".$filename."/$Prefix.energy.all: $!";
|
---|
122 | # skip first line containing the header
|
---|
123 | $line = <TE>;
|
---|
124 | # ($Time, $Total, $Kinetic, $NonLocal, $Correlation, $Exchange, $Pseudo, $Hartree, $Gauss, $Ewald, $ETotal)
|
---|
125 | while ($line = <TE>) {
|
---|
126 | chomp($line);
|
---|
127 | my @tmp = split(/[ \t]+/, $line);
|
---|
128 | for $k ( 0 .. $#tmp) {
|
---|
129 | $tmp[$k] *= $Factors[$i];
|
---|
130 | }
|
---|
131 | push @LocalEnergy, [ @tmp ];
|
---|
132 | }
|
---|
133 | close(TE);
|
---|
134 |
|
---|
135 | # sum up energy
|
---|
136 | for $j ( 0 .. $#LocalEnergy )
|
---|
137 | {
|
---|
138 | #print " @{$LocalEnergy[$j]} \n";
|
---|
139 | if ( $i == 0) {
|
---|
140 | push @TotalEnergy, [ @{$LocalEnergy[$j]} ];
|
---|
141 | } else {
|
---|
142 | for $k ( 0 .. $#{$LocalEnergy[$j]} ) {
|
---|
143 | $TotalEnergy[$j][$k] += $LocalEnergy[$j][$k];
|
---|
144 | }
|
---|
145 | }
|
---|
146 | }
|
---|
147 |
|
---|
148 | my @LocalForce;
|
---|
149 | open(FORCE, "<$Inputdir/BondFragment".$filename."/$Prefix.forces.all") or die "could not open $Inputdir/BondFragment".$filename."/$Prefix.forces.all: $!";
|
---|
150 | # skip first line containing the header
|
---|
151 | $line = <FORCE>;
|
---|
152 | while (<FORCE>) {
|
---|
153 | next if /MeanForce:/;
|
---|
154 | chomp;
|
---|
155 | my @tmp = split(/[ \t]/);
|
---|
156 | push @LocalForce, [ @tmp ];
|
---|
157 | }
|
---|
158 | close(FORCE);
|
---|
159 |
|
---|
160 | # sum up forces
|
---|
161 | for $j ( 0 .. $#LocalForce) { # atom in fragment
|
---|
162 | # Add local forces times their factor
|
---|
163 | for $k ( 0 .. $#{$LocalForce[$j]} ) { # force type
|
---|
164 | for $l ( 0 .. $#{$ForceFactors[$i]} ) { # whole molecule atom
|
---|
165 | #print "fragment $i\tfragment atom $j\t force type $k\t molecule atom $l\n";
|
---|
166 | if (0) { # ($j == 0) && ($i == 0)) {
|
---|
167 | if ($k >= 5) { # forces start at column 5
|
---|
168 | $TotalForce[$l][$k] = $LocalForce[$j][$k] * $ForceFactors[$i][$l][$j];
|
---|
169 | } else { # take correct position only if local fragment atom relates to whole molecule atom
|
---|
170 | if ($ForceFactors[$i][$l][$j] != 0) {
|
---|
171 | $TotalForce[$l][$k] = $LocalForce[$j][$k];
|
---|
172 | }
|
---|
173 | }
|
---|
174 | } else {
|
---|
175 | if ($k >= 5) { # forces start at column 5
|
---|
176 | $TotalForce[$l][$k] += $LocalForce[$j][$k] * $ForceFactors[$i][$l][$j];
|
---|
177 | } else { # take correct position only if local fragment atom relates to whole molecule atom
|
---|
178 | if ($ForceFactors[$i][$l][$j] != 0) {
|
---|
179 | $TotalForce[$l][$k] = $LocalForce[$j][$k];
|
---|
180 | }
|
---|
181 | }
|
---|
182 | }
|
---|
183 | }
|
---|
184 | }
|
---|
185 | }
|
---|
186 | }
|
---|
187 |
|
---|
188 | # output summed up approximate total energy
|
---|
189 | open(TE, ">$Inputdir/$Prefix.energy.all") or die "could not open $Inputdir/$Prefix.energy.all: $!";
|
---|
190 | printf(TE "#Level\t%s\t\t%s\t\t%s\t\t%s\t%s\t%s\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\n",
|
---|
191 | "Time",
|
---|
192 | "Total",
|
---|
193 | "Kinetic", "NonLocal",
|
---|
194 | "Correlation", "Exchange",
|
---|
195 | "Pseudo", "Hartree",
|
---|
196 | "-Gauss",
|
---|
197 | "Ewald",
|
---|
198 | "IonKin",
|
---|
199 | "ETotal");
|
---|
200 | for $j ( 0 .. $#TotalEnergy )
|
---|
201 | {
|
---|
202 | print TE ($j+1)."\t";
|
---|
203 | for $k ( 0 .. $#{$TotalEnergy[$j]} ) {
|
---|
204 | print TE "$TotalEnergy[$j][$k]\t";
|
---|
205 | }
|
---|
206 | print TE "\n";
|
---|
207 | }
|
---|
208 | print TE "\n";
|
---|
209 | close(TE);
|
---|
210 |
|
---|
211 | # output summed up approximate total forces
|
---|
212 | open(FORCE, ">$Inputdir/$Prefix.forces.all") or die "could not open $Inputdir/$Prefix.forces.all: $!";
|
---|
213 | printf(FORCE "#%s\t%s\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t%s\t%s\t%s\t\t%s\t\t%s\n",
|
---|
214 | "Type", "No",
|
---|
215 | "Pos0", "Pos1", "Pos2",
|
---|
216 | "Total0", "Total1", "Total2",
|
---|
217 | "Local0", "Local1", "Local2",
|
---|
218 | "NLocal0", "NLocal1", "NLocal2",
|
---|
219 | "Magnetic0", "Magnetic1", "Magnetic2",
|
---|
220 | "Ewald0", "Ewald1", "Ewald2");
|
---|
221 | for $i ( 0 .. $#TotalForce ) {
|
---|
222 | for $j ( 0 .. $#{$TotalForce[$i]} ) {
|
---|
223 | print FORCE "$TotalForce[$i][$j]\t";
|
---|
224 | }
|
---|
225 | print FORCE "\n";
|
---|
226 | }
|
---|
227 | print FORCE "\n";
|
---|
228 | close(FORCE);
|
---|
229 |
|
---|
230 |
|
---|
231 | exit 0;
|
---|