示例#1
0
  void H1FETransformation<OutputShape>::map_phi( const unsigned int dim,
						 const Elem* const elem,
						 const std::vector<Point>& qp,
						 const FEGenericBase<OutputShape>& fe,
						 std::vector<std::vector<OutputShape> >& phi ) const
  {
    switch(dim)
      {
      case 0:
	{
	  for (unsigned int i=0; i<phi.size(); i++)
	    {
	      libmesh_assert_equal_to ( qp.size(), phi[i].size() );
	      for (unsigned int p=0; p<phi[i].size(); p++)
		FEInterface::shape<OutputShape>(0, fe.get_fe_type(), elem, i, qp[p], phi[i][p]);
	    }
	  break;
	}
      case 1:
	{
	  for (unsigned int i=0; i<phi.size(); i++)
	    {
	      libmesh_assert_equal_to ( qp.size(), phi[i].size() );
	      for (unsigned int p=0; p<phi[i].size(); p++)
		FEInterface::shape<OutputShape>(1, fe.get_fe_type(), elem, i, qp[p], phi[i][p]);
	    }
	  break;
	}
      case 2:
	{
	  for (unsigned int i=0; i<phi.size(); i++)
	    {
	      libmesh_assert_equal_to ( qp.size(), phi[i].size() );
	      for (unsigned int p=0; p<phi[i].size(); p++)
		FEInterface::shape<OutputShape>(2, fe.get_fe_type(), elem, i, qp[p], phi[i][p]);
	    }
	  break;
	}
      case 3:
	{
	  for (unsigned int i=0; i<phi.size(); i++)
	    {
	      libmesh_assert_equal_to ( qp.size(), phi[i].size() );
	      for (unsigned int p=0; p<phi[i].size(); p++)
		FEInterface::shape<OutputShape>(3, fe.get_fe_type(), elem, i, qp[p], phi[i][p]);
	    }
	  break;
	}
      default:
	libmesh_error();
      }

    return;
  }
