public release 4.2.0 - see README.md and CHANGES.md for details
This commit is contained in:
@@ -1,44 +0,0 @@
|
||||
SHELL=/bin/sh
|
||||
|
||||
# makefile for PHAGEN program and module
|
||||
#
|
||||
# the PHAGEN source code is not included in the public distribution.
|
||||
# please obtain the PHAGEN code from the original author,
|
||||
# and copy it to this directory before compilation.
|
||||
#
|
||||
# see the top-level makefile for additional information.
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .cpp .cxx .exe .f .h .i .o .py .pyf .so
|
||||
.PHONY: all clean phagen
|
||||
|
||||
FC?=gfortran
|
||||
FCOPTS?=-std=legacy
|
||||
F2PY?=f2py
|
||||
F2PYOPTS?=--f77flags=-std=legacy --f90flags=-std=legacy
|
||||
CC?=gcc
|
||||
CCOPTS?=
|
||||
SWIG?=swig
|
||||
SWIGOPTS?=
|
||||
PYTHON?=python
|
||||
PYTHONOPTS?=
|
||||
PYTHONINC?=
|
||||
PYTHON_CONFIG = ${PYTHON}-config
|
||||
PYTHON_CFLAGS ?= $(shell ${PYTHON_CONFIG} --cflags)
|
||||
PYTHON_EXT_SUFFIX ?= $(shell ${PYTHON_CONFIG} --extension-suffix)
|
||||
|
||||
all: phagen
|
||||
|
||||
phagen: phagen.exe phagen$(PYTHON_EXT_SUFFIX)
|
||||
|
||||
phagen.exe: phagen_scf.f msxas3.inc msxasc3.inc
|
||||
$(FC) $(FCOPTS) -o phagen.exe phagen_scf.f
|
||||
|
||||
phagen.pyf: | phagen_scf.f
|
||||
$(F2PY) -h phagen.pyf -m phagen phagen_scf.f only: libmain
|
||||
|
||||
phagen$(PYTHON_EXT_SUFFIX): phagen_scf.f phagen.pyf msxas3.inc msxasc3.inc
|
||||
$(F2PY) -c $(F2PYOPTS) -m phagen phagen.pyf phagen_scf.f
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o *.exe
|
||||
@@ -1,102 +0,0 @@
|
||||
--- phagen_scf.orig.f 2019-06-05 16:45:52.977855859 +0200
|
||||
+++ phagen_scf.f 2019-05-09 16:32:35.790286429 +0200
|
||||
@@ -174,6 +174,99 @@
|
||||
1100 format(//,1x,' ** phagen terminated normally ** ',//)
|
||||
end
|
||||
|
||||
+
|
||||
+c-----------------------------------------------------------------------
|
||||
+ subroutine libmain(infile,outfile,etcfile)
|
||||
+c main calculation routine
|
||||
+c entry point for external callers
|
||||
+c
|
||||
+c infile: name of parameter input file
|
||||
+c
|
||||
+c outfile: base name of output files
|
||||
+c output files with endings .list, .clu, .pha, .tl, .rad
|
||||
+c will be created
|
||||
+c-----------------------------------------------------------------------
|
||||
+ implicit real*8 (a-h,o-z)
|
||||
+c
|
||||
+ include 'msxas3.inc'
|
||||
+ include 'msxasc3.inc'
|
||||
+
|
||||
+ character*60 infile,outfile,etcfile
|
||||
+ character*70 listfile,clufile,tlfile,radfile,phafile
|
||||
+
|
||||
+c
|
||||
+c.. constants
|
||||
+ antoau = 0.52917715d0
|
||||
+ pi = 3.141592653589793d0
|
||||
+ ev = 13.6058d0
|
||||
+ zero = 0.d0
|
||||
+c.. threshold for linearity
|
||||
+ thresh = 1.d-4
|
||||
+c.. fortran io units
|
||||
+ idat = 5
|
||||
+ iwr = 6
|
||||
+ iphas = 30
|
||||
+ iedl0 = 31
|
||||
+ iwf = 32
|
||||
+ iof = 17
|
||||
+
|
||||
+ iii=LnBlnk(outfile)+1
|
||||
+ listfile=outfile
|
||||
+ listfile(iii:)='.list'
|
||||
+ clufile=outfile
|
||||
+ clufile(iii:)='.clu'
|
||||
+ phafile=outfile
|
||||
+ phafile(iii:)='.pha'
|
||||
+ tlfile=outfile
|
||||
+ tlfile(iii:)='.tl'
|
||||
+ radfile=outfile
|
||||
+ radfile(iii:)='.rad'
|
||||
+
|
||||
+ open(idat,file=infile,form='formatted',status='old')
|
||||
+ open(iwr,file=listfile,form='formatted',status='unknown')
|
||||
+ open(10,file=clufile,form='formatted',status='unknown')
|
||||
+ open(35,file=tlfile,form='formatted',status='unknown')
|
||||
+ open(55,file=radfile,form='formatted',status='unknown')
|
||||
+ open(iphas,file=phafile,form='formatted',status='unknown')
|
||||
+
|
||||
+ open(iedl0,form='unformatted',status='scratch')
|
||||
+ open(iof,form='unformatted',status='scratch')
|
||||
+ open(unit=21,form='unformatted',status='scratch')
|
||||
+ open(60,form='formatted',status='scratch')
|
||||
+ open(50,form='formatted',status='scratch')
|
||||
+ open(unit=13,form='formatted',status='scratch')
|
||||
+ open(unit=14,form='formatted',status='scratch')
|
||||
+ open(unit=11,status='scratch')
|
||||
+ open(unit=iwf,status='scratch')
|
||||
+ open(unit=33,status='scratch')
|
||||
+ open(unit=66,status='scratch')
|
||||
+
|
||||
+ call inctrl
|
||||
+ call intit(iof)
|
||||
+ call incoor
|
||||
+ call calphas
|
||||
+
|
||||
+ close(idat)
|
||||
+ close(iwr)
|
||||
+ close(10)
|
||||
+ close(35)
|
||||
+ close(55)
|
||||
+ close(iphas)
|
||||
+ close(iedl0)
|
||||
+ close(iof)
|
||||
+ close(60)
|
||||
+ close(50)
|
||||
+ close(13)
|
||||
+ close(14)
|
||||
+ close(11)
|
||||
+ close(iwf)
|
||||
+ close(33)
|
||||
+ close(66)
|
||||
+ close(21)
|
||||
+
|
||||
+ endsubroutine
|
||||
+
|
||||
+
|
||||
subroutine inctrl
|
||||
implicit real*8 (a-h,o-z)
|
||||
include 'msxas3.inc'
|
||||
@@ -2,33 +2,41 @@
|
||||
@package pmsco.calculators.phagen.runner
|
||||
Natoli/Sebilleau PHAGEN interface
|
||||
|
||||
this module runs the PHAGEN program to calculate scattering factors and radial matrix element.
|
||||
This module runs the PHAGEN program to calculate scattering factors and radial matrix elements.
|
||||
|
||||
Requires PHAGEN version 2.2 from https://git.ipr.univ-rennes.fr/epsi/msspec_python3.git (contained in subprojects).
|
||||
|
||||
@author Matthias Muntwiler
|
||||
|
||||
@copyright (c) 2015-19 by Paul Scherrer Institut @n
|
||||
@copyright (c) 2015-23 by Paul Scherrer Institut @n
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); @n
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
from pmsco.calculators.calculator import AtomicCalculator
|
||||
from pmsco.calculators.phagen.phagen import libmain
|
||||
|
||||
from pmsco.calculators.phagen.translator import Translator
|
||||
import pmsco.cluster
|
||||
from pmsco.helpers import stdout_redirected
|
||||
import pmsco.project
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
import phagen
|
||||
except (ImportError, ModuleNotFoundError) as e:
|
||||
phagen = None
|
||||
logger.critical("Error importing the phagen package.", exc_info=e)
|
||||
|
||||
|
||||
class PhagenCalculator(AtomicCalculator):
|
||||
"""
|
||||
@@ -37,7 +45,11 @@ class PhagenCalculator(AtomicCalculator):
|
||||
this produces scatterer, radial matrix element and cluster files for EDAC.
|
||||
"""
|
||||
|
||||
def run(self, params, cluster, scan, output_file):
|
||||
def run(self,
|
||||
params: pmsco.project.CalculatorParams,
|
||||
cluster: pmsco.cluster.Cluster,
|
||||
scan: pmsco.project.Scan,
|
||||
output_file: str):
|
||||
"""
|
||||
create the input file, run PHAGEN, and translate the output to EDAC format.
|
||||
|
||||
@@ -85,19 +97,16 @@ class PhagenCalculator(AtomicCalculator):
|
||||
phagen_cluster = pmsco.cluster.Cluster()
|
||||
|
||||
files = {}
|
||||
prev_wd = os.getcwd()
|
||||
prev_wd = Path.cwd()
|
||||
try:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
os.chdir(temp_dir)
|
||||
os.mkdir("div")
|
||||
os.mkdir("div/wf")
|
||||
os.mkdir("plot")
|
||||
os.mkdir("data")
|
||||
|
||||
# prepare input for phagen
|
||||
infile = "phagen.in"
|
||||
outfile = "phagen.out"
|
||||
temp_path = Path(temp_dir)
|
||||
in_path = temp_path / "input"
|
||||
in_path.mkdir(exist_ok=True)
|
||||
out_path = temp_path / "output"
|
||||
out_path.mkdir(exist_ok=True)
|
||||
|
||||
infile = in_path / "input.ms"
|
||||
try:
|
||||
transl.write_input(infile)
|
||||
report_infile = os.path.join(prev_wd, output_file + ".phagen.in")
|
||||
@@ -106,12 +115,22 @@ class PhagenCalculator(AtomicCalculator):
|
||||
except IOError:
|
||||
logger.warning("error writing phagen input file {fi}.".format(fi=infile))
|
||||
|
||||
# call phagen
|
||||
libmain(infile, outfile)
|
||||
report_listfile = os.path.join(prev_wd, output_file + ".phagen.list")
|
||||
files[report_listfile] = "log"
|
||||
|
||||
# call phagen, redirect stdout (unit 6)
|
||||
os.chdir(out_path)
|
||||
with open(report_listfile, "wb") as f:
|
||||
with stdout_redirected(f):
|
||||
phagen.phagen()
|
||||
|
||||
phafile = out_path / "div" / "phases.dat"
|
||||
radfile = out_path / "fort.55"
|
||||
# tlfile = out_path / "fort.35"
|
||||
clufile = out_path / "clus" / "clus.out"
|
||||
|
||||
# collect results
|
||||
try:
|
||||
phafile = outfile + ".pha"
|
||||
transl.parse_phagen_phase(phafile)
|
||||
report_phafile = os.path.join(prev_wd, output_file + ".phagen.pha")
|
||||
shutil.copy(phafile, report_phafile)
|
||||
@@ -120,7 +139,6 @@ class PhagenCalculator(AtomicCalculator):
|
||||
logger.error("error loading phagen phase file {fi}".format(fi=phafile))
|
||||
|
||||
try:
|
||||
radfile = outfile + ".rad"
|
||||
transl.parse_radial_file(radfile)
|
||||
report_radfile = os.path.join(prev_wd, output_file + ".phagen.rad")
|
||||
shutil.copy(radfile, report_radfile)
|
||||
@@ -129,31 +147,23 @@ class PhagenCalculator(AtomicCalculator):
|
||||
logger.error("error loading phagen radial file {fi}".format(fi=radfile))
|
||||
|
||||
try:
|
||||
clufile = outfile + ".clu"
|
||||
phagen_cluster.load_from_file(clufile, pmsco.cluster.FMT_PHAGEN_OUT)
|
||||
except IOError:
|
||||
logger.error("error loading phagen cluster file {fi}".format(fi=clufile))
|
||||
|
||||
try:
|
||||
listfile = outfile + ".list"
|
||||
report_listfile = os.path.join(prev_wd, output_file + ".phagen.list")
|
||||
shutil.copy(listfile, report_listfile)
|
||||
files[report_listfile] = "log"
|
||||
except IOError:
|
||||
logger.error("error loading phagen list file {fi}".format(fi=listfile))
|
||||
|
||||
finally:
|
||||
os.chdir(prev_wd)
|
||||
|
||||
# write edac files
|
||||
scatfile = output_file + "_{}.scat"
|
||||
scatfiles = transl.write_edac_scattering(scatfile)
|
||||
params.phase_files = {c: scatfiles[c] for c in scatfiles}
|
||||
files.update({scatfiles[c]: "atomic" for c in scatfiles})
|
||||
params.phase_files = scatfiles.copy()
|
||||
files.update({f: "atomic" for f in params.phase_files.values()})
|
||||
|
||||
rmefile = output_file + ".rme"
|
||||
transl.write_edac_emission(rmefile)
|
||||
files[rmefile] = "atomic"
|
||||
rmefile = output_file + "_{}.rme"
|
||||
rmefiles = transl.write_edac_emission(rmefile)
|
||||
params.rme_files = rmefiles.copy()
|
||||
files.update({f: "atomic" for f in params.rme_files.values()})
|
||||
|
||||
cluster.update_atoms(phagen_cluster, {'c'})
|
||||
clufile = output_file + ".pmsco.clu"
|
||||
|
||||
@@ -13,14 +13,12 @@ Licensed under the Apache License, Version 2.0 (the "License"); @n
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import logging
|
||||
import numpy as np
|
||||
|
||||
from pmsco.cluster import Cluster
|
||||
from pmsco.compat import open
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
## rydberg energy in electron volts
|
||||
ERYDBERG = 13.6056923
|
||||
@@ -59,7 +57,7 @@ class TranslationParams(object):
|
||||
self.initial_state = "1s"
|
||||
self.binding_energy = 0.
|
||||
self.cluster = None
|
||||
self.kinetic_energies = np.empty(0, dtype=np.float)
|
||||
self.kinetic_energies = np.empty(0, dtype=float)
|
||||
|
||||
@property
|
||||
def l_init(self):
|
||||
@@ -287,7 +285,7 @@ class Translator(object):
|
||||
self.write_cluster(f)
|
||||
self.write_ionicity(f)
|
||||
else:
|
||||
with open(f, "w") as fi:
|
||||
with open(f, "wt", encoding="latin1") as fi:
|
||||
self.write_input(fi)
|
||||
|
||||
def parse_phagen_phase(self, f):
|
||||
@@ -392,7 +390,7 @@ class Translator(object):
|
||||
f.write(" 0 0")
|
||||
f.write("\n")
|
||||
else:
|
||||
with open(f, "w") as fi:
|
||||
with open(f, "wt", encoding="latin1") as fi:
|
||||
self.write_edac_scattering_file(fi, scat)
|
||||
|
||||
def write_edac_phase_file(self, f, scat):
|
||||
@@ -426,26 +424,36 @@ class Translator(object):
|
||||
f.write(" 0")
|
||||
f.write("\n")
|
||||
else:
|
||||
with open(f, "w") as fi:
|
||||
with open(f, "wt", encoding="latin1") as fi:
|
||||
self.write_edac_phase_file(fi, scat)
|
||||
|
||||
def parse_radial_file(self, f):
|
||||
"""
|
||||
parse the radial matrix element output file from phagen.
|
||||
parse the radial matrix element output file from phagen version 2.2.
|
||||
|
||||
the file contains 7 header lines and one data line per requested energy.
|
||||
the data line contains real and imaginary parts of the matrix elements.
|
||||
the first four columns contain the electric dipole transitions Rd(li --> li - 1) and Rd(li --> li + 1),
|
||||
followed by higher orders that we do not use here.
|
||||
|
||||
@param f: file or path (any file-like or path-like object that can be passed to numpy.genfromtxt).
|
||||
|
||||
@return: None
|
||||
|
||||
@raise ValueError if the file is in a wrong format.
|
||||
"""
|
||||
dt = [('ar', 'f8'), ('ai', 'f8'), ('br', 'f8'), ('bi', 'f8')]
|
||||
data = np.atleast_1d(np.genfromtxt(f, dtype=dt))
|
||||
data = np.atleast_2d(np.genfromtxt(f, skip_header=7))
|
||||
if data.shape[0] != self.params.kinetic_energies.shape[0] or data.shape[1] < 4:
|
||||
raise ValueError(f"Unexpected array size of Phagen radial matrix elements output: "
|
||||
f"expected ({self.params.kinetic_energies.shape[0]}, >= 4), received {data.shape}")
|
||||
|
||||
self.emission = np.resize(self.emission, data.shape)
|
||||
self.emission = np.resize(self.emission, data.shape[0:1])
|
||||
emission = self.emission
|
||||
emission['dw'] = data['ar'] + 1j * data['ai']
|
||||
emission['up'] = data['br'] + 1j * data['bi']
|
||||
emission['e'] = self.params.kinetic_energies
|
||||
emission['dw'] = data[:, 0] + 1j * data[:, 1]
|
||||
emission['up'] = data[:, 2] + 1j * data[:, 3]
|
||||
|
||||
def write_edac_emission(self, f):
|
||||
def write_edac_emission_file(self, f):
|
||||
"""
|
||||
write the radial photoemission matrix element in EDAC format.
|
||||
|
||||
@@ -472,5 +480,24 @@ class Translator(object):
|
||||
f.write(" {0:.6f} {1:.6f}".format(item['dw'].real, item['dw'].imag))
|
||||
f.write("\n")
|
||||
else:
|
||||
with open(f, "w") as of:
|
||||
self.write_edac_emission(of)
|
||||
with open(f, "wt", encoding="latin1") as of:
|
||||
self.write_edac_emission_file(of)
|
||||
|
||||
def write_edac_emission(self, filename_format):
|
||||
"""
|
||||
write the radial photoemission matrix element in EDAC format.
|
||||
|
||||
requires self.scattering, self.emission, self.params.kinetic_energies and self.params.initial_state.
|
||||
|
||||
@param filename_format: file name including, optionally, a placeholder {} for the atom class.
|
||||
since phagen calculates only one emitter, the placeholder is not necessary.
|
||||
|
||||
@return: dictionary that maps atom classes to file names.
|
||||
since phagen calculates only one emitter, this dictionary will contain just one entry.
|
||||
"""
|
||||
scat = self.scattering
|
||||
atom = scat['a'][0]
|
||||
f = filename_format.format(atom)
|
||||
self.write_edac_emission_file(f)
|
||||
files = {atom: f}
|
||||
return files
|
||||
|
||||
Reference in New Issue
Block a user