Example #1
0
void UNVIO::count_elements (std::istream& in_file)
{
  START_LOG("count_elements()","UNVIO");

  if (this->_n_elements != 0)
    {
      libMesh::err << "Error: Trying to scan elements twice!"
		    << std::endl;
      libmesh_error();
    }


  // Simply read the element
  // dataset for the @e only
  // purpose to count nodes!

  std::string data;
  unsigned int fe_id;

  while (!in_file.eof())
    {
      // read element label
      in_file >> data;

      // end of dataset?
      if (data == "-1")
	break;

      // read fe_id
      in_file >> fe_id;

      // Skip related data,
      // and node number list
      in_file.ignore (256,'\n');
      in_file.ignore (256,'\n');

      // For some elements the node numbers
      // are given more than one record

      // TET10 or QUAD9
      if (fe_id == 118 || fe_id == 300)
	  in_file.ignore (256,'\n');

      // HEX20
      if (fe_id == 116)
	{
	  in_file.ignore (256,'\n');
	  in_file.ignore (256,'\n');
	}

      this->_n_elements++;
    }


  if (in_file.eof())
    {
      libMesh::err << "ERROR: File ended before end of element dataset!"
		    << std::endl;
      libmesh_error();
    }

  if (this->verbose())
    libMesh::out << "  Elements: " << this->_n_elements << std::endl;

  STOP_LOG("count_elements()","UNVIO");
}
Example #2
0
void JumpErrorEstimator::estimate_error (const System & system,
                                         ErrorVector & error_per_cell,
                                         const NumericVector<Number> * solution_vector,
                                         bool estimate_parent_error)
{
  START_LOG("estimate_error()", "JumpErrorEstimator");
  /*

    Conventions for assigning the direction of the normal:

    - e & f are global element ids

    Case (1.) Elements are at the same level, e<f
    Compute the flux jump on the face and
    add it as a contribution to error_per_cell[e]
    and error_per_cell[f]

    ----------------------
    |           |          |
    |           |    f     |
    |           |          |
    |    e      |---> n    |
    |           |          |
    |           |          |
    ----------------------


    Case (2.) The neighbor is at a higher level.
    Compute the flux jump on e's face and
    add it as a contribution to error_per_cell[e]
    and error_per_cell[f]

    ----------------------
    |     |     |          |
    |     |  e  |---> n    |
    |     |     |          |
    |-----------|    f     |
    |     |     |          |
    |     |     |          |
    |     |     |          |
    ----------------------
  */

  // The current mesh
  const MeshBase & mesh = system.get_mesh();

  // The number of variables in the system
  const unsigned int n_vars = system.n_vars();

  // The DofMap for this system
  const DofMap & dof_map = system.get_dof_map();

  // Resize the error_per_cell vector to be
  // the number of elements, initialize it to 0.
  error_per_cell.resize (mesh.max_elem_id());
  std::fill (error_per_cell.begin(), error_per_cell.end(), 0.);

  // Declare a vector of floats which is as long as
  // error_per_cell above, and fill with zeros.  This vector will be
  // used to keep track of the number of edges (faces) on each active
  // element which are either:
  // 1) an internal edge
  // 2) an edge on a Neumann boundary for which a boundary condition
  //    function has been specified.
  // The error estimator can be scaled by the number of flux edges (faces)
  // which the element actually has to obtain a more uniform measure
  // of the error.  Use floats instead of ints since in case 2 (above)
  // f gets 1/2 of a flux face contribution from each of his
  // neighbors
  std::vector<float> n_flux_faces;
  if (scale_by_n_flux_faces)
    n_flux_faces.resize(error_per_cell.size(), 0);

  // Prepare current_local_solution to localize a non-standard
  // solution vector if necessary
  if (solution_vector && solution_vector != system.solution.get())
    {
      NumericVector<Number> * newsol =
        const_cast<NumericVector<Number> *>(solution_vector);
      System & sys = const_cast<System &>(system);
      newsol->swap(*sys.solution);
      sys.update();
    }

  fine_context.reset(new FEMContext(system));
  coarse_context.reset(new FEMContext(system));

  // Loop over all the variables we've been requested to find jumps in, to
  // pre-request
  for (var=0; var<n_vars; var++)
    {
      // Possibly skip this variable
      if (error_norm.weight(var) == 0.0) continue;

      // FIXME: Need to generalize this to vector-valued elements. [PB]
      FEBase * side_fe = libmesh_nullptr;

      const std::set<unsigned char> & elem_dims =
        fine_context->elem_dimensions();

      for (std::set<unsigned char>::const_iterator dim_it =
             elem_dims.begin(); dim_it != elem_dims.end(); ++dim_it)
        {
          const unsigned char dim = *dim_it;

          fine_context->get_side_fe( var, side_fe, dim );

          libmesh_assert_not_equal_to(side_fe->get_fe_type().family, SCALAR);

          side_fe->get_xyz();
        }
    }

  this->init_context(*fine_context);
  this->init_context(*coarse_context);

  // Iterate over all the active elements in the mesh
  // that live on this processor.
  MeshBase::const_element_iterator       elem_it  = mesh.active_local_elements_begin();
  const MeshBase::const_element_iterator elem_end = mesh.active_local_elements_end();

  for (; elem_it != elem_end; ++elem_it)
    {
      // e is necessarily an active element on the local processor
      const Elem * e = *elem_it;
      const dof_id_type e_id = e->id();

#ifdef LIBMESH_ENABLE_AMR
      // See if the parent of element e has been examined yet;
      // if not, we may want to compute the estimator on it
      const Elem * parent = e->parent();

      // We only can compute and only need to compute on
      // parents with all active children
      bool compute_on_parent = true;
      if (!parent || !estimate_parent_error)
        compute_on_parent = false;
      else
        for (unsigned int c=0; c != parent->n_children(); ++c)
          if (!parent->child(c)->active())
            compute_on_parent = false;

      if (compute_on_parent &&
          !error_per_cell[parent->id()])
        {
          // Compute a projection onto the parent
          DenseVector<Number> Uparent;
          FEBase::coarsened_dof_values
            (*(system.solution), dof_map, parent, Uparent, false);

          // Loop over the neighbors of the parent
          for (unsigned int n_p=0; n_p<parent->n_neighbors(); n_p++)
            {
              if (parent->neighbor(n_p) != libmesh_nullptr) // parent has a neighbor here
                {
                  // Find the active neighbors in this direction
                  std::vector<const Elem *> active_neighbors;
                  parent->neighbor(n_p)->
                    active_family_tree_by_neighbor(active_neighbors,
                                                   parent);
                  // Compute the flux to each active neighbor
                  for (unsigned int a=0;
                       a != active_neighbors.size(); ++a)
                    {
                      const Elem * f = active_neighbors[a];
                      // FIXME - what about when f->level <
                      // parent->level()??
                      if (f->level() >= parent->level())
                        {
                          fine_context->pre_fe_reinit(system, f);
                          coarse_context->pre_fe_reinit(system, parent);
                          libmesh_assert_equal_to
                            (coarse_context->get_elem_solution().size(),
                             Uparent.size());
                          coarse_context->get_elem_solution() = Uparent;

                          this->reinit_sides();

                          // Loop over all significant variables in the system
                          for (var=0; var<n_vars; var++)
                            if (error_norm.weight(var) != 0.0)
                              {
                                this->internal_side_integration();

                                error_per_cell[fine_context->get_elem().id()] +=
                                  static_cast<ErrorVectorReal>(fine_error);
                                error_per_cell[coarse_context->get_elem().id()] +=
                                  static_cast<ErrorVectorReal>(coarse_error);
                              }

                          // Keep track of the number of internal flux
                          // sides found on each element
                          if (scale_by_n_flux_faces)
                            {
                              n_flux_faces[fine_context->get_elem().id()]++;
                              n_flux_faces[coarse_context->get_elem().id()] +=
                                this->coarse_n_flux_faces_increment();
                            }
                        }
                    }
                }
              else if (integrate_boundary_sides)
                {
                  fine_context->pre_fe_reinit(system, parent);
                  libmesh_assert_equal_to
                    (fine_context->get_elem_solution().size(),
                     Uparent.size());
                  fine_context->get_elem_solution() = Uparent;
                  fine_context->side = n_p;
                  fine_context->side_fe_reinit();

                  // If we find a boundary flux for any variable,
                  // let's just count it as a flux face for all
                  // variables.  Otherwise we'd need to keep track of
                  // a separate n_flux_faces and error_per_cell for
                  // every single var.
                  bool found_boundary_flux = false;

                  for (var=0; var<n_vars; var++)
                    if (error_norm.weight(var) != 0.0)
                      {
                        if (this->boundary_side_integration())
                          {
                            error_per_cell[fine_context->get_elem().id()] +=
                              static_cast<ErrorVectorReal>(fine_error);
                            found_boundary_flux = true;
                          }
                      }

                  if (scale_by_n_flux_faces && found_boundary_flux)
                    n_flux_faces[fine_context->get_elem().id()]++;
                }
            }
        }
#endif // #ifdef LIBMESH_ENABLE_AMR

      // If we do any more flux integration, e will be the fine element
      fine_context->pre_fe_reinit(system, e);

      // Loop over the neighbors of element e
      for (unsigned int n_e=0; n_e<e->n_neighbors(); n_e++)
        {
          if ((e->neighbor(n_e) != libmesh_nullptr) ||
              integrate_boundary_sides)
            {
              fine_context->side = n_e;
              fine_context->side_fe_reinit();
            }

          if (e->neighbor(n_e) != libmesh_nullptr) // e is not on the boundary
            {
              const Elem * f           = e->neighbor(n_e);
              const dof_id_type f_id = f->id();

              // Compute flux jumps if we are in case 1 or case 2.
              if ((f->active() && (f->level() == e->level()) && (e_id < f_id))
                  || (f->level() < e->level()))
                {
                  // f is now the coarse element
                  coarse_context->pre_fe_reinit(system, f);

                  this->reinit_sides();

                  // Loop over all significant variables in the system
                  for (var=0; var<n_vars; var++)
                    if (error_norm.weight(var) != 0.0)
                      {
                        this->internal_side_integration();

                        error_per_cell[fine_context->get_elem().id()] +=
                          static_cast<ErrorVectorReal>(fine_error);
                        error_per_cell[coarse_context->get_elem().id()] +=
                          static_cast<ErrorVectorReal>(coarse_error);
                      }

                  // Keep track of the number of internal flux
                  // sides found on each element
                  if (scale_by_n_flux_faces)
                    {
                      n_flux_faces[fine_context->get_elem().id()]++;
                      n_flux_faces[coarse_context->get_elem().id()] +=
                        this->coarse_n_flux_faces_increment();
                    }
                } // end if (case1 || case2)
            } // if (e->neigbor(n_e) != libmesh_nullptr)

          // Otherwise, e is on the boundary.  If it happens to
          // be on a Dirichlet boundary, we need not do anything.
          // On the other hand, if e is on a Neumann (flux) boundary
          // with grad(u).n = g, we need to compute the additional residual
          // (h * \int |g - grad(u_h).n|^2 dS)^(1/2).
          // We can only do this with some knowledge of the boundary
          // conditions, i.e. the user must have attached an appropriate
          // BC function.
          else if (integrate_boundary_sides)
            {
              bool found_boundary_flux = false;

              for (var=0; var<n_vars; var++)
                if (error_norm.weight(var) != 0.0)
                  if (this->boundary_side_integration())
                    {
                      error_per_cell[fine_context->get_elem().id()] +=
                        static_cast<ErrorVectorReal>(fine_error);
                      found_boundary_flux = true;
                    }

              if (scale_by_n_flux_faces && found_boundary_flux)
                n_flux_faces[fine_context->get_elem().id()]++;
            } // end if (e->neighbor(n_e) == libmesh_nullptr)
        } // end loop over neighbors
    } // End loop over active local elements


  // Each processor has now computed the error contribuions
  // for its local elements.  We need to sum the vector
  // and then take the square-root of each component.  Note
  // that we only need to sum if we are running on multiple
  // processors, and we only need to take the square-root
  // if the value is nonzero.  There will in general be many
  // zeros for the inactive elements.

  // First sum the vector of estimated error values
  this->reduce_error(error_per_cell, system.comm());

  // Compute the square-root of each component.
  for (std::size_t i=0; i<error_per_cell.size(); i++)
    if (error_per_cell[i] != 0.)
      error_per_cell[i] = std::sqrt(error_per_cell[i]);


  if (this->scale_by_n_flux_faces)
    {
      // Sum the vector of flux face counts
      this->reduce_error(n_flux_faces, system.comm());

      // Sanity check: Make sure the number of flux faces is
      // always an integer value
#ifdef DEBUG
      for (unsigned int i=0; i<n_flux_faces.size(); ++i)
        libmesh_assert_equal_to (n_flux_faces[i], static_cast<float>(static_cast<unsigned int>(n_flux_faces[i])) );
#endif

      // Scale the error by the number of flux faces for each element
      for (unsigned int i=0; i<n_flux_faces.size(); ++i)
        {
          if (n_flux_faces[i] == 0.0) // inactive or non-local element
            continue;

          //libMesh::out << "Element " << i << " has " << n_flux_faces[i] << " flux faces." << std::endl;
          error_per_cell[i] /= static_cast<ErrorVectorReal>(n_flux_faces[i]);
        }
    }

  // If we used a non-standard solution before, now is the time to fix
  // the current_local_solution
  if (solution_vector && solution_vector != system.solution.get())
    {
      NumericVector<Number> * newsol =
        const_cast<NumericVector<Number> *>(solution_vector);
      System & sys = const_cast<System &>(system);
      newsol->swap(*sys.solution);
      sys.update();
    }

  STOP_LOG("estimate_error()", "JumpErrorEstimator");
}
Example #3
0
Real RBEvaluation::rb_solve(unsigned int N)
{
  START_LOG("rb_solve()", "RBEvaluation");

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

  const RBParameters& mu = get_parameters();

  // Resize (and clear) the solution vector
  RB_solution.resize(N);

  // Assemble the RB system
  DenseMatrix<Number> RB_system_matrix(N,N);
  RB_system_matrix.zero();

  DenseMatrix<Number> RB_Aq_a;
  for(unsigned int q_a=0; q_a<rb_theta_expansion->get_n_A_terms(); q_a++)
    {
      RB_Aq_vector[q_a].get_principal_submatrix(N, RB_Aq_a);

      RB_system_matrix.add(rb_theta_expansion->eval_A_theta(q_a, mu), RB_Aq_a);
    }

  // Assemble the RB rhs
  DenseVector<Number> RB_rhs(N);
  RB_rhs.zero();

  DenseVector<Number> RB_Fq_f;
  for(unsigned int q_f=0; q_f<rb_theta_expansion->get_n_F_terms(); q_f++)
    {
      RB_Fq_vector[q_f].get_principal_subvector(N, RB_Fq_f);

      RB_rhs.add(rb_theta_expansion->eval_F_theta(q_f, mu), RB_Fq_f);
    }

  // Solve the linear system
  if(N > 0)
    {
      RB_system_matrix.lu_solve(RB_rhs, RB_solution);
    }

  // Evaluate RB outputs
  DenseVector<Number> RB_output_vector_N;
  for(unsigned int n=0; n<rb_theta_expansion->get_n_outputs(); n++)
    {
      RB_outputs[n] = 0.;
      for(unsigned int q_l=0; q_l<rb_theta_expansion->get_n_output_terms(n); q_l++)
        {
          RB_output_vectors[n][q_l].get_principal_subvector(N, RB_output_vector_N);
          RB_outputs[n] += rb_theta_expansion->eval_output_theta(n,q_l,mu)*RB_output_vector_N.dot(RB_solution);
        }
    }

  if(evaluate_RB_error_bound) // Calculate the error bounds
    {
      // Evaluate the dual norm of the residual for RB_solution_vector
      Real epsilon_N = compute_residual_dual_norm(N);

      // Get lower bound for coercivity constant
      const Real alpha_LB = get_stability_lower_bound();
      // alpha_LB needs to be positive to get a valid error bound
      libmesh_assert_greater ( alpha_LB, 0. );

      // Evaluate the (absolute) error bound
      Real abs_error_bound = epsilon_N / residual_scaling_denom(alpha_LB);

      // Now compute the output error bounds
      for(unsigned int n=0; n<rb_theta_expansion->get_n_outputs(); n++)
        {
          RB_output_error_bounds[n] = abs_error_bound * eval_output_dual_norm(n, mu);
        }

      STOP_LOG("rb_solve()", "RBEvaluation");

      return abs_error_bound;
    }
  else // Don't calculate the error bounds
    {
      STOP_LOG("rb_solve()", "RBEvaluation");
      // Just return -1. if we did not compute the error bound
      return -1.;
    }
}
void NloptOptimizationSolver<T>::solve ()
{
  START_LOG("solve()", "NloptOptimizationSolver");

  this->init ();

  unsigned int nlopt_size = this->system().solution->size();

  // We have to have an objective function
  libmesh_assert( this->objective_object );

  // Set routine for objective and (optionally) gradient evaluation
  {
    nlopt_result ierr =
      nlopt_set_min_objective(_opt,
                              __libmesh_nlopt_objective,
                              this);
    if (ierr < 0)
      libmesh_error_msg("NLopt failed to set min objective: " << ierr);
  }

  if (this->lower_and_upper_bounds_object)
    {
      // Need to actually compute the bounds vectors first
      this->lower_and_upper_bounds_object->lower_and_upper_bounds(this->system());

      std::vector<Real> nlopt_lb(nlopt_size);
      std::vector<Real> nlopt_ub(nlopt_size);
      for(unsigned int i=0; i<nlopt_size; i++)
        {
          nlopt_lb[i] = this->system().get_vector("lower_bounds")(i);
          nlopt_ub[i] = this->system().get_vector("upper_bounds")(i);
        }

      nlopt_set_lower_bounds(_opt, &nlopt_lb[0]);
      nlopt_set_upper_bounds(_opt, &nlopt_ub[0]);
    }

  // If we have an equality constraints object, tell NLopt about it.
  if (this->equality_constraints_object)
    {
      // NLopt requires a vector to specify the tolerance for each constraint.
      // NLopt makes a copy of this vector internally, so it's safe for us to
      // let it go out of scope.
      std::vector<double> equality_constraints_tolerances(this->system().C_eq->size(),
                                                          _constraints_tolerance);

      // It would be nice to call the C interface directly, at least it should return an error
      // code we could parse... unfortunately, there does not seem to be a way to extract
      // the underlying nlopt_opt object from the nlopt::opt class!
      nlopt_result ierr =
        nlopt_add_equality_mconstraint(_opt,
                                       equality_constraints_tolerances.size(),
                                       __libmesh_nlopt_equality_constraints,
                                       this,
                                       &equality_constraints_tolerances[0]);

      if (ierr < 0)
        libmesh_error_msg("NLopt failed to add equality constraint: " << ierr);
    }

  // If we have an inequality constraints object, tell NLopt about it.
  if (this->inequality_constraints_object)
    {
      // NLopt requires a vector to specify the tolerance for each constraint
      std::vector<double> inequality_constraints_tolerances(this->system().C_ineq->size(),
                                                            _constraints_tolerance);

      nlopt_add_inequality_mconstraint(_opt,
                                       inequality_constraints_tolerances.size(),
                                       __libmesh_nlopt_inequality_constraints,
                                       this,
                                       &inequality_constraints_tolerances[0]);
    }

  // Set a relative tolerance on the optimization parameters
  nlopt_set_ftol_rel(_opt, this->objective_function_relative_tolerance);

  // Set the maximum number of allowed objective function evaluations
  nlopt_set_maxeval(_opt, this->max_objective_function_evaluations);

  // Reset internal iteration counter
  this->_iteration_count = 0;

  // Perform the optimization
  std::vector<Real> x(nlopt_size);
  Real min_val = 0.;
  _result = nlopt_optimize(_opt, &x[0], &min_val);

  if (_result < 0)
    libMesh::out << "NLopt failed!" << std::endl;
  else
    libMesh::out << "NLopt obtained optimal value: "
                 << min_val
                 << " in "
                 << this->get_iteration_count()
                 << " iterations."
                 << std::endl;

  STOP_LOG("solve()", "NloptOptimizationSolver");
}
Example #5
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.;
}
Example #6
0
void RBEIMEvaluation::legacy_read_offline_data_from_files(const std::string& directory_name,
                                                          bool read_error_bound_data,
                                                          const bool read_binary_data)
{
  START_LOG("legacy_read_offline_data_from_files()", "RBEIMEvaluation");

  Parent::legacy_read_offline_data_from_files(directory_name, read_error_bound_data);

  // First, find out how many basis functions we had when Greedy terminated
  // This was set in RBSystem::read_offline_data_from_files
  unsigned int n_bfs = this->get_n_basis_functions();

  // The writing mode: DECODE for binary, READ for ASCII
  XdrMODE mode = read_binary_data ? DECODE : READ;

  // The suffix to use for all the files that are written out
  const std::string suffix = read_binary_data ? ".xdr" : ".dat";

  // Stream for creating file names
  std::ostringstream file_name;

  // Read in the interpolation matrix
  file_name.str("");
  file_name << directory_name << "/interpolation_matrix" << suffix;
  assert_file_exists(file_name.str());

  Xdr interpolation_matrix_in(file_name.str(), mode);

  for(unsigned int i=0; i<n_bfs; i++)
    {
      for(unsigned int j=0; j<=i; j++)
        {
          Number value;
          interpolation_matrix_in >> value;
          interpolation_matrix(i,j) = value;
        }
    }
  interpolation_matrix_in.close();

  // Also, read in the "extra" row
  file_name.str("");
  file_name << directory_name << "/extra_interpolation_matrix_row" << suffix;
  assert_file_exists(file_name.str());

  Xdr extra_interpolation_matrix_row_in(file_name.str(), mode);

  for(unsigned int j=0; j<n_bfs; j++)
    {
      Number value;
      extra_interpolation_matrix_row_in >> value;
      extra_interpolation_matrix_row(j) = value;
    }
  extra_interpolation_matrix_row_in.close();

  // Next read in interpolation_points
  file_name.str("");
  file_name << directory_name << "/interpolation_points" << suffix;
  assert_file_exists(file_name.str());

  Xdr interpolation_points_in(file_name.str(), mode);

  for(unsigned int i=0; i<n_bfs; i++)
    {
      Real x_val, y_val, z_val = 0.;
      interpolation_points_in >> x_val;

      if(LIBMESH_DIM >= 2)
        interpolation_points_in >> y_val;

      if(LIBMESH_DIM >= 3)
        interpolation_points_in >> z_val;

      Point p(x_val, y_val, z_val);
      interpolation_points.push_back(p);
    }
  interpolation_points_in.close();

  // Also, read in the extra interpolation point
  file_name.str("");
  file_name << directory_name << "/extra_interpolation_point" << suffix;
  assert_file_exists(file_name.str());

  Xdr extra_interpolation_point_in(file_name.str(), mode);

  {
    Real x_val, y_val, z_val = 0.;
    extra_interpolation_point_in >> x_val;

    if(LIBMESH_DIM >= 2)
      extra_interpolation_point_in >> y_val;

    if(LIBMESH_DIM >= 3)
      extra_interpolation_point_in >> z_val;

    Point p(x_val, y_val, z_val);
    extra_interpolation_point = p;
  }
  extra_interpolation_point_in.close();


  // Next read in interpolation_points_var
  file_name.str("");
  file_name << directory_name << "/interpolation_points_var" << suffix;
  assert_file_exists(file_name.str());

  Xdr interpolation_points_var_in(file_name.str(), mode);

  for(unsigned int i=0; i<n_bfs; i++)
    {
      unsigned int var;
      interpolation_points_var_in >> var;
      interpolation_points_var.push_back(var);
    }
  interpolation_points_var_in.close();

  // Also, read in extra_interpolation_point_var
  file_name.str("");
  file_name << directory_name << "/extra_interpolation_point_var" << suffix;
  assert_file_exists(file_name.str());

  Xdr extra_interpolation_point_var_in(file_name.str(), mode);

  {
    unsigned int var;
    extra_interpolation_point_var_in >> var;
    extra_interpolation_point_var = var;
  }
  extra_interpolation_point_var_in.close();

  // Read in the elements corresponding to the interpolation points
  legacy_read_in_interpolation_points_elem(directory_name);

  STOP_LOG("legacy_read_offline_data_from_files()", "RBEIMEvaluation");
}
void __libmesh_nlopt_inequality_constraints(unsigned m,
                                            double * result,
                                            unsigned n,
                                            const double * x,
                                            double * gradient,
                                            void * data)
{
  START_LOG("inequality_constraints()", "NloptOptimizationSolver");

  libmesh_assert(data);

  // data should be a pointer to the solver (it was passed in as void *)
  NloptOptimizationSolver<Number> * solver =
    static_cast<NloptOptimizationSolver<Number> *> (data);

  OptimizationSystem & sys = solver->system();

  // We'll use current_local_solution below, so let's ensure that it's consistent
  // with the vector x that was passed in.
  if (sys.solution->size() != n)
    libmesh_error_msg("Error: Input vector x has different length than sys.solution!");

  for(unsigned int i=sys.solution->first_local_index(); i<sys.solution->last_local_index(); i++)
    sys.solution->set(i, x[i]);
  sys.solution->close();

  // Impose constraints on the solution vector
  sys.get_dof_map().enforce_constraints_exactly(sys);

  // Update sys.current_local_solution based on the solution vector
  sys.update();

  // Call the user's inequality constraints function if there is one.
  OptimizationSystem::ComputeInequalityConstraints * ineco = solver->inequality_constraints_object;
  if (ineco)
    {
      ineco->inequality_constraints(*sys.current_local_solution,
                                    *sys.C_ineq,
                                    sys);

      sys.C_ineq->close();

      // Copy the values out of ineq_constraints into 'result'.
      // TODO: Even better would be if we could use 'result' directly
      // as the storage of ineq_constraints.  Perhaps a serial-only
      // NumericVector variant which supports this option?
      for (unsigned i=0; i<m; ++i)
        result[i] = (*sys.C_ineq)(i);

      // If gradient != NULL, then the Jacobian matrix of the equality
      // constraints has been requested.  The incoming 'gradient'
      // array is of length m*n and d(c_i)/d(x_j) = gradient[n*i+j].
      if (gradient)
        {
          OptimizationSystem::ComputeInequalityConstraintsJacobian * ineco_jac =
            solver->inequality_constraints_jacobian_object;

          if (ineco_jac)
            {
              ineco_jac->inequality_constraints_jacobian(*sys.current_local_solution,
                                                         *sys.C_ineq_jac,
                                                         sys);

              sys.C_ineq_jac->close();

              // copy the Jacobian data to the gradient array
              for(numeric_index_type i=0; i<m; i++)
                {
                  std::set<numeric_index_type>::iterator it = sys.ineq_constraint_jac_sparsity[i].begin();
                  std::set<numeric_index_type>::iterator it_end = sys.ineq_constraint_jac_sparsity[i].end();
                  for( ; it != it_end; ++it)
                    {
                      numeric_index_type dof_index = *it;
                      gradient[n*i+dof_index] = (*sys.C_ineq_jac)(i,dof_index);
                    }
                }
            }
          else
            libmesh_error_msg("Jacobian function not defined in __libmesh_nlopt_inequality_constraints");
        }

    }
  else
    libmesh_error_msg("Constraints function not defined in __libmesh_nlopt_inequality_constraints");

  STOP_LOG("inequality_constraints()", "NloptOptimizationSolver");
}
Example #8
0
void InfFE<Dim,T_radial,T_map>::init_shape_functions(const Elem * inf_elem)
{
  libmesh_assert(inf_elem);


  // Start logging the radial shape function initialization
  START_LOG("init_shape_functions()", "InfFE");


  // -----------------------------------------------------------------
  // fast access to some const int's for the radial data
  const unsigned int n_radial_mapping_sf =
    cast_int<unsigned int>(radial_map.size());
  const unsigned int n_radial_approx_sf  =
    cast_int<unsigned int>(mode.size());
  const unsigned int n_radial_qp         =
    cast_int<unsigned int>(som.size());


  // -----------------------------------------------------------------
  // initialize most of the things related to mapping

  // The element type and order to use in the base map
  const Order    base_mapping_order     ( base_elem->default_order() );
  const ElemType base_mapping_elem_type ( base_elem->type()          );

  // the number of base shape functions used to construct the map
  // (Lagrange shape functions are used for mapping in the base)
  unsigned int n_base_mapping_shape_functions = Base::n_base_mapping_sf(base_mapping_elem_type,
                                                                        base_mapping_order);

  const unsigned int n_total_mapping_shape_functions =
    n_radial_mapping_sf * n_base_mapping_shape_functions;



  // -----------------------------------------------------------------
  // initialize most of the things related to physical approximation

  unsigned int n_base_approx_shape_functions;
  if (Dim > 1)
    n_base_approx_shape_functions = base_fe->n_shape_functions();
  else
    n_base_approx_shape_functions = 1;


  const unsigned int n_total_approx_shape_functions =
    n_radial_approx_sf * n_base_approx_shape_functions;

  // update class member field
  _n_total_approx_sf = n_total_approx_shape_functions;


  // The number of the base quadrature points.
  const unsigned int        n_base_qp =  base_qrule->n_points();

  // The total number of quadrature points.
  const unsigned int        n_total_qp =  n_radial_qp * n_base_qp;


  // update class member field
  _n_total_qp = n_total_qp;



  // -----------------------------------------------------------------
  // initialize the node and shape numbering maps
  {
    // these vectors work as follows: the i-th entry stores
    // the associated base/radial node number
    _radial_node_index.resize    (n_total_mapping_shape_functions);
    _base_node_index.resize      (n_total_mapping_shape_functions);

    // similar for the shapes: the i-th entry stores
    // the associated base/radial shape number
    _radial_shape_index.resize   (n_total_approx_shape_functions);
    _base_shape_index.resize     (n_total_approx_shape_functions);

    const ElemType inf_elem_type (inf_elem->type());

    // fill the node index map
    for (unsigned int n=0; n<n_total_mapping_shape_functions; n++)
      {
        compute_node_indices (inf_elem_type,
                              n,
                              _base_node_index[n],
                              _radial_node_index[n]);
        libmesh_assert_less (_base_node_index[n], n_base_mapping_shape_functions);
        libmesh_assert_less (_radial_node_index[n], n_radial_mapping_sf);
      }

    // fill the shape index map
    for (unsigned int n=0; n<n_total_approx_shape_functions; n++)
      {
        compute_shape_indices (this->fe_type,
                               inf_elem_type,
                               n,
                               _base_shape_index[n],
                               _radial_shape_index[n]);
        libmesh_assert_less (_base_shape_index[n], n_base_approx_shape_functions);
        libmesh_assert_less (_radial_shape_index[n], n_radial_approx_sf);
      }
  }





  // -----------------------------------------------------------------
  // resize the base data fields
  dist.resize(n_base_mapping_shape_functions);



  // -----------------------------------------------------------------
  // resize the total data fields

  // the phase term varies with xi, eta and zeta(v): store it for _all_ qp
  //
  // when computing the phase, we need the base approximations
  // therefore, initialize the phase here, but evaluate it
  // in combine_base_radial().
  //
  // the weight, though, is only needed at the radial quadrature points, n_radial_qp.
  // but for a uniform interface to the protected data fields
  // the weight data field (which are accessible from the outside) are expanded to n_total_qp.
  weight.resize      (n_total_qp);
  dweightdv.resize   (n_total_qp);
  dweight.resize     (n_total_qp);

  dphase.resize      (n_total_qp);
  dphasedxi.resize   (n_total_qp);
  dphasedeta.resize  (n_total_qp);
  dphasedzeta.resize (n_total_qp);

  // this vector contains the integration weights for the combined quadrature rule
  _total_qrule_weights.resize(n_total_qp);


  // -----------------------------------------------------------------
  // InfFE's data fields phi, dphi, dphidx, phi_map etc hold the _total_
  // shape and mapping functions, respectively
  {
    phi.resize     (n_total_approx_shape_functions);
    dphi.resize    (n_total_approx_shape_functions);
    dphidx.resize  (n_total_approx_shape_functions);
    dphidy.resize  (n_total_approx_shape_functions);
    dphidz.resize  (n_total_approx_shape_functions);
    dphidxi.resize (n_total_approx_shape_functions);
#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    libmesh_do_once(libMesh::err << "Second derivatives for Infinite elements"
                    << " are not yet implemented!"
                    << std::endl);

    d2phi.resize     (n_total_approx_shape_functions);
    d2phidx2.resize  (n_total_approx_shape_functions);
    d2phidxdy.resize (n_total_approx_shape_functions);
    d2phidxdz.resize (n_total_approx_shape_functions);
    d2phidy2.resize  (n_total_approx_shape_functions);
    d2phidydz.resize (n_total_approx_shape_functions);
    d2phidz2.resize  (n_total_approx_shape_functions);
    d2phidxi2.resize (n_total_approx_shape_functions);

    if (Dim > 1)
      {
        d2phidxideta.resize   (n_total_approx_shape_functions);
        d2phideta2.resize     (n_total_approx_shape_functions);
      }

    if (Dim > 2)
      {
        d2phidetadzeta.resize (n_total_approx_shape_functions);
        d2phidxidzeta.resize  (n_total_approx_shape_functions);
        d2phidzeta2.resize    (n_total_approx_shape_functions);
      }
#endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES

    if (Dim > 1)
      dphideta.resize      (n_total_approx_shape_functions);

    if (Dim == 3)
      dphidzeta.resize     (n_total_approx_shape_functions);



    std::vector<std::vector<Real> > & phi_map = this->_fe_map->get_phi_map();
    std::vector<std::vector<Real> > & dphidxi_map = this->_fe_map->get_dphidxi_map();

    phi_map.resize         (n_total_mapping_shape_functions);
    dphidxi_map.resize     (n_total_mapping_shape_functions);
#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    std::vector<std::vector<Real> > & d2phidxi2_map = this->_fe_map->get_d2phidxi2_map();
    d2phidxi2_map.resize   (n_total_mapping_shape_functions);

    if (Dim > 1)
      {
        std::vector<std::vector<Real> > & d2phidxideta_map = this->_fe_map->get_d2phidxideta_map();
        std::vector<std::vector<Real> > & d2phideta2_map = this->_fe_map->get_d2phideta2_map();
        d2phidxideta_map.resize   (n_total_mapping_shape_functions);
        d2phideta2_map.resize     (n_total_mapping_shape_functions);
      }

    if (Dim == 3)
      {
        std::vector<std::vector<Real> > & d2phidxidzeta_map = this->_fe_map->get_d2phidxidzeta_map();
        std::vector<std::vector<Real> > & d2phidetadzeta_map = this->_fe_map->get_d2phidetadzeta_map();
        std::vector<std::vector<Real> > & d2phidzeta2_map = this->_fe_map->get_d2phidzeta2_map();
        d2phidxidzeta_map.resize  (n_total_mapping_shape_functions);
        d2phidetadzeta_map.resize (n_total_mapping_shape_functions);
        d2phidzeta2_map.resize    (n_total_mapping_shape_functions);
      }
#endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES

    if (Dim > 1)
      {
        std::vector<std::vector<Real> > & dphideta_map = this->_fe_map->get_dphideta_map();
        dphideta_map.resize  (n_total_mapping_shape_functions);
      }

    if (Dim == 3)
      {
        std::vector<std::vector<Real> > & dphidzeta_map = this->_fe_map->get_dphidzeta_map();
        dphidzeta_map.resize (n_total_mapping_shape_functions);
      }
  }



  // -----------------------------------------------------------------
  // collect all the for loops, where inner vectors are
  // resized to the appropriate number of quadrature points
  {
    for (unsigned int i=0; i<n_total_approx_shape_functions; i++)
      {
        phi[i].resize         (n_total_qp);
        dphi[i].resize        (n_total_qp);
        dphidx[i].resize      (n_total_qp);
        dphidy[i].resize      (n_total_qp);
        dphidz[i].resize      (n_total_qp);
        dphidxi[i].resize     (n_total_qp);
#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
        d2phi[i].resize       (n_total_qp);
        d2phidx2[i].resize    (n_total_qp);
        d2phidxdy[i].resize   (n_total_qp);
        d2phidxdz[i].resize   (n_total_qp);
        d2phidy2[i].resize    (n_total_qp);
        d2phidydz[i].resize   (n_total_qp);
        d2phidy2[i].resize    (n_total_qp);
        d2phidxi2[i].resize   (n_total_qp);

        if (Dim > 1)
          {
            d2phidxideta[i].resize   (n_total_qp);
            d2phideta2[i].resize     (n_total_qp);
          }
        if (Dim > 2)
          {
            d2phidxidzeta[i].resize  (n_total_qp);
            d2phidetadzeta[i].resize (n_total_qp);
            d2phidzeta2[i].resize    (n_total_qp);
          }
#endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES

        if (Dim > 1)
          dphideta[i].resize  (n_total_qp);

        if (Dim == 3)
          dphidzeta[i].resize (n_total_qp);

      }

    for (unsigned int i=0; i<n_total_mapping_shape_functions; i++)
      {
        std::vector<std::vector<Real> > & phi_map = this->_fe_map->get_phi_map();
        std::vector<std::vector<Real> > & dphidxi_map = this->_fe_map->get_dphidxi_map();
        phi_map[i].resize         (n_total_qp);
        dphidxi_map[i].resize     (n_total_qp);
#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
        std::vector<std::vector<Real> > & d2phidxi2_map = this->_fe_map->get_d2phidxi2_map();
        d2phidxi2_map[i].resize   (n_total_qp);
        if (Dim > 1)
          {
            std::vector<std::vector<Real> > & d2phidxideta_map = this->_fe_map->get_d2phidxideta_map();
            std::vector<std::vector<Real> > & d2phideta2_map = this->_fe_map->get_d2phideta2_map();
            d2phidxideta_map[i].resize   (n_total_qp);
            d2phideta2_map[i].resize     (n_total_qp);
          }

        if (Dim > 2)
          {
            std::vector<std::vector<Real> > & d2phidxidzeta_map = this->_fe_map->get_d2phidxidzeta_map();
            std::vector<std::vector<Real> > & d2phidetadzeta_map = this->_fe_map->get_d2phidetadzeta_map();
            std::vector<std::vector<Real> > & d2phidzeta2_map = this->_fe_map->get_d2phidzeta2_map();
            d2phidxidzeta_map[i].resize  (n_total_qp);
            d2phidetadzeta_map[i].resize (n_total_qp);
            d2phidzeta2_map[i].resize    (n_total_qp);
          }
#endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES

        if (Dim > 1)
          {
            std::vector<std::vector<Real> > & dphideta_map = this->_fe_map->get_dphideta_map();
            dphideta_map[i].resize  (n_total_qp);
          }

        if (Dim == 3)
          {
            std::vector<std::vector<Real> > & dphidzeta_map = this->_fe_map->get_dphidzeta_map();
            dphidzeta_map[i].resize (n_total_qp);
          }
      }
  }



  {
    // -----------------------------------------------------------------
    // (a) compute scalar values at _all_ quadrature points  -- for uniform
    //     access from the outside to these fields
    // (b) form a std::vector<Real> which contains the appropriate weights
    //     of the combined quadrature rule!
    const std::vector<Point> &  radial_qp = radial_qrule->get_points();
    libmesh_assert_equal_to (radial_qp.size(), n_radial_qp);

    const std::vector<Real> &   radial_qw = radial_qrule->get_weights();
    const std::vector<Real> &   base_qw   = base_qrule->get_weights();
    libmesh_assert_equal_to (radial_qw.size(), n_radial_qp);
    libmesh_assert_equal_to (base_qw.size(), n_base_qp);

    for (unsigned int rp=0; rp<n_radial_qp; rp++)
      for (unsigned int bp=0; bp<n_base_qp; bp++)
        {
          weight   [ bp+rp*n_base_qp ] = Radial::D       (radial_qp[rp](0));
          dweightdv[ bp+rp*n_base_qp ] = Radial::D_deriv (radial_qp[rp](0));

          _total_qrule_weights[  bp+rp*n_base_qp ] = radial_qw[rp] * base_qw[bp];
        }
  }


  /**
   * Stop logging the radial shape function initialization
   */
  STOP_LOG("init_shape_functions()", "InfFE");

}
Example #9
0
void InfFE<Dim,T_radial,T_map>::combine_base_radial(const Elem * inf_elem)
{
  libmesh_assert(inf_elem);
  // at least check whether the base element type is correct.
  // otherwise this version of computing dist would give problems
  libmesh_assert_equal_to (base_elem->type(), Base::get_elem_type(inf_elem->type()));


  /**
   * Start logging the combination of radial and base parts
   */
  START_LOG("combine_base_radial()", "InfFE");


  // zero  the phase, since it is to be summed up
  std::fill (dphasedxi.begin(),   dphasedxi.end(),   0.);
  std::fill (dphasedeta.begin(),  dphasedeta.end(),  0.);
  std::fill (dphasedzeta.begin(), dphasedzeta.end(), 0.);


  const unsigned int n_base_mapping_sf =
    cast_int<unsigned int>(dist.size());
  const Point origin = inf_elem->origin();

  // for each new infinite element, compute the radial distances
  for (unsigned int n=0; n<n_base_mapping_sf; n++)
    dist[n] =  Point(base_elem->point(n) - origin).size();


  switch (Dim)
    {

      //------------------------------------------------------------
      // 1D
    case 1:
      {
        libmesh_not_implemented();
        break;
      }



      //------------------------------------------------------------
      // 2D
    case 2:
      {
        libmesh_not_implemented();
        break;
      }



      //------------------------------------------------------------
      // 3D
    case 3:
      {
        // fast access to the approximation and mapping shapes of base_fe
        const std::vector<std::vector<Real> > & S  = base_fe->phi;
        const std::vector<std::vector<Real> > & Ss = base_fe->dphidxi;
        const std::vector<std::vector<Real> > & St = base_fe->dphideta;
        const std::vector<std::vector<Real> > & S_map  = (base_fe->get_fe_map()).get_phi_map();
        const std::vector<std::vector<Real> > & Ss_map = (base_fe->get_fe_map()).get_dphidxi_map();
        const std::vector<std::vector<Real> > & St_map = (base_fe->get_fe_map()).get_dphideta_map();

        const unsigned int n_radial_qp         = radial_qrule->n_points();
        const unsigned int n_base_qp           = base_qrule->  n_points();

        const unsigned int n_total_mapping_sf  =
          cast_int<unsigned int>(radial_map.size()) * n_base_mapping_sf;

        const unsigned int n_total_approx_sf   = Radial::n_dofs(fe_type.radial_order) *  base_fe->n_shape_functions();


        // compute the phase term derivatives
        {
          unsigned int tp=0;
          for (unsigned int rp=0; rp<n_radial_qp; rp++)  // over radial qp's
            for (unsigned int bp=0; bp<n_base_qp; bp++)  // over base qp's
              {
                // sum over all base shapes, to get the average distance
                for (unsigned int i=0; i<n_base_mapping_sf; i++)
                  {
                    dphasedxi[tp]   += Ss_map[i][bp] * dist[i] * radial_map   [1][rp];
                    dphasedeta[tp]  += St_map[i][bp] * dist[i] * radial_map   [1][rp];
                    dphasedzeta[tp] += S_map [i][bp] * dist[i] * dradialdv_map[1][rp];
                  }

                tp++;

              } // loop radial and base qp's

        }

        libmesh_assert_equal_to (phi.size(), n_total_approx_sf);
        libmesh_assert_equal_to (dphidxi.size(), n_total_approx_sf);
        libmesh_assert_equal_to (dphideta.size(), n_total_approx_sf);
        libmesh_assert_equal_to (dphidzeta.size(), n_total_approx_sf);

        // compute the overall approximation shape functions,
        // pick the appropriate radial and base shapes through using
        // _base_shape_index and _radial_shape_index
        for (unsigned int rp=0; rp<n_radial_qp; rp++)  // over radial qp's
          for (unsigned int bp=0; bp<n_base_qp; bp++)  // over base qp's
            for (unsigned int ti=0; ti<n_total_approx_sf; ti++)  // over _all_ approx_sf
              {
                // let the index vectors take care of selecting the appropriate base/radial shape
                const unsigned int bi = _base_shape_index  [ti];
                const unsigned int ri = _radial_shape_index[ti];
                phi      [ti][bp+rp*n_base_qp] = S [bi][bp] * mode[ri][rp] * som[rp];
                dphidxi  [ti][bp+rp*n_base_qp] = Ss[bi][bp] * mode[ri][rp] * som[rp];
                dphideta [ti][bp+rp*n_base_qp] = St[bi][bp] * mode[ri][rp] * som[rp];
                dphidzeta[ti][bp+rp*n_base_qp] = S [bi][bp]
                  * (dmodedv[ri][rp] * som[rp] + mode[ri][rp] * dsomdv[rp]);
              }

        std::vector<std::vector<Real> > & phi_map = this->_fe_map->get_phi_map();
        std::vector<std::vector<Real> > & dphidxi_map = this->_fe_map->get_dphidxi_map();
        std::vector<std::vector<Real> > & dphideta_map = this->_fe_map->get_dphideta_map();
        std::vector<std::vector<Real> > & dphidzeta_map = this->_fe_map->get_dphidzeta_map();

        libmesh_assert_equal_to (phi_map.size(), n_total_mapping_sf);
        libmesh_assert_equal_to (dphidxi_map.size(), n_total_mapping_sf);
        libmesh_assert_equal_to (dphideta_map.size(), n_total_mapping_sf);
        libmesh_assert_equal_to (dphidzeta_map.size(), n_total_mapping_sf);

        // compute the overall mapping functions,
        // pick the appropriate radial and base entries through using
        // _base_node_index and _radial_node_index
        for (unsigned int rp=0; rp<n_radial_qp; rp++)  // over radial qp's
          for (unsigned int bp=0; bp<n_base_qp; bp++)  // over base qp's
            for (unsigned int ti=0; ti<n_total_mapping_sf; ti++)  // over all mapping shapes
              {
                // let the index vectors take care of selecting the appropriate base/radial mapping shape
                const unsigned int bi = _base_node_index  [ti];
                const unsigned int ri = _radial_node_index[ti];
                phi_map      [ti][bp+rp*n_base_qp] = S_map [bi][bp] * radial_map   [ri][rp];
                dphidxi_map  [ti][bp+rp*n_base_qp] = Ss_map[bi][bp] * radial_map   [ri][rp];
                dphideta_map [ti][bp+rp*n_base_qp] = St_map[bi][bp] * radial_map   [ri][rp];
                dphidzeta_map[ti][bp+rp*n_base_qp] = S_map [bi][bp] * dradialdv_map[ri][rp];
              }


        break;
      }

    default:
      libmesh_error_msg("Unsupported Dim = " << Dim);
    }


  /**
   * Start logging the combination of radial and base parts
   */
  STOP_LOG("combine_base_radial()", "InfFE");
}
Example #10
0
void FEMap::compute_edge_map(int dim,
			     const std::vector<Real>& qw,
			     const Elem* edge)
{
  libmesh_assert (edge != NULL);

  if (dim == 2)
    {
      // A 2D finite element living in either 2D or 3D space.
      // The edges here are the sides of the element, so the
      // (misnamed) compute_face_map function does what we want
      this->compute_face_map(dim, qw, edge);
      return;
    }

  libmesh_assert (dim == 3);  // 1D is unnecessary and currently unsupported

  START_LOG("compute_edge_map()", "FEMap");

  // The number of quadrature points.
  const unsigned int n_qp = qw.size();

  // Resize the vectors to hold data at the quadrature points
  this->xyz.resize(n_qp);
  this->dxyzdxi_map.resize(n_qp);
  this->dxyzdeta_map.resize(n_qp);
  this->d2xyzdxi2_map.resize(n_qp);
  this->d2xyzdxideta_map.resize(n_qp);
  this->d2xyzdeta2_map.resize(n_qp);
  this->tangents.resize(n_qp);
  this->normals.resize(n_qp);
  this->curvatures.resize(n_qp);

  this->JxW.resize(n_qp);

  // Clear the entities that will be summed
  for (unsigned int p=0; p<n_qp; p++)
    {
      this->tangents[p].resize(1);
      this->xyz[p].zero();
      this->dxyzdxi_map[p].zero();
      this->dxyzdeta_map[p].zero();
      this->d2xyzdxi2_map[p].zero();
      this->d2xyzdxideta_map[p].zero();
      this->d2xyzdeta2_map[p].zero();
    }

  // compute x, dxdxi at the quadrature points
  for (unsigned int i=0; i<this->psi_map.size(); i++) // sum over the nodes
    {
      const Point& edge_point = edge->point(i);

      for (unsigned int p=0; p<n_qp; p++) // for each quadrature point...
        {
	  this->xyz[p].add_scaled             (edge_point, this->psi_map[i][p]);
	  this->dxyzdxi_map[p].add_scaled     (edge_point, this->dpsidxi_map[i][p]);
	  this->d2xyzdxi2_map[p].add_scaled   (edge_point, this->d2psidxi2_map[i][p]);
        }
    }

  // Compute the tangents at the quadrature point
  // FIXME: normals (plural!) and curvatures are uncalculated
  for (unsigned int p=0; p<n_qp; p++)
    {
      const Point n  = this->dxyzdxi_map[p].cross(this->dxyzdeta_map[p]);
      this->tangents[p][0] = this->dxyzdxi_map[p].unit();

      // compute the jacobian at the quadrature points
      const Real jac = std::sqrt(this->dxdxi_map(p)*this->dxdxi_map(p) +
				 this->dydxi_map(p)*this->dydxi_map(p) +
				 this->dzdxi_map(p)*this->dzdxi_map(p));

      libmesh_assert (jac > 0.);

      this->JxW[p] = jac*qw[p];
    }

  STOP_LOG("compute_edge_map()", "FEMap");
}
Example #11
0
void InfFE<Dim,T_radial,T_map>::init_radial_shape_functions(const Elem * libmesh_dbg_var(inf_elem))
{
  libmesh_assert(radial_qrule);
  libmesh_assert(inf_elem);


  /**
   * Start logging the radial shape function initialization
   */
  START_LOG("init_radial_shape_functions()", "InfFE");


  // -----------------------------------------------------------------
  // initialize most of the things related to mapping

  // The order to use in the radial map (currently independent of the element type)
  const Order        radial_mapping_order             (Radial::mapping_order());
  const unsigned int n_radial_mapping_shape_functions (Radial::n_dofs(radial_mapping_order));



  // -----------------------------------------------------------------
  // initialize most of the things related to physical approximation

  const Order        radial_approx_order             (fe_type.radial_order);
  const unsigned int n_radial_approx_shape_functions (Radial::n_dofs(radial_approx_order));

  const unsigned int        n_radial_qp = radial_qrule->n_points();
  const std::vector<Point> &   radial_qp = radial_qrule->get_points();



  // -----------------------------------------------------------------
  // resize the radial data fields

  mode.resize      (n_radial_approx_shape_functions);       // the radial polynomials (eval)
  dmodedv.resize   (n_radial_approx_shape_functions);

  som.resize       (n_radial_qp);                           // the (1-v)/2 weight
  dsomdv.resize    (n_radial_qp);

  radial_map.resize    (n_radial_mapping_shape_functions);  // the radial map
  dradialdv_map.resize (n_radial_mapping_shape_functions);


  for (unsigned int i=0; i<n_radial_mapping_shape_functions; i++)
    {
      radial_map[i].resize    (n_radial_qp);
      dradialdv_map[i].resize (n_radial_qp);
    }


  for (unsigned int i=0; i<n_radial_approx_shape_functions; i++)
    {
      mode[i].resize    (n_radial_qp);
      dmodedv[i].resize (n_radial_qp);
    }


  // compute scalar values at radial quadrature points
  for (unsigned int p=0; p<n_radial_qp; p++)
    {
      som[p]       = Radial::decay       (radial_qp[p](0));
      dsomdv[p]    = Radial::decay_deriv (radial_qp[p](0));
    }


  // evaluate the mode shapes in radial direction at radial quadrature points
  for (unsigned int i=0; i<n_radial_approx_shape_functions; i++)
    for (unsigned int p=0; p<n_radial_qp; p++)
      {
        mode[i][p]    = InfFE<Dim,T_radial,T_map>::eval       (radial_qp[p](0), radial_approx_order, i);
        dmodedv[i][p] = InfFE<Dim,T_radial,T_map>::eval_deriv (radial_qp[p](0), radial_approx_order, i);
      }


  // evaluate the mapping functions in radial direction at radial quadrature points
  for (unsigned int i=0; i<n_radial_mapping_shape_functions; i++)
    for (unsigned int p=0; p<n_radial_qp; p++)
      {
        radial_map[i][p]    = InfFE<Dim,INFINITE_MAP,T_map>::eval       (radial_qp[p](0), radial_mapping_order, i);
        dradialdv_map[i][p] = InfFE<Dim,INFINITE_MAP,T_map>::eval_deriv (radial_qp[p](0), radial_mapping_order, i);
      }

  /**
   * Stop logging the radial shape function initialization
   */
  STOP_LOG("init_radial_shape_functions()", "InfFE");

}
Example #12
0
void FEMap::compute_face_map(int dim, const std::vector<Real>& qw,
			     const Elem* side)
{
  libmesh_assert (side  != NULL);

  START_LOG("compute_face_map()", "FEMap");

  // The number of quadrature points.
  const unsigned int n_qp = qw.size();


  switch (dim)
    {
    case 1:
      {
	// A 1D finite element, currently assumed to be in 1D space
	// This means the boundary is a "0D finite element", a
        // NODEELEM.

	// Resize the vectors to hold data at the quadrature points
	{
	  this->xyz.resize(n_qp);
	  normals.resize(n_qp);

	  this->JxW.resize(n_qp);
        }

        // If we have no quadrature points, there's nothing else to do
        if (!n_qp)
          break;

        // We need to look back at the full edge to figure out the normal
        // vector
        const Elem *elem = side->parent();
        libmesh_assert (elem);
        if (side->node(0) == elem->node(0))
          normals[0] = Point(-1.);
        else
          {
            libmesh_assert (side->node(0) == elem->node(1));
            normals[0] = Point(1.);
          }

        // Calculate x at the point
	libmesh_assert (this->psi_map.size() == 1);
        // In the unlikely event we have multiple quadrature
        // points, they'll be in the same place
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    this->xyz[p].zero();
	    this->xyz[p].add_scaled          (side->point(0), this->psi_map[0][p]);
            normals[p] = normals[0];
	    this->JxW[p] = 1.0*qw[p];
          }

	// done computing the map
	break;
      }

    case 2:
      {
	// A 2D finite element living in either 2D or 3D space.
	// This means the boundary is a 1D finite element, i.e.
	// and EDGE2 or EDGE3.
	// Resize the vectors to hold data at the quadrature points
	{
	  this->xyz.resize(n_qp);
	  this->dxyzdxi_map.resize(n_qp);
	  this->d2xyzdxi2_map.resize(n_qp);
	  this->tangents.resize(n_qp);
	  this->normals.resize(n_qp);
	  this->curvatures.resize(n_qp);

	  this->JxW.resize(n_qp);
	}

	// Clear the entities that will be summed
	// Compute the tangent & normal at the quadrature point
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    this->tangents[p].resize(LIBMESH_DIM-1); // 1 Tangent in 2D, 2 in 3D
	    this->xyz[p].zero();
	    this->dxyzdxi_map[p].zero();
	    this->d2xyzdxi2_map[p].zero();
	  }

	// compute x, dxdxi at the quadrature points
	for (unsigned int i=0; i<this->psi_map.size(); i++) // sum over the nodes
	  {
	    const Point& side_point = side->point(i);

	    for (unsigned int p=0; p<n_qp; p++) // for each quadrature point...
	      {
		this->xyz[p].add_scaled          (side_point, this->psi_map[i][p]);
		this->dxyzdxi_map[p].add_scaled  (side_point, this->dpsidxi_map[i][p]);
		this->d2xyzdxi2_map[p].add_scaled(side_point, this->d2psidxi2_map[i][p]);
	      }
	  }

	// Compute the tangent & normal at the quadrature point
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    // The first tangent comes from just the edge's Jacobian
	    this->tangents[p][0] = this->dxyzdxi_map[p].unit();

#if LIBMESH_DIM == 2
	    // For a 2D element living in 2D, the normal is given directly
	    // from the entries in the edge Jacobian.
	    this->normals[p] = (Point(this->dxyzdxi_map[p](1), -this->dxyzdxi_map[p](0), 0.)).unit();

#elif LIBMESH_DIM == 3
	    // For a 2D element living in 3D, there is a second tangent.
	    // For the second tangent, we need to refer to the full
	    // element's (not just the edge's) Jacobian.
	    const Elem *elem = side->parent();
	    libmesh_assert (elem != NULL);

	    // Inverse map xyz[p] to a reference point on the parent...
	    Point reference_point = FE<2,LAGRANGE>::inverse_map(elem, this->xyz[p]);

	    // Get dxyz/dxi and dxyz/deta from the parent map.
	    Point dx_dxi  = FE<2,LAGRANGE>::map_xi (elem, reference_point);
	    Point dx_deta = FE<2,LAGRANGE>::map_eta(elem, reference_point);

	    // The second tangent vector is formed by crossing these vectors.
	    tangents[p][1] = dx_dxi.cross(dx_deta).unit();

	    // Finally, the normal in this case is given by crossing these
	    // two tangents.
	    normals[p] = tangents[p][0].cross(tangents[p][1]).unit();
#endif


	    // The curvature is computed via the familiar Frenet formula:
	    // curvature = [d^2(x) / d (xi)^2] dot [normal]
	    // For a reference, see:
	    // F.S. Merritt, Mathematics Manual, 1962, McGraw-Hill, p. 310
	    //
	    // Note: The sign convention here is different from the
	    // 3D case.  Concave-upward curves (smiles) have a positive
	    // curvature.  Concave-downward curves (frowns) have a
	    // negative curvature.  Be sure to take that into account!
	    const Real numerator   = this->d2xyzdxi2_map[p] * this->normals[p];
	    const Real denominator = this->dxyzdxi_map[p].size_sq();
	    libmesh_assert (denominator != 0);
	    curvatures[p] = numerator / denominator;
	  }

	// compute the jacobian at the quadrature points
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    const Real jac = this->dxyzdxi_map[p].size();

	    libmesh_assert (jac > 0.);

	    this->JxW[p] = jac*qw[p];
	  }

	// done computing the map
	break;
      }



    case 3:
      {
	// A 3D finite element living in 3D space.
	// Resize the vectors to hold data at the quadrature points
	{
	  this->xyz.resize(n_qp);
	  this->dxyzdxi_map.resize(n_qp);
	  this->dxyzdeta_map.resize(n_qp);
	  this->d2xyzdxi2_map.resize(n_qp);
	  this->d2xyzdxideta_map.resize(n_qp);
	  this->d2xyzdeta2_map.resize(n_qp);
	  this->tangents.resize(n_qp);
	  this->normals.resize(n_qp);
	  this->curvatures.resize(n_qp);

	  this->JxW.resize(n_qp);
	}

	// Clear the entities that will be summed
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    this->tangents[p].resize(LIBMESH_DIM-1); // 1 Tangent in 2D, 2 in 3D
	    this->xyz[p].zero();
	    this->dxyzdxi_map[p].zero();
	    this->dxyzdeta_map[p].zero();
	    this->d2xyzdxi2_map[p].zero();
	    this->d2xyzdxideta_map[p].zero();
	    this->d2xyzdeta2_map[p].zero();
	  }

	// compute x, dxdxi at the quadrature points
	for (unsigned int i=0; i<this->psi_map.size(); i++) // sum over the nodes
	  {
	    const Point& side_point = side->point(i);

	    for (unsigned int p=0; p<n_qp; p++) // for each quadrature point...
	      {
		this->xyz[p].add_scaled         (side_point, this->psi_map[i][p]);
		this->dxyzdxi_map[p].add_scaled (side_point, this->dpsidxi_map[i][p]);
		this->dxyzdeta_map[p].add_scaled(side_point, this->dpsideta_map[i][p]);
		this->d2xyzdxi2_map[p].add_scaled   (side_point, this->d2psidxi2_map[i][p]);
		this->d2xyzdxideta_map[p].add_scaled(side_point, this->d2psidxideta_map[i][p]);
		this->d2xyzdeta2_map[p].add_scaled  (side_point, this->d2psideta2_map[i][p]);
	      }
	  }

	// Compute the tangents, normal, and curvature at the quadrature point
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    const Point n  = this->dxyzdxi_map[p].cross(this->dxyzdeta_map[p]);
	    this->normals[p]     = n.unit();
	    this->tangents[p][0] = this->dxyzdxi_map[p].unit();
	    this->tangents[p][1] = n.cross(this->dxyzdxi_map[p]).unit();

	    // Compute curvature using the typical nomenclature
	    // of the first and second fundamental forms.
	    // For reference, see:
	    // 1) http://mathworld.wolfram.com/MeanCurvature.html
	    //    (note -- they are using inward normal)
	    // 2) F.S. Merritt, Mathematics Manual, 1962, McGraw-Hill
	    const Real L  = -this->d2xyzdxi2_map[p]    * this->normals[p];
	    const Real M  = -this->d2xyzdxideta_map[p] * this->normals[p];
	    const Real N  = -this->d2xyzdeta2_map[p]   * this->normals[p];
	    const Real E  =  this->dxyzdxi_map[p].size_sq();
	    const Real F  =  this->dxyzdxi_map[p]      * this->dxyzdeta_map[p];
	    const Real G  =  this->dxyzdeta_map[p].size_sq();

	    const Real numerator   = E*N -2.*F*M + G*L;
	    const Real denominator = E*G - F*F;
	    libmesh_assert (denominator != 0.);
	    curvatures[p] = 0.5*numerator/denominator;
	  }

	// compute the jacobian at the quadrature points, see
	// http://sp81.msi.umn.edu:999/fluent/fidap/help/theory/thtoc.htm
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    const Real g11 = (dxdxi_map(p)*dxdxi_map(p) +
			      dydxi_map(p)*dydxi_map(p) +
			      dzdxi_map(p)*dzdxi_map(p));

	    const Real g12 = (dxdxi_map(p)*dxdeta_map(p) +
			      dydxi_map(p)*dydeta_map(p) +
			      dzdxi_map(p)*dzdeta_map(p));

	    const Real g21 = g12;

	    const Real g22 = (dxdeta_map(p)*dxdeta_map(p) +
			      dydeta_map(p)*dydeta_map(p) +
			      dzdeta_map(p)*dzdeta_map(p));


	    const Real jac = std::sqrt(g11*g22 - g12*g21);

	    libmesh_assert (jac > 0.);

	    this->JxW[p] = jac*qw[p];
	  }

	// done computing the map
	break;
      }


    default:
      libmesh_error();

    }
  STOP_LOG("compute_face_map()", "FEMap");
}
Example #13
0
void FEMap::init_face_shape_functions(const std::vector<Point>& qp,
				      const Elem* side)
{
  libmesh_assert (side  != NULL);

  /**
   * Start logging the shape function initialization
   */
  START_LOG("init_face_shape_functions()", "FEMap");

  // The element type and order to use in
  // the map
  const Order    mapping_order     (side->default_order());
  const ElemType mapping_elem_type (side->type());

  // The number of quadrature points.
  const unsigned int n_qp = qp.size();

  const unsigned int n_mapping_shape_functions =
    FE<Dim,LAGRANGE>::n_shape_functions (mapping_elem_type,
					 mapping_order);

  // resize the vectors to hold current data
  // Psi are the shape functions used for the FE mapping
  this->psi_map.resize        (n_mapping_shape_functions);

  if (Dim > 1)
    {
      this->dpsidxi_map.resize    (n_mapping_shape_functions);
      this->d2psidxi2_map.resize  (n_mapping_shape_functions);
    }

  if (Dim == 3)
    {
      this->dpsideta_map.resize     (n_mapping_shape_functions);
      this->d2psidxideta_map.resize (n_mapping_shape_functions);
      this->d2psideta2_map.resize   (n_mapping_shape_functions);
    }

  for (unsigned int i=0; i<n_mapping_shape_functions; i++)
    {
      // Allocate space to store the values of the shape functions
      // and their first and second derivatives at the quadrature points.
      this->psi_map[i].resize        (n_qp);
      if (Dim > 1)
        {
          this->dpsidxi_map[i].resize    (n_qp);
          this->d2psidxi2_map[i].resize  (n_qp);
        }
      if (Dim == 3)
	{
	  this->dpsideta_map[i].resize     (n_qp);
	  this->d2psidxideta_map[i].resize (n_qp);
	  this->d2psideta2_map[i].resize   (n_qp);
	}

      // Compute the value of shape function i, and its first and
      // second derivatives at quadrature point p
      // (Lagrange shape functions are used for the mapping)
      for (unsigned int p=0; p<n_qp; p++)
	{
	  this->psi_map[i][p]        = FE<Dim-1,LAGRANGE>::shape             (mapping_elem_type, mapping_order, i,    qp[p]);
          if (Dim > 1)
	    {
	      this->dpsidxi_map[i][p]    = FE<Dim-1,LAGRANGE>::shape_deriv       (mapping_elem_type, mapping_order, i, 0, qp[p]);
	      this->d2psidxi2_map[i][p]  = FE<Dim-1,LAGRANGE>::shape_second_deriv(mapping_elem_type, mapping_order, i, 0, qp[p]);
	    }
	  // libMesh::out << "this->d2psidxi2_map["<<i<<"][p]=" << d2psidxi2_map[i][p] << std::endl;

	  // If we are in 3D, then our sides are 2D faces.
	  // For the second derivatives, we must also compute the cross
	  // derivative d^2() / dxi deta
	  if (Dim == 3)
	    {
	      this->dpsideta_map[i][p]     = FE<Dim-1,LAGRANGE>::shape_deriv       (mapping_elem_type, mapping_order, i, 1, qp[p]);
	      this->d2psidxideta_map[i][p] = FE<Dim-1,LAGRANGE>::shape_second_deriv(mapping_elem_type, mapping_order, i, 1, qp[p]);
	      this->d2psideta2_map[i][p]   = FE<Dim-1,LAGRANGE>::shape_second_deriv(mapping_elem_type, mapping_order, i, 2, qp[p]);
	    }
	}
    }


  /**
   * Stop logging the shape function initialization
   */
  STOP_LOG("init_face_shape_functions()", "FEMap");
}
Example #14
0
void UNVIO::node_in (std::istream& in_file)
{
  START_LOG("node_in()","UNVIO");

  if (this->verbose())
    libMesh::out << "  Reading nodes" << std::endl;

  // adjust the \p istream to our position
  const bool ok = this->beginning_of_dataset(in_file, _label_dataset_nodes);

  if (!ok)
    {
      libMesh::err << "ERROR: Could not find node dataset!" << std::endl;
      libmesh_error();
    }

  MeshBase& mesh = MeshInput<MeshBase>::mesh();

  unsigned int node_lab;           // label of the node
  unsigned int exp_coord_sys_num,  // export coordinate system number       (not supported yet)
               disp_coord_sys_num, // displacement coordinate system number (not supported yet)
               color;              // color                                 (not supported yet)

  // allocate the correct amount
  // of memory for the node vector
  this->_assign_nodes.reserve (this->_n_nodes);


  // always 3 coordinates in the UNV file, no matter
  // which dimensionality libMesh is in
  //std::vector<Real> xyz (3);
  Point xyz;

  // depending on whether we have to convert each
  // coordinate (float), we offer two versions.
  // Note that \p count_nodes() already verified
  // whether this file uses "D" of "e"
  if (this->_need_D_to_e)
    {
      // ok, convert...
      std::string num_buf;

      for(unsigned int i=0; i<this->_n_nodes; i++)
        {
	  libmesh_assert (!in_file.eof());

	  in_file >> node_lab                // read the node label
		  >> exp_coord_sys_num       // (not supported yet)
		  >> disp_coord_sys_num      // (not supported yet)
		  >> color;                  // (not supported yet)

	  // take care of the
	  // floating-point data
	  for (unsigned int d=0; d<3; d++)
	    {
	      in_file >> num_buf;
	      xyz(d) = this->D_to_e (num_buf);
	    }

	  // set up the id map
	  this->_assign_nodes.push_back (node_lab);

	  // add node to the Mesh &
	  // tell the MeshData object the foreign node id
	  // (note that mesh.add_point() returns a pointer to the new node)
	  this->_mesh_data.add_foreign_node_id (mesh.add_point(xyz,i), node_lab);
	}
    }
Example #15
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_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);

  // 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,
                                                     *extra_interpolation_point_elem);
      else
        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++)
        {
          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.;
    }

}
Example #16
0
void InfFE<Dim,T_radial,T_map>::compute_shape_functions(const Elem *,
                                                        const std::vector<Point> &)
{
  libmesh_assert(radial_qrule);

  // Start logging the overall computation of shape functions
  START_LOG("compute_shape_functions()", "InfFE");


  const unsigned int n_total_qp  = _n_total_qp;


  //-------------------------------------------------------------------------
  // Compute the shape function values (and derivatives)
  // at the Quadrature points.  Note that the actual values
  // have already been computed via init_shape_functions

  // Compute the value of the derivative shape function i at quadrature point p
  switch (dim)
    {

    case 1:
      {
        libmesh_not_implemented();
        break;
      }

    case 2:
      {
        libmesh_not_implemented();
        break;
      }

    case 3:
      {
        const std::vector<Real> & dxidx_map = this->_fe_map->get_dxidx();
        const std::vector<Real> & dxidy_map = this->_fe_map->get_dxidy();
        const std::vector<Real> & dxidz_map = this->_fe_map->get_dxidz();

        const std::vector<Real> & detadx_map = this->_fe_map->get_detadx();
        const std::vector<Real> & detady_map = this->_fe_map->get_detady();
        const std::vector<Real> & detadz_map = this->_fe_map->get_detadz();

        const std::vector<Real> & dzetadx_map = this->_fe_map->get_dzetadx();
        const std::vector<Real> & dzetady_map = this->_fe_map->get_dzetady();
        const std::vector<Real> & dzetadz_map = this->_fe_map->get_dzetadz();

        // These are _all_ shape functions of this infinite element
        for (unsigned int i=0; i<phi.size(); i++)
          for (unsigned int p=0; p<n_total_qp; p++)
            {
              // dphi/dx    = (dphi/dxi)*(dxi/dx) + (dphi/deta)*(deta/dx) + (dphi/dzeta)*(dzeta/dx);
              dphi[i][p](0) =
                dphidx[i][p] = (dphidxi[i][p]*dxidx_map[p] +
                                dphideta[i][p]*detadx_map[p] +
                                dphidzeta[i][p]*dzetadx_map[p]);

              // dphi/dy    = (dphi/dxi)*(dxi/dy) + (dphi/deta)*(deta/dy) + (dphi/dzeta)*(dzeta/dy);
              dphi[i][p](1) =
                dphidy[i][p] = (dphidxi[i][p]*dxidy_map[p] +
                                dphideta[i][p]*detady_map[p] +
                                dphidzeta[i][p]*dzetady_map[p]);

              // dphi/dz    = (dphi/dxi)*(dxi/dz) + (dphi/deta)*(deta/dz) + (dphi/dzeta)*(dzeta/dz);
              dphi[i][p](2) =
                dphidz[i][p] = (dphidxi[i][p]*dxidz_map[p] +
                                dphideta[i][p]*detadz_map[p] +
                                dphidzeta[i][p]*dzetadz_map[p]);
            }


        // This is the derivative of the phase term of this infinite element
        for (unsigned int p=0; p<n_total_qp; p++)
          {
            // the derivative of the phase term
            dphase[p](0) = (dphasedxi[p]   * dxidx_map[p] +
                            dphasedeta[p]  * detadx_map[p] +
                            dphasedzeta[p] * dzetadx_map[p]);

            dphase[p](1) = (dphasedxi[p]   * dxidy_map[p] +
                            dphasedeta[p]  * detady_map[p] +
                            dphasedzeta[p] * dzetady_map[p]);

            dphase[p](2) = (dphasedxi[p]   * dxidz_map[p] +
                            dphasedeta[p]  * detadz_map[p] +
                            dphasedzeta[p] * dzetadz_map[p]);

            // the derivative of the radial weight - varies only in radial direction,
            // therefore dweightdxi = dweightdeta = 0.
            dweight[p](0) = dweightdv[p] * dzetadx_map[p];

            dweight[p](1) = dweightdv[p] * dzetady_map[p];

            dweight[p](2) = dweightdv[p] * dzetadz_map[p];

          }

        break;
      }

    default:
      libmesh_error_msg("Unsupported dim = " << dim);
    }

  // Stop logging the overall computation of shape functions
  STOP_LOG("compute_shape_functions()", "InfFE");
}
Example #17
0
void RBEIMEvaluation::legacy_write_offline_data_to_files(const std::string& directory_name,
                                                         const bool read_binary_data)
{
  START_LOG("legacy_write_offline_data_to_files()", "RBEIMEvaluation");

  Parent::legacy_write_offline_data_to_files(directory_name);

  // Get the number of basis functions
  unsigned int n_bfs = get_n_basis_functions();

  // The writing mode: ENCODE for binary, WRITE for ASCII
  XdrMODE mode = read_binary_data ? ENCODE : WRITE;

  // The suffix to use for all the files that are written out
  const std::string suffix = read_binary_data ? ".xdr" : ".dat";

  if(this->processor_id() == 0)
    {
      std::ostringstream file_name;

      // Next write out the interpolation_matrix
      file_name.str("");
      file_name << directory_name << "/interpolation_matrix" << suffix;
      Xdr interpolation_matrix_out(file_name.str(), mode);

      for(unsigned int i=0; i<n_bfs; i++)
        {
          for(unsigned int j=0; j<=i; j++)
            {
              interpolation_matrix_out << interpolation_matrix(i,j);
            }
        }

      // Also, write out the "extra" row
      file_name.str("");
      file_name << directory_name << "/extra_interpolation_matrix_row" << suffix;
      Xdr extra_interpolation_matrix_row_out(file_name.str(), mode);

      for(unsigned int j=0; j<n_bfs; j++)
        {
          extra_interpolation_matrix_row_out << extra_interpolation_matrix_row(j);
        }
      extra_interpolation_matrix_row_out.close();

      // Next write out interpolation_points
      file_name.str("");
      file_name << directory_name << "/interpolation_points" << suffix;
      Xdr interpolation_points_out(file_name.str(), mode);

      for(unsigned int i=0; i<n_bfs; i++)
        {
          interpolation_points_out << interpolation_points[i](0);

          if(LIBMESH_DIM >= 2)
            interpolation_points_out << interpolation_points[i](1);

          if(LIBMESH_DIM >= 3)
            interpolation_points_out << interpolation_points[i](2);
        }
      interpolation_points_out.close();

      // Also, write out the "extra" interpolation point
      file_name.str("");
      file_name << directory_name << "/extra_interpolation_point" << suffix;
      Xdr extra_interpolation_point_out(file_name.str(), mode);

      extra_interpolation_point_out << extra_interpolation_point(0);

      if(LIBMESH_DIM >= 2)
        extra_interpolation_point_out << extra_interpolation_point(1);

      if(LIBMESH_DIM >= 3)
        extra_interpolation_point_out << extra_interpolation_point(2);

      extra_interpolation_point_out.close();

      // Next write out interpolation_points_var
      file_name.str("");
      file_name << directory_name << "/interpolation_points_var" << suffix;
      Xdr interpolation_points_var_out(file_name.str(), mode);

      for(unsigned int i=0; i<n_bfs; i++)
        {
          interpolation_points_var_out << interpolation_points_var[i];
        }
      interpolation_points_var_out.close();

      // Also, write out the "extra" interpolation variable
      file_name.str("");
      file_name << directory_name << "/extra_interpolation_point_var" << suffix;
      Xdr extra_interpolation_point_var_out(file_name.str(), mode);

      extra_interpolation_point_var_out << extra_interpolation_point_var;
      extra_interpolation_point_var_out.close();
    }

  // Write out the elements associated with the interpolation points.
  // This uses mesh I/O, hence we have to do it on all processors.
  legacy_write_out_interpolation_points_elem(directory_name);

  STOP_LOG("legacy_write_offline_data_to_files()", "RBEIMEvaluation");
}
Example #18
0
void PointLocatorList::init ()
{
    libmesh_assert (!this->_list);

    if (this->_initialized)
    {
        libMesh::err << "ERROR: Already initialized!  Will ignore this call..."
                     << std::endl;
    }

    else

    {

        if (this->_master == NULL)
        {
            START_LOG("init(no master)", "PointLocatorList");

            // We are the master, so we have to build the list.
            // First create it, then get a handy reference, and
            // then try to speed up by reserving space...
            this->_list = new std::vector<std::pair<Point, const Elem *> >;
            std::vector<std::pair<Point, const Elem *> >& my_list = *(this->_list);

            my_list.clear();
            my_list.reserve(this->_mesh.n_active_elem());

            // fill our list with the centroids and element
            // pointers of the mesh.  For this use the handy
            // element iterators.
// 	  const_active_elem_iterator       el (this->_mesh.elements_begin());
// 	  const const_active_elem_iterator end(this->_mesh.elements_end());

            MeshBase::const_element_iterator       el  = _mesh.active_elements_begin();
            const MeshBase::const_element_iterator end = _mesh.active_elements_end();

            for (; el!=end; ++el)
                my_list.push_back(std::make_pair((*el)->centroid(), *el));

            STOP_LOG("init(no master)", "PointLocatorList");
        }

        else

        {
            // We are _not_ the master.  Let our _list point to
            // the master's list.  But for this we first transform
            // the master in a state for which we are friends
            // (this should also beware of a bad master pointer?).
            // And make sure the master @e has a list!
            const PointLocatorList* my_master =
                libmesh_cast_ptr<const PointLocatorList*>(this->_master);

            if (my_master->initialized())
                this->_list = my_master->_list;
            else
            {
                libMesh::err << "ERROR: Initialize master first, then servants!"
                             << std::endl;
                libmesh_error();
            }
        }

    }


    // ready for take-off
    this->_initialized = true;
}
void ParmetisPartitioner::_do_repartition (MeshBase& mesh,
					   const unsigned int n_sbdmns)
{
  libmesh_assert_greater (n_sbdmns, 0);

  // Check for an easy return
  if (n_sbdmns == 1)
    {
      this->single_partition(mesh);
      return;
    }

  // This function must be run on all processors at once
  parallel_only();

// What to do if the Parmetis library IS NOT present
#ifndef LIBMESH_HAVE_PARMETIS

  libmesh_here();
  libMesh::err << "ERROR: The library has been built without"  << std::endl
	        << "Parmetis support.  Using a Metis"           << std::endl
	        << "partitioner instead!"                       << std::endl;

  MetisPartitioner mp;

  mp.partition (mesh, n_sbdmns);

// What to do if the Parmetis library IS present
#else

  // Revert to METIS on one processor.
  if (libMesh::n_processors() == 1)
    {
      MetisPartitioner mp;
      mp.partition (mesh, n_sbdmns);
      return;
    }

  START_LOG("repartition()", "ParmetisPartitioner");

  // Initialize the data structures required by ParMETIS
  this->initialize (mesh, n_sbdmns);

  // Make sure all processors have enough active local elements.
  // Parmetis tends to crash when it's given only a couple elements
  // per partition.
  {
    bool all_have_enough_elements = true;
    for (unsigned int pid=0; pid<_n_active_elem_on_proc.size(); pid++)
      if (_n_active_elem_on_proc[pid] < MIN_ELEM_PER_PROC)
	all_have_enough_elements = false;

    // Parmetis will not work unless each processor has some
    // elements. Specifically, it will abort when passed a NULL
    // partition array on *any* of the processors.
    if (!all_have_enough_elements)
      {
	// FIXME: revert to METIS, although this requires a serial mesh
        MeshSerializer serialize(mesh);

	STOP_LOG ("repartition()", "ParmetisPartitioner");

	MetisPartitioner mp;
	mp.partition (mesh, n_sbdmns);

	return;
      }
  }

  // build the graph corresponding to the mesh
  this->build_graph (mesh);


  // Partition the graph
  std::vector<int> vsize(_vwgt.size(), 1);
  float itr = 1000000.0;
  MPI_Comm mpi_comm = libMesh::COMM_WORLD;

  // Call the ParMETIS adaptive repartitioning method.  This respects the
  // original partitioning when computing the new partitioning so as to
  // minimize the required data redistribution.
  Parmetis::ParMETIS_V3_AdaptiveRepart(_vtxdist.empty() ? NULL : &_vtxdist[0],
				       _xadj.empty()    ? NULL : &_xadj[0],
				       _adjncy.empty()  ? NULL : &_adjncy[0],
				       _vwgt.empty()    ? NULL : &_vwgt[0],
				       vsize.empty()    ? NULL : &vsize[0],
				       NULL,
				       &_wgtflag,
				       &_numflag,
				       &_ncon,
				       &_nparts,
				       _tpwgts.empty()  ? NULL : &_tpwgts[0],
				       _ubvec.empty()   ? NULL : &_ubvec[0],
				       &itr,
				       &_options[0],
				       &_edgecut,
				       _part.empty()    ? NULL : &_part[0],
				       &mpi_comm);

  // Assign the returned processor ids
  this->assign_partitioning (mesh);


  STOP_LOG ("repartition()", "ParmetisPartitioner");

#endif // #ifndef LIBMESH_HAVE_PARMETIS ... else ...

}
Example #20
0
void StatisticsVector<T>::histogram(std::vector<unsigned int>& bin_members,
				    unsigned int n_bins)
{
  // Must have at least 1 bin
  libmesh_assert (n_bins>0);

  const unsigned int n   = this->size();

  std::sort(this->begin(), this->end());

  // The StatisticsVector can hold both integer and float types.
  // We will define all the bins, etc. using Reals.
  Real min      = static_cast<Real>(this->minimum());
  Real max      = static_cast<Real>(this->maximum());
  Real bin_size = (max - min) / static_cast<Real>(n_bins);

  START_LOG ("histogram()", "StatisticsVector");

  std::vector<Real> bin_bounds(n_bins+1);
  for (unsigned int i=0; i<bin_bounds.size(); i++)
    bin_bounds[i] = min + i * bin_size;

  // Give the last bin boundary a little wiggle room: we don't want
  // it to be just barely less than the max, otherwise our bin test below
  // may fail.
  bin_bounds.back() += 1.e-6 * bin_size;

  // This vector will store the number of members each bin has.
  bin_members.resize(n_bins);

  unsigned int data_index = 0;
  for (unsigned int j=0; j<bin_members.size(); j++) // bin vector indexing
    {
      // libMesh::out << "(debug) Filling bin " << j << std::endl;

      for (unsigned int i=data_index; i<n; i++) // data vector indexing
	{
	  //	libMesh::out << "(debug) Processing index=" << i << std::endl;
	  Real current_val = static_cast<Real>( (*this)[i] );

	  // There may be entries in the vector smaller than the value
	  // reported by this->minimum().  (e.g. inactive elements in an
	  // ErrorVector.)  We just skip entries like that.
	  if ( current_val < min )
	    {
	      // 	    libMesh::out << "(debug) Skipping entry v[" << i << "]="
	      // 		      << (*this)[i]
	      // 		      << " which is less than the min value: min="
	      // 		      << min << std::endl;
	      continue;
	    }

	  if ( current_val > bin_bounds[j+1] ) // if outside the current bin (bin[j] is bounded
	                                       // by bin_bounds[j] and bin_bounds[j+1])
	    {
	      // libMesh::out.precision(16);
	      // 	    libMesh::out.setf(std::ios_base::fixed);
	      // 	    libMesh::out << "(debug) (*this)[i]= " << (*this)[i]
	      // 		      << " is greater than bin_bounds[j+1]="
	      //		      << bin_bounds[j+1]	 << std::endl;
	      data_index = i; // start searching here for next bin
	      break; // go to next bin
	    }

	  // Otherwise, increment current bin's count
	  bin_members[j]++;
	  // libMesh::out << "(debug) Binned index=" << i << std::endl;
	}
    }

#ifdef DEBUG
  // Check the number of binned entries
  const unsigned int n_binned = std::accumulate(bin_members.begin(),
						bin_members.end(),
						static_cast<unsigned int>(0),
						std::plus<unsigned int>());

  if (n != n_binned)
    {
      libMesh::out << "Warning: The number of binned entries, n_binned="
		<< n_binned
		<< ", did not match the total number of entries, n="
		<< n << "." << std::endl;
      //libmesh_error();
    }
#endif


  STOP_LOG ("histogram()", "StatisticsVector");
}
Example #21
0
double __libmesh_nlopt_objective(unsigned n,
                                 const double * x,
                                 double * gradient,
                                 void * data)
{
  START_LOG("objective()", "NloptOptimizationSolver");

  // ctx should be a pointer to the solver (it was passed in as void *)
  NloptOptimizationSolver<Number> * solver =
    static_cast<NloptOptimizationSolver<Number> *> (data);

  OptimizationSystem & sys = solver->system();

  // We'll use current_local_solution below, so let's ensure that it's consistent
  // with the vector x that was passed in.
  for (unsigned int i=sys.solution->first_local_index();
       i<sys.solution->last_local_index(); i++)
    sys.solution->set(i, x[i]);

  // Make sure the solution vector is parallel-consistent
  sys.solution->close();

  // Impose constraints on X
  sys.get_dof_map().enforce_constraints_exactly(sys);

  // Update sys.current_local_solution based on X
  sys.update();

  Real objective;
  if (solver->objective_object != NULL)
    {
      objective =
        solver->objective_object->objective(
                                            *(sys.current_local_solution), sys);
    }
  else
    {
      libmesh_error_msg("Objective function not defined in __libmesh_nlopt_objective");
    }

  // If the gradient has been requested, fill it in
  if (gradient)
    {
      if (solver->gradient_object != NULL)
        {
          solver->gradient_object->gradient(
                                            *(sys.current_local_solution), *(sys.rhs), sys);

          // we've filled up sys.rhs with the gradient data, now copy it
          // to the nlopt data structure
          libmesh_assert(sys.rhs->size() == n);

          std::vector<double> grad;
          sys.rhs->localize_to_one(grad);
          for (unsigned i=0; i<n; ++i)
            gradient[i] = grad[i];
        }
      else
        libmesh_error_msg("Gradient function not defined in __libmesh_nlopt_objective");
    }

  STOP_LOG("objective()", "NloptOptimizationSolver");

  // Increment the iteration count.
  solver->get_iteration_count()++;

  // Possibly print the current value of the objective function
  if (solver->verbose)
    libMesh::out << objective << std::endl;

  return objective;
}
void RadialBasisInterpolation<KDDim,RBF>::prepare_for_use()
{
  // Call base class methods for prep
  InverseDistanceInterpolation<KDDim>::prepare_for_use();
  InverseDistanceInterpolation<KDDim>::construct_kd_tree();

#ifndef LIBMESH_HAVE_EIGEN

  libmesh_error_msg("ERROR: this functionality presently requires Eigen!");

#else
  START_LOG ("prepare_for_use()", "RadialBasisInterpolation<>");

  // Construct a bounding box for our source points
  _src_bbox.invalidate();

  const unsigned int n_src_pts = this->_src_pts.size();
  const unsigned int n_vars    = this->n_field_variables();
  libmesh_assert_equal_to (this->_src_vals.size(), n_src_pts*this->n_field_variables());

  {
    Point
      &p_min(_src_bbox.min()),
      &p_max(_src_bbox.max());

    for (unsigned int p=0; p<n_src_pts; p++)
      {
        const Point &p_src(_src_pts[p]);

        for (unsigned int d=0; d<LIBMESH_DIM; d++)
          {
            p_min(d) = std::min(p_min(d), p_src(d));
            p_max(d) = std::max(p_max(d), p_src(d));
          }
      }
  }

  libMesh::out << "bounding box is \n"
               << _src_bbox.min() << '\n'
               << _src_bbox.max() << std::endl;


  // Construct the Radial Basis Function, giving it the size of the domain
  if(_r_override < 0)
    _r_bbox = (_src_bbox.max() - _src_bbox.min()).size();
  else
    _r_bbox = _r_override;

  RBF rbf(_r_bbox);

  libMesh::out << "bounding box is \n"
               << _src_bbox.min() << '\n'
               << _src_bbox.max() << '\n'
               << "r_bbox = " << _r_bbox << '\n'
               << "rbf(r_bbox/2) = " << rbf(_r_bbox/2) << std::endl;


  // Construct the projection Matrix
  typedef Eigen::Matrix<Number, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> DynamicMatrix;
  //typedef Eigen::Matrix<Number, Eigen::Dynamic,              1, Eigen::ColMajor> DynamicVector;

  DynamicMatrix A(n_src_pts, n_src_pts), x(n_src_pts,n_vars), b(n_src_pts,n_vars);

  for (unsigned int i=0; i<n_src_pts; i++)
    {
      const Point &x_i (_src_pts[i]);

      // Diagonal
      A(i,i) = rbf(0.);

      for (unsigned int j=i+1; j<n_src_pts; j++)
        {
          const Point &x_j (_src_pts[j]);

          const Real r_ij = (x_j - x_i).size();

          A(i,j) = A(j,i) = rbf(r_ij);
        }

      // set source data
      for (unsigned int var=0; var<n_vars; var++)
        b(i,var) = _src_vals[i*n_vars + var];
    }


  // Solve the linear system
  x = A.ldlt().solve(b);
  //x = A.fullPivLu().solve(b);

  // save  the weights for each variable
  _weights.resize (this->_src_vals.size());

  for (unsigned int i=0; i<n_src_pts; i++)
    for (unsigned int var=0; var<n_vars; var++)
      _weights[i*n_vars + var] = x(i,var);


  STOP_LOG  ("prepare_for_use()", "RadialBasisInterpolation<>");
#endif

}
Example #23
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 = 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 = 0;
  dof_id_type optimal_elem_id = DofObject::invalid_id;

  // Initialize largest_abs_value to be negative so that it definitely gets updated.
  Real largest_abs_value = -1.;

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

  UniquePtr<DGFEMContext> c = this->build_context();
  DGFEMContext &context  = cast_ref<DGFEMContext&>(*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.get_element_qrule().n_points();

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

              if( abs_value > largest_abs_value )
                {
                  optimal_value = value;
                  largest_abs_value = abs_value;
                  optimal_var = var;
                  optimal_elem_id = (*el)->id();

                  FEBase* elem_fe = NULL;
                  context.get_element_fe( var, elem_fe );
                  optimal_point = elem_fe->get_xyz()[qp];
                }

            }
        }
    }

  // Find out which processor has the largest of the abs values
  unsigned int proc_ID_index;
  this->comm().maxloc(largest_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, optimal_value, and optimal_elem_id
  this->comm().broadcast(optimal_var, proc_ID_index);
  this->comm().broadcast(optimal_value, proc_ID_index);
  this->comm().broadcast(optimal_elem_id, proc_ID_index);

  // In debug mode, assert that we found an optimal_elem_id
  libmesh_assert_not_equal_to(optimal_elem_id, DofObject::invalid_id);

  // 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);
      Elem* elem_ptr = mesh.elem(optimal_elem_id);
      eim_eval.interpolation_points_elem.push_back( elem_ptr );

      NumericVector<Number>* new_bf = NumericVector<Number>::build(this->comm()).release();
      new_bf->init (this->n_dofs(), this->n_local_dofs(), false, 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;
      eim_eval.extra_interpolation_point_elem = mesh.elem(optimal_elem_id);
    }

  STOP_LOG("enrich_RB_space()", "RBEIMConstruction");
}
Example #24
0
// ------------------------------------------------------------
// MetisPartitioner implementation
void MetisPartitioner::_do_partition (MeshBase& mesh,
                                      const unsigned int n_pieces)
{
  libmesh_assert_greater (n_pieces, 0);
  libmesh_assert (mesh.is_serial());

  // Check for an easy return
  if (n_pieces == 1)
    {
      this->single_partition (mesh);
      return;
    }

  // What to do if the Metis library IS NOT present
#ifndef LIBMESH_HAVE_METIS

  libmesh_here();
  libMesh::err << "ERROR: The library has been built without"    << std::endl
               << "Metis support.  Using a space-filling curve"  << std::endl
               << "partitioner instead!"                         << std::endl;

  SFCPartitioner sfcp;

  sfcp.partition (mesh, n_pieces);

  // What to do if the Metis library IS present
#else

  START_LOG("partition()", "MetisPartitioner");

  const dof_id_type n_active_elem = mesh.n_active_elem();

  // build the graph
  // std::vector<Metis::idx_t> options(5);
  std::vector<Metis::idx_t> vwgt(n_active_elem);
  std::vector<Metis::idx_t> part(n_active_elem);

  Metis::idx_t
    n = static_cast<Metis::idx_t>(n_active_elem),  // number of "nodes" (elements)
                                                   //   in the graph
    //    wgtflag = 2,                             // weights on vertices only,
    //                                             //   none on edges
    //    numflag = 0,                             // C-style 0-based numbering
    nparts  = static_cast<Metis::idx_t>(n_pieces), // number of subdomains to create
    edgecut = 0;                                   // the numbers of edges cut by the
                                                   //   resulting partition

  // Set the options
  // options[0] = 0; // use default options

  // Metis will only consider the active elements.
  // We need to map the active element ids into a
  // contiguous range.  Further, we want the unique range indexing to be
  // independent of the element ordering, otherwise a circular dependency
  // can result in which the partitioning depends on the ordering which
  // depends on the partitioning...
  vectormap<dof_id_type, dof_id_type> global_index_map;
  global_index_map.reserve (n_active_elem);

  {
    std::vector<dof_id_type> global_index;

    MeshBase::element_iterator       it  = mesh.active_elements_begin();
    const MeshBase::element_iterator end = mesh.active_elements_end();

    MeshCommunication().find_global_indices (mesh.comm(),
                                             MeshTools::bounding_box(mesh),
                                             it, end, global_index);

    libmesh_assert_equal_to (global_index.size(), n_active_elem);

    for (std::size_t cnt=0; it != end; ++it)
      {
        const Elem *elem = *it;

        global_index_map.insert (std::make_pair(elem->id(), global_index[cnt++]));
      }
    libmesh_assert_equal_to (global_index_map.size(), n_active_elem);
  }

  // If we have boundary elements in this mesh, we want to account for
  // the connectivity between them and interior elements.  We can find
  // interior elements from boundary elements, but we need to build up
  // a lookup map to do the reverse.

  typedef LIBMESH_BEST_UNORDERED_MAP<const Elem *, const Elem *>
    map_type;
  map_type interior_to_boundary_map;

  {
    MeshBase::const_element_iterator       elem_it  = mesh.active_elements_begin();
    const MeshBase::const_element_iterator elem_end = mesh.active_elements_end();

    for (; elem_it != elem_end; ++elem_it)
      {
        const Elem* elem = *elem_it;

        // If we don't have an interior_parent then there's nothing to look us
        // up.
        if ((elem->dim() >= LIBMESH_DIM) ||
            !elem->interior_parent())
          continue;

        // get all relevant interior elements
        std::set<const Elem*> neighbor_set;
        elem->find_interior_neighbors(neighbor_set);

        std::set<const Elem*>::iterator n_it = neighbor_set.begin();
        for (; n_it != neighbor_set.end(); ++n_it)
          {
            // FIXME - non-const versions of the Elem set methods
            // would be nice
            Elem* neighbor = const_cast<Elem*>(*n_it);

#if defined(LIBMESH_HAVE_UNORDERED_MAP) || defined(LIBMESH_HAVE_TR1_UNORDERED_MAP) || defined(LIBMESH_HAVE_HASH_MAP) || defined(LIBMESH_HAVE_EXT_HASH_MAP)
            interior_to_boundary_map.insert
              (std::make_pair(neighbor, elem));
#else
            interior_to_boundary_map.insert
              (interior_to_boundary_map.begin(),
               std::make_pair(neighbor, elem));
#endif
          }
      }
  }


  // Invoke METIS, but only on processor 0.
  // Then broadcast the resulting decomposition
  if (mesh.processor_id() == 0)
    {
      METIS_CSR_Graph<Metis::idx_t> csr_graph;

      csr_graph.offsets.resize(n_active_elem+1, 0);

      // Local scope for these
      {
        // build the graph in CSR format.  Note that
        // the edges in the graph will correspond to
        // face neighbors

#ifdef LIBMESH_ENABLE_AMR
        std::vector<const Elem*> neighbors_offspring;
#endif

        MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
        const MeshBase::element_iterator elem_end = mesh.active_elements_end();

#ifndef NDEBUG
        std::size_t graph_size=0;
#endif

        // (1) first pass - get the row sizes for each element by counting the number
        // of face neighbors.  Also populate the vwght array if necessary
        for (; elem_it != elem_end; ++elem_it)
          {
            const Elem* elem = *elem_it;

            const dof_id_type elem_global_index =
              global_index_map[elem->id()];

            libmesh_assert_less (elem_global_index, vwgt.size());

            // maybe there is a better weight?
            // The weight is used to define what a balanced graph is
            if(!_weights)
              vwgt[elem_global_index] = elem->n_nodes();
            else
              vwgt[elem_global_index] = static_cast<Metis::idx_t>((*_weights)[elem->id()]);

            unsigned int num_neighbors = 0;

            // Loop over the element's neighbors.  An element
            // adjacency corresponds to a face neighbor
            for (unsigned int ms=0; ms<elem->n_neighbors(); ms++)
              {
                const Elem* neighbor = elem->neighbor(ms);

                if (neighbor != NULL)
                  {
                    // If the neighbor is active treat it
                    // as a connection
                    if (neighbor->active())
                      num_neighbors++;

#ifdef LIBMESH_ENABLE_AMR

                    // Otherwise we need to find all of the
                    // neighbor's children that are connected to
                    // us and add them
                    else
                      {
                        // The side of the neighbor to which
                        // we are connected
                        const unsigned int ns =
                          neighbor->which_neighbor_am_i (elem);
                        libmesh_assert_less (ns, neighbor->n_neighbors());

                        // Get all the active children (& grandchildren, etc...)
                        // of the neighbor.

                        // FIXME - this is the wrong thing, since we
                        // should be getting the active family tree on
                        // our side only.  But adding too many graph
                        // links may cause hanging nodes to tend to be
                        // on partition interiors, which would reduce
                        // communication overhead for constraint
                        // equations, so we'll leave it.

                        neighbor->active_family_tree (neighbors_offspring);

                        // Get all the neighbor's children that
                        // live on that side and are thus connected
                        // to us
                        for (unsigned int nc=0; nc<neighbors_offspring.size(); nc++)
                          {
                            const Elem* child =
                              neighbors_offspring[nc];

                            // This does not assume a level-1 mesh.
                            // Note that since children have sides numbered
                            // coincident with the parent then this is a sufficient test.
                            if (child->neighbor(ns) == elem)
                              {
                                libmesh_assert (child->active());
                                num_neighbors++;
                              }
                          }
                      }

#endif /* ifdef LIBMESH_ENABLE_AMR */

                  }
              }

            // Check for any interior neighbors
            if ((elem->dim() < LIBMESH_DIM) &&
                elem->interior_parent())
              {
                // get all relevant interior elements
                std::set<const Elem*> neighbor_set;
                elem->find_interior_neighbors(neighbor_set);

                num_neighbors += neighbor_set.size();
              }

            // Check for any boundary neighbors
            typedef map_type::iterator map_it_type;
            std::pair<map_it_type, map_it_type>
              bounds = interior_to_boundary_map.equal_range(elem);
            num_neighbors += std::distance(bounds.first, bounds.second);

            csr_graph.prep_n_nonzeros(elem_global_index, num_neighbors);
#ifndef NDEBUG
            graph_size += num_neighbors;
#endif
          }

        csr_graph.prepare_for_use();

        // (2) second pass - fill the compressed adjacency array
        elem_it  = mesh.active_elements_begin();

        for (; elem_it != elem_end; ++elem_it)
          {
            const Elem* elem = *elem_it;

            const dof_id_type elem_global_index =
              global_index_map[elem->id()];

            unsigned int connection=0;

            // Loop over the element's neighbors.  An element
            // adjacency corresponds to a face neighbor
            for (unsigned int ms=0; ms<elem->n_neighbors(); ms++)
              {
                const Elem* neighbor = elem->neighbor(ms);

                if (neighbor != NULL)
                  {
                    // If the neighbor is active treat it
                    // as a connection
                    if (neighbor->active())
                      csr_graph(elem_global_index, connection++) = global_index_map[neighbor->id()];

#ifdef LIBMESH_ENABLE_AMR

                    // Otherwise we need to find all of the
                    // neighbor's children that are connected to
                    // us and add them
                    else
                      {
                        // The side of the neighbor to which
                        // we are connected
                        const unsigned int ns =
                          neighbor->which_neighbor_am_i (elem);
                        libmesh_assert_less (ns, neighbor->n_neighbors());

                        // Get all the active children (& grandchildren, etc...)
                        // of the neighbor.
                        neighbor->active_family_tree (neighbors_offspring);

                        // Get all the neighbor's children that
                        // live on that side and are thus connected
                        // to us
                        for (unsigned int nc=0; nc<neighbors_offspring.size(); nc++)
                          {
                            const Elem* child =
                              neighbors_offspring[nc];

                            // This does not assume a level-1 mesh.
                            // Note that since children have sides numbered
                            // coincident with the parent then this is a sufficient test.
                            if (child->neighbor(ns) == elem)
                              {
                                libmesh_assert (child->active());

                                csr_graph(elem_global_index, connection++) = global_index_map[child->id()];
                              }
                          }
                      }

#endif /* ifdef LIBMESH_ENABLE_AMR */

                  }
              }

            if ((elem->dim() < LIBMESH_DIM) &&
                elem->interior_parent())
              {
                // get all relevant interior elements
                std::set<const Elem*> neighbor_set;
                elem->find_interior_neighbors(neighbor_set);

                std::set<const Elem*>::iterator n_it = neighbor_set.begin();
                for (; n_it != neighbor_set.end(); ++n_it)
                  {
                    // FIXME - non-const versions of the Elem set methods
                    // would be nice
                    Elem* neighbor = const_cast<Elem*>(*n_it);

                    csr_graph(elem_global_index, connection++) =
                      global_index_map[neighbor->id()];
                  }
              }

            // Check for any boundary neighbors
            typedef map_type::iterator map_it_type;
            std::pair<map_it_type, map_it_type>
              bounds = interior_to_boundary_map.equal_range(elem);

            for (map_it_type it = bounds.first; it != bounds.second; ++it)
              {
                const Elem* neighbor = it->second;
                csr_graph(elem_global_index, connection++) =
                  global_index_map[neighbor->id()];
              }
          }

        // We create a non-empty vals for a disconnected graph, to
        // work around a segfault from METIS.
        libmesh_assert_equal_to (csr_graph.vals.size(),
                                 std::max(graph_size,std::size_t(1)));
      } // done building the graph

      Metis::idx_t ncon = 1;

      // Select which type of partitioning to create

      // Use recursive if the number of partitions is less than or equal to 8
      if (n_pieces <= 8)
        Metis::METIS_PartGraphRecursive(&n, &ncon, &csr_graph.offsets[0], &csr_graph.vals[0], &vwgt[0], NULL,
                                        NULL, &nparts, NULL, NULL, NULL,
                                        &edgecut, &part[0]);

      // Otherwise  use kway
      else
        Metis::METIS_PartGraphKway(&n, &ncon, &csr_graph.offsets[0], &csr_graph.vals[0], &vwgt[0], NULL,
                                   NULL, &nparts, NULL, NULL, NULL,
                                   &edgecut, &part[0]);

    } // end processor 0 part

  // Broadcase the resutling partition
  mesh.comm().broadcast(part);

  // Assign the returned processor ids.  The part array contains
  // the processor id for each active element, but in terms of
  // the contiguous indexing we defined above
  {
    MeshBase::element_iterator       it  = mesh.active_elements_begin();
    const MeshBase::element_iterator end = mesh.active_elements_end();

    for (; it!=end; ++it)
      {
        Elem* elem = *it;

        libmesh_assert (global_index_map.count(elem->id()));

        const dof_id_type elem_global_index =
          global_index_map[elem->id()];

        libmesh_assert_less (elem_global_index, part.size());
        const processor_id_type elem_procid =
          static_cast<processor_id_type>(part[elem_global_index]);

        elem->processor_id() = elem_procid;
      }
  }

  STOP_LOG("partition()", "MetisPartitioner");
#endif
}
Example #25
0
void CondensedEigenSystem::solve()
{
  START_LOG("solve()", "CondensedEigenSystem");

  // If we haven't initialized any condensed dofs,
  // just use the default eigen_system
  if(!condensed_dofs_initialized)
  {
    STOP_LOG("solve()", "CondensedEigenSystem");
    Parent::solve();
    return;
  }

  // A reference to the EquationSystems
  EquationSystems& es = this->get_equation_systems();

  // check that necessary parameters have been set
  libmesh_assert (es.parameters.have_parameter<unsigned int>("eigenpairs"));
  libmesh_assert (es.parameters.have_parameter<unsigned int>("basis vectors"));

  if (this->assemble_before_solve)
    // Assemble the linear system
    this->assemble ();

  // If we reach here, then there should be some non-condensed dofs
  libmesh_assert(!local_non_condensed_dofs_vector.empty());

  // Now condense the matrices
  matrix_A->create_submatrix(*condensed_matrix_A,
                             local_non_condensed_dofs_vector,
                             local_non_condensed_dofs_vector);

  if(generalized())
  {
    matrix_B->create_submatrix(*condensed_matrix_B,
                               local_non_condensed_dofs_vector,
                               local_non_condensed_dofs_vector);
  }


  // Get the tolerance for the solver and the maximum
  // number of iterations. Here, we simply adopt the linear solver
  // specific parameters.
  const Real tol            =
    es.parameters.get<Real>("linear solver tolerance");

  const unsigned int maxits =
    es.parameters.get<unsigned int>("linear solver maximum iterations");

  const unsigned int nev    =
    es.parameters.get<unsigned int>("eigenpairs");

  const unsigned int ncv    =
    es.parameters.get<unsigned int>("basis vectors");

  std::pair<unsigned int, unsigned int> solve_data;

  // call the solver depending on the type of eigenproblem
  if ( generalized() )
    {
      //in case of a generalized eigenproblem
      solve_data = eigen_solver->solve_generalized
        (*condensed_matrix_A,*condensed_matrix_B, nev, ncv, tol, maxits);
    }

  else
    {
      libmesh_assert (!matrix_B);

      //in case of a standard eigenproblem
      solve_data = eigen_solver->solve_standard (*condensed_matrix_A, nev, ncv, tol, maxits);
    }

  set_n_converged(solve_data.first);
  set_n_iterations(solve_data.second);

  STOP_LOG("solve()", "CondensedEigenSystem");
}
std::pair<unsigned int, Real>
EigenSparseLinearSolver<T>::solve (SparseMatrix<T> &matrix_in,
                                   NumericVector<T> &solution_in,
                                   NumericVector<T> &rhs_in,
                                   const double tol,
                                   const unsigned int m_its)
{
  START_LOG("solve()", "EigenSparseLinearSolver");
  this->init ();

  // Make sure the data passed in are really Eigen types
  EigenSparseMatrix<T>& matrix   = libmesh_cast_ref<EigenSparseMatrix<T>&>(matrix_in);
  EigenSparseVector<T>& solution = libmesh_cast_ref<EigenSparseVector<T>&>(solution_in);
  EigenSparseVector<T>& rhs      = libmesh_cast_ref<EigenSparseVector<T>&>(rhs_in);

  // Close the matrix and vectors in case this wasn't already done.
  matrix.close();
  solution.close();
  rhs.close();

  std::pair<unsigned int, Real> retval(0,0.);

  // Solve the linear system
  switch (this->_solver_type)
    {
      // Conjugate-Gradient
    case CG:
      {
        Eigen::ConjugateGradient<EigenSM> solver (matrix._mat);
        solver.setMaxIterations(m_its);
        solver.setTolerance(tol);
        solution._vec = solver.solveWithGuess(rhs._vec,solution._vec);
        libMesh::out << "#iterations: " << solver.iterations() << std::endl;
        libMesh::out << "estimated error: " << solver.error() << std::endl;
        retval = std::make_pair(solver.iterations(), solver.error());
        break;
      }

      // Bi-Conjugate Gradient Stabilized
    case BICGSTAB:
      {
        Eigen::BiCGSTAB<EigenSM> solver (matrix._mat);
        solver.setMaxIterations(m_its);
        solver.setTolerance(tol);
        solution._vec = solver.solveWithGuess(rhs._vec,solution._vec);
        libMesh::out << "#iterations: " << solver.iterations() << std::endl;
        libMesh::out << "estimated error: " << solver.error() << std::endl;
        retval = std::make_pair(solver.iterations(), solver.error());
        break;
      }

      //   // Generalized Minimum Residual
      // case GMRES:
      //   {
      // libmesh_not_implemented();
      // break;
      //   }

      // Unknown solver, use BICGSTAB
    default:
      {
        libMesh::err << "ERROR:  Unsupported Eigen Solver: "
                     << Utility::enum_to_string(this->_solver_type) << std::endl
                     << "Continuing with BICGSTAB" << std::endl;

        this->_solver_type = BICGSTAB;

        STOP_LOG("solve()", "EigenSparseLinearSolver");

        return this->solve (matrix,
                            solution,
                            rhs,
                            tol,
                            m_its);
      }
    }

  STOP_LOG("solve()", "EigenSparseLinearSolver");
  return retval;
}
Example #27
0
void RBEvaluation::resize_data_structures(const unsigned int Nmax,
                                          bool resize_error_bound_data)
{
  START_LOG("resize_data_structures()", "RBEvaluation");

  if(Nmax < this->get_n_basis_functions())
    libmesh_error_msg("Error: Cannot set Nmax to be less than the current number of basis functions.");

  // Resize/clear inner product matrix
  if(compute_RB_inner_product)
    RB_inner_product_matrix.resize(Nmax,Nmax);

  // Allocate dense matrices for RB solves
  RB_Aq_vector.resize(rb_theta_expansion->get_n_A_terms());

  for(unsigned int q=0; q<rb_theta_expansion->get_n_A_terms(); q++)
    {
      // Initialize the memory for the RB matrices
      RB_Aq_vector[q].resize(Nmax,Nmax);
    }

  RB_Fq_vector.resize(rb_theta_expansion->get_n_F_terms());

  for(unsigned int q=0; q<rb_theta_expansion->get_n_F_terms(); q++)
    {
      // Initialize the memory for the RB vectors
      RB_Fq_vector[q].resize(Nmax);
    }


  // Initialize the RB output vectors
  RB_output_vectors.resize(rb_theta_expansion->get_n_outputs());
  for(unsigned int n=0; n<rb_theta_expansion->get_n_outputs(); n++)
    {
      RB_output_vectors[n].resize(rb_theta_expansion->get_n_output_terms(n));
      for(unsigned int q_l=0; q_l<rb_theta_expansion->get_n_output_terms(n); q_l++)
        {
          RB_output_vectors[n][q_l].resize(Nmax);
        }
    }

  // Initialize vectors storing output data
  RB_outputs.resize(rb_theta_expansion->get_n_outputs(), 0.);


  if(resize_error_bound_data)
    {
      // Initialize vectors for the norms of the Fq representors
      unsigned int Q_f_hat = rb_theta_expansion->get_n_F_terms()*(rb_theta_expansion->get_n_F_terms()+1)/2;
      Fq_representor_innerprods.resize(Q_f_hat);

      // Initialize vectors for the norms of the representors
      Fq_Aq_representor_innerprods.resize(rb_theta_expansion->get_n_F_terms());
      for(unsigned int i=0; i<rb_theta_expansion->get_n_F_terms(); i++)
        {
          Fq_Aq_representor_innerprods[i].resize(rb_theta_expansion->get_n_A_terms());
          for(unsigned int j=0; j<rb_theta_expansion->get_n_A_terms(); j++)
            {
              Fq_Aq_representor_innerprods[i][j].resize(Nmax, 0.);
            }
        }

      unsigned int Q_a_hat = rb_theta_expansion->get_n_A_terms()*(rb_theta_expansion->get_n_A_terms()+1)/2;
      Aq_Aq_representor_innerprods.resize(Q_a_hat);
      for(unsigned int i=0; i<Q_a_hat; i++)
        {
          Aq_Aq_representor_innerprods[i].resize(Nmax);
          for(unsigned int j=0; j<Nmax; j++)
            {
              Aq_Aq_representor_innerprods[i][j].resize(Nmax, 0.);
            }
        }

      RB_output_error_bounds.resize(rb_theta_expansion->get_n_outputs(), 0.);

      // Resize the output dual norm vectors
      output_dual_innerprods.resize(rb_theta_expansion->get_n_outputs());
      for(unsigned int n=0; n<rb_theta_expansion->get_n_outputs(); n++)
        {
          unsigned int Q_l_hat = rb_theta_expansion->get_n_output_terms(n)*(rb_theta_expansion->get_n_output_terms(n)+1)/2;
          output_dual_innerprods[n].resize(Q_l_hat);
        }

      // Clear and resize the vector of Aq_representors
      clear_riesz_representors();

      Aq_representor.resize(rb_theta_expansion->get_n_A_terms());
      for(unsigned int q_a=0; q_a<rb_theta_expansion->get_n_A_terms(); q_a++)
        {
          Aq_representor[q_a].resize(Nmax);
        }
    }


  STOP_LOG("resize_data_structures()", "RBEvaluation");
}
Example #28
0
void FEXYZMap::compute_face_map(int dim, const std::vector<Real>& qw, const Elem* side)
{
  libmesh_assert(side);

  START_LOG("compute_face_map()", "FEXYZMap");

  // The number of quadrature points.
  const unsigned int n_qp = libmesh_cast_int<unsigned int>(qw.size());

  switch(dim)
    {
    case 2:
      {

	// Resize the vectors to hold data at the quadrature points
	{
	  this->xyz.resize(n_qp);
	  this->dxyzdxi_map.resize(n_qp);
	  this->d2xyzdxi2_map.resize(n_qp);
	  this->tangents.resize(n_qp);
	  this->normals.resize(n_qp);
	  this->curvatures.resize(n_qp);

	  this->JxW.resize(n_qp);
	}

	// Clear the entities that will be summed
	// Compute the tangent & normal at the quadrature point
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    this->tangents[p].resize(LIBMESH_DIM-1); // 1 Tangent in 2D, 2 in 3D
	    this->xyz[p].zero();
	    this->dxyzdxi_map[p].zero();
	    this->d2xyzdxi2_map[p].zero();
	  }

	// compute x, dxdxi at the quadrature points
	for (unsigned int i=0; i<this->psi_map.size(); i++) // sum over the nodes
	  {
	    const Point& side_point = side->point(i);

	    for (unsigned int p=0; p<n_qp; p++) // for each quadrature point...
	      {
		this->xyz[p].add_scaled          (side_point, this->psi_map[i][p]);
		this->dxyzdxi_map[p].add_scaled  (side_point, this->dpsidxi_map[i][p]);
		this->d2xyzdxi2_map[p].add_scaled(side_point, this->d2psidxi2_map[i][p]);
	      }
	  }

	// Compute the tangent & normal at the quadrature point
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    const Point n(this->dxyzdxi_map[p](1), -this->dxyzdxi_map[p](0), 0.);

	    this->normals[p]     = n.unit();
	    this->tangents[p][0] = this->dxyzdxi_map[p].unit();
#if LIBMESH_DIM == 3  // Only good in 3D space
	    this->tangents[p][1] = this->dxyzdxi_map[p].cross(n).unit();
#endif
	    // The curvature is computed via the familiar Frenet formula:
	    // curvature = [d^2(x) / d (xi)^2] dot [normal]
	    // For a reference, see:
	    // F.S. Merritt, Mathematics Manual, 1962, McGraw-Hill, p. 310
	    //
	    // Note: The sign convention here is different from the
	    // 3D case.  Concave-upward curves (smiles) have a positive
	    // curvature.  Concave-downward curves (frowns) have a
	    // negative curvature.  Be sure to take that into account!
	    const Real numerator   = this->d2xyzdxi2_map[p] * this->normals[p];
	    const Real denominator = this->dxyzdxi_map[p].size_sq();
	    libmesh_assert_not_equal_to (denominator, 0);
	    this->curvatures[p] = numerator / denominator;
	  }

	// compute the jacobian at the quadrature points
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    const Real the_jac = std::sqrt(this->dxdxi_map(p)*this->dxdxi_map(p) +
                                           this->dydxi_map(p)*this->dydxi_map(p));

	    libmesh_assert_greater (the_jac, 0.);

	    this->JxW[p] = the_jac*qw[p];
	  }

	break;
      }

    case 3:
      {
	// Resize the vectors to hold data at the quadrature points
	{
	  this->xyz.resize(n_qp);
	  this->dxyzdxi_map.resize(n_qp);
	  this->dxyzdeta_map.resize(n_qp);
	  this->d2xyzdxi2_map.resize(n_qp);
	  this->d2xyzdxideta_map.resize(n_qp);
	  this->d2xyzdeta2_map.resize(n_qp);
	  this->tangents.resize(n_qp);
	  this->normals.resize(n_qp);
	  this->curvatures.resize(n_qp);

	  this->JxW.resize(n_qp);
	}

	// Clear the entities that will be summed
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    this->tangents[p].resize(LIBMESH_DIM-1); // 1 Tangent in 2D, 2 in 3D
	    this->xyz[p].zero();
	    this->dxyzdxi_map[p].zero();
	    this->dxyzdeta_map[p].zero();
	    this->d2xyzdxi2_map[p].zero();
	    this->d2xyzdxideta_map[p].zero();
	    this->d2xyzdeta2_map[p].zero();
	  }

	// compute x, dxdxi at the quadrature points
	for (unsigned int i=0; i<this->psi_map.size(); i++) // sum over the nodes
	  {
	    const Point& side_point = side->point(i);

	    for (unsigned int p=0; p<n_qp; p++) // for each quadrature point...
	      {
		this->xyz[p].add_scaled             (side_point, this->psi_map[i][p]);
		this->dxyzdxi_map[p].add_scaled     (side_point, this->dpsidxi_map[i][p]);
		this->dxyzdeta_map[p].add_scaled    (side_point, this->dpsideta_map[i][p]);
		this->d2xyzdxi2_map[p].add_scaled   (side_point, this->d2psidxi2_map[i][p]);
		this->d2xyzdxideta_map[p].add_scaled(side_point, this->d2psidxideta_map[i][p]);
		this->d2xyzdeta2_map[p].add_scaled  (side_point, this->d2psideta2_map[i][p]);
	      }
	  }

	// Compute the tangents, normal, and curvature at the quadrature point
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    const Point n  = this->dxyzdxi_map[p].cross(this->dxyzdeta_map[p]);
	    this->normals[p]     = n.unit();
	    this->tangents[p][0] = this->dxyzdxi_map[p].unit();
	    this->tangents[p][1] = n.cross(this->dxyzdxi_map[p]).unit();

	    // Compute curvature using the typical nomenclature
	    // of the first and second fundamental forms.
	    // For reference, see:
	    // 1) http://mathworld.wolfram.com/MeanCurvature.html
	    //    (note -- they are using inward normal)
	    // 2) F.S. Merritt, Mathematics Manual, 1962, McGraw-Hill
	    const Real L  = -this->d2xyzdxi2_map[p]    * this->normals[p];
	    const Real M  = -this->d2xyzdxideta_map[p] * this->normals[p];
	    const Real N  = -this->d2xyzdeta2_map[p]   * this->normals[p];
	    const Real E  =  this->dxyzdxi_map[p].size_sq();
	    const Real F  =  this->dxyzdxi_map[p]      * this->dxyzdeta_map[p];
	    const Real G  =  this->dxyzdeta_map[p].size_sq();

	    const Real numerator   = E*N -2.*F*M + G*L;
	    const Real denominator = E*G - F*F;
	    libmesh_assert_not_equal_to (denominator, 0.);
	    this->curvatures[p] = 0.5*numerator/denominator;
	  }

	// compute the jacobian at the quadrature points, see
	// http://sp81.msi.umn.edu:999/fluent/fidap/help/theory/thtoc.htm
	for (unsigned int p=0; p<n_qp; p++)
	  {
	    const Real g11 = (this->dxdxi_map(p)*this->dxdxi_map(p) +
			      this->dydxi_map(p)*this->dydxi_map(p) +
			      this->dzdxi_map(p)*this->dzdxi_map(p));

	    const Real g12 = (this->dxdxi_map(p)*this->dxdeta_map(p) +
			      this->dydxi_map(p)*this->dydeta_map(p) +
			      this->dzdxi_map(p)*this->dzdeta_map(p));

	    const Real g21 = g12;

	    const Real g22 = (this->dxdeta_map(p)*this->dxdeta_map(p) +
			      this->dydeta_map(p)*this->dydeta_map(p) +
			      this->dzdeta_map(p)*this->dzdeta_map(p));


	    const Real the_jac = std::sqrt(g11*g22 - g12*g21);

	    libmesh_assert_greater (the_jac, 0.);

	    this->JxW[p] = the_jac*qw[p];
	  }

	break;
      }
    default:
      libmesh_error();

    } // switch(dim)

  STOP_LOG("compute_face_map()", "FEXYZMap");

  return;
}
Example #29
0
Real RBEvaluation::compute_residual_dual_norm(const unsigned int N)
{
  START_LOG("compute_residual_dual_norm()", "RBEvaluation");

  const RBParameters& mu = get_parameters();

  // Use the stored representor inner product values
  // to evaluate the residual norm
  Number residual_norm_sq = 0.;

  unsigned int q=0;
  for(unsigned int q_f1=0; q_f1<rb_theta_expansion->get_n_F_terms(); q_f1++)
    {
      for(unsigned int q_f2=q_f1; q_f2<rb_theta_expansion->get_n_F_terms(); q_f2++)
        {
          Real delta = (q_f1==q_f2) ? 1. : 2.;
          residual_norm_sq += delta * libmesh_real(
                                                   rb_theta_expansion->eval_F_theta(q_f1, mu)
                                                   * libmesh_conj(rb_theta_expansion->eval_F_theta(q_f2, mu)) * Fq_representor_innerprods[q] );

          q++;
        }
    }

  for(unsigned int q_f=0; q_f<rb_theta_expansion->get_n_F_terms(); q_f++)
    {
      for(unsigned int q_a=0; q_a<rb_theta_expansion->get_n_A_terms(); q_a++)
        {
          for(unsigned int i=0; i<N; i++)
            {
              Real delta = 2.;
              residual_norm_sq +=
                delta * libmesh_real( rb_theta_expansion->eval_F_theta(q_f, mu) *
                                      libmesh_conj(rb_theta_expansion->eval_A_theta(q_a, mu)) *
                                      libmesh_conj(RB_solution(i)) * Fq_Aq_representor_innerprods[q_f][q_a][i] );
            }
        }
    }

  q=0;
  for(unsigned int q_a1=0; q_a1<rb_theta_expansion->get_n_A_terms(); q_a1++)
    {
      for(unsigned int q_a2=q_a1; q_a2<rb_theta_expansion->get_n_A_terms(); q_a2++)
        {
          Real delta = (q_a1==q_a2) ? 1. : 2.;

          for(unsigned int i=0; i<N; i++)
            {
              for(unsigned int j=0; j<N; j++)
                {
                  residual_norm_sq +=
                    delta * libmesh_real( libmesh_conj(rb_theta_expansion->eval_A_theta(q_a1, mu)) *
                                          rb_theta_expansion->eval_A_theta(q_a2, mu) *
                                          libmesh_conj(RB_solution(i)) * RB_solution(j) * Aq_Aq_representor_innerprods[q][i][j] );
                }
            }

          q++;
        }
    }

  if(libmesh_real(residual_norm_sq) < 0.)
    {
      //    libMesh::out << "Warning: Square of residual norm is negative "
      //                 << "in RBSystem::compute_residual_dual_norm()" << std::endl;

      //     Sometimes this is negative due to rounding error,
      //     but when this occurs the error is on the order of 1.e-10,
      //     so shouldn't affect error bound much...
      residual_norm_sq = std::abs(residual_norm_sq);
    }

  STOP_LOG("compute_residual_dual_norm()", "RBEvaluation");

  return std::sqrt( libmesh_real(residual_norm_sq) );
}
Example #30
0
void UNVIO::count_nodes (std::istream& in_file)
{
  START_LOG("count_nodes()","UNVIO");

  // if this->_n_nodes is not 0 the dataset
  // has already been scanned
  if (this->_n_nodes != 0)
    {
      libMesh::err << "Error: Trying to scan nodes twice!"
		    << std::endl;
      libmesh_error();
    }


  // Read from file, count nodes,
  // check if floats have to be converted
  std::string data;

  in_file >> data; // read the first node label


  if (data == "-1")
    {
      libMesh::err << "ERROR: Bad, already reached end of dataset before even starting to read nodes!"
		    << std::endl;
      libmesh_error();
    }


  // ignore the misc data for this node
  in_file.ignore(256,'\n');



  // Now we are there to verify whether we need
  // to convert from D to e or not
  in_file >> data;

  // When this "data" contains a "D", then
  // we have to convert each and every float...
  // But also assume when _this_ specific
  // line does not contain a "D", then the
  // other lines won't, too.
  {
// #ifdef __HP_aCC
//     // Use an "int" instead of unsigned int,
//     // otherwise HP aCC may crash!
//     const int position          = data.find("D",6);
// #else
//     const unsigned int position = data.find("D",6);
// #endif
    std::string::size_type position = data.find("D",6);

    if (position!=std::string::npos) // npos means no position
      {
	this->_need_D_to_e = true;

	if (this->verbose())
	  libMesh::out << "  Convert from \"D\" to \"e\"" << std::endl;
      }
    else
      this->_need_D_to_e = false;
  }

  // read the remaining two coordinates
  in_file >> data;
  in_file >> data;


  // this was our first node
  this->_n_nodes++;



  // proceed _counting_ the remaining
  // nodes.
  while (in_file.good())
    {
      // read the node label
      in_file >> data;

      if (data == "-1")
	// end of dataset is reached
	break;

      // ignore the remaining data (coord_sys_label, color etc)
      in_file.ignore (256, '\n');
      // ignore the coordinates
      in_file.ignore (256, '\n');

      this->_n_nodes++;
    }


  if (in_file.eof())
    {
      libMesh::err << "ERROR: File ended before end of node dataset!"
		    << std::endl;
      libmesh_error();
    }

  if (this->verbose())
    libMesh::out << "  Nodes   : " << this->_n_nodes << std::endl;

  STOP_LOG("count_nodes()","UNVIO");
}