Bugfix to LCALIF_update_state.cl

Bugfix to LCALIF_update_state.cl

git-svn-id: 602a26e73ae9f2a14e2bb95676f2e137fcc39919@6360 7c0444ca-5550-0410-9008-faecdbe78eb5

#include "LIF_params.h"
#include "cl_random.hcl"

#ifndef PV_USE_OPENCL
#  include <math.h>
#  define EXP expf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_CONST
#  define CL_MEM_LOCAL
#else  /* compiling with OpenCL */
#  define EXP exp
#  define CL_KERNEL       __kernel
#  define CL_MEM_GLOBAL   __global
#  define CL_MEM_CONST    __constant
#  define CL_MEM_LOCAL    __local
#  include "conversions.hcl"
#  define CHANNEL_EXC   0
#  define CHANNEL_INH   1
#  define CHANNEL_INHB  2
#  define CHANNEL_GAP   3
#endif

//#undef USE_CLRANDOM
#ifndef USE_CLRANDOM
#  include "../utils/pv_random.h"
#endif

inline
float LCALIF_tauInf(const float tau, const float G_E, const float G_I, const float G_IB, const float sum_gap) {
   return tau/(1+G_E+G_I+G_IB+sum_gap);
}

inline
float LCALIF_VmemInf(const float Vrest, const float V_E, const float V_I, const float V_B, const float G_E, const float G_I, const float G_B, const float G_gap, const float sumgap) {
   return (Vrest + V_E*G_E + V_I*G_I + V_B*G_B + G_gap)/(1+G_E+G_I+G_B+sumgap);
}

// The commented-out code below is only used for the Heun's method integration, which works very poorly when the equation is stiff.
/*
inline
float LIFGap_Vmem_derivative(
      const float Vmem,
      const float G_E,
      const float G_I,
      const float G_IB,
      const float G_Gap,
      const float V_E,
      const float V_I,
      const float V_IB,
      const float sum_gap,
      const float Vrest,
      const float tau) {
   float totalconductance = 1.0 + G_E + G_I + G_IB + sum_gap;
   float Vmeminf = (Vrest + V_E*G_E + V_I*G_I + V_IB*G_IB + G_Gap)/totalconductance;
   return totalconductance*(Vmeminf-Vmem)/tau;
}
 */

//
// update the state of a LCALIF layer (spiking)
//
//    assume called with 1D kernel
//
// LCALIF_update_state_beginning uses a Heun scheme for V, using values of the conductances at both the beginning and end of the timestep.  Spikes in the input are applied at the beginning of the timestep.
//
CL_KERNEL
void LCALIF_update_state(
    const int numNeurons,
    const double timed,
    const double dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    float Vscale,
    float * Vadpt,
    float tauTHR,
    const float targetRateHz,

    pvdata_t * integratedSpikeCount,

    CL_MEM_CONST LIF_params * params,
    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * V,
    CL_MEM_GLOBAL float * Vth,
    CL_MEM_GLOBAL float * G_E,
    CL_MEM_GLOBAL float * G_I,
    CL_MEM_GLOBAL float * G_IB,
    CL_MEM_GLOBAL float * GSynHead,
//    CL_MEM_GLOBAL float * GSynExc,
//    CL_MEM_GLOBAL float * GSynInh,
//    CL_MEM_GLOBAL float * GSynInhB,
//    CL_MEM_GLOBAL float * GSynGap,
    CL_MEM_GLOBAL float * activity,

    const float sum_gap,
    CL_MEM_GLOBAL float * G_Gap,
    CL_MEM_GLOBAL float * Vattained,
    CL_MEM_GLOBAL float * Vmeminf)
{

   // convert target rate from Hz to kHz
   float targetRatekHz = targetRateHz/1000;

   // tau parameters
   const float tauO = 1/targetRatekHz;   //Convert target rate from kHz to ms (tauO)

   const float decayE   = EXP(-dt/params->tauE);
   const float decayI   = EXP(-dt/params->tauI);
   const float decayIB  = EXP(-dt/params->tauIB);
   const float decayVth = EXP(-dt/params->tauVth);
   const float decayO   = EXP(-dt/tauO);

   //Convert dt to seconds
   const float dt_sec = .001 * dt;

#ifndef PV_USE_OPENCL

for (int k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // local param variables
   float tau, Vrest, VthRest, Vexc, Vinh, VinhB, deltaVth;

   // const float GMAX = 10.0;

   // local variables
   float l_activ;

   uint4 l_rnd = rnd[k];

   float l_V   = V[k];
   float l_Vth = Vth[k];

   // The correction factors to the conductances are so that if l_GSyn_* is the same every timestep,
   // then the asymptotic value of l_G_* will be l_GSyn_*
   float l_G_E  = G_E[k];
   float l_G_I  = G_I[k];
   float l_G_IB = G_IB[k];
   float l_G_Gap = G_Gap[k];

#define CHANNEL_NORM (CHANNEL_GAP+1)
   CL_MEM_GLOBAL float * GSynExc = &GSynHead[CHANNEL_EXC*numNeurons];
   CL_MEM_GLOBAL float * GSynInh = &GSynHead[CHANNEL_INH*numNeurons];
   CL_MEM_GLOBAL float * GSynInhB = &GSynHead[CHANNEL_INHB*numNeurons];
   CL_MEM_GLOBAL float * GSynGap = &GSynHead[CHANNEL_GAP*numNeurons];
   CL_MEM_GLOBAL float * GSynNorm = &GSynHead[CHANNEL_NORM*numNeurons];
   float l_GSynExc  = GSynExc[k];
   float l_GSynInh  = GSynInh[k];
   float l_GSynInhB = GSynInhB[k];
   float l_GSynGap  = GSynGap[k];
   float l_GSynNorm = GSynNorm[k];

   // define local param variables
   //
   tau        = params->tau;
   Vexc       = params->Vexc;
   Vinh       = params->Vinh;
   VinhB      = params->VinhB;
   Vrest      = params->Vrest;

   VthRest  = params->VthRest;
   deltaVth = params->deltaVth;

   // assert(l_GSynNorm>=0 && l_GSynExc>=0 && (l_GSynNorm!=0 || l_GSynExc==0));
   if (!(l_GSynNorm>=0 && l_GSynExc>=0 && (l_GSynNorm!=0 || l_GSynExc==0))) {
      fprintf(stderr, "time = %f, k = %d, l_GSynNorm = %f, l_GSynExc = %f\n", timed, k, l_GSynNorm, l_GSynExc);
      abort();
   };
   l_GSynExc /= (l_GSynNorm + (l_GSynNorm==0 ? 1 : 0));

   // add noise
   //
#ifdef USE_CLRANDOM
   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqE) {
      l_rnd = cl_random_get(l_rnd);
      l_GSynExc = l_GSynExc + params->noiseAmpE*cl_random_prob(l_rnd);
   }

   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqI) {
      l_rnd = cl_random_get(l_rnd);
      l_GSynInh = l_GSynInh + params->noiseAmpI*cl_random_prob(l_rnd);
   }

   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqIB) {
      l_rnd = cl_random_get(l_rnd);
      l_GSynInhB = l_GSynInhB + params->noiseAmpIB*cl_random_prob(l_rnd);
   }
#else
   if (pv_random_prob() < dt_sec*params->noiseFreqE) {
      l_GSynExc = l_GSynExc + params->noiseAmpE*pv_random_prob();
   }

   if (pv_random_prob() < dt_sec*params->noiseFreqI) {
      l_GSynInh = l_GSynInh + params->noiseAmpI*pv_random_prob();
   }

   if (pv_random_prob() < dt_sec*params->noiseFreqIB) {
      l_GSynInhB = l_GSynInhB + params->noiseAmpIB*pv_random_prob();
   }
