NOX::Abstract::Group::ReturnType
LOCA::MultiContinuation::CompositeConstraintMVDX::computeDX()
{
    string callingFunction = 
    "LOCA::MultiContinuation::CompositeConstraintMVDX::computeConstraints()";
  NOX::Abstract::Group::ReturnType status;
  NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok;

  if (isValidDX)
    return finalStatus;

  if (isDXZero())
    return finalStatus;

  Teuchos::RCP<NOX::Abstract::MultiVector> dx;
  for (int i=0; i<numConstraintObjects; i++) {

    if (!constraintMVDXPtrs[i]->isDXZero()) {

      // Compute constraint derivative
      status = constraintMVDXPtrs[i]->computeDX();
      finalStatus = 
	globalData->locaErrorCheck->combineAndCheckReturnTypes(
							     status, 
							     finalStatus,
							     callingFunction);
      
      // Copy columns of constraint dervative into composite
      dx = compositeDX->subView(indices[i]);
      *dx = *(constraintMVDXPtrs[i]->getDX());
    }
  }

  return finalStatus;
}
NOX::Abstract::Group::ReturnType
LOCA::MultiContinuation::CompositeConstraint::multiplyDX(
		      double alpha, 
		      const NOX::Abstract::MultiVector& input_x,
	              NOX::Abstract::MultiVector::DenseMatrix& result_p) const
{
  std::string callingFunction = 
    "LOCA::MultiContinuation::CompositeConstraint::multiplyDX()";
  NOX::Abstract::Group::ReturnType status;
  NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok;

  // If dg/dx is zero for every constraint, result_p is zero
  if (isDXZero()) {
    result_p.putScalar(0.0);
    return finalStatus;
  }

  Teuchos::RCP<NOX::Abstract::MultiVector::DenseMatrix> result_p_sub;
  int num_rows;
  int num_cols = result_p.numCols();
  for (int i=0; i<numConstraintObjects; i++) {

    num_rows = constraintPtrs[i]->numConstraints();

    // if dg/dx is zero for this constraint, set corresponding entries of
    // result_p to zero
    if (constraintPtrs[i]->isDXZero()) {
      for (int j=0; j<num_rows; j++)
	for (int k=0; k<num_cols; k++)
	  result_p(indices[i][j],k) = 0.0;
    }
    else {

      // Create a sub view of rows indices[i][0] -- indices[i][end] 
      // of result_p 
      result_p_sub = 
	Teuchos::rcp(new NOX::Abstract::MultiVector::DenseMatrix(Teuchos::View,
								 result_p,
								 num_rows,
								 num_cols,
								 indices[i][0],
								 0));

      status = constraintPtrs[i]->multiplyDX(alpha, input_x, 
					     *result_p_sub);
      finalStatus = 
	globalData->locaErrorCheck->combineAndCheckReturnTypes(
							     status, 
							     finalStatus,
							     callingFunction);
    }

  }

  return finalStatus;
}
NOX::Abstract::Group::ReturnType
LOCA::MultiContinuation::ConstraintInterfaceMVDX::addDX(
                      Teuchos::ETransp transb,
                  double alpha,
                      const NOX::Abstract::MultiVector::DenseMatrix& b,
                  double beta,
                  NOX::Abstract::MultiVector& result_x) const
{
  if (!isDXZero()) {
    const NOX::Abstract::MultiVector* dgdx = getDX();
    result_x.update(transb, alpha, *dgdx, b, beta);
  }
  else
    result_x.scale(beta);

  return NOX::Abstract::Group::Ok;
}
NOX::Abstract::Group::ReturnType
LOCA::MultiContinuation::ConstraintInterfaceMVDX::multiplyDX(
               double alpha,
               const NOX::Abstract::MultiVector& input_x,
               NOX::Abstract::MultiVector::DenseMatrix& result_p) const
{


  if (!isDXZero()) {
    const NOX::Abstract::MultiVector* dgdx = getDX();
    input_x.multiply(alpha, *dgdx, result_p);
  }
  else
    result_p.putScalar(0.0);

  return NOX::Abstract::Group::Ok;
}
NOX::Abstract::Group::ReturnType
LOCA::MultiContinuation::CompositeConstraint::addDX(
		              Teuchos::ETransp transb,
			      double alpha, 
	                      const NOX::Abstract::MultiVector::DenseMatrix& b,
			      double beta,
			      NOX::Abstract::MultiVector& result_x) const
{
  std::string callingFunction = 
    "LOCA::MultiContinuation::CompositeConstraint::addDX()";
  NOX::Abstract::Group::ReturnType status;
  NOX::Abstract::Group::ReturnType finalStatus = NOX::Abstract::Group::Ok;

  // First scale result_x
  result_x.scale(beta);

  // If dg/dx is zero for every constraint, result_x = beta * result_x
  if (isDXZero())
    return finalStatus;

  Teuchos::RCP<NOX::Abstract::MultiVector::DenseMatrix> b_sub;
  Teuchos::RCP<NOX::Abstract::MultiVector> result_x_sub;
  int num_rows;
  int num_cols = result_x.numVectors();
  for (int j=0; j<numConstraintObjects; j++) {
      
    if (!constraintPtrs[j]->isDXZero()) {

      // Create a sub view of rows indices[j][0] -- indices[j][end],
      // of b or b^T
      num_rows = constraintPtrs[j]->numConstraints();
      if (transb == Teuchos::NO_TRANS) {
	b_sub = 
	  Teuchos::rcp(new NOX::Abstract::MultiVector::DenseMatrix(
							       Teuchos::View,
							       b,
							       num_rows,
							       num_cols,
							       indices[j][0],
							       0));
      }
      else {
	b_sub = 
	  Teuchos::rcp(new NOX::Abstract::MultiVector::DenseMatrix(
							       Teuchos::View,
							       b,
							       num_cols,
							       num_rows,
							       0,
							       indices[j][0]));
      }
	
      // Compute result_x = result_x + alpha*(dg/dx)_j*op(b)_j
      status = constraintPtrs[j]->addDX(transb, alpha, *b_sub, 1.0, 
					result_x);
      finalStatus = 
	globalData->locaErrorCheck->combineAndCheckReturnTypes(
							     status, 
							     finalStatus,
							     callingFunction);
    }

  }

  return finalStatus;
}