示例#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'
示例#2
0
void AtomFluxJumpTest::force_deriv_matrix(const FEMesh* mesh,
					  const Element* element,
					  const Equation* eqn,
					  const ElementFuncNodeIterator &efi,
					  const MasterPosition& gpt,
					  double time, SmallSystem *eqndata) 
  const 
{
  std::cerr << "AtomFluxJumpTest::force_deriv_matrix called." << std::endl;
  
  FuncNode *left,*right;

  left = dynamic_cast<FuncNode*>(efi.leftnode());
  right = dynamic_cast<FuncNode*>(efi.rightnode());

  std::cerr << "Left: " << *left << std::endl; 

  std::cerr << "Right: " << *right << std::endl;

}
示例#3
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;
  }
}
示例#4
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;
  }
}
示例#5
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'
示例#7
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'
示例#8
0
void EqnProperty::force_deriv_matrix(const FEMesh *mesh, const Element *element,
				     const Equation *eqn,
				     const ElementFuncNodeIterator &node,
				     const MasterPosition &pt, double time,
				     SmallSystem *eqndata)  const
{
  int nrows = eqndata->nrows();
  int ncols = eqndata->ncols();
  DoubleVec forceVec0(nrows), forceVec1(nrows);
  SmallSystem eqndata0( nrows, ncols );
  SmallSystem eqndata1( nrows, ncols );

  // Get the current subproblem, to check if the fields are active
  CSubProblem *subproblem = mesh->getCurrentSubProblem();
  if ( !subproblem )
    throw ErrProgrammingError("Current subproblem not defined",
			      __FILE__, __LINE__);

  // Loop over all the fields (that the node might have)
  for(std::vector<Field*>::size_type fi=0; fi<Field::all().size(); fi++)
  {
    Field *field = &( *Field::all()[fi] );
    if (node.hasField( *field ) && field->is_active( subproblem ))
    {
      // Loop over field components
      for(IteratorP fieldcomp=field->iterator(ALL_INDICES);
	  !fieldcomp.end(); ++fieldcomp)
      {
	DegreeOfFreedom *dof = (*field)(node, fieldcomp.integer());
	double oldValue = dof->value( mesh );

	// Scale eps by original value for robustness
	double eps = max(min_eps, fabs(oldValue) * deriv_eps);
	double upValue = oldValue + eps;
	double dnValue = oldValue - eps;

	// First compute forceVec0 = f(u-eps)
	dof->setValue( mesh, dnValue );
	force_value(mesh, element, eqn, pt, time, &eqndata0);
	forceVec0 = eqndata0.forceVector();

	// Now compute forceVec1 = f(u+eps)
	dof->setValue( mesh, upValue );
	force_value(mesh, element, eqn, pt, time, &eqndata1);
	forceVec1 = eqndata1.forceVector();
	dof->setValue( mesh, oldValue );

	// Compute the numerical derivative: (f1 - f0) / (2*eps)
	forceVec1 -= forceVec0;
	forceVec1 /= (upValue - dnValue);

	// Assign the derivative value to force_deriv_matrix
	for(IteratorP eqncomp = eqn->iterator(); !eqncomp.end(); ++eqncomp)
	  eqndata->force_deriv_matrix_element( eqncomp, field, fieldcomp, node )
	    += forceVec1[ eqncomp.integer() ];

	zero( eqndata0.forceVector() );
	zero( eqndata1.forceVector() );
      } // loop over field components
    } // end if (node.hasfield())
  } // loop over all fields

} // end of force_deriv_matrix
示例#9
0
void FluxProperty::flux_matrix(const FEMesh *mesh, const Element *element,
			       const ElementFuncNodeIterator  &node,
			       const Flux *flux, const MasterPosition &pt,
			       double time, SmallSystem *fluxdata)
  const
{
#ifdef _OPENMP
  bool& recurse = recurse_flags[omp_get_thread_num()];
#endif

  if(recurse) {
    return;
  }
  recurse = true;

  int nrows = fluxdata->nrows();
  int ncols = fluxdata->ncols();
  DoubleVec fluxVec0(nrows);
  DoubleVec fluxVec1(nrows);
  SmallSystem fluxdata0( nrows, ncols );
  SmallSystem fluxdata1( nrows, ncols );
  CSubProblem *subproblem = mesh->getCurrentSubProblem();

  // Get the current subproblem, to check if the fields are active
  if ( !subproblem )
    throw ErrProgrammingError("Current subproblem not defined",
			      __FILE__, __LINE__);

  // Loop over all the fields (that the node might have)
  for (std::vector<Field*>::size_type fi=0; fi<Field::all().size(); fi++)
  {
    Field *field = &( *Field::all()[fi] );
    if (node.hasField( *field ) && field->is_active( subproblem ))
    {
      // Loop over field components
      for(IteratorP fieldcomp=field->iterator(ALL_INDICES);
	  !fieldcomp.end(); ++fieldcomp)
      {
	DegreeOfFreedom *dof = (*field)(node, fieldcomp.integer());
	double oldValue = dof->value( mesh );

	// Scale eps by original value for robustness
	double eps = max(min_eps, fabs(oldValue)* deriv_eps); 

	double upValue = oldValue + eps;
	double dnValue = oldValue - eps;

	// First compute fluxVec0 = sigma(u-eps)
	dof->setValue( mesh, dnValue );
	static_flux_value(mesh, element, flux, pt, time, &fluxdata0);
	fluxVec0 = fluxdata0.fluxVector();

	// Now compute fluxVec1 = sigma(u+eps)
	dof->setValue( mesh, upValue );
	static_flux_value(mesh, element, flux, pt, time, &fluxdata1);
	fluxVec1 = fluxdata1.fluxVector();

	// Reset to original value!
	dof->setValue( mesh, oldValue );

	// Compute the numerical derivative: (fluxVec1 - fluxVec0) / 2*eps
	fluxVec1 -= fluxVec0;
	fluxVec1 /= (upValue - dnValue);

	// Assign the derivative value to flux_matrix
	for(IteratorP fluxcomp = flux->iterator(ALL_INDICES);
	    !fluxcomp.end(); ++fluxcomp)
	  fluxdata->stiffness_matrix_element( fluxcomp, field, fieldcomp, node )
	    += fluxVec1[ fluxcomp.integer() ];

	zero( fluxdata0.fluxVector() );
	zero( fluxdata1.fluxVector() );
      } // loop over field components
    } // end if (node.hasfield())
  } // loop over all fields

} // end of 'FluxProperty::flux_matrix'