Beispiel #1
0
Real FE<3,MONOMIAL>::shape(const ElemType,
			   const Order libmesh_dbg_var(order),
			   const unsigned int i,
			   const Point& p)
{
#if LIBMESH_DIM == 3

  const Real xi   = p(0);
  const Real eta  = p(1);
  const Real zeta = p(2);

  libmesh_assert_less (i, (static_cast<unsigned int>(order)+1)*
              (static_cast<unsigned int>(order)+2)*
              (static_cast<unsigned int>(order)+3)/6);

    // monomials. since they are hierarchic we only need one case block.
  switch (i)
    {
      // constant
    case 0:
      return 1.;

      // linears
    case 1:
      return xi;

    case 2:
      return eta;

    case 3:
      return zeta;

      // quadratics
    case 4:
      return xi*xi;

    case 5:
      return xi*eta;

    case 6:
      return eta*eta;

    case 7:
      return xi*zeta;

    case 8:
      return zeta*eta;

    case 9:
      return zeta*zeta;

      // cubics
    case 10:
      return xi*xi*xi;

    case 11:
      return xi*xi*eta;

    case 12:
      return xi*eta*eta;

    case 13:
      return eta*eta*eta;

    case 14:
      return xi*xi*zeta;

    case 15:
      return xi*eta*zeta;

    case 16:
      return eta*eta*zeta;

    case 17:
      return xi*zeta*zeta;

    case 18:
      return eta*zeta*zeta;

    case 19:
      return zeta*zeta*zeta;

      // quartics
    case 20:
      return xi*xi*xi*xi;

    case 21:
      return xi*xi*xi*eta;

    case 22:
      return xi*xi*eta*eta;

    case 23:
      return xi*eta*eta*eta;

    case 24:
      return eta*eta*eta*eta;

    case 25:
      return xi*xi*xi*zeta;

    case 26:
      return xi*xi*eta*zeta;

    case 27:
      return xi*eta*eta*zeta;

    case 28:
      return eta*eta*eta*zeta;

    case 29:
      return xi*xi*zeta*zeta;

    case 30:
      return xi*eta*zeta*zeta;

    case 31:
      return eta*eta*zeta*zeta;

    case 32:
      return xi*zeta*zeta*zeta;

    case 33:
      return eta*zeta*zeta*zeta;

    case 34:
      return zeta*zeta*zeta*zeta;

    default:
      unsigned int o = 0;
      for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
      unsigned int i2 = i - (o*(o+1)*(o+2)/6);
      unsigned int block=o, nz = 0;
      for (; block < i2; block += (o-nz+1)) { nz++; }
      const unsigned int nx = block - i2;
      const unsigned int ny = o - nx - nz;
      Real val = 1.;
      for (unsigned int index=0; index != nx; index++)
        val *= xi;
      for (unsigned int index=0; index != ny; index++)
        val *= eta;
      for (unsigned int index=0; index != nz; index++)
        val *= zeta;
      return val;
    }

#endif

  libmesh_error();
  return 0.;
}
Real FE<1,L2_LAGRANGE>::shape_deriv(const ElemType,
			   	    const Order order,
				    const unsigned int i,
				    const unsigned int libmesh_dbg_var(j),
				    const Point& p)
{
  // only d()/dxi in 1D!

  libmesh_assert_equal_to (j, 0);

  const Real xi = p(0);


  switch (order)
    {
      // Lagrange linear shape function derivatives
    case FIRST:
      {
	libmesh_assert_less (i, 2);

	switch (i)
	  {
	  case 0:
	    return -.5;

	  case 1:
	    return .5;

	  default:
	    libMesh::err << "Invalid shape function index!" << std::endl;
	    libmesh_error();
	  }
      }


      // Lagrange quadratic shape function derivatives
    case SECOND:
      {
	libmesh_assert_less (i, 3);

	switch (i)
	  {
	  case 0:
	    return xi-.5;

	  case 1:
	    return xi+.5;

	  case 2:
	    return -2.*xi;

	  default:
	    libMesh::err << "Invalid shape function index!" << std::endl;
	    libmesh_error();
	  }
      }


      // Lagrange cubic shape function derivatives
    case THIRD:
      {
	libmesh_assert_less (i, 4);

	switch (i)
	  {
	  case 0:
	    return -9./16.*(3.*xi*xi-2.*xi-1./9.);

	  case 1:
	    return -9./16.*(-3.*xi*xi-2.*xi+1./9.);

	  case 2:
	    return 27./16.*(3.*xi*xi-2./3.*xi-1.);

	  case 3:
	    return 27./16.*(-3.*xi*xi-2./3.*xi+1.);

	  default:
	    libMesh::err << "Invalid shape function index!" << std::endl;
	    libmesh_error();
	  }
      }


    default:
      {
	libMesh::err << "ERROR: Unsupported polynomial order!" << std::endl;
	libmesh_error();
      }
    }

  libmesh_error();
  return 0.;
}
Real FE<1,L2_LAGRANGE>::shape(const ElemType,
			      const Order order,
			      const unsigned int i,
			      const Point& p)
{
  const Real xi = p(0);


  switch (order)
    {
      // Lagrange linears
    case FIRST:
      {
	libmesh_assert_less (i, 2);

	switch (i)
	  {
	  case 0:
	    return .5*(1. - xi);

	  case 1:
	    return .5*(1. + xi);

	  default:
	    libMesh::err << "Invalid shape function index!" << std::endl;
	    libmesh_error();
	  }
      }



      // Lagrange quadratics
    case SECOND:
      {
	libmesh_assert_less (i, 3);

	switch (i)
	  {
	  case 0:
	    return .5*xi*(xi - 1.);

	  case 1:
	    return .5*xi*(xi + 1);

	  case 2:
	    return (1. - xi*xi);

	  default:
	    libMesh::err << "Invalid shape function index!" << std::endl;
	    libmesh_error();
	  }
      }



      // Lagrange cubics
    case THIRD:
      {
	libmesh_assert_less (i, 4);

	switch (i)
	  {
	  case 0:
	    return 9./16.*(1./9.-xi*xi)*(xi-1.);

	  case 1:
	    return -9./16.*(1./9.-xi*xi)*(xi+1.);

	  case 2:
	    return 27./16.*(1.-xi*xi)*(1./3.-xi);

	  case 3:
	    return 27./16.*(1.-xi*xi)*(1./3.+xi);

	  default:
	    libMesh::err << "Invalid shape function index!" << std::endl;
	    libmesh_error();
	  }
      }

    default:
      {
	libMesh::err << "ERROR: Unsupported polynomial order!" << std::endl;
	libmesh_error();
      }
    }


  libmesh_error();
  return 0.;
}
void LaplaceMeshSmoother::init()
{
  switch (_mesh.mesh_dimension())
    {

      // TODO:[BSK] Fix this to work for refined meshes...  I think
      // the implementation was done quickly for Damien, who did not have
      // refined grids.  Fix it here and in the original Mesh member.

    case 2: // Stolen directly from build_L_graph in mesh_base.C
      {
	// Initialize space in the graph.  It is n_nodes long.  Each
	// node may be connected to an arbitrary number of other nodes
	// via edges.
	_graph.resize(_mesh.n_nodes());

	MeshBase::element_iterator       el  = _mesh.active_local_elements_begin();
	const MeshBase::element_iterator end = _mesh.active_local_elements_end();

	for (; el != end; ++el)
	  {
	    // Constant handle for the element
	    const Elem* elem = *el;

	    for (unsigned int s=0; s<elem->n_neighbors(); s++)
	      {
		// Only operate on sides which are on the
		// boundary or for which the current element's
		// id is greater than its neighbor's.
                // Sides get only built once.
		if ((elem->neighbor(s) == NULL) ||
		    (elem->id() > elem->neighbor(s)->id()))
		  {
		    AutoPtr<Elem> side(elem->build_side(s));
		    _graph[side->node(0)].push_back(side->node(1));
		    _graph[side->node(1)].push_back(side->node(0));
		  }
	      }
	  }
	_initialized = true;
	break;
      } // case 2

    case 3: // Stolen blatantly from build_L_graph in mesh_base.C
      {
	// Initialize space in the graph.
	_graph.resize(_mesh.n_nodes());

	MeshBase::element_iterator       el  = _mesh.active_local_elements_begin();
	const MeshBase::element_iterator end = _mesh.active_local_elements_end();

	for (; el != end; ++el)
	  {
	    // Shortcut notation for simplicity
	    const Elem* elem = *el;

	    for (unsigned int f=0; f<elem->n_neighbors(); f++) // Loop over faces
	      if ((elem->neighbor(f) == NULL) ||
		  (elem->id() > elem->neighbor(f)->id()))
		{
		  // We need a full (i.e. non-proxy) element for the face, since we will
		  // be looking at its sides as well!
		  AutoPtr<Elem> face = elem->build_side(f, /*proxy=*/false);

		  for (unsigned int s=0; s<face->n_neighbors(); s++) // Loop over face's edges
		    {
		      // Here we can use a proxy
		      AutoPtr<Elem> side = face->build_side(s);

		      // At this point, we just insert the node numbers
		      // again.  At the end we'll call sort and unique
		      // to make sure there are no duplicates
		      _graph[side->node(0)].push_back(side->node(1));
		      _graph[side->node(1)].push_back(side->node(0));
		    }
		}
	  }

	_initialized = true;
	break;
      } // case 3

    default:
      {
	libMesh::err << "At this time it is not possible "
		      << "to smooth a dimension "
		      << _mesh.mesh_dimension()
		      << "mesh.  Aborting..."
		      << std::endl;
	libmesh_error();
      }
    }

  // Done building graph from local elements.  Let's now allgather the
  // graph so that it is available on all processors for the actual
  // smoothing operation?
  this->allgather_graph();

  // In 3D, it's possible for > 2 processor partitions to meet
  // at a single edge, while in 2D only 2 processor partitions
  // share an edge.  Therefore the allgather'd graph in 3D may
  // now have duplicate entries and we need to remove them so
  // they don't foul up the averaging algorithm employed by the
  // Laplace smoother.
  for (unsigned i=0; i<_graph.size(); ++i)
    {
      // The std::unique algorithm removes duplicate *consecutive* elements from a range,
      // so it only makes sense to call it on a sorted range...
      std::sort(_graph[i].begin(), _graph[i].end());
      _graph[i].erase(std::unique(_graph[i].begin(), _graph[i].end()), _graph[i].end());
    }

} // init()
Beispiel #5
0
void
InitialCondition::compute()
{
  // -- NOTE ----
  // The following code is a copy from libMesh project_vector.C plus it adds some features, so we can couple variable values
  // and we also do not call any callbacks, but we use our initial condition system directly.
  // ------------

  // The element matrix and RHS for projections.
  // Note that Ke is always real-valued, whereas Fe may be complex valued if complex number support is enabled
  DenseMatrix<Real> Ke;
  DenseVector<Number> Fe;
  // The new element coefficients
  DenseVector<Number> Ue;

  const FEType & fe_type = _var.feType();

  // The dimension of the current element
  const unsigned int dim = _current_elem->dim();
  // The element type
  const ElemType elem_type = _current_elem->type();
  // The number of nodes on the new element
  const unsigned int n_nodes = _current_elem->n_nodes();
  // The global DOF indices
  std::vector<dof_id_type> dof_indices;
  // Side/edge DOF indices
  std::vector<unsigned int> side_dofs;

  // Get FE objects of the appropriate type
  // We cannot use the FE object in Assembly, since the following code is messing with the quadrature rules
  // for projections and would screw it up. However, if we implement projections from one mesh to another,
  // this code should use that implementation.
  UniquePtr<FEBase> fe (FEBase::build(dim, fe_type));

  // Prepare variables for projection
  UniquePtr<QBase> qrule     (fe_type.default_quadrature_rule(dim));
  UniquePtr<QBase> qedgerule (fe_type.default_quadrature_rule(1));
  UniquePtr<QBase> qsiderule (fe_type.default_quadrature_rule(dim-1));

  // The values of the shape functions at the quadrature points
  const std::vector<std::vector<Real> > & phi = fe->get_phi();

  // The gradients of the shape functions at the quadrature points on the child element.
  const std::vector<std::vector<RealGradient> > * dphi = NULL;

  const FEContinuity cont = fe->get_continuity();

  if (cont == C_ONE)
  {
    const std::vector<std::vector<RealGradient> > & ref_dphi = fe->get_dphi();
    dphi = &ref_dphi;
  }

  // The Jacobian * quadrature weight at the quadrature points
  const std::vector<Real> & JxW =  fe->get_JxW();
  // The XYZ locations of the quadrature points
  const std::vector<Point>& xyz_values = fe->get_xyz();

  // Update the DOF indices for this element based on the current mesh
  _var.prepareIC();
  dof_indices = _var.dofIndices();

  // The number of DOFs on the element
  const unsigned int n_dofs = dof_indices.size();
  if (n_dofs == 0)
    return;

  // Fixed vs. free DoFs on edge/face projections
  std::vector<char> dof_is_fixed(n_dofs, false); // bools
  std::vector<int> free_dof(n_dofs, 0);

  // Zero the interpolated values
  Ue.resize (n_dofs);
  Ue.zero();

  // In general, we need a series of
  // projections to ensure a unique and continuous
  // solution.  We start by interpolating nodes, then
  // hold those fixed and project edges, then
  // hold those fixed and project faces, then
  // hold those fixed and project interiors

  // Interpolate node values first
  unsigned int current_dof = 0;
  for (unsigned int n = 0; n != n_nodes; ++n)
  {
    // FIXME: this should go through the DofMap,
    // not duplicate dof_indices code badly!
    const unsigned int nc = FEInterface::n_dofs_at_node (dim, fe_type, elem_type, n);
    if (!_current_elem->is_vertex(n))
    {
      current_dof += nc;
      continue;
    }
    if (cont == DISCONTINUOUS)
    {
      libmesh_assert(nc == 0);
    }
    // Assume that C_ZERO elements have a single nodal
    // value shape function
    else if (cont == C_ZERO)
    {
      libmesh_assert(nc == 1);
      _qp = n;
      _current_node = _current_elem->get_node(n);
      Ue(current_dof) = value(*_current_node);
      dof_is_fixed[current_dof] = true;
      current_dof++;
    }
    // The hermite element vertex shape functions are weird
    else if (fe_type.family == HERMITE)
    {
      _qp = n;
      _current_node = _current_elem->get_node(n);
      Ue(current_dof) = value(*_current_node);
      dof_is_fixed[current_dof] = true;
      current_dof++;
      Gradient grad = gradient(*_current_node);
      // x derivative
      Ue(current_dof) = grad(0);
      dof_is_fixed[current_dof] = true;
      current_dof++;
      if (dim > 1)
      {
        // We'll finite difference mixed derivatives
        Point nxminus = _current_elem->point(n),
              nxplus = _current_elem->point(n);
        nxminus(0) -= TOLERANCE;
        nxplus(0) += TOLERANCE;
        Gradient gxminus = gradient(nxminus);
        Gradient gxplus = gradient(nxplus);
        // y derivative
        Ue(current_dof) = grad(1);
        dof_is_fixed[current_dof] = true;
        current_dof++;
        // xy derivative
        Ue(current_dof) = (gxplus(1) - gxminus(1)) / 2. / TOLERANCE;
        dof_is_fixed[current_dof] = true;
        current_dof++;

        if (dim > 2)
        {
          // z derivative
          Ue(current_dof) = grad(2);
          dof_is_fixed[current_dof] = true;
          current_dof++;
          // xz derivative
          Ue(current_dof) = (gxplus(2) - gxminus(2)) / 2. / TOLERANCE;
          dof_is_fixed[current_dof] = true;
          current_dof++;
          // We need new points for yz
          Point nyminus = _current_elem->point(n),
                nyplus = _current_elem->point(n);
          nyminus(1) -= TOLERANCE;
          nyplus(1) += TOLERANCE;
          Gradient gyminus = gradient(nyminus);
          Gradient gyplus = gradient(nyplus);
          // xz derivative
          Ue(current_dof) = (gyplus(2) - gyminus(2)) / 2. / TOLERANCE;
          dof_is_fixed[current_dof] = true;
          current_dof++;
          // Getting a 2nd order xyz is more tedious
          Point nxmym = _current_elem->point(n),
                nxmyp = _current_elem->point(n),
                nxpym = _current_elem->point(n),
                nxpyp = _current_elem->point(n);
          nxmym(0) -= TOLERANCE;
          nxmym(1) -= TOLERANCE;
          nxmyp(0) -= TOLERANCE;
          nxmyp(1) += TOLERANCE;
          nxpym(0) += TOLERANCE;
          nxpym(1) -= TOLERANCE;
          nxpyp(0) += TOLERANCE;
          nxpyp(1) += TOLERANCE;
          Gradient gxmym = gradient(nxmym);
          Gradient gxmyp = gradient(nxmyp);
          Gradient gxpym = gradient(nxpym);
          Gradient gxpyp = gradient(nxpyp);
          Number gxzplus = (gxpyp(2) - gxmyp(2)) / 2. / TOLERANCE;
          Number gxzminus = (gxpym(2) - gxmym(2)) / 2. / TOLERANCE;
          // xyz derivative
          Ue(current_dof) = (gxzplus - gxzminus) / 2. / TOLERANCE;
          dof_is_fixed[current_dof] = true;
          current_dof++;
        }
      }
    }
    // Assume that other C_ONE elements have a single nodal
    // value shape function and nodal gradient component
    // shape functions
    else if (cont == C_ONE)
    {
      libmesh_assert(nc == 1 + dim);
      _current_node = _current_elem->get_node(n);
      Ue(current_dof) = value(*_current_node);
      dof_is_fixed[current_dof] = true;
      current_dof++;
      Gradient grad = gradient(*_current_node);
      for (unsigned int i=0; i != dim; ++i)
      {
        Ue(current_dof) = grad(i);
        dof_is_fixed[current_dof] = true;
        current_dof++;
      }
    }
    else
      libmesh_error();
  } // loop over nodes

  // From here on out we won't be sampling at nodes anymore
  _current_node = NULL;

  // In 3D, project any edge values next
  if (dim > 2 && cont != DISCONTINUOUS)
    for (unsigned int e=0; e != _current_elem->n_edges(); ++e)
    {
      FEInterface::dofs_on_edge(_current_elem, dim, fe_type, e, side_dofs);

      // Some edge dofs are on nodes and already
      // fixed, others are free to calculate
      unsigned int free_dofs = 0;
      for (unsigned int i=0; i != side_dofs.size(); ++i)
        if (!dof_is_fixed[side_dofs[i]])
          free_dof[free_dofs++] = i;

      // There may be nothing to project
      if (!free_dofs)
        continue;

      Ke.resize (free_dofs, free_dofs); Ke.zero();
      Fe.resize (free_dofs); Fe.zero();
      // The new edge coefficients
      DenseVector<Number> Uedge(free_dofs);

      // Initialize FE data on the edge
      fe->attach_quadrature_rule (qedgerule.get());
      fe->edge_reinit (_current_elem, e);
      const unsigned int n_qp = qedgerule->n_points();

      // Loop over the quadrature points
      for (unsigned int qp = 0; qp < n_qp; qp++)
      {
        // solution at the quadrature point
        Number fineval = value(xyz_values[qp]);
        // solution grad at the quadrature point
        Gradient finegrad;
        if (cont == C_ONE)
          finegrad = gradient(xyz_values[qp]);

        // Form edge projection matrix
        for (unsigned int sidei = 0, freei = 0; sidei != side_dofs.size(); ++sidei)
        {
          unsigned int i = side_dofs[sidei];
          // fixed DoFs aren't test functions
          if (dof_is_fixed[i])
            continue;
          for (unsigned int sidej = 0, freej = 0; sidej != side_dofs.size(); ++sidej)
          {
            unsigned int j = side_dofs[sidej];
            if (dof_is_fixed[j])
              Fe(freei) -= phi[i][qp] * phi[j][qp] * JxW[qp] * Ue(j);
            else
              Ke(freei,freej) += phi[i][qp] * phi[j][qp] * JxW[qp];
            if (cont == C_ONE)
            {
              if (dof_is_fixed[j])
                Fe(freei) -= ((*dphi)[i][qp] * (*dphi)[j][qp]) * JxW[qp] * Ue(j);
              else
                Ke(freei,freej) += ((*dphi)[i][qp] * (*dphi)[j][qp]) * JxW[qp];
            }
            if (!dof_is_fixed[j])
              freej++;
          }
          Fe(freei) += phi[i][qp] * fineval * JxW[qp];
          if (cont == C_ONE)
            Fe(freei) += (finegrad * (*dphi)[i][qp]) * JxW[qp];
          freei++;
        }
      }

      Ke.cholesky_solve(Fe, Uedge);

      // Transfer new edge solutions to element
      for (unsigned int i=0; i != free_dofs; ++i)
      {
        Number &ui = Ue(side_dofs[free_dof[i]]);
        libmesh_assert(std::abs(ui) < TOLERANCE || std::abs(ui - Uedge(i)) < TOLERANCE);
        ui = Uedge(i);
        dof_is_fixed[side_dofs[free_dof[i]]] = true;
      }
    }

  // Project any side values (edges in 2D, faces in 3D)
  if (dim > 1 && cont != DISCONTINUOUS)
    for (unsigned int s=0; s != _current_elem->n_sides(); ++s)
    {
      FEInterface::dofs_on_side(_current_elem, dim, fe_type, s, side_dofs);

      // Some side dofs are on nodes/edges and already
      // fixed, others are free to calculate
      unsigned int free_dofs = 0;
      for (unsigned int i=0; i != side_dofs.size(); ++i)
        if (!dof_is_fixed[side_dofs[i]])
          free_dof[free_dofs++] = i;

      // There may be nothing to project
      if (!free_dofs)
        continue;

      Ke.resize (free_dofs, free_dofs); Ke.zero();
      Fe.resize (free_dofs); Fe.zero();
      // The new side coefficients
      DenseVector<Number> Uside(free_dofs);

      // Initialize FE data on the side
      fe->attach_quadrature_rule (qsiderule.get());
      fe->reinit (_current_elem, s);
      const unsigned int n_qp = qsiderule->n_points();

      // Loop over the quadrature points
      for (unsigned int qp = 0; qp < n_qp; qp++)
      {
        // solution at the quadrature point
        Number fineval = value(xyz_values[qp]);
        // solution grad at the quadrature point
        Gradient finegrad;
        if (cont == C_ONE)
          finegrad = gradient(xyz_values[qp]);

        // Form side projection matrix
        for (unsigned int sidei = 0, freei = 0; sidei != side_dofs.size(); ++sidei)
        {
          unsigned int i = side_dofs[sidei];
          // fixed DoFs aren't test functions
          if (dof_is_fixed[i])
            continue;
          for (unsigned int sidej = 0, freej = 0; sidej != side_dofs.size(); ++sidej)
          {
            unsigned int j = side_dofs[sidej];
            if (dof_is_fixed[j])
              Fe(freei) -= phi[i][qp] * phi[j][qp] * JxW[qp] * Ue(j);
            else
              Ke(freei,freej) += phi[i][qp] * phi[j][qp] * JxW[qp];
            if (cont == C_ONE)
            {
              if (dof_is_fixed[j])
                Fe(freei) -= ((*dphi)[i][qp] * (*dphi)[j][qp]) * JxW[qp] * Ue(j);
              else
                Ke(freei,freej) += ((*dphi)[i][qp] * (*dphi)[j][qp]) * JxW[qp];
            }
            if (!dof_is_fixed[j])
              freej++;
          }
          Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
          if (cont == C_ONE)
            Fe(freei) += (finegrad * (*dphi)[i][qp]) * JxW[qp];
          freei++;
        }
      }

      Ke.cholesky_solve(Fe, Uside);

      // Transfer new side solutions to element
      for (unsigned int i=0; i != free_dofs; ++i)
      {
        Number &ui = Ue(side_dofs[free_dof[i]]);
        libmesh_assert(std::abs(ui) < TOLERANCE || std::abs(ui - Uside(i)) < TOLERANCE);
        ui = Uside(i);
        dof_is_fixed[side_dofs[free_dof[i]]] = true;
      }
    }

  // Project the interior values, finally

  // Some interior dofs are on nodes/edges/sides and
  // already fixed, others are free to calculate
  unsigned int free_dofs = 0;
  for (unsigned int i=0; i != n_dofs; ++i)
    if (!dof_is_fixed[i])
      free_dof[free_dofs++] = i;

  // There may be nothing to project
  if (free_dofs)
  {
    Ke.resize (free_dofs, free_dofs); Ke.zero();
    Fe.resize (free_dofs); Fe.zero();
    // The new interior coefficients
    DenseVector<Number> Uint(free_dofs);

    // Initialize FE data
    fe->attach_quadrature_rule (qrule.get());
    fe->reinit (_current_elem);
    const unsigned int n_qp = qrule->n_points();

    // Loop over the quadrature points
    for (unsigned int qp=0; qp<n_qp; qp++)
    {
      // solution at the quadrature point
      Number fineval = value(xyz_values[qp]);
      // solution grad at the quadrature point
      Gradient finegrad;
      if (cont == C_ONE)
        finegrad = gradient(xyz_values[qp]);

      // Form interior projection matrix
      for (unsigned int i=0, freei=0; i != n_dofs; ++i)
      {
        // fixed DoFs aren't test functions
        if (dof_is_fixed[i])
          continue;
        for (unsigned int j=0, freej=0; j != n_dofs; ++j)
        {
          if (dof_is_fixed[j])
            Fe(freei) -= phi[i][qp] * phi[j][qp] * JxW[qp] * Ue(j);
          else
            Ke(freei,freej) += phi[i][qp] * phi[j][qp] * JxW[qp];
          if (cont == C_ONE)
          {
            if (dof_is_fixed[j])
              Fe(freei) -= ((*dphi)[i][qp] * (*dphi)[j][qp]) * JxW[qp] * Ue(j);
            else
              Ke(freei,freej) += ((*dphi)[i][qp] * (*dphi)[j][qp]) * JxW[qp];
          }
          if (!dof_is_fixed[j])
            freej++;
        }
        Fe(freei) += phi[i][qp] * fineval * JxW[qp];
        if (cont == C_ONE)
          Fe(freei) += (finegrad * (*dphi)[i][qp]) * JxW[qp];
        freei++;
      }
    }
    Ke.cholesky_solve(Fe, Uint);

    // Transfer new interior solutions to element
    for (unsigned int i=0; i != free_dofs; ++i)
    {
      Number &ui = Ue(free_dof[i]);
      libmesh_assert(std::abs(ui) < TOLERANCE || std::abs(ui - Uint(i)) < TOLERANCE);
      ui = Uint(i);
      dof_is_fixed[free_dof[i]] = true;
    }
  } // if there are free interior dofs

  // Make sure every DoF got reached!
  for (unsigned int i=0; i != n_dofs; ++i)
    libmesh_assert(dof_is_fixed[i]);

  NumericVector<Number> & solution = _var.sys().solution();

  // 'first' and 'last' are no longer used, see note about subdomain-restricted variables below
  // const dof_id_type
  //   first = solution.first_local_index(),
  //   last  = solution.last_local_index();

  // Lock the new_vector since it is shared among threads.
  {
    Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);

    for (unsigned int i = 0; i < n_dofs; i++)
      // We may be projecting a new zero value onto
      // an old nonzero approximation - RHS
      // if (Ue(i) != 0.)

      // This is commented out because of subdomain restricted variables.
      // It can be the case that if a subdomain restricted variable's boundary
      // aligns perfectly with a processor boundary that the variable will get
      // no value.  To counteract this we're going to let every processor set a
      // value at every node and then let PETSc figure it out.
      // Later we can choose to do something different / better.
//      if ((dof_indices[i] >= first) && (dof_indices[i] < last))
      {
        solution.set(dof_indices[i], Ue(i));
      }
    _var.setNodalValue(Ue);
  }
}
void DenseMatrix<T>::_svd_helper (char JOBU,
                                  char JOBVT,
                                  std::vector<T>& sigma_val,
                                  std::vector<T>& U_val,
                                  std::vector<T>& VT_val)
{

  //    M       (input) int*
  //            The number of rows of the matrix A.  M >= 0.
  // In C/C++, pass the number of *cols* of A
  int M = this->n();

  //    N       (input) int*
  //            The number of columns of the matrix A.  N >= 0.
  // In C/C++, pass the number of *rows* of A
  int N = this->m();

  int min_MN = (M < N) ? M : N;
  int max_MN = (M > N) ? M : N;

  //  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
  //          On entry, the M-by-N matrix A.
  //          On exit,
  //          if JOBU = 'O',  A is overwritten with the first min(m,n)
  //                          columns of U (the left singular vectors,
  //                          stored columnwise);
  //          if JOBVT = 'O', A is overwritten with the first min(m,n)
  //                          rows of V**T (the right singular vectors,
  //                          stored rowwise);
  //          if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A
  //                          are destroyed.
  // Here, we pass &(_val[0]).

  //    LDA     (input) int*
  //            The leading dimension of the array A.  LDA >= max(1,M).
  int LDA = M;

  //  S       (output) DOUBLE PRECISION array, dimension (min(M,N))
  //          The singular values of A, sorted so that S(i) >= S(i+1).
  sigma_val.resize( min_MN );

  //  LDU     (input) INTEGER
  //          The leading dimension of the array U.  LDU >= 1; if
  //          JOBU = 'S' or 'A', LDU >= M.
  int LDU = M;

  //  U       (output) DOUBLE PRECISION array, dimension (LDU,UCOL)
  //          (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'.
  //          If JOBU = 'A', U contains the M-by-M orthogonal matrix U;
  //          if JOBU = 'S', U contains the first min(m,n) columns of U
  //          (the left singular vectors, stored columnwise);
  //          if JOBU = 'N' or 'O', U is not referenced.
  U_val.resize( LDU*M );

  //  LDVT    (input) INTEGER
  //          The leading dimension of the array VT.  LDVT >= 1; if
  //          JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N).
  int LDVT = N;

  //  VT      (output) DOUBLE PRECISION array, dimension (LDVT,N)
  //          If JOBVT = 'A', VT contains the N-by-N orthogonal matrix
  //          V**T;
  //          if JOBVT = 'S', VT contains the first min(m,n) rows of
  //          V**T (the right singular vectors, stored rowwise);
  //          if JOBVT = 'N' or 'O', VT is not referenced.
  VT_val.resize( LDVT*N );

  //  LWORK   (input) INTEGER
  //          The dimension of the array WORK.
  //          LWORK >= MAX(1,3*MIN(M,N)+MAX(M,N),5*MIN(M,N)).
  //          For good performance, LWORK should generally be larger.
  //
  //          If LWORK = -1, then a workspace query is assumed; the routine
  //          only calculates the optimal size of the WORK array, returns
  //          this value as the first entry of the WORK array, and no error
  //          message related to LWORK is issued by XERBLA.
  int larger = (3*min_MN+max_MN > 5*min_MN) ? 3*min_MN+max_MN : 5*min_MN;
  int LWORK  = (larger > 1) ? larger : 1;


  //  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
  //          On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
  //          if INFO > 0, WORK(2:MIN(M,N)) contains the unconverged
  //          superdiagonal elements of an upper bidiagonal matrix B
  //          whose diagonal is in S (not necessarily sorted). B
  //          satisfies A = U * B * VT, so it has the same singular values
  //          as A, and singular vectors related by U and VT.
  std::vector<T> WORK( LWORK );

  //  INFO    (output) INTEGER
  //          = 0:  successful exit.
  //          < 0:  if INFO = -i, the i-th argument had an illegal value.
  //          > 0:  if DBDSQR did not converge, INFO specifies how many
  //                superdiagonals of an intermediate bidiagonal form B
  //                did not converge to zero. See the description of WORK
  //                above for details.
  int INFO = 0;

  // Ready to call the actual factorization routine through PETSc's interface
  LAPACKgesvd_(&JOBU, &JOBVT, &M, &N, &(_val[0]), &LDA, &(sigma_val[0]), &(U_val[0]),
               &LDU, &(VT_val[0]), &LDVT, &(WORK[0]), &LWORK, &INFO);

  // Check return value for errors
  if (INFO != 0)
    {
      libMesh::out << "INFO="
		    << INFO
		    << ", Error during Lapack SVD calculation!" << std::endl;
      libmesh_error();
    }
}
void DenseMatrix<T>::_lu_back_substitute_lapack (const DenseVector<T>& ,
						 DenseVector<T>& )
{
  libMesh::err << "No PETSc-provided BLAS/LAPACK available!" << std::endl;
  libmesh_error();
}
Beispiel #8
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   = 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  = 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();
    }


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

}
Beispiel #9
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();
      }
    }



  // Stop logging the overall computation of shape functions
  STOP_LOG("compute_shape_functions()", "InfFE");

}
Beispiel #10
0
std::string ElementTypes::basic_name (const ElemType t)
{
  std::string its_name;
  switch (t)
    {
    case EDGE2:
    case EDGE3:
    case EDGE4:
      {
	its_name = "Edge";
	break;
      }

    case TRI3:
    case TRI6:
      {
	its_name = "Triangle";
	break;
      }

    case QUAD4:
    case QUAD8:
    case QUAD9:
      {
	its_name = "Quadrilateral";
	break;
      }

    case TET4:
    case TET10:
      {
	its_name = "Tetrahedron";
	break;
      }

    case HEX8:
    case HEX20:
    case HEX27:
      {
	its_name = "Hexahedron";
	break;
      }

    case PRISM6:
    case PRISM18:
      {
	its_name = "Prism";
	break;
      }

    case PYRAMID5:
    case PYRAMID14:
      {
	its_name = "Pyramid";
	break;
      }



#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS

    // infinite elements
    case INFEDGE2:
      {
	its_name = "Infinite Edge";
	break;
      }

    case INFQUAD4:
    case INFQUAD6:
      {
	its_name = "Infinite Quadrilateral";
	break;
      }

    case INFHEX8:
    case INFHEX16:
    case INFHEX18:
      {
 	its_name = "Infinite Hexahedron";
	break;
      }

    case INFPRISM6:
    case INFPRISM12:
      {
	its_name = "Infinite Prism";
	break;
      }

#endif


    default:
      {
	libMesh::out << "Undefined element type!." << std::endl;
	libmesh_error();
      }
    }
  return its_name;
}
Beispiel #11
0
void PointLocatorTree::init (const Trees::BuildType build_type)
{
  libmesh_assert (!this->_tree);

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

  else

    {

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

          if (this->_mesh.mesh_dimension() == 3)
            _tree = new Trees::OctTree (this->_mesh, 200, build_type);
          else
            {
              // A 1D/2D mesh in 3D space needs special consideration.
              // If the mesh is planar XY, we want to build a QuadTree
              // to search efficiently.  If the mesh is truly a manifold,
              // then we need an octree
#if LIBMESH_DIM > 2
              bool is_planar_xy = false;

              // Build the bounding box for the mesh.  If the delta-z bound is
              // negligibly small then we can use a quadtree.
              {
                MeshTools::BoundingBox bbox = MeshTools::bounding_box(this->_mesh);

                const Real
                  Dx = bbox.second(0) - bbox.first(0),
                  Dz = bbox.second(2) - bbox.first(2);

                if (std::abs(Dz/(Dx + 1.e-20)) < 1e-10)
                  is_planar_xy = true;
              }

              if (!is_planar_xy)
                _tree = new Trees::OctTree (this->_mesh, 200, build_type);
              else
#endif
#if LIBMESH_DIM > 1
                _tree = new Trees::QuadTree (this->_mesh, 200, build_type);
#else
              _tree = new Trees::BinaryTree (this->_mesh, 200, build_type);
#endif
            }

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

      else

        {
          // We are _not_ the master.  Let our Tree point to
          // the master's tree.  But for this we first transform
          // the master in a state for which we are friends.
          // And make sure the master @e has a tree!
          const PointLocatorTree* my_master =
            libmesh_cast_ptr<const PointLocatorTree*>(this->_master);

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


      // Not all PointLocators may own a tree, but all of them
      // use their own element pointer.  Let the element pointer
      // be unique for every interpolator.
      // Suppose the interpolators are used concurrently
      // at different locations in the mesh, then it makes quite
      // sense to have unique start elements.
      this->_element = NULL;
    }


  // ready for take-off
  this->_initialized = true;
}
Beispiel #12
0
std::string ElementTypes::name(const ElemType t)
{
  std::string its_name;
  switch (t)
    {
    case EDGE2:
      {
	its_name = "Edge 2";
	break;
      }

    case EDGE3:
      {
	its_name = "Edge 3";
	break;
      }

    case EDGE4:
      {
	its_name = "Edge 4";
	break;
      }

    case TRI3:
      {
	its_name = "Tri 3";
	break;
      }

    case TRI6:
      {
	its_name = "Tri 6";
	break;
      }

    case QUAD4:
      {
	its_name = "Quad 4";
	break;
      }

    case QUAD8:
      {
	its_name = "Quad 8";
	break;
      }

    case QUAD9:
      {
	its_name = "Quad 9";
	break;
      }

    case TET4:
      {
	its_name = "Tet 4";
	break;
      }

    case TET10:
      {
	its_name = "Tet 10";
	break;
      }

    case HEX8:
      {
	its_name = "Hex 8";
	break;
      }

    case HEX20:
      {
	its_name = "Hex 20";
	break;
      }

    case HEX27:
      {
	its_name = "Hex 27";
	break;
      }

    case PRISM6:
      {
	its_name = "Prism 6";
	break;
      }

    case PRISM18:
      {
	its_name = "Prism 8";
	break;
      }

    case PYRAMID5:
      {
	its_name = "Pyramid 5";
	break;
      }

    case PYRAMID14:
      {
	its_name = "Pyramid 14";
	break;
      }



#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS

    case INFEDGE2:
      {
	its_name = "Infinite Edge 2";
	break;
      }

    case INFQUAD4:
      {
	its_name = "Infinite Quad 4";
	break;
      }

    case INFQUAD6:
      {
	its_name = "Infinite Quad 6";
	break;
      }

    case INFHEX8:
      {
 	its_name = "Infinite Hex 8";
	break;
      }

    case INFHEX16:
      {
 	its_name = "Infinite Hex 16";
	break;
      }

    case INFHEX18:
      {
 	its_name = "Infinite Hex 18";
	break;
      }

    case INFPRISM6:
      {
	its_name = "Infinite Prism 6";
	break;
      }

    case INFPRISM12:
      {
	its_name = "Infinite Prism 12";
	break;
      }

#endif



    default:
      {
	libMesh::err << "Undefined element type!." << std::endl;
	libmesh_error();
      }
    }
  return its_name;
}
void
InitialConditionTempl<T>::compute()
{
  // -- NOTE ----
  // The following code is a copy from libMesh project_vector.C plus it adds some features, so we
  // can couple variable values
  // and we also do not call any callbacks, but we use our initial condition system directly.
  // ------------

  // The dimension of the current element
  _dim = _current_elem->dim();
  // The element type
  const ElemType elem_type = _current_elem->type();
  // The number of nodes on the new element
  const unsigned int n_nodes = _current_elem->n_nodes();

  // Get FE objects of the appropriate type
  // We cannot use the FE object in Assembly, since the following code is messing with the
  // quadrature rules
  // for projections and would screw it up. However, if we implement projections from one mesh to
  // another,
  // this code should use that implementation.
  std::unique_ptr<FEBaseType> fe(FEBaseType::build(_dim, _fe_type));

  // Prepare variables for projection
  std::unique_ptr<QBase> qrule(_fe_type.default_quadrature_rule(_dim));
  std::unique_ptr<QBase> qedgerule(_fe_type.default_quadrature_rule(1));
  std::unique_ptr<QBase> qsiderule(_fe_type.default_quadrature_rule(_dim - 1));

  // The values of the shape functions at the quadrature points
  _phi = &fe->get_phi();

  // The gradients of the shape functions at the quadrature points on the child element.
  _dphi = nullptr;

  _cont = fe->get_continuity();

  if (_cont == C_ONE)
  {
    const std::vector<std::vector<GradientType>> & ref_dphi = fe->get_dphi();
    _dphi = &ref_dphi;
  }

  // The Jacobian * quadrature weight at the quadrature points
  _JxW = &fe->get_JxW();
  // The XYZ locations of the quadrature points
  _xyz_values = &fe->get_xyz();

  // Update the DOF indices for this element based on the current mesh
  _var.prepareIC();
  _dof_indices = _var.dofIndices();

  // The number of DOFs on the element
  const unsigned int n_dofs = _dof_indices.size();
  if (n_dofs == 0)
    return;

  // Fixed vs. free DoFs on edge/face projections
  _dof_is_fixed.clear();
  _dof_is_fixed.resize(n_dofs, false);
  _free_dof.clear();
  _free_dof.resize(n_dofs, 0);

  // Zero the interpolated values
  _Ue.resize(n_dofs);
  _Ue.zero();

  // In general, we need a series of
  // projections to ensure a unique and continuous
  // solution.  We start by interpolating nodes, then
  // hold those fixed and project edges, then
  // hold those fixed and project faces, then
  // hold those fixed and project interiors

  // Interpolate node values first
  _current_dof = 0;
  for (_n = 0; _n != n_nodes; ++_n)
  {
    // FIXME: this should go through the DofMap,
    // not duplicate _dof_indices code badly!
    _nc = FEInterface::n_dofs_at_node(_dim, _fe_type, elem_type, _n);
    if (!_current_elem->is_vertex(_n))
    {
      _current_dof += _nc;
      continue;
    }
    if (_cont == DISCONTINUOUS)
      libmesh_assert(_nc == 0);
    else if (_cont == C_ZERO)
      setCZeroVertices();
    else if (_fe_type.family == HERMITE)
      setHermiteVertices();
    else if (_cont == C_ONE)
      setOtherCOneVertices();
    else
      libmesh_error();
  } // loop over nodes

  // From here on out we won't be sampling at nodes anymore
  _current_node = nullptr;

  // In 3D, project any edge values next
  if (_dim > 2 && _cont != DISCONTINUOUS)
    for (unsigned int e = 0; e != _current_elem->n_edges(); ++e)
    {
      FEInterface::dofs_on_edge(_current_elem, _dim, _fe_type, e, _side_dofs);

      // Some edge dofs are on nodes and already
      // fixed, others are free to calculate
      _free_dofs = 0;
      for (unsigned int i = 0; i != _side_dofs.size(); ++i)
        if (!_dof_is_fixed[_side_dofs[i]])
          _free_dof[_free_dofs++] = i;

      // There may be nothing to project
      if (!_free_dofs)
        continue;

      // Initialize FE data on the edge
      fe->attach_quadrature_rule(qedgerule.get());
      fe->edge_reinit(_current_elem, e);
      _n_qp = qedgerule->n_points();

      choleskySolve(false);
    }

  // Project any side values (edges in 2D, faces in 3D)
  if (_dim > 1 && _cont != DISCONTINUOUS)
    for (unsigned int s = 0; s != _current_elem->n_sides(); ++s)
    {
      FEInterface::dofs_on_side(_current_elem, _dim, _fe_type, s, _side_dofs);

      // Some side dofs are on nodes/edges and already
      // fixed, others are free to calculate
      _free_dofs = 0;
      for (unsigned int i = 0; i != _side_dofs.size(); ++i)
        if (!_dof_is_fixed[_side_dofs[i]])
          _free_dof[_free_dofs++] = i;

      // There may be nothing to project
      if (!_free_dofs)
        continue;

      // Initialize FE data on the side
      fe->attach_quadrature_rule(qsiderule.get());
      fe->reinit(_current_elem, s);
      _n_qp = qsiderule->n_points();

      choleskySolve(false);
    }

  // Project the interior values, finally

  // Some interior dofs are on nodes/edges/sides and
  // already fixed, others are free to calculate
  _free_dofs = 0;
  for (unsigned int i = 0; i != n_dofs; ++i)
    if (!_dof_is_fixed[i])
      _free_dof[_free_dofs++] = i;

  // There may be nothing to project
  if (_free_dofs)
  {
    // Initialize FE data
    fe->attach_quadrature_rule(qrule.get());
    fe->reinit(_current_elem);
    _n_qp = qrule->n_points();

    choleskySolve(true);
  } // if there are free interior dofs

  // Make sure every DoF got reached!
  for (unsigned int i = 0; i != n_dofs; ++i)
    libmesh_assert(_dof_is_fixed[i]);

  NumericVector<Number> & solution = _var.sys().solution();

  // 'first' and 'last' are no longer used, see note about subdomain-restricted variables below
  // const dof_id_type
  //   first = solution.first_local_index(),
  //   last  = solution.last_local_index();

  // Lock the new_vector since it is shared among threads.
  {
    Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);

    for (unsigned int i = 0; i < n_dofs; i++)
    // We may be projecting a new zero value onto
    // an old nonzero approximation - RHS
    // if (_Ue(i) != 0.)

    // This is commented out because of subdomain restricted variables.
    // It can be the case that if a subdomain restricted variable's boundary
    // aligns perfectly with a processor boundary that the variable will get
    // no value.  To counteract this we're going to let every processor set a
    // value at every node and then let PETSc figure it out.
    // Later we can choose to do something different / better.
    //      if ((_dof_indices[i] >= first) && (_dof_indices[i] < last))
    {
      solution.set(_dof_indices[i], _Ue(i));
    }
    _var.setDofValues(_Ue);
  }
}
Beispiel #14
0
Real FE<3,MONOMIAL>::shape_second_deriv(const ElemType,
				        const Order libmesh_dbg_var(order),
				        const unsigned int i,
				        const unsigned int j,
				        const Point& p)
{
#if LIBMESH_DIM == 3

  libmesh_assert_less (j, 6);

  libmesh_assert_less (i, (static_cast<unsigned int>(order)+1)*
              (static_cast<unsigned int>(order)+2)*
              (static_cast<unsigned int>(order)+3)/6);

  const Real xi   = p(0);
  const Real eta  = p(1);
  const Real zeta = p(2);

    // monomials. since they are hierarchic we only need one case block.
  switch (j)
    {
      // d^2()/dxi^2
    case 0:
      {
        switch (i)
  	{
  	  // constant
  	case 0:

  	  // linear
  	case 1:
  	case 2:
  	case 3:
  	  return 0.;

  	  // quadratic
  	case 4:
  	  return 2.;

  	case 5:
  	case 6:
  	case 7:
  	case 8:
  	case 9:
  	  return 0.;

  	  // cubic
  	case 10:
  	  return 6.*xi;

  	case 11:
  	  return 2.*eta;

  	case 12:
  	case 13:
  	  return 0.;

  	case 14:
  	  return 2.*zeta;

  	case 15:
  	case 16:
  	case 17:
  	case 18:
  	case 19:
  	  return 0.;

  	  // quartics
  	case 20:
  	  return 12.*xi*xi;

  	case 21:
  	  return 6.*xi*eta;

  	case 22:
  	  return 2.*eta*eta;

  	case 23:
  	case 24:
  	  return 0.;

  	case 25:
  	  return 6.*xi*zeta;

  	case 26:
  	  return 2.*eta*zeta;

  	case 27:
  	case 28:
  	  return 0.;

  	case 29:
  	  return 2.*zeta*zeta;

  	case 30:
  	case 31:
  	case 32:
  	case 33:
  	case 34:
  	  return 0.;

  	default:
          unsigned int o = 0;
          for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
          unsigned int i2 = i - (o*(o+1)*(o+2)/6);
          unsigned int block=o, nz = 0;
          for (; block < i2; block += (o-nz+1)) { nz++; }
          const unsigned int nx = block - i2;
          const unsigned int ny = o - nx - nz;
          Real val = nx * (nx - 1);
          for (unsigned int index=2; index < nx; index++)
            val *= xi;
          for (unsigned int index=0; index != ny; index++)
            val *= eta;
          for (unsigned int index=0; index != nz; index++)
            val *= zeta;
          return val;
  	}
      }


      // d^2()/dxideta
    case 1:
      {
        switch (i)
  	{
  	  // constant
  	case 0:

  	  // linear
  	case 1:
  	case 2:
  	case 3:
  	  return 0.;

  	  // quadratic
  	case 4:
  	  return 0.;

  	case 5:
  	  return 1.;

  	case 6:
  	case 7:
  	case 8:
  	case 9:
  	  return 0.;

  	  // cubic
  	case 10:
  	  return 0.;

  	case 11:
  	  return 2.*xi;

  	case 12:
  	  return 2.*eta;

  	case 13:
  	case 14:
  	  return 0.;

  	case 15:
  	  return zeta;

  	case 16:
  	case 17:
  	case 18:
  	case 19:
  	  return 0.;

  	  // quartics
  	case 20:
  	  return 0.;

  	case 21:
  	  return 3.*xi*xi;

  	case 22:
  	  return 4.*xi*eta;

  	case 23:
  	  return 3.*eta*eta;

  	case 24:
  	case 25:
  	  return 0.;

  	case 26:
  	  return 2.*xi*zeta;

  	case 27:
  	  return 2.*eta*zeta;

  	case 28:
  	case 29:
  	  return 0.;

  	case 30:
  	  return zeta*zeta;

  	case 31:
  	case 32:
  	case 33:
  	case 34:
  	  return 0.;

  	default:
          unsigned int o = 0;
          for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
          unsigned int i2 = i - (o*(o+1)*(o+2)/6);
          unsigned int block=o, nz = 0;
          for (; block < i2; block += (o-nz+1)) { nz++; }
          const unsigned int nx = block - i2;
          const unsigned int ny = o - nx - nz;
          Real val = nx * ny;
          for (unsigned int index=1; index < nx; index++)
            val *= xi;
          for (unsigned int index=1; index < ny; index++)
            val *= eta;
          for (unsigned int index=0; index != nz; index++)
            val *= zeta;
          return val;
  	}
      }


      // d^2()/deta^2
    case 2:
      {
        switch (i)
  	{
  	  // constant
  	case 0:

  	  // linear
  	case 1:
  	case 2:
  	case 3:
  	  return 0.;

  	  // quadratic
  	case 4:
  	case 5:
  	  return 0.;

  	case 6:
  	  return 2.;

  	case 7:
  	case 8:
  	case 9:
  	  return 0.;

  	  // cubic
  	case 10:
  	case 11:
  	  return 0.;

  	case 12:
  	  return 2.*xi;
  	case 13:
  	  return 6.*eta;

  	case 14:
  	case 15:
  	  return 0.;

  	case 16:
  	  return 2.*zeta;

  	case 17:
  	case 18:
  	case 19:
  	  return 0.;

  	  // quartics
  	case 20:
  	case 21:
  	  return 0.;

  	case 22:
  	  return 2.*xi*xi;

  	case 23:
  	  return 6.*xi*eta;

  	case 24:
  	  return 12.*eta*eta;

  	case 25:
  	case 26:
  	  return 0.;

  	case 27:
  	  return 2.*xi*zeta;

  	case 28:
  	  return 6.*eta*zeta;

  	case 29:
  	case 30:
  	  return 0.;

  	case 31:
  	  return 2.*zeta*zeta;

  	case 32:
  	case 33:
  	case 34:
  	  return 0.;

  	default:
          unsigned int o = 0;
          for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
          unsigned int i2 = i - (o*(o+1)*(o+2)/6);
          unsigned int block=o, nz = 0;
          for (; block < i2; block += (o-nz+1)) { nz++; }
          const unsigned int nx = block - i2;
          const unsigned int ny = o - nx - nz;
          Real val = ny * (ny - 1);
          for (unsigned int index=0; index != nx; index++)
            val *= xi;
          for (unsigned int index=2; index < ny; index++)
            val *= eta;
          for (unsigned int index=0; index != nz; index++)
            val *= zeta;
          return val;
  	}
      }


      // d^2()/dxidzeta
    case 3:
      {
        switch (i)
  	{
  	  // constant
  	case 0:

  	  // linear
  	case 1:
  	case 2:
  	case 3:
  	  return 0.;

  	  // quadratic
  	case 4:
  	case 5:
  	case 6:
  	  return 0.;

  	case 7:
  	  return 1.;

  	case 8:
  	case 9:
  	  return 0.;

  	  // cubic
  	case 10:
  	case 11:
  	case 12:
  	case 13:
  	  return 0.;

  	case 14:
  	  return 2.*xi;

  	case 15:
  	  return eta;

  	case 16:
  	  return 0.;

  	case 17:
  	  return 2.*zeta;

  	case 18:
  	case 19:
  	  return 0.;

  	  // quartics
  	case 20:
  	case 21:
  	case 22:
  	case 23:
  	case 24:
  	  return 0.;

  	case 25:
  	  return 3.*xi*xi;

  	case 26:
  	  return 2.*xi*eta;

  	case 27:
  	  return eta*eta;

  	case 28:
  	  return 0.;

  	case 29:
  	  return 4.*xi*zeta;

  	case 30:
  	  return 2.*eta*zeta;

  	case 31:
  	  return 0.;

  	case 32:
  	  return 3.*zeta*zeta;

  	case 33:
  	case 34:
  	  return 0.;

  	default:
          unsigned int o = 0;
          for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
          unsigned int i2 = i - (o*(o+1)*(o+2)/6);
          unsigned int block=o, nz = 0;
          for (; block < i2; block += (o-nz+1)) { nz++; }
          const unsigned int nx = block - i2;
          const unsigned int ny = o - nx - nz;
          Real val = nx * nz;
          for (unsigned int index=1; index < nx; index++)
            val *= xi;
          for (unsigned int index=0; index != ny; index++)
            val *= eta;
          for (unsigned int index=1; index < nz; index++)
            val *= zeta;
          return val;
  	}
      }

      // d^2()/detadzeta
    case 4:
      {
        switch (i)
  	{
  	  // constant
  	case 0:

  	  // linear
  	case 1:
  	case 2:
  	case 3:
  	  return 0.;

  	  // quadratic
  	case 4:
  	case 5:
  	case 6:
  	case 7:
  	  return 0.;

  	case 8:
  	  return 1.;

  	case 9:
  	  return 0.;

  	  // cubic
  	case 10:
  	case 11:
  	case 12:
  	case 13:
  	case 14:
  	  return 0.;

  	case 15:
  	  return xi;

  	case 16:
  	  return 2.*eta;

  	case 17:
  	  return 0.;

  	case 18:
  	  return 2.*zeta;

  	case 19:
  	  return 0.;

  	  // quartics
  	case 20:
  	case 21:
  	case 22:
  	case 23:
  	case 24:
  	case 25:
  	  return 0.;

  	case 26:
  	  return xi*xi;

  	case 27:
  	  return 2.*xi*eta;

  	case 28:
  	  return 3.*eta*eta;

  	case 29:
  	  return 0.;

  	case 30:
  	  return 2.*xi*zeta;

  	case 31:
  	  return 4.*eta*zeta;

  	case 32:
  	  return 0.;

  	case 33:
  	  return 3.*zeta*zeta;

  	case 34:
  	  return 0.;

  	default:
          unsigned int o = 0;
          for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
          unsigned int i2 = i - (o*(o+1)*(o+2)/6);
          unsigned int block=o, nz = 0;
          for (; block < i2; block += (o-nz+1)) { nz++; }
          const unsigned int nx = block - i2;
          const unsigned int ny = o - nx - nz;
          Real val = ny * nz;
          for (unsigned int index=0; index != nx; index++)
            val *= xi;
          for (unsigned int index=1; index < ny; index++)
            val *= eta;
          for (unsigned int index=1; index < nz; index++)
            val *= zeta;
          return val;
  	}
      }


      // d^2()/dzeta^2
    case 5:
      {
        switch (i)
  	{
  	  // constant
  	case 0:

  	  // linear
  	case 1:
  	case 2:
  	case 3:
  	  return 0.;

  	  // quadratic
  	case 4:
  	case 5:
  	case 6:
  	case 7:
  	case 8:
  	  return 0.;

  	case 9:
  	  return 2.;

  	  // cubic
  	case 10:
  	case 11:
  	case 12:
  	case 13:
  	case 14:
  	case 15:
  	case 16:
  	  return 0.;

  	case 17:
  	  return 2.*xi;

  	case 18:
  	  return 2.*eta;

  	case 19:
  	  return 6.*zeta;

  	  // quartics
  	case 20:
  	case 21:
  	case 22:
  	case 23:
  	case 24:
  	case 25:
  	case 26:
  	case 27:
  	case 28:
  	  return 0.;

  	case 29:
  	  return 2.*xi*xi;

  	case 30:
  	  return 2.*xi*eta;

  	case 31:
  	  return 2.*eta*eta;

  	case 32:
  	  return 6.*xi*zeta;

  	case 33:
  	  return 6.*eta*zeta;

  	case 34:
  	  return 12.*zeta*zeta;

  	default:
          unsigned int o = 0;
          for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
          unsigned int i2 = i - (o*(o+1)*(o+2)/6);
          unsigned int block=o, nz = 0;
          for (; block < i2; block += (o-nz+1)) { nz++; }
          const unsigned int nx = block - i2;
          const unsigned int ny = o - nx - nz;
          Real val = nz * (nz - 1);
          for (unsigned int index=0; index != nx; index++)
            val *= xi;
          for (unsigned int index=0; index != ny; index++)
            val *= eta;
          for (unsigned int index=2; index < nz; index++)
            val *= zeta;
          return val;
  	}
      }


    default:
      libmesh_error();
    }

#endif

  libmesh_error();
  return 0.;
}
void DenseMatrix<T>::_lu_decompose_lapack ()
{
  libMesh::err << "No PETSc-provided BLAS/LAPACK available!" << std::endl;
  libmesh_error();
}
Beispiel #16
0
Real FE<1,XYZ>::shape(const Elem* elem,
		      const Order libmesh_dbg_var(order),
		      const unsigned int i,
		      const Point& p)
{
  libmesh_assert(elem);
  libmesh_assert_less_equal (i, order + elem->p_level());

  // Only recompute the centroid if the element
  // has changed from the last one we computed.
  // This avoids repeated centroid calculations
  // when called in succession with the same element.
  if (elem->id() != old_elem_id)
    {
      centroid = elem->centroid();
      old_elem_id = elem->id();
      max_distance = 0.;
      for (unsigned int p = 0; p < elem->n_nodes(); p++)
      {
        const Real distance = std::abs(centroid(0) - elem->point(p)(0));
        max_distance = std::max(distance, max_distance);
      }
    }

  // Using static globals for old_elem_id, etc. will fail
  // horribly with more than one thread.
  libmesh_assert_equal_to (libMesh::n_threads(), 1);

  const Real x  = p(0);
  const Real xc = centroid(0);
  const Real dx = (x - xc)/max_distance;

  // monomials. since they are hierarchic we only need one case block.
  switch (i)
    {
    case 0:
      return 1.;

    case 1:
      return dx;

    case 2:
      return dx*dx;

    case 3:
      return dx*dx*dx;

    case 4:
      return dx*dx*dx*dx;

    default:
      Real val = 1.;
      for (unsigned int index = 0; index != i; ++index)
        val *= dx;
      return val;
    }

  libmesh_error();
  return 0.;

}
void DenseMatrix<T>::_multiply_blas(const DenseMatrixBase<T>& other,
				    _BLAS_Multiply_Flag flag)
{
  int result_size = 0;

  // For each case, determine the size of the final result make sure
  // that the inner dimensions match
  switch (flag)
    {
    case LEFT_MULTIPLY:
      {
	result_size = other.m() * this->n();
	if (other.n() == this->m())
	  break;
      }
    case RIGHT_MULTIPLY:
      {
	result_size = other.n() * this->m();
	if (other.m() == this->n())
	  break;
      }
    case LEFT_MULTIPLY_TRANSPOSE:
      {
	result_size = other.n() * this->n();
	if (other.m() == this->m())
	  break;
      }
    case RIGHT_MULTIPLY_TRANSPOSE:
      {
	result_size = other.m() * this->m();
	if (other.n() == this->n())
	  break;
      }
    default:
      {
	libMesh::out << "Unknown flag selected or matrices are ";
	libMesh::out << "incompatible for multiplication." << std::endl;
	libmesh_error();
      }
    }

  // For this to work, the passed arg. must actually be a DenseMatrix<T>
  const DenseMatrix<T>* const_that = libmesh_cast_ptr< const DenseMatrix<T>* >(&other);

  // Also, although 'that' is logically const in this BLAS routine,
  // the PETSc BLAS interface does not specify that any of the inputs are
  // const.  To use it, I must cast away const-ness.
  DenseMatrix<T>* that = const_cast< DenseMatrix<T>* > (const_that);

  // Initialize A, B pointers for LEFT_MULTIPLY* cases
  DenseMatrix<T>
    *A = this,
    *B = that;

  // For RIGHT_MULTIPLY* cases, swap the meaning of A and B.
  // Here is a full table of combinations we can pass to BLASgemm, and what the answer is when finished:
  // pass A B   -> (Fortran) -> A^T B^T -> (C++) -> (A^T B^T)^T -> (identity) -> B A   "lt multiply"
  // pass B A   -> (Fortran) -> B^T A^T -> (C++) -> (B^T A^T)^T -> (identity) -> A B   "rt multiply"
  // pass A B^T -> (Fortran) -> A^T B   -> (C++) -> (A^T B)^T   -> (identity) -> B^T A "lt multiply t"
  // pass B^T A -> (Fortran) -> B A^T   -> (C++) -> (B A^T)^T   -> (identity) -> A B^T "rt multiply t"
  if (flag==RIGHT_MULTIPLY || flag==RIGHT_MULTIPLY_TRANSPOSE)
    std::swap(A,B);

  // transa, transb values to pass to blas
  char
    transa[] = "n",
    transb[] = "n";

  // Integer values to pass to BLAS:
  //
  // M
  // In Fortran, the number of rows of op(A),
  // In the BLAS documentation, typically known as 'M'.
  //
  // In C/C++, we set:
  // M = n_cols(A) if (transa='n')
  //     n_rows(A) if (transa='t')
  int M = static_cast<int>( A->n() );

  // N
  // In Fortran, the number of cols of op(B), and also the number of cols of C.
  // In the BLAS documentation, typically known as 'N'.
  //
  // In C/C++, we set:
  // N = n_rows(B) if (transb='n')
  //     n_cols(B) if (transb='t')
  int N = static_cast<int>( B->m() );

  // K
  // In Fortran, the number of cols of op(A), and also
  // the number of rows of op(B). In the BLAS documentation,
  // typically known as 'K'.
  //
  // In C/C++, we set:
  // K = n_rows(A) if (transa='n')
  //     n_cols(A) if (transa='t')
  int K = static_cast<int>( A->m() );

  // LDA (leading dimension of A). In our cases,
  // LDA is always the number of columns of A.
  int LDA = static_cast<int>( A->n() );

  // LDB (leading dimension of B).  In our cases,
  // LDB is always the number of columns of B.
  int LDB = static_cast<int>( B->n() );

  if (flag == LEFT_MULTIPLY_TRANSPOSE)
    {
      transb[0] = 't';
      N = static_cast<int>( B->n() );
    }

  else if (flag == RIGHT_MULTIPLY_TRANSPOSE)
    {
      transa[0] = 't';
      std::swap(M,K);
    }

  // LDC (leading dimension of C).  LDC is the
  // number of columns in the solution matrix.
  int LDC = M;

  // Scalar values to pass to BLAS
  //
  // scalar multiplying the whole product AB
  T alpha = 1.;

  // scalar multiplying C, which is the original matrix.
  T beta  = 0.;

  // Storage for the result
  std::vector<T> result (result_size);

  // Finally ready to call the BLAS
  BLASgemm_(transa, transb, &M, &N, &K, &alpha, &(A->_val[0]), &LDA, &(B->_val[0]), &LDB, &beta, &result[0], &LDC);

  // Update the relevant dimension for this matrix.
  switch (flag)
    {
    case LEFT_MULTIPLY:            { this->_m = other.m(); break; }
    case RIGHT_MULTIPLY:           { this->_n = other.n(); break; }
    case LEFT_MULTIPLY_TRANSPOSE:  { this->_m = other.n(); break; }
    case RIGHT_MULTIPLY_TRANSPOSE: { this->_n = other.m(); break; }
    default:
      {
	libMesh::out << "Unknown flag selected." << std::endl;
	libmesh_error();
      }
    }

  // Swap my data vector with the result
  this->_val.swap(result);
}
Beispiel #18
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::err << "Error: Cannot set Nmax to be less than the "
                 << "current number of basis functions."  << std::endl;
    libmesh_error();
  }

  // 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");
}
void DenseMatrix<T>::_lu_back_substitute_lapack (const DenseVector<T>& b,
						 DenseVector<T>& x)
{
  // The calling sequence for getrs is:
  // dgetrs(TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO)

  //    trans   (input) char*
  //            'n' for no tranpose, 't' for transpose
  char TRANS[] = "t";

  //    N       (input) int*
  //            The order of the matrix A.  N >= 0.
  int N = this->m();


  //    NRHS    (input) int*
  //            The number of right hand sides, i.e., the number of columns
  //            of the matrix B.  NRHS >= 0.
  int NRHS = 1;

  //    A       (input) DOUBLE PRECISION array, dimension (LDA,N)
  //            The factors L and U from the factorization A = P*L*U
  //            as computed by dgetrf.
  // Here, we pass &(_val[0])

  //    LDA     (input) int*
  //            The leading dimension of the array A.  LDA >= max(1,N).
  int LDA = N;

  //    ipiv    (input) int array, dimension (N)
  //            The pivot indices from DGETRF; for 1<=i<=N, row i of the
  //            matrix was interchanged with row IPIV(i).
  // Here, we pass &(_pivots[0]) which was computed in _lu_decompose_lapack

  //    B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
  //            On entry, the right hand side matrix B.
  //            On exit, the solution matrix X.
  // Here, we pass a copy of the rhs vector's data array in x, so that the
  // passed right-hand side b is unmodified.  I don't see a way around this
  // copy if we want to maintain an unmodified rhs in LibMesh.
  x = b;
  std::vector<T>& x_vec = x.get_values();

  // We can avoid the copy if we don't care about overwriting the RHS: just
  // pass b to the Lapack routine and then swap with x before exiting
  // std::vector<T>& x_vec = b.get_values();

  //    LDB     (input) int*
  //            The leading dimension of the array B.  LDB >= max(1,N).
  int LDB = N;

  //    INFO    (output) int*
  //            = 0:  successful exit
  //            < 0:  if INFO = -i, the i-th argument had an illegal value
  int INFO = 0;

  // Finally, ready to call the Lapack getrs function
  LAPACKgetrs_(TRANS, &N, &NRHS, &(_val[0]), &LDA, &(_pivots[0]), &(x_vec[0]), &LDB, &INFO);

  // Check return value for errors
  if (INFO != 0)
    {
      libMesh::out << "INFO="
		    << INFO
		    << ", Error during Lapack LU solve!" << std::endl;
      libmesh_error();
    }

  // Don't do this if you already made a copy of b above
  // Swap b and x.  The solution will then be in x, and whatever was originally
  // in x, maybe garbage, maybe nothing, will be in b.
  // FIXME: Rewrite the LU and Cholesky solves to just take one input, and overwrite
  // the input.  This *should* make user code simpler, as they don't have to create
  // an extra vector just to pass it in to the solve function!
  // b.swap(x);
}
Beispiel #20
0
Real RBEvaluation::rb_solve(unsigned int N)
{
  START_LOG("rb_solve()", "RBEvaluation");

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

  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 DenseMatrix<T>::_matvec_blas(T alpha, T beta,
				  DenseVector<T>& dest,
				  const DenseVector<T>& arg,
                                  bool trans) const
{
  // Ensure that dest and arg sizes are compatible
  if (!trans)
    {
      // dest  ~ A     * arg
      // (mx1)   (mxn) * (nx1)
      if ((dest.size() != this->m()) || (arg.size() != this->n()))
	{
	  libMesh::out << "Improper input argument sizes!" << std::endl;
	  libmesh_error();
	}
    }

  else // trans == true
    {
      // Ensure that dest and arg are proper size
      // dest  ~ A^T   * arg
      // (nx1)   (nxm) * (mx1)
      if ((dest.size() != this->n()) || (arg.size() != this->m()))
	{
	  libMesh::out << "Improper input argument sizes!" << std::endl;
	  libmesh_error();
	}
    }

  // Calling sequence for dgemv:
  //
  // dgemv(TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY)

  //   TRANS  - CHARACTER*1, 't' for transpose, 'n' for non-transpose multiply
  // We store everything in row-major order, so pass the transpose flag for
  // non-transposed matvecs and the 'n' flag for transposed matvecs
  char TRANS[] = "t";
  if (trans)
    TRANS[0] = 'n';

  //   M      - INTEGER.
  //            On entry, M specifies the number of rows of the matrix A.
  // In C/C++, pass the number of *cols* of A
  int M = this->n();

  //   N      - INTEGER.
  //            On entry, N specifies the number of columns of the matrix A.
  // In C/C++, pass the number of *rows* of A
  int N = this->m();

  //   ALPHA  - DOUBLE PRECISION.
  // The scalar constant passed to this function

  //   A      - DOUBLE PRECISION array of DIMENSION ( LDA, n ).
  //            Before entry, the leading m by n part of the array A must
  //            contain the matrix of coefficients.
  // The matrix, *this.  Note that _matvec_blas is called from
  // a const function, vector_mult(), and so we have made this function const
  // as well.  Since BLAS knows nothing about const, we have to cast it away
  // now.
  DenseMatrix<T>& a_ref = const_cast< DenseMatrix<T>& > ( *this );
  std::vector<T>& a = a_ref.get_values();

  //   LDA    - INTEGER.
  //            On entry, LDA specifies the first dimension of A as declared
  //            in the calling (sub) program. LDA must be at least
  //            max( 1, m ).
  int LDA = M;

  //   X      - DOUBLE PRECISION array of DIMENSION at least
  //            ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n'
  //            and at least
  //            ( 1 + ( m - 1 )*abs( INCX ) ) otherwise.
  //            Before entry, the incremented array X must contain the
  //            vector x.
  // Here, we must cast away the const-ness of "arg" since BLAS knows
  // nothing about const
  DenseVector<T>& x_ref = const_cast< DenseVector<T>& > ( arg );
  std::vector<T>& x = x_ref.get_values();

  //   INCX   - INTEGER.
  //            On entry, INCX specifies the increment for the elements of
  //            X. INCX must not be zero.
  int INCX = 1;

  //   BETA   - DOUBLE PRECISION.
  //            On entry, BETA specifies the scalar beta. When BETA is
  //            supplied as zero then Y need not be set on input.
  // The second scalar constant passed to this function

  //   Y      - DOUBLE PRECISION array of DIMENSION at least
  //            ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n'
  //            and at least
  //            ( 1 + ( n - 1 )*abs( INCY ) ) otherwise.
  //            Before entry with BETA non-zero, the incremented array Y
  //            must contain the vector y. On exit, Y is overwritten by the
  //            updated vector y.
  // The input vector "dest"
  std::vector<T>& y = dest.get_values();

  //   INCY   - INTEGER.
  //            On entry, INCY specifies the increment for the elements of
  //            Y. INCY must not be zero.
  int INCY = 1;

  // Finally, ready to call the BLAS function
  BLASgemv_(TRANS, &M, &N, &alpha, &(a[0]), &LDA, &(x[0]), &INCX, &beta, &(y[0]), &INCY);
}
Beispiel #22
0
void RBEvaluation::read_in_vectors(System& sys,
                                   std::vector<NumericVector<Number>*>& vectors,
                                   const std::string& directory_name,
                                   const std::string& data_name,
                                   const bool read_binary_vectors)
{
  START_LOG("read_in_vectors()", "RBEvaluation");

  //libMesh::out << "Reading in the basis functions..." << std::endl;

  // Make sure processors are synced up before we begin
  this->comm().barrier();

  std::ostringstream file_name;
  const std::string basis_function_suffix = (read_binary_vectors ? ".xdr" : ".dat");
  struct stat stat_info;

  file_name << directory_name << "/" << data_name << "_header" << basis_function_suffix;
  Xdr header_data(file_name.str(),
                  read_binary_vectors ? DECODE : READ);

  // set the version number in header_data from io_version_string
  // (same code as in EquationSystemsIO::_read_impl)
  std::string io_version_string = get_io_version_string();
  std::string::size_type lm_pos = io_version_string.find("libMesh");
  std::istringstream iss(io_version_string.substr(lm_pos + 8));
  int ver_major = 0, ver_minor = 0, ver_patch = 0;
  char dot;
  iss >> ver_major >> dot >> ver_minor >> dot >> ver_patch;
  header_data.set_version(LIBMESH_VERSION_ID(ver_major, ver_minor, ver_patch));

  // We need to call sys.read_header (e.g. to set _written_var_indices properly),
  // but by setting the read_header argument to false, it doesn't reinitialize the system
  sys.read_header(header_data, io_version_string, /*read_header=*/false, /*read_additional_data=*/false);

  // Following EquationSystemsIO::read, we use a temporary numbering (node major)
  // before writing out the data
  MeshTools::Private::globally_renumber_nodes_and_elements(sys.get_mesh());


  const bool read_legacy_format = false;
  if (read_legacy_format)
    {
      // Use System::read_serialized_data to read in the basis functions
      // into this->solution and then swap with the appropriate
      // of basis function.
      for(unsigned int i=0; i<vectors.size(); i++)
	{
	  file_name.str(""); // reset the string
	  file_name << directory_name << "/" << data_name << i << basis_function_suffix;

	  // On processor zero check to be sure the file exists
	  if (this->processor_id() == 0)
	    {
	      int stat_result = stat(file_name.str().c_str(), &stat_info);

	      if (stat_result != 0)
		{
		  libMesh::out << "File does not exist: " << file_name.str() << std::endl;
		  libmesh_error();
		}
	    }

	  Xdr vector_data(file_name.str(),
		          read_binary_vectors ? DECODE : READ);

	  // The bf_data needs to know which version to read.
	  vector_data.set_version(LIBMESH_VERSION_ID(ver_major, ver_minor, ver_patch));

	  sys.read_serialized_data(vector_data, false);

	  vectors[i] = NumericVector<Number>::build(sys.comm()).release();
	  vectors[i]->init (sys.n_dofs(), sys.n_local_dofs(), false, libMeshEnums::PARALLEL);

	  // No need to copy, just swap
	  // *vectors[i] = *solution;
	  vectors[i]->swap(*sys.solution);
	}
    }

  //------------------------------------------------------
  // new implementation
  else
    {
      // Allocate storage for each vector
      for(unsigned int i=0; i<vectors.size(); i++)
	{
	  vectors[i] = NumericVector<Number>::build(sys.comm()).release();
	  vectors[i]->init (sys.n_dofs(), sys.n_local_dofs(), false, libMeshEnums::PARALLEL);
	}

      file_name.str("");
      file_name << directory_name << "/" << data_name << "_data" << basis_function_suffix;

      // On processor zero check to be sure the file exists
      if (this->processor_id() == 0)
	{
	  int stat_result = stat(file_name.str().c_str(), &stat_info);

	  if (stat_result != 0)
	    {
	      libMesh::out << "File does not exist: " << file_name.str() << std::endl;
	      libmesh_error();
	    }
	}

      Xdr vector_data(file_name.str(),
		      read_binary_vectors ? DECODE : READ);

      // The vector_data needs to know which version to read.
      vector_data.set_version(LIBMESH_VERSION_ID(ver_major, ver_minor, ver_patch));

      sys.read_serialized_vectors (vector_data, vectors);
    }
  //------------------------------------------------------

  // Undo the temporary renumbering
  sys.get_mesh().fix_broken_node_and_element_numbering();

  //libMesh::out << "Finished reading in the basis functions..." << std::endl;

  STOP_LOG("read_in_vectors()", "RBEvaluation");
}
Beispiel #23
0
void LaplaceMeshSmoother::smooth(unsigned int n_iterations)
{
  if (!_initialized)
    this->init();

  // Don't smooth the nodes on the boundary...
  // this would change the mesh geometry which
  // is probably not something we want!
  std::vector<bool> on_boundary;
  MeshTools::find_boundary_nodes(_mesh, on_boundary);

  // Ensure that the find_boundary_nodes() function returned a properly-sized vector
  if (on_boundary.size() != _mesh.n_nodes())
    {
      libMesh::err << "MeshTools::find_boundary_nodes() returned incorrect length vector!" << std::endl;
      libmesh_error();
    }

  // We can only update the nodes after all new positions were
  // determined. We store the new positions here
  std::vector<Point> new_positions;

  for (unsigned int n=0; n<n_iterations; n++)
    {
      new_positions.resize(_mesh.n_nodes());

      {
	MeshBase::node_iterator       it     = _mesh.local_nodes_begin();
	const MeshBase::node_iterator it_end = _mesh.local_nodes_end();
	for (; it != it_end; ++it)
	  {
	    Node* node = *it;

	    if (node == NULL)
	      {
		libMesh::err << "[" << _mesh.processor_id() << "]: Node iterator returned NULL pointer." << std::endl;
		libmesh_error();
	      }

	    // leave the boundary intact
	    // Only relocate the nodes which are vertices of an element
	    // All other entries of _graph (the secondary nodes) are empty
	    if (!on_boundary[node->id()] && (_graph[node->id()].size() > 0))
	      {
		Point avg_position(0.,0.,0.);

		for (unsigned j=0; j<_graph[node->id()].size(); ++j)
		  {
		    // Will these nodal positions always be available
		    // or will they refer to remote nodes?  To be
		    // careful, we grab a pointer and test it against
		    // NULL.
		    Node* connected_node = _mesh.node_ptr(_graph[node->id()][j]);

		    if (connected_node == NULL)
		      {
			libMesh::err << "Error! Libmesh returned NULL pointer for node " << _graph[connected_node->id()][j] << std::endl;
			libmesh_error();
		      }

		    avg_position.add( *connected_node );
		  } // end for(j)

		// Compute the average, store in the new_positions vector
		new_positions[node->id()] = avg_position / static_cast<Real>(_graph[node->id()].size());
	      } // end if
	  } // end for
      } // end scope


      // now update the node positions (local node positions only)
      {
	MeshBase::node_iterator it           = _mesh.local_nodes_begin();
	const MeshBase::node_iterator it_end = _mesh.local_nodes_end();
	for (; it != it_end; ++it)
	  {
	    Node* node = *it;

	    if (!on_boundary[node->id()] && (_graph[node->id()].size() > 0))
	      {
		// Should call Point::op=
		// libMesh::out << "Setting node id " << node->id() << " to position " << new_positions[node->id()];
		_mesh.node(node->id()) = new_positions[node->id()];
	      }
	  } // end for
      } // end scope

      // Now the nodes which are ghosts on this processor may have been moved on
      // the processors which own them.  So we need to synchronize with our neighbors
      // and get the most up-to-date positions for the ghosts.
      SyncNodalPositions sync_object(_mesh);
      Parallel::sync_dofobject_data_by_id
	(_mesh.comm(), _mesh.nodes_begin(), _mesh.nodes_end(), sync_object);

    } // end for n_iterations

  // finally adjust the second order nodes (those located between vertices)
  // these nodes will be located between their adjacent nodes
  // do this element-wise
  MeshBase::element_iterator       el  = _mesh.active_elements_begin();
  const MeshBase::element_iterator end = _mesh.active_elements_end();

  for (; el != end; ++el)
    {
      // Constant handle for the element
      const Elem* elem = *el;

      // get the second order nodes (son)
      // their element indices start at n_vertices and go to n_nodes
      const unsigned int son_begin = elem->n_vertices();
      const unsigned int son_end   = elem->n_nodes();

      // loop over all second order nodes (son)
      for (unsigned int son=son_begin; son<son_end; son++)
        {
	  // Don't smooth second-order nodes which are on the boundary
	  if (!on_boundary[elem->node(son)])
	    {
	      const unsigned int n_adjacent_vertices =
		elem->n_second_order_adjacent_vertices(son);

	      // calculate the new position which is the average of the
	      // position of the adjacent vertices
	      Point avg_position(0,0,0);
	      for (unsigned int v=0; v<n_adjacent_vertices; v++)
		avg_position +=
		  _mesh.point( elem->node( elem->second_order_adjacent_vertex(son,v) ) );

	      _mesh.node(elem->node(son)) = avg_position / n_adjacent_vertices;
	    }
        }
    }
}
  //---------------------------------------------------------------
  // this function is called by PETSc to evaluate the Jacobian at X
  PetscErrorCode
  __libmesh_petsc_snes_jacobian (SNES snes, Vec x, Mat *jac, Mat *pc, MatStructure *msflag, void *ctx)
  {
    START_LOG("jacobian()", "PetscNonlinearSolver");

    PetscErrorCode ierr=0;

    libmesh_assert(ctx);

    PetscNonlinearSolver<Number>* solver =
      static_cast<PetscNonlinearSolver<Number>*> (ctx);

    // Get the current iteration number from the snes object,
    // store it in the PetscNonlinearSolver object for possible use
    // by the user's Jacobian function.
    {
      PetscInt n_iterations = 0;
      ierr = SNESGetIterationNumber(snes, &n_iterations);
      CHKERRABORT(solver->comm().get(),ierr);
      solver->_current_nonlinear_iteration_number = static_cast<unsigned>(n_iterations);
    }

    NonlinearImplicitSystem &sys = solver->system();

    PetscMatrix<Number> PC(*pc, sys.comm());
    PetscMatrix<Number> Jac(*jac, sys.comm());
    PetscVector<Number>& X_sys = *libmesh_cast_ptr<PetscVector<Number>*>(sys.solution.get());
    PetscMatrix<Number>& Jac_sys = *libmesh_cast_ptr<PetscMatrix<Number>*>(sys.matrix);
    PetscVector<Number> X_global(x, sys.comm());

    // Set the dof maps
    PC.attach_dof_map(sys.get_dof_map());
    Jac.attach_dof_map(sys.get_dof_map());

    // Use the systems update() to get a good local version of the parallel solution
    X_global.swap(X_sys);
    Jac.swap(Jac_sys);

    sys.get_dof_map().enforce_constraints_exactly(sys);
    sys.update();

    X_global.swap(X_sys);
    Jac.swap(Jac_sys);

    if (solver->_zero_out_jacobian)
      PC.zero();

    //-----------------------------------------------------------------------------
    // if the user has provided both function pointers and objects only the pointer
    // will be used, so catch that as an error
    if (solver->jacobian && solver->jacobian_object)
      {
	libMesh::err << "ERROR: cannot specify both a function and object to compute the Jacobian!" << std::endl;
	libmesh_error();
      }

    if (solver->matvec && solver->residual_and_jacobian_object)
      {
	libMesh::err << "ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!" << std::endl;
	libmesh_error();
      }
    //-----------------------------------------------------------------------------

    if      (solver->jacobian != NULL)                     solver->jacobian                                            (*sys.current_local_solution.get(), PC, sys);
    else if (solver->jacobian_object != NULL)              solver->jacobian_object->jacobian                           (*sys.current_local_solution.get(), PC, sys);
    else if (solver->matvec   != NULL)                     solver->matvec                                              (*sys.current_local_solution.get(), NULL, &PC, sys);
    else if (solver->residual_and_jacobian_object != NULL) solver->residual_and_jacobian_object->residual_and_jacobian (*sys.current_local_solution.get(), NULL, &PC, sys);
    else libmesh_error();

    PC.close();
    Jac.close();
    X_global.close();

    *msflag = SAME_NONZERO_PATTERN;

    STOP_LOG("jacobian()", "PetscNonlinearSolver");

    return ierr;
  }
Beispiel #25
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;
}
  //---------------------------------------------------------------
  // this function is called by PETSc to evaluate the residual at X
  PetscErrorCode
  __libmesh_petsc_snes_residual (SNES snes, Vec x, Vec r, void *ctx)
  {
    START_LOG("residual()", "PetscNonlinearSolver");

    PetscErrorCode ierr=0;

    libmesh_assert(x);
    libmesh_assert(r);
    libmesh_assert(ctx);

    PetscNonlinearSolver<Number>* solver =
      static_cast<PetscNonlinearSolver<Number>*> (ctx);

    // Get the current iteration number from the snes object,
    // store it in the PetscNonlinearSolver object for possible use
    // by the user's residual function.
    {
      PetscInt n_iterations = 0;
      ierr = SNESGetIterationNumber(snes, &n_iterations);
      CHKERRABORT(solver->comm().get(),ierr);
      solver->_current_nonlinear_iteration_number = static_cast<unsigned>(n_iterations);
    }

    NonlinearImplicitSystem &sys = solver->system();

    PetscVector<Number>& X_sys = *libmesh_cast_ptr<PetscVector<Number>*>(sys.solution.get());
    PetscVector<Number>& R_sys = *libmesh_cast_ptr<PetscVector<Number>*>(sys.rhs);
    PetscVector<Number> X_global(x, sys.comm()), R(r, sys.comm());

    // Use the systems update() to get a good local version of the parallel solution
    X_global.swap(X_sys);
    R.swap(R_sys);

    sys.get_dof_map().enforce_constraints_exactly(sys);

    sys.update();

    //Swap back
    X_global.swap(X_sys);
    R.swap(R_sys);

    if (solver->_zero_out_residual)
      R.zero();

    //-----------------------------------------------------------------------------
    // if the user has provided both function pointers and objects only the pointer
    // will be used, so catch that as an error
    if (solver->residual && solver->residual_object)
      {
	libMesh::err << "ERROR: cannot specifiy both a function and object to compute the Residual!" << std::endl;
	libmesh_error();
      }

    if (solver->matvec && solver->residual_and_jacobian_object)
      {
	libMesh::err << "ERROR: cannot specifiy both a function and object to compute the combined Residual & Jacobian!" << std::endl;
	libmesh_error();
      }
    //-----------------------------------------------------------------------------

    if      (solver->residual != NULL)                     solver->residual                                            (*sys.current_local_solution.get(), R, sys);
    else if (solver->residual_object != NULL)              solver->residual_object->residual                           (*sys.current_local_solution.get(), R, sys);
    else if (solver->matvec   != NULL)                     solver->matvec                                              (*sys.current_local_solution.get(), &R, NULL, sys);
    else if (solver->residual_and_jacobian_object != NULL) solver->residual_and_jacobian_object->residual_and_jacobian (*sys.current_local_solution.get(), &R, NULL, sys);
    else libmesh_error();

    R.close();
    X_global.close();

    STOP_LOG("residual()", "PetscNonlinearSolver");

    return ierr;
  }
