Properties

See more details about the Properties in the API

Properties are containers of physical properties that can be calculated from a Model. They store both the data itself and meta-data, such as the energy interval they have been calculated over. Properties can also be used as functions of the arguments for which they have been calculated. This makes them convenient building blocks for applications that extend the capabilities beyond those of the standard Solvers.

This chapter discusses the Properties themselves. For information on how to calculate them, see the PropertyExtractors chapter.

Many Properties are EnergyResolvedProperties, which means that they contain data over some energy interval. It is possible to get information about the interval as follows.

double lowerBound = energyResolvedProperty.getLowerBound();

double upperBound = energyResolvedProperty.getUpperBound();

unsigned resolution = energyResolvedProperty.getResolution();

Here *resolution* is the number of points with which the data is resolved between the *lowerBound* and the *upperBound*.

There are three different storage modes for Properties called None, Ranges, and Custom. Here we describe the difference between these modes. We also describe how the mode affects how data can be accessed from the Property.

Independently of the storage mode, the total number of data points contained in the Property can be retrieved using

unsigned int size = property.getSize();

This storage mode is for Properties that have no Indices associated with them. For example, the density of states (DOS) and the EigenValues.

If the Property is a function of energy, it is possible to get the nth element using the notation

property(n);

This storage mode is meant for extracting Properties on a regular grid, e.g., the Density on a quadratic lattice. It can be particularly useful when the Property is to be exported for external postprocessing.

When stored on this format, the data and its ranges can be extracted as follows.

const vector<DataType> &data = property.getData();

vector<int> ranges = property.getRanges();

Here DataType should be replaced by the particular data type of the Property's values.

If the data also is a function of energy, with resolution ENERGY_RESOLUTION, then the layout is such that the data can be accessed as follows.

data[ENERGY_RESOLUTION*(ranges[2]*(ranges[1]*x + y) + z) + n];

If the data instead would be two-dimensional and without energy dependence, the data is accessed as follows.

data[ranges[1]*x + y];

This storage format is meant for Properties that have been calculated for arbitrary Indices. If the Property has been calculated for a given Index, say {x, y, z, spin}, it is possible to access the value as follows.

property({x, y, z, spin});

If the Property is energy-dependent, we instead use

property({x, y, z, spin}, n);

where n is an energy index.

A Property may have been calculated using a specifier in one of the Subindices. Consider for example the Index structure {x, y, z, spin}, and the Density obtained through

Property::Density density = propertyExtractor.calculateDensity({

{5, _a_, _a_, IDX_SUM_ALL}

});

Here the Density is being calculated for all possible coordinates of the form \((5, y, z)\). However, the subindex specifier IDX_SUM_ALL ensures the spin Subindex is summed over. The resulting Density retains the original Index structure, including the spin Subindex. To get the value of the Density at a specific point \((5, y, z)\), we call the Density with a wildcard in the spin Subindex.

density({5, y, z, _a_});

By default, a Property will generate an error when trying to access a value that is not contained in the Property. However, it is possible to configure the Property such that it instead return some default value (e.g. zero). This can be done as follows.

property.setAllowIndexOutOfBoundsAccess(true);

property.setDefaultValue(defaultValue);

We note that it is recommended to be cautious about turning this feature on. Out-of-bounds access is often a sign that something is wrong, and turning this on can, therefore, mask bugs.

See the PropertyExtractors chapter for details about the different ways that Properties can be extracted.

Assume the Index structure {x, y, orbital, spin}.

**Ranges format**

Property::Density density = propertyExtractor.calculateDensity(

{ _a_, _a_, IDX_SUM_ALL, IDX_SUM_ALL},

{sizeX, sizeY, numOrbitals, 2}

);

vector<int> ranges = density.getRanges();

const vector<double> &data = density.getData();

double d = data[ranges[1]*x + y];

**Custom format**

Property::Density density = propertyExtractor.calculateDensity({

{_a_, _a_, IDX_SUM_ALL, IDX_SUM_ALL}

});

double d = density({x, y, _a_, _a_});

See more details about the Density in the API

**None format**

Property::DOS dos = propertyExtractor.calculateDOS();

double lowerBound = dos.getLowerBound();

double upperBound = dos.getUpperBound();

double resolution = dos.getResolution();

double d = dos(n);

