Beispiel #1
0
int main(int, char **argv) {
  const double myT = hughes_water_prop.kT; // room temperature in Hartree
  const double R = 2.7;

  Functional x(Identity());
  Grid n(gd);
  n = 0.001*VectorXd::Ones(gd.NxNyNz) + 0.001*(-10*r2(gd)).cwise().exp();

  compare_functionals(NiceSum(), x + kT(), myT, n, 4e-13);

  compare_functionals(NiceQuad(), sqr(x + kT()) - x + 2*kT(), myT, n, 3e-12);

  compare_functionals(NiceSqrt(), sqrt(x) , myT, n, 1e-12);

  compare_functionals(NiceSqrtandMore(), sqrt(x) - x + 2*kT(), myT, n, 1e-12);

  compare_functionals(NiceLog(), log(x), myT, n, 7e-14);

  compare_functionals(NiceLogandSqr(), log(x) + sqr(x), myT, n, 6e-13);

  compare_functionals(NiceLogandSqrandInverse(), log(x) + (sqr(x)-Pow(3)) + Functional(1)/x, myT, n, 3e-10);

  compare_functionals(NiceLogOneMinusX(), log(1-x), myT, n, 1e-12);

  compare_functionals(NiceNbar(R), StepConvolve(R), myT, n, 3e-13);

  compare_functionals(NiceLogOneMinusNbar(R), log(1 - StepConvolve(R)), myT, n, 3e-13);

  Functional n2 = ShellConvolve(R);
  Functional n3 = StepConvolve(R);
  compare_functionals(NiceN2(R), n2, myT, n, 1e-14);

  const double four_pi_r2 = 4*M_PI*R*R;
  Functional one_minus_n3 = 1 - n3;
  Functional phi1 = (-1/four_pi_r2)*n2*log(one_minus_n3);
  compare_functionals(NicePhi1(R), phi1, myT, n, 1e-6);

  const double four_pi_r = 4*M_PI*R;
  Functional n2x = xShellConvolve(R);
  Functional n2y = yShellConvolve(R);
  Functional n2z = zShellConvolve(R);
  Functional phi2 = (sqr(n2) - sqr(n2x) - sqr(n2y) - sqr(n2z))/(four_pi_r*one_minus_n3);

  compare_functionals(NiceN2xsqr(R), sqr(n2x), myT, n, 3e-14);

  compare_functionals(NicePhi2(R), phi2, myT, n, 1e-13);

  Functional phi3 = (n3 + sqr(one_minus_n3)*log(one_minus_n3))/(36*M_PI*sqr(n3)*sqr(one_minus_n3))
    *n2*(sqr(n2) - 3*(sqr(n2x) + sqr(n2y) + sqr(n2z)));
  compare_functionals(NicePhi3(R), phi3, myT, n, 1e-13, 0.001, 1e-14);

  compare_functionals(TensorWhiteBear(R), HardSpheresWB(R), myT, n, 1e-13, 0.0001, 1e-13);

  compare_functionals(gSigmaA_by_hand(R), gSigmaA_automagic(R), myT, n, 1e-13, 0.0001, 1e-13);

  if (errors == 0) printf("\n%s passes!\n", argv[0]);
  else printf("\n%s fails %d tests!\n", argv[0], errors);
  return errors;
}
Beispiel #2
0
void run_with_eta(double eta, const char *name, Functional fhs) {
  // Generates a data file for the pair distribution function, for filling fraction eta
  // and distance of first sphere from wall of z0. Data saved in a table such that the
  // columns are x values and rows are z1 values.
  printf("Now starting run_with_eta with eta = %g name = %s\n",
         eta, name);
  Functional f = OfEffectivePotential(fhs + IdealGas());
  double mu = find_chemical_potential(f, 1, eta/(4*M_PI/3));
  f = OfEffectivePotential(fhs + IdealGas()
                           + ChemicalPotential(mu));
  Lattice lat(Cartesian(width,0,0), Cartesian(0,width,0), Cartesian(0,0,width));
  GridDescription gd(lat, dx);
  Grid potential(gd);
  Grid constraint(gd);
  constraint.Set(notinsphere);
  f = constrain(constraint, f);
  potential = (eta*constraint + 1e-4*eta*VectorXd::Ones(gd.NxNyNz))/(4*M_PI/3);
  potential = -potential.cwise().log();

  const double approx_energy = (fhs + IdealGas() + ChemicalPotential(mu))(1, eta/(4*M_PI/3))*uipow(width,3);
  const double precision = fabs(approx_energy*1e-10);
  //printf("Minimizing to %g absolute precision...\n", precision);
  { // Put mimizer in block so as to free it when we finish minimizing to save memory.
    Minimizer min = Precision(precision,
                              PreconditionedConjugateGradient(f, gd, 1,
                                                              &potential,
                                                              QuadraticLineMinimizer));
    for (int i=0;min.improve_energy(true) && i<100;i++) {
      double peak = peak_memory()/1024.0/1024;
      double current = current_memory()/1024.0/1024;
      printf("Peak memory use is %g M (current is %g M)\n", peak, current);
      fflush(stdout);
    }
    took("Doing the minimization");
  }
  Grid density(gd, EffectivePotentialToDensity()(1, gd, potential));
  Grid gsigma(gd, gSigmaA(1.0)(1, gd, density));
  Grid nA(gd, ShellConvolve(2)(1, density)/(4*M_PI*4));
  Grid n3(gd, StepConvolve(1)(1, density));
  Grid nbar_sokolowski(gd, StepConvolve(1.6)(1, density));
  nbar_sokolowski /= (4.0/3.0*M_PI*ipow(1.6, 3));
  // Create the walls directory if it doesn't exist.
  if (mkdir("papers/pair-correlation/figs/walls", 0777) != 0 && errno != EEXIST) {
    // We failed to create the directory, and it doesn't exist.
    printf("Failed to create papers/pair-correlation/figs/walls: %s",
           strerror(errno));
    exit(1); // fail immediately with error code
  }

  // here you choose the values of z0 to use
  // dx is the resolution at which we compute the density.
  char *plotname = new char[4096];
  for (double z0 = 2.1; z0 < 4.5; z0 += 2.1) {
    // For each z0, we now pick one of our methods for computing the
    // pair distribution function:
    for (int version = 0; version < numplots; version++) {
      sprintf(plotname,
              "papers/pair-correlation/figs/triplet%s-%s-%04.2f-%1.2f.dat",
              name, fun[version], eta, z0);
      FILE *out = fopen(plotname,"w");
      FILE *xfile = fopen("papers/pair-correlation/figs/triplet-x.dat","w");
      FILE *zfile = fopen("papers/pair-correlation/figs/triplet-z.dat","w");
      // the +1 for z0 and z1 are to shift the plot over, so that a sphere touching the wall
      // is at z = 0, to match with the monte carlo data
      const Cartesian r0(0,0,z0);
      for (double x = 0; x < 4; x += dx) {
        for (double z1 = -4; z1 <= 9; z1 += dx) {
          const Cartesian r1(x,0,z1);
          double g2 = pairdists[version](gsigma, density, nA, n3, nbar_sokolowski, r0, r1);
          double n_bulk = (3.0/4.0/M_PI)*eta;
          double g3 = g2*density(r0)*density(r1)/n_bulk/n_bulk;
          fprintf(out, "%g\t", g3);
          fprintf(xfile, "%g\t", x);
          fprintf(zfile, "%g\t", z1);
        }
        fprintf(out, "\n");
        fprintf(xfile, "\n");
        fprintf(zfile, "\n");
      }
      fclose(out);
      fclose(xfile);
      fclose(zfile);
    }
  }
  delete[] plotname;
  took("Dumping the triplet dist plots");
  const double ds = 0.01; // step size to use in path plots, FIXME increase for publication!
  const double delta = .1; //this is the value of radius of the
                           //particle as it moves around the contact
                           //sphere on its path
  char *plotname_path = new char[4096];
  for (int version = 0; version < numplots; version++) {
    sprintf(plotname_path,
            "papers/pair-correlation/figs/triplet%s-path-%s-%04.2f.dat",
            name, fun[version], eta);
    FILE *out_path = fopen(plotname_path, "w");
    if (!out_path) {
      fprintf(stderr, "Unable to create file %s!\n", plotname_path);
      return;
    }

    sprintf(plotname_path,
            "papers/pair-correlation/figs/triplet-back-contact-%s-%04.2f.dat",
            fun[version], eta);
    FILE *out_back = fopen(plotname_path, "w");
    if (!out_back) {
      fprintf(stderr, "Unable to create file %s!\n", plotname_path);
      return;
    }
    fprintf(out_path, "# unused\tg3\tz\tx\n");
    fprintf(out_back, "# unused\tg3\tz\tx\n");

    const Cartesian r0(0,0, 2.0+delta);
    const double max_theta = M_PI*2.0/3;
    for (double z = 7; z >= 2*(2.0 + delta); z-=ds) {
      const Cartesian r1(0,0,z);
      double g2_path = pairdists[version](gsigma, density, nA, n3, nbar_sokolowski, r0, r1);
      double n_bulk = (3.0/4.0/M_PI)*eta;
      double g3 = g2_path*density(r0)*density(r1)/n_bulk/n_bulk;
      fprintf(out_path,"0\t%g\t%g\t%g\n", g3, r1[2], r1[0]);
    }
    for (double z = -7; z <= -(2.0 + delta); z+=ds) {
      const Cartesian r1(0,0,z);
      double g2_path = pairdists[version](gsigma, density, nA, n3, nbar_sokolowski, r0, r1);
      double n_bulk = (3.0/4.0/M_PI)*eta;
      double g3 = g2_path*density(r0)*density(r1)/n_bulk/n_bulk;
      fprintf(out_back,"0\t%g\t%g\t%g\n", g3, r1[2], r1[0]);
    }
    const double dtheta = ds/2;
    for (double theta = 0; theta <= max_theta; theta += dtheta){
      const Cartesian r1((2.0+delta)*sin(theta), 0, (2.0+delta)*(1+cos(theta)));
      double g2_path = pairdists[version](gsigma, density, nA, n3, nbar_sokolowski, r0, r1);
      double n_bulk = (3.0/4.0/M_PI)*eta;
      double g3 = g2_path*density(r0)*density(r1)/n_bulk/n_bulk;
      fprintf(out_path,"0\t%g\t%g\t%g\n", g3, r1[2], r1[0]);
    }
    for (double theta = 0; theta <= max_theta; theta += dtheta){
      const Cartesian r1((2.0+delta)*sin(theta), 0,-(2.0+delta)*cos(theta));
      double g2_path = pairdists[version](gsigma, density, nA, n3, nbar_sokolowski, r0, r1);
      double n_bulk = (3.0/4.0/M_PI)*eta;
      double g3 = g2_path*density(r0)*density(r1)/n_bulk/n_bulk;
      fprintf(out_back,"0\t%g\t%g\t%g\n", g3, r1[2], r1[0]);
    }
    for (double x = (2.0+delta)*sqrt(3)/2; x<=6; x+=ds){
      const Cartesian r1(x, 0, 1.0+delta/2);
      double g2_path = pairdists[version](gsigma, density, nA, n3, nbar_sokolowski, r0, r1);
      double n_bulk = (3.0/4.0/M_PI)*eta;
      double g3 = g2_path*density(r0)*density(r1)/n_bulk/n_bulk;
      fprintf(out_path,"0\t%g\t%g\t%g\n", g3, r1[2], r1[0]);
      fprintf(out_back,"0\t%g\t%g\t%g\n", g3, r1[2], r1[0]);
    }
    fclose(out_path);
    fclose(out_back);
  }
  for (int version = 0; version < numplots; version++) {
    sprintf(plotname_path,
            "papers/pair-correlation/figs/triplet-path-inbetween-%s-%04.2f.dat",
            fun[version], eta);
    FILE *out_path = fopen(plotname_path, "w");
    if (!out_path) {
      fprintf(stderr, "Unable to create file %s!\n", plotname_path);
      return;
    }
    sprintf(plotname_path,
            "papers/pair-correlation/figs/triplet-back-inbetween-%s-%04.2f.dat",
            fun[version], eta);
    FILE *out_back = fopen(plotname_path, "w");
    if (!out_back) {
      fprintf(stderr, "Unable to create file %s!\n", plotname_path);
      return;
    }
    fprintf(out_path, "# unused\tg3\tz\tx\n");
    fprintf(out_back, "# unused\tg3\tz\tx\n");

    const Cartesian r0(0,0, 4.0+2*delta);
    const double max_theta = M_PI;
    for (double z = 11; z >= 3*(2.0 + delta); z-=ds) {
      const Cartesian r1(0,0,z);
      double g2_path = pairdists[version](gsigma, density, nA, n3, nbar_sokolowski, r0, r1);
      double n_bulk = (3.0/4.0/M_PI)*eta;
      double g3 = g2_path*density(r0)*density(r1)/n_bulk/n_bulk;
      fprintf(out_path,"0\t%g\t%g\t%g\n", g3, r1[2], r1[0]);
    }
    for (double z = -10; z <= -(2.0 + delta); z+=ds) {
      const Cartesian r1(0,0,z);
      double g2_path = pairdists[version](gsigma, density, nA, n3, nbar_sokolowski, r0, r1);
      double n_bulk = (3.0/4.0/M_PI)*eta;
      double g3 = g2_path*density(r0)*density(r1)/n_bulk/n_bulk;
      fprintf(out_back,"0\t%g\t%g\t%g\n", g3, r1[2], r1[0]);
    }
    const double dtheta = ds/2;
    for (double theta = 0; theta <= max_theta; theta += dtheta){
      const Cartesian r1((2.0+delta)*sin(theta), 0, (2.0+delta)*(2+cos(theta)));
      double g2_path = pairdists[version](gsigma, density, nA, n3, nbar_sokolowski, r0, r1);
      double n_bulk = (3.0/4.0/M_PI)*eta;
      double g3 = g2_path*density(r0)*density(r1)/n_bulk/n_bulk;
      fprintf(out_path,"0\t%g\t%g\t%g\n", g3, r1[2], r1[0]);
    }
    for (double theta = 0; theta <= max_theta; theta += dtheta){
      const Cartesian r1((2.0+delta)*sin(theta), 0, -(2.0+delta)*cos(theta));
      double g2_path = pairdists[version](gsigma, density, nA, n3, nbar_sokolowski, r0, r1);
      double n_bulk = (3.0/4.0/M_PI)*eta;
      double g3 = g2_path*density(r0)*density(r1)/n_bulk/n_bulk;
      fprintf(out_back,"0\t%g\t%g\t%g\n", g3, r1[2], r1[0]);
    }
    for (double x = 0; x>=-6; x-=ds){
      const Cartesian r1(x, 0, 2.0+delta);
      double g2_path = pairdists[version](gsigma, density, nA, n3, nbar_sokolowski, r0, r1);
      double n_bulk = (3.0/4.0/M_PI)*eta;
      double g3 = g2_path*density(r0)*density(r1)/n_bulk/n_bulk;
      fprintf(out_path,"0\t%g\t%g\t%g\n", g3, r1[2], r1[0]);
      fprintf(out_back,"0\t%g\t%g\t%g\n", g3, r1[2], r1[0]);
    }
    fclose(out_path);
    fclose(out_back);
  }
  delete[] plotname_path;
}
Beispiel #3
0
int main(int, char **argv) {
  const double myT = water_prop.kT; // room temperature in Hartree
  const double R = 2.7;

  Functional x(Identity());
  Grid n(gd);
  n = 0.001*VectorXd::Ones(gd.NxNyNz) + 0.001*(-10*r2(gd)).cwise().exp();

  compare_functionals(Sum(), x + kT, myT, n, 2e-13);

  compare_functionals(Quadratic(), sqr(x + kT) - x + 2*kT, myT, n, 2e-12);

  compare_functionals(Sqrt(), sqrt(x), myT, n, 1e-12);

  compare_functionals(SqrtAndMore(), sqrt(x) - x + 2*kT, myT, n, 1e-12);

  compare_functionals(Log(), log(x), myT, n, 3e-14);

  compare_functionals(LogAndSqr(), log(x) + sqr(x), myT, n, 3e-14);

  compare_functionals(LogAndSqrAndInverse(), log(x) + (sqr(x)-Pow(3)) + Functional(1)/x, myT, n, 3e-10);

  compare_functionals(LogOneMinusX(), log(1-x), myT, n, 1e-12);

  compare_functionals(LogOneMinusNbar(R), log(1-StepConvolve(R)), myT, n, 1e-13);

  compare_functionals(SquareXshell(R), sqr(xShellConvolve(R)), myT, n);

  Functional n2 = ShellConvolve(R);
  Functional n3 = StepConvolve(R);
  compare_functionals(n2_and_n3(R), sqr(n2) + sqr(n3), myT, n, 1e-14);

  const double four_pi_r2 = 4*M_PI*R*R;
  Functional one_minus_n3 = 1 - n3;
  Functional phi1 = (-1/four_pi_r2)*n2*log(one_minus_n3);
  compare_functionals(Phi1(R), phi1, myT, n, 1e-13);

  const double four_pi_r = 4*M_PI*R;
  Functional n2x = xShellConvolve(R);
  Functional n2y = yShellConvolve(R);
  Functional n2z = zShellConvolve(R);
  Functional phi2 = (sqr(n2) - sqr(n2x) - sqr(n2y) - sqr(n2z))/(four_pi_r*one_minus_n3);
  compare_functionals(Phi2(R), phi2, myT, n, 1e-14);

  Functional phi3rf = n2*(sqr(n2) - 3*(sqr(n2x) + sqr(n2y) + sqr(n2z)))/(24*M_PI*sqr(one_minus_n3));
  compare_functionals(Phi3rf(R), phi3rf, myT, n, 1e-13);

  compare_functionals(AlmostRF(R), myT*(phi1 + phi2 + phi3rf), myT, n, 2e-14);

  Functional veff = EffectivePotentialToDensity();
  compare_functionals(SquareVeff(R), sqr(veff), myT, Grid(gd, -myT*n.cwise().log()), 1e-12);

  compare_functionals(AlmostRFnokT(R), phi1 + phi2 + phi3rf, myT, n, 3e-14);

  compare_functionals(AlmostRF(R),
                      (myT*phi1).set_name("phi1") + (myT*phi2).set_name("phi2") + (myT*phi3rf).set_name("phi3"),
                      myT, n, 4e-14);

  compare_functionals(Phi1Veff(R), phi1(veff), myT, Grid(gd, -myT*n.cwise().log()), 1e-13);

  compare_functionals(Phi2Veff(R), phi2(veff), myT, Grid(gd, -myT*n.cwise().log()), 1e-14);

  compare_functionals(Phi3rfVeff(R), phi3rf(veff), myT, Grid(gd, -myT*n.cwise().log()), 1e-13);

  compare_functionals(IdealGasFast(), IdealGasOfVeff, myT, Grid(gd, -myT*n.cwise().log()),
                      1e-12);

  double mu = -1;
  compare_functionals(Phi1plus(R, mu),
                      phi1(veff) + IdealGasOfVeff + ChemicalPotential(mu)(veff),
                      myT, Grid(gd, -myT*n.cwise().log()), 1e-12);

  if (errors == 0) printf("\n%s passes!\n", argv[0]);
  else printf("\n%s fails %d tests!\n", argv[0], errors);
  return errors;
}
Beispiel #4
0
int main(int, char **argv) {
  const double kT = 1e-3;
  Lattice lat(Cartesian(0,5,5), Cartesian(5,0,5), Cartesian(5,5,0));
  Cartesian plotcorner(-5, -5, 0), plotx(10,0,0), ploty(0,10,0);
  int resolution = 200;
  GridDescription gd(lat, resolution, resolution, resolution);
  Grid foo(gd), bar(gd), ref(gd);
  printf("Running Set(gaussian)...\n");
  foo.Set(gaussian);
  const double integrate_foo = Identity().integral(kT, foo);
  printf("Original integrates to %.15g\n", integrate_foo);
  printf("Original Maximum is %g\n", foo.maxCoeff());
  int retval = 0;
  if (integrate_foo < 0) {
    printf("Integral of original is negative (which may throw off tests):  %g\n", integrate_foo);
    retval++;
  }
  //mkdir("tests/vis", 0777);
  //foo.epsNativeSlice("tests/vis/unblurred.eps", plotx, ploty, plotcorner);

  printf("Running Gaussian(10)...\n");
  bar = Gaussian(10)(kT, foo);
  printf("Gaussian(10) integrates to %.15g\n", Identity().integral(kT, bar));
  if (fabs(Identity().integral(kT, bar)/integrate_foo-1) > 1e-6) {
    printf("Error in Gaussian(10) is too large:  %g\n", Identity().integral(kT, bar)/integrate_foo-1);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/gaussian-width-10.eps", plotx, ploty, plotcorner);

  printf("Gaussian(1) integrates to %g\n", Identity().integral(kT, bar));
  printf("Running Gaussian(1)...\n");
  bar = Gaussian(1)(kT, foo);
  if (fabs(Identity().integral(kT, bar)/integrate_foo-1) > 1e-6) {
    printf("Error in Gaussian(1) is too large:  %g\n", Identity().integral(kT, bar)/integrate_foo-1);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/gaussian-width-1.eps", plotx, ploty, plotcorner);

  printf("Running StepConvolve(1)...\n");
  bar = StepConvolve(1)(kT, foo);
  printf("StepConvolve(1) integrates to %.15g\n", Identity().integral(kT, bar));
  printf("StepConvolve(1) Maximum is %g\n", bar.maxCoeff());
  if (fabs(bar.maxCoeff()/integrate_foo-1) > 1e-6) {
    printf("FAIL: Max of StepConvolve(1) is wrong:  %g\n", bar.maxCoeff()/integrate_foo - 1);
    retval++;
  }
  printf("StepConvolve(1) Minimum is %g\n", bar.minCoeff());
  if (bar.minCoeff()/integrate_foo < -1e-9) {
    printf("Min of StepConvolve(1) is wrong:  %g\n", bar.minCoeff()/integrate_foo);
    retval++;
  }
  const double fourpiover3 = 4*M_PI/3;
  if (fabs((Identity().integral(kT, bar)/integrate_foo-fourpiover3)/fourpiover3) > 1e-6) {
    printf("Integral of StepConvolve(1) is wrong:  %g\n",
           (Identity().integral(kT, bar)/integrate_foo-fourpiover3)/fourpiover3);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/step-1.eps", plotx, ploty, plotcorner);

  printf("Running StepConvolve(2)...\n");
  bar = StepConvolve(2)(kT, foo);
  printf("StepConvolve(2) Maximum is %g\n", bar.maxCoeff());
  printf("StepConvolve(2) integrates to %.15g\n", Identity().integral(kT, bar));
  if (fabs((Identity().integral(kT, bar)/integrate_foo-fourpiover3*8)/fourpiover3/8) > 1e-6) {
    printf("Integral of StepConvolve(2) is wrong:  %g\n", (Identity().integral(kT, bar)/integrate_foo-fourpiover3*8)/fourpiover3/8);
    retval++;
  }
  if (fabs((bar.maxCoeff()-integrate_foo)/integrate_foo) > 1e-6) {
    printf("Max of StepConvolve(2) is wrong:  %g\n", (bar.maxCoeff()-integrate_foo)/integrate_foo);
    retval++;
  }
  printf("StepConvolve(2) Minimum is %g\n", bar.minCoeff());
  if (bar.minCoeff()/integrate_foo < -1e-9) {
    printf("Min of StepConvolve(2) is wrong:  %g\n", bar.minCoeff()/integrate_foo);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/step-2.eps", plotx, ploty, plotcorner);

  printf("Running StepConvolve(3)...\n");
  bar = StepConvolve(3)(kT, foo);
  printf("StepConvolve(3) Maximum is %g\n", bar.maxCoeff());
  printf("StepConvolve(3) integrates to %.15g\n", Identity().integral(kT, bar));
  if (fabs((Identity().integral(kT, bar)/integrate_foo-fourpiover3*27)/fourpiover3/27) > 1e-6) {
    printf("Integral of StepConvolve(3) is wrong:  %g\n",
           (Identity().integral(kT, bar)/integrate_foo-fourpiover3*27)/fourpiover3/27);
    retval++;
  }
  if (fabs((bar.maxCoeff()-integrate_foo)/integrate_foo) > 1e-6) {
    printf("Max of StepConvolve(3) is wrong:  %g\n", (bar.maxCoeff()-integrate_foo)/integrate_foo);
    retval++;
  }
  printf("StepConvolve(3) Minimum is %g\n", bar.minCoeff());
  if (fabs(bar.minCoeff()/integrate_foo) < -1e-9) {
    printf("Min of StepConvolve(3) is wrong:  %g\n", bar.minCoeff()/integrate_foo);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/step-3.eps", plotx, ploty, plotcorner);


  const double fourpi = 4*M_PI;
  printf("Running ShellConvolve(1)...\n");
  bar = ShellConvolve(1)(kT, foo);
  printf("ShellConvolve(1) integrates to %.15g\n", Identity().integral(kT, bar));
  printf("ShellConvolve(1) Maximum is %g\n", bar.maxCoeff());
  if (fabs((Identity().integral(kT, bar)/integrate_foo-fourpi)/fourpi) > 1e-6) {
    printf("Integral of ShellConvolve(1) is wrong:  %g\n",
           (Identity().integral(kT, bar)/integrate_foo-fourpi)/fourpi);
    retval++;
  }
  printf("ShellConvolve(1) Minimum is %g\n", bar.minCoeff());
  if (bar.minCoeff()/integrate_foo < -1e-9) {
    printf("Min of ShellConvolve(1) is wrong:  %g\n", bar.minCoeff()/integrate_foo);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/shell-1.eps", plotx, ploty, plotcorner);


  printf("Running ShellPrimeConvolve(1)...\n");
  bar = ShellPrimeConvolve(1)(kT, foo);
  printf("ShellPrimeConvolve(1) integrates to %.15g\n", Identity().integral(kT, bar));
  printf("ShellPrimeConvolve(1) Maximum is %g\n", bar.maxCoeff());
  //bar.epsNativeSlice("tests/vis/shellPrime-1.eps", plotx, ploty, plotcorner);

  printf("Running ShellConvolve(3)...\n");
  bar = ShellConvolve(3)(kT, foo);
  printf("ShellConvolve(3) Maximum is %g\n", bar.maxCoeff());
  printf("ShellConvolve(3) integrates to %.15g\n", Identity().integral(kT, bar));
  if (fabs((Identity().integral(kT, bar)/integrate_foo-fourpi*9)/fourpi/9) > 1e-6) {
    printf("Integral of ShellConvolve(3) is wrong:  %g\n",
           (Identity().integral(kT, bar)/integrate_foo-fourpi*9)/fourpi/9);
    retval++;
  }
  printf("ShellConvolve(3) Minimum is %g\n", bar.minCoeff());
  if (bar.minCoeff()/integrate_foo < -1e-9) {
    printf("Min of ShellConvolve(3) is wrong:  %g\n", bar.minCoeff()/integrate_foo);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/shell-3.eps", plotx, ploty, plotcorner);

  printf("Running yShellConvolve(1)...\n");
  bar = yShellConvolve(1)(kT, foo);
  printf("yShellConvolve(1) integrates to %.15g\n", Identity().integral(kT, bar));
  printf("yShellConvolve(1) Maximum is %g\n", bar.maxCoeff());
  printf("yShellConvolve(1) Minimum is %g\n", bar.minCoeff());
  if (fabs(Identity().integral(kT, bar)/integrate_foo) > 1e-6) {
    printf("Integral of yShellConvolve(1) is wrong:  %g\n",
           Identity().integral(kT, bar)/integrate_foo-fourpi);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/y-shell-1.eps", plotx, ploty, plotcorner);
  Functional ysh = yShellConvolve(1), sh = ShellConvolve(1);
  {
    Grid scalarsh(gd, ShellConvolve(1)(kT, foo));
    if (bar.maxCoeff() > scalarsh.maxCoeff()) {
      printf("FAIL: max of vector shell greater than scalar shell!\n");
      retval++;
    }
    if (-bar.minCoeff() > scalarsh.maxCoeff()) {
      printf("FAIL: min of vector shell greater in magnitude than scalar shell!\n");
      retval++;
    }
  }

  printf("Running xShellConvolve(3)...\n");
  ref = ShellConvolve(3)(kT, foo);
  bar = xShellConvolve(3)(kT, foo);
  printf("xShellConvolve(3) Maximum is %g\n", bar.maxCoeff());
  printf("xShellConvolve(3) integrates to %.15g\n", Identity().integral(kT, bar));
  if (fabs(Identity().integral(kT, bar)/integrate_foo) > 1e-6) {
    printf("Integral of xShellConvolve(3) is wrong:  %g\n",
           Identity().integral(kT, bar)/integrate_foo);
    retval++;
  }
  double mymax = ref.maxCoeff();
  if (fabs(bar.maxCoeff() - mymax)/mymax > 2e-3) {
    printf("problem with xShellConvolve max: %g != %g (error of %g)\n",
           bar.maxCoeff(), mymax, (bar.maxCoeff() - mymax)/mymax);
    retval++;
    exit(1);
  }
  if (fabs((bar.minCoeff() + mymax)/mymax) > 2e-3) {
    printf("problem with xShellConvolve min: %g != minus %g (error of %g)\n",
           bar.minCoeff(), mymax, (bar.minCoeff() + mymax)/mymax);
    retval++;
    exit(1);
  }
  //bar.epsNativeSlice("tests/vis/x-shell-3.eps", plotx, ploty, plotcorner);
  for (int i=0;i<gd.NxNyNz;i++) {
    if ((fabs(bar[i]) - fabs(ref[i]))/mymax > 1e-11) {
      printf("FAIL: x shell is bigger in magnitude than shell by %g out of %g compared with %g!\n",
             fabs(bar[i]) - fabs(ref[i]), fabs(ref[i]), mymax);
      retval++;
    }
  }

  printf("Running VectorDensityX(3)...\n");
  ref = n2Density(3)(kT, foo);
  bar = VectorDensityX(3)(kT, foo);
  printf("VectorDensityX(3) Maximum is %g\n", bar.maxCoeff());
  printf("VectorDensityX(3) integrates to %.15g\n", Identity().integral(kT, bar));
  if (fabs(Identity().integral(kT, bar)/integrate_foo) > 1e-6) {
    printf("Integral of VectorDensityX(3) is wrong:  %g\n",
           Identity().integral(kT, bar)/integrate_foo);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/x-vector-3.eps", plotx, ploty, plotcorner);
  mymax = ref.maxCoeff();
  if (fabs(bar.maxCoeff() - mymax)/mymax > 2e-3) {
    printf("problem with VectorDensityX max: %g != %g (error of %g)\n",
           bar.maxCoeff(), mymax, (bar.maxCoeff() - mymax)/mymax);
    retval++;
    exit(1);
  }
  if (fabs((bar.minCoeff() + mymax)/mymax) > 2e-3) {
    printf("problem with VectorDensityX min: %g != minus %g (error of %g)\n",
           bar.minCoeff(), mymax, (bar.minCoeff() + mymax)/mymax);
    retval++;
    exit(1);
  }
  for (int i=0;i<gd.NxNyNz;i++) {
    if ((fabs(bar[i]) - fabs(ref[i]))/mymax > 1e-11) {
      printf("FAIL: x shell is bigger in magnitude than shell by %g out of %g compared with %g!\n",
             fabs(bar[i]) - fabs(ref[i]), fabs(ref[i]), mymax);
      retval++;
    }
  }

  printf("Running xyShellConvolve(1)...\n");
  ref = xShellConvolve(1)(kT, foo);
  bar = xyShellConvolve(1)(kT, foo);
  printf("xyShellConvolve(1) integrates to %.15g\n", Identity().integral(kT, bar));
  printf("xyShellConvolve(1) Maximum is %g\n", bar.maxCoeff());
  if (fabs(Identity().integral(kT, bar)/integrate_foo) > 1e-6) {
    printf("Integral of xyShellConvolve(1) is wrong:  %g\n",
           Identity().integral(kT, bar)/integrate_foo-fourpi);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/xy-shell-1.eps", plotx, ploty, plotcorner);
  mymax = ref.maxCoeff();
  for (int i=0;i<gd.NxNyNz;i++) {
    if ((fabs(bar[i]) - fabs(ref[i]))/mymax > 1e-11) {
      printf("FAIL: xy shell is bigger in magnitude than x shell by %g out of %g!\n",
             fabs(bar[i]) - fabs(ref[i]), fabs(ref[i]));
      retval++;
    }
  }

  printf("Running xxShellConvolve(2)...\n");
  ref = xShellConvolve(2)(kT, foo).cwise().abs() + 1./3*ShellConvolve(2)(kT, foo);
  bar = xxShellConvolve(2)(kT, foo);
  printf("xxShellConvolve(2) integrates to %.15g\n", Identity().integral(kT, bar));
  printf("xxShellConvolve(2) Maximum is %g\n", bar.maxCoeff());
  if (fabs(Identity().integral(kT, bar)/integrate_foo) > 1e-14) {
    printf("FAIL: Integral of xxShellConvolve(2) is wrong:  %g\n",
           Identity().integral(kT, bar)/integrate_foo);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/xx-shell-2.eps", plotx, ploty, plotcorner);
  //bar.epsNativeSlice("tests/vis/xx-shell-2.eps", Cartesian(0,10,0), Cartesian(0,0,10), Cartesian(0,0,0));
  mymax = ref.maxCoeff();
  for (int i=0;i<gd.NxNyNz;i++) {
    if ((fabs(bar[i]) - fabs(ref[i]))/mymax > 1e-12) {
      printf("FAIL: xx shell is bigger in magnitude than x shell by %g out of %g compared with %g!\n",
             fabs(bar[i]) - fabs(ref[i]), fabs(ref[i]), mymax);
      retval++;
    }
  }

  printf("Running TensorDensityXX(2)...\n");
  ref = VectorDensityX(2)(kT, foo).cwise().abs() + 1./3*n2Density(2)(kT, foo);
  bar = TensorDensityXX(2)(kT, foo);
  printf("TensorDensityXX(2) integrates to %.15g\n", Identity().integral(kT, bar));
  printf("TensorDensityXX(2) Maximum is %g\n", bar.maxCoeff());
  if (fabs(Identity().integral(kT, bar)/integrate_foo) > 1e-14) {
    printf("FAIL: Integral of xxShellConvolve(2) is wrong:  %g\n",
           Identity().integral(kT, bar)/integrate_foo);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/xx-tensor-2.eps", plotx, ploty, plotcorner);
  mymax = ref.maxCoeff();
  double shellmax = n2Density(3)(kT, foo).maxCoeff();
  if (fabs(bar.maxCoeff() - 2*shellmax/3)/(2*shellmax/3) > 1e-2) {
    printf("problem with TensorDensityXX max: %g != %g (error of %g)\n",
           bar.maxCoeff(), 2*shellmax/3, (bar.maxCoeff() - 2*shellmax/3)/(2*shellmax/3));
    retval++;
    exit(1);
  }
  for (int i=0;i<gd.NxNyNz;i++) {
    if ((fabs(bar[i]) - fabs(ref[i]))/mymax > 1e-12) {
      printf("FAIL: xx shell is bigger in magnitude than x shell by %g out of %g compared with %g!\n",
             fabs(bar[i]) - fabs(ref[i]), fabs(ref[i]), mymax);
      retval++;
    }
  }
  printf("Running zxShellConvolve(3)...\n");
  Functional zxsh = zxShellConvolve(3);
  bar = zxsh(kT, foo);
  printf("zxShellConvolve(3) Maximum is %g\n", bar.maxCoeff());
  printf("zxShellConvolve(3) integrates to %.15g\n", Identity().integral(kT, bar));
  if (fabs(Identity().integral(kT, bar)/integrate_foo) > 1e-6) {
    printf("Integral of zxShellConvolve(3) is wrong:  %g\n",
           Identity().integral(kT, bar)/integrate_foo);
    retval++;
  }
  //bar.epsNativeSlice("tests/vis/zx-shell-3.eps", plotx, ploty, Cartesian(-5,-5,0.5));

  if (retval == 0) printf("\n%s passes!\n", argv[0]);
  else printf("\n%s fails %d tests!\n", argv[0], retval);
  return retval;
}