(Demeter main page) (Cookbook main page)
| /AtomsAndFeff /DataHandling /Fitting /PlottingAndConfiguration |
Atoms and Feff
The Atoms and Feff interfaces are evolving in Demeter. Their features and interfaces are subject to change.
Contents
How do I run Atoms using Demeter?
This script replicates almost all the functionality of any prior version of Atoms.
1 #!/usr/bin/perl
2 use Ifeffit::Demeter qw(Atoms);
3
4 my $atoms = Ifeffit::Demeter::Atoms->new();
5 $atoms->read_inp("ybco.inp");
6 print $atoms->Write("feff6");
It's that simple. A Feff6 input file will be written to standard output.
At this moment, Demeter is not reading CIF files, but that is a small chore. When CIF import is supported, Demeter will figure out the input format seamlessly.
Output files are formed using templates. Currently templates exist for feff6, feff7, feff8, absorption, and atoms. The argument to the Write method chooses the output template.
In the future, OpenBabel will be used to write other output formats, such as Protein Data Bank, Alchemy, and so on. If you need one of those immediately, it would be simple to write a new template.
How do I run Feff using Demeter?
See Demeter/Feff for an overview of Demeter's interface with Feff.
This script reads a Feff input file, computes the potentials, runs the path finder, and serializes the results to a file. Although this example reads a file actually called feff.inp, the Feff input file need not actually be called that (which is a huge improvement over old skool Feff!)
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4 use Ifeffit::Demeter;
5 use aliased 'Ifeffit::Demeter::Feff';
6
7 my $feff = Feff -> new();
8 $feff->set({workspace=>"pf", screen=>1, buffer=>q{}, save=>1});
9
10 $feff -> rdinp("feff.inp") -> potentials();
11 $feff -> pathfinder;
12
13 ### Freezing this cluster+pathlist to a YAML
14 $feff->freeze("feff.yaml");
Here is the screen output of this script. The first few lines are familiar to anyone who has ever run Feff. Only the first part of Feff is run -- the part that computes the potentials and writes the phase.bin file. The lines starting with equals signs are the progress messages of the path finder.
Feff 6L.02 Copper example Calculating potentials and phases... free atom potential and density for atom type 0 free atom potential and density for atom type 1 overlapped potential and density for unique potential 0 overlapped potential and density for unique potential 1 muffin tin radii and interstitial parameters phase shifts for unique potential 0 phase shifts for unique potential 1 Feff done. Have a nice day. === Cluster contains 86 atoms === Populating Tree (contains 949 nodes from the 55 atoms within 5.2 Ang.) === Traversing Tree and populating Heap (contains 750 elements) === Collapsing Heap to a degenerate list (found 23 unique paths)
At the end, the state of the Feff calculation is written to the file feff.yaml. This is a text file in the YAML format. This file is used to do things with the results of the path finder calculation.
Writing an interpretation of the Feff calculation
This script writes an interpretation of the Feff calculation which is rather like the one presented in Artemis.
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4 use Ifeffit::Demeter;
5
6 ## Deserializing feff.yaml;
7 my $feff = Ifeffit::Demeter::Feff -> thaw("feff.yaml");
8 print $feff->intrp;
# Copper example # This paths.dat file was written by Demeter 0.0.1 # The central atom is denoted by this token: <+> # Cluster size = 5.20000 Angstroms, containing 86 atoms # 23 paths were found # Forward scattering cutoff 20.00 # Distance fuzz = 0.0100 Angstroms # Angle fuzz = 3.0000 degrees # Suppressing eta: yes # ------------------------------------------------------------------------------- # degen Reff scattering path I legs type 0001 12 2.553 ---- <+> Cu_1 <+> 2 2 single scattering 0002 6 3.610 ---- <+> Cu_2 <+> 2 2 single scattering 0003 48 3.829 ---- <+> Cu_1 Cu_1 <+> 1 3 acute triangle 0004 24 4.358 ---- <+> Cu_1 Cu_1 <+> 0 3 other double scattering 0005 48 4.358 ---- <+> Cu_1 Cu_2 <+> 0 3 other double scattering 0006 24 4.421 ---- <+> Cu_3 <+> 2 2 single scattering 0007 48 4.763 ---- <+> Cu_1 Cu_1 <+> 1 3 obtuse triangle 0008 96 4.763 ---- <+> Cu_1 Cu_3 <+> 1 3 obtuse triangle 0009 12 5.105 ---- <+> Cu_4 <+> 2 2 single scattering 0010 12 5.105 ---- <+> Cu_1 Cu_1 <+> 2 3 non-forward linear 0011 24 5.105 ---- <+> Cu_1 Cu_4 <+> 2 3 forward scattering 0012 12 5.105 ---- <+> Cu_1 <+> Cu_1 <+> 2 4 forward through absorber 0013 12 5.105 ---- <+> Cu_1 Cu_4 Cu_1 <+> 2 4 double forward scattering 0014 48 5.105 ---- <+> Cu_1 <+> Cu_1 <+> 0 4 hinge 0015 48 5.105 ---- <+> Cu_1 Cu_1 Cu_1 <+> 0 4 dog-leg 0016 48 5.105 ---- <+> Cu_1 Cu_1 Cu_1 <+> 0 4 other triple scattering 0017 48 5.105 ---- <+> Cu_1 Cu_3 Cu_1 <+> 1 4 obtuse triangle 0018 12 5.105 ---- <+> Cu_1 <+> Cu_1 <+> 1 4 rattle 0019 48 5.105 ---- <+> Cu_1 <+> Cu_1 <+> 0 4 hinge 0020 48 5.105 ---- <+> Cu_1 Cu_3 Cu_1 <+> 0 4 dog-leg 0021 24 5.105 ---- <+> Cu_1 <+> Cu_1 <+> 0 4 hinge 0022 24 5.105 ---- <+> Cu_1 Cu_2 Cu_1 <+> 0 4 dog-leg 0023 24 5.105 ---- <+> Cu_1 Cu_2 Cu_1 <+> 0 4 other triple scattering
Some new information (compared to Artemis) is available in this interpretation. Demeter uses heuristics to make a guess about which paths are significant. The Importance column displays this guess. Paths with an importance of 2 probably cannot be ignored. These tend to be single scattering paths and colinear or nearly colinear multiple scattering paths. Paths with an importance of 1 include various triangles and four legged paths that "rattle" between the absorber and one other atoms. These may or may not be important. Paths with 0 importance probably do not carry significant spectral weight. Please not that these evaluations are determined by heuristics. I try to be conservative, preferring false positives to false negatives. You should always check your paths.
At the end of each line is a description of the paths geometry which, hopefully, will help you visualize the structure of the path.
Writing a paths.dat file and running genfmt
This script finishes off the Feff calculation in a way that closely resembles the normal behavior of Feff. Demeter writes a paths.dat file (line 13) then runs Feff's genfmt segment (line 16) which writes out the feffNNNN.dat files.
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4 use Ifeffit::Demeter;
5
6 ## Deserializing feff.yaml;
7 my $feff = Ifeffit::Demeter::Feff -> thaw("feff.yaml");
8
9 $feff->pathsdat(); # all paths
10 #$feff->pathsdat(1,2,6,9); # the first four SS paths
11
12 $feff->genfmt;
The genfmt output can be controlled using the argument of the pathsdat method, which is a list of path indeces. (See line 14, which is commented out.) Only those paths will be written to feffNNNN.dat files by genfmt since only those paths will be listed in the paths.dat file.
Examining the geometries contributing to the degeneracy of a path
One of the features of Demeter's path finder is that it remembers the scattering geometries of every degenerate path. This is demonstrated in this script, which writes out the guts of a paths.dat file with one entry for each of the degenerate paths.
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4 use Ifeffit::Demeter;
5
6 ## Deserializing feff.yaml;
7 my $feff = Ifeffit::Demeter::Feff -> thaw("feff.yaml");
8 my @list_of_paths = $feff->pathlist;
9
10 ### The 6 scattering geometries that contribute to path #2:
11 my $sp = $list_of_paths[1];
12 my $j=1000;
13 foreach my $s ($sp->all_strings) {
14 print $sp -> pathsdat({index=>++$j, string=>$s, angles=>1});
15 };
Here is what gets printed:
### Here are the 6 scattering geometries that contribute to path #2: 1001 2 6.000 index, nleg, degeneracy, r= 3.6100 x y z ipot label rleg beta eta 3.610000 0.000000 0.000000 1 'Cu_2 ' 3.6100 180.0000 0.0000 0.000000 0.000000 0.000000 0 'abs ' 3.6100 180.0000 0.0000 1002 2 6.000 index, nleg, degeneracy, r= 3.6100 x y z ipot label rleg beta eta -3.610000 0.000000 0.000000 1 'Cu_2 ' 3.6100 180.0000 0.0000 0.000000 0.000000 0.000000 0 'abs ' 3.6100 180.0000 0.0000 1003 2 6.000 index, nleg, degeneracy, r= 3.6100 x y z ipot label rleg beta eta 0.000000 3.610000 0.000000 1 'Cu_2 ' 3.6100 180.0000 0.0000 0.000000 0.000000 0.000000 0 'abs ' 3.6100 180.0000 0.0000 1004 2 6.000 index, nleg, degeneracy, r= 3.6100 x y z ipot label rleg beta eta 0.000000 -3.610000 0.000000 1 'Cu_2 ' 3.6100 180.0000 0.0000 0.000000 0.000000 0.000000 0 'abs ' 3.6100 180.0000 0.0000 1005 2 6.000 index, nleg, degeneracy, r= 3.6100 x y z ipot label rleg beta eta 0.000000 0.000000 3.610000 1 'Cu_2 ' 3.6100 180.0000 0.0000 0.000000 0.000000 0.000000 0 'abs ' 3.6100 180.0000 0.0000 1006 2 6.000 index, nleg, degeneracy, r= 3.6100 x y z ipot label rleg beta eta 0.000000 0.000000 -3.610000 1 'Cu_2 ' 3.6100 180.0000 0.0000 0.000000 0.000000 0.000000 0 'abs ' 3.6100 180.0000 0.0000
Note that the pathlist method of the Feff object (line 10) returns a list of ScatteringPath objects. The pathsdat method of the ScatteringPath object is used to write out the paths.dat entry for each scattering geometry.
Plotting paths
This script imports the serialized path finder calculation and plots the first several paths. The next recipe is the first hint about how ScatteringPath objects will be used in a fit.
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4 use Ifeffit::Demeter;
5 my $plot_features = Ifeffit::Demeter::Plot -> new();
6 $plot_features->legend({key_dy => 0.05, # set nice legend parameters for the plot
7 key_x => 0.6});
8
9 ## Deserializing feff.yaml;
10 my $feff = Ifeffit::Demeter::Feff -> thaw("feff.yaml");
11 my @list_of_paths = $feff->pathlist;
12
13 ### Plotting the first 6 paths
14 my @pobjects = ();
15 foreach my $i (0 .. 5) {
16 my $j = $i+1;
17 Ifeffit::Demeter::Path -> new()
18 -> set({sp => $list_of_paths[$i],
19 index => $j,
20 })
21 -> plot('r');
22 };
Here is the plot. The sharp observer will see one difference between this list of paths and what a normal Feff6 calculation using the default heap and keep criteria values would produce. The fourth path is one which falls below the heap criterion, which uses a plane wave approximation to find paths which are too small to put onto the heap. With no such capability, Demeter's path finder includes that path in the final list.
How do I integrate the Feff and Fitting systems in Demeter?
Here is the multiple data set copper fit from the data handling recipes page rewritten to use the Feff and ScatteringPath objects:
1 #!/usr/bin/perl ### multiple data set fit to Cu foil data at two temperatures
2 ## -----------------------------------------------------------
3 ## boilerplate required in every script:
4 use warnings;
5 use strict;
6 use Ifeffit::Demeter;
7 my $plot = Ifeffit::Demeter::Plot -> new();
8 ## -----------------------------------------------------------
9 Ifeffit::Demeter->set_mode({screen => 0, ifeffit => 1, file => ">mdsfit.iff",});
10
11 my %common = (fft_kmin => 3, fft_kmax => 14,
12 bft_rmax => 1.0, bft_rmax => 4.3,
13 fit_k1 => 1, fit_k3 => 1,);
14
15 my $data_010k = Ifeffit::Demeter::Data -> new({group => 'data0',});
16 $data_010k -> set(\%common);
17 $data_010k -> set({file => "cu10k.chi",
18 label => '10 K copper data',
19 cv => 10,
20 });
21 my $data_150k = Ifeffit::Demeter::Data -> new({group => 'data1',});
22 $data_150k -> set(\%common);
23 $data_150k -> set({file => "cu150k.chi",
24 label => '150 K copper data',
25 cv => 150,
26 });
27
28 ###--- make GDS objects for an isotropic expansion, correlated Debye model
29 my @gdsobjects =
30 (Ifeffit::Demeter::GDS -> new({type => 'lguess', name => 'alpha', mathexp => 0,}),
31 ## here is some syntactic sugar provided by the Tools module
32 Ifeffit::Demeter::Tools -> simpleGDS("guess amp = 1"),
33 Ifeffit::Demeter::GDS -> new({type => 'guess', name => 'enot', mathexp => 0,}),
34 Ifeffit::Demeter::GDS -> new({type => 'guess', name => 'theta', mathexp => 500,}),
35 Ifeffit::Demeter::GDS -> new({type => 'set', name => 'sigmm', mathexp => 0.0005,}),
36 );
37
38 ## thaw a Feff calculation
39 my $feff = Ifeffit::Demeter::Feff -> thaw("cu_feff.yaml");
40 my @scattering_paths = $feff->pathlist;
41
42 ## make Path objects for the first 5 paths in copper (3 shell fit)
43 my @paths_010k = ();
44 foreach my $i (0 .. 4) {
45 my $j = $i+1;
46 $paths_010k[$i] = Ifeffit::Demeter::Path -> new();
47 $paths_010k[$i]->set({data => $data_010k,
48 sp => $scattering_paths[$i],
49 label => "10K, path $j",
50 s02 => 'amp',
51 e0 => 'enot',
52 delr => 'alpha*reff',
53 sigma2 => 'debye([cv], theta) + sigmm',
54 });
55 };
56
57 ## clone these 5 paths for the second data set
58 my @paths_150k = ();
59 foreach my $i (0 .. 4) {
60 my $j = $i+1;
61 $paths_150k[$i] = $paths_010k[$i] -> clone({data => $data_150k,
62 label => "150K, path $j",
63 });
64 };
65
66 ## make a Fit object
67 my $fitobject = Ifeffit::Demeter::Fit -> new({gds => \@gdsobjects,
68 data => [$data_010k, $data_150k],
69 paths => [@paths_010k, @paths_150k],
70 });
71 ## do the fit
72 $fitobject -> fit;
A Feff calculation on copper metal is thawed at line 39 and the list of paths is read at line 40. Then at line 48, the sp attribute is set to a thawed ScatteringPath from the Feff calculation. When using a ScatteringPath object rather than directly reading a feffNNNN.dat file, you do not (must not!) set the file and folder attributes by hand. Note that the feffNNNN.dat file is given a strange name which is chosen to avoid filename collisions resulting from rerunning Feff or from running multiple Feff calculations.
When Demeter sets up the fit at line 72, it will notice that the feffNNNN.dat file does not exist for that Path and will run Feff to make it as soon as it is needed.
Note that in version 0.1 there are still some shortcomings in Demeter's serialization scheme. You need to be careful that Demeter can find the phase.bin file from the original Feff calculation. Fixing this shortcoming is one of the goals for version 0.2.