Real FE<1,L2_LAGRANGE>::shape_second_deriv(const ElemType,
					   const Order order,
					   const unsigned int i,
					   const unsigned int libmesh_dbg_var(j),
					   const Point& p)
{
  // Don't need to switch on j.  1D shape functions
  // depend on xi only!

  const Real xi = p(0);
  libmesh_assert_equal_to (j, 0);

  switch (order)
    {
      // linear Lagrange shape functions
    case FIRST:
      {
	// All second derivatives of linears are zero....
	return 0.;
      }

      // quadratic Lagrange shape functions
    case SECOND:
      {
	switch (i)
	  {
	  case 0:
	    return 1.;

	  case 1:
	    return 1.;

	  case 2:
	    return -2.;

	  default:
	    {
	      libMesh::err << "Invalid shape function index requested!"
			    << std::endl;
	      libmesh_error();
	    }
	  }
      } // end case SECOND

    case THIRD:
     {
      switch (i)
        {
        case 0:
            return -9./16.*(6.*xi-2);

        case 1:
            return -9./16.*(-6*xi-2.);

        case 2:
            return 27./16.*(6*xi-2./3.);

        case 3:
            return 27./16.*(-6*xi-2./3.);

        default:
          {
            libMesh::err << "Invalid shape function index requested!"
                          << std::endl;
            libmesh_error();
          }
        }
     } // end case THIRD


    default:
      {
	libMesh::err << "ERROR: Unsupported polynomial order!" << std::endl;
	libmesh_error();
      }
    } // end switch (order)

  libmesh_error();
  return 0.;
}
void DenseMatrix<T>::_multiply_blas(const DenseMatrixBase<T>& ,
				    _BLAS_Multiply_Flag )
{
  libMesh::err << "No PETSc-provided BLAS/LAPACK available!" << std::endl;
  libmesh_error();
}
Beispiel #29
0
 // Needed for ExactSolution to compile
 Number curl_from_grad( const VectorValue<Number>& )
 {
   libMesh::err << "Operation not defined for scalar quantities." << std::endl;
   libmesh_error();
 }
