#!/usr/bin/perl 
################################################################################
#                                                                              #
#  2DHF version 1-2003                                                         #
#  Copyright (C) 2003  Jacek Kobus                                             #
#                                                                              #
#  This software may be used and distributed according to the terms            #
#  of the GNU General Public License, see README and COPYING.                  #
#                                                                              #
################################################################################
# Last update 11/09/02 

# This script facilitates the calculation of polarizabilities and
# hyperpolarizabilities from a series of calculations performed by
# means of the 2D HF program.

# Usage:
 
#    ./elprop file_m2 file_m1 file_p0 file_p1 file_p2 

# where file_i are output files from x2dhf program corresponding to
# calculations with an external finite field -2F, -F, 0, +F and +2F,
# respectively.  F is extracted from the second of these files.

# The derivatives are evaluated by means of the 3 and 5-point central
# differences formulae in order to assess the accuracy of calculations.

# For further details see 

# J.~Kobus, D.~Moncrieff, and S.~Wilson, A comparison of the electric
# moments obtained from finite basis set and finite difference
# {Hartree-Fock} calculations for diatomic molecules, Phys. Rev. A 62
# (2000), 062503/1--9.

# J.~Kobus, D.~Moncrieff, and S.~Wilson, Comparison of the
# polarizabilities and hyperpolarizabilities obtained from finite
# basis set and finite field, finite difference {Hartree-Fock}
# calculations for diatomic molecules, J. Phys. B:
# At. Mol. Opt. Phys. 34 (2001) 5127-5143.

#######################################################################

# check the number of command line arguments

foreach ($i=0; $i<=4;$i++) {
    if ( $ARGV[$i] eq '' ) {
	print ("\nError: missing argument(s) \n\n");
	print ("Usage: ./elprop file_m2 file_m1 file_p0 file_p1 file_p2 \n\n"); 
	exit;
    }
}

$debug=0; # set $debug to nozero value for additional printouts
$narg=5;

if ($ARGV[5] == "") {

# extract the strength of a field from the second of the files

    $x2dhf_out=$ARGV[1]; 
    open(X2DHF_OUT,$x2dhf_out) || die " cannot open: $!";
    
    while (<X2DHF_OUT>){
	if ( $_ =~ /finite electric field:/) {
	    ($t[0],$t[1],$t[2],$t[3])=split(" ",$_);
	    $F=abs($t[3]);
	}
    }
    close(X2DHF_OUT);
}
else {
# in case the F value is not included in an output file it can be given as the last argument
    $F=$ARGV[5];
}

# stop if the field strength has not been determined
if ($F == "" ) {
    print ("Error: field strength is zero \n");
    exit;
}

# examine the five output files in turn

for ($i=0; $i<$narg; $i++) {

    $x2dhf_out=$ARGV[$i]; 

    if ($debug) {print $x2dhf_out, "   ", "\n";}

    open(X2DHF_OUT,$x2dhf_out) || die " nie moge otworzyc: $!";

    while (<X2DHF_OUT>){
	if ( $_ =~ /nuclei /) {
# extract Z1 Z2 
	    ($t[0],$t[1],$t[2],$t[3])=split(" ",$_);
	    $Z1=$t[1];
	    $Z2=$t[2];
	}

	if ( $_ =~ /molecular system:/) {
# extract the description of a case and the internuclear distance
	    $_=<X2DHF_OUT>;
	    $_=<X2DHF_OUT>;
	    $header=$_;
	    ($t[0],$t[1])=split("=",$_);
	    $t[2]=$t[1];
	    ($t[0],$t[1])=split(" ",$t[2]);
	    $R=$t[0];
	}

	if ( $_ =~ /centre     atomic weight       z/ ) {
# extract atomic masses and the centre of mass
	    $_=<X2DHF_OUT>;
	    ($t[0],$t[1],$t[2]) = split (" ",$_);
	    $ma=$t[1];
	    $_=<X2DHF_OUT>;
	    ($t[0],$t[1],$t[2]) = split (" ",$_);
	    $mb=$t[1];
	    $_=<X2DHF_OUT>;
	    ($t[0],$t[1]) = split (" ",$_);
	    $z=$t[1];
	    if ($debug) {print $ma,"  ",$mb, "  ",$z,"\n";}

	    $_=<X2DHF_OUT>;
	    $_=<X2DHF_OUT>;
	    $_=<X2DHF_OUT>;
	    $_=<X2DHF_OUT>;

# extract dipole and quadrupole moments etc
# electronic
# Q_1t    Q_2t  
# Q_1tda  Q_2tda Debye-Ang**0
# total
# Q_1     Q_2
# Q_1da   Q_2da Debye-Ang**0

	    ($t[0],$t[1],$t[2],$t[3],$t[4],$t[5],$t[6]) = split (" ",$_);
	    $Q_1t[$i]=$t[2]; $Q_2t[$i]=$t[3]; $Q_3t[$i]=$t[4]; $Q_4t[$i]=$t[5];
	    if ($debug) {print $t[4],"  ",$t[5],"\n";}

	    $_=<X2DHF_OUT>;
	    ($t[0],$t[1],$t[2],$t[3],$t[4],$t[5],$t[6]) = split (" ",$_);
	    $Q_1tda[$i]=$t[2]; $Q_2tda[$i]=$t[3]; $Q_3tda[$i]=$t[4]; $Q_4tda[$i]=$t[5];
	    if ($debug) {print $t[4],"  ",$t[5],"\n";}

	    $_=<X2DHF_OUT>;
	    ($t[0],$t[1],$t[2],$t[3],$t[4],$t[5],$t[6]) = split (" ",$_);
	    $Q_1[$i]=$t[2]; $Q_2[$i]=$t[3]; $Q_3[$i]=$t[4]; $Q_4[$i]=$t[5];
	    if ($debug) {print $t[4],"  ",$t[5],"\n";}

	    $_=<X2DHF_OUT>;
	    ($t[0],$t[1],$t[2],$t[3],$t[4],$t[5],$t[6]) = split (" ",$_);
	    $Q_1da[$i]=$t[2]; $Q_2da[$i]=$t[3]; $Q_3da[$i]=$t[4]; $Q_4da[$i]=$t[5];
	    if ($debug) {print $t[4],"  ",$t[5],"\n";}
	}

	if ( $_ =~ / ... writing functions to disk .../) {
# extract total energy
	    $_=<X2DHF_OUT>;
	    $_=<X2DHF_OUT>;
	    if ( $_ =~ /total energy/) {
		($t[0],$t[1],$t[2]) = split (" ",$_);
		$t[2] =~ s/D/E/;
		$E[$i]=$t[2];
		if ($debug) {print $E[$i],"  ","\n";}
	    }
	}
	
    };

    close(X2DHF_OUT);
}
print "          ","\n";
print " molecular system:          ","\n";
print ($header," \n");
print " F         ",$F,"\n";
print " Z1        ",$Z1,"\n";
print " Z2        ",$Z2,"\n";
print " R         ",$R,"\n";
print " E(-2F)   ",$E[0], "\n";
print " E(-F)    ",$E[1], "\n";
print " E( 0)    ",$E[2], "\n";
print " E(+F)    ",$E[3], "\n";
print " E(+2F)   ",$E[4], "\n";
print "          ","\n";