#endif

   const float GMAX = FLT_MAX;

   // The portion of code below uses the newer method of calculating l_V.
   float G_E_initial, G_I_initial, G_IB_initial, G_E_final, G_I_final, G_IB_final;

   G_E_initial = l_G_E + l_GSynExc;
   G_I_initial = l_G_I + l_GSynInh;
   G_IB_initial = l_G_IB + l_GSynInhB;

   G_E_initial  = (G_E_initial  > GMAX) ? GMAX : G_E_initial;
   G_I_initial  = (G_I_initial  > GMAX) ? GMAX : G_I_initial;
   G_IB_initial = (G_IB_initial > GMAX) ? GMAX : G_IB_initial;

   float totalconductance = 1.0 + G_E_initial + G_I_initial + G_IB_initial + sum_gap;
   Vmeminf[k] = (Vrest + Vexc*G_E_initial + Vinh*G_I_initial + VinhB*G_IB_initial + l_GSynGap)/totalconductance;

   G_E_final = G_E_initial * decayE;
   G_I_final = G_I_initial * decayI;
   G_IB_final = G_IB_initial * decayIB;

   l_G_Gap = l_GSynGap;

   float VmemInf1 = LCALIF_VmemInf(Vrest, Vexc, Vinh, VinhB, G_E_initial, G_I_initial, G_IB_initial, l_G_Gap, sum_gap);
   float tauInf1 = LCALIF_tauInf(tau, G_E_initial, G_I_initial, G_IB_initial, l_G_Gap);
   // float VmemInf2 = LCALIF_VmemInf(Vrest, Vexc, Vinh, VinhB, G_E_final, G_I_final, G_IB_final, l_G_Gap, sum_gap);
   // float tauInf2 = LCALIF_tauInf(tau, G_E_final, G_I_final, G_IB_final, l_G_Gap);
   l_V = exp(-dt/tauInf1)*(l_V - VmemInf1) + VmemInf1;
   // The commented-out code works very poorly if the equation for the membrane potential is stiff, which happens if tauInf < dt
   // dV1 = LIFGap_Vmem_derivative(l_V, G_E_initial, G_I_initial, G_IB_initial, l_G_Gap, Vexc, Vinh, VinhB, sum_gap, Vrest, tau);
   // dV2 = LIFGap_Vmem_derivative(l_V+dt*dV1, G_E_final, G_I_final, G_IB_final, l_G_Gap, Vexc, Vinh, VinhB, sum_gap, Vrest, tau);
   // dV = (dV1+dV2)*0.5;
   // l_V = l_V + dt*dV;

   l_G_E = G_E_final;
   l_G_I = G_I_final;
   l_G_IB = G_IB_final;

   //l_Vth updates according to traditional LIF rule in addition to the slow threshold adaptation
   //      See LCA_Equations.pdf in the documentation for a full description of the neuron adaptive firing threshold.

   Vadpt[k] += (dt/tauTHR) * ((integratedSpikeCount[k]/tauO) - targetRatekHz) * (Vscale/targetRatekHz);

   l_Vth = Vadpt[k] + decayVth * (l_Vth - Vadpt[k]);

   bool fired_flag = (l_V > l_Vth);

   l_activ = fired_flag ? 1.0f             : 0.0f;
   Vattained[k] = l_V; // Save the value of V before it drops due to the spike
   l_V     = fired_flag ? Vrest            : l_V;
   l_Vth   = fired_flag ? l_Vth + deltaVth : l_Vth;
   l_G_IB  = fired_flag ? l_G_IB + 1.0f    : l_G_IB;

   //integratedSpikeCount is the trace activity of the neuron, with an exponential decay
   integratedSpikeCount[k] = decayO * (l_activ + integratedSpikeCount[k]);

   //
   // These actions must be done outside of kernel
   //    1. set activity to 0 in boundary (if needed)
   //    2. update active indices
   //

   // store local variables back to global memory
   //
   rnd[k] = l_rnd;

   activity[kex] = l_activ;

   V[k]   = l_V;
   Vth[k] = l_Vth;

   G_E[k]  = l_G_E;
   G_I[k]  = l_G_I;
   G_IB[k] = l_G_IB;
   G_Gap[k] = l_G_Gap;

   GSynExc[k]  = 0.0f;
   GSynInh[k]  = 0.0f;
   GSynInhB[k] = 0.0f;
   GSynGap[k]  = 0.0f;
   GSynNorm[k] = 0.0f;

#ifndef PV_USE_OPENCL
   } // loop over k
#endif

}

#include "LIF_params.h"
#include "cl_random.hcl"

#ifndef PV_USE_OPENCL
#  include <math.h>
#  define EXP expf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_CONST
#  define CL_MEM_LOCAL
#else  /* compiling with OpenCL */
#  define EXP exp
#  define CL_KERNEL       __kernel
#  define CL_MEM_GLOBAL   __global
#  define CL_MEM_CONST    __constant
#  define CL_MEM_LOCAL    __local
#  include "conversions.hcl"
#  define CHANNEL_EXC   0
#  define CHANNEL_INH   1
#  define CHANNEL_INHB  2
#  define CHANNEL_GAP   3
#endif

//#undef USE_CLRANDOM
#ifndef USE_CLRANDOM
#  include "../utils/pv_random.h"
#endif

inline
float LCALIF_tauInf(const float tau, const float G_E, const float G_I, const float G_IB, const float sum_gap) {
   return tau/(1+G_E+G_I+G_IB+sum_gap);
}

inline
float LCALIF_VmemInf(const float Vrest, const float V_E, const float V_I, const float V_B, const float G_E, const float G_I, const float G_B, const float G_gap, const float sumgap) {
   return (Vrest + V_E*G_E + V_I*G_I + V_B*G_B + G_gap)/(1+G_E+G_I+G_B+sumgap);
}

// The commented-out code below is only used for the Heun's method integration, which works very poorly when the equation is stiff.
/*
inline
float LIFGap_Vmem_derivative(
      const float Vmem,
      const float G_E,
      const float G_I,
      const float G_IB,
      const float G_Gap,
      const float V_E,
      const float V_I,
      const float V_IB,
      const float sum_gap,
      const float Vrest,
      const float tau) {
   float totalconductance = 1.0 + G_E + G_I + G_IB + sum_gap;
   float Vmeminf = (Vrest + V_E*G_E + V_I*G_I + V_IB*G_IB + G_Gap)/totalconductance;
   return totalconductance*(Vmeminf-Vmem)/tau;
}
 */

//
// update the state of a LCALIF layer (spiking)
//
//    assume called with 1D kernel
//
// LCALIF_update_state_beginning uses a Heun scheme for V, using values of the conductances at both the beginning and end of the timestep.  Spikes in the input are applied at the beginning of the timestep.
//
CL_KERNEL
void LCALIF_update_state(
    const int numNeurons,
    const double timed,
    const double dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    float Vscale,
    float * Vadpt,
    float tauTHR,
    const float targetRateHz,

    pvdata_t * integratedSpikeCount,

    CL_MEM_CONST LIF_params * params,
    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * V,
    CL_MEM_GLOBAL float * Vth,
    CL_MEM_GLOBAL float * G_E,
    CL_MEM_GLOBAL float * G_I,
    CL_MEM_GLOBAL float * G_IB,
    CL_MEM_GLOBAL float * GSynHead,
//    CL_MEM_GLOBAL float * GSynExc,
//    CL_MEM_GLOBAL float * GSynInh,
//    CL_MEM_GLOBAL float * GSynInhB,
//    CL_MEM_GLOBAL float * GSynGap,
    CL_MEM_GLOBAL float * activity,

    const float sum_gap,
    CL_MEM_GLOBAL float * G_Gap,
    CL_MEM_GLOBAL float * Vattained,
    CL_MEM_GLOBAL float * Vmeminf)
{

   // convert target rate from Hz to kHz
   float targetRatekHz = targetRateHz/1000;

   // tau parameters
   const float tauO = 1/targetRatekHz;   //Convert target rate from kHz to ms (tauO)

   const float decayE   = EXP(-dt/params->tauE);
   const float decayI   = EXP(-dt/params->tauI);
   const float decayIB  = EXP(-dt/params->tauIB);
   const float decayVth = EXP(-dt/params->tauVth);
   const float decayO   = EXP(-dt/tauO);

   //Convert dt to seconds
   const float dt_sec = .001 * dt;

#ifndef PV_USE_OPENCL

for (int k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // local param variables
   float tau, Vrest, VthRest, Vexc, Vinh, VinhB, deltaVth;

   // const float GMAX = 10.0;

   // local variables
   float l_activ;

   uint4 l_rnd = rnd[k];

   float l_V   = V[k];
   float l_Vth = Vth[k];

   // The correction factors to the conductances are so that if l_GSyn_* is the same every timestep,
   // then the asymptotic value of l_G_* will be l_GSyn_*
   float l_G_E  = G_E[k];
   float l_G_I  = G_I[k];
   float l_G_IB = G_IB[k];
   float l_G_Gap = G_Gap[k];

   CL_MEM_GLOBAL float * GSynExc = &GSynHead[CHANNEL_EXC*numNeurons];
   CL_MEM_GLOBAL float * GSynInh = &GSynHead[CHANNEL_INH*numNeurons];
   CL_MEM_GLOBAL float * GSynInhB = &GSynHead[CHANNEL_INHB*numNeurons];
   CL_MEM_GLOBAL float * GSynGap = &GSynHead[CHANNEL_GAP*numNeurons];
   float l_GSynExc  = GSynExc[k];
   float l_GSynInh  = GSynInh[k];
   float l_GSynInhB = GSynInhB[k];
   float l_GSynGap  = GSynGap[k];

   // define local param variables
   //
   tau        = params->tau;
   Vexc       = params->Vexc;
   Vinh       = params->Vinh;
   VinhB      = params->VinhB;
   Vrest      = params->Vrest;

   VthRest  = params->VthRest;
   deltaVth = params->deltaVth;

   // add noise
   //

#ifdef USE_CLRANDOM
   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqE) {
      l_rnd = cl_random_get(l_rnd);
      l_GSynExc = l_GSynExc + params->noiseAmpE*cl_random_prob(l_rnd);
   }

   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqI) {
      l_rnd = cl_random_get(l_rnd);
      l_GSynInh = l_GSynInh + params->noiseAmpI*cl_random_prob(l_rnd);
   }

   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqIB) {
      l_rnd = cl_random_get(l_rnd);
      l_GSynInhB = l_GSynInhB + params->noiseAmpIB*cl_random_prob(l_rnd);
   }
#else
   if (pv_random_prob() < dt_sec*params->noiseFreqE) {
      l_GSynExc = l_GSynExc + params->noiseAmpE*pv_random_prob();
   }

   if (pv_random_prob() < dt_sec*params->noiseFreqI) {
      l_GSynInh = l_GSynInh + params->noiseAmpI*pv_random_prob();
   }

   if (pv_random_prob() < dt_sec*params->noiseFreqIB) {
      l_GSynInhB = l_GSynInhB + params->noiseAmpIB*pv_random_prob();
   }
