ida.c

Go to the documentation of this file.
00001 /*
00002  * -----------------------------------------------------------------
00003  * $Revision: 1.3 $
00004  * $Date: 2006/10/05 22:09:14 $
00005  * ----------------------------------------------------------------- 
00006  * Programmer(s): Alan Hindmarsh, Radu Serban and Aaron Collier @ LLNL
00007  * -----------------------------------------------------------------
00008  * Copyright (c) 2002, The Regents of the University of California.
00009  * Produced at the Lawrence Livermore National Laboratory.
00010  * All rights reserved.
00011  * For details, see the LICENSE file.
00012  * -----------------------------------------------------------------
00013  * This is the implementation file for the main IDA solver.
00014  * It is independent of the linear solver in use.
00015  * -----------------------------------------------------------------
00016  *
00017  * EXPORTED FUNCTIONS
00018  * ------------------
00019  *   Creation, allocation and re-initialization functions
00020  *       IDACreate
00021  *       IDAMalloc
00022  *       IDAReInit
00023  *       IDARootInit
00024  *   Main solver function
00025  *       IDASolve
00026  *   Interpolated output and extraction functions
00027  *       IDAGetSolution
00028  *   Deallocation functions
00029  *       IDAFree
00030  *
00031  * PRIVATE FUNCTIONS
00032  * -----------------
00033  *       IDACheckNvector
00034  *   Memory allocation/deallocation
00035  *       IDAAllocVectors
00036  *       IDAFreeVectors
00037  *   Initial setup
00038  *       IDAInitialSetup
00039  *       IDAEwtSet
00040  *       IDAEwtSetSS
00041  *       IDAEwtSetSV
00042  *   Stopping tests
00043  *       IDAStopTest1
00044  *       IDAStopTest2
00045  *   Error handler
00046  *       IDAHandleFailure
00047  *   Main IDAStep function
00048  *       IDAStep
00049  *       IDASetCoeffs
00050  *   Nonlinear solver functions
00051  *       IDANls
00052  *       IDAPredict
00053  *       IDANewtonIter
00054  *   Error test
00055  *       IDATestError
00056  *       IDARestore
00057  *   Handler for convergence and/or error test failures
00058  *       IDAHandleNFlag
00059  *       IDAReset
00060  *   Function called after a successful step
00061  *       IDACompleteStep
00062  *   Norm functions
00063  *       IDAWrmsNorm
00064  *   Functions for rootfinding
00065  *       IDARcheck1
00066  *       IDARcheck2
00067  *       IDARcheck3
00068  *       IDARootfind
00069  *   IDA Error message handling functions 
00070  *       IDAProcessError
00071  *       IDAErrHandler
00072  * -----------------------------------------------------------------
00073  */
00074 
00075 /* 
00076  * =================================================================
00077  * IMPORTED HEADER FILES
00078  * =================================================================
00079  */
00080 
00081 #include <stdio.h>
00082 #include <stdlib.h>
00083 #include <stdarg.h>
00084 
00085 #include "ida_impl.h"
00086 #include "sundials_math.h"
00087 
00088 /* 
00089  * =================================================================
00090  * MACRO DEFINITIONS
00091  * =================================================================
00092  */
00093 
00094 /* Macro: loop */
00095 #define loop for(;;)
00096 
00097 /* 
00098  * =================================================================
00099  * IDAS PRIVATE CONSTANTS
00100  * =================================================================
00101  */
00102 
00103 #define ZERO      RCONST(0.0)    /* real 0.0    */
00104 #define HALF      RCONST(0.5)    /* real 0.5    */
00105 #define QUARTER   RCONST(0.25)   /* real 0.25   */
00106 #define TWOTHIRDS RCONST(0.667)  /* real 2/3    */
00107 #define ONE       RCONST(1.0)    /* real 1.0    */
00108 #define ONEPT5    RCONST(1.5)    /* real 1.5    */
00109 #define TWO       RCONST(2.0)    /* real 2.0    */
00110 #define FOUR      RCONST(4.0)    /* real 4.0    */
00111 #define FIVE      RCONST(5.0)    /* real 5.0    */
00112 #define TEN       RCONST(10.0)   /* real 10.0   */
00113 #define TWELVE    RCONST(12.0)   /* real 12.0   */
00114 #define TWENTY    RCONST(20.0)   /* real 20.0   */
00115 #define HUNDRED   RCONST(100.0)  /* real 100.0  */
00116 #define PT9       RCONST(0.9)    /* real 0.9    */
00117 #define PT99      RCONST(0.99)   /* real 0.99   */
00118 #define PT1       RCONST(0.1)    /* real 0.1    */
00119 #define PT01      RCONST(0.01)   /* real 0.01   */
00120 #define PT001     RCONST(0.001)  /* real 0.001  */
00121 #define PT0001    RCONST(0.0001) /* real 0.0001 */
00122 
00123 /* 
00124  * =================================================================
00125  * IDAS ROUTINE-SPECIFIC CONSTANTS
00126  * =================================================================
00127  */
00128 
00129 /* 
00130  * Control constants for lower-level functions used by IDASolve 
00131  * ------------------------------------------------------------
00132  */
00133 
00134 /* IDAStep control constants */
00135 
00136 #define PREDICT_AGAIN 20
00137 
00138 /* Return values for lower level routines used by IDASolve */
00139 
00140 #define IDA_RES_RECVR    +1
00141 #define IDA_LSETUP_RECVR +2
00142 #define IDA_LSOLVE_RECVR +3
00143 
00144 #define IDA_NCONV_RECVR  +4
00145 #define IDA_CONSTR_RECVR +5
00146 #define CONTINUE_STEPS   +99
00147 
00148 /* IDACompleteStep constants */
00149 
00150 #define UNSET            -1
00151 #define LOWER            +1 
00152 #define RAISE            +2 
00153 #define MAINTAIN         +3
00154 
00155 /* IDATestError constants */
00156 
00157 #define ERROR_TEST_FAIL  +7
00158 
00159 /*
00160  * Control constants for lower-level rootfinding functions
00161  * -------------------------------------------------------
00162  */
00163 
00164 #define RTFOUND          +1
00165 #define INITROOT         +2
00166 #define CLOSERT          +3
00167 #define ZERODETACHING    +4
00168 #define MASKED           55
00169 /*
00170  * Algorithmic constants
00171  * ---------------------
00172  */
00173 
00174 #define MXNCF           10  /* max number of convergence failures allowed */
00175 #define MXNEF           10  /* max number of error test failures allowed  */
00176 #define MAXNH            5  /* max. number of h tries in IC calc. */
00177 #define MAXNJ            4  /* max. number of J tries in IC calc. */
00178 #define MAXNI           10  /* max. Newton iterations in IC calc. */
00179 #define EPCON RCONST(0.33)  /* Newton convergence test constant */
00180 
00181 /* IDANewtonIter constants */
00182 
00183 #define MAXIT   4
00184 #define RATEMAX RCONST(0.9)
00185 #define XRATE   RCONST(0.25)        
00186 
00187 /* 
00188  * =================================================================
00189  * PRIVATE FUNCTION PROTOTYPES
00190  * =================================================================
00191  */
00192 
00193 static booleantype IDACheckNvector(N_Vector tmpl);
00194 
00195 /* Memory allocation/deallocation */
00196 
00197 static booleantype IDAAllocVectors(IDAMem IDA_mem, N_Vector tmpl, int tol);
00198 static void IDAFreeVectors(IDAMem IDA_mem);
00199 
00200 /* Initial setup */
00201 
00202 int IDAInitialSetup(IDAMem IDA_mem);
00203 static int IDAEwtSetSS(IDAMem IDA_mem, N_Vector ycur, N_Vector weight);
00204 static int IDAEwtSetSV(IDAMem IDA_mem, N_Vector ycur, N_Vector weight);
00205 
00206 /* Main IDAStep function */
00207 
00208 static int IDAStep(IDAMem IDA_mem);
00209 
00210 /* Function called at beginning of step */
00211 
00212 static void IDASetCoeffs(IDAMem IDA_mem, realtype *ck);
00213 
00214 /* Nonlinear solver functions */
00215 
00216 static void IDAPredict(IDAMem IDA_mem);
00217 static int IDANls(IDAMem IDA_mem);
00218 static int IDANewtonIter(IDAMem IDA_mem);
00219 
00220 /* Error test */
00221 
00222 static int IDATestError(IDAMem IDA_mem, realtype ck, 
00223                         realtype *err_k, realtype *err_km1);
00224 
00225 /* Handling of convergence and/or error test failures */
00226 
00227 static void IDARestore(IDAMem IDA_mem, realtype saved_t);
00228 static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype err_km1,
00229                           long int *ncfnPtr, int *ncfPtr, long int *netfPtr, int *nefPtr);
00230 static void IDAReset(IDAMem IDA_mem);
00231 
00232 /* Function called after a successful step */
00233 
00234 static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1);
00235 
00236 /* Stopping tests and failure handling */
00237 
00238 static int IDAStopTest1(IDAMem IDA_mem, realtype tout,realtype *tret, 
00239                         N_Vector yret, N_Vector ypret, int itask);
00240 static int IDAStopTest2(IDAMem IDA_mem, realtype tout, realtype *tret, 
00241                         N_Vector yret, N_Vector ypret, int itask);
00242 static int IDAHandleFailure(IDAMem IDA_mem, int sflag);
00243 
00244 /* Functions for rootfinding */
00245 
00246 static int IDARcheck1(IDAMem IDA_mem);
00247 static int IDARcheck2(IDAMem IDA_mem);
00248 static int IDARcheck3(IDAMem IDA_mem);
00249 static int IDARootfind(IDAMem IDA_mem);
00250 
00251 /* Norm functions */
00252 
00253 realtype IDAWrmsNorm(IDAMem IDA_mem, N_Vector x, N_Vector w, booleantype mask);
00254 
00255 /* 
00256  * =================================================================
00257  * EXPORTED FUNCTIONS IMPLEMENTATION
00258  * =================================================================
00259  */
00260 
00261 /* 
00262  * -----------------------------------------------------------------
00263  * Creation, allocation and re-initialization functions
00264  * -----------------------------------------------------------------
00265  */
00266 
00267 /* 
00268  * IDACreate
00269  *
00270  * IDACreate creates an internal memory block for a problem to 
00271  * be solved by IDA.
00272  * If successful, IDACreate returns a pointer to the problem memory. 
00273  * This pointer should be passed to IDAMalloc.  
00274  * If an initialization error occurs, IDACreate prints an error 
00275  * message to standard err and returns NULL. 
00276  */
00277 
00278 void *IDACreate(void)
00279 {
00280   IDAMem IDA_mem;
00281 
00282   IDA_mem = NULL;
00283   IDA_mem = (IDAMem) malloc(sizeof(struct IDAMemRec));
00284   if (IDA_mem == NULL) {
00285     IDAProcessError(NULL, 0, "IDA", "IDACreate", MSG_MEM_FAIL);
00286     return (NULL);
00287   }
00288 
00289   /* Set unit roundoff in IDA_mem */
00290   IDA_mem->ida_uround = UNIT_ROUNDOFF;
00291 
00292   /* Set default values for integrator optional inputs */
00293   IDA_mem->ida_res         = NULL;
00294   IDA_mem->ida_rdata       = NULL;
00295   IDA_mem->ida_efun        = NULL;
00296   IDA_mem->ida_edata       = NULL;
00297   IDA_mem->ida_ehfun       = IDAErrHandler;
00298   IDA_mem->ida_eh_data     = (void *) IDA_mem;
00299   IDA_mem->ida_errfp       = stderr;
00300   IDA_mem->ida_maxord      = MAXORD_DEFAULT;
00301   IDA_mem->ida_mxstep      = MXSTEP_DEFAULT;
00302   IDA_mem->ida_hmax_inv    = HMAX_INV_DEFAULT;
00303   IDA_mem->ida_hin         = ZERO;
00304   IDA_mem->ida_epcon       = EPCON;
00305   IDA_mem->ida_maxnef      = MXNEF;
00306   IDA_mem->ida_maxncf      = MXNCF;
00307   IDA_mem->ida_maxcor      = MAXIT;
00308   IDA_mem->ida_suppressalg = FALSE;
00309   IDA_mem->ida_id          = NULL;
00310   IDA_mem->ida_constraints = NULL;
00311   IDA_mem->ida_constraintsSet = FALSE;
00312   IDA_mem->ida_tstopset    = FALSE;
00313 
00314   /* set the saved value maxord_alloc */
00315   IDA_mem->ida_maxord_alloc = MAXORD_DEFAULT;
00316 
00317   /* Set default values for IC optional inputs */
00318   IDA_mem->ida_epiccon = PT01 * EPCON;
00319   IDA_mem->ida_maxnh   = MAXNH;
00320   IDA_mem->ida_maxnj   = MAXNJ;
00321   IDA_mem->ida_maxnit  = MAXNI;
00322   IDA_mem->ida_lsoff   = FALSE;
00323   IDA_mem->ida_steptol = RPowerR(IDA_mem->ida_uround, TWOTHIRDS);
00324 
00325   /* Initialize lrw and liw */
00326   IDA_mem->ida_lrw = 25 + 5*MXORDP1;
00327   IDA_mem->ida_liw = 38;
00328 
00329   /* No mallocs have been done yet */
00330   IDA_mem->ida_VatolMallocDone = FALSE;
00331   IDA_mem->ida_constraintsMallocDone = FALSE;
00332   IDA_mem->ida_idMallocDone = FALSE;
00333   IDA_mem->ida_MallocDone = FALSE;
00334 
00335   /* Return pointer to IDA memory block */
00336   return((void *)IDA_mem);
00337 }
00338 
00339 /*-----------------------------------------------------------------*/
00340 
00341 #define lrw   (IDA_mem->ida_lrw)
00342 #define liw   (IDA_mem->ida_liw)
00343 
00344 /*-----------------------------------------------------------------*/
00345 
00346 /*
00347  * IDAMalloc
00348  *
00349  * IDAMalloc allocates and initializes memory for a problem. All
00350  * problem specification inputs are checked for errors. If any
00351  * error occurs during initialization, it is reported to the 
00352  * error handler function.
00353  */
00354 
00355 int IDAMalloc(void *ida_mem, IDAResFn res,
00356               realtype t0, N_Vector yy0, N_Vector yp0, 
00357               int itol, realtype rtol, void *atol)
00358 {
00359   IDAMem IDA_mem;
00360   booleantype nvectorOK, allocOK, neg_atol;
00361   long int lrw1, liw1;
00362 
00363   /* Check ida_mem */
00364   if (ida_mem == NULL) {
00365     IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAMalloc", MSG_NO_MEM);
00366     return(IDA_MEM_NULL);
00367   }
00368   IDA_mem = (IDAMem) ida_mem;
00369   
00370   /* Check for legal input parameters */
00371   
00372   if (yy0 == NULL) { 
00373     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAMalloc", MSG_Y0_NULL);
00374     /*  return(IDA_ILL_INPUT); Masoud */
00375     return(IDA_NULL_Y0); 
00376 
00377   }
00378   
00379   if (yp0 == NULL) { 
00380     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAMalloc", MSG_YP0_NULL);
00381     /*  return(IDA_ILL_INPUT); Masoud */
00382     return(IDA_YP0_NULL); 
00383   }
00384 
00385   if ((itol != IDA_SS) && (itol != IDA_SV) && (itol != IDA_WF)) {
00386     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAMalloc", MSG_BAD_ITOL);
00387     /*  return(IDA_ILL_INPUT); Masoud */
00388     return(IDA_BAD_ITOL);
00389   }
00390 
00391   if (res == NULL) { 
00392     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAMalloc", MSG_RES_NULL);
00393     /*  return(IDA_ILL_INPUT); Masoud */
00394     return(IDA_RES_NULL); 
00395   }
00396 
00397   /* Test if all required vector operations are implemented */
00398   nvectorOK = IDACheckNvector(yy0);
00399   if (!nvectorOK) {
00400     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAMalloc", MSG_BAD_NVECTOR);
00401     /*  return(IDA_ILL_INPUT); Masoud */
00402     return(IDA_BAD_NVECTOR);
00403   }
00404 
00405   /* Test tolerances */
00406 
00407   if (itol != IDA_WF) {
00408 
00409     if (atol == NULL) { 
00410       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAMalloc", MSG_ATOL_NULL);
00411     /*  return(IDA_ILL_INPUT); Masoud */
00412       return(IDA_NULL_ABSTOL); 
00413     }
00414 
00415     if (rtol < ZERO) { 
00416       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAMalloc", MSG_BAD_RTOL);
00417     /*  return(IDA_ILL_INPUT); Masoud */
00418       return(IDA_BAD_RELTOL); 
00419     }
00420    
00421     if (itol == IDA_SS) { 
00422       neg_atol = (*((realtype *)atol) < ZERO); 
00423     } else { 
00424       neg_atol = (N_VMin((N_Vector)atol) < ZERO); 
00425     }
00426 
00427     if (neg_atol) { 
00428       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAMalloc", MSG_BAD_ATOL);
00429       /*  return(IDA_ILL_INPUT); Masoud */
00430       return(IDA_BAD_ABSTOL); 
00431     }
00432 
00433   }
00434 
00435   /* Set space requirements for one N_Vector */
00436   if (yy0->ops->nvspace != NULL) {
00437     N_VSpace(yy0, &lrw1, &liw1);
00438   } else {
00439     lrw1 = 0;
00440     liw1 = 0;
00441   }
00442   IDA_mem->ida_lrw1 = lrw1;
00443   IDA_mem->ida_liw1 = liw1;
00444 
00445   /* Allocate the vectors (using yy0 as a template) */
00446   allocOK = IDAAllocVectors(IDA_mem, yy0, itol);
00447   if (!allocOK) {
00448     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDAMalloc", MSG_MEM_FAIL);
00449     return(IDA_MEM_FAIL);
00450   }
00451  
00452   /* All error checking is complete at this point */
00453 
00454   /* Copy the input parameters into IDA memory block */
00455 
00456   IDA_mem->ida_res = res;
00457   IDA_mem->ida_tn  = t0;
00458 
00459   /* Copy tolerances into memory */
00460 
00461   IDA_mem->ida_itol = itol;
00462   IDA_mem->ida_rtol = rtol;      
00463 
00464   if (itol == IDA_SS)
00465     IDA_mem->ida_Satol = *((realtype *)atol);
00466   else if (itol == IDA_SV) 
00467     N_VScale(ONE, (N_Vector)atol, IDA_mem->ida_Vatol);
00468 
00469   /* Set the linear solver addresses to NULL */
00470   IDA_mem->ida_linit  = NULL;
00471   IDA_mem->ida_lsetup = NULL;
00472   IDA_mem->ida_lsolve = NULL;
00473   IDA_mem->ida_lperf  = NULL;
00474   IDA_mem->ida_lfree  = NULL;
00475   IDA_mem->ida_lmem   = NULL;
00476 
00477   /* Initialize the phi array */
00478   N_VScale(ONE, yy0, IDA_mem->ida_phi[0]);  
00479   N_VScale(ONE, yp0, IDA_mem->ida_phi[1]);  
00480  
00481   /* Initialize all the counters and other optional output values */
00482   IDA_mem->ida_nst     = 0;
00483   IDA_mem->ida_nre     = 0;
00484   IDA_mem->ida_ncfn    = 0;
00485   IDA_mem->ida_netf    = 0;
00486   IDA_mem->ida_nni     = 0;
00487   IDA_mem->ida_nsetups = 0;
00488   
00489   IDA_mem->ida_kused = 0;
00490   IDA_mem->ida_hused = ZERO;
00491   IDA_mem->ida_tolsf = ONE;
00492 
00493   IDA_mem->ida_nge = 0;
00494 
00495   /* Initialize root-finding variables */
00496 
00497   IDA_mem->ida_glo    = NULL;
00498   IDA_mem->ida_ghi    = NULL;
00499   IDA_mem->ida_grout  = NULL;
00500   IDA_mem->ida_iroots = NULL;
00501   IDA_mem->ida_gfun   = NULL;
00502   IDA_mem->ida_g_data = NULL;
00503   IDA_mem->ida_nrtfn  = 0;
00504 
00505   /* Initial setup not done yet */
00506   IDA_mem->ida_SetupDone = FALSE;
00507 
00508   /* Problem memory has been successfully allocated */
00509   IDA_mem->ida_MallocDone = TRUE;
00510   return(IDA_SUCCESS);
00511 }
00512 
00513 /*-----------------------------------------------------------------*/
00514 
00515 #define lrw1 (IDA_mem->ida_lrw1)
00516 #define liw1 (IDA_mem->ida_liw1)
00517 
00518 /*-----------------------------------------------------------------*/
00519 
00520 /*
00521  * IDAReInit
00522  *
00523  * IDAReInit re-initializes IDA's memory for a problem, assuming
00524  * it has already beeen allocated in a prior IDAMalloc call.
00525  * All problem specification inputs are checked for errors.
00526  * The problem size Neq is assumed to be unchaged since the call
00527  * to IDAMalloc, and the maximum order maxord must not be larger.
00528  * If any error occurs during reinitialization, it is reported to
00529  * the error handler function.
00530  * The return value is IDA_SUCCESS = 0 if no errors occurred, or
00531  * a negative value otherwise.
00532  */
00533 
00534 int IDAReInit(void *ida_mem, IDAResFn res,
00535               realtype t0, N_Vector yy0, N_Vector yp0,
00536               int itol, realtype rtol, void *atol)
00537 {
00538   IDAMem IDA_mem;
00539   booleantype neg_atol;
00540 
00541   /* Check for legal input parameters */
00542   
00543   if (ida_mem == NULL) {
00544     IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAReInit", MSG_NO_MEM);
00545     return(IDA_MEM_NULL);
00546   }
00547   IDA_mem = (IDAMem) ida_mem;
00548 
00549   /* Check if problem was malloc'ed */
00550   
00551   if (IDA_mem->ida_MallocDone == FALSE) {
00552     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDAReInit", MSG_NO_MALLOC);
00553     return(IDA_NO_MALLOC);
00554   }
00555 
00556   /* Check for legal input parameters */
00557   
00558   if (yy0 == NULL) { 
00559     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAReInit", MSG_Y0_NULL);
00560     /*  return(IDA_ILL_INPUT); Masoud */
00561     return(IDA_NULL_Y0); 
00562   }
00563   
00564   if (yp0 == NULL) { 
00565     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAReInit", MSG_YP0_NULL);
00566     /*  return(IDA_ILL_INPUT); Masoud */
00567     return(IDA_YP0_NULL); 
00568   }
00569 
00570   if ((itol != IDA_SS) && (itol != IDA_SV) && (itol != IDA_WF)) {
00571     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAReInit", MSG_BAD_ITOL);
00572     /*  return(IDA_ILL_INPUT); Masoud */
00573     return(IDA_BAD_ITOL);
00574   }
00575 
00576   if (res == NULL) { 
00577     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAReInit", MSG_RES_NULL);
00578     /*  return(IDA_ILL_INPUT); Masoud */
00579     return(IDA_RES_NULL); 
00580   }
00581 
00582   /* Test tolerances */
00583 
00584   if (itol != IDA_WF) {
00585 
00586     if (atol == NULL) { 
00587       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAReInit", MSG_ATOL_NULL);
00588     /*  return(IDA_ILL_INPUT); Masoud */
00589       return(IDA_NULL_ABSTOL); 
00590     }
00591     
00592     if (rtol < ZERO) {
00593       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAReInit", MSG_BAD_RTOL);
00594     /*  return(IDA_ILL_INPUT); Masoud */
00595       return(IDA_BAD_RELTOL); 
00596     }
00597    
00598     if (itol == IDA_SS) { 
00599       neg_atol = (*((realtype *)atol) < ZERO); 
00600     } else { 
00601       neg_atol = (N_VMin((N_Vector)atol) < ZERO); 
00602     }
00603     if (neg_atol) { 
00604       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAReInit", MSG_BAD_ATOL);
00605     /*  return(IDA_ILL_INPUT); Masoud */
00606       return(IDA_BAD_ABSTOL); 
00607     }
00608 
00609   }
00610 
00611   /* Copy the input parameters into IDA memory block */
00612   IDA_mem->ida_res = res;
00613   IDA_mem->ida_tn  = t0;
00614 
00615   if ( (itol != IDA_SV) && (IDA_mem->ida_VatolMallocDone) ) {
00616     N_VDestroy(IDA_mem->ida_Vatol);
00617     lrw -= lrw1;
00618     liw -= liw1;
00619     IDA_mem->ida_VatolMallocDone = FALSE;
00620   }
00621 
00622   if ( (itol == IDA_SV) && !(IDA_mem->ida_VatolMallocDone) ) {
00623     IDA_mem->ida_Vatol = NULL;
00624     IDA_mem->ida_Vatol = N_VClone(yy0);
00625     lrw += lrw1;
00626     liw += liw1;
00627     IDA_mem->ida_VatolMallocDone = TRUE;
00628   }
00629 
00630   IDA_mem->ida_itol = itol;
00631   IDA_mem->ida_rtol = rtol;      
00632   if (itol == IDA_SS)
00633     IDA_mem->ida_Satol = *((realtype *)atol);
00634   else if (itol == IDA_SV)
00635     N_VScale(ONE, (N_Vector)atol, IDA_mem->ida_Vatol);
00636 
00637   /* Initialize the phi array */
00638   N_VScale(ONE, yy0, IDA_mem->ida_phi[0]);  
00639   N_VScale(ONE, yp0, IDA_mem->ida_phi[1]);  
00640  
00641   /* Initialize all the counters and other optional output values */
00642  
00643   IDA_mem->ida_nst     = 0;
00644   IDA_mem->ida_nre     = 0;
00645   IDA_mem->ida_ncfn    = 0;
00646   IDA_mem->ida_netf    = 0;
00647   IDA_mem->ida_nni     = 0;
00648   IDA_mem->ida_nsetups = 0;
00649   
00650   IDA_mem->ida_kused = 0;
00651   IDA_mem->ida_hused = ZERO;
00652   IDA_mem->ida_tolsf = ONE;
00653 
00654   IDA_mem->ida_nge = 0;
00655 
00656   /* Initial setup not done yet */
00657   IDA_mem->ida_SetupDone = FALSE;
00658       
00659   /* Problem has been successfully re-initialized */
00660 
00661   return(IDA_SUCCESS);
00662 }
00663 
00664 /*-----------------------------------------------------------------*/
00665 
00666 #define gfun   (IDA_mem->ida_gfun)
00667 #define g_data (IDA_mem->ida_g_data) 
00668 #define glo    (IDA_mem->ida_glo)
00669 #define ghi    (IDA_mem->ida_ghi)
00670 #define grout  (IDA_mem->ida_grout)
00671 #define iroots (IDA_mem->ida_iroots)
00672 
00673 /*-----------------------------------------------------------------*/
00674 
00675 /*
00676  * IDARootInit
00677  *
00678  * IDARootInit initializes a rootfinding problem to be solved
00679  * during the integration of the DAE system.  It loads the root
00680  * function pointer and the number of root functions, and allocates
00681  * workspace memory.  The return value is IDA_SUCCESS = 0 if no
00682  * errors occurred, or a negative value otherwise.
00683  */
00684 
00685 int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g, void *gdata)
00686 {
00687   IDAMem IDA_mem;
00688   int nrt;
00689 
00690   /* Check ida_mem pointer */
00691   if (ida_mem == NULL) {
00692     IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDARootInit", MSG_NO_MEM);
00693     return(IDA_MEM_NULL);
00694   }
00695   IDA_mem = (IDAMem) ida_mem;
00696 
00697   nrt = (nrtfn < 0) ? 0 : nrtfn;
00698 
00699   /* If rerunning IDARootInit() with a different number of root
00700      functions (changing number of gfun components), then free
00701      currently held memory resources */
00702   if ((nrt != IDA_mem->ida_nrtfn) && (IDA_mem->ida_nrtfn > 0)) {
00703 
00704     free(glo); glo = NULL;
00705     free(ghi); ghi = NULL;
00706     free(grout); grout = NULL;
00707     free(iroots); iroots = NULL;
00708 
00709     lrw -= 3* (IDA_mem->ida_nrtfn);
00710     liw -= IDA_mem->ida_nrtfn;
00711 
00712   }
00713 
00714   /* If IDARootInit() was called with nrtfn == 0, then set ida_nrtfn to
00715      zero and ida_gfun to NULL before returning */
00716   if (nrt == 0) {
00717     IDA_mem->ida_nrtfn = nrt;
00718     gfun = NULL;
00719     g_data = NULL;
00720     return(IDA_SUCCESS);
00721   }
00722 
00723   /* Store user's data pointer */
00724   g_data = gdata;
00725 
00726   /* If rerunning IDARootInit() with the same number of root functions
00727      (not changing number of gfun components), then check if the root
00728      function argument has changed */
00729   /* If g != NULL then return as currently reserved memory resources
00730      will suffice */
00731   if (nrt == IDA_mem->ida_nrtfn) {
00732     if (g != gfun) {
00733       if (g == NULL) {
00734         free(glo); glo = NULL;
00735         free(ghi); ghi = NULL;
00736         free(grout); grout = NULL;
00737         free(iroots); iroots = NULL;
00738 
00739         lrw -= 3*nrt;
00740         liw -= nrt;
00741 
00742         IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDARootInit", MSG_ROOT_FUNC_NULL);
00743         /*  return(IDA_ILL_INPUT); Masoud */
00744         return(IDA_NULL_G);
00745       }
00746       else {
00747         gfun = g;
00748         return(IDA_SUCCESS);
00749       }
00750     }
00751     else return(IDA_SUCCESS);
00752   }
00753 
00754   /* Set variable values in IDA memory block */
00755   IDA_mem->ida_nrtfn = nrt;
00756   if (g == NULL) {
00757     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDARootInit", MSG_ROOT_FUNC_NULL);
00758     /*  return(IDA_ILL_INPUT); Masoud */
00759     return(IDA_NULL_G);
00760   }
00761   else gfun = g;
00762 
00763   /* Allocate necessary memory and return */
00764   glo = NULL;
00765   glo = (realtype *) malloc(nrt*sizeof(realtype));
00766   if (glo == NULL) {
00767     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL);
00768     return(IDA_MEM_FAIL);
00769   }
00770 
00771   ghi = NULL;
00772   ghi = (realtype *) malloc(nrt*sizeof(realtype));
00773   if (ghi == NULL) {
00774     free(glo); glo = NULL;
00775     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL);
00776     return(IDA_MEM_FAIL);
00777   }
00778 
00779   grout = NULL;
00780   grout = (realtype *) malloc(nrt*sizeof(realtype));
00781   if (grout == NULL) {
00782     free(glo); glo = NULL;
00783     free(ghi); ghi = NULL;
00784     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL);
00785     return(IDA_MEM_FAIL);
00786   }
00787 
00788   iroots = NULL;
00789   iroots = (int *) malloc(nrt*sizeof(int));
00790   if (iroots == NULL) {
00791     free(glo); glo = NULL;
00792     free(ghi); ghi = NULL;
00793     free(grout); grout = NULL;
00794     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL);
00795     return(IDA_MEM_FAIL);
00796   }
00797 
00798   lrw += 3*nrt;
00799   liw += nrt;
00800 
00801   return(IDA_SUCCESS);
00802 }
00803 
00804 /*
00805  * -----------------------------------------------------------------
00806  * readability constants
00807  * -----------------------------------------------------------------
00808  */
00809 
00810 #define res (IDA_mem->ida_res)
00811 #define y0  (IDA_mem->ida_y0)
00812 #define yp0 (IDA_mem->ida_yp0)
00813 
00814 #define itol  (IDA_mem->ida_itol)
00815 #define rtol  (IDA_mem->ida_rtol)
00816 #define Satol (IDA_mem->ida_Satol)
00817 #define Vatol (IDA_mem->ida_Vatol)
00818 #define efun  (IDA_mem->ida_efun)
00819 #define edata (IDA_mem->ida_edata)
00820 
00821 #define rdata       (IDA_mem->ida_rdata)
00822 #define maxord      (IDA_mem->ida_maxord)
00823 #define mxstep      (IDA_mem->ida_mxstep)
00824 #define hin         (IDA_mem->ida_hin)
00825 #define hmax_inv    (IDA_mem->ida_hmax_inv)
00826 #define istop       (IDA_mem->ida_istop)
00827 #define tstop       (IDA_mem->ida_tstop)
00828 #define tstopset    (IDA_mem->ida_tstopset)
00829 #define epcon       (IDA_mem->ida_epcon)
00830 #define maxnef      (IDA_mem->ida_maxnef)
00831 #define maxncf      (IDA_mem->ida_maxncf)
00832 #define maxcor      (IDA_mem->ida_maxcor)
00833 #define suppressalg (IDA_mem->ida_suppressalg)
00834 #define id          (IDA_mem->ida_id)
00835 #define constraints (IDA_mem->ida_constraints)
00836 
00837 #define epiccon (IDA_mem->ida_epiccon)
00838 #define maxnh   (IDA_mem->ida_maxnh)
00839 #define maxnj   (IDA_mem->ida_maxnj)
00840 #define maxnit  (IDA_mem->ida_maxnit)
00841 #define lsoff   (IDA_mem->ida_lsoff)
00842 #define steptol (IDA_mem->ida_steptol)
00843 
00844 #define uround         (IDA_mem->ida_uround)  
00845 #define phi            (IDA_mem->ida_phi) 
00846 #define ewt            (IDA_mem->ida_ewt)  
00847 #define yy             (IDA_mem->ida_yy)
00848 #define yp             (IDA_mem->ida_yp)
00849 #define delta          (IDA_mem->ida_delta)
00850