Commit a6c5371e authored by Giovanni La Mura's avatar Giovanni La Mura
Browse files

Write a C++ parser for sphere/edfb input data

parent 4948b419
Loading
Loading
Loading
Loading

src/sphere/List.h

0 → 100644
+150 −0
Original line number Diff line number Diff line
#ifndef LIST_OUT_OF_BOUNDS_EXCEPTION
#define LIST_OUT_OF_BOUNDS_EXCEPTION 1
#endif

/*! \class List<T>
 * \brief A class to represent dynamic lists.
 *
 * This class helps in the creation and management of dynamic lists of
 * objects, whose size is not known in advance. List offers the advantage
 * of saving memory, since only the necessary space will be allocated,
 * but it has the disadvantage of creating an object which is not contiguous
 * in memory and, therefore, is very inefficient for subsequent manipulation.
 *
 * For this reason, the best use of List objects is to collect all the
 * desired members and then, once the element number is known, to convert
 * the List to C array, by calling List.to_array(). This function returns
 * a contiguous array of type T[SIZE] that can be used for indexed access.
 */
template<class T> class List {
 protected:
  int size; //!< Size of the List.
  struct element {T value; element* p_prev;}; //!< List element connector.
  element *current, //!< Pointer to element affected by last operation.
    *first, //!< Pointer to the first element in the List.
    *last; //!< Pointer to the last element in the List.

 public:
  /*! \fn List(int)
   * \brief List constructor.
   *
   * Use the constructor List<T>(SIZE) to create a new list with a given
   * size. If the required size is not known in advance, it is recommended
   * to create a List with SIZE=1 (this is the default behavior) and then
   * to append the elements dynamically, using List.append(ELEMENT) (where
   * ELEMENT needs to be a value of type T, corresponding to the class
   * template specialization). Note that, due to the default behavior, the
   * following calls are equivalent and they both produce an integer List
   * with size equal to 1:
   *
   * a = List<int>(1);
   *
   * b = List<int>();
   */
  List(int size = 1) {
    this->size = size;
    element* p_prev = NULL;
    T value = (T)0;
    current = new element;
    current->value = value;
    current->p_prev = p_prev;
    p_prev = current;
    first = current;
    for (int i = 1; i < size; i++) {
      T value;
      current = new element;
      current->value = value;
      current->p_prev = p_prev;
      p_prev = current;
    }
    last = current;
  }

  ~List() {
    current = last;
    element *old;
    while (current->p_prev) {
      old = current;
      current = old->p_prev;
      delete old;
    }
  }
  
  /*! \fn append(T)
   * \brief Append an element at the end of the list.
   *
   * To dynamically create a list whose size is not known in advance,
   * elements can be appended in an iterative way. Note that element
   * manipulation is much more effective in a C array than in a List
   * object. For this reason, after the List has been created, it is
   * strongly advised to convert it to a C array by calling the function
   * List.to_array().
   */
  void append(T value) {
    element *p_prev = last;
    current = new element;
    current->value = value;
    current->p_prev = p_prev;
    last = current;
    size++;
  }

  /*! \fn get(int)
   * \brief Get the element at given index.
   *
   * Get the element specified by the index argument. The first element
   * has index 0 and the last one has index [size - 1].
   *
   * \return T: the value of the element at the requested position.
   * \throw LIST_OUT_OF_BOUNDS_EXCEPTION: raised if the index is out of bounds.
   */
  T get(int index) {
    if (index < 0 || index > size - 1) {
      throw LIST_OUT_OF_BOUNDS_EXCEPTION;
    }
    current = last;
    for (int i = size - 1; i > index; i--) current = current->p_prev;
    return current->value;
  }

  /*! \fn set(int, T)
   * \brief Set an element by index and value.
   *
   * Set the element at the position specified by the index to the value
   * specified by the value argument.
   *
   * \throw LIST_OUT_OF_BOUNDS_EXCEPTION: raised if the index is out of bounds.
   */
  void set(int index, T value) {
    if (index < 0 || index > size - 1) {
      throw LIST_OUT_OF_BOUNDS_EXCEPTION;
    }
    current = last;
    for (int i = size - 1; i > index; i--) current = current->p_prev;
    current->value = value;
  }

  /*! \fn to_array()
   * \brief Convert the list to a C array.
   *
   * The List object is useful to dynamically manage a set of objects
   * when the number of elements is not known in advance. However, the
   * resulting object is not contiguosly stored in memory. As a result,
   * access to specific elements in the middle of the list is not very
   * effective, because the list needs to be walked every time up to
   * the desired position. In order to avoid this, List.to_array() makes
   * a conversion from List to C array, returning a contiguous object,
   * where indexed access can be used.
   *
   * \return T[size]: a C array of type T and size equal to the List size.
   */
  T* to_array() {
    T *result = new T[size];
    current = last;
    for (int i = size - 1; i > 0; i--) {
      result[i] = current->value;
      current = current->p_prev;
    }
    return result;
  }
};