#endif

   const float GMAX = FLT_MAX;

   // The portion of code below uses the newer method of calculating l_V.
   float G_E_initial, G_I_initial, G_IB_initial, G_E_final, G_I_final, G_IB_final;

   G_E_initial = l_G_E + l_GSynExc;
   G_I_initial = l_G_I + l_GSynInh;
   G_IB_initial = l_G_IB + l_GSynInhB;

   G_E_initial  = (G_E_initial  > GMAX) ? GMAX : G_E_initial;
   G_I_initial  = (G_I_initial  > GMAX) ? GMAX : G_I_initial;
   G_IB_initial = (G_IB_initial > GMAX) ? GMAX : G_IB_initial;

   float totalconductance = 1.0 + G_E_initial + G_I_initial + G_IB_initial + sum_gap;
   Vmeminf[k] = (Vrest + Vexc*G_E_initial + Vinh*G_I_initial + VinhB*G_IB_initial + l_GSynGap)/totalconductance;

   G_E_final = G_E_initial * decayE;
   G_I_final = G_I_initial * decayI;
   G_IB_final = G_IB_initial * decayIB;

   l_G_Gap = l_GSynGap;

   float VmemInf1 = LCALIF_VmemInf(Vrest, Vexc, Vinh, VinhB, G_E_initial, G_I_initial, G_IB_initial, l_G_Gap, sum_gap);
   float tauInf1 = LCALIF_tauInf(tau, G_E_initial, G_I_initial, G_IB_initial, l_G_Gap);
   // float VmemInf2 = LCALIF_VmemInf(Vrest, Vexc, Vinh, VinhB, G_E_final, G_I_final, G_IB_final, l_G_Gap, sum_gap);
   // float tauInf2 = LCALIF_tauInf(tau, G_E_final, G_I_final, G_IB_final, l_G_Gap);
   l_V = exp(-dt/tauInf1)*(l_V - VmemInf1) + VmemInf1;
   // The commented-out code works very poorly if the equation for the membrane potential is stiff, which happens if tauInf < dt
   // dV1 = LIFGap_Vmem_derivative(l_V, G_E_initial, G_I_initial, G_IB_initial, l_G_Gap, Vexc, Vinh, VinhB, sum_gap, Vrest, tau);
   // dV2 = LIFGap_Vmem_derivative(l_V+dt*dV1, G_E_final, G_I_final, G_IB_final, l_G_Gap, Vexc, Vinh, VinhB, sum_gap, Vrest, tau);
   // dV = (dV1+dV2)*0.5;
   // l_V = l_V + dt*dV;

   l_G_E = G_E_final;
   l_G_I = G_I_final;
   l_G_IB = G_IB_final;

   //l_Vth updates according to traditional LIF rule in addition to the slow threshold adaptation
   //      See LCA_Equations.pdf in the documentation for a full description of the neuron adaptive firing threshold.

   Vadpt[k] += (dt/tauTHR) * ((integratedSpikeCount[k]/tauO) - targetRatekHz) * (Vscale/targetRatekHz);

   l_Vth = Vadpt[k] + decayVth * (l_Vth - Vadpt[k]);

   bool fired_flag = (l_V > l_Vth);

   l_activ = fired_flag ? 1.0f             : 0.0f;
   Vattained[k] = l_V; // Save the value of V before it drops due to the spike
   l_V     = fired_flag ? Vrest            : l_V;
   l_Vth   = fired_flag ? l_Vth + deltaVth : l_Vth;
   l_G_IB  = fired_flag ? l_G_IB + 1.0f    : l_G_IB;

   //integratedSpikeCount is the trace activity of the neuron, with an exponential decay
   integratedSpikeCount[k] = decayO * (l_activ + integratedSpikeCount[k]);

   //
   // These actions must be done outside of kernel
   //    1. set activity to 0 in boundary (if needed)
   //    2. update active indices
   //

   // store local variables back to global memory
   //
   rnd[k] = l_rnd;

   activity[kex] = l_activ;

   V[k]   = l_V;
   Vth[k] = l_Vth;

   G_E[k]  = l_G_E;
   G_I[k]  = l_G_I;
   G_IB[k] = l_G_IB;
   G_Gap[k] = l_G_Gap;

   GSynExc[k]  = 0.0f;
   GSynInh[k]  = 0.0f;
   GSynInhB[k] = 0.0f;
   GSynGap[k]  = 0.0f;

#ifndef PV_USE_OPENCL
   } // loop over k
#endif

}


use pv_random until cl_random is fixed (currently seeds are not different enough between ON and OFF layers)

git-svn-id: 602a26e73ae9f2a14e2bb95676f2e137fcc39919@6266 7c0444ca-5550-0410-9008-faecdbe78eb5

#include "Retina_params.h"
#include "cl_random.hcl"

#ifndef PI
#  define PI 3.1415926535897932
#endif

#ifndef PV_USE_OPENCL

#  include <math.h>
#  define EXP  expf
#  define COS  cosf
#  define FMOD fmodf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_CONST
#  define CL_MEM_LOCAL

#else

#  define EXP exp
#  define COS  __cosf
#  define FMOD __fmodf
#  define CL_KERNEL     __kernel
#  define CL_MEM_GLOBAL __global
#  define CL_MEM_CONST    __constant
#  define CL_MEM_LOCAL  __local
#  include "conversions.hcl"
#  define CHANNEL_EXC   0
#  define CHANNEL_INH   1
#  define CHANNEL_INHB  2
#  define CHANNEL_GAP   3

#endif /* PV_USE_OPENCL */

/*
 * Spiking method for Retina
 * Returns 1 if an event should occur, 0 otherwise. This is a stochastic model.
 *
 * REMARKS:
 *      - During ABS_REFRACTORY_PERIOD a neuron does not spike
 *      - The neurons that correspond to stimuli (on Image pixels)
 *        spike with probability probStim.
 *      - The neurons that correspond to background image pixels
 *        spike with probability probBase.
 *      - After ABS_REFRACTORY_PERIOD the spiking probability
 *        grows exponentially to probBase and probStim respectively.
 *      - The burst of the retina is periodic with period T set by
 *        T = 1000/burstFreq in milliseconds
 *      - When the time t is such that mT < t < mT + burstDuration, where m is
 *        an integer, the burstStatus is set to 1.
 *      - The burstStatus is also determined by the condition that
 *        beginStim < t < endStim. These parameters are set in the input
 *        params file params.stdp
 *      - sinAmp modulates the spiking probability only when burstDuration <= 0
 *        or burstFreq = 0
 *      - probSpike is set to probBase for all neurons.
 *      - for neurons exposed to Image on pixels, probSpike increases with probStim.
 *      - When the probability is negative, the neuron does not spike.
 *
 * NOTES:
 *      - time is measured in milliseconds.
 *
 */

static inline
float calcBurstStatus(float timef, CL_MEM_CONST Retina_params * params) {
   float burstStatus;
   if (params->burstDuration <= 0 || params->burstFreq == 0) {
      // sinAmp = COS( 2*PI*time * params->burstFreq / 1000. );
      burstStatus = COS( 2*PI*timef * params->burstFreq / 1000. );
   }
   else {
      burstStatus = FMOD(timef, 1000. / params->burstFreq);
      burstStatus = burstStatus < params->burstDuration;
   }
   burstStatus *= (int) ( (timef >= params->beginStim) && (timef < params->endStim) );
   return burstStatus;
}

static inline
int spike(float time, float dt,
          float prev, float stimFactor, uint4 * rnd_state, float burst_status, CL_MEM_CONST Retina_params * params)
{
   float probSpike;
   // float burstStatus = 1;
   // float sinAmp = 1.0;

   // input parameters
   //
   float probBase  = params->probBase;
   float probStim  = params->probStim * stimFactor;

   // see if neuron is in a refractory period
   //
   if ((time - prev) < params->abs_refractory_period) {
      return 0;
   }
   else {
      float delta = time - prev - params->abs_refractory_period;
      float refact = 1.0f - EXP(-delta/params->refractory_period);
      refact = (refact < 0) ? 0 : refact;
      probBase *= refact;
      probStim *= refact;
   }

   // burstStatus = calcBurstStatus(time, params);
//   if (params->burstDuration <= 0 || params->burstFreq == 0) {
//      // sinAmp = COS( 2*PI*time * params->burstFreq / 1000. );
//      burstStatus = COS( 2*PI*time * params->burstFreq / 1000. );
//   }
//   else {
//      burstStatus = FMOD(time, 1000. / params->burstFreq);
//      burstStatus = burstStatus <= params->burstDuration;
//   }

//   burstStatus *= (int) ( (time >= params->beginStim) && (time < params->endStim) );
   probSpike = probBase;

//   if ((int)burstStatus) {
//      probSpike += probStim * sinAmp;  // negative prob is OK
//   }
   probSpike += probStim * burst_status;  // negative prob is OK

   probSpike *= dt; // convert rate from number of spikes per millisecond to number of spikes in dt.

   // !!!TODO!!! cl_random_prob does not currently produce independent sequences for each cell
   //*rnd_state = cl_random_get(*rnd_state);
   //int spike_flag = (cl_random_prob(*rnd_state) < probSpike);
   int spike_flag = (pv_random_prob() < probSpike);
   return spike_flag;
}

//
// update the state of a retinal layer (spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void Retina_spiking_update_state (
    const int numNeurons,
    const float time,
    const float dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_CONST Retina_params * params,
    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * GSynHead,
//    CL_MEM_GLOBAL float * phiExc,
//    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * activity,
    CL_MEM_GLOBAL float * prevTime)
{
   int k;
   float burst_status = calcBurstStatus(time, params);
#ifndef PV_USE_OPENCL
for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // load local variables from global memory
   //
   uint4 l_rnd = rnd[k];
   CL_MEM_GLOBAL float * phiExc = &GSynHead[CHANNEL_EXC*numNeurons];
   CL_MEM_GLOBAL float * phiInh = &GSynHead[CHANNEL_INH*numNeurons];
   float l_phiExc = phiExc[k];
   float l_phiInh = phiInh[k];
   float l_prev   = prevTime[kex];
   float l_activ;

   l_activ = (float) spike(time, dt, l_prev, (l_phiExc - l_phiInh), &l_rnd, burst_status, params);
   l_prev  = (l_activ > 0.0f) ? time : l_prev;

   l_phiExc = 0.0f;
   l_phiInh = 0.0f;

   // store local variables back to global memory
   //
   rnd[k] = l_rnd;
   phiExc[k] = l_phiExc;
   phiInh[k] = l_phiInh;
   prevTime[kex] = l_prev;
   activity[kex] = l_activ;

#ifndef PV_USE_OPENCL
   }
#endif

}

//
// update the state of a retinal layer (non-spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void Retina_nonspiking_update_state (
    const int numNeurons,
    const float time,
    const float dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_CONST Retina_params * params,
    CL_MEM_GLOBAL float * GSynHead,
