• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

ne_sim_gslode.c

00001 /*===========================================================================
00002  NetEvo Foundation Library
00003  Copyright (C) 2009, 2010 Thomas E. Gorochowski <tgorochowski@me.com>
00004  Bristol Centre for Complexity Sciences, University of Bristol, Bristol, UK
00005  ---------------------------------------------------------------------------- 
00006  NetEvo is a computing framework designed to allow researchers to investigate 
00007  evolutionary aspects of dynamical complex networks. By providing tools to 
00008  easily integrate each of these factors in a coherent way, it is hoped a 
00009  greater understanding can be gained of key attributes and features displayed 
00010  by complex systems.
00011  
00012  NetEvo is open-source software released under the Open Source Initiative 
00013  (OSI) approved Non-Profit Open Software License ("Non-Profit OSL") 3.0. 
00014  Detailed information about this licence can be found in the COPYING file 
00015  included as part of the source distribution.
00016  
00017  This library is distributed in the hope that it will be useful, but
00018  WITHOUT ANY WARRANTY; without even the implied warranty of
00019  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
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    /* Free the full structure */
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    /* Build the ODE system to run the simulation */
00075    odeSystem.function  = &ne_sim_gslode_sys_fn;
00076    odeSystem.jacobian  = NULL;
00077    odeSystem.dimension = dimension;
00078    odeSystem.params    = (void *)sys;
00079    
00080    /* Define the parameters required by NetEvo when simulating */
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    /* Allocate dynamic vector to hold output */
00086    vecOut = ne_dyn_vec_alloc(dimension + 1);
00087    
00088    /* Setup internal variables and allocate required memory */
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    /* Copy accross the initial starting point */
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       /* Allocate memory to hold the error */
00106       yErr = (double*)malloc((sizeof(double)*dimension));
00107       dydtIn = (double*)malloc((sizeof(double)*dimension));
00108       dydtOut = (double*)malloc((sizeof(double)*dimension));
00109       
00110       /* Calculate the initial dydt value */
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          /* Update the current time to the new timepoint */
00118          t += h;
00119          
00120          /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
00121          /* TODO: Check errors and return error if found to be outside range */
00122          /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
00123          
00124          if (status != GSL_SUCCESS) {
00125             break;
00126          }
00127          
00128          /* Copy output of previous step to input of next */
00129          for ( i=0; i<dimension; i++ ) {
00130             dydtIn[i] = dydtOut[i];
00131          }
00132          
00133          /* Make a copy of the results and append to the output vector */
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          /* Allocate memory to hold the error */
00144          yErr = (double*)malloc((sizeof(double)*dimension));
00145          dydtIn = (double*)malloc((sizeof(double)*dimension));
00146          dydtOut = (double*)malloc((sizeof(double)*dimension));
00147          
00148          /* Calculate the initial dydt value */
00149          GSL_ODEIV_FN_EVAL(&odeSystem, t, y, dydtIn);
00150          
00151          /* No error for the first point */
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             /* Must maintain a minimum h value */
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             /* Update the current time */
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             /* Ensure we do not exceed t1 */
00188             if ( t > t1 ) {
00189                t = t1;
00190             }           
00191          }
00192          else {
00193             
00194             /* Allow GSL to evolve the system to maintain bounded errors */
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    /* Check that simulation was successful */
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    /* Free used memory and return dynamical output */
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    /* Calculate the dynamics for each node */
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    /* Calculate the dynamics for each edge */
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 }

Generated on Thu Aug 26 2010 11:04:24 for NetEvo by  doxygen 1.7.1