00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "ne_sim_gslode.h"
00024 #include "ne_sim.h"
00025 #include <gsl/gsl_rng.h>
00026 #include <string.h>
00027
00028
00029 ne_sim_gslode_params_t * ne_sim_gslode_params_alloc (const gsl_odeiv_step_type *step,
00030 double eps_abs, double eps_rel, double length,
00031 ne_bool_t fixedStep, double initStep, double minStep)
00032 {
00033 ne_sim_gslode_params_t *params;
00034
00035 if ((params = (ne_sim_gslode_params_t *)malloc(sizeof(ne_sim_gslode_params_t))) == NULL) {
00036 ne_error("ne_sim_gslode_alloc: Could not allocate memory for parameters");
00037 return NULL;
00038 }
00039
00040 params->length = length;
00041 params->step = step;
00042 params->initStep = initStep;
00043 params->minStep = minStep;
00044 params->fixedStep = fixedStep;
00045 params->eps_abs = eps_abs;
00046 params->eps_rel = eps_rel;
00047
00048 return params;
00049 }
00050
00051
00052 void ne_sim_gslode_params_free (ne_sim_gslode_params_t *params)
00053 {
00054
00055 free(params);
00056 }
00057
00058
00059 ne_dyn_vec_t * ne_sim_gslode (ne_sys_t *sys, void *p, double *iy, FILE *file)
00060 {
00061 double t, t1, h, hMin, *y, *yErr, *yCopy, *dydtIn, *dydtOut;
00062 int fixedStep, status, i, stepStatus, dimension;
00063 ne_dyn_vec_t *vecOut;
00064 ne_sim_gslode_params_t *params;
00065 gsl_odeiv_system odeSystem;
00066 gsl_odeiv_step *step;
00067 gsl_odeiv_control *control;
00068 gsl_odeiv_evolve *evolve;
00069
00070 params = (ne_sim_gslode_params_t *)p;
00071 dimension = (ne_sys_nodes(sys) * ne_sys_node_states(sys)) +
00072 (ne_sys_edges(sys) * ne_sys_edge_states(sys));
00073
00074
00075 odeSystem.function = &ne_sim_gslode_sys_fn;
00076 odeSystem.jacobian = NULL;
00077 odeSystem.dimension = dimension;
00078 odeSystem.params = (void *)sys;
00079
00080
00081 step = gsl_odeiv_step_alloc(params->step, dimension);
00082 control = gsl_odeiv_control_y_new(params->eps_abs, params->eps_rel);
00083 evolve = gsl_odeiv_evolve_alloc(dimension);
00084
00085
00086 vecOut = ne_dyn_vec_alloc(dimension + 1);
00087
00088
00089 t = 0.0;
00090 t1 = params->length;
00091 h = params->initStep;
00092 hMin = params->minStep;
00093 fixedStep = params->fixedStep;
00094 y = (double*)malloc(sizeof(double)*(dimension));
00095
00096
00097 memcpy(y, iy, sizeof(double)*dimension);
00098 yCopy = (double*)malloc((sizeof(double)*dimension)+1);
00099 memcpy(&yCopy[1], y, sizeof(double)*dimension);
00100 yCopy[0] = t;
00101 ne_dyn_vec_append_item(vecOut, yCopy);
00102
00103 if ( fixedStep == TRUE ) {
00104
00105
00106 yErr = (double*)malloc((sizeof(double)*dimension));
00107 dydtIn = (double*)malloc((sizeof(double)*dimension));
00108 dydtOut = (double*)malloc((sizeof(double)*dimension));
00109
00110
00111 GSL_ODEIV_FN_EVAL(&odeSystem, t, y, dydtIn);
00112
00113 while ( t < t1 ) {
00114
00115 status = gsl_odeiv_step_apply(step, t, h, y, yErr, dydtIn, dydtOut, &odeSystem);
00116
00117
00118 t += h;
00119
00120
00121
00122
00123
00124 if (status != GSL_SUCCESS) {
00125 break;
00126 }
00127
00128
00129 for ( i=0; i<dimension; i++ ) {
00130 dydtIn[i] = dydtOut[i];
00131 }
00132
00133
00134 yCopy = (double*)malloc((sizeof(double)*dimension)+1);
00135 memcpy(&yCopy[1], y, sizeof(double)*dimension);
00136 yCopy[0] = t;
00137 ne_dyn_vec_append_item(vecOut, yCopy);
00138 }
00139 }
00140 else {
00141
00142 if ( hMin > 0 ) {
00143
00144 yErr = (double*)malloc((sizeof(double)*dimension));
00145 dydtIn = (double*)malloc((sizeof(double)*dimension));
00146 dydtOut = (double*)malloc((sizeof(double)*dimension));
00147
00148
00149 GSL_ODEIV_FN_EVAL(&odeSystem, t, y, dydtIn);
00150
00151
00152 for ( i=0; i<dimension; i++ ) {
00153 yErr[i] = 0;
00154 }
00155 }
00156
00157 while ( t < t1 ) {
00158
00159 if ( hMin > 0 ) {
00160
00161
00162 stepStatus = gsl_odeiv_control_hadjust(control, step, y, yErr, dydtIn, &h);
00163
00164 if ( stepStatus == GSL_ODEIV_HADJ_DEC && h < hMin ) {
00165 h = hMin;
00166 ne_error("ne_dyn_ode_solver_evolve - Estimated step size is smaller than given minimum. Error bounds will be exceeded.\n");
00167 }
00168
00169 status = gsl_odeiv_step_apply(step, t, h, y, yErr, dydtIn, dydtOut, &odeSystem);
00170
00171
00172 t += h;
00173
00174 if (status != GSL_SUCCESS) {
00175 break;
00176 }
00177
00178 for ( i=0; i<dimension; i++ ) {
00179 dydtIn[i] = dydtOut[i];
00180 }
00181
00182 yCopy = (double*)malloc((sizeof(double)*dimension)+1);
00183 memcpy(&yCopy[1], y, sizeof(double)*dimension);
00184 yCopy[0] = t;
00185 ne_dyn_vec_append_item(vecOut, yCopy);
00186
00187
00188 if ( t > t1 ) {
00189 t = t1;
00190 }
00191 }
00192 else {
00193
00194
00195 status = gsl_odeiv_evolve_apply(evolve, control, step, &odeSystem, &t, t1, &h, y);
00196 }
00197
00198 if (status != GSL_SUCCESS) {
00199 break;
00200 }
00201
00202 yCopy = (double*)malloc((sizeof(double)*dimension)+1);
00203 memcpy(&yCopy[1], y, sizeof(double)*dimension);
00204 yCopy[0] = t;
00205 ne_dyn_vec_append_item(vecOut, yCopy);
00206 }
00207 }
00208
00209
00210 if (status != GSL_SUCCESS) {
00211 ne_dyn_vec_free(vecOut);
00212 free(y);
00213 return NULL;
00214 }
00215
00216 if ( file != NULL ) {
00217 ne_sim_fprint_dyn_vec(vecOut, file);
00218 }
00219
00220
00221 free(y);
00222 gsl_odeiv_step_free(step);
00223 gsl_odeiv_control_free(control);
00224 gsl_odeiv_evolve_free(evolve);
00225 return vecOut;
00226 }
00227
00228
00229 int ne_sim_gslode_sys_fn (double t, const double y[], double dydt[], void *params)
00230 {
00231 int nodes, edges, nStates, eStates, i, j;
00232 ne_dyn_node_t *nodeDyn;
00233 ne_dyn_edge_t *edgeDyn;
00234 ne_sys_t *sys;
00235
00236 sys = (ne_sys_t *)params;
00237
00238 nodes = ne_sys_nodes(sys);
00239 edges = ne_sys_edges(sys);
00240 nStates = ne_sys_node_states(sys);
00241 eStates = ne_sys_edge_states(sys);
00242
00243
00244 for (i=0; i<nodes; i++) {
00245 nodeDyn = ne_sys_dyn_node(sys, i);
00246 (nodeDyn->fn)(i, (void *)sys, t, y, dydt, ne_sys_dyn_node_params(sys,i));
00247 }
00248
00249
00250 if (igraph_is_directed(sys->graph)) {
00251 for (j=0; j<edges; j++) {
00252 edgeDyn = ne_sys_dyn_eid(sys, j);
00253 (edgeDyn->fn)(j, (int)IGRAPH_FROM(sys->graph, (igraph_integer_t)j), (int)IGRAPH_TO(sys->graph, (igraph_integer_t)j),
00254 (void *)sys, t, y, dydt, ne_sys_dyn_eid_params(sys,j));
00255 }
00256 }
00257 else {
00258 for (j=0; j<edges; j++) {
00259 edgeDyn = ne_sys_dyn_eid(sys, j);
00260 (edgeDyn->fn)(j, (int)IGRAPH_FROM(sys->graph, (igraph_integer_t)j), (int)IGRAPH_TO(sys->graph, (igraph_integer_t)j),
00261 (void *)sys, t, y, dydt, ne_sys_dyn_eid_params(sys,j));
00262 (edgeDyn->fn)(j, (int)IGRAPH_TO(sys->graph, (igraph_integer_t)j), (int)IGRAPH_FROM(sys->graph, (igraph_integer_t)j),
00263 (void *)sys, t, y, dydt, ne_sys_dyn_eid_params(sys,j));
00264 }
00265 }
00266
00267 return GSL_SUCCESS;
00268 }