std::shared_ptr<Matrix> MultiExcitonHamiltonian<VecType>::compute_offdiagonal_1e(const DSubSpace& AB, const DSubSpace& ApBp, std::shared_ptr<const Matrix> hAB) const {
  Coupling term_type = coupling_type(AB,ApBp);

  GammaSQ operatorA;
  GammaSQ operatorB;
  int neleA = AB.template ci<0>()->det()->nelea() + AB.template ci<0>()->det()->neleb();

  switch(term_type) {
    case Coupling::aET :
      operatorA = GammaSQ::CreateAlpha;
      operatorB = GammaSQ::AnnihilateAlpha;
      break;
    case Coupling::inv_aET :
      operatorA = GammaSQ::AnnihilateAlpha;
      operatorB = GammaSQ::CreateAlpha;
      --neleA;
      break;
    case Coupling::bET :
      operatorA = GammaSQ::CreateBeta;
      operatorB = GammaSQ::AnnihilateBeta;
      break;
    case Coupling::inv_bET :
      operatorA = GammaSQ::AnnihilateBeta;
      operatorB = GammaSQ::CreateBeta;
      --neleA;
      break;
    default :
      return std::make_shared<Matrix>(AB.dimerstates(), ApBp.dimerstates());
  }

  Matrix gamma_A = *gammaforest_->template get<0>(AB.offset(), ApBp.offset(), operatorA);
  Matrix gamma_B = *gammaforest_->template get<1>(AB.offset(), ApBp.offset(), operatorB);
  Matrix tmp = gamma_A * (*hAB) ^ gamma_B;

  auto out = std::make_shared<Matrix>(AB.dimerstates(), ApBp.dimerstates());
  reorder_matrix(tmp.data(), out->data(), AB.template nstates<0>(), ApBp.template nstates<0>(), AB.template nstates<1>(), ApBp.template nstates<1>());

  if ( (neleA % 2) == 1 ) out->scale(-1.0);

  return out;
}
std::shared_ptr<Matrix> MultiExcitonHamiltonian<VecType>::couple_blocks(DSubSpace& AB, DSubSpace& ApBp) {
  Coupling term_type = coupling_type(AB, ApBp);

  DSubSpace* space1 = &AB;
  DSubSpace* space2 = &ApBp;

  bool flip = (static_cast<int>(term_type) < 0);

  if (flip) {
    term_type = Coupling(-1*static_cast<int>(term_type));
    std::swap(space1,space2);
  }

  std::shared_ptr<Matrix> out;

  switch(term_type) {
    case Coupling::none :
      out = std::make_shared<Matrix>(space1->dimerstates(), space2->dimerstates()); break;
    case Coupling::diagonal :
      out = compute_inter_2e(*space1, *space2); break;
    case Coupling::aET :
      out = compute_aET(*space1, *space2); break;
    case Coupling::bET :
      out = compute_bET(*space1, *space2); break;
    case Coupling::abFlip :
      out = compute_abFlip(*space1, *space2); break;
    case Coupling::abET :
      out = compute_abET(*space1, *space2); break;
    case Coupling::aaET :
      out = compute_aaET(*space1, *space2); break;
    case Coupling::bbET :
      out = compute_bbET(*space1, *space2); break;
    default :
      throw std::logic_error("Asking for a coupling type that has not been written.");
  }

  if (flip) out = out->transpose();

  return out;
}
InputParameters
validParams<PorousFlowFullySaturatedMassTimeDerivative>()
{
  InputParameters params = validParams<TimeKernel>();
  MooseEnum coupling_type("Hydro ThermoHydro HydroMechanical ThermoHydroMechanical", "Hydro");
  params.addParam<MooseEnum>("coupling_type",
                             coupling_type,
                             "The type of simulation.  For simulations involving Mechanical "
                             "deformations, you will need to supply the correct Biot coefficient.  "
                             "For simulations involving Thermal flows, you will need an associated "
                             "ConstantThermalExpansionCoefficient Material");
  params.addRangeCheckedParam<Real>(
      "biot_coefficient", 1.0, "biot_coefficient>=0 & biot_coefficient<=1", "Biot coefficient");
  params.addParam<bool>("multiply_by_density",
                        true,
                        "If true, then this Kernel is the time derivative of the fluid "
                        "mass.  If false, then this Kernel is the derivative of the "
                        "fluid volume (which is common in poro-mechanics)");
  params.addRequiredParam<UserObjectName>(
      "PorousFlowDictator", "The UserObject that holds the list of Porous-Flow variable names.");
  params.addClassDescription("Fully-saturated version of the single-component, single-phase fluid "
                             "mass derivative wrt time");
  return params;
}
Esempio n. 4
0
void ASDSpinMap<VecType>::couple_blocks(const DimerSubspace<VecType>& AB, const DimerSubspace<VecType>& ApBp) {
  const Coupling term_type = coupling_type(AB, ApBp);

  auto spin_block = std::make_shared<Matrix>(AB.dimerstates(), ApBp.dimerstates());

  if ( (term_type == Coupling::abFlip) || (term_type == Coupling::baFlip) ) {
    std::shared_ptr<VecType> SAp, SBp;

    std::shared_ptr<const VecType> A = AB.template ci<0>();
    std::shared_ptr<const VecType> B = AB.template ci<1>();
    switch (term_type) {
      case Coupling::abFlip :
        SAp = ApBp.template ci<0>()->spin_lower(A->det());
        SBp = ApBp.template ci<1>()->spin_raise(B->det());
        break;
      case Coupling::baFlip :
        SAp = ApBp.template ci<0>()->spin_raise(A->det());
        SBp = ApBp.template ci<1>()->spin_lower(B->det());
        break;
      default: assert(false); break; // Control should never be able to reach here...
    }

    const int nA = AB.template nstates<0>();
    const int nB = AB.template nstates<1>();
    const int nAp = ApBp.template nstates<0>();
    const int nBp = ApBp.template nstates<1>();

    std::vector<double> AdotAp, BdotBp;

    for (int iAp = 0; iAp < nAp; ++iAp) {
      for (int iA = 0; iA < nA; ++iA) {
        AdotAp.push_back(SAp->data(iAp)->dot_product(*A->data(iA)));
      }
    }

    for (int iBp = 0; iBp < nBp; ++iBp) {
      for (int iB = 0; iB < nB; ++iB) {
        BdotBp.push_back(SBp->data(iBp)->dot_product(*B->data(iB)));
      }
    }


    for (int iBp = 0; iBp < nBp; ++iBp) {
      for (int iAp = 0; iAp < nAp; ++iAp) {
        const int iABp = ApBp.dimerindex(iAp,iBp);
        int iAB = 0;
        for (int iB = 0; iB < nB; ++iB) {
          for (int iA = 0; iA < nA; ++iA, ++iAB) {
            spin_block->element(iAB,iABp) += AdotAp[iA+ nA*iAp] * BdotBp[iB + nB*iBp];
          }
        }
      }
    }

    const int n = spin_block->ndim();
    const int m = spin_block->mdim();

    const int ioff = AB.offset();
    const int joff = ApBp.offset();

    for (int ispin = 0; ispin < n; ++ispin) {
      for (int jspin = 0; jspin < m; ++jspin) {
        const double ele = spin_block->element(ispin, jspin);
        if ( std::fabs(ele) > 1.0e-4)  {
          this->emplace(std::make_pair(ispin + ioff, jspin + joff), ele);
          this->emplace(std::make_pair(jspin + joff, ispin + ioff), ele);
        }
      }
    }
  }
}