void p2p (PointAccum *one, PointAccum *other)
{
  if (one != other)
    {
      VsgVector3d tmp;
      VsgVector3d tmp1;
      VsgVector3d tmp2;
      gdouble r, inv_r, inv_r3;

      /* destination - source */
      vsg_vector3d_sub (&one->vector, &other->vector, &tmp);

      r = vsg_vector3d_norm (&tmp);

      if (r > epsilon)
        {
          inv_r = 1. / r;
          inv_r3 = inv_r*inv_r*inv_r;

/*           one->accum += inv_r * other->density; */
          vsg_vector3d_scalp (&tmp, - inv_r3*other->density, &tmp1);
          vsg_vector3d_add (&one->field, &tmp1, &one->field);

/*           other->accum += inv_r * one->density; */
          vsg_vector3d_scalp (&tmp, inv_r3*one->density, &tmp2);
          vsg_vector3d_add (&other->field, &tmp2, &other->field);

/*           g_printerr ("%d : p2p %d %d ", rk, one->id, other->id); */
/*           vsg_vector3d_write (&one->vector, stderr); */
/*           g_printerr (" "); */
/*           vsg_vector3d_write (&one->field, stderr); */
/*           g_printerr ("\n"); */
        }
    }
}
static void p2p (PointAccum *one, PointAccum *other)
{
  if (one != other)
    {
      VsgVector3d tmp;
      VsgVector3d tmp1;
      VsgVector3d tmp2;
      gdouble r, inv_r, inv_r3;

      /* destination - source */
      vsg_vector3d_sub (&one->vector, &other->vector, &tmp);

      r = vsg_vector3d_norm (&tmp);

      if (r > epsilon)
        {
          inv_r = 1. / r;
          inv_r3 = inv_r*inv_r*inv_r;

/*           one->accum += inv_r * other->density; */
          vsg_vector3d_scalp (&tmp, - inv_r3*other->density, &tmp1);
          vsg_vector3d_add (&one->field, &tmp1, &one->field);

/*           other->accum += inv_r * one->density; */
          vsg_vector3d_scalp (&tmp, inv_r3*one->density, &tmp2);
          vsg_vector3d_add (&other->field, &tmp2, &other->field);
        }
    }
}
gcomplex128 newtonpot (VsgVector3d *vec)
{
  VsgVector3d tmp;

  vsg_vector3d_sub (vec, &p, &tmp);

  return 1. / vsg_vector3d_norm (&tmp);
}
/**
 * aran_development3d_local_evaluate:
 * @devel_node: tree node info of @devel.
 * @devel: an #AranDevelopment3d.
 * @pos: evaluation position.
 *
 * Evaluates the local part of @devel at @pos.
 *
 * Returns: value of local part of @devel(@pos).
 */
gcomplex128 aran_development3d_local_evaluate (const VsgPRTree3dNodeInfo *devel_node,
					       AranDevelopment3d *devel,
					       const VsgVector3d *pos)
{
  VsgVector3d tmp;

  vsg_vector3d_sub (pos, &devel_node->center, &tmp);

  return aran_spherical_seriesd_evaluate (devel->local, &tmp);
}
Exemple #5
0
void newtongrad (VsgVector3d *vec, VsgVector3d *grad)
{
  gdouble r;

  vsg_vector3d_sub (vec, &p, grad);

  r = vsg_vector3d_norm (grad);

  vsg_vector3d_scalp (grad, 1./ (r*r*r), grad);
}
/**
 * aran_development3d_local_gradient_evaluate:
 * @devel_node: tree node info of @devel.
 * @devel: an #AranDevelopment3d.
 * @pos: evaluation position.
 * @grad: result gradient.
 *
 * Evaluates the gradient of the local part of @devel at @pos.
 */
