Analytical Hamiltonian ====================== We have already demonstrated the derivation of analytical Hamiltonian of primitive cell in section :ref:`prim_cell` In this tutorial, we show how to utilize analytical Hamiltonian in calculations. The utilization of analytical Hamiltonian is restrict to the C++ API only. The examples are available at ``tbplas-cpp/samples/speedtest/model.cpp`` and its header ``model.h``, where we define the following model classes using analytical Hamiltonian: .. code-block:: c++ :linenos: /** * @brief Analytical QAH model for testing Berry utilities. * @note Ref: https://www.guanjihuan.com/archives/3932. */ class QAH : public AnalyticalModel { public: QAH(); void build_ham_dense( const Eigen::Vector3d& k_point, Eigen::MatrixXcd& ham, int convention = 1) const; void build_ham_der_dense( const Eigen::Vector3d& k_point, Eigen::MatrixXcd& dh_dka, Eigen::MatrixXcd& dh_dkb, Eigen::MatrixXcd& dh_dkc, int convention = 1) const; }; /** * @brief Analytical CheckerBoard model for testing Berry utilities. * @note Ref: https://www.guanjihuan.com/archives/23989 */ class CheckerBoard : public AnalyticalModel { public: explicit CheckerBoard(int ny); void build_ham_dense( const Eigen::Vector3d& k_point, Eigen::MatrixXcd& ham, int convention = 1) const; private: int ny_ = 5; }; /** * @brief Analytical Haldane model for testing Berry utilities. * @note Ref: https://www.guanjihuan.com/archives/5133 */ class Haldane : public AnalyticalModel { public: Haldane(); void build_ham_dense( const Eigen::Vector3d& k_point, Eigen::MatrixXcd& ham, int convention = 1) const; }; where the implementation can be found in ``model.cpp``. Generally speaking, to utilize the analytical Hamiltonian, the users must derive their own model class from the ``AnalyticalModel`` class defined in ``tbplas-cpp/sources/builder/analytical.h`` and implement the proper member functions: * build_ham_dr_coo: required for AC conductivity calculation using Lindhard * build_ham_curr_csr: required for TBPM AC and DC conductivity calculations * build_ham_csr: required for general TBPM calculations * build_ham_dense: required for general exact diagonalization calculations * build_density_coeff: required for Lindhard and TBPM dynamic polarization calculations * build_ham_der_dense: required for Berry curvature calculation using analytical Hamiltonian derivatives For example, the ``QAH`` class implements the ``build_ham_dense`` and ``build_ham_der_dense`` functions, so it can be utilized for general exact diagonalization and Berry curvature/Chern number calculations using analytical Hamiltonian derivatives. On the contrary, the ``CheckerBoard`` and ``Haldane`` class implement only the ``build_ham_dense`` method, so they can only be utilized for general exact diagonalization and Berry curvature/Chern number calculations using number Hamiltonian derivatives. The utilization of the models can be found in ``tbplas-cpp/samples/speedtest/diag.cpp``: .. code-block:: c++ :linenos: void test_berry() { // QAH model; // Berry solver(model); // CheckerBoard model(20); // Berry solver(model); // Haldane model; // Berry solver(model); model_t model = make_haldane(); #ifdef WITH_OVERLAP model_t overlap = make_overlap(model); Berry solver(model, overlap); #else Berry solver(model); #endif solver.config.k_grid_size = { 100, 100, 1 }; solver.config.num_occ = 1; solver.config.diag_algo = DIAG_ALGO; solver.config.ham_deriv_analytical = true; solver.config.convention = CONVENTION; Timer timer; timer.tic("berry"); solver.config.prefix = "haldane_kubo"; auto data_kubo = solver.calc_berry_curvature_kubo(); solver.config.prefix = "haldane_wilson"; auto data_wilson = solver.calc_berry_curvature_wilson(); timer.toc("berry"); if (solver.is_master()) { timer.report_total_time(); } } Firstly, we use the Haldane model produced by the ``make_haldane`` function, which is an object of C++ ``PrimitiveCell`` class. The output should look like: .. code-block:: text (tbplas) yhli@n02:~/proj/tbplas-cpp/build$ ./bin/speedtest berry Using Eigen backend for diagonalization. Chern number for band 0: -1 Chern number for band 1: 1 Using Eigen backend for diagonalization. Chern number for num_occ 1: -1 berry: 0.371 sec. Then use the analytical ``Haldane`` class: .. code-block:: c++ :linenos: void test_berry() { // QAH model; // Berry solver(model); // CheckerBoard model(20); // Berry solver(model); Haldane model; Berry solver(model); // model_t model = make_haldane(); // #ifdef WITH_OVERLAP // model_t overlap = make_overlap(model); // Berry solver(model, overlap); // #else // Berry solver(model); // #endif solver.config.k_grid_size = { 100, 100, 1 }; solver.config.num_occ = 1; solver.config.diag_algo = DIAG_ALGO; solver.config.ham_deriv_analytical = false; solver.config.convention = CONVENTION; Timer timer; timer.tic("berry"); solver.config.prefix = "haldane_kubo"; auto data_kubo = solver.calc_berry_curvature_kubo(); solver.config.prefix = "haldane_wilson"; auto data_wilson = solver.calc_berry_curvature_wilson(); timer.toc("berry"); if (solver.is_master()) { timer.report_total_time(); } } Note that ``ham_deriv_analytical`` should be set to ``false`` since the ``Haldane`` class does not implement the ``build_ham_dense`` function. The output should look like: .. code-block:: text :linenos: (tbplas) yhli@n02:~/proj/tbplas-cpp/build$ ./bin/speedtest berry Using Eigen backend for diagonalization. Chern number for band 0: 1 Chern number for band 1: -1 Using Eigen backend for diagonalization. Chern number for num_occ 1: 1 berry: 0.330 sec. which is consistent with ``PrimitiveCell`` class, i.e., both bands are topologically non-trivial, and have opposite Chern number.