Feff6 Development
This page describes some ideas for re-engineering the input/output of Feff6 to make it more flexible. The main goals are
- Replace the pathfinder to be able to better model distortions. This mainly means not 'forgetting' geometries for degenerate paths. Practically, it also means rewriting it in something non-Fortran. Bruce is tackling this aspect.
- Make it possible to call Genfmt with a distorted path, as from within the fitting loop of Ifeffit.
Eliminate annoying dependencies on hardwired file names such as feff.inp, paths.dat, etc so that calculations can be better managed.
- Simplify the input, including making it easier to move the atomic coordinates to/from other formats and molecular viewers.
- Allow a SWIG-ed and/or Ifeffit-callable version.
Status Report on implementing these changes
Current Layout of Feff6
The Feff6 program layout is approximately:
rdinp: read feff.inp: Goal: replace with outer scripting language
- passes many parameters in arg list mostly scalar params puts polarization data in common block (??) writes temporary output files geom.dat, potph.dat, paths.dat
- geom.dat: subroutine paths, deleted by feff(main)??
- paths.dat: subroutine pathsd, subroutine gemfmt
- potph.dat: subroutine potph deleted by feff(main)??
- passes many parameters in arg list mostly scalar params puts polarization data in common block (??) writes temporary output files geom.dat, potph.dat, paths.dat
potph potentials calc
- uses common blocks: const.h, dim.h (relatively harmless) array.h -- no other routine uses this??
- reads potph.dat writes misc.dat (useless??) writes phase.bin
paths pathfinder
- reads geom.dat writes paths.dat OK, doesn't matter so much -- we'll replace it
genfmt for xafs path calc
- reads phase.bin reads paths.dat writes feff.bin / feffNNNN.dat writes files.dat writes nstar.dat
- uses many common block, but AFAIK all internally (except pola.h!!): const.h dim.h clmz.h fmatrx.h lambda.h pdata.h nlm.h rotmat.h vers.h pola.h
Proposed Changes to Feff6
This discusses the proposed changes to make feff6 more modular
Overall Changes
- Remove all 'hardwired' file names 'feff.inp', 'phase.bin', 'paths.dat', etc, and pass in file names where needed. We also get rid of the temporary files such as geom.dat and potph.dat.
- Pathfinder dropped in favor of some non-Fortran version.
- The needed modules are then:
Potentials (pot): atoms/potentials list -> phase.bin
Pathfinder : atoms list -> path list
GenFMT (genfmt): phase.bin + path data -> chi_path(k)
Input Structure (replace feff.inp)
Replace feff.inp with an input file as follows:
- remove need for explicit potentials list, and simply list
- Atomic Positions as x,y,z, atomic number, [ipot] , [tag] something like
iz x y z [ipot] [tag]
- or
sym x y z [ipot] [tag]
I'd recommend using an established format like XYZ or at least a format that is easily converted to one of these (say, by stripping trailing words). These two formats start with a single line title, and the number of atoms listed -- fine by me. The ipot should be optional, and automatically determined from the Atomic Number/Symbol. If ipot=0 isn't explicitly specified, the first atom listed would be the central atom.
With the potentials list gone, the atomic coordinates in a separate file, and no Pathfinder, the needed inputs are:
- Edge / Hole
- Rmax
- Exchange Model, vi, vr.
- Polarization vector / Ellipticity
- Name of Geometry (XYZ) file
- Name of Potentials file to use
These are now small enough to pass directly into the Potentials Calc For a 'standalone executable', a feff.inp could look like:
Title XXX
Hole K
Rmax 6.0
Exchange HL 0 0
Polarization 1.0 0.0 0.0
Geometry MyStructure.xyz
I'm not commited to this syntax, but it seems reasonable. As an aside, this is a simple enough to have 'feff_potentials()' and 'genfmt()' be ifeffit commands....
Potentials Calc
This is actually pretty clean, and I'd propose to make few changes except I/O. That is, have the Fortran call look like:
subroutine potentials(geom_file_name, hole, exchange_model, vr, vi, pot_filename)
and have the output be one file specified by pot_filename (say, Potentials.bin). This would be largely unchanged from the existing version, except using PAD format for portability.
Pathfinder
I'd propose the output be simpler than the current paths.dat, and simply list iz,x,y,z,[ipot] for each non-central atom in the path. Again, I think ipot can be optional. So something like:
0 29 0. 0. 0. # That is, the central atom
1 8 1. 1. 1. # SS
2 8 -1. 1. 1. # Another SS
3 8 1. 1. 1. 8 -1. 1. 1. # Triangle
That's just a suggestion (this doesn't include any tags, for example). I think the goal should be simplicity, and there's no need to include any angular info (GenFMT can do that).
Chi(k) Calc (GenFMT)
This has fairly substantial changes. I propose breaking this into three routines:
- GenFMT_init (to set potentials data, polarization data)
- GenFMT_path (to calculate chi(k) for a path)
- GenFMT_out (to write feff.dat)
GenFMT_init(potential_file, pol_vec, ellip_vec)
This sets up for later chi(k) calcs.
I propose a minor change to polarization / ellipticity so that pol_vector was the major axis, and ellip_vector was the minor axis of the polarization ellipse
GenFMT_path(ipot_vec, x_vec, y_vec, z_vec, nlegs, kout, ampout, phaseout)
- ipot_vec, x_vec, y_vec, z_vec each on length nlegs, giving ipot, x, y, z for all atoms in path.
- kout, ampout, phaseout are output |chi(k)|, phase(k)
- This could be used inside a feffit loop.....
GenFMT_out(path_index, ipot_vec, x_vec, y_vec, z_vec, nlegs, k, amp, phase)
- here all args are input, and the output is to write a feffNNNN.dat
Note that neither GenFMT_init nor GenFMT_path actually read the paths data.... an outer loop will do that, either in Fortran (for the standalone executable) or Ifeffit or Artemis.
subroutine genfmt_main(potentials_file, paths_file, pol_vec, ellip_vec)
GenFMT_init(potentials_file, pol_vec, ellip_vec)
open(paths.dat)
read central_atom
loop over lines in paths.dat:
read path_data
create ipot, x, y, z arrays
GenFMT_path(ipot,x,y,z, k, amp, phase)
GenFMT_out(index, ipot,x,y,z, k, amp, phase)
end loop
API
SWIG-exposed routines should probably include:
ReadXYZ to read the XYZ geometry file and assign IPOTS. That is, it may be better to have a single routine that does this so that results are known to be self-consistent.
GenFMT_init to read Potentials.bin, set polarization vector
PlaneWaveCrit to calculate the Plane Wave Zabinsky factor for a given path. Would need to be called after GenFMT_init
GenFMT_path to calculate chi(k) amplitude and phase for a path.
These may be a little more complicated (ie, more arguments) than the Ifeffit API, but not hard.
Issues
I think the main issues with this change are:
- possible lack of functionality, especially wrt Potentials options(no AFOLP, NOHOLE, etc). I think this is worth it.
- handling of polarization is now more explicit, but clearer.