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 ; }
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"); /************/ }
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; }
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); } } } } } } /************/ }
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 ; }