/* Precomputes the influence function 2.0/L^2 * exp(-(PI*n/(alpha*L))^2)/n^2 as a function of lattice vector n (NOT k=2*PI*n/L). This is stored in the array Ghat[Maxkmax+1][Maxkmax+1][Maxkmax+1] For symmetry reasons only one octant is actually needed. */ void Ewald_compute_influence_function(system_t *s, parameters_t *p, data_t *d) { int nx,ny,nz; FLOAT_TYPE n_sqr,fak1,fak2; const int kmax = p->mesh - 1; const int kmax2 = kmax*kmax; fak1 = 2.0/SQR(s->length); fak2 = SQR(PI/(p->alpha*s->length)); #ifdef _OPENMP #pragma omp parallel for collapse(2) private(n_sqr) #endif for (nx=0; nx <= kmax; nx++) for (ny=0; ny <= kmax; ny++) for (nz=0; nz <= kmax; nz++) { n_sqr = SQR(nx) + SQR(ny) + SQR(nz); if ((nx==0 && ny==0 && nz==0) || (n_sqr > kmax2)) { // printf("%d %d %d, kmax %d, kmax2 %d\n", nx, ny, nz, kmax, kmax2); d->G_hat[r_ind(nx,ny,nz)] = 0.0; } else { d->G_hat[r_ind(nx,ny,nz)] = fak1/n_sqr * EXP(-fak2*n_sqr); } } }
//--------------------------------------------------------------------- std::vector<int> getRInd(int const nBF, int const nD) { std::vector<int> r_ind(nBF); for(int i=0; i<nBF;i++) r_ind[i]=nD*(2+nBF)+i*2; return r_ind; }
void Ewald_k_space(system_t *s, parameters_t *p, data_t *d, forces_t *f) { int i; int nx, ny, nz; FLOAT_TYPE kr, energy=0.0; FLOAT_TYPE rhohat_re=0, rhohat_im=0, ghat=0; FLOAT_TYPE force_factor; FLOAT_TYPE Leni = 1.0/s->length; const int kmax = p->mesh; const int kmax2 = kmax*kmax; for (nx=-kmax; nx<=kmax; nx++) for (ny=-kmax; ny<=kmax; ny++) for (nz=-kmax; nz<=kmax; nz++) if (nx*nx + ny*ny + nz*nz <= kmax2) { /* compute rhohat */ rhohat_re = 0.0; rhohat_im = 0.0; ghat = d->G_hat[r_ind(abs(nx), abs(ny), abs(nz))]; #ifdef _OPENMP #pragma omp parallel for private(kr) reduction( + : rhohat_re ) reduction( + : rhohat_im ) #endif for (i=0; i<s->nparticles; i++) { kr = 2.0*PI*Leni*(nx*(s->p->x[i]) + ny*(s->p->y[i]) + nz*(s->p->z[i])); rhohat_re += s->q[i] * COS(kr); rhohat_im += s->q[i] * -SIN(kr); } #ifdef _OPENMP #pragma omp barrier #pragma omp parallel for private(kr, force_factor) #endif for (i=0; i<s->nparticles; i++) { kr = 2.0*PI*Leni*(nx*(s->p->x[i]) + ny*(s->p->y[i]) + nz*(s->p->z[i])); force_factor = s->q[i] * ghat * (rhohat_re*SIN(kr) + rhohat_im*COS(kr)); f->f_k->x[i] += nx * force_factor; f->f_k->y[i] += ny * force_factor; f->f_k->z[i] += nz * force_factor; } } #ifdef _OPENMP #pragma omp barrier #endif /* compute energy */ energy += ghat*(SQR(rhohat_re) + SQR(rhohat_im)); s->energy +=(0.5*s->length /(2.0*PI)) * energy; s->energy += Ewald_self_energy(s, p); }
void P3M_ad( system_t *s, parameters_t *p, data_t *d, forces_t *f ) { /* Loop counters */ int i, j, k, c_index; /* Helper variables */ FLOAT_TYPE T1; FLOAT_TYPE Leni = 1.0/s->length; int Mesh = p->mesh; memset(d->Qmesh, 0, 2*Mesh*Mesh*Mesh * sizeof(FLOAT_TYPE)); TIMING_START_C /* chargeassignment */ assign_charge_and_derivatives( s, p, d, 0); TIMING_STOP_C TIMING_START_G /* Forward Fast Fourier Transform */ forward_fft(d); for (i=0; i<Mesh; i++) for (j=0; j<Mesh; j++) for (k=0; k<Mesh; k++) { c_index = c_ind(i,j,k); T1 = d->G_hat[r_ind(i,j,k)]; d->Qmesh[c_index] *= T1; d->Qmesh[c_index+1] *= T1; } /* Backward FFT */ backward_fft(d); TIMING_STOP_G TIMING_START_F /* Force assignment */ assign_forces_ad( Mesh * Leni * Leni * Leni , s, p, d, f, 0 ); #ifdef P3M_AD_SELF_FORCES Substract_self_forces(s,p,d,f); #endif TIMING_STOP_F return; }
void Influence_function_berechnen_ad( system_t *s, parameters_t *p, data_t *d ) { int NX,NY,NZ; FLOAT_TYPE Zaehler=0.0,Nenner1=0.0, Nenner2=0.0; int ind = 0; int Mesh = p->mesh; if(p->alpha == 0.0) { memset(d->G_hat, 0, Mesh*Mesh*Mesh*sizeof(FLOAT_TYPE)); return; } /* bei Zahlen >= Mesh/2 wird noch Mesh abgezogen! */ #ifdef _OPENMP #pragma omp parallel for private(ind, Zaehler, Nenner1, Nenner2) collapse(3) #endif for (NX=0; NX<Mesh; NX++) { for (NY=0; NY<Mesh; NY++) { for (NZ=0; NZ<Mesh; NZ++) { ind = r_ind(NX,NY,NZ); if ((NX==0) && (NY==0) && (NZ==0)) d->G_hat[ind]=0.0; /* else if ((NX%(Mesh/2) == 0) && (NY%(Mesh/2) == 0) && (NZ%(Mesh/2) == 0)) */ /* d->G_hat[ind]=0.0; */ else { Aliasing_sums_ad(NX,NY,NZ,s,p,d,&Zaehler,&Nenner1, &Nenner2); d->G_hat[ind] = Zaehler / ( PI * Nenner1 * Nenner2 ); } assert(!isnan(d->G_hat[ind])); } } } #ifdef _OPENMP #pragma omp barrier #endif #ifdef P3M_AD_SELF_FORCES Init_self_forces( s, p, d); #else #warning Self force compensation disabled #endif }
void Influence_ik_i( system_t *s, parameters_t *p, data_t *d ) { int NX,NY,NZ; FLOAT_TYPE Dnx,Dny,Dnz; FLOAT_TYPE Zaehler[3]={0.0,0.0,0.0},Nenner1=0.0, Nenner2=0.0; FLOAT_TYPE zwi; int ind = 0; int Mesh = p->mesh; FLOAT_TYPE Leni = 1.0/s->length; for (NX=0; NX<Mesh; NX++) { for (NY=0; NY<Mesh; NY++) { for (NZ=0; NZ<Mesh; NZ++) { ind = r_ind( NX, NY, NZ ); if ((NX==0) && (NY==0) && (NZ==0)) d->G_hat[ind]=0.0; else if ((NX%(Mesh/2) == 0) && (NY%(Mesh/2) == 0) && (NZ%(Mesh/2) == 0)) d->G_hat[ind]=0.0; else { Aliasing_sums_ik_i( s, p, d, NX, NY, NZ, Zaehler, &Nenner1, &Nenner2); Dnx = d->Dn[NX]; Dny = d->Dn[NY]; Dnz = d->Dn[NZ]; zwi = Dnx*Zaehler[0]*Leni + Dny*Zaehler[1]*Leni + Dnz*Zaehler[2]*Leni; zwi /= ( SQR(Dnx*Leni) + SQR(Dny*Leni) + SQR(Dnz*Leni) ); zwi /= 0.5*(SQR(Nenner1) + SQR(Nenner2)); d->G_hat[ind] = 2.0 * zwi / PI; } } } } }
bool valid_entry() const { return r_ind() >= 0; }
void P3M_ik_i( system_t *s, parameters_t *p, data_t *d, forces_t *f ) { /* Zaehlvariablen: */ int i, j, k, l; /* Schnelles Modulo: */ FLOAT_TYPE T1; FLOAT_TYPE Mesh = p->mesh; FLOAT_TYPE Leni = 1.0/s->length; FLOAT_TYPE dop; int c_index; /* Initialisieren von Qmesh */ memset ( d->Qmesh, 0, 2*Mesh*Mesh*Mesh*sizeof ( FLOAT_TYPE ) ); TIMING_START_C /* chargeassignment */ assign_charge( s, p, d, 0 ); assign_charge( s, p, d, 1 ); TIMING_STOP_C /* assign_charge_interlacing( s, p, d ); */ TIMING_START_G /* Durchfuehren der Fourier-Hin-Transformationen: */ forward_fft(d); for (i=0; i<Mesh; i++) for (j=0; j<Mesh; j++) for (k=0; k<Mesh; k++) { c_index = c_ind(i,j,k); T1 = d->G_hat[r_ind(i,j,k)]; d->Qmesh[c_index] *= T1; d->Qmesh[c_index+1] *= T1; for (l=0;l<3;l++) { switch ( l ) { case 0: dop = d->Dn[i]; break; case 1: dop = d->Dn[j]; break; case 2: dop = d->Dn[k]; break; } d->Fmesh->fields[l][c_index] = -2.0*PI*Leni*dop*d->Qmesh[c_index+1]; d->Fmesh->fields[l][c_index+1] = 2.0*PI*Leni*dop*d->Qmesh[c_index]; } } /* Durchfuehren der Fourier-Rueck-Transformation: */ backward_fft(d); TIMING_STOP_G TIMING_START_F /* force assignment */ /* assign_forces ( 1.0 / ( 2.0*s->length*s->length*s->length ), s, p, d, f, 0 ); */ /* assign_forces ( 1.0 / ( 2.0*s->length*s->length*s->length ), s, p, d, f, 1 ); */ assign_forces_interlacing ( 1.0 / ( 2.0*s->length*s->length*s->length ), s, p, d, f ); TIMING_STOP_F return; }