Exemplo n.º 1
0
void RBEIMConstruction::update_RB_system_matrices()
{
  START_LOG("update_RB_system_matrices()", "RBEIMConstruction");

  Parent::update_RB_system_matrices();

  unsigned int RB_size = get_rb_evaluation().get_n_basis_functions();

  RBEIMEvaluation& eim_eval = libmesh_cast_ref<RBEIMEvaluation&>(get_rb_evaluation());

  // update the EIM interpolation matrix
  for(unsigned int j=0; j<RB_size; j++)
  {
    // Sample the basis functions at the
    // new interpolation point
    get_rb_evaluation().get_basis_function(j).localize(*_ghosted_meshfunction_vector, this->get_dof_map().get_send_list());

    if(!_performing_extra_greedy_step)
    {
      eim_eval.interpolation_matrix(RB_size-1,j) =
        evaluate_mesh_function( eim_eval.interpolation_points_var[RB_size-1],
                                eim_eval.interpolation_points[RB_size-1] );
    }
    else
    {
      eim_eval.extra_interpolation_matrix_row(j) =
        evaluate_mesh_function( eim_eval.extra_interpolation_point_var,
                                eim_eval.extra_interpolation_point );
    }
  }

  STOP_LOG("update_RB_system_matrices()", "RBEIMConstruction");
}
void DerivedRBConstruction<RBConstruction>::enrich_RB_space()
{
  START_LOG("enrich_RB_space()", "DerivedRBConstruction");

  EquationSystems& es = this->get_equation_systems();
  RBConstruction& uber_system = es.get_system<RBConstruction>(uber_system_name);
  const unsigned int uber_size = uber_system.get_rb_evaluation().get_n_basis_functions();

  DenseVector<Number> new_bf = uber_system.get_rb_evaluation().RB_solution;

  // Need to cast the RBEvaluation object
  DerivedRBEvaluation<RBEvaluation>& der_rb_eval =
    libmesh_cast_ref<DerivedRBEvaluation<RBEvaluation>&>(get_rb_evaluation());

  // compute Gram-Schmidt orthogonalization
  DenseVector<Number> proj_sum(uber_size);
  for(unsigned int index=0; index<get_rb_evaluation().get_n_basis_functions(); index++)
  {
    // orthogonalize using the Identity matrix as the inner product,
    // since the uber basis functions should be orthogonal already
    // (i.e. neglect possible rounding errors in uber orthogonalization)
    Number scalar = new_bf.dot(der_rb_eval.derived_basis_functions[index]);
    proj_sum.add(scalar, der_rb_eval.derived_basis_functions[index]);
  }
  new_bf -= proj_sum;
  new_bf.scale(1./new_bf.l2_norm());

  // load the new basis function into the basis_functions vector.
  der_rb_eval.derived_basis_functions.push_back( new_bf );

  STOP_LOG("enrich_RB_space()", "DerivedRBConstruction");
}
Exemplo n.º 3
0
bool RBEIMConstruction::greedy_termination_test(Real training_greedy_error, int)
{
  if(_performing_extra_greedy_step)
  {
    libMesh::out << "Extra Greedy iteration finished." << std::endl;
    _performing_extra_greedy_step = false;
    return true;
  }

  _performing_extra_greedy_step = false;

  if(training_greedy_error < get_training_tolerance())
  {
    libMesh::out << "Specified error tolerance reached." << std::endl
                 << "Perform one more Greedy iteration for error bounds." << std::endl;
    _performing_extra_greedy_step = true;
    return false;
  }

  if(get_rb_evaluation().get_n_basis_functions() >= this->get_Nmax())
  {
    libMesh::out << "Maximum number of basis functions reached: Nmax = "
              << get_Nmax() << "." << std::endl
              << "Perform one more Greedy iteration for error bounds." << std::endl;
    _performing_extra_greedy_step = true;
    return false;
  }

  return false;
}
Exemplo n.º 4
0
void RBEIMConstruction::initialize_parametrized_functions_in_training_set()
{
  if(!serial_training_set)
  {
    libMesh::err << "Error: We must have serial_training_set==true in "
                 << "RBEIMConstruction::initialize_parametrized_functions_in_training_set"
                 << std::endl;
    libmesh_error();
  }

  libMesh::out << "Initializing parametrized functions in training set..." << std::endl;
  // initialize rb_eval's parameters
  get_rb_evaluation().initialize_parameters(*this);

  _parametrized_functions_in_training_set.resize( get_n_training_samples() );
  for(unsigned int i=0; i<get_n_training_samples(); i++)
  {
    set_params_from_training_set(i);
    truth_solve(-1);

    _parametrized_functions_in_training_set[i] = solution->clone().release();

    libMesh::out << "Completed solve for training sample " << (i+1) << " of " << get_n_training_samples() << std::endl;
  }

  _parametrized_functions_in_training_set_initialized = true;

  libMesh::out << "Parametrized functions in training set initialized" << std::endl << std::endl;
}
DenseVector<Number> DerivedRBConstruction<RBConstruction>::get_derived_basis_function(unsigned int i)
{
  DerivedRBEvaluation<RBEvaluation>& der_rb_eval =
    libmesh_cast_ref<DerivedRBEvaluation<RBEvaluation>&>(get_rb_evaluation());

  return der_rb_eval.derived_basis_functions[i];
}
Exemplo n.º 6
0
void RBEIMConstruction::initialize_eim_assembly_objects()
{
  _rb_eim_assembly_objects.clear();
  for(unsigned int i=0; i<get_rb_evaluation().get_n_basis_functions(); i++)
  {
    _rb_eim_assembly_objects.push_back( build_eim_assembly(i).release() );
  }
}
void DerivedRBConstruction<RBConstruction>::load_rb_solution()
{
  START_LOG("load_rb_solution()", "DerivedRBConstruction");

  solution->zero();

  if(get_rb_evaluation().RB_solution.size() > get_rb_evaluation().get_n_basis_functions())
  {
    libMesh::err << "ERROR: rb_eval contains " << get_rb_evaluation().get_n_basis_functions() << " basis functions."
                 << " RB_solution vector constains " << get_rb_evaluation().RB_solution.size() << " entries."
                 << " RB_solution in RBConstruction::load_rb_solution is too long!" << std::endl;
    libmesh_error();
  }

  DerivedRBEvaluation<RBEvaluation>& der_rb_eval =
    libmesh_cast_ref<DerivedRBEvaluation<RBEvaluation>&>(get_rb_evaluation());

  EquationSystems& es = this->get_equation_systems();
  RBConstruction& uber_system = es.get_system<RBConstruction>(uber_system_name);

  for(unsigned int i=0; i<get_rb_evaluation().RB_solution.size(); i++)
    for(unsigned int j=0; j<uber_system.get_rb_evaluation().get_n_basis_functions(); j++)
    {
      solution->add(get_rb_evaluation().RB_solution(i)*der_rb_eval.derived_basis_functions[i](j),
                    uber_system.get_rb_evaluation().get_basis_function(j));
    }

  update();

  STOP_LOG("load_rb_solution()", "DerivedRBConstruction");
}
void DerivedRBConstruction<RBConstruction>::update_RB_system_matrices()
{
  START_LOG("update_RB_system_matrices()", "DerivedRBConstruction");

  DerivedRBEvaluation<RBEvaluation>& der_rb_eval =
    libmesh_cast_ref<DerivedRBEvaluation<RBEvaluation>&>(get_rb_evaluation());

  EquationSystems& es = this->get_equation_systems();
  RBConstruction& uber_system = es.get_system<RBConstruction>(uber_system_name);

  unsigned int derived_RB_size = get_rb_evaluation().get_n_basis_functions();
  unsigned int uber_RB_size    = uber_system.get_rb_evaluation().get_n_basis_functions();

  const unsigned int Q_a = get_rb_theta_expansion().get_n_A_terms();
  const unsigned int Q_f = get_rb_theta_expansion().get_n_F_terms();

  DenseVector<Number> temp_vector;
  for(unsigned int q_f=0; q_f<Q_f; q_f++)
  {
    for(unsigned int i=(derived_RB_size-delta_N); i<derived_RB_size; i++)
    {
      uber_system.get_rb_evaluation().RB_Fq_vector[q_f].get_principal_subvector(uber_RB_size, temp_vector);
      get_rb_evaluation().RB_Fq_vector[q_f](i) = temp_vector.dot(der_rb_eval.derived_basis_functions[i]);
    }
  }

  DenseMatrix<Number> temp_matrix;
  for(unsigned int i=(derived_RB_size-delta_N); i<derived_RB_size; i++)
  {
    for(unsigned int n=0; n<get_rb_theta_expansion().get_n_outputs(); n++)
      for(unsigned int q_l=0; q_l<get_rb_theta_expansion().get_n_output_terms(n); q_l++)
      {
        uber_system.get_rb_evaluation().RB_output_vectors[n][q_l].get_principal_subvector(uber_RB_size, temp_vector);
        get_rb_evaluation().RB_output_vectors[n][q_l](i) = temp_vector.dot(der_rb_eval.derived_basis_functions[i]);
      }

    for(unsigned int j=0; j<derived_RB_size; j++)
    {
      for(unsigned int q_a=0; q_a<Q_a; q_a++)
      {
        // Compute reduced Aq matrix
        uber_system.get_rb_evaluation().RB_Aq_vector[q_a].get_principal_submatrix(uber_RB_size, temp_matrix);
        temp_matrix.vector_mult(temp_vector, der_rb_eval.derived_basis_functions[j]);
        get_rb_evaluation().RB_Aq_vector[q_a](i,j) = der_rb_eval.derived_basis_functions[i].dot(temp_vector);

        if(i!=j)
        {
          temp_vector.zero();
          temp_matrix.vector_mult(temp_vector, der_rb_eval.derived_basis_functions[i]);
          get_rb_evaluation().RB_Aq_vector[q_a](j,i) = (der_rb_eval.derived_basis_functions[j]).dot(temp_vector);
        }
      }
    }
  }

  STOP_LOG("update_RB_system_matrices()", "DerivedRBConstruction");
}
Exemplo n.º 9
0
Real RBEIMConstruction::truth_solve(int plot_solution)
{
  START_LOG("truth_solve()", "RBEIMConstruction");

//  matrix should have been set to inner_product_matrix during initialization
//  if(!single_matrix_mode)
//  {
//    matrix->zero();
//    matrix->add(1., *inner_product_matrix);
//  }
//  else
//  {
//    assemble_inner_product_matrix(matrix);
//  }

  int training_parameters_found_index = -1;
  if( _parametrized_functions_in_training_set_initialized )
  {
    // Check if parameters are in the training set. If so, we can just load the
    // solution from _parametrized_functions_in_training_set

    for(unsigned int i=0; i<get_n_training_samples(); i++)
    {
      if(get_parameters() == get_params_from_training_set(i))
      {
        training_parameters_found_index = i;
        break;
      }
    }
  }

  // If the parameters are in the training set, just copy the solution vector
  if(training_parameters_found_index >= 0)
  {
    *solution = *_parametrized_functions_in_training_set[training_parameters_found_index];
    update(); // put the solution into current_local_solution as well
  }
  // Otherwise, we have to compute the projection
  else
  {
    RBEIMEvaluation& eim_eval = libmesh_cast_ref<RBEIMEvaluation&>(get_rb_evaluation());
    eim_eval.set_parameters( get_parameters() );

    // Compute truth representation via projection
    const MeshBase& mesh = this->get_mesh();

    AutoPtr<FEMContext> c = this->build_context();
    FEMContext &context  = libmesh_cast_ref<FEMContext&>(*c);

    this->init_context(context);

    rhs->zero();

    MeshBase::const_element_iterator       el     = mesh.active_local_elements_begin();
    const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end();

    for ( ; el != end_el; ++el)
    {
      context.pre_fe_reinit(*this, *el);
      context.elem_fe_reinit();

      for(unsigned int var=0; var<n_vars(); var++)
      {
        const std::vector<Real> &JxW =
          context.element_fe_var[var]->get_JxW();

        const std::vector<std::vector<Real> >& phi =
          context.element_fe_var[var]->get_phi();

        const std::vector<Point> &xyz =
          context.element_fe_var[var]->get_xyz();

        unsigned int n_qpoints = context.element_qrule->n_points();
        unsigned int n_var_dofs = libmesh_cast_int<unsigned int>
	  (context.dof_indices_var[var].size());

        DenseSubVector<Number>& subresidual_var = *context.elem_subresiduals[var];

        for(unsigned int qp=0; qp<n_qpoints; qp++)
          for(unsigned int i=0; i != n_var_dofs; i++)
            subresidual_var(i) += JxW[qp] * eim_eval.evaluate_parametrized_function(var, xyz[qp]) * phi[i][qp];
      }

      // Apply constraints, e.g. periodic constraints
      this->get_dof_map().constrain_element_vector(context.get_elem_residual(), context.dof_indices);

      // Add element vector to global vector
      rhs->add_vector(context.get_elem_residual(), context.dof_indices);
    }

    // Solve to find the best fit, then solution stores the truth representation
    // of the function to be approximated
    solve();

    // Make sure we didn't max out the number of iterations
    if( (this->n_linear_iterations() >=
         this->get_equation_systems().parameters.get<unsigned int>("linear solver maximum iterations")) &&
        (this->final_linear_residual() >
         this->get_equation_systems().parameters.get<Real>("linear solver tolerance")) )
    {
        libMesh::out << "Warning: Linear solver may not have converged! Final linear residual = "
                     << this->final_linear_residual() << ", number of iterations = "
                     << this->n_linear_iterations() << std::endl << std::endl;
  //     libmesh_error();
    }

    if(reuse_preconditioner)
    {
      // After we've done a solve we can now reuse the preconditioner
      // because the matrix is not changing
      linear_solver->reuse_preconditioner(true);
    }
  }

  if(plot_solution > 0)
  {
#ifdef LIBMESH_HAVE_EXODUS_API
    ExodusII_IO(get_mesh()).write_equation_systems ("truth.e",
                                                    this->get_equation_systems());
#endif
  }

  STOP_LOG("truth_solve()", "RBEIMConstruction");

  return 0.;
}
Exemplo n.º 10
0
Real RBEIMConstruction::compute_best_fit_error()
{
  START_LOG("compute_best_fit_error()", "RBEIMConstruction");

  const unsigned int RB_size = get_rb_evaluation().get_n_basis_functions();

  // load up the parametrized function for the current parameters
  truth_solve(-1);

  switch(best_fit_type_flag)
  {
    // Perform an L2 projection in order to find an approximation to solution (from truth_solve above)
    case(PROJECTION_BEST_FIT):
    {
      // compute the rhs by performing inner products
      DenseVector<Number> best_fit_rhs(RB_size);
      for(unsigned int i=0; i<RB_size; i++)
      {
        if(!single_matrix_mode)
        {
          inner_product_matrix->vector_mult(*inner_product_storage_vector, *solution);
        }
        else // In low memory mode we loaded the inner-product matrix into matrix during initialization
        {
          matrix->vector_mult(*inner_product_storage_vector, *solution);
        }
        best_fit_rhs(i) = inner_product_storage_vector->dot(get_rb_evaluation().get_basis_function(i));
      }

      // Now compute the best fit by an LU solve
      get_rb_evaluation().RB_solution.resize(RB_size);
      DenseMatrix<Number> RB_inner_product_matrix_N(RB_size);
      get_rb_evaluation().RB_inner_product_matrix.get_principal_submatrix(RB_size, RB_inner_product_matrix_N);

      RB_inner_product_matrix_N.lu_solve(best_fit_rhs, get_rb_evaluation().RB_solution);
      break;
    }
    // Perform EIM solve in order to find the approximation to solution
    // (rb_solve provides the EIM basis function coefficients used below)
    case(EIM_BEST_FIT):
    {
      // Turn off error estimation for this rb_solve, we use the linfty norm instead
      get_rb_evaluation().evaluate_RB_error_bound = false;
      get_rb_evaluation().set_parameters( get_parameters() );
      get_rb_evaluation().rb_solve(RB_size);
      get_rb_evaluation().evaluate_RB_error_bound = true;
      break;
    }
    default:
    {
      libMesh::out << "Should not reach here" << std::endl;
      libmesh_error();
    }
  }

  // load the error into solution
  for(unsigned int i=0; i<get_rb_evaluation().get_n_basis_functions(); i++)
  {
    solution->add(-get_rb_evaluation().RB_solution(i), get_rb_evaluation().get_basis_function(i));
  }

  Real best_fit_error = solution->linfty_norm();

  STOP_LOG("compute_best_fit_error()", "RBEIMConstruction");

  return best_fit_error;
}
Exemplo n.º 11
0
void RBEIMConstruction::enrich_RB_space()
{
  START_LOG("enrich_RB_space()", "RBEIMConstruction");

  // put solution in _ghosted_meshfunction_vector so we can access it from the mesh function
  // this allows us to compute EIM_rhs appropriately
  solution->localize(*_ghosted_meshfunction_vector, this->get_dof_map().get_send_list());

  RBEIMEvaluation& eim_eval = libmesh_cast_ref<RBEIMEvaluation&>(get_rb_evaluation());

  // If we have at least one basis function we need to use
  // rb_solve to find the EIM interpolation error, otherwise just use solution as is
  if(get_rb_evaluation().get_n_basis_functions() > 0)
  {
    // get the right-hand side vector for the EIM approximation
    // by sampling the parametrized function (stored in solution)
    // at the interpolation points
    unsigned int RB_size = get_rb_evaluation().get_n_basis_functions();
    DenseVector<Number> EIM_rhs(RB_size);
    for(unsigned int i=0; i<RB_size; i++)
    {
      EIM_rhs(i) = evaluate_mesh_function( eim_eval.interpolation_points_var[i],
                                           eim_eval.interpolation_points[i] );
    }

    eim_eval.set_parameters( get_parameters() );
    eim_eval.rb_solve(EIM_rhs);

    // Load the "EIM residual" into solution by subtracting
    // the EIM approximation
    for(unsigned int i=0; i<get_rb_evaluation().get_n_basis_functions(); i++)
    {
      solution->add(-eim_eval.RB_solution(i), get_rb_evaluation().get_basis_function(i));
    }
  }

  // need to update since context uses current_local_solution
  update();

  // Find the quadrature point at which solution (which now stores
  // the "EIM residual") has maximum absolute value
  // by looping over the mesh
  Point optimal_point;
  Number optimal_value = 0.;
  unsigned int optimal_var;

  // Compute truth representation via projection
  const MeshBase& mesh = this->get_mesh();

  AutoPtr<FEMContext> c = this->build_context();
  FEMContext &context  = libmesh_cast_ref<FEMContext&>(*c);

  this->init_context(context);

  MeshBase::const_element_iterator       el     = mesh.active_local_elements_begin();
  const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end();

  for ( ; el != end_el; ++el)
  {
    context.pre_fe_reinit(*this, *el);
    context.elem_fe_reinit();

    for(unsigned int var=0; var<n_vars(); var++)
    {
      unsigned int n_qpoints = context.element_qrule->n_points();

      for(unsigned int qp=0; qp<n_qpoints; qp++)
      {
        Number value = context.interior_value(var, qp);

        if( std::abs(value) > std::abs(optimal_value) )
        {
          optimal_value = value;
          optimal_point = context.element_fe_var[var]->get_xyz()[qp];
          optimal_var = var;
        }

      }
    }
  }

  Real global_abs_value = std::abs(optimal_value);
  unsigned int proc_ID_index;
  this->comm().maxloc(global_abs_value, proc_ID_index);

  // Broadcast the optimal point from proc_ID_index
  this->comm().broadcast(optimal_point, proc_ID_index);

  // Also broadcast the corresponding optimal_var and optimal_value
  this->comm().broadcast(optimal_var, proc_ID_index);
  this->comm().broadcast(optimal_value, proc_ID_index);

  // Scale the solution
  solution->scale(1./optimal_value);

  // Store optimal point in interpolation_points
  if(!_performing_extra_greedy_step)
  {
    eim_eval.interpolation_points.push_back(optimal_point);
    eim_eval.interpolation_points_var.push_back(optimal_var);

    NumericVector<Number>* new_bf = NumericVector<Number>::build(this->comm()).release();
    new_bf->init (this->n_dofs(), this->n_local_dofs(), false, libMeshEnums::PARALLEL);
    *new_bf = *solution;
    get_rb_evaluation().basis_functions.push_back( new_bf );
  }
  else
  {
    eim_eval.extra_interpolation_point = optimal_point;
    eim_eval.extra_interpolation_point_var = optimal_var;
  }

  STOP_LOG("enrich_RB_space()", "RBEIMConstruction");
}
Exemplo n.º 12
0
Real RBEIMConstruction::truth_solve(int plot_solution)
{
  START_LOG("truth_solve()", "RBEIMConstruction");

  int training_parameters_found_index = -1;
  if( _parametrized_functions_in_training_set_initialized )
    {
      // Check if parameters are in the training set. If so, we can just load the
      // solution from _parametrized_functions_in_training_set

      for(unsigned int i=0; i<get_n_training_samples(); i++)
        {
          if(get_parameters() == get_params_from_training_set(i))
            {
              training_parameters_found_index = i;
              break;
            }
        }
    }

  // If the parameters are in the training set, just copy the solution vector
  if(training_parameters_found_index >= 0)
    {
      *solution = *_parametrized_functions_in_training_set[training_parameters_found_index];
      update(); // put the solution into current_local_solution as well
    }
  // Otherwise, we have to compute the projection
  else
    {
      RBEIMEvaluation& eim_eval = cast_ref<RBEIMEvaluation&>(get_rb_evaluation());
      eim_eval.set_parameters( get_parameters() );

      // Compute truth representation via projection
      const MeshBase& mesh = this->get_mesh();

      UniquePtr<DGFEMContext> c = this->build_context();
      DGFEMContext &context  = cast_ref<DGFEMContext&>(*c);

      this->init_context(context);

      rhs->zero();

      MeshBase::const_element_iterator       el     = mesh.active_local_elements_begin();
      const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end();

      for ( ; el != end_el; ++el)
        {
          context.pre_fe_reinit(*this, *el);
          context.elem_fe_reinit();

          // All variables should have the same quadrature rule, hence
          // we can get JxW and xyz based on first_elem_fe.
          FEBase* first_elem_fe = NULL;
          context.get_element_fe( 0, first_elem_fe );
          unsigned int n_qpoints = context.get_element_qrule().n_points();
          const std::vector<Real> &JxW = first_elem_fe->get_JxW();
          const std::vector<Point> &xyz = first_elem_fe->get_xyz();

          // Loop over qp before var because parametrized functions often use
          // some caching based on qp.
          for (unsigned int qp=0; qp<n_qpoints; qp++)
            {
              for (unsigned int var=0; var<n_vars(); var++)
                {
                  FEBase* elem_fe = NULL;
                  context.get_element_fe( var, elem_fe );
                  const std::vector<std::vector<Real> >& phi = elem_fe->get_phi();

                  DenseSubVector<Number>& subresidual_var = context.get_elem_residual( var );

                  unsigned int n_var_dofs = cast_int<unsigned int>(context.get_dof_indices( var ).size());

                  Number eval_result = eim_eval.evaluate_parametrized_function(var, xyz[qp], *(*el));
                  for (unsigned int i=0; i != n_var_dofs; i++)
                    subresidual_var(i) += JxW[qp] * eval_result * phi[i][qp];
                }
            }

          // Apply constraints, e.g. periodic constraints
          this->get_dof_map().constrain_element_vector(context.get_elem_residual(), context.get_dof_indices() );

          // Add element vector to global vector
          rhs->add_vector(context.get_elem_residual(), context.get_dof_indices() );
        }

      // Solve to find the best fit, then solution stores the truth representation
      // of the function to be approximated
      solve_for_matrix_and_rhs(*inner_product_solver, *inner_product_matrix, *rhs);

      if (assert_convergence)
        check_convergence(*inner_product_solver);
    }

  if(plot_solution > 0)
    {
#ifdef LIBMESH_HAVE_EXODUS_API
      ExodusII_IO(get_mesh()).write_equation_systems ("truth.exo",
                                                      this->get_equation_systems());
#endif
    }

  STOP_LOG("truth_solve()", "RBEIMConstruction");

  return 0.;
}
void DerivedRBConstruction<RBConstruction>::update_residual_terms(bool compute_inner_products)
{
  START_LOG("update_residual_terms()", "DerivedRBConstruction");

  DerivedRBEvaluation<RBEvaluation>& der_rb_eval =
    libmesh_cast_ref<DerivedRBEvaluation<RBEvaluation>&>(get_rb_evaluation());

  EquationSystems& es = this->get_equation_systems();
  RBConstruction& uber_system = es.get_system<RBConstruction>(uber_system_name);

  const unsigned int Q_a = get_rb_theta_expansion().get_n_A_terms();
  const unsigned int Q_f = get_rb_theta_expansion().get_n_F_terms();

  switch(der_rb_eval.residual_type_flag)
  {
    case(SteadyDerivedRBEvaluation::RESIDUAL_WRT_UBER):
    {
      unsigned int derived_RB_size = get_rb_evaluation().get_n_basis_functions();
      unsigned int uber_RB_size = uber_system.get_rb_evaluation().get_n_basis_functions();
      DenseVector<Number> temp_vector1, temp_vector2;

      // Now compute and store the inner products (if requested)
      if (compute_inner_products)
      {

        DenseMatrix<Number> temp_matrix;
        for(unsigned int q_f=0; q_f<Q_f; q_f++)
	  {
	    for(unsigned int q_a=0; q_a<Q_a; q_a++)
	      {
	        for(unsigned int i=(derived_RB_size-delta_N); i<derived_RB_size; i++)
		  {
                    uber_system.get_rb_evaluation().RB_Aq_vector[q_a].get_principal_submatrix(uber_RB_size, temp_matrix);
                    temp_matrix.vector_mult(temp_vector1, der_rb_eval.derived_basis_functions[i]);
                    uber_system.get_rb_evaluation().RB_Fq_vector[q_f].get_principal_subvector(uber_RB_size, temp_vector2);
		    get_rb_evaluation().Fq_Aq_representor_innerprods[q_f][q_a][i] = -temp_vector1.dot(temp_vector2);
		  }
	      }
	  }

        unsigned int q=0;
        for(unsigned int q_a1=0; q_a1<Q_a; q_a1++)
	  {
	    for(unsigned int q_a2=q_a1; q_a2<Q_a; q_a2++)
	      {
	        for(unsigned int i=(derived_RB_size-delta_N); i<derived_RB_size; i++)
		  {
		    for(unsigned int j=0; j<derived_RB_size; j++)
		      {
                        uber_system.get_rb_evaluation().RB_Aq_vector[q_a1].get_principal_submatrix(uber_RB_size, temp_matrix);
                        temp_matrix.vector_mult(temp_vector1, der_rb_eval.derived_basis_functions[i]);
                        uber_system.get_rb_evaluation().RB_Aq_vector[q_a2].get_principal_submatrix(uber_RB_size, temp_matrix);
                        temp_matrix.vector_mult(temp_vector2, der_rb_eval.derived_basis_functions[j]);
		        get_rb_evaluation().Aq_Aq_representor_innerprods[q][i][j] = temp_vector1.dot(temp_vector2);

		        if(i != j)
			  {
                            uber_system.get_rb_evaluation().RB_Aq_vector[q_a1].get_principal_submatrix(uber_RB_size, temp_matrix);
                            temp_matrix.vector_mult(temp_vector1, der_rb_eval.derived_basis_functions[j]);
                            uber_system.get_rb_evaluation().RB_Aq_vector[q_a2].get_principal_submatrix(uber_RB_size, temp_matrix);
                            temp_matrix.vector_mult(temp_vector2, der_rb_eval.derived_basis_functions[i]);
			    get_rb_evaluation().Aq_Aq_representor_innerprods[q][j][i] = temp_vector1.dot(temp_vector2);
			  }
		      }
		  }
	        q++;
	      }
	  }
      } // end if (compute_inner_products)

      break;
    }

    case(SteadyDerivedRBEvaluation::RESIDUAL_WRT_TRUTH):
    {
      unsigned int RB_size = get_rb_evaluation().get_n_basis_functions();

      for(unsigned int q_f=0; q_f<Q_f; q_f++)
      {
        for(unsigned int q_a=0; q_a<Q_a; q_a++)
        {
          for(unsigned int i=(RB_size-delta_N); i<RB_size; i++)
          {
            get_rb_evaluation().Fq_Aq_representor_innerprods[q_f][q_a][i] = 0.;
            for(unsigned int j=0; j<uber_system.get_rb_evaluation().get_n_basis_functions(); j++) // Evaluate the dot product
            {
              get_rb_evaluation().Fq_Aq_representor_innerprods[q_f][q_a][i] +=
	        uber_system.get_rb_evaluation().Fq_Aq_representor_innerprods[q_f][q_a][j] *
	        der_rb_eval.derived_basis_functions[i](j);
            }
          }
        }
      }

      unsigned int q=0;
      for(unsigned int q_a1=0; q_a1<Q_a; q_a1++)
      {
        for(unsigned int q_a2=q_a1; q_a2<Q_a; q_a2++)
        {
          for(unsigned int i=(RB_size-delta_N); i<RB_size; i++)
          {
            for(unsigned int j=0; j<RB_size; j++)
	    {

              get_rb_evaluation().Aq_Aq_representor_innerprods[q][i][j] = 0.;
              if(i != j)
                get_rb_evaluation().Aq_Aq_representor_innerprods[q][j][i] = 0.;

              for(unsigned int k=0; k<uber_system.get_rb_evaluation().get_n_basis_functions(); k++)
                for(unsigned int k_prime=0; k_prime<uber_system.get_rb_evaluation().get_n_basis_functions(); k_prime++)
                {
                  get_rb_evaluation().Aq_Aq_representor_innerprods[q][i][j] +=
                    der_rb_eval.derived_basis_functions[i](k)*der_rb_eval.derived_basis_functions[j](k_prime)*
                    uber_system.get_rb_evaluation().Aq_Aq_representor_innerprods[q][k][k_prime];

                  if(i != j)
                  {
                    get_rb_evaluation().Aq_Aq_representor_innerprods[q][j][i] +=
                      der_rb_eval.derived_basis_functions[j](k)*der_rb_eval.derived_basis_functions[i](k_prime)*
                      uber_system.get_rb_evaluation().Aq_Aq_representor_innerprods[q][k][k_prime];
                  }
                }
            }
          }
          q++;
        }
      }

      break;
    }

    default:
    {
      libMesh::out << "Invalid RESIDUAL_TYPE in update_residual_terms" << std::endl;
      break;
    }
  }

  STOP_LOG("update_residual_terms()", "DerivedRBConstruction");
}
void DerivedRBConstruction<RBConstruction>::compute_Fq_representor_innerprods(bool compute_inner_products)
{
  START_LOG("compute_Fq_representor_innerprods()", "DerivedRBConstruction");

  // We don't short-circuit here even if Fq_representor_innerprods_computed = true because
  // the residual mode may have changed (this function is very cheap so not much
  // incentive to make sure we do not call it extra times)

  EquationSystems& es = this->get_equation_systems();
  RBConstruction& uber_system = es.get_system<RBConstruction>(uber_system_name);

  SteadyDerivedRBEvaluation& drb_eval = libmesh_cast_ref< SteadyDerivedRBEvaluation& >(get_rb_evaluation());

  const unsigned int Q_f = get_rb_theta_expansion().get_n_F_terms();

  switch(drb_eval.residual_type_flag)
  {
    case(SteadyDerivedRBEvaluation::RESIDUAL_WRT_UBER):
    {
      unsigned int uber_RB_size = uber_system.get_rb_evaluation().get_n_basis_functions();
      DenseVector<Number> temp_vector1, temp_vector2;

      // Assume inner product matrix is the identity, hence don't need to
      // do any solves
      if (compute_inner_products)
      {
        unsigned int q=0;
        for(unsigned int q_f1=0; q_f1<Q_f; q_f1++)
        {
          for(unsigned int q_f2=q_f1; q_f2<Q_f; q_f2++)
          {
            uber_system.get_rb_evaluation().RB_Fq_vector[q_f2].get_principal_subvector(uber_RB_size, temp_vector1);
            uber_system.get_rb_evaluation().RB_Fq_vector[q_f1].get_principal_subvector(uber_RB_size, temp_vector2);
            Fq_representor_innerprods[q] = temp_vector1.dot( temp_vector2 );
            q++;
          }
        }
      } // end if (compute_inner_products)

      break;
    }

    case(SteadyDerivedRBEvaluation::RESIDUAL_WRT_TRUTH):
    {
      // Copy the output terms over from uber_system
      for(unsigned int n=0; n<get_rb_theta_expansion().get_n_outputs(); n++)
      {
        output_dual_innerprods[n] = uber_system.output_dual_innerprods[n];
      }

      // Copy the Fq terms over from uber_system
      Fq_representor_innerprods = uber_system.Fq_representor_innerprods;

      break;
    }

    default:
    {
      libMesh::out << "Invalid RESIDUAL_TYPE in compute_Fq_representor_innerprods" << std::endl;
      break;
    }
  }

  Fq_representor_innerprods_computed = true;

  // Copy the Fq_representor_innerprods and output_dual_innerprods to the rb_eval,
  // where they are actually needed
  // (we store them in DerivedRBConstruction as well in order to cache
  // the data and possibly save work)
  get_rb_evaluation().Fq_representor_innerprods = Fq_representor_innerprods;
  get_rb_evaluation().output_dual_innerprods = output_dual_innerprods;

  STOP_LOG("compute_Fq_representor_innerprods()", "DerivedRBConstruction");
}
void DerivedRBConstruction<RBConstruction>::generate_residual_terms_wrt_truth()
{
  START_LOG("generate_residual_terms_wrt_truth()", "DerivedRBConstruction");

  SteadyDerivedRBEvaluation& drb_eval = libmesh_cast_ref< SteadyDerivedRBEvaluation& >(get_rb_evaluation());

  if(drb_eval.residual_type_flag != SteadyDerivedRBEvaluation::RESIDUAL_WRT_TRUTH)
  {
    // Set flag to compute residual wrt truth space
    drb_eval.residual_type_flag = SteadyDerivedRBEvaluation::RESIDUAL_WRT_TRUTH;

    recompute_all_residual_terms(/*compute_inner_products = */ true);
  }
  STOP_LOG("generate_residual_terms_wrt_truth()", "DerivedRBConstruction");
}