void
aran_development3d_local_gradient_evaluate (const VsgPRTree3dNodeInfo *devel_node,
                                            AranDevelopment3d *devel,
                                            const VsgVector3d *pos,
                                            VsgVector3d *grad)
{
  VsgVector3d tmp;

  vsg_vector3d_sub (pos, &devel_node->center, &tmp);

  aran_spherical_seriesd_local_gradient_evaluate (devel->local, &tmp, grad);
}
Exemple #7
0
static gdouble kernel (PointAccum *one, PointAccum *other)
{
  VsgVector3d tmp;
  gdouble inv_r;

  /* destination - source */
  vsg_vector3d_sub (&one->vector, &other->vector, &tmp);

  inv_r = 1. / vsg_vector3d_norm (&tmp);

  return inv_r * one->density;
}
Exemple #8
0
static vsgrloc3 _sphere_loc3 (Sphere *sphere, VsgVector3d *center)
{
  VsgVector3d tmp;
  gdouble dist;
  vsgloc3 centerpos;
  vsgrloc3 ret;

  vsg_vector3d_sub (center, &sphere->center, &tmp);

  dist = vsg_vector3d_norm (&tmp);

  if (dist <= sphere->radius) return VSG_RLOC3_MASK;

  ret = 0;

  centerpos = vsg_vector3d_vector3d_locfunc (&sphere->center, center);

/*   g_printerr ("%d: {c=", rk); */
/*   vsg_vector3d_write (&sphere->center, stderr); */
/*   g_printerr (" r=%g} ref=", sphere->radius); */
/*   vsg_vector3d_write (center, stderr); */

  ret |= VSG_RLOC3_COMP (centerpos);

/*   g_printerr (" / 0x%X", ret); */

  if (fabs (tmp.x) <= sphere->radius)
    {
      vsgloc3 itmp = centerpos ^ VSG_LOC3_X;
      ret |= VSG_RLOC3_COMP (itmp);
/*       g_printerr (" / x<rad 0x%X (%x %x)", itmp, centerpos, VSG_LOC3_X); */
    }

  if (fabs (tmp.y) <= sphere->radius)
    {
      vsgloc3 itmp = centerpos ^ VSG_LOC3_Y;
      ret |= VSG_RLOC3_COMP (itmp);
/*       g_printerr (" / y<rad 0x%X (%x %x)", itmp, centerpos, VSG_LOC3_Y); */
    }

  if (fabs (tmp.z) <= sphere->radius)
    {
      vsgloc3 itmp = centerpos ^ VSG_LOC3_Z;
      ret |= VSG_RLOC3_COMP (itmp);
/*       g_printerr (" / y<rad 0x%X (%x %x)", itmp, centerpos, VSG_LOC3_Y); */
    }

/*   g_printerr (" => 0x%X\n", ret); */

  return ret;
}
Exemple #9
0
static AranSphericalSeriesd *create_taylor (guint deg, VsgVector3d *center,
                                            VsgVector3d *p)
{
  AranSphericalSeriesd *ass;
  gint l, m;
  const guint size = ((deg+1)*(deg+2))/2;
  gcomplex128 harmonics[size];
  gdouble r, cost, sint, cosp, sinp;
  gcomplex128 expp;
  gdouble fact, inv_r;
  VsgVector3d tmp;

  ass = aran_spherical_seriesd_new (deg, 0);
  aran_spherical_seriesd_set_zero (ass);

  vsg_vector3d_sub (p, center, &tmp);

  vsg_vector3d_to_spherical_internal (&tmp, &r, &cost, &sint, &cosp, &sinp);
  expp = cosp + G_I * sinp;

  aran_spherical_harmonic_evaluate_multiple_internal (deg, cost, sint, expp,
						      harmonics);

  *aran_spherical_seriesd_get_term (ass, 0, 0) = 0.;

  inv_r = 1./ r;
  fact = inv_r;

  for (l=0; l<=deg; l ++)
    {
      gcomplex128 term;

      term = fact * (4.*G_PI / (l+l+1.)) *
	*aran_spherical_harmonic_multiple_get_term (l, 0, harmonics);

      *aran_spherical_seriesd_get_term (ass, l, 0) = conj (term);

      for (m=1; m<=l; m ++)
	{
	  term = fact * (4.*G_PI / (l+l+1.)) *
	    *aran_spherical_harmonic_multiple_get_term (l, m, harmonics);

	    *aran_spherical_seriesd_get_term (ass, l, m) = conj (term);

	}
      fact *= inv_r;
    }

  return ass;
}
static void p2m (PointAccum *particle, const VsgVector3d *center,
		 AranDevelopment3d *devel)
{
  VsgVector3d tmp;
  guint deg = aran_spherical_seriesd_get_negdeg (devel->multipole);
  gint l, m;
  gcomplex128 harmonics[((deg+1)*(deg+2))/2];
  gdouble r, cost, sint, cosp, sinp;
  gcomplex128 expp;
  gdouble fact;

  vsg_vector3d_sub (&particle->vector, center, &tmp);

  vsg_vector3d_to_spherical_internal (&tmp, &r, &cost, &sint, &cosp, &sinp);
  expp = cosp + G_I * sinp;

  aran_spherical_harmonic_evaluate_multiple_internal (deg, cost, sint, expp,
						      harmonics);


  *aran_spherical_seriesd_get_term (devel->multipole, 0, 0) += 0.;

  fact = particle->density;

  for (l=0; l<deg; l ++)
    {
      gcomplex128 *ptr;
      gcomplex128 term;

      term = fact * (4.*G_PI / (l+l+1.)) *
	*aran_spherical_harmonic_multiple_get_term (l, 0, harmonics);

      ptr = aran_spherical_seriesd_get_term (devel->multipole, -l-1, 0);
      ptr[0] += conj (term);

      for (m=1; m<=l; m ++)
	{

	  term = fact * (4.*G_PI / (l+l+1.)) *
	    *aran_spherical_harmonic_multiple_get_term (l, m, harmonics);

          ptr[m] += conj (term);
	}
      fact *= r;
    }

}
/**
 * aran_spherical_seriesd_to_local:
 * @src: source expansion series.
 * @xsrc: @src center.
 * @dst: destination expansion series.
 * @xdst: @dst center.
 *
 * Like aran_spherical_seriesd_translate() except the multipole part of
 * @src is transformed into a local expansion in @dst.
 */