//    CL_MEM_GLOBAL float * phiExc,
//    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * activity)
{
   int k;
   float burstStatus = calcBurstStatus(time, params);
#ifndef PV_USE_OPENCL
for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // load local variables from global memory
   //
   CL_MEM_GLOBAL float * phiExc = &GSynHead[CHANNEL_EXC*numNeurons];
   CL_MEM_GLOBAL float * phiInh = &GSynHead[CHANNEL_INH*numNeurons];
   float l_phiExc = phiExc[k];
   float l_phiInh = phiInh[k];
   float l_activ;

   // adding base prob should not change default behavior
   l_activ = burstStatus * params->probStim*(l_phiExc - l_phiInh) + params->probBase;
//   if (l_activ != 0.0f && burstStatus != 1.0f)
//       l_activ *= burstStatus;

   l_phiExc = 0.0f;
   l_phiInh = 0.0f;

   // store local variables back to global memory
   //
   phiExc[k] = l_phiExc;
   phiInh[k] = l_phiInh;
   activity[kex] = l_activ;

#ifndef PV_USE_OPENCL
   }
#endif

}

#include "Retina_params.h"
#include "cl_random.hcl"

#ifndef PI
#  define PI 3.1415926535897932
#endif

#ifndef PV_USE_OPENCL

#  include <math.h>
#  define EXP  expf
#  define COS  cosf
#  define FMOD fmodf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_CONST
#  define CL_MEM_LOCAL

#else

#  define EXP exp
#  define COS  __cosf
#  define FMOD __fmodf
#  define CL_KERNEL     __kernel
#  define CL_MEM_GLOBAL __global
#  define CL_MEM_CONST    __constant
#  define CL_MEM_LOCAL  __local
#  include "conversions.hcl"
#  define CHANNEL_EXC   0
#  define CHANNEL_INH   1
#  define CHANNEL_INHB  2
#  define CHANNEL_GAP   3

#endif /* PV_USE_OPENCL */

/*
 * Spiking method for Retina
 * Returns 1 if an event should occur, 0 otherwise. This is a stochastic model.
 *
 * REMARKS:
 *      - During ABS_REFRACTORY_PERIOD a neuron does not spike
 *      - The neurons that correspond to stimuli (on Image pixels)
 *        spike with probability probStim.
 *      - The neurons that correspond to background image pixels
 *        spike with probability probBase.
 *      - After ABS_REFRACTORY_PERIOD the spiking probability
 *        grows exponentially to probBase and probStim respectively.
 *      - The burst of the retina is periodic with period T set by
 *        T = 1000/burstFreq in milliseconds
 *      - When the time t is such that mT < t < mT + burstDuration, where m is
 *        an integer, the burstStatus is set to 1.
 *      - The burstStatus is also determined by the condition that
 *        beginStim < t < endStim. These parameters are set in the input
 *        params file params.stdp
 *      - sinAmp modulates the spiking probability only when burstDuration <= 0
 *        or burstFreq = 0
 *      - probSpike is set to probBase for all neurons.
 *      - for neurons exposed to Image on pixels, probSpike increases with probStim.
 *      - When the probability is negative, the neuron does not spike.
 *
 * NOTES:
 *      - time is measured in milliseconds.
 *
 */

static inline
float calcBurstStatus(float timef, CL_MEM_CONST Retina_params * params) {
   float burstStatus;
   if (params->burstDuration <= 0 || params->burstFreq == 0) {
      // sinAmp = COS( 2*PI*time * params->burstFreq / 1000. );
      burstStatus = COS( 2*PI*timef * params->burstFreq / 1000. );
   }
   else {
      burstStatus = FMOD(timef, 1000. / params->burstFreq);
      burstStatus = burstStatus < params->burstDuration;
   }
   burstStatus *= (int) ( (timef >= params->beginStim) && (timef < params->endStim) );
   return burstStatus;
}

static inline
int spike(float time, float dt,
          float prev, float stimFactor, uint4 * rnd_state, float burst_status, CL_MEM_CONST Retina_params * params)
{
   float probSpike;
   // float burstStatus = 1;
   // float sinAmp = 1.0;

   // input parameters
   //
   float probBase  = params->probBase;
   float probStim  = params->probStim * stimFactor;

   // see if neuron is in a refractory period
   //
   if ((time - prev) < params->abs_refractory_period) {
      return 0;
   }
   else {
      float delta = time - prev - params->abs_refractory_period;
      float refact = 1.0f - EXP(-delta/params->refractory_period);
      refact = (refact < 0) ? 0 : refact;
      probBase *= refact;
      probStim *= refact;
   }

   // burstStatus = calcBurstStatus(time, params);
//   if (params->burstDuration <= 0 || params->burstFreq == 0) {
//      // sinAmp = COS( 2*PI*time * params->burstFreq / 1000. );
//      burstStatus = COS( 2*PI*time * params->burstFreq / 1000. );
//   }
//   else {
//      burstStatus = FMOD(time, 1000. / params->burstFreq);
//      burstStatus = burstStatus <= params->burstDuration;
//   }

//   burstStatus *= (int) ( (time >= params->beginStim) && (time < params->endStim) );
   probSpike = probBase;

//   if ((int)burstStatus) {
//      probSpike += probStim * sinAmp;  // negative prob is OK
//   }
   probSpike += probStim * burst_status;  // negative prob is OK

   probSpike *= dt; // convert rate from number of spikes per millisecond to number of spikes in dt.

   *rnd_state = cl_random_get(*rnd_state);
   int spike_flag = (cl_random_prob(*rnd_state) < probSpike);
   return spike_flag;
}

//
// update the state of a retinal layer (spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void Retina_spiking_update_state (
    const int numNeurons,
    const float time,
    const float dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_CONST Retina_params * params,
    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * GSynHead,
//    CL_MEM_GLOBAL float * phiExc,
//    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * activity,
    CL_MEM_GLOBAL float * prevTime)
{
   int k;
   float burst_status = calcBurstStatus(time, params);
#ifndef PV_USE_OPENCL
for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // load local variables from global memory
   //
   uint4 l_rnd = rnd[k];
   CL_MEM_GLOBAL float * phiExc = &GSynHead[CHANNEL_EXC*numNeurons];
   CL_MEM_GLOBAL float * phiInh = &GSynHead[CHANNEL_INH*numNeurons];
   float l_phiExc = phiExc[k];
   float l_phiInh = phiInh[k];
   float l_prev   = prevTime[kex];
   float l_activ;

   l_activ = (float) spike(time, dt, l_prev, (l_phiExc - l_phiInh), &l_rnd, burst_status, params);
   l_prev  = (l_activ > 0.0f) ? time : l_prev;

   l_phiExc = 0.0f;
   l_phiInh = 0.0f;

   // store local variables back to global memory
   //
   rnd[k] = l_rnd;
   phiExc[k] = l_phiExc;
   phiInh[k] = l_phiInh;
   prevTime[kex] = l_prev;
   activity[kex] = l_activ;

#ifndef PV_USE_OPENCL
   }
#endif

}

//
// update the state of a retinal layer (non-spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void Retina_nonspiking_update_state (
    const int numNeurons,
    const float time,
    const float dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_CONST Retina_params * params,
    CL_MEM_GLOBAL float * GSynHead,
//    CL_MEM_GLOBAL float * phiExc,
//    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * activity)
{
   int k;
   float burstStatus = calcBurstStatus(time, params);
#ifndef PV_USE_OPENCL
for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // load local variables from global memory
   //
   CL_MEM_GLOBAL float * phiExc = &GSynHead[CHANNEL_EXC*numNeurons];
   CL_MEM_GLOBAL float * phiInh = &GSynHead[CHANNEL_INH*numNeurons];
   float l_phiExc = phiExc[k];
   float l_phiInh = phiInh[k];
   float l_activ;

   // adding base prob should not change default behavior
   l_activ = burstStatus * params->probStim*(l_phiExc - l_phiInh) + params->probBase;
//   if (l_activ != 0.0f && burstStatus != 1.0f)
//       l_activ *= burstStatus;

   l_phiExc = 0.0f;
   l_phiInh = 0.0f;

   // store local variables back to global memory
   //
   phiExc[k] = l_phiExc;
   phiInh[k] = l_phiInh;
   activity[kex] = l_activ;

#ifndef PV_USE_OPENCL
   }
#endif

}


Initial Commit

Initial Commit

error: pathspec 'poly.cl' did not match any file(s) known to git


Put OpenCL attribute macro definitions back in.

git-svn-id: 602a26e73ae9f2a14e2bb95676f2e137fcc39919@3180 7c0444ca-5550-0410-9008-faecdbe78eb5

#include "LIF_params.h"
#include "cl_random.hcl"

#ifndef PV_USE_OPENCL
#  include <math.h>
#  define EXP expf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_LOCAL
#else  /* compiling with OpenCL */
#  define EXP exp
#  define CL_KERNEL       __kernel
#  define CL_MEM_GLOBAL   __global
#  define CL_MEM_LOCAL    __local
#  include "conversions.hcl"
#endif

