Example #1
0
void electric_field_zero_core( int grid_size , float *elec_grid , float *surface_grid , float internal_value ) {

/************/

  /* Co-ordinates */

  int	x , y , z ;

/************/

  for( x = 0 ; x < grid_size ; x ++ ) {
    for( y = 0 ; y < grid_size ; y ++ ) {
      for( z = 0 ; z < grid_size ; z ++ ) {

        if( surface_grid[gaddress(x,y,z,grid_size)] == (float)internal_value ) elec_grid[gaddress(x,y,z,grid_size)] = (float)0 ;

      }
    }
  }

/************/

  return ;

}
Example #2
0
void electric_field_init(struct Structure This_Structure, struct atom_values **atoms_out, int *natoms_in_out, fftw_real * grid, int grid_size)
{
	// Bien, vamos a arrejuntar todo lo interesante...
	int natoms = 0, residue, atom, x, y, z;
	
	for (residue = 1; residue <= This_Structure.length; residue++)
		natoms += This_Structure.Residue[residue].size;
	
	int natoms_in = natoms % IN_NFLOATS == 0 ? natoms / IN_NFLOATS : natoms / IN_NFLOATS + 1;
	
	// El array debe estar alineado a IN_NFLOATS * 4 bytes
	struct atom_values *atoms = memalign(IN_NFLOATS * 4, natoms_in * sizeof(struct atom_values));
	
	int i = 0;
	for (residue = 1; residue <= This_Structure.length; residue++)
		for (atom = 1; atom <= This_Structure.Residue[residue].size; atom++) {
			if (This_Structure.Residue[residue].Atom[atom].charge == 0) {
				natoms--;
				continue;
			}
			
			atoms[i/IN_NFLOATS].xs[i%IN_NFLOATS] = This_Structure.Residue[residue].Atom[atom].coord[1];
			atoms[i/IN_NFLOATS].ys[i%IN_NFLOATS] = This_Structure.Residue[residue].Atom[atom].coord[2];
			atoms[i/IN_NFLOATS].zs[i%IN_NFLOATS] = This_Structure.Residue[residue].Atom[atom].coord[3];
			atoms[i/IN_NFLOATS].charges[i%IN_NFLOATS] = This_Structure.Residue[residue].Atom[atom].charge;
			i++;
		}
	
	// Me aseguro de que todos los átomos quedan inicializados en caso de que
	// su número no sea múltiplo de IN_NFLOATS. Los átomos con carga 0 no afectan al
	// cálculo ya que la carga se usa para multiplicar el incremento de phi,
	// así que es seguro computar estos "átomos" de más.
	for (; i % IN_NFLOATS != 0; i++) {
		atoms[i/IN_NFLOATS].xs[i%IN_NFLOATS] = 0;
		atoms[i/IN_NFLOATS].ys[i%IN_NFLOATS] = 0;
		atoms[i/IN_NFLOATS].zs[i%IN_NFLOATS] = 0;
		atoms[i/IN_NFLOATS].charges[i%IN_NFLOATS] = 0;
	}
	
	*natoms_in_out = natoms % IN_NFLOATS == 0 ? natoms / IN_NFLOATS : natoms / IN_NFLOATS + 1;
	*atoms_out = atoms;
	
	/************/

	for (x = 0; x < grid_size; x++) {
		for (y = 0; y < grid_size; y++) {
			for (z = 0; z < grid_size; z++) {

				grid[gaddress(x, y, z, grid_size)] = (fftw_real) 0;

			}
		}
	}

	/************/

	setvbuf(stdout, (char *)NULL, _IONBF, 0);
}
Example #3
0
void discretise_structure( struct Structure This_Structure , float grid_span , int grid_size , float *grid ) {

/************/

  /* Counters */

  int	residue , atom ;

  /* Co-ordinates */

  int	x , y , z ;
  int	steps , x_step , y_step , z_step ;

  float		x_centre , y_centre , z_centre ;

  /* Variables */

  float         distance , one_span ;

/************/

  one_span = grid_span / (float)grid_size ;

  distance = 1.8 ;

/************/

  for( x = 0 ; x < grid_size ; x ++ ) {
    for( y = 0 ; y < grid_size ; y ++ ) {
      for( z = 0 ; z < grid_size ; z ++ ) {

        grid[gaddress(x,y,z,grid_size)] = (float)0 ;

      }
    }
  }

/************/

  steps = (int)( ( distance / one_span ) + 1.5 ) ;

  for( residue = 1 ; residue <= This_Structure.length ; residue ++ ) {
    for( atom = 1 ; atom <= This_Structure.Residue[residue].size ; atom ++ ) {

      x = gord( This_Structure.Residue[residue].Atom[atom].coord[1] , grid_span , grid_size ) ;
      y = gord( This_Structure.Residue[residue].Atom[atom].coord[2] , grid_span , grid_size ) ;
      z = gord( This_Structure.Residue[residue].Atom[atom].coord[3] , grid_span , grid_size ) ;

      for( x_step = max( ( x - steps ) , 0 ) ; x_step <= min( ( x + steps ) , ( grid_size - 1 ) ) ; x_step ++ ) {

        x_centre  = gcentre( x_step , grid_span , grid_size ) ;

        for( y_step = max( ( y - steps ) , 0 ) ; y_step <= min( ( y + steps ) , ( grid_size - 1 ) ) ; y_step ++ ) {

          y_centre  = gcentre( y_step , grid_span , grid_size ) ;

          for( z_step = max( ( z - steps ) , 0 ) ; z_step <= min( ( z + steps ) , ( grid_size - 1 ) ) ; z_step ++ ) {

            z_centre  = gcentre( z_step , grid_span , grid_size ) ;

            if( pythagoras( This_Structure.Residue[residue].Atom[atom].coord[1] , This_Structure.Residue[residue].Atom[atom].coord[2] , This_Structure.Residue[residue].Atom[atom].coord[3] , x_centre , y_centre , z_centre ) < distance ) grid[gaddress(x_step,y_step,z_step,grid_size)] = (float)1 ;

          }
        }
      }

    }
  }

/************/

  return ;

}
Example #4
0
void surface_grid( float grid_span , int grid_size , float *grid , float surface , float internal_value ) {


/************/

  /* Counters */

  int	x , y , z ;
  int	steps , x_step , y_step , z_step ;

  /* Variables */

  float		one_span ;

  int	at_surface ;

/************/

  one_span = grid_span / (float)grid_size ;

/************/

  /* Surface grid atoms */

  steps = (int)( ( surface / one_span ) + 1.5 ) ;

  for( x = 0 ; x < grid_size ; x ++ ) {
    for( y = 0 ; y < grid_size ; y ++ ) {
      for( z = 0 ; z < grid_size ; z ++ ) {

        if( (int)grid[gaddress(x,y,z,grid_size)] == 1 ) {

          at_surface = 0 ;

          for( x_step = max( x - steps , 0 ) ; x_step <= min( x + steps , grid_size - 1 ) ; x_step ++ ) {
            for( y_step = max( y - steps , 0 ) ; y_step <= min( y + steps , grid_size - 1 ) ; y_step ++ ) {
              for( z_step = max( z - steps , 0 ) ; z_step <= min( z + steps , grid_size - 1 ) ; z_step ++ ) {

                if( (int)grid[gaddress(x_step,y_step,z_step,grid_size)] == 0 ) {

                  if( ( (float)( ( ( x_step - x ) * ( x_step - x ) ) + ( ( y_step - y ) * ( y_step - y ) ) + ( ( z_step - z ) * ( z_step - z ) ) ) * one_span * one_span ) < ( surface * surface ) ) at_surface = 1 ;

                }

              }
            }
          }

          if( at_surface == 0 ) grid[gaddress(x,y,z,grid_size)] = (float)internal_value ;

        }

      }
    }
  }

/************/

  return ;

}
Example #5
0
void electric_field(struct Structure This_Structure, float grid_span, int grid_size, float *grid) {
    /************/

    /* Counters */

    int residue, atom;

    /* Co-ordinates */

    int   x, y, z;
    float x_centre, y_centre, z_centre;

    /* Variables */

    float distance;
    float phi, epsilon;

    /************/

    for (x = 0; x < grid_size; x++) {
        for (y = 0; y < grid_size; y++) {
            for (z = 0; z < grid_size; z++) {
                grid[gaddress(x, y, z, grid_size)] = (float)0;
            }
        }
    }

    /************/

    setvbuf(stdout, (char *)NULL, _IONBF, 0);

    printf("  electric field calculations ( one dot / grid sheet ) ");

    for (residue = 1; residue <= This_Structure.length; residue++) {
        printf(".");
        for (atom = 1; atom <= This_Structure.Residue[residue].size; atom++) {
            if (This_Structure.Residue[residue].Atom[atom].charge == 0) continue;
            for (x = 0; x < grid_size; x++) {
                x_centre = gcentre(x, grid_span, grid_size);
                for (y = 0; y < grid_size; y++) {
                    y_centre = gcentre(y, grid_span, grid_size);
                    for (z = 0; z < grid_size; z++) {
                        z_centre = gcentre(z, grid_span, grid_size);

                        // Inlined pythagoras function with a macro to avoid call overhead
                        distance = PYTHAGORAS(This_Structure.Residue[residue].Atom[atom].coord[1],
                                              This_Structure.Residue[residue].Atom[atom].coord[2],
                                              This_Structure.Residue[residue].Atom[atom].coord[3],
                                              x_centre,
                                              y_centre,
                                              z_centre);

                        if (distance < 2.0) distance = 2.0;

                        if (distance >= 2.0) {
                            if (distance >= 8.0) {
                                epsilon = 80;
                            } else {
                                if (distance <= 6.0) {
                                    epsilon = 4;
                                } else {
                                    epsilon = (38 * distance) - 224;
                                }
                            }

                            grid[gaddress(x, y, z, grid_size)] += (This_Structure.Residue[residue].Atom[atom].charge / (epsilon * distance));
                        }
                    }
                }
            }
        }
    }

    printf("\n");

    /************/
}
Example #6
0
void electric_point_charge(struct Structure This_Structure, float grid_span, int grid_size, float *grid) {
    /************/

    /* Counters */

    int residue, atom;

    /* Co-ordinates */

    int x, y, z;
    int x_low, x_high, y_low, y_high, z_low, z_high;

    float a, b, c;
    float x_corner, y_corner, z_corner;
    float w;

    /* Variables */

    float one_span;

    /************/

    for (x = 0; x < grid_size; x++) {
        for (y = 0; y < grid_size; y++) {
            for (z = 0; z < grid_size; z++) {
                grid[gaddress(x, y, z, grid_size)] = (float)0;
            }
        }
    }

    /************/

    one_span = grid_span / (float)grid_size;

    for (residue = 1; residue <= This_Structure.length; residue++) {
        for (atom = 1; atom <= This_Structure.Residue[residue].size; atom++) {
            if (This_Structure.Residue[residue].Atom[atom].charge != 0) {
                x_low = gord(This_Structure.Residue[residue].Atom[atom].coord[1] - (one_span / 2),
                             grid_span,
                             grid_size);
                y_low = gord(This_Structure.Residue[residue].Atom[atom].coord[2] - (one_span / 2),
                             grid_span,
                             grid_size);
                z_low = gord(This_Structure.Residue[residue].Atom[atom].coord[3] - (one_span / 2),
                             grid_span,
                             grid_size);

                x_high = x_low + 1;
                y_high = y_low + 1;
                z_high = z_low + 1;

                a = This_Structure.Residue[residue].Atom[atom].coord[1] -
                    gcentre(x_low, grid_span, grid_size) - (one_span / 2);
                b = This_Structure.Residue[residue].Atom[atom].coord[2] -
                    gcentre(y_low, grid_span, grid_size) - (one_span / 2);
                c = This_Structure.Residue[residue].Atom[atom].coord[3] -
                    gcentre(z_low, grid_span, grid_size) - (one_span / 2);

                for (x = x_low; x <= x_high; x++) {
                    x_corner = one_span * ((float)(x - x_high) + .5);

                    for (y = y_low; y <= y_high; y++) {
                        y_corner = one_span * ((float)(y - y_high) + .5);

                        for (z = z_low; z <= z_high; z++) {
                            z_corner = one_span * ((float)(z - z_high) + .5);

                            w = ((x_corner + a) * (y_corner + b) * (z_corner + c)) /
                                (8.0 * x_corner * y_corner * z_corner);

                            grid[gaddress(x, y, z,
                                          grid_size)] +=
                                (float)(w * This_Structure.Residue[residue].Atom[atom].charge);
                        }
                    }
                }
            }
        }
    }

    /************/
}
Example #7
0
void electric_field(struct Structure This_Structure, float grid_span, int grid_size, fftw_real * grid, int *shared_x, struct atom_values *atoms, int natoms_in)
{

/************/

	/* Counters */

	int residue, atom, i;

	/* Co-ordinates */

	int x, y, z;
	float x_centre, y_centre, z_centre;

	/* Variables */

	float distance;
	float phi, epsilon;

	while (1) {
		
		pthread_mutex_lock(&shared_x_mutex);
		x = *shared_x;
		*shared_x = *shared_x + 1;
		pthread_mutex_unlock(&shared_x_mutex);
		
		if (x >= grid_size)
			break;
		
		printf(".");

		x_centre = gcentre(x, grid_span, grid_size);
		__mtype mx_centre = _set1_ps(x_centre);

		for (y = 0; y < grid_size; y++) {

			y_centre = gcentre(y, grid_span, grid_size);
			__mtype my_centre = _set1_ps(y_centre);

			for (z = 0; z < grid_size; z++) {

				z_centre = gcentre(z, grid_span, grid_size);
				__mtype mz_centre = _set1_ps(z_centre);

				phi = 0;
				__mtype phis = _set1_ps(0.0);
				
				for (i = 0; i < natoms_in; i++) {
				
					__mtype xs = _load_ps(atoms[i].xs);
					__mtype ys = _load_ps(atoms[i].ys);
					__mtype zs = _load_ps(atoms[i].zs);
					__mtype charges = _load_ps(atoms[i].charges);
					__mtype distances;
					
					// Calculo distancias (el original pythagoras)
					__mtype diffxs = _sub_ps(xs, mx_centre);
					__mtype diffys = _sub_ps(ys, my_centre);
					__mtype diffzs = _sub_ps(zs, mz_centre);
					
					diffxs = _mul_ps(diffxs, diffxs);
					diffys = _mul_ps(diffys, diffys);
					diffzs = _mul_ps(diffzs, diffzs);
					
					distances = _add_ps(diffxs, diffys);
					distances = _add_ps(distances, diffzs);
					
					distances = _sqrt_ps(distances);
					
					// A partir de aquí implemento los if's originales usando solo máscaras de bits
					
					// Trunco a 2 como mínimo
					distances = _max_ps(distances, _set1_ps(2.0));
					
					__mtype epsilons = _set1_ps(0.0);
					__mtype tmp;
					__mtype tmp2;
					
					// if >= 8
					tmp = _cmpge_ps(distances, _set1_ps(8.0));
					epsilons = _and_ps(tmp, _set1_ps(80.0));
					
					// else if <= 6
					tmp = _cmple_ps(distances, _set1_ps(6.0));
					tmp = _and_ps(tmp, _set1_ps(4.0));
					epsilons = _or_ps(epsilons, tmp);
					
					// else
					tmp = _cmpgt_ps(distances, _set1_ps(6.0));
					tmp2 = _cmpeq_ps(epsilons, _set1_ps(0.0));
					tmp = _and_ps(tmp, tmp2);
					tmp2 = _mul_ps(distances, _set1_ps(38.0));
					tmp2 = _sub_ps(tmp2, _set1_ps(224.0));
					tmp = _and_ps(tmp, tmp2);
			
					// Valor final
					epsilons = _or_ps(epsilons, tmp);
					
					// Calculo las phis
					tmp = _mul_ps(epsilons, distances);
					tmp = _div_ps(charges, tmp);
					
					// Acumulo las phis
					phis = _add_ps(phis, tmp);
				}
				#ifdef USE_AVX
				
				phis = _mm256_hadd_ps(phis, phis);
				phis = _mm256_hadd_ps(phis, phis);
				
				phi = phis[0] + phis[4];
				
				#else
				
				float tmp, tmp2;
				
				tmp = phis[0] + phis[1];
				tmp2 = phis[2] + phis[3];
				
				phi = tmp + tmp2;
				
				#endif
				grid[gaddress(x, y, z, grid_size)] = (fftw_real) phi;

			}
		}
	}

/************/

	return;

}
Example #8
0
void electric_field( struct Structure This_Structure , float grid_span , int grid_size , fftw_real *grid ) {
  /* Counters */
  int	residue , atom ;
  /* Co-ordinates */
  int	x, y, z, i, k;
	float *coord1, *coord2, *coord3, *charge;
 	/* Blocking stuff */
	int block_size = 512;
	/* Threads stuff */
	int num_threads = 2; 
	ready_threads = 0;
	Thinfo *thinfo;
 	pthread_t threads[num_threads];

  int maxTotalElements = 0;
  int totalElements = 0;

	for (residue = 1; residue <= This_Structure.length; residue++)
		maxTotalElements += This_Structure.Residue[residue].size;

	allocatedata_electric_field(&charge, &coord1, &coord2, &coord3, maxTotalElements);
	
	for (residue = 1; residue <= This_Structure.length; residue++)
		for (atom = 1; atom <= This_Structure.Residue[residue].size; atom++)
			if (This_Structure.Residue[residue].Atom[atom].charge != 0){
				charge[totalElements] = This_Structure.Residue[residue].Atom[atom].charge;
				coord1[totalElements] = This_Structure.Residue[residue].Atom[atom].coord[1]; 
				coord2[totalElements] = This_Structure.Residue[residue].Atom[atom].coord[2]; 
				coord3[totalElements] = This_Structure.Residue[residue].Atom[atom].coord[3]; 
				totalElements++;
			}

  for (x = 0; x < grid_size; x++)
    for (y = 0; y < grid_size; y++)
      for (z = 0; z < grid_size; z++)
        grid[gaddress(x,y,z,grid_size)] = (fftw_real)0;

  setvbuf( stdout , (char *)NULL , _IONBF , 0 ) ;
  printf( "  electric field calculations ( one dot / grid sheet ) " ) ;

	thinfo = (Thinfo *) malloc (sizeof(Thinfo)*num_threads);
	if (thinfo == NULL) {
    printf("No memory.\n");
    exit(-1);
	}
	int elements_per_thread = grid_size/num_threads;
	for (i = 0; i < num_threads; i++) {
		thinfo[i].coord1 = coord1;
		thinfo[i].coord2 = coord2;
		thinfo[i].coord3 = coord3;
		thinfo[i].charge = charge;
		thinfo[i].grid_size = grid_size;
		thinfo[i].grid_span = grid_span;
		thinfo[i].grid = grid;
		thinfo[i].block_size = block_size;
		thinfo[i].totalElements = totalElements;
		thinfo[i].x_start = elements_per_thread*i;
		thinfo[i].x_end = elements_per_thread*i+elements_per_thread;
		thinfo[i].num_threads = num_threads;
	}
	//Ensures repartition of all elements
	thinfo[num_threads-1].x_end = grid_size; 
	
	int rc;
	for (i=0; i < num_threads; i++) {
		rc = pthread_create(&threads[i], NULL, th_electric_field, (void *) &thinfo[i]);
		if (rc) {
			printf("ERROR creating thread\n");
			exit(-1);
		}
	}

	for (i=0; i < num_threads; i++) {
		rc = pthread_join(threads[i], NULL);
		if (rc) {
			printf("ERROR joining thread\n");
			exit(-1);
		}
	}
  printf( "\n" ) ;

	#ifdef grid_out
	 FILE *f = fopen("grid_dolent", "w");
   for (x = 0; x < grid_size; x++)
    for (y = 0; y < grid_size; y++)
      for (z = 0; z < grid_size; z++)
        fprintf(f,"%f\n",grid[gaddress(x,y,z,grid_size)]);
	#endif

  return ;
}
Example #9
0
void *th_electric_field(void *argthinfo) {
	Thinfo *thinfo = (Thinfo *) argthinfo;
	float * charge = thinfo->charge;
	float * coord1 = thinfo->coord1;
	float * coord2 = thinfo->coord2;
	float * coord3 = thinfo->coord3;
	float grid_span = thinfo->grid_span;
	int grid_size = thinfo->grid_size;
	int totalElements = thinfo->totalElements;
	int block_size = thinfo->block_size;
	int x_start = thinfo->x_start;
	int x_end = thinfo->x_end;
	int num_threads = thinfo->num_threads;
	fftw_real *grid = thinfo->grid;

	float phi;
	int block_ini, block_fin;
	float x_centre, y_centre, z_centre;
	int x, y, z, i, k;
	
	__m128 _phi_tmp;
	__m128 _phiSet;
	float *phiSet = (float *) &_phiSet;

	float * distance;
	float * epsilon;

  if ((posix_memalign((void**)&distance, 16, 4*sizeof(float))!=0)) {
    printf("No memory.\n");
    exit(-1);
  }
  if ((posix_memalign((void**)&epsilon, 16, 4*sizeof(float))!=0)) {
    printf("No memory.\n");
    exit(-1);
  }

	for (block_ini = 0; block_ini < totalElements-(block_size-1); block_ini += block_size) { 
		block_fin = block_ini + block_size;
	  for (x = x_start; x < x_end; x++) {
	    x_centre  = gcentre(x ,grid_span, grid_size ) ;
	    for (y = 0; y < grid_size; y++) {
	      y_centre = gcentre(y ,grid_span ,grid_size ) ;
	      for (z = 0; z < grid_size; z++) {
	        z_centre  = gcentre( z , grid_span , grid_size ) ;
	        phi = 0 ;
					computeBlock(block_ini, block_fin);
	    	  grid[gaddress(x,y,z,grid_size)] += (fftw_real)phi;
	      }
	    }
	  }
		//Changing block. Must wait for others threads to finish.
		pthread_mutex_lock(&mut);
		ready_threads++;
		if (ready_threads==num_threads) {
			ready_threads=0;
			pthread_cond_broadcast(&cond);
		} else {
			pthread_cond_wait(&cond, &mut);
		}
		pthread_mutex_unlock(&mut);
	}

	//Last block is not a multiple of block_size
	if (block_ini != totalElements) {
	  for (x = x_start; x < x_end; x++ ) {
	    x_centre = gcentre(x, grid_span, grid_size) ;
	    for (y = 0; y < grid_size; y++) {
	      y_centre = gcentre(y, grid_span, grid_size) ;
	      for (z = 0; z < grid_size; z++) {
	        z_centre = gcentre(z, grid_span, grid_size) ;
	        phi = 0 ;
					computeEndBlock(block_ini, totalElements);
	    	  grid[gaddress(x,y,z,grid_size)] += (fftw_real)phi ;
	      }
	    }
	  }
	}
	pthread_exit(NULL);
	return ;
}