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);
?>