Raw File
force.cc
#include "force.h"

#include <math.h>

#include "assert.h"

Force::Force() {}

Coordinate Force::force_from_coordinate_to_coordinate(
    const Coordinate &sender, const Coordinate &receiver, bool attractive) {
  assert(
      "The Force class is abstract. Derive from it and implement the "
      "'applyForceFromCoordinateToCoordinate' method!");

  return Coordinate();
}

double Force::radial_force_from_coordinate_to_coordinate(
    const Coordinate &sender, const Coordinate &receiver, bool attractive) {
  assert(
      "The Force class is abstract. Derive from it and implement the "
      "'radialForceFromCoordinateToCoordinate' method!");
  return 0.0;
}

double Force::distance_between_coordinates(const Coordinate &coord1,
                                           const Coordinate &coord2) const {
  assert(
      "The Force class is abstract. Derive from it and implement the "
      "'distanceBetweenCordinates' method!");
  return 0.0;
}

double Force::hyperbolic_distance_between_coordinates(
    const Coordinate &coord1, const Coordinate &coord2) {
  /**
   * Check whether one of the coordinates is the origin. If it is, we can simply
   * return the radius of the second coordinate.
   */
  Coordinate origin = Coordinate();
  if (coord1 == origin) {
    return coord2.length();
  }
  if (coord2 == origin) {
    return coord1.length();
  }

  /**
   * At first we determine central angle between the two vertices.
   * This is done by first converting the coordinates spherical coordinates.
   */

  Coordinate spherical1 = coord1.cartesian_to_spherical();
  Coordinate spherical2 = coord2.cartesian_to_spherical();

  double lambda1 = spherical1.y;
  double lambda2 = spherical2.y;
  double phi1 = spherical1.z;
  double phi2 = spherical2.z;

  if (lambda1 == lambda2 && phi1 == phi2) {
    return fabs(spherical1.x - spherical2.x);
  }

  double delta_lambda = fabs(lambda1 - lambda2);

  /**
   * The central angle is determined using the following function, which is said
   * to be rather robust against numerical difficulties.
   */
  double delta_sigma = atan2(
      sqrt((cos(phi2) * sin(delta_lambda)) * (cos(phi2) * sin(delta_lambda)) +
           (cos(phi1) * sin(phi2) - sin(phi1) * cos(phi2) * cos(delta_lambda)) *
               (cos(phi1) * sin(phi2) -
                sin(phi1) * cos(phi2) * cos(delta_lambda))),
      (sin(phi1) * sin(phi2) + cos(phi1) * cos(phi2) * cos(delta_lambda)));

  /**
   * Now we now the angular distance between the to particles. Next up: the
   * radial coordinates.
   */

  double r1 = spherical1.x;
  double r2 = spherical2.x;

  double distance =
      acosh(cosh(r1) * cosh(r2) - sinh(r1) * sinh(r2) * cos(delta_sigma));

  /**
   * We assume that NaNs occur when two coordinates are too close to
   * each other. In that case we set the distance to 0 and hope for
   * the best.
   */
  if (distance != distance) {
    distance = 0.0;
  }

  return distance;
}
back to top