Beispiel #30
0
vtkIdType VTKIO::get_elem_type(ElemType type)
{
  vtkIdType celltype = VTK_EMPTY_CELL; // initialize to something to avoid compiler warning

  switch(type)
  {
    case EDGE2:
      celltype = VTK_LINE;
      break;
    case EDGE3:
      celltype = VTK_QUADRATIC_EDGE;
      break;// 1
    case TRI3:
      celltype = VTK_TRIANGLE;
      break;// 3
    case TRI6:
      celltype = VTK_QUADRATIC_TRIANGLE;
      break;// 4
    case QUAD4:
      celltype = VTK_QUAD;
      break;// 5
    case QUAD8:
      celltype = VTK_QUADRATIC_QUAD;
      break;// 6
    case TET4:
      celltype = VTK_TETRA;
      break;// 8
    case TET10:
      celltype = VTK_QUADRATIC_TETRA;
      break;// 9
    case HEX8:
      celltype = VTK_HEXAHEDRON;
      break;// 10
    case HEX20:
      celltype = VTK_QUADRATIC_HEXAHEDRON;
      break;// 12
    case HEX27:
      celltype = VTK_TRIQUADRATIC_HEXAHEDRON;
      break;
    case PRISM6:
      celltype = VTK_WEDGE;
      break;// 13
    case PRISM15:
      celltype = VTK_QUADRATIC_WEDGE;
      break;// 14
    case PRISM18:
      celltype = VTK_BIQUADRATIC_QUADRATIC_WEDGE;
      break;// 15
    case PYRAMID5:
      celltype = VTK_PYRAMID;
      break;// 16
#if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0)
    case QUAD9:
      celltype = VTK_BIQUADRATIC_QUAD;
      break;
#else
    case QUAD9:
#endif
    case EDGE4:
    case INFEDGE2:
    case INFQUAD4:
    case INFQUAD6:
    case INFHEX8:
    case INFHEX16:
    case INFHEX18:
    case INFPRISM6:
    case INFPRISM12:
    case NODEELEM:
    case INVALID_ELEM:
    default:
      {
        libMesh::err<<"element type "<<type<<" not implemented"<<std::endl;
        libmesh_error();
        break;
      }
  }
  return celltype;
}