void
  MultiVectorMatrix::AddRightMultMatrix(Number a,
                                        const MultiVectorMatrix& U,
                                        const Matrix& C,
                                        Number b)
  {
    DBG_ASSERT(NRows()==U.NRows());
    DBG_ASSERT(U.NCols()==C.NRows());
    DBG_ASSERT(NCols()==C.NCols());

    if (b==0.) {
      FillWithNewVectors();
    }

    // ToDo: For now, we simply use MatrixVector multiplications, but
    // we might be more efficient (at least in the non-parallel case)
    // if we used Level 3 Blas
    SmartPtr<const DenseVectorSpace> mydspace = new DenseVectorSpace(C.NRows());
    SmartPtr<DenseVector> mydvec = mydspace->MakeNewDenseVector();

    const DenseGenMatrix* dgm_C = static_cast<const DenseGenMatrix*>(&C);
    DBG_ASSERT(dynamic_cast<const DenseGenMatrix*>(&C));
    for (Index i=0; i<NCols(); i++) {
      const Number* CValues = dgm_C->Values();
      Number* myvalues = mydvec->Values();
      for (Index j=0; j<U.NCols(); j++) {
        myvalues[j] = CValues[i*C.NRows() + j];
      }
      U.MultVector(a, *mydvec, b, *Vec(i));
    }
    ObjectChanged();
  }
Exemple #2
0
ESymSolverStatus LowRankAugSystemSolver::Solve(
   const SymMatrix* W,
   double           W_factor,
   const Vector*    D_x,
   double           delta_x,
   const Vector*    D_s,
   double           delta_s,
   const Matrix*    J_c,
   const Vector*    D_c,
   double           delta_c,
   const Matrix*    J_d,
   const Vector*    D_d,
   double           delta_d,
   const Vector&    rhs_x,
   const Vector&    rhs_s,
   const Vector&    rhs_c,
   const Vector&    rhs_d,
   Vector&          sol_x,
   Vector&          sol_s,
   Vector&          sol_c,
   Vector&          sol_d,
   bool             check_NegEVals,
   Index            numberOfNegEVals
   )
{
   DBG_START_METH("LowRankAugSystemSolver::Solve", dbg_verbosity);

   ESymSolverStatus retval;

   if( first_call_ )
   {
      DBG_ASSERT(IsNull(Wdiag_));
      // Set up the diagonal matrix Wdiag_
      Index dimx = rhs_x.Dim();
      SmartPtr<DiagMatrixSpace> Wdiag_space = new DiagMatrixSpace(dimx);
      Wdiag_ = Wdiag_space->MakeNewDiagMatrix();
   }

   // This might be used with a linear solver that cannot detect the
   // inertia.  In that case, we should not asked for checking the
   // number of negative eigenvalues.
   if( !aug_system_solver_->ProvidesInertia() )
   {
      check_NegEVals = false;
   }

   if( first_call_
      || AugmentedSystemRequiresChange(W, W_factor, D_x, delta_x, D_s, delta_s, *J_c, D_c, delta_c, *J_d, D_d,
         delta_d) )
   {
      retval = UpdateFactorization(W, W_factor, D_x, delta_x, D_s, delta_s, *J_c, D_c, delta_c, *J_d, D_d, delta_d,
         rhs_x, rhs_s, rhs_c, rhs_d, check_NegEVals, numberOfNegEVals);
      if( retval != SYMSOLVER_SUCCESS )
      {
         return retval;
      }

      // Store the tags
      w_tag_ = W->GetTag();
      w_factor_ = W_factor;
      if( D_x )
      {
         d_x_tag_ = D_x->GetTag();
      }
      else
      {
         d_x_tag_ = 0;
      }
      delta_x_ = delta_x;
      if( D_s )
      {
         d_s_tag_ = D_s->GetTag();
      }
      else
      {
         d_s_tag_ = 0;
      }
      delta_s_ = delta_s;
      if( J_c )
      {
         j_c_tag_ = J_c->GetTag();
      }
      else
      {
         j_c_tag_ = 0;
      }
      if( D_c )
      {
         d_c_tag_ = D_c->GetTag();
      }
      else
      {
         d_c_tag_ = 0;
      }
      delta_c_ = delta_c;
      if( J_d )
      {
         j_d_tag_ = J_d->GetTag();
      }
      else
      {
         j_d_tag_ = 0;
      }
      if( D_d )
      {
         d_d_tag_ = D_d->GetTag();
      }
      else
      {
         d_d_tag_ = 0;
      }
      delta_d_ = delta_d;

      first_call_ = false;
   }

   // Now solve the system for the given right hand side, using the
   // Sherman-Morrison formula with factorization information already
   // computed.
   retval = aug_system_solver_->Solve(GetRawPtr(Wdiag_), W_factor, D_x, delta_x, D_s, delta_s, J_c, D_c, delta_c, J_d,
      D_d, delta_d, rhs_x, rhs_s, rhs_c, rhs_d, sol_x, sol_s, sol_c, sol_d, check_NegEVals, numberOfNegEVals);
   if( aug_system_solver_->ProvidesInertia() )
   {
      num_neg_evals_ = aug_system_solver_->NumberOfNegEVals();
   }
   if( retval != SYMSOLVER_SUCCESS )
   {
      Jnlst().Printf(J_DETAILED, J_SOLVE_PD_SYSTEM,
         "LowRankAugSystemSolver: AugSystemSolver returned retval = %d for right hand side.\n", retval);
      return retval;
   }

   if( IsValid(Vtilde1_) || IsValid(Utilde2_) )
   {
      // Create a CompoundVectors to store the right hand side and
      // solutions
      SmartPtr<CompoundVector> crhs = compound_sol_vecspace_->MakeNewCompoundVector(false);
      crhs->SetComp(0, rhs_x);
      crhs->SetComp(1, rhs_s);
      crhs->SetComp(2, rhs_c);
      crhs->SetComp(3, rhs_d);
      SmartPtr<CompoundVector> csol = compound_sol_vecspace_->MakeNewCompoundVector(false);
      csol->SetCompNonConst(0, sol_x);
      csol->SetCompNonConst(1, sol_s);
      csol->SetCompNonConst(2, sol_c);
      csol->SetCompNonConst(3, sol_d);

      if( IsValid(Utilde2_) )
      {
         Index nU = Utilde2_->NCols();
         SmartPtr<DenseVectorSpace> bUspace = new DenseVectorSpace(nU);
         SmartPtr<DenseVector> bU = bUspace->MakeNewDenseVector();
         Utilde2_->TransMultVector(1., *crhs, 0., *bU);
         J2_->CholeskySolveVector(*bU);
         Utilde2_->MultVector(1., *bU, 1., *csol);
      }
      if( IsValid(Vtilde1_) )
      {
         Index nV = Vtilde1_->NCols();
         SmartPtr<DenseVectorSpace> bVspace = new DenseVectorSpace(nV);
         SmartPtr<DenseVector> bV = bVspace->MakeNewDenseVector();
         Vtilde1_->TransMultVector(1., *crhs, 0., *bV);
         J1_->CholeskySolveVector(*bV);
         Vtilde1_->MultVector(-1., *bV, 1., *csol);
      }
   }

   return retval;
}