Skip to content

Latest commit

 

History

History
222 lines (180 loc) · 6.94 KB

File metadata and controls

222 lines (180 loc) · 6.94 KB

example files are here

From this directory, you can build the examples below with the following commands.

$ cd FMChain
$ mkdir build
$ cd build
$ cmake ..
$ make

This should create executables FMDispersion, FMcut, and FMPowderAverage

For our first example, let's calculate the the spin wave dispersion and S(Q,E) for a one-dimensional ferromagnetic chain.

Image Ferromagnetic chain

This first script calculates the dispersion relation along 100. It's repeated below for convenience.

#include <cmath>
#include <string>
#include "SpinWaveGenie/SpinWaveGenie.h"

using namespace std;
using namespace SpinWaveGenie;

int main(int argc, const char* argv[])
{
    // Cell object stores the basis vectors and Sublattice objects
    Cell cell;
    // set a,b,c,alpha,beta,gamma in units of Angstroms, Degrees
    cell.setBasisVectors(1.0,10.0,10.0,90.0,90.0,90.0);

    Sublattice spin0;
    // each Sublattice contains:
    //   a unique name,
    string name0 = "Spin0";
    spin0.setName(name0);
    //   type (used to calculate the magnetic form factor)
    spin0.setType("NONE");
    //  magnetic moment (magnitude,theta (radians), phi (radians))
    spin0.setMoment(1.0,0.0,0.0);
    //  add sublattice to Cell cell.
    cell.addSublattice(spin0);
    // add atom to sublattice name1 at position (0,0.5,0) in reduced lattice units.
    cell.addAtom(name0,0.0,0.0,0.0);

    // add Cell cell to the builder
    SpinWaveBuilder builder(cell);
    
    // defining interactions.
    InteractionFactory interactions;
    
    // Get exchange interaction named "J" with value "1.0" between sublattices name0 and name0.
    // limit atoms to those between 0.9 and 1.1 angstroms.
    // pass this interaction to the builder.
    builder.addInteraction(interactions.getExchange("J",1.0,name0,name0,0.9,1.1));

    // Returns a SpinWave object containing the cell, sublattices and interactions.
    SpinWave test = builder.createElement();
    
    // Generate 61 points between (0,0,0) and (3,0,0) (units: r.l.u.)
    PointsAlongLine Line;
    Line.setFirstPoint(0.0,0.0,0.0);
    Line.setFinalPoint(3.0,0.0,0.0);
    Line.setNumberPoints(61);
    ThreeVectors<double> kPoints = Line.getPoints();
    
    // Helper function to calculate and save the calculated frequencies and intensities in "FMChain.txt"
    SpinWaveDispersion dispersion;
    dispersion.setFilename("FMChain.txt");
    dispersion.setGenie(test);
    dispersion.setPoints(kPoints);
    // The calculation occurs within the member function SpinWaveDispersion::save().
    dispersion.save();
    return 0;
}

After building an running, please examine "FMChain.txt". Each line is of the form. H, K, L, (energies), (intensities)

Direct comparison with experimental measurements is facilitated by convoluting these results with an instrument resolution function and plotting on a grid.

TwoDimensionalCut.cpp

    // everything above this point is the same as Dispersion.cpp
    SpinWave SW = builder.createElement();
    
    // More points generates a less pixelated images.
    PointsAlongLine Line;
    Line.setFirstPoint(0.0,0.0,0.0);
    Line.setFinalPoint(3.0,0.0,0.0);
    Line.setNumberPoints(401);
    ThreeVectors<double> kPoints = Line.getPoints();
    
    // Specify energy values for the calculation.
    // min (meV), max (meV), number of points
    Energies energies(0.0, 5.0, 401);
    
    // Define a Gaussian in energy
    OneDimensionalFactory factory;
    // FWHM (meV), tolerance (meV)
    auto gauss = factory.getGaussian(0.25,1.0e-5);
    
    // Convolute results with Gaussian function described earlier.
    unique_ptr<SpinWavePlot> res(memory::make_unique<EnergyResolutionFunction>(move(gauss), SW,energies));
    
    // Helper function to calculate and save the calculated frequencies and intensities in "FMCut.x","FMCut.y" and "FMChut.mat"
    TwoDimensionalCut twodimcut;
    twodimcut.setFilename("FMcut");
    twodimcut.setPlotObject(move(res));
    twodimcut.setPoints(kPoints);
    twodimcut.save();
    return 0;
}

