void local_rotate_system(double phi, double theta, double alpha) { // Culculate center of mass double com[3] = {0,0,0}; int N=0; // Num of particles int c, np, i; Particle *part; Cell *cell; for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; part = cell->part; np = cell->n; for(i = 0; i < np; i++) { for (int j=0;j<3;j++){ com[j]+=part[i].r.p[j]; } N++; } } for (int j=0;j<3;j++) com[j]/=N; // Rotation axis in carthesian coordinates double axis[3]; axis[0]=sin(theta)*cos(phi); axis[1]=sin(theta)*sin(phi); axis[2]=cos(theta); // Rotate particle coordinates for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; part = cell->part; np = cell->n; for(i = 0; i < np; i++) { // Move the center of mass of the system to the origin for (int j=0;j<3;j++){ part[i].r.p[j]-=com[j]; } // Rotate double res[3]; vec_rotate(axis,alpha,part[i].r.p,res); // Write back result and shift back the center of mass for (int j=0;j<3;j++){ part[i].r.p[j]=com[j]+res[j]; } #ifdef ROTATION rotate_particle(part+i,axis,alpha); #endif } } resort_particles =1; announce_resort_particles(); }
bool steepest_descent_step(void) { Cell *cell; Particle *p; int c, i, j, np; double f_max = -std::numeric_limits<double>::max(); double f; /* Verlet list criterion */ const double skin2 = SQR(0.5*skin); double f_max_global; double dx[3], dx2; const double max_dx2 = SQR(params->max_displacement); for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { f = 0.0; dx2 = 0.0; #ifdef VIRTUAL_SITES if (ifParticleIsVirtual(&p[i])) continue; #endif for(j=0; j < 3; j++){ #ifdef EXTERNAL_FORCES if (!(p[i].p.ext_flag & COORD_FIXED(j))) #endif { f += SQR(p[i].f.f[j]); dx[j] = params->gamma * p[i].f.f[j]; dx2 += SQR(dx[j]); MINIMIZE_ENERGY_TRACE(printf("part %d dim %d dx %e gamma*f %e\n", i, j, dx[j], params->gamma * p[i].f.f[j])); } #ifdef EXTERNAL_FORCES else { dx[j] = 0.0; } #endif } if(dx2 <= max_dx2) { p[i].r.p[0] += dx[0]; p[i].r.p[1] += dx[1]; p[i].r.p[2] += dx[2]; } else { const double c = params->max_displacement/std::sqrt(dx2); p[i].r.p[0] += c*dx[0]; p[i].r.p[1] += c*dx[1]; p[i].r.p[2] += c*dx[2]; } if(distance2(p[i].r.p,p[i].l.p_old) > skin2 ) resort_particles = 1; f_max = std::max(f_max, f); } } MINIMIZE_ENERGY_TRACE(printf("f_max %e resort_particles %d\n", f_max, resort_particles)); announce_resort_particles(); MPI_Allreduce(&f_max, &f_max_global, 1, MPI_DOUBLE, MPI_MAX, comm_cart); return (sqrt(f_max_global) < params->f_max); }
void check_resort_particles() { int i, c, np; Cell *cell; Particle *p; double skin2 = SQR(skin/2.0); for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { /* Verlet criterion check */ if(distance2(p[i].r.p, p[i].l.p_old) > skin2) resort_particles = 1; } } announce_resort_particles(); }
void propagate_pos_sd() { /* Verlet list criterion */ double skin2 = SQR(0.5 * skin); INTEG_TRACE(fprintf(stderr,"%d: propagate_pos:\n",this_node)); Cell *cell; Particle *p; int c, i, np; //get total number of particles int N=sd_get_particle_num(); // gather all the data for mobility calculation real * pos=NULL; pos=(real *)Utils::malloc(DIM*N*sizeof(double)); assert(pos!=NULL); real * force=NULL; force=(real *)Utils::malloc(DIM*N*sizeof(double)); assert(force!=NULL); real * velocity=NULL; velocity=(real *)Utils::malloc(DIM*N*sizeof(real)); assert(velocity!=NULL); #ifdef EXTERNAL_FORCES const int COORD_ALL=COORD_FIXED(0)&COORD_FIXED(1)&COORD_FIXED(2); #endif int j=0; // total particle counter for (c = 0; c < local_cells.n; c++){ cell = local_cells.cell[c]; p = cell->part; np = cell->n; for (i = 0; i < np; i++) { // only count nonVirtual Particles #ifdef EXTERNAL_FORCES if (p[i].p.ext_flag & COORD_ALL) { fprintf (stderr, "Warning: Fixing particle in StokesDynamics this way with EXTERNAL_FORCES is not possible (and will be ignored). Please try to bind them e.g. harmonicaly.\n"); } #endif #ifdef VIRTUAL_SITES if (!ifParticleIsVirtual(&p[i])) #endif { #ifdef SD_USE_FLOAT for (int d=0;d<3;d++){ pos[3*j+d] = p[i].r.p[d]; pos[3*j+d] -=rint(pos[3*j+d]/box_l[d])*box_l[d]; force[3*j+d] = p[i].f.f[d]; } #else memmove(&pos[3*j], p[i].r.p, 3*sizeof(double)); memmove(&force[3*j], p[i].f.f, 3*sizeof(double)); for (int d=0;d<3;d++){ pos[3*j+d] -=rint(pos[3*j+d]/box_l[d])*box_l[d]; } #endif j++; } } } if (!(thermo_switch & THERMO_SD) && thermo_switch & THERMO_BD){ propagate_pos_bd(N,pos,force, velocity); } else { // cuda part #ifdef CUDA //void propagate_pos_sd_cuda(double * box_l_h, int N,double * pos_h, double * force_h, double * velo_h){ #ifdef SD_USE_FLOAT real box_size[3]; for (int d=0;d<3;d++){ box_size[d]=box_l[d]; } #else real * box_size = box_l; #endif if (!(thermo_switch & THERMO_SD)){ temperature*=-1; } propagate_pos_sd_cuda(box_size,N,pos,force, velocity); if (!(thermo_switch & THERMO_SD)){ temperature*=-1; } #else fprintf(stderr, "Warning - CUDA is currently required for SD\n"); fprintf(stderr, "So i am just sitting here and copying stupidly stuff :'(\n"); #endif } #ifdef NEMD /* change momentum of each particle in top and bottom slab */ fprintf (stderr, "Warning: NEMD is in SD not supported.\n"); #endif j=0; for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for (i = 0; i < np; i++) { #ifdef VIRTUAL_SITES if (ifParticleIsVirtual(&p[i])) continue; #endif // write back of position and velocity data #ifdef SD_USE_FLOAT for (int d=0;d<3;d++){ p[i].r.p[d] = pos[3*j+d]+box_l[d]*rint(p[i].r.p[d]/box_l[d]); p[i].m.v[d] = velocity[3*j+d]; //p[i].f.f[d] *= (0.5*time_step*time_step)/(*part).p.mass; } #else for (int d=0;d<3;d++){ p[i].r.p[d] = pos[3*j+d]+box_l[d]*rint(p[i].r.p[d]/box_l[d]); } memmove(p[i].m.v, &velocity[DIM*j], 3*sizeof(double)); #endif // somehow this does not effect anything, although it is called ... for (int d=0;d<3;d++){ p[i].f.f[d] *= (0.5*time_step*time_step)/(*p).p.mass; } for (int d=0;d<DIM;d++){ assert(!isnan(pos[DIM*i+d])); } j++; ONEPART_TRACE(if(p[i].p.identity==check_id) fprintf(stderr,"%d: OPT: PV_1 v_new = (%.3e,%.3e,%.3e)\n",this_node,p[i].m.v[0],p[i].m.v[1],p[i].m.v[2])); ONEPART_TRACE(if(p[i].p.identity==check_id) fprintf(stderr,"%d: OPT: PPOS p = (%.3f,%.3f,%.3f)\n",this_node,p[i].r.p[0],p[i].r.p[1],p[i].r.p[2])); #ifdef ROTATION propagate_omega_quat_particle(&p[i]); #endif /* Verlet criterion check */ if(distance2(p[i].r.p,p[i].l.p_old) > skin2 ) resort_particles = 1; } } free(pos); free(force); free(velocity); announce_resort_particles(); }
bool steepest_descent_step(void) { Cell *cell; Particle *p; int c, i, j, np; // Maximal force encountered on node double f_max = -std::numeric_limits<double>::max(); // and globally double f_max_global; // Square of force,torque on particle double f,t; // Positional increments double dp, dp2, dp2_max = -std::numeric_limits<double>::max(); // Iteration over all local particles for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { f = 0.0; t = 0.0; dp2 = 0.0; #ifdef EXTERNAL_FORCES // Skip, if coordinate is fixed if (!(p[i].p.ext_flag & COORD_FIXED(j))) #endif // For all Cartesian coordinates for(j=0; j < 3; j++){ #ifdef VIRTUAL_SITES // Skip positional increments of virtual particles if (!ifParticleIsVirtual(&p[i])) #endif { // Square of force on particle f += SQR(p[i].f.f[j]); // Positional increment dp = params->gamma * p[i].f.f[j]; if(fabs(dp) > params->max_displacement) // Crop to maximum allowed by user dp = sgn<double>(dp)*params->max_displacement; dp2 += SQR(dp); // Move particle p[i].r.p[j] += dp; MINIMIZE_ENERGY_TRACE(printf("part %d dim %d dp %e gamma*f %e\n", i, j, dp, params->gamma * p[i].f.f[j])); } } #ifdef ROTATION // Rotational increment double dq[3]; // Vector parallel to torque for (int j=0;j<3;j++){ dq[j]=0; // Square of torque t += SQR(p[i].f.torque[j]); // Rotational increment dq[j] = params->gamma * p[i].f.torque[j]; } // Normalize rotation axis and compute amount of rotation double l=normr(dq); if (l>0.0) { for (j=0;j<3;j++) dq[j]/=l; if(fabs(l) > params->max_displacement) // Crop to maximum allowed by user l=sgn(l)*params->max_displacement; // printf("dq: %g %g %g, l=%g\n",dq[0],dq[1],dq[2],l); // Rotate the particle around axis dq by amount l rotate_particle(&(p[i]),dq,l); } #endif // Note maximum force/torque encountered f_max = std::max(f_max, f); f_max = std::max(f_max, t); dp2_max = std::max(dp2_max, dp2); resort_particles = 1; } } MINIMIZE_ENERGY_TRACE(printf("f_max %e resort_particles %d\n", f_max, resort_particles)); announce_resort_particles(); // Synchronize maximum force/torque encountered MPI_Allreduce(&f_max, &f_max_global, 1, MPI_DOUBLE, MPI_MAX, comm_cart); // Return true, if the maximum force/torque encountered is below the user limit. return (sqrt(f_max_global) < params->f_max); }