//
// update the state of a retinal layer (spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void LIF_update_state(
    const float time,
    const float dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_GLOBAL LIF_params * params,
    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * V,
    CL_MEM_GLOBAL float * Vth,
    CL_MEM_GLOBAL float * G_E,
    CL_MEM_GLOBAL float * G_I,
    CL_MEM_GLOBAL float * G_IB,
    CL_MEM_GLOBAL float * phiExc,
    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * phiInhB,
    CL_MEM_GLOBAL float * activity)
{
   int k;
#ifndef PV_USE_OPENCL
for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // local param variables
   float tau, tauE, tauI, tauIB, Vrest, VthRest, Vexc, Vinh, VinhB, tauVth, deltaVth;

   float dt_sec;
   const float GMAX = 10.0;

   // local variables
   float l_activ;

   uint4 l_rnd = rnd[k];

   float l_V   = V[k];
   float l_Vth = Vth[k];

   float l_G_E  = G_E[k];
   float l_G_I  = G_I[k];
   float l_G_IB = G_IB[k];

   float l_phiExc  = phiExc[k];
   float l_phiInh  = phiInh[k];
   float l_phiInhB = phiInhB[k];

   // temporary arrays
   float tauInf, VmemInf;

   //
   // start of LIF2_update_exact_linear
   //

   // define local param variables
   //
   tau   = params->tau;
   tauE  = params->tauE;
   tauI  = params->tauI;
   tauIB = params->tauIB;

   Vrest = params->Vrest;
   Vexc  = params->Vexc;
   Vinh  = params->Vinh;
   VinhB = params->VinhB;

   tauVth   = params->tauVth;
   VthRest  = params->VthRest;
   deltaVth = params->deltaVth;

   // add noise
   //
   dt_sec = .001 * dt;   // convert to seconds

   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqE) {
      l_rnd = cl_random_state(l_rnd);
      l_phiExc = l_phiExc + params->noiseAmpE*cl_random_prob(l_rnd);
      l_rnd = cl_random_state(l_rnd);
   }

   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqI) {
      l_rnd = cl_random_state(l_rnd);
      l_phiInh = l_phiInh + params->noiseAmpI*cl_random_prob(l_rnd);
      l_rnd = cl_random_state(l_rnd);
   }

   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqIB) {
      l_rnd = cl_random_state(l_rnd);
      l_phiInhB = l_phiInhB + params->noiseAmpIB*cl_random_prob(l_rnd);
      l_rnd = cl_random_state(l_rnd);
   }

   l_G_E  = l_phiExc  + l_G_E *EXP(-dt/tauE );
   l_G_I  = l_phiInh  + l_G_I *EXP(-dt/tauI );
   l_G_IB = l_phiInhB + l_G_IB*EXP(-dt/tauIB);

   tauInf  = (dt/tau) * (1.0 + l_G_E + l_G_I + l_G_IB);
   VmemInf = (Vrest + l_G_E*Vexc + l_G_I*Vinh + l_G_IB*VinhB)
           / (1.0 + l_G_E + l_G_I + l_G_IB);

   l_V = VmemInf + (l_V - VmemInf)*EXP(-tauInf);

   //
   // start of LIF2_update_finish
   //

   l_phiExc  = 0.0f;
   l_phiInh  = 0.0f;
   l_phiInhB = 0.0f;

   l_Vth = VthRest + (l_Vth - VthRest)*EXP(-dt/tauVth);

   //
   // start of update_f
   //

   l_G_E  = (l_G_E  > GMAX) ? GMAX : l_G_E;
   l_G_I  = (l_G_I  > GMAX) ? GMAX : l_G_I;
   l_G_IB = (l_G_IB > GMAX) ? GMAX : l_G_IB;

   l_activ = activity[kex];

   l_activ = (l_V > l_Vth) ? 1.0f           : 0.0f;
   l_V     = (l_V > l_Vth) ? Vrest          : l_V;
   l_Vth   = (l_V > l_Vth) ? l_Vth + deltaVth : l_Vth;
   l_G_IB  = (l_V > l_Vth) ? l_G_IB + 1.0f    : l_G_IB;

   //
   // These actions must be done outside of kernel
   //    1. set activity to 0 in boundary (if needed)
   //    2. update active indices
   //

   // store local variables back to global memory
   //
   activity[kex] = l_activ;

   V[k]   = l_V;
   Vth[k] = l_Vth;

   G_E[k]  = l_G_E;
   G_I[k]  = l_G_I;
   G_IB[k] = l_G_IB;

   phiExc[k]  = l_phiExc;
   phiInh[k]  = l_phiInh;
   phiInhB[k] = l_phiInhB;

#ifndef PV_USE_OPENCL
   } // loop over k
#endif

}

#include "LIF_params.h"
#include "cl_random.hcl"
#include "conversions.hcl"

#include "../arch/opencl/pv_opencl.h"

#ifndef PV_USE_OPENCL
#  include <math.h>
#  define EXP expf
#else  /* compiling with OpenCL */
#  define EXP exp
#endif

//
// update the state of a retinal layer (spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void LIF_update_state(
    const float time,
    const float dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_GLOBAL LIF_params * params,
    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * V,
    CL_MEM_GLOBAL float * Vth,
    CL_MEM_GLOBAL float * G_E,
    CL_MEM_GLOBAL float * G_I,
    CL_MEM_GLOBAL float * G_IB,
    CL_MEM_GLOBAL float * phiExc,
    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * phiInhB,
    CL_MEM_GLOBAL float * activity)
{
   int k;
#ifndef __CL_PLATFORM_H
for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // local param variables
   float tau, tauE, tauI, tauIB, Vrest, VthRest, Vexc, Vinh, VinhB, tauVth, deltaVth;

   float dt_sec;
   const float GMAX = 10.0;

   // local variables
   float l_activ;

   uint4 l_rnd = rnd[k];

   float l_V   = V[k];
   float l_Vth = Vth[k];

   float l_G_E  = G_E[k];
   float l_G_I  = G_I[k];
   float l_G_IB = G_IB[k];

   float l_phiExc  = phiExc[k];
   float l_phiInh  = phiInh[k];
   float l_phiInhB = phiInhB[k];

   // temporary arrays
   float tauInf, VmemInf;

   //
   // start of LIF2_update_exact_linear
   //

   // define local param variables
   //
   tau   = params->tau;
   tauE  = params->tauE;
   tauI  = params->tauI;
   tauIB = params->tauIB;

   Vrest = params->Vrest;
   Vexc  = params->Vexc;
   Vinh  = params->Vinh;
   VinhB = params->VinhB;

   tauVth   = params->tauVth;
   VthRest  = params->VthRest;
   deltaVth = params->deltaVth;

   // add noise
   //
   dt_sec = .001 * dt;   // convert to seconds

   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqE) {
      l_rnd = cl_random_state(l_rnd);
      l_phiExc = l_phiExc + params->noiseAmpE*cl_random_prob(l_rnd);
      l_rnd = cl_random_state(l_rnd);
   }

   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqI) {
      l_rnd = cl_random_state(l_rnd);
      l_phiInh = l_phiInh + params->noiseAmpI*cl_random_prob(l_rnd);
      l_rnd = cl_random_state(l_rnd);
   }

   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqIB) {
      l_rnd = cl_random_state(l_rnd);
      l_phiInhB = l_phiInhB + params->noiseAmpIB*cl_random_prob(l_rnd);
      l_rnd = cl_random_state(l_rnd);
   }

   l_G_E  = l_phiExc  + l_G_E *EXP(-dt/tauE );
   l_G_I  = l_phiInh  + l_G_I *EXP(-dt/tauI );
   l_G_IB = l_phiInhB + l_G_IB*EXP(-dt/tauIB);

   tauInf  = (dt/tau) * (1.0 + l_G_E + l_G_I + l_G_IB);
   VmemInf = (Vrest + l_G_E*Vexc + l_G_I*Vinh + l_G_IB*VinhB)
           / (1.0 + l_G_E + l_G_I + l_G_IB);

   l_V = VmemInf + (l_V - VmemInf)*EXP(-tauInf);

   //
   // start of LIF2_update_finish
   //

   l_phiExc  = 0.0f;
   l_phiInh  = 0.0f;
   l_phiInhB = 0.0f;

   l_Vth = VthRest + (l_Vth - VthRest)*EXP(-dt/tauVth);

   //
   // start of update_f
   //

   l_G_E  = (l_G_E  > GMAX) ? GMAX : l_G_E;
   l_G_I  = (l_G_I  > GMAX) ? GMAX : l_G_I;
   l_G_IB = (l_G_IB > GMAX) ? GMAX : l_G_IB;

   l_activ = activity[kex];

   l_activ = (l_V > l_Vth) ? 1.0f           : 0.0f;
   l_V     = (l_V > l_Vth) ? Vrest          : l_V;
   l_Vth   = (l_V > l_Vth) ? l_Vth + deltaVth : l_Vth;
   l_G_IB  = (l_V > l_Vth) ? l_G_IB + 1.0f    : l_G_IB;

   //
   // These actions must be done outside of kernel
   //    1. set activity to 0 in boundary (if needed)
   //    2. update active indices
   //

   // store local variables back to global memory
   //
   activity[kex] = l_activ;

   V[k]   = l_V;
   Vth[k] = l_Vth;

   G_E[k]  = l_G_E;
   G_I[k]  = l_G_I;
   G_IB[k] = l_G_IB;

   phiExc[k]  = l_phiExc;
   phiInh[k]  = l_phiInh;
   phiInhB[k] = l_phiInhB;

#ifndef __CL_PLATFORM_H
   } // loop over k
#endif

}


barriers

barriers

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Saytiras/Massively-Parallel-Algorithms.git/'


Initialize write packet buffer

Initialize write packet buffer

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/CLBplustree/CLBplustree.git/'


Create db.ex.cl

Create db.ex.cl

$TTL    300
@                       1D IN SOA       example.cl. hostmaster.example.cl. (
                                        2016100501     ; serial
                                        3H              ; refresh
                                        15M             ; retry
                                        4W              ; expiry
                                        600 )            ; minimum

                        1D IN NS        ns.example.cl.
			IN MX 10	mail.example.cl.

$ORIGIN example.cl.
                IN    	A	      19.19.19.19
ns      600     IN      A       19.19.19.20
www     120     IN      A       19.19.19.21
mail	  120     IN	    A	      19.19.19.22

error: pathspec 'protocol/dns/lab/db.ex.cl' did not match any file(s) known to git


Changed to use cl_random number generator.

git-svn-id: 602a26e73ae9f2a14e2bb95676f2e137fcc39919@3411 7c0444ca-5550-0410-9008-faecdbe78eb5