示例#2
0
void LaplaceSystem::init_context(DiffContext &context)
{
  FEMContext &c = libmesh_cast_ref<FEMContext&>(context);

  // Get finite element object
  FEGenericBase<RealGradient>* fe;
  c.get_element_fe<RealGradient>( u_var, fe );

  // We should prerequest all the data
  // we will need to build the linear system.
  fe->get_JxW();
  fe->get_phi();
  fe->get_dphi();
  fe->get_xyz();

  FEGenericBase<RealGradient>* side_fe;
  c.get_side_fe<RealGradient>( u_var, side_fe );

  side_fe->get_JxW();
  side_fe->get_phi();
}
示例#3
0
bool LaplaceSystem::element_time_derivative (bool request_jacobian,
                                            DiffContext &context)
{
  FEMContext &c = libmesh_cast_ref<FEMContext&>(context);

  // Get finite element object
  FEGenericBase<RealGradient>* fe = NULL;
  c.get_element_fe<RealGradient>( u_var, fe );

  // First we get some references to cell-specific data that
  // will be used to assemble the linear system.

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

  // The velocity shape functions at interior quadrature points.
  const std::vector<std::vector<RealGradient> >& phi = fe->get_phi();

  // The velocity shape function gradients at interior
  // quadrature points.
  const std::vector<std::vector<RealTensor> >& grad_phi = fe->get_dphi();

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

  // The number of local degrees of freedom in each variable
  const unsigned int n_u_dofs = c.dof_indices_var[u_var].size();

  DenseSubMatrix<Number> &Kuu = *c.elem_subjacobians[u_var][u_var];

  DenseSubVector<Number> &Fu = *c.elem_subresiduals[u_var];

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

  for (unsigned int qp=0; qp != n_qpoints; qp++)
    {
      Tensor grad_u;

      c.interior_gradient( u_var, qp, grad_u );


      // Value of the forcing function at this quadrature point
      RealGradient f = this->forcing(qpoint[qp]);

      // First, an i-loop over the velocity degrees of freedom.
      // We know that n_u_dofs == n_v_dofs so we can compute contributions
      // for both at the same time.
      for (unsigned int i=0; i != n_u_dofs; i++)
        {
          Fu(i) += ( grad_u.contract(grad_phi[i][qp]) - f*phi[i][qp] )*JxW[qp];

          if (request_jacobian)
            {
              // Matrix contributions for the uu and vv couplings.
              for (unsigned int j=0; j != n_u_dofs; j++)
                {
                  Kuu(i,j) += grad_phi[j][qp].contract(grad_phi[i][qp])*JxW[qp];

		}
	    }
        }
    } // end of the quadrature point qp-loop

  return request_jacobian;
}
示例#4
0
bool CurlCurlSystem::element_time_derivative (bool request_jacobian,
                                              DiffContext &context)
{
  FEMContext &c = cast_ref<FEMContext&>(context);

  // Get finite element object
  FEGenericBase<RealGradient>* fe = NULL;
  c.get_element_fe<RealGradient>( u_var, fe );

  // First we get some references to cell-specific data that
  // will be used to assemble the linear system.

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

  // The velocity shape functions at interior quadrature points.
  const std::vector<std::vector<RealGradient> >& phi = fe->get_phi();

  // The velocity shape function gradients at interior
  // quadrature points.
  const std::vector<std::vector<RealGradient> >& curl_phi = fe->get_curl_phi();

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

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

  DenseSubMatrix<Number> &Kuu = c.get_elem_jacobian(u_var,u_var);

  DenseSubVector<Number> &Fu = c.get_elem_residual(u_var);

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

  // Loop over quadrature points
  for (unsigned int qp=0; qp != n_qpoints; qp++)
    {
      Gradient u;
      Gradient curl_u;

      c.interior_value( u_var, qp, u );

      c.interior_curl( u_var, qp, curl_u );

      // Value of the forcing function at this quadrature point
      RealGradient f = this->forcing(qpoint[qp]);

      // First, an i-loop over the degrees of freedom.
      for (unsigned int i=0; i != n_u_dofs; i++)
        {
          Fu(i) += ( curl_u*curl_phi[i][qp] + u*phi[i][qp] - f*phi[i][qp] )*JxW[qp];

          if (request_jacobian)
            {
              // Matrix contributions for the uu and vv couplings.
              for (unsigned int j=0; j != n_u_dofs; j++)
                {
                  Kuu(i,j) += ( curl_phi[j][qp]*curl_phi[i][qp] +
                                phi[j][qp]*phi[i][qp] )*JxW[qp];

                }
            }

        }
    } // end of the quadrature point qp-loop

  return request_jacobian;
}
示例#5
0
  void HCurlFETransformation<OutputShape>::map_phi( const unsigned int dim,
						    const Elem* const elem,
						    const std::vector<Point>& qp,
						    const FEGenericBase<OutputShape>& fe,
						    std::vector<std::vector<OutputShape> >& phi ) const
  {
    switch(dim)
      {
	// These element transformations only make sense in 2D and 3D
      case 0: 
      case 1:
	{
	  libmesh_error();
	}
	
      case 2:
	{
	  const std::vector<Real>& dxidx_map = fe.get_fe_map().get_dxidx();
	  const std::vector<Real>& dxidy_map = fe.get_fe_map().get_dxidy();

	  const std::vector<Real>& detadx_map = fe.get_fe_map().get_detadx();
	  const std::vector<Real>& detady_map = fe.get_fe_map().get_detady();

	  // FIXME: Need to update for 2D elements in 3D space
	  /* phi = (dx/dxi)^-T * \hat{phi} 
	     In 2D:
	             (dx/dxi)^{-1} = [  dxi/dx   dxi/dy 
		                        deta/dx  deta/dy ]

	         so: dxi/dx^{-T} * \hat{phi} = [ dxi/dx  deta/dx   [ \hat{phi}_xi
                                                 dxi/dy  deta/dy ]   \hat{phi}_eta ]

	      or in indicial notation:  phi_j = xi_{i,j}*\hat{phi}_i */

	  for (unsigned int i=0; i<phi.size(); i++)
	    for (unsigned int p=0; p<phi[i].size(); p++)
	      {
		// Need to temporarily cache reference shape functions
		// TODO: PB: Might be worth trying to build phi_ref separately to see
		//           if we can get vectorization
		OutputShape phi_ref;
		FEInterface::shape<OutputShape>(2, fe.get_fe_type(), elem, i, qp[p], phi_ref);

		phi[i][p](0) = dxidx_map[p]*phi_ref.slice(0) + detadx_map[p]*phi_ref.slice(1);

		phi[i][p](1) = dxidy_map[p]*phi_ref.slice(0) + detady_map[p]*phi_ref.slice(1);
	      }

	  break;
	}

      case 3:
	{
	  const std::vector<Real>& dxidx_map = fe.get_fe_map().get_dxidx();
	  const std::vector<Real>& dxidy_map = fe.get_fe_map().get_dxidy();
	  const std::vector<Real>& dxidz_map = fe.get_fe_map().get_dxidz();

	  const std::vector<Real>& detadx_map = fe.get_fe_map().get_detadx();
	  const std::vector<Real>& detady_map = fe.get_fe_map().get_detady();
	  const std::vector<Real>& detadz_map = fe.get_fe_map().get_detadz();

	  const std::vector<Real>& dzetadx_map = fe.get_fe_map().get_dzetadx();
	  const std::vector<Real>& dzetady_map = fe.get_fe_map().get_dzetady();
	  const std::vector<Real>& dzetadz_map = fe.get_fe_map().get_dzetadz();

	  /* phi = (dx/dxi)^-T * \hat{phi} 
	     In 3D:
	          dx/dxi^-1 = [  dxi/dx    dxi/dy    dxi/dz
                                 deta/dx   deta/dy   deta/dz
                                 dzeta/dx  dzeta/dy  dzeta/dz]

	         so: dxi/dx^-T * \hat{phi} = [ dxi/dx  deta/dx  dzeta/dx   [ \hat{phi}_xi
                                               dxi/dy  deta/dy  dzeta/dy     \hat{phi}_eta 
                                               dxi/dz  deta/dz  dzeta/dz ]   \hat{phi}_zeta ]

	      or in indicial notation:  phi_j = xi_{i,j}*\hat{phi}_i */

	  for (unsigned int i=0; i<phi.size(); i++)
	    for (unsigned int p=0; p<phi[i].size(); p++)
	      {
		// Need to temporarily cache reference shape functions
		// TODO: PB: Might be worth trying to build phi_ref separately to see
		//           if we can get vectorization
		OutputShape phi_ref;
		FEInterface::shape<OutputShape>(3, fe.get_fe_type(), elem, i, qp[p], phi_ref);

		phi[i][p].slice(0) = dxidx_map[p]*phi_ref.slice(0) + detadx_map[p]*phi_ref.slice(1)
		  + dzetadx_map[p]*phi_ref.slice(2);

		phi[i][p].slice(1) = dxidy_map[p]*phi_ref.slice(0) + detady_map[p]*phi_ref.slice(1)
		  + dzetady_map[p]*phi_ref.slice(2);

		phi[i][p].slice(2) = dxidz_map[p]*phi_ref.slice(0) + detadz_map[p]*phi_ref.slice(1)
		  + dzetadz_map[p]*phi_ref.slice(2);
	      }
	  break;
	}
	
      default:
	libmesh_error();

      } // switch(dim)

    return;
  }
