static void Random_Prm(DBL * Prm) { int i; for (i = 0; i < MAX_PRM; ++i) Prm[i] = Gauss_Rand(Mid_Prm[i], Amp_Prm[i], 4.0); }
/* Sets up initial conditions for a flow without all the extra baggage that goes with init_flow */ static void restart_flow(ModeInfo * mi) { flowstruct *sp; int b; if (flows == NULL) return; sp = &flows[MI_SCREEN(mi)]; sp->count = 0; /* Re-Initialize point positions, velocities, etc. */ for (b = 0; b < sp->beecount; b++) { X(0, b) = Gauss_Rand(sp->range.x); Y(0, b) = (sp->yperiod > 0)? balance_rand(sp->range.y) : Gauss_Rand(sp->range.y); Z(0, b) = Gauss_Rand(sp->range.z); } }
static Bool discover(ModeInfo * mi) { flowstruct *sp; double l = 0; dvector dl; dvector max, min; double dl2, df, rs, lsum = 0, s, maxv2 = 0, v2; int N, i, nl = 0; if (flows == NULL) return 0; sp = &flows[MI_SCREEN(mi)]; if(sp->count2 == 0) { /* initial conditions */ sp->p2[0].x = Gauss_Rand(sp->range.x); sp->p2[0].y = (sp->yperiod > 0)? balance_rand(sp->range.y) : Gauss_Rand(sp->range.y); sp->p2[0].z = Gauss_Rand(sp->range.z); /* 1000 steps to find an attractor */ /* Most cases explode out here */ for(N=0; N < 1000; N++){ Iterate(sp->p2, sp->ODE, sp->par2, sp->step2); if(sp->yperiod > 0 && sp->p2[0].y > sp->yperiod) sp->p2[0].y -= sp->yperiod; if(fabs(sp->p2[0].x) > LOST_IN_SPACE || fabs(sp->p2[0].y) > LOST_IN_SPACE || fabs(sp->p2[0].z) > LOST_IN_SPACE) { return 0; } sp->count2++; } /* Small perturbation */ sp->p2[1].x = sp->p2[0].x + 0.000001; sp->p2[1].y = sp->p2[0].y; sp->p2[1].z = sp->p2[0].z; } /* Reset bounding box */ max.x = min.x = sp->p2[0].x; max.y = min.y = sp->p2[0].y; max.z = min.z = sp->p2[0].z; /* Compute Lyapunov Exponent */ /* (Technically, we're only estimating the largest Lyapunov Exponent, but that's all we need to know to determine if we have a strange attractor.) [TDA] */ /* Fly two bees close together */ for(N=0; N < 5000; N++){ for(i=0; i< 2; i++) { v2 = Iterate(sp->p2+i, sp->ODE, sp->par2, sp->step2); if(sp->yperiod > 0 && sp->p2[i].y > sp->yperiod) sp->p2[i].y -= sp->yperiod; if(fabs(sp->p2[i].x) > LOST_IN_SPACE || fabs(sp->p2[i].y) > LOST_IN_SPACE || fabs(sp->p2[i].z) > LOST_IN_SPACE) { return 0; } if(v2 > maxv2) maxv2 = v2; /* Track max v^2 */ } /* find bounding box */ if ( sp->p2[0].x < min.x ) min.x = sp->p2[0].x; else if ( sp->p2[0].x > max.x ) max.x = sp->p2[0].x; if ( sp->p2[0].y < min.y ) min.y = sp->p2[0].y; else if ( sp->p2[0].y > max.y ) max.y = sp->p2[0].y; if ( sp->p2[0].z < min.z ) min.z = sp->p2[0].z; else if ( sp->p2[0].z > max.z ) max.z = sp->p2[0].z; /* Measure how much we have to pull the two bees to prevent them diverging. */ dl.x = sp->p2[1].x - sp->p2[0].x; dl.y = sp->p2[1].y - sp->p2[0].y; dl.z = sp->p2[1].z - sp->p2[0].z; dl2 = dl.x*dl.x + dl.y*dl.y + dl.z*dl.z; if(dl2 > 0) { df = 1e12 * dl2; rs = 1/sqrt(df); sp->p2[1].x = sp->p2[0].x + rs * dl.x; sp->p2[1].y = sp->p2[0].y + rs * dl.y; sp->p2[1].z = sp->p2[0].z + rs * dl.z; lsum = lsum + log(df); nl = nl + 1; l = M_LOG2E / 2 * lsum / nl / sp->step2; } sp->count2++; } /* Anything that didn't explode has a finite attractor */ /* If Lyapunov is negative then it probably hit a fixed point or a * limit cycle. Positive Lyapunov indicates a strange attractor. */ sp->lyap2 = l; sp->size2 = max.x - min.x; s = max.y - min.y; if(s > sp->size2) sp->size2 = s; s = max.z - min.z; if(s > sp->size2) sp->size2 = s; sp->mid2.x = (max.x + min.x) / 2; sp->mid2.y = (max.y + min.y) / 2; sp->mid2.z = (max.z + min.z) / 2; if(sqrt(maxv2) > sp->size2 * 0.2) { /* Flowing too fast, reduce step size. This helps to eliminate high-speed limit cycles, which can show +ve Lyapunov due to integration inaccuracy. */ sp->step2 /= 2; } return 1; }