Exemplo n.º 1
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
Exemplo n.º 2
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'