Exemplo n.º 1
0
void MMM1D_recalcTables()
{
  /* polygamma, determine order */
  int n;
  double err;
  double rhomax2nm2, rhomax2 = uz2*mmm1d_params.far_switch_radius_2;
  /* rhomax2 < 1, so rhomax2m2 falls monotonously */

  n = 1;
  rhomax2nm2 = 1.0;
  do {
    create_mod_psi_up_to(n+1);

    /* |uz*z| <= 0.5 */
    err = 2*n*fabs(mod_psi_even(n, 0.5))*rhomax2nm2;
    rhomax2nm2 *= rhomax2;
    n++;
    // fprintf(stderr, "%f\n", err);
  }
  while (err > 0.1*mmm1d_params.maxPWerror);
}
static void prepare_polygamma_series(double maxPWerror, double maxrad2)
{
  /* polygamma, determine order */
  int n;
  double err;
  double rhomax2nm2, rhomax2 = uz2*maxrad2;
  /* rhomax2 < 1, so rhomax2m2 falls monotonously */

  n = 1;
  rhomax2nm2 = 1.0;
  do {
    create_mod_psi_up_to(n+1);

    /* |uz*z| <= 0.5 */
    err = 2*n*fabs(mod_psi_even(n, 0.5))*rhomax2nm2;
    rhomax2nm2 *= rhomax2;
    n++;
    // fprintf(stderr, "%f\n", err);
  }
  while (err > 0.1*maxPWerror);
}
Exemplo n.º 3
0
double mmm1d_coulomb_pair_energy(Particle *p1, Particle *p2, double d[3], double r2, double r)
{
  double chpref = p1->p.q*p2->p.q;
  double rxy2, rxy2_d, z_d;
  double E;

  if (chpref == 0)
    return 0;

  rxy2   = d[0]*d[0] + d[1]*d[1];
  rxy2_d = rxy2*uz2;
  z_d    = d[2]*uz;

  if (rxy2 <= mmm1d_params.far_switch_radius_2) {
    /* near range formula */
    double r2n, rt, shift_z;
    int n;

    E = -2*C_GAMMA;

    /* polygamma summation */
    r2n = 1.0;
    for (n = 0; n < n_modPsi; n++) {
      double add = mod_psi_even(n, z_d)*r2n;
      E -= add;
      
      if (fabs(add) < mmm1d_params.maxPWerror)
	break;
 
      r2n *= rxy2_d;
    }
    E *= coulomb.prefactor*uz;

    /* real space parts */

    E += coulomb.prefactor/r; 

    shift_z = d[2] + box_l[2];
    rt = sqrt(rxy2 + shift_z*shift_z);
    E += coulomb.prefactor/rt; 

    shift_z = d[2] - box_l[2];
    rt = sqrt(rxy2 + shift_z*shift_z);
    E += coulomb.prefactor/rt; 
  }
  else {
    /* far range formula */
    double rxy   = sqrt(rxy2);
    double rxy_d = rxy*uz;
    int bp;
    /* The first Bessel term will compensate a little bit the
       log term, so add them close together */
    E = -0.25*log(rxy2_d) + 0.5*(M_LN2 - C_GAMMA);
    for (bp = 1; bp < mmm1d_params.bessel_cutoff; bp++) {
      double fq = C_2PI*bp;
      E += K0(fq*rxy_d)*cos(fq*z_d);
    }
    E *= 4*coulomb.prefactor*uz;
  }

  return chpref*E;
}
Exemplo n.º 4
0
void add_mmm1d_coulomb_pair_force(double chpref, double d[3], double r2, double r, double force[3])
{
  int dim;
  double F[3];
  double rxy2, rxy2_d, z_d;
  double pref;
  double Fx, Fy, Fz;
  

  rxy2   = d[0]*d[0] + d[1]*d[1];
  rxy2_d = rxy2*uz2;
  z_d    = d[2]*uz;

  if (rxy2 <= mmm1d_params.far_switch_radius_2) {
    /* near range formula */
    double sr, sz, r2nm1, rt, rt2, shift_z;
    int n;

    /* polygamma summation */
    sr = 0;
    sz = mod_psi_odd(0, z_d);

    r2nm1 = 1.0;
    for (n = 1; n < n_modPsi; n++) {
      double deriv = 2*n;
      double mpe   = mod_psi_even(n, z_d);
      double mpo   = mod_psi_odd(n, z_d);
      double r2n   = r2nm1*rxy2_d;

      sz +=         r2n*mpo;
      sr += deriv*r2nm1*mpe;

      if (fabs(deriv*r2nm1*mpe) < mmm1d_params.maxPWerror)
	break;

      r2nm1 = r2n;
    }
    // fprintf(stderr, "max_n %d\n", n);

    Fx = prefL3_i*sr*d[0];
    Fy = prefL3_i*sr*d[1];
    Fz = prefuz2*sz;

    /* real space parts */

    pref = coulomb.prefactor/(r2*r); 
    Fx += pref*d[0];
    Fy += pref*d[1];
    Fz += pref*d[2];

    shift_z = d[2] + box_l[2];
    rt2 = rxy2 + shift_z*shift_z;
    rt  = sqrt(rt2);
    pref = coulomb.prefactor/(rt2*rt); 
    Fx += pref*d[0];
    Fy += pref*d[1];
    Fz += pref*shift_z;

    shift_z = d[2] - box_l[2];
    rt2 = rxy2 + shift_z*shift_z;
    rt  = sqrt(rt2);
    pref = coulomb.prefactor/(rt2*rt); 
    Fx += pref*d[0];
    Fy += pref*d[1];
    Fz += pref*shift_z;

    F[0] = Fx;
    F[1] = Fy;
    F[2] = Fz;
  }
  else {
    /* far range formula */
    double rxy   = sqrt(rxy2);
    double rxy_d = rxy*uz;
    double sr = 0, sz = 0;
    int bp;

    for (bp = 1; bp < mmm1d_params.bessel_cutoff; bp++) {
      double fq = C_2PI*bp, k0, k1;
#ifdef BESSEL_MACHINE_PREC
      k0 = K0(fq*rxy_d);
      k1 = K1(fq*rxy_d);
#else
      LPK01(fq*rxy_d, &k0, &k1);
#endif
      sr += bp*k1*cos(fq*z_d);
      sz += bp*k0*sin(fq*z_d);
    }
    sr *= uz2*4*C_2PI;
    sz *= uz2*4*C_2PI;
    
    pref = coulomb.prefactor*(sr/rxy + 2*uz/rxy2);

    F[0] = pref*d[0];
    F[1] = pref*d[1];
    F[2] = coulomb.prefactor*sz;
  }

  for (dim = 0; dim < 3; dim++)
    force[dim] += chpref * F[dim];
}