///
/// Functions and classes for advanced modeling
///
/// @author: Yunhai Li (yhli)
///

#ifndef TBPLAS_BUILDER_ADVANCED_H
#define TBPLAS_BUILDER_ADVANCED_H
#include <map>
#include <cassert>
#include <cmath>
#include <tuple>
#include <complex>
#include<Eigen/Dense> 
#include<set>
//定义i为虚部单位
using namespace std::complex_literals;
//使用变长参数（参数类型相同，数量不确定）...
#include <cstdarg>
typedef std::complex<double> complex_t;
typedef int32_t cell_index_t;
typedef uint64_t orbital_index_t;
namespace tbplas::builder {
    complex_t conj_t(const complex_t& t);
/*
    Class for evaluating hopping integrals using Slater-Koster formula.

    The maximum supported angular momentum is l=2 (d orbitals).
    Reference: https://journals.aps.org/pr/abstract/10.1103/PhysRev.94.1498

    The reason why we make orbital labels as attributes is to avoid misspelling,
    which is likely to happen as we have to repeat them many times.
*/
/*

这是一个用于使用 Slater-Koster 公式计算跃迁积分的类。

最大支持的角动量是 l=2（d轨道）。
参考文献: https://journals.aps.org/pr/abstract/10.1103/PhysRev.94.1498

将轨道标签设为属性的原因是为了避免拼写错误，因为我们需要多次重复它们。
*/

/// @brief Class for evaluating hopping integrals using Slater-Koster formula.
/// The maximum supported angular momentum is l=2 (d orbitals).
/// Reference: https://journals.aps.org/pr/abstract/10.1103/PhysRev.94.1498
/// The reason why we make orbital labels as attributes is to avoid misspelling,
/// which is likely to happen as we have to repeat them many times.
class SK 
{
private:
    std::string s_ = "s";
    std::string px_ = "px";
    std::string py_ = "py";
    std::string pz_ = "pz";
    std::string dxy_ = "dxy";
    std::string dyz_ = "dyz";
    std::string dzx_ = "dzx";
    std::string dx2_y2_ = "dx2-y2";
    std::string dz2_ = "dz2";
    std::set<std::string> p_labels_ = { px_,py_,pz_ };
    std::set<std::string> d_labels_ = { dxy_,dyz_,dzx_,dx2_y2_,dz2_ };
    double sqrt3_ = std::sqrt(3.0);
    double half_sqrt3_ = sqrt3_ * 0.5;

/*
    检查 p 轨道标签的合法性。

    :param labels: 要检查的标签
    :return: None
    :raises ValueError: 如果任何一个标签不在 self.p_labels 中
*/
/// @brief Check the sanity of labels of p orbitals.
/// @param[in] label labels to check
/// @warning check label in p_labels_
void check_p_labels_(const std::string& label);

/*
    检查 D 轨道标签的合法性。

    :param labels: 要检查的标签
    :return: None
    :raises ValueError: 如果任何一个标签不在 self.p_labels 中
*/
/// @brief Check the sanity of labels of d orbitals.
/// @param[in] label labels to check
/// @warning check label in d_labels_
void check_d_labels_(const std::string& label);

/*
根据新的x轴对给定的向量进行排列。(坐标循环左移、右移、不移)

:param vector: 要排列的向量
:param x_new: 新x轴的标签
:return: 排列后的向量
:raises ValueError: 如果x_new不是'x'、'y'或'z'
*/
/// @brief Permute a given vector according to the new x_axis.
/// @param[in] vector vector to permute
/// @param[in] x_new label of the new x_axis
/// @return permuted vector  
/// @warning check x_new in 'x', 'y', 'z'
Eigen::Vector3d perm_vector_(const Eigen::Vector3d& vector, const char x_new);

/*
置换后重新映射轨道标签。(映射生成新的标签)

:param label：要重新映射的轨道标签
:param x_new：新“x”方向的索引
:return：重新映射的轨道标签
:raises ValueError：如果 x_new 不在“x”、“y”、“z”中
*/
/// @brief Remap orbital label after permutation.
/// @param[in] label orbital label to remap
/// @param[in] x_new index of the new 'x' direction
/// @return remapped orbital label
/// @warning check x_new in 'x', 'y', 'z'
std::string remap_label_(const std::string& label, const char x_new); 

/*
   计算给定位移向量的方向余弦。

    :param r: 位移向量的笛卡尔坐标
    :return: 沿 x、y 和 z 方向的方向余弦
    :raises ValueError: 如果 r 的范数太小
*/
 /// @brief Evaluate direction cosines for given displacement vector.
 /// @param r[in] Cartesian coordinates of the displacement vector 
 /// @return the direction cosines along x, y, and z directions
 /// @warning check the norm of r greater than 1e-15
 std::tuple<double, double, double> eval_dir_cos_(const Eigen::Vector3d& r);

public:
    

/*
    计算跃迁积分 <s,0|H|s,r>。

    :param v_sss: V_ss_sigma
    :return: 跃迁积分
*/
/// @brief Evaluate the hopping integral <s,0|H|s,r>
/// @param[in] v_sss V_ss_sigma
/// @return hopping integral
complex_t ss(const complex_t& v_sss = 1.0);

/*
   计算跃迁积分 <s,0|H|p,r>。

    :param r: 位移向量的笛卡尔坐标
    :param label_p: p轨道的标签
    :param v_sps: V_sp_sigma
    :return: 跃迁积分
    :raises ValueError: 如果 label_p 不在 self.p_labels 中
*/
/// @brief Evaluate the hopping integral <s,0|H|p,r>.
/// @param[in] r Cartesian coordinates of the displacement vector 
/// @param[in] label_p label of p orbital
/// @param[in] v_sps V_sp_sigma
/// @return hopping integral
/// @warning check label_p in p_labels_
complex_t sp(const Eigen::Vector3d& r, const std::string& label_p = "px", const complex_t& v_sps = 0.0);

/*
计算跳跃积分 <s,0|H|d,r>。

:param r: 位移矢量的笛卡尔坐标
:param label_d: d 轨道的标签
:param v_sds: V_sd_sigma
:return: 跳跃积分
:raises ValueError: 如果 label_d 不在 self.d_labels 中
*/
/// @brief Evaluate the hopping integral <s,0|H|d,r>.
/// @param[in] r Cartesian coordinates of the displacement vector
/// @param[in] label_d label of d orbital
/// @param[in] v_sds V_sd_sigma
/// @return hopping integral
/// @warning check label_d in d_labels_
complex_t sd(const Eigen::Vector3d& r, const std::string& label_d = "dxy", const complex_t& v_sds = 0.0);

/*
计算跳跃积分 <p_i,0|H|p_j,r>。

:param r: 位移矢量的笛卡尔坐标
:param label_i: p_i 轨道的标签
:param label_j: p_j 轨道的标签
:param v_pps: V_pp_sigma
:param v_ppp: V_pp_pi
:return: 跳跃积分
:raises ValueError: 如果 label_i 或 label_j 不在 self.p_labels 中
*/
/// @brief Evaluate the hopping integral <p_i,0|H|p_j,r>.
/// @param r Cartesian coordinates of the displacement vector
/// @param label_i label of p_i orbital
/// @param label_j label of p_j orbital
/// @param v_pps V_pp_sigma
/// @param v_ppp  V_pp_pi
/// @return hopping integral
/// @warning check label_i in p_labels_ and label_j in p_labels_
complex_t pp(const Eigen::Vector3d& r, const std::string& label_i = "px", const std::string& label_j = "px", const complex_t& v_pps = 0.0, const complex_t& v_ppp = 0.0);

/*
计算跳跃积分 <p,0|H|d,r>。

:param r: 位移矢量的笛卡尔坐标
:param label_p: p 轨道的标签
:param label_d: d 轨道的标签
:param v_pds: V_pd_sigma
:param v_pdp: V_pd_pi
:return: 跳跃积分
:raises ValueError: 如果 label_p 不在 self.p_labels 中或
label_d 不在 self.d_labels 中
*/
/// @brief Evaluate the hopping integral <p,0|H|d,r>.
/// @param r Cartesian coordinates of the displacement vector
/// @param label_p label of p orbital
/// @param label_d label of d orbital
/// @param v_pds V_pd_sigma
/// @param v_pdp V_pd_pi
/// @return hopping integral
/// @warning check label_i in p_labels_ and label_j in p_labels_
complex_t pd(const Eigen::Vector3d& r, const std::string& label_p = "px", const std::string& label_d = "dxy", const complex_t& v_pds = 0.0, const complex_t& v_pdp = 0.0);

/*
计算跳跃积分 <d_i,0|H|d_j,r>。

:param r: 位移矢量的笛卡尔坐标
:param label_i: d_i 轨道的标签
:param label_j: d_j 轨道的标签
:param v_dds: V_dd_sigma
:param v_ddp: V_dd_pi
:param v_ddd: V_dd_delta
:return: 跳跃积分
:raises ValueError: 如果 label_i 或 label_j 不在 self.d_labels 中
*/
/// @brief Evaluate the hopping integral <d_i,0|H|d_j,r>.
/// @param r Cartesian coordinates of the displacement vector
/// @param label_i label of d_i orbital
/// @param label_j label of d_j orbital
/// @param v_dds  V_dd_sigma
/// @param v_ddp V_dd_pi
/// @param v_ddd V_dd_delta
/// @return hopping integral
/// @warning check label_i in p_labels_ and label_j in p_labels_
complex_t dd(const Eigen::Vector3d& r, const std::string& label_i = "dxy", const std::string& label_j = "dxy", const complex_t& v_dds = 0.0, const complex_t& v_ddp = 0.0, const complex_t& v_ddd = 0.0);

/// @brief Evaluate the hopping integral <p,0|H|s,r>.
/// @param r Cartesian coordinates of the displacement vector
/// @param label_p label of p orbital
/// @param v_sps V_sp_sigma
/// @return hopping integral
/// @warning check label_p in p_labels_
complex_t ps(const Eigen::Vector3d& r, const std::string& label_p = "px", const complex_t& v_sps = 0.0);

/// @brief Evaluate the hopping integral <d,0|H|s,r>.
/// @param r Cartesian coordinates of the displacement vector
/// @param label_d label of d orbital
/// @param v_sds V_sd_sigma
/// @return hopping integral
/// @warning check label_d in d_labels_
complex_t ds(const Eigen::Vector3d& r, const std::string& label_d = "dxy", const complex_t& v_sds = 0.0);

/// @brief Evaluate the hopping integral <d,0|H|p,r>.
/// @param r Cartesian coordinates of the displacement vector
/// @param label_p label of p orbital
/// @param label_d label of d orbital
/// @param v_pds V_pd_sigma
/// @param v_pdp V_pd_pi
/// @return hopping integral
/// @warning check label_p in p_labels_ and label_d in d_labels_
complex_t dp(const Eigen::Vector3d& r, const std::string& label_p = "px", const std::string& label_d = "dxy", const complex_t& v_pds = 0.0, const complex_t& v_pdp = 0.0);

//用于评估跳跃积分<i,0|H|j,r>的通用接口。
/// @brief Common interface for evaluating hopping integral <i,0|H|j,r>.
/// @param r Cartesian coordinates of the displacement vector
/// @param label_i label for orbital i
/// @param label_j label for orbital j
/// @param v_sss V_ss_sigma
/// @param v_sps V_sp_sigma
/// @param v_sds V_sd_sigma
/// @param v_pps V_pp_sigma
/// @param v_ppp V_pp_pi
/// @param v_pds V_pd_sigma
/// @param v_pdp V_pd_pi
/// @param v_dds V_dd_sigma
/// @param v_ddp V_dd_pi
/// @param v_ddd V_dd_delta
/// @return hopping integral
complex_t eval(const Eigen::Vector3d& r, const std::string& label_i = "s", const std::string& label_j = "s",
    const complex_t& v_sss = 0.0, const complex_t& v_sps = 0.0, const complex_t& v_sds = 0.0,
    const complex_t& v_pps = 0.0, const complex_t& v_ppp = 0.0, const complex_t& v_pds = 0.0, const complex_t& v_pdp = 0.0,
    const complex_t& v_dds = 0.0, const complex_t& v_ddp = 0.0, const complex_t& v_ddd = 0.0);

};


/// @brief Hardcoded spin-orbit coupling glossary, including f orbitals

}
#endif // TBPLAS_BUILDER_ADVANCED_H