Add support for SPRKKR potential.
This is a first version for this option. Some work has still to be done...
This commit is contained in:
parent
81459cfcfc
commit
8ebfd624e1
|
@ -1,302 +0,0 @@
|
|||
INFO:msspec:Getting the TMatrix...
|
||||
_________________________________________________________________
|
||||
|
||||
PHAGEN
|
||||
_________________________________________________________________
|
||||
|
||||
parameters for this xpd calculation:
|
||||
-----------------------------------------------------------------
|
||||
edge= k
|
||||
potype= hedin norman= stdcrm absorber= 1
|
||||
coor= angs emin= 13.52 Ry emax= 13.52 Ry
|
||||
delta= 0.300 Ry gamma= 0.03 Ry eftri= 0.000 Ry
|
||||
ionization state : neutral
|
||||
final state potential generated internally
|
||||
|
||||
|
||||
Computes the T-matrix and radial matrix elements
|
||||
|
||||
|
||||
coordinates in angstroms Radii
|
||||
-----------------------------------------------------------------
|
||||
Cu 29 0.0000 0.0000 -3.6000 0.0000 0.0000
|
||||
Cu 29 -1.8000 -1.8000 0.0000 0.0000 0.0000
|
||||
Cu 29 -1.8000 0.0000 -1.8000 0.0000 0.0000
|
||||
Cu 29 -3.6000 0.0000 0.0000 0.0000 0.0000
|
||||
Cu 29 -1.8000 1.8000 0.0000 0.0000 0.0000
|
||||
Cu 29 0.0000 -1.8000 -1.8000 0.0000 0.0000
|
||||
Cu 29 0.0000 -3.6000 0.0000 0.0000 0.0000
|
||||
Cu 29 1.8000 -1.8000 0.0000 0.0000 0.0000
|
||||
Cu 29 0.0000 1.8000 -1.8000 0.0000 0.0000
|
||||
Cu 29 1.8000 0.0000 -1.8000 0.0000 0.0000
|
||||
Cu 29 0.0000 0.0000 0.0000 0.0000 0.0000
|
||||
Cu 29 1.8000 1.8000 0.0000 0.0000 0.0000
|
||||
Cu 29 0.0000 3.6000 0.0000 0.0000 0.0000
|
||||
Cu 29 3.6000 0.0000 0.0000 0.0000 0.0000
|
||||
-----------------------------------------------------------------
|
||||
|
||||
|
||||
** enter calphas **
|
||||
---
|
||||
total energy for atom in ground state
|
||||
total energy for atom with a hole in k edge
|
||||
calculated ionization energy for edge k = 8994.86914 eV
|
||||
---
|
||||
calculated ionization potential (ryd) = 661.387451
|
||||
---
|
||||
|
||||
|
||||
symmetrizing coordinates...
|
||||
|
||||
|
||||
symmetrized atomic coordinates of cluster
|
||||
|
||||
position
|
||||
atom no. x y z eq
|
||||
|
||||
1 osph 0 0.0000 0.0000 0.0000 0
|
||||
2 Cu 29 0.0000 0.0000 -5.3452 0
|
||||
3 Cu 29 -3.4015 -3.4015 1.4578 0
|
||||
4 Cu 29 -3.4015 0.0000 -1.9437 0
|
||||
5 Cu 29 -6.8030 0.0000 1.4578 0
|
||||
6 Cu 29 0.0000 0.0000 1.4578 0
|
||||
7 Cu 29 -3.4015 3.4015 1.4578 3
|
||||
8 Cu 29 3.4015 -3.4015 1.4578 3
|
||||
9 Cu 29 3.4015 3.4015 1.4578 3
|
||||
10 Cu 29 0.0000 -3.4015 -1.9437 4
|
||||
11 Cu 29 0.0000 3.4015 -1.9437 4
|
||||
12 Cu 29 3.4015 0.0000 -1.9437 4
|
||||
13 Cu 29 0.0000 -6.8030 1.4578 5
|
||||
14 Cu 29 0.0000 6.8030 1.4578 5
|
||||
15 Cu 29 6.8030 0.0000 1.4578 5
|
||||
|
||||
computing muffin tin potential and phase shifts
|
||||
generating core state wavefunction
|
||||
generating final potential (complex hedin-lundqvist exchange)
|
||||
MT radii for Hydrogen atoms determined by stdcrm unless other options are specified
|
||||
|
||||
-----------------------------------------------------------------
|
||||
i rs(i) i=1,natoms
|
||||
1 9.28 2 2.50 3 2.46 4 2.35 5 2.48 6 2.33 7 2.46 8 2.46
|
||||
9 2.46 10 2.35 11 2.35 12 2.35 13 2.48 14 2.48 15 2.48
|
||||
N.B.: Order of atoms as reshuffled by symmetry routines
|
||||
-----------------------------------------------------------------
|
||||
|
||||
input value for coulomb interst. potential = -0.699999988
|
||||
and interstitial rs = 3.00000000
|
||||
lower bound for coulomb interst. potential = -0.290025890
|
||||
and for interst. rs = 2.54297900
|
||||
|
||||
lmax assignment based on l_max = r_mt * k_e + 2
|
||||
where e is the running energy
|
||||
optimal lmax chosen according to the running energy e for each atom
|
||||
|
||||
|
||||
number of centers= 14
|
||||
|
||||
starting potentials and/or charge densities written to file 13
|
||||
symmetry information generated internally
|
||||
symmetry information written to file 14
|
||||
|
||||
|
||||
core initial state of type: 1s1/2
|
||||
|
||||
fermi level = -0.17690
|
||||
|
||||
generating t_l (for030) and atomic cross section (for050)
|
||||
|
||||
gamma = 0.030000 rsint = 3.944844
|
||||
|
||||
check in subroutine cont
|
||||
order of neighb. -- symb. -- dist. from absorber
|
||||
|
||||
3 Cu 4.81045771
|
||||
5 Cu 6.80301476
|
||||
2 Cu 8.33195782
|
||||
4 Cu 9.62091541
|
||||
-----------------------------------------------------------------
|
||||
1 Cu 0.000000
|
||||
3 Cu 4.810458
|
||||
5 Cu 6.803015
|
||||
2 Cu 8.331958
|
||||
4 Cu 9.620915
|
||||
1 Cu 0.000000
|
||||
3 Cu 4.810458
|
||||
5 Cu 6.803015
|
||||
2 Cu 8.331958
|
||||
4 Cu 9.620915
|
||||
|
||||
irho = 2 entering vxc to calculate energy dependent exchange
|
||||
energy dependent vcon = (-0.181322575,0.183172509) at energy 13.5235996
|
||||
calculating atomic t-matrix elements atm(n)
|
||||
check orthogonality between core and continuum state
|
||||
scalar product between core and continuum state = (0.215178907,-7.336383685E-03)
|
||||
sqrt(xe/pi) = (1.08555424,-3.627028549E-03)
|
||||
check ionization potential: 661.387451
|
||||
|
||||
|
||||
value of the mean free path:
|
||||
-----------------------------------------------------------------
|
||||
average mean free path due to finite gamma: mfp = 8.81667 angstrom at energy 13.52360
|
||||
|
||||
average mean free path in the cluster : mfp = 8.71420 angstrom at energy 13.52360
|
||||
|
||||
total mean free path due to Im V and gamma: mfp = 4.38257 angstrom at energy 13.52360
|
||||
-----------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
** phagen terminated normally **
|
||||
|
||||
|
||||
INFO:msspec:Getting the TMatrix...
|
||||
_________________________________________________________________
|
||||
|
||||
PHAGEN
|
||||
_________________________________________________________________
|
||||
|
||||
parameters for this xpd calculation:
|
||||
-----------------------------------------------------------------
|
||||
edge= k
|
||||
potype= hedin norman= stdcrm absorber= 1
|
||||
coor= angs emin= 13.52 Ry emax= 13.52 Ry
|
||||
delta= 0.300 Ry gamma= 0.03 Ry eftri= 0.000 Ry
|
||||
ionization state : neutral
|
||||
final state potential generated internally
|
||||
|
||||
|
||||
Computes the T-matrix and radial matrix elements
|
||||
|
||||
|
||||
coordinates in angstroms Radii
|
||||
-----------------------------------------------------------------
|
||||
Cu 29 0.0000 0.0000 -3.8000 0.0000 0.0000
|
||||
Cu 29 -1.9000 -1.9000 0.0000 0.0000 0.0000
|
||||
Cu 29 -1.9000 0.0000 -1.9000 0.0000 0.0000
|
||||
Cu 29 -3.8000 0.0000 0.0000 0.0000 0.0000
|
||||
Cu 29 -1.9000 1.9000 0.0000 0.0000 0.0000
|
||||
Cu 29 0.0000 -1.9000 -1.9000 0.0000 0.0000
|
||||
Cu 29 0.0000 -3.8000 0.0000 0.0000 0.0000
|
||||
Cu 29 1.9000 -1.9000 0.0000 0.0000 0.0000
|
||||
Cu 29 0.0000 1.9000 -1.9000 0.0000 0.0000
|
||||
Cu 29 1.9000 0.0000 -1.9000 0.0000 0.0000
|
||||
Cu 29 0.0000 0.0000 0.0000 0.0000 0.0000
|
||||
Cu 29 1.9000 1.9000 0.0000 0.0000 0.0000
|
||||
Cu 29 0.0000 3.8000 0.0000 0.0000 0.0000
|
||||
Cu 29 3.8000 0.0000 0.0000 0.0000 0.0000
|
||||
-----------------------------------------------------------------
|
||||
|
||||
|
||||
** enter calphas **
|
||||
---
|
||||
total energy for atom in ground state
|
||||
total energy for atom with a hole in k edge
|
||||
calculated ionization energy for edge k = 8994.86914 eV
|
||||
---
|
||||
calculated ionization potential (ryd) = 661.387451
|
||||
---
|
||||
|
||||
|
||||
symmetrizing coordinates...
|
||||
|
||||
|
||||
symmetrized atomic coordinates of cluster
|
||||
|
||||
position
|
||||
atom no. x y z eq
|
||||
|
||||
1 osph 0 0.0000 0.0000 0.0000 0
|
||||
2 Cu 29 0.0000 0.0000 -5.6422 0
|
||||
3 Cu 29 -3.5905 -3.5905 1.5388 0
|
||||
4 Cu 29 -3.5905 0.0000 -2.0517 0
|
||||
5 Cu 29 -7.1810 0.0000 1.5388 0
|
||||
6 Cu 29 0.0000 0.0000 1.5388 0
|
||||
7 Cu 29 -3.5905 3.5905 1.5388 3
|
||||
8 Cu 29 3.5905 -3.5905 1.5388 3
|
||||
9 Cu 29 3.5905 3.5905 1.5388 3
|
||||
10 Cu 29 0.0000 -3.5905 -2.0517 4
|
||||
11 Cu 29 0.0000 3.5905 -2.0517 4
|
||||
12 Cu 29 3.5905 0.0000 -2.0517 4
|
||||
13 Cu 29 0.0000 -7.1810 1.5388 5
|
||||
14 Cu 29 0.0000 7.1810 1.5388 5
|
||||
15 Cu 29 7.1810 0.0000 1.5388 5
|
||||
|
||||
computing muffin tin potential and phase shifts
|
||||
generating core state wavefunction
|
||||
generating final potential (complex hedin-lundqvist exchange)
|
||||
MT radii for Hydrogen atoms determined by stdcrm unless other options are specified
|
||||
|
||||
-----------------------------------------------------------------
|
||||
i rs(i) i=1,natoms
|
||||
1 9.80 2 2.64 3 2.60 4 2.44 5 2.61 6 2.46 7 2.60 8 2.60
|
||||
9 2.60 10 2.44 11 2.44 12 2.44 13 2.61 14 2.61 15 2.61
|
||||
N.B.: Order of atoms as reshuffled by symmetry routines
|
||||
-----------------------------------------------------------------
|
||||
|
||||
input value for coulomb interst. potential = -0.699999988
|
||||
and interstitial rs = 3.00000000
|
||||
lower bound for coulomb interst. potential = -0.232031077
|
||||
and for interst. rs = 2.76609278
|
||||
|
||||
lmax assignment based on l_max = r_mt * k_e + 2
|
||||
where e is the running energy
|
||||
optimal lmax chosen according to the running energy e for each atom
|
||||
|
||||
|
||||
number of centers= 14
|
||||
|
||||
starting potentials and/or charge densities written to file 13
|
||||
symmetry information generated internally
|
||||
symmetry information written to file 14
|
||||
|
||||
|
||||
core initial state of type: 1s1/2
|
||||
|
||||
fermi level = -0.16924
|
||||
|
||||
generating t_l (for030) and atomic cross section (for050)
|
||||
|
||||
gamma = 0.030000 rsint = 4.292365
|
||||
|
||||
check in subroutine cont
|
||||
order of neighb. -- symb. -- dist. from absorber
|
||||
|
||||
3 Cu 5.07770586
|
||||
5 Cu 7.18096018
|
||||
2 Cu 8.79484367
|
||||
4 Cu 10.1554117
|
||||
-----------------------------------------------------------------
|
||||
1 Cu 0.000000
|
||||
3 Cu 5.077706
|
||||
5 Cu 7.180960
|
||||
2 Cu 8.794844
|
||||
4 Cu 10.155412
|
||||
1 Cu 0.000000
|
||||
3 Cu 5.077706
|
||||
5 Cu 7.180960
|
||||
2 Cu 8.794844
|
||||
4 Cu 10.155412
|
||||
|
||||
irho = 2 entering vxc to calculate energy dependent exchange
|
||||
energy dependent vcon = (-0.151319593,0.168841615) at energy 13.5235996
|
||||
calculating atomic t-matrix elements atm(n)
|
||||
check orthogonality between core and continuum state
|
||||
scalar product between core and continuum state = (0.217915282,-9.193832986E-03)
|
||||
sqrt(xe/pi) = (1.08495688,-3.348779166E-03)
|
||||
check ionization potential: 661.387451
|
||||
|
||||
|
||||
value of the mean free path:
|
||||
-----------------------------------------------------------------
|
||||
average mean free path due to finite gamma: mfp = 8.81667 angstrom at energy 13.52360
|
||||
|
||||
average mean free path in the cluster : mfp = 9.13179 angstrom at energy 13.52360
|
||||
|
||||
total mean free path due to Im V and gamma: mfp = 4.48573 angstrom at energy 13.52360
|
||||
-----------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
** phagen terminated normally **
|
||||
|
||||
|
|
@ -1,8 +1,30 @@
|
|||
import ase
|
||||
from .version import __version__
|
||||
from .misc import LOGGER
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright © 2016-2020 - Rennes Physics Institute
|
||||
#
|
||||
# This file is part of msspec.
|
||||
#
|
||||
# msspec is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
# msspec is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this msspec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Source file : src/msspec/__init__.py
|
||||
# Last modified: ven. 10 avril 2020 17:22:12
|
||||
# Committed by : "Sylvain Tricot <sylvain.tricot@univ-rennes1.fr>"
|
||||
|
||||
|
||||
import ase
|
||||
|
||||
from msspec.misc import LOGGER
|
||||
from msspec.version import __version__
|
||||
|
||||
__sha__ = "$Id$"
|
||||
|
||||
def init_msspec():
|
||||
LOGGER.debug('Initialization of the msspec module')
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# coding: utf-8
|
||||
# vim: set et ts=4 sw=4 fdm=indent mouse=a cc=+1 tw=80:
|
||||
|
||||
"""
|
||||
Module calcio
|
||||
|
@ -6,13 +7,16 @@ Module calcio
|
|||
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from datetime import datetime
|
||||
import ase
|
||||
import re
|
||||
import numpy as np
|
||||
import ase
|
||||
from ase import Atom, Atoms
|
||||
from ase.data import chemical_symbols
|
||||
|
||||
from msspec.misc import UREG, LOGGER
|
||||
|
||||
|
||||
class PhagenIO(object):
|
||||
def __init__(self, phagen_parameters, malloc_parameters):
|
||||
self.parameters = phagen_parameters
|
||||
|
@ -27,8 +31,9 @@ class PhagenIO(object):
|
|||
self.nlmax = None
|
||||
self.energies = None
|
||||
|
||||
def write_input_file(self, filename='input.ms'):
|
||||
def write_input_file(self, filename='input.ms'): # noqa: C901
|
||||
# in input folder
|
||||
LOGGER.debug("Writing Phagen input file")
|
||||
atoms = self.parameters.atoms
|
||||
if not atoms.has('mt_radii'):
|
||||
for a in atoms:
|
||||
|
@ -58,7 +63,7 @@ class PhagenIO(object):
|
|||
# other sections
|
||||
continue
|
||||
value = parameter.value
|
||||
if isinstance(value, str) and not re.match('\..*\.', value):
|
||||
if isinstance(value, str) and not re.match(r'\..*\.', value):
|
||||
s = ' {}=\'{:s}\''.format(name, str(parameter))
|
||||
else:
|
||||
s = ' {}={:s}'.format(name, str(parameter))
|
||||
|
@ -167,7 +172,8 @@ class PhagenIO(object):
|
|||
lines = pattern.split(content)
|
||||
|
||||
# get the number of atoms (nat) and the number of energy points (ne)
|
||||
nat, ne, _, ipot, lmax_mode = list(map(int, content.split('\n')[0].split()))
|
||||
nat, ne, _, ipot, lmax_mode = list(map(int,
|
||||
content.split('\n')[0].split()))
|
||||
self.nat = nat
|
||||
self.ne = ne
|
||||
self.ipot = ipot
|
||||
|
@ -181,7 +187,7 @@ class PhagenIO(object):
|
|||
if not re.match(r'^\d+$', n):
|
||||
numbers.append(float(n))
|
||||
if len(numbers) > 0:
|
||||
array = np.array(numbers).reshape((-1, 4)) # pylint: disable=no-member
|
||||
array = np.array(numbers).reshape((-1, 4))
|
||||
atom_data.append(array)
|
||||
|
||||
# construct the data array
|
||||
|
@ -265,8 +271,27 @@ class PhagenIO(object):
|
|||
proto_index = int(data[i, -1])
|
||||
proto_indices.append(proto_index)
|
||||
atoms.set_array('proto_indices', np.array(proto_indices))
|
||||
self.nateqm = int(np.max([len(np.where(data[:,-1]==i)[0]) for i in range(
|
||||
1, self.nat + 1)]))
|
||||
self.nateqm = int(np.max([
|
||||
len(np.where(data[:, -1] == i)[0]) for i in range(1, self.nat + 1)
|
||||
]))
|
||||
|
||||
def load_prototypical_atoms(self, filename='molinpot3.out'):
|
||||
with open(filename, 'r') as fd:
|
||||
content = fd.readlines()
|
||||
|
||||
content = content[-len(self.parameters.atoms):]
|
||||
cluster = Atoms()
|
||||
for line in content:
|
||||
datatxt = np.array(re.split(r'\s+', line.strip(' \n')))
|
||||
neq = int(datatxt[-1])
|
||||
if neq == 0:
|
||||
Z = int(datatxt[1])
|
||||
xyz = (datatxt[[2, 3, 4]].astype(float) * UREG.a0).to(
|
||||
'angstrom').magnitude
|
||||
sym = chemical_symbols[Z]
|
||||
cluster += Atom(sym, position=xyz)
|
||||
self.prototypical_atoms = cluster
|
||||
return cluster
|
||||
|
||||
def load_potential_file(self, filename='plot_vc.dat'):
|
||||
a_index = 0
|
||||
|
@ -279,11 +304,13 @@ class PhagenIO(object):
|
|||
a_index += 1
|
||||
d = d.split()
|
||||
a = {'Symbol': d[1], 'distance': float(d[4]),
|
||||
'coord': np.array([float(d[7]), float(d[8]), float(d[9])]),
|
||||
'coord': np.array([float(d[7]), float(d[8]),
|
||||
float(d[9])]),
|
||||
'index': int(a_index), 'values': []}
|
||||
pot_data.append(a)
|
||||
else:
|
||||
pot_data[a_index - 1]['values'].append(tuple(float(_) for _ in d.split()))
|
||||
pot_data[a_index - 1]['values'].append(
|
||||
tuple(float(_) for _ in d.split()))
|
||||
|
||||
# convert the values list to a numpy array
|
||||
for _pot_data in pot_data:
|
||||
|
@ -292,27 +319,30 @@ class PhagenIO(object):
|
|||
|
||||
return pot_data
|
||||
|
||||
|
||||
class SpecIO(object):
|
||||
def __init__(self, parameters, malloc_parameters, phagenio):
|
||||
self.parameters = parameters
|
||||
self.malloc_parameters = malloc_parameters
|
||||
self.phagenio = phagenio
|
||||
|
||||
def write_input_file(self, filename='spec.dat'):
|
||||
def write_input_file(self, filename='spec.dat'): # noqa: C901
|
||||
def title(t, shift=4, width=79, center=True):
|
||||
if center:
|
||||
s = ('{}*{:^%ds}*\n' % (width - shift - 2)).format(' ' * shift, t)
|
||||
s = ('{}*{:^%ds}*\n' % (width - shift - 2)
|
||||
).format(' ' * shift, t)
|
||||
else:
|
||||
s = ('{}*{:%ds}*\n' % (width - shift - 2)).format(' ' * shift, t)
|
||||
s = ('{}*{:%ds}*\n' % (width - shift - 2)
|
||||
).format(' ' * shift, t)
|
||||
return s
|
||||
|
||||
def rule(tabs=(5, 10, 10, 10, 10), symbol='=', shift=4, width=79):
|
||||
s = ' ' * shift + '*' + symbol * (width - shift - 2) + '*\n'
|
||||
t = np.cumsum(tabs) + shift
|
||||
l = list(s)
|
||||
sep = list(s)
|
||||
for i in t:
|
||||
l[i] = '+'
|
||||
return ''.join(l)
|
||||
sep[i] = '+'
|
||||
return ''.join(sep)
|
||||
|
||||
def fillstr(a, b, index, justify='left'):
|
||||
alist = list(a)
|
||||
|
@ -426,7 +456,8 @@ class SpecIO(object):
|
|||
content += rule()
|
||||
line = create_line("SPECTRO,ISPIN,IDICHR,IPOL")
|
||||
line = fillstr(line, str(p.calctype_spectro), 9, 'left')
|
||||
line = fillstr(line, str(p.get_parameter('calctype_ispin')), 19, 'left')
|
||||
line = fillstr(line,
|
||||
str(p.get_parameter('calctype_ispin')), 19, 'left')
|
||||
line = fillstr(line, str(p.calctype_idichr), 29, 'left')
|
||||
line = fillstr(line, str(p.calctype_ipol), 39, 'left')
|
||||
content += line
|
||||
|
@ -476,11 +507,13 @@ class SpecIO(object):
|
|||
line = fillstr(line, str(p.get_parameter('ped_imod')), 9, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('ped_imoy')), 19, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('ped_accept')), 29, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('ped_ichkdir')), 39, 'decimal')
|
||||
line = fillstr(line,
|
||||
str(p.get_parameter('ped_ichkdir')), 39, 'decimal')
|
||||
content += line
|
||||
content += rule()
|
||||
|
||||
content += title(' ' * 22 + 'LEED EXPERIMENTAL PARAMETERS :', center=False)
|
||||
content += title(' ' * 22 + 'LEED EXPERIMENTAL PARAMETERS :',
|
||||
center=False)
|
||||
content += rule()
|
||||
line = create_line("IPHI,ITHETA,IE,IFTHET")
|
||||
line = fillstr(line, str(p.get_parameter('leed_iphi')), 9, 'left')
|
||||
|
@ -496,48 +529,57 @@ class SpecIO(object):
|
|||
content += line
|
||||
line = create_line("PHI0,THETA0,E0,R0")
|
||||
line = fillstr(line, str(p.get_parameter('leed_phi0')), 9, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('leed_theta0')), 19, 'decimal')
|
||||
line = fillstr(line,
|
||||
str(p.get_parameter('leed_theta0')), 19, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('leed_e0')), 29, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('leed_r0')), 39, 'decimal')
|
||||
content += line
|
||||
line = create_line("PHI1,THETA1,E1,R1")
|
||||
line = fillstr(line, str(p.get_parameter('leed_phi1')), 9, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('leed_theta1')), 19, 'decimal')
|
||||
line = fillstr(line,
|
||||
str(p.get_parameter('leed_theta1')), 19, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('leed_e1')), 29, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('leed_r1')), 39, 'decimal')
|
||||
content += line
|
||||
line = create_line("TH_INI,PHI_INI")
|
||||
line = fillstr(line, str(p.get_parameter('leed_thini')), 9, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('leed_phiini')), 19, 'decimal')
|
||||
line = fillstr(line,
|
||||
str(p.get_parameter('leed_phiini')), 19, 'decimal')
|
||||
content += line
|
||||
line = create_line("IMOD,IMOY,ACCEPT,ICHKDIR")
|
||||
line = fillstr(line, str(p.get_parameter('leed_imod')), 9, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('leed_imoy')), 19, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('leed_accept')), 29, 'decimal')
|
||||
line = fillstr(line,
|
||||
str(p.get_parameter('leed_accept')), 29, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('leed_ichkdir')), 39,
|
||||
'decimal')
|
||||
content += line
|
||||
content += rule()
|
||||
|
||||
content += title(' ' * 21 + 'EXAFS EXPERIMENTAL PARAMETERS :', center=False)
|
||||
content += title(' ' * 21 + 'EXAFS EXPERIMENTAL PARAMETERS :',
|
||||
center=False)
|
||||
content += rule()
|
||||
line = create_line("EDGE,INITL,THLUM,PHILUM")
|
||||
line = fillstr(line, str(p.get_parameter('exafs_edge')), 9, 'left')
|
||||
line = fillstr(line, str(p.get_parameter('exafs_initl')), 19, 'left')
|
||||
line = fillstr(line, str(p.get_parameter('exafs_thlum')), 29, 'decimal')
|
||||
line = fillstr(line,
|
||||
str(p.get_parameter('exafs_thlum')), 29, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('exafs_philum')), 39,
|
||||
'decimal')
|
||||
content += line
|
||||
line = create_line("NE,EK_INI,EK_FIN,EPH_INI")
|
||||
line = fillstr(line, str(p.get_parameter('exafs_ne')), 9, 'left')
|
||||
line = fillstr(line, str(p.get_parameter('exafs_ekini')), 19, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('exafs_ekfin')), 29, 'decimal')
|
||||
line = fillstr(line,
|
||||
str(p.get_parameter('exafs_ekini')), 19, 'decimal')
|
||||
line = fillstr(line,
|
||||
str(p.get_parameter('exafs_ekfin')), 29, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('exafs_ephini')), 39,
|
||||
'decimal')
|
||||
content += line
|
||||
content += rule()
|
||||
|
||||
content += title(' ' * 22 + 'AED EXPERIMENTAL PARAMETERS :', center=False)
|
||||
content += title(' ' * 22 + 'AED EXPERIMENTAL PARAMETERS :',
|
||||
center=False)
|
||||
content += rule()
|
||||
line = create_line("EDGE_C,EDGE_I,EDGE_A")
|
||||
line = fillstr(line, str(p.get_parameter('aed_edgec')), 9, 'left')
|
||||
|
@ -605,7 +647,8 @@ class SpecIO(object):
|
|||
line = fillstr(line, str(p.get_parameter('eigval_ipwm')), 9, 'left')
|
||||
line = fillstr(line, str(p.get_parameter('eigval_method')), 19, 'left')
|
||||
line = fillstr(line, str(p.get_parameter('eigval_acc')), 29, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('eigval_expo')), 39, 'decimal')
|
||||
line = fillstr(line,
|
||||
str(p.get_parameter('eigval_expo')), 39, 'decimal')
|
||||
content += line
|
||||
line = create_line("N_MAX,N_ITER,N_TABLE,SHIFT")
|
||||
line = fillstr(line, str(p.get_parameter('eigval_nmax')), 9, 'left')
|
||||
|
@ -673,7 +716,8 @@ class SpecIO(object):
|
|||
thfwd_arr = np.ones((nat))
|
||||
path_filtering = p.extra_parameters['calculation'].get_parameter(
|
||||
'path_filtering').value
|
||||
if path_filtering != None and 'backward_scattering' in path_filtering:
|
||||
if (path_filtering is not None and
|
||||
'backward_scattering' in path_filtering):
|
||||
ibwd_arr = np.ones((nat), dtype=np.int)
|
||||
else:
|
||||
ibwd_arr = np.zeros((nat), dtype=np.int)
|
||||
|
@ -694,7 +738,8 @@ class SpecIO(object):
|
|||
line = create_line("IPW,NCUT,PCTINT,IPP")
|
||||
line = fillstr(line, str(p.get_parameter('calc_ipw')), 9, 'left')
|
||||
line = fillstr(line, str(p.get_parameter('calc_ncut')), 19, 'left')
|
||||
line = fillstr(line, str(p.get_parameter('calc_pctint')), 29, 'decimal')
|
||||
line = fillstr(line,
|
||||
str(p.get_parameter('calc_pctint')), 29, 'decimal')
|
||||
line = fillstr(line, str(p.get_parameter('calc_ipp')), 39, 'left')
|
||||
content += line
|
||||
line = create_line("ILENGTH,RLENGTH,UNLENGTH")
|
||||
|
@ -713,7 +758,8 @@ class SpecIO(object):
|
|||
idcm = format(2, 'd')
|
||||
temp = format(0., '.2f')
|
||||
td = format(500., '.2f')
|
||||
LOGGER.warning('Vibrational damping is disabled for this calculation.')
|
||||
LOGGER.warning('Vibrational damping is disabled for this '
|
||||
'calculation.')
|
||||
else:
|
||||
idwsph = str(p.get_parameter('calc_idwsph'))
|
||||
idcm = str(p.get_parameter('calc_idcm'))
|
||||
|
@ -757,8 +803,9 @@ class SpecIO(object):
|
|||
content += title(' ' * 17 + 'INPUT FILES (PHD, EXAFS, LEED, AED, '
|
||||
'APECS) :', center=False)
|
||||
content += rule(tabs=(), symbol='-')
|
||||
content += title(' ' * 8 + 'NAME' + ' ' * 20 + 'UNIT' + ' ' * 16 + 'TYPE',
|
||||
center=False)
|
||||
content += title(
|
||||
' ' * 8 + 'NAME' + ' ' * 20 + 'UNIT' + ' ' * 16 + 'TYPE',
|
||||
center=False)
|
||||
content += rule(tabs=(5, 23, 7, 10))
|
||||
line = create_line("DATA FILE,UNIT")
|
||||
line = fillstr(line, str(p.get_parameter('input_data')), 9, 'right')
|
||||
|
@ -791,8 +838,9 @@ class SpecIO(object):
|
|||
center=False)
|
||||
content += title(' ' * 28 + '(AUGER ELECTRON)', center=False)
|
||||
content += rule(tabs=(), symbol='-')
|
||||
content += title(' ' * 8 + 'NAME' + ' ' * 20 + 'UNIT' + ' ' * 16 + 'TYPE',
|
||||
center=False)
|
||||
content += title(
|
||||
' ' * 8 + 'NAME' + ' ' * 20 + 'UNIT' + ' ' * 16 + 'TYPE',
|
||||
center=False)
|
||||
content += rule(tabs=(5, 23, 7, 10))
|
||||
line = create_line("PHASE SHIFTS/TL FILE,UNIT")
|
||||
line = fillstr(line, str(p.get_parameter('input2_tl')), 9, 'right')
|
||||
|
@ -810,8 +858,9 @@ class SpecIO(object):
|
|||
|
||||
content += title(' ' * 29 + 'OUTPUT FILES :', center=False)
|
||||
content += rule(tabs=(), symbol='-')
|
||||
content += title(' ' * 8 + 'NAME' + ' ' * 20 + 'UNIT' + ' ' * 16 + 'TYPE',
|
||||
center=False)
|
||||
content += title(
|
||||
' ' * 8 + 'NAME' + ' ' * 20 + 'UNIT' + ' ' * 16 + 'TYPE',
|
||||
center=False)
|
||||
content += rule(tabs=(5, 23, 7, 10))
|
||||
line = create_line("CONTROL FILE,UNIT")
|
||||
line = fillstr(line, str(p.get_parameter('output_log')), 9, 'right')
|
||||
|
@ -826,7 +875,8 @@ class SpecIO(object):
|
|||
line = fillstr(line, str(p.get_parameter('output_unit11')), 39, 'left')
|
||||
content += line
|
||||
line = create_line("AUGMENTED CLUSTER FILE,UNIT")
|
||||
line = fillstr(line, str(p.get_parameter('output_augclus')), 9, 'right')
|
||||
line = fillstr(line,
|
||||
str(p.get_parameter('output_augclus')), 9, 'right')
|
||||
line = fillstr(line, str(p.get_parameter('output_unit12')), 39, 'left')
|
||||
content += line
|
||||
content += rule(tabs=(5, 23, 7, 10))
|
||||
|
@ -874,15 +924,13 @@ class SpecIO(object):
|
|||
# backup the content in memory
|
||||
old_content = content
|
||||
|
||||
"""
|
||||
for key in ('NATP_M', 'NATCLU_M', 'NE_M', 'NEMET_M', 'LI_M', 'NL_M',
|
||||
'NO_ST_M'):
|
||||
required = requirements[key]
|
||||
limit = self.malloc_parameters.get_parameter(key).value
|
||||
value = required if required > limit else limit
|
||||
content = re.sub(r'({:s}\s*=\s*)\d+'.format(key),
|
||||
r'\g<1>{:d}'.format(value), content)
|
||||
"""
|
||||
# for key in ('NATP_M', 'NATCLU_M', 'NE_M', 'NEMET_M', 'LI_M', 'NL_M',
|
||||
# 'NO_ST_M'):
|
||||
# required = requirements[key]
|
||||
# limit = self.malloc_parameters.get_parameter(key).value
|
||||
# value = required if required > limit else limit
|
||||
# content = re.sub(r'({:s}\s*=\s*)\d+'.format(key),
|
||||
# r'\g<1>{:d}'.format(value), content)
|
||||
|
||||
for key in ('NAT_EQ_M', 'N_CL_N_M', 'NDIF_M', 'NSO_M', 'NTEMP_M',
|
||||
'NODES_EX_M', 'NSPIN_M', 'NTH_M', 'NPH_M', 'NDIM_M',
|
||||
|
@ -895,7 +943,6 @@ class SpecIO(object):
|
|||
content = re.sub(r'({:s}\s*=\s*)\d+'.format(key),
|
||||
r'\g<1>{:d}'.format(value), content)
|
||||
|
||||
|
||||
modified = False
|
||||
if content != old_content:
|
||||
with open(filename, 'w') as fd:
|
||||
|
@ -945,7 +992,7 @@ class SpecIO(object):
|
|||
|
||||
data = np.loadtxt(filename, skiprows=skip, unpack=True)
|
||||
if len(data.shape) <= 1:
|
||||
data = data.reshape((2,-1))
|
||||
data = data.reshape((2, -1))
|
||||
return data
|
||||
|
||||
def load_facdif(self, filename='facdif1.dat'):
|
||||
|
@ -956,8 +1003,4 @@ class SpecIO(object):
|
|||
pat = re.compile(r'ORDER\s+(\d+)\s+TOTAL NUMBER OF PATHS\s+:\s+(\d+)')
|
||||
with open(filename, 'r') as fd:
|
||||
content = fd.read()
|
||||
#return pat.findall(content.replace('\n', '__cr__'))
|
||||
return pat.findall(content)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
# coding: utf-8
|
||||
# vim: set et sw=4 ts=4 sts=4 nu ai cc=+0 fdm=indent mouse=a tw=80:
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright © 2016-2020 - Rennes Physics Institute
|
||||
#
|
||||
# This file is part of msspec.
|
||||
#
|
||||
# msspec is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
# msspec is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this msspec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Source file : src/msspec/calculator.py
|
||||
# Last modified: ven. 10 avril 2020 17:19:24
|
||||
# Committed by : "Sylvain Tricot <sylvain.tricot@univ-rennes1.fr>"
|
||||
|
||||
|
||||
"""
|
||||
Module calculator
|
||||
=================
|
||||
|
@ -21,54 +41,58 @@ For more information on MsSpec, follow this
|
|||
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import inspect
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import re
|
||||
import inspect
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
from shutil import copyfile, rmtree
|
||||
from datetime import datetime
|
||||
import time
|
||||
from io import StringIO
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime
|
||||
from io import StringIO
|
||||
from shutil import copyfile
|
||||
from shutil import rmtree
|
||||
from subprocess import PIPE
|
||||
from subprocess import Popen
|
||||
|
||||
from ase.calculators.calculator import Calculator
|
||||
import ase.data
|
||||
import ase.atom
|
||||
import ase.atoms
|
||||
|
||||
import ase.data
|
||||
import numpy as np
|
||||
|
||||
from ase.calculators.calculator import Calculator
|
||||
from terminaltables.ascii_table import AsciiTable
|
||||
|
||||
from msspec import iodata
|
||||
from msspec.data import electron_be
|
||||
from msspec.calcio import PhagenIO
|
||||
from msspec.calcio import SpecIO
|
||||
from msspec.config import Config
|
||||
from msspec.misc import (UREG, LOGGER, get_call_info,
|
||||
get_level_from_electron_configuration,
|
||||
XRaySource, set_log_output, log_process_output)
|
||||
from msspec.utils import get_atom_index
|
||||
|
||||
from msspec.parameters import (PhagenParameters, PhagenMallocParameters,
|
||||
SpecParameters, SpecMallocParameters,
|
||||
GlobalParameters, MuffintinParameters,
|
||||
TMatrixParameters, SourceParameters,
|
||||
DetectorParameters, ScanParameters,
|
||||
CalculationParameters,
|
||||
PEDParameters, EIGParameters)
|
||||
from msspec.calcio import PhagenIO, SpecIO
|
||||
|
||||
from msspec.data import electron_be
|
||||
from msspec.misc import get_call_info
|
||||
from msspec.misc import get_level_from_electron_configuration
|
||||
from msspec.misc import log_process_output
|
||||
from msspec.misc import LOGGER
|
||||
from msspec.misc import set_log_output
|
||||
from msspec.misc import UREG
|
||||
from msspec.misc import XRaySource
|
||||
from msspec.parameters import CalculationParameters
|
||||
from msspec.parameters import DetectorParameters
|
||||
from msspec.parameters import EIGParameters
|
||||
from msspec.parameters import GlobalParameters
|
||||
from msspec.parameters import MuffintinParameters
|
||||
from msspec.parameters import PEDParameters
|
||||
from msspec.parameters import PhagenMallocParameters
|
||||
from msspec.parameters import PhagenParameters
|
||||
from msspec.parameters import ScanParameters
|
||||
from msspec.parameters import SourceParameters
|
||||
from msspec.parameters import SpecMallocParameters
|
||||
from msspec.parameters import SpecParameters
|
||||
from msspec.parameters import TMatrixParameters
|
||||
from msspec.phagen.fortran.libphagen import main as do_phagen
|
||||
|
||||
from msspec.spec.fortran import _phd_se_noso_nosp_nosym, _phd_mi_noso_nosp_nosym
|
||||
from msspec.spec.fortran import _eig_mi
|
||||
from msspec.spec.fortran import _eig_pw
|
||||
|
||||
|
||||
from terminaltables.ascii_table import AsciiTable
|
||||
from msspec.spec.fortran import _phd_mi_noso_nosp_nosym
|
||||
from msspec.spec.fortran import _phd_se_noso_nosp_nosym
|
||||
from msspec.utils import get_atom_index
|
||||
|
||||
|
||||
class _MSCALCULATOR(Calculator):
|
||||
|
@ -277,34 +301,33 @@ class _MSCALCULATOR(Calculator):
|
|||
|
||||
|
||||
def run_phagen(self):
|
||||
#include_fname = os.path.join(self.tmp_folder, 'src/msxas3.inc')
|
||||
input_fname = os.path.join(self.tmp_folder, 'input/input.ms')
|
||||
modified = self.phagenio.write_input_file(filename=input_fname)
|
||||
|
||||
#mod0 = self.phagenio.write_include_file(filename=include_fname)
|
||||
mod1 = self.phagenio.write_input_file(filename=input_fname)
|
||||
# Write the external potential file
|
||||
pot = self.tmatrix_parameters.potential
|
||||
if pot != 'muffin_tin':
|
||||
inpot_fname = os.path.join(self.tmp_folder, 'output/fort.2')
|
||||
mflag = pot.write(inpot_fname, self.phagenio.prototypical_atoms)
|
||||
modified = modified or mflag
|
||||
# Make a copy of the input potential file
|
||||
dest = os.path.join(self.tmp_folder, 'input/extpot.dat')
|
||||
shutil.copy(inpot_fname, dest)
|
||||
|
||||
self.modified = self.modified or mod1 #or mod0 or mod1
|
||||
|
||||
#if self.modified:
|
||||
if mod1:
|
||||
# run phagen
|
||||
#self._make('tmatrix')
|
||||
# Run if input files changed
|
||||
if modified:
|
||||
# Run phagen
|
||||
os.chdir(os.path.join(self.tmp_folder, 'output'))
|
||||
# copy external potential file to the workspace
|
||||
if self.tmatrix_parameters.potential in ('lmto', 'spkkr', 'msf'):
|
||||
fname = os.path.join(self.init_folder,
|
||||
self.tmatrix_parameters.potential_file)
|
||||
shutil.copy(fname, 'fort.2')
|
||||
do_phagen()
|
||||
# rename some output files to be more explicit
|
||||
#os.rename('fort.10', 'cluster.clu')
|
||||
#os.rename('fort.35', 'tmatrix.tl')
|
||||
#os.rename('fort.55', 'tmatrix.rad')
|
||||
#shutil.copy('fort.10', 'cluster.clu')
|
||||
# Copy some output files to be more explicit
|
||||
shutil.copy('clus/clus.out', 'cluster.clu')
|
||||
shutil.copy('fort.35', 'tmatrix.tl')
|
||||
shutil.copy('fort.55', 'tmatrix.rad')
|
||||
|
||||
# Load data
|
||||
self.phagenio.load_tl_file('tmatrix.tl')
|
||||
self.phagenio.load_cluster_file('cluster.clu')
|
||||
self.phagenio.load_prototypical_atoms('div/molinpot3.out')
|
||||
# Change back to the init_folder
|
||||
os.chdir(self.init_folder)
|
||||
|
||||
|
||||
|
@ -425,15 +448,19 @@ class _MSCALCULATOR(Calculator):
|
|||
LOGGER.info("Getting the TMatrix...")
|
||||
LOGGER.debug(get_call_info(inspect.currentframe()))
|
||||
|
||||
# If using an external potential, Phagen should be run twice,
|
||||
# the first time with the internal MT potential.
|
||||
pot = self.tmatrix_parameters.potential
|
||||
if pot != 'muffin_tin':
|
||||
LOGGER.info("Phagen is running first with MuffinTin potential...")
|
||||
self.tmatrix_parameters.potential = "muffin_tin"
|
||||
self.tmatrix_parameters.exchange_correlation = "hedin_lundqvist_complex"
|
||||
self.run_phagen()
|
||||
self.tmatrix_parameters.potential = pot
|
||||
|
||||
self.run_phagen()
|
||||
|
||||
filename = os.path.join(self.tmp_folder, 'output/tmatrix.tl')
|
||||
tl = self.phagenio.load_tl_file(filename)
|
||||
|
||||
filename = os.path.join(self.tmp_folder, 'output/cluster.clu')
|
||||
self.phagenio.load_cluster_file(filename)
|
||||
|
||||
|
||||
tl = self.phagenio.tl
|
||||
tl_threshold = self.tmatrix_parameters.get_parameter('tl_threshold')
|
||||
if tl_threshold.value != None:
|
||||
LOGGER.debug(" applying tl_threshold to %s...",
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
# coding: utf-8
|
||||
"""
|
||||
Module config
|
||||
=============
|
||||
|
||||
"""
|
||||
|
||||
from configparser import NoSectionError
|
||||
from configparser import SafeConfigParser as ConfigParser
|
||||
import os
|
||||
import sys
|
||||
import fnmatch
|
||||
from msspec.misc import LOGGER
|
||||
|
||||
|
||||
class NoConfigFile(Exception): pass
|
||||
|
||||
|
||||
class Config(object):
|
||||
def __init__(self, **kwargs):
|
||||
self.fname = os.path.join(os.environ['HOME'], '.config/msspec/pymsspec.cfg')
|
||||
self.version = sys.modules['msspec'].__version__
|
||||
self.config = ConfigParser()
|
||||
self.defaults = {'path': 'None'}
|
||||
self.defaults.update(kwargs)
|
||||
|
||||
# try to load the config file, create one with defaults if none is found
|
||||
try:
|
||||
self.options = self.read()
|
||||
self.options.update(kwargs)
|
||||
self.set(**self.options)
|
||||
self.write()
|
||||
except NoConfigFile:
|
||||
# write a file with default options
|
||||
self.write(defaults=True)
|
||||
except NoSectionError:
|
||||
# the file exists but has no options for this version of pymsspec
|
||||
self.config.add_section(self.version)
|
||||
self.set(**self.defaults)
|
||||
self.write()
|
||||
|
||||
def read(self):
|
||||
fp = self.config.read(self.fname)
|
||||
if len(fp) == 0:
|
||||
raise NoConfigFile
|
||||
self.version = self.config.get('general', 'version')
|
||||
return dict(self.config.items(self.version))
|
||||
|
||||
def set(self, **kwargs):
|
||||
if not(self.config.has_section(self.version)):
|
||||
self.config.add_section(self.version)
|
||||
for k, v in list(kwargs.items()):
|
||||
self.config.set(self.version, k, v)
|
||||
|
||||
def get(self, key):
|
||||
return self.config.get(self.version, key)
|
||||
|
||||
def choose_msspec_folder(self, *folders):
|
||||
print("Several folders containing the appropriate version of MsSpec were found.")
|
||||
print("Please choose one tu use:")
|
||||
s = ""
|
||||
for i, f in enumerate(folders):
|
||||
s += '{:d}) {:s}\n'.format(i, f)
|
||||
print(s)
|
||||
return(folders[int(input('Your choice: '))])
|
||||
|
||||
def find_msspec_folders(self):
|
||||
version = sys.modules['msspec'].__version__
|
||||
folders = []
|
||||
i = 0
|
||||
prompt = 'Please wait while scanning the filesystem (%3d found) '
|
||||
sys.stdout.write(prompt % len(folders))
|
||||
sys.stdout.write('\033[s')
|
||||
|
||||
for root, dirnames, filenames in os.walk('/home/stricot'):
|
||||
sys.stdout.write('\033[u\033[k')
|
||||
sys.stdout.write('%d folders scanned' % i)
|
||||
i += 1
|
||||
for fn in fnmatch.filter(filenames, 'VERSION'):
|
||||
with open(os.path.join(root, fn), 'r') as fd:
|
||||
try:
|
||||
line = fd.readline()
|
||||
if line.strip() == version:
|
||||
folders.append(root)
|
||||
sys.stdout.write('\033[2000D\033[k')
|
||||
sys.stdout.write(prompt % len(folders))
|
||||
except:
|
||||
pass
|
||||
sys.stdout.write('\033[u\033[k\n')
|
||||
print('Done.')
|
||||
return(folders)
|
||||
|
||||
|
||||
def write(self, defaults=False):
|
||||
if defaults:
|
||||
self.set(**self.defaults)
|
||||
|
||||
with open(self.fname, 'w') as fd:
|
||||
self.config.write(fd)
|
||||
LOGGER.info("{} file written".format(self.fname))
|
||||
|
||||
def set_mode(self, mode="pymsspec"):
|
||||
if not(self.config.has_section("general")):
|
||||
self.config.add_section("general")
|
||||
self.config.set("general", "mode", str(mode))
|
||||
|
||||
def get_mode(self):
|
||||
return self.config.get("general", "mode")
|
||||
|
||||
def set_version(self, version=""):
|
||||
if not(self.config.has_section("general")):
|
||||
self.config.add_section("general")
|
||||
self.config.set("general", "version", version)
|
||||
|
||||
def remove_version(self, version):
|
||||
pass
|
||||
|
||||
|
|
@ -1,2 +1,28 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright © 2016-2020 - Rennes Physics Institute
|
||||
#
|
||||
# This file is part of msspec.
|
||||
#
|
||||
# msspec is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# msspec is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this msspec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Source file : src/msspec/create_tests_results.py
|
||||
# Last modified: ven. 10 avril 2020 17:29:16
|
||||
# Committed by : "Sylvain Tricot <sylvain.tricot@univ-rennes1.fr>"
|
||||
|
||||
|
||||
from msspec.tests import create_tests_results
|
||||
|
||||
|
||||
create_tests_results()
|
||||
|
|
|
@ -1,4 +1,25 @@
|
|||
# coding: utf-8
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright © 2016-2020 - Rennes Physics Institute
|
||||
#
|
||||
# This file is part of msspec.
|
||||
#
|
||||
# msspec is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
# msspec is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this msspec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Source file : src/msspec/iodata.py
|
||||
# Last modified: ven. 10 avril 2020 17:23:11
|
||||
# Committed by : "Sylvain Tricot <sylvain.tricot@univ-rennes1.fr>"
|
||||
|
||||
|
||||
"""
|
||||
Module iodata
|
||||
=============
|
||||
|
@ -47,29 +68,25 @@ Here is an example of how to store values in a Data object:
|
|||
|
||||
|
||||
import os
|
||||
import numpy as np
|
||||
import h5py
|
||||
from lxml import etree
|
||||
import msspec
|
||||
from msspec.misc import LOGGER
|
||||
import ase.io
|
||||
import sys
|
||||
from distutils.version import LooseVersion
|
||||
from distutils.version import StrictVersion
|
||||
from io import StringIO
|
||||
|
||||
import wx
|
||||
import ase.io
|
||||
import h5py
|
||||
import numpy as np
|
||||
import wx.grid
|
||||
|
||||
from lxml import etree
|
||||
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
|
||||
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg
|
||||
#from matplotlib.backends.backend_wxcairo import FigureCanvasWxCairo as FigureCanvas
|
||||
#from matplotlib.backends.backend_wxcairo import NavigationToolbar2WxCairo
|
||||
from matplotlib.figure import Figure
|
||||
|
||||
from terminaltables import AsciiTable
|
||||
from distutils.version import StrictVersion, LooseVersion
|
||||
|
||||
import sys
|
||||
#sys.path.append('../../MsSpecGui/msspecgui/msspec/gui')
|
||||
import msspec
|
||||
from msspec.msspecgui.msspec.gui.clusterviewer import ClusterViewer
|
||||
from msspec.misc import LOGGER
|
||||
|
||||
|
||||
def cols2matrix(x, y, z, nx=88*1+1, ny=360*1+1):
|
||||
# mix the values of existing theta and new theta and return the
|
||||
|
@ -1186,7 +1203,3 @@ if __name__ == "__main__":
|
|||
import sys
|
||||
data = Data.load(sys.argv[1])
|
||||
data.view()
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,34 @@
|
|||
# coding: utf-8
|
||||
# vim: set fdm=indent ts=4 sw=4 sts=4 et tw=80 ai cc=+0 mouse=a nu : #
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright © 2016-2020 - Rennes Physics Institute
|
||||
#
|
||||
# This file is part of msspec.
|
||||
#
|
||||
# msspec is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# msspec is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this msspec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Source file : src/msspec/misc.py
|
||||
# Last modified: ven. 10 avril 2020 17:30:42
|
||||
# Committed by : "Sylvain Tricot <sylvain.tricot@univ-rennes1.fr>"
|
||||
|
||||
|
||||
"""
|
||||
Module misc
|
||||
===========
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import logging
|
||||
from pint import UnitRegistry
|
||||
import numpy as np
|
||||
|
@ -12,6 +36,7 @@ import inspect
|
|||
import re
|
||||
import os
|
||||
|
||||
|
||||
class XRaySource(object):
|
||||
MG_KALPHA = 1253.6
|
||||
AL_KALPHA = 1486.6
|
||||
|
@ -19,10 +44,10 @@ class XRaySource(object):
|
|||
pass
|
||||
|
||||
UREG = UnitRegistry()
|
||||
UREG.define('rydberg = c * h * rydberg_constant = Ry')
|
||||
UREG.define('bohr_radius = 4 * pi * epsilon_0 * hbar**2 / electron_mass / e**2 = a0')
|
||||
#UREG.define('rydberg = c * h * rydberg_constant = Ry')
|
||||
#UREG.define('bohr_radius = 4 * pi * epsilon_0 * hbar**2 / electron_mass / e**2 = a0')
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
#logging.basicConfig(level=logging.INFO)
|
||||
LOGGER = logging.getLogger('msspec')
|
||||
|
||||
np.set_printoptions(formatter={'float': lambda x:'%.2f' % x}, threshold=5)
|
||||
|
|
|
@ -1,16 +1,47 @@
|
|||
# coding: utf-8
|
||||
# vim: set et ts=4 sw=4 nu fdm=indent:
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright © 2016-2020 - Rennes Physics Institute
|
||||
#
|
||||
# This file is part of msspec.
|
||||
#
|
||||
# msspec is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# msspec is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this msspec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Source file : src/msspec/parameters.py
|
||||
# Last modified: ven. 10 avril 2020 17:31:50
|
||||
# Committed by : "Sylvain Tricot <sylvain.tricot@univ-rennes1.fr>"
|
||||
|
||||
|
||||
"""
|
||||
Module parameters
|
||||
=================
|
||||
|
||||
"""
|
||||
import textwrap
|
||||
import numpy as np
|
||||
|
||||
|
||||
import re
|
||||
from terminaltables import AsciiTable
|
||||
from msspec.misc import LOGGER, UREG, XRaySource, get_level_from_electron_configuration
|
||||
import textwrap
|
||||
|
||||
import ase
|
||||
import numpy as np
|
||||
from terminaltables import AsciiTable
|
||||
|
||||
from msspec.misc import get_level_from_electron_configuration
|
||||
from msspec.misc import LOGGER
|
||||
from msspec.misc import UREG
|
||||
from msspec.misc import XRaySource
|
||||
from msspec.utils import ForeignPotential
|
||||
from msspec.utils import SPRKKRPotential
|
||||
|
||||
class Parameter(object):
|
||||
def __init__(self, name, types=None, limits=(None, None),
|
||||
|
@ -31,7 +62,7 @@ class Parameter(object):
|
|||
self.fmt = fmt
|
||||
self.binding = binding
|
||||
self.private = private
|
||||
self.docstring = doc
|
||||
self.docstring = textwrap.dedent(doc)
|
||||
self._value = None
|
||||
|
||||
self.value = default
|
||||
|
@ -59,41 +90,41 @@ class Parameter(object):
|
|||
return value.to(self.unit).magnitude
|
||||
return value
|
||||
|
||||
def assert_message(self, msg, *args):
|
||||
s = '\'{}\': {}'.format(self.name, msg)
|
||||
s = s.format(*args)
|
||||
|
||||
try:
|
||||
allowed_types = '\n'.join(
|
||||
['- ' + str(_) for _ in self.allowed_types])
|
||||
except TypeError:
|
||||
allowed_types = self.allowed_types
|
||||
|
||||
try:
|
||||
allowed_values = '\n'.join(
|
||||
['- ' + str(_) for _ in self.allowed_values])
|
||||
except TypeError:
|
||||
allowed_values = self.allowed_values
|
||||
|
||||
data = [
|
||||
['PROPERTY', 'VALUE'],
|
||||
['Name', '\'{}\''.format(self.name)],
|
||||
['Allowed types', '{}'.format(allowed_types)],
|
||||
['Limits', '{} <= value <= {}'.format(self.low_limit,
|
||||
self.high_limit)],
|
||||
['Unit', '{}'.format(self.unit)],
|
||||
['Allowed values', '{}'.format(allowed_values)],
|
||||
['Default', '{}'.format(self.default)]
|
||||
]
|
||||
t = AsciiTable(data)
|
||||
table = '\n'.join(['\t' * 2 + _ for _ in t.table.split('\n')])
|
||||
|
||||
s = "{}\n\n{}\n{}".format(s, table, self.docstring)
|
||||
|
||||
return s
|
||||
|
||||
def check(self, value):
|
||||
|
||||
def assert_message(msg, *args):
|
||||
s = '\'{}\': {}'.format(self.name, msg)
|
||||
s = s.format(*args)
|
||||
|
||||
try:
|
||||
allowed_types = '\n'.join(
|
||||
['- ' + str(_) for _ in self.allowed_types])
|
||||
except TypeError:
|
||||
allowed_types = self.allowed_types
|
||||
|
||||
try:
|
||||
allowed_values = '\n'.join(
|
||||
['- ' + str(_) for _ in self.allowed_values])
|
||||
except TypeError:
|
||||
allowed_values = self.allowed_values
|
||||
|
||||
data = [
|
||||
['PROPERTY', 'VALUE'],
|
||||
['Name', '\'{}\''.format(self.name)],
|
||||
['Allowed types', '{}'.format(allowed_types)],
|
||||
['Limits', '{} <= value <= {}'.format(self.low_limit,
|
||||
self.high_limit)],
|
||||
['Unit', '{}'.format(self.unit)],
|
||||
['Allowed values', '{}'.format(allowed_values)],
|
||||
['Default', '{}'.format(self.default)]
|
||||
]
|
||||
t = AsciiTable(data)
|
||||
table = '\n'.join(['\t' * 2 + _ for _ in t.table.split('\n')])
|
||||
|
||||
s = "{}\n\n{}\n{}".format(s, table, self.docstring)
|
||||
|
||||
return s
|
||||
|
||||
# convert if a unit was given
|
||||
_value = self.convert(value)
|
||||
|
||||
|
@ -106,7 +137,7 @@ class Parameter(object):
|
|||
assert bool in self.allowed_types
|
||||
assert isinstance(_value, self.allowed_types)
|
||||
except AssertionError:
|
||||
raise AssertionError(assert_message(
|
||||
raise AssertionError(self.assert_message(
|
||||
'Type {} is not an allowed type for this option '
|
||||
'({} allowed)',
|
||||
str(type(_value)), str(self.allowed_types)))
|
||||
|
@ -120,22 +151,22 @@ class Parameter(object):
|
|||
# for i, val in enumerate(_values):
|
||||
for val in np.array(_value).flatten():
|
||||
if self.low_limit != None:
|
||||
assert val >= self.low_limit, assert_message(
|
||||
assert val >= self.low_limit, self.assert_message(
|
||||
'Value must be >= {:s}',
|
||||
str(self.low_limit))
|
||||
if self.high_limit != None:
|
||||
assert val <= self.high_limit, assert_message(
|
||||
assert val <= self.high_limit, self.assert_message(
|
||||
'Value must be <= {:s}',
|
||||
str(self.high_limit))
|
||||
if self.allowed_values != None and isinstance(val, tuple(type(x) for x in self.allowed_values)):
|
||||
assert val in self.allowed_values, assert_message(
|
||||
if self.allowed_values != None: # and isinstance(val, tuple(type(x) for x in self.allowed_values)):
|
||||
assert val in self.allowed_values, self.assert_message(
|
||||
'This value is not allowed. Please choose between '
|
||||
'one of {:s}',
|
||||
str(self.allowed_values))
|
||||
if self.pattern != None:
|
||||
p = re.compile(self.pattern)
|
||||
m = p.match(val)
|
||||
assert m != None, assert_message(
|
||||
assert m != None, self.assert_message(
|
||||
'Wrong string format')
|
||||
# _value[i] = val
|
||||
|
||||
|
@ -157,8 +188,8 @@ class Parameter(object):
|
|||
new_value = None
|
||||
try:
|
||||
new_value = self.binding(self)
|
||||
except AttributeError:
|
||||
pass
|
||||
except AttributeError as err:
|
||||
LOGGER.warning(err)
|
||||
if new_value is not None:
|
||||
self._value = new_value
|
||||
# LOGGER.debug('{:s} = {:s}'.format(self.name, str(self.value)))
|
||||
|
@ -716,7 +747,7 @@ class GlobalParameters(BaseParameters):
|
|||
parameters = (
|
||||
Parameter('spectroscopy', types=str, allowed_values=(
|
||||
'PED', 'AED', 'LEED', 'EXAFS', 'EIG'), default='PED',
|
||||
doc=textwrap.dedent("""
|
||||
doc="""
|
||||
There are 4 choices for the spectroscopy option:
|
||||
|
||||
- '**PED**', for Photo Electron Diffraction
|
||||
|
@ -729,12 +760,12 @@ class GlobalParameters(BaseParameters):
|
|||
matrix.
|
||||
|
||||
The value is case insensitive.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('algorithm', types=str, allowed_values=('expansion',
|
||||
'inversion',
|
||||
'correlation',
|
||||
'power'),
|
||||
default='expansion', doc=textwrap.dedent("""
|
||||
default='expansion', doc="""
|
||||
You can choose the algorithm used for the computation of the scattering path operator.
|
||||
|
||||
- '**inversion**', for the classical matrix inversion method
|
||||
|
@ -745,10 +776,10 @@ class GlobalParameters(BaseParameters):
|
|||
The series expansion algorithm is well suited for high energy since the number of terms
|
||||
required decreases as the energy increases. The exact solution is obtained by the matrix inversion
|
||||
method but should be preferably used for lower energy.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('polarization', types=(type(None), str),
|
||||
allowed_values=(None, 'linear_qOz', 'linear_xOy',
|
||||
'circular'), default=None, doc=textwrap.dedent("""
|
||||
'circular'), default=None, doc="""
|
||||
Specify the polarization of the incident light.
|
||||
|
||||
- **None**, for unpolarized light
|
||||
|
@ -756,16 +787,16 @@ class GlobalParameters(BaseParameters):
|
|||
- '**linear_xOy**' for a polarization vector in the :math:`(x0y)` plane
|
||||
- '**circular**' for circular dichroism
|
||||
|
||||
""")),
|
||||
"""),
|
||||
Parameter('dichroism', types=(type(None), str),
|
||||
allowed_values=(None, 'natural', 'sum_over_spin',
|
||||
'spin_resolved'), default=None, doc=textwrap.dedent("""
|
||||
'spin_resolved'), default=None, doc="""
|
||||
Used to perform dichroic calculations. The default (None) is to disable this.
|
||||
""")),
|
||||
Parameter('spinpol', types=bool, default=False, doc=textwrap.dedent("""
|
||||
"""),
|
||||
Parameter('spinpol', types=bool, default=False, doc="""
|
||||
Enable or disbale spin-resolved calculations.
|
||||
""")),
|
||||
Parameter('folder', types=str, default='./calc', doc=textwrap.dedent("""
|
||||
"""),
|
||||
Parameter('folder', types=str, default='./calc', doc="""
|
||||
This parameter is the path to the temporary folder used for the calculations. If you do not change this
|
||||
parameter between calculations, all the content will be overridden. This is usually not a problem, since the
|
||||
whole bunch of data created during a computation is not meant to be saved. But you may want to anyway by
|
||||
|
@ -781,7 +812,7 @@ class GlobalParameters(BaseParameters):
|
|||
calc.shutdown() # the folder is removed
|
||||
|
||||
|
||||
"""))
|
||||
""")
|
||||
)
|
||||
BaseParameters.__init__(self)
|
||||
self.add_parameters(*parameters)
|
||||
|
@ -816,11 +847,11 @@ class GlobalParameters(BaseParameters):
|
|||
class MuffintinParameters(BaseParameters):
|
||||
def __init__(self, phagen_parameters, spec_parameters):
|
||||
parameters = (
|
||||
Parameter('charge_relaxation', types=bool, default=True, doc=textwrap.dedent("""
|
||||
Parameter('charge_relaxation', types=bool, default=True, doc="""
|
||||
Used to specify wether the charge density of the photoabsorbing atom, which is used
|
||||
to construct the potential, is allowaed to relax around the core hole or not.
|
||||
""")),
|
||||
Parameter('ionicity', types=dict, default={}, doc=textwrap.dedent("""
|
||||
"""),
|
||||
Parameter('ionicity', types=dict, default={}, doc="""
|
||||
A dictionary to specify the ionicity of each kind of atoms. If empty, the atoms are considered to be
|
||||
neutral. Otherwise, each key must be a chemical symbol and the corresponding value should be the fraction
|
||||
of electrons added (negative) or substracted (positive) with respect to neutrality.
|
||||
|
@ -831,28 +862,28 @@ class MuffintinParameters(BaseParameters):
|
|||
means that 0.15 electrons have been substracted from La, likewise from Fe. Neutrality implies that 0.3
|
||||
electrons have to be added to oxygen atoms.
|
||||
|
||||
""")),
|
||||
"""),
|
||||
Parameter('relativistic_mode', types=str,
|
||||
allowed_values=('non_relativistic', 'scalar_relativistic',
|
||||
'spin_orbit_resolved'),
|
||||
default='non_relativistic', doc=textwrap.dedent("""
|
||||
default='non_relativistic', doc="""
|
||||
To tell whether to use the scalar relativistic approximation or not.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('radius_overlapping', types=float, limits=(0., 1.),
|
||||
default=0., doc=textwrap.dedent("""
|
||||
default=0., doc="""
|
||||
to allow atomic spheres to overlapp with each other. The value is a percentage, 1. means 100%.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('interstitial_potential', types=(int, float),
|
||||
unit=UREG.eV, default=0., doc=textwrap.dedent("""
|
||||
unit=UREG.eV, default=0., doc="""
|
||||
The average interstitial potential (or inner potential) expressed in eV. It is used to compute
|
||||
the refraction at the surface.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('hydrogen_radius', types=(int, float), default=0.9,
|
||||
limits=(0., None), unit=UREG.angstroms, doc=textwrap.dedent("""
|
||||
limits=(0., None), unit=UREG.angstroms, doc="""
|
||||
The program can have difficulties to find the radius of the hydrogen atom (small atom). You can
|
||||
specify here a value for the radius. If you set it to 'None', the calculation of the muffin-tin
|
||||
radius of H atoms will be left to the program.
|
||||
"""))
|
||||
""")
|
||||
)
|
||||
BaseParameters.__init__(self)
|
||||
self.add_parameters(*parameters)
|
||||
|
@ -884,28 +915,28 @@ class MuffintinParameters(BaseParameters):
|
|||
class TMatrixParameters(BaseParameters):
|
||||
def __init__(self, phagen_parameters):
|
||||
parameters = (
|
||||
Parameter('potential', types=str,
|
||||
allowed_values=('muffin_tin', 'lmto', 'spkkr', 'msf'),
|
||||
default='muffin_tin', doc=textwrap.dedent("""
|
||||
This option allows to choose which kind of potential is used to compute the T-Matrix. For now,
|
||||
only the internal *Muffin-Tin* potential is supported.
|
||||
""")),
|
||||
Parameter('potential_file', types=(str,type(None)), default=None),
|
||||
Parameter('potential', types=(str, ForeignPotential),
|
||||
default='muffin_tin',
|
||||
doc="""
|
||||
This option allows to choose which kind of potential is
|
||||
used to compute the T-Matrix. For now, only the internal
|
||||
*Muffin-Tin* potential is supported.""",
|
||||
),
|
||||
Parameter('exchange_correlation', types=str,
|
||||
allowed_values=('hedin_lundqvist_real',
|
||||
'hedin_lundqvist_complex',
|
||||
'x_alpha_real',
|
||||
'dirac_hara_real', 'dirac_hara_complex'),
|
||||
default='hedin_lundqvist_complex', doc=textwrap.dedent("""
|
||||
default='hedin_lundqvist_complex', doc="""
|
||||
Set the type of exchange and correlation potential that will be used.
|
||||
""")),
|
||||
Parameter('imaginery_part', types=(int, float), default=0., doc=textwrap.dedent("""
|
||||
"""),
|
||||
Parameter('imaginery_part', types=(int, float), default=0., doc="""
|
||||
This value is added to complex potentials to account for core-hole lifetime and experimental resolution
|
||||
broadening effects.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('lmax_mode', types=str,
|
||||
allowed_values=('max_ke', 'true_ke', 'imposed'),
|
||||
default='true_ke', doc=textwrap.dedent("""
|
||||
default='true_ke', doc="""
|
||||
This allows to control the number of basis functions used to expand the wave function on each
|
||||
atom. It can be:
|
||||
|
||||
|
@ -919,11 +950,11 @@ class TMatrixParameters(BaseParameters):
|
|||
:math:`l_{max} = kr_{at} + 1` where :math:`k=E^{1/2}_k` with :math:`E_k` being the kinetic
|
||||
energy. In this case :math:`l_{max}` depends both on the energy and the atom number.
|
||||
|
||||
""")),
|
||||
Parameter('lmaxt', types=int, limits=(1, None), default=19, doc=textwrap.dedent("""
|
||||
"""),
|
||||
Parameter('lmaxt', types=int, limits=(1, None), default=19, doc="""
|
||||
The value of :math:`l_{max}` if *lmax_mode = 'imposed'*
|
||||
""")),
|
||||
Parameter('tl_threshold', types=(type(None), float), default=None, doc=textwrap.dedent("""
|
||||
"""),
|
||||
Parameter('tl_threshold', types=(type(None), float), default=None, doc="""
|
||||
This option allows to control the number of basis function by defining a threshold value for the *tl*.
|
||||
For example::
|
||||
|
||||
|
@ -934,8 +965,8 @@ class TMatrixParameters(BaseParameters):
|
|||
.. note::
|
||||
This option is compatible with any modes of the *lmax_mode* option.
|
||||
|
||||
""")),
|
||||
Parameter('max_tl', types=(type(None), dict), default=None, doc=textwrap.dedent("""
|
||||
"""),
|
||||
Parameter('max_tl', types=(type(None), dict), default=None, doc="""
|
||||
*max_tl* is used to sepcify a maximum number of basis functions to use for each kind of atoms. For example,
|
||||
in the case of an MgO cluster, you could write::
|
||||
|
||||
|
@ -948,7 +979,7 @@ class TMatrixParameters(BaseParameters):
|
|||
.. note::
|
||||
This option is compatible with any modes of the *lmax_mode* option.
|
||||
|
||||
"""))
|
||||
""")
|
||||
)
|
||||
BaseParameters.__init__(self)
|
||||
self.add_parameters(*parameters)
|
||||
|
@ -956,12 +987,17 @@ class TMatrixParameters(BaseParameters):
|
|||
self.freeze()
|
||||
|
||||
def bind_potential(self, p):
|
||||
mapping = {'muffin_tin': 'in', 'lmto': 'ex', 'spkkr': 'ex', 'msf': 'ex'}
|
||||
if p.value.lower() in ('muffin_tin'):
|
||||
mapping = {SPRKKRPotential: 'spkkr'}
|
||||
if isinstance(p.value, str):
|
||||
assert p.value.lower() in ('muffin_tin'), p.assert_message(
|
||||
"\"{}\" is not an known potential type", p.value)
|
||||
self.phagen_parameters.potgen = 'in'
|
||||
elif p.value.lower() in ('spkkr', 'lmto', 'msf'):
|
||||
elif isinstance(p.value, ForeignPotential):
|
||||
self.phagen_parameters.potgen = 'ex'
|
||||
self.phagen_parameters.potype = p.value.lower()
|
||||
potype = mapping[p.value.__class__]
|
||||
self.phagen_parameters.potype = potype
|
||||
|
||||
|
||||
|
||||
def bind_exchange_correlation(self, p):
|
||||
potential = self.get_parameter('potential').value
|
||||
|
@ -975,7 +1011,8 @@ class TMatrixParameters(BaseParameters):
|
|||
}
|
||||
self.phagen_parameters.potype = mapping[p.value]
|
||||
else:
|
||||
self.phagen_parameters.potype = potential
|
||||
mapping = {SPRKKRPotential: 'spkkr'}
|
||||
self.phagen_parameters.potype = mapping[potential.value.__class__]
|
||||
|
||||
def bind_potential_file(self, p):
|
||||
pass
|
||||
|
@ -1009,7 +1046,7 @@ class SourceParameters(BaseParameters):
|
|||
def __init__(self, global_parameters=None, phagen_parameters=None, spec_parameters=None):
|
||||
parameters = (
|
||||
Parameter('energy', types=(list, tuple, int, float),
|
||||
limits=(0, None), unit=UREG.eV, doc=textwrap.dedent("""
|
||||
limits=(0, None), unit=UREG.eV, doc="""
|
||||
The photon energy in eV.
|
||||
|
||||
Common laboratories X-ray source Mg |kalpha| and Al |kalpha| lines are
|
||||
|
@ -1026,20 +1063,20 @@ class SourceParameters(BaseParameters):
|
|||
1253.6
|
||||
|
||||
|
||||
"""),
|
||||
""",
|
||||
default=XRaySource.MG_KALPHA),
|
||||
Parameter('theta', types=(int, float), limits=(-180., 180.),
|
||||
unit=UREG.degree, default=-55., doc=textwrap.dedent("""
|
||||
unit=UREG.degree, default=-55., doc="""
|
||||
The polar angle of the photon incidence (in degrees). Please refer to
|
||||
:ref:`this figure <ped_full_picture>` for questions regarding the proper
|
||||
orientation.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('phi', types=(int, float), limits=(-180., 180.),
|
||||
unit=UREG.degree, default=0., doc=textwrap.dedent("""
|
||||
unit=UREG.degree, default=0., doc="""
|
||||
The azimuthal angle of the photon incidence (in degrees). Please refer to
|
||||
:ref:`this figure <ped_full_picture>` for questions regarding the proper
|
||||
orientation.
|
||||
""")),
|
||||
"""),
|
||||
)
|
||||
BaseParameters.__init__(self)
|
||||
self.add_parameters(*parameters)
|
||||
|
@ -1091,13 +1128,13 @@ class DetectorParameters(BaseParameters):
|
|||
parameters = (
|
||||
Parameter('angular_acceptance', types=(int, float),
|
||||
unit=UREG.degree, limits=(0., None), default=0.,
|
||||
doc=textwrap.dedent("""
|
||||
doc="""
|
||||
The angular acceptance of the detector in degrees used
|
||||
when the *average_sampling* option is enabled below.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('average_sampling', types=(type(None), str),
|
||||
allowed_values=(None, 'low', 'medium', 'high'),
|
||||
default=None, doc=textwrap.dedent("""
|
||||
default=None, doc="""
|
||||
Used to averaged the signal over directions lying in the
|
||||
cone of half-angle *angular_acceptance*. The number of
|
||||
directions to take into account depends on the choosen
|
||||
|
@ -1107,11 +1144,11 @@ class DetectorParameters(BaseParameters):
|
|||
- '**low**', to average over 5 directions
|
||||
- '**medium**', to average over 13 directions
|
||||
- '**high**', to average over 49 directions
|
||||
""")),
|
||||
Parameter('rotate', types=bool, default=False, doc=textwrap.dedent("""
|
||||
"""),
|
||||
Parameter('rotate', types=bool, default=False, doc="""
|
||||
When False, the sample is rotated when doing a scan (the
|
||||
usual way). Otherwise, the detector is rotated.
|
||||
"""))
|
||||
""")
|
||||
)
|
||||
BaseParameters.__init__(self)
|
||||
self.add_parameters(*parameters)
|
||||
|
@ -1172,7 +1209,7 @@ class ScanParameters(BaseParameters):
|
|||
default=np.array([0.])),
|
||||
Parameter('kinetic_energy', types=(list, tuple, int, float),
|
||||
unit=UREG.eV, limits=(0., None),
|
||||
default=200., doc=textwrap.dedent("""
|
||||
default=200., doc="""
|
||||
if given as a list or tuple:
|
||||
* with 2 elements, 10 points of energy will be generated
|
||||
with the first element as the starting energy and the
|
||||
|
@ -1183,7 +1220,7 @@ class ScanParameters(BaseParameters):
|
|||
|
||||
if given as a float or integer, there will be one point
|
||||
for the kinetic energy.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('ke_array', types=np.ndarray, unit=UREG.eV,
|
||||
default=np.array([200., ]), private=True)
|
||||
)
|
||||
|
@ -1380,48 +1417,48 @@ class CalculationParameters(BaseParameters):
|
|||
def __init__(self, global_parameters, phagen_parameters, spec_parameters):
|
||||
parameters = (
|
||||
Parameter('RA_cutoff', types=int, limits=(0, 8), default=1,
|
||||
doc=textwrap.dedent("""
|
||||
doc="""
|
||||
The Rehr-Albers cut-off parameter which controls the degree of
|
||||
sphericity introduced in the description of the basis functions
|
||||
used to expand the wave function around each atomic center.
|
||||
It is only meaningful for the series expansion algorithm.
|
||||
Its value is limited to 8 but it is rarely necessary to go beyond
|
||||
2 or 3.""")),
|
||||
2 or 3."""),
|
||||
Parameter('scattering_order', types=int, limits=(1, 10), default=3,
|
||||
doc=textwrap.dedent("""
|
||||
doc="""
|
||||
The scattering order. Only meaningful for the 'expansion' algorithm.
|
||||
Its value is limited to 10.""")),
|
||||
Its value is limited to 10."""),
|
||||
Parameter('renormalization_mode', allowed_values=(None, 'G_n', 'Sigma_n',
|
||||
'Z_n', 'Pi_1', 'Lowdin'),
|
||||
types=(type(None), str), default=None,
|
||||
doc=textwrap.dedent("""
|
||||
doc="""
|
||||
Enable the calculation of the coefficients for the renormalization of
|
||||
the multiple scattering series.
|
||||
You can choose to renormalize in terms of the :math:`G_n`, the
|
||||
:math:`\\Sigma_n`, the :math:`Z_n`, the :math:`\\Pi_1` or the Lowdin
|
||||
:math:`K^2` matrices""")),
|
||||
:math:`K^2` matrices"""),
|
||||
Parameter('renormalization_omega', types=(int,float,complex),
|
||||
default=1.+0j,
|
||||
doc=textwrap.dedent("""
|
||||
doc="""
|
||||
The :math:`\\omega` coefficient used to initialize the
|
||||
renormalization alogorithm.""")),
|
||||
renormalization alogorithm."""),
|
||||
Parameter('RA_cutoff_damping', types=int, limits=(0, None),
|
||||
default=0, doc=textwrap.dedent("""
|
||||
default=0, doc="""
|
||||
The Rehr-Albers truncation order. If > 0, the *RA_cutoff* is
|
||||
decreased by 1 every *i*\ :sup:`th` scatterer until 0, where
|
||||
*i* = *RA_cutoff_damping*.""")),
|
||||
*i* = *RA_cutoff_damping*."""),
|
||||
Parameter('spin_flip', types=bool, default=False,
|
||||
doc=textwrap.dedent("""
|
||||
doc="""
|
||||
This parameter tells if spin-flip is authorized or not in the
|
||||
scattering process.
|
||||
|
||||
:Note:
|
||||
|
||||
This option works only if the spin polarization is
|
||||
enabled in your calculator object (see spinpol_).""")),
|
||||
enabled in your calculator object (see spinpol_)."""),
|
||||
Parameter('integrals', types=str, allowed_values=('all',
|
||||
'diagonal'),
|
||||
default='all', doc=textwrap.dedent("""
|
||||
default='all', doc="""
|
||||
This option allows to take into account all four radial integrals
|
||||
(R++, R+-, R-+ and R--) in the calculation or only the diagonal
|
||||
radial integrals (R++ and R--) which are generally much larger.
|
||||
|
@ -1431,7 +1468,7 @@ class CalculationParameters(BaseParameters):
|
|||
This option works only if the spin polarization is
|
||||
enabled in your calculator object.
|
||||
|
||||
""")),
|
||||
"""),
|
||||
Parameter('path_filtering', types=(type(None), str, tuple, list),
|
||||
allowed_values=(None,
|
||||
'forward_scattering',
|
||||
|
@ -1439,66 +1476,66 @@ class CalculationParameters(BaseParameters):
|
|||
'distance_cutoff',
|
||||
'plane_wave_normal',
|
||||
'plane_wave_spin_averaged'),
|
||||
default=None, doc=textwrap.dedent("""
|
||||
default=None, doc="""
|
||||
Used to activate some filters. It is possible to specify several
|
||||
of them by grouping them in a tuple or a list. For example::
|
||||
|
||||
>>> my_filters = ('forward_scattering', 'backward_scattering')
|
||||
>>> calc.calculation_parameters.path_filtering = my_filters
|
||||
|
||||
""")),
|
||||
"""),
|
||||
Parameter('off_cone_events', types=int, limits=(0, None), default=1,
|
||||
doc=textwrap.dedent("""
|
||||
doc="""
|
||||
Used in conjunction with the '*forward_scattering*' filter.
|
||||
If the number of scattering processes outside the forward (or
|
||||
backward) scattering cone is greater than this number, then the
|
||||
path is rejected and its contribution to the scattering path
|
||||
operator won’t be computed.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('scattering_order_cutoff', types=int, limits=(0, 10),
|
||||
default=2, doc=textwrap.dedent("""
|
||||
default=2, doc="""
|
||||
Used in conjunction with the ‘*plane_wave_normal*’ filter. It states
|
||||
to activate the plane wave approximation (which is fast but
|
||||
less accurate) to compute the contribution when the scattering order
|
||||
is greater than this value.""")),
|
||||
is greater than this value."""),
|
||||
|
||||
Parameter('distance', types=(int, float), limits=(0, None),
|
||||
unit=UREG.angstroms, default=10., doc=textwrap.dedent("""
|
||||
unit=UREG.angstroms, default=10., doc="""
|
||||
Used with the '*distance_cut_off*' filter. Paths whose length is
|
||||
larger than this value are simply rejected.""")),
|
||||
larger than this value are simply rejected."""),
|
||||
Parameter('vibrational_damping', types=(type(None), str),
|
||||
allowed_values=(None, 'debye_waller', 'averaged_tl'),
|
||||
default='debye_waller', doc=textwrap.dedent("""
|
||||
default='debye_waller', doc="""
|
||||
Tells how to compute the effect of atomic vibrations. It can be:
|
||||
|
||||
- '**debye_waller**' for using the Debye Waller model.
|
||||
- '**averaged_tl**' to use the more correct averaging over T-matrix elements.""")),
|
||||
- '**averaged_tl**' to use the more correct averaging over T-matrix elements."""),
|
||||
Parameter('temperature', types=(int, float), limits=(0, None),
|
||||
unit=UREG.degK, default=293., doc=textwrap.dedent("""
|
||||
unit=UREG.degK, default=293., doc="""
|
||||
The temperature of the cluster. Used when *use_debye_model* = True
|
||||
""")),
|
||||
"""),
|
||||
Parameter('debye_temperature', types=(int, float), limits=(0, None),
|
||||
unit=UREG.degK, default=420., doc=textwrap.dedent("""
|
||||
unit=UREG.degK, default=420., doc="""
|
||||
The Debye temperature used for the calculation of the mean square
|
||||
displacements if *use_debye_model* = True""")),
|
||||
displacements if *use_debye_model* = True"""),
|
||||
Parameter('use_debye_model', types=bool, default=False,
|
||||
doc=textwrap.dedent("""
|
||||
doc="""
|
||||
No matter the way you compute the effect of atomic vibrations,
|
||||
you need the mean square displacements of atoms. It can be computed
|
||||
internally following the Debye model if you set this option to True.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('vibration_scaling', types=(int, float),
|
||||
limits=(0., None), default=1.2, doc=textwrap.dedent("""
|
||||
limits=(0., None), default=1.2, doc="""
|
||||
Used to simulate the fact that surface atoms vibrate more than
|
||||
bulk ones. It is a factor applied to the mean square displacements.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('basis_functions', types=str, allowed_values=(
|
||||
'plane_wave', 'spherical'), default='spherical', private=True),
|
||||
Parameter('cutoff_factor', types=(int, float),
|
||||
limits=(1e-4, 999.9999), default=0.01, private=True),
|
||||
Parameter('mean_free_path', types=(int, float, str),
|
||||
default='SeahDench', allowed_values=('mono', 'SeahDench'),
|
||||
doc=textwrap.dedent("""
|
||||
doc="""
|
||||
The electron mean free path value. You can either:
|
||||
- Enter a value (in Angströms), in this case any value <=0 will disable the damping
|
||||
- Enter the keyword 'mono' to use a formula valid only for monoelemental samples
|
||||
|
@ -1510,7 +1547,7 @@ class CalculationParameters(BaseParameters):
|
|||
to a real potential as, when the potential is complex, this damping is taken care
|
||||
of by the imaginery part othe potential.
|
||||
|
||||
""")),
|
||||
"""),
|
||||
|
||||
)
|
||||
BaseParameters.__init__(self)
|
||||
|
@ -1728,7 +1765,7 @@ class PEDParameters(BaseParameters):
|
|||
def __init__(self, phagen_parameters, spec_parameters):
|
||||
parameters = (
|
||||
Parameter('level', types=str, pattern=r'\d+[spdfgSPDFG](\d/2)?$',
|
||||
default='1s', doc=textwrap.dedent("""
|
||||
default='1s', doc="""
|
||||
The level is the electronic level where the electron comes from.
|
||||
It is written: *nlJ*
|
||||
where:
|
||||
|
@ -1742,7 +1779,7 @@ class PEDParameters(BaseParameters):
|
|||
>>> calc.spectroscopy_parameters.level = '2p3/2'
|
||||
>>> calc.spectroscopy_parameters.level = '2p' # is equivalent to '2p1/2'
|
||||
|
||||
""")),
|
||||
"""),
|
||||
Parameter('final_state', types=int, limits=(-1, 2), default=2),
|
||||
Parameter('spin_orbit', types=(type(None), str),
|
||||
allowed_values=(None, 'single', 'both'), default=None),
|
||||
|
@ -1779,7 +1816,7 @@ class EIGParameters(BaseParameters):
|
|||
def __init__(self, phagen_parameters, spec_parameters):
|
||||
parameters = (
|
||||
Parameter('level', types=str, pattern=r'\d+[spdfgSPDFG](\d/2)?$',
|
||||
default='1s', doc=textwrap.dedent("""
|
||||
default='1s', doc="""
|
||||
The level is the electronic level where the electron comes from.
|
||||
It is written: *nlJ*
|
||||
where:
|
||||
|
@ -1793,21 +1830,21 @@ class EIGParameters(BaseParameters):
|
|||
>>> calc.spectroscopy_parameters.level = '2p3/2'
|
||||
>>> calc.spectroscopy_parameters.level = '2p' # is equivalent to '2p1/2'
|
||||
|
||||
""")),
|
||||
"""),
|
||||
Parameter('final_state', types=int, limits=(-1, 2), default=2),
|
||||
Parameter('spin_orbit', types=(type(None), str),
|
||||
allowed_values=(None, 'single', 'both'), default=None),
|
||||
Parameter('kernel_matrix_spectrum', types=(bool,), default=False, doc=textwrap.dedent("""
|
||||
Parameter('kernel_matrix_spectrum', types=(bool,), default=False, doc="""
|
||||
Whether to output the kernel matrix spectrum for each energy point.
|
||||
""")),
|
||||
"""),
|
||||
Parameter('method', types=(str,), default='EPSI',
|
||||
allowed_values=['AITK', 'RICH', 'SALZ', 'EPSI', 'EPSG',
|
||||
'RHOA', 'THET', 'LEGE', 'CHEB', 'OVER',
|
||||
'DURB', 'DLEV', 'TLEV', 'ULEV', 'VLEV',
|
||||
'ELEV', 'EULE', 'GBWT', 'VARI', 'ITHE',
|
||||
'EALG'],
|
||||
doc=textwrap.dedent("""The convergence acceleration scheme to be used.
|
||||
""")),
|
||||
doc="""The convergence acceleration scheme to be used.
|
||||
"""),
|
||||
)
|
||||
BaseParameters.__init__(self)
|
||||
self.add_parameters(*parameters)
|
||||
|
@ -1832,5 +1869,3 @@ class EIGParameters(BaseParameters):
|
|||
def bind_kernel_matrix_spectrum(self, p):
|
||||
value = int(p.value)
|
||||
self.spec_parameters.eigval_ispectrum_ne = value
|
||||
|
||||
|
||||
|
|
|
@ -1,21 +1,41 @@
|
|||
# coding: utf-8
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright © 2016-2020 - Rennes Physics Institute
|
||||
#
|
||||
# This file is part of msspec.
|
||||
#
|
||||
# msspec is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
# msspec is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this msspec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Source file : src/msspec/tests.py
|
||||
# Last modified: ven. 10 avril 2020 17:33:28
|
||||
# Committed by : "Sylvain Tricot <sylvain.tricot@univ-rennes1.fr>"
|
||||
|
||||
from msspec.calculator import MSSPEC
|
||||
from msspec.utils import *
|
||||
from msspec.misc import set_log_level
|
||||
|
||||
from ase.build import bulk
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
from hashlib import md5
|
||||
from pickle import dumps
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
import os
|
||||
from ase.build import bulk
|
||||
|
||||
from msspec.calculator import MSSPEC
|
||||
from msspec.misc import set_log_level
|
||||
from msspec.utils import *
|
||||
|
||||
set_log_level('error')
|
||||
RESULTS_FILENAME = os.path.join(os.path.dirname(__file__), 'results.txt')
|
||||
|
||||
|
||||
def perform_test(obj, funcname, filename=RESULTS_FILENAME):
|
||||
f = getattr(obj, '_' + funcname)
|
||||
output = md5(dumps(f())).hexdigest()
|
||||
|
|
|
@ -1,5 +1,26 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
# vim: set fdm=indent ts=4 sw=4 sts=4 et tw=80 ai cc=+0 mouse=a nu : #
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright © 2016-2020 - Rennes Physics Institute
|
||||
#
|
||||
# This file is part of msspec.
|
||||
#
|
||||
# msspec is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# msspec is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this msspec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Source file : src/msspec/utils.py
|
||||
# Last modified: ven. 10 avril 2020 15:49:35
|
||||
# Committed by : "Sylvain Tricot <sylvain.tricot@univ-rennes1.fr>"
|
||||
|
||||
|
||||
"""
|
||||
Module utils
|
||||
|
@ -8,20 +29,159 @@ Module utils
|
|||
|
||||
"""
|
||||
|
||||
|
||||
import re
|
||||
|
||||
import numpy as np
|
||||
from ase import Atoms, Atom
|
||||
from ase.visualize import view
|
||||
from ase import Atom
|
||||
from ase import Atoms
|
||||
|
||||
class MsSpecAtoms(Atoms):
|
||||
def __init__(self, *args, **kwargs):
|
||||
Atoms.__init__(self, *args, **kwargs)
|
||||
self.__absorber_index = None
|
||||
from msspec.iodata import Data
|
||||
from msspec.misc import LOGGER
|
||||
|
||||
def set_absorber(self, index):
|
||||
self.__absorber_index = index
|
||||
|
||||
def get_absorber(self):
|
||||
return self.__absorber_index
|
||||
class ForeignPotential(object):
|
||||
def __init__(self):
|
||||
self.data = Data(title='Foreign Potential')
|
||||
# Load exported potentials
|
||||
# phagen_data is a dictionary with:
|
||||
# self.phagen_data = {
|
||||
# 'VintTotal' : <float>,
|
||||
# 'VintCoulomb': <float>,
|
||||
# 'RHOint' : <float>,
|
||||
# 'types': [
|
||||
# {
|
||||
# 'Z' : <int>,
|
||||
# 'RWS' : <float>,
|
||||
# 'data': <np.array(..., 4, dtype=float)>
|
||||
# },
|
||||
# ...
|
||||
# ...
|
||||
# ...
|
||||
# ]
|
||||
# }
|
||||
self.phagen_data = {'types': []}
|
||||
|
||||
def write(self, filename, prototypical_atoms):
|
||||
LOGGER.debug(f"Writing Phagen input potential file: {filename}")
|
||||
|
||||
def append_atom_potential(atom):
|
||||
Z = atom.number
|
||||
# Find the right type (Z) in the phagen_data
|
||||
itypes = []
|
||||
for i, t in enumerate(self.phagen_data['types']):
|
||||
if t['Z'] == Z:
|
||||
itypes.append(i)
|
||||
# Check now that we have only one type in the list
|
||||
# otherwise we do not know yet how to deal with this.
|
||||
assert len(itypes) > 0, f"Cannot find the data for atom with Z={Z}"
|
||||
assert len(itypes) == 1, f"Too many datasets for atom with Z={Z}"
|
||||
# So far so good, let's write the block
|
||||
t = self.phagen_data['types'][itypes[0]]
|
||||
s = "{:<7d}{:<10d}{:1.4f}\n".format(
|
||||
t['Z'], len(t['data']), t['RWS'])
|
||||
line_fmt = "{:+1.8e} " * 4 + "\n"
|
||||
for row in t['data']:
|
||||
s += line_fmt.format(*row)
|
||||
return s
|
||||
|
||||
content = ""
|
||||
# Start by writing the header line
|
||||
content += "{:.2f} {:.4f} {:.2f}\n".format(
|
||||
self.phagen_data['VintCoulomb'],
|
||||
self.phagen_data['RHOint'],
|
||||
self.phagen_data['VintTotal'])
|
||||
# Then for each atom in the given prototypical cluster,
|
||||
# write the data block
|
||||
for atom in prototypical_atoms:
|
||||
content += append_atom_potential(atom)
|
||||
|
||||
# Write the content to filename
|
||||
try:
|
||||
with open(filename, 'r') as fd:
|
||||
old_content = fd.read()
|
||||
except IOError:
|
||||
old_content = ''
|
||||
|
||||
modified = False
|
||||
if content != old_content:
|
||||
with open(filename, 'w') as fd:
|
||||
fd.write(content)
|
||||
modified = True
|
||||
|
||||
return modified
|
||||
|
||||
|
||||
class SPRKKRPotential(ForeignPotential):
|
||||
def __init__(self, atoms, potfile, *exported_files):
|
||||
super().__init__()
|
||||
|
||||
def read(content, pattern, types):
|
||||
# compile the pattern for regex matching
|
||||
pat = re.compile(pattern, re.MULTILINE)
|
||||
# get the keys and data as list of strings
|
||||
keys = re.split(r'\s+',
|
||||
pat.search(content).group('KEYS').strip(' \n'))
|
||||
txt = pat.search(content).group('DATA').strip('\n').split('\n')
|
||||
data = []
|
||||
for line in txt:
|
||||
# Unpacking values
|
||||
values_txt = re.split(r'\s+', line.strip())
|
||||
data_dict = {}
|
||||
for i, _ in enumerate(values_txt):
|
||||
# Type casting
|
||||
value = types[i].__call__(_)
|
||||
data_dict[keys[i]] = value
|
||||
# push to the list
|
||||
data.append(data_dict)
|
||||
return data
|
||||
|
||||
# load info in *.pot file
|
||||
with open(potfile, 'r') as fd:
|
||||
content = fd.read()
|
||||
|
||||
self.sites_data = read(content,
|
||||
(r'^\s*SITES\s*\n((.*\n)+?\s*(?P<KEYS>IQ.*)\n'
|
||||
r'(?P<DATA>(.*\n)+?))\*+'),
|
||||
[int] + [float] * 3)
|
||||
self.types_data = read(content,
|
||||
(r'^\s*TYPES\s*\n(\s*(?P<KEYS>IT.*)\n'
|
||||
r'(?P<DATA>(.*\n)+?))\*+'),
|
||||
[int, str] + [int] * 4)
|
||||
self.occ_data = read(content,
|
||||
(r'^\s*OCCUPATION\s*\n(\s*(?P<KEYS>IQ.*)\n'
|
||||
r'(?P<DATA>(.*\n)+?))\*+'),
|
||||
[int] * 5 + [float])
|
||||
|
||||
for f in exported_files:
|
||||
# get the IT from the filename
|
||||
# m=re.match('SPRKKR-IT_(?P<IT>\d+)-PHAGEN.*', os.path.basename(f))
|
||||
# it = int(m.group('IT'))
|
||||
|
||||
# load the content of the header (2 lines)
|
||||
with open(f, 'r') as fd:
|
||||
first_line = fd.readline().strip('\n')
|
||||
second_line = fd.readline().strip('\n')
|
||||
|
||||
# load Coulomb and Total interstitial potential
|
||||
pattern = (r'#\s*VMTZ_TOTAL\s*=\s*(?P<TOTAL>.*?)\s+'
|
||||
r'VMTZ_Coulomb\s*=\s*(?P<COULOMB>.*?)\s+.*$')
|
||||
m = re.match(pattern, first_line)
|
||||
self.phagen_data.update(VintCoulomb=float(m.group('COULOMB')),
|
||||
VintTotal=float(m.group('TOTAL')),
|
||||
RHOint=0.)
|
||||
|
||||
# load Z, Wigner-Seitz radius from 2nd line of header
|
||||
type_data = {}
|
||||
_ = re.split(r'\s+', second_line.strip("# "))
|
||||
type_data.update(Z=int(_[0]), RWS=float(_[3]))
|
||||
|
||||
# load the data
|
||||
data = np.loadtxt(f, comments='#')
|
||||
type_data.update(data=data)
|
||||
|
||||
self.phagen_data['types'].append(type_data)
|
||||
|
||||
|
||||
class EmptySphere(Atom):
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -30,135 +190,117 @@ class EmptySphere(Atom):
|
|||
|
||||
|
||||
def get_atom_index(atoms, x, y, z):
|
||||
""" Return the index of the atom that is the closest to the coordiantes
|
||||
given as parameters.
|
||||
""" Return the index of the atom that is the closest to the coordiantes
|
||||
given as parameters.
|
||||
|
||||
:param ase.Atoms atoms: an ASE Atoms object
|
||||
:param float x: the x position in angstroms
|
||||
:param float y: the y position in angstroms
|
||||
:param float z: the z position in angstroms
|
||||
:param ase.Atoms atoms: an ASE Atoms object
|
||||
:param float x: the x position in angstroms
|
||||
:param float y: the y position in angstroms
|
||||
:param float z: the z position in angstroms
|
||||
|
||||
:return: the index of the atom as an integer
|
||||
:rtype: int
|
||||
"""
|
||||
# get all distances
|
||||
d = np.linalg.norm(atoms.get_positions() - np.array([x, y, z]), axis = 1)
|
||||
# get the index of the min distance
|
||||
i = np.argmin(d)
|
||||
# return the index and the corresponding distance
|
||||
return i
|
||||
:return: the index of the atom as an integer
|
||||
:rtype: int
|
||||
"""
|
||||
# get all distances
|
||||
d = np.linalg.norm(atoms.get_positions() - np.array([x, y, z]), axis=1)
|
||||
# get the index of the min distance
|
||||
i = np.argmin(d)
|
||||
# return the index and the corresponding distance
|
||||
return i
|
||||
|
||||
|
||||
def center_cluster(atoms, invert=False):
|
||||
""" Centers an Atoms object by translating it so the origin is roughly
|
||||
at the center of the cluster.
|
||||
The function supposes that the cluster is wrapped inside the unit cell,
|
||||
with the origin being at the corner of the cell.
|
||||
It is used in combination with the cut functions, which work only if the
|
||||
origin is at the center of the cluster
|
||||
|
||||
:param ase.Atoms atoms: an ASE Atoms object
|
||||
:param bool invert: if True, performs the opposite translation (uncentering the cluster)
|
||||
|
||||
"""
|
||||
for i, cell_vector in enumerate(atoms.get_cell()):
|
||||
if invert:
|
||||
atoms.translate(0.5*cell_vector)
|
||||
else:
|
||||
atoms.translate(-0.5*cell_vector)
|
||||
""" Centers an Atoms object by translating it so the origin is roughly
|
||||
at the center of the cluster.
|
||||
The function supposes that the cluster is wrapped inside the unit cell,
|
||||
with the origin being at the corner of the cell.
|
||||
It is used in combination with the cut functions, which work only if the
|
||||
origin is at the center of the cluster
|
||||
:param ase.Atoms atoms: an ASE Atoms object
|
||||
:param bool invert: if True, performs the opposite translation
|
||||
(uncentering the cluster)
|
||||
"""
|
||||
for i, cell_vector in enumerate(atoms.get_cell()):
|
||||
if invert:
|
||||
atoms.translate(0.5*cell_vector)
|
||||
else:
|
||||
atoms.translate(-0.5*cell_vector)
|
||||
|
||||
|
||||
def cut_sphere(atoms, radius, center=(0, 0, 0)):
|
||||
""" Removes all the atoms of an Atoms object outside a sphere with a
|
||||
given radius
|
||||
|
||||
:param ase.Atoms atoms: an ASE Atoms object
|
||||
:param float radius: the radius of the sphere
|
||||
|
||||
:return: The modified atom cluster
|
||||
:rtype: ase.Atoms
|
||||
"""
|
||||
assert radius >= 0, "Please give a positive radius value"
|
||||
radii = np.linalg.norm(atoms.positions - center, axis=1)
|
||||
indices = np.where(radii <= radius)[0]
|
||||
return atoms[indices]
|
||||
|
||||
|
||||
|
||||
|
||||
def _cut_sphere(atoms, radius=None):
|
||||
""" Removes all the atoms of an Atoms object outside a sphere with a
|
||||
given radius
|
||||
|
||||
:param ase.Atoms atoms: an ASE Atoms object
|
||||
:param float radius: the radius of the sphere
|
||||
|
||||
:return: The modified atom cluster
|
||||
:rtype: ase.Atoms
|
||||
"""
|
||||
if radius is None:
|
||||
raise ValueError("radius not set")
|
||||
|
||||
new_atoms = atoms.copy()
|
||||
|
||||
del_list = []
|
||||
for index, position in enumerate(new_atoms.positions):
|
||||
if np.linalg.norm(position) > radius:
|
||||
del_list.append(index)
|
||||
|
||||
del_list.reverse()
|
||||
for index in del_list:
|
||||
del new_atoms[index]
|
||||
|
||||
return new_atoms
|
||||
|
||||
def cut_cylinder(atoms, axis="z", radius=None):
|
||||
""" Removes all the atoms of an Atoms object outside a cylinder with a
|
||||
given axis and radius
|
||||
""" Removes all the atoms of an Atoms object outside a cylinder with a
|
||||
given axis and radius
|
||||
|
||||
:param ase.Atoms atoms: an ASE Atoms object
|
||||
:param str axis: string "x", "y", or "z". The axis of the cylinder, "z" by default
|
||||
:param float radius: the radius of the cylinder
|
||||
:param ase.Atoms atoms: an ASE Atoms object
|
||||
:param str axis: string "x", "y", or "z". The axis of the cylinder,
|
||||
"z" by default
|
||||
:param float radius: the radius of the cylinder
|
||||
|
||||
:return: The modified atom cluster
|
||||
:rtype: ase.Atoms
|
||||
"""
|
||||
if radius is None:
|
||||
raise ValueError("radius not set")
|
||||
:return: The modified atom cluster
|
||||
:rtype: ase.Atoms
|
||||
"""
|
||||
if radius is None:
|
||||
raise ValueError("radius not set")
|
||||
|
||||
new_atoms = atoms.copy()
|
||||
new_atoms = atoms.copy()
|
||||
|
||||
dims = {"x": 0, "y": 1, "z": 2}
|
||||
if axis in dims:
|
||||
axis = dims[axis]
|
||||
else:
|
||||
raise ValueError("axis not valid, must be 'x','y', or 'z'")
|
||||
dims = {"x": 0, "y": 1, "z": 2}
|
||||
if axis in dims:
|
||||
axis = dims[axis]
|
||||
else:
|
||||
raise ValueError("axis not valid, must be 'x','y', or 'z'")
|
||||
|
||||
del_list = []
|
||||
for index, position in enumerate(new_atoms.positions):
|
||||
# calculating the distance of the atom to the given axis
|
||||
r = 0
|
||||
for dim in range(3):
|
||||
if dim != axis:
|
||||
r = r + position[dim]**2
|
||||
r = np.sqrt(r)
|
||||
del_list = []
|
||||
for index, position in enumerate(new_atoms.positions):
|
||||
# calculating the distance of the atom to the given axis
|
||||
r = 0
|
||||
for dim in range(3):
|
||||
if dim != axis:
|
||||
r = r + position[dim]**2
|
||||
r = np.sqrt(r)
|
||||
|
||||
if r > radius:
|
||||
del_list.append(index)
|
||||
if r > radius:
|
||||
del_list.append(index)
|
||||
|
||||
del_list.reverse()
|
||||
for index in del_list:
|
||||
del new_atoms[index]
|
||||
del_list.reverse()
|
||||
for index in del_list:
|
||||
del new_atoms[index]
|
||||
|
||||
return new_atoms
|
||||
return new_atoms
|
||||
|
||||
def cut_cone(atoms, radius, z = 0):
|
||||
|
||||
def cut_cone(atoms, radius, z=0):
|
||||
"""Shapes the cluster as a cone.
|
||||
|
||||
Keeps all the atoms of the input Atoms object inside a cone of based radius *radius* and of height *z*.
|
||||
Keeps all the atoms of the input Atoms object inside a cone of based
|
||||
radius *radius* and of height *z*.
|
||||
|
||||
:param atoms: The cluster to modify.
|
||||
:type atoms: :py:class:`ase.Atoms`
|
||||
:param radius: The base cone radius in :math:`\mathring{A}`.
|
||||
:param radius: The base cone radius in :math:`\mathring{A}`. # noqa: W605
|
||||
:type radius: float
|
||||
:param z: The height of the cone in :math:`\mathring{A}`.
|
||||
:param z: The height of the cone in :math:`\mathring{A}`. # noqa: W605
|
||||
:type z: float
|
||||
:return: A new cluster.
|
||||
:rtype: :py:class:`ase.Atoms`
|
||||
"""
|
||||
new_atoms = atoms.copy()
|
||||
origin = np.array((0, 0, 0))
|
||||
max_theta = np.arctan(radius/(-z))
|
||||
|
||||
u = np.array((0, 0, -z))
|
||||
|
@ -176,12 +318,12 @@ def cut_cone(atoms, radius, z = 0):
|
|||
if theta <= max_theta:
|
||||
indices.append(i)
|
||||
|
||||
|
||||
new_atoms = new_atoms[indices]
|
||||
new_atoms.translate(-u) # pylint: disable=invalid-unary-operand-type
|
||||
new_atoms.translate(-u)
|
||||
|
||||
return new_atoms
|
||||
|
||||
|
||||
def cut_plane(atoms, x=None, y=None, z=None):
|
||||
""" Removes the atoms whose coordinates are higher (or lower, for a
|
||||
negative cutoff value) than the coordinates given for every dimension.
|
||||
|
@ -191,9 +333,9 @@ def cut_plane(atoms, x=None, y=None, z=None):
|
|||
.. code-block:: python
|
||||
|
||||
cut_plane(atoms, x=[-5,5], y=3.6, z=0)
|
||||
#every atom whose x-coordinate is higher than 5 or lower than -5, and/or
|
||||
#y-coordinate is higher than 3.6, and/or z-coordinate is higher than 0
|
||||
#is deleted.
|
||||
# every atom whose x-coordinate is higher than 5 or lower than -5,
|
||||
# and/or y-coordinate is higher than 3.6, and/or z-coordinate is higher
|
||||
# than 0 is deleted.
|
||||
|
||||
:param ase.Atoms atoms: an ASE Atoms object
|
||||
:param int x: x cutoff value
|
||||
|
@ -206,9 +348,11 @@ def cut_plane(atoms, x=None, y=None, z=None):
|
|||
dim_names = ('x', 'y', 'z')
|
||||
dim_values = [x, y, z]
|
||||
for i, (name, value) in enumerate(zip(dim_names, dim_values)):
|
||||
assert isinstance(value, (int, float, list, tuple, type(None))), "Wrong type"
|
||||
assert isinstance(value, (int, float, list, tuple, type(None))), \
|
||||
"Wrong type"
|
||||
if isinstance(value, (tuple, list)):
|
||||
assert len(value) == 2 and np.all([isinstance(el, (int, float, type(None))) for el in value]), \
|
||||
assert len(value) == 2 and np.all(
|
||||
[isinstance(el, (int, float, type(None))) for el in value]), \
|
||||
"Wrong length"
|
||||
else:
|
||||
try:
|
||||
|
@ -216,7 +360,7 @@ def cut_plane(atoms, x=None, y=None, z=None):
|
|||
dim_values[i] = [-np.inf, value]
|
||||
else:
|
||||
dim_values[i] = [value, np.inf]
|
||||
except:
|
||||
except Exception:
|
||||
dim_values[i] = [value, value]
|
||||
|
||||
if dim_values[i][0] is None:
|
||||
|
@ -227,15 +371,18 @@ def cut_plane(atoms, x=None, y=None, z=None):
|
|||
dim_values = np.array(dim_values)
|
||||
|
||||
def constraint(coordinates):
|
||||
return np.all(np.logical_and(coordinates >= dim_values[:,0], coordinates <= dim_values[:,1]))
|
||||
return np.all(np.logical_and(coordinates >= dim_values[:, 0],
|
||||
coordinates <= dim_values[:, 1]))
|
||||
|
||||
indices = np.where(list(map(constraint, atoms.positions)))[0]
|
||||
return atoms[indices]
|
||||
|
||||
|
||||
def hemispherical_cluster(cluster, emitter_tag=0, emitter_plane=0, diameter=0,
|
||||
planes=0, shape='spherical'):
|
||||
|
||||
"""Creates and returns a cluster based on an Atoms object and some parameters.
|
||||
"""Creates and returns a cluster based on an Atoms object and some
|
||||
parameters.
|
||||
|
||||
:param cluster: the Atoms object used to create the cluster
|
||||
:type cluster: Atoms object
|
||||
|
@ -245,7 +392,8 @@ def hemispherical_cluster(cluster, emitter_tag=0, emitter_plane=0, diameter=0,
|
|||
:type diameter: float
|
||||
:param planes: the number of planes of your cluster
|
||||
:type planes: integer
|
||||
:param emitter_plane: the plane where your emitter will be starting by 0 for the first plane
|
||||
:param emitter_plane: the plane where your emitter will be starting by 0
|
||||
for the first plane
|
||||
:type emitter_plane: integer
|
||||
|
||||
See :ref:`hemispherical_cluster_faq` for more informations.
|
||||
|
@ -255,7 +403,8 @@ def hemispherical_cluster(cluster, emitter_tag=0, emitter_plane=0, diameter=0,
|
|||
nmin = np.inf
|
||||
|
||||
for atom in cluster:
|
||||
if ze - eps < atom.z < ze + eps and (atom.symbol == symbol or symbol == None):
|
||||
if ze - eps < atom.z < ze + eps and (atom.symbol == symbol or
|
||||
symbol is None):
|
||||
n = np.sqrt(atom.x**2 + atom.y**2)
|
||||
if (n < nmin):
|
||||
nmin = n
|
||||
|
@ -270,68 +419,115 @@ def hemispherical_cluster(cluster, emitter_tag=0, emitter_plane=0, diameter=0,
|
|||
eps = 0.01 # a useful small value
|
||||
c = cell[:, 2].max() # a lattice parameter
|
||||
a = cell[:, 0].max() # a lattice parameter
|
||||
p = np.alen(np.unique(np.round(cluster.get_positions()[:, 2], 4))) # the number of planes in the cluster
|
||||
symbol = cluster[np.where(cluster.get_tags() == emitter_tag)[0][0]].symbol # the symbol of your emitter
|
||||
|
||||
assert (diameter != 0 or planes != 0), "At least one of diameter or planes parameter must be use."
|
||||
# the number of planes in the cluster
|
||||
p = np.alen(np.unique(np.round(cluster.get_positions()[:, 2], 4)))
|
||||
# the symbol of your emitter
|
||||
symbol = cluster[np.where(cluster.get_tags() == emitter_tag)[0][0]].symbol
|
||||
|
||||
assert (diameter != 0 or planes != 0), \
|
||||
"At least one of diameter or planes parameter must be use."
|
||||
|
||||
if diameter == 0:
|
||||
l = 1+2*(planes*c/p+1) # calculate the minimal diameter according to the number of planes
|
||||
# calculate the minimal diameter according to the number of planes
|
||||
min_diameter = 1+2*(planes*c/p+1)
|
||||
else:
|
||||
l = diameter
|
||||
min_diameter = diameter
|
||||
|
||||
rep = int(2*l/min(a,c)) # number of repetition in each direction
|
||||
cluster = cluster.repeat((rep, rep, rep)) # repeat the cluster
|
||||
# number of repetition in each direction
|
||||
rep = int(3*min_diameter/min(a, c))
|
||||
|
||||
center_cluster(cluster) # center the cluster
|
||||
cluster.set_cell(cell) # reset the cell
|
||||
cluster = cut_plane(cluster, z=eps) # cut the cluster so that we have a centered surface
|
||||
# repeat the cluster
|
||||
cluster = cluster.repeat((rep, rep, rep))
|
||||
|
||||
i = np.where(cluster.get_tags() == emitter_tag) # positions where atoms have the tag of the emitter_tag
|
||||
all_ze = np.sort(np.unique(np.round(cluster.get_positions()[:, 2][i], 4))) # an array of all unique z corresponding to where we have the right atom's tag
|
||||
all_z = np.sort(np.unique(np.round(cluster.get_positions()[:, 2], 4))) # an array of all unique z
|
||||
# center the cluster
|
||||
center_cluster(cluster)
|
||||
|
||||
n = np.where(all_z == all_z.max())[0][0] - np.where(all_z == all_ze.max())[0][0] # calculate the number of planes above the emitter's plane
|
||||
ze = all_ze.max() # the height of the emitter's plane
|
||||
# reset the cell
|
||||
cluster.set_cell(cell)
|
||||
|
||||
# cut the cluster so that we have a centered surface
|
||||
cluster = cut_plane(cluster, z=eps)
|
||||
|
||||
# if the number of planes above the emitter's plane is smaller than it must be, recalculate n and ze
|
||||
# positions where atoms have the tag of the emitter_tag
|
||||
i = np.where(cluster.get_tags() == emitter_tag)
|
||||
|
||||
# an array of all unique z corresponding to where we have the right
|
||||
# atom's tag
|
||||
all_ze = np.sort(np.unique(np.round(cluster.get_positions()[:, 2][i], 4)))
|
||||
|
||||
# an array of all unique z
|
||||
all_z = np.sort(np.unique(np.round(cluster.get_positions()[:, 2], 4)))
|
||||
|
||||
# calculate the number of planes above the emitter's plane
|
||||
n = np.where(all_z == all_z.max())[0][0] - np.where(
|
||||
all_z == all_ze.max())[0][0]
|
||||
|
||||
# the height of the emitter's plane
|
||||
ze = all_ze.max()
|
||||
|
||||
# if the number of planes above the emitter's plane is smaller than it must
|
||||
# be, recalculate n and ze
|
||||
while n < emitter_plane:
|
||||
all_ze = all_ze[:-1]
|
||||
n = np.where(all_z == all_z.max())[0][0] - np.where(all_z == all_ze.max())[0][0]
|
||||
n = np.where(all_z == all_z.max())[0][0] - np.where(
|
||||
all_z == all_ze.max())[0][0]
|
||||
ze = all_ze.max()
|
||||
|
||||
# values of x and y of the emitter
|
||||
tx, ty = get_xypos(cluster, ze, symbol)
|
||||
|
||||
tx, ty = get_xypos(cluster, ze, symbol) # values of x and y of the emitter
|
||||
Atoms.translate(cluster, [-tx, -ty, 0]) # center the cluster on the emitter
|
||||
# center the cluster on the emitter
|
||||
Atoms.translate(cluster, [-tx, -ty, 0])
|
||||
|
||||
z_cut = all_z[np.where(all_z == all_ze.max())[0][0] + emitter_plane] # calculate where to cut to get the right number of planes above the emitter
|
||||
Atoms.translate(cluster, [0, 0, -z_cut]) # translate the surface at z=0
|
||||
cluster = cut_plane(cluster, z=eps) # cut the planes above those we want to keep
|
||||
# calculate where to cut to get the right number of planes above the
|
||||
# emitter
|
||||
z_cut = all_z[np.where(all_z == all_ze.max())[0][0] + emitter_plane]
|
||||
|
||||
# translate the surface at z=0
|
||||
Atoms.translate(cluster, [0, 0, -z_cut])
|
||||
|
||||
# cut the planes above those we want to keep
|
||||
cluster = cut_plane(cluster, z=eps)
|
||||
|
||||
radius = diameter/2
|
||||
if planes!=0:
|
||||
all_z = np.sort(np.unique(np.round(cluster.get_positions()[:, 2], 4))) # an array of all unique remaining z
|
||||
if planes != 0:
|
||||
# an array of all unique remaining z
|
||||
all_z = np.sort(np.unique(np.round(cluster.get_positions()[:, 2], 4)))
|
||||
|
||||
zplan = all_z[-planes]
|
||||
xplan, yplan = get_xypos(cluster, zplan)
|
||||
radius = np.sqrt(xplan**2 + yplan**2 + zplan**2)
|
||||
if diameter!=0:
|
||||
assert (radius <= diameter/2), "The number of planes is too high compared to the diameter."
|
||||
|
||||
if diameter != 0:
|
||||
assert (radius <= diameter/2), ("The number of planes is too high "
|
||||
"compared to the diameter.")
|
||||
radius = max(radius, diameter/2)
|
||||
|
||||
if shape in ('spherical'):
|
||||
cluster = cut_sphere(cluster, radius=radius + eps) # cut a sphere in our cluster with the diameter which is indicate in the parameters
|
||||
# cut a sphere in our cluster with the diameter which is indicate in
|
||||
# the parameters
|
||||
cluster = cut_sphere(cluster, radius=radius + eps)
|
||||
elif shape in ('cylindrical'):
|
||||
cluster = cut_cylinder(cluster, radius=radius + eps) # cut a sphere in our cluster with the diameter which is indicate in the parameters
|
||||
# cut a sphere in our cluster with the diameter which is indicate in
|
||||
# the parameters
|
||||
cluster = cut_cylinder(cluster, radius=radius + eps)
|
||||
else:
|
||||
raise NameError('Unkknown shape specifier: \"{}\"'.format(shape))
|
||||
|
||||
if planes!=0:
|
||||
zcut = np.sort(np.unique(np.round(cluster.get_positions()[:, 2], 4)))[::-1][planes-1] - eps # calculate where to cut to get the right number of planes
|
||||
cluster = cut_plane(cluster, z=zcut) # cut the right number of planes
|
||||
if planes != 0:
|
||||
# calculate where to cut to get the right number of planes
|
||||
positions = np.unique(np.round(cluster.get_positions()[:, 2], 4))
|
||||
zcut = np.sort(positions)[::-1][planes-1] - eps
|
||||
|
||||
all_z = np.sort(np.unique(np.round(cluster.get_positions()[:, 2], 4))) # an array of all unique remaining z
|
||||
assert emitter_plane < np.alen(all_z), "There are not enough existing plans."
|
||||
# cut the right number of planes
|
||||
cluster = cut_plane(cluster, z=zcut)
|
||||
|
||||
# an array of all unique remaining z
|
||||
all_z = np.sort(np.unique(np.round(cluster.get_positions()[:, 2], 4)))
|
||||
|
||||
assert emitter_plane < np.alen(all_z), ("There are not enough existing "
|
||||
"plans.")
|
||||
ze = all_z[- emitter_plane - 1] # the z-coordinate of the emitter
|
||||
Atoms.translate(cluster, [0, 0, -ze]) # put the emitter in (0,0,0)
|
||||
|
||||
|
|
|
@ -1,10 +1,33 @@
|
|||
# coding: utf-8
|
||||
# vim: set et sw=4 ts=4 sts=4 nu ai cc=+0 fdm=indent mouse=a:
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright © 2016-2020 - Rennes Physics Institute
|
||||
#
|
||||
# This file is part of msspec.
|
||||
#
|
||||
# msspec is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
# msspec is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this msspec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Source file : src/msspec/version.py
|
||||
# Last modified: ven. 10 avril 2020 17:34:38
|
||||
# Committed by : "Sylvain Tricot <sylvain.tricot@univ-rennes1.fr>"
|
||||
|
||||
|
||||
from setuptools_scm import get_version
|
||||
from pkg_resources import parse_version, DistributionNotFound, get_distribution
|
||||
import os
|
||||
|
||||
from pkg_resources import DistributionNotFound
|
||||
from pkg_resources import get_distribution
|
||||
from pkg_resources import parse_version
|
||||
from setuptools_scm import get_version
|
||||
|
||||
|
||||
# find the version number
|
||||
# 1- Try to read it from the git info
|
||||
# 2- If it fails, try to read it from the distribution file
|
||||
|
|
113
src/setup.py
113
src/setup.py
|
@ -1,22 +1,31 @@
|
|||
# coding: utf-8
|
||||
# vim: set fdm=indent ts=4 sw=4 sts=4 et tw=80 ai cc=+0 mouse=a nu :
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright © 2016-2020 - Rennes Physics Institute
|
||||
#
|
||||
# This file is part of msspec.
|
||||
#
|
||||
# msspec is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
from setuptools import setup, Extension, find_packages
|
||||
from distutils.file_util import copy_file
|
||||
# msspec is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
from distutils.command.build import build as _build
|
||||
from setuptools.command.build_ext import build_ext as _build_ext
|
||||
from setuptools.command.install import install as _install
|
||||
from distutils.command.clean import clean as _clean
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this msspec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Source file : src/setup.py
|
||||
# Last modified: mar. 07 avril 2020 17:01:42
|
||||
# Committed by : "Sylvain Tricot <sylvain.tricot@univ-rennes1.fr>"
|
||||
|
||||
import subprocess
|
||||
import traceback
|
||||
import os
|
||||
from setuptools import setup, find_packages
|
||||
from version import __version__
|
||||
import sys
|
||||
import glob
|
||||
sys.path.insert(0, "msspec")
|
||||
|
||||
from version import __version__
|
||||
|
||||
with open('setup_requirements.txt', 'r') as fd:
|
||||
SETUP_REQUIREMENTS = fd.read().strip().split('\n')
|
||||
|
@ -26,46 +35,46 @@ with open('requirements.txt', 'r') as fd:
|
|||
|
||||
if __name__ == "__main__":
|
||||
setup(name='msspec',
|
||||
version=__version__,
|
||||
include_package_data=True,
|
||||
packages=find_packages(include='msspec.*'),
|
||||
setup_requires=SETUP_REQUIREMENTS,
|
||||
install_requires=REQUIREMENTS,
|
||||
version=__version__,
|
||||
include_package_data=True,
|
||||
packages=find_packages(include='msspec.*'),
|
||||
setup_requires=SETUP_REQUIREMENTS,
|
||||
install_requires=REQUIREMENTS,
|
||||
|
||||
author='Didier Sébilleau, Sylvain Tricot',
|
||||
author_email='sylvain.tricot@univ-rennes1.fr',
|
||||
maintainer='Sylvain Tricot',
|
||||
maintainer_email='sylvain.tricot@univ-rennes1.fr',
|
||||
url='https://msspec.cnrs.fr',
|
||||
description=('A multiple scattering package for sepectroscopies using '
|
||||
'electrons to probe materials'),
|
||||
long_description="""MsSpec is a Fortran package to compute the
|
||||
cross-section of several spectroscopies involving one (or more)
|
||||
electron(s) as the probe. This package provides a python interface to
|
||||
control all the steps of the calculation.
|
||||
author='Didier Sébilleau, Sylvain Tricot',
|
||||
author_email='sylvain.tricot@univ-rennes1.fr',
|
||||
maintainer='Sylvain Tricot',
|
||||
maintainer_email='sylvain.tricot@univ-rennes1.fr',
|
||||
url='https://msspec.cnrs.fr',
|
||||
description=('A multiple scattering package for sepectroscopies '
|
||||
'using electrons to probe materials'),
|
||||
long_description="""MsSpec is a Fortran package to compute the
|
||||
cross-section of several spectroscopies involving one (or more)
|
||||
electron(s) as the probe. This package provides a python interface to
|
||||
control all the steps of the calculation.
|
||||
|
||||
Available spectroscopies:
|
||||
* Photoelectron diffraction
|
||||
* Auger electron diffraction
|
||||
* Low energy electron diffraction
|
||||
* X-Ray absorption spectroscopy
|
||||
* Auger Photoelectron coincidence spectroscopy
|
||||
* Computation of the spectral radius""",
|
||||
download_url='https://msspec.cnrs.fr/downloads.html',
|
||||
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||
classifiers=[
|
||||
'Development Status :: 3 - Alpha',
|
||||
'Environment :: Console',
|
||||
'Intended Audience :: Science/Research',
|
||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||
'Natural Language :: English',
|
||||
'Operating System :: Microsoft :: Windows :: Windows 10',
|
||||
'Operating System :: POSIX :: Linux',
|
||||
'Operating System :: MacOS :: MacOS X',
|
||||
'Programming Language :: Fortran',
|
||||
'Programming Language :: Python :: 3 :: Only',
|
||||
'Topic :: Scientific/Engineering :: Physics',
|
||||
Available spectroscopies:
|
||||
* Photoelectron diffraction
|
||||
* Auger electron diffraction
|
||||
* Low energy electron diffraction
|
||||
* X-Ray absorption spectroscopy
|
||||
* Auger Photoelectron coincidence spectroscopy
|
||||
* Computation of the spectral radius""",
|
||||
download_url='https://msspec.cnrs.fr/downloads.html',
|
||||
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||
classifiers=[
|
||||
'Development Status :: 3 - Alpha',
|
||||
'Environment :: Console',
|
||||
'Intended Audience :: Science/Research',
|
||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||
'Natural Language :: English',
|
||||
'Operating System :: Microsoft :: Windows :: Windows 10',
|
||||
'Operating System :: POSIX :: Linux',
|
||||
'Operating System :: MacOS :: MacOS X',
|
||||
'Programming Language :: Fortran',
|
||||
'Programming Language :: Python :: 3 :: Only',
|
||||
'Topic :: Scientific/Engineering :: Physics',
|
||||
],
|
||||
keywords='spectroscopy atom electron photon multiple scattering',
|
||||
license='GPL',
|
||||
keywords='spectroscopy atom electron photon multiple scattering',
|
||||
license='GPL',
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue