#!/usr/bin/perl -ws our ($h,$help,$func,$debug); if ($h || $help) { (my $program = $0) =~ s/^.*[\/\\]//; print <[0] =~ s/Edisp\s+-?\d+(\.\d+)?\s*// or last; } $mol->[0] =~ s/\s+$//; } if (@mols > 1) { my $tmp = 'dftd3.xyz'; foreach my $mol (@mols) { write_molden($mol, $tmp); my $D3 = D3correction($tmp); $mol->[0] .= " Edisp $D3"; } unlink $tmp; write_molden(@mols,$file); } else { my $D3 = D3correction($file); $mols[0][0] .= " Edisp $D3"; write_molden($mols[0], $file); } } sub D3correction { my $file = shift; # filename of xyz as input my $D3; # return value my @args = ($dftd3_x, $file, '-func', $func, '-bj'); print "Run `@args`\n" if $debug; open DFTD3, '-|', @args or do {warn "Can't run @args : $!\n"; return undef}; while () { print if $debug; if (/^\s*Edisp \/kcal,au:\s+(\S+)/) { $D3 = $1; } } close DFTD3; if (! defined($D3)) { die "Problems in subroutine D3correction\n"; } return sprintf("%.2f", $D3); } sub read_molden { ############################################################################ ## Молекула -- ссылка на массив, 0-й элемент -- свойства, следующие - атомы. ## Свойства -- ссылка на хэш с ключами Energy, Symmetry ## Атом -- ссылка на массив [atom, x, y, z, ppm] (ppm может не быть). ## ## Читает xyz. Параметры - имена xyz-файлов. Если параметров нет, то <>. ## Возвращает массив найденных молекул. ############################################################################ local @ARGV = @_ ? @_ : @ARGV; my $num = qr/-?\d+(?:\.\d+)?/; my @mols; my $line; LOOP: while ($line || defined($line = <>)) { #print $line; if ($line =~/^\s*(\d+)\s*$/) { my @mol; my $N = $1; last LOOP if eof(); next LOOP if eof(ARGV); $line = <>; chomp $line; $mol[0] = $line; for (my $i=1; $i<=$N; $i++) { last LOOP if eof(); next LOOP if eof(ARGV); $line = <>; #print $line; if ($line =~ /^\s*([A-Z]{1,2})\s+($num)\s+($num)\s+($num)\s*(.*)/io) { $mol[$i] = [$1,$2,$3,$4,$5]; } else { next LOOP; } } push @mols, \@mol; last LOOP if eof(); } else { undef $line; } } return @mols; } sub write_molden { my $file = pop @_; open F, '>', $file or do {warn "Can't write to $file: $!\n"; return}; foreach my $mol (@_) {; my $N = $#{$mol}; print F " $N\n$mol->[0]\n"; for (my $i=1; $i<=$N; $i++) { printf F " %-2s %12.8f %12.8f %12.8f", $mol->[$i][0],$mol->[$i][1],$mol->[$i][2],$mol->[$i][3]; print F " $mol->[$i][4]" if defined $mol->[$i][4]; print F "\n"; } } close F; }