src/sphere/edfb.cpp

0 → 100644
+16 −0
Original line number Diff line number Diff line
/*! \brief C++ implementation of EDFB
 *
 *  This code aims at replicating the original work-flow in C++.
 */

#include <cstdio>
#include <cmath>
#include <string>
#include "List.h"
#include "edfb.h"

int main(int argc, char **argv) {
  DEDFB input_data = DEDFB(std::string("../../test_data/sphere/DEDFB"));
  input_data.print();
  return 0;
}

src/sphere/edfb.h

0 → 100644
+160 −0
Original line number Diff line number Diff line
/*! \class DEDFB
 * \brief A class to represent EDFB configuration data.
 *
 * This class replicates the structure of formatted DEDFB input data
 * files for the EDFB program. The class is built on the SPHERE/DEDFB
 * file template, but it is meant to grant compliance with the CLUSTER
 * case too.
 *
 * Compatibility between the SPHERE and the CLUSTER cases is planned
 * through the introduction of dynamic pointers that can fit both cases,
 * provided that the DEDFB formatting has been properly understood. In
 * case not, the suggested work-around is to develop specialized classes
 * for the SPHERE case and the CLUSTER case. In that case, the current
 * class would already represent a valid implementation for the single
 * sphere problem.
 *
 * It should be noted that the variable names have been left intentionally
 * equal to the FORTRAN equivalents. In addition they are not documented
 * yet. Documentation and naming may be revised after the code has been
 * tested to succesfully reproduce the original work-flow.
 */
class DEDFB {
 protected:
  int nsph, ies;
  double exdc, wp, xip;
  int idfc, nxi, instpc, insn;
  double *xi_vector;
  int *iog;
  int *nshl;
  double *ros;
  double *rcf;
  double *dc0;

public:
  DEDFB(std::string file_name);
  void print();
};

/*! \fn DEDFB(std::string)
 * \brief Data structure constructor.
 *
 * The default procedure to import a configuration file is to build a
 * configuration object, according to one of the following flavours:
 *
 * DEDFB edfb_cfg = DEDFB("FILE_NAME"); // configuration object
 *
 * or
 *
 * DEDFB *edfb_cfg_ptr = new DEDFB("FILE_NAME"); // pointer version
 */
