Пример #1
0
/* evaluate the integrals for the given m[] using the cached values in vc,
   storing the integrals in val[], the error estimate in err[], and the
   dimension to subdivide next (the largest error contribution) in *mi */
static void eval_integral(valcache vc, const unsigned *m, 
			  unsigned fdim, unsigned dim, double V,
			  unsigned *mi, double *val, double *err, double *val1)
{
     double maxerr = 0;
     unsigned i, j;
     
     evals(vc, m, dim, fdim, dim, V, val);

     /* error estimates along each dimension by comparing val with
	lower-order rule in that dimension; overall (conservative)
	error estimate from maximum error of lower-order rules. */
     memset(err, 0, sizeof(double) * fdim);
     *mi = 0;
     for (i = 0; i < dim; ++i) {
	  double emax = 0;
	  evals(vc, m, i, fdim, dim, V, val1);
	  for (j = 0; j < fdim; ++j) {
	       double e = fabs(val[j] - val1[j]);
	       if (e > emax) emax = e;
	       if (e > err[j]) err[j] = e;
	  }
	  if (emax > maxerr) {
	       maxerr = emax;
	       *mi = i;
	  }
     }
     /* printf("eval: %g +/- %g (dim %u)\n", val[0], err[0], *mi); */
}
Пример #2
0
 vec PolyTrajectoryGenerator::evaluateByCoefficientsMultiple(vec x, int sampleCount, vec coeff) {
     int coeffDegree = this->getBasisFunctionCount();
     vec evals(sampleCount);
     for(int i = 0; i < sampleCount; ++i) {
         evals(i) = evaluateByCoefficientsSingle(x(i), coeff);
     }
     return evals;
 }
Пример #3
0
tensor2D eigenVectors(const tensor2D& t)
{
    vector2D evals(eigenValues(t));

    tensor2D evs
    (
        eigenVector(t, evals.x()),
        eigenVector(t, evals.y())
    );

    return evs;
}
Пример #4
0
tensor eigenVectors(const symmTensor& t)
{
    vector evals(eigenValues(t));

    tensor evs
    (
        eigenVector(t, evals.x()),
        eigenVector(t, evals.y()),
        eigenVector(t, evals.z())
    );

    return evs;
}
Пример #5
0
sexpr import(const std::vector<sexpr>& a, environment* env)
{
	if (a.size() < 1)
		throw std::invalid_argument("<import>: Wrong number of arguments");
	auto path = a[0].get<lisp_string>();
	std::ifstream file(path);
	if (!file)
		throw std::invalid_argument("<import>: File not found: " + path);
	std::regex reg("([;]{2,}.*$)");
	std::string line;
	std::string content;
	while (std::getline(file, line)) {
		content += std::regex_replace(line, reg, "");
	}
	return evals(parse(tokenize(content)), env);
}
Пример #6
0
Vector3f FlyingLayer::RotationMatrixToVector(const Matrix3x3f& rotationMatrix) const {
  static const float epsilon = 1e-6;
  const float cs = (rotationMatrix.trace() - 1.0)*0.5;
  if (cs > 1.0 - epsilon) {
    return Vector3f::Zero();
  } else if (cs < epsilon - 1.0) {
    Eigen::SelfAdjointEigenSolver<Matrix3x3f> evals(rotationMatrix, Eigen::ComputeEigenvectors);
    Vector3f rotVector = evals.eigenvectors().col(2).transpose();
    return rotVector.normalized()*M_PI;
  } else {
    const float sn = std::sqrt(1.0 - cs*cs);
    const float angle = std::acos(cs);
    const float multiplier = angle * 0.5 / sn;
    return Vector3f((rotationMatrix(2, 1) - rotationMatrix(1, 2))*multiplier,
                    (rotationMatrix(0, 2) - rotationMatrix(2, 0))*multiplier,
                    (rotationMatrix(1, 0) - rotationMatrix(0, 1))*multiplier);
  }
}
Пример #7
0
EigenTypes::Vector3f MathUtility::RotationMatrixToVector(const EigenTypes::Matrix3x3f& rotationMatrix) {
  static const float epsilon = 1e-6f;
  const float cs = (rotationMatrix.trace() - 1.0f)*0.5f;
  if (cs > 1.0f - epsilon) {
    return EigenTypes::Vector3f::Zero();
  } else if (cs < epsilon - 1.0f) {
    Eigen::SelfAdjointEigenSolver<EigenTypes::Matrix3x3f> evals(rotationMatrix, Eigen::ComputeEigenvectors);
    EigenTypes::Vector3f rotVector = evals.eigenvectors().col(2).transpose();
    return rotVector.normalized()*(float)M_PI;
  } else {
    const float sn = std::sqrt(1.0f - cs*cs);
    const float angle = std::acos(cs);
    const float multiplier = angle * 0.5f / sn;
    return EigenTypes::Vector3f((rotationMatrix(2, 1) - rotationMatrix(1, 2))*multiplier,
                    (rotationMatrix(0, 2) - rotationMatrix(2, 0))*multiplier,
                    (rotationMatrix(1, 0) - rotationMatrix(0, 1))*multiplier);
  }
}
Пример #8
0
/**
 * \ingroup eigen
 * Eigenvectors
 * \param m \f$m\f$
 * \return a variable matrix with the
 *         eigenvectors of \f$m\f$ stored in its columns.
 */
