from ctypes import *
import numpy as np
import os, sys
import types
# get_bath_dimension
[docs]
def get_bath_dimension(self):
"""
This function returns the correct dimension for the bath to be allocated (for each impurity) given the parameters of the system.
:return: a number which is the dimension of the bath array for each impurity.
:rtype: int
"""
get_bath_dimension_wrap = self.library.get_bath_dimension
get_bath_dimension_wrap.argtypes = None
get_bath_dimension_wrap.restype = c_int
return get_bath_dimension_wrap()
# init_hreplica
[docs]
def set_hreplica(self, hvec, lambdavec):
"""
This function is specific to :f:var:`bath_type` = :code:`=replica`. It sets the basis of matrices\
and scalar parameters that, upon linear combination, make up the bath replica.
:type hvec: np.array(dtype=complex)
:param hvec: array of bath matrices. They decompose the nonzero part of the replica in a set.\
Each element of the set correspond to a variational parameter.\
That way the bath replica matrix is updated while preserving symmetries\
of the user's choosing. The array can have the following shapes:
* [ :code:`(Nnambu)` :math:`\\cdot` :data:`Nspin` :math:`\\cdot` :data:`Norb` , :code:`(Nnambu)` :math:`\\cdot` :data:`Nspin` :math:`\\cdot` :data:`Norb` , :code:`Nsym` ]:\
3-dimensional, where Nnambu refers to the superconducting case and Nsym \
is the number of matrices that make up the linear combination
* [:code:`(Nnambu)` :math:`\\cdot` :data:`Nspin` , :code:`(Nnambu)` :data:`Nspin` , :data:`Norb` , :data:`Norb` , :code:`Nsym` ]:\
5-dimensional, where Nnambu refers to the superconducting case and Nsym is \
the number of matrices that make up the linear combination
:type lambdavec: np.array(dtype=float)
:param lambdavec: the array of coefficients of the linear combination.\
This, along with the hybridizations V, are the fitting parameters of \
the bath. The array has the following shape
* [ :data:`Nbath` , :code:`Nsym` ]: for single-impurity DMFT, 2-dimensional,\
where Nsym is the number of matrices that make up the linear combination
* [ :code:`Nlat`, :data:`Nbath` , :code:`Nsym` ]: for real-space DMFT, 3-dimensional,\
where Nlat is the number of inequivalent impurity sites and Nsym is\
the number of matrices that make up the linear combination
:raise ValueError: if the shapes of the arrays are inconsistent
:return: Nothing
:rtype: None
"""
init_hreplica_symmetries_d5 = self.library.init_Hreplica_symmetries_d5
init_hreplica_symmetries_d5.argtypes = [
np.ctypeslib.ndpointer(dtype=complex, ndim=5, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=float, ndim=2, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
]
init_hreplica_symmetries_d5.restype = None
init_hreplica_symmetries_d3 = self.library.init_Hreplica_symmetries_d3
init_hreplica_symmetries_d3.argtypes = [
np.ctypeslib.ndpointer(dtype=complex, ndim=3, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=float, ndim=2, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
]
init_hreplica_symmetries_d3.restype = None
init_hreplica_symmetries_lattice_d5 = (
self.library.init_Hreplica_symmetries_lattice_d5
)
init_hreplica_symmetries_lattice_d5.argtypes = [
np.ctypeslib.ndpointer(dtype=complex, ndim=5, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=float, ndim=3, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
]
init_hreplica_symmetries_lattice_d5.restype = None
init_hreplica_symmetries_lattice_d3 = (
self.library.init_Hreplica_symmetries_lattice_d3
)
init_hreplica_symmetries_lattice_d3.argtypes = [
np.ctypeslib.ndpointer(dtype=complex, ndim=3, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=float, ndim=3, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
]
init_hreplica_symmetries_lattice_d3.restype = None
aux_norb = c_int.in_dll(self.library, "Norb").value
aux_nspin = c_int.in_dll(self.library, "Nspin").value
dim_hvec = np.asarray(np.shape(hvec), dtype=np.int64, order="F")
dim_lambdavec = np.asarray(np.shape(lambdavec), dtype=np.int64, order="F")
self.Nsym = dim_lambdavec[1]
if len(dim_hvec) == 3:
if len(dim_lambdavec) == 2:
init_hreplica_symmetries_d3(hvec, dim_hvec, lambdavec, dim_lambdavec)
elif len(Ddim_lambdavec) == 3:
init_hreplica_symmetries_lattice_d3(
hvec, dim_hvec, lambdavec, dim_lambdavec
)
else:
raise ValueError("Shape(lambdavec) != 2 or 3 in set_Hreplica")
elif len(dim_hvec) == 5:
if len(dim_lambdavec) == 2:
init_hreplica_symmetries_d5(hvec, dim_hvec, lambdavec, dim_lambdavec)
elif len(dim_lambdavec) == 3:
init_hreplica_symmetries_lattice_d5(
hvec, dim_hvec, lambdavec, dim_lambdavec
)
else:
raise ValueError("Shape(lambdavec) != 2 or 3 in set_Hreplica")
else:
raise ValueError("Shape(Hvec) != 3 or 5 in set_Hreplica")
return
# init_hgeneral
[docs]
def set_hgeneral(self, hvec, lambdavec):
"""
This function is specific to :code:`BATH_TYPE=GENERAL`. It sets the basis of matrices\
and scalar parameters that, upon linear combination, make up the bath replica. \
The input is the same as that of :func:`set_hreplica`.
:type hvec: np.array(dtype=complex)
:param hvec: array of bath matrices. They decompose the nonzero part of the replica in a set.\
Each element of the set correspond to a variational parameter.\
That way the bath replica matrix is updated while preserving symmetries\
of the user's choosing. The array can have the following shapes:
* [:code:`(Nnambu)` :math:`\\cdot`:data:`Nspin` :math:`\\cdot` :data:`Norb` , :code:`(Nnambu)` :math:`\\cdot` :data:`Nspin` :math:`\\cdot` :data:`Norb` , :code:`Nsym` ]:\
3-dimensional, where Nnambu refers to the superconducting case and Nsym \
is the number of matrices that make up the linear combination
* [:code:`(Nnambu)` :math:`\\cdot` :data:`Nspin` , :code:`(Nnambu)` :math:`\\cdot` :data:`Nspin` , :data:`Norb` , :data:`Norb` , :code:`Nsym` ]:\
5-dimensional, where Nnambu refers to the superconducting case and Nsym is \
the number of matrices that make up the linear combination
:type lambdavec: np.array(dtype=float)
:param lambdavec: the array of coefficients of the linear combination.\
This, along with the hybridizations V, are the fitting parameters of \
the bath. The array has the following shape
* [ :data:`Nbath` , :code:`Nsym` ]: for single-impurity DMFT, 2-dimensional,\
where Nsym is the number of matrices that make up the linear combination
* [ :code:`Nlat`, :data:`Nbath` , :code:`Nsym` ]: for real-space DMFT, 3-dimensional,\
where Nlat is the number of inequivalent impurity sites and Nsym is\
the number of matrices that make up the linear combination
:raise ValueError: if the shapes of the arrays are inconsistent
:return: Nothing
:rtype: None
"""
init_hgeneral_symmetries_d5 = self.library.init_Hgeneral_symmetries_d5
init_hgeneral_symmetries_d5.argtypes = [
np.ctypeslib.ndpointer(dtype=complex, ndim=5, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=float, ndim=2, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
]
init_hgeneral_symmetries_d5.restype = None
init_hgeneral_symmetries_d3 = self.library.init_Hgeneral_symmetries_d3
init_hgeneral_symmetries_d3.argtypes = [
np.ctypeslib.ndpointer(dtype=complex, ndim=3, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=float, ndim=2, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
]
init_hgeneral_symmetries_d3.restype = None
init_hgeneral_symmetries_lattice_d5 = (
self.library.init_Hgeneral_symmetries_lattice_d5
)
init_hgeneral_symmetries_lattice_d5.argtypes = [
np.ctypeslib.ndpointer(dtype=complex, ndim=5, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=float, ndim=3, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
]
init_hgeneral_symmetries_lattice_d5.restype = None
init_hgeneral_symmetries_lattice_d3 = (
self.library.init_Hgeneral_symmetries_lattice_d3
)
init_hgeneral_symmetries_lattice_d3.argtypes = [
np.ctypeslib.ndpointer(dtype=complex, ndim=3, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=float, ndim=3, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
]
init_hgeneral_symmetries_lattice_d3.restype = None
aux_norb = c_int.in_dll(self.library, "Norb").value
aux_nspin = c_int.in_dll(self.library, "Nspin").value
dim_hvec = np.asarray(np.shape(hvec), dtype=np.int64, order="F")
dim_lambdavec = np.asarray(np.shape(lambdavec), dtype=np.int64, order="F")
self.Nsym = dim_lambdavec[1]
if len(dim_hvec) == 3:
if len(dim_lambdavec) == 2:
init_hgeneral_symmetries_d3(hvec, dim_hvec, lambdavec, dim_lambdavec)
elif len(Ddim_lambdavec) == 3:
init_hgeneral_symmetries_lattice_d3(
hvec, dim_hvec, lambdavec, dim_lambdavec
)
else:
raise ValueError("Shape(lambdavec) != 2 or 3 in set_Hgeneral")
elif len(dim_hvec) == 5:
if len(dim_lambdavec) == 2:
init_hgeneral_symmetries_d5(hvec, dim_hvec, lambdavec, dim_lambdavec)
elif len(dim_lambdavec) == 3:
init_hgeneral_symmetries_lattice_d5(
hvec, dim_hvec, lambdavec, dim_lambdavec
)
else:
raise ValueError("Shape(lambdavec) != 2 or 3 in set_Hgeneral")
else:
raise ValueError("Shape(Hvec) != 3 or 5 in set_Hgeneral")
return
# break_symmetry_bath
[docs]
def break_symmetry_bath(self, bath, field, sign, save=True):
"""
This function breaks the spin symmetry of the bath, useful \
for magnetic calculations to incite symmetry breaking.\
Not compatible with :code:`REPLICA` or :code:`GENERAL` bath types.
:type bath: np.array(dtype=float)
:param bath: The user-accessible bath array
:type field: float
:param field: the magnitude of the symmetry-breaking shift
:type sign: float
:param sign: the sign of the symmetry-breaking shift
:type save: bool
:param save: whether to save the symmetry-broken bath for reading
:return: the modified bath array
:rtype: np.array(dtype=float)
"""
break_symmetry_bath_site = self.library.break_symmetry_bath_site
break_symmetry_bath_site.argtypes = [
np.ctypeslib.ndpointer(dtype=float, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
c_double,
c_double,
c_int,
]
break_symmetry_bath_site.restype = None
break_symmetry_bath_ineq = self.library.break_symmetry_bath_ineq
break_symmetry_bath_ineq.argtypes = [
np.ctypeslib.ndpointer(dtype=float, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
c_double,
c_double,
c_int,
]
break_symmetry_bath_ineq.restype = None
if save:
save_int = 1
else:
save_int = 0
bath_shape = np.asarray(np.shape(bath), dtype=np.int64, order="F")
if (len(bath_shape)) == 1:
break_symmetry_bath_site(bath, bath_shape, field, float(sign), save_int)
else:
break_symmetry_bath_ineq(bath, bath_shape, field, float(sign), save_int)
return bath
# spin_symmetrize_bath
[docs]
def spin_symmetrize_bath(self, bath, save=True):
"""
This function enforces equality of the opposite-spin components\
of the bath array. Not compatible with :code:`REPLICA` or :code:`GENERAL` bath types.
:type bath: np.array(dtype=float)
:param bath: The user-accessible bath array
:type save: bool
:param save: whether to save the symmetry-broken bath for reading
:return: the modified bath array
:rtype: np.array(dtype=float)
"""
spin_symmetrize_bath_site = self.library.spin_symmetrize_bath_site
spin_symmetrize_bath_site.argtypes = [
np.ctypeslib.ndpointer(dtype=float, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
c_int,
]
spin_symmetrize_bath_site.restypes = None
spin_symmetrize_bath_ineq = self.library.spin_symmetrize_bath_ineq
spin_symmetrize_bath_ineq.argtypes = [
np.ctypeslib.ndpointer(dtype=float, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
c_int,
]
spin_symmetrize_bath_ineq.restypes = None
if save:
save_int = 1
else:
save_int = 0
bath_shape = np.asarray(np.shape(bath), dtype=np.int64, order="F")
if (len(bath_shape)) == 1:
spin_symmetrize_bath_site(bath, bath_shape, save_int)
else:
spin_symmetrize_bath_ineq(bath, bath_shape, save_int)
return bath
# orb_symmetrize_bath
[docs]
def orb_symmetrize_bath(self, bath, orb1, orb2, save=True):
"""
This function enforces equality of the different-orbital components \
of the bath array. Not compatible with :code:`REPLICA` or :code:`GENERAL` bath types.
:type bath: np.array(dtype=float)
:param bath: The user-accessible bath array
:type orb1: int
:param orb1: first orbital index
:type orb2: int
:param orb2: second orbital index
:type save: bool
:param save: whether to save the symmetry-broken bath for reading
:return: the modified bath array
:rtype: np.array(dtype=float)
"""
orb_symmetrize_bath_site = self.library.orb_symmetrize_bath_site
orb_symmetrize_bath_site.argtypes = [
np.ctypeslib.ndpointer(dtype=float, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
c_int,
]
orb_symmetrize_bath_site.restypes = None
orb_symmetrize_bath_ineq = self.library.orb_symmetrize_bath_ineq
orb_symmetrize_bath_ineq.argtypes = [
np.ctypeslib.ndpointer(dtype=float, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
c_int,
]
orb_symmetrize_bath_ineq.restypes = None
if save:
save_int = 1
else:
save_int = 0
bath_shape = np.asarray(np.shape(bath), dtype=np.int64, order="F")
if (len(bath_shape)) == 1:
orb_symmetrize_bath_site(bath, bath_shape, orb1 + 1, orb2 + 1, save_int)
else:
orb_symmetrize_bath_ineq(bath, bath_shape, orb1 + 1, orb2 + 1, save_int)
return bath
# orb_equality_bath
[docs]
def orb_equality_bath(self, bath, indx, save=True):
"""
This function sets every orbital component to be equal to the \
one of orbital :code:`indx`. Not compatible with :code:`REPLICA` or :code:`GENERAL` bath types.
:type bath: np.array(dtype=float)
:param bath: The user-accessible bath array
:type iorb: int
:param iorb: the orbital index to which every other will be set as equal
:type save: bool
:param save: whether to save the symmetry-broken bath for reading
:raise ValueError: if the orbital index is out of bounds
:return: the modified bath array
:rtype: np.array(dtype=float)
"""
orb_equality_bath_site = self.library.orb_equality_bath_site
orb_equality_bath_site.argtypes = [
np.ctypeslib.ndpointer(dtype=float, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
c_int,
c_int,
]
orb_equality_bath_site.restypes = None
orb_equality_bath_ineq = self.library.orb_equality_bath_ineq
orb_equality_bath_ineq.argtypes = [
np.ctypeslib.ndpointer(dtype=float, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
c_int,
c_int,
]
orb_equality_bath_ineq.restypes = None
aux_norb = c_int.in_dll(self.library, "Norb").value
if save:
save_int = 1
else:
save_int = 0
bath_shape = np.asarray(np.shape(bath), dtype=np.int64, order="F")
if (indx < 0) or (indx >= aux_norb):
raise ValueError("orb_equality_bath: orbital index should be in [0,Norb]")
else:
indx = indx + 1 # python to fortran convention
if (len(bath_shape)) == 1:
orb_equality_bath_site(bath, bath_shape, indx, save_int)
else:
orb_equality_bath_ineq(bath, bath_shape, indx, save_int)
return bath
# ph_symmetrize_bath
[docs]
def ph_symmetrize_bath(self, bath, save):
"""
This function enforces particle-hole symmetry of the bath hybridization \
function. Not compatible with :code:`REPLICA` or :code:`GENERAL` bath types.
:type bath: np.array(dtype=float)
:param bath: The user-accessible bath array
:type save: bool
:param save: whether to save the symmetry-broken bath for reading
:return: the modified bath array
:rtype: np.array(dtype=float)
"""
ph_symmetrize_bath_site = self.library.ph_symmetrize_bath_site
ph_symmetrize_bath_site.argtypes = [
np.ctypeslib.ndpointer(dtype=float, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
c_int,
]
ph_symmetrize_bath_site.restypes = None
ph_symmetrize_bath_ineq = self.library.ph_symmetrize_bath_ineq
ph_symmetrize_bath_ineq.argtypes = [
np.ctypeslib.ndpointer(dtype=float, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
c_int,
]
ph_symmetrize_bath_ineq.restypes = None
if save:
save_int = 1
else:
save_int = 0
bath_shape = np.asarray(np.shape(bath), dtype=np.int64, order="F")
if (len(bath_shape)) == 1:
ph_symmetrize_bath_site(bath, bath_shape, save_int)
else:
ph_symmetrize_bath_ineq(bath, bath_shape, save_int)
return bath
# save array as .restart file
[docs]
def save_array_as_bath(self, bath):
"""
This function takes the user-accessible array and saves it in the \
correct format for every bath type in the file :code:`hamiltonian.restart`
:type bath: np.array(dtype=float)
:param bath: The user-accessible bath array
:return: Nothing
:rtype: None
"""
save_array_as_bath_site = self.library.save_array_as_bath_site
save_array_as_bath_site.argtypes = [
np.ctypeslib.ndpointer(dtype=float, ndim=1, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
]
save_array_as_bath_site.restypes = None
save_array_as_bath_ineq = self.library.save_array_as_bath_ineq
save_array_as_bath_ineq.argtypes = [
np.ctypeslib.ndpointer(dtype=float, ndim=2, flags="F_CONTIGUOUS"),
np.ctypeslib.ndpointer(dtype=np.int64, ndim=1, flags="F_CONTIGUOUS"),
]
save_array_as_bath_ineq.restypes = None
bath_shape = np.asarray(np.shape(bath), dtype=np.int64, order="F")
if (len(bath_shape)) == 1:
save_array_as_bath_site(bath, bath_shape)
else:
save_array_as_bath_ineq(bath, bath_shape)
return
# auxiliary functions to get/set bath structure. Only works for single-site. User has to do a loop on sites
[docs]
def bath_inspect(self, bath=None, e=None, v=None, d=None, u=None, l=None):
"""
This function translates between the user-accessible continuous \
bath array and the bath components (energy level, hybridization and so on). \
It functions in both ways, given the array returns the components and \
vice-versa. It autonomously determines the type of bath and ED mode.
:type bath: np.array(dtype=float)
:param bath: The user-accessible bath array
:type e: np.array(dtype=float)
:param e: an array for the bath levels ( :f:var:`ed_mode` = \
:code:`NORMAL, NONSU2, SUPERC`). It has dimension [ :data:`Nspin` , \
:data:`Norb` , :data:`Nbath` ] for :code:`NORMAL` bath, \
[ :data:`Nspin` , :data:`Nbath` ] for :code:`HYBRID` bath
:type v: np.array(dtype=float)
:param v: an array for the bath hybridizations ( :f:var:`ed_mode` = \
:code:`NORMAL, NONSU2, SUPERC`). It has dimension [ :data:`Nspin` , :data:`Norb` , \
:data:`Nbath` ] for :code:`NORMAL` and :code:`HYBRID` bath. \
For :code:`REPLICA` bath it has dimension [ :data:`Nbath` ] and for \
:code:`GENERAL` bath it has dimension [ :data:`Nbath` , :data:`Nspin` \
:math:`\\cdot` :data:`Norb` ]
:type d: np.array(dtype=float)
:param d: an array for the bath anomalous enery levels( :f:var:`ed_mode` \
= :code:`SUPERC`). It has dimension [ :data:`Nspin` , :data:`Norb` , \
:data:`Nbath` ] for :code:`NORMAL` bath, [ :data:`Nspin` , :data:`Nbath` ] \
for :code:`HYBRID` bath
:type u: np.array(dtype=float)
:param u: an array for the bath spin off-diagonal hybridization \
( :f:var:`ed_mode` = :code:`NONSU2`). It has dimension [ :data:`Nspin`, \
:data:`Norb` , :data:`Nbath` ] for :code:`NORMAL` and :code:`HYBRID` bath
:type l: np.array(dtype=float)
:param l: an array for the linear coefficients of the Replica matrix \
linear combination ( :f:var:`bath_type` = :code:`REPLICA,GENERAL`). \
It has dimension [ :data:`Nbath` , :code:`Nsym` ], the latter being \
the number of terms on the linear combination
:raise ValueError: if both :code:`bath` and some among :code:`e,u,v,d,l` \
are provided, none is provided, the shapes are inconsistent \
or the inputs are inconsistent with :f:var:`bath_type` and :f:var:`ed_mode` .
:return:
- if :code:`bath` is provided, returns :code:`e,v`, :code:`e,d,v`, \
:code:`e,v,u` or :code:`l,v` depending on :f:var:`ed_mode`
- if :code:`e,v`, :code:`e,d,v`, :code:`e,v,u` or :code:`l,v` \
depending on :f:var:`ed_mode` are provided, returns :code:`bath`
:rtype: np.array(dtype=float)
"""
aux_norb = c_int.in_dll(self.library, "Norb").value
aux_nspin = c_int.in_dll(self.library, "Nspin").value
aux_nbath = c_int.in_dll(self.library, "Nbath").value
settings = (self.get_ed_mode(), self.get_bath_type())
if settings == (1, 1): # normal ed mode, normal bath
if bath is None and e is not None and v is not None:
e = np.asarray(e, order="F")
v = np.asarray(v, order="F")
try:
if np.shape(e) != (aux_nspin, aux_norb, aux_nbath):
raise ValueError("e must be (nspin,norb,nbath)")
if np.shape(v) != (aux_nspin, aux_norb, aux_nbath):
raise ValueError("v must be (nspin,norb,nbath)")
except:
print(np.shape(e))
print(np.shape(v))
raise ValueError("e or v have wrong dimension")
Nb = self.get_bath_dimension()
bath = np.zeros(Nb)
stride = 0
io = 0
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
bath[io] = e[ispin, iorb, ibath]
stride = aux_nspin * aux_norb * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
bath[io] = v[ispin, iorb, ibath]
return bath
elif bath is not None and e is None and v is None: # e and v are none
bath = np.asarray(bath, order="F")
Nb = self.get_bath_dimension()
if np.shape(bath)[0] != Nb:
raise ValueError("bath has the wrong length")
e = np.zeros((aux_nspin, aux_norb, aux_nbath))
v = np.zeros((aux_nspin, aux_norb, aux_nbath))
stride = 0
io = 0
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
e[ispin, iorb, ibath] = bath[io]
stride = aux_nspin * aux_norb * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
v[ispin, iorb, ibath] = bath[io]
return e, v
else:
raise ValueError("Wrong input for normal/normal")
elif settings == (2, 1): # superc ed mode, normal bath
if bath is None and e is not None and v is not None and d is not None:
e = np.asarray(e, order="F")
v = np.asarray(v, order="F")
d = np.asarray(u, order="F")
try:
if np.shape(e) != (aux_nspin, aux_norb, aux_nbath):
raise ValueError("e must be (nspin,norb,nbath)")
if np.shape(d) != (aux_nspin, aux_norb, aux_nbath):
raise ValueError("d must be (nspin,norb,nbath)")
if np.shape(v) != (aux_nspin, aux_norb, aux_nbath):
raise ValueError("v must be (nspin,norb,nbath)")
except:
raise ValueError("e,d or v have wrong dimension")
Nb = self.get_bath_dimension()
bath = np.zeros(Nb)
stride = 0
io = 0
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
bath[io] = e[ispin, iorb, ibath]
stride = aux_nspin * aux_norb * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
bath[io] = d[ispin, iorb, ibath]
stride = 2 * aux_nspin * aux_norb * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
bath[io] = v[ispin, iorb, ibath]
return bath
elif bath is None and e is None and v is None and d is None:
bath = np.asarray(bath, order="F")
Nb = self.get_bath_dimension()
if np.shape(bath)[0] != Nb:
raise ValueError("bath has the wrong length")
e = np.zeros((aux_nspin, aux_norb, aux_nbath))
v = np.zeros((aux_nspin, aux_norb, aux_nbath))
d = np.zeros((aux_nspin, aux_norb, aux_nbath))
stride = 0
io = 0
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
e[ispin, iorb, ibath] = bath[io]
stride = aux_nspin * aux_norb * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
d[ispin, iorb, ibath] = bath[io]
stride = 2 * aux_nspin * aux_norb * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
v[ispin, iorb, ibath] = bath[io]
return e, d, v
else:
raise ValueError("Wrong input for superc/normal")
elif settings == (3, 1): # nonsu2 ed mode, normal bath
if bath is None and e is not None and v is not None and u is not None:
try:
e = np.asarray(e, order="F")
v = np.asarray(v, order="F")
u = np.asarray(u, order="F")
if np.shape(e) != (aux_nspin, aux_norb, aux_nbath):
raise ValueError("e must be (nspin,norb,nbath)")
if np.shape(v) != (aux_nspin, aux_norb, aux_nbath):
raise ValueError("v must be (nspin,norb,nbath)")
if np.shape(u) != (aux_nspin, aux_norb, aux_nbath):
raise ValueError("u must be (nspin,norb,nbath)")
except:
raise ValueError("e,v or u have wrong dimension")
Nb = self.get_bath_dimension()
bath = np.zeros(Nb)
stride = 0
io = 0
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
bath[io] = e[ispin, iorb, ibath]
stride = aux_nspin * aux_norb * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
bath[io] = v[ispin, iorb, ibath]
stride = 2 * aux_nspin * aux_norb * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
bath[io] = u[ispin, iorb, ibath]
return bath
elif bath is not None and e is None and v is None and u is None:
bath = np.asarray(bath, order="F")
Nb = self.get_bath_dimension()
if np.shape(bath)[0] != Nb:
raise ValueError("bath has the wrong length")
e = np.zeros((aux_nspin, aux_norb, aux_nbath))
v = np.zeros((aux_nspin, aux_norb, aux_nbath))
u = np.zeros((aux_nspin, aux_norb, aux_nbath))
stride = 0
io = 0
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
e[ispin, iorb, ibath] = bath[io]
stride = aux_nspin * aux_norb * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
v[ispin, iorb, ibath] = bath[io]
stride = 2 * aux_nspin * aux_norb * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
u[ispin, iorb, ibath] = bath[io]
return e, v, u
else:
raise ValueError("Wrong input for nonsu2/normal")
elif settings == (1, 2): # normal ed mode, hybrid bath
if bath is None and e is not None and v is not None:
try:
e = np.asarray(e, order="F")
v = np.asarray(v, order="F")
if np.shape(e) != (aux_nspin, aux_nbath):
raise ValueError("e must be (nspin,nbath)")
if np.shape(v) != (aux_nspin, aux_norb, aux_nbath):
raise ValueError("v must be (nspin,norb,nbath)")
except:
print(np.shape(e))
print(np.shape(v))
raise ValueError("e or v have wrong dimension")
Nb = self.get_bath_dimension()
bath = np.zeros(Nb)
stride = 0
io = 0
for ispin in range(aux_nspin):
for ibath in range(aux_nbath):
io = stride + ibath + (ispin) * aux_nbath
bath[io] = e[ispin, ibath]
stride = aux_nspin * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
bath[io] = v[ispin, iorb, ibath]
return bath
elif bath is not None and e is None and v is None:
bath = np.asarray(bath, order="F")
Nb = self.get_bath_dimension()
if np.shape(bath)[0] != Nb:
raise ValueError("bath has the wrong length")
e = np.zeros((aux_nspin, aux_nbath))
v = np.zeros((aux_nspin, aux_norb, aux_nbath))
stride = 0
io = 0
for ispin in range(aux_nspin):
for ibath in range(aux_nbath):
io = stride + ibath + ispin * aux_nbath
e[ispin, ibath] = bath[io]
stride = aux_nspin * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
v[ispin, iorb, ibath] = bath[io]
return e, v
else:
raise ValueError("Wrong input for normal/hybrid")
elif settings == (2, 2): # superc ed mode, hybrid bath
if bath is None and e is not None and v is not None and d is not None:
try:
e = np.asarray(e, order="F")
d = np.asarray(d, order="F")
v = np.asarray(v, order="F")
if np.shape(e) != (aux_nspin, aux_nbath):
raise ValueError("e must be (nspin,nbath)")
if np.shape(d) != (aux_nspin, aux_nbath):
raise ValueError("d must be (nspin,nbath)")
if np.shape(v) != (aux_nspin, aux_norb, aux_nbath):
raise ValueError("v must be (nspin,norb,nbath)")
except:
raise ValueError("e,d or v have wrong dimension")
Nb = self.get_bath_dimension()
bath = np.zeros(Nb)
stride = 0
io = 0
for ispin in range(aux_nspin):
for ibath in range(aux_nbath):
io = stride + ibath + (ispin) * aux_nbath
bath[io] = e[ispin, ibath]
stride = aux_nspin * aux_nbath
for ispin in range(aux_nspin):
for ibath in range(aux_nbath):
io = stride + ibath + (ispin) * aux_nbath
bath[io] = bath_d[ispin, ibath]
stride = 2 * aux_nspin * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
bath[io] = v[ispin, iorb, ibath]
return bath
elif bath is not None and e is None and v is None and d is None:
bath = np.asarray(bath, order="F")
Nb = self.get_bath_dimension()
if np.shape(bath)[0] != Nb:
raise ValueError("bath has the wrong length")
e = np.zeros((aux_nspin, aux_nbath))
d = np.zeros((aux_nspin, aux_nbath))
v = np.zeros((aux_nspin, aux_norb, aux_nbath))
stride = 0
io = 0
for ispin in range(aux_nspin):
for ibath in range(aux_nbath):
io = stride + ibath + (ispin) * aux_nbath
e[ispin, ibath] = bath[io]
stride = aux_nspin * aux_nbath
for ispin in range(aux_nspin):
for ibath in range(aux_nbath):
io = stride + ibath + (ispin) * aux_nbath
d[ispin, ibath] = bath[io]
stride = 2 * aux_nspin * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
v[ispin, iorb, ibath] = bath[io]
return e, d, v
else:
raise ValueError("Wrong input for superc/hybrid")
elif settings == (3, 2): # nonsu2 ed mode, hybrid bath
if bath is None and e is not None and v is not None and u is not None:
try:
e = np.asarray(e, order="F")
v = np.asarray(v, order="F")
u = np.asarray(u, order="F")
if np.shape(e) != (aux_nspin, aux_nbath):
raise ValueError("e must be (nspin,norb,nbath)")
if np.shape(v) != (aux_nspin, aux_norb, aux_nbath):
raise ValueError("v must be (nspin,norb,nbath)")
if np.shape(u) != (aux_nspin, aux_norb, aux_nbath):
raise ValueError("u must be (nspin,norb,nbath)")
except:
raise ValueError("e,v or u have wrong dimension")
Nb = self.get_bath_dimension()
bath = np.zeros(Nb)
stride = 0
io = 0
for ispin in range(aux_nspin):
for ibath in range(aux_nbath):
io = stride + ibath + (ispin) * aux_nbath
bat[io] = e[ispin, ibath]
stride = aux_nspin * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
bath[io] = v[ispin, iorb, ibath]
stride = aux_nspin * aux_nbath + aux_nspin * aux_norb * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
bath[io] = u[ispin, iorb, ibath]
return bath
elif bath is not None and e is None and v is None and u is None:
bath = np.asarray(bath, order="F")
Nb = self.get_bath_dimension()
if np.shape(bath)[0] != Nb:
raise ValueError("bath has the wrong length")
e = np.zeros((aux_nspin, aux_nbath))
v = np.zeros((aux_nspin, aux_norb, aux_nbath))
u = np.zeros((aux_nspin, aux_norb, aux_nbath))
stride = 0
io = 0
for ispin in range(aux_nspin):
for ibath in range(aux_nbath):
io = stride + ibath + (ispin) * aux_nbath
e[ispin, ibath] = bath[io]
stride = aux_nspin * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
v[ispin, iorb, ibath] = bath[io]
stride = aux_nspin * aux_nbath + aux_nspin * aux_norb * aux_nbath
for ispin in range(aux_nspin):
for iorb in range(aux_norb):
for ibath in range(aux_nbath):
io = (
stride
+ ibath
+ (iorb) * aux_nbath
+ (ispin) * aux_nbath * aux_norb
)
u[ispin, iorb, ibath] = bath[io]
return e, v, u
else:
raise ValueError("Wrong input for nonsu2/hybrid")
elif settings == (1, 3) or settings == (2, 3) or settings == (3, 3): # replica bath
if bath is None and l is not None and v is not None:
l = np.asarray(l, order="F")
v = np.asarray(v, order="F")
if self.Nsym is None:
raise ValueError("Nsym is none, is Hreplica initialized?")
if np.shape(l) != (aux_nbath, self.Nsym):
raise ValueError("l must be (nbath,nsym)")
if np.shape(v) != (aux_nbath):
raise ValueError("v must be (nbath)")
Nb = self.get_bath_dimension()
bath = np.zeros(Nb)
io = 0
il = 0
bath[io] = self.Nsym
io += 1
for ibath in range(aux_nbath):
bath[io] = v[ibath]
io += 1
il = 0
for il in range(Nsym):
bath[io] = l[ibath, il]
io += 1
il += 1
return bath
elif bath is not None and l is None and v is None: # e and v are none
bath = np.asarray(bath, order="F")
Nb = self.get_bath_dimension()
if np.shape(bath)[0] != Nb:
raise ValueError("bath has the wrong length")
if bath[0] != self.Nsym:
raise ValueError("bath[0] is not Nsym")
l = np.zeros((aux_nbath, self.Nsym))
v = np.zeros((aux_nbath))
io = 1
il = 0
for ibath in range(aux_nbath):
v[ibath] = bath[io]
io += 1
il = 0
for il in range(Nsym):
l[ibath, il] = bath[io]
io += 1
il += 1
return l, v
else:
raise ValueError("Wrong input for replica")
elif settings == (1, 4) or settings == (2, 4) or settings == (3, 4): # general bath
if bath is None and l is not None and v is not None:
l = np.asarray(l, order="F")
v = np.asarray(v, order="F")
if self.Nsym is None:
raise ValueError("Nsym is none, is Hgeneral initialized?")
if np.shape(l) != (aux_nbath, self.Nsym):
raise ValueError("l must be (Nbath,Nsym)")
if np.shape(v) != (aux_nbath, aux_nspin * aux_norb):
raise ValueError("v must be (Nbath,Nspin*Norb)")
Nb = self.get_bath_dimension()
bath = np.zeros(Nb)
io = 0
il = 0
iv = 0
bath[io] = self.Nsym
io += 1
for ibath in range(aux_nbath):
iv = 0
for iv in range(aux_nspin * aux_norb):
bath[io] = v[ibath, iv]
io += 1
iv += 1
il = 0
for il in range(Nsym):
bath[io] = l[ibath, il]
io += 1
il += 1
return bath
elif bath is not None and l is None and v is None: # e and v are none
bath = np.asarray(bath, order="F")
Nb = self.get_bath_dimension()
if np.shape(bath)[0] != Nb:
raise ValueError("bath has the wrong length")
if bath[0] != self.Nsym:
raise ValueError("bath[0] is not Nsym")
l = np.zeros((aux_nbath, self.Nsym))
v = np.zeros((aux_nbath, aux_nspin * aux_norb))
io = 1
il = 0
iv = 0
for ibath in range(aux_nbath):
iv = 0
for iv in range(aux_nspin * aux_norb):
v[ibath, iv] = bath[io]
io += 1
iv += 1
il = 0
for il in range(Nsym):
l[ibath, il] = bath[io]
io += 1
il += 1
return l, v
else:
raise ValueError("Wrong input for replica")
else:
raise ValueError("EDmode/bath combination not valid or not implemented.")