Here 0 <= *n* < *resolution*.

See more details about the DOS in the API

**None format**

unsigned int numEigenValues = eigenValues.getSize();

double e = eigenValues(n);

Here 0 <= *n* < *numEigenValues*.

See more details about the EigenValues in the API

Assume the Index structure {x, y, z, spin}.

**Ranges format**

Property::LDOS ldos = propertyExtractor.calculateLDOS(

{ _a_, _a_, IDX_SUM_ALL, IDX_SUM_ALL},

{sizeX, sizeY, numOrbitals, 2}

);

double lowerBound = ldos.getLowerBound();

double upperBound = ldos.getUpperBound();

double resolution = ldos.getResolution();

vector<int> ranges = ldos.getRanges();

const vector<double> &data = ldos.getData();

double d = data[resolution*(ranges[1]*x + y) + n];

Here 0 <= *n* < resolution.

**Custom format**

Property::LDOS ldos = propertyExtractor.calculateLDOS({

{_a_, _a_, IDX_SUM_ALL, IDX_SUM_ALL}

});

double lowerBound = ldos.getLowerBound();

double upperBound = ldos.getUpperBound();

double resolution = ldos.getResolution();

double d = ldos({x, y, _a_, _a_}, n);

Here 0 <= *n* < resolution.

See more details about the LDOS in the API

Assume the Index structure {x, y, orbital, spin}.

**Ranges format**

Property::Magnetization magnetization

= propertyExtractor.calculateMagnetization(

{ _a_, _a_, IDX_SUM_ALL, IDX_SPIN},

{sizeX, sizeY, numOrbitals, 2}

);

vector<int> ranges = magnetiation.getRanges();

const vector<SpinMatrix> &data = magnetization.getData();

SpinMatrix spinMatrix = data[ranges[1]*x + y];

**Custom format**

Property::Magnetization magnetization

= propertyExtractor.calculateMagnetization({

{_a_, _a_, IDX_SUM_ALL, IDX_SPIN}

});

SpinMatrix spinMatrix = magnetization({x, y, _a_, _a_});

See more details about the Magnetization in the API

See more details about the SpinMatrix in the API

Assume the Index structure {x, y, orbital, spin}.

**Ranges format**

Property::SpinPolarizedLDOS spinPolarizedLDOS

= propertyExtractor.calculateSpinPolarizedLDOS(

{ _a_, _a_, IDX_SUM_ALL, IDX_SPIN},

{sizeX, sizeY, numOrbitals, 2}

);

double lowerBound = spinPolarizedLDOS.getLowerBound();

double upperBound = spinPolarizedLDOS.getUpperBound();

double resolution = spinPolarizedLDOS.getResolution();

vector<int> ranges = spinPolarizedLDOS.getRanges();

const vector<SpinMatrix> &data = spinPolarizedLDOS.getData();

SpinMatrix spinMatrix = data[resolution*(ranges[1]*x + y) + n];

Here 0 <= *n* < *resolution*.

**Custom format**

Property::SpinPolarizedLDOS spinPolarizedLDOS

= propertyExtractor.calculateSpinPolarizedLDOS({

{_a_, _a_, IDX_SUM_ALL, IDX_SPIN}

});

double lowerBound = spinPolarizedLDOS.getLowerBound();

double upperBound = spinPolarizedLDOS.getUpperBound();

double resolution = spinPolarizedLDOS.getResolution();

SpinMatrix spinMatrix = spinPolarizedLDOS({x, y, _a_, _a_}, n);

Here 0 <= *n* < *resolution*.

See more details about the SpinPolarizedLDOS in the API

See more details about the SpinMatrix in the API

Assume the Index structure {x, y, orbital, spin}.

**Custom format**

The WaveFunctions are extracted somewhat differently from all other Properties. The second argument to the PropertyExtractor call is a list of the eigenstate indices for which to extract the WaveFunctions. This can also be set to _a_ to extract all states.

Property::WaveFunctions waveFunctions

= propertyExtractor.calculateWaveFunctions(

{{_a_, _a_, _a_, _a_}},

{1, 3, 7}

);

vector<unsigned int> &states = waveFunction.getStates();

complex<double> &w = waveFunctions({x, y, orbital, spin}, n);

where *n* is one of the numbers contained in *states*.