#include "LIF_params.h"
#include "cl_random.hcl"
#include "../utils/pv_random.h"

#ifndef PV_USE_OPENCL
#  include <math.h>
#  define EXP expf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_LOCAL
#else  /* compiling with OpenCL */
#  define EXP exp
#  define CL_KERNEL       __kernel
#  define CL_MEM_GLOBAL   __global
#  define CL_MEM_LOCAL    __local
#  include "conversions.hcl"
#endif

//
// update the state of a retinal layer (spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void LIF_update_state(
    const float time,
    const float dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_GLOBAL LIF_params * params,
    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * V,
    CL_MEM_GLOBAL float * Vth,
    CL_MEM_GLOBAL float * G_E,
    CL_MEM_GLOBAL float * G_I,
    CL_MEM_GLOBAL float * G_IB,
    CL_MEM_GLOBAL float * phiExc,
    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * phiInhB,
    CL_MEM_GLOBAL float * R,
    CL_MEM_GLOBAL float * activity)
{
   int k;

   const float exp_tauE    = EXP(-dt/params->tauE);
   const float exp_tauI    = EXP(-dt/params->tauI);
   const float exp_tauIB   = EXP(-dt/params->tauIB);
   const float exp_tauVth  = EXP(-dt/params->tauVth);

   const float dt_sec = .001 * dt;   // convert to seconds
   const float exp_tauRate = EXP(-dt/params->tauRate);

#ifndef PV_USE_OPENCL

for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // local param variables
   float tau, Vrest, VthRest, Vexc, Vinh, VinhB, deltaVth;

   const float GMAX = 10.0;

   // local variables
   float l_activ;

   uint4 l_rnd = rnd[k];

   float l_V   = V[k];
   float l_Vth = Vth[k];

   float l_G_E  = G_E[k];
   float l_G_I  = G_I[k];
   float l_G_IB = G_IB[k];

   float l_phiExc  = phiExc[k];
   float l_phiInh  = phiInh[k];
   float l_phiInhB = phiInhB[k];

   float l_R = R[k];

   // temporary arrays
   float tauInf, VmemInf;

   //
   // start of LIF2_update_exact_linear
   //

   // define local param variables
   //
   tau   = params->tau;
   Vexc  = params->Vexc;
   Vinh  = params->Vinh;
   VinhB = params->VinhB;
   Vrest = params->Vrest;

   VthRest  = params->VthRest;
   deltaVth = params->deltaVth;

   // add noise
   //

#define CLRANDOM

#ifdef CLRANDOM
   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqE) {
      l_rnd = cl_random_get(l_rnd);
      l_phiExc = l_phiExc + params->noiseAmpE*cl_random_prob(l_rnd);
   }

   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqI) {
      l_rnd = cl_random_get(l_rnd);
      l_phiInh = l_phiInh + params->noiseAmpI*cl_random_prob(l_rnd);
   }

   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqIB) {
      l_rnd = cl_random_get(l_rnd);
      l_phiInhB = l_phiInhB + params->noiseAmpIB*cl_random_prob(l_rnd);
   }
#else
   if (pv_random_prob() < dt_sec*params->noiseFreqE) {
      l_phiExc = l_phiExc + params->noiseAmpE*pv_random_prob();
   }

   if (pv_random_prob() < dt_sec*params->noiseFreqI) {
      l_phiInh = l_phiInh + params->noiseAmpI*pv_random_prob();
   }

   if (pv_random_prob() < dt_sec*params->noiseFreqIB) {
      l_phiInhB = l_phiInhB + params->noiseAmpIB*pv_random_prob();
   }
#endif

   l_G_E  = l_phiExc  + l_G_E *exp_tauE;
   l_G_I  = l_phiInh  + l_G_I *exp_tauI;
   l_G_IB = l_phiInhB + l_G_IB*exp_tauIB;

   l_G_E  = (l_G_E  > GMAX) ? GMAX : l_G_E;
   l_G_I  = (l_G_I  > GMAX) ? GMAX : l_G_I;
   l_G_IB = (l_G_IB > GMAX) ? GMAX : l_G_IB;

   tauInf  = (dt/tau) * (1.0 + l_G_E + l_G_I + l_G_IB);
   VmemInf = (Vrest + l_G_E*Vexc + l_G_I*Vinh + l_G_IB*VinhB)
           / (1.0 + l_G_E + l_G_I + l_G_IB);

   l_V = VmemInf + (l_V - VmemInf)*EXP(-tauInf);;

   //
   // start of LIF2_update_finish
   //

   l_Vth = VthRest + (l_Vth - VthRest)*exp_tauVth;

   //
   // start of update_f
   //

   bool fired_flag = (l_V > l_Vth);

   l_activ = fired_flag ? 1.0f             : 0.0f;
   l_V     = fired_flag ? Vrest            : l_V;
   l_Vth   = fired_flag ? l_Vth + deltaVth : l_Vth;
   l_G_IB  = fired_flag ? l_G_IB + 1.0f    : l_G_IB;

   // update average rate
   l_R = l_activ + l_R*exp_tauRate;

   //
   // These actions must be done outside of kernel
   //    1. set activity to 0 in boundary (if needed)
   //    2. update active indices
   //

   // store local variables back to global memory
   //
   activity[kex] = l_activ;

   R[k] = l_R;

   V[k]   = l_V;
   Vth[k] = l_Vth;

   G_E[k]  = l_G_E;
   G_I[k]  = l_G_I;
   G_IB[k] = l_G_IB;

   phiExc[k]  = 0.0f;
   phiInh[k]  = 0.0f;
   phiInhB[k] = 0.0f;

#ifndef PV_USE_OPENCL
   } // loop over k
#endif

}

#include "LIF_params.h"
#include "cl_random.hcl"
#include "../utils/pv_random.h"

#ifndef PV_USE_OPENCL
#  include <math.h>
#  define EXP expf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_LOCAL
#else  /* compiling with OpenCL */
#  define EXP exp
#  define CL_KERNEL       __kernel
#  define CL_MEM_GLOBAL   __global
#  define CL_MEM_LOCAL    __local
#  include "conversions.hcl"
#endif

//
// update the state of a retinal layer (spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void LIF_update_state(
    const float time,
    const float dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_GLOBAL LIF_params * params,
    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * V,
    CL_MEM_GLOBAL float * Vth,
    CL_MEM_GLOBAL float * G_E,
    CL_MEM_GLOBAL float * G_I,
    CL_MEM_GLOBAL float * G_IB,
    CL_MEM_GLOBAL float * phiExc,
    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * phiInhB,
    CL_MEM_GLOBAL float * R,
    CL_MEM_GLOBAL float * activity)
{
   int k;

   const float exp_tauE    = EXP(-dt/params->tauE);
   const float exp_tauI    = EXP(-dt/params->tauI);
   const float exp_tauIB   = EXP(-dt/params->tauIB);
   const float exp_tauVth  = EXP(-dt/params->tauVth);

   const float dt_sec = .001 * dt;   // convert to seconds
   const float exp_tauRate = EXP(-dt/params->tauRate);

#ifndef PV_USE_OPENCL

for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // local param variables
   float tau, Vrest, VthRest, Vexc, Vinh, VinhB, deltaVth;

   const float GMAX = 10.0;

   // local variables
   float l_activ;

   uint4 l_rnd = rnd[k];

   float l_V   = V[k];
   float l_Vth = Vth[k];

   float l_G_E  = G_E[k];
   float l_G_I  = G_I[k];
   float l_G_IB = G_IB[k];

   float l_phiExc  = phiExc[k];
   float l_phiInh  = phiInh[k];
   float l_phiInhB = phiInhB[k];

   float l_R = R[k];

   // temporary arrays
   float tauInf, VmemInf;

   //
   // start of LIF2_update_exact_linear
   //

   // define local param variables
   //
   tau   = params->tau;
   Vexc  = params->Vexc;
   Vinh  = params->Vinh;
   VinhB = params->VinhB;
   Vrest = params->Vrest;

   VthRest  = params->VthRest;
   deltaVth = params->deltaVth;

   // add noise
   //

#undef CLRANDOM

#ifdef CLRANDOM
   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqE) {
      l_rnd = cl_random_get(l_rnd);
      l_phiExc = l_phiExc + params->noiseAmpE*cl_random_prob(l_rnd);
   }

   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqI) {
      l_rnd = cl_random_get(l_rnd);
      l_phiInh = l_phiInh + params->noiseAmpI*cl_random_prob(l_rnd);
   }

   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqIB) {
      l_rnd = cl_random_get(l_rnd);
      l_phiInhB = l_phiInhB + params->noiseAmpIB*cl_random_prob(l_rnd);
   }
#else
   if (pv_random_prob() < dt_sec*params->noiseFreqE) {
      l_phiExc = l_phiExc + params->noiseAmpE*pv_random_prob();
   }

   if (pv_random_prob() < dt_sec*params->noiseFreqI) {
      l_phiInh = l_phiInh + params->noiseAmpI*pv_random_prob();
   }

   if (pv_random_prob() < dt_sec*params->noiseFreqIB) {
      l_phiInhB = l_phiInhB + params->noiseAmpIB*pv_random_prob();
   }
#endif

   l_G_E  = l_phiExc  + l_G_E *exp_tauE;
   l_G_I  = l_phiInh  + l_G_I *exp_tauI;
   l_G_IB = l_phiInhB + l_G_IB*exp_tauIB;

   l_G_E  = (l_G_E  > GMAX) ? GMAX : l_G_E;
   l_G_I  = (l_G_I  > GMAX) ? GMAX : l_G_I;
   l_G_IB = (l_G_IB > GMAX) ? GMAX : l_G_IB;

   tauInf  = (dt/tau) * (1.0 + l_G_E + l_G_I + l_G_IB);
   VmemInf = (Vrest + l_G_E*Vexc + l_G_I*Vinh + l_G_IB*VinhB)
           / (1.0 + l_G_E + l_G_I + l_G_IB);

   l_V = VmemInf + (l_V - VmemInf)*EXP(-tauInf);;

   //
   // start of LIF2_update_finish
   //

   l_Vth = VthRest + (l_Vth - VthRest)*exp_tauVth;

   //
   // start of update_f
   //

