Пример #1
0
  void testRestart()
  {
    SlitFunc slitfunc;

    _mesh->write("slit_mesh.xda");
    _es->write("slit_solution.xda",
               EquationSystems::WRITE_DATA |
               EquationSystems::WRITE_SERIAL_FILES);

    Mesh mesh2(*TestCommWorld);
    mesh2.read("slit_mesh.xda");
    EquationSystems es2(mesh2);
    es2.read("slit_solution.xda");

    System & sys2 = es2.get_system<System> ("SimpleSystem");

    unsigned int dim = 2;

    CPPUNIT_ASSERT_EQUAL( sys2.n_vars(), 1u );

    FEMContext context(sys2);
    FEBase * fe = NULL;
    context.get_element_fe( 0, fe, dim );
    const std::vector<Point> & xyz = fe->get_xyz();
    fe->get_phi();

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

    for (; el != end_el; ++el)
      {
        const Elem * elem = *el;
        context.pre_fe_reinit(sys2, elem);
        context.elem_fe_reinit();

        const unsigned int n_qp = xyz.size();

        for (unsigned int qp=0; qp != n_qp; ++qp)
          {
            const Number exact_val = slitfunc(context, xyz[qp]);

            const Number discrete_val = context.interior_value(0, qp);

            CPPUNIT_ASSERT_DOUBLES_EQUAL(libmesh_real(exact_val),
                                         libmesh_real(discrete_val),
                                         TOLERANCE*TOLERANCE);
          }
      }
  }
Пример #2
0
void
MaxQpsThread::operator() (const ConstElemRange & range)
{
    ParallelUniqueId puid;
    _tid = puid.id;

    // For short circuiting reinit
    std::set<ElemType> seen_it;
    for (ConstElemRange::const_iterator elem_it = range.begin() ; elem_it != range.end(); ++elem_it)
    {
        const Elem * elem = *elem_it;

        // Only reinit if the element type has not previously been seen
        if (seen_it.insert(elem->type()).second)
        {
            FEType fe_type(FIRST, LAGRANGE);
            unsigned int dim = elem->dim();
            unsigned int side = 0;           // we assume that any element will have at least one side ;)

            // We cannot mess with the FE objects in Assembly, because we might need to request second derivatives
            // later on. If we used them, we'd call reinit on them, thus making the call to request second
            // derivatives harmful (i.e. leading to segfaults/asserts). Thus, we have to use a locally allocated object here.
            FEBase * fe = FEBase::build(dim, fe_type).release();

            // figure out the number of qps for volume
            QBase * qrule = QBase::build(_qtype, dim, _order).release();
            fe->attach_quadrature_rule(qrule);
            fe->reinit(elem);
            if (qrule->n_points() > _max)
                _max = qrule->n_points();
            delete qrule;

            // figure out the number of qps for the face
            // NOTE: user might specify higher order rule for faces, thus possibly ending up with more qps than in the volume
            QBase * qrule_face = QBase::build(_qtype, dim - 1, _face_order).release();
            fe->attach_quadrature_rule(qrule_face);
            fe->reinit(elem, side);
            if (qrule_face->n_points() > _max)
                _max = qrule_face->n_points();
            delete qrule_face;

            delete fe;
        }
    }
}
Пример #3
0
  void testSystem()
  {
    SlitFunc slitfunc;

    unsigned int dim = 2;

    CPPUNIT_ASSERT_EQUAL( _sys->n_vars(), 1u );

    FEMContext context(*_sys);
    FEBase * fe = NULL;
    context.get_element_fe( 0, fe, dim );
    const std::vector<Point> & xyz = fe->get_xyz();
    fe->get_phi();

    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)
      {
        const Elem * elem = *el;
        context.pre_fe_reinit(*_sys, elem);
        context.elem_fe_reinit();

        const unsigned int n_qp = xyz.size();

        for (unsigned int qp=0; qp != n_qp; ++qp)
          {
            const Number exact_val = slitfunc(context, xyz[qp]);

            const Number discrete_val = context.interior_value(0, qp);

            CPPUNIT_ASSERT_DOUBLES_EQUAL(libmesh_real(exact_val),
                                         libmesh_real(discrete_val),
                                         TOLERANCE*TOLERANCE);
          }
      }
  }
