Changes in / [87e2e39:c111db]


Ignore:
Files:
83 added
2 deleted
47 edited

Legend:

Unmodified
Added
Removed
  • configure.ac

    r87e2e39 rc111db  
    2525# Checks for libraries.
    2626AC_CHECK_LIB(m, sqrt, ,AC_MSG_ERROR([compatible libc math library not found]))
     27
     28# Boost libraries
     29AX_BOOST_BASE([1.33.1])
     30AX_BOOST_PROGRAM_OPTIONS
     31#AX_BOOST_FOREACH
     32#AX_BOOST_FILESYSTEM
     33#AX_BOOST_THREAD
     34#AX_BOOST_PROGRAM_OPTIONS
     35#AX_BOOST_SERIALIZATION
    2736
    2837# Checks for header files.
  • src/Makefile.am

    r87e2e39 rc111db  
    1 SOURCE = atom.cpp bond.cpp boundary.cpp config.cpp          element.cpp ellipsoid.cpp helpers.cpp leastsquaremin.cpp linkedcell.cpp memoryusageobserver.cpp molecules.cpp moleculelist.cpp parser.cpp periodentafel.cpp                tesselation.cpp tesselationhelpers.cpp vector.cpp verbose.cpp
    2 HEADER = atom.hpp bond.hpp boundary.hpp config.hpp defs.hpp element.hpp ellipsoid.hpp helpers.hpp leastsquaremin.hpp linkedcell.hpp memoryusageobserver.hpp molecules.hpp                  parser.hpp periodentafel.hpp stackclass.hpp tesselation.hpp tesselationhelpers.hpp vector.hpp verbose.hpp
     1SOURCE = atom.cpp bond.cpp boundary.cpp config.cpp element.cpp ellipsoid.cpp graph.cpp helpers.cpp leastsquaremin.cpp linkedcell.cpp memoryusageobserver.cpp moleculelist.cpp molecule.cpp molecule_dynamics.cpp molecule_fragmentation.cpp molecule_geometry.cpp molecule_graph.cpp molecule_pointcloud.cpp parser.cpp periodentafel.cpp tesselation.cpp tesselationhelpers.cpp vector.cpp verbose.cpp
     2HEADER = atom.hpp bond.hpp boundary.hpp config.hpp defs.hpp element.hpp ellipsoid.hpp graph.hpp helpers.hpp leastsquaremin.hpp linkedcell.hpp lists.hpp memoryallocator.hpp memoryusageobserver.hpp molecule.hpp molecule_template.hpp parser.hpp periodentafel.hpp stackclass.hpp tesselation.hpp tesselationhelpers.hpp vector.hpp verbose.hpp
    33
     4BOOST_LIB = $(BOOST_LDFLAGS) $(BOOST_MPL_LIB)
    45INCLUDES = -I$(top_srcdir)/src/unittests
    56
     
    910libmolecuilder_a_SOURCES = ${SOURCE} ${HEADER}
    1011molecuilder_DATA = elements.db valence.db orbitals.db Hbonddistance.db Hbondangle.db
     12molecuilder_LDFLAGS = $(BOOST_LIB)
    1113molecuilder_SOURCES = builder.cpp
    1214molecuilder_LDADD = libmolecuilder.a
  • src/atom.cpp

    r87e2e39 rc111db  
    66
    77#include "atom.hpp"
     8#include "bond.hpp"
     9#include "element.hpp"
    810#include "memoryallocator.hpp"
     11#include "vector.hpp"
    912
    1013/************************************* Functions for class atom *************************************/
     
    6265atom::~atom()
    6366{
    64   Free(&ComponentNr);
     67  Free<int>(&ComponentNr, "atom::~atom: *ComponentNr");
     68  Free<char>(&Name, "atom::~atom: *Name");
     69  Trajectory.R.clear();
     70  Trajectory.U.clear();
     71  Trajectory.F.clear();
    6572};
    6673
     
    8087};
    8188
     89/** Sets father to itself or its father in case of copying a molecule.
     90 */
     91void atom::CorrectFather()
     92{
     93  if (father->father == father)   // same atom in copy's father points to itself
     94    father = this;  // set father to itself (copy of a whole molecule)
     95  else
     96   father = father->father;  // set father to original's father
     97
     98};
     99
     100/** Check whether father is equal to given atom.
     101 * \param *ptr atom to compare father to
     102 * \param **res return value (only set if atom::father is equal to \a *ptr)
     103 */
     104void atom::EqualsFather ( atom *ptr, atom **res )
     105{
     106  if ( ptr == father )
     107    *res = this;
     108};
     109
     110/** Checks whether atom is within the given box.
     111 * \param offset offset to box origin
     112 * \param *parallelepiped box matrix
     113 * \return true - is inside, false - is not
     114 */
     115bool atom::IsInParallelepiped(Vector offset, double *parallelepiped)
     116{
     117  return (node->IsInParallelepiped(offset, parallelepiped));
     118};
     119
    82120/** Output of a single atom.
    83121 * \param ElementNo cardinal number of the element
     
    85123 * \param *out stream to output to
    86124 * \param *comment commentary after '#' sign
    87  */
    88 bool atom::Output(int ElementNo, int AtomNo, ofstream *out, const char *comment) const
     125  * \return true - \a *out present, false - \a *out is NULL
     126 */
     127bool atom::Output(ofstream *out, int ElementNo, int AtomNo, const char *comment) const
    89128{
    90129  if (out != NULL) {
     
    102141    return false;
    103142};
     143bool atom::Output(ofstream *out, int *ElementNo, int *AtomNo, const char *comment)
     144{
     145  AtomNo[type->Z]++;  // increment number
     146  if (out != NULL) {
     147    *out << "Ion_Type" << ElementNo[type->Z] << "_" << AtomNo[type->Z] << "\t"  << fixed << setprecision(9) << showpoint;
     148    *out << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2];
     149    *out << "\t" << FixedIon;
     150    if (v.Norm() > MYEPSILON)
     151      *out << "\t" << scientific << setprecision(6) << v.x[0] << "\t" << v.x[1] << "\t" << v.x[2] << "\t";
     152    if (comment != NULL)
     153      *out << " # " << comment << endl;
     154    else
     155      *out << " # molecule nr " << nr << endl;
     156    return true;
     157  } else
     158    return false;
     159};
    104160
    105161/** Output of a single atom as one lin in xyz file.
    106162 * \param *out stream to output to
     163  * \return true - \a *out present, false - \a *out is NULL
    107164 */
    108165bool atom::OutputXYZLine(ofstream *out) const
     
    110167  if (out != NULL) {
    111168    *out << type->symbol << "\t" << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2] << "\t" << endl;
     169    return true;
     170  } else
     171    return false;
     172};
     173
     174/** Output of a single atom as one lin in xyz file.
     175 * \param *out stream to output to
     176 * \param *ElementNo array with ion type number in the config file this atom's element shall have
     177 * \param *AtomNo array with atom number in the config file this atom shall have, is increase by one automatically
     178 * \param step Trajectory time step to output
     179  * \return true - \a *out present, false - \a *out is NULL
     180 */
     181bool atom::OutputTrajectory(ofstream *out, int *ElementNo, int *AtomNo, int step) const
     182{
     183  AtomNo[type->Z]++;
     184  if (out != NULL) {
     185    *out << "Ion_Type" << ElementNo[type->Z] << "_" << AtomNo[type->Z] << "\t"  << fixed << setprecision(9) << showpoint;
     186    *out << Trajectory.R.at(step).x[0] << "\t" << Trajectory.R.at(step).x[1] << "\t" << Trajectory.R.at(step).x[2];
     187    *out << "\t" << FixedIon;
     188    if (Trajectory.U.at(step).Norm() > MYEPSILON)
     189      *out << "\t" << scientific << setprecision(6) << Trajectory.U.at(step).x[0] << "\t" << Trajectory.U.at(step).x[1] << "\t" << Trajectory.U.at(step).x[2] << "\t";
     190    if (Trajectory.F.at(step).Norm() > MYEPSILON)
     191      *out << "\t" << scientific << setprecision(6) << Trajectory.F.at(step).x[0] << "\t" << Trajectory.F.at(step).x[1] << "\t" << Trajectory.F.at(step).x[2] << "\t";
     192    *out << "\t# Number in molecule " << nr << endl;
     193    return true;
     194  } else
     195    return false;
     196};
     197
     198/** Output of a single atom as one lin in xyz file.
     199 * \param *out stream to output to
     200 * \param step Trajectory time step to output
     201 * \return true - \a *out present, false - \a *out is NULL
     202 */
     203bool atom::OutputTrajectoryXYZ(ofstream *out, int step) const
     204{
     205  if (out != NULL) {
     206    *out << type->symbol << "\t";
     207    *out << Trajectory.R.at(step).x[0] << "\t";
     208    *out << Trajectory.R.at(step).x[1] << "\t";
     209    *out << Trajectory.R.at(step).x[2] << endl;
     210    return true;
     211  } else
     212    return false;
     213};
     214
     215/** Prints all bonds of this atom from given global lists.
     216 * \param *out stream to output to
     217 * \param *NumberOfBondsPerAtom array with number of bonds per atomic index
     218 * \param ***ListOfBondsPerAtom array per atomic index of array with pointer to bond
     219 * \return true - \a *out present, false - \a *out is NULL
     220 */
     221bool atom::OutputBondOfAtom(ofstream *out, int *NumberOfBondsPerAtom, bond ***ListOfBondsPerAtom) const
     222{
     223  if (out != NULL) {
     224#ifdef ADDHYDROGEN
     225    if (type->Z != 1) {   // regard only non-hydrogen
     226#endif
     227      *out << Verbose(4) << "Atom " << Name << "/" << nr << " with " << NumberOfBondsPerAtom[nr] << " bonds: ";
     228      int TotalDegree = 0;
     229      for (int j=0;j<NumberOfBondsPerAtom[nr];j++) {
     230        *out << *ListOfBondsPerAtom[nr][j] << "\t";
     231        TotalDegree += ListOfBondsPerAtom[nr][j]->BondDegree;
     232      }
     233      *out << " -- TotalDegree: " << TotalDegree << endl;
     234#ifdef ADDHYDROGEN
     235    }
     236#endif
    112237    return true;
    113238  } else
     
    139264};
    140265
     266/** Returns squared distance to a given vector.
     267 * \param origin vector to calculate distance to
     268 * \return distance squared
     269 */
     270double atom::DistanceSquaredToVector(Vector &origin)
     271{
     272  return origin.DistanceSquared(&x);
     273};
     274
     275/** Adds kinetic energy of this atom to given temperature value.
     276 * \param *temperature add on this value
     277 * \param step given step of trajectory to add
     278 */
     279void atom::AddKineticToTemperature(double *temperature, int step) const
     280{
     281  for (int i=NDIM;i--;)
     282    *temperature += type->mass * Trajectory.U.at(step).x[i]* Trajectory.U.at(step).x[i];
     283};
     284
     285/** Returns distance to a given vector.
     286 * \param origin vector to calculate distance to
     287 * \return distance
     288 */
     289double atom::DistanceToVector(Vector &origin)
     290{
     291  return origin.Distance(&x);
     292};
     293
    141294bool operator < (atom &a, atom &b)
    142295{
  • src/atom.hpp

    r87e2e39 rc111db  
    1111using namespace std;
    1212
     13/*********************************************** includes ***********************************/
     14
    1315// include config.h
    1416#ifdef HAVE_CONFIG_H
     
    1618#endif
    1719
     20#include <iostream>
     21#include <vector>
    1822
    19 #include <iostream>
     23#include "tesselation.hpp"
    2024
    21 #include "element.hpp"
    22 #include "tesselation.hpp"
    23 #include "vector.hpp"
     25/****************************************** forward declarations *****************************/
     26
     27class bond;
     28class element;
     29class Vector;
     30
     31/********************************************** declarations *******************************/
    2432
    2533/** Single atom.
     
    2836class atom : public TesselPoint {
    2937  public:
    30     Vector x;       //!< coordinate array of atom, giving position within cell
    31     Vector v;       //!< velocity array of atom
     38    struct
     39    {
     40      vector<Vector> R;  //!< position vector
     41      vector<Vector> U;  //!< velocity vector
     42      vector<Vector> F;  //!< last force vector
     43    } Trajectory;
     44
     45    Vector x;       //!< coordinate vector of atom, giving last position within cell
     46    Vector v;       //!< velocity vector of atom, giving last velocity within cell
     47    Vector F;       //!< Force vector of atom, giving last force within cell
    3248    element *type;  //!< pointing to element
    3349    atom *previous; //!< previous atom in molecule list
     
    5167  virtual ~atom();
    5268
    53   bool Output(int ElementNo, int AtomNo, ofstream *out, const char *comment = NULL) const;
     69  bool Output(ofstream *out, int ElementNo, int AtomNo, const char *comment = NULL) const;
     70  bool Output(ofstream *out, int *ElementNo, int *AtomNo, const char *comment = NULL);
    5471  bool OutputXYZLine(ofstream *out) const;
     72  bool OutputTrajectory(ofstream *out, int *ElementNo, int *AtomNo, int step) const;
     73  bool OutputTrajectoryXYZ(ofstream *out, int step) const;
     74  bool OutputBondOfAtom(ofstream *out, int *NumberOfBondsPerAtom, bond ***ListOfBondsPerAtom) const;
     75
     76  void EqualsFather ( atom *ptr, atom **res );
     77  void CorrectFather();
    5578  atom *GetTrueFather();
    5679  bool Compare(const atom &ptr);
     80
     81  double DistanceToVector(Vector &origin);
     82  double DistanceSquaredToVector(Vector &origin);
     83
     84  void AddKineticToTemperature(double *temperature, int step) const;
     85
     86  bool IsInParallelepiped(Vector offset, double *parallelepiped);
    5787
    5888  ostream & operator << (ostream &ost);
  • src/bond.cpp

    r87e2e39 rc111db  
    55 */
    66
     7#include "atom.hpp"
    78#include "bond.hpp"
     9#include "element.hpp"
     10#include "lists.hpp"
     11
    812
    913/***************************************** Functions for class bond ********************************/
  • src/bond.hpp

    r87e2e39 rc111db  
    1111using namespace std;
    1212
     13/*********************************************** includes ***********************************/
     14
    1315// include config.h
    1416#ifdef HAVE_CONFIG_H
     
    1618#endif
    1719
    18 #include "atom.hpp"
     20/****************************************** forward declarations *****************************/
     21
     22class atom;
     23
     24/********************************************** declarations *******************************/
    1925
    2026/** Bonds between atoms.
  • src/boundary.cpp

    r87e2e39 rc111db  
    1 /** \file boundary.hpp
     1/** \file boundary.cpp
    22 *
    33 * Implementations and super-function for envelopes
    44 */
    55
    6 
     6#include "atom.hpp"
     7#include "bond.hpp"
    78#include "boundary.hpp"
     9#include "config.hpp"
     10#include "element.hpp"
     11#include "helpers.hpp"
     12#include "linkedcell.hpp"
    813#include "memoryallocator.hpp"
     14#include "molecule.hpp"
     15#include "tesselation.hpp"
     16#include "tesselationhelpers.hpp"
    917
    1018#include<gsl/gsl_poly.h>
     
    2129 * \return NDIM array of the diameters
    2230 */
    23 double *
    24 GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol,
    25     bool IsAngstroem)
     31double *GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem)
    2632{
    2733  // get points on boundary of NULL was given as parameter
     
    113119;
    114120
    115 /** Creates the objects in a VRML file.
    116  * \param *out output stream for debugging
    117  * \param *vrmlfile output stream for tecplot data
    118  * \param *Tess Tesselation structure with constructed triangles
    119  * \param *mol molecule structure with atom positions
    120  */
    121 void WriteVrmlFile(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, class molecule *mol)
    122 {
    123   atom *Walker = mol->start;
    124   bond *Binder = mol->first;
    125   int i;
    126   Vector *center = mol->DetermineCenterOfAll(out);
    127   if (vrmlfile != NULL) {
    128     //cout << Verbose(1) << "Writing Raster3D file ... ";
    129     *vrmlfile << "#VRML V2.0 utf8" << endl;
    130     *vrmlfile << "#Created by molecuilder" << endl;
    131     *vrmlfile << "#All atoms as spheres" << endl;
    132     while (Walker->next != mol->end) {
    133       Walker = Walker->next;
    134       *vrmlfile << "Sphere {" << endl << "  "; // 2 is sphere type
    135       for (i=0;i<NDIM;i++)
    136         *vrmlfile << Walker->x.x[i]-center->x[i] << " ";
    137       *vrmlfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
    138     }
    139 
    140     *vrmlfile << "# All bonds as vertices" << endl;
    141     while (Binder->next != mol->last) {
    142       Binder = Binder->next;
    143       *vrmlfile << "3" << endl << "  "; // 2 is round-ended cylinder type
    144       for (i=0;i<NDIM;i++)
    145         *vrmlfile << Binder->leftatom->x.x[i]-center->x[i] << " ";
    146       *vrmlfile << "\t0.03\t";
    147       for (i=0;i<NDIM;i++)
    148         *vrmlfile << Binder->rightatom->x.x[i]-center->x[i] << " ";
    149       *vrmlfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
    150     }
    151 
    152     *vrmlfile << "# All tesselation triangles" << endl;
    153     for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
    154       *vrmlfile << "1" << endl << "  "; // 1 is triangle type
    155       for (i=0;i<3;i++) { // print each node
    156         for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
    157           *vrmlfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";
    158         *vrmlfile << "\t";
    159       }
    160       *vrmlfile << "1. 0. 0." << endl;  // red as colour
    161       *vrmlfile << "18" << endl << "  0.5 0.5 0.5" << endl; // 18 is transparency type for previous object
    162     }
    163   } else {
    164     cerr << "ERROR: Given vrmlfile is " << vrmlfile << "." << endl;
    165   }
    166   delete(center);
    167 };
    168 
    169 /** Creates the objects in a raster3d file (renderable with a header.r3d).
    170  * \param *out output stream for debugging
    171  * \param *rasterfile output stream for tecplot data
    172  * \param *Tess Tesselation structure with constructed triangles
    173  * \param *mol molecule structure with atom positions
    174  */
    175 void WriteRaster3dFile(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, class molecule *mol)
    176 {
    177   atom *Walker = mol->start;
    178   bond *Binder = mol->first;
    179   int i;
    180   Vector *center = mol->DetermineCenterOfAll(out);
    181   if (rasterfile != NULL) {
    182     //cout << Verbose(1) << "Writing Raster3D file ... ";
    183     *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl;
    184     *rasterfile << "@header.r3d" << endl;
    185     *rasterfile << "# All atoms as spheres" << endl;
    186     while (Walker->next != mol->end) {
    187       Walker = Walker->next;
    188       *rasterfile << "2" << endl << "  ";  // 2 is sphere type
    189       for (i=0;i<NDIM;i++)
    190         *rasterfile << Walker->x.x[i]-center->x[i] << " ";
    191       *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
    192     }
    193 
    194     *rasterfile << "# All bonds as vertices" << endl;
    195     while (Binder->next != mol->last) {
    196       Binder = Binder->next;
    197       *rasterfile << "3" << endl << "  ";  // 2 is round-ended cylinder type
    198       for (i=0;i<NDIM;i++)
    199         *rasterfile << Binder->leftatom->x.x[i]-center->x[i] << " ";
    200       *rasterfile << "\t0.03\t";
    201       for (i=0;i<NDIM;i++)
    202         *rasterfile << Binder->rightatom->x.x[i]-center->x[i] << " ";
    203       *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
    204     }
    205 
    206     *rasterfile << "# All tesselation triangles" << endl;
    207     *rasterfile << "8\n  25. -1.   1. 1. 1.   0.0    0 0 0 2\n  SOLID     1.0 0.0 0.0\n  BACKFACE  0.3 0.3 1.0   0 0\n";
    208     for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
    209       *rasterfile << "1" << endl << "  ";  // 1 is triangle type
    210       for (i=0;i<3;i++) {  // print each node
    211         for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
    212           *rasterfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";
    213         *rasterfile << "\t";
    214       }
    215       *rasterfile << "1. 0. 0." << endl;  // red as colour
    216       //*rasterfile << "18" << endl << "  0.5 0.5 0.5" << endl;  // 18 is transparency type for previous object
    217     }
    218     *rasterfile << "9\n#  terminating special property\n";
    219   } else {
    220     cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl;
    221   }
    222   delete(center);
    223 };
    224 
    225 /** This function creates the tecplot file, displaying the tesselation of the hull.
    226  * \param *out output stream for debugging
    227  * \param *tecplot output stream for tecplot data
    228  * \param N arbitrary number to differentiate various zones in the tecplot format
    229  */
    230 void WriteTecplotFile(ofstream *out, ofstream *tecplot, class Tesselation *TesselStruct, class molecule *mol, int N)
    231 {
    232   if ((tecplot != NULL) && (TesselStruct != NULL)) {
    233     // write header
    234     *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;
    235     *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\" \"U\"" << endl;
    236     *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N=" << TesselStruct->PointsOnBoundary.size() << ", E=" << TesselStruct->TrianglesOnBoundary.size() << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
    237     int *LookupList = new int[mol->AtomCount];
    238     for (int i = 0; i < mol->AtomCount; i++)
    239       LookupList[i] = -1;
    240 
    241     // print atom coordinates
    242     *out << Verbose(2) << "The following triangles were created:";
    243     int Counter = 1;
    244     TesselPoint *Walker = NULL;
    245     for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target != TesselStruct->PointsOnBoundary.end(); target++) {
    246       Walker = target->second->node;
    247       LookupList[Walker->nr] = Counter++;
    248       *tecplot << Walker->node->x[0] << " " << Walker->node->x[1] << " " << Walker->node->x[2] << " " << target->second->value << endl;
    249     }
    250     *tecplot << endl;
    251     // print connectivity
    252     for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) {
    253       *out << " " << runner->second->endpoints[0]->node->Name << "<->" << runner->second->endpoints[1]->node->Name << "<->" << runner->second->endpoints[2]->node->Name;
    254       *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl;
    255     }
    256     delete[] (LookupList);
    257     *out << endl;
    258   }
    259 }
    260 
    261121
    262122/** Determines the boundary points of a cluster.
     
    537397
    538398        // flip the line
    539         if (!mol->TesselStruct->PickFarthestofTwoBaselines(out, line))
     399        if (mol->TesselStruct->PickFarthestofTwoBaselines(out, line) == 0.)
    540400          *out << Verbose(1) << "ERROR: Correction of concave baselines failed!" << endl;
    541         else
     401        else {
     402          mol->TesselStruct->FlipBaseline(out, line);
    542403          *out << Verbose(1) << "INFO: Correction of concave baselines worked." << endl;
     404        }
    543405      }
    544406    }
     
    577439
    578440  cout << Verbose(1) << "End of FindConvexBorder" << endl;
     441};
     442
     443/** For testing removes one boundary point after another to check for leaks.
     444 * \param *out output stream for debugging
     445 * \param *TesselStruct Tesselation containing envelope with boundary points
     446 * \param *mol molecule
     447 * \param *filename name of file
     448 * \return true - all removed, false - something went wrong
     449 */
     450bool RemoveAllBoundaryPoints(ofstream *out, class Tesselation *TesselStruct, molecule *mol, char *filename)
     451{
     452  int i=0;
     453  char number[MAXSTRINGSIZE];
     454
     455  if ((TesselStruct == NULL) || (TesselStruct->PointsOnBoundary.empty())) {
     456    *out << Verbose(2) << "ERROR: TesselStruct is empty." << endl;
     457    return false;
     458  }
     459
     460  PointMap::iterator PointRunner;
     461  while (!TesselStruct->PointsOnBoundary.empty()) {
     462    *out << Verbose(2) << "Remaining points are: ";
     463    for (PointMap::iterator PointSprinter = TesselStruct->PointsOnBoundary.begin(); PointSprinter != TesselStruct->PointsOnBoundary.end(); PointSprinter++)
     464      *out << *(PointSprinter->second) << "\t";
     465      *out << endl;
     466
     467    PointRunner = TesselStruct->PointsOnBoundary.begin();
     468    // remove point
     469    TesselStruct->RemovePointFromTesselatedSurface(out, PointRunner->second);
     470
     471    // store envelope
     472    sprintf(number, "-%04d", i++);
     473    StoreTrianglesinFile(out, mol, filename, number);
     474  }
     475
     476  return true;
    579477};
    580478
     
    609507  class BoundaryLineSet *line = NULL;
    610508  bool Concavity;
     509  char dummy[MAXSTRINGSIZE];
    611510  PointMap::iterator PointRunner, PointAdvance;
    612511  LineMap::iterator LineRunner, LineAdvance;
     
    621520  }
    622521
    623   //CalculateConcavityPerBoundaryPoint(out, TesselStruct);
    624   StoreTrianglesinFile(out, mol, filename, "-first");
    625 
    626522  // First step: RemovePointFromTesselatedSurface
     523  int run = 0;
     524  double tmp;
    627525  do {
    628526    Concavity = false;
     527    sprintf(dummy, "-first-%d", run);
     528    //CalculateConcavityPerBoundaryPoint(out, TesselStruct);
     529    StoreTrianglesinFile(out, mol, filename, dummy);
     530
    629531    PointRunner = TesselStruct->PointsOnBoundary.begin();
    630532    PointAdvance = PointRunner; // we need an advanced point, as the PointRunner might get removed
     
    636538        line = LineRunner->second;
    637539        *out << Verbose(2) << "INFO: Current line of point " << *point << " is " << *line << "." << endl;
    638       }
    639       if (!line->CheckConvexityCriterion(out)) {
    640         *out << Verbose(1) << "... point " << *point << " cannot be on convex envelope." << endl;
    641         // remove the point
    642         Concavity = true;
    643         TesselStruct->RemovePointFromTesselatedSurface(out, point);
     540        if (!line->CheckConvexityCriterion(out)) {
     541          // remove the point if needed
     542          *out << Verbose(1) << "... point " << *point << " cannot be on convex envelope." << endl;
     543          volume += TesselStruct->RemovePointFromTesselatedSurface(out, point);
     544          sprintf(dummy, "-first-%d", ++run);
     545          StoreTrianglesinFile(out, mol, filename, dummy);
     546          Concavity = true;
     547          break;
     548        }
    644549      }
    645550      PointRunner = PointAdvance;
    646551    }
    647552
     553    sprintf(dummy, "-second-%d", run);
    648554    //CalculateConcavityPerBoundaryPoint(out, TesselStruct);
    649     //StoreTrianglesinFile(out, mol, filename, "-second");
     555    StoreTrianglesinFile(out, mol, filename, dummy);
    650556
    651557    // second step: PickFarthestofTwoBaselines
     
    658564      // take highest of both lines
    659565      if (TesselStruct->IsConvexRectangle(out, line) == NULL) {
    660         TesselStruct->PickFarthestofTwoBaselines(out, line);
    661         Concavity = true;
     566        tmp = TesselStruct->PickFarthestofTwoBaselines(out, line);
     567        volume += tmp;
     568        if (tmp != 0) {
     569          mol->TesselStruct->FlipBaseline(out, line);
     570          Concavity = true;
     571        }
    662572      }
    663573      LineRunner = LineAdvance;
    664574    }
     575    run++;
    665576  } while (Concavity);
     577  //CalculateConcavityPerBoundaryPoint(out, TesselStruct);
     578  //StoreTrianglesinFile(out, mol, filename, "-third");
     579
     580  // third step: IsConvexRectangle
     581//  LineRunner = TesselStruct->LinesOnBoundary.begin();
     582//  LineAdvance = LineRunner;  // we need an advanced line, as the LineRunner might get removed
     583//  while (LineRunner != TesselStruct->LinesOnBoundary.end()) {
     584//    LineAdvance++;
     585//    line = LineRunner->second;
     586//    *out << Verbose(1) << "INFO: Current line is " << *line << "." << endl;
     587//    //if (LineAdvance != TesselStruct->LinesOnBoundary.end())
     588//      //*out << Verbose(1) << "INFO: Next line will be " << *(LineAdvance->second) << "." << endl;
     589//    if (!line->CheckConvexityCriterion(out)) {
     590//      *out << Verbose(1) << "... line " << *line << " is concave, flipping it." << endl;
     591//
     592//      // take highest of both lines
     593//      point = TesselStruct->IsConvexRectangle(out, line);
     594//      if (point != NULL)
     595//        volume += TesselStruct->RemovePointFromTesselatedSurface(out, point);
     596//    }
     597//    LineRunner = LineAdvance;
     598//  }
     599
    666600  CalculateConcavityPerBoundaryPoint(out, TesselStruct);
    667   StoreTrianglesinFile(out, mol, filename, "-third");
    668 
    669   // third step: IsConvexRectangle
    670   LineRunner = TesselStruct->LinesOnBoundary.begin();
    671   LineAdvance = LineRunner;  // we need an advanced line, as the LineRunner might get removed
    672   while (LineRunner != TesselStruct->LinesOnBoundary.end()) {
    673     LineAdvance++;
    674     line = LineRunner->second;
    675     *out << Verbose(1) << "INFO: Current line is " << *line << "." << endl;
    676     //if (LineAdvance != TesselStruct->LinesOnBoundary.end())
    677       //*out << Verbose(1) << "INFO: Next line will be " << *(LineAdvance->second) << "." << endl;
    678     if (!line->CheckConvexityCriterion(out)) {
    679       *out << Verbose(1) << "... line " << *line << " is concave, flipping it." << endl;
    680 
    681       // take highest of both lines
    682       point = TesselStruct->IsConvexRectangle(out, line);
    683       if (point != NULL)
    684         TesselStruct->RemovePointFromTesselatedSurface(out, point);
    685     }
    686     LineRunner = LineAdvance;
    687   }
    688 
    689   CalculateConcavityPerBoundaryPoint(out, TesselStruct);
    690   StoreTrianglesinFile(out, mol, filename, "-fourth");
     601  StoreTrianglesinFile(out, mol, filename, "");
    691602
    692603  // end
     604  *out << Verbose(1) << "Volume is " << volume << "." << endl;
    693605  *out << Verbose(0) << "End of ConvexizeNonconvexEnvelope" << endl;
    694606  return volume;
    695607};
    696608
    697 /** Calculates the concavity for each of the BoundaryPointSet's in a Tesselation.
    698  * Sets BoundaryPointSet::value equal to the number of connected lines that are not convex.
    699  * \param *out output stream for debugging
    700  * \param *TesselStruct pointer to Tesselation structure
    701  */
    702 void CalculateConcavityPerBoundaryPoint(ofstream *out, class Tesselation *TesselStruct)
    703 {
    704   class BoundaryPointSet *point = NULL;
    705   class BoundaryLineSet *line = NULL;
    706   // calculate remaining concavity
    707   for (PointMap::iterator PointRunner = TesselStruct->PointsOnBoundary.begin(); PointRunner != TesselStruct->PointsOnBoundary.end(); PointRunner++) {
    708     point = PointRunner->second;
    709     *out << Verbose(1) << "INFO: Current point is " << *point << "." << endl;
    710     point->value = 0;
    711     for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) {
    712       line = LineRunner->second;
    713       *out << Verbose(2) << "INFO: Current line of point " << *point << " is " << *line << "." << endl;
    714       if (!line->CheckConvexityCriterion(out))
    715         point->value += 1;
    716     }
    717   }
    718 };
    719 
    720 /** Stores triangles to file.
    721  * \param *out output stream for debugging
    722  * \param *mol molecule with atoms and bonds
    723  * \param *filename prefix of filename
    724  * \param *extraSuffix intermediate suffix
    725  */
    726 void StoreTrianglesinFile(ofstream *out, molecule *mol, const char *filename, const char *extraSuffix)
    727 {
    728   // 4. Store triangles in tecplot file
    729   if (filename != NULL) {
    730     if (DoTecplotOutput) {
    731       string OutputName(filename);
    732       OutputName.append(extraSuffix);
    733       OutputName.append(TecplotSuffix);
    734       ofstream *tecplot = new ofstream(OutputName.c_str());
    735       WriteTecplotFile(out, tecplot, mol->TesselStruct, mol, 0);
    736       tecplot->close();
    737       delete(tecplot);
    738     }
    739     if (DoRaster3DOutput) {
    740       string OutputName(filename);
    741       OutputName.append(extraSuffix);
    742       OutputName.append(Raster3DSuffix);
    743       ofstream *rasterplot = new ofstream(OutputName.c_str());
    744       WriteRaster3dFile(out, rasterplot, mol->TesselStruct, mol);
    745       rasterplot->close();
    746       delete(rasterplot);
    747     }
    748   }
    749 };
    750609
    751610/** Determines the volume of a cluster.
     
    794653
    795654  return volume;
    796 }
    797 ;
     655};
     656
     657/** Stores triangles to file.
     658 * \param *out output stream for debugging
     659 * \param *mol molecule with atoms and bonds
     660 * \param *filename prefix of filename
     661 * \param *extraSuffix intermediate suffix
     662 */
     663void StoreTrianglesinFile(ofstream *out, molecule *mol, const char *filename, const char *extraSuffix)
     664{
     665  // 4. Store triangles in tecplot file
     666  if (filename != NULL) {
     667    if (DoTecplotOutput) {
     668      string OutputName(filename);
     669      OutputName.append(extraSuffix);
     670      OutputName.append(TecplotSuffix);
     671      ofstream *tecplot = new ofstream(OutputName.c_str());
     672      WriteTecplotFile(out, tecplot, mol->TesselStruct, mol, 0);
     673      tecplot->close();
     674      delete(tecplot);
     675    }
     676    if (DoRaster3DOutput) {
     677      string OutputName(filename);
     678      OutputName.append(extraSuffix);
     679      OutputName.append(Raster3DSuffix);
     680      ofstream *rasterplot = new ofstream(OutputName.c_str());
     681      WriteRaster3dFile(out, rasterplot, mol->TesselStruct, mol);
     682      rasterplot->close();
     683      delete(rasterplot);
     684    }
     685  }
     686};
    798687
    799688/** Creates multiples of the by \a *mol given cluster and suspends them in water with a given final density.
     
    939828  int N[NDIM];
    940829  int n[NDIM];
    941   double *M =  filler->ReturnFullMatrixforSymmetric(filler->cell_size);
     830  double *M =  ReturnFullMatrixforSymmetric(filler->cell_size);
    942831  double Rotations[NDIM*NDIM];
    943832  Vector AtomTranslations;
     
    958847    if ((*ListRunner)->TesselStruct == NULL) {
    959848      *out << Verbose(1) << "Pre-creating tesselation for molecule " << *ListRunner << "." << endl;
    960       FindNonConvexBorder((ofstream *)&cout, (*ListRunner), LCList[i], NULL, 5.);
     849      FindNonConvexBorder((ofstream *)&cout, (*ListRunner), LCList[i], 5., NULL);
    961850    }
    962851    i++;
     
    1080969 * \param *Tess Tesselation filled with points, lines and triangles on boundary on return
    1081970 * \param *LCList atoms in LinkedCell list
     971 * \param RADIUS radius of the virtual sphere
    1082972 * \param *filename filename prefix for output of vertex data
    1083  * \para RADIUS radius of the virtual sphere
    1084  */
    1085 void FindNonConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LCList, const char *filename, const double RADIUS)
     973 */
     974void FindNonConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LCList, const double RADIUS, const char *filename = NULL)
    1086975{
    1087   int N = 0;
    1088976  bool freeLC = false;
    1089   ofstream *tempstream = NULL;
    1090   char NumberName[255];
    1091   int TriangleFilesWritten = 0;
    1092977
    1093978  *out << Verbose(1) << "Entering search for non convex hull. " << endl;
     
    1103988  LineMap::iterator testline;
    1104989  *out << Verbose(0) << "Begin of FindNonConvexBorder\n";
    1105   bool flag = false;  // marks whether we went once through all baselines without finding any without two triangles
    1106   bool failflag = false;
    1107 
     990  bool OneLoopWithoutSuccessFlag = false;  // marks whether we went once through all baselines without finding any without two triangles
     991  bool TesselationFailFlag = false;
     992
     993  // initialise Linked Cell
    1108994  if (LCList == NULL) {
    1109995    LCList = new LinkedCell(mol, 2.*RADIUS);
     
    1111997  }
    1112998
     999  // 1. get starting triangle
    11131000  mol->TesselStruct->FindStartingTriangle(out, RADIUS, LCList);
    11141001
     1002  // 2. expand from there
    11151003  baseline = mol->TesselStruct->LinesOnBoundary.begin();
    1116   // the outward most line is dangerous, as we may end up with wrapping up the starting triangle, hence
    1117   // terminating the algorithm too early.
    1118   if (baseline != mol->TesselStruct->LinesOnBoundary.end()) // skip first line as it its the outwardmost!
    1119         baseline++;
    1120   while ((baseline != mol->TesselStruct->LinesOnBoundary.end()) || (flag)) {
     1004  baseline++; // skip first line
     1005  while ((baseline != mol->TesselStruct->LinesOnBoundary.end()) || (OneLoopWithoutSuccessFlag)) {
    11211006    if (baseline->second->triangles.size() == 1) {
    1122       failflag = mol->TesselStruct->FindNextSuitableTriangle(out, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, LCList); //the line is there, so there is a triangle, but only one.
    1123       flag = flag || failflag;
    1124       if (!failflag)
     1007      // 3. find next triangle
     1008      TesselationFailFlag = mol->TesselStruct->FindNextSuitableTriangle(out, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, LCList); //the line is there, so there is a triangle, but only one.
     1009      OneLoopWithoutSuccessFlag = OneLoopWithoutSuccessFlag || TesselationFailFlag;
     1010      if (!TesselationFailFlag)
    11251011        cerr << "WARNING: FindNextSuitableTriangle failed." << endl;
     1012
    11261013      // write temporary envelope
    1127       if ((DoSingleStepOutput && (mol->TesselStruct->TrianglesOnBoundaryCount % SingleStepWidth == 0))) { // if we have a new triangle and want to output each new triangle configuration
    1128         TriangleMap::iterator runner = mol->TesselStruct->TrianglesOnBoundary.end();
    1129         runner--;
    1130         class BoundaryTriangleSet *triangle = runner->second;
    1131         if (triangle != NULL) {
    1132           sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, triangle->endpoints[0]->node->Name, triangle->endpoints[1]->node->Name, triangle->endpoints[2]->node->Name);
    1133           if (DoTecplotOutput) {
    1134             string NameofTempFile(filename);
    1135             NameofTempFile.append(NumberName);
    1136             for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
    1137             NameofTempFile.erase(npos, 1);
    1138             NameofTempFile.append(TecplotSuffix);
    1139             *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    1140             tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    1141             WriteTecplotFile(out, tempstream, mol->TesselStruct, mol, TriangleFilesWritten);
    1142             tempstream->close();
    1143             tempstream->flush();
    1144             delete(tempstream);
    1145           }
    1146 
    1147           if (DoRaster3DOutput) {
    1148             string NameofTempFile(filename);
    1149             NameofTempFile.append(NumberName);
    1150             for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
    1151             NameofTempFile.erase(npos, 1);
    1152             NameofTempFile.append(Raster3DSuffix);
    1153             *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    1154             tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    1155             WriteRaster3dFile(out, tempstream, mol->TesselStruct, mol);
    1156     //        // include the current position of the virtual sphere in the temporary raster3d file
    1157     //        // make the circumsphere's center absolute again
    1158     //        helper.CopyVector(BaseRay->endpoints[0]->node->node);
    1159     //        helper.AddVector(BaseRay->endpoints[1]->node->node);
    1160     //        helper.Scale(0.5);
    1161     //        (*it)->OptCenter.AddVector(&helper);
    1162     //        Vector *center = mol->DetermineCenterOfAll(out);
    1163     //        (*it)->OptCenter.SubtractVector(center);
    1164     //        delete(center);
    1165     //        // and add to file plus translucency object
    1166     //        *tempstream << "# current virtual sphere\n";
    1167     //        *tempstream << "8\n  25.0    0.6     -1.0 -1.0 -1.0     0.2        0 0 0 0\n";
    1168     //        *tempstream << "2\n  " << (*it)->OptCenter.x[0] << " "
    1169     //          << (*it)->OptCenter.x[1] << " " << (*it)->OptCenter.x[2]
    1170     //          << "\t" << RADIUS << "\t1 0 0\n";
    1171     //        *tempstream << "9\n  terminating special property\n";
    1172             tempstream->close();
    1173             tempstream->flush();
    1174             delete(tempstream);
    1175           }
    1176         }
    1177         if (DoTecplotOutput || DoRaster3DOutput)
    1178           TriangleFilesWritten++;
     1014      if (filename != NULL) {
     1015        if ((DoSingleStepOutput && ((mol->TesselStruct->TrianglesOnBoundary.size() % SingleStepWidth == 0)))) { // if we have a new triangle and want to output each new triangle configuration
     1016          mol->TesselStruct->Output(out, filename, mol);
     1017        }
    11791018      }
     1019      baseline = mol->TesselStruct->LinesOnBoundary.end();
     1020      *out << Verbose(2) << "Baseline set to end." << endl;
    11801021    } else {
    11811022      //cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->triangles.size() << " triangles adjacent" << endl;
     
    11841025    }
    11851026
    1186     N++;
     1027    if ((baseline == mol->TesselStruct->LinesOnBoundary.end()) && (OneLoopWithoutSuccessFlag)) {
     1028      baseline = mol->TesselStruct->LinesOnBoundary.begin();   // restart if we reach end due to newly inserted lines
     1029      OneLoopWithoutSuccessFlag = false;
     1030    }
    11871031    baseline++;
    1188     if ((baseline == mol->TesselStruct->LinesOnBoundary.end()) && (flag)) {
    1189       baseline = mol->TesselStruct->LinesOnBoundary.begin();   // restart if we reach end due to newly inserted lines
    1190       flag = false;
    1191     }
    1192   }
     1032  }
     1033  // check envelope for consistency
     1034  CheckListOfBaselines(out, mol->TesselStruct);
     1035
     1036  // look whether all points are inside of the convex envelope, otherwise add them via degenerated triangles
     1037  //mol->TesselStruct->InsertStraddlingPoints(out, mol, LCList);
     1038//  mol->GoToFirst();
     1039//  class TesselPoint *Runner = NULL;
     1040//  while (!mol->IsEnd()) {
     1041//    Runner = mol->GetPoint();
     1042//    *out << Verbose(1) << "Checking on " << Runner->Name << " ... " << endl;
     1043//    if (!mol->TesselStruct->IsInnerPoint(out, Runner, LCList)) {
     1044//      *out << Verbose(2) << Runner->Name << " is outside of envelope, adding via degenerated triangles." << endl;
     1045//      mol->TesselStruct->AddBoundaryPointByDegeneratedTriangle(out, Runner, LCList);
     1046//    } else {
     1047//      *out << Verbose(2) << Runner->Name << " is inside of or on envelope." << endl;
     1048//    }
     1049//    mol->GoToNext();
     1050//  }
    11931051
    11941052  // Purges surplus triangles.
    11951053  mol->TesselStruct->RemoveDegeneratedTriangles();
    11961054
     1055  // check envelope for consistency
     1056  CheckListOfBaselines(out, mol->TesselStruct);
     1057
    11971058  // write final envelope
    1198   if (filename != 0) {
    1199     *out << Verbose(1) << "Writing final tecplot file\n";
    1200     if (DoTecplotOutput) {
    1201       string OutputName(filename);
    1202       OutputName.append(TecplotSuffix);
    1203       ofstream *tecplot = new ofstream(OutputName.c_str());
    1204       WriteTecplotFile(out, tecplot, mol->TesselStruct, mol, -1);
    1205       tecplot->close();
    1206       delete(tecplot);
    1207     }
    1208     if (DoRaster3DOutput) {
    1209       string OutputName(filename);
    1210       OutputName.append(Raster3DSuffix);
    1211       ofstream *raster = new ofstream(OutputName.c_str());
    1212       WriteRaster3dFile(out, raster, mol->TesselStruct, mol);
    1213       raster->close();
    1214       delete(raster);
    1215     }
    1216   } else {
    1217     cerr << "ERROR: Could definitively not find all necessary triangles!" << endl;
    1218   }
    1219 
    1220   cout << Verbose(2) << "Check: List of Baselines with not two connected triangles:" << endl;
    1221   int counter = 0;
    1222   for (testline = mol->TesselStruct->LinesOnBoundary.begin(); testline != mol->TesselStruct->LinesOnBoundary.end(); testline++) {
    1223     if (testline->second->triangles.size() != 2) {
    1224       cout << Verbose(2) << *testline->second << "\t" << testline->second->triangles.size() << endl;
    1225       counter++;
    1226     }
    1227   }
    1228   if (counter == 0)
    1229     *out << Verbose(2) << "None." << endl;
    1230 
    1231 //  // Tests the IsInnerAtom() function.
    1232 //  Vector x (0, 0, 0);
    1233 //  *out << Verbose(0) << "Point to check: " << x << endl;
    1234 //  *out << Verbose(0) << "Check: IsInnerPoint() returns " << mol->TesselStruct->IsInnerPoint(out, x, LCList)
    1235 //    << "for vector " << x << "." << endl;
    1236 //  TesselPoint* a = mol->TesselStruct->PointsOnBoundary.begin()->second->node;
    1237 //  *out << Verbose(0) << "Point to check: " << *a << " (on boundary)." << endl;
    1238 //  *out << Verbose(0) << "Check: IsInnerAtom() returns " << mol->TesselStruct->IsInnerPoint(out, a, LCList)
    1239 //    << "for atom " << a << " (on boundary)." << endl;
    1240 //  LinkedNodes *List = NULL;
    1241 //  for (int i=0;i<NDIM;i++) { // each axis
    1242 //    LCList->n[i] = LCList->N[i]-1; // current axis is topmost cell
    1243 //    for (LCList->n[(i+1)%NDIM]=0;LCList->n[(i+1)%NDIM]<LCList->N[(i+1)%NDIM];LCList->n[(i+1)%NDIM]++)
    1244 //      for (LCList->n[(i+2)%NDIM]=0;LCList->n[(i+2)%NDIM]<LCList->N[(i+2)%NDIM];LCList->n[(i+2)%NDIM]++) {
    1245 //        List = LCList->GetCurrentCell();
    1246 //        //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    1247 //        if (List != NULL) {
    1248 //          for (LinkedNodes::iterator Runner = List->begin();Runner != List->end();Runner++) {
    1249 //            if (mol->TesselStruct->PointsOnBoundary.find((*Runner)->nr) == mol->TesselStruct->PointsOnBoundary.end()) {
    1250 //              a = *Runner;
    1251 //              i=3;
    1252 //              for (int j=0;j<NDIM;j++)
    1253 //                LCList->n[j] = LCList->N[j];
    1254 //              break;
    1255 //            }
    1256 //          }
    1257 //        }
    1258 //      }
    1259 //  }
    1260 //  *out << Verbose(0) << "Check: IsInnerPoint() returns " << mol->TesselStruct->IsInnerPoint(out, a, LCList)
    1261 //    << "for atom " << a << " (inside)." << endl;
     1059  CalculateConcavityPerBoundaryPoint(out, mol->TesselStruct);
     1060  StoreTrianglesinFile(out, mol, filename, "");
    12621061
    12631062  if (freeLC)
     
    12651064  *out << Verbose(0) << "End of FindNonConvexBorder\n";
    12661065};
     1066
    12671067
    12681068/** Finds a hole of sufficient size in \a this molecule to embed \a *srcmol into it.
  • src/boundary.hpp

    r87e2e39 rc111db  
    11#ifndef BOUNDARY_HPP_
    22#define BOUNDARY_HPP_
     3
     4using namespace std;
     5
     6/*********************************************** includes ***********************************/
    37
    48// include config.h
     
    711#endif
    812
     13#include <fstream>
     14#include <iostream>
     15
    916// STL headers
    1017#include <map>
    1118
    12 #include "config.hpp"
    13 #include "linkedcell.hpp"
    14 #include "molecules.hpp"
    15 #include "tesselation.hpp"
     19#include "defs.hpp"
     20
     21/****************************************** forward declarations *****************************/
     22
     23class atom;
     24class BoundaryPointSet;
     25class BoundaryLineSet;
     26class BoundaryTriangleSet;
     27class config;
     28class LinkedCell;
     29class molecule;
     30class MoleculeListClass;
     31class Tesselation;
     32class Vector;
     33
     34/********************************************** definitions *********************************/
    1635
    1736#define DEBUG 1
    1837#define DoSingleStepOutput 0
    1938#define SingleStepWidth 1
    20 #define DoTecplotOutput 1
    21 #define DoRaster3DOutput 1
    22 #define DoVRMLOutput 1
    23 #define TecplotSuffix ".dat"
    24 #define Raster3DSuffix ".r3d"
    25 #define VRMLSUffix ".wrl"
    2639
    2740#define DistancePair pair < double, atom* >
     
    3346#define BoundariesTestPair pair< Boundaries::iterator, bool>
    3447
     48/********************************************** declarations *******************************/
     49
    3550double VolumeOfConvexEnvelope(ofstream *out, class Tesselation *TesselStruct, class config *configuration);
    3651double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem);
     
    3853molecule * FillBoxWithMolecule(ofstream *out, MoleculeListClass *List, molecule *filler, config &configuration, double distance[NDIM], double RandAtomDisplacement, double RandMolDisplacement, bool DoRandomRotation);
    3954void FindConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LCList, const char *filename);
    40 void FindNonConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LC, const char *tempbasename, const double RADIUS);
     55void FindNonConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LC, const double RADIUS, const char *tempbasename);
    4156double ConvexizeNonconvexEnvelope(ofstream *out, class Tesselation *TesselStruct, molecule *mol, char *filename);
    4257void FindNextSuitablePoint(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC);
    4358Boundaries *GetBoundaryPoints(ofstream *out, molecule *mol);
    44 void CalculateConcavityPerBoundaryPoint(ofstream *out, class Tesselation *TesselStruct);
    4559void StoreTrianglesinFile(ofstream *out, molecule *mol, const char *filename, const char *extraSuffix);
     60bool RemoveAllBoundaryPoints(ofstream *out, class Tesselation *TesselStruct, molecule *mol, char *filename);
    4661
    4762
  • src/builder.cpp

    r87e2e39 rc111db  
    5050using namespace std;
    5151
     52#include "atom.hpp"
     53#include "bond.hpp"
    5254#include "boundary.hpp"
     55#include "config.hpp"
     56#include "element.hpp"
    5357#include "ellipsoid.hpp"
    5458#include "helpers.hpp"
     59#include "leastsquaremin.hpp"
     60#include "linkedcell.hpp"
    5561#include "memoryusageobserverunittest.hpp"
    56 #include "molecules.hpp"
     62#include "molecule.hpp"
     63#include "periodentafel.hpp"
     64
    5765/********************************************* Subsubmenu routine ************************************/
    5866
     
    10181026      cin >> nr;
    10191027      count = 1;
    1020       for( MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     1028      for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
    10211029        if (nr == (*ListRunner)->IndexNr) {
    10221030          mol = *ListRunner;
    10231031          molecules->ListOfMolecules.erase(ListRunner);
    10241032          delete(mol);
     1033          break;
    10251034        }
    10261035      break;
     
    10751084
    10761085    case 'e':
    1077       cout << Verbose(0) << "Not implemented yet." << endl;
     1086      {
     1087        int src, dest;
     1088        molecule *srcmol = NULL, *destmol = NULL;
     1089        do {
     1090          cout << Verbose(0) << "Enter index of matrix molecule (the variable one): ";
     1091          cin >> src;
     1092          srcmol = molecules->ReturnIndex(src);
     1093        } while ((srcmol == NULL) && (src != -1));
     1094        do {
     1095          cout << Verbose(0) << "Enter index of molecule to merge into (the fixed one): ";
     1096          cin >> dest;
     1097          destmol = molecules->ReturnIndex(dest);
     1098        } while ((destmol == NULL) && (dest != -1));
     1099        if ((src != -1) && (dest != -1))
     1100          molecules->EmbedMerge(destmol, srcmol);
     1101      }
    10781102      break;
    10791103
     
    13661390            cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;
    13671391            cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl;
    1368             cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;
    1369             cout << "\t-R\t\tRemove all atoms out of sphere around a given one." << endl;
     1392            cout << "\t-r <id>\t\tRemove an atom with given id." << endl;
     1393            cout << "\t-R <id> <radius>\t\tRemove all atoms out of sphere around a given one." << endl;
    13701394            cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl;
    13711395            cout << "\t-S <file> Store temperatures from the config file in <file>." << endl;
     
    14641488          switch(argv[argptr-1][1]) {
    14651489            case 'p':
    1466               ExitFlag = 1;
     1490              if (ExitFlag == 0) ExitFlag = 1;
    14671491              if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    14681492                ExitFlag = 255;
     
    14801504              break;
    14811505            case 'a':
    1482               ExitFlag = 1;
     1506              if (ExitFlag == 0) ExitFlag = 1;
    14831507              if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) {
    14841508                ExitFlag = 255;
     
    15191543              break;
    15201544            case 'D':
    1521               ExitFlag = 1;
     1545              if (ExitFlag == 0) ExitFlag = 1;
    15221546              {
    15231547                cout << Verbose(1) << "Depth-First-Search Analysis." << endl;
     
    15521576              break;
    15531577            case 'E':
    1554               ExitFlag = 1;
     1578              if (ExitFlag == 0) ExitFlag = 1;
    15551579              if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) {
    15561580                ExitFlag = 255;
     
    15651589              break;
    15661590            case 'F':
    1567               ExitFlag = 1;
     1591              if (ExitFlag == 0) ExitFlag = 1;
    15681592              if (argptr+5 >=argc) {
    15691593                ExitFlag = 255;
     
    16031627              break;
    16041628            case 'A':
    1605               ExitFlag = 1;
     1629              if (ExitFlag == 0) ExitFlag = 1;
    16061630              if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    16071631                ExitFlag =255;
     
    16161640              break;
    16171641            case 'N':
    1618               ExitFlag = 1;
     1642              if (ExitFlag == 0) ExitFlag = 1;
    16191643              if ((argptr+1 >= argc) || (argv[argptr+1][0] == '-')){
    16201644                ExitFlag = 255;
     
    16261650                cout << Verbose(0) << "Evaluating non-convex envelope.";
    16271651                cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl;
    1628                 start = clock();
     1652                start = clock();
    16291653                LinkedCell LCList(mol, atof(argv[argptr])*2.);
    1630                 FindNonConvexBorder((ofstream *)&cout, mol, &LCList, argv[argptr+1], atof(argv[argptr]));
     1654                FindNonConvexBorder((ofstream *)&cout, mol, &LCList, atof(argv[argptr]), argv[argptr+1]);
    16311655                //FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str());
    1632                 end = clock();
    1633                 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
     1656                end = clock();
     1657                cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
    16341658                argptr+=2;
    16351659              }
    16361660              break;
    16371661            case 'S':
    1638               ExitFlag = 1;
     1662              if (ExitFlag == 0) ExitFlag = 1;
    16391663              if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    16401664                ExitFlag = 255;
     
    16531677              break;
    16541678            case 'L':
    1655               ExitFlag = 1;
    1656               SaveFlag = true;
    1657               cout << Verbose(1) << "Linear interpolation between configuration " << argv[argptr] << " and " << argv[argptr+1] << "." << endl;
    1658               if (!mol->LinearInterpolationBetweenConfiguration((ofstream *)&cout, atoi(argv[argptr]), atoi(argv[argptr+1]), argv[argptr+2], configuration))
    1659                 cout << Verbose(2) << "Could not store " << argv[argptr+2] << " files." << endl;
    1660               else
    1661                 cout << Verbose(2) << "Steps created and " << argv[argptr+2] << " files stored." << endl;
    1662               argptr+=3;
     1679              if (ExitFlag == 0) ExitFlag = 1;
     1680              if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     1681                ExitFlag = 255;
     1682                cerr << "Not enough or invalid arguments given for storing tempature: -L <step0> <step1> <prefix> <identity mapping?>" << endl;
     1683              } else {
     1684                SaveFlag = true;
     1685                cout << Verbose(1) << "Linear interpolation between configuration " << argv[argptr] << " and " << argv[argptr+1] << "." << endl;
     1686                if (atoi(argv[argptr+3]) == 1)
     1687                  cout << Verbose(1) << "Using Identity for the permutation map." << endl;
     1688                if (!mol->LinearInterpolationBetweenConfiguration((ofstream *)&cout, atoi(argv[argptr]), atoi(argv[argptr+1]), argv[argptr+2], configuration, atoi(argv[argptr+3])) == 1 ? true : false)
     1689                  cout << Verbose(2) << "Could not store " << argv[argptr+2] << " files." << endl;
     1690                else
     1691                  cout << Verbose(2) << "Steps created and " << argv[argptr+2] << " files stored." << endl;
     1692                argptr+=4;
     1693              }
    16631694              break;
    16641695            case 'P':
    1665               ExitFlag = 1;
     1696              if (ExitFlag == 0) ExitFlag = 1;
    16661697              if ((argptr >= argc) || (argv[argptr][0] == '-')) {
    16671698                ExitFlag = 255;
     
    16781709              break;
    16791710            case 'R':
    1680               ExitFlag = 1;
    1681               if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])))  {
     1711              if (ExitFlag == 0) ExitFlag = 1;
     1712              if ((argptr+1 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])))  {
    16821713                ExitFlag = 255;
    16831714                cerr << "Not enough or invalid arguments given for removing atoms: -R <id> <distance>" << endl;
     
    17031734              break;
    17041735            case 't':
    1705               ExitFlag = 1;
    1706               if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
     1736              if (ExitFlag == 0) ExitFlag = 1;
     1737              if ((argptr+2 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
    17071738                ExitFlag = 255;
    17081739                cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl;
    17091740              } else {
    1710                 ExitFlag = 1;
     1741                if (ExitFlag == 0) ExitFlag = 1;
    17111742                SaveFlag = true;
    1712                 cout << Verbose(1) << "Translating all ions to new origin." << endl;
     1743                cout << Verbose(1) << "Translating all ions by given vector." << endl;
    17131744                for (int i=NDIM;i--;)
    17141745                  x.x[i] = atof(argv[argptr+i]);
     
    17161747                argptr+=3;
    17171748              }
     1749              break;
    17181750            case 'T':
    1719               ExitFlag = 1;
    1720               if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
     1751              if (ExitFlag == 0) ExitFlag = 1;
     1752              if ((argptr+2 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
    17211753                ExitFlag = 255;
    17221754                cerr << "Not enough or invalid arguments given for periodic translation: -T <x> <y> <z>" << endl;
    17231755              } else {
    1724                 ExitFlag = 1;
     1756                if (ExitFlag == 0) ExitFlag = 1;
    17251757                SaveFlag = true;
    1726                 cout << Verbose(1) << "Translating all ions periodically to new origin." << endl;
     1758                cout << Verbose(1) << "Translating all ions periodically by given vector." << endl;
    17271759                for (int i=NDIM;i--;)
    17281760                  x.x[i] = atof(argv[argptr+i]);
     
    17321764              break;
    17331765            case 's':
    1734               ExitFlag = 1;
    1735               if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {
     1766              if (ExitFlag == 0) ExitFlag = 1;
     1767              if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) ) {
    17361768                ExitFlag = 255;
    17371769                cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl;
     
    17591791              break;
    17601792            case 'b':
    1761               ExitFlag = 1;
    1762               if ((argptr+5 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) || (!IsValidNumber(argv[argptr+3])) || (!IsValidNumber(argv[argptr+4])) || (!IsValidNumber(argv[argptr+5])) ) {
     1793              if (ExitFlag == 0) ExitFlag = 1;
     1794              if ((argptr+5 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) || (!IsValidNumber(argv[argptr+3])) || (!IsValidNumber(argv[argptr+4])) || (!IsValidNumber(argv[argptr+5])) ) {
    17631795                ExitFlag = 255;
    17641796                cerr << "Not enough or invalid arguments given for centering in box: -b <xx> <xy> <xz> <yy> <yz> <zz>" << endl;
     
    17761808              break;
    17771809            case 'B':
    1778               ExitFlag = 1;
    1779               if ((argptr+5 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) || (!IsValidNumber(argv[argptr+3])) || (!IsValidNumber(argv[argptr+4])) || (!IsValidNumber(argv[argptr+5])) ) {
     1810              if (ExitFlag == 0) ExitFlag = 1;
     1811              if ((argptr+5 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) || (!IsValidNumber(argv[argptr+3])) || (!IsValidNumber(argv[argptr+4])) || (!IsValidNumber(argv[argptr+5])) ) {
    17801812                ExitFlag = 255;
    17811813                cerr << "Not enough or invalid arguments given for bounding in box: -B <xx> <xy> <xz> <yy> <yz> <zz>" << endl;
     
    17931825              break;
    17941826            case 'c':
    1795               ExitFlag = 1;
    1796               if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
     1827              if (ExitFlag == 0) ExitFlag = 1;
     1828              if ((argptr+2 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
    17971829                ExitFlag = 255;
    17981830                cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl;
     
    18171849              break;
    18181850            case 'O':
    1819               ExitFlag = 1;
     1851              if (ExitFlag == 0) ExitFlag = 1;
    18201852              SaveFlag = true;
    18211853              cout << Verbose(1) << "Centering atoms on edge and setting box dimensions." << endl;
     
    18261858              break;
    18271859            case 'r':
    1828               ExitFlag = 1;
    1829               SaveFlag = true;
    1830               cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl;
     1860              if (ExitFlag == 0) ExitFlag = 1;
     1861              if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])))  {
     1862                ExitFlag = 255;
     1863                cerr << "Not enough or invalid arguments given for removing atoms: -r <id>" << endl;
     1864              } else {
     1865                SaveFlag = true;
     1866                cout << Verbose(1) << "Removing atom " << argv[argptr] << "." << endl;
     1867                atom *first = mol->FindAtom(atoi(argv[argptr]));
     1868                mol->RemoveAtom(first);
     1869                argptr+=1;
     1870              }
    18311871              break;
    18321872            case 'f':
    1833               ExitFlag = 1;
    1834               if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) {
     1873              if (ExitFlag == 0) ExitFlag = 1;
     1874              if ((argptr+1 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) {
    18351875                ExitFlag = 255;
    18361876                cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl;
     
    18501890              break;
    18511891            case 'm':
    1852               ExitFlag = 1;
     1892              if (ExitFlag == 0) ExitFlag = 1;
    18531893              j = atoi(argv[argptr++]);
    18541894              if ((j<0) || (j>1)) {
     
    18641904              break;
    18651905            case 'o':
    1866               ExitFlag = 1;
    1867               if ((argptr >= argc) || (argv[argptr][0] == '-')){
     1906              if (ExitFlag == 0) ExitFlag = 1;
     1907              if ((argptr+1 >= argc) || (argv[argptr][0] == '-')){
    18681908                ExitFlag = 255;
    1869                 cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl;
     1909                cerr << "Not enough or invalid arguments given for convex envelope: -o <convex output file> <non-convex output file>" << endl;
    18701910              } else {
    18711911                cout << Verbose(0) << "Evaluating volume of the convex envelope.";
    1872                 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl;
     1912                cout << Verbose(1) << "Storing tecplot convex data in " << argv[argptr] << "." << endl;
     1913                cout << Verbose(1) << "Storing tecplot non-convex data in " << argv[argptr+1] << "." << endl;
    18731914                LinkedCell LCList(mol, 10.);
    18741915                //FindConvexBorder((ofstream *)&cout, mol, &LCList, argv[argptr]);
    1875                 FindNonConvexBorder((ofstream *)&cout, mol, &LCList, argv[argptr], 10.);
    1876 
     1916                FindNonConvexBorder((ofstream *)&cout, mol, &LCList, 5., argv[argptr+1]);
     1917//                RemoveAllBoundaryPoints((ofstream *)&cout, mol->TesselStruct, mol, argv[argptr]);
    18771918                double volumedifference = ConvexizeNonconvexEnvelope((ofstream *)&cout, mol->TesselStruct, mol, argv[argptr]);
    18781919                double clustervolume = VolumeOfConvexEnvelope((ofstream *)&cout, mol->TesselStruct, &configuration);
    18791920                cout << Verbose(0) << "The tesselated volume area is " << clustervolume << " " << (configuration.GetIsAngstroem() ? "angstrom" : "atomiclength") << "^3." << endl;
    18801921                cout << Verbose(0) << "The non-convex tesselated volume area is " << clustervolume-volumedifference << " " << (configuration.GetIsAngstroem() ? "angstrom" : "atomiclength") << "^3." << endl;
    1881                 argptr+=1;
     1922                argptr+=2;
    18821923              }
    18831924              break;
    18841925            case 'U':
    1885               ExitFlag = 1;
    1886               if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) {
     1926              if (ExitFlag == 0) ExitFlag = 1;
     1927              if ((argptr+1 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) {
    18871928                ExitFlag = 255;
    18881929                cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl;
     
    18931934              }
    18941935            case 'u':
    1895               ExitFlag = 1;
    1896               if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {
     1936              if (ExitFlag == 0) ExitFlag = 1;
     1937              if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) ) {
    18971938                if (volume != -1)
    18981939                  ExitFlag = 255;
     
    19171958              break;
    19181959            case 'd':
    1919               ExitFlag = 1;
    1920               if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
     1960              if (ExitFlag == 0) ExitFlag = 1;
     1961              if ((argptr+2 >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {
    19211962                ExitFlag = 255;
    19221963                cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl;
     
    20322073      return 0;
    20332074      break;
     2075    case 2:  // just for -f option
     2076      delete(molecules); // also free's all molecules contained
     2077      delete(periode);
     2078      cout << Verbose(0) <<  "Maximum of allocated memory: "
     2079        << MemoryUsageObserver::getInstance()->getMaximumUsedMemory() << endl;
     2080      cout << Verbose(0) <<  "Remaining non-freed memory: "
     2081        << MemoryUsageObserver::getInstance()->getUsedMemorySize() << endl;
     2082      return 2;
     2083      break;
    20342084    default:
    20352085      break;
  • src/config.cpp

    r87e2e39 rc111db  
    55 */
    66
     7#include "atom.hpp"
    78#include "config.hpp"
     9#include "element.hpp"
    810#include "memoryallocator.hpp"
     11#include "molecule.hpp"
     12#include "periodentafel.hpp"
    913
    1014/******************************** Functions for class ConfigFileBuffer **********************/
     
    964968
    965969            // check size of vectors
    966             if (mol->Trajectories[neues].R.size() <= (unsigned int)(repetition)) {
     970            if (neues->Trajectory.R.size() <= (unsigned int)(repetition)) {
    967971              //cout << "Increasing size for trajectory array of " << keyword << " to " << (repetition+10) << "." << endl;
    968               mol->Trajectories[neues].R.resize(repetition+10);
    969               mol->Trajectories[neues].U.resize(repetition+10);
    970               mol->Trajectories[neues].F.resize(repetition+10);
     972              neues->Trajectory.R.resize(repetition+10);
     973              neues->Trajectory.U.resize(repetition+10);
     974              neues->Trajectory.F.resize(repetition+10);
    971975            }
    972976
    973977            // put into trajectories list
    974978            for (int d=0;d<NDIM;d++)
    975               mol->Trajectories[neues].R.at(repetition).x[d] = neues->x.x[d];
     979              neues->Trajectory.R.at(repetition).x[d] = neues->x.x[d];
    976980
    977981            // parse velocities if present
     
    983987              neues->v.x[2] = 0.;
    984988            for (int d=0;d<NDIM;d++)
    985               mol->Trajectories[neues].U.at(repetition).x[d] = neues->v.x[d];
     989              neues->Trajectory.U.at(repetition).x[d] = neues->v.x[d];
    986990
    987991            // parse forces if present
     
    993997              value[2] = 0.;
    994998            for (int d=0;d<NDIM;d++)
    995               mol->Trajectories[neues].F.at(repetition).x[d] = value[d];
     999              neues->Trajectory.F.at(repetition).x[d] = value[d];
    9961000
    9971001  //            cout << "Parsed position of step " << (repetition) << ": (";
    9981002  //            for (int d=0;d<NDIM;d++)
    999   //              cout << mol->Trajectories[neues].R.at(repetition).x[d] << " ";          // next step
     1003  //              cout << neues->Trajectory.R.at(repetition).x[d] << " ";          // next step
    10001004  //            cout << ")\t(";
    10011005  //            for (int d=0;d<NDIM;d++)
    1002   //              cout << mol->Trajectories[neues].U.at(repetition).x[d] << " ";          // next step
     1006  //              cout << neues->Trajectory.U.at(repetition).x[d] << " ";          // next step
    10031007  //            cout << ")\t(";
    10041008  //            for (int d=0;d<NDIM;d++)
    1005   //              cout << mol->Trajectories[neues].F.at(repetition).x[d] << " ";          // next step
     1009  //              cout << neues->Trajectory.F.at(repetition).x[d] << " ";          // next step
    10061010  //            cout << ")" << endl;
    10071011          }
     
    10111015      repetition--;
    10121016      cout << "Found " << repetition << " trajectory steps." << endl;
    1013       mol->MDSteps = repetition;
     1017      if (repetition <= 1)  // if onyl one step, desactivate use of trajectories
     1018        mol->MDSteps = 0;
     1019      else
     1020        mol->MDSteps = repetition;
    10141021    } else {
    10151022      // find the maximum number of MD steps so that we may parse last one (Ion_Type1_1 must always be present, because is the first atom)
  • src/config.hpp

    r87e2e39 rc111db  
    1111using namespace std;
    1212
     13/*********************************************** includes ***********************************/
     14
    1315// include config.h
    1416#ifdef HAVE_CONFIG_H
     
    1618#endif
    1719
    18 #include "molecules.hpp"
    19 #include "periodentafel.hpp"
     20#include <string>
     21
     22/****************************************** forward declarations *****************************/
     23
     24class molecule;
     25class periodentafel;
     26
     27/********************************************** declarations *******************************/
    2028
    2129class ConfigFileBuffer {
  • src/datacreator.cpp

    r87e2e39 rc111db  
    88
    99#include "datacreator.hpp"
     10#include "helpers.hpp"
     11#include "parser.hpp"
    1012
    1113//=========================== FUNCTIONS============================
     
    4951/** Plots an energy vs. order.
    5052 * \param &Fragments EnergyMatrix class containing matrix values
    51  * \param KeySet KeySetContainer class holding bond KeySetContainer::Order
     53 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
    5254 * \param *prefix prefix in filename (without ending)
    5355 * \param *msg message to be place in first line as a comment
    5456 * \return true if file was written successfully
    5557 */
    56 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, const char *dir, const char *prefix, const char *msg, const char *datum)
     58bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
    5759{
    5860  stringstream filename;
     
    6466  output << "# " << msg << ", created on " << datum;
    6567  output << "#Order\tFrag.No.\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
    66   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    67     for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {
    68       for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;)
    69         for(int k=Fragments.ColumnCounter[ KeySet.OrderSet[BondOrder][i] ];k--;)
    70           Fragments.Matrix[Fragments.MatrixCounter][j][k] += Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
    71     }
    72     output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
     68  for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
     69    for(int i=KeySets.FragmentsPerOrder[BondOrder];i--;) {
     70      for(int j=Fragments.RowCounter[ KeySets.OrderSet[BondOrder][i] ];j--;)
     71        for(int k=Fragments.ColumnCounter[ KeySets.OrderSet[BondOrder][i] ];k--;)
     72          Fragments.Matrix[Fragments.MatrixCounter][j][k] += Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][k];
     73    }
     74    output << BondOrder+1 << "\t" << KeySets.FragmentsPerOrder[BondOrder];
    7375    for (int l=0;l<Fragments.ColumnCounter[Fragments.MatrixCounter];l++)
    7476      output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l];
     
    8284 * \param &Energy EnergyMatrix class containing reference values (in MatrixCounter matrix)
    8385 * \param &Fragments EnergyMatrix class containing matrix values
    84  * \param KeySet KeySetContainer class holding bond KeySetContainer::Order
     86 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
    8587 * \param *prefix prefix in filename (without ending)
    8688 * \param *msg message to be place in first line as a comment
    8789 * \return true if file was written successfully
    8890 */
    89 bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, const char *dir, const char *prefix, const char *msg, const char *datum)
     91bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
    9092{
    9193  stringstream filename;
     
    98100  output << "#Order\tFrag.No.\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
    99101  Fragments.SetLastMatrix(Energy.Matrix[Energy.MatrixCounter],0);
    100   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    101     for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {
    102       for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;)
    103         for(int k=Fragments.ColumnCounter[ KeySet.OrderSet[BondOrder][i] ];k--;)
    104           Fragments.Matrix[Fragments.MatrixCounter][j][k] -= Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
    105     }
    106     output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
     102  for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
     103    for(int i=KeySets.FragmentsPerOrder[BondOrder];i--;) {
     104      for(int j=Fragments.RowCounter[ KeySets.OrderSet[BondOrder][i] ];j--;)
     105        for(int k=Fragments.ColumnCounter[ KeySets.OrderSet[BondOrder][i] ];k--;)
     106          Fragments.Matrix[Fragments.MatrixCounter][j][k] -= Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][k];
     107    }
     108    output << BondOrder+1 << "\t" << KeySets.FragmentsPerOrder[BondOrder];
    107109    for (int l=0;l<Fragments.ColumnCounter[Energy.MatrixCounter];l++)
    108110      if (fabs(Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]) < MYEPSILON)
     
    118120/** Plot forces vs. order.
    119121 * \param &Fragments ForceMatrix class containing matrix values
    120  * \param KeySet KeySetContainer class holding bond KeySetContainer::Order
     122 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
    121123 * \param *prefix prefix in filename (without ending)
    122124 * \param *msg message to be place in first line as a comment
     
    124126 * \return true if file was written successfully
    125127 */
    126 bool CreateDataForcesOrder(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, const char *dir, const char *prefix,const  char *msg, const char *datum, void (*CreateForce)(class MatrixContainer &, int))
     128bool CreateDataForcesOrder(class ForceMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix,const  char *msg, const char *datum, void (*CreateForce)(class MatrixContainer &, int))
    127129{
    128130  stringstream filename;
     
    135137  output << "# Order\tFrag.No.\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
    136138  Fragments.SetLastMatrix(0.,0);
    137   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    138     Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.);
    139     output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
     139  for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
     140    Fragments.SumSubForces(Fragments, KeySets, BondOrder, 1.);
     141    output << BondOrder+1 << "\t" << KeySets.FragmentsPerOrder[BondOrder];
    140142    CreateForce(Fragments, Fragments.MatrixCounter);
    141143    for (int l=0;l<Fragments.ColumnCounter[Fragments.MatrixCounter];l++)
     
    150152 * \param &Force ForceMatrix containing reference values (in MatrixCounter matrix)
    151153 * \param &Fragments ForceMatrix class containing matrix values
    152  * \param KeySet KeySetContainer class holding bond KeySetContainer::Order
     154 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
    153155 * \param *prefix prefix in filename (without ending)
    154156 * \param *msg message to be place in first line as a comment
     
    156158 * \return true if file was written successfully
    157159 */
    158 bool CreateDataDeltaForcesOrder(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, const char *dir, const char *prefix, const char *msg, const char *datum, void (*CreateForce)(class MatrixContainer &, int))
     160bool CreateDataDeltaForcesOrder(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum, void (*CreateForce)(class MatrixContainer &, int))
    159161{
    160162  stringstream filename;
     
    167169  output << "# Order\tFrag.No.\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
    168170  Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter],0);
    169   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    170     Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.);
    171     output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
     171  for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
     172    Fragments.SumSubForces(Fragments, KeySets, BondOrder, -1.);
     173    output << BondOrder+1 << "\t" << KeySets.FragmentsPerOrder[BondOrder];
    172174    CreateForce(Fragments, Fragments.MatrixCounter);
    173175    for (int l=0;l<Fragments.ColumnCounter[Fragments.MatrixCounter];l++)
     
    182184 * \param &Force ForceMatrix containing reference values (in MatrixCounter matrix)
    183185 * \param &Fragments ForceMatrix class containing matrix values
    184  * \param KeySet KeySetContainer class holding bond KeySetContainer::Order
     186 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
    185187 * \param *prefix prefix in filename (without ending)
    186188 * \param *msg message to be place in first line as a comment
     
    188190 * \return true if file was written successfully
    189191 */
    190 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, const char *dir, const char *prefix, const char *msg, const char *datum)
     192bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
    191193{
    192194  stringstream filename;
     
    200202  output << "# AtomNo\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
    201203  Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter], 0);
    202   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     204  for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
    203205    //cout << "Current order is " << BondOrder << "." << endl;
    204     Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.);
     206    Fragments.SumSubForces(Fragments, KeySets, BondOrder, -1.);
    205207    // errors per atom
    206208    output << endl << "#Order\t" << BondOrder+1 << endl;
     
    229231/** Plot forces error vs. vs atom vs. order.
    230232 * \param &Fragments ForceMatrix class containing matrix values
    231  * \param KeySet KeySetContainer class holding bond KeySetContainer::Order
     233 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
    232234 * \param *prefix prefix in filename (without ending)
    233235 * \param *msg message to be place in first line as a comment
     
    235237 * \return true if file was written successfully
    236238 */
    237 bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, const char *dir, const char *prefix, const char *msg, const char *datum)
     239bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
    238240{
    239241  stringstream filename;
     
    245247  output << "# " << msg << ", created on " << datum;
    246248  output << "# AtomNo\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
    247   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     249  for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
    248250    //cout << "Current order is " << BondOrder << "." << endl;
    249     Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.);
     251    Fragments.SumSubForces(Fragments, KeySets, BondOrder, 1.);
    250252    // errors per atom
    251253    output << endl << "#Order\t" << BondOrder+1 << endl;
     
    266268 * \param &Hessian HessianMatrix containing reference values (in MatrixCounter matrix)
    267269 * \param &Fragments HessianMatrix class containing matrix values
    268  * \param KeySet KeySetContainer class holding bond KeySetContainer::Order
     270 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
    269271 * \param *prefix prefix in filename (without ending)
    270272 * \param *msg message to be place in first line as a comment
     
    272274 * \return true if file was written successfully
    273275 */
    274 bool CreateDataDeltaHessianOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySet, const char *dir, const char *prefix, const char *msg, const char *datum)
     276bool CreateDataDeltaHessianOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
    275277{
    276278  stringstream filename;
     
    283285  output << "# AtomNo\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
    284286  Fragments.SetLastMatrix(Hessian.Matrix[Hessian.MatrixCounter], 0);
    285   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     287  for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
    286288    //cout << "Current order is " << BondOrder << "." << endl;
    287     Fragments.SumSubHessians(Fragments, KeySet, BondOrder, -1.);
     289    Fragments.SumSubHessians(Fragments, KeySets, BondOrder, -1.);
    288290    // errors per atom
    289291    output << endl << "#Order\t" << BondOrder+1 << endl;
     
    304306 * \param &Hessian HessianMatrix containing reference values (in MatrixCounter matrix)
    305307 * \param &Fragments HessianMatrix class containing matrix values
    306  * \param KeySet KeySetContainer class holding bond KeySetContainer::Order
     308 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
    307309 * \param *prefix prefix in filename (without ending)
    308310 * \param *msg message to be place in first line as a comment
     
    310312 * \return true if file was written successfully
    311313 */
    312 bool CreateDataDeltaFrobeniusOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySet, const char *dir, const char *prefix, const char *msg, const char *datum)
     314bool CreateDataDeltaFrobeniusOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
    313315{
    314316  stringstream filename;
     
    323325  output << "# AtomNo\t";
    324326  Fragments.SetLastMatrix(Hessian.Matrix[Hessian.MatrixCounter], 0);
    325   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     327  for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
    326328    output << "Order" << BondOrder+1 << "\t";
    327329  }
    328330  output << endl;
    329331  output << Fragments.RowCounter[ Fragments.MatrixCounter ] << "\t";
    330   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     332  for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
    331333    //cout << "Current order is " << BondOrder << "." << endl;
    332     Fragments.SumSubHessians(Fragments, KeySet, BondOrder, -1.);
     334    Fragments.SumSubHessians(Fragments, KeySets, BondOrder, -1.);
    333335    // frobenius norm of errors per atom
    334336    norm = 0.;
     
    348350/** Plot hessian error vs. vs atom vs. order.
    349351 * \param &Fragments HessianMatrix class containing matrix values
    350  * \param KeySet KeySetContainer class holding bond KeySetContainer::Order
     352 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
    351353 * \param *prefix prefix in filename (without ending)
    352354 * \param *msg message to be place in first line as a comment
     
    354356 * \return true if file was written successfully
    355357 */
    356 bool CreateDataHessianOrderPerAtom(class HessianMatrix &Fragments, class KeySetsContainer &KeySet, const char *dir, const char *prefix, const char *msg, const char *datum)
     358bool CreateDataHessianOrderPerAtom(class HessianMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
    357359{
    358360  stringstream filename;
     
    365367  output << "# AtomNo\t" << Fragments.Header[ Fragments.MatrixCounter ] << endl;
    366368  Fragments.SetLastMatrix(0., 0);
    367   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     369  for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
    368370    //cout << "Current order is " << BondOrder << "." << endl;
    369     Fragments.SumSubHessians(Fragments, KeySet, BondOrder, 1.);
     371    Fragments.SumSubHessians(Fragments, KeySets, BondOrder, 1.);
    370372    // errors per atom
    371373    output << endl << "#Order\t" << BondOrder+1 << endl;
     
    384386/** Plot matrix vs. fragment.
    385387 */
    386 bool CreateDataFragment(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, const char *dir, const char *prefix, const char *msg, const char *datum, void (*CreateFragment)(class MatrixContainer &, int))
     388bool CreateDataFragment(class MatrixContainer &Fragment, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum, void (*CreateFragment)(class MatrixContainer &, int))
    387389{
    388390  stringstream filename;
     
    394396  output << "# " << msg << ", created on " << datum << endl;
    395397  output << "#Order\tFrag.No.\t" << Fragment.Header[ Fragment.MatrixCounter ] << endl;
    396   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
    397     for(int i=0;i<KeySet.FragmentsPerOrder[BondOrder];i++) {
    398       output << BondOrder+1 << "\t" << KeySet.OrderSet[BondOrder][i]+1;
    399       CreateFragment(Fragment, KeySet.OrderSet[BondOrder][i]);
    400       for (int l=0;l<Fragment.ColumnCounter[ KeySet.OrderSet[BondOrder][i] ];l++)
    401         output << scientific << "\t" << Fragment.Matrix[ KeySet.OrderSet[BondOrder][i] ][ Fragment.RowCounter[ KeySet.OrderSet[BondOrder][i] ] ][l];
     398  for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
     399    for(int i=0;i<KeySets.FragmentsPerOrder[BondOrder];i++) {
     400      output << BondOrder+1 << "\t" << KeySets.OrderSet[BondOrder][i]+1;
     401      CreateFragment(Fragment, KeySets.OrderSet[BondOrder][i]);
     402      for (int l=0;l<Fragment.ColumnCounter[ KeySets.OrderSet[BondOrder][i] ];l++)
     403        output << scientific << "\t" << Fragment.Matrix[ KeySets.OrderSet[BondOrder][i] ][ Fragment.RowCounter[ KeySets.OrderSet[BondOrder][i] ] ][l];
    402404      output << endl;
    403405    }
     
    409411/** Copies fragment energy values into last matrix of \a Matrix with greatest total energy.
    410412 * \param &Matrix MatrixContainer with all fragment energy values
    411  * \param &KeySet KeySetsContainer with associations of each fragment to a bond order
     413 * \param &KeySets KeySetsContainer with associations of each fragment to a bond order
    412414 * \param BondOrder current bond order
    413415 */
    414 void CreateMaxFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder)
     416void CreateMaxFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySets, int BondOrder)
    415417{
    416418  for(int j=Fragments.RowCounter[ Fragments.MatrixCounter ];j--;) {
    417     for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {
    418       if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) {
     419    for(int i=KeySets.FragmentsPerOrder[BondOrder];i--;) {
     420      if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < fabs(Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][1])) {
    419421        for (int k=Fragments.ColumnCounter[ Fragments.MatrixCounter ];k--;)
    420           Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     422          Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][k];
    421423      }
    422424    }
     
    426428/** Copies fragment energy values into last matrix of \a Matrix with smallest total energy.
    427429 * \param &Matrix MatrixContainer with all fragment energy values
    428  * \param &KeySet KeySetsContainer with associations of each fragment to a bond order
     430 * \param &KeySets KeySetsContainer with associations of each fragment to a bond order
    429431 * \param BondOrder current bond order
    430432 */
    431 void CreateMinFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder)
     433void CreateMinFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySets, int BondOrder)
    432434{
    433435  for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
     
    435437    do {  // first get a minimum value unequal to 0
    436438      for (int k=Fragments.ColumnCounter[ Fragments.MatrixCounter ];k--;)
    437         Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     439        Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][k];
    438440      i++;
    439     } while ((fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < MYEPSILON) && (i<KeySet.FragmentsPerOrder[BondOrder]));
    440     for(;i<KeySet.FragmentsPerOrder[BondOrder];i++) { // then find lowest
    441       if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) > fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) {
     441    } while ((fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < MYEPSILON) && (i<KeySets.FragmentsPerOrder[BondOrder]));
     442    for(;i<KeySets.FragmentsPerOrder[BondOrder];i++) { // then find lowest
     443      if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) > fabs(Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][1])) {
    442444        for (int k=Fragments.ColumnCounter[ Fragments.MatrixCounter ];k--;)
    443           Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];
     445          Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][k];
    444446      }
    445447    }
     
    449451/** Plot matrix vs. fragment.
    450452 */
    451 bool CreateDataFragmentOrder(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, const char *dir, const char *prefix, const char *msg, const char *datum, void (*CreateFragmentOrder)(class MatrixContainer &, class KeySetsContainer &, int))
     453bool CreateDataFragmentOrder(class MatrixContainer &Fragment, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum, void (*CreateFragmentOrder)(class MatrixContainer &, class KeySetsContainer &, int))
    452454{
    453455  stringstream filename;
     
    460462  output << "#Order\tFrag.No.\t" << Fragment.Header[ Fragment.MatrixCounter ] << endl;
    461463  // max
    462   for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
     464  for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
    463465    Fragment.SetLastMatrix(0.,0);
    464     CreateFragmentOrder(Fragment, KeySet, BondOrder);
    465     output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];
     466    CreateFragmentOrder(Fragment, KeySets, BondOrder);
     467    output << BondOrder+1 << "\t" << KeySets.FragmentsPerOrder[BondOrder];
    466468    for (int l=0;l<Fragment.ColumnCounter[ Fragment.MatrixCounter ];l++)
    467469      output << scientific << "\t" << Fragment.Matrix[ Fragment.MatrixCounter ][ Fragment.RowCounter[ Fragment.MatrixCounter ]-1 ][l];
     
    618620/** Creates the pyxplotfile for energy data.
    619621 * \param Matrix MatrixContainer with matrix values
    620  * \param KeySet contains bond order
     622 * \param KeySets contains bond order
    621623 * \param *dir directory
    622624 * \param *prefix prefix for all filenames (without ending)
     
    635637 * \return true if file was written successfully
    636638 */
    637 bool CreatePlotOrder(class MatrixContainer &Matrix, const class KeySetsContainer &KeySet, const char *dir, const char *prefix, const int keycolumns, const char *key, const char *logscale, const char *extraline, const int mxtics, const int xtics, const char *xlabel, const char *ylabel, const char *xrange, const char *yrange, const char *xargument, const char *uses, void (*CreatePlotLines)(ofstream &, class MatrixContainer &, const char *, const char *, const char *))
     639bool CreatePlotOrder(class MatrixContainer &Matrix, const class KeySetsContainer &KeySets, const char *dir, const char *prefix, const int keycolumns, const char *key, const char *logscale, const char *extraline, const int mxtics, const int xtics, const char *xlabel, const char *ylabel, const char *xrange, const char *yrange, const char *xargument, const char *uses, void (*CreatePlotLines)(ofstream &, class MatrixContainer &, const char *, const char *, const char *))
    638640{
    639641  stringstream filename;
  • src/datacreator.hpp

    r87e2e39 rc111db  
    1010using namespace std;
    1111
    12 //============================ INCLUDES ===========================
     12#include <iostream>
    1313
    14 #include "helpers.hpp"
    15 #include "parser.hpp"
     14/****************************************** forward declarations *****************************/
    1615
    17 //=========================== FUNCTIONS============================
     16class EnergyMatrix;
     17class ForceMatrix;
     18class HessianMatrix;
     19class KeySetsContainer;
     20class MatrixContainer;
     21
     22/********************************************** declarations *******************************/
    1823
    1924bool OpenOutputFile(ofstream &output, const char *dir, const char *filename);
  • src/element.hpp

    r87e2e39 rc111db  
    1111using namespace std;
    1212
     13/*********************************************** includes ***********************************/
     14
    1315// include config.h
    1416#ifdef HAVE_CONFIG_H
     
    1618#endif
    1719
    18 
    1920#include <iostream>
    2021
    2122#include "defs.hpp"
     23
     24/********************************************** declarations *******************************/
    2225
    2326/** Chemical element.
  • src/ellipsoid.cpp

    r87e2e39 rc111db  
    99#include <gsl/gsl_vector.h>
    1010
     11#include <iomanip>
     12
     13#include <set>
     14
    1115#include "boundary.hpp"
    1216#include "ellipsoid.hpp"
     17#include "linkedcell.hpp"
     18#include "tesselation.hpp"
     19#include "vector.hpp"
     20#include "verbose.hpp"
    1321
    1422/** Determines squared distance for a given point \a x to surface of ellipsoid.
  • src/ellipsoid.hpp

    r87e2e39 rc111db  
    99#define ELLIPSOID_HPP_
    1010
     11using namespace std;
     12
     13/*********************************************** includes ***********************************/
     14
    1115// include config.h
    1216#ifdef HAVE_CONFIG_H
     
    1418#endif
    1519
    16 #include "linkedcell.hpp"
    17 #include "vector.hpp"
     20#include <gsl/gsl_vector.h>
     21
     22/****************************************** forward declarations *****************************/
     23
     24class LinkedCell;
     25class Vector;
     26
     27/********************************************** declarations *******************************/
    1828
    1929double SquaredDistanceToEllipsoid(Vector &x, Vector &EllipsoidCenter, double *EllipsoidLength, double *EllipsoidAngle);
  • src/graph.cpp

    r87e2e39 rc111db  
    77using namespace std;
    88
     9#include "atom.hpp"
     10#include "bond.hpp"
     11#include "config.hpp"
    912#include "graph.hpp"
     13#include "molecule.hpp"
    1014
    1115/***************************************** Implementations for graph classes ********************************/
    1216
    13 /** Constructor of class Graph.
     17///** Constructor of class Graph.
     18// */
     19//Graph::Graph()
     20//{
     21//};
     22//
     23///** Destructor of class Graph.
     24// * Destructor does release memory for nodes and edges contained in its lists as well.
     25// */
     26//Graph::~Graph()
     27//{
     28//};
     29//
     30///** Constructor of class SubGraph.
     31// */
     32//SubGraph::SubGraph()
     33//{
     34//};
     35//
     36///** Destructor of class SubGraph.
     37// * Note that destructor does not deallocate either nodes or edges! (this is done by its subgraph!)
     38// */
     39//SubGraph::~SubGraph()
     40//{
     41//};
     42//
     43///** Constructor of class Node.
     44// */
     45//Node::Node()
     46//{
     47//};
     48//
     49///** Destructor of class Node.
     50// */
     51//Node::~Node()
     52//{
     53//};
     54//
     55///** Constructor of class Edge.
     56// */
     57//Edge::Edge()
     58//{
     59//};
     60//
     61///** Destructor of class Edge.
     62// */
     63//Edge::~Edge()
     64//{
     65//};
     66
     67
     68//bool operator < (KeySet SubgraphA, KeySet SubgraphB)
     69//{
     70//  return KeyCompare(SubgraphA, SubgraphB);
     71//};
     72
     73/** Checking whether KeySet is not already present in Graph, if so just adds factor.
     74 * \param *out output stream for debugging
     75 * \param &set KeySet to insert
     76 * \param &graph Graph to insert into
     77 * \param *counter pointer to unique fragment count
     78 * \param factor energy factor for the fragment
    1479 */
    15 Graph::Graph()
     80void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment)
    1681{
     82  GraphTestPair testGraphInsert;
     83
     84  testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor)));  // store fragment number and current factor
     85  if (testGraphInsert.second) {
     86    *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl;
     87    Fragment->FragmentCounter++;
     88  } else {
     89    *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
     90    ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;  // increase the "created" counter
     91    *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl;
     92  }
     93};
     94//void inline InsertIntoGraph(ofstream *out, KeyStack &stack, Graph &graph, int *counter, double factor)
     95//{
     96//  // copy stack contents to set and call overloaded function again
     97//  KeySet set;
     98//  for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++)
     99//    set.insert((*runner));
     100//  InsertIntoGraph(out, set, graph, counter, factor);
     101//};
     102
     103/** Inserts each KeySet in \a graph2 into \a graph1.
     104 * \param *out output stream for debugging
     105 * \param graph1 first (dest) graph
     106 * \param graph2 second (source) graph
     107 * \param *counter keyset counter that gets increased
     108 */
     109void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter)
     110{
     111  GraphTestPair testGraphInsert;
     112
     113  for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) {
     114    testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));  // store fragment number and current factor
     115    if (testGraphInsert.second) {
     116      *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl;
     117    } else {
     118      *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;
     119      ((*(testGraphInsert.first)).second).second += (*runner).second.second;
     120      *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl;
     121    }
     122  }
    17123};
    18124
    19 /** Destructor of class Graph.
    20  * Destructor does release memory for nodes and edges contained in its lists as well.
    21  */
    22 Graph::~Graph()
    23 {
    24 };
    25 
    26 /** Constructor of class SubGraph.
    27  */
    28 SubGraph::SubGraph()
    29 {
    30 };
    31 
    32 /** Destructor of class SubGraph.
    33  * Note that destructor does not deallocate either nodes or edges! (this is done by its subgraph!)
    34  */
    35 SubGraph::~SubGraph()
    36 {
    37 };
    38 
    39 /** Constructor of class Node.
    40  */
    41 Node::Node()
    42 {
    43 };
    44 
    45 /** Destructor of class Node.
    46  */
    47 Node::~Node()
    48 {
    49 };
    50 
    51 /** Constructor of class Edge.
    52  */
    53 Edge::Edge()
    54 {
    55 };
    56 
    57 /** Destructor of class Edge.
    58  */
    59 Edge::~Edge()
    60 {
    61 };
    62 
  • src/graph.hpp

    r87e2e39 rc111db  
    88#define GRAPH_HPP_
    99
     10/*********************************************** includes ***********************************/
     11
    1012// include config.h
    1113#ifdef HAVE_CONFIG_H
     
    1416
    1517// STL headers
     18#include <deque>
    1619#include <map>
    17 #include <multimap>
     20#include <set>
    1821
    19 #include "molecules.hpp"
     22/****************************************** forward declarations *****************************/
     23
     24class atom;
     25class bond;
     26class config;
     27class molecule;
    2028
    2129class Graph;
     
    2432class Edge;
    2533
    26 /***************************************** Various graph-related STL defines ********************************/
     34/********************************************** definitions *********************************/
    2735
    2836#define NodeMap pair < int, class Node* >
    2937#define EdgeMap multimap < class Node*, class Edge* >
    3038
    31 /***************************************** Definition for classes ********************************/
     39#define KeyStack deque<int>
     40#define KeySet set<int>
     41#define NumberValuePair pair<int, double>
     42#define Graph map <KeySet, NumberValuePair, KeyCompare >
     43#define GraphPair pair <KeySet, NumberValuePair >
     44#define KeySetTestPair pair<KeySet::iterator, bool>
     45#define GraphTestPair pair<Graph::iterator, bool>
    3246
    33 /** Graph class containing the graphs behind molecules.
    34  */
    35 class Graph
     47
     48/******************************** Some small functions and/or structures **********************************/
     49
     50struct KeyCompare
    3651{
    37         NodeMap ListOfNodes;            //!< tree-list of all nodes in this graph
    38         EdgeMap ListOfEdges;            //!< tree-multi-list of all nodes, referenced to node id
     52  bool operator() (const KeySet SubgraphA, const KeySet SubgraphB) const;
    3953};
    4054
    41 /** Class describing subgraphs of the Class \a Graph.
    42  * SubGraph has its own node and edge lists, however also a pointer to its father graph
    43  * and hence access to its list as well.
     55//bool operator < (KeySet SubgraphA, KeySet SubgraphB);   //note: this declaration is important, otherwise normal < is used (producing wrong order)
     56void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment); // Insert a KeySet into a Graph
     57void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter);  // Insert all KeySet's in a Graph into another Graph
     58
     59/** Structure containing all values in power set combination generation.
    4460 */
    45 class SubGraph : class Graph
    46 {
    47         class Graph *FatherGraph;               //!< Graph whose subgraph we are
     61struct UniqueFragments {
     62  config *configuration;
     63  atom *Root;
     64  Graph *Leaflet;
     65  KeySet *FragmentSet;
     66  int ANOVAOrder;
     67  int FragmentCounter;
     68  int CurrentIndex;
     69  double TEFactor;
     70  int *ShortestPathList;
     71  bool **UsedList;
     72  bond **BondsPerSPList;
     73  int *BondsPerSPCount;
    4874};
    4975
    50 /** Class containing the nodes of a graph.
    51  */
    52 class Node
    53 {
    54         int     id;                             //!< individual id of the node
    55         char *Name;             //!< Name of the node for pretty printing
    56 };
     76/********************************************** declarations *******************************/
    5777
    58 /** Class containing egdes in a Graph strructure.
    59  */
    60 class Edge
    61 {
    62         class Node *leftnode;           //!< pointer to first node
    63         class Node *atomnode;           //!< pointer to second node
    64 };
     78///** Graph class containing the graphs behind molecules.
     79// */
     80//class Graph
     81//{
     82//      NodeMap ListOfNodes;            //!< tree-list of all nodes in this graph
     83//      EdgeMap ListOfEdges;            //!< tree-multi-list of all nodes, referenced to node id
     84//};
     85//
     86///** Class describing subgraphs of the Class \a Graph.
     87// * SubGraph has its own node and edge lists, however also a pointer to its father graph
     88// * and hence access to its list as well.
     89// */
     90//class SubGraph : class Graph
     91//{
     92//      class Graph *FatherGraph;               //!< Graph whose subgraph we are
     93//};
     94//
     95///** Class containing the nodes of a graph.
     96// */
     97//class Node
     98//{
     99//      int     id;                             //!< individual id of the node
     100//      char *Name;             //!< Name of the node for pretty printing
     101//};
     102//
     103///** Class containing egdes in a Graph strructure.
     104// */
     105//class Edge
     106//{
     107//      class Node *leftnode;           //!< pointer to first node
     108//      class Node *atomnode;           //!< pointer to second node
     109//};
    65110
    66111
  • src/helpers.cpp

    r87e2e39 rc111db  
    66
    77#include "helpers.hpp"
    8 #include "memoryusageobserver.hpp"
    98
    109/********************************************** helpful functions *********************************/
     
    118117};
    119118
    120 /**
    121  * Allocates a memory range using malloc().
     119/** Blows the 6-dimensional \a cell_size array up to a full NDIM by NDIM matrix.
     120 * \param *symm 6-dim array of unique symmetric matrix components
     121 * \return allocated NDIM*NDIM array with the symmetric matrix
     122 */
     123double * ReturnFullMatrixforSymmetric(double *symm)
     124{
     125  double *matrix = Malloc<double>(NDIM * NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix");
     126  matrix[0] = symm[0];
     127  matrix[1] = symm[1];
     128  matrix[2] = symm[3];
     129  matrix[3] = symm[1];
     130  matrix[4] = symm[2];
     131  matrix[5] = symm[4];
     132  matrix[6] = symm[3];
     133  matrix[7] = symm[4];
     134  matrix[8] = symm[5];
     135  return matrix;
     136};
     137
     138/** Comparison function for GSL heapsort on distances in two molecules.
     139 * \param *a
     140 * \param *b
     141 * \return <0, \a *a less than \a *b, ==0 if equal, >0 \a *a greater than \a *b
     142 */
     143int CompareDoubles (const void * a, const void * b)
     144{
     145  if (*(double *)a > *(double *)b)
     146    return -1;
     147  else if (*(double *)a < *(double *)b)
     148    return 1;
     149  else
     150    return 0;
     151};
     152
     153
     154/** Allocates a memory range using malloc().
    122155 * Prints the provided error message in case of a failure.
    123156 *
     
    147180 * Frees all memory registered by the memory observer and calls exit(225) afterwards.
    148181 */
    149 void performCriticalExit() {
     182static void performCriticalExit() {
    150183  map<void*, size_t> pointers = MemoryUsageObserver::getInstance()->getPointersToAllocatedMemory();
    151184  for (map<void*, size_t>::iterator runner = pointers.begin(); runner != pointers.end(); runner++) {
  • src/helpers.hpp

    r87e2e39 rc111db  
    99using namespace std;
    1010
     11/*********************************************** includes ***********************************/
     12
    1113// include config.h
    1214#ifdef HAVE_CONFIG_H
     
    1416#endif
    1517
    16 #include <iostream>
    17 #include <iomanip>
    1818#include <fstream>
    19 #include <sstream>
    20 #include <math.h>
    21 #include <string>
    2219
    23 #include "defs.hpp"
    24 #include "verbose.hpp"
    2520#include "memoryallocator.hpp"
    2621
     
    5348char *FixedDigitNumber(const int FragmentNumber, const int digits);
    5449bool IsValidNumber( const char *string);
     50int CompareDoubles (const void * a, const void * b);
     51double * ReturnFullMatrixforSymmetric(double *cell_size);
    5552static void performCriticalExit();
    5653
     
    115112};
    116113
    117 /******************************** Some templates for list management ***********************************/
    118 
    119 /** Adds linking of an item to a list.
    120  * \param *walker
    121  * \return true - adding succeeded, false - error in list
    122  */
    123 template <typename X> void link(X *walker, X *end)
    124 {
    125   X *vorher = end->previous;
    126   if (vorher != NULL)
    127     vorher->next = walker;
    128   end->previous = walker;
    129   walker->previous = vorher;
    130   walker->next = end;
    131 };
    132 
    133 /** Removes linking of an item in a list.
    134  * \param *walker
    135  * \return true - removing succeeded, false - given item not found in list
    136  */
    137 template <typename X> void unlink(X *walker)
    138 {
    139   if (walker->next != NULL)
    140     walker->next->previous = walker->previous;
    141   if (walker->previous != NULL)
    142     walker->previous->next = walker->next;
    143 };
    144 
    145 /** Adds new item before an item \a *end in a list.
    146  * \param *pointer   item to be added
    147  * \param *end  end of list
    148  * \return true - addition succeeded, false - unable to add item to list
    149  */
    150 template <typename X>  bool add(X *pointer, X *end)
    151 {
    152   if (end != NULL) {
    153     link(pointer, end);
    154   } else {
    155     pointer->previous = NULL;
    156     pointer->next = NULL;
    157   }
    158   return true;
    159 };
    160 
    161 /** Finds item in list
    162  * \param *suche  search criteria
    163  * \param *start  begin of list
    164  * \param *end  end of list
    165  * \return X - if found, NULL - if not found
    166  */
    167 template <typename X, typename Y> X * find(Y *suche, X *start, X *end)
    168 {
    169   X *walker = start;
    170   while (walker->next != end) { // go through list
    171     walker = walker->next; // step onward beforehand
    172     if (*walker->sort == *suche) return (walker);
    173   }
    174   return NULL;
    175 };
    176 
    177 /** Removes an item from the list without check.
    178  * \param *walker item to be removed
    179  * \return true - removing succeeded, false - given item not found in list
    180  */
    181 template <typename X> void removewithoutcheck(X *walker)
    182 {
    183   if (walker != NULL) {
    184     unlink(walker);
    185     delete(walker);
    186     walker = NULL;
    187   }
    188 };
    189 
    190 /** Removes an item from the list, checks if exists.
    191  * Checks beforehand if atom is really within molecule list.
    192  * \param *pointer   item to be removed
    193  * \param *start  begin of list
    194  * \param *end  end of list
    195  * \return true - removing succeeded, false - given item not found in list
    196  */
    197 template <typename X> bool remove(X *pointer, X *start, X *end)
    198 {
    199   X *walker = find (pointer->sort, start, end);
    200 /*  while (walker->next != pointer) { // search through list
    201     walker = walker->next;
    202     if (walker == end) return false;  // item not found in list
    203   }*/
    204   // atom found, now unlink
    205   if (walker != NULL)
    206     removewithoutcheck(walker);
    207   else
    208     return false;
    209   return true;
    210 };
    211 
    212 /** Cleans the whole list.
    213  * \param *start begin of list
    214  * \param *end end of list
    215  * \return true - list was cleaned successfully, false - error in list structure
    216  */
    217 template <typename X> bool cleanup(X *start, X *end)
    218 {
    219   X *pointer = start->next;
    220   X *walker;
    221   while (pointer != end) { // go through list
    222     walker = pointer; // mark current
    223     pointer = pointer->next; // step onward beforehand
    224     // remove walker
    225     unlink(walker);
    226     delete(walker);
    227     walker = NULL;
    228   }
    229   return true;
    230 };
    231 
    232 /** Returns the first marker in a chain list.
    233  * \param *me one arbitrary item in chain list
    234  * \return poiner to first marker
    235  */
    236 template <typename X> X *GetFirst(X *me)
    237 {
    238   X *Binder = me;
    239   while(Binder->previous != NULL)
    240     Binder = Binder->previous;
    241   return Binder;
    242 };
    243 
    244 /** Returns the last marker in a chain list.
    245  * \param *me one arbitrary item in chain list
    246  * \return poiner to last marker
    247  */
    248 template <typename X> X *GetLast(X *me)
    249 {
    250   X *Binder = me;
    251   while(Binder->next != NULL)
    252     Binder = Binder->next;
    253   return Binder;
    254 };
    255 
    256114/** Frees a two-dimensional array.
    257115 * \param *ptr pointer to array
     
    269127};
    270128
     129template <typename T> void Increment(T *value, T inc)
     130{
     131  *value += inc;
     132};
     133
     134template <typename T> void AbsoluteValue(T *value, T abs)
     135{
     136  *value = abs;
     137};
     138
     139
    271140
    272141
  • src/leastsquaremin.cpp

    r87e2e39 rc111db  
    66 */
    77
     8#include <iostream>
     9
    810#include "leastsquaremin.hpp"
     11#include "vector.hpp"
    912
    1013/** Determines sum of squared distances of \a X to all \a **vectors.
  • src/leastsquaremin.hpp

    r87e2e39 rc111db  
    99#define LEASTSQUAREMIN_HPP_
    1010
    11 #include "vector.hpp"
     11using namespace std;
     12
     13/*********************************************** includes ***********************************/
     14
     15// include config.h
     16#ifdef HAVE_CONFIG_H
     17#include <config.h>
     18#endif
     19
     20#include <gsl/gsl_vector.h>
     21
     22/****************************************** forward declarations *****************************/
    1223
    1324class element;
    1425class molecule;
     26class Vector;
     27
     28/********************************************** declarations *******************************/
    1529
    1630/** Parameter structure for least square minimsation.
  • src/linkedcell.cpp

    r87e2e39 rc111db  
    66
    77
     8#include "atom.hpp"
     9#include "helpers.hpp"
    810#include "linkedcell.hpp"
    9 #include "molecules.hpp"
     11#include "molecule.hpp"
    1012#include "tesselation.hpp"
     13#include "vector.hpp"
    1114
    1215// ========================================================= class LinkedCell ===========================================
     
    9699    //cout << Verbose(2) << *Walker << " goes into cell " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl;
    97100    set->GoToNext();
     101  }
     102  cout << "done."  << endl;
     103  cout << Verbose(1) << "End of LinkedCell" << endl;
     104};
     105
     106
     107/** Puts all atoms in \a *mol into a linked cell list with cell's lengths of \a RADIUS
     108 * \param *set LCNodeSet class with all LCNode's
     109 * \param RADIUS edge length of cells
     110 */
     111LinkedCell::LinkedCell(LinkedNodes *set, double radius)
     112{
     113  class TesselPoint *Walker = NULL;
     114  RADIUS = radius;
     115  LC = NULL;
     116  for(int i=0;i<NDIM;i++)
     117    N[i] = 0;
     118  index = -1;
     119  max.Zero();
     120  min.Zero();
     121  cout << Verbose(1) << "Begin of LinkedCell" << endl;
     122  if (set->empty()) {
     123    cerr << "ERROR: set contains no linked cell nodes!" << endl;
     124    return;
     125  }
     126  // 1. find max and min per axis of atoms
     127  LinkedNodes::iterator Runner = set->begin();
     128  for (int i=0;i<NDIM;i++) {
     129    max.x[i] = (*Runner)->node->x[i];
     130    min.x[i] = (*Runner)->node->x[i];
     131  }
     132  for (LinkedNodes::iterator Runner = set->begin(); Runner != set->end(); Runner++) {
     133    Walker = *Runner;
     134    for (int i=0;i<NDIM;i++) {
     135      if (max.x[i] < Walker->node->x[i])
     136        max.x[i] = Walker->node->x[i];
     137      if (min.x[i] > Walker->node->x[i])
     138        min.x[i] = Walker->node->x[i];
     139    }
     140  }
     141  cout << Verbose(2) << "Bounding box is " << min << " and " << max << "." << endl;
     142
     143  // 2. find then number of cells per axis
     144  for (int i=0;i<NDIM;i++) {
     145    N[i] = (int)floor((max.x[i] - min.x[i])/RADIUS)+1;
     146  }
     147  cout << Verbose(2) << "Number of cells per axis are " << N[0] << ", " << N[1] << " and " << N[2] << "." << endl;
     148
     149  // 3. allocate the lists
     150  cout << Verbose(2) << "Allocating cells ... ";
     151  if (LC != NULL) {
     152    cout << Verbose(1) << "ERROR: Linked Cell list is already allocated, I do nothing." << endl;
     153    return;
     154  }
     155  LC = new LinkedNodes[N[0]*N[1]*N[2]];
     156  for (index=0;index<N[0]*N[1]*N[2];index++) {
     157    LC [index].clear();
     158  }
     159  cout << "done."  << endl;
     160
     161  // 4. put each atom into its respective cell
     162  cout << Verbose(2) << "Filling cells ... ";
     163  for (LinkedNodes::iterator Runner = set->begin(); Runner != set->end(); Runner++) {
     164    Walker = *Runner;
     165    for (int i=0;i<NDIM;i++) {
     166      n[i] = (int)floor((Walker->node->x[i] - min.x[i])/RADIUS);
     167    }
     168    index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];
     169    LC[index].push_back(Walker);
     170    //cout << Verbose(2) << *Walker << " goes into cell " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl;
    98171  }
    99172  cout << "done."  << endl;
  • src/linkedcell.hpp

    r87e2e39 rc111db  
    1414using namespace std;
    1515
     16/*********************************************** includes ***********************************/
     17
    1618// include config.h
    1719#ifdef HAVE_CONFIG_H
     
    2224
    2325#include "defs.hpp"
    24 #include "helpers.hpp"
    2526#include "vector.hpp"
    2627
     28/****************************************** forward declarations *****************************/
     29
     30class PointCloud;
    2731class TesselPoint;
    28 class PointCloud;
     32
     33/********************************************** definitions *********************************/
    2934
    3035#define LinkedNodes list<TesselPoint *>
     36
     37/********************************************** declarations *******************************/
    3138
    3239/** Linked Cell class for containing Vectors in real space efficiently.
     
    4451    LinkedCell();
    4552    LinkedCell(PointCloud *set, double RADIUS);
     53    LinkedCell(LinkedNodes *set, double radius);
    4654    ~LinkedCell();
    4755    LinkedNodes* GetCurrentCell();
  • src/memoryallocator.hpp

    r87e2e39 rc111db  
    88
    99using namespace std;
     10
     11/*********************************************** includes ***********************************/
    1012
    1113// include config.h
     
    2628#include "memoryusageobserver.hpp"
    2729
    28 /******************* wrappers for memory allocation functions ***********************/
     30/********************************************** declarations *******************************/
    2931
    30 /**
    31  * Allocates a memory range using malloc().
     32/** Allocates a memory range using malloc().
    3233 * Prints the provided error message in case of a failure.
    3334 *
     
    5455template <> char* Malloc<char>(size_t size, const char* output);
    5556
    56 /**
    57  * Allocates a memory range using calloc().
     57/** Allocates a memory range using calloc().
    5858 * Prints the provided error message in case of a failure.
    5959 *
     
    7777};
    7878
    79 /**
    80  * Reallocates a memory range using realloc(). If the provided pointer to the old
     79/** Reallocates a memory range using realloc(). If the provided pointer to the old
    8180 * memory range is NULL, malloc() is called instead.
    8281 * Prints the provided error message in case of a failure (of either malloc() or realloc()).
     
    106105};
    107106
    108 /**
    109  * Frees allocated memory range using free().
     107/** Frees allocated memory range using free().
    110108 *
    111109 * \param pointer to the allocated memory range to free; may be NULL, this function is a no-op then
     110 * \param *msg optional error message
    112111 */
    113112template <typename X> void Free(X** buffer, const char *msg = NULL)
  • src/memoryusageobserver.cpp

    r87e2e39 rc111db  
    7777 *
    7878 * \param pointer to the allocated piece of memory
     79 * \param *msg optional error message
    7980 */
    8081void MemoryUsageObserver::removeMemory(void* pointer, const char *msg) {
     
    8384  if (current == memoryUsers.end()) {
    8485    cout << "WARNING: There is non-tracked memory to be freed. Pointer "
    85       << pointer << " is not registered by MemoryUsageObserver";
     86      << pointer << " is not registered by MemoryUsageObserver: ";
    8687    if (msg != NULL)
    87       cout << ": " << msg;
    88     cout << "." << endl;
     88      cout << *msg;
     89    cout << endl;
    8990    return;
    9091  }
  • src/memoryusageobserver.hpp

    r87e2e39 rc111db  
    88
    99using namespace std;
     10
     11/*********************************************** includes ***********************************/
    1012
    1113// include config.h
     
    2224#include <string>
    2325#include <typeinfo>
     26
     27/********************************************** declarations *******************************/
    2428
    2529class MemoryUsageObserver {
  • src/moleculelist.cpp

    r87e2e39 rc111db  
    55 */
    66
     7#include "atom.hpp"
     8#include "bond.hpp"
     9#include "boundary.hpp"
    710#include "config.hpp"
    8 #include "molecules.hpp"
     11#include "element.hpp"
     12#include "helpers.hpp"
     13#include "linkedcell.hpp"
     14#include "molecule.hpp"
    915#include "memoryallocator.hpp"
     16#include "periodentafel.hpp"
    1017
    1118/*********************************** Functions for class MoleculeListClass *************************/
     
    292299/** Embedding merge of a given set of molecules into one.
    293300 * Embedding merge inserts one molecule into the other.
    294  * \param *mol destination molecule
    295  * \param *srcmol source molecule
    296  * \return true - merge successful, false - merge failed (probably due to non-existant indices
    297  * \TODO find embedding center
     301 * \param *mol destination molecule (fixed one)
     302 * \param *srcmol source molecule (variable one, where atoms are taken from)
     303 * \return true - merge successful, false - merge failed (probably due to non-existant indices)
     304 * \TODO linked cell dimensions for boundary points has to be as big as inner diameter!
    298305 */
    299306bool MoleculeListClass::EmbedMerge(molecule *mol, molecule *srcmol)
    300307{
    301   if (srcmol == NULL)
     308  if ((srcmol == NULL) || (mol == NULL)) {
     309    cout << Verbose(1) << "ERROR: Either fixed or variable molecule is given as NULL." << endl;
    302310    return false;
    303 
    304   // calculate center for merge
    305   srcmol->Center.CopyVector(mol->FindEmbeddingHole((ofstream *)&cout, srcmol));
    306   srcmol->Center.Zero();
    307 
    308   // perform simple merge
    309   SimpleMerge(mol, srcmol);
     311  }
     312
     313  // calculate envelope for *mol
     314  LinkedCell *LCList = new LinkedCell(mol, 8.);
     315  FindNonConvexBorder((ofstream *)&cout, mol, LCList, 4., NULL);
     316  if (mol->TesselStruct == NULL) {
     317    cout << Verbose(1) << "ERROR: Could not tesselate the fixed molecule." << endl;
     318    return false;
     319  }
     320  delete(LCList);
     321  LCList = new LinkedCell(mol->TesselStruct, 8.);  // re-create with boundary points only!
     322
     323  // prepare index list for bonds
     324  srcmol->CountAtoms((ofstream *)&cout);
     325  atom ** CopyAtoms = new atom*[srcmol->AtomCount];
     326  for(int i=0;i<srcmol->AtomCount;i++)
     327    CopyAtoms[i] = NULL;
     328
     329  // for each of the source atoms check whether we are in- or outside and add copy atom
     330  atom *Walker = srcmol->start;
     331  int nr=0;
     332  while (Walker->next != srcmol->end) {
     333    Walker = Walker->next;
     334    cout << Verbose(2) << "INFO: Current Walker is " << *Walker << "." << endl;
     335    if (!mol->TesselStruct->IsInnerPoint((ofstream *)&cout, Walker->x, LCList)) {
     336      CopyAtoms[Walker->nr] = new atom(Walker);
     337      mol->AddAtom(CopyAtoms[Walker->nr]);
     338      nr++;
     339    } else {
     340      // do nothing
     341    }
     342  }
     343  cout << Verbose(1) << nr << " of " << srcmol->AtomCount << " atoms have been merged.";
     344
     345  // go through all bonds and add as well
     346  bond *Binder = srcmol->first;
     347  while(Binder->next != srcmol->last) {
     348    Binder = Binder->next;
     349    cout << Verbose(3) << "Adding Bond between " << *CopyAtoms[Binder->leftatom->nr] << " and " << *CopyAtoms[Binder->rightatom->nr]<< "." << endl;
     350    mol->AddBond(CopyAtoms[Binder->leftatom->nr], CopyAtoms[Binder->rightatom->nr], Binder->BondDegree);
     351  }
     352  delete(LCList);
    310353  return true;
    311354};
  • src/parser.cpp

    r87e2e39 rc111db  
    399399 * Sums over "E"-terms to create the "F"-terms
    400400 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.
    401  * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order
     401 * \param KeySets KeySetContainer with bond Order and association mapping of each fragment to an order
    402402 * \param Order bond order
    403403 * \return true if summing was successful
    404404 */
    405 bool MatrixContainer::SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySet, int Order)
     405bool MatrixContainer::SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySets, int Order)
    406406{
    407407  // go through each order
    408   for (int CurrentFragment=0;CurrentFragment<KeySet.FragmentsPerOrder[Order];CurrentFragment++) {
    409     //cout << "Current Fragment is " << CurrentFragment << "/" << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;
     408  for (int CurrentFragment=0;CurrentFragment<KeySets.FragmentsPerOrder[Order];CurrentFragment++) {
     409    //cout << "Current Fragment is " << CurrentFragment << "/" << KeySets.OrderSet[Order][CurrentFragment] << "." << endl;
    410410    // then go per order through each suborder and pick together all the terms that contain this fragment
    411411    for(int SubOrder=0;SubOrder<=Order;SubOrder++) { // go through all suborders up to the desired order
    412       for (int j=0;j<KeySet.FragmentsPerOrder[SubOrder];j++) { // go through all possible fragments of size suborder
    413         if (KeySet.Contains(KeySet.OrderSet[Order][CurrentFragment], KeySet.OrderSet[SubOrder][j])) {
    414           //cout << "Current other fragment is " << j << "/" << KeySet.OrderSet[SubOrder][j] << "." << endl;
     412      for (int j=0;j<KeySets.FragmentsPerOrder[SubOrder];j++) { // go through all possible fragments of size suborder
     413        if (KeySets.Contains(KeySets.OrderSet[Order][CurrentFragment], KeySets.OrderSet[SubOrder][j])) {
     414          //cout << "Current other fragment is " << j << "/" << KeySets.OrderSet[SubOrder][j] << "." << endl;
    415415          // if the fragment's indices are all in the current fragment
    416           for(int k=0;k<RowCounter[ KeySet.OrderSet[SubOrder][j] ];k++) { // go through all atoms in this fragment
    417             int m = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][k];
     416          for(int k=0;k<RowCounter[ KeySets.OrderSet[SubOrder][j] ];k++) { // go through all atoms in this fragment
     417            int m = MatrixValues.Indices[ KeySets.OrderSet[SubOrder][j] ][k];
    418418            //cout << "Current index is " << k << "/" << m << "." << endl;
    419419            if (m != -1) { // if it's not an added hydrogen
    420               for (int l=0;l<RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ];l++) { // look for the corresponding index in the current fragment
    421                 //cout << "Comparing " << m << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l] << "." << endl;
    422                 if (m == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l]) {
     420              for (int l=0;l<RowCounter[ KeySets.OrderSet[Order][CurrentFragment] ];l++) { // look for the corresponding index in the current fragment
     421                //cout << "Comparing " << m << " with " << MatrixValues.Indices[ KeySets.OrderSet[Order][CurrentFragment] ][l] << "." << endl;
     422                if (m == MatrixValues.Indices[ KeySets.OrderSet[Order][CurrentFragment] ][l]) {
    423423                  m = l;
    424424                  break;
     
    426426              }
    427427              //cout << "Corresponding index in CurrentFragment is " << m << "." << endl;
    428               if (m > RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) {
    429                 cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment]   << " current force index " << m << " is greater than " << RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl;
     428              if (m > RowCounter[ KeySets.OrderSet[Order][CurrentFragment] ]) {
     429                cerr << "In fragment No. " << KeySets.OrderSet[Order][CurrentFragment]   << " current force index " << m << " is greater than " << RowCounter[ KeySets.OrderSet[Order][CurrentFragment] ] << "!" << endl;
    430430                return false;
    431431              }
    432432              if (Order == SubOrder) { // equal order is always copy from Energies
    433                 for(int l=ColumnCounter[ KeySet.OrderSet[SubOrder][j] ];l--;) // then adds/subtract each column
    434                   Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] += MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];
     433                for(int l=ColumnCounter[ KeySets.OrderSet[SubOrder][j] ];l--;) // then adds/subtract each column
     434                  Matrix[ KeySets.OrderSet[Order][CurrentFragment] ][m][l] += MatrixValues.Matrix[ KeySets.OrderSet[SubOrder][j] ][k][l];
    435435              } else {
    436                 for(int l=ColumnCounter[ KeySet.OrderSet[SubOrder][j] ];l--;)
    437                   Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] -= Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];
     436                for(int l=ColumnCounter[ KeySets.OrderSet[SubOrder][j] ];l--;)
     437                  Matrix[ KeySets.OrderSet[Order][CurrentFragment] ][m][l] -= Matrix[ KeySets.OrderSet[SubOrder][j] ][k][l];
    438438              }
    439439            }
    440             //if ((ColumnCounter[ KeySet.OrderSet[SubOrder][j] ]>1) && (RowCounter[0]-1 >= 1))
    441              //cout << "Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " <<  Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl;
     440            //if ((ColumnCounter[ KeySets.OrderSet[SubOrder][j] ]>1) && (RowCounter[0]-1 >= 1))
     441             //cout << "Fragments[ KeySets.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySets.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " <<  Matrix[ KeySets.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl;
    442442          }
    443443        } else {
    444           //cout << "Fragment " << KeySet.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;
     444          //cout << "Fragment " << KeySets.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySets.OrderSet[Order][CurrentFragment] << "." << endl;
    445445        }
    446446      }
    447447    }
    448    //cout << "Final Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << KeySet.AtomCounter[0]-1 << "][" << 1 << "] = " <<  Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][KeySet.AtomCounter[0]-1][1] << endl;
     448   //cout << "Final Fragments[ KeySets.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySets.OrderSet[Order][CurrentFragment] << " ][" << KeySets.AtomCounter[0]-1 << "][" << 1 << "] = " <<  Matrix[ KeySets.OrderSet[Order][CurrentFragment] ][KeySets.AtomCounter[0]-1][1] << endl;
    449449  }
    450450
     
    534534 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.
    535535 * \param CorrectionFragments MatrixContainer with hydrogen saturation correction per fragments
    536  * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order
     536 * \param KeySets KeySetContainer with bond Order and association mapping of each fragment to an order
    537537 * \param Order bond order
    538538 * \parsm sign +1 or -1
    539539 * \return true if summing was successful
    540540 */
    541 bool EnergyMatrix::SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign)
     541bool EnergyMatrix::SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySets, int Order, double sign)
    542542{
    543543  // sum energy
    544544  if (CorrectionFragments == NULL)
    545     for(int i=KeySet.FragmentsPerOrder[Order];i--;)
    546       for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;)
    547         for(int k=ColumnCounter[ KeySet.OrderSet[Order][i] ];k--;)
    548           Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k];
     545    for(int i=KeySets.FragmentsPerOrder[Order];i--;)
     546      for(int j=RowCounter[ KeySets.OrderSet[Order][i] ];j--;)
     547        for(int k=ColumnCounter[ KeySets.OrderSet[Order][i] ];k--;)
     548          Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ KeySets.OrderSet[Order][i] ][j][k];
    549549  else
    550     for(int i=KeySet.FragmentsPerOrder[Order];i--;)
    551       for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;)
    552         for(int k=ColumnCounter[ KeySet.OrderSet[Order][i] ];k--;)
    553           Matrix[MatrixCounter][j][k] += sign*(Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k] + CorrectionFragments->Matrix[ KeySet.OrderSet[Order][i] ][j][k]);
     550    for(int i=KeySets.FragmentsPerOrder[Order];i--;)
     551      for(int j=RowCounter[ KeySets.OrderSet[Order][i] ];j--;)
     552        for(int k=ColumnCounter[ KeySets.OrderSet[Order][i] ];k--;)
     553          Matrix[MatrixCounter][j][k] += sign*(Fragments.Matrix[ KeySets.OrderSet[Order][i] ][j][k] + CorrectionFragments->Matrix[ KeySets.OrderSet[Order][i] ][j][k]);
    554554  return true;
    555555};
     
    641641/** Sums the forces and puts into last element of \a ForceMatrix::Matrix.
    642642 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.
    643  * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order
     643 * \param KeySets KeySetContainer with bond Order and association mapping of each fragment to an order
    644644 * \param Order bond order
    645645 *  \param sign +1 or -1
    646646 * \return true if summing was successful
    647647 */
    648 bool ForceMatrix::SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign)
     648bool ForceMatrix::SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySets, int Order, double sign)
    649649{
    650650  int FragmentNr;
    651651  // sum forces
    652   for(int i=0;i<KeySet.FragmentsPerOrder[Order];i++) {
    653     FragmentNr = KeySet.OrderSet[Order][i];
     652  for(int i=0;i<KeySets.FragmentsPerOrder[Order];i++) {
     653    FragmentNr = KeySets.OrderSet[Order][i];
    654654    for(int l=0;l<RowCounter[ FragmentNr ];l++) {
    655655      int j = Indices[ FragmentNr ][l];
     
    778778/** Sums the hessian entries and puts into last element of \a HessianMatrix::Matrix.
    779779 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.
    780  * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order
     780 * \param KeySets KeySetContainer with bond Order and association mapping of each fragment to an order
    781781 * \param Order bond order
    782782 *  \param sign +1 or -1
    783783 * \return true if summing was successful
    784784 */
    785 bool HessianMatrix::SumSubHessians(class HessianMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign)
     785bool HessianMatrix::SumSubHessians(class HessianMatrix &Fragments, class KeySetsContainer &KeySets, int Order, double sign)
    786786{
    787787  int FragmentNr;
    788788  // sum forces
    789   for(int i=0;i<KeySet.FragmentsPerOrder[Order];i++) {
    790     FragmentNr = KeySet.OrderSet[Order][i];
     789  for(int i=0;i<KeySets.FragmentsPerOrder[Order];i++) {
     790    FragmentNr = KeySets.OrderSet[Order][i];
    791791    for(int l=0;l<RowCounter[ FragmentNr ];l++) {
    792792      int j = Indices[ FragmentNr ][l];
     
    823823 * Sums over "E"-terms to create the "F"-terms
    824824 * \param Matrix MatrixContainer with matrices (LevelCounter by *ColumnCounter) with all the energies.
    825  * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order
     825 * \param KeySets KeySetContainer with bond Order and association mapping of each fragment to an order
    826826 * \param Order bond order
    827827 * \return true if summing was successful
    828828 */
    829 bool HessianMatrix::SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySet, int Order)
     829bool HessianMatrix::SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySets, int Order)
    830830{
    831831  // go through each order
    832   for (int CurrentFragment=0;CurrentFragment<KeySet.FragmentsPerOrder[Order];CurrentFragment++) {
    833     //cout << "Current Fragment is " << CurrentFragment << "/" << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;
     832  for (int CurrentFragment=0;CurrentFragment<KeySets.FragmentsPerOrder[Order];CurrentFragment++) {
     833    //cout << "Current Fragment is " << CurrentFragment << "/" << KeySets.OrderSet[Order][CurrentFragment] << "." << endl;
    834834    // then go per order through each suborder and pick together all the terms that contain this fragment
    835835    for(int SubOrder=0;SubOrder<=Order;SubOrder++) { // go through all suborders up to the desired order
    836       for (int j=0;j<KeySet.FragmentsPerOrder[SubOrder];j++) { // go through all possible fragments of size suborder
    837         if (KeySet.Contains(KeySet.OrderSet[Order][CurrentFragment], KeySet.OrderSet[SubOrder][j])) {
    838           //cout << "Current other fragment is " << j << "/" << KeySet.OrderSet[SubOrder][j] << "." << endl;
     836      for (int j=0;j<KeySets.FragmentsPerOrder[SubOrder];j++) { // go through all possible fragments of size suborder
     837        if (KeySets.Contains(KeySets.OrderSet[Order][CurrentFragment], KeySets.OrderSet[SubOrder][j])) {
     838          //cout << "Current other fragment is " << j << "/" << KeySets.OrderSet[SubOrder][j] << "." << endl;
    839839          // if the fragment's indices are all in the current fragment
    840           for(int k=0;k<RowCounter[ KeySet.OrderSet[SubOrder][j] ];k++) { // go through all atoms in this fragment
    841             int m = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][k];
     840          for(int k=0;k<RowCounter[ KeySets.OrderSet[SubOrder][j] ];k++) { // go through all atoms in this fragment
     841            int m = MatrixValues.Indices[ KeySets.OrderSet[SubOrder][j] ][k];
    842842            //cout << "Current row index is " << k << "/" << m << "." << endl;
    843843            if (m != -1) { // if it's not an added hydrogen
    844               for (int l=0;l<RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ];l++) { // look for the corresponding index in the current fragment
    845                 //cout << "Comparing " << m << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l] << "." << endl;
    846                 if (m == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l]) {
     844              for (int l=0;l<RowCounter[ KeySets.OrderSet[Order][CurrentFragment] ];l++) { // look for the corresponding index in the current fragment
     845                //cout << "Comparing " << m << " with " << MatrixValues.Indices[ KeySets.OrderSet[Order][CurrentFragment] ][l] << "." << endl;
     846                if (m == MatrixValues.Indices[ KeySets.OrderSet[Order][CurrentFragment] ][l]) {
    847847                  m = l;
    848848                  break; 
     
    850850              }
    851851              //cout << "Corresponding row index for " << k << " in CurrentFragment is " << m << "." << endl;
    852               if (m > RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) {
    853                 cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment]   << " current row index " << m << " is greater than " << RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl;
     852              if (m > RowCounter[ KeySets.OrderSet[Order][CurrentFragment] ]) {
     853                cerr << "In fragment No. " << KeySets.OrderSet[Order][CurrentFragment]   << " current row index " << m << " is greater than " << RowCounter[ KeySets.OrderSet[Order][CurrentFragment] ] << "!" << endl;
    854854                return false;
    855855              }
    856856             
    857               for(int l=0;l<ColumnCounter[ KeySet.OrderSet[SubOrder][j] ];l++) {
    858                 int n = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][l];
     857              for(int l=0;l<ColumnCounter[ KeySets.OrderSet[SubOrder][j] ];l++) {
     858                int n = MatrixValues.Indices[ KeySets.OrderSet[SubOrder][j] ][l];
    859859                //cout << "Current column index is " << l << "/" << n << "." << endl;
    860860                if (n != -1) { // if it's not an added hydrogen
    861                   for (int p=0;p<ColumnCounter[ KeySet.OrderSet[Order][CurrentFragment] ];p++) { // look for the corresponding index in the current fragment
    862                     //cout << "Comparing " << n << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][p] << "." << endl;
    863                     if (n == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][p]) {
     861                  for (int p=0;p<ColumnCounter[ KeySets.OrderSet[Order][CurrentFragment] ];p++) { // look for the corresponding index in the current fragment
     862                    //cout << "Comparing " << n << " with " << MatrixValues.Indices[ KeySets.OrderSet[Order][CurrentFragment] ][p] << "." << endl;
     863                    if (n == MatrixValues.Indices[ KeySets.OrderSet[Order][CurrentFragment] ][p]) {
    864864                      n = p;
    865865                      break; 
     
    867867                  }
    868868                  //cout << "Corresponding column index for " << l << " in CurrentFragment is " << n << "." << endl;
    869                   if (n > ColumnCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) {
    870                     cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment]   << " current column index " << n << " is greater than " << ColumnCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl;
     869                  if (n > ColumnCounter[ KeySets.OrderSet[Order][CurrentFragment] ]) {
     870                    cerr << "In fragment No. " << KeySets.OrderSet[Order][CurrentFragment]   << " current column index " << n << " is greater than " << ColumnCounter[ KeySets.OrderSet[Order][CurrentFragment] ] << "!" << endl;
    871871                    return false;
    872872                  }
    873873                  if (Order == SubOrder) { // equal order is always copy from Energies
    874                     //cout << "Adding " << MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l] << " from [" << k << "][" << l << "] onto [" << m << "][" << n << "]." << endl;
    875                     Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][n] += MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];
     874                    //cout << "Adding " << MatrixValues.Matrix[ KeySets.OrderSet[SubOrder][j] ][k][l] << " from [" << k << "][" << l << "] onto [" << m << "][" << n << "]." << endl;
     875                    Matrix[ KeySets.OrderSet[Order][CurrentFragment] ][m][n] += MatrixValues.Matrix[ KeySets.OrderSet[SubOrder][j] ][k][l];
    876876                  } else {
    877                     //cout << "Subtracting " << Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l] << " from [" << k << "][" << l << "] onto [" << m << "][" << n << "]." << endl;
    878                     Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][n] -= Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];
     877                    //cout << "Subtracting " << Matrix[ KeySets.OrderSet[SubOrder][j] ][k][l] << " from [" << k << "][" << l << "] onto [" << m << "][" << n << "]." << endl;
     878                    Matrix[ KeySets.OrderSet[Order][CurrentFragment] ][m][n] -= Matrix[ KeySets.OrderSet[SubOrder][j] ][k][l];
    879879                  }
    880880                }
    881881              }
    882882            }
    883             //if ((ColumnCounter[ KeySet.OrderSet[SubOrder][j] ]>1) && (RowCounter[0]-1 >= 1))
    884              //cout << "Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " <<  Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl;
     883            //if ((ColumnCounter[ KeySets.OrderSet[SubOrder][j] ]>1) && (RowCounter[0]-1 >= 1))
     884             //cout << "Fragments[ KeySets.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySets.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " <<  Matrix[ KeySets.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl;
    885885          }
    886886        } else {
    887           //cout << "Fragment " << KeySet.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;
     887          //cout << "Fragment " << KeySets.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySets.OrderSet[Order][CurrentFragment] << "." << endl;
    888888        }
    889889      }
    890890    }
    891    //cout << "Final Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << KeySet.AtomCounter[0]-1 << "][" << 1 << "] = " <<  Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][KeySet.AtomCounter[0]-1][1] << endl;
     891   //cout << "Final Fragments[ KeySets.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySets.OrderSet[Order][CurrentFragment] << " ][" << KeySets.AtomCounter[0]-1 << "][" << 1 << "] = " <<  Matrix[ KeySets.OrderSet[Order][CurrentFragment] ][KeySets.AtomCounter[0]-1][1] << endl;
    892892  }
    893893 
  • src/parser.hpp

    r87e2e39 rc111db  
    1 /** \file parsing.hpp
     1/** \file parser.hpp
    22 *
    33 * Definitions of various class functions for the parsing of value files.
     
    66
    77
    8 #ifndef PARSING_HPP_
    9 #define PARSING_HPP_
     8#ifndef PARSER_HPP_
     9#define PARSER_HPP_
    1010
    1111using namespace std;
     12
     13/*********************************************** includes ***********************************/
    1214
    1315// include config.h
     
    1618#endif
    1719
    18 // ======================================= DEFINES ==========================================
     20/****************************************** forward declarations *****************************/
     21
     22class EnergyMatrix;
     23class ForceMatrix;
     24class HessianMatrix;
     25class KeySetsContainer;
     26class MatrixContainer;
     27
     28/********************************************** definitions *********************************/
    1929
    2030#define EnergySuffix ".energy.all"
     
    4252bool TestParams(int argc, char **argv);
    4353
     54// ======================================= CLASS KeySetsContainer =============================
     55
     56class KeySetsContainer {
     57  public:
     58    int **KeySets;
     59    int *AtomCounter;
     60    int FragmentCounter;
     61    int Order;
     62    int *FragmentsPerOrder;
     63    int **OrderSet;
     64
     65  KeySetsContainer();
     66  ~KeySetsContainer();
     67
     68  bool ParseKeySets(const char *name, const int *ACounter, const int FCounter);
     69  bool ParseManyBodyTerms();
     70  bool Contains(const int GreaterSet, const int SmallerSet);
     71};
    4472
    4573// ======================================= CLASS MatrixContainer =============================
     
    6896  //bool ParseIndices();
    6997  //bool SumSubValues();
    70   bool SumSubManyBodyTerms(class MatrixContainer &Matrix, class KeySetsContainer &KeySet, int Order);
     98  bool SumSubManyBodyTerms(class MatrixContainer &Matrix, class KeySetsContainer &KeySets, int Order);
    7199  bool WriteTotalFragments(const char *name, const char *prefix);
    72100  bool WriteLastMatrix(const char *name, const char *prefix, const char *suffix);
     
    78106  public:
    79107    bool ParseIndices();
    80     bool SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign);
     108    bool SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySets, int Order, double sign);
    81109    bool ParseFragmentMatrix(const char *name, const char *prefix, string suffix, int skiplines, int skipcolumns);
    82110};
     
    87115  public:
    88116    bool ParseIndices(const char *name);
    89     bool SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign);
     117    bool SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySets, int Order, double sign);
    90118    bool ParseFragmentMatrix(const char *name, const char *prefix, string suffix, int skiplines, int skipcolumns);
    91119};
     
    98126    //~HessianMatrix();
    99127    bool ParseIndices(char *name);
    100     bool SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySet, int Order);
    101     bool SumSubHessians(class HessianMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign);
     128    bool SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySets, int Order);
     129    bool SumSubHessians(class HessianMatrix &Fragments, class KeySetsContainer &KeySets, int Order, double sign);
    102130    bool ParseFragmentMatrix(const char *name, const char *prefix, string suffix, int skiplines, int skipcolumns);
    103131  private:
     
    105133};
    106134
    107 // ======================================= CLASS KeySetsContainer =============================
    108 
    109 class KeySetsContainer {
    110   public:
    111     int **KeySets;
    112     int *AtomCounter;
    113     int FragmentCounter;
    114     int Order;
    115     int *FragmentsPerOrder;
    116     int **OrderSet;
    117 
    118   KeySetsContainer();
    119   ~KeySetsContainer();
    120 
    121   bool ParseKeySets(const char *name, const int *ACounter, const int FCounter);
    122   bool ParseManyBodyTerms();
    123   bool Contains(const int GreaterSet, const int SmallerSet);
    124 };
    125135
    126136// ======================================= END =============================================
    127137
    128 #endif /*PARSING_HPP_*/
     138#endif /*PARSER_HPP_*/
  • src/periodentafel.cpp

    r87e2e39 rc111db  
    1010#include <fstream>
    1111
     12#include "element.hpp"
    1213#include "helpers.hpp"
     14#include "lists.hpp"
    1315#include "periodentafel.hpp"
    1416#include "verbose.hpp"
  • src/periodentafel.hpp

    r87e2e39 rc111db  
    33
    44using namespace std;
     5
     6/*********************************************** includes ***********************************/
    57
    68// include config.h
     
    1214
    1315#include "defs.hpp"
    14 #include "element.hpp"
    1516
    16 // ====================================== class definitions =========================
     17/****************************************** forward declarations *****************************/
     18
     19class element;
     20
     21/********************************************** declarations *******************************/
    1722
    1823
  • src/stackclass.hpp

    r87e2e39 rc111db  
    22#define STACKCLASS_HPP_
    33
     4using namespace std;
     5
     6/*********************************************** includes ***********************************/
     7
     8// include config.h
     9#ifdef HAVE_CONFIG_H
     10#include <config.h>
     11#endif
     12
    413#include "verbose.hpp"
    514#include "memoryallocator.hpp"
     15
     16/****************************************** forward declarations *****************************/
    617
    718template <typename T> class StackClass;
  • src/tesselation.cpp

    r87e2e39 rc111db  
    66 */
    77
     8#include <fstream>
     9
     10#include "linkedcell.hpp"
    811#include "tesselation.hpp"
    9 #include "memoryallocator.hpp"
     12#include "tesselationhelpers.hpp"
     13#include "vector.hpp"
     14#include "verbose.hpp"
     15
     16class molecule;
    1017
    1118// ======================================== Points on Boundary =================================
     
    3744BoundaryPointSet::~BoundaryPointSet()
    3845{
    39   cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;
     46  //cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;
    4047  if (!lines.empty())
    4148    cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl;
     
    6774ostream & operator <<(ostream &ost, BoundaryPointSet &a)
    6875{
    69   ost << "[" << a.Nr << "|" << a.node->Name << "]";
     76  ost << "[" << a.Nr << "|" << a.node->Name << " at " << *a.node->node << "]";
    7077  return ost;
    7178}
     
    125132        for (LineMap::iterator Runner = erasor.first; Runner != erasor.second; Runner++)
    126133          if ((*Runner).second == this) {
    127             cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
     134            //cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
    128135            endpoints[i]->lines.erase(Runner);
    129136            break;
    130137          }
    131138      } else { // there's just a single line left
    132         if (endpoints[i]->lines.erase(Nr))
    133           cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
     139        if (endpoints[i]->lines.erase(Nr)) {
     140          //cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
     141        }
    134142      }
    135143      if (endpoints[i]->lines.empty()) {
    136         cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;
     144        //cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;
    137145        if (endpoints[i] != NULL) {
    138146          delete(endpoints[i]);
     
    168176
    169177/** Checks whether the adjacent triangles of a baseline are convex or not.
    170  * We sum the two angles of each normal vector with a ficticious normnal vector from this baselinbe pointing outwards.
     178 * We sum the two angles of each height vector with respect to the center of the baseline.
    171179 * If greater/equal M_PI than we are convex.
    172180 * \param *out output stream for debugging
     
    178186  // get the two triangles
    179187  if (triangles.size() != 2) {
    180     *out << Verbose(1) << "ERROR: Baseline " << *this << " is connect to less than two triangles, Tesselation incomplete!" << endl;
     188    *out << Verbose(1) << "ERROR: Baseline " << *this << " is connected to less than two triangles, Tesselation incomplete!" << endl;
    181189    return true;
    182190  }
     
    201209    NormalCheck.Scale(sign);
    202210    sign = -sign;
    203     BaseLineNormal.SubtractVector(&runner->second->NormalVector);   // we subtract as BaseLineNormal has to point inward in direction of [pi,2pi]
     211    if (runner->second->NormalVector.NormSquared() > MYEPSILON)
     212      BaseLineNormal.CopyVector(&runner->second->NormalVector);   // yes, copy second on top of first
     213    else {
     214      *out << Verbose(1) << "CRITICAL: Triangle " << *runner->second << " has zero normal vector!" << endl;
     215      exit(255);
     216    }
    204217    node = runner->second->GetThirdEndpoint(this);
    205218    if (node != NULL) {
     
    211224      i++;
    212225    } else {
    213       //*out << Verbose(2) << "WARNING: I cannot find third node in triangle, something's wrong." << endl;
     226      //*out << Verbose(2) << "ERROR: I cannot find third node in triangle, something's wrong." << endl;
    214227      return true;
    215228    }
     
    217230  //*out << Verbose(3) << "INFO: BaselineNormal is " << BaseLineNormal << "." << endl;
    218231  if (NormalCheck.NormSquared() < MYEPSILON) {
    219     *out << Verbose(2) << "ACCEPT: Normalvectors of both triangles are the same: convex." << endl;
     232    *out << Verbose(3) << "ACCEPT: Normalvectors of both triangles are the same: convex." << endl;
    220233    return true;
    221234  }
     235  BaseLineNormal.Scale(-1.);
    222236  double angle = GetAngle(helper[0], helper[1], BaseLineNormal);
    223237  if ((angle - M_PI) > -MYEPSILON) {
    224     *out << Verbose(2) << "ACCEPT: Angle is greater than pi: convex." << endl;
     238    *out << Verbose(3) << "ACCEPT: Angle is greater than pi: convex." << endl;
    225239    return true;
    226240  } else {
    227     *out << Verbose(2) << "REJECT: Angle is less than pi: concave." << endl;
     241    *out << Verbose(3) << "REJECT: Angle is less than pi: concave." << endl;
    228242    return false;
    229243  }
     
    262276ostream & operator <<(ostream &ost, BoundaryLineSet &a)
    263277{
    264   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "]";
     278  ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << " at " << *a.endpoints[0]->node->node << "," << a.endpoints[1]->node->Name << " at " << *a.endpoints[1]->node->node << "]";
    265279  return ost;
    266280};
     
    332346  for (int i = 0; i < 3; i++) {
    333347    if (lines[i] != NULL) {
    334       if (lines[i]->triangles.erase(Nr))
    335         cout << Verbose(5) << "Triangle Nr." << Nr << " erased in line " << *lines[i] << "." << endl;
     348      if (lines[i]->triangles.erase(Nr)) {
     349        //cout << Verbose(5) << "Triangle Nr." << Nr << " erased in line " << *lines[i] << "." << endl;
     350      }
    336351      if (lines[i]->triangles.empty()) {
    337           cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;
     352          //cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;
    338353          delete (lines[i]);
    339354          lines[i] = NULL;
     
    341356    }
    342357  }
    343   cout << Verbose(5) << "Erasing triangle Nr." << Nr << " itself." << endl;
     358  //cout << Verbose(5) << "Erasing triangle Nr." << Nr << " itself." << endl;
    344359};
    345360
     
    361376 * We call Vector::GetIntersectionWithPlane() to receive the intersection point with the plane
    362377 * This we test if it's really on the plane and whether it's inside the triangle on the plane or not.
    363  * The latter is done as follows: if it's really outside, then for any endpoint of the triangle and it's opposite
    364  * base line, the intersection between the line from endpoint to intersection and the base line will have a Vector::NormSquared()
    365  * smaller than the first line.
     378 * The latter is done as follows: We calculate the cross point of one of the triangle's baseline with the line
     379 * given by the intersection and the third basepoint. Then, we check whether it's on the baseline (i.e. between
     380 * the first two basepoints) or not.
    366381 * \param *out output stream for debugging
    367382 * \param *MolCenter offset vector of line
     
    395410    exit(255);
    396411  }
    397   CrossPoint.SubtractVector(endpoints[i%3]->node->node);
     412  CrossPoint.SubtractVector(endpoints[i%3]->node->node);  // cross point was returned as absolute vector
    398413
    399414  // check whether intersection is inside or not by comparing length of intersection and length of cross point
    400   if ((CrossPoint.NormSquared() - helper.NormSquared()) > -MYEPSILON) { // inside
     415  if ((CrossPoint.NormSquared() - helper.NormSquared()) < MYEPSILON) { // inside
    401416    return true;
    402417  } else { // outside!
     
    426441  for(int i=0;i<3;i++)
    427442    if (point == endpoints[i])
     443      return true;
     444  return false;
     445};
     446
     447/** Checks whether point is any of the three endpoints this triangle contains.
     448 * \param *point TesselPoint to test
     449 * \return true - point is of the triangle, false - is not
     450 */
     451bool BoundaryTriangleSet::ContainsBoundaryPoint(class TesselPoint *point)
     452{
     453  for(int i=0;i<3;i++)
     454    if (point == endpoints[i]->node)
    428455      return true;
    429456  return false;
     
    451478};
    452479
     480/** Checks whether three given \a *Points coincide with triangle's endpoints.
     481 * \param *Points[3] pointer to BoundaryPointSet
     482 * \return true - is the very triangle, false - is not
     483 */
     484bool BoundaryTriangleSet::IsPresentTupel(class BoundaryTriangleSet *T)
     485{
     486  return (((endpoints[0] == T->endpoints[0])
     487            || (endpoints[0] == T->endpoints[1])
     488            || (endpoints[0] == T->endpoints[2])
     489          ) && (
     490            (endpoints[1] == T->endpoints[0])
     491            || (endpoints[1] == T->endpoints[1])
     492            || (endpoints[1] == T->endpoints[2])
     493          ) && (
     494            (endpoints[2] == T->endpoints[0])
     495            || (endpoints[2] == T->endpoints[1])
     496            || (endpoints[2] == T->endpoints[2])
     497
     498          ));
     499};
     500
    453501/** Returns the endpoint which is not contained in the given \a *line.
    454502 * \param *line baseline defining two endpoints
     
    485533ostream &operator <<(ostream &ost, BoundaryTriangleSet &a)
    486534{
    487   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    488       << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]";
     535  ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << " at " << *a.endpoints[0]->node->node << ","
     536      << a.endpoints[1]->node->Name << " at " << *a.endpoints[1]->node->node << "," << a.endpoints[2]->node->Name << " at " << *a.endpoints[2]->node->node << "]";
    489537  return ost;
    490538};
     
    505553TesselPoint::~TesselPoint()
    506554{
    507   Free(&Name);
    508555};
    509556
     
    512559ostream & operator << (ostream &ost, const TesselPoint &a)
    513560{
    514   ost << "[" << (a.Name) << "|" << &a << "]";
     561  ost << "[" << (a.Name) << "|" << a.Name << " at " << *a.node << "]";
    515562  return ost;
    516563};
     
    569616  TrianglesOnBoundaryCount = 0;
    570617  InternalPointer = PointsOnBoundary.begin();
     618  LastTriangle = NULL;
     619  TriangleFilesWritten = 0;
    571620}
    572621;
     
    585634      cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl;
    586635  }
     636  cout << "This envelope was written to file " << TriangleFilesWritten << " times(s)." << endl;
    587637}
    588638;
     
    10521102  Vector *Center = cloud->GetCenter(out);
    10531103  list<BoundaryTriangleSet*> *triangles = NULL;
     1104  bool AddFlag = false;
     1105  LinkedCell *BoundaryPoints = NULL;
    10541106
    10551107  *out << Verbose(1) << "Begin of InsertStraddlingPoints" << endl;
    10561108
    10571109  cloud->GoToFirst();
     1110  BoundaryPoints = new LinkedCell(this, 5.);
    10581111  while (!cloud->IsEnd()) {  // we only have to go once through all points, as boundary can become only bigger
    1059     LinkedCell BoundaryPoints(this, 5.);
     1112    if (AddFlag) {
     1113      delete(BoundaryPoints);
     1114      BoundaryPoints = new LinkedCell(this, 5.);
     1115      AddFlag = false;
     1116    }
    10601117    Walker = cloud->GetPoint();
    10611118    *out << Verbose(2) << "Current point is " << *Walker << "." << endl;
    10621119    // get the next triangle
    1063     triangles = FindClosestTrianglesToPoint(out, Walker->node, &BoundaryPoints);
    1064     if (triangles == NULL) {
    1065       *out << Verbose(1) << "No triangles found, probably a tesselation point itself." << endl;
     1120    triangles = FindClosestTrianglesToPoint(out, Walker->node, BoundaryPoints);
     1121    BTS = triangles->front();
     1122    if ((triangles == NULL) || (BTS->ContainsBoundaryPoint(Walker))) {
     1123      *out << Verbose(2) << "No triangles found, probably a tesselation point itself." << endl;
    10661124      cloud->GoToNext();
    10671125      continue;
    10681126    } else {
    1069       BTS = triangles->front();
    10701127    }
    10711128    *out << Verbose(2) << "Closest triangle is " << *BTS << "." << endl;
     
    10901147        // add Walker to boundary points
    10911148        *out << Verbose(2) << "Adding " << *Walker << " to BoundaryPoints." << endl;
     1149        AddFlag = true;
    10921150        if (AddBoundaryPoint(Walker,0))
    10931151          NewPoint = BPS[0];
     
    11801238  } else {
    11811239    delete TPS[n];
    1182     cout << Verbose(3) << "Node " << *((InsertUnique.first)->second->node) << " is already present in PointsOnBoundary." << endl;
     1240    cout << Verbose(4) << "Node " << *((InsertUnique.first)->second->node) << " is already present in PointsOnBoundary." << endl;
    11831241    TPS[n] = (InsertUnique.first)->second;
    11841242  }
     
    11971255
    11981256  if (a->lines.find(b->node->nr) != a->lines.end()) {
    1199     LineMap::iterator FindLine;
     1257    LineMap::iterator FindLine = a->lines.find(b->node->nr);
    12001258    pair<LineMap::iterator,LineMap::iterator> FindPair;
    12011259    FindPair = a->lines.equal_range(b->node->nr);
    1202 
    1203     for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) {
     1260    cout << Verbose(5) << "INFO: There is at least one line between " << *a << " and " << *b << ": " << *(FindLine->second) << "." << endl;
     1261
     1262    for (FindLine = FindPair.first; FindLine != FindPair.second; FindLine++) {
    12041263      // If there is a line with less than two attached triangles, we don't need a new line.
    12051264      if (FindLine->second->triangles.size() < 2) {
    12061265        insertNewLine = false;
    1207         cout << Verbose(3) << "Using existing line " << *FindLine->second << endl;
     1266        cout << Verbose(4) << "Using existing line " << *FindLine->second << endl;
    12081267
    12091268        BPS[0] = FindLine->second->endpoints[0];
     
    12321291void Tesselation::AlwaysAddTesselationTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n)
    12331292{
    1234   cout << Verbose(3) << "Adding line between " << *(a->node) << " and " << *(b->node) << "." << endl;
     1293  cout << Verbose(4) << "Adding line [" << LinesOnBoundaryCount << "|" << *(a->node) << " and " << *(b->node) << "." << endl;
    12351294  BPS[0] = a;
    12361295  BPS[1] = b;
     
    12421301};
    12431302
    1244 /** Function tries to add Triangle just created to Triangle and remarks if already existent (Failure of algorithm).
    1245  * Furthermore it adds the triangle to all of its lines, in order to recognize those which are saturated later.
     1303/** Function adds triangle to global list.
     1304 * Furthermore, the triangle receives the next free id and id counter \a TrianglesOnBoundaryCount is increased.
    12461305 */
    12471306void Tesselation::AddTesselationTriangle()
     
    12521311  TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    12531312  TrianglesOnBoundaryCount++;
     1313
     1314  // set as last new triangle
     1315  LastTriangle = BTS;
     1316
     1317  // NOTE: add triangle to local maps is done in constructor of BoundaryTriangleSet
     1318};
     1319
     1320/** Function adds triangle to global list.
     1321 * Furthermore, the triangle number is set to \a nr.
     1322 * \param nr triangle number
     1323 */
     1324void Tesselation::AddTesselationTriangle(int nr)
     1325{
     1326  cout << Verbose(1) << "Adding triangle to global TrianglesOnBoundary map." << endl;
     1327
     1328  // add triangle to global map
     1329  TrianglesOnBoundary.insert(TrianglePair(nr, BTS));
     1330
     1331  // set as last new triangle
     1332  LastTriangle = BTS;
    12541333
    12551334  // NOTE: add triangle to local maps is done in constructor of BoundaryTriangleSet
     
    12721351          cout << Verbose(5) << *triangle->lines[i] << " is no more attached to any triangle, erasing." << endl;
    12731352          RemoveTesselationLine(triangle->lines[i]);
    1274           triangle->lines[i] = NULL;
    1275       } else
    1276         cout << Verbose(5) << *triangle->lines[i] << " is still attached to another triangle." << endl;
     1353      } else {
     1354        cout << Verbose(5) << *triangle->lines[i] << " is still attached to another triangle: ";
     1355        for(TriangleMap::iterator TriangleRunner = triangle->lines[i]->triangles.begin(); TriangleRunner != triangle->lines[i]->triangles.end(); TriangleRunner++)
     1356          cout << "[" << (TriangleRunner->second)->Nr << "|" << *((TriangleRunner->second)->endpoints[0]) << ", " << *((TriangleRunner->second)->endpoints[1]) << ", " << *((TriangleRunner->second)->endpoints[2]) << "] \t";
     1357        cout << endl;
     1358//        for (int j=0;j<2;j++) {
     1359//          cout << Verbose(5) << "Lines of endpoint " << *(triangle->lines[i]->endpoints[j]) << ": ";
     1360//          for(LineMap::iterator LineRunner = triangle->lines[i]->endpoints[j]->lines.begin(); LineRunner != triangle->lines[i]->endpoints[j]->lines.end(); LineRunner++)
     1361//            cout << "[" << *(LineRunner->second) << "] \t";
     1362//          cout << endl;
     1363//        }
     1364      }
     1365      triangle->lines[i] = NULL;  // free'd or not: disconnect
    12771366    } else
    12781367      cerr << "ERROR: This line " << i << " has already been free'd." << endl;
     
    12941383  if (line == NULL)
    12951384    return;
    1296   // get other endpoint number of finding copies of same line
     1385  // get other endpoint number for finding copies of same line
    12971386  if (line->endpoints[1] != NULL)
    12981387    Numbers[0] = line->endpoints[1]->Nr;
     
    13211410        cout << Verbose(5) << *line->endpoints[i] << " has no more lines it's attached to, erasing." << endl;
    13221411        RemoveTesselationPoint(line->endpoints[i]);
    1323         line->endpoints[i] = NULL;
    1324       } else
    1325         cout << Verbose(5) << *line->endpoints[i] << " has still lines it's attached to." << endl;
     1412      } else {
     1413        cout << Verbose(5) << *line->endpoints[i] << " has still lines it's attached to: ";
     1414        for(LineMap::iterator LineRunner = line->endpoints[i]->lines.begin(); LineRunner != line->endpoints[i]->lines.end(); LineRunner++)
     1415          cout << "[" << *(LineRunner->second) << "] \t";
     1416        cout << endl;
     1417      }
     1418      line->endpoints[i] = NULL;  // free'd or not: disconnect
    13261419    } else
    13271420      cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl;
     
    13901483          }
    13911484          // Only one of the triangle lines must be considered for the triangle count.
    1392           *out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl;
    1393           return adjacentTriangleCount;
     1485          //*out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl;
     1486          //return adjacentTriangleCount;
    13941487        }
    13951488      }
     
    14001493  *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
    14011494  return adjacentTriangleCount;
     1495};
     1496
     1497/** Checks whether the triangle consisting of the three points is already present.
     1498 * Searches for the points in Tesselation::PointsOnBoundary and checks their
     1499 * lines. If any of the three edges already has two triangles attached, false is
     1500 * returned.
     1501 * \param *out output stream for debugging
     1502 * \param *Candidates endpoints of the triangle candidate
     1503 * \return NULL - none found or pointer to triangle
     1504 */
     1505class BoundaryTriangleSet * Tesselation::GetPresentTriangle(ofstream *out, TesselPoint *Candidates[3])
     1506{
     1507  class BoundaryTriangleSet *triangle = NULL;
     1508  class BoundaryPointSet *Points[3];
     1509
     1510  // builds a triangle point set (Points) of the end points
     1511  for (int i = 0; i < 3; i++) {
     1512    PointMap::iterator FindPoint = PointsOnBoundary.find(Candidates[i]->nr);
     1513    if (FindPoint != PointsOnBoundary.end()) {
     1514      Points[i] = FindPoint->second;
     1515    } else {
     1516      Points[i] = NULL;
     1517    }
     1518  }
     1519
     1520  // checks lines between the points in the Points for their adjacent triangles
     1521  for (int i = 0; i < 3; i++) {
     1522    if (Points[i] != NULL) {
     1523      for (int j = i; j < 3; j++) {
     1524        if (Points[j] != NULL) {
     1525          LineMap::iterator FindLine = Points[i]->lines.find(Points[j]->node->nr);
     1526          for (; (FindLine != Points[i]->lines.end()) && (FindLine->first == Points[j]->node->nr); FindLine++) {
     1527            TriangleMap *triangles = &FindLine->second->triangles;
     1528            for (TriangleMap::iterator FindTriangle = triangles->begin(); FindTriangle != triangles->end(); FindTriangle++) {
     1529              if (FindTriangle->second->IsPresentTupel(Points)) {
     1530                if ((triangle == NULL) || (triangle->Nr > FindTriangle->second->Nr))
     1531                  triangle = FindTriangle->second;
     1532              }
     1533            }
     1534          }
     1535          // Only one of the triangle lines must be considered for the triangle count.
     1536          //*out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl;
     1537          //return adjacentTriangleCount;
     1538        }
     1539      }
     1540    }
     1541  }
     1542
     1543  return triangle;
    14021544};
    14031545
     
    14611603  CandidateList *OptCandidates = new CandidateList();
    14621604  for (int k=0;k<NDIM;k++) {
     1605    Oben.Zero();
    14631606    Oben.x[k] = 1.;
    14641607    FirstPoint = MaxPoint[k];
     
    14691612    ShortestAngle = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant.
    14701613
    1471     FindSecondPointForTesselation(FirstPoint, NULL, Oben, OptCandidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...
     1614    FindSecondPointForTesselation(FirstPoint, Oben, OptCandidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...
    14721615    SecondPoint = OptCandidate;
    14731616    if (SecondPoint == NULL)  // have we found a second point?
    14741617      continue;
    1475     else
    1476       cout << Verbose(1) << "Found second point is at " << *SecondPoint->node << ".\n";
    14771618
    14781619    helper.CopyVector(FirstPoint->node);
     
    14961637
    14971638    // adding point 1 and point 2 and add the line between them
     1639    cout << Verbose(1) << "Coordinates of start node at " << *FirstPoint->node << "." << endl;
    14981640    AddTesselationPoint(FirstPoint, 0);
     1641    cout << Verbose(1) << "Found second point is at " << *SecondPoint->node << ".\n";
    14991642    AddTesselationPoint(SecondPoint, 1);
    15001643    AddTesselationLine(TPS[0], TPS[1], 0);
     
    15691712 * @param *LC LinkedCell structure with neighbouring points
    15701713 */
    1571 bool Tesselation::FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, LinkedCell *LC)
     1714bool Tesselation::FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, LinkedCell *LC)
    15721715{
    15731716  cout << Verbose(0) << "Begin of FindNextSuitableTriangle\n";
     
    16041747    CircleRadius = RADIUS*RADIUS - radius/4.;
    16051748    CirclePlaneNormal.Normalize();
    1606     cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     1749    //cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    16071750
    16081751    // construct old center
     
    16911834        result = false;
    16921835      }
    1693     } else if (existentTrianglesCount == 1) { // If there is a planar region within the structure, we need this triangle a second time.
     1836    } else if ((existentTrianglesCount >= 1) && (existentTrianglesCount <= 3)) { // If there is a planar region within the structure, we need this triangle a second time.
    16941837        AddTesselationPoint((*it)->point, 0);
    16951838        AddTesselationPoint(BaseRay->endpoints[0]->node, 1);
     
    17321875    // set baseline to new ray from ref point (here endpoints[0]->node) to current candidate (here (*it)->point))
    17331876    BaseRay = BLS[0];
     1877    if ((BTS != NULL) && (BTS->NormalVector.NormSquared() < MYEPSILON)) {
     1878      *out << Verbose(1) << "CRITICAL: Triangle " << *BTS << " has zero normal vector!" << endl;
     1879      exit(255);
     1880    }
     1881
    17341882  }
    17351883
     
    17501898 * \param *out output stream for debugging
    17511899 * \param *Base line to be flipped
    1752  * \return NULL - concave, otherwise endpoint that makes it concave
     1900 * \return NULL - convex, otherwise endpoint that makes it concave
    17531901 */
    17541902class BoundaryPointSet *Tesselation::IsConvexRectangle(ofstream *out, class BoundaryLineSet *Base)
     
    18271975 * \param *out output stream for debugging
    18281976 * \param *Base line to be flipped
    1829  * \return true - line was changed, false - same line as before
    1830  */
    1831 bool Tesselation::PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base)
     1977 * \return volume change due to flipping (0 - then no flipped occured)
     1978 */
     1979double Tesselation::PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base)
    18321980{
    18331981  class BoundaryLineSet *OtherBase;
    18341982  Vector *ClosestPoint[2];
     1983  double volume;
    18351984
    18361985  int m=0;
     
    18522001  Distance.CopyVector(ClosestPoint[1]);
    18532002  Distance.SubtractVector(ClosestPoint[0]);
     2003
     2004  // calculate volume
     2005  volume = CalculateVolumeofGeneralTetraeder(Base->endpoints[1]->node->node, OtherBase->endpoints[0]->node->node, OtherBase->endpoints[1]->node->node, Base->endpoints[0]->node->node);
    18542006
    18552007  // delete the temporary other base line and the closest points
     
    18662018    if (Base->triangles.size() < 2) {
    18672019      *out << Verbose(2) << "ERROR: Less than two triangles are attached to this baseline!" << endl;
    1868       return false;
     2020      return 0.;
    18692021    }
    18702022    for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) {
     
    18762028    if (Distance.ScalarProduct(&BaseLineNormal) > MYEPSILON) { // Distance points outwards, hence OtherBase higher than Base -> flip
    18772029      *out << Verbose(2) << "ACCEPT: Other base line would be higher: Flipping baseline." << endl;
    1878       FlipBaseline(out, Base);
    1879       return true;
     2030      // calculate volume summand as a general tetraeder
     2031      return volume;
    18802032    } else {  // Base higher than OtherBase -> do nothing
    18812033      *out << Verbose(2) << "REJECT: Base line is higher: Nothing to do." << endl;
    1882       return false;
    1883     }
    1884   }
    1885 };
    1886 
    1887 /** Returns the closest point on \a *Base with respect to \a *OtherBase.
    1888  * \param *out output stream for debugging
    1889  * \param *Base reference line
    1890  * \param *OtherBase other base line
    1891  * \return Vector on reference line that has closest distance
    1892  */
    1893 Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase)
    1894 {
    1895   // construct the plane of the two baselines (i.e. take both their directional vectors)
    1896   Vector Normal;
    1897   Vector Baseline, OtherBaseline;
    1898   Baseline.CopyVector(Base->endpoints[1]->node->node);
    1899   Baseline.SubtractVector(Base->endpoints[0]->node->node);
    1900   OtherBaseline.CopyVector(OtherBase->endpoints[1]->node->node);
    1901   OtherBaseline.SubtractVector(OtherBase->endpoints[0]->node->node);
    1902   Normal.CopyVector(&Baseline);
    1903   Normal.VectorProduct(&OtherBaseline);
    1904   Normal.Normalize();
    1905   *out << Verbose(4) << "First direction is " << Baseline << ", second direction is " << OtherBaseline << ", normal of intersection plane is " << Normal << "." << endl;
    1906 
    1907   // project one offset point of OtherBase onto this plane (and add plane offset vector)
    1908   Vector NewOffset;
    1909   NewOffset.CopyVector(OtherBase->endpoints[0]->node->node);
    1910   NewOffset.SubtractVector(Base->endpoints[0]->node->node);
    1911   NewOffset.ProjectOntoPlane(&Normal);
    1912   NewOffset.AddVector(Base->endpoints[0]->node->node);
    1913   Vector NewDirection;
    1914   NewDirection.CopyVector(&NewOffset);
    1915   NewDirection.AddVector(&OtherBaseline);
    1916 
    1917   // calculate the intersection between this projected baseline and Base
    1918   Vector *Intersection = new Vector;
    1919   Intersection->GetIntersectionOfTwoLinesOnPlane(out, Base->endpoints[0]->node->node, Base->endpoints[1]->node->node, &NewOffset, &NewDirection, &Normal);
    1920   Normal.CopyVector(Intersection);
    1921   Normal.SubtractVector(Base->endpoints[0]->node->node);
    1922   *out << Verbose(3) << "Found closest point on " << *Base << " at " << *Intersection << ", factor in line is " << fabs(Normal.ScalarProduct(&Baseline)/Baseline.NormSquared()) << "." << endl;
    1923 
    1924   return Intersection;
     2034      return 0.;
     2035    }
     2036  }
    19252037};
    19262038
     
    19302042 * \param *out output stream for debugging
    19312043 * \param *Base line to be flipped
    1932  * \return true - flipping successful, false - something went awry
    1933  */
    1934 bool Tesselation::FlipBaseline(ofstream *out, class BoundaryLineSet *Base)
     2044 * \return pointer to allocated new baseline - flipping successful, NULL - something went awry
     2045 */
     2046class BoundaryLineSet * Tesselation::FlipBaseline(ofstream *out, class BoundaryLineSet *Base)
    19352047{
    19362048  class BoundaryLineSet *OldLines[4], *NewLine;
     
    19462058  if (Base->triangles.size() < 2) {
    19472059    *out << Verbose(2) << "ERROR: Less than two triangles are attached to this baseline!" << endl;
    1948     return false;
     2060    return NULL;
    19492061  }
    19502062  for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) {
     
    19822094  if (i<4) {
    19832095    *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl;
    1984     return false;
     2096    return NULL;
    19852097  }
    19862098  for (int j=0;j<4;j++)
    19872099    if (OldLines[j] == NULL) {
    19882100      *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl;
    1989       return false;
     2101      return NULL;
    19902102    }
    19912103  for (int j=0;j<2;j++)
    19922104    if (OldPoints[j] == NULL) {
    19932105      *out << Verbose(1) << "ERROR: We have not gathered enough endpoints!" << endl;
    1994       return false;
     2106      return NULL;
    19952107    }
    19962108
     
    20242136    BTS = new class BoundaryTriangleSet(BLS, OldTriangleNrs[0]);
    20252137    BTS->GetNormalVector(BaseLineNormal);
    2026     TrianglesOnBoundary.insert(TrianglePair(OldTriangleNrs[0], BTS));
     2138    AddTesselationTriangle(OldTriangleNrs[0]);
    20272139    *out << Verbose(3) << "INFO: Created new triangle " << *BTS << "." << endl;
    20282140
     
    20322144    BTS = new class BoundaryTriangleSet(BLS, OldTriangleNrs[1]);
    20332145    BTS->GetNormalVector(BaseLineNormal);
    2034     TrianglesOnBoundary.insert(TrianglePair(OldTriangleNrs[1], BTS));
     2146    AddTesselationTriangle(OldTriangleNrs[1]);
    20352147    *out << Verbose(3) << "INFO: Created new triangle " << *BTS << "." << endl;
    20362148  } else {
    20372149    *out << Verbose(1) << "The four old lines do not connect, something's utterly wrong here!" << endl;
    2038     return false;
     2150    return NULL;
    20392151  }
    20402152
    20412153  *out << Verbose(1) << "End of FlipBaseline" << endl;
    2042   return true;
     2154  return NewLine;
    20432155};
    20442156
     
    20462158/** Finds the second point of starting triangle.
    20472159 * \param *a first node
    2048  * \param *Candidate pointer to candidate node on return
    20492160 * \param Oben vector indicating the outside
    20502161 * \param OptCandidate reference to recommended candidate on return
     
    20532164 * \param *LC LinkedCell structure with neighbouring points
    20542165 */
    2055 void Tesselation::FindSecondPointForTesselation(TesselPoint* a, TesselPoint* Candidate, Vector Oben, TesselPoint*& OptCandidate, double Storage[3], double RADIUS, LinkedCell *LC)
     2166void Tesselation::FindSecondPointForTesselation(TesselPoint* a, Vector Oben, TesselPoint*& OptCandidate, double Storage[3], double RADIUS, LinkedCell *LC)
    20562167{
    20572168  cout << Verbose(2) << "Begin of FindSecondPointForTesselation" << endl;
    20582169  Vector AngleCheck;
     2170  class TesselPoint* Candidate = NULL;
    20592171  double norm = -1., angle;
    20602172  LinkedNodes *List = NULL;
     
    21912303  cout << Verbose(1) << "Begin of FindThirdPointForTesselation" << endl;
    21922304
    2193   //cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
     2305  cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
    21942306
    21952307  // construct center of circle
     
    22162328    radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
    22172329    if (fabs(radius - CircleRadius) < HULLEPSILON) {
     2330      //cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
    22182331
    22192332      // check SearchDirection
     
    23922505  TesselPoint *trianglePoints[3];
    23932506  TesselPoint *SecondPoint = NULL;
     2507  list<BoundaryTriangleSet*> *triangles = NULL;
    23942508
    23952509  if (LinesOnBoundary.empty()) {
     
    24022516  // check whether closest point is "too close" :), then it's inside
    24032517  if (trianglePoints[0] == NULL) {
    2404     *out << Verbose(1) << "Is the only point, no one else is closeby." << endl;
     2518    *out << Verbose(2) << "Is the only point, no one else is closeby." << endl;
    24052519    return NULL;
    24062520  }
    24072521  if (trianglePoints[0]->node->DistanceSquared(x) < MYEPSILON) {
    2408     *out << Verbose(1) << "Point is right on a tesselation point, no nearest triangle." << endl;
    2409     return NULL;
    2410   }
    2411   list<TesselPoint*> *connectedPoints = GetCircleOfConnectedPoints(out, trianglePoints[0]);
    2412   list<TesselPoint*> *connectedClosestPoints = GetNeighboursOnCircleOfConnectedPoints(out, connectedPoints, trianglePoints[0], x);
    2413   delete(connectedPoints);
    2414   trianglePoints[1] = connectedClosestPoints->front();
    2415   trianglePoints[2] = connectedClosestPoints->back();
    2416   for (int i=0;i<3;i++) {
    2417     if (trianglePoints[i] == NULL) {
    2418       *out << Verbose(1) << "IsInnerPoint encounters serious error, point " << i << " not found." << endl;
    2419     }
    2420     //*out << Verbose(1) << "List of possible points:" << endl;
    2421     //*out << Verbose(2) << *trianglePoints[i] << endl;
    2422   }
    2423 
    2424   list<BoundaryTriangleSet*> *triangles = FindTriangles(trianglePoints);
    2425 
    2426   delete(connectedClosestPoints);
     2522    *out << Verbose(3) << "Point is right on a tesselation point, no nearest triangle." << endl;
     2523    PointMap::iterator PointRunner = PointsOnBoundary.find(trianglePoints[0]->nr);
     2524    triangles = new list<BoundaryTriangleSet*>;
     2525    if (PointRunner != PointsOnBoundary.end()) {
     2526      for(LineMap::iterator LineRunner = PointRunner->second->lines.begin(); LineRunner != PointRunner->second->lines.end(); LineRunner++)
     2527        for(TriangleMap::iterator TriangleRunner = LineRunner->second->triangles.begin(); TriangleRunner != LineRunner->second->triangles.end(); TriangleRunner++)
     2528          triangles->push_back(TriangleRunner->second);
     2529      triangles->sort();
     2530      triangles->unique();
     2531    } else {
     2532      PointRunner = PointsOnBoundary.find(SecondPoint->nr);
     2533      trianglePoints[0] = SecondPoint;
     2534      if (PointRunner != PointsOnBoundary.end()) {
     2535        for(LineMap::iterator LineRunner = PointRunner->second->lines.begin(); LineRunner != PointRunner->second->lines.end(); LineRunner++)
     2536          for(TriangleMap::iterator TriangleRunner = LineRunner->second->triangles.begin(); TriangleRunner != LineRunner->second->triangles.end(); TriangleRunner++)
     2537            triangles->push_back(TriangleRunner->second);
     2538        triangles->sort();
     2539        triangles->unique();
     2540      } else {
     2541        *out << Verbose(1) << "ERROR: I cannot find a boundary point to the tessel point " << *trianglePoints[0] << "." << endl;
     2542        return NULL;
     2543      }
     2544    }
     2545  } else {
     2546    list<TesselPoint*> *connectedClosestPoints = GetCircleOfConnectedPoints(out, trianglePoints[0], x);
     2547    trianglePoints[1] = connectedClosestPoints->front();
     2548    trianglePoints[2] = connectedClosestPoints->back();
     2549    for (int i=0;i<3;i++) {
     2550      if (trianglePoints[i] == NULL) {
     2551        *out << Verbose(1) << "ERROR: IsInnerPoint encounters serious error, point " << i << " not found." << endl;
     2552      }
     2553      //*out << Verbose(2) << "List of triangle points:" << endl;
     2554      //*out << Verbose(3) << *trianglePoints[i] << endl;
     2555    }
     2556
     2557    triangles = FindTriangles(trianglePoints);
     2558    *out << Verbose(2) << "List of possible triangles:" << endl;
     2559    for(list<BoundaryTriangleSet*>::iterator Runner = triangles->begin(); Runner != triangles->end(); Runner++)
     2560      *out << Verbose(3) << **Runner << endl;
     2561
     2562    delete(connectedClosestPoints);
     2563  }
    24272564 
    24282565  if (triangles->empty()) {
    2429     *out << Verbose(0) << "Error: There is no nearest triangle. Please check the tesselation structure.";
     2566    *out << Verbose(0) << "ERROR: There is no nearest triangle. Please check the tesselation structure.";
     2567    delete(triangles);
    24302568    return NULL;
    24312569  } else
     
    24432581  class BoundaryTriangleSet *result = NULL;
    24442582  list<BoundaryTriangleSet*> *triangles = FindClosestTrianglesToPoint(out, x, LC);
     2583  Vector Center;
    24452584
    24462585  if (triangles == NULL)
    24472586    return NULL;
    24482587
    2449   if (x->ScalarProduct(&triangles->front()->NormalVector) < 0)
    2450     result = triangles->back();
    2451   else
     2588  if (triangles->size() == 1) { // there is no degenerate case
    24522589    result = triangles->front();
    2453 
     2590    *out << Verbose(2) << "Normal Vector of this triangle is " << result->NormalVector << "." << endl;
     2591  } else {
     2592    result = triangles->front();
     2593    result->GetCenter(&Center);
     2594    Center.SubtractVector(x);
     2595    *out << Verbose(2) << "Normal Vector of this front side is " << result->NormalVector << "." << endl;
     2596    if (Center.ScalarProduct(&result->NormalVector) < 0) {
     2597      result = triangles->back();
     2598      *out << Verbose(2) << "Normal Vector of this back side is " << result->NormalVector << "." << endl;
     2599      if (Center.ScalarProduct(&result->NormalVector) < 0) {
     2600        *out << Verbose(1) << "ERROR: Front and back side yield NormalVector in wrong direction!" << endl;
     2601      }
     2602    }
     2603  }
    24542604  delete(triangles);
    24552605  return result;
     
    24662616{
    24672617  class BoundaryTriangleSet *result = FindClosestTriangleToPoint(out, &Point, LC);
    2468   if (result == NULL)
     2618  Vector Center;
     2619
     2620  if (result == NULL) {// is boundary point or only point in point cloud?
     2621    *out << Verbose(1) << Point << " is the only point in vicinity." << endl;
     2622    return false;
     2623  }
     2624
     2625  result->GetCenter(&Center);
     2626  *out << Verbose(3) << "INFO: Central point of the triangle is " << Center << "." << endl;
     2627  Center.SubtractVector(&Point);
     2628  *out << Verbose(3) << "INFO: Vector from center to point to test is " << Center << "." << endl;
     2629  if (Center.ScalarProduct(&result->NormalVector) > -MYEPSILON) {
     2630    *out << Verbose(1) << Point << " is an inner point." << endl;
    24692631    return true;
    2470   if (Point.ScalarProduct(&result->NormalVector) < 0)
    2471     return true;
    2472   else
     2632  } else {
     2633    *out << Verbose(1) << Point << " is NOT an inner point." << endl;
    24732634    return false;
     2635  }
    24742636}
    24752637
     
    24832645bool Tesselation::IsInnerPoint(ofstream *out, TesselPoint *Point, LinkedCell* LC)
    24842646{
    2485   class BoundaryTriangleSet *result = FindClosestTriangleToPoint(out, Point->node, LC);
    2486   if (result == NULL)
    2487     return true;
    2488   if (Point->node->ScalarProduct(&result->NormalVector) < 0)
    2489     return true;
    2490   else
    2491     return false;
     2647  return IsInnerPoint(out, *(Point->node), LC);
    24922648}
    24932649
     
    24962652 * @param *Point of which get all connected points
    24972653 *
    2498  * @return list of the all points linked to the provided one
    2499  */
    2500 list<TesselPoint*> * Tesselation::GetCircleOfConnectedPoints(ofstream *out, TesselPoint* Point)
    2501 {
    2502   list<TesselPoint*> *connectedPoints = new list<TesselPoint*>;
     2654 * @return set of the all points linked to the provided one
     2655 */
     2656set<TesselPoint*> * Tesselation::GetAllConnectedPoints(ofstream *out, TesselPoint* Point)
     2657{
     2658  set<TesselPoint*> *connectedPoints = new set<TesselPoint*>;
    25032659  class BoundaryPointSet *ReferencePoint = NULL;
    25042660  TesselPoint* current;
     
    25102666    ReferencePoint = PointRunner->second;
    25112667  } else {
    2512     *out << Verbose(2) << "getCircleOfConnectedPoints() could not find the BoundaryPoint belonging to " << *Point << "." << endl;
     2668    *out << Verbose(2) << "GetAllConnectedPoints() could not find the BoundaryPoint belonging to " << *Point << "." << endl;
    25132669    ReferencePoint = NULL;
    25142670  }
    25152671
    2516   // little trick so that we look just through lines connect to the BoundaryPoint 
     2672  // little trick so that we look just through lines connect to the BoundaryPoint
    25172673  // OR fall-back to look through all lines if there is no such BoundaryPoint
    25182674  LineMap *Lines = &LinesOnBoundary;
     
    25212677  LineMap::iterator findLines = Lines->begin();
    25222678  while (findLines != Lines->end()) {
    2523     takePoint = false;
    2524 
    2525     if (findLines->second->endpoints[0]->Nr == Point->nr) {
    2526       takePoint = true;
    2527       current = findLines->second->endpoints[1]->node;
    2528     } else if (findLines->second->endpoints[1]->Nr == Point->nr) {
    2529       takePoint = true;
    2530       current = findLines->second->endpoints[0]->node;
    2531     }
    2532    
    2533     if (takePoint) {
    2534       *out << Verbose(3) << "INFO: Endpoint " << *current << " of line " << *(findLines->second) << " is taken into the circle." << endl;
    2535       connectedPoints->push_back(current);
    2536     }
    2537 
    2538     findLines++;
     2679   takePoint = false;
     2680
     2681   if (findLines->second->endpoints[0]->Nr == Point->nr) {
     2682     takePoint = true;
     2683     current = findLines->second->endpoints[1]->node;
     2684   } else if (findLines->second->endpoints[1]->Nr == Point->nr) {
     2685     takePoint = true;
     2686     current = findLines->second->endpoints[0]->node;
     2687   }
     2688
     2689   if (takePoint) {
     2690     *out << Verbose(5) << "INFO: Endpoint " << *current << " of line " << *(findLines->second) << " is enlisted." << endl;
     2691     connectedPoints->insert(current);
     2692   }
     2693
     2694   findLines++;
    25392695  }
    25402696
     
    25432699    return NULL;
    25442700  }
     2701
    25452702  return connectedPoints;
    2546 }
    2547 
    2548 /** Gets the two neighbouring points with respect to a reference line to the provided point.
     2703};
     2704
     2705
     2706/** Gets all points connected to the provided point by triangulation lines, ordered such that we have the circle round the point.
    25492707 * Maps them down onto the plane designated by the axis \a *Point and \a *Reference. The center of all points
    25502708 * connected in the tesselation to \a *Point is mapped to spherical coordinates with the zero angle being given
     
    25532711 *
    25542712 * @param *out output stream for debugging
    2555  * @param *connectedPoints list of connected points to the central \a *Point
    25562713 * @param *Point of which get all connected points
    2557  * @param *Reference Vector to be checked whether it is an inner point
    2558  *
    2559  * @return list of the two points linked to the provided one and closest to the point to be checked,
    2560  */
    2561 list<TesselPoint*> * Tesselation::GetNeighboursOnCircleOfConnectedPoints(ofstream *out, list<TesselPoint*> *connectedPoints, TesselPoint* Point, Vector* Reference)
     2714 * @param *Reference Reference vector for zero angle or NULL for no preference
     2715 * @return list of the all points linked to the provided one
     2716 */
     2717list<TesselPoint*> * Tesselation::GetCircleOfConnectedPoints(ofstream *out, TesselPoint* Point, Vector *Reference)
    25622718{
    25632719  map<double, TesselPoint*> anglesOfPoints;
    2564   map<double, TesselPoint*>::iterator runner;
    2565   ;
    2566   Vector center, PlaneNormal, OrthogonalVector, helper, AngleZero;
    2567 
    2568   if (connectedPoints->size() == 0) { // if have not found any points
    2569     *out << Verbose(1) << "ERROR: We have not found any connected points to " << *Point<< "." << endl;
    2570     return NULL;
    2571   }
     2720  set<TesselPoint*> *connectedPoints = GetAllConnectedPoints(out, Point);
     2721  list<TesselPoint*> *connectedCircle = new list<TesselPoint*>;
     2722  Vector center;
     2723  Vector PlaneNormal;
     2724  Vector AngleZero;
     2725  Vector OrthogonalVector;
     2726  Vector helper;
    25722727
    25732728  // calculate central point
    2574   for (list<TesselPoint*>::iterator TesselRunner = connectedPoints->begin(); TesselRunner != connectedPoints->end(); TesselRunner++)
     2729  for (set<TesselPoint*>::iterator TesselRunner = connectedPoints->begin(); TesselRunner != connectedPoints->end(); TesselRunner++)
    25752730    center.AddVector((*TesselRunner)->node);
    25762731  //*out << "Summed vectors " << center << "; number of points " << connectedPoints.size()
     
    25862741
    25872742  // construct one orthogonal vector
    2588   AngleZero.CopyVector(Reference);
     2743  if (Reference != NULL)
     2744    AngleZero.CopyVector(Reference);
     2745  else
     2746    AngleZero.CopyVector((*connectedPoints->begin())->node);
    25892747  AngleZero.SubtractVector(Point->node);
    25902748  AngleZero.ProjectOntoPlane(&PlaneNormal);
     
    25942752
    25952753  // go through all connected points and calculate angle
    2596   for (list<TesselPoint*>::iterator listRunner = connectedPoints->begin(); listRunner != connectedPoints->end(); listRunner++) {
     2754  for (set<TesselPoint*>::iterator listRunner = connectedPoints->begin(); listRunner != connectedPoints->end(); listRunner++) {
    25972755    helper.CopyVector((*listRunner)->node);
    25982756    helper.SubtractVector(Point->node);
    25992757    helper.ProjectOntoPlane(&PlaneNormal);
    26002758    double angle = GetAngle(helper, AngleZero, OrthogonalVector);
    2601     *out << Verbose(2) << "INFO: Calculated angle is " << angle << " for point " << **listRunner << "." << endl;
     2759    *out << Verbose(3) << "INFO: Calculated angle is " << angle << " for point " << **listRunner << "." << endl;
    26022760    anglesOfPoints.insert(pair<double, TesselPoint*>(angle, (*listRunner)));
    26032761  }
    26042762
    2605   list<TesselPoint*> *result = new list<TesselPoint*>;
    2606   runner = anglesOfPoints.begin();
    2607   result->push_back(runner->second);
    2608   runner = anglesOfPoints.end();
    2609   runner--;
    2610   result->push_back(runner->second);
    2611 
    2612   *out << Verbose(2) << "List of closest points has " << result->size() << " elements, which are "
    2613     << *(result->front()) << " and " << *(result->back()) << endl;
    2614 
    2615   return result;
     2763  for(map<double, TesselPoint*>::iterator AngleRunner = anglesOfPoints.begin(); AngleRunner != anglesOfPoints.end(); AngleRunner++) {
     2764    connectedCircle->push_back(AngleRunner->second);
     2765  }
     2766
     2767  delete(connectedPoints);
     2768  return connectedCircle;
    26162769}
    26172770
     2771/** Gets all points connected to the provided point by triangulation lines, ordered such that we walk along a closed path.
     2772 *
     2773 * @param *out output stream for debugging
     2774 * @param *Point of which get all connected points
     2775 * @return list of the all points linked to the provided one
     2776 */
     2777list<list<TesselPoint*> *> * Tesselation::GetPathsOfConnectedPoints(ofstream *out, TesselPoint* Point)
     2778{
     2779  map<double, TesselPoint*> anglesOfPoints;
     2780  list<list<TesselPoint*> *> *ListOfPaths = new list<list<TesselPoint*> *>;
     2781  list<TesselPoint*> *connectedPath = NULL;
     2782  Vector center;
     2783  Vector PlaneNormal;
     2784  Vector AngleZero;
     2785  Vector OrthogonalVector;
     2786  Vector helper;
     2787  class BoundaryPointSet *ReferencePoint = NULL;
     2788  class BoundaryPointSet *CurrentPoint = NULL;
     2789  class BoundaryTriangleSet *triangle = NULL;
     2790  class BoundaryLineSet *CurrentLine = NULL;
     2791  class BoundaryLineSet *StartLine = NULL;
     2792
     2793  // find the respective boundary point
     2794  PointMap::iterator PointRunner = PointsOnBoundary.find(Point->nr);
     2795  if (PointRunner != PointsOnBoundary.end()) {
     2796    ReferencePoint = PointRunner->second;
     2797  } else {
     2798    *out << Verbose(2) << "ERROR: GetPathOfConnectedPoints() could not find the BoundaryPoint belonging to " << *Point << "." << endl;
     2799    return NULL;
     2800  }
     2801
     2802  map <class BoundaryLineSet *, bool> TouchedLine;
     2803  map <class BoundaryTriangleSet *, bool> TouchedTriangle;
     2804  map <class BoundaryLineSet *, bool>::iterator LineRunner;
     2805  map <class BoundaryTriangleSet *, bool>::iterator TriangleRunner;
     2806  for (LineMap::iterator Runner = ReferencePoint->lines.begin(); Runner != ReferencePoint->lines.end(); Runner++) {
     2807    TouchedLine.insert( pair <class BoundaryLineSet *, bool>(Runner->second, false) );
     2808    for (TriangleMap::iterator Sprinter = Runner->second->triangles.begin(); Sprinter != Runner->second->triangles.end(); Sprinter++)
     2809      TouchedTriangle.insert( pair <class BoundaryTriangleSet *, bool>(Sprinter->second, false) );
     2810  }
     2811  if (!ReferencePoint->lines.empty()) {
     2812    for (LineMap::iterator runner = ReferencePoint->lines.begin(); runner != ReferencePoint->lines.end(); runner++) {
     2813      LineRunner = TouchedLine.find(runner->second);
     2814      if (LineRunner == TouchedLine.end()) {
     2815        *out << Verbose(2) << "ERROR: I could not find " << *runner->second << " in the touched list." << endl;
     2816      } else if (!LineRunner->second) {
     2817        LineRunner->second = true;
     2818        connectedPath = new list<TesselPoint*>;
     2819        triangle = NULL;
     2820        CurrentLine = runner->second;
     2821        StartLine = CurrentLine;
     2822        CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint);
     2823        *out << Verbose(3)<< "INFO: Beginning path retrieval at " << *CurrentPoint << " of line " << *CurrentLine << "." << endl;
     2824        do {
     2825          // push current one
     2826          *out << Verbose(3) << "INFO: Putting " << *CurrentPoint << " at end of path." << endl;
     2827          connectedPath->push_back(CurrentPoint->node);
     2828
     2829          // find next triangle
     2830          for (TriangleMap::iterator Runner = CurrentLine->triangles.begin(); Runner != CurrentLine->triangles.end(); Runner++) {
     2831            *out << Verbose(3) << "INFO: Inspecting triangle " << *Runner->second << "." << endl;
     2832            if ((Runner->second != triangle)) { // look for first triangle not equal to old one
     2833              triangle = Runner->second;
     2834              TriangleRunner = TouchedTriangle.find(triangle);
     2835              if (TriangleRunner != TouchedTriangle.end()) {
     2836                if (!TriangleRunner->second) {
     2837                  TriangleRunner->second = true;
     2838                  *out << Verbose(3) << "INFO: Connecting triangle is " << *triangle << "." << endl;
     2839                  break;
     2840                } else {
     2841                  *out << Verbose(3) << "INFO: Skipping " << *triangle << ", as we have already visited it." << endl;
     2842                  triangle = NULL;
     2843                }
     2844              } else {
     2845                *out << Verbose(2) << "ERROR: I could not find " << *triangle << " in the touched list." << endl;
     2846                triangle = NULL;
     2847              }
     2848            }
     2849          }
     2850          if (triangle == NULL)
     2851            break;
     2852          // find next line
     2853          for (int i=0;i<3;i++) {
     2854            if ((triangle->lines[i] != CurrentLine) && (triangle->lines[i]->ContainsBoundaryPoint(ReferencePoint))) { // not the current line and still containing Point
     2855              CurrentLine = triangle->lines[i];
     2856              *out << Verbose(3) << "INFO: Connecting line is " << *CurrentLine << "." << endl;
     2857              break;
     2858            }
     2859          }
     2860          LineRunner = TouchedLine.find(CurrentLine);
     2861          if (LineRunner == TouchedLine.end())
     2862            *out << Verbose(2) << "ERROR: I could not find " << *CurrentLine << " in the touched list." << endl;
     2863          else
     2864            LineRunner->second = true;
     2865          // find next point
     2866          CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint);
     2867
     2868        } while (CurrentLine != StartLine);
     2869        // last point is missing, as it's on start line
     2870        *out << Verbose(3) << "INFO: Putting " << *CurrentPoint << " at end of path." << endl;
     2871        if (StartLine->GetOtherEndpoint(ReferencePoint)->node != connectedPath->back())
     2872          connectedPath->push_back(StartLine->GetOtherEndpoint(ReferencePoint)->node);
     2873
     2874        ListOfPaths->push_back(connectedPath);
     2875      } else {
     2876        *out << Verbose(3) << "INFO: Skipping " << *runner->second << ", as we have already visited it." << endl;
     2877      }
     2878    }
     2879  } else {
     2880    *out << Verbose(1) << "ERROR: There are no lines attached to " << *ReferencePoint << "." << endl;
     2881  }
     2882
     2883  return ListOfPaths;
     2884}
     2885
     2886/** Gets all closed paths on the circle of points connected to the provided point by triangulation lines, if this very point is removed.
     2887 * From GetPathsOfConnectedPoints() extracts all single loops of intracrossing paths in the list of closed paths.
     2888 * @param *out output stream for debugging
     2889 * @param *Point of which get all connected points
     2890 * @return list of the closed paths
     2891 */
     2892list<list<TesselPoint*> *> * Tesselation::GetClosedPathsOfConnectedPoints(ofstream *out, TesselPoint* Point)
     2893{
     2894  list<list<TesselPoint*> *> *ListofPaths = GetPathsOfConnectedPoints(out, Point);
     2895  list<list<TesselPoint*> *> *ListofClosedPaths = new list<list<TesselPoint*> *>;
     2896  list<TesselPoint*> *connectedPath = NULL;
     2897  list<TesselPoint*> *newPath = NULL;
     2898  int count = 0;
     2899
     2900
     2901  list<TesselPoint*>::iterator CircleRunner;
     2902  list<TesselPoint*>::iterator CircleStart;
     2903
     2904  for(list<list<TesselPoint*> *>::iterator ListRunner = ListofPaths->begin(); ListRunner != ListofPaths->end(); ListRunner++) {
     2905    connectedPath = *ListRunner;
     2906
     2907    *out << Verbose(2) << "INFO: Current path is " << connectedPath << "." << endl;
     2908
     2909    // go through list, look for reappearance of starting Point and count
     2910    CircleStart = connectedPath->begin();
     2911
     2912    // go through list, look for reappearance of starting Point and create list
     2913    list<TesselPoint*>::iterator Marker = CircleStart;
     2914    for (CircleRunner = CircleStart; CircleRunner != connectedPath->end(); CircleRunner++) {
     2915      if ((*CircleRunner == *CircleStart) && (CircleRunner != CircleStart)) { // is not the very first point
     2916        // we have a closed circle from Marker to new Marker
     2917        *out << Verbose(3) << count+1 << ". closed path consists of: ";
     2918        newPath = new list<TesselPoint*>;
     2919        list<TesselPoint*>::iterator CircleSprinter = Marker;
     2920        for (; CircleSprinter != CircleRunner; CircleSprinter++) {
     2921          newPath->push_back(*CircleSprinter);
     2922          *out << (**CircleSprinter) << " <-> ";
     2923        }
     2924        *out << ".." << endl;
     2925        count++;
     2926        Marker = CircleRunner;
     2927
     2928        // add to list
     2929        ListofClosedPaths->push_back(newPath);
     2930      }
     2931    }
     2932  }
     2933  *out << Verbose(3) << "INFO: " << count << " closed additional path(s) have been created." << endl;
     2934
     2935  // delete list of paths
     2936  while (!ListofPaths->empty()) {
     2937    connectedPath = *(ListofPaths->begin());
     2938    ListofPaths->remove(connectedPath);
     2939    delete(connectedPath);
     2940  }
     2941  delete(ListofPaths);
     2942
     2943  // exit
     2944  return ListofClosedPaths;
     2945};
     2946
     2947
     2948/** Gets all belonging triangles for a given BoundaryPointSet.
     2949 * \param *out output stream for debugging
     2950 * \param *Point BoundaryPoint
     2951 * \return pointer to allocated list of triangles
     2952 */
     2953set<BoundaryTriangleSet*> *Tesselation::GetAllTriangles(ofstream *out, class BoundaryPointSet *Point)
     2954{
     2955  set<BoundaryTriangleSet*> *connectedTriangles = new set<BoundaryTriangleSet*>;
     2956
     2957  if (Point == NULL) {
     2958    *out << Verbose(1) << "ERROR: Point given is NULL." << endl;
     2959  } else {
     2960    // go through its lines and insert all triangles
     2961    for (LineMap::iterator LineRunner = Point->lines.begin(); LineRunner != Point->lines.end(); LineRunner++)
     2962      for (TriangleMap::iterator TriangleRunner = (LineRunner->second)->triangles.begin(); TriangleRunner != (LineRunner->second)->triangles.end(); TriangleRunner++) {
     2963      connectedTriangles->insert(TriangleRunner->second);
     2964    }
     2965  }
     2966
     2967  return connectedTriangles;
     2968};
     2969
     2970
    26182971/** Removes a boundary point from the envelope while keeping it closed.
    2619  * We create new triangles and remove the old ones connected to the point.
     2972 * We remove the old triangles connected to the point and re-create new triangles to close the surface following this ansatz:
     2973 *  -# a closed path(s) of boundary points surrounding the point to be removed is constructed
     2974 *  -# on each closed path, we pick three adjacent points, create a triangle with them and subtract the middle point from the path
     2975 *  -# we advance two points (i.e. the next triangle will start at the ending point of the last triangle) and continue as before
     2976 *  -# the surface is closed, when the path is empty
     2977 * Thereby, we (hopefully) make sure that the removed points remains beneath the surface (this is checked via IsInnerPoint eventually).
    26202978 * \param *out output stream for debugging
    26212979 * \param *point point to be removed
     
    26252983  class BoundaryLineSet *line = NULL;
    26262984  class BoundaryTriangleSet *triangle = NULL;
    2627   Vector OldPoint, TetraederVector[3];
     2985  Vector OldPoint, NormalVector;
    26282986  double volume = 0;
    2629   int *numbers = NULL;
    26302987  int count = 0;
    2631   int i;
    26322988
    26332989  if (point == NULL) {
     
    26453001    return 0.;
    26463002  }
    2647   list<TesselPoint*> *CircleofPoints = GetCircleOfConnectedPoints(out, point->node);
    2648 
    2649   // remove all triangles
     3003
     3004  list<list<TesselPoint*> *> *ListOfClosedPaths = GetClosedPathsOfConnectedPoints(out, point->node);
     3005  list<TesselPoint*> *connectedPath = NULL;
     3006
     3007  // gather all triangles
    26503008  for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++)
    26513009    count+=LineRunner->second->triangles.size();
    2652   numbers = new int[count];
    2653   class BoundaryTriangleSet **Candidates = new BoundaryTriangleSet*[count];
    2654   i=0;
    2655   for (LineMap::iterator LineRunner = point->lines.begin(); (point != NULL) && (LineRunner != point->lines.end()); LineRunner++) {
     3010  map<class BoundaryTriangleSet *, int> Candidates;
     3011  for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) {
    26563012    line = LineRunner->second;
    26573013    for (TriangleMap::iterator TriangleRunner = line->triangles.begin(); TriangleRunner != line->triangles.end(); TriangleRunner++) {
    26583014      triangle = TriangleRunner->second;
    2659       Candidates[i] = triangle;
    2660       numbers[i++] = triangle->Nr;
    2661     }
    2662   }
    2663   for (int j=0;j<i;j++) {
    2664     RemoveTesselationTriangle(Candidates[j]);
    2665   }
    2666   delete[](Candidates);
    2667   *out << Verbose(1) << i << " triangles were removed." << endl;
    2668 
    2669   // re-create all triangles by going through connected points list
    2670   list<TesselPoint*>::iterator CircleRunner = CircleofPoints->begin();
    2671   list<TesselPoint*>::iterator OtherCircleRunner = CircleofPoints->begin();
    2672   class TesselPoint *CentralNode = *CircleRunner;
    2673   // advance two with CircleRunner and one with OtherCircleRunner
    2674   CircleRunner++;
    2675   CircleRunner++;
    2676   OtherCircleRunner++;
    2677   i=0;
    2678   cout << Verbose(2) << "INFO: CentralNode is " << *CentralNode << "." << endl;
    2679   for (; (OtherCircleRunner != CircleofPoints->end()) && (CircleRunner != CircleofPoints->end()); (CircleRunner++), (OtherCircleRunner++)) {
    2680     cout << Verbose(3) << "INFO: CircleRunner's node is " << **CircleRunner << "." << endl;
    2681     cout << Verbose(3) << "INFO: OtherCircleRunner's node is " << **OtherCircleRunner << "." << endl;
    2682     *out << Verbose(4) << "Adding new triangle points."<< endl;
    2683     AddTesselationPoint(CentralNode, 0);
    2684     AddTesselationPoint(*OtherCircleRunner, 1);
    2685     AddTesselationPoint(*CircleRunner, 2);
    2686     *out << Verbose(4) << "Adding new triangle lines."<< endl;
    2687     AddTesselationLine(TPS[0], TPS[1], 0);
    2688     AddTesselationLine(TPS[0], TPS[2], 1);
    2689     AddTesselationLine(TPS[1], TPS[2], 2);
    2690     BTS = new class BoundaryTriangleSet(BLS, numbers[i]);
    2691     TrianglesOnBoundary.insert(TrianglePair(numbers[i], BTS));
    2692     *out << Verbose(4) << "Created triangle " << *BTS << "." << endl;
    2693     // calculate volume summand as a general tetraeder
    2694     for (int j=0;j<3;j++) {
    2695       TetraederVector[j].CopyVector(TPS[j]->node->node);
    2696       TetraederVector[j].SubtractVector(&OldPoint);
    2697     }
    2698     OldPoint.CopyVector(&TetraederVector[0]);
    2699     OldPoint.VectorProduct(&TetraederVector[1]);
    2700     volume += 1./6. * fabs(OldPoint.ScalarProduct(&TetraederVector[2]));
    2701     // advance number
    2702     i++;
    2703     if (i >= count)
    2704       *out << Verbose(2) << "WARNING: Maximum of numbers reached!" << endl;
    2705   }
    2706   *out << Verbose(1) << i << " triangles were created." << endl;
    2707 
    2708   delete[](numbers);
    2709 
    2710   return volume;
    2711 };
    2712 
    2713 /** Checks for a new special triangle whether one of its edges is already present with one one triangle connected.
    2714  * This enforces that special triangles (i.e. degenerated ones) should at last close the open-edge frontier and not
    2715  * make it bigger (i.e. closing one (the baseline) and opening two new ones).
    2716  * \param TPS[3] nodes of the triangle
    2717  * \return true - there is such a line (i.e. creation of degenerated triangle is valid), false - no such line (don't create)
    2718  */
    2719 bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3])
    2720 {
    2721   bool result = false;
    2722   int counter = 0;
    2723 
    2724   // check all three points
    2725   for (int i=0;i<3;i++)
    2726     for (int j=i+1; j<3; j++) {
    2727       if (nodes[i]->lines.find(nodes[j]->node->nr) != nodes[i]->lines.end()) {  // there already is a line
    2728         LineMap::iterator FindLine;
    2729         pair<LineMap::iterator,LineMap::iterator> FindPair;
    2730         FindPair = nodes[i]->lines.equal_range(nodes[j]->node->nr);
    2731         for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) {
    2732           // If there is a line with less than two attached triangles, we don't need a new line.
    2733           if (FindLine->second->triangles.size() < 2) {
    2734             counter++;
    2735             break;  // increase counter only once per edge
    2736           }
     3015      Candidates.insert( pair<class BoundaryTriangleSet *, int> (triangle, triangle->Nr) );
     3016    }
     3017  }
     3018
     3019  // remove all triangles
     3020  count=0;
     3021  NormalVector.Zero();
     3022  for (map<class BoundaryTriangleSet *, int>::iterator Runner = Candidates.begin(); Runner != Candidates.end(); Runner++) {
     3023    *out << Verbose(3) << "INFO: Removing triangle " << *(Runner->first) << "." << endl;
     3024    NormalVector.SubtractVector(&Runner->first->NormalVector); // has to point inward
     3025    RemoveTesselationTriangle(Runner->first);
     3026    count++;
     3027  }
     3028  *out << Verbose(1) << count << " triangles were removed." << endl;
     3029
     3030  list<list<TesselPoint*> *>::iterator ListAdvance = ListOfClosedPaths->begin();
     3031  list<list<TesselPoint*> *>::iterator ListRunner = ListAdvance;
     3032  map<class BoundaryTriangleSet *, int>::iterator NumberRunner = Candidates.begin();
     3033  list<TesselPoint*>::iterator StartNode, MiddleNode, EndNode;
     3034  double angle;
     3035  double smallestangle;
     3036  Vector Point, Reference, OrthogonalVector;
     3037  if (count > 2) {  // less than three triangles, then nothing will be created
     3038    class TesselPoint *TriangleCandidates[3];
     3039    count = 0;
     3040    for ( ; ListRunner != ListOfClosedPaths->end(); ListRunner = ListAdvance) {  // go through all closed paths
     3041      if (ListAdvance != ListOfClosedPaths->end())
     3042        ListAdvance++;
     3043
     3044      connectedPath = *ListRunner;
     3045
     3046      // re-create all triangles by going through connected points list
     3047      list<class BoundaryLineSet *> NewLines;
     3048      for (;!connectedPath->empty();) {
     3049        // search middle node with widest angle to next neighbours
     3050        EndNode = connectedPath->end();
     3051        smallestangle = 0.;
     3052        for (MiddleNode = connectedPath->begin(); MiddleNode != connectedPath->end(); MiddleNode++) {
     3053          cout << Verbose(3) << "INFO: MiddleNode is " << **MiddleNode << "." << endl;
     3054          // construct vectors to next and previous neighbour
     3055          StartNode = MiddleNode;
     3056          if (StartNode == connectedPath->begin())
     3057            StartNode = connectedPath->end();
     3058          StartNode--;
     3059          //cout << Verbose(3) << "INFO: StartNode is " << **StartNode << "." << endl;
     3060          Point.CopyVector((*StartNode)->node);
     3061          Point.SubtractVector((*MiddleNode)->node);
     3062          StartNode = MiddleNode;
     3063          StartNode++;
     3064          if (StartNode == connectedPath->end())
     3065            StartNode = connectedPath->begin();
     3066          //cout << Verbose(3) << "INFO: EndNode is " << **StartNode << "." << endl;
     3067          Reference.CopyVector((*StartNode)->node);
     3068          Reference.SubtractVector((*MiddleNode)->node);
     3069          OrthogonalVector.CopyVector((*MiddleNode)->node);
     3070          OrthogonalVector.SubtractVector(&OldPoint);
     3071          OrthogonalVector.MakeNormalVector(&Reference);
     3072          angle = GetAngle(Point, Reference, OrthogonalVector);
     3073          //if (angle < M_PI)  // no wrong-sided triangles, please?
     3074            if(fabs(angle - M_PI) < fabs(smallestangle - M_PI)) {  // get straightest angle (i.e. construct those triangles with smallest area first)
     3075              smallestangle = angle;
     3076              EndNode = MiddleNode;
     3077            }
    27373078        }
    2738       } else { // no line
    2739         cout << Verbose(1) << "The line between " << nodes[i] << " and " << nodes[j] << " is not yet present, hence no need for a degenerate triangle." << endl;
    2740         result = true;
     3079        MiddleNode = EndNode;
     3080        if (MiddleNode == connectedPath->end()) {
     3081          cout << Verbose(1) << "CRITICAL: Could not find a smallest angle!" << endl;
     3082          exit(255);
     3083        }
     3084        StartNode = MiddleNode;
     3085        if (StartNode == connectedPath->begin())
     3086          StartNode = connectedPath->end();
     3087        StartNode--;
     3088        EndNode++;
     3089        if (EndNode == connectedPath->end())
     3090          EndNode = connectedPath->begin();
     3091        cout << Verbose(4) << "INFO: StartNode is " << **StartNode << "." << endl;
     3092        cout << Verbose(4) << "INFO: MiddleNode is " << **MiddleNode << "." << endl;
     3093        cout << Verbose(4) << "INFO: EndNode is " << **EndNode << "." << endl;
     3094        *out << Verbose(3) << "INFO: Attempting to create triangle " << (*StartNode)->Name << ", " << (*MiddleNode)->Name << " and " << (*EndNode)->Name << "." << endl;
     3095        TriangleCandidates[0] = *StartNode;
     3096        TriangleCandidates[1] = *MiddleNode;
     3097        TriangleCandidates[2] = *EndNode;
     3098        triangle = GetPresentTriangle(out, TriangleCandidates);
     3099        if (triangle != NULL) {
     3100          cout << Verbose(1) << "WARNING: New triangle already present, skipping!" << endl;
     3101          StartNode++;
     3102          MiddleNode++;
     3103          EndNode++;
     3104          if (StartNode == connectedPath->end())
     3105            StartNode = connectedPath->begin();
     3106          if (MiddleNode == connectedPath->end())
     3107            MiddleNode = connectedPath->begin();
     3108          if (EndNode == connectedPath->end())
     3109            EndNode = connectedPath->begin();
     3110          continue;
     3111        }
     3112        *out << Verbose(5) << "Adding new triangle points."<< endl;
     3113        AddTesselationPoint(*StartNode, 0);
     3114        AddTesselationPoint(*MiddleNode, 1);
     3115        AddTesselationPoint(*EndNode, 2);
     3116        *out << Verbose(5) << "Adding new triangle lines."<< endl;
     3117        AddTesselationLine(TPS[0], TPS[1], 0);
     3118        AddTesselationLine(TPS[0], TPS[2], 1);
     3119        NewLines.push_back(BLS[1]);
     3120        AddTesselationLine(TPS[1], TPS[2], 2);
     3121        BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     3122        BTS->GetNormalVector(NormalVector);
     3123        AddTesselationTriangle();
     3124        // calculate volume summand as a general tetraeder
     3125        volume += CalculateVolumeofGeneralTetraeder(TPS[0]->node->node, TPS[1]->node->node, TPS[2]->node->node, &OldPoint);
     3126        // advance number
     3127        count++;
     3128
     3129        // prepare nodes for next triangle
     3130        StartNode = EndNode;
     3131        cout << Verbose(4) << "Removing " << **MiddleNode << " from closed path, remaining points: " << connectedPath->size() << "." << endl;
     3132        connectedPath->remove(*MiddleNode); // remove the middle node (it is surrounded by triangles)
     3133        if (connectedPath->size() == 2) { // we are done
     3134          connectedPath->remove(*StartNode); // remove the start node
     3135          connectedPath->remove(*EndNode); // remove the end node
     3136          break;
     3137        } else if (connectedPath->size() < 2) { // something's gone wrong!
     3138          cout << Verbose(1) << "CRITICAL: There are only two endpoints left!" << endl;
     3139          exit(255);
     3140        } else {
     3141          MiddleNode = StartNode;
     3142          MiddleNode++;
     3143          if (MiddleNode == connectedPath->end())
     3144            MiddleNode = connectedPath->begin();
     3145          EndNode = MiddleNode;
     3146          EndNode++;
     3147          if (EndNode == connectedPath->end())
     3148            EndNode = connectedPath->begin();
     3149        }
    27413150      }
    2742     }
    2743   if (counter > 1) {
    2744     cout << Verbose(2) << "INFO: Degenerate triangle is ok, at least two, here " << counter << ", existing lines are used." << endl;
    2745     result = true;
    2746   }
    2747   return result;
    2748 };
    2749 
    2750 
    2751 /** Sort function for the candidate list.
    2752  */
    2753 bool SortCandidates(CandidateForTesselation* candidate1, CandidateForTesselation* candidate2)
    2754 {
    2755   Vector BaseLineVector, OrthogonalVector, helper;
    2756   if (candidate1->BaseLine != candidate2->BaseLine) {  // sanity check
    2757     cout << Verbose(0) << "ERROR: sortCandidates was called for two different baselines: " << candidate1->BaseLine << " and " << candidate2->BaseLine << "." << endl;
    2758     //return false;
    2759     exit(1);
    2760   }
    2761   // create baseline vector
    2762   BaseLineVector.CopyVector(candidate1->BaseLine->endpoints[1]->node->node);
    2763   BaseLineVector.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);
    2764   BaseLineVector.Normalize();
    2765 
    2766   // create normal in-plane vector to cope with acos() non-uniqueness on [0,2pi] (note that is pointing in the "right" direction already, hence ">0" test!)
    2767   helper.CopyVector(candidate1->BaseLine->endpoints[0]->node->node);
    2768   helper.SubtractVector(candidate1->point->node);
    2769   OrthogonalVector.CopyVector(&helper);
    2770   helper.VectorProduct(&BaseLineVector);
    2771   OrthogonalVector.SubtractVector(&helper);
    2772   OrthogonalVector.Normalize();
    2773 
    2774   // calculate both angles and correct with in-plane vector
    2775   helper.CopyVector(candidate1->point->node);
    2776   helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);
    2777   double phi = BaseLineVector.Angle(&helper);
    2778   if (OrthogonalVector.ScalarProduct(&helper) > 0) {
    2779     phi = 2.*M_PI - phi;
    2780   }
    2781   helper.CopyVector(candidate2->point->node);
    2782   helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);
    2783   double psi = BaseLineVector.Angle(&helper);
    2784   if (OrthogonalVector.ScalarProduct(&helper) > 0) {
    2785     psi = 2.*M_PI - psi;
    2786   }
    2787 
    2788   cout << Verbose(2) << *candidate1->point << " has angle " << phi << endl;
    2789   cout << Verbose(2) << *candidate2->point << " has angle " << psi << endl;
    2790 
    2791   // return comparison
    2792   return phi < psi;
    2793 };
    2794 
    2795 /**
    2796  * Finds the point which is second closest to the provided one.
    2797  *
    2798  * @param Point to which to find the second closest other point
    2799  * @param linked cell structure
    2800  *
    2801  * @return point which is second closest to the provided one
    2802  */
    2803 TesselPoint* FindSecondClosestPoint(const Vector* Point, LinkedCell* LC)
    2804 {
    2805   LinkedNodes *List = NULL;
    2806   TesselPoint* closestPoint = NULL;
    2807   TesselPoint* secondClosestPoint = NULL;
    2808   double distance = 1e16;
    2809   double secondDistance = 1e16;
    2810   Vector helper;
    2811   int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2812 
    2813   LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly
    2814   for(int i=0;i<NDIM;i++) // store indices of this cell
    2815     N[i] = LC->n[i];
    2816   cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    2817 
    2818   LC->GetNeighbourBounds(Nlower, Nupper);
    2819   //cout << endl;
    2820   for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2821     for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2822       for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2823         List = LC->GetCurrentCell();
    2824         cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;
    2825         if (List != NULL) {
    2826           for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2827             helper.CopyVector(Point);
    2828             helper.SubtractVector((*Runner)->node);
    2829             double currentNorm = helper. Norm();
    2830             if (currentNorm < distance) {
    2831               // remember second point
    2832               secondDistance = distance;
    2833               secondClosestPoint = closestPoint;
    2834               // mark down new closest point
    2835               distance = currentNorm;
    2836               closestPoint = (*Runner);
    2837               cout << Verbose(2) << "INFO: New Nearest Neighbour is " << *closestPoint << "." << endl;
     3151      // maximize the inner lines (we preferentially created lines with a huge angle, which is for the tesselation not wanted though useful for the closing)
     3152      if (NewLines.size() > 1) {
     3153        list<class BoundaryLineSet *>::iterator Candidate;
     3154        class BoundaryLineSet *OtherBase = NULL;
     3155        double tmp, maxgain;
     3156        do {
     3157          maxgain = 0;
     3158          for(list<class BoundaryLineSet *>::iterator Runner = NewLines.begin(); Runner != NewLines.end(); Runner++) {
     3159            tmp = PickFarthestofTwoBaselines(out, *Runner);
     3160            if (maxgain < tmp) {
     3161              maxgain = tmp;
     3162              Candidate = Runner;
    28383163            }
    28393164          }
    2840         } else {
    2841           cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","
    2842             << LC->n[2] << " is invalid!" << endl;
    2843         }
     3165          if (maxgain != 0) {
     3166            volume += maxgain;
     3167            cout << Verbose(3) << "Flipping baseline with highest volume" << **Candidate << "." << endl;
     3168            OtherBase = FlipBaseline(out, *Candidate);
     3169            NewLines.erase(Candidate);
     3170            NewLines.push_back(OtherBase);
     3171          }
     3172        } while (maxgain != 0.);
    28443173      }
    28453174
    2846   return secondClosestPoint;
    2847 };
    2848 
    2849 /**
    2850  * Finds the point which is closest to the provided one.
    2851  *
    2852  * @param Point to which to find the closest other point
    2853  * @param SecondPoint the second closest other point on return, NULL if none found
    2854  * @param linked cell structure
    2855  *
    2856  * @return point which is closest to the provided one, NULL if none found
    2857  */
    2858 TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC)
    2859 {
    2860   LinkedNodes *List = NULL;
    2861   TesselPoint* closestPoint = NULL;
    2862   SecondPoint = NULL;
    2863   double distance = 1e16;
    2864   double secondDistance = 1e16;
    2865   Vector helper;
    2866   int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2867 
    2868   LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly
    2869   for(int i=0;i<NDIM;i++) // store indices of this cell
    2870     N[i] = LC->n[i];
    2871   cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    2872 
    2873   LC->GetNeighbourBounds(Nlower, Nupper);
    2874   //cout << endl;
    2875   for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2876     for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2877       for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2878         List = LC->GetCurrentCell();
    2879         cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;
    2880         if (List != NULL) {
    2881           for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2882             helper.CopyVector(Point);
    2883             helper.SubtractVector((*Runner)->node);
    2884             double currentNorm = helper. Norm();
    2885             if (currentNorm < distance) {
    2886               secondDistance = distance;
    2887               SecondPoint = closestPoint;
    2888               distance = currentNorm;
    2889               closestPoint = (*Runner);
    2890               cout << Verbose(2) << "INFO: New Nearest Neighbour is " << *closestPoint << "." << endl;
    2891             } else if (currentNorm < secondDistance) {
    2892               secondDistance = currentNorm;
    2893               SecondPoint = (*Runner);
    2894               cout << Verbose(2) << "INFO: New Second Nearest Neighbour is " << *SecondPoint << "." << endl;
    2895             }
    2896           }
    2897         } else {
    2898           cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","
    2899             << LC->n[2] << " is invalid!" << endl;
    2900         }
    2901       }
    2902 
    2903   return closestPoint;
    2904 };
     3175      ListOfClosedPaths->remove(connectedPath);
     3176      delete(connectedPath);
     3177    }
     3178    *out << Verbose(1) << count << " triangles were created." << endl;
     3179  } else {
     3180    while (!ListOfClosedPaths->empty()) {
     3181      ListRunner = ListOfClosedPaths->begin();
     3182      connectedPath = *ListRunner;
     3183      ListOfClosedPaths->remove(connectedPath);
     3184      delete(connectedPath);
     3185    }
     3186    *out << Verbose(1) << "No need to create any triangles." << endl;
     3187  }
     3188  delete(ListOfClosedPaths);
     3189
     3190  *out << Verbose(1) << "Removed volume is " << volume << "." << endl;
     3191
     3192  return volume;
     3193};
     3194
     3195
    29053196
    29063197/**
     
    29393230              FindTriangle = FindLine->second->triangles.begin();
    29403231              for (; FindTriangle != FindLine->second->triangles.end(); FindTriangle++) {
    2941                 if ((
    2942                   (FindTriangle->second->endpoints[0] == TrianglePoints[0])
    2943                     || (FindTriangle->second->endpoints[0] == TrianglePoints[1])
    2944                     || (FindTriangle->second->endpoints[0] == TrianglePoints[2])
    2945                   ) && (
    2946                     (FindTriangle->second->endpoints[1] == TrianglePoints[0])
    2947                     || (FindTriangle->second->endpoints[1] == TrianglePoints[1])
    2948                     || (FindTriangle->second->endpoints[1] == TrianglePoints[2])
    2949                   ) && (
    2950                     (FindTriangle->second->endpoints[2] == TrianglePoints[0])
    2951                     || (FindTriangle->second->endpoints[2] == TrianglePoints[1])
    2952                     || (FindTriangle->second->endpoints[2] == TrianglePoints[2])
    2953                   )
    2954                 ) {
     3232                if (FindTriangle->second->IsPresentTupel(TrianglePoints)) {
    29553233                  result->push_back(FindTriangle->second);
    29563234                }
     
    29703248
    29713249/**
     3250 * Finds all degenerated lines within the tesselation structure.
     3251 *
     3252 * @return map of keys of degenerated line pairs, each line occurs twice
     3253 *         in the list, once as key and once as value
     3254 */
     3255map<int, int> * Tesselation::FindAllDegeneratedLines()
     3256{
     3257  map<int, class BoundaryLineSet *> AllLines;
     3258  map<int, int> * DegeneratedLines = new map<int, int>;
     3259
     3260  // sanity check
     3261  if (LinesOnBoundary.empty()) {
     3262    cout << Verbose(1) << "Warning: FindAllDegeneratedTriangles() was called without any tesselation structure.";
     3263    return DegeneratedLines;
     3264  }
     3265
     3266  LineMap::iterator LineRunner1;
     3267  pair<LineMap::iterator, bool> tester;
     3268  for (LineRunner1 = LinesOnBoundary.begin(); LineRunner1 != LinesOnBoundary.end(); ++LineRunner1) {
     3269    tester = AllLines.insert( pair<int,BoundaryLineSet *> (LineRunner1->second->endpoints[0]->Nr, LineRunner1->second) );
     3270    if ((!tester.second) && (tester.first->second->endpoints[1]->Nr == LineRunner1->second->endpoints[1]->Nr)) { // found degenerated line
     3271      DegeneratedLines->insert ( pair<int, int> (LineRunner1->second->Nr, tester.first->second->Nr) );
     3272      DegeneratedLines->insert ( pair<int, int> (tester.first->second->Nr, LineRunner1->second->Nr) );
     3273    }
     3274  }
     3275
     3276  AllLines.clear();
     3277
     3278  cout << Verbose(1) << "FindAllDegeneratedLines() found " << DegeneratedLines->size() << " lines." << endl;
     3279  map<int,int>::iterator it;
     3280  for (it = DegeneratedLines->begin(); it != DegeneratedLines->end(); it++)
     3281      cout << Verbose(2) << (*it).first << " => " << (*it).second << endl;
     3282
     3283  return DegeneratedLines;
     3284}
     3285
     3286/**
    29723287 * Finds all degenerated triangles within the tesselation structure.
    29733288 *
     
    29753290 *         in the list, once as key and once as value
    29763291 */
    2977 map<int, int> Tesselation::FindAllDegeneratedTriangles()
    2978 {
    2979   map<int, int> DegeneratedTriangles;
    2980 
    2981   // sanity check
    2982   if (LinesOnBoundary.empty()) {
    2983     cout << Verbose(1) << "Warning: FindAllDegeneratedTriangles() was called without any tesselation structure.";
    2984     return DegeneratedTriangles;
    2985   }
    2986 
    2987   LineMap::iterator LineRunner1, LineRunner2;
    2988 
    2989   for (LineRunner1 = LinesOnBoundary.begin(); LineRunner1 != LinesOnBoundary.end(); ++LineRunner1) {
    2990     for (LineRunner2 = LinesOnBoundary.begin(); LineRunner2 != LinesOnBoundary.end(); ++LineRunner2) {
    2991       if ((LineRunner1->second != LineRunner2->second)
    2992         && (LineRunner1->second->endpoints[0] == LineRunner2->second->endpoints[0])
    2993         && (LineRunner1->second->endpoints[1] == LineRunner2->second->endpoints[1])
    2994       ) {
    2995         TriangleMap::iterator TriangleRunner1 = LineRunner1->second->triangles.begin(),
    2996           TriangleRunner2 = LineRunner2->second->triangles.begin();
    2997 
    2998         for (; TriangleRunner1 != LineRunner1->second->triangles.end(); ++TriangleRunner1) {
    2999           for (; TriangleRunner2 != LineRunner2->second->triangles.end(); ++TriangleRunner2) {
    3000             if ((TriangleRunner1->second != TriangleRunner2->second)
    3001               && (TriangleRunner1->second->endpoints[0] == TriangleRunner2->second->endpoints[0])
    3002               && (TriangleRunner1->second->endpoints[1] == TriangleRunner2->second->endpoints[1])
    3003               && (TriangleRunner1->second->endpoints[2] == TriangleRunner2->second->endpoints[2])
    3004             ) {
    3005               DegeneratedTriangles[TriangleRunner1->second->Nr] = TriangleRunner2->second->Nr;
    3006               DegeneratedTriangles[TriangleRunner2->second->Nr] = TriangleRunner1->second->Nr;
    3007             }
    3008           }
     3292map<int, int> * Tesselation::FindAllDegeneratedTriangles()
     3293{
     3294  map<int, int> * DegeneratedLines = FindAllDegeneratedLines();
     3295  map<int, int> * DegeneratedTriangles = new map<int, int>;
     3296
     3297  TriangleMap::iterator TriangleRunner1, TriangleRunner2;
     3298  LineMap::iterator Liner;
     3299  class BoundaryLineSet *line1 = NULL, *line2 = NULL;
     3300
     3301  for (map<int, int>::iterator LineRunner = DegeneratedLines->begin(); LineRunner != DegeneratedLines->end(); ++LineRunner) {
     3302    // run over both lines' triangles
     3303    Liner = LinesOnBoundary.find(LineRunner->first);
     3304    if (Liner != LinesOnBoundary.end())
     3305      line1 = Liner->second;
     3306    Liner = LinesOnBoundary.find(LineRunner->second);
     3307    if (Liner != LinesOnBoundary.end())
     3308      line2 = Liner->second;
     3309    for (TriangleRunner1 = line1->triangles.begin(); TriangleRunner1 != line1->triangles.end(); ++TriangleRunner1) {
     3310      for (TriangleRunner2 = line2->triangles.begin(); TriangleRunner2 != line2->triangles.end(); ++TriangleRunner2) {
     3311        if ((TriangleRunner1->second != TriangleRunner2->second)
     3312          && (TriangleRunner1->second->IsPresentTupel(TriangleRunner2->second))) {
     3313          DegeneratedTriangles->insert( pair<int, int> (TriangleRunner1->second->Nr, TriangleRunner2->second->Nr) );
     3314          DegeneratedTriangles->insert( pair<int, int> (TriangleRunner2->second->Nr, TriangleRunner1->second->Nr) );
    30093315        }
    30103316      }
    30113317    }
    30123318  }
    3013 
    3014   cout << Verbose(1) << "FindAllDegeneratedTriangles() found " << DegeneratedTriangles.size() << " triangles." << endl;
     3319  delete(DegeneratedLines);
     3320
     3321  cout << Verbose(1) << "FindAllDegeneratedTriangles() found " << DegeneratedTriangles->size() << " triangles:" << endl;
    30153322  map<int,int>::iterator it;
    3016   for (it = DegeneratedTriangles.begin(); it != DegeneratedTriangles.end(); it++)
     3323  for (it = DegeneratedTriangles->begin(); it != DegeneratedTriangles->end(); it++)
    30173324      cout << Verbose(2) << (*it).first << " => " << (*it).second << endl;
    30183325
     
    30263333void Tesselation::RemoveDegeneratedTriangles()
    30273334{
    3028   map<int, int> DegeneratedTriangles = FindAllDegeneratedTriangles();
    3029 
    3030   for (map<int, int>::iterator TriangleKeyRunner = DegeneratedTriangles.begin();
    3031     TriangleKeyRunner != DegeneratedTriangles.end(); ++TriangleKeyRunner
     3335  map<int, int> * DegeneratedTriangles = FindAllDegeneratedTriangles();
     3336  TriangleMap::iterator finder;
     3337  BoundaryTriangleSet *triangle = NULL, *partnerTriangle = NULL;
     3338  int count  = 0;
     3339
     3340  cout << Verbose(1) << "Begin of RemoveDegeneratedTriangles" << endl;
     3341
     3342  for (map<int, int>::iterator TriangleKeyRunner = DegeneratedTriangles->begin();
     3343    TriangleKeyRunner != DegeneratedTriangles->end(); ++TriangleKeyRunner
    30323344  ) {
    3033     BoundaryTriangleSet *triangle = TrianglesOnBoundary.find(TriangleKeyRunner->first)->second,
    3034       *partnerTriangle = TrianglesOnBoundary.find(TriangleKeyRunner->second)->second;
     3345    finder = TrianglesOnBoundary.find(TriangleKeyRunner->first);
     3346    if (finder != TrianglesOnBoundary.end())
     3347      triangle = finder->second;
     3348    else
     3349      break;
     3350    finder = TrianglesOnBoundary.find(TriangleKeyRunner->second);
     3351    if (finder != TrianglesOnBoundary.end())
     3352      partnerTriangle = finder->second;
     3353    else
     3354      break;
    30353355
    30363356    bool trianglesShareLine = false;
     
    30443364      && (triangle->endpoints[0]->LinesCount > 2)
    30453365    ) {
     3366      // check whether we have to fix lines
     3367      BoundaryTriangleSet *Othertriangle = NULL;
     3368      BoundaryTriangleSet *OtherpartnerTriangle = NULL;
     3369      TriangleMap::iterator TriangleRunner;
     3370      for (int i = 0; i < 3; ++i)
     3371        for (int j = 0; j < 3; ++j)
     3372          if (triangle->lines[i] != partnerTriangle->lines[j]) {
     3373            // get the other two triangles
     3374            for (TriangleRunner = triangle->lines[i]->triangles.begin(); TriangleRunner != triangle->lines[i]->triangles.end(); ++TriangleRunner)
     3375              if (TriangleRunner->second != triangle) {
     3376                Othertriangle = TriangleRunner->second;
     3377              }
     3378            for (TriangleRunner = partnerTriangle->lines[i]->triangles.begin(); TriangleRunner != partnerTriangle->lines[i]->triangles.end(); ++TriangleRunner)
     3379              if (TriangleRunner->second != partnerTriangle) {
     3380                OtherpartnerTriangle = TriangleRunner->second;
     3381              }
     3382            /// interchanges their lines so that triangle->lines[i] == partnerTriangle->lines[j]
     3383            // the line of triangle receives the degenerated ones
     3384            triangle->lines[i]->triangles.erase(Othertriangle->Nr);
     3385            triangle->lines[i]->triangles.insert( TrianglePair( partnerTriangle->Nr, partnerTriangle) );
     3386            for (int k=0;k<3;k++)
     3387              if (triangle->lines[i] == Othertriangle->lines[k]) {
     3388                Othertriangle->lines[k] = partnerTriangle->lines[j];
     3389                break;
     3390              }
     3391            // the line of partnerTriangle receives the non-degenerated ones
     3392            partnerTriangle->lines[j]->triangles.erase( partnerTriangle->Nr);
     3393            partnerTriangle->lines[j]->triangles.insert( TrianglePair( Othertriangle->Nr, Othertriangle) );
     3394            partnerTriangle->lines[j] = triangle->lines[i];
     3395          }
     3396
     3397      // erase the pair
     3398      count += (int) DegeneratedTriangles->erase(triangle->Nr);
    30463399      cout << Verbose(1) << "RemoveDegeneratedTriangles() removes triangle " << *triangle << "." << endl;
    30473400      RemoveTesselationTriangle(triangle);
     3401      count += (int) DegeneratedTriangles->erase(partnerTriangle->Nr);
    30483402      cout << Verbose(1) << "RemoveDegeneratedTriangles() removes triangle " << *partnerTriangle << "." << endl;
    30493403      RemoveTesselationTriangle(partnerTriangle);
    3050       DegeneratedTriangles.erase(DegeneratedTriangles.find(partnerTriangle->Nr));
    30513404    } else {
    30523405      cout << Verbose(1) << "RemoveDegeneratedTriangles() does not remove triangle " << *triangle
     
    30553408    }
    30563409  }
     3410  delete(DegeneratedTriangles);
     3411
     3412  cout << Verbose(1) << "RemoveDegeneratedTriangles() removed " << count << " triangles:" << endl;
     3413  cout << Verbose(1) << "End of RemoveDegeneratedTriangles" << endl;
    30573414}
    30583415
    3059 /** Gets the angle between a point and a reference relative to the provided center.
    3060  * We have two shanks point and reference between which the angle is calculated
    3061  * and by scalar product with OrthogonalVector we decide the interval.
    3062  * @param point to calculate the angle for
    3063  * @param reference to which to calculate the angle
    3064  * @param OrthogonalVector points in direction of [pi,2pi] interval
    3065  *
    3066  * @return angle between point and reference
    3067  */
    3068 double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector)
    3069 {
    3070   if (reference.IsZero())
    3071     return M_PI;
    3072 
    3073   // calculate both angles and correct with in-plane vector
    3074   if (point.IsZero())
    3075     return M_PI;
    3076   double phi = point.Angle(&reference);
    3077   if (OrthogonalVector.ScalarProduct(&point) > 0) {
    3078     phi = 2.*M_PI - phi;
    3079   }
    3080 
    3081   cout << Verbose(3) << "INFO: " << point << " has angle " << phi << " with respect to reference " << reference << "." << endl;
    3082 
    3083   return phi;
    3084 }
    3085 
     3416/** Adds an outside Tesselpoint to the envelope via (two) degenerated triangles.
     3417 * We look for the closest point on the boundary, we look through its connected boundary lines and
     3418 * seek the one with the minimum angle between its center point and the new point and this base line.
     3419 * We open up the line by adding a degenerated triangle, whose other side closes the base line again.
     3420 * \param *out output stream for debugging
     3421 * \param *point point to add
     3422 * \param *LC Linked Cell structure to find nearest point
     3423 */
     3424void Tesselation::AddBoundaryPointByDegeneratedTriangle(ofstream *out, class TesselPoint *point, LinkedCell *LC)
     3425{
     3426  *out << Verbose(2) << "Begin of AddBoundaryPointByDegeneratedTriangle" << endl;
     3427
     3428  // find nearest boundary point
     3429  class TesselPoint *BackupPoint = NULL;
     3430  class TesselPoint *NearestPoint = FindClosestPoint(point->node, BackupPoint, LC);
     3431  class BoundaryPointSet *NearestBoundaryPoint = NULL;
     3432  PointMap::iterator PointRunner;
     3433
     3434  if (NearestPoint == point)
     3435    NearestPoint = BackupPoint;
     3436  PointRunner = PointsOnBoundary.find(NearestPoint->nr);
     3437  if (PointRunner != PointsOnBoundary.end()) {
     3438    NearestBoundaryPoint = PointRunner->second;
     3439  } else {
     3440    *out << Verbose(1) << "ERROR: I cannot find the boundary point." << endl;
     3441    return;
     3442  }
     3443  *out << Verbose(2) << "Nearest point on boundary is " << NearestPoint->Name << "." << endl;
     3444
     3445  // go through its lines and find the best one to split
     3446  Vector CenterToPoint;
     3447  Vector BaseLine;
     3448  double angle, BestAngle = 0.;
     3449  class BoundaryLineSet *BestLine = NULL;
     3450  for (LineMap::iterator Runner = NearestBoundaryPoint->lines.begin(); Runner != NearestBoundaryPoint->lines.end(); Runner++) {
     3451    BaseLine.CopyVector(Runner->second->endpoints[0]->node->node);
     3452    BaseLine.SubtractVector(Runner->second->endpoints[1]->node->node);
     3453    CenterToPoint.CopyVector(Runner->second->endpoints[0]->node->node);
     3454    CenterToPoint.AddVector(Runner->second->endpoints[1]->node->node);
     3455    CenterToPoint.Scale(0.5);
     3456    CenterToPoint.SubtractVector(point->node);
     3457    angle = CenterToPoint.Angle(&BaseLine);
     3458    if (fabs(angle - M_PI/2.) < fabs(BestAngle - M_PI/2.)) {
     3459      BestAngle = angle;
     3460      BestLine = Runner->second;
     3461    }
     3462  }
     3463
     3464  // remove one triangle from the chosen line
     3465  class BoundaryTriangleSet *TempTriangle = (BestLine->triangles.begin())->second;
     3466  BestLine->triangles.erase(TempTriangle->Nr);
     3467  int nr = -1;
     3468  for (int i=0;i<3; i++) {
     3469    if (TempTriangle->lines[i] == BestLine) {
     3470      nr = i;
     3471      break;
     3472    }
     3473  }
     3474
     3475  // create new triangle to connect point (connects automatically with the missing spot of the chosen line)
     3476  *out << Verbose(5) << "Adding new triangle points."<< endl;
     3477  AddTesselationPoint((BestLine->endpoints[0]->node), 0);
     3478  AddTesselationPoint((BestLine->endpoints[1]->node), 1);
     3479  AddTesselationPoint(point, 2);
     3480  *out << Verbose(5) << "Adding new triangle lines."<< endl;
     3481  AddTesselationLine(TPS[0], TPS[1], 0);
     3482  AddTesselationLine(TPS[0], TPS[2], 1);
     3483  AddTesselationLine(TPS[1], TPS[2], 2);
     3484  BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     3485  BTS->GetNormalVector(TempTriangle->NormalVector);
     3486  BTS->NormalVector.Scale(-1.);
     3487  *out << Verbose(3) << "INFO: NormalVector of new triangle is " << BTS->NormalVector << "." << endl;
     3488  AddTesselationTriangle();
     3489
     3490  // create other side of this triangle and close both new sides of the first created triangle
     3491  *out << Verbose(5) << "Adding new triangle points."<< endl;
     3492  AddTesselationPoint((BestLine->endpoints[0]->node), 0);
     3493  AddTesselationPoint((BestLine->endpoints[1]->node), 1);
     3494  AddTesselationPoint(point, 2);
     3495  *out << Verbose(5) << "Adding new triangle lines."<< endl;
     3496  AddTesselationLine(TPS[0], TPS[1], 0);
     3497  AddTesselationLine(TPS[0], TPS[2], 1);
     3498  AddTesselationLine(TPS[1], TPS[2], 2);
     3499  BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     3500  BTS->GetNormalVector(TempTriangle->NormalVector);
     3501  *out << Verbose(3) << "INFO: NormalVector of other new triangle is " << BTS->NormalVector << "." << endl;
     3502  AddTesselationTriangle();
     3503
     3504  // add removed triangle to the last open line of the second triangle
     3505  for (int i=0;i<3;i++) { // look for the same line as BestLine (only it's its degenerated companion)
     3506    if ((BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[0])) && (BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[1]))) {
     3507      if (BestLine == BTS->lines[i]){
     3508        *out << Verbose(1) << "CRITICAL: BestLine is same as found line, something's wrong here!" << endl;
     3509        exit(255);
     3510      }
     3511      BTS->lines[i]->triangles.insert( pair<int, class BoundaryTriangleSet *> (TempTriangle->Nr, TempTriangle) );
     3512      TempTriangle->lines[nr] = BTS->lines[i];
     3513      break;
     3514    }
     3515  }
     3516
     3517  // exit
     3518  *out << Verbose(2) << "End of AddBoundaryPointByDegeneratedTriangle" << endl;
     3519};
     3520
     3521/** Writes the envelope to file.
     3522 * \param *out otuput stream for debugging
     3523 * \param *filename basename of output file
     3524 * \param *cloud PointCloud structure with all nodes
     3525 */
     3526void Tesselation::Output(ofstream *out, const char *filename, PointCloud *cloud)
     3527{
     3528  ofstream *tempstream = NULL;
     3529  string NameofTempFile;
     3530  char NumberName[255];
     3531
     3532  if (LastTriangle != NULL) {
     3533    sprintf(NumberName, "-%04d-%s_%s_%s", (int)TrianglesOnBoundary.size(), LastTriangle->endpoints[0]->node->Name, LastTriangle->endpoints[1]->node->Name, LastTriangle->endpoints[2]->node->Name);
     3534    if (DoTecplotOutput) {
     3535      string NameofTempFile(filename);
     3536      NameofTempFile.append(NumberName);
     3537      for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
     3538      NameofTempFile.erase(npos, 1);
     3539      NameofTempFile.append(TecplotSuffix);
     3540      *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     3541      tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     3542      WriteTecplotFile(out, tempstream, this, cloud, TriangleFilesWritten);
     3543      tempstream->close();
     3544      tempstream->flush();
     3545      delete(tempstream);
     3546    }
     3547
     3548    if (DoRaster3DOutput) {
     3549      string NameofTempFile(filename);
     3550      NameofTempFile.append(NumberName);
     3551      for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
     3552      NameofTempFile.erase(npos, 1);
     3553      NameofTempFile.append(Raster3DSuffix);
     3554      *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     3555      tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     3556      WriteRaster3dFile(out, tempstream, this, cloud);
     3557      IncludeSphereinRaster3D(out, tempstream, this, cloud);
     3558      tempstream->close();
     3559      tempstream->flush();
     3560      delete(tempstream);
     3561    }
     3562  }
     3563  if (DoTecplotOutput || DoRaster3DOutput)
     3564    TriangleFilesWritten++;
     3565};
  • src/tesselation.hpp

    r87e2e39 rc111db  
    1313using namespace std;
    1414
     15/*********************************************** includes ***********************************/
     16
    1517// include config.h
    1618#ifdef HAVE_CONFIG_H
     
    2224#include <set>
    2325
    24 
    25 #include "helpers.hpp"
    26 #include "linkedcell.hpp"
    27 #include "tesselationhelpers.hpp"
    2826#include "vector.hpp"
     27
     28/****************************************** forward declarations *****************************/
    2929
    3030class BoundaryPointSet;
    3131class BoundaryLineSet;
    3232class BoundaryTriangleSet;
     33class LinkedCell;
    3334class TesselPoint;
    3435class PointCloud;
    3536class Tesselation;
     37
     38/********************************************** definitions *********************************/
     39
     40#define DoTecplotOutput 1
     41#define DoRaster3DOutput 1
     42#define DoVRMLOutput 1
     43#define TecplotSuffix ".dat"
     44#define Raster3DSuffix ".r3d"
     45#define VRMLSUffix ".wrl"
    3646
    3747// ======================================================= some template functions =========================================
     
    5363#define DistanceMultiMapPair pair <double, pair < PointMap::iterator, PointMap::iterator> >
    5464
    55 
     65/********************************************** declarations *******************************/
    5666
    5767template <typename T> void SetEndpointsOrdered(T endpoints[2], T endpoint1, T endpoint2)
     
    115125
    116126    void GetNormalVector(Vector &NormalVector);
     127    void GetCenter(Vector *center);
    117128    bool GetIntersectionInsideTriangle(ofstream *out, Vector *MolCenter, Vector *x, Vector *Intersection);
    118129    bool ContainsBoundaryLine(class BoundaryLineSet *line);
    119130    bool ContainsBoundaryPoint(class BoundaryPointSet *point);
     131    bool ContainsBoundaryPoint(class TesselPoint *point);
    120132    class BoundaryPointSet *GetThirdEndpoint(class BoundaryLineSet *line);
    121133    bool IsPresentTupel(class BoundaryPointSet *Points[3]);
    122     void GetCenter(Vector *center);
     134    bool IsPresentTupel(class BoundaryTriangleSet *T);
    123135
    124136    class BoundaryPointSet *endpoints[3];
     
    196208    void AlwaysAddTesselationTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n);
    197209    void AddTesselationTriangle();
     210    void AddTesselationTriangle(int nr);
    198211    void RemoveTesselationTriangle(class BoundaryTriangleSet *triangle);
    199212    void RemoveTesselationLine(class BoundaryLineSet *line);
    200213    void RemoveTesselationPoint(class BoundaryPointSet *point);
    201214
    202     bool IsInside(Vector *pointer);
    203215    class BoundaryPointSet *GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2);
    204216
    205217    // concave envelope
    206218    void FindStartingTriangle(ofstream *out, const double RADIUS, class LinkedCell *LC);
    207     void FindSecondPointForTesselation(class TesselPoint* a, class TesselPoint* Candidate, Vector Oben, class TesselPoint*& OptCandidate, double Storage[3], double RADIUS, class LinkedCell *LC);
     219    void FindSecondPointForTesselation(class TesselPoint* a, Vector Oben, class TesselPoint*& OptCandidate, double Storage[3], double RADIUS, class LinkedCell *LC);
    208220    void FindThirdPointForTesselation(Vector NormalVector, Vector SearchDirection, Vector OldSphereCenter, class BoundaryLineSet *BaseLine, class TesselPoint *ThirdNode, CandidateList* &candidates, double *ShortestAngle, const double RADIUS, class LinkedCell *LC);
    209     bool FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, LinkedCell *LC);
     221    bool FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, LinkedCell *LC);
    210222    int CheckPresenceOfTriangle(ofstream *out, class TesselPoint *Candidates[3]);
     223    class BoundaryTriangleSet * GetPresentTriangle(ofstream *out, TesselPoint *Candidates[3]);
    211224
    212225    // convex envelope
     
    215228    bool InsertStraddlingPoints(ofstream *out, PointCloud *cloud, LinkedCell *LC);
    216229    double RemovePointFromTesselatedSurface(ofstream *out, class BoundaryPointSet *point);
    217     bool FlipBaseline(ofstream *out, class BoundaryLineSet *Base);
    218     bool PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base);
     230    class BoundaryLineSet * FlipBaseline(ofstream *out, class BoundaryLineSet *Base);
     231    double PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base);
    219232    class BoundaryPointSet *IsConvexRectangle(ofstream *out, class BoundaryLineSet *Base);
    220     map<int, int> FindAllDegeneratedTriangles();
     233    map<int, int> * FindAllDegeneratedTriangles();
     234    map<int, int> * FindAllDegeneratedLines();
    221235    void RemoveDegeneratedTriangles();
    222 
    223     list<TesselPoint*> * GetCircleOfConnectedPoints(ofstream *out, TesselPoint* Point);
    224     list<TesselPoint*> * GetNeighboursOnCircleOfConnectedPoints(ofstream *out, list<TesselPoint*> *connectedPoints, TesselPoint* Point, Vector* Reference);
     236    void AddBoundaryPointByDegeneratedTriangle(ofstream *out, class TesselPoint *point, LinkedCell *LC);
     237
     238    set<TesselPoint*> * GetAllConnectedPoints(ofstream *out, TesselPoint* Point);
     239    set<BoundaryTriangleSet*> *GetAllTriangles(ofstream *out, class BoundaryPointSet *Point);
     240    list<list<TesselPoint*> *> * GetPathsOfConnectedPoints(ofstream *out, TesselPoint* Point);
     241    list<list<TesselPoint*> *> * GetClosedPathsOfConnectedPoints(ofstream *out, TesselPoint* Point);
     242    list<TesselPoint*> * GetCircleOfConnectedPoints(ofstream *out, TesselPoint* Point, Vector *Reference = NULL);
    225243    list<BoundaryTriangleSet*> *FindTriangles(TesselPoint* Points[3]);
    226244    list<BoundaryTriangleSet*> * FindClosestTrianglesToPoint(ofstream *out, Vector *x, LinkedCell* LC);
     
    235253    void PrintAllBoundaryTriangles(ofstream *out);
    236254
     255    // store envelope in file
     256    void Output(ofstream *out, const char *filename, PointCloud *cloud);
    237257
    238258    PointMap PointsOnBoundary;
     
    257277    class BoundaryLineSet *BLS[3];
    258278    class BoundaryTriangleSet *BTS;
     279    class BoundaryTriangleSet *LastTriangle;
     280    int TriangleFilesWritten;
    259281
    260282  private:
     
    264286};
    265287
    266 bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3]);
    267 bool SortCandidates(class CandidateForTesselation* candidate1, class CandidateForTesselation* candidate2);
    268 TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC);
    269 TesselPoint* FindSecondClosestPoint(const Vector*, LinkedCell*);
    270 double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector);
    271 Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase);
    272288
    273289#endif /* TESSELATION_HPP_ */
  • src/tesselationhelpers.cpp

    r87e2e39 rc111db  
    66 */
    77
     8#include <fstream>
     9
     10#include "linkedcell.hpp"
     11#include "tesselation.hpp"
    812#include "tesselationhelpers.hpp"
     13#include "vector.hpp"
     14#include "verbose.hpp"
    915
    1016double DetGet(gsl_matrix *A, int inPlace) {
     
    386392
    387393  return result;
     394};
     395
     396/** Gets the angle between a point and a reference relative to the provided center.
     397 * We have two shanks point and reference between which the angle is calculated
     398 * and by scalar product with OrthogonalVector we decide the interval.
     399 * @param point to calculate the angle for
     400 * @param reference to which to calculate the angle
     401 * @param OrthogonalVector points in direction of [pi,2pi] interval
     402 *
     403 * @return angle between point and reference
     404 */
     405double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector)
     406{
     407  if (reference.IsZero())
     408    return M_PI;
     409
     410  // calculate both angles and correct with in-plane vector
     411  if (point.IsZero())
     412    return M_PI;
     413  double phi = point.Angle(&reference);
     414  if (OrthogonalVector.ScalarProduct(&point) > 0) {
     415    phi = 2.*M_PI - phi;
     416  }
     417
     418  cout << Verbose(4) << "INFO: " << point << " has angle " << phi << " with respect to reference " << reference << "." << endl;
     419
     420  return phi;
    388421}
    389422
     423
     424/** Calculates the volume of a general tetraeder.
     425 * \param *a first vector
     426 * \param *a first vector
     427 * \param *a first vector
     428 * \param *a first vector
     429 * \return \f$ \frac{1}{6} \cdot ((a-d) \times (a-c) \cdot  (a-b)) \f$
     430 */
     431double CalculateVolumeofGeneralTetraeder(Vector *a, Vector *b, Vector *c, Vector *d)
     432{
     433  Vector Point, TetraederVector[3];
     434  double volume;
     435
     436  TetraederVector[0].CopyVector(a);
     437  TetraederVector[1].CopyVector(b);
     438  TetraederVector[2].CopyVector(c);
     439  for (int j=0;j<3;j++)
     440    TetraederVector[j].SubtractVector(d);
     441  Point.CopyVector(&TetraederVector[0]);
     442  Point.VectorProduct(&TetraederVector[1]);
     443  volume = 1./6. * fabs(Point.ScalarProduct(&TetraederVector[2]));
     444  return volume;
     445};
     446
     447
     448/** Checks for a new special triangle whether one of its edges is already present with one one triangle connected.
     449 * This enforces that special triangles (i.e. degenerated ones) should at last close the open-edge frontier and not
     450 * make it bigger (i.e. closing one (the baseline) and opening two new ones).
     451 * \param TPS[3] nodes of the triangle
     452 * \return true - there is such a line (i.e. creation of degenerated triangle is valid), false - no such line (don't create)
     453 */
     454bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3])
     455{
     456  bool result = false;
     457  int counter = 0;
     458
     459  // check all three points
     460  for (int i=0;i<3;i++)
     461    for (int j=i+1; j<3; j++) {
     462      if (nodes[i]->lines.find(nodes[j]->node->nr) != nodes[i]->lines.end()) {  // there already is a line
     463        LineMap::iterator FindLine;
     464        pair<LineMap::iterator,LineMap::iterator> FindPair;
     465        FindPair = nodes[i]->lines.equal_range(nodes[j]->node->nr);
     466        for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) {
     467          // If there is a line with less than two attached triangles, we don't need a new line.
     468          if (FindLine->second->triangles.size() < 2) {
     469            counter++;
     470            break;  // increase counter only once per edge
     471          }
     472        }
     473      } else { // no line
     474        cout << Verbose(1) << "The line between " << *nodes[i] << " and " << *nodes[j] << " is not yet present, hence no need for a degenerate triangle." << endl;
     475        result = true;
     476      }
     477    }
     478  if ((!result) && (counter > 1)) {
     479    cout << Verbose(2) << "INFO: Degenerate triangle is ok, at least two, here " << counter << ", existing lines are used." << endl;
     480    result = true;
     481  }
     482  return result;
     483};
     484
     485
     486/** Sort function for the candidate list.
     487 */
     488bool SortCandidates(CandidateForTesselation* candidate1, CandidateForTesselation* candidate2)
     489{
     490  Vector BaseLineVector, OrthogonalVector, helper;
     491  if (candidate1->BaseLine != candidate2->BaseLine) {  // sanity check
     492    cout << Verbose(0) << "ERROR: sortCandidates was called for two different baselines: " << candidate1->BaseLine << " and " << candidate2->BaseLine << "." << endl;
     493    //return false;
     494    exit(1);
     495  }
     496  // create baseline vector
     497  BaseLineVector.CopyVector(candidate1->BaseLine->endpoints[1]->node->node);
     498  BaseLineVector.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);
     499  BaseLineVector.Normalize();
     500
     501  // create normal in-plane vector to cope with acos() non-uniqueness on [0,2pi] (note that is pointing in the "right" direction already, hence ">0" test!)
     502  helper.CopyVector(candidate1->BaseLine->endpoints[0]->node->node);
     503  helper.SubtractVector(candidate1->point->node);
     504  OrthogonalVector.CopyVector(&helper);
     505  helper.VectorProduct(&BaseLineVector);
     506  OrthogonalVector.SubtractVector(&helper);
     507  OrthogonalVector.Normalize();
     508
     509  // calculate both angles and correct with in-plane vector
     510  helper.CopyVector(candidate1->point->node);
     511  helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);
     512  double phi = BaseLineVector.Angle(&helper);
     513  if (OrthogonalVector.ScalarProduct(&helper) > 0) {
     514    phi = 2.*M_PI - phi;
     515  }
     516  helper.CopyVector(candidate2->point->node);
     517  helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);
     518  double psi = BaseLineVector.Angle(&helper);
     519  if (OrthogonalVector.ScalarProduct(&helper) > 0) {
     520    psi = 2.*M_PI - psi;
     521  }
     522
     523  cout << Verbose(2) << *candidate1->point << " has angle " << phi << endl;
     524  cout << Verbose(2) << *candidate2->point << " has angle " << psi << endl;
     525
     526  // return comparison
     527  return phi < psi;
     528};
     529
     530/**
     531 * Finds the point which is second closest to the provided one.
     532 *
     533 * @param Point to which to find the second closest other point
     534 * @param linked cell structure
     535 *
     536 * @return point which is second closest to the provided one
     537 */
     538TesselPoint* FindSecondClosestPoint(const Vector* Point, LinkedCell* LC)
     539{
     540  LinkedNodes *List = NULL;
     541  TesselPoint* closestPoint = NULL;
     542  TesselPoint* secondClosestPoint = NULL;
     543  double distance = 1e16;
     544  double secondDistance = 1e16;
     545  Vector helper;
     546  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     547
     548  LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly
     549  for(int i=0;i<NDIM;i++) // store indices of this cell
     550    N[i] = LC->n[i];
     551  cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     552
     553  LC->GetNeighbourBounds(Nlower, Nupper);
     554  //cout << endl;
     555  for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     556    for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     557      for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     558        List = LC->GetCurrentCell();
     559        //cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;
     560        if (List != NULL) {
     561          for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     562            helper.CopyVector(Point);
     563            helper.SubtractVector((*Runner)->node);
     564            double currentNorm = helper. Norm();
     565            if (currentNorm < distance) {
     566              // remember second point
     567              secondDistance = distance;
     568              secondClosestPoint = closestPoint;
     569              // mark down new closest point
     570              distance = currentNorm;
     571              closestPoint = (*Runner);
     572              //cout << Verbose(2) << "INFO: New Second Nearest Neighbour is " << *secondClosestPoint << "." << endl;
     573            }
     574          }
     575        } else {
     576          cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","
     577            << LC->n[2] << " is invalid!" << endl;
     578        }
     579      }
     580
     581  return secondClosestPoint;
     582};
     583
     584/**
     585 * Finds the point which is closest to the provided one.
     586 *
     587 * @param Point to which to find the closest other point
     588 * @param SecondPoint the second closest other point on return, NULL if none found
     589 * @param linked cell structure
     590 *
     591 * @return point which is closest to the provided one, NULL if none found
     592 */
     593TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC)
     594{
     595  LinkedNodes *List = NULL;
     596  TesselPoint* closestPoint = NULL;
     597  SecondPoint = NULL;
     598  double distance = 1e16;
     599  double secondDistance = 1e16;
     600  Vector helper;
     601  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     602
     603  LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly
     604  for(int i=0;i<NDIM;i++) // store indices of this cell
     605    N[i] = LC->n[i];
     606  cout << Verbose(3) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     607
     608  LC->GetNeighbourBounds(Nlower, Nupper);
     609  //cout << endl;
     610  for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     611    for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     612      for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     613        List = LC->GetCurrentCell();
     614        //cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;
     615        if (List != NULL) {
     616          for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     617            helper.CopyVector(Point);
     618            helper.SubtractVector((*Runner)->node);
     619            double currentNorm = helper. Norm();
     620            if (currentNorm < distance) {
     621              secondDistance = distance;
     622              SecondPoint = closestPoint;
     623              distance = currentNorm;
     624              closestPoint = (*Runner);
     625              //cout << Verbose(2) << "INFO: New Nearest Neighbour is " << *closestPoint << "." << endl;
     626            } else if (currentNorm < secondDistance) {
     627              secondDistance = currentNorm;
     628              SecondPoint = (*Runner);
     629              //cout << Verbose(2) << "INFO: New Second Nearest Neighbour is " << *SecondPoint << "." << endl;
     630            }
     631          }
     632        } else {
     633          cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","
     634            << LC->n[2] << " is invalid!" << endl;
     635        }
     636      }
     637
     638  return closestPoint;
     639};
     640
     641/** Returns the closest point on \a *Base with respect to \a *OtherBase.
     642 * \param *out output stream for debugging
     643 * \param *Base reference line
     644 * \param *OtherBase other base line
     645 * \return Vector on reference line that has closest distance
     646 */
     647Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase)
     648{
     649  // construct the plane of the two baselines (i.e. take both their directional vectors)
     650  Vector Normal;
     651  Vector Baseline, OtherBaseline;
     652  Baseline.CopyVector(Base->endpoints[1]->node->node);
     653  Baseline.SubtractVector(Base->endpoints[0]->node->node);
     654  OtherBaseline.CopyVector(OtherBase->endpoints[1]->node->node);
     655  OtherBaseline.SubtractVector(OtherBase->endpoints[0]->node->node);
     656  Normal.CopyVector(&Baseline);
     657  Normal.VectorProduct(&OtherBaseline);
     658  Normal.Normalize();
     659  *out << Verbose(4) << "First direction is " << Baseline << ", second direction is " << OtherBaseline << ", normal of intersection plane is " << Normal << "." << endl;
     660
     661  // project one offset point of OtherBase onto this plane (and add plane offset vector)
     662  Vector NewOffset;
     663  NewOffset.CopyVector(OtherBase->endpoints[0]->node->node);
     664  NewOffset.SubtractVector(Base->endpoints[0]->node->node);
     665  NewOffset.ProjectOntoPlane(&Normal);
     666  NewOffset.AddVector(Base->endpoints[0]->node->node);
     667  Vector NewDirection;
     668  NewDirection.CopyVector(&NewOffset);
     669  NewDirection.AddVector(&OtherBaseline);
     670
     671  // calculate the intersection between this projected baseline and Base
     672  Vector *Intersection = new Vector;
     673  Intersection->GetIntersectionOfTwoLinesOnPlane(out, Base->endpoints[0]->node->node, Base->endpoints[1]->node->node, &NewOffset, &NewDirection, &Normal);
     674  Normal.CopyVector(Intersection);
     675  Normal.SubtractVector(Base->endpoints[0]->node->node);
     676  *out << Verbose(3) << "Found closest point on " << *Base << " at " << *Intersection << ", factor in line is " << fabs(Normal.ScalarProduct(&Baseline)/Baseline.NormSquared()) << "." << endl;
     677
     678  return Intersection;
     679};
     680
     681
     682/** Creates the objects in a VRML file.
     683 * \param *out output stream for debugging
     684 * \param *vrmlfile output stream for tecplot data
     685 * \param *Tess Tesselation structure with constructed triangles
     686 * \param *mol molecule structure with atom positions
     687 */
     688void WriteVrmlFile(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, PointCloud *cloud)
     689{
     690  TesselPoint *Walker = NULL;
     691  int i;
     692  Vector *center = cloud->GetCenter(out);
     693  if (vrmlfile != NULL) {
     694    //cout << Verbose(1) << "Writing Raster3D file ... ";
     695    *vrmlfile << "#VRML V2.0 utf8" << endl;
     696    *vrmlfile << "#Created by molecuilder" << endl;
     697    *vrmlfile << "#All atoms as spheres" << endl;
     698    cloud->GoToFirst();
     699    while (!cloud->IsEnd()) {
     700      Walker = cloud->GetPoint();
     701      *vrmlfile << "Sphere {" << endl << "  "; // 2 is sphere type
     702      for (i=0;i<NDIM;i++)
     703        *vrmlfile << Walker->node->x[i]-center->x[i] << " ";
     704      *vrmlfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
     705      cloud->GoToNext();
     706    }
     707
     708    *vrmlfile << "# All tesselation triangles" << endl;
     709    for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
     710      *vrmlfile << "1" << endl << "  "; // 1 is triangle type
     711      for (i=0;i<3;i++) { // print each node
     712        for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
     713          *vrmlfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";
     714        *vrmlfile << "\t";
     715      }
     716      *vrmlfile << "1. 0. 0." << endl;  // red as colour
     717      *vrmlfile << "18" << endl << "  0.5 0.5 0.5" << endl; // 18 is transparency type for previous object
     718    }
     719  } else {
     720    cerr << "ERROR: Given vrmlfile is " << vrmlfile << "." << endl;
     721  }
     722  delete(center);
     723};
     724
     725/** Writes additionally the current sphere (i.e. the last triangle to file).
     726 * \param *out output stream for debugging
     727 * \param *rasterfile output stream for tecplot data
     728 * \param *Tess Tesselation structure with constructed triangles
     729 * \param *mol molecule structure with atom positions
     730 */
     731void IncludeSphereinRaster3D(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, PointCloud *cloud)
     732{
     733  Vector helper;
     734  // include the current position of the virtual sphere in the temporary raster3d file
     735  Vector *center = cloud->GetCenter(out);
     736  // make the circumsphere's center absolute again
     737  helper.CopyVector(Tess->LastTriangle->endpoints[0]->node->node);
     738  helper.AddVector(Tess->LastTriangle->endpoints[1]->node->node);
     739  helper.AddVector(Tess->LastTriangle->endpoints[2]->node->node);
     740  helper.Scale(1./3.);
     741  helper.SubtractVector(center);
     742  // and add to file plus translucency object
     743  *rasterfile << "# current virtual sphere\n";
     744  *rasterfile << "8\n  25.0    0.6     -1.0 -1.0 -1.0     0.2        0 0 0 0\n";
     745  *rasterfile << "2\n  " << helper.x[0] << " " << helper.x[1] << " " << helper.x[2] << "\t" << 5. << "\t1 0 0\n";
     746  *rasterfile << "9\n  terminating special property\n";
     747  delete(center);
     748};
     749
     750/** Creates the objects in a raster3d file (renderable with a header.r3d).
     751 * \param *out output stream for debugging
     752 * \param *rasterfile output stream for tecplot data
     753 * \param *Tess Tesselation structure with constructed triangles
     754 * \param *mol molecule structure with atom positions
     755 */
     756void WriteRaster3dFile(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, PointCloud *cloud)
     757{
     758  TesselPoint *Walker = NULL;
     759  int i;
     760  Vector *center = cloud->GetCenter(out);
     761  if (rasterfile != NULL) {
     762    //cout << Verbose(1) << "Writing Raster3D file ... ";
     763    *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl;
     764    *rasterfile << "@header.r3d" << endl;
     765    *rasterfile << "# All atoms as spheres" << endl;
     766    cloud->GoToFirst();
     767    while (!cloud->IsEnd()) {
     768      Walker = cloud->GetPoint();
     769      *rasterfile << "2" << endl << "  ";  // 2 is sphere type
     770      for (i=0;i<NDIM;i++)
     771        *rasterfile << Walker->node->x[i]-center->x[i] << " ";
     772      *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
     773      cloud->GoToNext();
     774    }
     775
     776    *rasterfile << "# All tesselation triangles" << endl;
     777    *rasterfile << "8\n  25. -1.   1. 1. 1.   0.0    0 0 0 2\n  SOLID     1.0 0.0 0.0\n  BACKFACE  0.3 0.3 1.0   0 0\n";
     778    for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
     779      *rasterfile << "1" << endl << "  ";  // 1 is triangle type
     780      for (i=0;i<3;i++) {  // print each node
     781        for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
     782          *rasterfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";
     783        *rasterfile << "\t";
     784      }
     785      *rasterfile << "1. 0. 0." << endl;  // red as colour
     786      //*rasterfile << "18" << endl << "  0.5 0.5 0.5" << endl;  // 18 is transparency type for previous object
     787    }
     788    *rasterfile << "9\n#  terminating special property\n";
     789  } else {
     790    cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl;
     791  }
     792  IncludeSphereinRaster3D(out, rasterfile, Tess, cloud);
     793  delete(center);
     794};
     795
     796/** This function creates the tecplot file, displaying the tesselation of the hull.
     797 * \param *out output stream for debugging
     798 * \param *tecplot output stream for tecplot data
     799 * \param N arbitrary number to differentiate various zones in the tecplot format
     800 */
     801void WriteTecplotFile(ofstream *out, ofstream *tecplot, class Tesselation *TesselStruct, PointCloud *cloud, int N)
     802{
     803  if ((tecplot != NULL) && (TesselStruct != NULL)) {
     804    // write header
     805    *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;
     806    *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\" \"U\"" << endl;
     807    *tecplot << "ZONE T=\"" << N << "-";
     808    for (int i=0;i<3;i++)
     809      *tecplot << (i==0 ? "" : "_") << TesselStruct->LastTriangle->endpoints[i]->node->Name;
     810    *tecplot << "\", N=" << TesselStruct->PointsOnBoundary.size() << ", E=" << TesselStruct->TrianglesOnBoundary.size() << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
     811    int i=0;
     812    for (cloud->GoToFirst(); !cloud->IsEnd(); cloud->GoToNext(), i++);
     813    int *LookupList = new int[i];
     814    for (cloud->GoToFirst(), i=0; !cloud->IsEnd(); cloud->GoToNext(), i++)
     815      LookupList[i] = -1;
     816
     817    // print atom coordinates
     818    *out << Verbose(2) << "The following triangles were created:";
     819    int Counter = 1;
     820    TesselPoint *Walker = NULL;
     821    for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target != TesselStruct->PointsOnBoundary.end(); target++) {
     822      Walker = target->second->node;
     823      LookupList[Walker->nr] = Counter++;
     824      *tecplot << Walker->node->x[0] << " " << Walker->node->x[1] << " " << Walker->node->x[2] << " " << target->second->value << endl;
     825    }
     826    *tecplot << endl;
     827    // print connectivity
     828    for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) {
     829      *out << " " << runner->second->endpoints[0]->node->Name << "<->" << runner->second->endpoints[1]->node->Name << "<->" << runner->second->endpoints[2]->node->Name;
     830      *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl;
     831    }
     832    delete[] (LookupList);
     833    *out << endl;
     834  }
     835};
     836
     837/** Calculates the concavity for each of the BoundaryPointSet's in a Tesselation.
     838 * Sets BoundaryPointSet::value equal to the number of connected lines that are not convex.
     839 * \param *out output stream for debugging
     840 * \param *TesselStruct pointer to Tesselation structure
     841 */
     842void CalculateConcavityPerBoundaryPoint(ofstream *out, class Tesselation *TesselStruct)
     843{
     844  class BoundaryPointSet *point = NULL;
     845  class BoundaryLineSet *line = NULL;
     846
     847  //*out << Verbose(2) << "Begin of CalculateConcavityPerBoundaryPoint" << endl;
     848  // calculate remaining concavity
     849  for (PointMap::iterator PointRunner = TesselStruct->PointsOnBoundary.begin(); PointRunner != TesselStruct->PointsOnBoundary.end(); PointRunner++) {
     850    point = PointRunner->second;
     851    *out << Verbose(1) << "INFO: Current point is " << *point << "." << endl;
     852    point->value = 0;
     853    for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) {
     854      line = LineRunner->second;
     855      //*out << Verbose(2) << "INFO: Current line of point " << *point << " is " << *line << "." << endl;
     856      if (!line->CheckConvexityCriterion(out))
     857        point->value += 1;
     858    }
     859  }
     860  //*out << Verbose(2) << "End of CalculateConcavityPerBoundaryPoint" << endl;
     861};
     862
     863
     864/** Checks whether each BoundaryLineSet in the Tesselation has two triangles.
     865 * \param *out output stream for debugging
     866 * \param *TesselStruct
     867 * \return true - all have exactly two triangles, false - some not, list is printed to screen
     868 */
     869bool CheckListOfBaselines(ofstream *out, Tesselation *TesselStruct)
     870{
     871  LineMap::iterator testline;
     872  bool result = false;
     873  int counter = 0;
     874
     875  *out << Verbose(1) << "Check: List of Baselines with not two connected triangles:" << endl;
     876  for (testline = TesselStruct->LinesOnBoundary.begin(); testline != TesselStruct->LinesOnBoundary.end(); testline++) {
     877    if (testline->second->triangles.size() != 2) {
     878      *out << Verbose(1) << *testline->second << "\t" << testline->second->triangles.size() << endl;
     879      counter++;
     880    }
     881  }
     882  if (counter == 0) {
     883    *out << Verbose(1) << "None." << endl;
     884    result = true;
     885  }
     886  return result;
     887}
     888
  • src/tesselationhelpers.hpp

    r87e2e39 rc111db  
    1313using namespace std;
    1414
     15/*********************************************** includes ***********************************/
     16
    1517// include config.h
    1618#ifdef HAVE_CONFIG_H
    1719#include <config.h>
    1820#endif
    19 
    20 #define HULLEPSILON 1e-7
    2121
    2222#include <gsl/gsl_linalg.h>
     
    2626#include <gsl/gsl_vector.h>
    2727
    28 #include "vector.hpp"
     28#include <iostream>
     29
     30#include "defs.hpp"
     31
     32/****************************************** forward declarations *****************************/
     33
     34class BoundaryPointSet;
     35class BoundaryLineSet;
     36class BoundaryTriangleSet;
     37class LinkedCell;
     38class TesselPoint;
     39class PointCloud;
     40class Tesselation;
     41class Vector;
     42
     43/********************************************** definitions *********************************/
     44
     45#define HULLEPSILON 1e-10
     46
     47/********************************************** declarations *******************************/
    2948
    3049double DetGet(gsl_matrix *A, int inPlace);
     
    3554double MinIntersectDistance(const gsl_vector * x, void *params);
    3655bool existsIntersection(Vector point1, Vector point2, Vector point3, Vector point4);
     56double CalculateVolumeofGeneralTetraeder(Vector *a, Vector *b, Vector *c, Vector *d);
     57double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector);
     58
     59bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3]);
     60bool SortCandidates(class CandidateForTesselation* candidate1, class CandidateForTesselation* candidate2);
     61TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC);
     62TesselPoint* FindSecondClosestPoint(const Vector*, LinkedCell*);
     63Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase);
     64
     65void WriteTecplotFile(ofstream *out, ofstream *tecplot, class Tesselation *TesselStruct, PointCloud *cloud, int N);
     66void WriteRaster3dFile(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, PointCloud *cloud);
     67void IncludeSphereinRaster3D(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, PointCloud *cloud);
     68void WriteVrmlFile(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, PointCloud *cloud);
     69void CalculateConcavityPerBoundaryPoint(ofstream *out, class Tesselation *TesselStruct);
     70
     71bool CheckListOfBaselines(ofstream *out, Tesselation *TesselStruct);
     72
    3773
    3874#endif /* TESSELATIONHELPERS_HPP_ */
  • src/unittests/Makefile.am

    r87e2e39 rc111db  
    11INCLUDES = -I$(top_srcdir)/src
    22
    3 noinst_PROGRAMS =  MemoryAllocatorUnitTest MemoryUsageObserverUnitTest VectorUnitTest
     3noinst_PROGRAMS =  ActOnAllTest MemoryAllocatorUnitTest MemoryUsageObserverUnitTest VectorUnitTest
    44
    5 TESTS = VectorUnitTest MemoryUsageObserverUnitTest MemoryAllocatorUnitTest
     5TESTS = ActOnAllTest MemoryUsageObserverUnitTest MemoryAllocatorUnitTest VectorUnitTest
    66check_PROGRAMS = $(TESTS)
     7
     8ActOnAllTest_SOURCES = ActOnAllTest.hpp ActOnAllUnitTest.cpp ActOnAllUnitTest.hpp memoryallocator.hpp
     9ActOnAllTest_CXXFLAGS = $(CPPUNIT_CFLAGS)
     10ActOnAllTest_LDFLAGS = $(CPPUNIT_LIBS) -ldl
     11ActOnAllTest_LDADD = ../libmolecuilder.a
     12
    713
    814VectorUnitTest_SOURCES = defs.hpp helpers.hpp leastsquaremin.hpp memoryallocator.hpp memoryusageobserver.hpp vectorunittest.cpp vectorunittest.hpp vector.hpp verbose.hpp
  • src/unittests/tesselationunittest.cpp

    • Property mode changed from 100755 to 100644
    r87e2e39 rc111db  
    8484  delete(TesselStruct);
    8585  for (LinkedNodes::iterator Runner = Corners.begin(); Runner != Corners.end(); Runner++) {
    86     delete((*Runner)->Name);
     86    delete[]((*Runner)->Name);
    8787    delete((*Runner)->node);
    8888    delete(*Runner);
     
    178178    for (set<BoundaryTriangleSet*>::iterator TriangleRunner = triangles->begin(); TriangleRunner != triangles->end(); TriangleRunner++)
    179179      CPPUNIT_ASSERT_EQUAL( true, (*TriangleRunner)->ContainsBoundaryPoint(Walker) );
     180    delete(triangles);
    180181  }
    181182}
  • src/unittests/tesselationunittest.hpp

    • Property mode changed from 100755 to 100644
    r87e2e39 rc111db  
    99#define TESSELATIONUNITTEST_HPP_
    1010
     11/*********************************************** includes ***********************************/
    1112
    1213#include <cppunit/extensions/HelperMacros.h>
    1314
     15#include "linkedcell.hpp"
    1416#include "tesselation.hpp"
    1517
  • src/unittests/vectorunittest.cpp

    r87e2e39 rc111db  
    1313#include <cppunit/ui/text/TestRunner.h>
    1414
     15#include "defs.hpp"
     16#include "vector.hpp"
    1517#include "vectorunittest.hpp"
    16 #include "vector.hpp"
    17 #include "defs.hpp"
    1818
    1919/********************************************** Test classes **************************************/
  • src/vector.cpp

    r87e2e39 rc111db  
    225225  Direction.CopyVector(LineVector);
    226226  Direction.SubtractVector(Origin);
     227  Direction.Normalize();
    227228  //*out << Verbose(4) << "INFO: Direction is " << Direction << "." << endl;
    228229  factor = Direction.ScalarProduct(PlaneNormal);
     
    234235  helper.SubtractVector(Origin);
    235236  factor = helper.ScalarProduct(PlaneNormal)/factor;
     237  if (factor < MYEPSILON) { // Origin is in-plane
     238    //*out << Verbose(2) << "Origin of line is in-plane, simple." << endl;
     239    CopyVector(Origin);
     240    return true;
     241  }
    236242  //factor = Origin->ScalarProduct(PlaneNormal)*(-PlaneOffset->ScalarProduct(PlaneNormal))/(Direction.ScalarProduct(PlaneNormal));
    237243  Direction.Scale(factor);
     
    655661};
    656662
     663/** Given a box by its matrix \a *M and its inverse *Minv the vector is made to point within that box.
     664 * \param *M matrix of box
     665 * \param *Minv inverse matrix
     666 */
     667void Vector::WrapPeriodically(const double *M, const double *Minv)
     668{
     669  MatrixMultiplication(Minv);
     670  // truncate to [0,1] for each axis
     671  for (int i=0;i<NDIM;i++) {
     672    x[i] += 0.5;  // set to center of box
     673    while (x[i] >= 1.)
     674      x[i] -= 1.;
     675    while (x[i] < 0.)
     676      x[i] += 1.;
     677  }
     678  MatrixMultiplication(M);
     679};
     680
    657681/** Do a matrix multiplication.
    658682 * \param *matrix NDIM_NDIM array
    659683 */
    660 void Vector::MatrixMultiplication(double *M)
     684void Vector::MatrixMultiplication(const double *M)
    661685{
    662686  Vector C;
     
    700724 * \param *matrix NDIM_NDIM array
    701725 */
    702 void Vector::InverseMatrixMultiplication(double *A)
     726void Vector::InverseMatrixMultiplication(const double *A)
    703727{
    704728  Vector C;
  • src/vector.hpp

    r87e2e39 rc111db  
    44using namespace std;
    55
    6 #include "helpers.hpp"
     6/*********************************************** includes ***********************************/
     7
     8// include config.h
     9#ifdef HAVE_CONFIG_H
     10#include <config.h>
     11#endif
    712
    813#include <gsl/gsl_vector.h>
    914#include <gsl/gsl_multimin.h>
    1015
    11 class Vector;
     16#include "defs.hpp"
     17
     18/********************************************** declarations *******************************/
    1219
    1320/** Single vector.
     
    5259  void Scale(double *factor);
    5360  void Scale(double factor);
    54   void MatrixMultiplication(double *M);
     61  void MatrixMultiplication(const double *M);
    5562  double * InverseMatrix(double *A);
    56   void InverseMatrixMultiplication(double *M);
     63  void InverseMatrixMultiplication(const double *M);
    5764  void KeepPeriodic(ofstream *out, double *matrix);
    5865  void LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors);
     
    6976  bool Output(ofstream *out) const;
    7077  bool IsInParallelepiped(Vector offset, double *parallelepiped);
     78  void WrapPeriodically(const double *M, const double *Minv);
    7179};
    7280
  • src/verbose.cpp

    r87e2e39 rc111db  
    1 #include "molecules.hpp"
     1using namespace std;
     2
     3#include "verbose.hpp"
    24
    35/** Prints the tabs according to verbosity stored in the temporary constructed class.
  • src/verbose.hpp

    r87e2e39 rc111db  
    88#ifndef VERBOSE_HPP_
    99#define VERBOSE_HPP_
     10
     11using namespace std;
     12
     13/*********************************************** includes ***********************************/
     14
     15// include config.h
     16#ifdef HAVE_CONFIG_H
     17#include <config.h>
     18#endif
     19
     20#include <iostream>
    1021
    1122/************************************* Class Verbose & Binary *******************************/
  • tests/Makefile.am

    r87e2e39 rc111db  
    11AUTOM4TE = autom4te
    2 EXTRA_DIST = testsuite.at $(TESTSUITE) atlocal.in
     2EXTRA_DIST = testsuite.at $(TESTSUITE) atlocal.in regression
    33TESTSUITE = $(srcdir)/testsuite
    44
  • tests/testsuite.at

    r87e2e39 rc111db  
    11# Process with autom4te to create an -*- Autotest -*- test suite.
    2 
     2#
     3# see regression/... subdirs wherein for each of the cases and each check (enumerated) is a pre and post dir.
     4# In pre initial files are placed, in post results can be found to be checked by diff in this testsuite.
    35
    46AT_INIT([Molecular Builder])
     
    79AT_BANNER([MoleCuilder - standard options])
    810AT_SETUP([Standard Options])
     11AT_KEYWORDS([options])
    912AT_CHECK([pwd],[ignore],[ignore])
    1013AT_CHECK([../../molecuilder -v], 0, [stdout], [ignore])
     
    1821AT_CLEANUP
    1922
     23
    2024AT_BANNER([MoleCuilder - molecular config creation from xyz file and atom adding])
    21 AT_SETUP([Simple configuration])
    22 # 1. create a fake element database with the only element we need
    23 AT_DATA([elements.db],[#        Covalent        radius  of      each    element in      Angstroem       from    CSD     (binding        is:     [Rcov(A)+Rcov(B)-t,Rcov(A)+Rcov(B)+t]   with    t       =       0.4A
    24 #Element        Name    Symbol  Period  Group   Block   Atomic  Number  AtomicWeight    Covalent        Radius  vdW     Radius
    25 Hydrogen        H       1       1       s       1       1.008   0.23    1.09
    26 ])
    27 # 2. create some simplest molecular geometry
     25AT_KEYWORDS([Atom handling])
     26# 1. create some simplest molecular geometry
     27AT_SETUP([Simple configuration - xyz file generation])
    2828AT_DATA([test.xyz], [[1
    2929 # test configuration, created by molecuilder test suite
    3030H       10.     10.     10.
    3131]])
    32 # 3. make sure config is empty and not remnant from last test with broken dirs
    33 AT_DATA([test.conf], [])
    34 AT_CHECK([../../molecuilder test.conf -e ./ -p test.xyz], 0, [ignore], [ignore])
    35 AT_CHECK([fgrep "Ion_Type1_1" test.conf], 0, [Ion_Type1_1       10.000000000    10.000000000    10.000000000    0 # Number in molecule 0
     32AT_CHECK([file=test.xyz; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/1/post/$file], 0, [ignore], [ignore])
     33AT_CLEANUP
     34
     35# 2. parsing an xyz
     36AT_SETUP([Simple configuration - parsing xyz file])
     37AT_CHECK([/bin/cp -f ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/2/pre/test.xyz .], 0)
     38AT_CHECK([../../molecuilder test.conf -e ${abs_top_srcdir}/src/ -p test.xyz], 0, [ignore], [ignore])
     39AT_CHECK([fgrep "Ion_Type1_1" test.conf], 0, [Ion_Type1_1       10.000000000    10.000000000    10.000000000    0 # molecule nr 0
    3640], [ignore])
    37 AT_CHECK([cp test.conf main_pcp_linux], 0, [ignore], [ignore])
    38 AT_DATA([input], [aa 10. 10. 10. 1
    39 s
    40 q
    41 ])
    42 AT_CHECK([../../molecuilder -e ./ <input], 0, [ignore], [ignore])
    43 AT_CHECK([diff main_pcp_linux test.conf], 0, [ignore], [ignore])
    44 # 4. test some more configuration
    45 AT_CHECK([../../molecuilder test.conf -e ./ -t -s -b -F -E -c -b -a -U -T -u], 0, [ignore], [stderr])
    46 AT_CHECK([fgrep -c "Not enough or invalid" stderr], 0, [10
     41AT_CHECK([file=test.conf; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/2/post/$file], 0, [ignore], [ignore])
     42AT_CHECK([file=test.conf.in; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/2/post/$file], 0, [ignore], [ignore])
     43AT_CHECK([file=test.conf.xyz; diff -I '.*Created by molecuilder.*' $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/2/post/$file], 0, [ignore], [ignore])
     44
     45# 3. add atom
     46AT_CLEANUP
     47AT_SETUP([Simple configuration - adding atom])
     48AT_CHECK([../../molecuilder test.conf -e ${abs_top_srcdir}/src/ -a 1 10. 10. 10.], 0, [ignore], [ignore])
     49AT_CHECK([file=test.conf; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/3/post/$file], 0, [ignore], [ignore])
     50AT_CHECK([file=test.conf.in; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/3/post/$file], 0, [ignore], [ignore])
     51AT_CHECK([file=test.conf.xyz; diff -I '.*Created by molecuilder.*' $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/3/post/$file], 0, [ignore], [ignore])
     52AT_CLEANUP
     53
     54# 4. change the element
     55AT_SETUP([Simple configuration - Changing element])
     56AT_CHECK([/bin/cp -f ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/4/pre/test.conf test.conf], 0)
     57AT_CHECK([../../molecuilder test.conf -e ${abs_top_srcdir}/src/ -E 0 6], 0, [ignore], [ignore])
     58AT_CHECK([file=test.conf; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/4/post/$file], 0, [ignore], [ignore])
     59AT_CLEANUP
     60
     61# 5. remove atom
     62AT_SETUP([Simple configuration - Atom removal])
     63AT_CHECK([/bin/cp -f ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/5/pre/test.conf .], 0)
     64AT_CHECK([../../molecuilder test.conf -e ${abs_top_srcdir}/src/ -r 0], 0, [ignore], [ignore])
     65AT_CHECK([file=test.conf; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/5/post/$file], 0, [ignore], [ignore])
     66AT_CHECK([file=test.conf.in; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/5/post/$file], 0, [ignore], [ignore])
     67AT_CHECK([file=test.conf.xyz; diff -I '.*Created by molecuilder.*' $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/5/post/$file], 0, [ignore], [ignore])
     68AT_CLEANUP
     69
     70# 6. test some more configuration that all desire parameters and count how many complain
     71AT_SETUP([Simple configuration - invalid commands on empty configs])
     72AT_CHECK([../../molecuilder empty.conf -e ${abs_top_srcdir}/src/ -t -s -b -E -c -b -a -U -T -u], 255, [ignore], [stderr])
     73AT_CHECK([fgrep -c "Not enough or invalid" stderr], 0, [1
     74], [ignore])
     75AT_CLEANUP
     76
     77# 7. test some more configuration that all need parameters and count how many complain
     78AT_SETUP([Simple configuration - invalid commands on present configs])
     79AT_CHECK([/bin/cp -f ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Simple_configuration/7/pre/test.conf .], 0)
     80AT_CHECK([../../molecuilder test.conf -e ${abs_top_srcdir}/src/ -t -s -b -E -c -b -a -U -T -u], 255, [ignore], [stderr])
     81AT_CHECK([fgrep -c "Not enough or invalid" stderr], 0, [9
     82], [ignore])
     83AT_CLEANUP
     84
     85
     86AT_BANNER([MoleCuilder - Graph routines test])
     87AT_KEYWORDS([graph])
     88AT_SETUP([Graph - DFS analysis])
     89AT_CHECK([/bin/cp -f ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Graph/1/pre/test.conf .], 0)
     90AT_CHECK([../../molecuilder test.conf -e ${abs_top_srcdir}/src/ -D 2.], 0, [stdout], [stderr])
     91AT_CHECK([fgrep -c "No rings were detected in the molecular structure." stdout], 0, [1
    4792], [ignore])
    4893AT_CLEANUP
    4994
    5095AT_BANNER([MoleCuilder - Fragmentation and Re-fragmentation test])
    51 AT_SETUP([Fragmentation])
    52 # 1. create a fake element database with the only two elements we need
    53 AT_DATA([elements.db],[#  Covalent  radius  of  each  element in  Angstroem from  CSD (binding  is: [Rcov(A)+Rcov(B)-t,Rcov(A)+Rcov(B)+t] with  t = 0.4A
    54 #Element  Name  Symbol  Period  Group Block Atomic  Number  AtomicWeight  Covalent  Radius  vdW Radius
    55 Hydrogen  H 1 1 s 1 1.008 0.23  1.09
    56 Carbon  C       2       14      p       6       12.011  0.68    1.70
    57 ])
    58 # 2. create molecular geometry
    59 AT_DATA([test.xyz], [[11
    60  # test configuration, created by molecuilder test suite
    61 C       9.782085945     3.275186040     3.535886037
    62 C       8.532785963     4.158586027     3.535886037
    63 C       7.283585982     3.275186040     3.535886037
    64 H       9.782085945     2.645886050     2.645886050
    65 H       9.782085945     2.645886050     4.425886024
    66 H       10.672039608    3.904536878     3.535886037
    67 H       8.532785963     4.787886018     2.645886050
    68 H       8.532785963     4.787886018     4.425886024
    69 H       6.393632318     3.904536877     3.535886037
    70 H       7.283585982     2.645886050     2.645886050
    71 H       7.283585982     2.645886050     4.425886024
    72 ]])
    73 # 3. make sure config is empty and not remnant from last test with broken dirs
    74 AT_DATA([test.conf], [])
    75 # 4. create the config and check it
    76 AT_CHECK([../../molecuilder test.conf -e ./ -p test.xyz], 0, [ignore], [ignore])
    77 AT_CHECK([fgrep "Ion_Type1_4" test.conf], 0, [Ion_Type1_4       8.532785963     4.787886018     2.645886050     0 # Number in molecule 6
     96AT_KEYWORDS([fragmentation])
     97# 1. check config
     98AT_SETUP([Fragmentation - Checking present config])
     99AT_CHECK([/bin/cp -f ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Fragmentation/1/pre/test.conf .], 0)
     100AT_CHECK([fgrep "Ion_Type1_4" test.conf], 0, [Ion_Type1_4       8.532785963     4.787886018     2.645886050     0 # molecule nr 6
    78101], [ignore])
    79102AT_CHECK([fgrep "Ion_Type2_4" test.conf], 1, [ignore], [ignore])
    80 # 5. fragment the molecule and check the number of configs
    81 AT_CHECK([../../molecuilder test.conf -e ./ -f 1.55 2], 0, [ignore], [ignore], [mkdir std; mv BondFragment*.conf* std/])
     103AT_CLEANUP
     104# 2. fragment the molecule and check the number of configs
     105AT_SETUP([Fragmentation - Fragmentation])
     106AT_CHECK([/bin/cp -f ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Fragmentation/2/pre/test.conf .], 0)
     107AT_CHECK([../../molecuilder test.conf -e ${abs_top_srcdir}/src/ -f 1.55 2], 0, [ignore], [ignore], [mkdir std; mv BondFragment*.conf* std/])
    82108AT_CHECK([mkdir std; mv BondFragment*.conf* std/], 0)
    83109AT_CHECK([ls -l std/BondFragment*.conf | wc -l], 0, [5
    84110], [ignore])
    85 # 3a. check whether parsing of BondFragment files and re-rwriting config files is working (exit code is 2 as we don't need to continue wrt to ...OrderAtSite)
    86 AT_CHECK([../../molecuilder test.conf -e ./ -f 1.55 2], 2, [ignore], [ignore], [mkdir new; mv BondFragment*.conf* new/])
     111AT_CLEANUP
     112# 3. check whether parsing of BondFragment files and re-rwriting config files is working (exit code is 2 as we don't need to continue wrt to ...OrderAtSite)
     113AT_SETUP([Fragmentation - Fragmentation is at MaxOrder])
     114AT_CHECK([/bin/cp -f ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Fragmentation/3/pre/* .], 0)
     115AT_CHECK([../../molecuilder test.conf -e ${abs_top_srcdir}/src/ -f 1.55 2], 2, [ignore], [ignore], [mkdir new; mv BondFragment*.conf* new/])
    87116AT_CHECK([mkdir new; mv BondFragment*.conf* new/], 0)
    88 # 6. compare both dirs by diff'ing
    89 AT_CHECK([diff -I '.*Created by molecuilder.*' std/ new/], 0, [], [])
    90117AT_CLEANUP
    91118
     119
     120AT_BANNER([MoleCuilder - Tesselation test])
     121AT_KEYWORDS([Tesselation])
     122# 1. Non convex tesselation
     123AT_SETUP([Tesselation - Non-Convex Envelope])
     124AT_CHECK([/bin/cp -f ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Tesselation/1/pre/* .], 0)
     125AT_CHECK([../../molecuilder test.conf -e ${abs_top_srcdir}/src/ -N 4. NonConvexEnvelope], 0, [stdout], [stderr])
     126AT_CHECK([file=NonConvexEnvelope.dat; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Tesselation/1/post/$file], 0, [ignore], [ignore])
     127AT_CHECK([file=NonConvexEnvelope.r3d; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Tesselation/1/post/$file], 0, [ignore], [ignore])
     128AT_CLEANUP
     129
     130# 2. convex tesselation (where the non-convex is already convex)
     131AT_SETUP([Tesselation - Convex Envelope])
     132AT_CHECK([/bin/cp -f ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Tesselation/2/pre/* .], 0)
     133AT_CHECK([../../molecuilder test.conf -e ${abs_top_srcdir}/src/ -o ConvexEnvelope NonConvexEnvelope], 0, [stdout], [stderr])
     134AT_CHECK([file=ConvexEnvelope.dat; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Tesselation/2/post/$file], 0, [ignore], [ignore])
     135AT_CHECK([file=ConvexEnvelope.r3d; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Tesselation/2/post/$file], 0, [ignore], [ignore])
     136AT_CHECK([fgrep "RESULT: The summed volume is 16.401577 angstrom^3" stdout], 0, [ignore], [ignore])
     137AT_CHECK([diff ConvexEnvelope.dat NonConvexEnvelope.dat], 0, [ignore], [ignore])
     138AT_CLEANUP
     139
     140# 3. Big Non convex tesselation
     141AT_SETUP([Tesselation - Big non-Convex Envelope])
     142AT_CHECK([/bin/cp -f ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Tesselation/3/pre/* .], 0)
     143AT_CHECK([../../molecuilder test.conf -e ${abs_top_srcdir}/src/ -N 4. NonConvexEnvelope], 0, [stdout], [stderr])
     144AT_CHECK([file=NonConvexEnvelope.dat; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Tesselation/3/post/$file], 0, [ignore], [ignore])
     145AT_CHECK([file=NonConvexEnvelope.r3d; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Tesselation/3/post/$file], 0, [ignore], [ignore])
     146AT_CLEANUP
     147
     148# 4. Big convex tesselation - is not working yet
     149#AT_SETUP([Tesselation - big convex Envelope])
     150#AT_CHECK([/bin/cp -f ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Tesselation/4/pre/* .], 0)
     151#AT_CHECK([../../molecuilder test.conf -e ${abs_top_srcdir}/src/ -o ConvexEnvelope NonConvexEnvelope], 0, [stdout], [stderr])
     152#AT_CHECK([file=ConvexEnvelope.dat; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Tesselation/4/post/$file], 0, [ignore], [ignore])
     153#AT_CHECK([file=ConvexEnvelope.r3d; diff $file ${abs_top_srcdir}/${AUTOTEST_PATH}/regression/Tesselation/4/post/$file], 0, [ignore], [ignore])
     154#AT_CHECK([fgrep "RESULT: The summed volume is 16.401577 angstrom^3" stdout], 0, [ignore], [ignore])
     155#AT_CLEANUP
     156
Note: See TracChangeset for help on using the changeset viewer.