# VirtualCrystalBasisSet¶

class VirtualCrystalBasisSet(basis_sets, x=None)

Class providing the virtual crystal approximation basis set.

Parameters: basis_sets (tuple of two BasisSet instances) – The two basis sets to combine. The basis sets must have pseudopotentials with the same number of valence electrons. x (float) – The relative weight of the first element (between zero and one). Default: 0.5
angularMomenta()

Return the angular momenta of the basis set.

Returns: The angular momentum (azimuthal quantum number) for each orbital. list
basisSets()

The constituent basis sets.

Returns: The two basis sets that make up the virtual crystal basis. list of two BasisSet instances
dftHalfParameters()

The DFT-1/2 parameters.

Returns: The DFT-1/2 parameters. DFTHalfParameters | Automatic | Disabled
element()

The element for this basis set.

Returns: The atomic element. PeriodicTableElement
fillingMethod()

The method using for filling the orbitals.

Returns: The method for filling the orbitals. SphericalSymmetric | Anisotropic
filterMeshCutoff()

The cutoff for the filter function.

Returns: The cutoff. PhysicalQuantity of type energy
hubbardU()

The Hubbard U associated with the orbitals.

Returns: The Hubbard U energies either as a PhysicalQuantity with one element for each orbital. PhysicalQuantity of type energy.
numberOfValenceElectrons()
occupations()

The occupations associated with the orbitals.

Returns: The occupations of the orbitals given as a list of non-negative floats. list
onsiteSpinOrbitSplit()

List of spin-orbit splits per orbital.

Returns: Spin-orbit splittings with one element for each orbital. PhysicalQuantity of type energy
orbitals()

The orbitals that forms this basis set.

Returns: A list of orbital objects. list
projectorShift()

A query method for the pseudopotential projector shift.

Returns: The projector shift energies specified for each angular momentum. PseudoPotentialProjectorShift
pseudopotential()

The pseudopotential used in generating the basis set.

Returns: The pseudopotential. NormConservingPseudoPotential
x()

The weight parameter for mixing the elements.

Returns: The weight parameter x. float

## Usage Examples¶

### Six Ge1-x with a fixed value for x¶

# Set x for the alloy Si_x Ge_(1-x)
x = 0.39

# Lattice constant, from http://www.ioffe.ru/SVA/NSM/Semicond/SiGe/basic.html
a = 5.431 + 0.20*(1-x) + 0.027*(1-x)**2

# Setup a BulkConfiguration
lattice = FaceCenteredCubic(a*Angstrom)

# Define elements
elements = [Silicon, Silicon]

# Define coordinates
fractional_coordinates = [[ 0.  ,  0.  ,  0.  ],
[ 0.25,  0.25,  0.25]]

# Set up configuration
bulk_configuration = BulkConfiguration(
bravais_lattice=lattice,
elements=elements,
fractional_coordinates=fractional_coordinates
)

# Define a basis set for Si.
SiliconBasis = LDABasis.Silicon_DoubleZetaPolarized

# Define a basis set for Ge.
GermaniumBasis = LDABasis.Germanium_DoubleZetaPolarized

# Define the virtual crystal basis set for the Si_x Ge_1-x system.
SiliconVirtualCrystalBasis = VirtualCrystalBasisSet(
basis_sets=[SiliconBasis, GermaniumBasis],
x=x)

basis_set = [SiliconVirtualCrystalBasis]

# Define a calculator and use the virtual crystal basis set.
k_point_sampling = MonkhorstPackGrid(
na=5,
nb=5,
nc=5,
)

numerical_accuracy_parameters = NumericalAccuracyParameters(
k_point_sampling=k_point_sampling,
)

calculator = LCAOCalculator(
basis_set=basis_set,
numerical_accuracy_parameters=numerical_accuracy_parameters,
)

# Attach the calculator to the configuration.
bulk_configuration.setCalculator(calculator)

# Calculate the bandstructure.
bandstructure = Bandstructure(
configuration=bulk_configuration,
route=['G', 'X'],
points_per_segment=40,
bands_above_fermi_level=4)

# Calculate the direct and indirect gap.
direct_gap = bandstructure.directBandGap()
indirect_gap = bandstructure.indirectBandGap()

# Print the results.
print('%f\t%f\t%f' % (x, direct_gap.inUnitsOf(eV), indirect_gap.inUnitsOf(eV)))


### Six Ge1-x with x ranging from 0 (pure Ge) to 1 (pure Si)¶

# Define a basis set for Si
SiliconBasis = LDABasis.Silicon_DoubleZetaPolarized
# Define a basis set for Ge
GermaniumBasis = LDABasis.Germanium_DoubleZetaPolarized

# Loop over Si concentration.
x_values = numpy.linspace(0.0, 1.0, 21)

for x in x_values:
# Lattice constant for specific x. From http://www.ioffe.ru/SVA/NSM/Semicond/SiGe/basic.html
a = 5.431 + 0.20*(1-x) + 0.027*(1-x)**2

# Setup a BulkConfiguration
lattice = FaceCenteredCubic(a*Angstrom)

# Define elements
elements = [Silicon, Silicon]

# Define coordinates
fractional_coordinates = [[ 0.  ,  0.  ,  0.  ],
[ 0.25,  0.25,  0.25]]