Пример #4
0
void HeatSystem::init_context(DiffContext & context)
{
  FEMContext & c = libmesh_cast_ref<FEMContext &>(context);

  const std::set<unsigned char> & elem_dims =
    c.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;

      FEBase * fe = libmesh_nullptr;

      c.get_element_fe(T_var, fe, dim);

      fe->get_JxW();  // For integration
      fe->get_dphi(); // For bilinear form
      fe->get_xyz();  // For forcing
      fe->get_phi();  // For forcing
    }

  FEMSystem::init_context(context);
}
Пример #5
0
bool HeatSystem::element_time_derivative (bool request_jacobian,
                                          DiffContext & context)
{
  FEMContext & c = libmesh_cast_ref<FEMContext &>(context);

  const unsigned int mesh_dim =
    c.get_system().get_mesh().mesh_dimension();

  // First we get some references to cell-specific data that
  // will be used to assemble the linear system.
  const unsigned int dim = c.get_elem().dim();
  FEBase * fe = libmesh_nullptr;
  c.get_element_fe(T_var, fe, dim);

  // Element Jacobian * quadrature weights for interior integration
  const std::vector<Real> & JxW = fe->get_JxW();

  const std::vector<Point> & xyz = fe->get_xyz();

  const std::vector<std::vector<Real> > & phi = fe->get_phi();

  const std::vector<std::vector<RealGradient> > & dphi = fe->get_dphi();

  // The number of local degrees of freedom in each variable
  const unsigned int n_T_dofs = c.get_dof_indices(T_var).size();

  // The subvectors and submatrices we need to fill:
  DenseSubMatrix<Number> & K = c.get_elem_jacobian(T_var, T_var);
  DenseSubVector<Number> & F = c.get_elem_residual(T_var);

  // Now we will build the element Jacobian and residual.
  // Constructing the residual requires the solution and its
  // gradient from the previous timestep.  This must be
  // calculated at each quadrature point by summing the
  // solution degree-of-freedom values by the appropriate
  // weight functions.
  unsigned int n_qpoints = c.get_element_qrule().n_points();

  for (unsigned int qp=0; qp != n_qpoints; qp++)
    {
      // Compute the solution gradient at the Newton iterate
      Gradient grad_T = c.interior_gradient(T_var, qp);

      const Number k = _k[dim];

      const Point & p = xyz[qp];

      // solution + laplacian depend on problem dimension
      const Number u_exact = (mesh_dim == 2) ?
        std::sin(libMesh::pi*p(0)) * std::sin(libMesh::pi*p(1)) :
        std::sin(libMesh::pi*p(0)) * std::sin(libMesh::pi*p(1)) *
        std::sin(libMesh::pi*p(2));

      // Only apply forcing to interior elements
      const Number forcing = (dim == mesh_dim) ?
        -k * u_exact * (dim * libMesh::pi * libMesh::pi) : 0;

      const Number JxWxNK = JxW[qp] * -k;

      for (unsigned int i=0; i != n_T_dofs; i++)
        F(i) += JxWxNK * (grad_T * dphi[i][qp] + forcing * phi[i][qp]);
      if (request_jacobian)
        {
          const Number JxWxNKxD = JxWxNK *
            context.get_elem_solution_derivative();

          for (unsigned int i=0; i != n_T_dofs; i++)
            for (unsigned int j=0; j != n_T_dofs; ++j)
              K(i,j) += JxWxNKxD * (dphi[i][qp] * dphi[j][qp]);
        }
    } // end of the quadrature point qp-loop

  return request_jacobian;
}
Пример #6
0
// This function assembles the system matrix and right-hand-side
// for the discrete form of our wave equation.
void assemble_wave(EquationSystems & es,
                   const std::string & system_name)
{
    // It is a good idea to make sure we are assembling
    // the proper system.
    libmesh_assert_equal_to (system_name, "Wave");


#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS

    // Get a constant reference to the mesh object.
    const MeshBase & mesh = es.get_mesh();

    // Get a reference to the system we are solving.
    LinearImplicitSystem & system = es.get_system<LinearImplicitSystem>("Wave");

    // A reference to the \p DofMap object for this system.  The \p DofMap
    // object handles the index translation from node and element numbers
    // to degree of freedom numbers.
    const DofMap & dof_map = system.get_dof_map();

    // The dimension that we are running.
    const unsigned int dim = mesh.mesh_dimension();

    // Copy the speed of sound to a local variable.
    const Real speed = es.parameters.get<Real>("speed");

    // Get a constant reference to the Finite Element type
    // for the first (and only) variable in the system.
    const FEType & fe_type = dof_map.variable_type(0);

    // Build a Finite Element object of the specified type.  Since the
    // \p FEBase::build() member dynamically creates memory we will
    // store the object as an \p UniquePtr<FEBase>.  Check ex5 for details.
    UniquePtr<FEBase> fe (FEBase::build(dim, fe_type));

    // Do the same for an infinite element.
    UniquePtr<FEBase> inf_fe (FEBase::build_InfFE(dim, fe_type));

    // A 2nd order Gauss quadrature rule for numerical integration.
    QGauss qrule (dim, SECOND);

    // Tell the finite element object to use our quadrature rule.
    fe->attach_quadrature_rule (&qrule);

    // Due to its internal structure, the infinite element handles
    // quadrature rules differently.  It takes the quadrature
    // rule which has been initialized for the FE object, but
    // creates suitable quadrature rules by @e itself.  The user
    // need not worry about this.
    inf_fe->attach_quadrature_rule (&qrule);

    // Define data structures to contain the element matrix
    // and right-hand-side vector contribution.  Following
    // basic finite element terminology we will denote these
    // "Ke",  "Ce", "Me", and "Fe" for the stiffness, damping
    // and mass matrices, and the load vector.  Note that in
    // Acoustics, these descriptors though do @e not match the
    // true physical meaning of the projectors.  The final
    // overall system, however, resembles the conventional
    // notation again.
    DenseMatrix<Number> Ke;
    DenseMatrix<Number> Ce;
    DenseMatrix<Number> Me;
    DenseVector<Number> Fe;

    // This vector will hold the degree of freedom indices for
    // the element.  These define where in the global system
    // the element degrees of freedom get mapped.
    std::vector<dof_id_type> dof_indices;

    // Now we will loop over all the elements in the mesh.
    // We will compute the element matrix and right-hand-side
    // contribution.
    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)
    {
        // Store a pointer to the element we are currently
        // working on.  This allows for nicer syntax later.
        const Elem * elem = *el;

        // Get the degree of freedom indices for the
        // current element.  These define where in the global
        // matrix and right-hand-side this element will
        // contribute to.
        dof_map.dof_indices (elem, dof_indices);

        // The mesh contains both finite and infinite elements.  These
        // elements are handled through different classes, namely
        // \p FE and \p InfFE, respectively.  However, since both
        // are derived from \p FEBase, they share the same interface,
        // and overall burden of coding is @e greatly reduced through
        // using a pointer, which is adjusted appropriately to the
        // current element type.
        FEBase * cfe = libmesh_nullptr;

        // This here is almost the only place where we need to
        // distinguish between finite and infinite elements.
        // For faster computation, however, different approaches
        // may be feasible.
        //
        // Up to now, we do not know what kind of element we
        // have.  Aske the element of what type it is:
        if (elem->infinite())
        {
            // We have an infinite element.  Let \p cfe point
            // to our \p InfFE object.  This is handled through
            // an UniquePtr.  Through the \p UniquePtr::get() we "borrow"
            // the pointer, while the \p  UniquePtr \p inf_fe is
            // still in charge of memory management.
            cfe = inf_fe.get();
        }
        else
        {
            // This is a conventional finite element.  Let \p fe handle it.
            cfe = fe.get();

            // Boundary conditions.
            // Here we just zero the rhs-vector. For natural boundary
            // conditions check e.g. previous examples.
            {
                // Zero the RHS for this element.
                Fe.resize (dof_indices.size());

                system.rhs->add_vector (Fe, dof_indices);
            } // end boundary condition section
        } // else if (elem->infinite())

        // This is slightly different from the Poisson solver:
        // Since the finite element object may change, we have to
        // initialize the constant references to the data fields
        // each time again, when a new element is processed.
        //
        // The element Jacobian * quadrature weight at each integration point.
        const std::vector<Real> & JxW = cfe->get_JxW();

        // The element shape functions evaluated at the quadrature points.
        const std::vector<std::vector<Real> > & phi = cfe->get_phi();

        // The element shape function gradients evaluated at the quadrature
        // points.
        const std::vector<std::vector<RealGradient> > & dphi = cfe->get_dphi();

        // The infinite elements need more data fields than conventional FE.
        // These are the gradients of the phase term \p dphase, an additional
        // radial weight for the test functions \p Sobolev_weight, and its
        // gradient.
        //
        // Note that these data fields are also initialized appropriately by
        // the \p FE method, so that the weak form (below) is valid for @e both
        // finite and infinite elements.
        const std::vector<RealGradient> & dphase  = cfe->get_dphase();
        const std::vector<Real> &         weight  = cfe->get_Sobolev_weight();
        const std::vector<RealGradient> & dweight = cfe->get_Sobolev_dweight();

        // Now this is all independent of whether we use an \p FE
        // or an \p InfFE.  Nice, hm? ;-)
        //
        // Compute the element-specific data, as described
        // in previous examples.
        cfe->reinit (elem);

        // Zero the element matrices.  Boundary conditions were already
        // processed in the \p FE-only section, see above.
        Ke.resize (dof_indices.size(), dof_indices.size());
        Ce.resize (dof_indices.size(), dof_indices.size());
        Me.resize (dof_indices.size(), dof_indices.size());

        // The total number of quadrature points for infinite elements
        // @e has to be determined in a different way, compared to
        // conventional finite elements.  This type of access is also
        // valid for finite elements, so this can safely be used
        // anytime, instead of asking the quadrature rule, as
        // seen in previous examples.
        unsigned int max_qp = cfe->n_quadrature_points();

        // Loop over the quadrature points.
        for (unsigned int qp=0; qp<max_qp; qp++)
        {
            // Similar to the modified access to the number of quadrature
            // points, the number of shape functions may also be obtained
            // in a different manner.  This offers the great advantage
            // of being valid for both finite and infinite elements.
            const unsigned int n_sf = cfe->n_shape_functions();

            // Now we will build the element matrices.  Since the infinite
            // elements are based on a Petrov-Galerkin scheme, the
            // resulting system matrices are non-symmetric. The additional
            // weight, described before, is part of the trial space.
            //
            // For the finite elements, though, these matrices are symmetric
            // just as we know them, since the additional fields \p dphase,
            // \p weight, and \p dweight are initialized appropriately.
            //
            // test functions:    weight[qp]*phi[i][qp]
            // trial functions:   phi[j][qp]
            // phase term:        phase[qp]
            //
            // derivatives are similar, but note that these are of type
            // Point, not of type Real.
            for (unsigned int i=0; i<n_sf; i++)
                for (unsigned int j=0; j<n_sf; j++)
                {
                    // (ndt*Ht + nHt*d) * nH
                    Ke(i,j) +=
                        (
                            (dweight[qp] * phi[i][qp] // Point * Real  = Point
                             +                        // +
                             dphi[i][qp] * weight[qp] // Point * Real  = Point
                            ) * dphi[j][qp]
                        ) * JxW[qp];

                    // (d*Ht*nmut*nH - ndt*nmu*Ht*H - d*nHt*nmu*H)
                    Ce(i,j) +=
                        (
                            (dphase[qp] * dphi[j][qp]) // (Point * Point) = Real
                            * weight[qp] * phi[i][qp]  // * Real * Real   = Real
                            -                          // -
                            (dweight[qp] * dphase[qp]) // (Point * Point) = Real
                            * phi[i][qp] * phi[j][qp]  // * Real * Real   = Real
                            -                          // -
                            (dphi[i][qp] * dphase[qp]) // (Point * Point) = Real
                            * weight[qp] * phi[j][qp]  // * Real * Real   = Real
                        ) * JxW[qp];

                    // (d*Ht*H * (1 - nmut*nmu))
                    Me(i,j) +=
                        (
                            (1. - (dphase[qp] * dphase[qp]))       // (Real  - (Point * Point)) = Real
                            * phi[i][qp] * phi[j][qp] * weight[qp] // * Real *  Real  * Real    = Real
                        ) * JxW[qp];

                } // end of the matrix summation loop
        } // end of quadrature point loop

        // The element matrices are now built for this element.
        // Collect them in Ke, and then add them to the global matrix.
        // The \p SparseMatrix::add_matrix() member does this for us.
        Ke.add(1./speed        , Ce);
        Ke.add(1./(speed*speed), Me);

        // If this assembly program were to be used on an adaptive mesh,
        // we would have to apply any hanging node constraint equations
        dof_map.constrain_element_matrix(Ke, dof_indices);

        system.matrix->add_matrix (Ke, dof_indices);
    } // end of element loop

    // Note that we have not applied any boundary conditions so far.
    // Here we apply a unit load at the node located at (0,0,0).
    {
        // Iterate over local nodes
        MeshBase::const_node_iterator           nd = mesh.local_nodes_begin();
        const MeshBase::const_node_iterator nd_end = mesh.local_nodes_end();

        for (; nd != nd_end; ++nd)
        {
            // Get a reference to the current node.
            const Node & node = **nd;

            // Check the location of the current node.
            if (std::abs(node(0)) < TOLERANCE &&
                    std::abs(node(1)) < TOLERANCE &&
                    std::abs(node(2)) < TOLERANCE)
            {
                // The global number of the respective degree of freedom.
                unsigned int dn = node.dof_number(0,0,0);

                system.rhs->add (dn, 1.);
            }
        }
    }

