Example #1
0
void Diffusion::flux_matrix(const FEMesh  *mesh,
			    const Element *el,
			    const ElementFuncNodeIterator &j,
			    const Flux    *flux,
			    const MasterPosition &pt,
			    double time,
			    SmallSystem *fluxdata)
  const
{
  // The atom flux matrix M_{ij} multiplies the vector of nodal
  // concentrations to give the vector atom current J at point pt.
  // M_{ij} = -D_{ik} grad_k N_j
  // J_i = -M_{ij} T_j
  // where N_j is the shapefunction at node j.
  // printf("flux");
  if (*flux != *atom_flux) {
    throw ErrProgrammingError("Unexpected flux", __FILE__, __LINE__);
  }

  double sf   = j.shapefunction( pt );
  double dsf0 = j.dshapefunction( 0, pt );
  double dsf1 = j.dshapefunction( 1, pt );
#if DIM==3
  double dsf2 = j.dshapefunction( 2, pt );
#endif

  const SymmMatrix3 cond( conductivitytensor( mesh, el, pt ) );

  // Loop over flux components.  Loop over all components, even if
  // the flux is in-plane, because the out-of-plane components of
  // the flux matrix are used to construct the constraint equation.

  for(VectorFieldIterator i; !i.end(); ++i){
#if DIM==2
    // in-plane concentration gradient contributions
    fluxdata->stiffness_matrix_element( i, concentration, j ) -=
                  cond(i.integer(), 0) * dsf0 + cond(i.integer(), 1) * dsf1;

    // out-of-plane concentration gradient contribution
    if(!concentration->in_plane(mesh))
      fluxdata->stiffness_matrix_element(i, concentration->out_of_plane(), j)
                                          -= cond(i.integer(), 2) * sf;

#elif DIM==3
    fluxdata->stiffness_matrix_element( i, concentration, j ) -=
                              cond( i.integer(), 0 ) * dsf0 +
                              cond( i.integer(), 1 ) * dsf1 +
                              cond( i.integer(), 2 ) * dsf2;
#endif

  }
} // end of 'Diffusion::flux_matrix'
Example #2
0
void MassDensityProp::second_time_deriv_matrix(const FEMesh *mesh,
					       const Element *lmnt,
					       const Equation *eqn,
					       const ElementFuncNodeIterator &eni,
					       const MasterPosition &mpos,
					       double time,
					       SmallSystem *eqdata) const {

  // Optional -- check that the equation is the right one.
  double shapeFuncVal = eni.shapefunction(mpos);
  for(IteratorP component = eqn->iterator(); !component.end(); ++component) {
    eqdata->mass_matrix_element(component, disp, component, eni) -= rho_ * shapeFuncVal;
  }
}
Example #3
0
void Mobility::first_time_deriv_matrix(const FEMesh *mesh,
					const Element *lmnt,
					const Equation *eqn,
					const ElementFuncNodeIterator &eni,
					const MasterPosition &mpos,
					double time,
					SmallSystem *eqdata) const {

  double shapeFuncVal = eni.shapefunction( mpos );
  for(IteratorP eqncomp = eqn->iterator(); !eqncomp.end(); ++eqncomp) {
    // Kinetic coefficient is unity.
    eqdata->damping_matrix_element(eqncomp,concentration,eqncomp,eni) += \
      shapeFuncVal;
  }
}
Example #4
0
void NonlinearHeatSource::force_deriv_matrix(const FEMesh   *mesh,
					     const Element  *element,
					     const Equation *eqn,
					     const ElementFuncNodeIterator &j,
					     const MasterPosition &point,
					     double time,
					     SmallSystem *eqndata ) const
{
  double fieldVal, funcDerivVal, shapeFuncVal;
  Coord  coord;

  // first compute the current value of the temperature field at the gauss point

  fieldVal = 0.0;
  for(CleverPtr<ElementFuncNodeIterator> node(element->funcnode_iterator());
      !node->end(); ++*node){
    shapeFuncVal = node->shapefunction( point );
    fieldVal += shapeFuncVal * (*temperature)( *node )->value( mesh );
  }

  // compute the value of the deriv of the nonlinear source function
  // using the world coordinates and the value of the temperature field

  coord = element->from_master( point );

#if DIM==2
  funcDerivVal = nonlin_heat_source_deriv_wrt_temperature( coord.x, coord.y, 0.0,
							   time, fieldVal );
#elif DIM==3
  funcDerivVal = nonlin_heat_source_deriv_wrt_temperature( coord.x, coord.y, coord.z,
							   time, fieldVal );
#endif

  // compute the value of the jth shape function at gauss point point and
  // add its contribution f(point)*phi_j(point) to the small stiffness-like matrix

  shapeFuncVal = j.shapefunction( point );

  for (IteratorP eqncomp = eqn->iterator(); !eqncomp.end(); ++eqncomp)
    eqndata->force_deriv_matrix_element( eqncomp, temperature, j )
                -= funcDerivVal * shapeFuncVal;

} // NonlinearHeatSource::force_deriv_matrix
void NonlinearForceDensity::force_deriv_matrix(const FEMesh   *mesh,
					       const Element  *element,
					       const Equation *eqn,
					       const ElementFuncNodeIterator &j,
					       const MasterPosition &point,
					       double time,
					       SmallSystem *eqndata) const
{
  SmallMatrix forceDeriv(3);
  DoubleVec fieldVal(3);
  double shapeFuncVal;
  Coord  coord;

  // first compute the current value of the displacement field at the gauss point

  fieldVal[0] = fieldVal[1] = 0.0;
#if DIM==3
  fieldVal[2] = 0.0;
#endif
  for(CleverPtr<ElementFuncNodeIterator> node(element->funcnode_iterator());
      !node->end(); ++*node){
    shapeFuncVal = node->shapefunction( point );
    fieldVal[0] += shapeFuncVal * (*displacement)( *node, 0 )->value( mesh );
    fieldVal[1] += shapeFuncVal * (*displacement)( *node, 1 )->value( mesh );
#if DIM==3
    fieldVal[2] += shapeFuncVal * (*displacement)( *node, 2 )->value( mesh );
#endif
  }

  // now compute the value of the force density derivative function
  // for the current coordinate x,y,z, time and displacement,
  // the nonlinear force density derivative function returns the
  // corresponding force derivative value in the array 'forceDeriv',
  // the function definition is given in USER_CODE.C

  coord = element->from_master( point );

#if DIM==2
  nonlin_force_density_deriv( coord.x, coord.y, 0.0,
			      time, fieldVal, forceDeriv );
#elif DIM==3
  nonlin_force_density_deriv( coord.x, coord.y, coord.z,
			      time, fieldVal, forceDeriv );
#endif

  // compute the value of the jth shape function at gauss point point and add
  // its contribution Df(point,field)*phi_j(point) to the small mass-like matrix

  shapeFuncVal = j.shapefunction( point );

  for(IteratorP eqncomp = eqn->iterator(); !eqncomp.end(); ++eqncomp) {
    int eqno = eqncomp.integer();

    for (IteratorP fieldcomp = displacement->iterator(); !fieldcomp.end(); ++fieldcomp)
    { // TODO: get rid of this loop, and write component contributions explicitly
      int fieldno = fieldcomp.integer();

      eqndata->force_deriv_matrix_element( eqncomp, displacement, fieldcomp, j )
	-= forceDeriv( eqno, fieldno ) * shapeFuncVal;
    }
  }

} // end of 'NonlinearForceDensity::force_deriv_matrix'
Example #6
0
void CLargeStrainElasticity::flux_matrix(const FEMesh  *mesh,
					 const Element *element,
					 const ElementFuncNodeIterator &node,
					 const Flux    *flux,
					 const MasterPosition &pt,
					 double time,
					 SmallSystem *fluxmtx) const
{
  int (*ij2voigt)(int,int) = &SymTensorIndex::ij2voigt; // shorter func name
  SmallMatrix dU(3);	// gradient of displacement
  double Fval;		// the value of the shape function (for node)
  DoubleVec dF(3);	// and its derivative at the given pt
  bool inplane = false;	// needed both in 2D & 3D versions regardless,
			// passed to contract_C_dU_dF

#if DIM==2
  // in 2D, check if it is an in-plane eqn or a plane-flux eqn.
  static CompoundField *displacement =
    dynamic_cast<CompoundField*>(Field::getField("Displacement"));
  inplane = displacement->in_plane( mesh );
#endif

  // check for unexpected flux, flux should be a stress flux
  if (*flux != *stress_flux) {
    throw ErrProgrammingError("Unexpected flux", __FILE__, __LINE__);
  }

  // evaluate the shape function and its gradient (of node) at the given pt
  Fval  = node.shapefunction( pt );     // value of the shape function
  dF[0] = node.dshapefunction( 0, pt ); // x-deriv of the shape function
  dF[1] = node.dshapefunction( 1, pt ); // y-deriv of the shape function
#if DIM==3
  dF[2] = node.dshapefunction( 2, pt ); // z-deriv of the shape function
#endif

  computeDisplacementGradient( mesh, element, pt, dU );

  const Cijkl CC = cijkl( mesh, element, pt ); // elasticity modulus

  // add the flux contributions to stiffness matrix element

  // k_indx is needed for fluxmtx->stifness_matrix_element function,
  // which does not take int k as argument
  VectorFieldIndex k_indx;

  for (SymTensorIterator ij_iter; !ij_iter.end(); ++ij_iter) {
    int k0, k1, k2, ij = ij_iter.integer();
    double nonlinear_part; // to store the sum from the nonlinear terms

    // TODO: Use tensor iterators for k0, k1, k2.

#if DIM==2

    // sum CC(i,j,k,l)*dF(l),  k=0   over l=0,1, then add to stiffness_mtx
    k_indx.set( 0 );
    k0 = ij2voigt( 0,0 );
    k1 = ij2voigt( 0,1 );
    nonlinear_part = contract_C_dU_dF(CC, dU, dF, ij, 0, inplane ); // at ij, k=0
    fluxmtx->stiffness_matrix_element( ij_iter, displacement, k_indx, node )
      += CC( ij,k0 ) * dF[0] + CC( ij,k1 ) * dF[1]
      + nonlinear_part;


    // sum CC(i,j,k,l)*dF(l),  k=1   over l=0,1, then add to stiffness_mtx
    k_indx.set( 1 ); 
    k0 = ij2voigt( 1,0 );
    k1 = ij2voigt( 1,1 );
    nonlinear_part = contract_C_dU_dF( CC, dU, dF, ij, 1, inplane ); // at ij, k=1
    fluxmtx->stiffness_matrix_element( ij_iter, displacement, k_indx, node )
      += CC( ij,k0 ) * dF[0] + CC( ij,k1 ) * dF[1]
      + nonlinear_part;

#elif DIM==3

    // sum CC(i,j,k,l)*dF(l),  k=0   over l=0,1,2 then add to stiffness_mtx
    k_indx.set( 0 );
    k0 = ij2voigt( 0,0 ); 
    k1 = ij2voigt( 0,1 );
    k2 = ij2voigt( 0,2 );
    nonlinear_part = contract_C_dU_dF( CC, dU, dF, ij, 0, inplane ); // at ij, k=0
    fluxmtx->stiffness_matrix_element( ij_iter, displacement, k_indx, node )
      += CC( ij,k0 ) * dF[0] + CC( ij,k1 ) * dF[1] + CC( ij,k2 ) * dF[2]
      + nonlinear_part;

    // sum CC(i,j,k,l)*dF(l),  k=1   over l=0,1,2 then add to stiffness_mtx
    k_indx.set( 1 );
    k0 = ij2voigt( 1,0 );
    k1 = ij2voigt( 1,1 ); 
    k2 = ij2voigt( 1,2 );
    nonlinear_part = contract_C_dU_dF( CC, dU, dF, ij, 1, inplane ); // at ij, k=1
    fluxmtx->stiffness_matrix_element( ij_iter, displacement, k_indx, node )
      += CC( ij,k0 ) * dF[0] + CC( ij,k1 ) * dF[1] + CC( ij,k2 ) * dF[2]
      + nonlinear_part;

    // sum CC(i,j,k,l)*dF(l),  k=2   over l=0,1,2 then add to stiffness_mtx
    k_indx.set( 2 );
    k0 = ij2voigt( 2,0 ); 
    k1 = ij2voigt( 2,1 ); 
    k2 = ij2voigt( 2,2 );
    nonlinear_part = contract_C_dU_dF( CC, dU, dF, ij, 2, inplane ); // at ij, k=2

    fluxmtx->stiffness_matrix_element( ij_iter, displacement, k_indx, node )
      += CC( ij,k0 ) * dF[0] + CC( ij,k1 ) * dF[1] + CC( ij,k2 ) * dF[2]
      + nonlinear_part;
#endif

#if DIM==2

    if ( !inplane ) // now contributions from z-deriv of displacement field
    {
      Field *disp_z_deriv = displacement->out_of_plane();

      for(IteratorP k_iter = disp_z_deriv->iterator( ALL_INDICES ); !k_iter.end(); ++k_iter)
      {
	double diag_factor = ( k_iter.integer()==2 ? 1.0 : 0.5 );

	k2 = ij2voigt( 2, k_iter.integer() );

	fluxmtx->stiffness_matrix_element( ij_iter, disp_z_deriv, k_iter, node )
 	             += diag_factor * Fval * CC( ij,k2 );
      }
    } // end of 'if (!inplane)'
#endif
  } // end of loop over ij

} // end of 'CLargeStrainElasticity::flux_matrix'