Exemplo n.º 1
0
double
_energyInterParticle(pullTask *task, pullPoint *me, pullPoint *she, 
                     /* output */
                     double egrad[4]) {
  char meme[]="_energyInterParticle";
  double spadist, sparad, diff[4], rr, enr, frc, *parm;

  ELL_4V_SUB(diff, she->pos, me->pos);
  spadist = ELL_3V_LEN(diff);
  sparad = task->pctx->radiusSpace;
  
  rr = spadist/(2*sparad);
  /*
  fprintf(stderr, "!%s: rr(%u,%u) = %g\n", meme, me->idtag, she->idtag, rr);
  */
  if (rr > 1) {
    ELL_4V_SET(egrad, 0, 0, 0, 0);
    return 0;
  }
  if (rr == 0) {
    fprintf(stderr, "%s: pos of pts %u, %u equal: (%g,%g,%g,%g)\n",
            meme, me->idtag, she->idtag, 
            me->pos[0], me->pos[1], me->pos[2], me->pos[3]);
    ELL_4V_SET(egrad, 0, 0, 0, 0);
    return 0;
  }

  parm = task->pctx->energySpec->parm;
  enr = task->pctx->energySpec->energy->eval(&frc, rr, parm);
  frc *= -1.0/(2*sparad*spadist);
  ELL_3V_SCALE(egrad, frc, diff);
  egrad[3] = 0;
  /*
  fprintf(stderr, "%s: %u <-- %u = %g,%g,%g -> egrad = %g,%g,%g, enr = %g\n",
          meme, me->idtag, she->idtag, 
          diff[0], diff[1], diff[2],
          egrad[0], egrad[1], egrad[2], enr);
  */
  return enr;
}
Exemplo n.º 2
0
double
_energyFromPoints(pullTask *task, pullBin *bin, pullPoint *point, 
                  /* output */
                  double egradSum[4]) {
  /* char me[]="_energyFromPoints"; */
  double energySum, distSqSum, spaDistSqMax, wghtSum;
  int nopt,     /* optimiziation: we sometimes re-use neighbor lists */
    ntrue;      /* we search all possible neighbors, stored in the bins
                   (either because !nopt, or, this iter we learn true
                   subset of interacting neighbors).  This could also
                   be called "dontreuse" or something like that */
  unsigned int nidx,
    nnum;       /* how much of task->neigh[] we use */

  /* set nopt and ntrue */
  if (task->pctx->neighborTrueProb < 1) {
    nopt = AIR_TRUE;
    if (egradSum) {
      /* We allow the neighbor list optimization only when we're also asked
         to compute the energy gradient.  When we're not getting the energy
         gradient, we're being called to test the waters at possible new
         locations, in which case we can't be changing the effective particle 
         neighborhood */
      ntrue = (0 == task->pctx->iter
               || airDrandMT_r(task->rng) < task->pctx->neighborTrueProb);
    } else {
      ntrue = AIR_FALSE;
    }
  } else {
    nopt = AIR_FALSE;
    ntrue = AIR_TRUE;
  }
  /*
  fprintf(stderr, "!%s(%u), nopt = %d, ntrue = %d\n", me, point->idtag,
          nopt, ntrue);
  */
  /* set nnum and task->neigh[] */
  if (ntrue) {
    nnum = _neighBinPoints(task, bin, point);
    if (nopt) {
      airArrayLenSet(point->neighArr, 0);
    }
  } else {
    /* (nopt true) this iter we re-use existing neighbor list */
    nnum = point->neighNum;
    for (nidx=0; nidx<nnum; nidx++) {
      task->neighPoint[nidx] = point->neighPoint[nidx];
    }
  }

  /* loop through neighbor points */
  spaDistSqMax = 4*task->pctx->radiusSpace*task->pctx->radiusSpace;
  /*
  fprintf(stderr, "%s: radiusSpace = %g -> spaDistSqMax = %g\n", me,
          task->pctx->radiusSpace, spaDistSqMax);
  */
  wghtSum = 0;
  energySum = 0;
  distSqSum = 0;
  point->neighInterNum = 0;
  point->neighDist = 0.0;
  point->neighMode = 0.0;
  if (egradSum) {
    ELL_4V_SET(egradSum, 0, 0, 0, 0);
  }
  for (nidx=0; nidx<nnum; nidx++) {
    double diff[4], spaDistSq, enr, egrad[4];
    pullPoint *herPoint;
    herPoint = task->neighPoint[nidx];
    ELL_4V_SUB(diff, herPoint->pos, point->pos);
    spaDistSq = ELL_3V_DOT(diff, diff);
    /*
    fprintf(stderr, "!%s: %u:%g,%g,%g <-- %u:%g,%g,%g = sqd %g %s %g\n", me,
            point->idtag, point->pos[0], point->pos[1], point->pos[2], 
            herPoint->idtag,
            herPoint->pos[0], herPoint->pos[1], herPoint->pos[2],
            spaDistSq, spaDistSq > spaDistSqMax ? ">" : "<=", spaDistSqMax);
    */
    if (spaDistSq > spaDistSqMax) {
      continue;
    }
    if (AIR_ABS(diff[3] > task->pctx->radiusScale)) {
      continue;
    }
    enr = _energyInterParticle(task, point, herPoint, egrad);
    /*
    fprintf(stderr, "!%s: energySum = %g + %g = %g\n", me, 
            energySum, enr, energySum + enr);
    */
    energySum += enr;
    if (egradSum) {
      ELL_4V_INCR(egradSum, egrad);
      if (ELL_4V_DOT(egrad, egrad)) {
        point->neighInterNum++;
        point->neighDist = spaDistSq;
        if (task->pctx->ispec[pullInfoTangentMode]) {
          double w, m;
          m = _pullPointScalar(task->pctx, herPoint, pullInfoTangentMode,
                               NULL, NULL);
          w = 1.0/spaDistSq;
          point->neighMode += w*m;
          wghtSum += w;
        }
        if (nopt && ntrue) {
          unsigned int ii;
          ii = airArrayLenIncr(point->neighArr, 1);
          point->neighPoint[ii] = herPoint;
        }
      }
    }
  }
  
  /* finish computing things averaged over neighbors */
  if (point->neighInterNum) {
    point->neighDist = sqrt(point->neighDist/point->neighInterNum);
    point->neighMode /= wghtSum;
  } else {
    point->neighDist = -1;
    point->neighMode = AIR_NAN;
  }

  return energySum;
}
Exemplo n.º 3
0
Arquivo: tq.c Projeto: rblake/seg3d2
int
main(int argc, char *argv[]) {
  float angleA_f, axisA_f[3], angleB_f, axisB_f[3],
    qA_f[4], qB_f[4], qC_f[4],
    mat3A_f[9], mat4A_f[16], mat3B_f[9], mat4B_f[16], mat3C_f[9], mat4C_f[16],
    pntA_f[4], pntB_f[4], pntC_f[4];
  double angleA_d, axisA_d[3], angleB_d, axisB_d[3],
    qA_d[4], qB_d[4], qC_d[4],
    mat3A_d[9], mat4A_d[16], mat3B_d[9], mat4B_d[16], mat3C_d[9], mat4C_d[16],
    pntA_d[4], pntB_d[4], pntC_d[4];

  int I, N;
  double tmp, det, frob;

  me = argv[0];
  N = 100000;

  AIR_UNUSED(pntA_d);
  AIR_UNUSED(pntB_d);
  AIR_UNUSED(pntC_d);
  AIR_UNUSED(mat4C_d);
  AIR_UNUSED(mat3C_d);
  AIR_UNUSED(mat4B_d);
  AIR_UNUSED(mat3B_d);
  AIR_UNUSED(mat4A_d);
  AIR_UNUSED(mat3A_d);
  AIR_UNUSED(qC_d);
  AIR_UNUSED(qB_d);
  AIR_UNUSED(qA_d);
  AIR_UNUSED(axisB_d);
  AIR_UNUSED(angleB_d);
  AIR_UNUSED(axisA_d);
  AIR_UNUSED(angleA_d);
  AIR_UNUSED(argc);

  for (I=0; I<N; I++) {
    /* make a rotation (as a quaternion) */
    ELL_3V_SET(axisA_f, 2*airDrandMT()-1, 2*airDrandMT()-1, 2*airDrandMT()-1);
    ELL_3V_NORM(axisA_f, axisA_f, tmp); /* yea, not uniform, so what */
    angleA_f = AIR_PI*(2*airDrandMT()-1);
    ell_aa_to_q_f(qA_f, angleA_f, axisA_f);

    /* convert to AA and back, and back */
    angleB_f = ell_q_to_aa_f(axisB_f, qA_f);
    if (ELL_3V_DOT(axisB_f, axisA_f) < 0) {
      ELL_3V_SCALE(axisB_f, -1, axisB_f);
      angleB_f *= -1;
    }
    ELL_3V_SUB(axisA_f, axisA_f, axisB_f);
    printf(" aa -> q -> aa error: %g, %g\n",
           CA + AIR_ABS(angleA_f - angleB_f), CA + ELL_3V_LEN(axisA_f));

    /* convert to 3m and back, and back */
    ell_q_to_3m_f(mat3A_f, qA_f);
    ell_3m_to_q_f(qB_f, mat3A_f);
    if (ELL_4V_DOT(qA_f, qB_f) < 0) {
      ELL_4V_SCALE(qB_f, -1, qB_f);
    }
    ELL_4V_SUB(qC_f, qA_f, qB_f);
    ELL_Q_TO_3M(mat3B_f, qA_f);
    ELL_3M_SUB(mat3C_f, mat3B_f, mat3A_f);
    printf(" q -> 3m -> q error: %g, %g\n",
           CA + ELL_4V_LEN(qC_f), CA + ELL_3M_FROB(mat3C_f));

    /* convert to 4m and back, and back */
    ell_q_to_4m_f(mat4A_f, qA_f);
    ell_4m_to_q_f(qB_f, mat4A_f);
    if (ELL_4V_DOT(qA_f, qB_f) < 0) {
      ELL_4V_SCALE(qB_f, -1, qB_f);
    }
    ELL_4V_SUB(qC_f, qA_f, qB_f);
    ELL_Q_TO_4M(mat4B_f, qA_f);
    ELL_4M_SUB(mat4C_f, mat4B_f, mat4A_f);
    printf(" q -> 4m -> q error: %g, %g\n",
           CA + ELL_4V_LEN(qC_f), CA + ELL_4M_FROB(mat4C_f));

    /* make a point that we'll rotate */
    ELL_3V_SET(pntA_f, 2*airDrandMT()-1, 2*airDrandMT()-1, 2*airDrandMT()-1);
    
    /* effect rotation in two different ways, and compare results */
    ELL_3MV_MUL(pntB_f, mat3A_f, pntA_f);
    ell_q_3v_rotate_f(pntC_f, qA_f, pntA_f);
    ELL_3V_SUB(pntA_f, pntB_f, pntC_f);
    printf("      rotation error = %g\n", CA + ELL_3V_LEN(pntA_f));

    /* mix up inversion with conversion */
    ell_3m_inv_f(mat3C_f, mat3A_f);
    ell_3m_to_q_f(qB_f, mat3C_f);
    ell_q_mul_f(qC_f, qA_f, qB_f);
    if (ELL_4V_DOT(qA_f, qC_f) < 0) {
      ELL_4V_SCALE(qC_f, -1, qC_f);
    }
    printf("    inv mul = %g %g %g %g\n", qC_f[0], 
           CA + qC_f[1], CA + qC_f[2], CA + qC_f[3]);
    ell_q_inv_f(qC_f, qB_f);
    ELL_4V_SUB(qC_f, qB_f, qB_f);
    printf("    inv diff = %g %g %g %g\n", CA + qC_f[0], 
           CA + qC_f[1], CA + qC_f[2], CA + qC_f[3]);

    /* exp and log */
    ell_q_log_f(qC_f, qA_f);
    ell_q_log_f(qB_f, qC_f);
    ell_q_exp_f(qC_f, qB_f);
    ell_q_exp_f(qB_f, qC_f);
    ELL_4V_SUB(qC_f, qB_f, qA_f);
    printf("    exp/log diff = %g %g %g %g\n", CA + qC_f[0], 
           CA + qC_f[1], CA + qC_f[2], CA + qC_f[3]);

    /* pow, not very exhaustive */
    ell_q_to_3m_f(mat3A_f, qA_f);
    ell_3m_post_mul_f(mat3A_f, mat3A_f);
    ell_3m_post_mul_f(mat3A_f, mat3A_f);
    ell_q_pow_f(qB_f, qA_f, 4);
    ell_q_to_3m_f(mat3B_f, qB_f);
    ELL_3M_SUB(mat3B_f, mat3B_f, mat3A_f);
    printf("   pow diff = %g\n", CA + ELL_3M_FROB(mat3B_f));
    if (ELL_3M_FROB(mat3B_f) > 2) {
      printf("  start q = %g %g %g %g\n", qA_f[0], qA_f[1], qA_f[2], qA_f[3]);
      angleA_f = ell_q_to_aa_f(axisA_f, qA_f);
      printf("  --> aa = %g  (%g %g %g)\n", angleA_f, 
             axisA_f[0], axisA_f[1], axisA_f[2]);
      printf("   q^3 = %g %g %g %g\n", qB_f[0], qB_f[1], qB_f[2], qB_f[3]);
      angleA_f = ell_q_to_aa_f(axisA_f, qB_f);
      printf("  --> aa = %g  (%g %g %g)\n", angleA_f, 
             axisA_f[0], axisA_f[1], axisA_f[2]);
      exit(1);
    }

    /* make sure it looks like a rotation matrix */
    ell_q_to_3m_f(mat3A_f, qA_f);
    det = ELL_3M_DET(mat3A_f);
    frob = ELL_3M_FROB(mat3A_f);
    ELL_3M_TRANSPOSE(mat3B_f, mat3A_f);
    ell_3m_inv_f(mat3C_f, mat3A_f);
    ELL_3M_SUB(mat3C_f, mat3B_f, mat3C_f);
    printf("      det = %g; size = %g; err = %g\n", det, frob*frob/3,
           CA + ELL_3M_FROB(mat3C_f));
    
  }

  exit(0);
}