Calculating individual scattering paths

After the path finder is run, the Feff object has its pathlist attribute filled with a reference to a list of ScatteringPath objects. The ScatteringPath object is an abstract representation of a scattering path. In DEMETER, the ScatteringPath object is somewhat like a feffNNNN.dat is to IFEFFIT -- it does indeed describe the path, but it needs to imported and parametrized before it can be used to make a plot or a fit.

The ScatteringPath object has attributes which describe all the geometry of the path, including degeneracy, leg lengths, and scattering angles. It also has a way of reconstructing the specific geometry of each degenerate path that gets combined when the path finder determines path degeneracy.

The methods of the ScatteringPath object include a way of generating the feffNNNN.dat file containing FEFF calculation of the scattering amplitude and phase shift for the path. The calculation of the feffNNNN.dat file is done on-the-fly by DEMETER and is written to temporary file in the directory specified by the workspace attribute of the Feff object from which the ScatteringPath object was created. That path file has a randomly generated name. The use of random names for the path files is intended to sever the link between the index of the path in FEFF path list and the path file. That number has been used in earlier versions of ARTEMIS, but has proven troublesome in many situations. As you will see in later chapters, DEMETER tries to emphasize semantic descriptions of paths, eschewing the path index.

DEMETER never saves feffNNNN.dat files when it saves a fitting model to a project file (nor does ARTEMIS). The recalculation of the feffNNNN.dat file is sufficiently fast that it is done when needed.

The main use of the ScatteringPath object is as the value of the sp attribute of the Path object. Here is an example of plotting the 6 shortest paths from a FEFF calculation.

  1. #!/usr/bin/perl
  2. use Demeter;
  3. my $feff = Demeter::Feff -> new(file => "feff/feff.inp");
  4. $feff -> set(workspace => "feff/", screen => 0,);
  5. $feff -> potph;
  6. $feff -> pathfinder;
  7. my @list_of_paths = @{ $feff-> pathlist };
  8. foreach (@list_of_paths[0..5]) {
  9.   my $this = Demeter::Path->new(parent => $feff,
  10.                                 sp     => $_);
  11.   $this -> plot('r');
  12. };

At line 9, the reference to the list of ScatteringPath objects is read into a normal array (the @{ } syntax dereferences the array). The first 6 elements of this array is then looped over and a Path object is created using those 6 ScatteringPath objects. Each Path object is then plotted at line 13.


 

Writing feffNNNN.dat files

As demonstrated above, generation of the individual feffNNNN.dat files is something that happens behind the scenes. DEMETER goes to great lengths to ensure that you do not need to worry about those files. It is certainly possible to write large, complex fitting programs with DEMETER without ever even thinking about those files.

That said, sometimes you may want to generate feffNNNN.dat files. The Feff object provides the genfmt method. This is the method used behind the scenes to generate path files as needed for plotting or fitting. This behind-the-scenes chore is quite efficient. The individual path file is saved during an instance of the DEMETER program so it can be reused without being recalculated. Even in a scenario where a single ScatteringPath object is used to define two or more Path objects (see the histogram example for an example where this is used to great effect), DEMETER is clever enough to only compute the path file once.

In a scenario where you wish to generate feffNNNN.dat files, you can do something like this:

  1. #!/usr/bin/perl  
  2. use Demeter;
  3. ## Deserialize feff.yaml;
  4. my $feff = Demeter::Feff -> new(yaml => "feff/feff.yaml");
  5. $feff->pathsdat(); # all paths
  6. #$feff->pathsdat(1,2,6,9); # the first four SS paths
  7. $feff->genfmt;

The pathsdat method writes a paths.dat file to the Feff object's workspace. This is the file that the genfmt part of FEFF uses to define the geometries of the scattering paths that go into the feffNNNN.dat files. Without an argument, as at line 6, all paths found by the path finder are written to the paths.dat file. With an argument, as commented out at line 7, only the paths listed will be written out. The path files then generated by the genfmt method will be named feffNNNN.dat with the NNNN replaced by the zero-padded path index. This behavior is very similar to the normal behavior of FEFF (with the exception of the ability to prescribe a truncated path list).

As great as it is that DEMETER can replicate the stodgy old behavior of FEFF, I strongly recommend that you avoid doing so.


 

Examining the degenerate paths

Along with fuzzy degeneracy, the ability to remember the entire list of scattering geometries contributing to the degeneracy of a path is one of the major new features DEMETER's path finder. If you ever want to examine the degenerate list, you can do something like this:

  1. #!/usr/bin/perl  
  2. use Demeter;
  3. ## Deserializing feff.yaml;
  4. my $feff = Demeter::Feff -> new("feff/feff.yaml");
  5. my @list_of_paths = $feff->pathlist;
  6. ### The 6 scattering geometries that contribute to path #2:
  7. my $sp = $list_of_paths[1];
  8. my $j=1000;
  9. foreach my $s ($sp->all_strings) {
  10.   print $sp -> pathsdat(index=>++$j, string=>$s, angles=>1);
  11. };

What gets printed out is something like this, which is in the form of a paths.dat file and can be used by the genfmt part of FEFF.

  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

In truth, DEMETER does not do much with the list of degerate scattering geometries at this time. In the future, I hope to incorporate an ability to propagate a strctural distortion through the degerate paths to examine the effect of broken degeneracy on the calculated or fitted χ(k).