示例#6
0
  void HCurlFETransformation<OutputShape>::map_curl( const unsigned int dim,
						     const Elem* const,
						     const std::vector<Point>&,
						     const FEGenericBase<OutputShape>& fe,
						     std::vector<std::vector<OutputShape> >& curl_phi ) const
  {
    switch(dim)
      {
	// These element transformations only make sense in 2D and 3D
      case 0: 
      case 1:
	{
	  libmesh_error();
	}
	
      case 2:
	{
	  const std::vector<std::vector<OutputShape> >& dphi_dxi = fe.get_dphidxi();
	  const std::vector<std::vector<OutputShape> >& dphi_deta = fe.get_dphideta();

	  const std::vector<Real>& J = fe.get_fe_map().get_jacobian();

	  // FIXME: I don't think this is valid for 2D elements in 3D space
	  /* In 2D: curl(phi) = J^{-1} * curl(\hat{phi}) */
	  for (unsigned int i=0; i<curl_phi.size(); i++)
	    for (unsigned int p=0; p<curl_phi[i].size(); p++)
	      {
		curl_phi[i][p].slice(0) = curl_phi[i][p].slice(1) = 0.0;

		curl_phi[i][p].slice(2) = ( dphi_dxi[i][p].slice(1) - dphi_deta[i][p].slice(0) )/J[p];
	      }

	  break;
	}

      case 3:
	{
	  const std::vector<std::vector<OutputShape> >& dphi_dxi = fe.get_dphidxi();
	  const std::vector<std::vector<OutputShape> >& dphi_deta = fe.get_dphideta();
	  const std::vector<std::vector<OutputShape> >& dphi_dzeta = fe.get_dphidzeta();
	  
	  const std::vector<RealGradient>& dxyz_dxi   = fe.get_fe_map().get_dxyzdxi();
	  const std::vector<RealGradient>& dxyz_deta  = fe.get_fe_map().get_dxyzdeta();
	  const std::vector<RealGradient>& dxyz_dzeta = fe.get_fe_map().get_dxyzdzeta();

	  const std::vector<Real>& J = fe.get_fe_map().get_jacobian();

	  for (unsigned int i=0; i<curl_phi.size(); i++)
	    for (unsigned int p=0; p<curl_phi[i].size(); p++)
	      {
		Real dx_dxi   = dxyz_dxi[p](0);
		Real dx_deta  = dxyz_deta[p](0);
		Real dx_dzeta = dxyz_dzeta[p](0);

		Real dy_dxi   = dxyz_dxi[p](1);
		Real dy_deta  = dxyz_deta[p](1);
		Real dy_dzeta = dxyz_dzeta[p](1);

		Real dz_dxi   = dxyz_dxi[p](2);
		Real dz_deta  = dxyz_deta[p](2);
		Real dz_dzeta = dxyz_dzeta[p](2);

		const Real inv_jac = 1.0/J[p];

		/* In 3D: curl(phi) = J^{-1} dx/dxi * curl(\hat{phi}) 

		   dx/dxi = [  dx/dxi  dx/deta  dx/dzeta
		               dy/dxi  dy/deta  dy/dzeta
			       dz/dxi  dz/deta  dz/dzeta ]

		   curl(u) = [ du_z/deta  - du_y/dzeta
                               du_x/dzeta - du_z/dxi
                               du_y/dxi   - du_x/deta ]
		 */
		curl_phi[i][p].slice(0) = inv_jac*( dx_dxi*( dphi_deta[i][p].slice(2)  - 
							     dphi_dzeta[i][p].slice(1)   ) + 
						    dx_deta*( dphi_dzeta[i][p].slice(0) - 
							      dphi_dxi[i][p].slice(2)     ) +
						    dx_dzeta*( dphi_dxi[i][p].slice(1) - 
							       dphi_deta[i][p].slice(0)    ) );

		curl_phi[i][p].slice(1) = inv_jac*( dy_dxi*( dphi_deta[i][p].slice(2) - 
							     dphi_dzeta[i][p].slice(1)  ) +
						    dy_deta*( dphi_dzeta[i][p].slice(0)- 
							      dphi_dxi[i][p].slice(2)    ) +
						    dy_dzeta*( dphi_dxi[i][p].slice(1) - 
							       dphi_deta[i][p].slice(0)   ) );

		curl_phi[i][p].slice(2) = inv_jac*( dz_dxi*( dphi_deta[i][p].slice(2) - 
							     dphi_dzeta[i][p].slice(1)   ) +
						    dz_deta*( dphi_dzeta[i][p].slice(0) -
							      dphi_dxi[i][p].slice(2)     ) +
						    dz_dzeta*( dphi_dxi[i][p].slice(1) - 
							       dphi_deta[i][p].slice(0)    ) );
	      }
	  
	  break;
	}
	
      default:
	libmesh_error();
	
      } // switch(dim)

    return;
  }