#else

    // dummy assert
    libmesh_assert_not_equal_to (es.get_mesh().mesh_dimension(), 1);

#endif //ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
}
Пример #7
0
bool SolidSystem::side_time_derivative(bool request_jacobian,
    DiffContext &context) {
  FEMContext &c = libmesh_cast_ref<FEMContext&>(context);

  // Apply displacement boundary conditions with penalty method

  // Get the current load step
  Real ratio = this->get_equation_systems().parameters.get<Real>("progress")
      + 0.001;

  // The BC are stored in the simulation parameters as array containing sequences of
  // four numbers: Id of the side for the displacements and three values describing the
  // displacement. E.g.: bc/displacement = '5 nan nan -1.0'. This will move all nodes of
  // side 5 about 1.0 units down the z-axis while leaving all other directions unrestricted

  // Get number of BCs to enforce
  unsigned int num_bc = args.vector_variable_size("bc/displacement");
  if (num_bc % 4 != 0) {
    libMesh::err
        << "ERROR, Odd number of values in displacement boundary condition.\n"
        << std::endl;
    libmesh_error();
  }
  num_bc /= 4;

  // Loop over all BCs
  for (unsigned int nbc = 0; nbc < num_bc; nbc++) {
    // Get IDs of the side for this BC
    short int positive_boundary_id = args("bc/displacement", 1, nbc * 4);

    // The current side may not be on the boundary to be restricted
    if (!this->get_mesh().boundary_info->has_boundary_id
	  (c.elem,c.side,positive_boundary_id))
      continue;

    // Read values from configuration file
    Point diff_value;
    for (unsigned int d = 0; d < c.dim; ++d) {
      diff_value(d) = args("bc/displacement", NAN, nbc * 4 + 1 + d);
    }
    // Scale according to current load step
    diff_value *= ratio;

    Real penalty_number = args("bc/displacement_penalty", 1e7);

    FEBase * fe = c.side_fe_var[var[0]];
    const std::vector<std::vector<Real> > & phi = fe->get_phi();
    const std::vector<Real>& JxW = fe->get_JxW();
    const std::vector<Point>& coords = fe->get_xyz();

    unsigned int n_x_dofs = c.dof_indices_var[this->var[0]].size();

    // get mappings for dofs for auxiliary system for original mesh positions
    const System & auxsys = this->get_equation_systems().get_system(
        "auxiliary");
    const DofMap & auxmap = auxsys.get_dof_map();
    std::vector<dof_id_type> undefo_dofs[3];
    for (unsigned int d = 0; d < c.dim; ++d) {
      auxmap.dof_indices(c.elem, undefo_dofs[d], undefo_var[d]);
    }

    for (unsigned int qp = 0; qp < c.side_qrule->n_points(); ++qp) {
      // calculate coordinates of qp on undeformed mesh
      Point orig_point;
      for (unsigned int i = 0; i < n_x_dofs; ++i) {
        for (unsigned int d = 0; d < c.dim; ++d) {
          Number orig_val = auxsys.current_solution(undefo_dofs[d][i]);

#if LIBMESH_USE_COMPLEX_NUMBERS
          orig_point(d) += phi[i][qp] * orig_val.real();
#else
          orig_point(d) += phi[i][qp] * orig_val;
#endif
        }
      }

      // Calculate displacement to be enforced.
      Point diff = coords[qp] - orig_point - diff_value;

      // Assemble
      for (unsigned int i = 0; i < n_x_dofs; ++i) {
        for (unsigned int d1 = 0; d1 < c.dim; ++d1) {
          if (libmesh_isnan(diff(d1)))
            continue;
          Real val = JxW[qp] * phi[i][qp] * diff(d1) * penalty_number;
          c.elem_subresiduals[var[d1]]->operator ()(i) += val;
        }
        if (request_jacobian) {
          for (unsigned int j = 0; j < n_x_dofs; ++j) {
            for (unsigned int d1 = 0; d1 < c.dim; ++d1) {
              if (libmesh_isnan(diff(d1)))
                continue;
              Real val = JxW[qp] * phi[i][qp] * phi[j][qp] * penalty_number;
              c.elem_subjacobians[var[d1]][var[d1]]->operator ()(i, j) += val;
            }
          }
        }
      }
    }
  }

  return request_jacobian;
}
Пример #8
0
void
Assembly::reinitFE(const Elem * elem)
{
  unsigned int dim = elem->dim();
  std::map<FEType, FEBase *>::iterator it = _fe[dim].begin();
  std::map<FEType, FEBase *>::iterator end = _fe[dim].end();

  ElementFEShapeData * efesd = NULL;

  // Whether or not we're going to do FE caching this time through
  bool do_caching = _should_use_fe_cache && _currently_fe_caching;

  if (do_caching)
  {
    efesd = _element_fe_shape_data_cache[elem->id()];

    if (!efesd)
    {
      efesd = new ElementFEShapeData;
      _element_fe_shape_data_cache[elem->id()] = efesd;
      efesd->_invalidated = true;
    }
  }

  for (; it != end; ++it)
  {
    FEBase * fe = it->second;
    const FEType & fe_type = it->first;

    _current_fe[fe_type] = fe;

    FEShapeData * fesd = _fe_shape_data[fe_type];

    FEShapeData * cached_fesd = NULL;
    if (do_caching)
      cached_fesd = efesd->_shape_data[fe_type];

    if (!cached_fesd || efesd->_invalidated)
    {
      fe->reinit(elem);

      fesd->_phi.shallowCopy(const_cast<std::vector<std::vector<Real> > &>(fe->get_phi()));
      fesd->_grad_phi.shallowCopy(const_cast<std::vector<std::vector<RealGradient> > &>(fe->get_dphi()));
      if (_need_second_derivative[fe_type])
        fesd->_second_phi.shallowCopy(const_cast<std::vector<std::vector<RealTensor> > &>(fe->get_d2phi()));

      if (do_caching)
      {
        if (!cached_fesd)
        {
          cached_fesd = new FEShapeData;
          efesd->_shape_data[fe_type] = cached_fesd;
        }

        *cached_fesd = *fesd;
      }
    }
    else // This means we have valid cached shape function values for this element / fe_type combo
    {
      fesd->_phi.shallowCopy(cached_fesd->_phi);
      fesd->_grad_phi.shallowCopy(cached_fesd->_grad_phi);
      if (_need_second_derivative[fe_type])
        fesd->_second_phi.shallowCopy(cached_fesd->_second_phi);
    }
  }

  // During that last loop the helper objects will have been reinitialized as well
  // We need to dig out the q_points and JxW from it.
  if (!do_caching || efesd->_invalidated)
  {
    _current_q_points.shallowCopy(const_cast<std::vector<Point> &>((*_holder_fe_helper[dim])->get_xyz()));
    _current_JxW.shallowCopy(const_cast<std::vector<Real> &>((*_holder_fe_helper[dim])->get_JxW()));

    if (do_caching)
    {
      efesd->_q_points = _current_q_points;
      efesd->_JxW = _current_JxW;
    }
  }
  else // Use cached values
  {
    _current_q_points.shallowCopy(efesd->_q_points);
    _current_JxW.shallowCopy(efesd->_JxW);
  }

  if (do_caching)
    efesd->_invalidated = false;
}
Пример #9
0
  void testRestart()
  {
    SlitFunc slitfunc;

    _mesh->write("slit_mesh.xda");
    _es->write("slit_solution.xda",
               EquationSystems::WRITE_DATA |
               EquationSystems::WRITE_SERIAL_FILES);

    Mesh mesh2(*TestCommWorld);
    mesh2.read("slit_mesh.xda");
    EquationSystems es2(mesh2);
    es2.read("slit_solution.xda");

    System & sys2 = es2.get_system<System> ("SimpleSystem");

    unsigned int dim = 2;

    CPPUNIT_ASSERT_EQUAL( sys2.n_vars(), 1u );

    FEMContext context(sys2);
    FEBase * fe = NULL;
    context.get_element_fe( 0, fe, dim );
    const std::vector<Point> & xyz = fe->get_xyz();
    fe->get_phi();

    // While we're in the middle of a unique id based test case, let's
    // make sure our unique ids were all read in correctly too.
    UniquePtr<PointLocatorBase> locator = _mesh->sub_point_locator();

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

    for (; el != end_el; ++el)
      {
        const Elem * elem = *el;

        const Elem * mesh1_elem = (*locator)(elem->centroid());
        if (mesh1_elem)
          {
            CPPUNIT_ASSERT_EQUAL( elem->unique_id(),
                                  mesh1_elem->unique_id() );

            for (unsigned int n=0; n != elem->n_nodes(); ++n)
              {
                const Node & node       = elem->node_ref(n);
                const Node & mesh1_node = mesh1_elem->node_ref(n);
                CPPUNIT_ASSERT_EQUAL( node.unique_id(),
                                      mesh1_node.unique_id() );
              }
          }

        context.pre_fe_reinit(sys2, elem);
        context.elem_fe_reinit();

        const unsigned int n_qp = xyz.size();

        for (unsigned int qp=0; qp != n_qp; ++qp)
          {
            const Number exact_val = slitfunc(context, xyz[qp]);

            const Number discrete_val = context.interior_value(0, qp);

            CPPUNIT_ASSERT_DOUBLES_EQUAL(libmesh_real(exact_val),
                                         libmesh_real(discrete_val),
                                         TOLERANCE*TOLERANCE);
          }
      }
  }