/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * This file is distributed subject to a Software License Agreement found * in the file LICENSE that is included with this distribution. \*************************************************************************/ /* $Log: mmid.c,v $ Revision 1.5 2003/08/28 19:56:27 soliday Cleaned up some of the code. Revision 1.4 2002/08/14 16:18:58 soliday Added Open License Revision 1.3 1999/07/29 21:26:24 borland Added mmid_odeint3_na() for nonadaptive integration with modified midpoint method. Calling is the same as rk_odeint3_na(). * Revision 1.2 1995/09/05 21:20:39 saunders * First test release of the SDDS1.5 package. * */ /* file: mmid.c * contents: mmid() * mmid2() * purpose: modified midpoint method for integrating ODEs * Based on Numerical Recipes in C . * Michael Borland, 1995 */ #include "mdb.h" #define MAX_EXIT_ITERATIONS 400 #define ITER_FACTOR 0.995 #define TINY 1.0e-30 void mmid( double *yInitial, /* starting values of dependent variables */ double *dydxInitial, /* and their derivatives */ long equations, /* number of equations */ double xInitial, /* starting value of independent variable */ double interval, /* size of interval in x */ long steps, /* number of steps to divide interval into */ double *yFinal, /* final values of dependent variables */ /* function return derivatives */ void (*derivs)(double *_dydx, double *_y, double _x) ) { long i, j; double x=0, ynSave, h, hTimes2; static double *ym, *yn; static long last_equations=0; double *dydxTemp; if (equations>last_equations) { if (last_equations) { free(ym); free(yn); } /* allocate arrays for solutions at two adjacent points in x */ ym = tmalloc(sizeof(*ym)*equations); yn = tmalloc(sizeof(*yn)*equations); last_equations = equations; } hTimes2 = (h=interval/steps)*2; /* Copy starting values and compute first set of estimated values */ for (i=0; ilast_equations) { if (last_equations) { free(yFinal2); } /* allocate arrays for second solution */ yFinal2 = tmalloc(sizeof(*yFinal2)*equations); last_equations = equations; } mmid(y, dydx, equations, x0, interval, steps, yFinal, derivs); mmid(y, dydx, equations, x0, interval, steps/2, yFinal2, derivs); for (i=0; i=1 on success */ long mmid_odeint3_na( double *yif, /* initial/final values of dependent variables */ void (*derivs)(double *dydx, double *y, double x),/* (*derivs)(dydx, y, x) */ long n_eq, /* number of equations */ /* for each dependent variable: */ double *accuracy, /* desired accuracy--see below for meaning */ long *accmode, /* desired accuracy-control mode */ double *tiny, /* ignored */ long *misses, /* ignored */ /* for the dependent variable: */ double *x0, /* initial/final value */ double xf, /* upper limit of integration */ double x_accuracy, /* accuracy of final value */ double h_step, /* step size */ double h_max, /* ignored */ double *h_rec, /* ignored */ /* function for determining when to stop integration: */ double (*exit_func)(double *dydx, double *y, double x), /* function that is to be zeroed */ double exit_accuracy /* how close to zero to get */ ) { static double *y0, *yscale; static double *dydx0, *y1, *dydx1, *dydx2, *y2, *accur; static long last_neq = 0; double ex0, ex1, ex2, x1, x2; double xdiff; long i, n_exit_iterations; #define MAX_N_STEP_UPS 10 if (*x0>xf) return(DIFFEQ_XI_GT_XF); if (FABS(*x0-xf)