// Helper function to determine whether a Fad type is real static bool is_fad_real(const FadType& x) { if (x.size() == 0) return true; if (Teuchos::ScalarTraits<ValueT>::isComplex) { if (!is_complex_real(x.val())) return false; for (int i=0; i<x.size(); i++) if (!is_complex_real(x.fastAccessDx(i))) return false; } return true; }
static magnitudeType magnitude(const FadType& a) { #ifdef TEUCHOS_DEBUG TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR( a, "Error, the input value to magnitude(...) a = " << a << " can not be NaN!" ); TEST_FOR_EXCEPTION(is_fad_real(a) == false, std::runtime_error, "Complex magnitude is not a differentiable " "function of complex inputs."); #endif //return std::fabs(a); magnitudeType b(a.size(), Teuchos::ScalarTraits<ValueT>::magnitude(a.val())); if (Teuchos::ScalarTraits<ValueT>::real(a.val()) >= 0) for (int i=0; i<a.size(); i++) b.fastAccessDx(i) = Teuchos::ScalarTraits<ValueT>::magnitude(a.fastAccessDx(i)); else for (int i=0; i<a.size(); i++) b.fastAccessDx(i) = -Teuchos::ScalarTraits<ValueT>::magnitude(a.fastAccessDx(i)); return b; }
void fad_process_fill(const ElemData& e, unsigned int neqn, const std::vector< std::vector<double> >& w_local, const std::vector<FadType>& f_fad, std::vector<double>& f, std::vector< std::vector<double> >& adj) { // Get residual for (unsigned int node=0; node<e.nnode; node++) for (unsigned int eqn=0; eqn<neqn; eqn++) f[e.gid[node]*neqn+eqn] += f_fad[node*neqn+eqn].val(); // Get adjoint for each adjoint direction for (unsigned int col=0; col<w_local.size(); col++) { FadType z = 0.0; for (unsigned int node=0; node<e.nnode; node++) for (unsigned int eqn=0; eqn<neqn; eqn++) z += f_fad[node*neqn+eqn]*w_local[col][node*neqn+eqn]; for (unsigned int node=0; node<e.nnode; node++) for (unsigned int eqn=0; eqn<neqn; eqn++) adj[col][e.gid[node]*neqn+eqn] += z.fastAccessDx(node*neqn+eqn); } }