Hex, Bugs and More Physics | Emre S. Tasci

a blog about physics, computation, computational physics and materials…

POSCAR2Cif with symmetries discovered

June 4, 2009 Posted by Emre S. Tasci

In previous posts, I had submitted two codes:

  • POSCAR2Cif : that converts a given POSCAR file to CIF, so to speak, ruthlessly, i.e. just as is, without checking for symmetries or anything.
  • POSCAR2findsymm : another converter that takes a POSCAR file, and prepares an input file such that Harold Stokes’ findsym code from the ISOTROPY package would proceed it and deduce the symmetry information. If findsym executable is not accessible in your system (or if you run the script with the “t” flag set to on), it would just print the input to the screen and you could use it to fill the input form of the code’s web implementation, instead

Anyway, recently it occured to me to write another script that would parse the output of the POSCAR2findsymm output and use that output to construct a CIF file that contained the equivalent sites, etc.. So, ladies and gentlemen, here it is (drums roll)…

Example: Code in action
Using the same POSCAR_Pd3S file as in the POSCAR2Cif entry… Feeding it to POSCAR2findsymm and then applying findsymm2cif on it

sururi@husniya tmp $ python /code/POSCAR2findsym/POSCAR2findsym.py POSCAR_Pd3S | php /code/vaspie/findsymm2cif.php speclist=Pd,S
_cell_length_a  7.21915
_cell_length_b  5.56683
_cell_length_c  7.68685
_cell_angle_alpha       90.00000
_cell_angle_beta        90.00000
_cell_angle_gamma       90.00000
_symmetry_Int_Tables_number     40

loop_
_atom_site_label
_atom_site_type_symbol
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
Pd01    Pd       0.75000         0.17834         0.31139
Pd02    Pd       0.75000         0.17845         0.69126
Pd03    Pd       0.50000         0.00000         0.00132
S01     S        0.75000         0.81592         0.50152

Code

#!/usr/bin/php
<?PHP

//require("/code/toolbox/commandline.inc.php"); # Equivalent handling of $_GET / $_POST
# ============/code/toolbox/commandline.inc.php========================================
// Enables the same treat for command line parameters
// as those of GET parameters.
// Also sets the $first, $last ranges including the gall parameter
 
//Support for command line variable passing:
for($i=1;$i<sizeof($_SERVER["argv"]);$i++)
{
  list($var0,$val0) = explode("=",$_SERVER["argv"][$i]);
  $_GET[$var0] = $val0;
}
 
