00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "ne_sim_cvode.h"
00031 #include <string.h>
00032
00033
00034 #define Ith(v,i) NV_Ith_S(v,i-1)
00035 #define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1)
00036
00037 ne_vec_dyn_t * ne_sim_cvode_run (ne_system_t *system, void *params, double length, double *iy,
00038 FILE *file)
00039 {
00040
00041 int dimension, flag, i;
00042 double *yCopy;
00043 realtype cvRelTol, cvAbsTol, t, tout;
00044 N_Vector y;
00045 void *cvode_mem;
00046 ne_vec_dyn_t *vecOut;
00047 ne_sim_cvode_params_t *cvodeParams;
00048
00049 cvodeParams = (ne_sim_cvode_params_t *)params;
00050 y = NULL;
00051 cvode_mem = NULL;
00052 dimension = system->nodes * system->nodeStates;
00053 vecOut = ne_vec_dyn_alloc(dimension + 1);
00054
00055
00056 y = N_VNew_Serial(dimension);
00057 if (check_flag((void *)y, "N_VNew_Serial", 0)) return NULL;
00058
00059
00060 for (i=0; i<dimension; i++) {
00061 NV_Ith_S(y,i) = iy[i];
00062 }
00063
00064
00065 if (cvodeParams->stiff == TRUE) {
00066 cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
00067 }
00068 else {
00069 cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL);
00070 }
00071 if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return NULL;
00072
00073
00074
00075
00076 flag = CVodeInit(cvode_mem, ne_sim_cvode_fn, 0.0, y);
00077 if (check_flag(&flag, "CVodeInit", 1)) return NULL;
00078
00079
00080
00081
00082 cvRelTol = (realtype)cvodeParams->relTol;
00083 cvAbsTol = (realtype)cvodeParams->absTol;
00084 flag = CVodeSStolerances(cvode_mem, cvRelTol, cvAbsTol);
00085 if (check_flag(&flag, "CVodeSStolerances", 1)) return NULL;
00086
00087
00088 flag = CVDense(cvode_mem, dimension);
00089 if (check_flag(&flag, "CVDense", 1)) return NULL;
00090
00091 tout = 0.0;
00092 do {
00093 if (flag == CV_SUCCESS) {
00094 tout += cvodeParams->step;
00095 if (tout > length) {
00096 tout = length;
00097 }
00098 }
00099
00100
00101 flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
00102
00103
00104 yCopy = (double*)malloc((sizeof(double)*dimension)+1);
00105 yCopy[0] = t;
00106 for (i=0; i<dimension; i++) {
00107 yCopy[i+1] = NV_Ith_S(y,i);
00108 }
00109 ne_vec_dyn_append_item(vecOut, yCopy);
00110
00111 if (check_flag(&flag, "CVode", 1)) break;
00112
00113 } while (tout < length);
00114
00115
00116 N_VDestroy_Serial(y);
00117
00118
00119 CVodeFree(&cvode_mem);
00120
00121 return vecOut;
00122 }
00123
00124
00125 int ne_sim_cvode_fn (realtype t, N_Vector y, N_Vector ydot, void *params)
00126 {
00127
00128
00129 ne_int_t states, i, j, k;
00130 ne_system_t *system;
00131 double *ydotNew, *ydotCum;
00132
00133 system = (ne_system_t *)params;
00134 states = ne_system_node_states(system);
00135
00136 ydotNew = (double *)malloc(sizeof(double) * states);
00137 ydotCum = (double *)malloc(sizeof(double) * states);
00138
00139
00140 for (i=0; i<system->nodes; i++) {
00141 (ne_system_dyn_node(system, i)->fn)(i, system, (double)t,
00142 (double *)&NV_Ith_S(y, i*states),
00143 (double *)&NV_Ith_S(ydot, i*states),
00144 ne_system_dyn_node_params(system, i));
00145 }
00146
00147
00148 if (ne_system_node_param(system, i, NE_NODE_PARAM_EDGE_INT_TYPE) == NE_INT_SUM) {
00149
00150
00151 for (i=0; i<system->nodes; i++) {
00152 memset(ydotCum, 0, sizeof(double)*states);
00153 for (j=0; j<system->nodes; j++) {
00154 if (ne_system_edge_exists(system, i, j) == TRUE) {
00155 memset(ydotNew, 0, sizeof(double)*states);
00156 (ne_system_dyn_edge(system, i, j)->fn)(i, j, system, (double)t,
00157 (double *)NV_DATA_S(y),
00158 ydotNew,
00159 ne_system_dyn_edge_params(system, i, j));
00160
00161 for (k=0; k<states; k++) {
00162 ydotCum[k] += ydotNew[k];
00163 }
00164 }
00165 }
00166
00167 for (k=0; k<states; k++) {
00168 NV_Ith_S(ydot, (i*states)+k) += ydotCum[k];
00169 }
00170 }
00171 }
00172 else if (ne_system_node_param(system, i, NE_NODE_PARAM_EDGE_INT_TYPE) == NE_INT_MUT) {
00173
00174
00175 for (i=0; i<system->nodes; i++) {
00176 memset(ydotCum, 1, sizeof(double)*states);
00177 for (j=0; j<system->nodes; j++) {
00178 if (ne_system_edge_exists(system, i, j) == TRUE) {
00179 memset(ydotNew, 0, sizeof(double)*states);
00180 (ne_system_dyn_edge(system, i, j)->fn)(i, j, system, (double)t,
00181 (double *)NV_DATA_S(y),
00182 ydotNew,
00183 ne_system_dyn_edge_params(system, i, j));
00184
00185 for (k=0; k<states; k++) {
00186 ydotCum[k] *= ydotNew[k];
00187 }
00188 }
00189 }
00190
00191 for (k=0; k<states; k++) {
00192 NV_Ith_S(ydot, (i*states)+k) += ydotCum[k];
00193 }
00194 }
00195 }
00196
00197 free(ydotNew);
00198 free(ydotCum);
00199
00200 return 0;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 static int check_flag(void *flagvalue, char *funcname, int opt)
00255 {
00256 int *errflag;
00257
00258
00259 if (opt == 0 && flagvalue == NULL) {
00260 fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n",
00261 funcname);
00262 return(1); }
00263
00264
00265 else if (opt == 1) {
00266 errflag = (int *) flagvalue;
00267 if (*errflag < 0) {
00268 fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed with flag = %d\n\n",
00269 funcname, *errflag);
00270 return(1); }}
00271
00272
00273 else if (opt == 2 && flagvalue == NULL) {
00274 fprintf(stderr, "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n",
00275 funcname);
00276 return(1); }
00277
00278 return(0);
00279 }
00280
00281
00282