# Set up configuration
bulk_configuration = BulkConfiguration(
bravais_lattice=lattice,
elements=elements,
fractional_coordinates=fractional_coordinates
)

# Define the virtual crystal basis set for the Si_x Ge_1-x with the current x.
SiliconVirtualCrystalBasis = VirtualCrystalBasisSet(
basis_sets=[SiliconBasis, GermaniumBasis],
x=x)

basis_set = [SiliconVirtualCrystalBasis]

# Define a calculator.
k_point_sampling = MonkhorstPackGrid(
na=5,
nb=5,
nc=5,
)

numerical_accuracy_parameters = NumericalAccuracyParameters(
k_point_sampling=k_point_sampling,
)

calculator = LCAOCalculator(
basis_set=basis_set,
numerical_accuracy_parameters=numerical_accuracy_parameters,
)

# Attach the calculator to the configuration.
bulk_configuration.setCalculator(calculator)

# Calculate the bandstructure.
bandstructure = Bandstructure(
configuration=bulk_configuration,
route=['G', 'X'],
points_per_segment=40,
bands_above_fermi_level=4)

# Calculate the direct and indirect gap.
direct_gap = bandstructure.directBandGap()
indirect_gap = bandstructure.indirectBandGap()

# Print the results.
print('%f\t%f\t%f' % (x, direct_gap.inUnitsOf(eV), indirect_gap.inUnitsOf(eV)))


### Gax In1-x As with x from 0 to 1¶

The following script sets up a calculation of the bandstructure of Ga(x) In(1-x) As as a function of the Ga concentration x. In order to obtain physically meaningful results, the spin-orbit interaction is included and the TB09 meta-GGA exchange-correlation potential is used. The spin-orbit coupling terms are contained in the pseudopotentials. Note that the pseudopotentials used in this script are not provided as part of QuantumATK. To run this script, the pseudopotentials have to be downloaded separately, e.g., from http://www.abinit.org/downloads/psp-links/hgh. Save the downloaded pseudopotentials in the same directory as the script.

# Setup a GaInAs calculation with spin-orbit coupling and TB09 meta-GGA.

#-----------------------------------------------------------------------------
# HGH Basis Set with manually set pseudopotential to include spin-orbit terms.
#-----------------------------------------------------------------------------
ga_basis = BasisLDAPZHGH.Gallium_13_Tier_4(pseudopotential=NormConservingPseudoPotential('31ga.13.hgh'))
in_basis = BasisLDAPZHGH.Indium_13_Tier_4(pseudopotential=NormConservingPseudoPotential('49in.13.hgh'))
as_basis = BasisLDAPZHGH.Arsenic_5_Tier_4(pseudopotential=NormConservingPseudoPotential('33as.5.hgh'))

#----------------------------------------
# Exchange-Correlation
#----------------------------------------
exchange_correlation = SOMGGA.TB09LDA

numerical_accuracy_parameters = NumericalAccuracyParameters(
density_cutoff=1e-06,
k_point_sampling=(9, 9, 9),
density_mesh_cutoff=300.0*Hartree)

iteration_control_parameters = IterationControlParameters(
max_steps=100,
tolerance=1e-06)

# Loop over Ga concentration x.
for x in numpy.linspace(0.0, 1.0, 21):
a = 6.0583 - 0.405*x

# -------------------------------------------------------------
# Bulk configuration
# -------------------------------------------------------------

# Set up lattice
lattice = FaceCenteredCubic(a*Angstrom)

# Define elements
elements = [Gallium, Arsenic]

# Define coordinates
fractional_coordinates = [[ 0.   ,  0.    ,  0.   ],
[ 0.25 ,  0.25  ,  0.25 ]]

# Set up configuration
bulk_configuration = BulkConfiguration(
bravais_lattice=lattice,
elements=elements,
fractional_coordinates=fractional_coordinates)

# -------------------------------------------------------------
# Calculator
# -------------------------------------------------------------
# Define the virtual crystal basis set for the Ga/In system.
GalliumVirtualCrystalBasis = VirtualCrystalBasisSet(
basis_sets=[ga_basis, in_basis],
x=x)

# Define the complete basis set consisting of the Ga/In virtual crystal basis
# and the ordinary As basis.
basis_set = [GalliumVirtualCrystalBasis, as_basis]

calculator = LCAOCalculator(
basis_set=basis_set,
exchange_correlation=exchange_correlation,
numerical_accuracy_parameters=numerical_accuracy_parameters,
iteration_control_parameters=iteration_control_parameters)

bulk_configuration.setCalculator(calculator)
bulk_configuration.update()

nlsave('GaInAs_VCA.nc', bulk_configuration)

# -------------------------------------------------------------
# Bandstructure
# -------------------------------------------------------------
bandstructure = Bandstructure(
configuration=bulk_configuration,
route=['X', 'G', 'L'],
points_per_segment=101,
bands_above_fermi_level=All)

nlsave('GaInAs_VCA.nc', bandstructure)


## Notes¶

When constructing a virtual crystal basis set in QuantumATK the following procedure is applied. The virtual crystal pseudopotential is obtained as a mixture of the two original pseudopotentials provided through the basis sets. The basis set orbitals will be the sum of the two original basis sets, each evaluated with their original pseudopotential. The total number of basis orbitals in a virtual crystal basis set will therefore always be larger than the individual basis sets, and calculations will be more time consuming.