这个脚本用于将Gaussian 09的Hartree-Fock计算的.fchk文件转换到Columbus软件使用的mocoef文件。
需要说明的是,测试工作还不完善,不保证此脚本的正确性。
注意:两个软件所使用的基组以及对称性等等必须完全一致!
#! /usr/bin/perl
# code by luozhen
# ATTENTION: MAKE SURE that the SAME BASIS SET has been used in the two softwares.
# results saved in the file "mocoef"
# you MUST have the access to write in the work directory.
open (Columbus, ">mocoef") or die "Can not create file \"mocoef\"!";
# read input data
# use command as "./hfg09tocol.pl inputfile" in bash shell.
while (<>) {
push @lines, $_;
}
# check necessary info
while ($id < @lines) {
if ($lines[$id] =~ m/Number of electrons.*([0-9][0-9]+)/) {
$count_electrons = $1;
} elsif ($lines[$id] =~ m/basis functions.*([0-9][0-9]+)/) {
$count_basis_func = $1;
} elsif ($lines[$id] =~ m/independent functions.*([0-9][0-9]+)/) {
$count_indp_func = $1;
} elsif ($lines[$id] =~ m/Alpha Orbital Energies/) {
$id_start_energy = $id + 1;
} elsif ($lines[$id] =~ m/Alpha MO coefficients/) {
$id_start_mocoef = $id + 1;
$id_end_energy = $id - 1;
} elsif ($lines[$id] =~ m/Total SCF Density/) {
$id_end_mocoef = $id - 1;
}
$id++;
}
# read orbital energies
$lines_count_orbeng = $id_end_energy - $id_start_energy + 1;
@data_orbeng = splice @lines, $id_start_energy, $lines_count_orbeng;
# read MO coefficients
$lines_count_mocoef = $id_end_mocoef - $id_start_mocoef + 1;
$id_start_mocoef -= $lines_count_orbeng;
@data_mocoef = splice @lines, $id_start_mocoef, $lines_count_mocoef;
# necessary lines in the file "mocoef"
print Columbus " 2mocoef\nheader\n" . "\t" x 5 . " 2\nHermit Integral Program : Gaussian 09 \nmo coefficients generated by Gaussian 09\n" . "\t" x 5 . " 1\n" . "\t" x 5 . "$count_basis_func" . "\t" x 5 . "$count_indp_func\n A\n";
# MO coefficients, print
print Columbus "mocoef\n(1p4e16.8)\n";
{
my @numbers;
foreach (@data_mocoef) {
my @temp = split;
push @numbers, @temp;
}
my $count = 0;
my $counts = @numbers;
while ($count < $counts) {
printf Columbus "%16s", $numbers[$count];
if (($count + 1) % 4 == 0) {# 4 numbers per line
print Columbus "\n";
$count ++;
} elsif (($count + 1) % $count_basis_func == 0) {
print Columbus "\n";
splice @numbers, 0, $count_basis_func;
$counts = @numbers;
$count = 0;
} else {
$count ++;
}
}
}
# orbocc, calculate and print
# there's no data about orbitals occupation in Gaussian's *.fchk file.
# so I have to do some calculations myself,
# and I can not ensure that the result of the following block is perfectly correct.
print Columbus "orbocc\n(1p4e16.8)\n";
{
my $count = 0;
my @numbers;
my $count_double_occ = $count_electrons / 2;
if ($count_electrons % 2 == 0) {
while ($count < $count_basis_func) {
if ($count < $count_double_occ) {
push @numbers, "2.00000000E+00";
} else {
push @numbers, "0.00000000E+00";
}
$count ++;
}
} else {
while ($count < $count_basis_func) {
if ($count < $count_double_occ) {
push @numbers, "2.00000000E+00";
} elsif ($count < $count_double_occ) {
push @numbers, "1.00000000E+00";
} else {
push @numbers, "0.00000000E+00";
}
$count ++;
}
}
my $count = 0;
my $counts = @numbers;
while ($count < $counts) {
printf Columbus "%16s", $numbers[$count];
if (($count + 1) % 4 == 0) {# 4 numbers per line
print Columbus "\n";
}
$count ++;
}
print Columbus "\n";
}
# energy, print
print Columbus "energy\n(1p4e16.8)\n";
{
my @numbers;
foreach (@data_orbeng) {
my @temp = split;
push @numbers, @temp;
}
my $count = 0;
my $counts = @numbers;
while ($count < $counts) {
printf Columbus "%16s", $numbers[$count];
if (($count + 1) % 4 == 0) {# 4 numbers per line
print Columbus "\n";
}
$count ++;
}
print Columbus "\n";
}