コード例 #1
0
Real RBEIMEvaluation::rb_solve(unsigned int N)
{
  // Short-circuit if we are using the same parameters and value of N
  if( (_previous_parameters == get_parameters()) &&
      (_previous_N == N) )
    {
      return _previous_error_bound;
    }

  // Otherwise, update _previous parameters, _previous_N
  _previous_parameters = get_parameters();
  _previous_N = N;

  LOG_SCOPE("rb_solve()", "RBEIMEvaluation");

  if(N > get_n_basis_functions())
    libmesh_error_msg("ERROR: N cannot be larger than the number of basis functions in rb_solve");

  if(N==0)
    libmesh_error_msg("ERROR: N must be greater than 0 in rb_solve");

  // Get the rhs by sampling parametrized_function
  // at the first N interpolation_points
  DenseVector<Number> EIM_rhs(N);
  for(unsigned int i=0; i<N; i++)
    {
      EIM_rhs(i) = evaluate_parametrized_function(interpolation_points_var[i],
                                                  interpolation_points[i],
                                                  *interpolation_points_elem[i]);
    }



  DenseMatrix<Number> interpolation_matrix_N;
  interpolation_matrix.get_principal_submatrix(N, interpolation_matrix_N);

  interpolation_matrix_N.lu_solve(EIM_rhs, RB_solution);

  // Optionally evaluate an a posteriori error bound. The EIM error estimate
  // recommended in the literature is based on using "next" EIM point, so
  // we skip this if N == get_n_basis_functions()
  if(evaluate_RB_error_bound && (N != get_n_basis_functions()))
    {
      // Compute the a posteriori error bound
      // First, sample the parametrized function at x_{N+1}
      Number g_at_next_x = evaluate_parametrized_function(interpolation_points_var[N],
                                                          interpolation_points[N],
                                                          *interpolation_points_elem[N]);

      // Next, evaluate the EIM approximation at x_{N+1}
      Number EIM_approx_at_next_x = 0.;
      for(unsigned int j=0; j<N; j++)
        {
          EIM_approx_at_next_x += RB_solution(j) * interpolation_matrix(N,j);
        }

      Real error_estimate = std::abs(g_at_next_x - EIM_approx_at_next_x);

      _previous_error_bound = error_estimate;
      return error_estimate;
    }
  else // Don't evaluate an error bound
    {
      _previous_error_bound = -1.;
      return -1.;
    }

}
コード例 #2
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");
}
コード例 #3
0
Real RBEIMEvaluation::rb_solve(unsigned int N)
{
  // Short-circuit if we are using the same parameters and value of N
  if( (_previous_parameters == get_parameters()) && 
      (_previous_N == N) )
  {
    return _previous_error_bound;
  }
  
  // Otherwise, update _previous parameters, _previous_N
  _previous_parameters = get_parameters();
  _previous_N = N;
  
  START_LOG("rb_solve()", "RBEIMEvaluation");

  if(N > get_n_basis_functions())
  {
    libMesh::err << "ERROR: N cannot be larger than the number "
                 << "of basis functions in rb_solve" << std::endl;
    libmesh_error();
  }
  if(N==0)
  {
    libMesh::err << "ERROR: N must be greater than 0 in rb_solve" << std::endl;
    libmesh_error();
  }

  // Get the rhs by sampling parametrized_function
  // at the first N interpolation_points
  DenseVector<Number> EIM_rhs(N);
  for(unsigned int i=0; i<N; i++)
  {
    EIM_rhs(i) = evaluate_parametrized_function(interpolation_points_var[i], interpolation_points[i]);
  }



  DenseMatrix<Number> interpolation_matrix_N;
  interpolation_matrix.get_principal_submatrix(N, interpolation_matrix_N);

  interpolation_matrix_N.lu_solve(EIM_rhs, RB_solution);

  // Evaluate an a posteriori error bound
  if(evaluate_RB_error_bound)
  {
    // Compute the a posteriori error bound
    // First, sample the parametrized function at x_{N+1}
    Number g_at_next_x;
    if(N == get_n_basis_functions())
      g_at_next_x = evaluate_parametrized_function(extra_interpolation_point_var, extra_interpolation_point);
    else
      g_at_next_x = evaluate_parametrized_function(interpolation_points_var[N], interpolation_points[N]);

    // Next, evaluate the EIM approximation at x_{N+1}
    Number EIM_approx_at_next_x = 0.;
    for(unsigned int j=0; j<N; j++)
    {
      if(N == get_n_basis_functions())
      {
        EIM_approx_at_next_x += RB_solution(j) * extra_interpolation_matrix_row(j);
      }
      else
      {
        EIM_approx_at_next_x += RB_solution(j) * interpolation_matrix(N,j);
      }
    }

    Real error_estimate = std::abs(g_at_next_x - EIM_approx_at_next_x);

    STOP_LOG("rb_solve()", "RBEIMEvaluation");

    _previous_error_bound = error_estimate;
    return error_estimate;
  }
  else // Don't evaluate an error bound
  {
    STOP_LOG("rb_solve()", "RBEIMEvaluation");
    _previous_error_bound = -1.;
    return -1.;
  }

}