//   l_G_E  = (l_G_E  > GMAX) ? GMAX : l_G_E;
//   l_G_I  = (l_G_I  > GMAX) ? GMAX : l_G_I;
//   l_G_IB = (l_G_IB > GMAX) ? GMAX : l_G_IB;

   bool fired_flag = (l_V > l_Vth);

   l_activ = fired_flag ? 1.0f             : 0.0f;
   l_V     = fired_flag ? Vrest            : l_V;
   l_Vth   = fired_flag ? l_Vth + deltaVth : l_Vth;
   l_G_IB  = fired_flag ? l_G_IB + 1.0f    : l_G_IB;

   // update average rate
   l_R = l_activ + l_R*exp_tauRate;

   //
   // These actions must be done outside of kernel
   //    1. set activity to 0 in boundary (if needed)
   //    2. update active indices
   //

   // store local variables back to global memory
   //
   activity[kex] = l_activ;

   R[k] = l_R;

   V[k]   = l_V;
   Vth[k] = l_Vth;

   G_E[k]  = l_G_E;
   G_I[k]  = l_G_I;
   G_IB[k] = l_G_IB;

   phiExc[k]  = 0.0f;
   phiInh[k]  = 0.0f;
   phiInhB[k] = 0.0f;

#ifndef PV_USE_OPENCL
   } // loop over k
#endif

}


Corrected and improved comment

Corrected and improved comment

git-svn-id: 602a26e73ae9f2a14e2bb95676f2e137fcc39919@5056 7c0444ca-5550-0410-9008-faecdbe78eb5

#include "../layers/updateStateFunctions.h"

#ifndef PV_USE_OPENCL
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_CONST
#  define CL_MEM_LOCAL
#else  /* compiling with OpenCL */
#  define CL_KERNEL       __kernel
#  define CL_MEM_GLOBAL   __global
#  define CL_MEM_CONST    __constant
#  define CL_MEM_LOCAL    __local
//#  include "conversions.hcl"
#endif

//
// update the state of an ANN layer
//
// To allow porting to GPUs, functions called from this function must be
// static inline functions.  If a subclass needs new behavior, it needs to
// have its own static inline function.
//
CL_KERNEL
void ANNLayer_update_state(
    const int numNeurons,
    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_GLOBAL float * V,
    const float Vth,
    const float VMax,
    const float VMin,
    CL_MEM_GLOBAL float * GSynHead,
//    CL_MEM_GLOBAL float * GSynExc,
//    CL_MEM_GLOBAL float * GSynInh,
    CL_MEM_GLOBAL float * activity)
{
   updateV_ANNLayer(numNeurons, V, GSynHead, VMax, VMin, Vth);
   setActivity_HyPerLayer(numNeurons, activity, V, nx, ny, nf, nb);
   resetGSynBuffers_HyPerLayer(numNeurons, 2, GSynHead);
}

#include "../layers/updateStateFunctions.h"

#ifndef PV_USE_OPENCL
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_CONST
#  define CL_MEM_LOCAL
#else  /* compiling with OpenCL */
#  define CL_KERNEL       __kernel
#  define CL_MEM_GLOBAL   __global
#  define CL_MEM_CONST    __constant
#  define CL_MEM_LOCAL    __local
//#  include "conversions.hcl"
#endif

//
// update the state of a retinal layer (spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void ANNLayer_update_state(
    const int numNeurons,
    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_GLOBAL float * V,
    const float Vth,
    const float VMax,
    const float VMin,
    CL_MEM_GLOBAL float * GSynHead,
//    CL_MEM_GLOBAL float * GSynExc,
//    CL_MEM_GLOBAL float * GSynInh,
    CL_MEM_GLOBAL float * activity)
{
//   int k;
//
//#ifndef PV_USE_OPENCL
//for (k = 0; k < nx*ny*nf; k++) {
//#else
//   k = get_global_id(0);
//#endif

   //int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // local variables
//   float l_activ;
//   float l_V   = V[k];
//
//   float l_GSynExc  = GSynExc[k];
//   float l_GSynInh  = GSynInh[k];
//#ifdef PV_USE_OPENCL
//   const int numNeurons=0;
//#endif
   //updateV():
   updateV_ANNLayer(numNeurons, V, GSynHead, VMax, VMin, Vth);
//   l_V=l_GSynExc-l_GSynInh;
//   //applyVMax():
//   if(l_V > VMax) l_V = VMax;
//   //applyVThresh():
//   if(l_V < Vth) l_V = VMin;

   //setActivity():
   setActivity_HyPerLayer(numNeurons, activity, V, nx, ny, nf, nb);
   //l_activ=l_V;

   //activity[kex] = l_activ;
   //V[k]   = l_V;

   //int k;
   resetGSynBuffers_HyPerLayer(numNeurons, 2, GSynHead);
//#ifndef PV_USE_OPENCL
//for (k = 0; k < nx*ny*nf; k++) {
//#else
//   k = get_global_id(0);
//#endif
//   //resetGSynBuffers():
//   CL_MEM_GLOBAL pvdata_t * GSynExc = &GSynHead[CHANNEL_EXC*numNeurons];
//   CL_MEM_GLOBAL pvdata_t * GSynInh = &GSynHead[CHANNEL_INH*numNeurons];
//   GSynExc[k]  = 0.0f;
//   GSynInh[k]  = 0.0f;
//
//#ifndef PV_USE_OPENCL
//   } // loop over k
//#endif

}


SBCL threaded version.

SBCL threaded version.

; PI Common LISP example.

; Abstract getting command line arguments.
; In sbcl the interpreter is an extra argument.

; For SBCL: sbcl --script pi.cl <n>

(defun getargs ()
  (or
   #+SBCL (cdr *posix-argv*)
   nil))

(defun getenvvar (name)
  (or
   #+SBCL (sb-unix::posix-getenv name)
   nil))

(defun calcpi (n fst fnl)
  (/ (loop for i from fst to fnl
	sum (/ 4.d0 (+ 1.d0 (expt (* (- i 0.5d0) (/ 1.d0 n)) 2 ))))
	 n)
)

(defvar n 50000000)
(defvar threads 1)

(if (> (list-length(getargs)) 0)
  (setq n (parse-integer (car (getargs))))
)

; Choose thread count based on OMP_NUM_THREADS.
(if (> (length(getenvvar "OMP_NUM_THREADS")) 0)
  (setq threads (parse-integer (getenvvar "OMP_NUM_THREADS")))
  (format t "DEBUG: OMP_NUM_THREADS not set - defaulting to 1~%")
)

(format t "Calculating PI using:~%")
(format t "  ~a slices~%" n)
(format t "  ~a thread(s)~%" threads)

; get-internal-real-time gets time from some arbitrary, implementation
; dependent starting point in some fraction of a second.
(defvar start (get-internal-real-time))

; This is SBCL specific.
(defvar fst 0)
(defvar fnl n)
(defvar chunk (floor (/ n threads)))
(defvar left (- n (* chunk threads)))
(defvar p 0)
(defvar tl nil)
(loop for j from 0 to (- threads 1) do
   (setq fst (* j chunk))
   (setq fnl (- (* (+ j 1) chunk) 1))
   (if (= j (- threads 1))
      (setq fnl (+ fnl left))
   )
   (format t "DEBUG: Thread ~a from ~a to ~a~%" j fst fnl)
   (setq tl (cons (sb-thread:make-thread (lambda () (calcpi n fst fnl))) tl))
)

(loop for item in tl
   do (setq p (+ p (sb-thread:join-thread item)))
)
; get-internal-real-time is in some platform specific unit which we can find in
; internal-time-units-per-second
(defvar stop (get-internal-real-time))

(defvar runt (/ (- stop start) internal-time-units-per-second))

(format t "Obtained value of PI: ~a~%" p)

; We have to print the time with ~f to force a float output.
(format t "Time taken: ~f seconds~%" runt)

error: pathspec 'clisp_pi_dir/pi-threads.cl' did not match any file(s) known to git


we have merge4k.cl

we have merge4k.cl

# This is a Sep 2015 version on gerard to convert Mont4k AZCam extended fits
# images to normal fits images that all IRAF tasks can deal with
#
# It should work for images taken prior to Sept 2015 (?)
#
# Inputs an individual raw mont4k extended fits (file binned 1x1,
# 2x2, 3x3, or 4x4) # and outputs a merged normal fits image
#
# A previously merged image is left unchanged by this routine
#
# The input images are saved unchanged in a subdirectory named raw
# (The exact image size is read from the headers (so this routine
# works for different numbers of rows and columns -- as long as the
# two sides of the ccd have the same number of columns!)
# !!  Does not yet work on any images with detector rows not from 1 to 4096
# development!)
#
# The only processing that has been done on the output image is the
# correction for electronic cross-talk, the overscan subtraction and
# trimming of each side required to merge the two halves into one image

procedure merge4k (rawimg)

string rawimg      {prompt="raw multi-extension mont4k image(s)"}
struct  *imagelist

begin
     string rimgstr,rimg,pkg,rimg0,rimg1,rimg2,img1,img2,imagel
     string hdr,typ,bin,ysec0,ysec,biassec,datasec,datasec2,datasec3
     string xt1,xt2,ccdsec,ccdsec1,strval
     real xtcoef,ovsc1,ovsc2
     int i,j,n1,n2,nlast,x1,x2,ibin,intval

     cache imgets

# 2005 original cross-talk coefficient
#    xtcoef = 0.00264
# Aug 2008 cross-talk coefficient, after pre-amps installed
#     xtcoef = 0.00026
# Sep 2014 cross-talk coefficient
     xtcoef = 0.00080