void aran_spherical_seriesd_to_local (const AranSphericalSeriesd * src,
                                      const VsgVector3d * xsrc,
                                      AranSphericalSeriesd * dst,
                                      const VsgVector3d * xdst)
{
  VsgVector3d tmp;
  gdouble r, cost, sint, cosp, sinp;

  vsg_vector3d_sub (xdst, xsrc, &tmp);

  vsg_vector3d_to_spherical_internal (&tmp, &r, &cost, &sint, &cosp, &sinp);

  aran_local_translate (src, dst, r, cost, sint, cosp, sinp);

  if (src->negdeg > 0)
    {
      aran_multipole_to_local (src, dst, r, cost, sint, cosp, sinp);
    }
}
void check_point_field (PointAccum *point, gint *ret)
{
  gint i;
  gdouble err;
  gdouble denom;
  PointAccum *check;
  VsgVector3d tmp;

  i = point->id;

  check = &check_points[i];

  denom = vsg_vector3d_norm (&check->field);
  vsg_vector3d_sub (&point->field, &check->field, &tmp);
  err = vsg_vector3d_norm (&tmp);
  if (denom > 0.) err /= denom;

  maxerr = MAX (maxerr, fabs (err));

  if (fabs (err) > err_lim || !finite (err))
    {
      g_printerr ("%d : Field simulation error: %d relative=(%e) "
                  "pos=(%f,%f,%f)\n"
                  "                        computed=(%f,%f,%f) "
                  "exact=(%f,%f,%f)\n",
                  rk, i, fabs(err),
                  point->vector.x, point->vector.y, point->vector.z,
                  point->field.x, point->field.y, point->field.z,
                  check->field.x, check->field.y, check->field.z);
      (*ret) ++;
    }
/*   else */
/*     { */
/*       g_printerr ("%d : Field simulation ok: %d relative=(%e) exact=(%f,%f,%f)\n", */
/*                   rk, i, fabs(err), check->field.x, check->field.y, check->field.z); */

/*     } */
}
/**
 * aran_spherical_seriesd_translate_rotate:
 * @src: source expansion series.
 * @xsrc: @src center.
 * @dst: destination expansion series.
 * @xdst: @dst center.
 *
 * Performs the same operation as aran_spherical_seriesd_translate() but
 * with the "Point and Shoot" algorithm which achieves O(p^3) complexity. 
 */