# ============/code/toolbox/commandline.inc.php========================================
if($_GET["h"]||$_GET["help"])
{
$help = <<<lol
 * Script name: findsymmetry2cif.php                                *
 * Converts the specified FINDSYM output to CIF format              *
 * More Information on FINDSYM : http://stokes.byu.edu/findsym.html *
 *                                                                  *
 * (If you have access) More information on script:                 *
 * http://dutsm2017.stm.tudelft.nl/mediawiki/index.php?title=Findsymm2cif
 *                                                                  *
 * Emre S. Tasci <e.tasci@tudelft.nl>                               *
 *                                                        23/05/09  *

 Usage:
 f         : input file  (Default = stdin)
 o         : output file (Default = stdout)
 identical : if set (identical=1), then the output will be the 
             transformation matrix and origin shift applied to the coordinates 
             so that the given coordinates will be regained.
 speclist  : Define the name of the species, seperated by 'xx' or ',' to be used
             with neighbour listing (Default = AxxBxxCxx...)
             (Labels can also be seperated via [space] as long as speclist is given
             in quotation -- Example: ... speclist=\"Au Si\" )

 Example : php findsymmetry2cif.php f=POSCAR_RhBi4 speclist=Bi,Rh identical=1
lol;
 echo $help."\n";
 exit;
}

$input = "php://stdin";
if($_GET["f"]) $input=$_GET["f"];

$outfile = "php://stdout";
if($_GET["o"]) $outfile=$_GET["o"];

$species_type_template = Array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
if($_GET["speclist"])$species_type_template = split("xx| |,",$_GET["speclist"]);

//if(file_exists("findsymm2cif_php.tmp"))
//    unlink("findsymm2cif_php.tmp");
if($input == "php://stdin")
{
    $lol = file("php://stdin");
    $fp1 = fopen("findsymm2cif_php2.tmp","w");
    foreach($lol as $line)
        fwrite($fp1,$line);
    fclose($fp1);
    $input = "findsymm2cif_php2.tmp";
}
exec('lstart=`grep -n "Type of each atom:" '.$input.'|sed "s:^\([0-9]\+\).*:\1:gi"`;lstart=`expr $lstart + 1`;lfinish=`grep -n "Position of each atom (dimensionless coordinates)" '.$input.'|sed "s:^\([0-9]\+\).*:\1:gi"`;lfinish=`expr $lfinish - 1`;cat '.$input.' |sed -n "`echo $lstart`,`echo $lfinish`p" | sed \':a;N;$!ba;s/\n/ /g\' > findsymm2cif_php.tmp');
exec('grep "Number of atoms in unit cell:" '.$input.' -A1 | tail -n1  >> findsymm2cif_php.tmp');
exec('grep "Space Group" '.$input.' | awk \'{print $3}\'  >> findsymm2cif_php.tmp');
exec('grep "Origin at" '.$input.' | awk \'{print $3 "\t" $4 "\t" $5}\'  >> findsymm2cif_php.tmp');
exec('grep "Vectors a,b,c:" '.$input.' -A3 | tail -n3  >> findsymm2cif_php.tmp');
exec('grep "Values of a,b,c,alpha,beta,gamma:" '.$input.' -A1 | tail -n1  >> findsymm2cif_php.tmp');
exec('grep "Wyckoff" '.$input.' -A1 -n | grep "^[0-9]\+-[0-9]"| sed "s:\(^[0-9]\+\)-[0-9]\+\(.*\):\1\t\2:gi" >> findsymm2cif_php.tmp');

if($input == "findsymm2cif_php2.tmp")
{
    $input = "php://stdin";
    //unlink("findsymm2cif_php2.tmp");
}

//exec("sh findsymm2cif.sh findsymm.out",$file);

$file = file("findsymm2cif_php.tmp");
$type_atoms = split("[ \t]+",trim($file[0]));
$specie_count = Array();
$k = 0;
$specie_count[$k] = 1;
for($i=1; $i < sizeof($type_atoms); $i++)
{
    if($type_atoms[$i] != $type_atoms[$i-1])
        $k++;
    $specie_count[$k]++;
}
for($i=1; $i<sizeof($specie_count); $i++)
    $specie_count[$i] += $specie_count[$i-1];
//print_r($specie_count);

$numatoms = trim($file[1]);
$sgno = trim($file[2]);
$origin_shift = split("[ \t]+",trim($file[3]));
$tr_x = split("[ \t]+",trim($file[4]));
$tr_y = split("[ \t]+",trim($file[5]));
$tr_z = split("[ \t]+",trim($file[6]));
$params = split("[ \t]+",trim($file[7]));
$specie = Array();
for($i = 8;$i<sizeof($file);$i++)
    $specie[] = split("[ \t]+",trim($file[$i]));
$totatoms = 0;
for($i = 0; $i < sizeof($specie)-1; $i++)
{
    $specie[$i][0] = $specie[$i+1][0] - $specie[$i][0] - 1;
    $totatoms += $specie[$i][0];
}
$specie[sizeof($specie)-1][0] = $numatoms - $totatoms;
//print_r($specie);
//print_r($specie_count);
$atoms_counted = 0;
for($i = 0; $i < sizeof($specie); $i++)
{
    # Going over atoms
    $atoms_counted += $specie[$i][0];
    for($j = 0; $j<sizeof($specie_count); $j++)
    {
        if($atoms_counted <= $specie_count[$j])
        {
            $specie[$i][0] = $species_type_template[$j];
            break;
        }
    }
}
//print_r($specie);

if($_GET["identical"])
{
    # Calculate the atom positions corresponding with the given POSCAR
    $trmatrix=Array();
    $trmatrix[0][0] = $tr_x[0];
    $trmatrix[0][1] = $tr_x[1];
    $trmatrix[0][2] = $tr_x[2];
    $trmatrix[1][0] = $tr_y[0];
    $trmatrix[1][1] = $tr_y[1];
    $trmatrix[1][2] = $tr_y[2];
    $trmatrix[2][0] = $tr_z[0];
    $trmatrix[2][1] = $tr_z[1];
    $trmatrix[2][2] = $tr_z[2];

    for($i=0;$i < sizeof($specie); $i++)
    {
        $x = $specie[$i][1];
        $y = $specie[$i][2];
        $z = $specie[$i][3];
        
        $xx = $x*$trmatrix[0][0] + $y*$trmatrix[1][0] + $z*$trmatrix[2][0];
        $yy = $x*$trmatrix[0][1] + $y*$trmatrix[1][1] + $z*$trmatrix[2][1];
        $zz = $x*$trmatrix[0][2] + $y*$trmatrix[1][2] + $z*$trmatrix[2][2];

        $xx += $origin_shift[0];
        $yy += $origin_shift[1];
        $zz += $origin_shift[2];

        $specie[$i][1] = $xx;
        $specie[$i][2] = $yy;
        $specie[$i][3] = $zz;

        for($j=1;$j<4;$j++)
        {
            while($specie[$i][$j]>=1.0)
                $specie[$i][$j]-=1.0;
            while($specie[$i][$j]<0.0)
                $specie[$i][$j]+=1.0;
        }

    }
}

$fp = fopen($outfile,"w");
fwrite($fp,"_cell_length_a"."\t".$params[0]."\n");
fwrite($fp,"_cell_length_b"."\t".$params[1]."\n");
fwrite($fp,"_cell_length_c"."\t".$params[2]."\n");
fwrite($fp,"_cell_angle_alpha"."\t".$params[3]."\n");
fwrite($fp,"_cell_angle_beta"."\t".$params[4]."\n");
fwrite($fp,"_cell_angle_gamma"."\t".$params[5]."\n");
fwrite($fp,"_symmetry_Int_Tables_number"."\t".$sgno."\n\n");
fwrite($fp, "loop_\n_atom_site_label\n_atom_site_type_symbol\n_atom_site_fract_x\n_atom_site_fract_y\n_atom_site_fract_z\n");
//print_r ($specie);
$k = 0;
$specie_type = $specie[0][0];
for($i=0;$i<sizeof($specie);$i++)
{
    if($specie[$i][0] == $specie_type)
        $k++;
    else
    {
        $k = 1;
        $specie_type = $specie[$i][0];
    }
    fwrite($fp, $specie[$i][0].sprintf("%02d",$k)."\t".$specie[$i][0]."\t".sprintf("%8.5f",$specie[$i][1])."\t".sprintf("%8.5f",$specie[$i][2])."\t".sprintf("%8.5f",$specie[$i][3])."\n");
}
fclose($fp);
?>