# check to make sure fitsutil package is loaded; needed to
#  split extended fits file with fxsplit
     if (access("pkg")) del ("pkg")
     lpar ("fxextract", >& "pkg")
     head ("pkg", nlines=1) | scan (pkg)
     if (substr(pkg,1,5) == "ERROR")  \
       error(1,"Load fitsutil package in order to run merge4k")
     del ("pkg")

# check to make sure ctio package is loaded; needed to create
#  new normal fits file with original headers using imcreate
     lpar ("imcreate", >& "pkg")
     head ("pkg", nlines=1) | scan (pkg)
     if (substr(pkg,1,5) == "ERROR")  \
       error(1,"Load ctio package in order to run merge4k")
     del ("pkg")

# create the raw directory if it doesn't exist
     if (!access("raw")) mkdir ("raw")

     nhedit.update = yes
     nhedit.add = yes
     nhedit.addonly = no
     nhedit.rename = no
     nhedit.verify = no
     nhedit.show = no

     colbias.median = yes
     colbias.interactive = no

     rimgstr = rawimg
     if (substr(rimgstr,1,1) != "@") {
       i = strlen(rimgstr)
       if (substr(rimgstr,i-3,i) != "fits") rimgstr = rimgstr//".fits"
     }
     imagel = mktemp ("img")
     files (rimgstr, > imagel)

# read and process each image in the list
     imagelist = imagel
     while (fscan (imagelist,rimg) != EOF) {

# only try to convert an image if it exists, hasn't already been converted
# (ie image type is not real), and the data type is ushort (ie it probably
# came direct from AZCam)
     if (access (rimg)) {
       hdr=""
       imhead ((rimg//"[0]")) | scan (hdr)
       i = strlen(hdr)
       typ = substr(hdr,i-5,i-2)
       if(typ != "real") {
         imhead ((rimg//"[1]")) | scan (hdr)
         i = strlen(hdr)
         typ = substr(hdr,i-7,i-2)
       }
       if(typ == "ushort") {
         i = strlen(rimg)
         rimg0 = substr(rimg,1,i-5)//"0"//".fits"
         rimg1 = substr(rimg,1,i-5)//"1"//".fits"
         rimg2 = substr(rimg,1,i-5)//"2"//".fits"

# delete any images with this same name in the raw directory
         if (access ("raw/"//rimg)) del (("raw/"//rimg), verify=no)
# delete any previously existing image parts & temp files in the current directory
         if (access (rimg0)) del (rimg0,verify=no)
         if (access (rimg1)) del (rimg1,verify=no)
         if (access (rimg2)) del (rimg2,verify=no)
         if (access ("stupid")) del ("stupid", verify=no)

# split the extended fits input image into its parts
         fxsplit (rimg, verb=no)

# do the crosstalk correction for each half
         xt1 = mktemp ("xt1")
         xt2 = mktemp ("xt2")
         imar ((rimg//"[1]"), "*", xtcoef, xt2)
         imar ((rimg//"[2]"), "*", xtcoef, xt1)
         imar (rimg1, "-", xt1, rimg1)
         imar (rimg2, "-", xt2, rimg2)
         imdel (xt1,verify=no)
         imdel (xt2,verify=no)

# get binning and image dimension info
         imgets ((rimg//"[0]"), "ccdsum")
         bin = imgets.value
         ibin = int(substr(bin,1,1))

         imgets ((rimg//"[1]"), "ccdsec")
         ccdsec = imgets.value
         j = stridx(",",ccdsec)
         ysec0 = substr(ccdsec,j,strlen(ccdsec))

# construct various image section sizes
         imgets ((rimg//"[1]"), "datasec")
         datasec = imgets.value
         i = stridx(":",datasec)
         j = stridx(",",datasec)
         n1 = int(substr(datasec,i+1,j-1))
         ysec = substr(datasec,j,strlen(datasec))

         hselect ((rimg//"[1]"), "naxis[1]", yes) | scan (nlast)
         x1 = n1+6; x2 = nlast
         biassec = "["//str(x1)//":"//str(x2)//ysec
         x1 = 1; x2 = n1
         datasec2 = "["//str(x2)//":"//str(x1)//ysec
         x1 = n1+1; x2 = 2*n1
         if (ibin == 3) {
           x1 = x1+1
           x2 = x2+1
         }
         datasec3 = "["//str(x1)//":"//str(x2)//ysec

# ccdsec no longer useful for working with binned images after 8/28/10 because it
#   doesn't take binning into account; write ccdsec1 keyword in header also
         x1 = 1 ; x2 = 4096
         ccdsec = "["//str(x1)//":"//str(x2)//ysec0
         i = 4096/ibin
         hselect (rimg1, "naxis[2]", yes) | scan (j)
         x1 = 1 ; x2 = i ; if (i == 3) x2 = i+1
         ccdsec1 = "["//str(x1)//":"//str(x2)//ysec

# overscan correct and trim each half
         colbias (rimg1,rimg1, bias=biassec, trim=datasec, func="spline3", order=2)
         colbias (rimg2,rimg2, bias=biassec, trim=datasec, func="spline3", order=2)

         imstat ((rimg//"[1]"//biassec),field="midpt",format=no) | scan (ovsc1)
         imstat ((rimg//"[2]"//biassec),field="midpt",format=no) | scan (ovsc2)

# save the original extended fits image in the raw subdirectory
         rename (rimg, ("raw/"//rimg))

# create new image with header of original [0]
         imcreate (rimg, naxis=2, naxis1=i, naxis2=j, header="copy", pixtype="real", \
            reference=rimg0)

# copy the crosstalk-corrected, overscan-corrected, trimmed images into a combined image
# the following lines are required to make iraf realize what size rimg1 is
         print (("imstat "//rimg1), > "stupid")
         cl < "stupid", >& "dev$null"
         del ("stupid")

         imcopy ((rimg1//datasec), (rimg//datasec), verbose=no)
         img1 = rimg2//datasec2 ; img2 = rimg//datasec3
         imcopy ((rimg2//datasec2), (rimg//datasec3), verbose=no)

# delete header keywords that are duplicates or no longer needed
         hedit (rimg, "detsize", delete=yes, verify=no, show=no, update=yes)
         hedit (rimg, "nextend", delete=yes, verify=no, show=no, update=yes)

# add useful header keywords from [1]/[2] that are not in [0] and/or
#   fix previously existing header keywords in combined image
         nhedit (rimg, "extend", "F", "")
         imgets (rimg1, "bunit")
         strval = imgets.value
         nhedit (rimg, "bunit", strval, "Physical unit of array values")
         imgets (rimg1, "ccdname")
         strval = imgets.value
         nhedit (rimg, "ccdname", strval, "CCD name")
         imgets (rimg1, "detsize")
         strval = imgets.value
         nhedit (rimg, "detsize", strval, "Detector size")
         imgets (rimg1, "ccdsize")
         strval = imgets.value
         nhedit (rimg, "ccdsize", strval, "CCD size")
         imgets (rimg1, "ampsec")
         strval = imgets.value
         nhedit (rimg, "ampsec", strval, "Amplifier section")
         imgets (rimg1, "detsec")
         strval = imgets.value
         nhedit (rimg, "detsec", strval, "Detector section")
         imgets (rimg1, "biassec")
         strval = imgets.value
         nhedit (rimg, "biassec", strval, "Bias section")
         imgets (rimg1, "trimsec")
         strval = imgets.value
         nhedit (rimg, "trimsec", strval, "Trim section")
# datasec keyword from rimg1 or rimg2 is only half of the image; use ccdsec1
#   value in datasec so that ds9 command will display the whole binned image
#         imgets (rimg1, "datasec")
#         strval = imgets.value
         nhedit (rimg, "datasec", ccdsec1, "Data section")
         nhedit (rimg, "ccdsec", ccdsec, "CCD section")
         nhedit (rimg, "ccdsec1", ccdsec1, "CCD section with binning")
         imgets (rimg1, "ovrscan1")
         intval = int(imgets.value)
         nhedit (rimg, "ovrscan1", intval, "Overscan on axis 1")
         imgets (rimg1, "ovrscan2")
         intval = int(imgets.value)
         nhedit (rimg, "ovrscan2", intval, "Overscan on axis 2")
         imgets (rimg1, "prescan1")
         intval = int(imgets.value)
         nhedit (rimg, "prescan1", intval, "Underscan on axis 1")
         imgets (rimg1, "prescan2")
         intval = int(imgets.value)
         nhedit (rimg, "prescan2", intval, "Underscan on axis 2")
         imgets (rimg1, "equinox")
         intval = int(imgets.value)
         nhedit (rimg, "equinox", intval, "Equinox of WCS")
         imgets (rimg1, "wcsdim")
         intval = int(imgets.value)
         nhedit (rimg, "wcsdim", intval, "WCS Dimensionality")
         imgets (rimg1, "ctype1")
         strval = imgets.value
         nhedit (rimg, "ctype1", strval, "Coordinate type")
         imgets (rimg1, "ctype2")
         strval = imgets.value
         nhedit (rimg, "ctype2", strval, "Coordinate type")

         nhedit (rimg, "xtkcoef", xtcoef, "Crosstalk coefficient")
         nhedit (rimg, "overscan", biassec, "Overscan region used")
         nhedit (rimg, "ovscmed1", ovsc1, "Overscan median counts, side 1")
         nhedit (rimg, "ovscmed2", ovsc2, "Overscan median counts, side 2")

# delete the intermediate split images
         imdel ((rimg0),verify=no)
         imdel ((rimg1),verify=no)
         imdel ((rimg2),verify=no)
       }
      } else {
       print ((rimg//" doesn't exist in this directory"))
     }
     }

     delete (imagel, verify=no)
     flpr
     flpr
     print (".")

end
# really the end

error: pathspec 'merge4k.cl' did not match any file(s) known to git