The python script below plots the dispersion relation on top of the cut in S(Q,E).

import matplotlib
matplotlib.use('Agg')
import numpy as np
from matplotlib import rc
import matplotlib.pyplot as plt

rc('font',**{'family':'serif','serif':['Times'],'size':16.0})
rc('text', usetex=True)
fig = matplotlib.pyplot.gcf()
fig.set_size_inches(4.0*2,3.0*2)
ax = plt.subplot(1,1,1)

dispersion = np.transpose(np.loadtxt('FMChain.txt'))
image_array = np.loadtxt('FMcut.mat')
E_array = np.loadtxt('FMcut.y')
x_axis = np.loadtxt('FMcut.x')

im = ax.pcolorfast(x_axis[:,0],E_array,image_array,vmin=0.0,vmax=1.0)
ax.scatter(dispersion[0],dispersion[3],c='white')
ax.set_ylabel(r'Energy (meV)')
ax.set_xlabel(r'distance $(\xi,0,0)$')
ax.set_xlim(left=0.0,right=3.0)
ax.set_ylim(bottom=0.0,top=5.0)
fig.colorbar(im);
plt.savefig('FMChain.png',dpi=400,bbox_inches='tight')
plt.close()

View the file 'FMChain.png` It should look like the image below.

Sometimes large single crystal are not available. One can also calculate a spherical average of S(|Q|,E)

PowderAverage.cpp

    SpinWave SW = builder.createElement();
    
    PointsAlongLine Line;
    Line.setFirstPoint(0.0,0.0,0.0);
    Line.setFinalPoint(0.0,0.0,3.0*2.0*M_PI);
    Line.setNumberPoints(401);
    ThreeVectors<double> kPoints = Line.getPoints();
    
    Energies energies(0.0, 5.0, 401);
    
    OneDimensionalFactory factory;
    auto gauss = factory.getGaussian(0.25,1.0e-2);
    
    unique_ptr<SpinWavePlot> res(new EnergyResolutionFunction(move(gauss), SW,energies));
    unique_ptr<SpinWavePlot> cut(new IntegrateThetaPhi(move(res),2.0e-2));

    TwoDimensionalCut twodimcut;
    twodimcut.setFilename("FMPowderAverage");
    twodimcut.setPlotObject(move(cut));
    twodimcut.setPoints(kPoints);
    twodimcut.save();
    return 0;
}

Last is a script for plotting. The dispersion is overplotted, showing the origin of various eatures.

FMavg.py

import matplotlib
matplotlib.use('Agg')
import numpy as np
from matplotlib import rc
import matplotlib.pyplot as plt

rc('font',**{'family':'serif','serif':['Times'],'size':16.0})
rc('text', usetex=True)
fig = matplotlib.pyplot.gcf()
fig.set_size_inches(4.0*2,3.0*2)
ax = plt.subplot(1,1,1)

dispersion = np.loadtxt('FMChain.txt')
x_axis = np.loadtxt('FMPowderAverage.x')
E_array = np.loadtxt('FMPowderAverage.y')
image_array = np.loadtxt('FMPowderAverage.mat')

print len(image_array)
print len(image_array[0])
print np.max(image_array)
im = ax.pcolorfast(x_axis[:,2]/(2.0*np.pi),E_array,image_array,vmin=0.0,vmax=0.3)
ax.scatter(dispersion[:,0],dispersion[:,3],c='white')
ax.set_ylabel(r'Energy (meV)')
ax.set_xlabel(r'distance $(\xi,0,0)$')
ax.set_xlim(left=0.0,right=3.0)
ax.set_ylim(bottom=0.0,top=5.0)
fig.colorbar(im);
plt.savefig('FMavg.png',dpi=400,bbox_inches='tight')
plt.close()