Документ взят из кэша поисковой машины. Адрес оригинального документа : http://erg.biophys.msu.ru/~comcon1/cubediff.r97
Дата изменения: Sun Dec 28 11:23:01 2014
Дата индексирования: Sat Apr 9 22:25:37 2016
Кодировка:
#!/usr/bin/perl -w

#
# PROGRAM
#
# CubeDiff
# (c) 2007, I. Silanes
#
# LICENSE
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License (version 2), as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details (http://www.gnu.org/licenses/gpl.txt).
#
# DESCRIPTION
#
# Computes combination between two (or more) .cube files (e.g. the output
# of Siesta's grid2cube). The cubes can be added or subtracted.
#
# USAGE
#
# % cubediff.pl [+/-]cube1 [+/-]cube2 [+/-cube3 ...]
#
# Cubes preceded by '-' will be subtracted. Cubes preceded by '+' (or by nothing)
# will be added.
#

use strict;

#-------------#
# Variables #
#-------------#
my $svn_revision = "r97 2007-06-29 18:02:55";
my @files; # list of files to process
my %do; # what to do with each file (file => +1/-1)
my $atoms; # string with atoms and geometry
my %fb; # hash with file => [@bulk] info
my @gnp; # (n1,n2,n3) -> number of mesh points in vector n.
my @gd; # ([x1,y1,z1],[x2,y2,z2],[x3,y3,z3]) -> mesh step size (dx,dy,dz) vectors 1,2,3.
my $tnatoms = 0; # total number of atoms
my $totalf; # file with the 'total' molecule (default is the .cube with most atoms)
my $tlines; # total number of data lines (discounting header info)
my @data; # array with total all resulting data

#------------------#
# Read arguments #
#------------------#
die "You MUST specify at least TWO file names!\n" unless ($#ARGV > 0);
foreach (@ARGV)
{
my $f = $_;
$f =~ s/^[-+]//; # delete leading + or -
die "File '$f' does not exist!\n" unless (-f $f); # check that file exists
my $do = 1; # default operation to do
$do = -1 if ($_ =~ /^\-/); # subtract, if preceded by -
$do{$f} = $do; # assign operation to each file
push(@files,$f); # add to list of files to process
};

#--------------------------#
# Read and process files #
#--------------------------#
foreach my $f (@files)
{
my $i = 0; # line we're at
my $j = 0; # index of datum
my $natoms = 0; # number of atoms this file contains
my $nv = 0; # index of mesh vector (0, 1 or 2)
my $s = $do{$f}; # whether to add or subtract data in file $f
open(IN,"<$f") or die "Couldn't open file '$f'!\n"; # open file
while ()
{
$i++; # increment line count
if ($i > $natoms + 6) # these are data lines
{
my @l = split(' ',$_);
foreach my $v (@l)
{
$data[$j] += $s*$v; # add value to $j-th datum
$j++; # increment data index
};
}
elsif ($i > 3 and $i < 7) # read vectors here
{
my @l = split(' ',$_);
my $np = $l[0]; # number of points in VectorN
&cdf_check_val($f,$np,\$gnp[$nv],
"number of points in Vector $nv of mesh"); # check that number of points in this vector
# is ok

foreach my $ii (0..2) # x, y and z
{
my $d = $l[$ii+1]; # dx/y/z in VectorN
&cdf_check_val($f,$d,\$gd[$nv][$ii],
"mesh D($ii) in Vector $nv"); # check it
};
$nv++; # increment vector index
}
elsif ($i == 3) # third line
{
my @l = split(' ',$_);
$natoms = $l[0]; # number of atoms in this file
if ($natoms > $tnatoms) # then this is the file with the most atoms
{
$tnatoms = $natoms;
$totalf = $f;
};
};
};
close(IN); # close the file just read
};

#----------------#
# Print header #
#----------------#
print "Made with cubediff.pl $svn_revision\n";
print "First processed file was $files[0]\n";
my $nh = $tnatoms + 6; # number of header lines
my $nt = $tnatoms + 4; # number of lines to take
my $str = `head -$nh $totalf | tail -$nt`;
print "$str";

#-------------------#
# Print data body #
#-------------------#
my $j = 0;
foreach (@data)
{
$j++;
printf "%12.6E ",$_; # print value
if ($j == 6) # end line every six data
{
print "\n";
$j = 0;
};
};

# ----- Subroutines ---------------------------------------------

####################################################################
# #
# Check that values in given file are the same as the general ones #
# #
####################################################################
sub cdf_check_val
{
my $f = $_[0]; # file name
my $v = $_[1]; # local value
my $pgv = $_[2]; # pointer to general value
my $m = $_[3]; # message to output if negative match

if ($$pgv) # if precedent exists
{
if ($v != $$pgv) # if current value is different from precedent
{
die "File $f has a value for $m ($v) that is different from the other files ($$pgv)!\n";
};
}
else { $$pgv = $v }; # then it is the first file, so general value should be set to local value
};