ExampleBasisSystem::ExampleBasisSystem(
  const VectorSpace::space_ptr_t       &space_x
  ,const Range1D                       &var_dep
  ,const Range1D                       &var_indep
  )
  :BasisSystemComposite(
    space_x
    ,var_dep
    ,var_indep
    ,space_x->sub_space(var_dep)
    ,Teuchos::rcp(
      new Teuchos::AbstractFactoryStd<MatrixOpNonsing,MatrixSymDiagStd>())       // C
    ,Teuchos::rcp(
      new Teuchos::AbstractFactoryStd<MatrixSymOp,MatrixSymDiagStd>())           // D'*D
    ,Teuchos::rcp(
      new Teuchos::AbstractFactoryStd<MatrixSymOpNonsing,MatrixSymDiagStd>())    // S
    ,Teuchos::rcp(
      new Teuchos::AbstractFactoryStd<MatrixOp,MatrixSymDiagStd>())              // D
    )
{}
void ExampleBasisSystem::initialize(
  const VectorSpace::space_ptr_t       &space_x
  ,const Range1D                       &var_dep
  ,const Range1D                       &var_indep
  )
{
  namespace mmp = MemMngPack;
  TEUCHOS_TEST_FOR_EXCEPTION(
    space_x.get() == NULL, std::invalid_argument
    ,"ExampleBasisSystem::initialize(...) : Error, space_x must be specified!"
    );
  BasisSystemComposite::initialize(
    space_x
    ,var_dep
    ,var_indep
    ,space_x->sub_space(var_dep)
    ,Teuchos::rcp(new Teuchos::AbstractFactoryStd<MatrixOpNonsing,MatrixSymDiagStd>())      // C
    ,Teuchos::rcp(new Teuchos::AbstractFactoryStd<MatrixSymOp,MatrixSymDiagStd>())          // D'*D
    ,Teuchos::rcp(new Teuchos::AbstractFactoryStd<MatrixSymOpNonsing,MatrixSymDiagStd>())   // S
    ,Teuchos::rcp(new Teuchos::AbstractFactoryStd<MatrixOp,MatrixSymDiagStd>())             // D
    );
}
void ExampleNLPFirstOrder::imp_calc_Gc(
    const Vector& x, bool newx, const FirstOrderInfo& first_order_info) const
{
    namespace rcp = MemMngPack;
    using Teuchos::dyn_cast;
    using AbstractLinAlgPack::Vp_S; // Should not have to do this!

    const index_type
    n = this->n(),
    m = this->m();
    const Range1D
    var_dep   = this->var_dep(),
    var_indep = this->var_indep();

    // Get references to aggregate C and N matrices (if allocated)
    MatrixOpNonsing
    *C_aggr = NULL;
    MatrixOp
    *N_aggr = NULL;
    BasisSystemComposite::get_C_N(
        first_order_info.Gc, &C_aggr, &N_aggr ); // Will return NULLs if Gc is not initialized

    // Allocate C and N matrix objects if not done yet!
    Teuchos::RCP<MatrixOpNonsing>
    C_ptr = Teuchos::null;
    Teuchos::RCP<MatrixOp>
    N_ptr = Teuchos::null;
    if( C_aggr == NULL ) {
        const VectorSpace::space_ptr_t
        space_x  = this->space_x(),
        space_xD = space_x->sub_space(var_dep);
        C_ptr  = Teuchos::rcp(new MatrixSymDiagStd(space_xD->create_member()));
        N_ptr  = Teuchos::rcp(new MatrixSymDiagStd(space_xD->create_member()));
        C_aggr = C_ptr.get();
        N_aggr = N_ptr.get();
    }

    // Get references to concreate C and N matrices
    MatrixSymDiagStd
    &C = dyn_cast<MatrixSymDiagStd>(*C_aggr);
    MatrixSymDiagStd
    &N = dyn_cast<MatrixSymDiagStd>(*N_aggr);
    // Get x = [ x_D' x_I ]
    Vector::vec_ptr_t
    x_D = x.sub_view(var_dep),
    x_I = x.sub_view(var_indep);
    // Set the diagonals of C and N (this is the only computation going on here)
    C.diag() = *x_I;          // C.diag = x_I - 1.0
    Vp_S( &C.diag(),  -1.0 ); // ...
    N.diag() = *x_D;          // N.diag = x_D - 10.0
    Vp_S( &N.diag(), -10.0 ); // ...
    // Initialize the matrix object Gc if not done so yet
    if( C_ptr.get() != NULL ) {
        BasisSystemComposite::initialize_Gc(
            this->space_x(), var_dep, var_indep
            ,this->space_c()
            ,C_ptr, N_ptr
            ,first_order_info.Gc
        );
    }
}