dmatrix eigenvectors(const dmatrix &m)
{
   if (m.rowsize() != m.colsize())
   {
      cerr <<
	 "error -- non square matrix passed to dmatrix eigenvectors(const dmatrix& m)\n";
      ad_exit(1);
   }

   int rmin = m.rowmin();
   int rmax = m.rowmax();

   dmatrix evecs(rmin, rmax, rmin, rmax);
   dvector evals(rmin, rmax);

   eigens(m, evecs, evals);

   return evecs;
}
Пример #9
0
vector<EquityResult> ShowdownEnumerator::calculateEquity (const vector<CardDistribution>& dists,
                                                          const CardSet& board,
                                                          boost::shared_ptr<PokerHandEvaluator> peval) const
{
    if (peval.get() == NULL)
        throw runtime_error("ShowdownEnumerator, null evaluator");
    assert(dists.size() > 1);
    const size_t ndists = dists.size();
    vector<EquityResult> results(ndists, EquityResult());
    size_t handsize = peval->handSize();

    // the dsizes vector is a list of the sizes of the player hand
    // distributions
    vector<size_t> dsizes;
    for (size_t i=0; i<ndists; i++)
    {
        assert(dists[i].size() > 0);
        dsizes.push_back (dists[i].size());
    }

    // need to figure out the board stuff, we'll be rolling the board into
    // the partitions to make enumeration easier down the line.
    size_t nboards = 0;
    size_t boardsize = peval->boardSize();
    if (boardsize > 0)
        nboards++;

    // for the most part, these are allocated here to avoid contant stack
    // reallocation as we cycle through the inner loops
    SimpleDeck deck;
    CardSet dead;
    double weight;
    vector<CardSet>             ehands         (ndists+nboards);
    vector<size_t>              parts          (ndists+nboards);
    vector<CardSet>             cardPartitions (ndists+nboards);
    vector<PokerHandEvaluation> evals          (ndists);         // NO BOARD

    // copy quickness
    CardSet * copydest = &ehands[0];
    CardSet * copysrc = &cardPartitions[0];
    size_t ncopy = (ndists+nboards)*sizeof(CardSet);
    Odometer o(dsizes);
    do
    {
        // colect all the cards being used by the players, skip out in the
        // case of card duplication
        bool disjoint = true;
        dead.clear ();
        weight = 1.0;
        for (size_t i=0; i<ndists+nboards; i++)
        {
            if (i<ndists)
            {
                cardPartitions[i] = dists[i][o[i]];
                parts[i]          = handsize-cardPartitions[i].size();
                weight           *= dists[i][cardPartitions[i]];
            }
            else
            {
                // this allows us to have board distributions in the future
                cardPartitions[i] = board;
                parts[i]          = boardsize-cardPartitions[i].size();
            }
            disjoint = disjoint && dead.disjoint(cardPartitions[i]);
            dead |= cardPartitions[i];
        }

        if (disjoint)
        {
            deck.reset ();
            deck.remove (dead);
            PartitionEnumerator2 pe(deck.size(), parts);
            do
            {
                // we use memcpy here for a little speed bonus
                memcpy (copydest, copysrc, ncopy);
                for (size_t p=0; p<ndists+nboards; p++)
                    ehands[p] |= deck.peek(pe.getMask (p));

                // TODO: do we need this if/else, or can we just use the if
                // clause? A: need to rework tracking of whether a board is needed
                if (nboards > 0)
                    peval->evaluateShowdown (ehands, ehands[ndists], evals, results, weight);
                else
                    peval->evaluateShowdown (ehands, board, evals, results, weight);
            }
            while (pe.next ());
        }
    }
    while (o.next ());

    return results;
}
Пример #10
0
void
MultiAppProjectionTransfer::execute()
{
  _console << "Beginning projection transfer " << name() << std::endl;

  getAppInfo();

  ////////////////////
  // We are going to project the solutions by solving some linear systems.  In
  // order to assemble the systems, we need to evaluate the "from" domain
  // solutions at quadrature points in the "to" domain.  Some parallel
  // communication is necessary because each processor doesn't necessarily have
  // all the "from" information it needs to set its "to" values.  We don't want
  // to use a bunch of big all-to-all broadcasts, so we'll use bounding boxes to
  // figure out which processors have the information we need and only
  // communicate with those processors.
  //
  // Each processor will
  // 1. Check its local quadrature points in the "to" domains to see which
  //    "from" domains they might be in.
  // 2. Send quadrature points to the processors with "from" domains that might
  //    contain those points.
  // 3. Recieve quadrature points from other processors, evaluate its mesh
  //    functions at those points, and send the values back to the proper
  //    processor
  // 4. Recieve mesh function evaluations from all relevant processors and
  //    decide which one to use at every quadrature point (the lowest global app
  //    index always wins)
  // 5. And use the mesh function evaluations to assemble and solve an L2
  //    projection system on its local elements.
  ////////////////////

  ////////////////////
  // For every combination of global "from" problem and local "to" problem, find
  // which "from" bounding boxes overlap with which "to" elements.  Keep track
  // of which processors own bounding boxes that overlap with which elements.
  // Build vectors of quadrature points to send to other processors for mesh
  // function evaluations.
  ////////////////////

  // Get the bounding boxes for the "from" domains.
  std::vector<MeshTools::BoundingBox> bboxes = getFromBoundingBoxes();

  // Figure out how many "from" domains each processor owns.
  std::vector<unsigned int> froms_per_proc = getFromsPerProc();

  std::vector<std::vector<Point> > outgoing_qps(n_processors());
  std::vector<std::map<std::pair<unsigned int, unsigned int>, unsigned int> > element_index_map(n_processors());
  // element_index_map[i_to, element_id] = index
  // outgoing_qps[index] is the first quadrature point in element

  if (! _qps_cached)
  {
    for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
    {
      MeshBase & to_mesh = _to_meshes[i_to]->getMesh();

      LinearImplicitSystem & system = * _proj_sys[i_to];

      FEType fe_type = system.variable_type(0);
      std::unique_ptr<FEBase> fe(FEBase::build(to_mesh.mesh_dimension(), fe_type));
      QGauss qrule(to_mesh.mesh_dimension(), fe_type.default_quadrature_order());
      fe->attach_quadrature_rule(&qrule);
      const std::vector<Point> & xyz = fe->get_xyz();

      MeshBase::const_element_iterator       el     = to_mesh.local_elements_begin();
      const MeshBase::const_element_iterator end_el = to_mesh.local_elements_end();

      unsigned int from0 = 0;
      for (processor_id_type i_proc = 0;
           i_proc < n_processors();
           from0 += froms_per_proc[i_proc], i_proc++)
      {
        for (el = to_mesh.local_elements_begin(); el != end_el; el++)
        {
          const Elem* elem = *el;
          fe->reinit (elem);

          bool qp_hit = false;
          for (unsigned int i_from = 0;
               i_from < froms_per_proc[i_proc] && ! qp_hit; i_from++)
          {
            for (unsigned int qp = 0;
                 qp < qrule.n_points() && ! qp_hit; qp ++)
            {
              Point qpt = xyz[qp];
              if (bboxes[from0 + i_from].contains_point(qpt + _to_positions[i_to]))
                qp_hit = true;
            }
          }

          if (qp_hit)
          {
            // The selected processor's bounding box contains at least one
            // quadrature point from this element.  Send all qps from this element
            // and remember where they are in the array using the map.
            std::pair<unsigned int, unsigned int> key(i_to, elem->id());
            element_index_map[i_proc][key] = outgoing_qps[i_proc].size();
            for (unsigned int qp = 0; qp < qrule.n_points(); qp ++)
            {
              Point qpt = xyz[qp];
              outgoing_qps[i_proc].push_back(qpt + _to_positions[i_to]);
            }
          }
        }
      }
    }

    if (_fixed_meshes)
      _cached_index_map = element_index_map;
  }
  else
  {
    element_index_map = _cached_index_map;
  }

  ////////////////////
  // Request quadrature point evaluations from other processors and handle
  // requests sent to this processor.
  ////////////////////

  // Non-blocking send quadrature points to other processors.
  std::vector<Parallel::Request> send_qps(n_processors());
  if (! _qps_cached)
    for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
      if (i_proc != processor_id())
        _communicator.send(i_proc, outgoing_qps[i_proc], send_qps[i_proc]);

  // Get the local bounding boxes.
  std::vector<MeshTools::BoundingBox> local_bboxes(froms_per_proc[processor_id()]);
  {
    // Find the index to the first of this processor's local bounding boxes.
    unsigned int local_start = 0;
    for (processor_id_type i_proc = 0;
         i_proc < n_processors() && i_proc != processor_id();
         i_proc++)
      local_start += froms_per_proc[i_proc];

    // Extract the local bounding boxes.
    for (unsigned int i_from = 0; i_from < froms_per_proc[processor_id()]; i_from++)
      local_bboxes[i_from] = bboxes[local_start + i_from];
  }

  // Setup the local mesh functions.
  std::vector<MeshFunction *> local_meshfuns(froms_per_proc[processor_id()], NULL);
  for (unsigned int i_from = 0; i_from < _from_problems.size(); i_from++)
  {
    FEProblemBase & from_problem = *_from_problems[i_from];
    MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);
    System & from_sys = from_var.sys().system();
    unsigned int from_var_num = from_sys.variable_number(from_var.name());

    MeshFunction * from_func = new MeshFunction(from_problem.es(),
         *from_sys.current_local_solution, from_sys.get_dof_map(), from_var_num);
    from_func->init(Trees::ELEMENTS);
    from_func->enable_out_of_mesh_mode(OutOfMeshValue);
    local_meshfuns[i_from] = from_func;
  }

  // Recieve quadrature points from other processors, evaluate mesh frunctions
  // at those points, and send the values back.
  std::vector<Parallel::Request> send_evals(n_processors());
  std::vector<Parallel::Request> send_ids(n_processors());
  std::vector<std::vector<Real> > outgoing_evals(n_processors());
  std::vector<std::vector<unsigned int> > outgoing_ids(n_processors());
  std::vector<std::vector<Real> > incoming_evals(n_processors());
  std::vector<std::vector<unsigned int> > incoming_app_ids(n_processors());
  for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
  {
    // Use the cached qps if they're available.
    std::vector<Point> incoming_qps;
    if (! _qps_cached)
    {
      if (i_proc == processor_id())
        incoming_qps = outgoing_qps[i_proc];
      else
        _communicator.receive(i_proc, incoming_qps);
      // Cache these qps for later if _fixed_meshes
      if (_fixed_meshes)
        _cached_qps[i_proc] = incoming_qps;
    }
    else
    {
      incoming_qps = _cached_qps[i_proc];
    }

    outgoing_evals[i_proc].resize(incoming_qps.size(), OutOfMeshValue);
    if (_direction == FROM_MULTIAPP)
      outgoing_ids[i_proc].resize(incoming_qps.size(), libMesh::invalid_uint);
    for (unsigned int qp = 0; qp < incoming_qps.size(); qp++)
    {
      Point qpt = incoming_qps[qp];

      // Loop until we've found the lowest-ranked app that actually contains
      // the quadrature point.
      for (unsigned int i_from = 0; i_from < _from_problems.size(); i_from++)
      {
        if (local_bboxes[i_from].contains_point(qpt))
        {
          outgoing_evals[i_proc][qp] = (* local_meshfuns[i_from])(qpt - _from_positions[i_from]);
          if (_direction == FROM_MULTIAPP)
            outgoing_ids[i_proc][qp] = _local2global_map[i_from];
        }
      }
    }

    if (i_proc == processor_id())
    {
      incoming_evals[i_proc] = outgoing_evals[i_proc];
      if (_direction == FROM_MULTIAPP)
        incoming_app_ids[i_proc] = outgoing_ids[i_proc];
    }
    else
    {
      _communicator.send(i_proc, outgoing_evals[i_proc], send_evals[i_proc]);
      if (_direction == FROM_MULTIAPP)
        _communicator.send(i_proc, outgoing_ids[i_proc], send_ids[i_proc]);
    }
  }

  ////////////////////
  // Gather all of the qp evaluations and pick out the best ones for each qp.
  ////////////////////
  for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
  {
    if (i_proc == processor_id())
      continue;
    _communicator.receive(i_proc, incoming_evals[i_proc]);
    if (_direction == FROM_MULTIAPP)
      _communicator.receive(i_proc, incoming_app_ids[i_proc]);
  }

  std::vector<std::vector<Real> > final_evals(_to_problems.size());
  std::vector<std::map<unsigned int, unsigned int> > trimmed_element_maps(_to_problems.size());

  for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
  {
    MeshBase & to_mesh = _to_meshes[i_to]->getMesh();
    LinearImplicitSystem & system = * _proj_sys[i_to];

    FEType fe_type = system.variable_type(0);
    std::unique_ptr<FEBase> fe(FEBase::build(to_mesh.mesh_dimension(), fe_type));
    QGauss qrule(to_mesh.mesh_dimension(), fe_type.default_quadrature_order());
    fe->attach_quadrature_rule(&qrule);
    const std::vector<Point> & xyz = fe->get_xyz();

    MeshBase::const_element_iterator       el     = to_mesh.local_elements_begin();
    const MeshBase::const_element_iterator end_el = to_mesh.local_elements_end();

    for (el = to_mesh.active_local_elements_begin(); el != end_el; el++)
    {
      const Elem* elem = *el;
      fe->reinit (elem);

      bool element_is_evaled = false;
      std::vector<Real> evals(qrule.n_points(), 0.);

      for (unsigned int qp = 0; qp < qrule.n_points(); qp++)
      {
        Point qpt = xyz[qp];

        unsigned int lowest_app_rank = libMesh::invalid_uint;
        for (unsigned int i_proc = 0; i_proc < n_processors(); i_proc++)
        {
          // Ignore the selected processor if the element wasn't found in it's
          // bounding box.
          std::map<std::pair<unsigned int, unsigned int>, unsigned int> & map = element_index_map[i_proc];
          std::pair<unsigned int, unsigned int> key(i_to, elem->id());
          if (map.find(key) == map.end())
            continue;
          unsigned int qp0 = map[key];

          // Ignore the selected processor if it's app has a higher rank than the
          // previously found lowest app rank.
          if (_direction == FROM_MULTIAPP)
            if (incoming_app_ids[i_proc][qp0 + qp] >= lowest_app_rank)
              continue;

          // Ignore the selected processor if the qp was actually outside the
          // processor's subapp's mesh.
          if (incoming_evals[i_proc][qp0 + qp] == OutOfMeshValue)
            continue;

          // This is the best meshfunction evaluation so far, save it.
          element_is_evaled = true;
          evals[qp] = incoming_evals[i_proc][qp0 + qp];
        }
      }

      // If we found good evaluations for any of the qps in this element, save
      // those evaluations for later.
      if (element_is_evaled)
      {
        trimmed_element_maps[i_to][elem->id()] = final_evals[i_to].size();
        for (unsigned int qp = 0; qp < qrule.n_points(); qp++)
          final_evals[i_to].push_back(evals[qp]);
      }
    }
  }

  ////////////////////
  // We now have just one or zero mesh function values at all of our local
  // quadrature points.  Stash those values (and a map linking them to element
  // ids) in the equation systems parameters and project the solution.
  ////////////////////

  for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
  {
    _to_es[i_to]->parameters.set<std::vector<Real>*>("final_evals") = & final_evals[i_to];
    _to_es[i_to]->parameters.set<std::map<unsigned int, unsigned int>*>("element_map") = & trimmed_element_maps[i_to];
    projectSolution(i_to);
    _to_es[i_to]->parameters.set<std::vector<Real>*>("final_evals") = NULL;
    _to_es[i_to]->parameters.set<std::map<unsigned int, unsigned int>*>("element_map") = NULL;
  }

  for (unsigned int i = 0; i < _from_problems.size(); i++)
    delete local_meshfuns[i];


  // Make sure all our sends succeeded.
  for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
  {
    if (i_proc == processor_id())
      continue;
    if (! _qps_cached)
      send_qps[i_proc].wait();
    send_evals[i_proc].wait();
    if (_direction == FROM_MULTIAPP)
      send_ids[i_proc].wait();
  }

  if (_fixed_meshes)
    _qps_cached = true;

  _console << "Finished projection transfer " << name() << std::endl;
}
Пример #11
0
void exec(const char *str, char *err)
{
	// this function executes a given instruction.
	// all important functions are done from here.

	int eval(const char *str);
	void * evals(const char *str, const char data_type);
	strcpy(err,"");  /* empty error container string */
	char *exp = NULL; /* string containing evaluation expression */
	char *asgn = NULL;  /* string containing assignment variable name */
	char data_type = '\0'; /* data type of variable to evaluate */

	/* assignment analysis & error handling */
	if((asgn=(char *)(malloc(sizeof(char)*
	(strlen(str)+1))))==NULL) allocerr(); *asgn='\0';
	if(prechar(asgn,str,"=")=='=') /* check for = operator */
	{
		/* ok, it is a variable assignment */
		strtrm(asgn,' ','S');

		if((*asgn==0)||(strlen(asgn)==0))
		{
			/* error: assignment string is empty */
			strcpy(err,"Assignment variable is not specified.");
			free(asgn);
			return;
		}
		else  /* assignment string is NOT empty */
		{
			char isid[2] = {'\0','\0'};
			/* check identifier validity*/
			isid[0] = id_check(asgn);
			if(isid[0]!=0)  /* error: is not an identifier */
			{
				if(isid[0]==1)  /* error: var name starts with a number */
				{
					strcpy(err,"Variable name cannot start with a number.");
				}
				else if(isid[0]==32)  /* error: var name contains spaces */
				{
					strcpy(err,"Variable name cannot contain spaces.");
				}
				else  /* error: var name has illegal chars*/
				{
					strcpy(err,"Variable name cannot contain [");
					strcat(err,isid);
					strcat(err,"] character.");
				}
				free(asgn);
				return;
			}
			else  /* success: assignment string is valid */
			{
				/* allocate string exp */
				if((exp=(char *)(malloc(sizeof(char)*
				(strlen(str)+1))))==NULL) allocerr(); *exp='\0';
				/* now split the equation to get the exp. */
				postchar(exp,str,"=");
				strtrm(exp,' ','S');
				// find out the data type of the assignment
				// variable & store it in char data_type
			} 

		}
	}
	else	/* there is no assigment involved */
	{
		/* allocate string exp */
		if((exp=(char *)(malloc(sizeof(char)*
		(strlen(str)+1))))==NULL) allocerr(); *exp='\0';
		strcpy(exp,str);
		strtrm(exp,' ','S');
		/* de-allocate asgn */
		free(asgn);
		asgn = NULL;
	}

	/* variable assignment */
	if(asgn!=NULL)
	{
		/* possible variable data types */
		long *i = NULL;            // <- (int)
		short *n = NULL;           // <- (int-)
		char *c = NULL;            // <- (chr)
		double *d = NULL;          // <- (real)
		float *f = NULL;           // <- (real-)
		unsigned long *j = NULL;   // <- (int+)
		unsigned short *m = NULL;  // <- (int-+)
		unsigned char *a = NULL;   // <- (chr+)

		switch(data_type)
		{
		case 'i':
			break;
		default:
			strcpy(err,"Fatal Data Transfer Error on [");
			strcat(err,asgn);
			strcat(err,"] variable.");
		}

		/* de-allocate memory of data type */
		switch(data_type)
		{
		case 'i':
			free(i);
			i = NULL;
			break;
		case 'n':
			free(n);
			n = NULL;
			break;
		case 'c':
			free(c);
			c = NULL;
			break;
		case 'd':
			free(d);
			d = NULL;
			break;
		case 'f':
			free(f);
			f = NULL;
			break;
		case 'j':
			free(j);
			j = NULL;
			break;
		case 'm':
			free(m);
			m = NULL;
			break;
		case 'a':
			free(a);
			a = NULL;
			break;
		}
		/* de-allocate asgn */
		free(asgn);
		asgn = NULL;
	}
	else	/* no assigment */
	{
   		// if there is no assignment then integer is considered
		// to be the default assignment data type for evaluation.
		puts("");

		int _i=0;
		_i = eval(exp);
		printf("eval: %d\n",_i);

		data_type = 'i';
		long *i = NULL;
		i=(long *)(evals(exp,data_type));
		printf("evals: %ld\n",*i);
		free(i);
		i = NULL;

		void evali(const char *str, char *err, int *eval);
		evali(exp,err,&_i);
		printf("evali: %d\n",_i);
		printf("evali was invoked %d time(s).\n",evali_count);
		evali_count = 0;
	}
	free(exp);
	exp = NULL;
}
Пример #12
0
int
main(int argc, const char *argv[]) {
  const char *me;
  hestOpt *hopt=NULL;
  airArray *mop;

  double _tt[6], tt[7], ss, pp[3], qq[4], rot[9], mat1[9], mat2[9], tmp,
    evalA[3], evecA[9], evalB[3], evecB[9];
  int roots;

  mop = airMopNew();
  me = argv[0];
  hestOptAdd(&hopt, NULL, "m00 m01 m02 m11 m12 m22",
             airTypeDouble, 6, 6, _tt, NULL, "symmtric matrix coeffs");
  hestOptAdd(&hopt, "p", "vec", airTypeDouble, 3, 3, pp, "0 0 0",
             "rotation as P vector");
  hestOptAdd(&hopt, "s", "scl", airTypeDouble, 1, 1, &ss, "1.0",
             "scaling");
  hestParseOrDie(hopt, argc-1, argv+1, NULL,
                 me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  ELL_6V_COPY(tt + 1, _tt);
  tt[0] = 1.0;
  TEN_T_SCALE(tt, ss, tt);

  ELL_4V_SET(qq, 1, pp[0], pp[1], pp[2]);
  ELL_4V_NORM(qq, qq, tmp);
  ell_q_to_3m_d(rot, qq);
  printf("%s: rot\n", me);
  printf("  %g %g %g\n", rot[0], rot[1], rot[2]);
  printf("  %g %g %g\n", rot[3], rot[4], rot[5]);
  printf("  %g %g %g\n", rot[6], rot[7], rot[8]);

  TEN_T2M(mat1, tt);
  ell_3m_mul_d(mat2, rot, mat1);
  ELL_3M_TRANSPOSE_IP(rot, tmp);
  ell_3m_mul_d(mat1, mat2, rot);
  TEN_M2T(tt, mat1);

  printf("input matrix = \n %g %g %g\n %g %g\n %g\n",
          tt[1], tt[2], tt[3], tt[4], tt[5], tt[6]);

  printf("================== tenEigensolve_d ==================\n");
  roots = tenEigensolve_d(evalA, evecA, tt);
  printf("%s roots\n", airEnumStr(ell_cubic_root, roots));
  testeigen(tt, evalA, evecA);

  printf("================== new eigensolve ==================\n");
  roots = evals(evalB, tt[1], tt[2], tt[3], tt[4], tt[5], tt[6]);
  printf("%s roots: %g %g %g\n", airEnumStr(ell_cubic_root, roots),
         evalB[0], evalB[1], evalB[2]);
  roots = evals_evecs(evalB, evecB,
                      tt[1], tt[2], tt[3], tt[4], tt[5], tt[6]);
  printf("%s roots\n", airEnumStr(ell_cubic_root, roots));
  testeigen(tt, evalB, evecB);

  airMopOkay(mop);
  return 0;
}
Пример #13
0
//A is an antisymmetric matrix and B is the output rotation matrix
void make_rotation_matrix_notworking(const Array2 <doublevar> & A,
                                     Array2 <doublevar> & B) {
    int n=A.GetDim(0);
    assert(A.GetDim(1)==n);
    B.Resize(n,n);

    Array2 <dcomplex> skew(n,n),VL(n,n),VR(n,n);
    Array1 <dcomplex> evals(n);
    for(int i=0; i< n; i++) {
        for(int j=0; j < n; j++) {
            skew(i,j)=A(i,j);
        }
    }
    GeneralizedEigenSystemSolverComplexGeneralMatrices(skew,evals,VL,VR);

    cout << "evals " << endl;
    for(int i=0; i< n; i++) cout << evals(i) << " ";
    cout << endl;
    cout << "VR " << endl;
    for(int i=0; i< n; i++) {
        for(int j=0; j< n; j++) {
            cout << VR(i,j) << " ";
        }
        cout << endl;
    }
    cout << "VL " << endl;
    for(int i=0; i< n; i++) {
        for(int j=0; j< n; j++) {
            cout << VL(i,j) << " ";
        }
        cout << endl;
    }
    //this is horribly inefficient,most likely

    skew=dcomplex(0.0,0.); //we don't need that any more so we reuse it
    Array2 <dcomplex> work(n,n);
    work=dcomplex(0.0,0.);
    for(int i=0; i< n; i++) {
        skew(i,i)=exp(evals(i));
    }
    for(int i=0; i< n; i++) {
        for(int j=0; j<n; j++) {
            for(int k=0; k< n; k++) {
                work(i,k)+=skew(i,j)*VR(j,k);
            }
        }
    }
    skew=dcomplex(0.,0.);
    for(int i=0; i< n; i++) {
        for(int j=0; j<n; j++) {
            for(int k=0; k< n; k++) {
//skew(i,k)+=conj(VL(i,j))*work(j,k);
                skew(i,k)=conj(VR(j,i))*work(j,k);
            }
        }
    }


    cout << "rotation " << endl;
    for(int i=0; i< n; i++) {
        for(int j=0; j< n; j++) {
            cout << skew(i,j) << " ";
        }
        cout << endl;
    }


}
Пример #14
0
int main(int argc, char *argv[]) {
    if(argc != 6 && argc != 7) {
        printf("usage: rrg N n s D seed (id_string)\n");
        return 1;
        }
    time_t t1,t2,tI,tF;
    ITensor U,Dg,P,S;
    Index ei;

    // RRG structure parameters
    const int    N  = atoi(argv[1]); // should be n*(power of 2)
    const int    n  = atoi(argv[2]); // initial blocking size
    int          w  = n;             // block size (scales with m)
    int          ll = 0;             // lambda block index
    int          m  = 0;             // RG scale factor

    // AGSP and subspace parameters
    const double t = 0.3;            // Trotter temperature
    const int    M = 100;            // num Trotter steps
    const int    k = 1;              // power of Trotter op (just use 1)
    const int    s = atoi(argv[3]);  // formal s param
    const int    D = atoi(argv[4]);  // formal D param
    
    // computational settings
    const bool   doI = true; // diag restricted Hamiltonian iteratively?

    // setup random sampling
    std::random_device r;
    const int seed = atoi(argv[5]);
    fprintf(stderr,"seed is %d\n",seed);
    std::mt19937 gen(seed);
    std::uniform_real_distribution<double> udist(0.0,1.0);

    FILE *sxfl,*syfl,*szfl,*gsfl;
    char id[128],sxnm[256],synm[256],sznm[256],gsnm[256];
    if(argc == 6) sprintf(id,"rrg-L%d-s%d-D%d",N,s,D);
    else sprintf(id,"%s",argv[6]);
    strcat(sxnm,id); strcat(sxnm,"-sx.dat");
    strcat(synm,id); strcat(synm,"-sy.dat");
    strcat(sznm,id); strcat(sznm,"-sz.dat");
    strcat(gsnm,id); strcat(gsnm,"-gs.dat");
    sxfl = fopen(sxnm,"a");
    syfl = fopen(synm,"a");
    szfl = fopen(sznm,"a");
    gsfl = fopen(gsnm,"a");

    // initialize Hilbert subspaces for each level m = 0,...,log(N/n)
    vector<SpinHalf> hsps;
    for(int x = n ; x <= N ; x *= 2) hsps.push_back(SpinHalf(x));
    SpinHalf hs = hsps.back();
 
    // generate product basis over m=0 Hilbert space
    auto p = int(pow(2,n));
    vector<MPS> V1;
    for(int i = 0 ; i < p ; ++i) {
        InitState istate(hsps[0],"Dn");
        for(int j = 1 ; j <= n ; ++j)
            if(i/(int)pow(2,j-1)%2) istate.set(j,"Up");
        V1.push_back(MPS(istate));
        }
    MPS bSpaceL(hsps[0]);
    MPS bSpaceR(hsps[0]);
    makeVS(V1,bSpaceL,LEFT);
    makeVS(V1,bSpaceR,RIGHT);

    // Hamiltonian parameters
    const double Gamma = 2.0;
    vector<double> J(2*(N-1));
    fprintf(stdout,"# Hamiltonian terms Jx1,Jy1,Jx2,... (seed=%d)\n",seed);
    for(int i = 0 ; i < N-1 ; ++i) {
        J[2*i+0] = pow(udist(gen),Gamma);
        J[2*i+1] = pow(udist(gen),Gamma);
        fprintf(stdout,"%16.14f,%16.14f",J[2*i],J[2*i+1]);
        if(i != N-2) fprintf(stdout,",");
        }
    fprintf(stdout,"\n");
    fflush(stdout);

    // initialize H for full system and extract block Hamiltonians
    AutoMPO autoH(hs);
    std::stringstream sts;
    auto out = std::cout.rdbuf(sts.rdbuf());
    vector<vector<MPO> > Hs(hsps.size());
    for(int i = 1 ; i < N ; ++i) {
        autoH += (J[2*(i-1)]-J[2*(i-1)+1]),"S+",i,"S+",i+1;
        autoH += (J[2*(i-1)]-J[2*(i-1)+1]),"S-",i,"S-",i+1;
        autoH += (J[2*(i-1)]+J[2*(i-1)+1]),"S+",i,"S-",i+1;
        autoH += (J[2*(i-1)]+J[2*(i-1)+1]),"S-",i,"S+",i+1;
        }
    auto H = toMPO<ITensor>(autoH,{"Exact",true});
    std::cout.rdbuf(out);

    for(auto i : args(hsps)) extractBlocks(autoH,Hs[i],hsps[i]);
    
    vector<MPO> prodSz,prodSx,projSzUp,projSzDn,projSxUp,projSxDn;
    for(auto& it : hsps) { 
        auto curSz = sysOp(it,"Sz",2.0).toMPO(); prodSz.push_back(curSz);
        auto curSx = sysOp(it,"Sx",2.0).toMPO(); prodSx.push_back(curSx);
        auto curSzUp = sysOp(it,"Id").toMPO(); curSzUp.plusEq(curSz); curSzUp /= 2.0;
        auto curSzDn = sysOp(it,"Id").toMPO(); curSzDn.plusEq(-1.0*curSz); curSzDn /= 2.0;
        auto curSxUp = sysOp(it,"Id").toMPO(); curSxUp.plusEq(curSx); curSxUp /= 2.0;
        auto curSxDn = sysOp(it,"Id").toMPO(); curSxDn.plusEq(-1.0*curSx); curSxDn /= 2.0;
        projSzUp.push_back(curSzUp); projSzDn.push_back(curSzDn);
        projSxUp.push_back(curSxUp); projSxDn.push_back(curSxDn);
        }   
 
    // approximate the thermal operator exp(-H/t)^k using Trotter
    // and MPO multiplication; temperature of K is k/t
    time(&tI);
    MPO eH(hs);
    twoLocalTrotter(eH,t,M,autoH);
    auto K = eH;    
    for(int i = 1 ; i < k ; ++i) {
        nmultMPO(eH,K,K,{"Cutoff",eps,"Maxm",MAXBD});
        K.Aref(1) *= 1.0/norm(K.A(1));
        }
    
    // INITIALIZATION: reduce dimension by sampling from initial basis, either
    // bSpaceL or bSpaceR depending on how the merge will work
    vector<MPS> Spre;
    for(ll = 0 ; ll < N/n ; ll++) {
        auto xs = ll % 2 ? 1 : n; // location of dangling Select index
        auto cur = ll % 2 ? bSpaceR : bSpaceL;
        Index si("ext",s,Select);
       
        // return orthonormal basis of evecs
        auto eigs = diagHermitian(-overlapT(cur,Hs[0][ll],cur),P,S,{"Maxm",s});
        cur.Aref(xs) *= P*delta(commonIndex(P,S),si);
        regauge(cur,xs,{"Truncate",false});

        Spre.push_back(cur);
        }
    time(&t2);
    fprintf(stderr,"initialization: %.f s\n",difftime(t2,tI));

    // ITERATION: proceed through RRG hierarchy, increasing the scale m
    vector<MPS> Spost;
    for(m = 0 ; (int)Spre.size() > 1 ; ++m,w*=2) {
        fprintf(stderr,"Level %d (w = %d)\n",m,w);
        auto hs = hsps[m];
        auto DD = D;//max(4,D/(int(log2(N/n)-m)));
        auto thr = 1e-8;
        Spost.clear();

        // EXPAND STEP: for each block, expand dimension of subspace with AGSP operators
        for(ll = 0 ; ll < N/w ; ++ll) {
            MPO A(hs) , Hc = Hs[m][ll];
            MPS pre = Spre[ll] , ret(hs);
            int xs = ll % 2 ? 1 : w;

            // STEP 1: extract filtering operators A from AGSP K
            time(&t1);
            restrictMPO(K,A,w*ll+1,DD,ll%2);
            time(&t2);
            fprintf(stderr,"trunc AGSP: %.f s\n",difftime(t2,t1));

            // STEP 2: expand subspace using the mapping A:pre->ret
            time(&t1);
            ret = applyMPO(A,pre,ll%2,{"Cutoff",eps,"Maxm",MAXBD});
            time(&t2);
            fprintf(stderr,"apply AGSP: %.f s\n",difftime(t2,t1));

            // rotate into principal components of subspace, poxsibly reducing dimension
            // and stabilizing numerics, then store subspace in eigenbasis of block H
            time(&t1); 
            diagHermitian(overlapT(ret,ret),U,Dg,{"Cutoff",thr});
            time(&t2);
            ei = Index("ext",int(commonIndex(Dg,U)),Select);
            Dg.apply(invsqrt);
            ret.Aref(xs) *= dag(U)*Dg*delta(prime(commonIndex(Dg,U)),ei);
            fprintf(stderr,"rotate MPS: %.f s\n",difftime(t2,t1));

            auto eigs = diagHermitian(-overlapT(ret,Hs[m][ll],ret),P,S);
            ret.Aref(xs) *= P*delta(commonIndex(P,S),ei);
            ret.Aref(xs) *= 1.0/sqrt(overlapT(ret,ret).real(ei(1),prime(ei)(1)));
            regauge(ret,xs,{"Cutoff",eps});

            fprintf(stderr,"max m: %d\n",maxM(ret));
            Spost.push_back(ret);
            
            }

        // MERGE/REDUCE STEP: construct tensor subspace, sample to reduce dimension
        Spre.clear();
        for(ll = 0 ; ll < N/w ; ll+=2) {
            auto spL = Spost[ll];                // L subspace
            auto spR = Spost[ll+1];              // R subspace

            // STEP 1: find s lowest eigenpairs of restricted H
            time(&t1);
            auto tpH = tensorProdContract(spL,spR,Hs[m+1][ll/2]);
            tensorProdH<ITensor> resH(tpH);
            resH.diag(s,doI);
            P = resH.eigenvectors();
            time(&t2);
            fprintf(stderr,"diag restricted H: %.f s\n",difftime(t2,t1));

            // STEP 2: tensor viable sets on each side and reduce dimension
            MPS ret(hsps[m+1]);
            time(&t1);
            tensorProduct(spL,spR,ret,P,(ll/2)%2);
            time(&t2);
            fprintf(stderr,"tensor product (ll=%d): %.f s\n",ll,difftime(t2,t1));
 
            Spre.push_back(ret);
            }
        }

    // EXIT: extract two lowest energy candidate states to determine gap
    auto res = Spre[0];
    auto fi = Index("ext",s/2,Select);
    vector<MPS> resSz = {res,res};
    
    // project to Sz sectors of the eigenspace
    diagHermitian(overlapT(res,prodSz[m],res),U,Dg);
    resSz[0].Aref(N) *= U*delta(commonIndex(U,Dg),fi);
    diagHermitian(overlapT(res,-1.0*prodSz[m],res),U,Dg);
    resSz[1].Aref(N) *= U*delta(commonIndex(U,Dg),fi);
   
    vector<MPS> evecs(2);
    for(int i : range(2)) {
        auto fc = resSz[i];
        
        // diagonalize H within the Sz sectors
        auto eigs = diagHermitian(-overlapT(fc,H,fc),P,S);
        fc.Aref(N) *= (P*setElt(commonIndex(P,S)(1)));
        
        fc.orthogonalize({"Cutoff",epx,"Maxm",MAXBD});
        fc.normalize();
        if(i == 0)
            fprintf(stderr,"RRG gs energy: %17.14f\n",overlap(fc,H,fc));
        evecs[i] = fc;
        }
    time(&t2);

    Real vz,vx;
    vz = overlap(evecs[0],prodSz[m],evecs[0]); vx = overlap(evecs[0],prodSx[m],evecs[0]);
    fprintf(stderr,"Vz,vx of 0 is: %17.14f,%17.14f\n",vz,vx);
    vz = overlap(evecs[1],prodSz[m],evecs[1]); vx = overlap(evecs[1],prodSx[m],evecs[1]);
    fprintf(stderr,"Vz,vx of 1 is: %17.14f,%17.14f\n",vz,vx);
    int x1_up = (vx > 0.0 ? 1 : 0);

    evecs[0] = exactApplyMPO(evecs[0],projSzUp[m],{"Cutoff",epx});
    evecs[0] = exactApplyMPO(evecs[0],projSxUp[m],{"Cutoff",epx});
    evecs[1] = exactApplyMPO(evecs[1],projSzDn[m],{"Cutoff",epx});
    evecs[1] = exactApplyMPO(evecs[1],(x1_up?projSxUp[m]:projSxDn[m]),{"Cutoff",epx});
    for(auto& it : evecs) it.normalize();

    fprintf(stderr,"gs candidate energy: %17.14f\nRRG BD ",overlap(evecs[0],H,evecs[0]));
    for(const auto& it : evecs) fprintf(stderr,"%d ",maxM(it));
    fprintf(stderr,"\telapsed: %.f s\n",difftime(t2,tI));

    // CLEANUP: use DMRG to improve discovered evecs
    vector<Real> evals(2),e_prev(2);
    int max_iter = 30 , used_max = 0;
    Real flr = 1e-13 , over_conv = 1e-1 , gap = 1.0 , conv = over_conv*gap , max_conv = 1.0;
    for(int i = 0 ; i < (int)evecs.size() ; ++i) evals[i] = overlap(evecs[i],H,evecs[i]);
    for(int i = 0 ; (i < 2 || conv < max_conv) && i < max_iter ; ++i) {
        e_prev = evals;

        time(&t1);
        evals = dmrgMPO(H,evecs,8,{"Penalty",0.1,"Cutoff",epx});
        time(&t2);
        
        gap = evals[1]-evals[0];

        max_conv = 0.0;
        for(auto& j : range(2))
            if(fabs(e_prev[j]-evals[j]) > max_conv) max_conv = e_prev[j]-evals[j];
        
        fprintf(stderr,"DMRG BD ");
        for(const auto& it : evecs) fprintf(stderr,"%3d ",maxM(it));
        fprintf(stderr,"\tgap: %e\tconv=%9.2e,%9.2e\telapsed: %.f s\n",gap,
            e_prev[0]-evals[0],e_prev[1]-evals[1],difftime(t2,t1));
        conv = max(over_conv*gap,flr);
        if(i == max_iter) used_max = 1;
        }

    for(int i = 0 ; i < (int)evecs.size() ; ++i) {
        vz = overlap(evecs[i],prodSz[m],evecs[i]); vx = overlap(evecs[i],prodSx[m],evecs[i]);
        fprintf(stderr,"Vz,vx of %d is: %12.9f,%12.9f\n",i,vz,vx);
        }

    evecs[0] = exactApplyMPO(evecs[0],projSzUp[m],{"Cutoff",1e-16});
    evecs[0] = exactApplyMPO(evecs[0],projSxUp[m],{"Cutoff",1e-16});
    evecs[1] = exactApplyMPO(evecs[1],projSzDn[m],{"Cutoff",1e-16});
    evecs[1] = exactApplyMPO(evecs[1],(x1_up?projSxUp[m]:projSxDn[m]),{"Cutoff",1e-16});
    for(auto& it : evecs) it.normalize();
    for(auto i : range(evecs.size())) evals[i] = overlap(evecs[i],H,evecs[i]);
    time(&tF);

    auto gsR = evecs[0];
    auto ee = measEE(gsR,N/2);
    gap = evals[1]-evals[0];

    fprintf(stderr,"gs: %17.14f gap: %15.9e ee: %10.8f\n",evals[0],gap,ee);
    fprintf(gsfl,"# GS data (L=%d s=%d D=%d seed=%d time=%.f)\n",N,s,D,seed,difftime(tF,tI));
    if(used_max) fprintf(gsfl,"# WARNING max iterations reached\n");
    fprintf(gsfl,"%17.14f\t%15.9e\t%10.8f\n",evals[0],gap,ee);

    // Compute two-point correlation functions in ground state via usual MPS method
    fprintf(sxfl,"# SxSx corr matrix (L=%d s=%d D=%d seed=%d)\n",N,s,D,seed);
    fprintf(syfl,"# SySy corr matrix (L=%d s=%d D=%d seed=%d)\n",N,s,D,seed);
    fprintf(szfl,"# SzSz corr matrix (L=%d s=%d D=%d seed=%d)\n",N,s,D,seed);
    for(int i = 1 ; i <= N ; ++i) {
        gsR.position(i,{"Cutoff",0.0});
        auto SxA = hs.op("Sx",i); auto SyA = hs.op("Sy",i); auto SzA = hs.op("Sz",i);
        for(int j = 1 ; j <= N ; ++j) {
            if(j <= i) {
                fprintf(sxfl,"%15.12f\t",0.0);
                fprintf(syfl,"%15.12f\t",0.0);
                fprintf(szfl,"%15.12f\t",0.0); 
            } else {
                auto SxB = hs.op("Sx",j); auto SyB = hs.op("Sy",j); auto SzB = hs.op("Sz",j);
                fprintf(sxfl,"%15.12f\t",measOp(gsR,SxA,i,SxB,j));
                fprintf(syfl,"%15.12f\t",measOp(gsR,SyA,i,SyB,j));
                fprintf(szfl,"%15.12f\t",measOp(gsR,SzA,i,SzB,j));
                }
            }
        fprintf(sxfl,"\n");
        fprintf(syfl,"\n");
        fprintf(szfl,"\n");
        }

    fclose(sxfl);
    fclose(syfl);
    fclose(szfl);
    fclose(gsfl);

    return 0;
    
    }
Пример #15
0
  void ContactAngle2::doFrame(int frame) {
    StuntDouble* sd;
    int i;

    // set up the bins for density analysis

    Mat3x3d hmat = info_->getSnapshotManager()->getCurrentSnapshot()->getHmat();
    RealType len = std::min(hmat(0, 0), hmat(1, 1));
    RealType zLen = hmat(2,2);

    RealType dr = len / (RealType) nRBins_;
    RealType dz = zLen / (RealType) nZBins_;

    std::vector<std::vector<RealType> > histo;
    histo.resize(nRBins_);
    for (unsigned int i = 0; i < histo.size(); ++i){
      histo[i].resize(nZBins_);
      std::fill(histo[i].begin(), histo[i].end(), 0.0);
    }      
        
    if (evaluator1_.isDynamic()) {
      seleMan1_.setSelectionSet(evaluator1_.evaluate());
    }
    
    Vector3d com(centroidX_, centroidY_, solidZ_);

    // now that we have the centroid, we can make cylindrical density maps
    Vector3d pos;
    RealType r;
    RealType z;
    
    for (sd = seleMan1_.beginSelected(i); sd != NULL;
         sd = seleMan1_.nextSelected(i)) {      
      pos = sd->getPos() - com;

      // r goes from zero upwards
      r = sqrt(pow(pos.x(), 2) + pow(pos.y(), 2));
      // z is possibly symmetric around 0
      z = pos.z();
          
      int whichRBin = int(r / dr);
      int whichZBin = int( (zLen/2.0 + z) / dz);
      
      if ((whichRBin < int(nRBins_)) && (whichZBin >= 0)
          && (whichZBin < int(nZBins_))) {
        histo[whichRBin][whichZBin] += sd->getMass();
      }
      
    }
    
    for(unsigned int i = 0 ; i < histo.size(); ++i){

      RealType rL = i * dr;
      RealType rU = rL + dr;
      RealType volSlice = NumericConstant::PI * dz * (( rU*rU ) - ( rL*rL ));

      for (unsigned int j = 0; j < histo[i].size(); ++j) {
        histo[i][j] *= PhysicalConstants::densityConvert / volSlice;
      }
    }

    std::vector<Vector<RealType, 2> > points;
    points.clear();
    
    for (unsigned int j = 0; j < nZBins_;  ++j) {

      // The z coordinates were measured relative to the selection
      // center of mass.  However, we're interested in the elevation
      // above the solid surface.  Also, the binning was done around
      // zero with enough bins to cover the zLength of the box:
      
      RealType thez =  com.z() - solidZ_  - zLen/2.0 + dz * (j + 0.5);
      bool aboveThresh = false;
      bool foundThresh = false;
      int rloc = 0;
      
      for (std::size_t i = 0; i < nRBins_;  ++i) {

        if (histo[i][j] >= threshDens_) aboveThresh = true;

        if (aboveThresh && (histo[i][j] <= threshDens_)) {
          rloc = i;
          foundThresh = true;
          aboveThresh = false;
        }

      }
      if (foundThresh) {
        Vector<RealType,2> point;
        point[0] = dr*(rloc+0.5);
        point[1] = thez;

        if (thez > bufferLength_) {
          points.push_back( point );
        }
      }      
    }

    int numPoints = points.size();

    // Compute the average of the data points.
    Vector<RealType, 2> average = points[0];
    int i0;
    for (i0 = 1; i0 < numPoints; ++i0) {
      average += points[i0];
    }
    RealType invNumPoints = ((RealType)1)/(RealType)numPoints;
    average *= invNumPoints;
    
    DynamicRectMatrix<RealType> mat(4, 4);
    int row, col;
    for (row = 0; row < 4; ++row) {
      for (col = 0; col < 4; ++col){
        mat(row,col) = 0.0;        
      }
    }
    for (int i = 0; i < numPoints; ++i) {
      RealType x = points[i][0];
      RealType y = points[i][1];
      RealType x2 = x*x;
      RealType y2 = y*y;
      RealType xy = x*y;
      RealType r2 = x2+y2;
      RealType xr2 = x*r2;
      RealType yr2 = y*r2;
      RealType r4 = r2*r2;

      mat(0,1) += x;
      mat(0,2) += y;
      mat(0,3) += r2;
      mat(1,1) += x2;
      mat(1,2) += xy;
      mat(1,3) += xr2;
      mat(2,2) += y2;
      mat(2,3) += yr2;
      mat(3,3) += r4;
    }
    mat(0,0) = (RealType)numPoints;

    for (row = 0; row < 4; ++row) {
      for (col = 0; col < row; ++col) {
        mat(row,col) = mat(col,row);
      }
    }

    for (row = 0; row < 4; ++row) {
      for (col = 0; col < 4; ++col) {
        mat(row,col) *= invNumPoints;
      }
    }

    JAMA::Eigenvalue<RealType> eigensystem(mat);
    DynamicRectMatrix<RealType> evects(4, 4);
    DynamicVector<RealType> evals(4);

    eigensystem.getRealEigenvalues(evals);
    eigensystem.getV(evects);

    DynamicVector<RealType> evector = evects.getColumn(0);
    RealType inv = ((RealType)1)/evector[3];  // beware zero divide
    RealType coeff[3];
    for (row = 0; row < 3; ++row) {
      coeff[row] = inv*evector[row];
    }

    Vector<RealType, 2> center;
    
    center[0] = -((RealType)0.5)*coeff[1];
    center[1] = -((RealType)0.5)*coeff[2];
    RealType radius = sqrt(fabs(center[0]*center[0] + center[1]*center[1]
                                - coeff[0]));

    int i1;
    for (i1 = 0; i1 < 100; ++i1) {
      // Update the iterates.
      Vector<RealType, 2> current = center;
      
      // Compute average L, dL/da, dL/db.
      RealType lenAverage = (RealType)0;
      Vector<RealType, 2> derLenAverage = Vector<RealType, 2>(0.0);
      for (i0 = 0; i0 < numPoints; ++i0) {
        Vector<RealType, 2> diff = points[i0] - center;
        RealType length = diff.length();
        if (length > 1e-6) {
          lenAverage += length;
          RealType invLength = ((RealType)1)/length;
          derLenAverage -= invLength*diff;
        }
      }
      lenAverage *= invNumPoints;
      derLenAverage *= invNumPoints;

      center = average + lenAverage*derLenAverage;
      radius = lenAverage;

      Vector<RealType, 2> diff = center - current;
      if (fabs(diff[0]) <= 1e-6 &&  fabs(diff[1]) <= 1e-6) {
        break;
      }
    }

    RealType zCen = center[1];
    RealType rDrop = radius;
    RealType ca;

    if (fabs(zCen) > rDrop) {
      ca = 180.0;
    } else {
      ca = 90.0 + asin(zCen/rDrop)*(180.0/M_PI);
    }

    values_.push_back( ca );    
  }