mirror of https://gitlab.com/QEF/q-e.git
300 lines
10 KiB
Python
Executable File
300 lines
10 KiB
Python
Executable File
#!/usr/bin/python
|
|
#
|
|
# Copyright (C) 2017 Quantum ESPRESSO group
|
|
# This file is distributed under the terms of the
|
|
# GNU General Public License. See the file `License'
|
|
# in the root directory of the present distribution,
|
|
# or http://www.gnu.org/copyleft/gpl.txt .
|
|
#
|
|
# Written by Lorenzo Paulatto 2017
|
|
#
|
|
from __future__ import print_function
|
|
from os.path import realpath, basename
|
|
from sys import argv
|
|
myname = basename(argv[0])
|
|
#ibrav2cell_x = realpath(__file__)
|
|
#ibrav2cell_x = ibrav2cell_x.replace(myname,"ibrav2cell.x")
|
|
ibrav2cell_x = argv[0].replace(myname,"ibrav2cell.x")
|
|
|
|
def main() :
|
|
from numpy import array
|
|
from argparse import ArgumentParser
|
|
parser = ArgumentParser()
|
|
parser.add_argument('-i', action='append', type=int, metavar="ibrav", dest="ibrav_list", default=[],
|
|
help="ibrav value to explore, can be repeated (default: all)")
|
|
parser.add_argument('-c', type=float, nargs=9, dest="at",
|
|
metavar=("a1x","a1y","a1z","a2x","a2y","a2z", "a3x", "a3y", "a3z"),
|
|
help="cell parameters (default: read from standard input)")
|
|
units = parser.add_mutually_exclusive_group()
|
|
units.add_argument('-A', default=False, action="store_true", dest="angst", help="cell is entered in Agstrom units")
|
|
units.add_argument('-B', default=True, action="store_false", dest="angst", help="cell is entered in Bohr units (default)")
|
|
units.add_argument('--alat', type=float, dest="alat", help="cell is entered in units of alat (in bohr)", metavar="ALAT")
|
|
|
|
parser.add_argument('--celldm', type=float,
|
|
default=[1, 1, 1, 0.5, 0.5, 0.5], nargs=6,
|
|
dest="celldm", metavar=("1","2","3","4","5","6"),
|
|
help="initial values of celldm(1..6), you have to specify all 6 or none (default: 1 1 1 .5 .5 .5)")
|
|
parser.add_argument('--angle', type=float,
|
|
default=[0, 0, 0], nargs=3,
|
|
dest="angle", metavar=("1","2","3"),
|
|
help="initial rotation of the cell (degrees) around x,y,z")
|
|
# parser.add_argument('-t', type=float, default=1.e-3, dest="mthr", help="match threshold", metavar="THR")
|
|
parser.add_argument('-k', type=float, default=1.e-8, dest="kthr", help="convergence threshold", metavar="THR")
|
|
parser.add_argument('-x', type=str, dest="ibrav2cell_x", help="full path to the ibrav2cell.x tool from PW/tools/ \
|
|
(default: look in the same directory as this program)", metavar="/path/to/ibrav2cell.x")
|
|
|
|
args = parser.parse_args()
|
|
|
|
ibrav_list = [1,2,3,-3,4,5,-5,6,7,8,9,-9,91,10,11,12,-12,13,-13,14]
|
|
if args.ibrav_list == []:
|
|
args.ibrav_list = ibrav_list
|
|
|
|
global ibrav2cell_x
|
|
if args.ibrav2cell_x:
|
|
ibrav2cell_x = args.ibrav2cell_x
|
|
|
|
check_ibrav2cell()
|
|
|
|
# test for ibrav = 5
|
|
# cell = [ 3.900896593574796, -2.252183691403927, 18.043044401344225,
|
|
# 0.000000000000000, 4.504367382807855, 18.043044401344225,
|
|
# -3.900896593574796, -2.252183691403927, 18.043044401344225]
|
|
# test for ibrav = 14
|
|
# cell = [ 1.200000000000000E+01, 0.000000000000000E+00, 0.000000000000000E+00,
|
|
# 1.224000000000000E+01, 7.585670702053973E+00, 0.000000000000000E+00,
|
|
# 7.979999999999999E+00, 1.474991525399383E+00, 2.168870673876157E+00]
|
|
|
|
if args.alat and args.angst:
|
|
print("You cannot specifiy both '-A' and '--alat'")
|
|
exit(254)
|
|
|
|
cell = args.at
|
|
if not cell:
|
|
cell = cell_stdin()
|
|
|
|
if args.angst:
|
|
cell = array(cell)*1.889725989
|
|
elif args.alat:
|
|
cell = array(cell)*args.alat
|
|
|
|
#bnds = ((0,None), (0,None), (0,None), (-1,1), (-1,1), (-1,1),
|
|
# (0,360), (0,360), (0,360))
|
|
#bnds = ((0,None), (0,0), (0,None), (0,0), (0,0), (0,0),
|
|
# (0,360), (0,360), (0,360))
|
|
|
|
print("Scanning...")
|
|
for ibrav in args.ibrav_list:
|
|
p=[]
|
|
p.extend(args.celldm)
|
|
p.extend(args.angle)
|
|
#print p
|
|
args0 = { "ibrav" : ibrav,
|
|
"cell" : cell
|
|
}
|
|
options={"maxiter" : 100000,
|
|
"maxls" : 10000,
|
|
"maxcor" : 10000,
|
|
"eps" : 1.e-6,
|
|
"ftol" : pow(args.kthr,2),
|
|
"gtol" : args.kthr,
|
|
"disp" : False,
|
|
}
|
|
|
|
bnds = guess_bounds(p,ibrav)
|
|
#print bnds
|
|
#from scipy.optimize import basinhopping
|
|
#r = basinhopping(recompute, p, minimizer_kwargs={"method":"L-BFGS-B", "bounds":bnds, "args":tuple([args0])}, niter=10)
|
|
from scipy.optimize import minimize
|
|
r = minimize(recompute, p, args=tuple([args0]), method="L-BFGS-B",
|
|
tol=args.kthr, bounds=bnds, options=options)
|
|
#r = minimize(recompute, p, args=tuple([args0]), method="Powell", tol=args.kthr, bounds=bnds, options=options)
|
|
#print r
|
|
#!if r["fun"] < args.mthr:
|
|
if r["success"] and r["fun"]<.1:
|
|
#if True:
|
|
print()
|
|
print(" ibrav =", ibrav )
|
|
check_zero(r["x"], ibrav)
|
|
print("Final discrepancy: {:.1e}".format(r["fun"]))
|
|
print()
|
|
#elif r["fun"] < 100*args.mthr:
|
|
# print "possible noisy match found: ibrav =", ibrav
|
|
# check_zero(r["x"], ibrav)
|
|
|
|
def check_ibrav2cell():
|
|
from numpy import array
|
|
from sys import argv
|
|
if not is_exe(ibrav2cell_x):
|
|
print(" File '"+ibrav2cell_x+"' not found or not executable.")
|
|
print(" Specify the position of ibrav2cell.x with the '-x' command line option.")
|
|
print(" Use '-h' for more help.")
|
|
exit(100)
|
|
namelist = make_namelist(1,[1,0,0,0,0,0,0,0,0])
|
|
at = compute_cell(namelist)
|
|
if not at or len(at)!=9 or any(at != array([1,0,0,0,1,0,0,0,1])):
|
|
print(" File '"+ibrav2cell_x+"' not working as expected.")
|
|
print(" Please verify that it comes from the same distribution as '"+argv[0]+"'")
|
|
print(" and that it is running correctly.")
|
|
exit(101)
|
|
|
|
def is_exe(fpath):
|
|
import os
|
|
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
|
|
|
def run_command(executable_file, input_data):
|
|
import subprocess
|
|
proc = subprocess.Popen(executable_file,
|
|
stdin=subprocess.PIPE,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT
|
|
)
|
|
#text=True
|
|
output, error = proc.communicate(input_data)
|
|
return (output, error)
|
|
|
|
def make_namelist(ibrav,p):
|
|
replacements = { "ibrav" : ibrav,
|
|
"celldm1" : p[0],
|
|
"celldm2" : p[1],
|
|
"celldm3" : p[2],
|
|
"celldm4" : p[3],
|
|
"celldm5" : p[4],
|
|
"celldm6" : p[5],
|
|
"angle1" : p[6],
|
|
"angle2" : p[7],
|
|
"angle3" : p[8]
|
|
}
|
|
systemnl = """
|
|
&system
|
|
ibrav = {ibrav},
|
|
celldm(1) ={celldm1},
|
|
celldm(2) ={celldm2},
|
|
celldm(3) ={celldm3},
|
|
celldm(4) ={celldm4},
|
|
celldm(5) ={celldm5},
|
|
celldm(6) ={celldm6},
|
|
angle(1) ={angle1},
|
|
angle(2) ={angle2},
|
|
angle(3) ={angle3}
|
|
/
|
|
"""
|
|
#print systemnl.format(**replacements)
|
|
return systemnl.format(**replacements)
|
|
|
|
def constraint(p):
|
|
result = all(p[0:3]>=0)
|
|
result = result and all(abs(p[4:7])<=1)
|
|
if result:
|
|
return 0
|
|
else:
|
|
return 1
|
|
|
|
def cell_stdin():
|
|
#import fileinput
|
|
from sys import argv, stdin
|
|
print("Type '{} -h' for help".format(argv[0]))
|
|
print()
|
|
print("Please enter cell parameters: ")
|
|
at = []
|
|
while len(at)<9:
|
|
line = stdin.readline()
|
|
for w in line.split():
|
|
at.append(float(w))
|
|
print(" ok ")
|
|
return at
|
|
|
|
def compute_cell(namelist):
|
|
from numpy import isnan
|
|
output,error = run_command(ibrav2cell_x,namelist)
|
|
output_lines = output.splitlines()
|
|
#output_cell = output_lines[-3]+output_lines[-2]+output_lines[-1]
|
|
output_cell = output_lines[-7]+output_lines[-6]+output_lines[-5]
|
|
# print output_cell
|
|
try:
|
|
at = list(map(float, output_cell.split()))
|
|
except ValueError:
|
|
at = [0,0,0, 0,0,0, 0,0,0]
|
|
if any(isnan(at)):
|
|
at = [0,0,0, 0,0,0, 0,0,0]
|
|
#print at
|
|
return at
|
|
|
|
def check_zero(p, ibrav):
|
|
from numpy import array
|
|
from numpy.linalg import norm
|
|
namelist = make_namelist(ibrav,p)
|
|
at0 = array(compute_cell(namelist))
|
|
p_out=list(p)
|
|
for i in range(len(p)):
|
|
q = list(p)
|
|
q[i] = 0
|
|
namelist = make_namelist(ibrav,q)
|
|
at1 = array(compute_cell(namelist))
|
|
if norm(at0-at1)==0:
|
|
p_out[i] = 0
|
|
else:
|
|
if i < 6:
|
|
print(" celldm({:d}) = {:.6f}".format(i+1, p[i]))
|
|
else :
|
|
print(" angle({:d}) = {:.6f}".format(i-5, p[i]))
|
|
return array(p_out)
|
|
|
|
def guess_bounds(p, ibrav):
|
|
from numpy import array
|
|
from numpy.linalg import norm
|
|
namelist = make_namelist(ibrav,p)
|
|
at0 = array(compute_cell(namelist))
|
|
bnds = [(0,None), (0,None), (0,None), (-1,1), (-1,1), (-1,1),
|
|
(-180,180), (-180,180), (-180,180)]
|
|
|
|
for i in range(len(p)):
|
|
q = list(p)
|
|
q[i] = 0
|
|
namelist = make_namelist(ibrav,q)
|
|
at1 = array(compute_cell(namelist))
|
|
q[i] = 1
|
|
namelist = make_namelist(ibrav,q)
|
|
at2 = array(compute_cell(namelist))
|
|
if norm(at0-at1)==0 and norm(at0-at2)==0:
|
|
#print i
|
|
bnds[i] = (0,0)
|
|
return array(tuple(bnds))
|
|
|
|
def recompute(p, options):
|
|
from numpy import array
|
|
from numpy.linalg import norm
|
|
namelist = make_namelist(options["ibrav"],p)
|
|
at = compute_cell(namelist)
|
|
at1 = array(at)
|
|
at0 = array(options["cell"])
|
|
pat = permutations(at0)
|
|
diff =1000000
|
|
for i in range(6):
|
|
#print(at1)
|
|
#print(pat[0])
|
|
diff = min( norm(at1-pat[i]), diff )
|
|
#print(diff)
|
|
return diff
|
|
|
|
def permutations(c):
|
|
#w, h = 9, 6;
|
|
from numpy import array
|
|
p = [[]]
|
|
p.append([])
|
|
p[0].append(c)
|
|
p.append([])
|
|
p[1].append(array([c[0], c[1], c[2], c[6], c[7], c[8], c[3], c[4], c[5]]))
|
|
p.append([])
|
|
p[2].append(array([c[3], c[4], c[5], c[0], c[1], c[2], c[6], c[7], c[8]]))
|
|
p.append([])
|
|
p[3].append(array([c[3], c[4], c[5], c[6], c[7], c[8], c[0], c[1], c[2]]))
|
|
p.append([])
|
|
p[4].append(array([c[6], c[7], c[8], c[0], c[1], c[2], c[3], c[4], c[5]]))
|
|
p.append([])
|
|
p[5].append(array([c[6], c[7], c[8], c[3], c[4], c[5], c[0], c[1], c[2]]))
|
|
#print(p)
|
|
return (p)
|
|
|
|
main()
|
|
|