// Eqintegr.cpp - A step in Runge_kutta integration // Project MOT // Kazanovich June 2005 #include "stdafx.h" #include "mot.h" #include //***** Subroutines ***** void My_error(CString); void derivs(double y[], double dydx[]); void odeint(double ystart[],int nvar,double x1,double x2,double eps, double h1,double hmin,int *nok,int *nbad, void (*derivs)(double [],double []), void (*rkqs)(double [],double [],int,double *,double, double,double [],double *,double *, void (*)(double[],double[]))); void rkqs(double y[],double dydx[],int n,double *x,double htry, double eps,double yscal[],double *hdid,double *hnext, void (*derivs)(double[],double[])); double gt(void); //***** Externakl var. ***** extern int it; extern struct network net[noaf]; extern struct connections *connec; extern struct parameters par; extern struct integration integr; extern struct imageproc improc; extern struct image im; const double pi = 3.1415926535; const double two_pi = 2.*pi; // Transformation of phases to the interval (-pi, pi) double r(double z) { double sgn = (z >= 0)? 1. : -1.; double x = fabs(z); double y = x - ((int)(x/two_pi))*two_pi; y = y*sgn; if (y > pi) y = y - two_pi; if (y < -pi) y = y + two_pi; return y; } // Interaction function - influence of POs on the CO double g(double x) { // return sin(x); double y = r(x); double sgn = (y > 0.0)? 1.0 : -1.0; y = fabs(y); double z = 0.0; if (y < integr.gs1) { z = integr.ga1*y;} else { if (y < integr.gs2) { z = integr.ga2*y + integr.gb2;} else { z = integr.ga3*y + integr.gb3;} } return sgn*z; } // Interaction function - influence of CO on POs const double ymax = pi/15.0; const double ymax2 = 2*ymax; const double lambda = 1.0/ymax; const double freemem = lambda*ymax2; /* double g1(double x) { return sin(x); } */ double g1(double x) { double y = r(x); double sgn = (y > 0)? 1.0 : -1.0; y = fabs(y); double z = lambda*y*exp(-lambda*y + 1.0); return sgn*z; } /* double g1(double x) { double z; double y = r(x); double sgn = (y > 0)? 1.0 : -1.0; y = fabs(y); if (y < ymax) { z = lambda*y; } else { if (y < ymax2) { z = freemem - lambda*y; } else { z = 0.0; } } return sgn*z; } */ // Interaction function between COs double g2(double x) { double y = r(x); double sgn = (y > 0)? 1.0 : -1.0; y = fabs(y); double z = lambda*y*exp(-lambda*y + 1.0); return sgn*z; } // Function for the dynamics of amplitudes double f(double x) { x = cos(x); x = (x > 0)? x*x : 0; double y = (x - integr.ksi)/integr.eta; if (y > 20) return 1 + integr.dzeta; if (y < -20) return integr.dzeta; double u = exp(y); return u/(1 + u) + integr.dzeta; } //==================== s/p Step ============ void Step() { int oaf; long n = par.n; long n1 = 2*(n + 1) + 1; long n2 = n1*noaf; static double *y_0 = new double[n2 + 1]; // pointer to integration array double *y; // current pointer to integration array int nok, nbad; int i; //***** Check of mamory allocation for integration array ***** if (!y_0) My_error("Not enough memory for integration array"); //***** Filling integration array ***** y = y_0; y++; for (oaf = 0; oaf < noaf; oaf++) { for (i = 0; i <= n; i++) { *y++ = net[oaf].osc[i].teta;} for (i = 0; i <= n; i++) { *y++ = net[oaf].osc[i].amp;} *y++ = net[oaf].osc[0].omega0; } // ***** Adding noise ***** for (oaf = 0; oaf < noaf; oaf++) { for (i = 0; i <= n; i++) { net[oaf].osc[i].noise = integr.noise*gt(); } } //***** Integration ***** odeint(y_0, n2, it*integr.dt, (it + 1)*integr.dt, integr.eps, integr.h1, integr.hmin, &nok, &nbad, derivs, rkqs); //***** Extracting network variables from the integration array ***** y = y_0; y++; for (oaf = 0; oaf < noaf; oaf++) { for (i = 0; i <= n; i++) { net[oaf].osc[i].teta = *y++;} for (i = 0; i <= n; i++) { net[oaf].osc[i].amp = *y++; } net[oaf].osc[0].omega0 = *y++; } } //======================= s/p derivs ============== // Computation of the RHS of equations void derivs(double y[], double dydx[]) { int oaf; long n = par.n; long n1 = 2*(n + 1) + 1; int i, j; double *teta[noaf]; double *amp[noaf]; double *comega0[noaf]; double *dteta_dt[noaf]; double *damp_dt[noaf]; double *dcomega0_dt[noaf]; // Assigning parameters different during exposition and normal work double COtoCOw = par.COtoCOw; double beta2 = integr.beta2; if (it*integr.dt <= integr.expos) { COtoCOw = par.COtoCOw_expos; } //===== Array addresses ===== teta[0] = &y[1]; amp[0] = &y[n + 2]; comega0[0] = &y[n + n + 3]; dteta_dt[0] = &dydx[1]; damp_dt[0] = &dydx[n + 2]; dcomega0_dt[0] = &dydx[n + n + 3]; for (oaf = 1; oaf < noaf; oaf++) { teta[oaf] = teta[0] + oaf*n1; amp[oaf] = amp[0] + oaf*n1; comega0[oaf] = comega0[0] +oaf*n1 ; dteta_dt[oaf] = dteta_dt[0] + oaf*n1; damp_dt[oaf] = damp_dt[0] + oaf*n1; dcomega0_dt[oaf] = dcomega0_dt[0] + oaf*n1; } for (oaf = 0; oaf < noaf; oaf++) { //===== Equations for phases ===== // POs for (i = 1; i <= n; i++) { dteta_dt[oaf][i] = net[oaf].osc[i].omega = 0; if (net[oaf].osc[i].state == active) { // Local interaction for (j = 0; j < connec[i].ncon; j++) { dteta_dt[oaf][i] += amp[oaf][connec[i].source[j]]* sin(teta[oaf][connec[i].source[j]] - teta[oaf][i]); } dteta_dt[oaf][i] *= par.POtoPOlocw; // Interaction with the CO dteta_dt[oaf][i] += two_pi*net[oaf].osc[i].omega0; dteta_dt[oaf][i] += par.COtoPOw*amp[oaf][0]*g1(teta[oaf][0] - teta[oaf][i]); dteta_dt[oaf][i] += net[oaf].osc[i].noise; // Interaction with POs of the same column double sum = 0.; for (int oafcount = 0; oafcount < noaf; oafcount++) { sum += amp[oaf][i]*sin(teta[oafcount][i] - teta[oaf][i]); } sum = sum*par.POtoPOcolw/noaf; dteta_dt[oaf][i] += sum; } net[oaf].osc[i].omega = dteta_dt[oaf][i]; } // CO // Computation of the number of resonance oscillators int nres = 0; // the number of resonant oscillators for (i = 1; i <= n; i++) { if (net[oaf].osc[i].amp > integr.resthresh) { nres++;} } if (nres < integr.nresmin) nres = integr.nresmin; // Interaction with POs double sum = 0; int column = 0, row = 0; for (i = 1; i <= n; i++) { if (net[oaf].osc[i].state == active) { sum += im.saliency[row][column]*amp[oaf][i]*g(teta[oaf][i] - teta[oaf][0]); } column++; if (column == ncolumns) { column = 0; row++; } } sum /= nres; sum *= par.POtoCOw; // Interaction with COs double sum1 = 0.; for (int oafcount = 0; oafcount < noaf; oafcount++) { if (oafcount != oaf) { sum1 += amp[oafcount][0]*g2(teta[oafcount][0] - teta[oaf][0]); } } sum1 *= COtoCOw; dteta_dt[oaf][0] = two_pi*comega0[oaf][0] + sum + sum1; net[oaf].osc[0].omega = dteta_dt[oaf][0]; //afxDump << "oaf = " << oaf << " comega = " << net[oaf].osc[0].omega << "\n"; //***** Equation for natural frequencies ***** dcomega0_dt[oaf][0] = integr.alpha*(dteta_dt[oaf][0] - two_pi*comega0[oaf][0]); //***** Equations for amplitudes ***** damp_dt[oaf][0] = 0.0; for (oafcount = 0; oafcount < noaf; oafcount++) { if (oafcount != oaf) { damp_dt[oaf][0] += f(teta[oafcount][0] - teta[oaf][0]); } } if (damp_dt[oaf][0] > 1.0) damp_dt[oaf][0] = 1.0; // Limit on the value // for the case of tripple conjunction damp_dt[oaf][0] *= integr.gamma1; damp_dt[oaf][0] += integr.dzeta1 - amp[oaf][0]; damp_dt[oaf][0] *= integr.beta_CO; for (i = 1; i <= n; i++) { damp_dt[oaf][i] = 0; if (net[oaf].osc[i].state == active) { damp_dt[oaf][i] = - amp[oaf][i]; damp_dt[oaf][i] += integr.gamma*f(teta[oaf][0] - teta[oaf][i]); if (damp_dt[oaf][i] >= 0) { damp_dt[oaf][i] *= integr.beta1; } else { damp_dt[oaf][i] *= beta2; } } } } }