Пример #1
0
void IEFSolver::buildIsotropicMatrix(const Cavity & cav, const IGreensFunction & gf_i, const IGreensFunction & gf_o)
{
    // The total size of the cavity
    size_t cavitySize = cav.size();
    // The number of irreps in the group
    int nrBlocks = cav.pointGroup().nrIrrep();
    // The size of the irreducible portion of the cavity
    int dimBlock = cav.irreducible_size();

    // Compute SI and DI on the whole cavity, regardless of symmetry
    Eigen::MatrixXd SI = gf_i.singleLayer(cav.elements());
    Eigen::MatrixXd DI = gf_i.doubleLayer(cav.elements());

    // Perform symmetry blocking
    // If the group is C1 avoid symmetry blocking, we will just pack the fullPCMMatrix
    // into "block diagonal" when all other manipulations are done.
    if (cav.pointGroup().nrGenerators() != 0) {
        symmetryBlocking(DI, cavitySize, dimBlock, nrBlocks);
        symmetryBlocking(SI, cavitySize, dimBlock, nrBlocks);
    }

    Eigen::MatrixXd a = cav.elementArea().asDiagonal();
    Eigen::MatrixXd aInv = Eigen::MatrixXd::Zero(cavitySize, cavitySize);
    aInv = a.inverse();

    // Tq = -Rv -> q = -(T^-1 * R)v = -Kv
    // T = (2 * M_PI * fact * aInv - DI) * a * SI; R = (2 * M_PI * aInv - DI)
    // fullPCMMatrix_ = K = T^-1 * R * a
    // 1. Form T
    double epsilon = profiles::epsilon(gf_o.permittivity());
    double fact = (epsilon + 1.0)/(epsilon - 1.0);
    fullPCMMatrix_ = (2 * M_PI * fact * aInv - DI) * a * SI;
    // 2. Invert T using LU decomposition with full pivoting
    //    This is a rank-revealing LU decomposition, this allows us
    //    to test if T is invertible before attempting to invert it.
    Eigen::FullPivLU<Eigen::MatrixXd> T_LU(fullPCMMatrix_);
    if (!(T_LU.isInvertible()))
        PCMSOLVER_ERROR("T matrix is not invertible!");
    fullPCMMatrix_ = T_LU.inverse();
    // 3. Multiply T^-1 and R
    fullPCMMatrix_ *= (2 * M_PI * aInv - DI);
    // 4. Multiply by a
    fullPCMMatrix_ *= a;
    // 5. Symmetrize K := (K + K+)/2
    if (hermitivitize_) {
        hermitivitize(fullPCMMatrix_);
    }
    // Pack into a block diagonal matrix
    // For the moment just packs into a std::vector<Eigen::MatrixXd>
    symmetryPacking(blockPCMMatrix_, fullPCMMatrix_, dimBlock, nrBlocks);
    std::ofstream matrixOut("PCM_matrix");
    matrixOut << "fullPCMMatrix" << std::endl;
    matrixOut << fullPCMMatrix_ << std::endl;
    for (int i = 0; i < nrBlocks; ++i) {
        matrixOut << "Block number " << i << std::endl;
        matrixOut << blockPCMMatrix_[i] << std::endl;
    }

    built_ = true;
}
Пример #2
0
void IEFSolver::buildIsotropicMatrix(const Cavity & cav, const IGreensFunction & gf_i, const IGreensFunction & gf_o)
{
  fullPCMMatrix_ = isotropicIEFMatrix(cav, gf_i, profiles::epsilon(gf_o.permittivity()));
  // Symmetrize K := (K + K+)/2
  if (hermitivitize_) {
    hermitivitize(fullPCMMatrix_);
  }
  // Pack into a block diagonal matrix
  // The number of irreps in the group
  int nrBlocks = cav.pointGroup().nrIrrep();
  // The size of the irreducible portion of the cavity
  int dimBlock = cav.irreducible_size();
  // For the moment just packs into a std::vector<Eigen::MatrixXd>
  symmetryPacking(blockPCMMatrix_, fullPCMMatrix_, dimBlock, nrBlocks);

  built_ = true;
}
Пример #3
0
void CPCMSolver::buildSystemMatrix_impl(const Cavity & cavity, const IGreensFunction & gf_i, const IGreensFunction & gf_o)
{
    if (!isotropic_) PCMSOLVER_ERROR("C-PCM is defined only for isotropic environments!");

    // The total size of the cavity
    size_t cavitySize = cavity.size();
    // The number of irreps in the group
    int nrBlocks = cavity.pointGroup().nrIrrep();
    // The size of the irreducible portion of the cavity
    int dimBlock = cavity.irreducible_size();

    // Compute SI on the whole cavity, regardless of symmetry
    Eigen::MatrixXd SI = gf_i.singleLayer(cavity.elements());

    // Perform symmetry blocking only for the SI matrix as the DI matrix is not used.
    // If the group is C1 avoid symmetry blocking, we will just pack the fullPCMMatrix
    // into "block diagonal" when all other manipulations are done.
    if (cavity.pointGroup().nrGenerators() != 0) {
        symmetryBlocking(SI, cavitySize, dimBlock, nrBlocks);
    }

    double epsilon = profiles::epsilon(gf_o.permittivity());
    double fact = (epsilon - 1.0)/(epsilon + correction_);
    // Invert SI  using LU decomposition with full pivoting
    // This is a rank-revealing LU decomposition, this allows us
    // to test if SI is invertible before attempting to invert it.
    Eigen::FullPivLU<Eigen::MatrixXd> SI_LU(SI);
    if (!(SI_LU.isInvertible()))
        PCMSOLVER_ERROR("SI matrix is not invertible!");
    fullPCMMatrix_ = fact * SI_LU.inverse();
    // 5. Symmetrize K := (K + K+)/2
    if (hermitivitize_) {
        hermitivitize(fullPCMMatrix_);
    }
    symmetryPacking(blockPCMMatrix_, fullPCMMatrix_, dimBlock, nrBlocks);

    built_ = true;
}
Пример #4
0
void CPCMSolver::buildSystemMatrix_impl(const ICavity & cavity,
                                        const IGreensFunction & gf_i,
                                        const IGreensFunction & gf_o,
                                        const IBoundaryIntegralOperator & op) {
  if (!isotropic_)
    PCMSOLVER_ERROR("C-PCM is defined only for isotropic environments!");
  TIMER_ON("Computing S");
  double epsilon = gf_o.permittivity();
  S_ = op.computeS(cavity, gf_i);
  S_ /= (epsilon - 1.0) / (epsilon + correction_);
  // Get in Hermitian form
  if (hermitivitize_)
    utils::hermitivitize(S_);
  TIMER_OFF("Computing S");

  // Symmetry-pack
  // The number of irreps in the group
  int nrBlocks = cavity.pointGroup().nrIrrep();
  // The size of the irreducible portion of the cavity
  int dimBlock = cavity.irreducible_size();
  utils::symmetryPacking(blockS_, S_, dimBlock, nrBlocks);

  built_ = true;
}