void aran_spherical_seriesd_translate_rotate (const AranSphericalSeriesd *src,
                                              const VsgVector3d *xsrc,
                                              AranSphericalSeriesd *dst,
                                              const VsgVector3d *xdst)
{
  gint l;
  guint8 nd = MAX (dst->negdeg, src->negdeg);
  guint8 pd = MAX (dst->posdeg, src->posdeg);
  guint8 lmax = MAX (pd+1, nd);

  gcomplex128 expma[lmax];
  gcomplex128 expa;

  AranWigner *aw;
  VsgVector3d dir;
  gdouble r, theta, phi;
  gdouble cost = 1.;
  AranSphericalSeriesd *rot = (AranSphericalSeriesd *)
    g_alloca (ARAN_SPHERICAL_SERIESD_SIZE (src->posdeg, src->negdeg));

  AranSphericalSeriesd *trans = (AranSphericalSeriesd *)
    g_alloca (ARAN_SPHERICAL_SERIESD_SIZE (dst->posdeg, dst->negdeg));

  /* create work AranSphericalSeriesd */
  memcpy (rot, src, sizeof (AranSphericalSeriesd));
  memcpy (trans, dst, sizeof (AranSphericalSeriesd));

  aran_spherical_seriesd_set_zero (rot);
  aran_spherical_seriesd_set_zero (trans);

  /* get translation vector */
  vsg_vector3d_sub (xdst, xsrc, &dir);

  if (dir.z < 0.)
    {
      cost = -1.;
      vsg_vector3d_scalp (&dir, -1., &dir);
    }

  /* get rotation angles */
  vsg_vector3d_to_spherical (&dir, &r, &theta, &phi);

  /* prepare rotation tools: AranWigner + complex exponentials arrays */
  aw = aran_wigner_repo_lookup (theta);

  aran_wigner_require (aw, lmax);

  expa = cos (-phi) - G_I * sin (-phi);

  expma[0] = 1.;
  for (l = 1; l < lmax; l++)
    {
      expma[l] = expma[l - 1] * expa;
    }

  /* rotate src */
  _buffer_rotate_ab (aw, src->posdeg, expma,
                     _spherical_seriesd_get_pos_term (src, 0, 0),
                     _spherical_seriesd_get_pos_term (rot, 0, 0));

  if (src->negdeg > 0)
    {
      _buffer_rotate_ab (aw, src->negdeg - 1, expma,
                      _spherical_seriesd_get_neg_term (src, 0, 0),
                      _spherical_seriesd_get_neg_term (rot, 0, 0));
    }
/*   aran_spherical_seriesd_rotate (src, -phi, theta, 0., rot); */

  /* translate src to dst center */
  aran_spherical_seriesd_translate_vertical (rot, trans,
                                             r, cost,
                                             1., 0.);

  /* rotate back and accumulate into dst */
  _buffer_rotate_ab_inverse (aw, dst->posdeg, expma,
                  _spherical_seriesd_get_pos_term (trans, 0, 0),
                  _spherical_seriesd_get_pos_term (dst, 0, 0));

  if (dst->negdeg > 0)
    {
      _buffer_rotate_ab_inverse (aw, dst->negdeg - 1, expma,
                      _spherical_seriesd_get_neg_term (trans, 0, 0),
                      _spherical_seriesd_get_neg_term (dst, 0, 0));
    }
/*   aran_spherical_seriesd_rotate_inverse (trans, -phi, theta, 0., dst); */
}
Exemple #14
0
static void check (const gchar *log,
                   AranSphericalSeriesd *ass, gdouble radius,
		   VsgVector3d *center,
		   void (*f) (VsgVector3d *x, VsgVector3d *grad))
{
  guint i, j, k;
  gdouble t, p;
  gdouble err;
  gdouble r, cost, sint, cosp, sinp;
  gcomplex128 dr, dt, dp;

  for (i=0; i<N ; i ++)
    {
      p = 2.*G_PI * i/(N-1.);
      cosp = cos (p);
      sinp = sin (p);

      for (j=0; j<N; j ++)
	{
	  t = G_PI * j/(N-1.);
	  cost = cos (t);
	  sint = sin (t);

	  for (k=0; k<N; k ++)
	    {
	      VsgVector3d vec;
	      VsgVector3d vref;
	      VsgVector3d vres;
	      VsgVector3d verr;

	      r = radius * k/(N-1.);

	      vsg_vector3d_from_spherical_internal (&vec, r,
						    cost, sint,
						    cosp, sinp);

/*               aran_spherical_seriesd_gradient_evaluate (ass, &vec, */
/*                                                               &vres); */

              aran_spherical_seriesd_gradient_evaluate_internal (ass,
                                                                 r,
                                                                 cost, sint,
                                                                 cosp, sinp,
                                                                 &dr, &dt, &dp);
              local_to_cartesian (r, cost, sint, cosp, sinp,
                                  creal (dr), creal (dt), creal (dp),
                                  &vres);

              
              vsg_vector3d_scalp (&vres, -1., &vres);

	      vsg_vector3d_add (&vec, center, &vec);

	      f (&vec, &vref);

	      vsg_vector3d_sub (&vref, &vres, &verr);

              err = vsg_vector3d_norm (&verr) / vsg_vector3d_norm (&vref);

	      if (fabs (err) > epsilon || !finite (err))
		{
		  g_printerr ("Error %s (%f,%f,%f) : " \
                              "(%f,%f,%f) != (%f,%f,%f) -> %e\n",
                              log,
			      r, t, p,
/* 			      vec.x, vec.y, vec.z, */
			      vref.x, vref.y, vref.z,
			      vres.x, vres.y, vres.z,
			      fabs (err));
		}
	    }
	}
    }
}
int main (int argc, char **argv)
{
  VsgVector3d lbound = {-TR, -TR, -TR};
  VsgVector3d ubound = {TR, TR, TR};
  PointAccum **points;
  VsgPRTree3d *prtree;
  AranSolver3d *solver;
  int ret = 0;
  guint i;

  aran_init();

  parse_args (argc, argv);

  points = g_malloc0 (np * sizeof (PointAccum *));

  prtree =
    vsg_prtree3d_new_full (&lbound, &ubound,
			    (VsgPoint3dLocFunc) vsg_vector3d_vector3d_locfunc,
			    (VsgPoint3dDistFunc) vsg_vector3d_dist,
			    (VsgRegion3dLocFunc) NULL, maxbox);

  solver = aran_solver3d_new (prtree, ARAN_TYPE_DEVELOPMENT3D,
			      aran_development3d_new (0, order),
			      (AranZeroFunc) aran_development3d_set_zero);

  aran_solver3d_set_functions (solver,
			       (AranParticle2ParticleFunc3d) p2p,
			       (AranParticle2MultipoleFunc3d) p2m,
                               m2m,
			       m2l,
			       l2l,
			       (AranLocal2ParticleFunc3d)l2p);

  _distribution (points, solver);

/*   g_printerr ("ok depth = %d size = %d\n", */
/*               aran_solver3d_depth (solver), */
/*               aran_solver3d_point_count (solver)); */

  if (direct) _direct (points, np);
  else aran_solver3d_solve (solver);

/*   vsg_prtree3d_write (prtree, stderr); */

  aran_solver3d_free (solver);

  if (check)
    {
      gint i, j;

      for (i=0; i<np; i ++)
        {
          PointAccum *particle = points[i];

          PointAccum check;
          VsgVector3d tmp;
          gdouble err, denom;

          memcpy (&check, particle, sizeof (PointAccum));

/*           check.accum = 0.; */
          check.field = VSG_V3D_ZERO;

          for (j=0; j<np; j ++)
            {
              p2p_one_way (&check, points[j]);
            }

          denom = vsg_vector3d_norm (&check.field);
          vsg_vector3d_sub (&particle->field, &check.field, &tmp);
          err = vsg_vector3d_norm (&tmp);
          if (denom > 0.) err /= denom;

          if (fabs (err) > err_lim)
            {
              g_printerr ("Field simulation error: %d relative=(%e) "
                          "pos=(%f,%f,%f)\n"
                          "                        computed=(%f,%f,%f) "
                          "exact=(%f,%f,%f)\n",
                          i, fabs(err),
                          particle->vector.x, particle->vector.y, particle->vector.z,
                          particle->field.x, particle->field.y, particle->field.z,
                          check.field.x, check.field.y, check.field.z);
/*               g_printerr ("         pc=%f pe=%f\n", */
/*                           creal (particle->accum), */
/*                           creal (check.accum)); */
              ret ++;
            }
        }
    }

  for (i=0; i<np; i++)
    {
      g_free (points[i]);
    }

  g_free (points);

  return ret;
}