예제 #1
0
/**
 * Diagonalize the block diagonal matrix. Needs lapack. Differs from MomHamiltonian::ExactDiagonalizeFull that
 * is diagonalize block per block and keeps the momentum associated with each eigenvalue.
 * @param calc_eigenvectors set to true to calculate the eigenvectors. The hamiltonian
 * matrix is then overwritten by the vectors.
 * @return a vector of pairs. The first member of the pair is the momentum, the second is
 * the eigenvalue. The vector is sorted to the eigenvalues.
 */
std::vector< std::pair<int,double> > MomHamiltonian::ExactMomDiagonalizeFull(bool calc_eigenvectors)
{
    std::vector<double> eigs(dim);
    std::vector< std::pair<int, double> > energy;

    int offset = 0;

    for(int B=0; B<L; B++)
    {
        int dim = mombase[B].size();

        Diagonalize(dim, blockmat[B].get(), &eigs[offset], calc_eigenvectors);

        for(int i=0; i<dim; i++)
            energy.push_back(std::make_pair(B,eigs[offset+i]));

        offset += dim;
    }

    std::sort(energy.begin(), energy.end(),
              [](const std::pair<int,double> & a, const std::pair<int,double> & b) -> bool
    {
        return a.second < b.second;
    });

    return energy;
}
예제 #2
0
/**
 * Exactly calculates the eigenvalues of the matrix.
 * Needs lapack.
 * @param calc_eigenvectors set to true to calculate the eigenvectors. The hamiltonian
 * matrix is then overwritten by the vectors.
 * @return the vector of the sorted eigenvalues
 */
std::vector<double> MomHamiltonian::ExactDiagonalizeFull(bool calc_eigenvectors)
{
    std::vector<double> eigenvalues(dim);

    int offset = 0;

    for(int B=0; B<L; B++)
    {
        int dim = mombase[B].size();

        Diagonalize(dim, blockmat[B].get(), &eigenvalues[offset], calc_eigenvectors);

        offset += dim;
    }

    std::sort(eigenvalues.begin(), eigenvalues.end());

    return eigenvalues;
}
/**
 * diag = u^* m v^+
 *
 * @param m mass matrix
 * @param u mixing matrix
 * @param v mixing matrix
 * @param eigenvalues eigenvalues (sorted)
 */
void Diagonalize(const softsusy::DoubleMatrix& m, softsusy::ComplexMatrix& u,
                 softsusy::ComplexMatrix& v, softsusy::DoubleVector& eigenvalues)
{
#ifdef ENABLE_DEBUG
   const int c = m.displayCols();
   if (m.displayRows() != c || eigenvalues.displayEnd() != c ||
       v.displayCols() != c || v.displayRows() !=c || c > 10) {
      ostringstream ii;
      ii << "Error: Trying to diagonalise matrix \n" << m;
      throw ii.str();
   }
#endif
   softsusy::DoubleMatrix realU(u.real()), realV(v.real());
   Diagonalize(m, realU, realV, eigenvalues);

   const softsusy::ComplexMatrix trans(phase_rotation(eigenvalues));
   u = trans * realU;
   v = trans * realV;
   eigenvalues = eigenvalues.apply(fabs);
}
예제 #4
0
	Matrix3 Diagonalized(Mat3Param matrix)
	{
		Matrix3 newMatrix = matrix;
		Diagonalize(&newMatrix);
		return newMatrix;
	}
예제 #5
0
/**
 * This methods calculates the eigenvalues for a range of U values. The interval is [Ubegin, Uend]
 * with a stepsize of step. The resulting data is written to a file in the HDF5 file format.
 * @param Ubegin the startpoint for U
 * @param Uend the endpoint for U. We demand Ubegin < Uend
 * @param step the stepsize to use for U
 * @param filename the name of the file write to written the eigenvalues to
 */