DEDFB::DEDFB(std::string file_name) {
  FILE *input_file = fopen(file_name.c_str(), "r");
  int exp_exdc, exp_wp, exp_xip;
  List<double> xi_list(1);
  fscanf(input_file, " %d %d", &nsph, &ies);
  fscanf(
	 input_file,
	 " %9lf D%d %9lf D%d %8lf D%d %d %d %d %d",
	 &exdc, &exp_exdc,
	 &wp, &exp_wp,
	 &xip, &exp_xip,
	 &idfc, &nxi, &instpc, &insn
	 );
  exdc *= pow(10.0, exp_exdc);
  wp *= pow(10.0, exp_wp);
  xip *= pow(10.0, exp_xip);
  for (int i_xi = 0; i_xi < nxi; i_xi++) {
    double xi;
    int exp_xi;
    fscanf(input_file, " %9lf D%d", &xi, &exp_xi);
    xi *= pow(10.0, exp_xi);
    if (i_xi == 0) {
      xi_list.set(0, xi);
    } else {
      xi_list.append(xi);
    }
  }
  xi_vector = xi_list.to_array();
  iog = new int[nsph];
  for (int i_iog = 0; i_iog < nsph; i_iog++) {
    fscanf(input_file, " %d", (iog + i_iog));
  }
  nshl = new int[nsph];
  ros = new double[nsph];
  for (int i_nshl = 0; i_nshl < nsph; i_nshl++) {
    double i_ros;
    int i_ros_exp;
    fscanf(input_file, " %d %9lf D%d", (nshl + i_nshl), &i_ros, &i_ros_exp);
    i_ros *= pow(10.0, i_ros_exp);
    ros[i_nshl] = i_ros;
  }
  rcf = new double[nsph * nshl[0]];
  for (int i_rcf = 0; i_rcf < nshl[0]; i_rcf++) {
    for (int j_rcf = 0; j_rcf < nsph; j_rcf++) {
      double ij_rcf;
      int ij_rcf_exp;
      fscanf(input_file, " %8lf D%d", &ij_rcf, &ij_rcf_exp);
      ij_rcf *= pow(10.0, ij_rcf_exp);
      rcf[(nsph * i_rcf) + j_rcf] = ij_rcf;
    }
  }
  dc0 = new double[nsph * nshl[0]];
  for (int i_dc0 = 0; i_dc0 < nsph; i_dc0++) {
    double ij_dc0;
    int ij_dc0_exp;
    fscanf(input_file, " (");
    for (int j_dc0 = 0; j_dc0 < nshl[0] - 1; j_dc0++) {
      fscanf(input_file, " %8lf D%d,", &ij_dc0, &ij_dc0_exp);
      ij_dc0 *= pow(10.0, ij_dc0_exp);
      dc0[(nshl[0] * i_dc0) + j_dc0] = ij_dc0;
    }
    fscanf(input_file, " %8lf D%d)", &ij_dc0, &ij_dc0_exp);
    ij_dc0 *= pow(10.0, ij_dc0_exp);
    dc0[(nshl[0] * i_dc0) + nshl[0] - 1] = ij_dc0;
  }
  fclose(input_file);
}

/*! \fn print()
 * \brief Print the data structure to console.
 *
 * This is a simple function to print the data read from a configuration
 * file to the screen. This operation can be useful for debug and testing.
 */
void DEDFB::print() {
  printf("### CONFIGURATION DATA ###\n");
  printf("NSPH   = %d\n", nsph);
  printf("IES    = %d\n", ies);
  printf("EXDC   = %E\n", exdc);
  printf("WP     = %E\n", wp);
  printf("XIP    = %E\n", xip);
  printf("IDFC   = %d\n", idfc);
  printf("NXI    = %d\n", nxi);
  printf("INSTPC = %d\n", instpc);
  printf("INSN   = %d\n", insn);
  printf("XIV    = [ %lE", xi_vector[0]);
  for (int i_xiv = 1; i_xiv < nxi; i_xiv++) printf(", %lE", xi_vector[i_xiv]);
  printf(" ]\n");
  printf("IOG    = [ %d", iog[0]);
  for (int i_iog = 1; i_iog < nsph; i_iog++) printf(", %d", iog[i_iog]);
  printf(" ]\n");
  printf("NSHL   = [ %d", nshl[0]);
  for (int i_nshl = 1; i_nshl < nsph; i_nshl++) printf(", %d", nshl[i_nshl]);
  printf(" ]\n");
  printf("ROS    = [ %lE", ros[0]);
  for (int i_ros = 1; i_ros < nsph; i_ros++) printf(", %lE", ros[i_ros]);
  printf(" ]\n");
  printf("RCF    = [ %lE", rcf[0]);
  for (int i_rcf = 1; i_rcf < nsph * nshl[0]; i_rcf++) printf(", %lE", rcf[i_rcf]);
  printf(" ]\n");
  printf("DC0    = [ %lE", dc0[0]);
  for (int i_dc0 = 1; i_dc0 < nsph * nshl[0]; i_dc0++) printf(", %lE", dc0[i_dc0]);
  printf(" ]\n");
  printf("######   END DATA   ######\n");
  
}

void inxi(
  DEDFB *data
); //!< \brief Initialization process