void render_particles(int time) {
  if (demo::playing() && demotracking) {
    const vec3f nom(0, 0, 0);
    newparticle(game::player1->o, nom, 100000000, 8);
  }
  if (particleibo == 0u) initparticles();

  // bucket sort the particles
  u32 partbucket[parttypen], partbucketsize[parttypen];
  loopi(parttypen) partbucketsize[i] = 0;
  for (particle *p, **pp = &parlist; (p = *pp);) {
    pp = &p->next;
    partbucketsize[p->type]++;
  }
  partbucket[0] = 0;
  loopi(parttypen-1) partbucket[i+1] = partbucket[i]+partbucketsize[i];

  // copy the particles to the vertex buffer
  int numrender = 0;
  for (particle *p, **pp = &parlist; (p = *pp);) {
    const u32 index = 4*partbucket[p->type]++;
    const parttype *pt = &parttypes[p->type];
    const float sz = pt->sz*particlesize/100.0f;
    const vec3f poxzy = p->o.xzy();
    glparts[index+0] = glparticle(pt->rgb, 0.f, 1.f, poxzy-(right-up)*sz);
    glparts[index+1] = glparticle(pt->rgb, 1.f, 1.f, poxzy+(right+up)*sz);
    glparts[index+2] = glparticle(pt->rgb, 0.f, 0.f, poxzy-(right+up)*sz);
    glparts[index+3] = glparticle(pt->rgb, 1.f, 0.f, poxzy-(up-right)*sz);
	if (numrender++>maxparticles || (p->fade -= time)<0) {
      *pp = p->next;
      p->next = parempty;
      parempty = p;
    } else {
      if (pt->gr) p->o.z -= ((game::lastmillis()-p->millis)/3.0f)*game::curtime()/(pt->gr*10000);
      vec3f a = p->d;
      a *= float(time);
      a /= 20000.f;
      p->o += a;
      pp = &p->next;
    }
  }

  // render all of them now
  partbucket[0] = 0;
  loopi(parttypen-1) partbucket[i+1] = partbucket[i]+partbucketsize[i];
  OGL(DepthMask, GL_FALSE);
  ogl::enable(GL_BLEND);
  OGL(BlendFunc, GL_SRC_ALPHA, GL_SRC_ALPHA);
  ogl::setattribarray()(ogl::POS0, ogl::COL, ogl::TEX0);
  ogl::bindbuffer(ogl::ARRAY_BUFFER, particlevbo);
  ogl::bindbuffer(ogl::ELEMENT_ARRAY_BUFFER, particleibo);
  OGL(BufferSubData, GL_ARRAY_BUFFER, 0, numrender*sizeof(glparticle[4]), glparts);
  OGL(VertexAttribPointer, ogl::COL, 3, GL_FLOAT, 0, sizeof(glparticle), (const void*)0);
  OGL(VertexAttribPointer, ogl::TEX0, 2, GL_FLOAT, 0, sizeof(glparticle), (const void*)sizeof(float[3]));
  OGL(VertexAttribPointer, ogl::POS0, 3, GL_FLOAT, 0, sizeof(glparticle), (const void*)sizeof(float[5]));
  loopi(parttypen) {
    if (partbucketsize[i] == 0) continue;
    const parttype *pt = &parttypes[i];
    const int n = partbucketsize[i]*6;
    ogl::bindgametexture(GL_TEXTURE_2D, pt->tex);
    const void *offset = (const void *) (partbucket[i] * sizeof(u16[6]));
    ogl::drawelements(GL_TRIANGLES, n, GL_UNSIGNED_SHORT, offset);
  }

  ogl::bindbuffer(ogl::ARRAY_BUFFER, 0);
  ogl::bindbuffer(ogl::ELEMENT_ARRAY_BUFFER, 0);
  ogl::disable(GL_BLEND);
  OGL(DepthMask, GL_TRUE);
}
void SystemEvolution(struct i2dGrid *pgrid, struct Population *pp, int mxiter)
{
    double *forces;
    double vmin, vmax;
	struct particle p1, p2;
	double f[2], ftem0=0.0, ftem1=0.0;
	int i, j, t;
	

     // temporary array of forces 
     forces = malloc(2 * pp->np * sizeof((double)1.0));
     if ( forces == NULL ) {
		 fprintf(stderr,"Error mem alloc of forces!\n");
		 exit(1);
	 }

	 // compute forces acting on each particle step by step
     for ( t=0; t < mxiter; t++ ) {
		 fprintf(stdout,"Step %d of %d\n",t,mxiter);
         for ( i=0; i < 2*pp->np; i++ ) forces[i] = 0.0;
         
         time_t t_comuteForce_0, t_comuteForce_1;
         
         // **** modifications
         time(&t_comuteForce_0);
         
         
		 for ( i=0; i < pp->np; i++ ) 
		 {
            newparticle(&p1,pp->weight[i],pp->x[i],pp->y[i],pp->vx[i],pp->vy[i]);
			#pragma omp parallel for \
            private(j, p2) firstprivate(f)\
            reduction(+:ftem0,ftem1)
			for ( j=0; j < pp->np; j++) 
			{
				if ( j != i ) 
				{
                 newparticle(&p2,pp->weight[j],pp->x[j],pp->y[j],pp->vx[j],pp->vy[j]);
				 ForceCompt(f,p1,p2);
				 ftem0 += f[0];
				 ftem1 += f[1];
				 // forces[index2D(0,i,2)] += f[0];
				 // forces[index2D(1,i,2)] += f[1];
				}
			 }
			 forces[index2D(0,i,2)]=	ftem0;
			 forces[index2D(1,i,2)]=	ftem1;		 
		 }
		 
		 time(&t_comuteForce_1);
		 fprintf(stdout,"time spent on ForceCompt(): %lf\n seconds",difftime(t_comuteForce_1,t_comuteForce_0));
		 // **** modifications, end

		 ParticleScreen(pgrid,*pp, t);
		 DumpPopulation(*pp, t);
		 ParticleStats(*pp,t);
		 
		 time_t t_ComptPopulation_0, t_ComptPopulation_1;
		 time(&t_ComptPopulation_0);
		 
		 ComptPopulation(pp,forces);

		 time(&t_ComptPopulation_1);
		 fprintf(stdout,"time spent on ComptPopulation(): %lf\n seconds",difftime(t_ComptPopulation_1,t_ComptPopulation_0));
	 }
	 free(forces);     
     
}   // end SystemEvolution