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
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'