void MomHamiltonian::GenerateData(double Ubegin, double Uend, double step, std::string filename)
{
    double Ucur = Ubegin;

    if( !baseUp.size() || !baseDown.size() )
        BuildBase();

    std::vector<double> eigenvalues(dim);

    hid_t       file_id, group_id, dataset_id, dataspace_id, attribute_id;
    herr_t      status;

    file_id = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
    HDF5_STATUS_CHECK(file_id);

    group_id = H5Gcreate(file_id, "run", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
    HDF5_STATUS_CHECK(group_id);

    dataspace_id = H5Screate(H5S_SCALAR);

    attribute_id = H5Acreate (group_id, "L", H5T_STD_I32LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
    status = H5Awrite (attribute_id, H5T_NATIVE_INT, &L );
    HDF5_STATUS_CHECK(status);
    status = H5Aclose(attribute_id);
    HDF5_STATUS_CHECK(status);

    attribute_id = H5Acreate (group_id, "Nu", H5T_STD_I32LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
    status = H5Awrite (attribute_id, H5T_NATIVE_INT, &Nu );
    HDF5_STATUS_CHECK(status);
    status = H5Aclose(attribute_id);
    HDF5_STATUS_CHECK(status);

    attribute_id = H5Acreate (group_id, "Nd", H5T_STD_I32LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
    status = H5Awrite (attribute_id, H5T_NATIVE_INT, &Nd );
    HDF5_STATUS_CHECK(status);
    status = H5Aclose(attribute_id);
    HDF5_STATUS_CHECK(status);

    attribute_id = H5Acreate (group_id, "J", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
    status = H5Awrite (attribute_id, H5T_NATIVE_DOUBLE, &J );
    HDF5_STATUS_CHECK(status);
    status = H5Aclose(attribute_id);
    HDF5_STATUS_CHECK(status);

    attribute_id = H5Acreate (group_id, "Ubegin", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
    status = H5Awrite (attribute_id, H5T_NATIVE_DOUBLE, &Ubegin );
    HDF5_STATUS_CHECK(status);
    status = H5Aclose(attribute_id);
    HDF5_STATUS_CHECK(status);

    attribute_id = H5Acreate (group_id, "Uend", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
    status = H5Awrite (attribute_id, H5T_NATIVE_DOUBLE, &Uend );
    HDF5_STATUS_CHECK(status);
    status = H5Aclose(attribute_id);
    HDF5_STATUS_CHECK(status);

    attribute_id = H5Acreate (group_id, "Ustep", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
    status = H5Awrite (attribute_id, H5T_NATIVE_DOUBLE, &step );
    HDF5_STATUS_CHECK(status);
    status = H5Aclose(attribute_id);
    HDF5_STATUS_CHECK(status);

    status = H5Sclose(dataspace_id);
    HDF5_STATUS_CHECK(status);

    status = H5Gclose(group_id);
    HDF5_STATUS_CHECK(status);

    status = H5Fclose(file_id);
    HDF5_STATUS_CHECK(status);

    std::vector<double> diagonalelements(dim);

    std::vector< std::unique_ptr<double []> > offdiag;
    offdiag.resize(L);

    // make sure that we don't rebuild the whole hamiltonian every time.
    // store the hopping and interaction part seperate so we can just
    // add them in every step
    #pragma omp parallel for
    for(int B=0; B<L; B++)
    {
        int cur_dim = mombase[B].size();
        int offset = 0;

        for(int tmp=0; tmp<B; tmp++)
            offset += mombase[tmp].size();

        offdiag[B].reset(new double [cur_dim*cur_dim]);

        for(int i=0; i<cur_dim; i++)
        {
            int a = mombase[B][i].first;
            int b = mombase[B][i].second;

            diagonalelements[offset+i] = hopping(baseUp[a]) + hopping(baseDown[b]);

            for(int j=i; j<cur_dim; j++)
            {
                int c = mombase[B][j].first;
                int d = mombase[B][j].second;

                offdiag[B][j+cur_dim*i] = 1.0/L*interaction(a,b,c,d);
                offdiag[B][i+cur_dim*j] = offdiag[B][j+cur_dim*i];
            }
        }
    }


    while(Ucur <= Uend)
    {
        std::cout << "U = " << Ucur << std::endl;
        setU(Ucur);

        // make hamiltonian
        #pragma omp parallel for
        for(int B=0; B<L; B++)
        {
            int cur_dim = mombase[B].size();
            int offset = 0;

            for(int tmp=0; tmp<B; tmp++)
                offset += mombase[tmp].size();

            std::memcpy(blockmat[B].get(),offdiag[B].get(),cur_dim*cur_dim*sizeof(double));

            int tmp = cur_dim*cur_dim;
            int inc = 1;
            dscal_(&tmp,&Ucur,blockmat[B].get(),&inc);

            for(int i=0; i<cur_dim; i++)
                blockmat[B][i+cur_dim*i] += diagonalelements[offset+i];
        }


        #pragma omp parallel for
        for(int B=0; B<L; B++)
        {
            int dim = mombase[B].size();
            int offset = 0;

            for(int tmp=0; tmp<B; tmp++)
                offset += mombase[tmp].size();

            Diagonalize(dim, blockmat[B].get(), &eigenvalues[offset], false);
        }

        hid_t U_id;
        std::stringstream name;
        name << std::setprecision(5) << std::fixed << "/run/" << Ucur;

        file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
        HDF5_STATUS_CHECK(file_id);

        U_id = H5Gcreate(file_id, name.str().c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
        HDF5_STATUS_CHECK(U_id);

        for(int B=0; B<L; B++)
        {
            int dim = mombase[B].size();
            int offset = 0;

            for(int tmp=0; tmp<B; tmp++)
                offset += mombase[tmp].size();

            hsize_t dimarr = dim;

            dataspace_id = H5Screate_simple(1, &dimarr, NULL);

            std::stringstream cur_block;
            cur_block << B;
            dataset_id = H5Dcreate(U_id, cur_block.str().c_str(), H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);

            status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &eigenvalues[offset] );
            HDF5_STATUS_CHECK(status);

            status = H5Sclose(dataspace_id);
            HDF5_STATUS_CHECK(status);

            status = H5Dclose(dataset_id);
            HDF5_STATUS_CHECK(status);
        }

        status = H5Gclose(U_id);
        HDF5_STATUS_CHECK(status);

        status = H5Fclose(file_id);
        HDF5_STATUS_CHECK(status);

        Ucur += step;
    }
}