# z-component of the dipole moment calculated from the 3-point formula
print " mu_z      ",-($E[3]-$E[1])/(2.0*$F)+(-($R/2.0+$z)*$Z1+($R/2.0-$z)*$Z2), " (E h^2)    ",$Q_1[2], " (Q_1)\n";

# z-component of the dipole moment calculated from the 5-point formula
print " mu_z      ",($E[4]-8*$E[3]+8*$E[1]-$E[0])/(12.0*$F)+(-($R/2.0+$z)*$Z1+($R/2.0-$z)*$Z2), " (E h^4)    ",$Q_1[2], " (Q_1)\n";

# alpha_zz calculated from the energy and dipole moment values by
# means of the 3-point formula

print "          ","\n";
print " alpha_zz  ",-($E[3]+$E[1]-2.0*$E[2])/($F*$F), " (E h^2)    ",-($Q_1t[3]-$Q_1t[1])/(2.0*$F), " (Q_1 h^2) \n";

# alpha_zz calculated from the energy and dipole moment values by
# means of the 5-point formula

print " alpha_zz  ",($E[4]-16*$E[3]+30*$E[2]-16*$E[1]+$E[0])/(12*$F*$F), " (E h^4)    ", ($Q_1t[4]-8*$Q_1t[3]+8*$Q_1t[1]-$Q_1t[0])/(12.0*$F), " (Q_1 h^4) \n";

# zzz-component of the first hyperpolarizability calculated from the energy
# and dipole moment values by means of the 3 and 5-point formulae

print ("\n");
print (" beta_zzz                               ",
       -($Q_1t[3]+$Q_1t[1]-2.0*$Q_1t[2])/($F*$F), " (Q_1 h^2)\n",
       " beta_zzz                               ",
       ($Q_1t[4]-16*$Q_1t[3]+30*$Q_1t[2]-16*$Q_1t[1]+$Q_1t[0])/(12*$F*$F), "( Q_1 h^4) \n");


$i=-1;

if ( $i<0 ) {
    exit;
}

print "------------------------------------------------------------------------- ","\n";
print " Multipole moments  ","\n";
print " R         ",$R,"\n";
print " Q_1  ",  $Q_1[$i], " au     ", $Q_1da[$i],  " Debye-Ang^0 \n";
print " Q_2  ",  $Q_2[$i], " au     ", $Q_2da[$i],  " Debye-Ang^1 \n";
print " Q_3  ",  $Q_3[$i], " au     ", $Q_3da[$i],  " Debye-Ang^2 \n";
print " Q_4  ",  $Q_4[$i], " au     ", $Q_4da[$i],  " Debye-Ang^3 \n";

print "------------------------------------------------------------------------- ","\n";
