static int IDANewtonIC(IDAMem IDA_mem) { int retval, mnewt; realtype delnorm, fnorm, fnorm0, oldfnrm, rate; /* Set pointer for vector delnew */ IDA_mem->ida_delnew = IDA_mem->ida_phi[2]; /* Call the linear solve function to get the Newton step, delta. */ retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_delta, IDA_mem->ida_ewt, IDA_mem->ida_yy0, IDA_mem->ida_yp0, IDA_mem->ida_savres); if(retval < 0) return(IDA_LSOLVE_FAIL); if(retval > 0) return(IC_FAIL_RECOV); /* Compute the norm of the step; return now if this is small. */ fnorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_delta, IDA_mem->ida_ewt, SUNFALSE); if(IDA_mem->ida_sysindex == 0) fnorm *= IDA_mem->ida_tscale * SUNRabs(IDA_mem->ida_cj); if(fnorm <= IDA_mem->ida_epsNewt) return(IDA_SUCCESS); fnorm0 = fnorm; /* Initialize rate to avoid compiler warning message */ rate = ZERO; /* Newton iteration loop */ for(mnewt = 0; mnewt < IDA_mem->ida_maxnit; mnewt++) { IDA_mem->ida_nni++; delnorm = fnorm; oldfnrm = fnorm; /* Call the Linesearch function and return if it failed. */ retval = IDALineSrch(IDA_mem, &delnorm, &fnorm); if(retval != IDA_SUCCESS) return(retval); /* Set the observed convergence rate and test for convergence. */ rate = fnorm/oldfnrm; if(fnorm <= IDA_mem->ida_epsNewt) return(IDA_SUCCESS); /* If not converged, copy new step vector, and loop. */ N_VScale(ONE, IDA_mem->ida_delnew, IDA_mem->ida_delta); } /* End of Newton iteration loop */ /* Return either IC_SLOW_CONVRG or recoverable fail flag. */ if(rate <= ICRATEMAX || fnorm < PT1*fnorm0) return(IC_SLOW_CONVRG); return(IC_CONV_FAIL); }
static int IDANewtonIC(IDAMem IDA_mem) { int retval, mnewt; realtype delnorm, fnorm, fnorm0, oldfnrm, rate; //---OPENCOR--- BEGIN unsigned char *uc; //---OPENCOR--- END /* Set pointer for vector delnew */ delnew = phi[2]; /* Call the linear solve function to get the Newton step, delta. */ retval = lsolve(IDA_mem, delta, ewt, yy0, yp0, savres); if(retval < 0) return(IDA_LSOLVE_FAIL); if(retval > 0) return(IC_FAIL_RECOV); /* Compute the norm of the step; return now if this is small. */ fnorm = IDAWrmsNorm(IDA_mem, delta, ewt, FALSE); if(sysindex == 0) fnorm *= tscale*ABS(cj); if(fnorm <= epsNewt) return(IDA_SUCCESS); //---OPENCOR--- BEGIN // Note #1: when trying to retrieve consistent initial conditions, the user may // have provided some (very) bad initial conditions, in which case // fnorm won't have a finite value. This means that we won't be able to // retrieve consistent initial conditions. So, IDA really ought to // check that fnorm has a finite value and, if not, then return with // some error code... // Note #2: the code to test whether a value is finite comes from Qt. It's just // that using it directly would require a C++ compiler while we would // rather stick to a C compiler whenever possible since this will avoid // potential warnings because of differences between C and C++... uc = (unsigned char *) &fnorm; #if Q_BYTE_ORDER == Q_BIG_ENDIAN if (((uc[0] & 0x7F) == 0x7F) && ((uc[1] & 0xF0) == 0xF0)) return IC_CONV_FAIL; #else if (((uc[7] & 0x7F) == 0x7F) && ((uc[6] & 0xF0) == 0xF0)) return IC_CONV_FAIL; #endif //---OPENCOR--- END fnorm0 = fnorm; /* Initialize rate to avoid compiler warning message */ rate = ZERO; /* Newton iteration loop */ for(mnewt = 0; mnewt < maxnit; mnewt++) { nni++; delnorm = fnorm; oldfnrm = fnorm; /* Call the Linesearch function and return if it failed. */ retval = IDALineSrch(IDA_mem, &delnorm, &fnorm); if(retval != IDA_SUCCESS) return(retval); /* Set the observed convergence rate and test for convergence. */ rate = fnorm/oldfnrm; if(fnorm <= epsNewt) return(IDA_SUCCESS); /* If not converged, copy new step vector, and loop. */ N_VScale(ONE, delnew, delta); } /* End of Newton iteration loop */ /* Return either IC_SLOW_CONVRG or recoverable fail flag. */ if(rate <= ICRATEMAX || fnorm < PT1*fnorm0) return(IC_SLOW_CONVRG); return(IC_CONV_FAIL); }
static int IDANewtonIC(IDAMem IDA_mem) { int retval, mnewt, is; realtype delnorm, fnorm, fnorm0, oldfnrm, rate; booleantype sensi_sim; /* Are we computing sensitivities with the IDA_SIMULTANEOUS approach? */ sensi_sim = (sensi && (ism==IDA_SIMULTANEOUS)); /* Set pointer for vector delnew */ delnew = phi[2]; /* Call the linear solve function to get the Newton step, delta. */ retval = lsolve(IDA_mem, delta, ewt, yy0, yp0, savres); if(retval < 0) return(IDA_LSOLVE_FAIL); if(retval > 0) return(IC_FAIL_RECOV); /* Compute the norm of the step. */ fnorm = IDAWrmsNorm(IDA_mem, delta, ewt, FALSE); /* Call the lsolve function to get correction vectors deltaS. */ if (sensi_sim) { for(is=0;is<Ns;is++) { retval = lsolve(IDA_mem, deltaS[is], ewtS[is], yy0, yp0, savres); if(retval < 0) return(IDA_LSOLVE_FAIL); if(retval > 0) return(IC_FAIL_RECOV); } /* Update the norm of delta. */ fnorm = IDASensWrmsNormUpdate(IDA_mem, fnorm, deltaS, ewtS, FALSE); } /* Test for convergence. Return now if the norm is small. */ if(sysindex == 0) fnorm *= tscale*SUNRabs(cj); if(fnorm <= epsNewt) return(IDA_SUCCESS); fnorm0 = fnorm; /* Initialize rate to avoid compiler warning message */ rate = ZERO; /* Newton iteration loop */ for(mnewt = 0; mnewt < maxnit; mnewt++) { nni++; delnorm = fnorm; oldfnrm = fnorm; /* Call the Linesearch function and return if it failed. */ retval = IDALineSrch(IDA_mem, &delnorm, &fnorm); if(retval != IDA_SUCCESS) return(retval); /* Set the observed convergence rate and test for convergence. */ rate = fnorm/oldfnrm; if(fnorm <= epsNewt) return(IDA_SUCCESS); /* If not converged, copy new step vector, and loop. */ N_VScale(ONE, delnew, delta); if(sensi_sim) { /* Update the iteration's step for sensitivities. */ for(is=0; is<Ns; is++) N_VScale(ONE, delnewS[is], deltaS[is]); } } /* End of Newton iteration loop */ /* Return either IC_SLOW_CONVRG or recoverable fail flag. */ if(rate <= ICRATEMAX || fnorm < PT1*fnorm0) return(IC_SLOW_CONVRG); return(IC_CONV_FAIL); }