@@ -545,20 +545,10 @@ void ReactorNet::preconditionerSetup(double t, double* y, double gamma)
545545 updateState (yCopy.data ());
546546 // Create jacobian triplet vector
547547 vector<Eigen::Triplet<double >> jac_vector;
548- vector<size_t > jstarts;
549- // Get jacobians and give elements to preconditioners
550- jstarts.push_back (jac_vector.size ());
551- for (size_t i = 0 ; i < m_reactors.size (); i++) {
552- m_reactors[i]->buildJacobian (jac_vector);
553- jstarts.push_back (jac_vector.size ());
554- }
548+ buildJacobian (jac_vector);
555549 // Add to preconditioner with offset
556- for (size_t i=0 ; i < m_reactors.size (); i++) {
557- for (size_t j = jstarts[i]; j < jstarts[i+1 ]; j++) {
558- auto it = jac_vector[j];
559- precon->setValue (it.row () + m_start[i], it.col () + m_start[i],
560- it.value ());
561- }
550+ for (auto it : jac_vector) {
551+ precon->setValue (it.row (), it.col (), it.value ());
562552 }
563553 // post reactor setup operations
564554 precon->setup ();
@@ -587,4 +577,72 @@ void ReactorNet::checkPreconditionerSupported() const {
587577 }
588578}
589579
580+ void ReactorNet::buildJacobian (vector<Eigen::Triplet<double >>& jacVector)
581+ {
582+ // network must be initialized for the jacobian
583+ if (! m_init) {
584+ initialize ();
585+ }
586+ // Create jacobian triplet vector
587+ vector<size_t > jstarts;
588+ // Get jacobians and give elements to preconditioners
589+ jstarts.push_back (jacVector.size ());
590+ for (size_t i = 0 ; i < m_reactors.size (); i++) {
591+ m_reactors[i]->buildJacobian (jacVector);
592+ jstarts.push_back (jacVector.size ());
593+ }
594+ // Add to preconditioner with offset
595+ for (size_t i=0 ; i < m_reactors.size (); i++) {
596+ for (size_t j = jstarts[i]; j < jstarts[i+1 ]; j++) {
597+ auto it = jacVector[j];
598+ auto newTrip = Eigen::Triplet<double >(it.row () + m_start[i], it.col ()
599+ + m_start[i], it.value ());
600+ jacVector[j] = newTrip;
601+ }
602+ }
603+ }
604+
605+ Eigen::SparseMatrix<double > ReactorNet::finiteDifferenceJacobian ()
606+ {
607+ // network must be initialized for the jacobian
608+ if (! m_init) {
609+ initialize ();
610+ }
611+
612+ // clear former jacobian elements
613+ vector<Eigen::Triplet<double >> jac_trips;
614+
615+ // Get the current state
616+ Eigen::ArrayXd yCurrent (m_nv);
617+ getState (yCurrent.data ());
618+
619+ Eigen::ArrayXd yPerturbed = yCurrent;
620+ Eigen::ArrayXd ydotCurrent (m_nv), ydotPerturbed (m_nv);
621+
622+ eval (m_time, yCurrent.data (), ydotCurrent.data (), m_sens_params.data ());
623+ double rel_perturb = std::sqrt (std::numeric_limits<double >::epsilon ());
624+
625+ for (size_t j = 0 ; j < m_nv; j++) {
626+ yPerturbed = yCurrent;
627+ double delta_y = std::max (std::abs (yCurrent[j]), 1000 * m_atols) * rel_perturb;
628+ yPerturbed[j] += delta_y;
629+ ydotPerturbed = 0 ;
630+ eval (m_time, yPerturbed.data (), ydotPerturbed.data (), m_sens_params.data ());
631+ // d ydot_i/dy_j
632+ for (size_t i = 0 ; i < m_nv; i++) {
633+ if (ydotCurrent[i] != ydotPerturbed[i]) {
634+ jac_trips.emplace_back (
635+ static_cast <int >(i), static_cast <int >(j),
636+ (ydotPerturbed[i] - ydotCurrent[i]) / delta_y);
637+ }
638+ }
639+ }
640+ updateState (yCurrent.data ());
641+
642+ Eigen::SparseMatrix<double > jac (m_nv, m_nv);
643+ jac.setFromTriplets (jac_trips.begin (), jac_trips.end ());
644+ return jac;
645+ }
646+
647+
590648}
0 commit comments