示例#7
0
  void H1FETransformation<OutputShape>::map_dphi( const unsigned int dim,
						  const Elem* const,
						  const std::vector<Point>&,
						  const FEGenericBase<OutputShape>& fe,
						  std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient> >& dphi,
						  std::vector<std::vector<OutputShape> >& dphidx,
						  std::vector<std::vector<OutputShape> >& dphidy, 
						  std::vector<std::vector<OutputShape> >& dphidz ) const
  {
    switch(dim)
      {
      case 0: // No derivatives in 0D
	{
	  for (unsigned int i=0; i<dphi.size(); i++)
	    for (unsigned int p=0; p<dphi[i].size(); p++)
	      {
		dphi[i][p] = 0.;
	      }
	  break;
	}

      case 1:
	{
	  const std::vector<std::vector<OutputShape> >& dphidxi = fe.get_dphidxi();

	  const std::vector<Real>& dxidx_map = fe.get_fe_map().get_dxidx();
#if LIBMESH_DIM>1
	  const std::vector<Real>& dxidy_map = fe.get_fe_map().get_dxidy();
#endif
#if LIBMESH_DIM>2
	  const std::vector<Real>& dxidz_map = fe.get_fe_map().get_dxidz();
#endif
	  
	  for (unsigned int i=0; i<dphi.size(); i++)
	    for (unsigned int p=0; p<dphi[i].size(); p++)
	      {
		// dphi/dx    = (dphi/dxi)*(dxi/dx)
		dphi[i][p].slice(0) = dphidx[i][p] = dphidxi[i][p]*dxidx_map[p];
		
#if LIBMESH_DIM>1
		dphi[i][p].slice(1)  = dphidy[i][p] = dphidxi[i][p]*dxidy_map[p];
#endif
#if LIBMESH_DIM>2
		dphi[i][p].slice(2) = dphidz[i][p] = dphidxi[i][p]*dxidz_map[p];
#endif
	      }
	  
	  break;
	}
	
      case 2:
	{
	  const std::vector<std::vector<OutputShape> >& dphidxi = fe.get_dphidxi();
	  const std::vector<std::vector<OutputShape> >& dphideta = fe.get_dphideta();

	  const std::vector<Real>& dxidx_map = fe.get_fe_map().get_dxidx();
	  const std::vector<Real>& dxidy_map = fe.get_fe_map().get_dxidy();
#if LIBMESH_DIM > 2
	  const std::vector<Real>& dxidz_map = fe.get_fe_map().get_dxidz();
#endif

	  const std::vector<Real>& detadx_map = fe.get_fe_map().get_detadx();
	  const std::vector<Real>& detady_map = fe.get_fe_map().get_detady();
#if LIBMESH_DIM > 2
	  const std::vector<Real>& detadz_map = fe.get_fe_map().get_detadz();
#endif

	  for (unsigned int i=0; i<dphi.size(); i++)
	    for (unsigned int p=0; p<dphi[i].size(); p++)
	      {
		// dphi/dx    = (dphi/dxi)*(dxi/dx) + (dphi/deta)*(deta/dx)
		dphi[i][p].slice(0) = dphidx[i][p] = (dphidxi[i][p]*dxidx_map[p] +
						      dphideta[i][p]*detadx_map[p]);
		
		// dphi/dy    = (dphi/dxi)*(dxi/dy) + (dphi/deta)*(deta/dy)
		dphi[i][p].slice(1) = dphidy[i][p] = (dphidxi[i][p]*dxidy_map[p] +
						      dphideta[i][p]*detady_map[p]);

#if LIBMESH_DIM > 2
		// dphi/dz    = (dphi/dxi)*(dxi/dz) + (dphi/deta)*(deta/dz)
		dphi[i][p].slice(2) = dphidz[i][p] = (dphidxi[i][p]*dxidz_map[p] +
						      dphideta[i][p]*detadz_map[p]);
#endif
	      }

	  break;
	}

      case 3: 
	{
	  const std::vector<std::vector<OutputShape> >& dphidxi = fe.get_dphidxi();
	  const std::vector<std::vector<OutputShape> >& dphideta = fe.get_dphideta();
	  const std::vector<std::vector<OutputShape> >& dphidzeta = fe.get_dphidzeta();

	  const std::vector<Real>& dxidx_map = fe.get_fe_map().get_dxidx();
	  const std::vector<Real>& dxidy_map = fe.get_fe_map().get_dxidy();
	  const std::vector<Real>& dxidz_map = fe.get_fe_map().get_dxidz();
	  
	  const std::vector<Real>& detadx_map = fe.get_fe_map().get_detadx();
	  const std::vector<Real>& detady_map = fe.get_fe_map().get_detady();
	  const std::vector<Real>& detadz_map = fe.get_fe_map().get_detadz();
	  
	  const std::vector<Real>& dzetadx_map = fe.get_fe_map().get_dzetadx();
	  const std::vector<Real>& dzetady_map = fe.get_fe_map().get_dzetady();
	  const std::vector<Real>& dzetadz_map = fe.get_fe_map().get_dzetadz();
	  
	  for (unsigned int i=0; i<dphi.size(); i++)
	    for (unsigned int p=0; p<dphi[i].size(); p++)
	      {
		// dphi/dx    = (dphi/dxi)*(dxi/dx) + (dphi/deta)*(deta/dx) + (dphi/dzeta)*(dzeta/dx);
		dphi[i][p].slice(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].slice(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].slice(2) = dphidz[i][p] = (dphidxi[i][p]*dxidz_map[p] +
						      dphideta[i][p]*detadz_map[p] +
						      dphidzeta[i][p]*dzetadz_map[p]);
	      }
	  break;
	}

      default:
	libmesh_error();

      } // switch(dim)

    return;
  }