Changes in / [ce5ac3:d067d45]
- Location:
- src
- Files:
-
- 4 added
- 3 deleted
- 24 edited
-
#border.cpp# (deleted)
-
#makefile# (deleted)
-
#molecules.hpp# (deleted)
-
Makefile.am (modified) (1 diff)
-
analyzer.cpp (modified) (18 diffs)
-
atom.cpp (modified) (6 diffs)
-
boundary.cpp (modified) (27 diffs)
-
boundary.hpp (modified) (3 diffs)
-
builder.cpp (modified) (37 diffs)
-
config.cpp (modified) (59 diffs)
-
datacreator.cpp (modified) (27 diffs)
-
datacreator.hpp (modified) (3 diffs)
-
element.cpp (modified) (2 diffs)
-
ellipsoid.cpp (added)
-
ellipsoid.hpp (added)
-
graph.cpp (modified) (1 diff)
-
helpers.cpp (modified) (13 diffs)
-
helpers.hpp (modified) (12 diffs)
-
joiner.cpp (modified) (5 diffs)
-
linkedcell.cpp (added)
-
linkedcell.hpp (added)
-
moleculelist.cpp (modified) (37 diffs)
-
molecules.cpp (modified) (27 diffs)
-
molecules.hpp (modified) (11 diffs)
-
parser.cpp (modified) (24 diffs)
-
parser.hpp (modified) (5 diffs)
-
periodentafel.hpp (modified) (2 diffs)
-
stackclass.hpp (modified) (12 diffs)
-
vector.cpp (modified) (36 diffs)
-
vector.hpp (modified) (1 diff)
-
verbose.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/Makefile.am
rce5ac3 rd067d45 1 SOURCE = atom.cpp bond.cpp boundary.cpp builder.cpp config.cpp element.cpp helpers.cpp molecules.cpp moleculelist.cpp parser.cpp periodentafel.cpp vector.cpp verbose.cpp2 HEADER = boundary.hpp defs.hpp helpers.hpp molecules.hpp parser.hpp periodentafel.hpp stackclass.hpp vector.hpp1 SOURCE = atom.cpp bond.cpp boundary.cpp builder.cpp config.cpp element.cpp ellipsoid.cpp helpers.cpp molecules.cpp linkedcell.cpp moleculelist.cpp parser.cpp periodentafel.cpp vector.cpp verbose.cpp 2 HEADER = boundary.hpp defs.hpp ellipsoid.hpp helpers.hpp linkedcell.hpp molecules.hpp parser.hpp periodentafel.hpp stackclass.hpp vector.hpp 3 3 4 4 bin_PROGRAMS = molecuilder joiner analyzer 5 5 molecuilderdir = ${bindir} 6 molecuilder_DATA = elements.db valence.db orbitals.db Hbonddistance.db Hbondangle.db6 molecuilder_DATA = elements.db valence.db orbitals.db Hbonddistance.db Hbondangle.db 7 7 molecuilder_SOURCES = ${SOURCE} ${HEADER} 8 8 joiner_SOURCES = joiner.cpp datacreator.cpp element.cpp helpers.cpp periodentafel.cpp parser.cpp verbose.cpp datacreator.hpp helpers.hpp parser.hpp periodentafel.hpp -
src/analyzer.cpp
rce5ac3 rd067d45 3 3 * Takes evaluated fragments (energy and forces) and does evaluation of how sensible the BOSSANOVA 4 4 * approach was, e.g. in the decay of the many-body-contributions. 5 * 5 * 6 6 */ 7 7 … … 9 9 10 10 #include "datacreator.hpp" 11 #include "helpers.hpp" 11 #include "helpers.hpp" 12 12 #include "parser.hpp" 13 #include "periodentafel.hpp" 13 #include "periodentafel.hpp" 14 14 15 15 // include config.h … … 55 55 stringstream yrange; 56 56 char *dir = NULL; 57 bool NoHCorrection = false;58 57 bool NoHessian = false; 59 58 bool NoTime = false; 59 bool NoHCorrection = true; 60 60 int counter; 61 61 62 62 cout << "ANOVA Analyzer" << endl; 63 63 cout << "==============" << endl; 64 64 65 65 // Get the command line options 66 66 if (argc < 4) { … … 76 76 strcat(dir, argv[2]); 77 77 } 78 78 79 79 if (argc > 4) { 80 80 cout << "Loading periodentafel." << endl; … … 82 82 periode->LoadPeriodentafel(argv[4]); 83 83 } 84 84 85 85 // Test the given directory 86 86 if (!TestParams(argc, argv)) … … 88 88 89 89 // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++ 90 90 91 91 // ------------- Parse through all Fragment subdirs -------- 92 92 if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix,0,0)) return 1; … … 113 113 114 114 // ---------- Parse the TE Factors into an array ----------------- 115 if (!Energy.InitialiseIndices()) return 1; 116 if (!NoHCorrection) 117 Hcorrection.InitialiseIndices(); 118 115 if (!Energy.ParseIndices()) return 1; 116 if (!NoHCorrection) Hcorrection.ParseIndices(); 117 119 118 // ---------- Parse the Force indices into an array --------------- 120 119 if (!Force.ParseIndices(argv[1])) return 1; … … 148 147 if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1; 149 148 if (!KeySet.ParseManyBodyTerms()) return 1; 150 149 151 150 // ---------- Parse fragment files created by 'joiner' into an array ------------- 152 151 if (!EnergyFragments.ParseFragmentMatrix(argv[1], dir, EnergyFragmentSuffix,0,0)) return 1; … … 164 163 165 164 // +++++++++++++++ TESTING ++++++++++++++++++++++++++++++ 166 165 167 166 // print energy and forces to file 168 167 filename.str(""); … … 245 244 246 245 // +++++++++++++++ ANALYZING ++++++++++++++++++++++++++++++ 247 246 248 247 cout << "Analyzing ..." << endl; 249 248 … … 330 329 } 331 330 332 331 333 332 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM 334 333 if (!CreateDataDeltaEnergyOrder(Energy, EnergyFragments, KeySet, argv[3], "DeltaEnergies-Order", "Plot of error between approximated and full energies energies versus the Bond Order", datum)) return 1; 335 334 336 335 // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order 337 336 if (!CreateDataEnergyOrder(EnergyFragments, KeySet, argv[3], "Energies-Order", "Plot of approximated energies versus the Bond Order", datum)) return 1; 338 337 339 338 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM 340 339 if (!CreateDataDeltaForcesOrderPerAtom(Force, ForceFragments, KeySet, argv[3], "DeltaForces-Order", "Plot of error between approximated forces and full forces versus the Bond Order", datum)) return 1; … … 399 398 400 399 // ======================================= Creating the plot files ============================================================== 401 400 402 401 Orderxrange << "[1:" << KeySet.Order << "]"; 403 402 Fragmentxrange << "[0:" << KeySet.FragmentCounter+1 << "]"; … … 411 410 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM 412 411 if (!CreatePlotOrder(Energy, KeySet, argv[3], "DeltaEnergies-Order", 1, "outside", "y", "", 1, 1, "bond order k", "absolute error in energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1; 413 412 414 413 // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order 415 414 if (!CreatePlotOrder(Energy, KeySet, argv[3], "Energies-Order", 1, "outside", "", "", 1, 1, "bond order k", "approximate energy [Ht]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1; … … 429 428 if(!OpenOutputFile(output, argv[3], "DeltaMinMeanMaxTotalForce-Order.pyx")) return 1; 430 429 CreatePlotHeader(output, "DeltaMinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL, 1, 1, "bond order k", "absolute error in total forces [Ht/a.u.]"); 431 output << "plot " << Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl; 430 output << "plot " << Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl; 432 431 output << "'DeltaMinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl; 433 432 output << "'DeltaMeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl; 434 433 output << "'DeltaMaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl; 435 output.close(); 434 output.close(); 436 435 437 436 // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order … … 448 447 if(!OpenOutputFile(output, argv[3],"MinMeanMaxTotalForce-Order.pyx")) return 1; 449 448 CreatePlotHeader(output, "MinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL, 1, 1, "bond order k", "absolute total force [Ht/a.u.]"); 450 output << "plot "<< Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl; 449 output << "plot "<< Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl; 451 450 output << "'MinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl; 452 451 output << "'MeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl; 453 452 output << "'MaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl; 454 output.close(); 453 output.close(); 455 454 456 455 // ++++++++++++++++++++++++++++++++++++++Plotting vector sum vs. Order … … 471 470 // min 472 471 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "minimum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; 473 472 474 473 // mean 475 474 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "mean of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1; 476 475 477 476 // max 478 477 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "maximum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; … … 481 480 // min 482 481 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "minimum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; 483 482 484 483 // mean 485 484 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "mean of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1; 486 485 487 486 // max 488 487 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "maximum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; 489 488 490 489 // +++++++++++++++++++++++++++++++=Ploting approximated and true shielding for each atom 491 490 if (periode != NULL) { // also look for PAS values … … 553 552 output << "\trm -rf $(EPS)" << endl; 554 553 output.close(); 555 554 556 555 // ++++++++++++++++ exit ++++++++++++++++++++++++++++++++++ 557 556 delete(periode); -
src/atom.cpp
rce5ac3 rd067d45 1 1 /** \file atom.cpp 2 * 2 * 3 3 * Function implementations for the class atom. 4 * 4 * 5 5 */ 6 6 7 7 #include "molecules.hpp" 8 8 9 9 /************************************* Functions for class atom *************************************/ 10 10 11 11 /** Constructor of class atom. 12 12 */ 13 atom::atom() 13 atom::atom() 14 14 { 15 15 Name = NULL; … … 33 33 /** Destructor of class atom. 34 34 */ 35 atom::~atom() 35 atom::~atom() 36 36 { 37 37 Free((void **)&Name, "atom::~atom: *Name"); … … 58 58 * \param AtomNo cardinal number among these atoms of the same element 59 59 * \param *out stream to output to 60 * \param *comment commentary after '#' sign 60 61 */ 61 bool atom::Output(int ElementNo, int AtomNo, ofstream *out ) const62 bool atom::Output(int ElementNo, int AtomNo, ofstream *out, const char *comment) const 62 63 { 63 64 if (out != NULL) { … … 67 68 if (v.Norm() > MYEPSILON) 68 69 *out << "\t" << scientific << setprecision(6) << v.x[0] << "\t" << v.x[1] << "\t" << v.x[2] << "\t"; 69 *out << " # Number in molecule " << nr << endl; 70 if (comment != NULL) 71 *out << " # " << comment << endl; 72 else 73 *out << " # molecule nr " << nr << endl; 70 74 return true; 71 75 } else … … 94 98 * \param ptr atom to compare index against 95 99 * \return true - this one's is smaller, false - not 96 */ 100 */ 97 101 bool atom::Compare(atom &ptr) 98 102 { … … 103 107 }; 104 108 105 bool operator < (atom &a, atom &b) 109 bool operator < (atom &a, atom &b) 106 110 { 107 111 return a.Compare(b); -
src/boundary.cpp
rce5ac3 rd067d45 1 #include "molecules.hpp"2 1 #include "boundary.hpp" 3 2 4 3 #define DEBUG 1 5 #define DoTecplotOutput 0 4 #define DoSingleStepOutput 0 5 #define DoTecplotOutput 1 6 6 #define DoRaster3DOutput 1 7 #define DoVRMLOutput 1 7 8 #define TecplotSuffix ".dat" 8 9 #define Raster3DSuffix ".r3d" 10 #define VRMLSUffix ".wrl" 11 #define HULLEPSILON MYEPSILON 9 12 10 13 // ======================================== Points on Boundary ================================= … … 28 31 { 29 32 cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl; 33 if (!lines.empty()) 34 cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl; 30 35 node = NULL; 31 36 lines.clear(); … … 33 38 ; 34 39 35 void 36 BoundaryPointSet::AddLine(class BoundaryLineSet *line) 40 void BoundaryPointSet::AddLine(class BoundaryLineSet *line) 37 41 { 38 42 cout << Verbose(6) << "Adding " << *this << " to line " << *line << "." … … 101 105 cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl; 102 106 } 107 if (!triangles.empty()) 108 cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some triangles." << endl; 103 109 } 104 110 ; … … 109 115 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." 110 116 << endl; 111 triangles.insert(TrianglePair( TrianglesCount, triangle));117 triangles.insert(TrianglePair(triangle->Nr, triangle)); 112 118 TrianglesCount++; 113 119 } … … 205 211 206 212 // make it always point inward (any offset vector onto plane projected onto normal vector suffices) 207 if ( endpoints[0]->node->x.Projection(&OtherVector) > 0)213 if (NormalVector.Projection(&OtherVector) > 0) 208 214 NormalVector.Scale(-1.); 209 215 } … … 565 571 ; 566 572 567 /** Creates the objects in a raster3d file (renderable with a header.r3d)573 /** Creates the objects in a VRML file. 568 574 * \param *out output stream for debugging 569 * \param *tecplot output stream for tecplot data 575 * \param *vrmlfile output stream for tecplot data 576 * \param *Tess Tesselation structure with constructed triangles 577 * \param *mol molecule structure with atom positions 578 */ 579 void write_vrml_file(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, class molecule *mol) 580 { 581 atom *Walker = mol->start; 582 bond *Binder = mol->first; 583 int i; 584 Vector *center = mol->DetermineCenterOfAll(out); 585 if (vrmlfile != NULL) { 586 //cout << Verbose(1) << "Writing Raster3D file ... "; 587 *vrmlfile << "#VRML V2.0 utf8" << endl; 588 *vrmlfile << "#Created by molecuilder" << endl; 589 *vrmlfile << "#All atoms as spheres" << endl; 590 while (Walker->next != mol->end) { 591 Walker = Walker->next; 592 *vrmlfile << "Sphere {" << endl << " "; // 2 is sphere type 593 for (i=0;i<NDIM;i++) 594 *vrmlfile << Walker->x.x[i]+center->x[i] << " "; 595 *vrmlfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour 596 } 597 598 *vrmlfile << "# All bonds as vertices" << endl; 599 while (Binder->next != mol->last) { 600 Binder = Binder->next; 601 *vrmlfile << "3" << endl << " "; // 2 is round-ended cylinder type 602 for (i=0;i<NDIM;i++) 603 *vrmlfile << Binder->leftatom->x.x[i]+center->x[i] << " "; 604 *vrmlfile << "\t0.03\t"; 605 for (i=0;i<NDIM;i++) 606 *vrmlfile << Binder->rightatom->x.x[i]+center->x[i] << " "; 607 *vrmlfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour 608 } 609 610 *vrmlfile << "# All tesselation triangles" << endl; 611 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) { 612 *vrmlfile << "1" << endl << " "; // 1 is triangle type 613 for (i=0;i<3;i++) { // print each node 614 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates 615 *vrmlfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " "; 616 *vrmlfile << "\t"; 617 } 618 *vrmlfile << "1. 0. 0." << endl; // red as colour 619 *vrmlfile << "18" << endl << " 0.5 0.5 0.5" << endl; // 18 is transparency type for previous object 620 } 621 } else { 622 cerr << "ERROR: Given vrmlfile is " << vrmlfile << "." << endl; 623 } 624 delete(center); 625 }; 626 627 /** Creates the objects in a raster3d file (renderable with a header.r3d). 628 * \param *out output stream for debugging 629 * \param *rasterfile output stream for tecplot data 570 630 * \param *Tess Tesselation structure with constructed triangles 571 631 * \param *mol molecule structure with atom positions … … 603 663 604 664 *rasterfile << "# All tesselation triangles" << endl; 665 *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"; 605 666 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) { 606 667 *rasterfile << "1" << endl << " "; // 1 is triangle type … … 613 674 *rasterfile << "18" << endl << " 0.5 0.5 0.5" << endl; // 18 is transparency type for previous object 614 675 } 676 *rasterfile << "9\n terminating special property\n"; 615 677 } else { 616 678 cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl; … … 673 735 * Determines first the convex envelope, then tesselates it and calculates its volume. 674 736 * \param *out output stream for debugging 675 * \param * tecplot output stream for tecplotdata737 * \param *filename filename prefix for output of vertex data 676 738 * \param *configuration needed for path to store convex envelope file 677 739 * \param *BoundaryPoints NDIM set of boundary points on the projected plane per axis, on return if desired … … 680 742 */ 681 743 double 682 VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration,744 VolumeOfConvexEnvelope(ofstream *out, const char *filename, config *configuration, 683 745 Boundaries *BoundaryPtr, molecule *mol) 684 746 { … … 761 823 y.CopyVector(&runner->second->endpoints[0]->node->x); 762 824 y.SubtractVector(&runner->second->endpoints[2]->node->x); 763 a = sqrt(runner->second->endpoints[0]->node->x.Distance (825 a = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared( 764 826 &runner->second->endpoints[1]->node->x)); 765 b = sqrt(runner->second->endpoints[0]->node->x.Distance (827 b = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared( 766 828 &runner->second->endpoints[2]->node->x)); 767 c = sqrt(runner->second->endpoints[2]->node->x.Distance (829 c = sqrt(runner->second->endpoints[2]->node->x.DistanceSquared( 768 830 &runner->second->endpoints[1]->node->x)); 769 G = sqrt(((a * a + b * b + c * c) * (a * a + b * b + c * c) - 2 * (a * a 770 * a * a + b * b * b * b + c * c * c * c)) / 16.); // area of tesselated triangle 831 G = sqrt(((a + b + c) * (a + b + c) - 2 * (a * a + b * b + c * c)) / 16.); // area of tesselated triangle 771 832 x.MakeNormalVector(&runner->second->endpoints[0]->node->x, 772 833 &runner->second->endpoints[1]->node->x, … … 797 858 798 859 // 8. Store triangles in tecplot file 860 string OutputName(filename); 861 OutputName.append(TecplotSuffix); 862 ofstream *tecplot = new ofstream(OutputName.c_str()); 799 863 write_tecplot_file(out, tecplot, TesselStruct, mol, 0); 864 tecplot->close(); 865 delete(tecplot); 800 866 801 867 // free reference lists … … 998 1064 for (; C != PointsOnBoundary.end(); C++) 999 1065 { 1000 tmp = A->second->node->x.Distance (&B->second->node->x);1066 tmp = A->second->node->x.DistanceSquared(&B->second->node->x); 1001 1067 distance = tmp * tmp; 1002 tmp = A->second->node->x.Distance (&C->second->node->x);1068 tmp = A->second->node->x.DistanceSquared(&C->second->node->x); 1003 1069 distance += tmp * tmp; 1004 tmp = B->second->node->x.Distance (&C->second->node->x);1070 tmp = B->second->node->x.DistanceSquared(&C->second->node->x); 1005 1071 distance += tmp * tmp; 1006 1072 DistanceMMap.insert(DistanceMultiMapPair(distance, pair< … … 1070 1136 } 1071 1137 // 4d. Check whether the point is inside the triangle (check distance to each node 1072 tmp = checker->second->node->x.Distance (&A->second->node->x);1138 tmp = checker->second->node->x.DistanceSquared(&A->second->node->x); 1073 1139 int innerpoint = 0; 1074 if ((tmp < A->second->node->x.Distance (1140 if ((tmp < A->second->node->x.DistanceSquared( 1075 1141 &baseline->second.first->second->node->x)) && (tmp 1076 < A->second->node->x.Distance (1142 < A->second->node->x.DistanceSquared( 1077 1143 &baseline->second.second->second->node->x))) 1078 1144 innerpoint++; 1079 tmp = checker->second->node->x.Distance (1145 tmp = checker->second->node->x.DistanceSquared( 1080 1146 &baseline->second.first->second->node->x); 1081 if ((tmp < baseline->second.first->second->node->x.Distance (1147 if ((tmp < baseline->second.first->second->node->x.DistanceSquared( 1082 1148 &A->second->node->x)) && (tmp 1083 < baseline->second.first->second->node->x.Distance (1149 < baseline->second.first->second->node->x.DistanceSquared( 1084 1150 &baseline->second.second->second->node->x))) 1085 1151 innerpoint++; 1086 tmp = checker->second->node->x.Distance (1152 tmp = checker->second->node->x.DistanceSquared( 1087 1153 &baseline->second.second->second->node->x); 1088 if ((tmp < baseline->second.second->second->node->x.Distance (1154 if ((tmp < baseline->second.second->second->node->x.DistanceSquared( 1089 1155 &baseline->second.first->second->node->x)) && (tmp 1090 < baseline->second.second->second->node->x.Distance (1156 < baseline->second.second->second->node->x.DistanceSquared( 1091 1157 &A->second->node->x))) 1092 1158 innerpoint++; … … 1483 1549 ; 1484 1550 1551 1552 double det_get(gsl_matrix *A, int inPlace) { 1553 /* 1554 inPlace = 1 => A is replaced with the LU decomposed copy. 1555 inPlace = 0 => A is retained, and a copy is used for LU. 1556 */ 1557 1558 double det; 1559 int signum; 1560 gsl_permutation *p = gsl_permutation_alloc(A->size1); 1561 gsl_matrix *tmpA; 1562 1563 if (inPlace) 1564 tmpA = A; 1565 else { 1566 gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2); 1567 gsl_matrix_memcpy(tmpA , A); 1568 } 1569 1570 1571 gsl_linalg_LU_decomp(tmpA , p , &signum); 1572 det = gsl_linalg_LU_det(tmpA , signum); 1573 gsl_permutation_free(p); 1574 if (! inPlace) 1575 gsl_matrix_free(tmpA); 1576 1577 return det; 1578 }; 1579 1580 void get_sphere(Vector *center, Vector &a, Vector &b, Vector &c, double RADIUS) 1581 { 1582 gsl_matrix *A = gsl_matrix_calloc(3,3); 1583 double m11, m12, m13, m14; 1584 1585 for(int i=0;i<3;i++) { 1586 gsl_matrix_set(A, i, 0, a.x[i]); 1587 gsl_matrix_set(A, i, 1, b.x[i]); 1588 gsl_matrix_set(A, i, 2, c.x[i]); 1589 } 1590 m11 = det_get(A, 1); 1591 1592 for(int i=0;i<3;i++) { 1593 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]); 1594 gsl_matrix_set(A, i, 1, b.x[i]); 1595 gsl_matrix_set(A, i, 2, c.x[i]); 1596 } 1597 m12 = det_get(A, 1); 1598 1599 for(int i=0;i<3;i++) { 1600 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]); 1601 gsl_matrix_set(A, i, 1, a.x[i]); 1602 gsl_matrix_set(A, i, 2, c.x[i]); 1603 } 1604 m13 = det_get(A, 1); 1605 1606 for(int i=0;i<3;i++) { 1607 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]); 1608 gsl_matrix_set(A, i, 1, a.x[i]); 1609 gsl_matrix_set(A, i, 2, b.x[i]); 1610 } 1611 m14 = det_get(A, 1); 1612 1613 if (fabs(m11) < MYEPSILON) 1614 cerr << "ERROR: three points are colinear." << endl; 1615 1616 center->x[0] = 0.5 * m12/ m11; 1617 center->x[1] = -0.5 * m13/ m11; 1618 center->x[2] = 0.5 * m14/ m11; 1619 1620 if (fabs(a.Distance(center) - RADIUS) > MYEPSILON) 1621 cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl; 1622 1623 gsl_matrix_free(A); 1624 }; 1625 1626 1627 1485 1628 /** 1486 1629 * Function returns center of sphere with RADIUS, which rests on points a, b, c … … 1489 1632 * @param b vector second point of triangle 1490 1633 * @param c vector third point of triangle 1491 * @param *Umkreismittelpunkt new cneter point of circumference1492 1634 * @param Direction vector indicates up/down 1493 1635 * @param AlternativeDirection vecotr, needed in case the triangles have 90 deg angle … … 1500 1642 * @param Umkreisradius double radius of circumscribing circle 1501 1643 */ 1502 1503 void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection, 1504 double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius) 1505 { 1506 Vector TempNormal, helper; 1507 double Restradius; 1508 cout << Verbose(3) << "Begin of Get_center_of_sphere.\n"; 1509 Center->Zero(); 1510 helper.CopyVector(&a); 1511 helper.Scale(sin(2.*alpha)); 1512 Center->AddVector(&helper); 1513 helper.CopyVector(&b); 1514 helper.Scale(sin(2.*beta)); 1515 Center->AddVector(&helper); 1516 helper.CopyVector(&c); 1517 helper.Scale(sin(2.*gamma)); 1518 Center->AddVector(&helper); 1519 //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ; 1520 Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma))); 1521 NewUmkreismittelpunkt->CopyVector(Center); 1522 cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n"; 1523 // Here we calculated center of circumscribing circle, using barycentric coordinates 1524 cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n"; 1525 1526 TempNormal.CopyVector(&a); 1527 TempNormal.SubtractVector(&b); 1528 helper.CopyVector(&a); 1529 helper.SubtractVector(&c); 1530 TempNormal.VectorProduct(&helper); 1531 if (fabs(HalfplaneIndicator) < MYEPSILON) 1532 { 1533 if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0)) 1534 { 1535 TempNormal.Scale(-1); 1536 } 1537 } 1538 else 1539 { 1540 if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0) 1541 { 1542 TempNormal.Scale(-1); 1543 } 1544 } 1545 1546 TempNormal.Normalize(); 1547 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius); 1548 cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n"; 1549 TempNormal.Scale(Restradius); 1550 cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n"; 1551 1552 Center->AddVector(&TempNormal); 1553 cout << Verbose(4) << "Center of sphere of circumference is " << *Center << ".\n"; 1554 cout << Verbose(3) << "End of Get_center_of_sphere.\n"; 1555 } 1556 ; 1557 1644 void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection, 1645 double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius) 1646 { 1647 Vector TempNormal, helper; 1648 double Restradius; 1649 Vector OtherCenter; 1650 cout << Verbose(3) << "Begin of Get_center_of_sphere.\n"; 1651 Center->Zero(); 1652 helper.CopyVector(&a); 1653 helper.Scale(sin(2.*alpha)); 1654 Center->AddVector(&helper); 1655 helper.CopyVector(&b); 1656 helper.Scale(sin(2.*beta)); 1657 Center->AddVector(&helper); 1658 helper.CopyVector(&c); 1659 helper.Scale(sin(2.*gamma)); 1660 Center->AddVector(&helper); 1661 //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ; 1662 Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma))); 1663 NewUmkreismittelpunkt->CopyVector(Center); 1664 cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n"; 1665 // Here we calculated center of circumscribing circle, using barycentric coordinates 1666 cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n"; 1667 1668 TempNormal.CopyVector(&a); 1669 TempNormal.SubtractVector(&b); 1670 helper.CopyVector(&a); 1671 helper.SubtractVector(&c); 1672 TempNormal.VectorProduct(&helper); 1673 if (fabs(HalfplaneIndicator) < MYEPSILON) 1674 { 1675 if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0)) 1676 { 1677 TempNormal.Scale(-1); 1678 } 1679 } 1680 else 1681 { 1682 if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0) 1683 { 1684 TempNormal.Scale(-1); 1685 } 1686 } 1687 TempNormal.Normalize(); 1688 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius); 1689 cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n"; 1690 TempNormal.Scale(Restradius); 1691 cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n"; 1692 1693 Center->AddVector(&TempNormal); 1694 cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n"; 1695 get_sphere(&OtherCenter, a, b, c, RADIUS); 1696 cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n"; 1697 cout << Verbose(3) << "End of Get_center_of_sphere.\n"; 1698 }; 1558 1699 1559 1700 /** This recursive function finds a third point, to form a triangle with two given ones. … … 1580 1721 * @param mol molecule structure with atoms and bonds 1581 1722 */ 1582 1583 1723 void Tesselation::Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent, 1584 1724 int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint, … … 1633 1773 } 1634 1774 1635 if ((M_PI* 4. > alpha*5.) && (M_PI*4. > beta*5.) && (M_PI*4 > gamma*5.)) {1775 if ((M_PI*179./180. > alpha) && (M_PI*179./180. > beta) && (M_PI*179./180. > gamma)) { 1636 1776 Umkreisradius = SideA / 2.0 / sin(alpha); 1637 1777 //cout << Umkreisradius << endl; … … 1655 1795 cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl; 1656 1796 } 1657 1658 Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius); 1659 1660 AngleCheck.CopyVector(&ReferencePoint); 1661 AngleCheck.Scale(-1); 1662 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl; 1663 AngleCheck.AddVector(&Mittelpunkt); 1664 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl; 1665 cout << Verbose(4) << "Reference vector to sphere's center is " << AngleCheck << "." << endl; 1666 1667 BallAngle = AngleCheck.Angle(OldNormal); 1668 cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl; 1669 1670 //cout << "direction1 is " << direction1->x[0] <<" "<< direction1->x[1] <<" "<< direction1->x[2] <<" " << endl; 1671 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl; 1797 if (sign >= 0) { 1798 cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl; 1799 Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius); 1800 Mittelpunkt.SubtractVector(&ReferencePoint); 1801 cout << Verbose(3) << "Reference vector to sphere's center is " << Mittelpunkt << "." << endl; 1802 BallAngle = Mittelpunkt.Angle(OldNormal); 1803 cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl; 1804 1672 1805 1673 1806 cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl; 1674 1807 1675 NewUmkreismittelpunkt.SubtractVector(&ReferencePoint); 1676 1677 if ((AngleCheck.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) { 1678 if (Storage[0]< -1.5) { // first Candidate at all 1679 if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) { 1680 cout << Verbose(2) << "First good candidate is " << *Candidate << " with "; 1681 Opt_Candidate = Candidate; 1682 Storage[0] = sign; 1683 Storage[1] = AlternativeSign; 1684 Storage[2] = BallAngle; 1685 cout << " angle " << Storage[2] << " and Up/Down " 1686 << Storage[0] << endl; 1687 } else 1688 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl; 1689 } else { 1690 if ( Storage[2] > BallAngle) { 1691 if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) { 1692 cout << Verbose(2) << "Next better candidate is " << *Candidate << " with "; 1808 if ((Mittelpunkt.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) { 1809 if (Storage[0]< -1.5) { // first Candidate at all 1810 if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) { 1811 cout << Verbose(2) << "First good candidate is " << *Candidate << " with "; 1693 1812 Opt_Candidate = Candidate; 1694 1813 Storage[0] = sign; 1695 1814 Storage[1] = AlternativeSign; 1696 1815 Storage[2] = BallAngle; 1697 cout << " angle " << Storage[2] << " and Up/Down " 1698 << Storage[0] << endl; 1816 cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl; 1699 1817 } else 1700 1818 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl; 1701 1819 } else { 1702 if (DEBUG) { 1703 cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl; 1820 if ( Storage[2] > BallAngle) { 1821 if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) { 1822 cout << Verbose(2) << "Next better candidate is " << *Candidate << " with "; 1823 Opt_Candidate = Candidate; 1824 Storage[0] = sign; 1825 Storage[1] = AlternativeSign; 1826 Storage[2] = BallAngle; 1827 cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl; 1828 } else 1829 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl; 1830 } else { 1831 if (DEBUG) { 1832 cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl; 1833 } 1704 1834 } 1835 } 1836 } else { 1837 if (DEBUG) { 1838 cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl; 1705 1839 } 1706 1840 } 1707 1841 } else { 1708 1842 if (DEBUG) { 1709 cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign<< endl;1843 cout << Verbose(3) << *Candidate << " is not in search direction." << endl; 1710 1844 } 1711 1845 } … … 1741 1875 1742 1876 1743 /** This recursive function finds a third point, to form a triangle with two given ones. 1744 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \ 1745 * supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \ 1746 * upon which we operate. 1747 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \ 1748 * direction and angle into Storage. 1749 * We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \ 1750 * with all neighbours of the candidate. 1751 * @param a first point 1752 * @param b second point 1753 * @param Candidate base point along whose bonds to start looking from 1754 * @param Parent point to avoid during search as its wrong direction 1755 * @param RecursionLevel contains current recursion depth 1756 * @param Chord baseline vector of first and second point 1757 * @param d1 second in plane vector (along with \a Chord) of the triangle the baseline belongs to 1758 * @param OldNormal normal of the triangle which the baseline belongs to 1759 * @param Opt_Candidate candidate reference to return 1760 * @param Opt_Mittelpunkt Centerpoint of ball, when resting on Opt_Candidate 1761 * @param Storage array containing two angles of current Opt_Candidate 1762 * @param RADIUS radius of ball 1763 * @param mol molecule structure with atoms and bonds 1764 */ 1765 void Find_next_suitable_point(atom* a, atom* b, atom* Candidate, atom* Parent, 1766 int RecursionLevel, Vector *Chord, Vector *d1, Vector *OldNormal, 1767 atom*& Opt_Candidate, Vector *Opt_Mittelpunkt, double *Storage, const double RADIUS, molecule* mol) 1768 { 1769 /* OldNormal is normal vector on the old triangle 1770 * d1 is normal on the triangle line, from which we come, as well as on OldNormal. 1771 * Chord points from b to a!!! 1772 */ 1773 Vector dif_a; //Vector from a to candidate 1774 Vector dif_b; //Vector from b to candidate 1775 Vector AngleCheck, AngleCheckReference, DirectionCheckPoint; 1776 Vector TempNormal, Umkreismittelpunkt, Mittelpunkt, helper; 1777 1778 double CurrentEpsilon = 0.1; 1779 double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius; 1780 double BallAngle; 1781 atom *Walker; // variable atom point 1782 1783 1784 dif_a.CopyVector(&(a->x)); 1785 dif_a.SubtractVector(&(Candidate->x)); 1786 dif_b.CopyVector(&(b->x)); 1787 dif_b.SubtractVector(&(Candidate->x)); 1788 DirectionCheckPoint.CopyVector(&dif_a); 1789 DirectionCheckPoint.Scale(-1); 1790 DirectionCheckPoint.ProjectOntoPlane(Chord); 1791 1792 SideA = dif_b.Norm(); 1793 SideB = dif_a.Norm(); 1794 SideC = Chord->Norm(); 1795 //Chord->Scale(-1); 1796 1797 alpha = Chord->Angle(&dif_a); 1798 beta = M_PI - Chord->Angle(&dif_b); 1799 gamma = dif_a.Angle(&dif_b); 1800 1801 1802 if (DEBUG) { 1803 cout << "Atom number" << Candidate->nr << endl; 1804 Candidate->x.Output((ofstream *) &cout); 1805 cout << "number of bonds " << mol->NumberOfBondsPerAtom[Candidate->nr] << endl; 1806 } 1807 1808 if (a != Candidate and b != Candidate) { 1809 // alpha = dif_a.Angle(&dif_b) / 2.; 1810 // SideA = Chord->Norm() / 2.;// (Chord->Norm()/2.) / sin(0.5*alpha); 1811 // SideB = dif_a.Norm(); 1812 // centerline = SideA * SideA + SideB * SideB - 2. * SideA * SideB * cos( 1813 // alpha); // note this is squared of center line length 1814 // centerline = (Chord->Norm()/2.) / sin(0.5*alpha); 1815 // Those are remains from Freddie. Needed? 1816 1817 Umkreisradius = SideA / 2.0 / sin(alpha); 1818 //cout << Umkreisradius << endl; 1819 //cout << SideB / 2.0 / sin(beta) << endl; 1820 //cout << SideC / 2.0 / sin(gamma) << endl; 1821 1822 if (Umkreisradius < RADIUS && DirectionCheckPoint.ScalarProduct(&(Candidate->x))>0) { //Checking whether ball will at least rest o points. 1823 // intermediate calculations to aquire centre of sphere, called Mittelpunkt: 1824 Umkreismittelpunkt.Zero(); 1825 helper.CopyVector(&a->x); 1826 helper.Scale(sin(2.*alpha)); 1827 Umkreismittelpunkt.AddVector(&helper); 1828 helper.CopyVector(&b->x); 1829 helper.Scale(sin(2.*beta)); 1830 Umkreismittelpunkt.AddVector(&helper); 1831 helper.CopyVector(&Candidate->x); 1832 helper.Scale(sin(2.*gamma)); 1833 Umkreismittelpunkt.AddVector(&helper); 1834 //Umkreismittelpunkt = (a->x) * sin(2.*alpha) + b->x * sin(2.*beta) + (Candidate->x) * sin(2.*gamma) ; 1835 Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma))); 1836 1837 TempNormal.CopyVector(&dif_a); 1838 TempNormal.VectorProduct(&dif_b); 1839 if (TempNormal.ScalarProduct(OldNormal)<0 && sign>0 || TempNormal.ScalarProduct(OldNormal)>0 && sign<0) { 1840 TempNormal.Scale(-1); 1877 /** Constructs the center of the circumcircle defined by three points \a *a, \a *b and \a *c. 1878 * \param *Center new center on return 1879 * \param *a first point 1880 * \param *b second point 1881 * \param *c third point 1882 */ 1883 void GetCenterofCircumcircle(Vector *Center, Vector *a, Vector *b, Vector *c) 1884 { 1885 Vector helper; 1886 double alpha, beta, gamma; 1887 Vector SideA, SideB, SideC; 1888 SideA.CopyVector(b); 1889 SideA.SubtractVector(c); 1890 SideB.CopyVector(c); 1891 SideB.SubtractVector(a); 1892 SideC.CopyVector(a); 1893 SideC.SubtractVector(b); 1894 alpha = M_PI - SideB.Angle(&SideC); 1895 beta = M_PI - SideC.Angle(&SideA); 1896 gamma = M_PI - SideA.Angle(&SideB); 1897 cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl; 1898 if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON) 1899 cerr << "Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl; 1900 1901 Center->Zero(); 1902 helper.CopyVector(a); 1903 helper.Scale(sin(2.*alpha)); 1904 Center->AddVector(&helper); 1905 helper.CopyVector(b); 1906 helper.Scale(sin(2.*beta)); 1907 Center->AddVector(&helper); 1908 helper.CopyVector(c); 1909 helper.Scale(sin(2.*gamma)); 1910 Center->AddVector(&helper); 1911 Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma))); 1912 }; 1913 1914 /** Returns the parameter "path length" for a given \a NewSphereCenter relative to \a OldSphereCenter on a circle on the plane \a CirclePlaneNormal with center \a CircleCenter and radius \a CircleRadius. 1915 * Test whether the \a NewSphereCenter is really on the given plane and in distance \a CircleRadius from \a CircleCenter. 1916 * It calculates the angle, making it unique on [0,2.*M_PI) by comparing to SearchDirection. 1917 * Also the new center is invalid if it the same as the old one and does not lie right above (\a NormalVector) the base line (\a CircleCenter). 1918 * \param CircleCenter Center of the parameter circle 1919 * \param CirclePlaneNormal normal vector to plane of the parameter circle 1920 * \param CircleRadius radius of the parameter circle 1921 * \param NewSphereCenter new center of a circumcircle 1922 * \param OldSphereCenter old center of a circumcircle, defining the zero "path length" on the parameter circle 1923 * \param NormalVector normal vector 1924 * \param SearchDirection search direction to make angle unique on return. 1925 * \return Angle between \a NewSphereCenter and \a OldSphereCenter relative to \a CircleCenter, 2.*M_PI if one test fails 1926 */ 1927 double GetPathLengthonCircumCircle(Vector &CircleCenter, Vector &CirclePlaneNormal, double CircleRadius, Vector &NewSphereCenter, Vector &OldSphereCenter, Vector &NormalVector, Vector &SearchDirection) 1928 { 1929 Vector helper; 1930 double radius, alpha; 1931 1932 helper.CopyVector(&NewSphereCenter); 1933 // test whether new center is on the parameter circle's plane 1934 if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) { 1935 cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal)) << "!" << endl; 1936 helper.ProjectOntoPlane(&CirclePlaneNormal); 1937 } 1938 radius = helper.ScalarProduct(&helper); 1939 // test whether the new center vector has length of CircleRadius 1940 if (fabs(radius - CircleRadius) > HULLEPSILON) 1941 cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl; 1942 alpha = helper.Angle(&OldSphereCenter); 1943 // make the angle unique by checking the halfplanes/search direction 1944 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON) // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals 1945 alpha = 2.*M_PI - alpha; 1946 cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl; 1947 radius = helper.Distance(&OldSphereCenter); 1948 helper.ProjectOntoPlane(&NormalVector); 1949 // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles 1950 if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) { 1951 cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl; 1952 return alpha; 1953 } else { 1954 cout << Verbose(1) << "ERROR: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl; 1955 return 2.*M_PI; 1956 } 1957 }; 1958 1959 1960 /** This recursive function finds a third point, to form a triangle with two given ones. 1961 * The idea is as follows: A sphere with fixed radius is (almost) uniquely defined in space by three points 1962 * that sit on its boundary. Hence, when two points are given and we look for the (next) third point, then 1963 * the center of the sphere is still fixed up to a single parameter. The band of possible values 1964 * describes a circle in 3D-space. The old center of the sphere for the current base triangle gives 1965 * us the "null" on this circle, the new center of the candidate point will be some way along this 1966 * circle. The shorter the way the better is the candidate. Note that the direction is clearly given 1967 * by the normal vector of the base triangle that always points outwards by construction. 1968 * Hence, we construct a Center of this circle which sits right in the middle of the current base line. 1969 * We construct the normal vector that defines the plane this circle lies in, it is just in the 1970 * direction of the baseline. And finally, we need the radius of the circle, which is given by the rest 1971 * with respect to the length of the baseline and the sphere's fixed \a RADIUS. 1972 * Note that there is one difficulty: The circumcircle is uniquely defined, but for the circumsphere's center 1973 * there are two possibilities which becomes clear from the construction as seen below. Hence, we must check 1974 * both. 1975 * Note also that the acos() function is not unique on [0, 2.*M_PI). Hence, we need an additional check 1976 * to decide for one of the two possible angles. Therefore we need a SearchDirection and to make this check 1977 * sensible we need OldSphereCenter to be orthogonal to it. Either we construct SearchDirection orthogonal 1978 * right away, or -- what we do here -- we rotate the relative sphere centers such that this orthogonality 1979 * holds. Then, the normalized projection onto the SearchDirection is either +1 or -1 and thus states whether 1980 * the angle is uniquely in either (0,M_PI] or [M_PI, 2.*M_PI). 1981 * @param BaseTriangle BoundaryTriangleSet of the current base triangle with all three points 1982 * @param BaseLine BoundaryLineSet of BaseTriangle with the current base line 1983 * @param OptCandidate candidate reference on return 1984 * @param OptCandidateCenter candidate's sphere center on return 1985 * @param ShortestAngle the current path length on this circle band for the current Opt_Candidate 1986 * @param RADIUS radius of sphere 1987 * @param *LC LinkedCell structure with neighbouring atoms 1988 */ 1989 // void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC) 1990 // { 1991 // atom *Walker = NULL; 1992 // Vector CircleCenter; // center of the circle, i.e. of the band of sphere's centers 1993 // Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in 1994 // Vector OldSphereCenter; // center of the sphere defined by the three points of BaseTriangle 1995 // Vector NewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility 1996 // Vector OtherNewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility 1997 // Vector NewNormalVector; // normal vector of the Candidate's triangle 1998 // Vector SearchDirection; // vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate) 1999 // Vector helper; 2000 // LinkedAtoms *List = NULL; 2001 // double CircleRadius; // radius of this circle 2002 // double radius; 2003 // double alpha, Otheralpha; // angles (i.e. parameter for the circle). 2004 // double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle 2005 // int N[NDIM], Nlower[NDIM], Nupper[NDIM]; 2006 // atom *Candidate = NULL; 2007 // 2008 // cout << Verbose(1) << "Begin of Find_next_suitable_point" << endl; 2009 // 2010 // cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << BaseTriangle->NormalVector << "." << endl; 2011 // 2012 // // construct center of circle 2013 // CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x)); 2014 // CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x); 2015 // CircleCenter.Scale(0.5); 2016 // 2017 // // construct normal vector of circle 2018 // CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x); 2019 // CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x); 2020 // 2021 // // calculate squared radius of circle 2022 // radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal); 2023 // if (radius/4. < RADIUS*RADIUS) { 2024 // CircleRadius = RADIUS*RADIUS - radius/4.; 2025 // CirclePlaneNormal.Normalize(); 2026 // cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl; 2027 // 2028 // // construct old center 2029 // GetCenterofCircumcircle(&OldSphereCenter, &(BaseTriangle->endpoints[0]->node->x), &(BaseTriangle->endpoints[1]->node->x), &(BaseTriangle->endpoints[2]->node->x)); 2030 // helper.CopyVector(&BaseTriangle->NormalVector); // normal vector ensures that this is correct center of the two possible ones 2031 // radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&OldSphereCenter); 2032 // helper.Scale(sqrt(RADIUS*RADIUS - radius)); 2033 // OldSphereCenter.AddVector(&helper); 2034 // OldSphereCenter.SubtractVector(&CircleCenter); 2035 // cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl; 2036 // 2037 // // test whether old center is on the band's plane 2038 // if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) { 2039 // cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl; 2040 // OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal); 2041 // } 2042 // radius = OldSphereCenter.ScalarProduct(&OldSphereCenter); 2043 // if (fabs(radius - CircleRadius) < HULLEPSILON) { 2044 // 2045 // // construct SearchDirection 2046 // SearchDirection.MakeNormalVector(&BaseTriangle->NormalVector, &CirclePlaneNormal); 2047 // helper.CopyVector(&BaseLine->endpoints[0]->node->x); 2048 // for(int i=0;i<3;i++) // just take next different endpoint 2049 // if ((BaseTriangle->endpoints[i]->node != BaseLine->endpoints[0]->node) && (BaseTriangle->endpoints[i]->node != BaseLine->endpoints[1]->node)) { 2050 // helper.SubtractVector(&BaseTriangle->endpoints[i]->node->x); 2051 // } 2052 // if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON) // ohoh, SearchDirection points inwards! 2053 // SearchDirection.Scale(-1.); 2054 // SearchDirection.ProjectOntoPlane(&OldSphereCenter); 2055 // SearchDirection.Normalize(); 2056 // cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl; 2057 // if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) { // rotated the wrong way! 2058 // cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl; 2059 // } 2060 // 2061 // if (LC->SetIndexToVector(&CircleCenter)) { // get cell for the starting atom 2062 // for(int i=0;i<NDIM;i++) // store indices of this cell 2063 // N[i] = LC->n[i]; 2064 // cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl; 2065 // } else { 2066 // cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl; 2067 // return; 2068 // } 2069 // // then go through the current and all neighbouring cells and check the contained atoms for possible candidates 2070 // cout << Verbose(2) << "LC Intervals:"; 2071 // for (int i=0;i<NDIM;i++) { 2072 // Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0; 2073 // Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1; 2074 // cout << " [" << Nlower[i] << "," << Nupper[i] << "] "; 2075 // } 2076 // cout << endl; 2077 // for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 2078 // for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 2079 // for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 2080 // List = LC->GetCurrentCell(); 2081 // cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 2082 // if (List != NULL) { 2083 // for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 2084 // Candidate = (*Runner); 2085 // 2086 // // check for three unique points 2087 // if ((Candidate != BaseTriangle->endpoints[0]->node) && (Candidate != BaseTriangle->endpoints[1]->node) && (Candidate != BaseTriangle->endpoints[2]->node)) { 2088 // cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl; 2089 // 2090 // // construct both new centers 2091 // GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x)); 2092 // OtherNewSphereCenter.CopyVector(&NewSphereCenter); 2093 // 2094 // if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) { 2095 // helper.CopyVector(&NewNormalVector); 2096 // cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl; 2097 // radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter); 2098 // if (radius < RADIUS*RADIUS) { 2099 // helper.Scale(sqrt(RADIUS*RADIUS - radius)); 2100 // cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl; 2101 // NewSphereCenter.AddVector(&helper); 2102 // NewSphereCenter.SubtractVector(&CircleCenter); 2103 // cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl; 2104 // 2105 // helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction 2106 // OtherNewSphereCenter.AddVector(&helper); 2107 // OtherNewSphereCenter.SubtractVector(&CircleCenter); 2108 // cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl; 2109 // 2110 // // check both possible centers 2111 // alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection); 2112 // Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection); 2113 // alpha = min(alpha, Otheralpha); 2114 // if (*ShortestAngle > alpha) { 2115 // OptCandidate = Candidate; 2116 // *ShortestAngle = alpha; 2117 // if (alpha != Otheralpha) 2118 // OptCandidateCenter->CopyVector(&NewSphereCenter); 2119 // else 2120 // OptCandidateCenter->CopyVector(&OtherNewSphereCenter); 2121 // cout << Verbose(1) << "We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl; 2122 // } else { 2123 // if (OptCandidate != NULL) 2124 // cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl; 2125 // else 2126 // cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl; 2127 // } 2128 // 2129 // } else { 2130 // cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl; 2131 // } 2132 // } else { 2133 // cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl; 2134 // } 2135 // } else { 2136 // cout << Verbose(1) << "REJECT: Base triangle " << *BaseTriangle << " contains Candidate " << *Candidate << "." << endl; 2137 // } 2138 // } 2139 // } 2140 // } 2141 // } else { 2142 // cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl; 2143 // } 2144 // } else { 2145 // cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and base triangle " << *BaseTriangle << " is too big!" << endl; 2146 // } 2147 // 2148 // cout << Verbose(1) << "End of Find_next_suitable_point" << endl; 2149 // }; 2150 2151 2152 /** This recursive function finds a third point, to form a triangle with two given ones. 2153 * Note that this function is for the starting triangle. 2154 * The idea is as follows: A sphere with fixed radius is (almost) uniquely defined in space by three points 2155 * that sit on its boundary. Hence, when two points are given and we look for the (next) third point, then 2156 * the center of the sphere is still fixed up to a single parameter. The band of possible values 2157 * describes a circle in 3D-space. The old center of the sphere for the current base triangle gives 2158 * us the "null" on this circle, the new center of the candidate point will be some way along this 2159 * circle. The shorter the way the better is the candidate. Note that the direction is clearly given 2160 * by the normal vector of the base triangle that always points outwards by construction. 2161 * Hence, we construct a Center of this circle which sits right in the middle of the current base line. 2162 * We construct the normal vector that defines the plane this circle lies in, it is just in the 2163 * direction of the baseline. And finally, we need the radius of the circle, which is given by the rest 2164 * with respect to the length of the baseline and the sphere's fixed \a RADIUS. 2165 * Note that there is one difficulty: The circumcircle is uniquely defined, but for the circumsphere's center 2166 * there are two possibilities which becomes clear from the construction as seen below. Hence, we must check 2167 * both. 2168 * Note also that the acos() function is not unique on [0, 2.*M_PI). Hence, we need an additional check 2169 * to decide for one of the two possible angles. Therefore we need a SearchDirection and to make this check 2170 * sensible we need OldSphereCenter to be orthogonal to it. Either we construct SearchDirection orthogonal 2171 * right away, or -- what we do here -- we rotate the relative sphere centers such that this orthogonality 2172 * holds. Then, the normalized projection onto the SearchDirection is either +1 or -1 and thus states whether 2173 * the angle is uniquely in either (0,M_PI] or [M_PI, 2.*M_PI). 2174 * @param NormalVector normal direction of the base triangle (here the unit axis vector, \sa Find_starting_triangle()) 2175 * @param SearchDirection general direction where to search for the next point, relative to center of BaseLine 2176 * @param OldSphereCenter center of sphere for base triangle, relative to center of BaseLine, giving null angle for the parameter circle 2177 * @param BaseLine BoundaryLineSet with the current base line 2178 * @param ThirdNode third atom to avoid in search 2179 * @param OptCandidate candidate reference on return 2180 * @param OptCandidateCenter candidate's sphere center on return 2181 * @param ShortestAngle the current path length on this circle band for the current Opt_Candidate 2182 * @param RADIUS radius of sphere 2183 * @param *LC LinkedCell structure with neighbouring atoms 2184 */ 2185 void Find_third_point_for_Tesselation(Vector NormalVector, Vector SearchDirection, Vector OldSphereCenter, class BoundaryLineSet *BaseLine, atom *ThirdNode, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC) 2186 { 2187 Vector CircleCenter; // center of the circle, i.e. of the band of sphere's centers 2188 Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in 2189 Vector NewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility 2190 Vector OtherNewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility 2191 Vector NewNormalVector; // normal vector of the Candidate's triangle 2192 Vector helper; 2193 LinkedAtoms *List = NULL; 2194 double CircleRadius; // radius of this circle 2195 double radius; 2196 double alpha, Otheralpha; // angles (i.e. parameter for the circle). 2197 int N[NDIM], Nlower[NDIM], Nupper[NDIM]; 2198 atom *Candidate = NULL; 2199 2200 cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl; 2201 2202 cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl; 2203 2204 // construct center of circle 2205 CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x)); 2206 CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x); 2207 CircleCenter.Scale(0.5); 2208 2209 // construct normal vector of circle 2210 CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x); 2211 CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x); 2212 2213 // calculate squared radius of circle 2214 radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal); 2215 if (radius/4. < RADIUS*RADIUS) { 2216 CircleRadius = RADIUS*RADIUS - radius/4.; 2217 CirclePlaneNormal.Normalize(); 2218 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl; 2219 2220 // test whether old center is on the band's plane 2221 if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) { 2222 cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl; 2223 OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal); 2224 } 2225 radius = OldSphereCenter.ScalarProduct(&OldSphereCenter); 2226 if (fabs(radius - CircleRadius) < HULLEPSILON) { 2227 2228 // check SearchDirection 2229 cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl; 2230 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) { // rotated the wrong way! 2231 cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl; 1841 2232 } 1842 TempNormal.Normalize(); 1843 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius); 1844 TempNormal.Scale(Restradius); 1845 1846 Mittelpunkt.CopyVector(&Umkreismittelpunkt); 1847 Mittelpunkt.AddVector(&TempNormal); //this is center of sphere supported by a, b and Candidate 1848 1849 AngleCheck.CopyVector(Chord); 1850 AngleCheck.Scale(-0.5); 1851 AngleCheck.SubtractVector(&(b->x)); 1852 AngleCheckReference.CopyVector(&AngleCheck); 1853 AngleCheckReference.AddVector(Opt_Mittelpunkt); 1854 AngleCheck.AddVector(&Mittelpunkt); 1855 1856 BallAngle = AngleCheck.Angle(&AngleCheckReference); 1857 1858 d1->ProjectOntoPlane(&AngleCheckReference); 1859 sign = AngleCheck.ScalarProduct(d1); 1860 if (fabs(sign) < MYEPSILON) 1861 sign = 0; 1862 else 1863 sign /= fabs(sign); // +1 if in direction of triangle plane, -1 if in other direction... 1864 1865 1866 if (Storage[0]< -1.5) { // first Candidate at all 1867 cout << "Next better candidate is " << *Candidate << " with "; 1868 Opt_Candidate = Candidate; 1869 Storage[0] = sign; 1870 Storage[1] = BallAngle; 1871 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1872 cout << "Angle is " << Storage[1] << ", Halbraum ist " << Storage[0] << endl; 2233 // get cell for the starting atom 2234 if (LC->SetIndexToVector(&CircleCenter)) { 2235 for(int i=0;i<NDIM;i++) // store indices of this cell 2236 N[i] = LC->n[i]; 2237 cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl; 1873 2238 } else { 1874 /* 1875 * removed due to change in criterium, now checking angle of ball to old normal. 1876 //We will now check for non interference, that is if the new candidate would have the Opt_Candidate 1877 //within the ball. 1878 1879 Distance = Opt_Candidate->x.Distance(&Mittelpunkt); 1880 //cout << "Opt_Candidate " << Opt_Candidate << " has distance " << Distance << " to Center of Candidate " << endl; 1881 1882 1883 if (Distance >RADIUS) { // We have no interference and may now check whether the new point is better. 1884 */ 1885 //cout << "Atom " << Candidate << " has distance " << Candidate->x.Distance(Opt_Mittelpunkt) << " to Center of Candidate " << endl; 1886 1887 if (((Storage[0] < 0 && fabs(sign - Storage[0]) > CurrentEpsilon))) { //This will give absolute preference to those in "right-hand" quadrants 1888 //(Candidate->x.Distance(Opt_Mittelpunkt) < RADIUS)) //and those where Candidate would be within old Sphere. 1889 cout << "Next better candidate is " << *Candidate << " with "; 1890 Opt_Candidate = Candidate; 1891 Storage[0] = sign; 1892 Storage[1] = BallAngle; 1893 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1894 cout << "Angle is " << Storage[1] << ", Halbraum ist " << Storage[0] << endl; 1895 } else { 1896 if ((fabs(sign - Storage[0]) < CurrentEpsilon && sign > 0 && Storage[1] > BallAngle) || (fabs(sign - Storage[0]) < CurrentEpsilon && sign < 0 && Storage[1] < BallAngle)) { 1897 //Depending on quadrant we prefer higher or lower atom with respect to Triangle normal first. 1898 cout << "Next better candidate is " << *Candidate << " with "; 1899 Opt_Candidate = Candidate; 1900 Storage[0] = sign; 1901 Storage[1] = BallAngle; 1902 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1903 cout << "Angle is " << Storage[1] << ", Halbraum ist " << Storage[0] << endl; 2239 cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl; 2240 return; 2241 } 2242 // then go through the current and all neighbouring cells and check the contained atoms for possible candidates 2243 cout << Verbose(2) << "LC Intervals:"; 2244 for (int i=0;i<NDIM;i++) { 2245 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0; 2246 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1; 2247 cout << " [" << Nlower[i] << "," << Nupper[i] << "] "; 2248 } 2249 cout << endl; 2250 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 2251 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 2252 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 2253 List = LC->GetCurrentCell(); 2254 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 2255 if (List != NULL) { 2256 for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 2257 Candidate = (*Runner); 2258 2259 // check for three unique points 2260 if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) && (Candidate != ThirdNode)) { 2261 cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl; 2262 2263 // construct both new centers 2264 GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x)); 2265 OtherNewSphereCenter.CopyVector(&NewSphereCenter); 2266 2267 if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) { 2268 helper.CopyVector(&NewNormalVector); 2269 cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl; 2270 radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter); 2271 if (radius < RADIUS*RADIUS) { 2272 helper.Scale(sqrt(RADIUS*RADIUS - radius)); 2273 cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl; 2274 NewSphereCenter.AddVector(&helper); 2275 NewSphereCenter.SubtractVector(&CircleCenter); 2276 cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl; 2277 2278 helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction 2279 OtherNewSphereCenter.AddVector(&helper); 2280 OtherNewSphereCenter.SubtractVector(&CircleCenter); 2281 cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl; 2282 2283 // check both possible centers 2284 alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection); 2285 Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection); 2286 alpha = min(alpha, Otheralpha); 2287 if (*ShortestAngle > alpha) { 2288 OptCandidate = Candidate; 2289 *ShortestAngle = alpha; 2290 if (alpha != Otheralpha) 2291 OptCandidateCenter->CopyVector(&NewSphereCenter); 2292 else 2293 OptCandidateCenter->CopyVector(&OtherNewSphereCenter); 2294 cout << Verbose(1) << "ACCEPT: We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl; 2295 } else { 2296 if (OptCandidate != NULL) 2297 cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl; 2298 else 2299 cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl; 2300 } 2301 2302 } else { 2303 cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl; 2304 } 2305 } else { 2306 cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl; 2307 } 2308 } else { 2309 if (ThirdNode != NULL) 2310 cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl; 2311 else 2312 cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl; 2313 } 2314 } 2315 } 1904 2316 } 1905 }1906 }1907 /*1908 * This is for checking point-angle and presence of Candidates in Ball, currently we are checking the ball Angle.1909 *1910 else1911 {1912 if (sign>0 && BallAngle>0 && Storage[0]<0)1913 {1914 cout << "Next better candidate is " << *Candidate << " with ";1915 Opt_Candidate = Candidate;1916 Storage[0] = sign;1917 Storage[1] = BallAngle;1918 Opt_Mittelpunkt->CopyVector(&Mittelpunkt);1919 cout << "Angle is " << Storage[1] << ", Halbraum ist "1920 << Storage[0] << endl;1921 1922 //Debugging purposes only1923 cout << "Umkreismittelpunkt has coordinates" << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] <<" "<<Umkreismittelpunkt.x[2] << endl;1924 cout << "Candidate has coordinates" << Candidate->x.x[0]<< " " << Candidate->x.x[1] << " " << Candidate->x.x[2] << endl;1925 cout << "a has coordinates" << a->x.x[0]<< " " << a->x.x[1] << " " << a->x.x[2] << endl;1926 cout << "b has coordinates" << b->x.x[0]<< " " << b->x.x[1] << " " << b->x.x[2] << endl;1927 cout << "Mittelpunkt has coordinates" << Mittelpunkt.x[0] << " " << Mittelpunkt.x[1]<< " " <<Mittelpunkt.x[2] << endl;1928 cout << "Umkreisradius ist " << Umkreisradius << endl;1929 cout << "Restradius ist " << Restradius << endl;1930 cout << "TempNormal has coordinates " << TempNormal.x[0] << " " << TempNormal.x[1] << " " << TempNormal.x[2] << " " << endl;1931 cout << "OldNormal has coordinates " << OldNormal->x[0] << " " << OldNormal->x[1] << " " << OldNormal->x[2] << " " << endl;1932 cout << "Dist a to UmkreisMittelpunkt " << a->x.Distance(&Umkreismittelpunkt) << endl;1933 cout << "Dist b to UmkreisMittelpunkt " << b->x.Distance(&Umkreismittelpunkt) << endl;1934 cout << "Dist Candidate to UmkreisMittelpunkt " << Candidate->x.Distance(&Umkreismittelpunkt) << endl;1935 cout << "Dist a to Mittelpunkt " << a->x.Distance(&Mittelpunkt) << endl;1936 cout << "Dist b to Mittelpunkt " << b->x.Distance(&Mittelpunkt) << endl;1937 cout << "Dist Candidate to Mittelpunkt " << Candidate->x.Distance(&Mittelpunkt) << endl;1938 1939 1940 1941 }1942 else1943 {1944 if (DEBUG)1945 cout << "Looses to better candidate" << endl;1946 }1947 }1948 */1949 2317 } else { 1950 if (DEBUG) { 1951 cout << "Doesn't satisfy requirements for circumscribing circle" << endl; 1952 } 2318 cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl; 1953 2319 } 1954 2320 } else { 1955 if (DEBUG) { 1956 cout << "identisch mit Ursprungslinie" << endl; 1957 } 1958 } 1959 1960 if (RecursionLevel < 9) { // Five is the recursion level threshold. 1961 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond 1962 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate); 1963 if (Walker == Parent) { // don't go back the same bond 1964 continue; 1965 } else { 1966 Find_next_suitable_point(a, b, Walker, Candidate, RecursionLevel+1, Chord, d1, OldNormal, Opt_Candidate, Opt_Mittelpunkt, Storage, RADIUS, mol); //call function again 1967 } 1968 } 1969 } 1970 }; 1971 1972 /** This function finds a triangle to a line, adjacent to an existing one. 1973 * @param out output stream for debugging 1974 * @param tecplot output stream for writing found triangles in TecPlot format 1975 * @param mol molecule structure with all atoms and bonds 1976 * @param Line current baseline to search from 1977 * @param T current triangle which \a Line is edge of 1978 * @param RADIUS radius of the rolling ball 1979 * @param N number of found triangles 1980 * @param *filename filename base for intermediate envelopes 1981 */ 1982 bool Tesselation::Find_next_suitable_triangle(ofstream *out, ofstream *tecplot, 1983 molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, 1984 const double& RADIUS, int N, const char *tempbasename) 1985 { 1986 cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n"; 1987 Vector direction1; 1988 Vector helper; 1989 Vector Chord; 1990 ofstream *tempstream = NULL; 1991 char NumberName[255]; 1992 double tmp; 1993 //atom* Walker; 1994 atom* OldThirdPoint; 1995 1996 double Storage[3]; 1997 Storage[0] = -2.; // This direction is either +1 or -1 one, so any result will take precedence over initial values 1998 Storage[1] = -2.; // This is also lower then any value produced by an eligible atom, which are all positive 1999 Storage[2] = 9999999.; 2000 atom* Opt_Candidate = NULL; 2001 Vector Opt_Mittelpunkt; 2002 2003 cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl; 2004 2005 helper.CopyVector(&(Line.endpoints[0]->node->x)); 2006 for (int i = 0; i < 3; i++) { 2007 if (T.endpoints[i]->node->nr != Line.endpoints[0]->node->nr && T.endpoints[i]->node->nr != Line.endpoints[1]->node->nr) { 2008 OldThirdPoint = T.endpoints[i]->node; 2009 helper.SubtractVector(&T.endpoints[i]->node->x); 2010 break; 2011 } 2012 } 2013 2014 direction1.CopyVector(&Line.endpoints[0]->node->x); 2015 direction1.SubtractVector(&Line.endpoints[1]->node->x); 2016 direction1.VectorProduct(&(T.NormalVector)); 2017 2018 if (direction1.ScalarProduct(&helper) < 0) { 2019 direction1.Scale(-1); 2020 } 2021 cout << Verbose(2) << "Looking in direction " << direction1 << " for candidates.\n"; 2022 2023 Chord.CopyVector(&(Line.endpoints[0]->node->x)); // bring into calling function 2024 Chord.SubtractVector(&(Line.endpoints[1]->node->x)); 2025 cout << Verbose(2) << "Baseline vector is " << Chord << ".\n"; 2026 2027 2028 Vector Umkreismittelpunkt, a, b, c; 2029 double alpha, beta, gamma; 2030 a.CopyVector(&(T.endpoints[0]->node->x)); 2031 b.CopyVector(&(T.endpoints[1]->node->x)); 2032 c.CopyVector(&(T.endpoints[2]->node->x)); 2033 a.SubtractVector(&(T.endpoints[1]->node->x)); 2034 b.SubtractVector(&(T.endpoints[2]->node->x)); 2035 c.SubtractVector(&(T.endpoints[0]->node->x)); 2036 2037 alpha = M_PI - a.Angle(&c); 2038 beta = M_PI - b.Angle(&a); 2039 gamma = M_PI - c.Angle(&b); 2040 if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) 2041 cerr << Verbose(0) << "WARNING: sum of angles for candidate triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n"; 2042 2043 Umkreismittelpunkt.Zero(); 2044 helper.CopyVector(&T.endpoints[0]->node->x); 2045 helper.Scale(sin(2.*alpha)); 2046 Umkreismittelpunkt.AddVector(&helper); 2047 helper.CopyVector(&T.endpoints[1]->node->x); 2048 helper.Scale(sin(2.*beta)); 2049 Umkreismittelpunkt.AddVector(&helper); 2050 helper.CopyVector(&T.endpoints[2]->node->x); 2051 helper.Scale(sin(2.*gamma)); 2052 Umkreismittelpunkt.AddVector(&helper); 2053 //Umkreismittelpunkt = (T.endpoints[0]->node->x) * sin(2.*alpha) + T.endpoints[1]->node->x * sin(2.*beta) + (T.endpoints[2]->node->x) * sin(2.*gamma) ; 2054 //cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl; 2055 Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma))); 2056 //cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl; 2057 cout << " We look over line " << Line << " in direction " << direction1.x[0] << " " << direction1.x[1] << " " << direction1.x[2] << " " << endl; 2058 cout << " Old Normal is " << (T.NormalVector.x)[0] << " " << T.NormalVector.x[1] << " " << (T.NormalVector.x)[2] << " " << endl; 2059 2060 cout << Verbose(2) << "Base triangle has sides " << a << ", " << b << ", " << c << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl; 2061 cout << Verbose(2) << "Center of circumference is " << Umkreismittelpunkt << "." << endl; 2062 if (DEBUG) 2063 cout << Verbose(3) << "Check of relative endpoints (same distance, equally spreaded): "<< endl; 2064 tmp = 0; 2065 for (int i=0;i<NDIM;i++) { 2066 helper.CopyVector(&T.endpoints[i]->node->x); 2067 helper.SubtractVector(&Umkreismittelpunkt); 2068 if (DEBUG) 2069 cout << Verbose(3) << "Endpoint[" << i << "]: " << helper << " with length " << helper.Norm() << "." << endl; 2070 if (tmp == 0) // set on first time for comparison against next ones 2071 tmp = helper.Norm(); 2072 if (fabs(helper.Norm() - tmp) > MYEPSILON) 2073 cerr << Verbose(1) << "WARNING: center of circumference is wrong!" << endl; 2074 } 2075 2076 cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl; 2077 2078 Find_next_suitable_point_via_Angle_of_Sphere(Line.endpoints[0]->node, Line.endpoints[1]->node, OldThirdPoint, Line.endpoints[0]->node, Line.endpoints[1]->node, 0, &Chord, &direction1, &(T.NormalVector), Umkreismittelpunkt, Opt_Candidate, Storage, RADIUS, mol); 2079 Find_next_suitable_point_via_Angle_of_Sphere(Line.endpoints[0]->node, Line.endpoints[1]->node, OldThirdPoint, Line.endpoints[1]->node, Line.endpoints[0]->node, 0, &Chord, &direction1, &(T.NormalVector), Umkreismittelpunkt, Opt_Candidate, Storage, RADIUS, mol); 2080 if (Opt_Candidate == NULL) { 2081 cerr << "WARNING: Could not find a suitable candidate." << endl; 2082 return false; 2083 } 2084 cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << endl; 2085 2086 // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2) 2087 bool flag = CheckPresenceOfTriangle(out, Opt_Candidate, Line.endpoints[0]->node, Line.endpoints[1]->node); 2088 2089 if (flag) { // if so, add 2090 AddTrianglePoint(Opt_Candidate, 0); 2091 AddTrianglePoint(Line.endpoints[0]->node, 1); 2092 AddTrianglePoint(Line.endpoints[1]->node, 2); 2093 2094 AddTriangleLine(TPS[0], TPS[1], 0); 2095 AddTriangleLine(TPS[0], TPS[2], 1); 2096 AddTriangleLine(TPS[1], TPS[2], 2); 2097 2098 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 2099 AddTriangleToLines(); 2100 2101 BTS->GetNormalVector(BTS->NormalVector); 2102 2103 if ((BTS->NormalVector.ScalarProduct(&(T.NormalVector)) < 0 && Storage[0] > 0) || (BTS->NormalVector.ScalarProduct(&(T.NormalVector)) > 0 && Storage[0] < 0) || (fabs(Storage[0]) < MYEPSILON && Storage[1]*BTS->NormalVector.ScalarProduct(&direction1) < 0) ) { 2104 BTS->NormalVector.Scale(-1); 2105 }; 2106 cout << Verbose(1) << "New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl; 2107 cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl; 2108 } else { // else, yell and do nothing 2109 cout << Verbose(1) << "This triangle consisting of "; 2110 cout << *Opt_Candidate << ", "; 2111 cout << *Line.endpoints[0]->node << " and "; 2112 cout << *Line.endpoints[1]->node << " "; 2113 cout << "is invalid!" << endl; 2114 return false; 2115 } 2116 2117 if ((TrianglesOnBoundaryCount % 10) == 0) { 2118 sprintf(NumberName, "-%d", TriangleFilesWritten); 2119 if (DoTecplotOutput) { 2120 string NameofTempFile(tempbasename); 2121 NameofTempFile.append(NumberName); 2122 NameofTempFile.append(TecplotSuffix); 2123 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2124 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2125 write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten); 2126 tempstream->close(); 2127 tempstream->flush(); 2128 delete(tempstream); 2129 } 2130 2131 if (DoRaster3DOutput) { 2132 string NameofTempFile(tempbasename); 2133 NameofTempFile.append(NumberName); 2134 NameofTempFile.append(Raster3DSuffix); 2135 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2136 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2137 write_raster3d_file(out, tempstream, this, mol); 2138 tempstream->close(); 2139 tempstream->flush(); 2140 delete(tempstream); 2141 } 2142 if (DoTecplotOutput || DoRaster3DOutput) 2143 TriangleFilesWritten++; 2144 } 2145 2146 cout << Verbose(1) << "End of Find_next_suitable_triangle\n"; 2147 return true; 2321 if (ThirdNode != NULL) 2322 cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl; 2323 else 2324 cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl; 2325 } 2326 2327 2328 cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl; 2148 2329 }; 2149 2330 … … 2194 2375 2195 2376 2196 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, atom* Parent, 2197 int RecursionLevel, Vector Oben, atom*& Opt_Candidate, double Storage[3], 2198 molecule* mol, double RADIUS) 2199 { 2200 cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation, recursive level " << RecursionLevel << endl; 2201 int i; 2377 /** Finds the second point of starting triangle. 2378 * \param *a first atom 2379 * \param *Candidate pointer to candidate atom on return 2380 * \param Oben vector indicating the outside 2381 * \param Opt_Candidate reference to recommended candidate on return 2382 * \param Storage[3] array storing angles and other candidate information 2383 * \param RADIUS radius of virtual sphere 2384 * \param *LC LinkedCell structure with neighbouring atoms 2385 */ 2386 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, Vector Oben, atom*& Opt_Candidate, double Storage[3], double RADIUS, LinkedCell *LC) 2387 { 2388 cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl; 2202 2389 Vector AngleCheck; 2203 atom* Walker;2204 2390 double norm = -1., angle; 2205 2206 // check if we only have one unique point yet ... 2207 if (a != Candidate) { 2208 cout << Verbose(3) << "Current candidate is " << *Candidate << ": "; 2209 AngleCheck.CopyVector(&(Candidate->x)); 2210 AngleCheck.SubtractVector(&(a->x)); 2211 norm = AngleCheck.Norm(); 2212 // second point shall have smallest angle with respect to Oben vector 2213 if (norm < RADIUS) { 2214 angle = AngleCheck.Angle(&Oben); 2215 if (angle < Storage[0]) { 2216 //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]); 2217 cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n"; 2218 Opt_Candidate = Candidate; 2219 Storage[0] = AngleCheck.Angle(&Oben); 2220 //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]); 2221 } else { 2222 cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl; 2391 LinkedAtoms *List = NULL; 2392 int N[NDIM], Nlower[NDIM], Nupper[NDIM]; 2393 2394 if (LC->SetIndexToAtom(a)) { // get cell for the starting atom 2395 for(int i=0;i<NDIM;i++) // store indices of this cell 2396 N[i] = LC->n[i]; 2397 } else { 2398 cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl; 2399 return; 2400 } 2401 // then go through the current and all neighbouring cells and check the contained atoms for possible candidates 2402 cout << Verbose(2) << "LC Intervals:"; 2403 for (int i=0;i<NDIM;i++) { 2404 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0; 2405 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1; 2406 cout << " [" << Nlower[i] << "," << Nupper[i] << "] "; 2407 } 2408 cout << endl; 2409 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 2410 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 2411 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 2412 List = LC->GetCurrentCell(); 2413 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 2414 if (List != NULL) { 2415 for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 2416 Candidate = (*Runner); 2417 // check if we only have one unique point yet ... 2418 if (a != Candidate) { 2419 cout << Verbose(3) << "Current candidate is " << *Candidate << ": "; 2420 AngleCheck.CopyVector(&(Candidate->x)); 2421 AngleCheck.SubtractVector(&(a->x)); 2422 norm = AngleCheck.Norm(); 2423 // second point shall have smallest angle with respect to Oben vector 2424 if (norm < RADIUS) { 2425 angle = AngleCheck.Angle(&Oben); 2426 if (angle < Storage[0]) { 2427 //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]); 2428 cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n"; 2429 Opt_Candidate = Candidate; 2430 Storage[0] = AngleCheck.Angle(&Oben); 2431 //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]); 2432 } else { 2433 cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl; 2434 } 2435 } else { 2436 cout << "Refused due to Radius " << norm << endl; 2437 } 2438 } 2439 } 2440 } 2223 2441 } 2224 } else { 2225 cout << "Refused due to Radius " << norm << endl; 2226 } 2227 } 2228 2229 // if not recursed to deeply, look at all its bonds 2230 if (RecursionLevel < 7) { 2231 for (i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { 2232 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate); 2233 if (Walker == Parent) // don't go back along the bond we came from 2234 continue; 2235 else 2236 Find_second_point_for_Tesselation(a, Walker, Candidate, RecursionLevel + 1, Oben, Opt_Candidate, Storage, mol, RADIUS); 2237 } 2238 } 2239 cout << Verbose(2) << "End of Find_second_point_for_Tesselation, recursive level " << RecursionLevel << endl; 2442 cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl; 2240 2443 }; 2241 2444 2242 void Tesselation::Find_starting_triangle(molecule* mol, const double RADIUS) 2445 /** Finds the starting triangle for find_non_convex_border(). 2446 * Looks at the outermost atom per axis, then Find_second_point_for_Tesselation() 2447 * for the second and Find_next_suitable_point_via_Angle_of_Sphere() for the third 2448 * point are called. 2449 * \param RADIUS radius of virtual rolling sphere 2450 * \param *LC LinkedCell structure with neighbouring atoms 2451 */ 2452 void Tesselation::Find_starting_triangle(ofstream *out, molecule *mol, const double RADIUS, LinkedCell *LC) 2243 2453 { 2244 2454 cout << Verbose(1) << "Begin of Find_starting_triangle\n"; 2245 2455 int i = 0; 2246 atom* Walker;2456 LinkedAtoms *List = NULL; 2247 2457 atom* FirstPoint; 2248 2458 atom* SecondPoint; 2249 atom* max_index[NDIM];2459 atom* MaxAtom[NDIM]; 2250 2460 double max_coordinate[NDIM]; 2251 2461 Vector Oben; 2252 2462 Vector helper; 2253 2463 Vector Chord; 2254 Vector CenterOfFirstLine; 2464 Vector SearchDirection; 2465 Vector OptCandidateCenter; 2255 2466 2256 2467 Oben.Zero(); 2257 2468 2258 2469 for (i = 0; i < 3; i++) { 2259 max_index[i] = NULL;2470 MaxAtom[i] = NULL; 2260 2471 max_coordinate[i] = -1; 2261 2472 } 2262 cout << Verbose(2) << "Molecule mol is there and has " << mol->AtomCount << " Atoms \n";2263 2473 2264 2474 // 1. searching topmost atom with respect to each axis 2265 Walker = mol->start; 2266 while (Walker->next != mol->end) { 2267 Walker = Walker->next; 2268 for (i = 0; i < 3; i++) { 2269 if (Walker->x.x[i] > max_coordinate[i]) { 2270 max_coordinate[i] = Walker->x.x[i]; 2271 max_index[i] = Walker; 2475 for (int i=0;i<NDIM;i++) { // each axis 2476 LC->n[i] = LC->N[i]-1; // current axis is topmost cell 2477 for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++) 2478 for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) { 2479 List = LC->GetCurrentCell(); 2480 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 2481 if (List != NULL) { 2482 for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) { 2483 cout << Verbose(2) << "Current atom is " << *(*Runner) << "." << endl; 2484 if ((*Runner)->x.x[i] > max_coordinate[i]) { 2485 max_coordinate[i] = (*Runner)->x.x[i]; 2486 MaxAtom[i] = (*Runner); 2487 } 2488 } 2489 } else { 2490 cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl; 2491 } 2272 2492 } 2273 }2274 2493 } 2275 2494 2276 2495 cout << Verbose(2) << "Found maximum coordinates: "; 2277 2496 for (int i=0;i<NDIM;i++) 2278 cout << i << ": " << * max_index[i] << "\t";2497 cout << i << ": " << *MaxAtom[i] << "\t"; 2279 2498 cout << endl; 2280 //Koennen dies fuer alle Richtungen, legen hier erstmal Richtung auf k=0 2281 const int k = 1; 2499 const int k = 1; // arbitrary choice 2282 2500 Oben.x[k] = 1.; 2283 FirstPoint = max_index[k]; 2284 2285 cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << " with " << mol->NumberOfBondsPerAtom[FirstPoint->nr] << " bonds." << endl; 2286 double Storage[3]; 2501 FirstPoint = MaxAtom[k]; 2502 cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl; 2503 2504 // add first point 2505 AddTrianglePoint(FirstPoint, 0); 2506 2507 double ShortestAngle; 2287 2508 atom* Opt_Candidate = NULL; 2288 Storage[0] = 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. 2289 Storage[1] = 999999.; // This will be an angle looking for the third point. 2290 Storage[2] = 999999.; 2291 2292 Find_second_point_for_Tesselation(FirstPoint, FirstPoint, FirstPoint, 0, Oben, Opt_Candidate, Storage, mol, RADIUS); // we give same point as next candidate as its bonds are looked into in find_second_... 2509 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. 2510 2511 Find_second_point_for_Tesselation(FirstPoint, NULL, Oben, Opt_Candidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_... 2293 2512 SecondPoint = Opt_Candidate; 2294 2513 cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n"; 2514 2515 // add second point and first baseline 2516 AddTrianglePoint(SecondPoint, 1); 2517 AddTriangleLine(TPS[0], TPS[1], 0); 2295 2518 2296 2519 helper.CopyVector(&(FirstPoint->x)); … … 2300 2523 Oben.Normalize(); 2301 2524 helper.VectorProduct(&Oben); 2302 Storage[0] = -2.; // This will indicate the quadrant. 2303 Storage[1] = 9999999.; // This will be an angle looking for the third point. 2304 Storage[2] = 9999999.; 2525 ShortestAngle = 2.*M_PI; // This will indicate the quadrant. 2305 2526 2306 2527 Chord.CopyVector(&(FirstPoint->x)); // bring into calling function 2307 2528 Chord.SubtractVector(&(SecondPoint->x)); 2529 double radius = Chord.ScalarProduct(&Chord); 2530 double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.); 2531 helper.CopyVector(&Oben); 2532 helper.Scale(CircleRadius); 2308 2533 // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized) 2309 2534 … … 2311 2536 // look in one direction of baseline for initial candidate 2312 2537 Opt_Candidate = NULL; 2313 CenterOfFirstLine.CopyVector(&Chord); 2314 CenterOfFirstLine.Scale(0.5); 2315 CenterOfFirstLine.AddVector(&(SecondPoint->x)); 2316 2317 cout << Verbose(1) << "Looking for third point candidates from " << *FirstPoint << " onward ...\n"; 2318 Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, SecondPoint, FirstPoint, 0, &Chord, &helper, &Oben, CenterOfFirstLine, Opt_Candidate, Storage, RADIUS, mol); 2319 // look in other direction of baseline for possible better candidate 2320 cout << Verbose(1) << "Looking for third point candidates from " << *SecondPoint << " onward ...\n"; 2321 Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, FirstPoint, SecondPoint, 0, &Chord, &helper, &Oben, CenterOfFirstLine, Opt_Candidate, Storage, RADIUS, mol); 2538 SearchDirection.MakeNormalVector(&Chord, &Oben); // whether we look "left" first or "right" first is not important ... 2539 2540 cout << Verbose(1) << "Looking for third point candidates ...\n"; 2541 Find_third_point_for_Tesselation(Oben, SearchDirection, helper, BLS[0], NULL, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC); 2322 2542 cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl; 2323 2543 2544 // add third point 2545 AddTrianglePoint(Opt_Candidate, 2); 2546 2324 2547 // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate 2325 2548 2326 // Finally, we only have to add the found points 2327 AddTrianglePoint(FirstPoint, 0); 2328 AddTrianglePoint(SecondPoint, 1); 2329 AddTrianglePoint(Opt_Candidate, 2); 2330 // ... and respective lines 2331 AddTriangleLine(TPS[0], TPS[1], 0); 2549 // Finally, we only have to add the found further lines 2332 2550 AddTriangleLine(TPS[1], TPS[2], 1); 2333 2551 AddTriangleLine(TPS[0], TPS[2], 2); … … 2336 2554 AddTriangleToLines(); 2337 2555 // ... and calculate its normal vector (with correct orientation) 2338 Oben.Scale(-1.); 2339 BTS->GetNormalVector(Oben); 2556 OptCandidateCenter.Scale(-1.); 2557 cout << Verbose(2) << "Oben is currently " << OptCandidateCenter << "." << endl; 2558 BTS->GetNormalVector(OptCandidateCenter); 2340 2559 cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n"; 2560 cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl; 2341 2561 cout << Verbose(1) << "End of Find_starting_triangle\n"; 2342 2562 }; 2343 2563 2344 void Find_non_convex_border(ofstream *out, ofstream *tecplot, molecule* mol, const char *filename, const double RADIUS) 2564 /** This function finds a triangle to a line, adjacent to an existing one. 2565 * @param out output stream for debugging 2566 * @param *mol molecule with Atom's and Bond's 2567 * @param Line current baseline to search from 2568 * @param T current triangle which \a Line is edge of 2569 * @param RADIUS radius of the rolling ball 2570 * @param N number of found triangles 2571 * @param *filename filename base for intermediate envelopes 2572 * @param *LC LinkedCell structure with neighbouring atoms 2573 */ 2574 bool Tesselation::Find_next_suitable_triangle(ofstream *out, 2575 molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, 2576 const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC) 2577 { 2578 cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n"; 2579 ofstream *tempstream = NULL; 2580 char NumberName[255]; 2581 2582 atom* Opt_Candidate = NULL; 2583 Vector OptCandidateCenter; 2584 2585 Vector CircleCenter; 2586 Vector CirclePlaneNormal; 2587 Vector OldSphereCenter; 2588 Vector SearchDirection; 2589 Vector helper; 2590 atom *ThirdNode = NULL; 2591 double ShortestAngle = 2.*M_PI; // This will indicate the quadrant. 2592 double radius, CircleRadius; 2593 2594 cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl; 2595 for (int i=0;i<3;i++) 2596 if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node)) 2597 ThirdNode = T.endpoints[i]->node; 2598 2599 // construct center of circle 2600 CircleCenter.CopyVector(&Line.endpoints[0]->node->x); 2601 CircleCenter.AddVector(&Line.endpoints[1]->node->x); 2602 CircleCenter.Scale(0.5); 2603 2604 // construct normal vector of circle 2605 CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x); 2606 CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x); 2607 2608 // calculate squared radius of circle 2609 radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal); 2610 if (radius/4. < RADIUS*RADIUS) { 2611 CircleRadius = RADIUS*RADIUS - radius/4.; 2612 CirclePlaneNormal.Normalize(); 2613 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl; 2614 2615 // construct old center 2616 GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x)); 2617 helper.CopyVector(&T.NormalVector); // normal vector ensures that this is correct center of the two possible ones 2618 radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter); 2619 helper.Scale(sqrt(RADIUS*RADIUS - radius)); 2620 OldSphereCenter.AddVector(&helper); 2621 OldSphereCenter.SubtractVector(&CircleCenter); 2622 cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl; 2623 2624 // construct SearchDirection 2625 SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal); 2626 helper.CopyVector(&Line.endpoints[0]->node->x); 2627 helper.SubtractVector(&ThirdNode->x); 2628 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON) // ohoh, SearchDirection points inwards! 2629 SearchDirection.Scale(-1.); 2630 SearchDirection.ProjectOntoPlane(&OldSphereCenter); 2631 SearchDirection.Normalize(); 2632 cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl; 2633 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) { // rotated the wrong way! 2634 cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl; 2635 } 2636 2637 // add third point 2638 cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl; 2639 Find_third_point_for_Tesselation(T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC); 2640 2641 } else { 2642 cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl; 2643 } 2644 2645 if (Opt_Candidate == NULL) { 2646 cerr << "WARNING: Could not find a suitable candidate." << endl; 2647 return false; 2648 } 2649 cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << " with circumsphere's center at " << OptCandidateCenter << "." << endl; 2650 2651 // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2) 2652 bool flag = CheckPresenceOfTriangle(out, Opt_Candidate, Line.endpoints[0]->node, Line.endpoints[1]->node); 2653 2654 if (flag) { // if so, add 2655 AddTrianglePoint(Opt_Candidate, 0); 2656 AddTrianglePoint(Line.endpoints[0]->node, 1); 2657 AddTrianglePoint(Line.endpoints[1]->node, 2); 2658 2659 AddTriangleLine(TPS[0], TPS[1], 0); 2660 AddTriangleLine(TPS[0], TPS[2], 1); 2661 AddTriangleLine(TPS[1], TPS[2], 2); 2662 2663 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 2664 AddTriangleToLines(); 2665 2666 OptCandidateCenter.Scale(-1.); 2667 BTS->GetNormalVector(OptCandidateCenter); 2668 OptCandidateCenter.Scale(-1.); 2669 2670 cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl; 2671 cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl; 2672 } else { // else, yell and do nothing 2673 cout << Verbose(1) << "This triangle consisting of "; 2674 cout << *Opt_Candidate << ", "; 2675 cout << *Line.endpoints[0]->node << " and "; 2676 cout << *Line.endpoints[1]->node << " "; 2677 cout << "is invalid!" << endl; 2678 return false; 2679 } 2680 2681 if (flag && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 10 == 0))) { // if we have a new triangle and want to output each new triangle configuration 2682 sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name); 2683 if (DoTecplotOutput) { 2684 string NameofTempFile(tempbasename); 2685 NameofTempFile.append(NumberName); 2686 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 2687 NameofTempFile.erase(npos, 1); 2688 NameofTempFile.append(TecplotSuffix); 2689 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2690 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2691 write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten); 2692 tempstream->close(); 2693 tempstream->flush(); 2694 delete(tempstream); 2695 } 2696 2697 if (DoRaster3DOutput) { 2698 string NameofTempFile(tempbasename); 2699 NameofTempFile.append(NumberName); 2700 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 2701 NameofTempFile.erase(npos, 1); 2702 NameofTempFile.append(Raster3DSuffix); 2703 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2704 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2705 write_raster3d_file(out, tempstream, this, mol); 2706 // include the current position of the virtual sphere in the temporary raster3d file 2707 // make the circumsphere's center absolute again 2708 helper.CopyVector(&Line.endpoints[0]->node->x); 2709 helper.AddVector(&Line.endpoints[1]->node->x); 2710 helper.Scale(0.5); 2711 OptCandidateCenter.AddVector(&helper); 2712 Vector *center = mol->DetermineCenterOfAll(out); 2713 OptCandidateCenter.AddVector(center); 2714 delete(center); 2715 // and add to file plus translucency object 2716 *tempstream << "# current virtual sphere\n"; 2717 *tempstream << "8\n 25.0 0.6 -1.0 -1.0 -1.0 0.2 0 0 0 0\n"; 2718 *tempstream << "2\n " << OptCandidateCenter.x[0] << " " << OptCandidateCenter.x[1] << " " << OptCandidateCenter.x[2] << "\t" << RADIUS << "\t1 0 0\n"; 2719 *tempstream << "9\n terminating special property\n"; 2720 tempstream->close(); 2721 tempstream->flush(); 2722 delete(tempstream); 2723 } 2724 if (DoTecplotOutput || DoRaster3DOutput) 2725 TriangleFilesWritten++; 2726 } 2727 2728 cout << Verbose(1) << "End of Find_next_suitable_triangle\n"; 2729 return true; 2730 }; 2731 2732 /** Tesselates the non convex boundary by rolling a virtual sphere along the surface of the molecule. 2733 * \param *out output stream for debugging 2734 * \param *mol molecule structure with Atom's and Bond's 2735 * \param *Tess Tesselation filled with points, lines and triangles on boundary on return 2736 * \param *LCList linked cell list of all atoms 2737 * \param *filename filename prefix for output of vertex data 2738 * \para RADIUS radius of the virtual sphere 2739 */ 2740 void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *Tess, class LinkedCell *LCList, const char *filename, const double RADIUS) 2345 2741 { 2346 2742 int N = 0; 2347 struct Tesselation *Tess = new Tesselation; 2348 cout << Verbose(1) << "Entering search for non convex hull. " << endl; 2349 cout << flush; 2743 bool freeTess = false; 2744 *out << Verbose(1) << "Entering search for non convex hull. " << endl; 2745 if (Tess == NULL) { 2746 *out << Verbose(1) << "Allocating Tesselation struct ..." << endl; 2747 Tess = new Tesselation; 2748 freeTess = true; 2749 } 2750 bool freeLC = false; 2350 2751 LineMap::iterator baseline; 2351 cout << Verbose(0) << "Begin of Find_non_convex_border\n";2752 *out << Verbose(0) << "Begin of Find_non_convex_border\n"; 2352 2753 bool flag = false; // marks whether we went once through all baselines without finding any without two triangles 2353 2754 bool failflag = false; 2354 if ((mol->first->next == mol->last) || (mol->last->previous == mol->first)) 2355 mol->CreateAdjacencyList((ofstream *)&cout, 1.6, true); 2356 2357 Tess->Find_starting_triangle(mol, RADIUS); 2755 2756 if (LCList == NULL) { 2757 LCList = new LinkedCell(mol, 2.*RADIUS); 2758 freeLC = true; 2759 } 2760 2761 Tess->Find_starting_triangle(out, mol, RADIUS, LCList); 2358 2762 2359 2763 baseline = Tess->LinesOnBoundary.begin(); 2360 2764 while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) { 2361 2765 if (baseline->second->TrianglesCount == 1) { 2362 failflag = Tess->Find_next_suitable_triangle(out, tecplot, mol, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename); //the line is there, so there is a triangle, but only one.2766 failflag = Tess->Find_next_suitable_triangle(out, mol, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename, LCList); //the line is there, so there is a triangle, but only one. 2363 2767 flag = flag || failflag; 2364 2768 if (!failflag) … … 2374 2778 } 2375 2779 } 2376 if (failflag) { 2377 cout << Verbose(1) << "Writing final tecplot file\n"; 2378 if (DoTecplotOutput) 2780 if (1) { //failflag) { 2781 *out << Verbose(1) << "Writing final tecplot file\n"; 2782 if (DoTecplotOutput) { 2783 string OutputName(filename); 2784 OutputName.append(TecplotSuffix); 2785 ofstream *tecplot = new ofstream(OutputName.c_str()); 2379 2786 write_tecplot_file(out, tecplot, Tess, mol, -1); 2380 if (DoRaster3DOutput) 2381 write_raster3d_file(out, tecplot, Tess, mol); 2787 tecplot->close(); 2788 delete(tecplot); 2789 } 2790 if (DoRaster3DOutput) { 2791 string OutputName(filename); 2792 OutputName.append(Raster3DSuffix); 2793 ofstream *raster = new ofstream(OutputName.c_str()); 2794 write_raster3d_file(out, raster, Tess, mol); 2795 raster->close(); 2796 delete(raster); 2797 } 2382 2798 } else { 2383 2799 cerr << "ERROR: Could definately not find all necessary triangles!" << endl; 2384 2800 } 2385 2386 cout << Verbose(0) << "End of Find_non_convex_border\n"; 2387 delete(Tess); 2801 if (freeTess) 2802 delete(Tess); 2803 if (freeLC) 2804 delete(LCList); 2805 *out << Verbose(0) << "End of Find_non_convex_border\n"; 2388 2806 }; 2389 2807 2808 /** Finds a hole of sufficient size in \a this molecule to embed \a *srcmol into it. 2809 * \param *out output stream for debugging 2810 * \param *srcmol molecule to embed into 2811 * \return *Vector new center of \a *srcmol for embedding relative to \a this 2812 */ 2813 Vector* molecule::FindEmbeddingHole(ofstream *out, molecule *srcmol) 2814 { 2815 Vector *Center = new Vector; 2816 Center->Zero(); 2817 // calculate volume/shape of \a *srcmol 2818 2819 // find embedding holes 2820 2821 // if more than one, let user choose 2822 2823 // return embedding center 2824 return Center; 2825 }; 2826 -
src/boundary.hpp
rce5ac3 rd067d45 17 17 18 18 #include <gsl/gsl_poly.h> 19 #include <gsl/gsl_matrix.h> 20 #include <gsl/gsl_linalg.h> 21 #include <gsl/gsl_multimin.h> 22 #include <gsl/gsl_permutation.h> 19 23 24 #include "linkedcell.hpp" 20 25 #include "molecules.hpp" 21 26 … … 85 90 void AddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n); 86 91 void AddTriangleToLines(); 87 void Find_starting_triangle( molecule* mol, const double RADIUS);88 bool Find_next_suitable_triangle(ofstream *out, ofstream *tecplot, molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, const char *filename);92 void Find_starting_triangle(ofstream *out, molecule* mol, const double RADIUS, LinkedCell *LC); 93 bool Find_next_suitable_triangle(ofstream *out, molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, const char *filename, LinkedCell *LC); 89 94 bool CheckPresenceOfTriangle(ofstream *out, atom *a, atom *b, atom *c); 90 95 void Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent, int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint, atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol); … … 109 114 110 115 111 double VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, Boundaries *BoundaryPoints, molecule *mol);116 double VolumeOfConvexEnvelope(ofstream *out, const char *filename, config *configuration, Boundaries *BoundaryPoints, molecule *mol); 112 117 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem); 113 118 void PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, double ClusterVolume, double celldensity); 114 void Find_non_convex_border(ofstream *out, ofstream *tecplot, molecule* mol, const char *tempbasename, const double RADIUS); 115 void Find_next_suitable_point(atom a, atom b, atom Candidate, int n, Vector *d1, Vector *d2, atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule *mol, bool problem); 116 119 void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *T, class LinkedCell *LCList, const char *tempbasename, const double RADIUS); 120 void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC); 117 121 118 122 #endif /*BOUNDARY_HPP_*/ -
src/builder.cpp
rce5ac3 rd067d45 50 50 using namespace std; 51 51 52 #include "boundary.hpp" 53 #include "ellipsoid.hpp" 52 54 #include "helpers.hpp" 53 55 #include "molecules.hpp" 54 #include "boundary.hpp" 55 56 /********************************************** Submenu routine **************************************/ 56 57 /********************************************* Subsubmenu routine ************************************/ 57 58 58 59 /** Submenu for adding atoms to the molecule. 59 60 * \param *periode periodentafel 60 * \param *mol the molecule to add to61 * \param *molecule molecules with atoms 61 62 */ 62 63 static void AddAtoms(periodentafel *periode, molecule *mol) … … 82 83 83 84 switch (choice) { 85 default: 86 cout << Verbose(0) << "Not a valid choice." << endl; 87 break; 84 88 case 'a': // absolute coordinates of atom 85 89 cout << Verbose(0) << "Enter absolute coordinates." << endl; … … 122 126 break; 123 127 124 case 'd': // two atoms, two angles and a distance128 case 'd': // two atoms, two angles and a distance 125 129 first = new atom; 126 130 valid = true; … … 255 259 256 260 /** Submenu for centering the atoms in the molecule. 257 * \param *mol themolecule with all the atoms261 * \param *mol molecule with all the atoms 258 262 */ 259 263 static void CenterAtoms(molecule *mol) … … 278 282 case 'a': 279 283 cout << Verbose(0) << "Centering atoms in config file on origin." << endl; 280 mol->CenterOrigin((ofstream *)&cout , &x);284 mol->CenterOrigin((ofstream *)&cout); 281 285 break; 282 286 case 'b': 283 287 cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl; 284 mol->Center Gravity((ofstream *)&cout, &x);288 mol->CenterPeriodic((ofstream *)&cout); 285 289 break; 286 290 case 'c': … … 291 295 } 292 296 mol->CenterEdge((ofstream *)&cout, &x); // make every coordinate positive 293 mol-> Translate(&y); // translate by boundary297 mol->Center.AddVector(&y); // translate by boundary 294 298 helper.CopyVector(&y); 295 299 helper.Scale(2.); … … 313 317 /** Submenu for aligning the atoms in the molecule. 314 318 * \param *periode periodentafel 315 * \param *mol themolecule with all the atoms319 * \param *mol molecule with all the atoms 316 320 */ 317 321 static void AlignAtoms(periodentafel *periode, molecule *mol) … … 381 385 382 386 /** Submenu for mirroring the atoms in the molecule. 383 * \param *mol themolecule with all the atoms387 * \param *mol molecule with all the atoms 384 388 */ 385 389 static void MirrorAtoms(molecule *mol) … … 428 432 429 433 /** Submenu for removing the atoms from the molecule. 430 * \param *mol themolecule with all the atoms434 * \param *mol molecule with all the atoms 431 435 */ 432 436 static void RemoveAtoms(molecule *mol) … … 461 465 while(first->next != mol->end) { 462 466 first = first->next; 463 if (first->x.Distance ((const Vector *)&second->x) > tmp1*tmp1) // distance to first above radius ...467 if (first->x.DistanceSquared((const Vector *)&second->x) > tmp1*tmp1) // distance to first above radius ... 464 468 mol->RemoveAtom(first); 465 469 } … … 486 490 /** Submenu for measuring out the atoms in the molecule. 487 491 * \param *periode periodentafel 488 * \param *mol themolecule with all the atoms492 * \param *mol molecule with all the atoms 489 493 */ 490 494 static void MeasureAtoms(periodentafel *periode, molecule *mol, config *configuration) … … 596 600 597 601 /** Submenu for measuring out the atoms in the molecule. 598 * \param *mol themolecule with all the atoms602 * \param *mol molecule with all the atoms 599 603 * \param *configuration configuration structure for the to be written config files of all fragments 600 604 */ … … 616 620 }; 617 621 622 /********************************************** Submenu routine **************************************/ 623 624 /** Submenu for manipulating atoms. 625 * \param *periode periodentafel 626 * \param *molecules list of molecules whose atoms are to be manipulated 627 */ 628 static void ManipulateAtoms(periodentafel *periode, MoleculeListClass *molecules, config *configuration) 629 { 630 atom *first, *second; 631 molecule *mol = NULL; 632 Vector x,y,z,n; // coordinates for absolute point in cell volume 633 double *factor; // unit factor if desired 634 double bond, min_bond; 635 char choice; // menu choice char 636 bool valid; 637 638 cout << Verbose(0) << "=========MANIPULATE ATOMS======================" << endl; 639 cout << Verbose(0) << "a - add an atom" << endl; 640 cout << Verbose(0) << "r - remove an atom" << endl; 641 cout << Verbose(0) << "b - scale a bond between atoms" << endl; 642 cout << Verbose(0) << "u - change an atoms element" << endl; 643 cout << Verbose(0) << "l - measure lengths, angles, ... for an atom" << endl; 644 cout << Verbose(0) << "all else - go back" << endl; 645 cout << Verbose(0) << "===============================================" << endl; 646 if (molecules->NumberOfActiveMolecules() > 1) 647 cout << Verbose(0) << "WARNING: There is more than one molecule active! Atoms will be added to each." << endl; 648 cout << Verbose(0) << "INPUT: "; 649 cin >> choice; 650 651 switch (choice) { 652 default: 653 cout << Verbose(0) << "Not a valid choice." << endl; 654 break; 655 656 case 'a': // add atom 657 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 658 if ((*ListRunner)->ActiveFlag) { 659 mol = *ListRunner; 660 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; 661 AddAtoms(periode, mol); 662 } 663 break; 664 665 case 'b': // scale a bond 666 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 667 if ((*ListRunner)->ActiveFlag) { 668 mol = *ListRunner; 669 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; 670 cout << Verbose(0) << "Scaling bond length between two atoms." << endl; 671 first = mol->AskAtom("Enter first (fixed) atom: "); 672 second = mol->AskAtom("Enter second (shifting) atom: "); 673 min_bond = 0.; 674 for (int i=NDIM;i--;) 675 min_bond += (first->x.x[i]-second->x.x[i])*(first->x.x[i] - second->x.x[i]); 676 min_bond = sqrt(min_bond); 677 cout << Verbose(0) << "Current Bond length between " << first->type->name << " Atom " << first->nr << " and " << second->type->name << " Atom " << second->nr << ": " << min_bond << " a.u." << endl; 678 cout << Verbose(0) << "Enter new bond length [a.u.]: "; 679 cin >> bond; 680 for (int i=NDIM;i--;) { 681 second->x.x[i] -= (second->x.x[i]-first->x.x[i])/min_bond*(min_bond-bond); 682 } 683 //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: "; 684 //second->Output(second->type->No, 1, (ofstream *)&cout); 685 } 686 break; 687 688 case 'c': // unit scaling of the metric 689 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 690 if ((*ListRunner)->ActiveFlag) { 691 mol = *ListRunner; 692 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; 693 cout << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl; 694 cout << Verbose(0) << "Enter three factors: "; 695 factor = new double[NDIM]; 696 cin >> factor[0]; 697 cin >> factor[1]; 698 cin >> factor[2]; 699 valid = true; 700 mol->Scale(&factor); 701 delete[](factor); 702 } 703 break; 704 705 case 'l': // measure distances or angles 706 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 707 if ((*ListRunner)->ActiveFlag) { 708 mol = *ListRunner; 709 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; 710 MeasureAtoms(periode, mol, configuration); 711 } 712 break; 713 714 case 'r': // remove atom 715 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 716 if ((*ListRunner)->ActiveFlag) { 717 mol = *ListRunner; 718 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; 719 RemoveAtoms(mol); 720 } 721 break; 722 723 case 'u': // change an atom's element 724 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 725 if ((*ListRunner)->ActiveFlag) { 726 int Z; 727 mol = *ListRunner; 728 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; 729 first = NULL; 730 do { 731 cout << Verbose(0) << "Change the element of which atom: "; 732 cin >> Z; 733 } while ((first = mol->FindAtom(Z)) == NULL); 734 cout << Verbose(0) << "New element by atomic number Z: "; 735 cin >> Z; 736 first->type = periode->FindElement(Z); 737 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl; 738 } 739 break; 740 } 741 }; 742 743 /** Submenu for manipulating molecules. 744 * \param *periode periodentafel 745 * \param *molecules list of molecule to manipulate 746 */ 747 static void ManipulateMolecules(periodentafel *periode, MoleculeListClass *molecules, config *configuration) 748 { 749 atom *first; 750 Vector x,y,z,n; // coordinates for absolute point in cell volume 751 int j, axis, count, faktor; 752 char choice; // menu choice char 753 molecule *mol = NULL; 754 element **Elements; 755 Vector **vectors; 756 MoleculeLeafClass *Subgraphs = NULL; 757 758 cout << Verbose(0) << "=========MANIPULATE GLOBALLY===================" << endl; 759 cout << Verbose(0) << "c - scale by unit transformation" << endl; 760 cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl; 761 cout << Verbose(0) << "f - fragment molecule many-body bond order style" << endl; 762 cout << Verbose(0) << "g - center atoms in box" << endl; 763 cout << Verbose(0) << "i - realign molecule" << endl; 764 cout << Verbose(0) << "m - mirror all molecules" << endl; 765 cout << Verbose(0) << "o - create connection matrix" << endl; 766 cout << Verbose(0) << "t - translate molecule by vector" << endl; 767 cout << Verbose(0) << "all else - go back" << endl; 768 cout << Verbose(0) << "===============================================" << endl; 769 if (molecules->NumberOfActiveMolecules() > 1) 770 cout << Verbose(0) << "WARNING: There is more than one molecule active! Atoms will be added to each." << endl; 771 cout << Verbose(0) << "INPUT: "; 772 cin >> choice; 773 774 switch (choice) { 775 default: 776 cout << Verbose(0) << "Not a valid choice." << endl; 777 break; 778 779 case 'd': // duplicate the periodic cell along a given axis, given times 780 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 781 if ((*ListRunner)->ActiveFlag) { 782 mol = *ListRunner; 783 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; 784 cout << Verbose(0) << "State the axis [(+-)123]: "; 785 cin >> axis; 786 cout << Verbose(0) << "State the factor: "; 787 cin >> faktor; 788 789 mol->CountAtoms((ofstream *)&cout); // recount atoms 790 if (mol->AtomCount != 0) { // if there is more than none 791 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand 792 Elements = new element *[count]; 793 vectors = new Vector *[count]; 794 j = 0; 795 first = mol->start; 796 while (first->next != mol->end) { // make a list of all atoms with coordinates and element 797 first = first->next; 798 Elements[j] = first->type; 799 vectors[j] = &first->x; 800 j++; 801 } 802 if (count != j) 803 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl; 804 x.Zero(); 805 y.Zero(); 806 y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude 807 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times 808 x.AddVector(&y); // per factor one cell width further 809 for (int k=count;k--;) { // go through every atom of the original cell 810 first = new atom(); // create a new body 811 first->x.CopyVector(vectors[k]); // use coordinate of original atom 812 first->x.AddVector(&x); // translate the coordinates 813 first->type = Elements[k]; // insert original element 814 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...) 815 } 816 } 817 if (mol->first->next != mol->last) // if connect matrix is present already, redo it 818 mol->CreateAdjacencyList((ofstream *)&cout, mol->BondDistance, configuration->GetIsAngstroem()); 819 // free memory 820 delete[](Elements); 821 delete[](vectors); 822 // correct cell size 823 if (axis < 0) { // if sign was negative, we have to translate everything 824 x.Zero(); 825 x.AddVector(&y); 826 x.Scale(-(faktor-1)); 827 mol->Translate(&x); 828 } 829 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 830 } 831 } 832 break; 833 834 case 'f': 835 FragmentAtoms(mol, configuration); 836 break; 837 838 case 'g': // center the atoms 839 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 840 if ((*ListRunner)->ActiveFlag) { 841 mol = *ListRunner; 842 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; 843 CenterAtoms(mol); 844 } 845 break; 846 847 case 'i': // align all atoms 848 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 849 if ((*ListRunner)->ActiveFlag) { 850 mol = *ListRunner; 851 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; 852 AlignAtoms(periode, mol); 853 } 854 break; 855 856 case 'm': // mirror atoms along a given axis 857 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 858 if ((*ListRunner)->ActiveFlag) { 859 mol = *ListRunner; 860 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; 861 MirrorAtoms(mol); 862 } 863 break; 864 865 case 'o': // create the connection matrix 866 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 867 if ((*ListRunner)->ActiveFlag) { 868 double bonddistance; 869 clock_t start,end; 870 cout << Verbose(0) << "What's the maximum bond distance: "; 871 cin >> bonddistance; 872 start = clock(); 873 mol->CreateAdjacencyList((ofstream *)&cout, bonddistance, configuration->GetIsAngstroem()); 874 mol->CreateListOfBondsPerAtom((ofstream *)&cout); 875 end = clock(); 876 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 877 } 878 break; 879 880 case 't': // translate all atoms 881 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 882 if ((*ListRunner)->ActiveFlag) { 883 mol = *ListRunner; 884 cout << Verbose(0) << "Current molecule is: " << mol->IndexNr << "\t" << mol->name << endl; 885 cout << Verbose(0) << "Enter translation vector." << endl; 886 x.AskPosition(mol->cell_size,0); 887 mol->Center.AddVector((const Vector *)&x); 888 } 889 break; 890 } 891 // Free all 892 if (Subgraphs != NULL) { // free disconnected subgraph list of DFS analysis was performed 893 while (Subgraphs->next != NULL) { 894 Subgraphs = Subgraphs->next; 895 delete(Subgraphs->previous); 896 } 897 delete(Subgraphs); 898 } 899 }; 900 901 902 /** Submenu for creating new molecules. 903 * \param *periode periodentafel 904 * \param *molecules list of molecules to add to 905 */ 906 static void EditMolecules(periodentafel *periode, MoleculeListClass *molecules) 907 { 908 char choice; // menu choice char 909 Vector center; 910 int nr, count; 911 molecule *mol = NULL; 912 913 cout << Verbose(0) << "==========EDIT MOLECULES=====================" << endl; 914 cout << Verbose(0) << "c - create new molecule" << endl; 915 cout << Verbose(0) << "l - load molecule from xyz file" << endl; 916 cout << Verbose(0) << "n - change molecule's name" << endl; 917 cout << Verbose(0) << "N - give molecules filename" << endl; 918 cout << Verbose(0) << "p - parse atoms in xyz file into molecule" << endl; 919 cout << Verbose(0) << "r - remove a molecule" << endl; 920 cout << Verbose(0) << "all else - go back" << endl; 921 cout << Verbose(0) << "===============================================" << endl; 922 cout << Verbose(0) << "INPUT: "; 923 cin >> choice; 924 925 switch (choice) { 926 default: 927 cout << Verbose(0) << "Not a valid choice." << endl; 928 break; 929 case 'c': 930 mol = new molecule(periode); 931 molecules->insert(mol); 932 break; 933 934 case 'l': // load from XYZ file 935 { 936 char filename[MAXSTRINGSIZE]; 937 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl; 938 mol = new molecule(periode); 939 do { 940 cout << Verbose(0) << "Enter file name: "; 941 cin >> filename; 942 } while (!mol->AddXYZFile(filename)); 943 mol->SetNameFromFilename(filename); 944 // center at set box dimensions 945 mol->CenterEdge((ofstream *)&cout, ¢er); 946 mol->cell_size[0] = center.x[0]; 947 mol->cell_size[1] = 0; 948 mol->cell_size[2] = center.x[1]; 949 mol->cell_size[3] = 0; 950 mol->cell_size[4] = 0; 951 mol->cell_size[5] = center.x[2]; 952 molecules->insert(mol); 953 } 954 break; 955 956 case 'n': 957 { 958 char filename[MAXSTRINGSIZE]; 959 do { 960 cout << Verbose(0) << "Enter index of molecule: "; 961 cin >> nr; 962 mol = molecules->ReturnIndex(nr); 963 } while (mol == NULL); 964 cout << Verbose(0) << "Enter name: "; 965 cin >> filename; 966 strcpy(mol->name, filename); 967 } 968 break; 969 970 case 'N': 971 { 972 char filename[MAXSTRINGSIZE]; 973 do { 974 cout << Verbose(0) << "Enter index of molecule: "; 975 cin >> nr; 976 mol = molecules->ReturnIndex(nr); 977 } while (mol == NULL); 978 cout << Verbose(0) << "Enter name: "; 979 cin >> filename; 980 mol->SetNameFromFilename(filename); 981 } 982 break; 983 984 case 'p': // parse XYZ file 985 { 986 char filename[MAXSTRINGSIZE]; 987 mol = NULL; 988 do { 989 cout << Verbose(0) << "Enter index of molecule: "; 990 cin >> nr; 991 mol = molecules->ReturnIndex(nr); 992 } while (mol == NULL); 993 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl; 994 do { 995 cout << Verbose(0) << "Enter file name: "; 996 cin >> filename; 997 } while (!mol->AddXYZFile(filename)); 998 mol->SetNameFromFilename(filename); 999 } 1000 break; 1001 1002 case 'r': 1003 cout << Verbose(0) << "Enter index of molecule: "; 1004 cin >> nr; 1005 count = 1; 1006 for( MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 1007 if (nr == (*ListRunner)->IndexNr) { 1008 mol = *ListRunner; 1009 molecules->ListOfMolecules.erase(ListRunner); 1010 delete(mol); 1011 } 1012 break; 1013 } 1014 }; 1015 1016 1017 /** Submenu for merging molecules. 1018 * \param *periode periodentafel 1019 * \param *molecules list of molecules to add to 1020 */ 1021 static void MergeMolecules(periodentafel *periode, MoleculeListClass *molecules) 1022 { 1023 char choice; // menu choice char 1024 1025 cout << Verbose(0) << "===========MERGE MOLECULES=====================" << endl; 1026 cout << Verbose(0) << "a - simple add of one molecule to another" << endl; 1027 cout << Verbose(0) << "e - embedding merge of two molecules" << endl; 1028 cout << Verbose(0) << "m - multi-merge of all molecules" << endl; 1029 cout << Verbose(0) << "s - scatter merge of two molecules" << endl; 1030 cout << Verbose(0) << "t - simple merge of two molecules" << endl; 1031 cout << Verbose(0) << "all else - go back" << endl; 1032 cout << Verbose(0) << "===============================================" << endl; 1033 cout << Verbose(0) << "INPUT: "; 1034 cin >> choice; 1035 1036 switch (choice) { 1037 default: 1038 cout << Verbose(0) << "Not a valid choice." << endl; 1039 break; 1040 1041 case 'a': 1042 { 1043 int src, dest; 1044 molecule *srcmol = NULL, *destmol = NULL; 1045 { 1046 do { 1047 cout << Verbose(0) << "Enter index of destination molecule: "; 1048 cin >> dest; 1049 destmol = molecules->ReturnIndex(dest); 1050 } while ((destmol == NULL) && (dest != -1)); 1051 do { 1052 cout << Verbose(0) << "Enter index of source molecule to add from: "; 1053 cin >> src; 1054 srcmol = molecules->ReturnIndex(src); 1055 } while ((srcmol == NULL) && (src != -1)); 1056 if ((src != -1) && (dest != -1)) 1057 molecules->SimpleAdd(srcmol, destmol); 1058 } 1059 } 1060 break; 1061 1062 case 'e': 1063 cout << Verbose(0) << "Not implemented yet." << endl; 1064 break; 1065 1066 case 'm': 1067 { 1068 int nr; 1069 molecule *mol = NULL; 1070 do { 1071 cout << Verbose(0) << "Enter index of molecule to merge into: "; 1072 cin >> nr; 1073 mol = molecules->ReturnIndex(nr); 1074 } while ((mol == NULL) && (nr != -1)); 1075 if (nr != -1) { 1076 int N = molecules->ListOfMolecules.size()-1; 1077 int *src = new int(N); 1078 for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 1079 if ((*ListRunner)->IndexNr != nr) 1080 src[N++] = (*ListRunner)->IndexNr; 1081 molecules->SimpleMultiMerge(mol, src, N); 1082 delete[](src); 1083 } 1084 } 1085 break; 1086 1087 case 's': 1088 cout << Verbose(0) << "Not implemented yet." << endl; 1089 break; 1090 1091 case 't': 1092 { 1093 int src, dest; 1094 molecule *srcmol = NULL, *destmol = NULL; 1095 { 1096 do { 1097 cout << Verbose(0) << "Enter index of destination molecule: "; 1098 cin >> dest; 1099 destmol = molecules->ReturnIndex(dest); 1100 } while ((destmol == NULL) && (dest != -1)); 1101 do { 1102 cout << Verbose(0) << "Enter index of source molecule to merge into: "; 1103 cin >> src; 1104 srcmol = molecules->ReturnIndex(src); 1105 } while ((srcmol == NULL) && (src != -1)); 1106 if ((src != -1) && (dest != -1)) 1107 molecules->SimpleMerge(srcmol, destmol); 1108 } 1109 } 1110 break; 1111 } 1112 }; 1113 1114 618 1115 /********************************************** Test routine **************************************/ 619 1116 620 1117 /** Is called always as option 'T' in the menu. 1118 * \param *molecules list of molecules 621 1119 */ 622 static void testroutine( molecule *mol)1120 static void testroutine(MoleculeListClass *molecules) 623 1121 { 624 1122 // the current test routine checks the functionality of the KeySet&Graph concept: 625 1123 // We want to have a multiindex (the KeySet) describing a unique subgraph 1124 int i, comp, counter=0; 1125 1126 // create a clone 1127 molecule *mol = NULL; 1128 if (molecules->ListOfMolecules.size() != 0) // clone 1129 mol = (molecules->ListOfMolecules.front())->CopyMolecule(); 1130 else { 1131 cerr << "I don't have anything to test on ... "; 1132 return; 1133 } 626 1134 atom *Walker = mol->start; 627 int i, comp, counter=0;628 1135 629 1136 // generate some KeySets … … 685 1192 A++; 686 1193 } 1194 delete(mol); 687 1195 }; 688 1196 … … 691 1199 * \param *configuration pointer to configuration structure with all the values 692 1200 * \param *periode pointer to periodentafel structure with all the elements 693 * \param *mol pointer to moleculestructure with all the atoms and coordinates1201 * \param *molecules list of molecules structure with all the atoms and coordinates 694 1202 */ 695 static void SaveConfig(char *ConfigFileName, config *configuration, periodentafel *periode, molecule *mol)1203 static void SaveConfig(char *ConfigFileName, config *configuration, periodentafel *periode, MoleculeListClass *molecules) 696 1204 { 697 1205 char filename[MAXSTRINGSIZE]; 698 1206 ofstream output; 699 string basis("3-21G"); 1207 molecule *mol = new molecule(periode); 1208 1209 // translate each to its center and merge all molecules in MoleculeListClass into this molecule 1210 int N = molecules->ListOfMolecules.size(); 1211 int *src = new int(N); 1212 N=0; 1213 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) { 1214 src[N++] = (*ListRunner)->IndexNr; 1215 (*ListRunner)->Translate(&(*ListRunner)->Center); 1216 } 1217 molecules->SimpleMultiAdd(mol, src, N); 1218 delete[](src); 1219 // ... and translate back 1220 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) { 1221 (*ListRunner)->Center.Scale(-1.); 1222 (*ListRunner)->Translate(&(*ListRunner)->Center); 1223 (*ListRunner)->Center.Scale(-1.); 1224 } 700 1225 701 1226 cout << Verbose(0) << "Storing configuration ... " << endl; … … 703 1228 mol->CalculateOrbitals(*configuration); 704 1229 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble; 705 strcpy(filename, ConfigFileName);706 1230 if (ConfigFileName != NULL) { // test the file name 707 output.open(ConfigFileName, ios::trunc); 1231 strcpy(filename, ConfigFileName); 1232 output.open(filename, ios::trunc); 708 1233 } else if (strlen(configuration->configname) != 0) { 709 1234 strcpy(filename, configuration->configname); … … 761 1286 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl; 762 1287 } 1288 delete(mol); 763 1289 }; 764 1290 … … 766 1292 * \param argc argument count 767 1293 * \param **argv arguments array 768 * \param *mol moleculestructure1294 * \param *molecules list of molecules structure 769 1295 * \param *periode elements structure 770 1296 * \param configuration config file structure … … 773 1299 * \return exit code (0 - successful, all else - something's wrong) 774 1300 */ 775 static int ParseCommandLineOptions(int argc, char **argv, molecule *&mol, periodentafel *&periode, config& configuration, char *&ConfigFileName, char *&PathToDatabases)1301 static int ParseCommandLineOptions(int argc, char **argv, MoleculeListClass *&molecules, periodentafel *&periode, config& configuration, char *ConfigFileName, char *&PathToDatabases) 776 1302 { 777 1303 Vector x,y,z,n; // coordinates for absolute point in cell volume … … 789 1315 int argptr; 790 1316 PathToDatabases = LocalPath; 1317 1318 // simply create a new molecule, wherein the config file is loaded and the manipulation takes place 1319 molecule *mol = new molecule(periode); 1320 mol->ActiveFlag = true; 1321 molecules->insert(mol); 791 1322 792 1323 if (argc > 1) { // config file specified as option … … 807 1338 cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl; 808 1339 cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl; 809 cout << "\t-B <basis>\t give gaussian basis for MPQC output." << endl;1340 cout << "\t-B <basis>\tSetting basis to store to MPQC config files." << endl; 810 1341 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl; 811 1342 cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl; … … 871 1402 return 1; 872 1403 } 873 874 1404 // 3. Find config file name and parse if possible 875 1405 if (argv[1][0] != '-') { … … 884 1414 } else { 885 1415 cout << "Empty configuration file." << endl; 886 ConfigFileName = argv[1];1416 strcpy(ConfigFileName, argv[1]); 887 1417 config_present = empty; 888 1418 output.close(); … … 890 1420 } else { 891 1421 test.close(); 892 ConfigFileName = argv[1];1422 strcpy(ConfigFileName, argv[1]); 893 1423 cout << Verbose(1) << "Specified config file found, parsing ... "; 894 1424 switch (configuration.TestSyntax(ConfigFileName, periode, mol)) { … … 910 1440 } else 911 1441 config_present = absent; 912 913 1442 // 4. parse again through options, now for those depending on elements db and config presence 914 1443 argptr = 1; … … 965 1494 switch(argv[argptr-1][1]) { 966 1495 case 'B': 967 if ((argptr >= argc) || ( !IsValidNumber(argv[argptr])) || (argv[argptr][0] == '-')) {1496 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 968 1497 ExitFlag = 255; 969 cerr << "Not enough or invalid arguments given for giving gaussian basis: -B <basis>" << endl;1498 cerr << "Not enough or invalid arguments given for setting MPQC basis: -B <basis name>" << endl; 970 1499 } else { 971 co ut << Verbose(1) << "Setting gaussian basis to " << argv[argptr] << "." << endl;972 co nfiguration.basis.copy(argv[argptr],strlen(argv[argptr]));1500 configuration.basis = argv[argptr]; 1501 cout << Verbose(1) << "Setting MPQC basis to " << configuration.basis << "." << endl; 973 1502 argptr+=1; 974 1503 } … … 1022 1551 case 'A': 1023 1552 ExitFlag = 1; 1024 if ((argptr >= argc) || ( !IsValidNumber(argv[argptr])) || (argv[argptr][0] == '-')) {1553 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1025 1554 ExitFlag =255; 1026 1555 cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl; … … 1030 1559 mol->CreateAdjacencyList2((ofstream *)&cout, input); 1031 1560 input->close(); 1561 argptr+=1; 1032 1562 } 1033 1563 break; … … 1038 1568 cerr << "Not enough or invalid arguments given for non-convex envelope: -o <radius> <tecplot output file>" << endl; 1039 1569 } else { 1040 cout << Verbose(0) << "Evaluating npn-convex envelope."; 1041 string TempName(argv[argptr+1]); 1042 TempName.append(".r3d"); 1043 ofstream *output = new ofstream(TempName.c_str(), ios::trunc); 1570 class Tesselation T; 1571 int N = 15; 1572 int number = 100; 1573 string filename(argv[argptr+1]); 1574 filename.append(".csv"); 1575 cout << Verbose(0) << "Evaluating non-convex envelope."; 1044 1576 cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl; 1045 Find_non_convex_border((ofstream *)&cout, output, mol, argv[argptr+1], atof(argv[argptr]));1046 output->close();1047 delete(output);1577 LinkedCell LCList(mol, atof(argv[argptr])); // \NOTE not twice the radius?? 1578 Find_non_convex_border((ofstream *)&cout, mol, &T, &LCList, argv[argptr+1], atof(argv[argptr])); 1579 FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str()); 1048 1580 argptr+=2; 1049 1581 } … … 1180 1712 ExitFlag = 1; 1181 1713 SaveFlag = true; 1182 cout << Verbose(1) << "Centering atoms in origin." << endl;1183 mol->Center Origin((ofstream *)&cout, &x);1714 cout << Verbose(1) << "Centering atoms on edge and setting box dimensions." << endl; 1715 mol->CenterEdge((ofstream *)&cout, &x); 1184 1716 mol->SetBoxDimension(&x); 1185 1717 break; … … 1230 1762 } else { 1231 1763 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 1232 ofstream *output = new ofstream(argv[argptr], ios::trunc);1233 //$$$1234 1764 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl; 1235 VolumeOfConvexEnvelope((ofstream *)&cout, output, &configuration, NULL, mol); 1236 output->close(); 1237 delete(output); 1765 VolumeOfConvexEnvelope((ofstream *)&cout, argv[argptr], &configuration, NULL, mol); 1238 1766 argptr+=1; 1239 1767 } … … 1341 1869 } while (argptr < argc); 1342 1870 if (SaveFlag) 1343 SaveConfig(ConfigFileName, &configuration, periode, mol );1871 SaveConfig(ConfigFileName, &configuration, periode, molecules); 1344 1872 if ((ExitFlag >= 1)) { 1345 1873 delete(mol); … … 1362 1890 { 1363 1891 periodentafel *periode = new periodentafel; // and a period table of all elements 1364 molecule *mol = new molecule(periode); // first we need an empty molecule 1892 MoleculeListClass *molecules = new MoleculeListClass; // list of all molecules 1893 molecule *mol = NULL; 1365 1894 config configuration; 1366 double tmp1;1367 double bond, min_bond;1368 atom *first, *second;1369 1895 char choice; // menu choice char 1370 1896 Vector x,y,z,n; // coordinates for absolute point in cell volume 1371 double *factor; // unit factor if desired1372 bool valid; // flag if input was valid or not1373 1897 ifstream test; 1374 1898 ofstream output; 1375 1899 string line; 1376 char filename[MAXSTRINGSIZE]; 1377 char *ConfigFileName = NULL; 1900 char ConfigFileName[MAXSTRINGSIZE]; 1378 1901 char *ElementsFileName = NULL; 1379 int Z; 1380 int j, axis, count, faktor; 1381 clock_t start,end; 1382 // int *MinimumRingSize = NULL; 1383 MoleculeLeafClass *Subgraphs = NULL; 1384 // class StackClass<bond *> *BackEdgeStack = NULL; 1385 element **Elements; 1386 Vector **vectors; 1902 int j; 1387 1903 1388 1904 // =========================== PARSE COMMAND LINE OPTIONS ==================================== 1389 j = ParseCommandLineOptions(argc, argv, mol, periode, configuration, ConfigFileName, ElementsFileName); 1905 ConfigFileName[0] = '\0'; 1906 j = ParseCommandLineOptions(argc, argv, molecules, periode, configuration, ConfigFileName, ElementsFileName); 1390 1907 if (j == 1) return 0; // just for -v and -h options 1391 1908 if (j) return j; // something went wrong 1392 1909 1393 1910 // General stuff 1394 if (mol->cell_size[0] == 0.) { 1395 cout << Verbose(0) << "enter lower triadiagonal form of basis matrix" << endl << endl; 1396 for (int i=0;i<6;i++) { 1397 cout << Verbose(1) << "Cell size" << i << ": "; 1398 cin >> mol->cell_size[i]; 1911 if (molecules->ListOfMolecules.size() == 0) { 1912 mol = new molecule(periode); 1913 if (mol->cell_size[0] == 0.) { 1914 cout << Verbose(0) << "enter lower tridiagonal form of basis matrix" << endl << endl; 1915 for (int i=0;i<6;i++) { 1916 cout << Verbose(1) << "Cell size" << i << ": "; 1917 cin >> mol->cell_size[i]; 1918 } 1399 1919 } 1920 molecules->insert(mol); 1400 1921 } 1922 if (strlen(ConfigFileName) == 0) 1923 strcpy(ConfigFileName, DEFAULTCONFIG); 1924 1401 1925 1402 1926 // =========================== START INTERACTIVE SESSION ==================================== … … 1406 1930 do { 1407 1931 cout << Verbose(0) << endl << endl; 1408 cout << Verbose(0) << "============Element list=======================" << endl; 1409 mol->Checkout((ofstream *)&cout); 1410 cout << Verbose(0) << "============Atom list==========================" << endl; 1411 mol->Output((ofstream *)&cout); 1932 cout << Verbose(0) << "============Molecule list=======================" << endl; 1933 molecules->Enumerate((ofstream *)&cout); 1412 1934 cout << Verbose(0) << "============Menu===============================" << endl; 1413 cout << Verbose(0) << "a - add an atom" << endl;1414 cout << Verbose(0) << " r - remove an atom" << endl;1415 cout << Verbose(0) << " b - scale a bond between atoms" << endl;1416 cout << Verbose(0) << " u - change an atoms element" << endl;1417 cout << Verbose(0) << " l - measure lengths, angles, ... for an atom" << endl;1935 cout << Verbose(0) << "a - set molecule (in)active" << endl; 1936 cout << Verbose(0) << "e - edit molecules (load, parse, save)" << endl; 1937 cout << Verbose(0) << "g - globally manipulate atoms in molecule" << endl; 1938 cout << Verbose(0) << "M - Merge molecules" << endl; 1939 cout << Verbose(0) << "m - manipulate atoms" << endl; 1418 1940 cout << Verbose(0) << "-----------------------------------------------" << endl; 1419 cout << Verbose(0) << "p - Parse xyz file" << endl; 1420 cout << Verbose(0) << "e - edit the current configuration" << endl; 1421 cout << Verbose(0) << "o - create connection matrix" << endl; 1422 cout << Verbose(0) << "f - fragment molecule many-body bond order style" << endl; 1423 cout << Verbose(0) << "-----------------------------------------------" << endl; 1424 cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl; 1425 cout << Verbose(0) << "i - realign molecule" << endl; 1426 cout << Verbose(0) << "m - mirror all molecules" << endl; 1427 cout << Verbose(0) << "t - translate molecule by vector" << endl; 1428 cout << Verbose(0) << "c - scale by unit transformation" << endl; 1429 cout << Verbose(0) << "g - center atoms in box" << endl; 1941 cout << Verbose(0) << "c - edit the current configuration" << endl; 1430 1942 cout << Verbose(0) << "-----------------------------------------------" << endl; 1431 1943 cout << Verbose(0) << "s - save current setup to config file" << endl; … … 1437 1949 1438 1950 switch (choice) { 1439 default: 1440 case 'a': // add atom 1441 AddAtoms(periode, mol); 1442 choice = 'a'; 1443 break; 1444 1445 case 'b': // scale a bond 1446 cout << Verbose(0) << "Scaling bond length between two atoms." << endl; 1447 first = mol->AskAtom("Enter first (fixed) atom: "); 1448 second = mol->AskAtom("Enter second (shifting) atom: "); 1449 min_bond = 0.; 1450 for (int i=NDIM;i--;) 1451 min_bond += (first->x.x[i]-second->x.x[i])*(first->x.x[i] - second->x.x[i]); 1452 min_bond = sqrt(min_bond); 1453 cout << Verbose(0) << "Current Bond length between " << first->type->name << " Atom " << first->nr << " and " << second->type->name << " Atom " << second->nr << ": " << min_bond << " a.u." << endl; 1454 cout << Verbose(0) << "Enter new bond length [a.u.]: "; 1455 cin >> bond; 1456 for (int i=NDIM;i--;) { 1457 second->x.x[i] -= (second->x.x[i]-first->x.x[i])/min_bond*(min_bond-bond); 1458 } 1459 //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: "; 1460 //second->Output(second->type->No, 1, (ofstream *)&cout); 1461 break; 1462 1463 case 'c': // unit scaling of the metric 1464 cout << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl; 1465 cout << Verbose(0) << "Enter three factors: "; 1466 factor = new double[NDIM]; 1467 cin >> factor[0]; 1468 cin >> factor[1]; 1469 cin >> factor[2]; 1470 valid = true; 1471 mol->Scale(&factor); 1472 delete[](factor); 1473 break; 1474 1475 case 'd': // duplicate the periodic cell along a given axis, given times 1476 cout << Verbose(0) << "State the axis [(+-)123]: "; 1477 cin >> axis; 1478 cout << Verbose(0) << "State the factor: "; 1479 cin >> faktor; 1480 1481 mol->CountAtoms((ofstream *)&cout); // recount atoms 1482 if (mol->AtomCount != 0) { // if there is more than none 1483 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand 1484 Elements = new element *[count]; 1485 vectors = new Vector *[count]; 1486 j = 0; 1487 first = mol->start; 1488 while (first->next != mol->end) { // make a list of all atoms with coordinates and element 1489 first = first->next; 1490 Elements[j] = first->type; 1491 vectors[j] = &first->x; 1492 j++; 1493 } 1494 if (count != j) 1495 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl; 1496 x.Zero(); 1497 y.Zero(); 1498 y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude 1499 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times 1500 x.AddVector(&y); // per factor one cell width further 1501 for (int k=count;k--;) { // go through every atom of the original cell 1502 first = new atom(); // create a new body 1503 first->x.CopyVector(vectors[k]); // use coordinate of original atom 1504 first->x.AddVector(&x); // translate the coordinates 1505 first->type = Elements[k]; // insert original element 1506 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...) 1507 } 1508 } 1509 if (mol->first->next != mol->last) // if connect matrix is present already, redo it 1510 mol->CreateAdjacencyList((ofstream *)&cout, mol->BondDistance, configuration.GetIsAngstroem()); 1511 // free memory 1512 delete[](Elements); 1513 delete[](vectors); 1514 // correct cell size 1515 if (axis < 0) { // if sign was negative, we have to translate everything 1516 x.Zero(); 1517 x.AddVector(&y); 1518 x.Scale(-(faktor-1)); 1519 mol->Translate(&x); 1520 } 1521 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1951 case 'a': // (in)activate molecule 1952 { 1953 cout << "Enter index of molecule: "; 1954 cin >> j; 1955 for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 1956 if ((*ListRunner)->IndexNr == j) 1957 (*ListRunner)->ActiveFlag = !(*ListRunner)->ActiveFlag; 1522 1958 } 1523 1959 break; 1524 1960 1525 case ' e': // edit each field of the configuration1526 configuration.Edit( mol);1961 case 'c': // edit each field of the configuration 1962 configuration.Edit(); 1527 1963 break; 1528 1964 1529 case ' f':1530 FragmentAtoms(mol, &configuration);1965 case 'e': // create molecule 1966 EditMolecules(periode, molecules); 1531 1967 break; 1532 1968 1533 case 'g': // center the atoms1534 CenterAtoms(mol);1969 case 'g': // manipulate molecules 1970 ManipulateMolecules(periode, molecules, &configuration); 1535 1971 break; 1536 1972 1537 case ' i': // align all atoms1538 AlignAtoms(periode, mol);1973 case 'M': // merge molecules 1974 MergeMolecules(periode, molecules); 1539 1975 break; 1540 1976 1541 case 'l': // measure distances or angles 1542 MeasureAtoms(periode, mol, &configuration); 1543 break; 1544 1545 case 'm': // mirror atoms along a given axis 1546 MirrorAtoms(mol); 1547 break; 1548 1549 case 'o': // create the connection matrix 1550 { 1551 cout << Verbose(0) << "What's the maximum bond distance: "; 1552 cin >> tmp1; 1553 start = clock(); 1554 mol->CreateAdjacencyList((ofstream *)&cout, tmp1, configuration.GetIsAngstroem()); 1555 mol->CreateListOfBondsPerAtom((ofstream *)&cout); 1556 // Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack); 1557 // while (Subgraphs->next != NULL) { 1558 // Subgraphs = Subgraphs->next; 1559 // Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize); 1560 // delete(Subgraphs->previous); 1561 // } 1562 // delete(Subgraphs); // we don't need the list here, so free everything 1563 // delete[](MinimumRingSize); 1564 // Subgraphs = NULL; 1565 end = clock(); 1566 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 1567 } 1568 break; 1569 1570 case 'p': // parse and XYZ file 1571 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl; 1572 do { 1573 cout << Verbose(0) << "Enter file name: "; 1574 cin >> filename; 1575 } while (!mol->AddXYZFile(filename)); 1977 case 'm': // manipulate atoms 1978 ManipulateAtoms(periode, molecules, &configuration); 1576 1979 break; 1577 1980 … … 1579 1982 break; 1580 1983 1581 case ' r': // remove atom1582 RemoveAtoms(mol);1984 case 's': // save to config file 1985 SaveConfig(ConfigFileName, &configuration, periode, molecules); 1583 1986 break; 1584 1987 1585 case ' s': // save to config file1586 SaveConfig(ConfigFileName, &configuration, periode, mol);1988 case 'T': 1989 testroutine(molecules); 1587 1990 break; 1588 1991 1589 case 't': // translate all atoms 1590 cout << Verbose(0) << "Enter translation vector." << endl; 1591 x.AskPosition(mol->cell_size,0); 1592 mol->Translate((const Vector *)&x); 1593 break; 1594 1595 case 'T': 1596 testroutine(mol); 1597 break; 1598 1599 case 'u': // change an atom's element 1600 first = NULL; 1601 do { 1602 cout << Verbose(0) << "Change the element of which atom: "; 1603 cin >> Z; 1604 } while ((first = mol->FindAtom(Z)) == NULL); 1605 cout << Verbose(0) << "New element by atomic number Z: "; 1606 cin >> Z; 1607 first->type = periode->FindElement(Z); 1608 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl; 1992 default: 1609 1993 break; 1610 1994 }; … … 1617 2001 cout << Verbose(0) << "Saving of elements.db failed." << endl; 1618 2002 1619 // Free all 1620 if (Subgraphs != NULL) { // free disconnected subgraph list of DFS analysis was performed 1621 while (Subgraphs->next != NULL) { 1622 Subgraphs = Subgraphs->next; 1623 delete(Subgraphs->previous); 1624 } 1625 delete(Subgraphs); 1626 } 1627 delete(mol); 2003 delete(molecules); 1628 2004 delete(periode); 1629 2005 return (0); -
src/config.cpp
rce5ac3 rd067d45 1 1 /** \file config.cpp 2 * 2 * 3 3 * Function implementations for the class config. 4 * 4 * 5 5 */ 6 6 … … 65 65 UseAddGramSch=1; 66 66 Seed=1; 67 67 68 MaxOuterStep=0; 68 69 Deltat=0.01; … … 73 74 MaxPsiStep=0; 74 75 EpsWannier=1e-7; 75 76 76 77 MaxMinStep=100; 77 78 RelEpsTotalEnergy=1e-7; … … 84 85 InitMaxMinStopStep=1; 85 86 InitMaxMinGapStopStep=0; 86 87 87 88 //BoxLength[NDIM*NDIM]; 88 89 89 90 ECut=128.; 90 91 MaxLevel=5; … … 99 100 PsiMaxNoDown=0; 100 101 AddPsis=0; 101 102 102 103 RCut=20.; 103 104 StructOpt=0; … … 199 200 * for each entry of the config file structure. 200 201 */ 201 void config::Edit( molecule *mol)202 void config::Edit() 202 203 { 203 204 char choice; 204 205 205 206 do { 206 207 cout << Verbose(0) << "===========EDIT CONFIGURATION============================" << endl; … … 235 236 cout << Verbose(0) << " g - Relative change in kinetic energy to stop min. iteration during initial level" << endl; 236 237 cout << Verbose(0) << " h - Check stop conditions every ..th step during min. iteration during initial level" << endl; 237 cout << Verbose(0) << " j - six lower diagonal entries of matrix, defining the unit cell" << endl;238 // cout << Verbose(0) << " j - six lower diagonal entries of matrix, defining the unit cell" << endl; 238 239 cout << Verbose(0) << " k - Energy cutoff of plane wave basis in Hartree" << endl; 239 240 cout << Verbose(0) << " l - Maximum number of levels in multi-level-ansatz" << endl; … … 255 256 cout << Verbose(0) << "INPUT: "; 256 257 cin >> choice; 257 258 258 259 switch (choice) { 259 260 case 'A': // mainname … … 380 381 cin >> config::InitMaxMinStopStep; 381 382 break; 382 383 case 'j': // BoxLength384 cout << Verbose(0) << "enter lower triadiagonalo form of basis matrix" << endl << endl;385 for (int i=0;i<6;i++) {386 cout << Verbose(0) << "Cell size" << i << ": ";387 cin >> mol->cell_size[i];388 }389 break;390 383 384 // case 'j': // BoxLength 385 // cout << Verbose(0) << "enter lower triadiagonalo form of basis matrix" << endl << endl; 386 // for (int i=0;i<6;i++) { 387 // cout << Verbose(0) << "Cell size" << i << ": "; 388 // cin >> mol->cell_size[i]; 389 // } 390 // break; 391 391 392 case 'k': // ECut 392 393 cout << Verbose(0) << "Old: " << config::ECut << "\t new: "; … … 462 463 * \param *periode pointer to a periodentafel class with all elements 463 464 * \param *mol pointer to molecule containing all atoms of the molecule 464 * \return 0 - old syntax, 1 - new syntax, -1 - unknown syntax 465 * \return 0 - old syntax, 1 - new syntax, -1 - unknown syntax 465 466 */ 466 467 int config::TestSyntax(char *filename, periodentafel *periode, molecule *mol) … … 468 469 int test; 469 470 ifstream file(filename); 470 471 471 472 // search file for keyword: ProcPEGamma (new syntax) 472 473 if (ParseForParameter(1,&file,"ProcPEGamma", 0, 1, 1, int_type, &test, 1, optional)) { … … 539 540 * \param *file input file stream being the opened config file 540 541 * \param *periode pointer to a periodentafel class with all elements 541 * \param *mol pointer to molecule containing all atoms of the molecule 542 * \param *mol pointer to molecule containing all atoms of the molecule 542 543 */ 543 544 void config::Load(char *filename, periodentafel *periode, molecule *mol) … … 550 551 RetrieveConfigPathAndName(filename); 551 552 // ParseParameters 552 553 553 554 /* Oeffne Hauptparameterdatei */ 554 555 int di; … … 595 596 config::DoOutCurrent = 0; 596 597 if (config::DoOutCurrent < 0) config::DoOutCurrent = 0; 597 if (config::DoOutCurrent > 1) config::DoOutCurrent = 1; 598 if (config::DoOutCurrent > 1) config::DoOutCurrent = 1; 598 599 ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical); 599 600 if (config::UseAddGramSch < 0) config::UseAddGramSch = 0; … … 630 631 if (!ParseForParameter(verbose,file,"EpsWannier", 0, 1, 1, double_type, &(config::EpsWannier), 1, optional)) 631 632 config::EpsWannier = 1e-8; 632 633 633 634 // stop conditions 634 635 //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1; 635 636 ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical); 636 637 if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3; 637 638 638 639 ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical); 639 640 ParseForParameter(verbose,file,"RelEpsTotalE", 0, 1, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical); … … 644 645 if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1; 645 646 if (config::MaxMinGapStopStep < 1) config::MaxMinGapStopStep = 1; 646 647 647 648 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical); 648 649 ParseForParameter(verbose,file,"InitRelEpsTotalE", 0, 1, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical); … … 653 654 if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1; 654 655 if (config::InitMaxMinGapStopStep < 1) config::InitMaxMinGapStopStep = 1; 655 656 656 657 // Unit cell and magnetic field 657 658 ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */ … … 669 670 config::DoFullCurrent = 0; 670 671 if (config::DoFullCurrent < 0) config::DoFullCurrent = 0; 671 if (config::DoFullCurrent > 2) config::DoFullCurrent = 2; 672 if (config::DoFullCurrent > 2) config::DoFullCurrent = 2; 672 673 if (config::DoOutNICS < 0) config::DoOutNICS = 0; 673 if (config::DoOutNICS > 2) config::DoOutNICS = 2; 674 if (config::DoOutNICS > 2) config::DoOutNICS = 2; 674 675 if (config::DoPerturbation == 0) { 675 676 config::DoFullCurrent = 0; … … 688 689 } else { 689 690 fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT"); 690 exit(1); 691 exit(1); 691 692 } 692 693 switch (config::RiemannTensor) { … … 705 706 if (config::RiemannLevel < 2) { 706 707 config::RiemannLevel = 2; 707 } 708 } 708 709 if (config::RiemannLevel > config::MaxLevel-1) { 709 710 config::RiemannLevel = config::MaxLevel-1; … … 712 713 if (config::LevRFactor < 2) { 713 714 config::LevRFactor = 2; 714 } 715 } 715 716 config::Lev0Factor = 2; 716 717 config::RTActualUse = 2; … … 722 723 } else { 723 724 fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown"); 724 exit(1); 725 exit(1); 725 726 } 726 727 switch (config::PsiType) { … … 736 737 break; 737 738 } 738 739 739 740 // IonsInitRead 740 741 741 742 ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical); 742 743 ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical); … … 756 757 ParseForParameter(verbose,file, name, 0, 2, 1, int_type, &Z, 1, critical); 757 758 elementhash[i] = periode->FindElement(Z); 758 cout << Verbose(1) << i << ". Z = " << elementhash[i]->Z << " with " << No[i] << " ions." << endl; 759 cout << Verbose(1) << i << ". Z = " << elementhash[i]->Z << " with " << No[i] << " ions." << endl; 759 760 } 760 761 int repetition = 0; // which repeated keyword shall be read 761 762 762 763 map<int, atom *> AtomList[config::MaxTypes]; 763 764 if (!FastParsing) { … … 778 779 } else 779 780 neues = AtomList[i][j]; 780 status = (status && 781 status = (status && 781 782 ParseForParameter(verbose,file, keyword, 0, 1, 1, double_type, &neues->x.x[0], 1, (repetition == 0) ? critical : optional) && 782 783 ParseForParameter(verbose,file, keyword, 0, 2, 1, double_type, &neues->x.x[1], 1, (repetition == 0) ? critical : optional) && … … 784 785 ParseForParameter(verbose,file, keyword, 0, 4, 1, int_type, &neues->FixedIon, 1, (repetition == 0) ? critical : optional)); 785 786 if (!status) break; 786 787 787 788 // check size of vectors 788 789 if (mol->Trajectories[neues].R.size() <= (unsigned int)(repetition)) { … … 792 793 mol->Trajectories[neues].F.resize(repetition+10); 793 794 } 794 795 795 796 // put into trajectories list 796 797 for (int d=0;d<NDIM;d++) 797 798 mol->Trajectories[neues].R.at(repetition).x[d] = neues->x.x[d]; 798 799 799 800 // parse velocities if present 800 801 if(!ParseForParameter(verbose,file, keyword, 0, 5, 1, double_type, &neues->v.x[0], 1,optional)) … … 806 807 for (int d=0;d<NDIM;d++) 807 808 mol->Trajectories[neues].U.at(repetition).x[d] = neues->v.x[d]; 808 809 809 810 // parse forces if present 810 811 if(!ParseForParameter(verbose,file, keyword, 0, 8, 1, double_type, &value[0], 1,optional)) … … 816 817 for (int d=0;d<NDIM;d++) 817 818 mol->Trajectories[neues].F.at(repetition).x[d] = value[d]; 818 819 // cout << "Parsed position of step " << (repetition) << ": ("; 819 820 // cout << "Parsed position of step " << (repetition) << ": ("; 820 821 // for (int d=0;d<NDIM;d++) 821 822 // cout << mol->Trajectories[neues].R.at(repetition).x[d] << " "; // next step … … 873 874 * \param *file input file stream being the opened config file with old pcp syntax 874 875 * \param *periode pointer to a periodentafel class with all elements 875 * \param *mol pointer to molecule containing all atoms of the molecule 876 * \param *mol pointer to molecule containing all atoms of the molecule 876 877 */ 877 878 void config::LoadOld(char *filename, periodentafel *periode, molecule *mol) … … 884 885 RetrieveConfigPathAndName(filename); 885 886 // ParseParameters 886 887 887 888 /* Oeffne Hauptparameterdatei */ 888 889 int l, i, di; … … 894 895 int Z, No, AtomNo, found; 895 896 int verbose = 0; 896 897 897 898 /* Namen einlesen */ 898 899 … … 926 927 ParseForParameter(verbose,file,"ScaleTempStep", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional); 927 928 config::EpsWannier = 1e-8; 928 929 929 930 // stop conditions 930 931 //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1; 931 932 ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical); 932 933 if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3; 933 934 934 935 ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical); 935 936 ParseForParameter(verbose,file,"MaxMinStep", 0, 2, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical); … … 939 940 if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1; 940 941 config::MaxMinGapStopStep = 1; 941 942 942 943 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical); 943 944 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 2, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical); … … 970 971 } else { 971 972 fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT"); 972 exit(1); 973 exit(1); 973 974 } 974 975 switch (config::RiemannTensor) { … … 987 988 if (config::RiemannLevel < 2) { 988 989 config::RiemannLevel = 2; 989 } 990 } 990 991 if (config::RiemannLevel > config::MaxLevel-1) { 991 992 config::RiemannLevel = config::MaxLevel-1; … … 994 995 if (config::LevRFactor < 2) { 995 996 config::LevRFactor = 2; 996 } 997 } 997 998 config::Lev0Factor = 2; 998 999 config::RTActualUse = 2; … … 1004 1005 } else { 1005 1006 fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown"); 1006 exit(1); 1007 exit(1); 1007 1008 } 1008 1009 switch (config::PsiType) { … … 1018 1019 break; 1019 1020 } 1020 1021 1021 1022 // IonsInitRead 1022 1023 1023 1024 ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical); 1024 1025 ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical); … … 1027 1028 1028 1029 // Routine from builder.cpp 1029 1030 1031 for (i=MAX_ELEMENTS;i--;) 1030 1031 1032 for (i=MAX_ELEMENTS;i--;) 1032 1033 elementhash[i] = NULL; 1033 1034 cout << Verbose(0) << "Parsing Ions ..." << endl; … … 1040 1041 } 1041 1042 if (found > 0) { 1042 if (zeile.find("Ions_Data") == 0) 1043 if (zeile.find("Ions_Data") == 0) 1043 1044 getline(*file,zeile,'\n'); // read next line and parse this one 1044 1045 istringstream input(zeile); … … 1069 1070 No++; 1070 1071 } 1071 } 1072 } 1072 1073 file->close(); 1073 1074 delete(file); … … 1077 1078 * \param *filename name of file 1078 1079 * \param *periode pointer to a periodentafel class with all elements 1079 * \param *mol pointer to molecule containing all atoms of the molecule 1080 * \param *mol pointer to molecule containing all atoms of the molecule 1080 1081 */ 1081 1082 bool config::Save(const char *filename, periodentafel *periode, molecule *mol) const … … 1207 1208 * Note that this format cannot be parsed again. 1208 1209 * \param *filename name of file (without ".in" suffix!) 1209 * \param *mol pointer to molecule containing all atoms of the molecule 1210 * \param *mol pointer to molecule containing all atoms of the molecule 1210 1211 */ 1211 1212 bool config::SaveMPQC(const char *filename, molecule *mol) const … … 1218 1219 ofstream *output = NULL; 1219 1220 stringstream *fname = NULL; 1220 1221 1221 1222 // first without hessian 1222 1223 fname = new stringstream; … … 1227 1228 *output << "\tsavestate = no" << endl; 1228 1229 *output << "\tdo_gradient = yes" << endl; 1229 *output << "\tmole< CLHF>: (" << endl;1230 *output << "\tmole<MBPT2>: (" << endl; 1230 1231 *output << "\t\tmaxiter = 200" << endl; 1231 1232 *output << "\t\tbasis = $:basis" << endl; 1232 1233 *output << "\t\tmolecule = $:molecule" << endl; 1234 *output << "\t\treference<CLHF>: (" << endl; 1235 *output << "\t\t\tbasis = $:basis" << endl; 1236 *output << "\t\t\tmolecule = $:molecule" << endl; 1237 *output << "\t\t)" << endl; 1233 1238 *output << "\t)" << endl; 1234 1239 *output << ")" << endl; … … 1313 1318 delete(output); 1314 1319 delete(fname); 1315 1320 1316 1321 return true; 1317 1322 }; … … 1325 1330 * \param file file to be parsed 1326 1331 * \param name Name of value in file (at least 3 chars!) 1327 * \param sequential 1 - do not reset file pointer to begin of file, 0 - set to beginning 1332 * \param sequential 1 - do not reset file pointer to begin of file, 0 - set to beginning 1328 1333 * (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read - 1329 1334 * best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now … … 1345 1350 dummy1 = free_dummy = (char *) Malloc(256 * sizeof(char), "config::ParseForParameter: *free_dummy"); 1346 1351 1347 //fprintf(stderr,"Parsing for %s\n",name); 1352 //fprintf(stderr,"Parsing for %s\n",name); 1348 1353 if (repetition == 0) 1349 1354 //Error(SomeError, "ParseForParameter(): argument repetition must not be 0!"); … … 1366 1371 file->clear(); 1367 1372 file->seekg(file_position, ios::beg); // rewind to start position 1368 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1373 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1369 1374 return 0; 1370 1375 } … … 1372 1377 line++; 1373 1378 } while (dummy != NULL && dummy1 != NULL && ((dummy1[0] == '#') || (dummy1[0] == '\0'))); // skip commentary and empty lines 1374 1379 1375 1380 // C++ getline removes newline at end, thus re-add 1376 1381 if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) { … … 1398 1403 //fprintf(stderr,"Error: Cannot find tabs or spaces on line %i in search for %s\n", line, name); 1399 1404 //Free((void **)&free_dummy); 1400 //Error(FileOpenParams, NULL); 1405 //Error(FileOpenParams, NULL); 1401 1406 } else { 1402 1407 //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)dummy1); … … 1407 1412 if ((name == NULL) || (((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0)) && ((unsigned int)(dummy-dummy1) == strlen(name)))) { 1408 1413 found++; // found the parameter! 1409 //fprintf(stderr,"found %s at line %i between %i and %i\n", name, line, dummy1, dummy); 1410 1414 //fprintf(stderr,"found %s at line %i between %i and %i\n", name, line, dummy1, dummy); 1415 1411 1416 if (found == repetition) { 1412 1417 for (i=0;i<xth;i++) { // i = rows … … 1447 1452 dummy1[j+1] = '\0'; 1448 1453 } 1449 1454 1450 1455 int start = (type >= grid) ? 0 : yth-1 ; 1451 1456 for (j=start;j<yth;j++) { // j = columns … … 1470 1475 //return 0; 1471 1476 exit(255); 1472 //Error(FileOpenParams, NULL); 1477 //Error(FileOpenParams, NULL); 1473 1478 } else { 1474 1479 //if (!sequential) … … 1485 1490 // found comment, skipping rest of line 1486 1491 //if (verbose) fprintf(stderr,"Error: '#' at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name); 1487 if (!sequential) { // here we need it! 1492 if (!sequential) { // here we need it! 1488 1493 file->seekg(file_position, ios::beg); // rewind to start position 1489 1494 } … … 1500 1505 //value += sizeof(int); 1501 1506 break; 1502 case(row_double): 1507 case(row_double): 1503 1508 case(grid): 1504 1509 case(lower_trigrid): … … 1541 1546 } 1542 1547 } 1543 } 1548 } 1544 1549 if ((type >= row_int) && (verbose)) fprintf(stderr,"\n"); 1545 1550 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); … … 1549 1554 } 1550 1555 //fprintf(stderr, "End of Parsing\n\n"); 1551 1556 1552 1557 return (found); // true if found, false if not 1553 1558 } -
src/datacreator.cpp
rce5ac3 rd067d45 1 1 /** \file datacreator.cpp 2 2 * 3 * Declarations of assisting functions in creating data and plot files. 4 * 3 * Declarations of assisting functions in creating data and plot files. 4 * 5 5 */ 6 6 … … 27 27 } 28 28 return true; 29 }; 29 }; 30 30 31 31 /** Opens a file for appending with \a *filename in \a *dir. … … 45 45 } 46 46 return true; 47 }; 47 }; 48 48 49 49 /** Plots an energy vs. order. … … 54 54 * \return true if file was written successfully 55 55 */ 56 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 57 { 58 stringstream filename; 59 ofstream output; 60 61 filename << prefix << ".dat"; 62 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 56 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 57 { 58 stringstream filename; 59 ofstream output; 60 61 filename << prefix << ".dat"; 62 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 63 63 cout << msg << endl; 64 64 output << "# " << msg << ", created on " << datum; … … 87 87 * \return true if file was written successfully 88 88 */ 89 bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 90 { 91 stringstream filename; 92 ofstream output; 93 94 filename << prefix << ".dat"; 95 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 89 bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 90 { 91 stringstream filename; 92 ofstream output; 93 94 filename << prefix << ".dat"; 95 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 96 96 cout << msg << endl; 97 97 output << "# " << msg << ", created on " << datum; … … 130 130 131 131 filename << prefix << ".dat"; 132 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 132 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 133 133 cout << msg << endl; 134 134 output << "# " << msg << ", created on " << datum; … … 162 162 163 163 filename << prefix << ".dat"; 164 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 164 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 165 165 cout << msg << endl; 166 166 output << "# " << msg << ", created on " << datum; … … 188 188 * \return true if file was written successfully 189 189 */ 190 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 190 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 191 191 { 192 192 stringstream filename; … … 195 195 196 196 filename << prefix << ".dat"; 197 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 197 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 198 198 cout << msg << endl; 199 199 output << "# " << msg << ", created on " << datum; … … 205 205 // errors per atom 206 206 output << endl << "#Order\t" << BondOrder+1 << endl; 207 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 207 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 208 208 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t"; 209 209 for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++) { … … 213 213 norm += Force.Matrix[Force.MatrixCounter][ j ][l+m]*Force.Matrix[Force.MatrixCounter][ j ][l+m]; 214 214 norm = sqrt(norm); 215 } 215 } 216 216 // if (norm < MYEPSILON) 217 217 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t"; … … 235 235 * \return true if file was written successfully 236 236 */ 237 bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 238 { 239 stringstream filename; 240 ofstream output; 241 242 filename << prefix << ".dat"; 243 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 237 bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 238 { 239 stringstream filename; 240 ofstream output; 241 242 filename << prefix << ".dat"; 243 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 244 244 cout << msg << endl; 245 245 output << "# " << msg << ", created on " << datum; … … 250 250 // errors per atom 251 251 output << endl << "#Order\t" << BondOrder+1 << endl; 252 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 252 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 253 253 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t"; 254 254 for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++) … … 390 390 391 391 filename << prefix << ".dat"; 392 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 392 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 393 393 cout << msg << endl; 394 394 output << "# " << msg << ", created on " << datum << endl; … … 411 411 * \param &KeySet KeySetsContainer with associations of each fragment to a bond order 412 412 * \param BondOrder current bond order 413 */ 413 */ 414 414 void CreateMaxFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder) 415 415 { … … 420 420 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 421 421 } 422 } 422 } 423 423 } 424 424 }; … … 428 428 * \param &KeySet KeySetsContainer with associations of each fragment to a bond order 429 429 * \param BondOrder current bond order 430 */ 430 */ 431 431 void CreateMinFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder) 432 432 { … … 443 443 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 444 444 } 445 } 445 } 446 446 } 447 447 }; … … 455 455 456 456 filename << prefix << ".dat"; 457 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 457 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 458 458 cout << msg << endl; 459 459 output << "# " << msg << ", created on " << datum; … … 496 496 do { 497 497 for (int m=NDIM;m--;) { 498 stored += Force.Matrix[MatrixNumber][ k ][l+m] 498 stored += Force.Matrix[MatrixNumber][ k ][l+m] 499 499 * Force.Matrix[MatrixNumber][ k ][l+m]; 500 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 500 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 501 501 } 502 502 k++; … … 505 505 double tmp = 0; 506 506 for (int m=NDIM;m--;) 507 tmp += Force.Matrix[MatrixNumber][ k ][l+m] 507 tmp += Force.Matrix[MatrixNumber][ k ][l+m] 508 508 * Force.Matrix[MatrixNumber][ k ][l+m]; 509 509 if ((fabs(tmp) > MYEPSILON) && (tmp < stored)) { // current force is greater than stored 510 510 for (int m=NDIM;m--;) 511 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 511 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 512 512 stored = tmp; 513 513 } … … 531 531 double norm = 0.; 532 532 for (int m=NDIM;m--;) 533 norm += Force.Matrix[MatrixNumber][ k ][l+m] 533 norm += Force.Matrix[MatrixNumber][ k ][l+m] 534 534 * Force.Matrix[MatrixNumber][ k ][l+m]; 535 535 tmp += sqrt(norm); … … 553 553 double tmp = 0; 554 554 for (int m=NDIM;m--;) 555 tmp += Force.Matrix[MatrixNumber][ k ][l+m] 555 tmp += Force.Matrix[MatrixNumber][ k ][l+m] 556 556 * Force.Matrix[MatrixNumber][ k ][l+m]; 557 557 if (tmp > stored) { // current force is greater than stored 558 558 for (int m=NDIM;m--;) 559 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 559 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 560 560 stored = tmp; 561 561 } … … 592 592 * \param *key position of key 593 593 * \param *logscale axis for logscale 594 * \param *extraline extra set lines if desired 594 * \param *extraline extra set lines if desired 595 595 * \param mxtics small tics at ... 596 596 * \param xtics large tics at ... 597 * \param *xlabel label for x axis 597 * \param *xlabel label for x axis 598 598 * \param *ylabel label for y axis 599 */ 599 */ 600 600 void CreatePlotHeader(ofstream &output, 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) 601 601 { … … 626 626 * \param mxtics small tics at ... 627 627 * \param xtics large tics at ... 628 * \param xlabel label for x axis 628 * \param xlabel label for x axis 629 629 * \param xlabel label for x axis 630 630 * \param *xrange xrange … … 634 634 * \param (*CreatePlotLines) function reference that writes a single plot line 635 635 * \return true if file was written successfully 636 */ 636 */ 637 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 *)) 638 638 { … … 641 641 642 642 filename << prefix << ".pyx"; 643 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 643 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 644 644 CreatePlotHeader(output, prefix, keycolumns, key, logscale, extraline, mxtics, xtics, xlabel, ylabel); 645 645 output << "plot " << xrange << " " << yrange << " \\" << endl; 646 646 CreatePlotLines(output, Matrix, prefix, xargument, uses); 647 output.close(); 647 output.close(); 648 648 return true; 649 649 }; -
src/datacreator.hpp
rce5ac3 rd067d45 1 1 /** \file datacreator.cpp 2 2 * 3 * Definitions of assisting functions in creating data and plot files. 4 * 3 * Definitions of assisting functions in creating data and plot files. 4 * 5 5 */ 6 6 … … 12 12 //============================ INCLUDES =========================== 13 13 14 #include "helpers.hpp" 14 #include "helpers.hpp" 15 15 #include "parser.hpp" 16 16 … … 20 20 bool AppendOutputFile(ofstream &output, const char *dir, const char *filename); 21 21 22 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 23 bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 22 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 23 bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 24 24 bool CreateDataForcesOrder(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)); 25 25 bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); -
src/element.cpp
rce5ac3 rd067d45 12 12 */ 13 13 element::element() { 14 Z = -1;15 No = -1;16 previous = NULL;17 next = NULL;18 sort = NULL;14 Z = -1; 15 No = -1; 16 previous = NULL; 17 next = NULL; 18 sort = NULL; 19 19 }; 20 20 … … 28 28 bool element::Output(ofstream *out) const 29 29 { 30 if (out != NULL) {31 *out << name << "\t" << symbol << "\t" << period << "\t" << group << "\t" << block << "\t" << Z << "\t" << mass << "\t" << CovalentRadius << "\t" << VanDerWaalsRadius << endl;32 //*out << Z << "\t"<< fixed << setprecision(11) << showpoint << mass << "g/mol\t" << name << "\t" << symbol << "\t" << endl;33 return true;34 } else35 return false;30 if (out != NULL) { 31 *out << name << "\t" << symbol << "\t" << period << "\t" << group << "\t" << block << "\t" << Z << "\t" << mass << "\t" << CovalentRadius << "\t" << VanDerWaalsRadius << endl; 32 //*out << Z << "\t" << fixed << setprecision(11) << showpoint << mass << "g/mol\t" << name << "\t" << symbol << "\t" << endl; 33 return true; 34 } else 35 return false; 36 36 }; 37 37 38 38 /** Prints element data to \a *out. 39 39 * \param *out outstream 40 * \param No cardinal number of element40 * \param No cardinal number of element 41 41 * \param NoOfAtoms total number of atom of this element type 42 42 */ 43 43 bool element::Checkout(ofstream *out, const int Number, const int NoOfAtoms) const 44 44 { 45 if (out != NULL) {46 *out << "Ion_Type" << Number << "\t" << NoOfAtoms << "\t" << Z << "\t1.0\t3\t3\t" << fixed << setprecision(11) << showpoint << mass << "\t" << name << "\t" << symbol <<endl;47 return true;48 } else49 return false;45 if (out != NULL) { 46 *out << "Ion_Type" << Number << "\t" << NoOfAtoms << "\t" << Z << "\t1.0\t3\t3\t" << fixed << setprecision(11) << showpoint << mass << "\t" << name << "\t" << symbol <<endl; 47 return true; 48 } else 49 return false; 50 50 }; -
src/graph.cpp
rce5ac3 rd067d45 1 1 /** \file graph.cpp 2 * 2 * 3 3 * Function implementations for the class graph. 4 * 4 * 5 5 */ 6 6 -
src/helpers.cpp
rce5ac3 rd067d45 1 1 /** \file helpers.cpp 2 2 * 3 * Implementation of some auxiliary functions for memory dis-/allocation and so on 3 * Implementation of some auxiliary functions for memory dis-/allocation and so on 4 4 */ 5 5 … … 15 15 double ask_value(const char *text) 16 16 { 17 double test = 0.1439851348959832147598734598273456723948652983045928346598365;18 do {19 cout << Verbose(0) << text;20 cin >> test;21 } while (test == 0.1439851348959832147598734598273456723948652983045928346598365);22 return test; 17 double test = 0.1439851348959832147598734598273456723948652983045928346598365; 18 do { 19 cout << Verbose(0) << text; 20 cin >> test; 21 } while (test == 0.1439851348959832147598734598273456723948652983045928346598365); 22 return test; 23 23 }; 24 24 … … 29 29 #ifdef HAVE_DEBUG 30 30 void debug_in(const char *output, const char *file, const int line) { 31 if (output) fprintf(stderr,"DEBUG: in %s at line %i: %s\n", file, line, output);31 if (output) fprintf(stderr,"DEBUG: in %s at line %i: %s\n", file, line, output); 32 32 } 33 33 #else 34 void debug_in(const char *output, const char *file, const int line) {} // print nothing34 void debug_in(const char *output, const char *file, const int line) {} // print nothing 35 35 #endif 36 36 … … 40 40 * \return pointer to memory range 41 41 */ 42 void * Malloc(size_t size, const char* output) 42 void * Malloc(size_t size, const char* output) 43 43 { 44 void *buffer = NULL;45 buffer = (void *)malloc(size); // alloc46 if (buffer == NULL)47 cout << Verbose(0) << "Malloc failed - pointer is NULL: " << output << endl;48 return(buffer);44 void *buffer = NULL; 45 buffer = (void *)malloc(size); // alloc 46 if (buffer == NULL) 47 cout << Verbose(0) << "Malloc failed - pointer is NULL: " << output << endl; 48 return(buffer); 49 49 }; 50 50 … … 54 54 * \return pointer to memory range 55 55 */ 56 void * Calloc(size_t size, const char* output) 56 void * Calloc(size_t size, const char* output) 57 57 { 58 void *buffer = NULL;59 buffer = (void *)calloc(size, (size_t)0); // alloc60 if (buffer == NULL)61 cout << Verbose(0) << "Calloc failed - pointer is NULL: " << output << endl;62 return(buffer);58 void *buffer = NULL; 59 buffer = (void *)calloc(size, (size_t)0); // alloc 60 if (buffer == NULL) 61 cout << Verbose(0) << "Calloc failed - pointer is NULL: " << output << endl; 62 return(buffer); 63 63 }; 64 64 … … 69 69 * \return pointer to memory range 70 70 */ 71 void * ReAlloc(void * OldPointer, size_t size, const char* output) 71 void * ReAlloc(void * OldPointer, size_t size, const char* output) 72 72 { 73 73 void *buffer = NULL; … … 86 86 * \param *output message if free fails 87 87 */ 88 void Free(void ** buffer, const char* output) 88 void Free(void ** buffer, const char* output) 89 89 { 90 if (*buffer == NULL) {91 //cout << Verbose(5) << "Free not necesary: " << output << endl;92 } else {93 free(*buffer);94 *buffer = NULL;95 }90 if (*buffer == NULL) { 91 //cout << Verbose(5) << "Free not necesary: " << output << endl; 92 } else { 93 free(*buffer); 94 *buffer = NULL; 95 } 96 96 }; 97 97 … … 101 101 * \return pointer to string array 102 102 */ 103 char* MallocString(size_t size, const char* output) 103 char* MallocString(size_t size, const char* output) 104 104 { 105 size_t i;106 char *buffer;107 buffer = (char *)malloc(sizeof(char) * (size+1)); // alloc108 if (buffer == NULL)109 cout << Verbose(0) << output << endl;110 for (i=size;i--;)// reset111 buffer[i] = i % 2 == 0 ? 'p': 'c';112 buffer[size] = '\0'; // and set length marker on its end113 return(buffer);105 size_t i; 106 char *buffer; 107 buffer = (char *)malloc(sizeof(char) * (size+1)); // alloc 108 if (buffer == NULL) 109 cout << Verbose(0) << output << endl; 110 for (i=size;i--;) // reset 111 buffer[i] = i % 2 == 0 ? 'p': 'c'; 112 buffer[size] = '\0'; // and set length marker on its end 113 return(buffer); 114 114 } 115 115 … … 121 121 void bound(double *b, double lower_bound, double upper_bound) 122 122 { 123 double step = (upper_bound - lower_bound);124 while (*b >= upper_bound)125 *b -= step; 126 while (*b < lower_bound)127 *b += step; 128 }; 123 double step = (upper_bound - lower_bound); 124 while (*b >= upper_bound) 125 *b -= step; 126 while (*b < lower_bound) 127 *b += step; 128 }; 129 129 130 130 /** Flips two doubles. … … 134 134 void flip(double *x, double *y) 135 135 { 136 double tmp;137 tmp = *x;138 *x = *y;139 *y = tmp;136 double tmp; 137 tmp = *x; 138 *x = *y; 139 *y = tmp; 140 140 }; 141 141 … … 147 147 int pot(int base, int n) 148 148 { 149 int res = 1;150 int j;151 for (j=n;j--;)152 res *= base;153 return res;149 int res = 1; 150 int j; 151 for (j=n;j--;) 152 res *= base; 153 return res; 154 154 }; 155 155 … … 161 161 char *FixedDigitNumber(const int FragmentNumber, const int digits) 162 162 { 163 char *returnstring;164 int number = FragmentNumber;165 int order = 0;166 while (number != 0) { // determine number of digits needed167 number = (int)floor(((double)number / 10.));168 order++;169 //cout << "Number is " << number << ", order is " << order << "." << endl;170 }171 // allocate string172 returnstring = (char *) Malloc(sizeof(char)*(order+2), "MoleculeListClass::CreateFragmentNumberForOutput: *returnstring");173 // terminateand fill string array from end backward174 returnstring[order] = '\0';175 number = digits;176 for (int i=order;i--;) {177 returnstring[i] = '0' + (char)(number % 10);178 number = (int)floor(((double)number / 10.));179 }180 //cout << returnstring << endl;181 return returnstring;163 char *returnstring; 164 int number = FragmentNumber; 165 int order = 0; 166 while (number != 0) { // determine number of digits needed 167 number = (int)floor(((double)number / 10.)); 168 order++; 169 //cout << "Number is " << number << ", order is " << order << "." << endl; 170 } 171 // allocate string 172 returnstring = (char *) Malloc(sizeof(char)*(order+2), "FixedDigitNumber: *returnstring"); 173 // terminate and fill string array from end backward 174 returnstring[order] = '\0'; 175 number = digits; 176 for (int i=order;i--;) { 177 returnstring[i] = '0' + (char)(number % 10); 178 number = (int)floor(((double)number / 10.)); 179 } 180 //cout << returnstring << endl; 181 return returnstring; 182 182 }; 183 183 … … 186 186 * \return true - is a number, false - is not a valid number 187 187 */ 188 bool IsValidNumber( const char *string) 188 bool IsValidNumber( const char *string) 189 189 { 190 int ptr = 0;191 if ((string[ptr] == '.') || (string[ptr] == '-')) // number may be negative or start with dot192 ptr++;193 if ((string[ptr] >= '0') && (string[ptr] <= '9'))194 return true;195 return false;190 int ptr = 0; 191 if ((string[ptr] == '.') || (string[ptr] == '-')) // number may be negative or start with dot 192 ptr++; 193 if ((string[ptr] >= '0') && (string[ptr] <= '9')) 194 return true; 195 return false; 196 196 }; 197 197 -
src/helpers.hpp
rce5ac3 rd067d45 1 1 /** \file helpers.hpp 2 2 * 3 * Declaration of some auxiliary functions for memory dis-/allocation and so on 3 * Declaration of some auxiliary functions for memory dis-/allocation and so on 4 4 */ 5 5 … … 38 38 39 39 /* Behandelt aufgetretene Fehler. error ist der Fehlertyp(enum Errors) 40 void *SpecialData ist ein untypisierter Zeiger auf Spezielle Daten zur Fehlerbehandlung.41 Man koennte auch noch einen Zeiger auf eine Funktion uebergeben */40 void *SpecialData ist ein untypisierter Zeiger auf Spezielle Daten zur Fehlerbehandlung. 41 Man koennte auch noch einen Zeiger auf eine Funktion uebergeben */ 42 42 extern void /*@exits@*/ debug(const char *output); 43 //__attribute__ ((__return__));43 //__attribute__ ((__return__)); 44 44 #define debug(data) debug_in((data), __FILE__, __LINE__) 45 45 46 46 extern void /*@exits@*/ debug_in(const char *output, 47 const char *file, const int line);48 //__attribute__ ((__return__));47 const char *file, const int line); 48 //__attribute__ ((__return__)); 49 49 50 50 double ask_value(const char *text); … … 73 73 template <typename T> bool CreateFatherLookupTable(ofstream *out, T *start, T *end, T **&LookupTable, int count = 0) 74 74 { 75 bool status = true;76 T *Walker = NULL;77 int AtomNo;78 79 if (LookupTable != NULL) {80 *out << "Pointer for Lookup table is not NULL! Aborting ..." <<endl;81 return false;82 }83 84 // count them85 if (count == 0) {86 Walker = start;87 while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron 88 Walker = Walker->next;89 count = (count < Walker->GetTrueFather()->nr) ? Walker->GetTrueFather()->nr : count;90 }91 }92 if (count <= 0) {93 *out << "Count of lookup list is 0 or less." << endl;94 return false;95 }96 97 // allocat and fill98 LookupTable = (T **) Malloc(sizeof(T *)*count, "CreateFatherLookupTable - **LookupTable");99 if (LookupTable == NULL) {100 cerr << "LookupTable memory allocation failed!" << endl;101 status = false;102 } else {103 for (int i=0;i<count;i++)104 LookupTable[i] = NULL;105 Walker = start;106 while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron 107 Walker = Walker->next;108 AtomNo = Walker->GetTrueFather()->nr;109 if ((AtomNo >= 0) && (AtomNo < count)) {110 //*out << "Setting LookupTable[" << AtomNo << "] to " << *Walker << endl;111 LookupTable[AtomNo] = Walker;112 } else {113 *out << "Walker " << *Walker << " exceeded range of nuclear ids [0, " << count << ")." << endl; 114 status = false;115 break;116 }117 }118 }119 120 return status; 75 bool status = true; 76 T *Walker = NULL; 77 int AtomNo; 78 79 if (LookupTable != NULL) { 80 *out << "Pointer for Lookup table is not NULL! Aborting ..." <<endl; 81 return false; 82 } 83 84 // count them 85 if (count == 0) { 86 Walker = start; 87 while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron 88 Walker = Walker->next; 89 count = (count < Walker->GetTrueFather()->nr) ? Walker->GetTrueFather()->nr : count; 90 } 91 } 92 if (count <= 0) { 93 *out << "Count of lookup list is 0 or less." << endl; 94 return false; 95 } 96 97 // allocat and fill 98 LookupTable = (T **) Malloc(sizeof(T *)*count, "CreateFatherLookupTable - **LookupTable"); 99 if (LookupTable == NULL) { 100 cerr << "LookupTable memory allocation failed!" << endl; 101 status = false; 102 } else { 103 for (int i=0;i<count;i++) 104 LookupTable[i] = NULL; 105 Walker = start; 106 while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron 107 Walker = Walker->next; 108 AtomNo = Walker->GetTrueFather()->nr; 109 if ((AtomNo >= 0) && (AtomNo < count)) { 110 //*out << "Setting LookupTable[" << AtomNo << "] to " << *Walker << endl; 111 LookupTable[AtomNo] = Walker; 112 } else { 113 *out << "Walker " << *Walker << " exceeded range of nuclear ids [0, " << count << ")." << endl; 114 status = false; 115 break; 116 } 117 } 118 } 119 120 return status; 121 121 }; 122 122 … … 129 129 template <typename X> void link(X *walker, X *end) 130 130 { 131 X *vorher = end->previous;132 if (vorher != NULL)133 vorher->next = walker;134 end->previous = walker;135 walker->previous = vorher;136 walker->next = end;131 X *vorher = end->previous; 132 if (vorher != NULL) 133 vorher->next = walker; 134 end->previous = walker; 135 walker->previous = vorher; 136 walker->next = end; 137 137 }; 138 138 … … 143 143 template <typename X> void unlink(X *walker) 144 144 { 145 if (walker->next != NULL) 146 walker->next->previous = walker->previous;147 if (walker->previous != NULL)148 walker->previous->next = walker->next;145 if (walker->next != NULL) 146 walker->next->previous = walker->previous; 147 if (walker->previous != NULL) 148 walker->previous->next = walker->next; 149 149 }; 150 150 151 151 /** Adds new item before an item \a *end in a list. 152 * \param *pointer item to be added153 * \param *end end of list152 * \param *pointer item to be added 153 * \param *end end of list 154 154 * \return true - addition succeeded, false - unable to add item to list 155 155 */ 156 template <typename X> bool add(X *pointer, X *end)157 { 158 if (end != NULL) {159 link(pointer, end);160 } else {161 pointer->previous = NULL;162 pointer->next = NULL; 163 }164 return true;156 template <typename X> bool add(X *pointer, X *end) 157 { 158 if (end != NULL) { 159 link(pointer, end); 160 } else { 161 pointer->previous = NULL; 162 pointer->next = NULL; 163 } 164 return true; 165 165 }; 166 166 167 167 /** Finds item in list 168 * \param *suche search criteria169 * \param *start begin of list170 * \param *end end of list168 * \param *suche search criteria 169 * \param *start begin of list 170 * \param *end end of list 171 171 * \return X - if found, NULL - if not found 172 172 */ 173 173 template <typename X, typename Y> X * find(Y *suche, X *start, X *end) 174 174 { 175 X *walker = start;176 while (walker->next != end) { // go through list177 walker = walker->next; // step onward beforehand178 if (*walker->sort == *suche) return (walker);179 }180 return NULL;175 X *walker = start; 176 while (walker->next != end) { // go through list 177 walker = walker->next; // step onward beforehand 178 if (*walker->sort == *suche) return (walker); 179 } 180 return NULL; 181 181 }; 182 182 … … 187 187 template <typename X> void removewithoutcheck(X *walker) 188 188 { 189 if (walker != NULL) {190 unlink(walker);191 delete(walker);192 walker = NULL;193 }189 if (walker != NULL) { 190 unlink(walker); 191 delete(walker); 192 walker = NULL; 193 } 194 194 }; 195 195 196 196 /** Removes an item from the list, checks if exists. 197 197 * Checks beforehand if atom is really within molecule list. 198 * \param *pointer item to be removed199 * \param *start begin of list200 * \param *end end of list198 * \param *pointer item to be removed 199 * \param *start begin of list 200 * \param *end end of list 201 201 * \return true - removing succeeded, false - given item not found in list 202 202 */ 203 203 template <typename X> bool remove(X *pointer, X *start, X *end) 204 204 { 205 X *walker = find (pointer->sort, start, end);206 /* while (walker->next != pointer) { // search through list207 walker = walker->next;208 if (walker == end) return false;// item not found in list209 }*/210 // atom found, now unlink211 if (walker != NULL)212 removewithoutcheck(walker);213 else214 return false;215 return true;205 X *walker = find (pointer->sort, start, end); 206 /* while (walker->next != pointer) { // search through list 207 walker = walker->next; 208 if (walker == end) return false; // item not found in list 209 }*/ 210 // atom found, now unlink 211 if (walker != NULL) 212 removewithoutcheck(walker); 213 else 214 return false; 215 return true; 216 216 }; 217 217 … … 223 223 template <typename X> bool cleanup(X *start, X *end) 224 224 { 225 X *pointer = start->next;226 X *walker;227 while (pointer != end) { // go through list228 walker = pointer; // mark current229 pointer = pointer->next; // step onward beforehand230 // remove walker231 unlink(walker);232 delete(walker);233 walker = NULL;234 }235 return true;225 X *pointer = start->next; 226 X *walker; 227 while (pointer != end) { // go through list 228 walker = pointer; // mark current 229 pointer = pointer->next; // step onward beforehand 230 // remove walker 231 unlink(walker); 232 delete(walker); 233 walker = NULL; 234 } 235 return true; 236 236 }; 237 237 … … 242 242 template <typename X> X *GetFirst(X *me) 243 243 { 244 X *Binder = me;245 while(Binder->previous != NULL)246 Binder = Binder->previous;247 return Binder;248 }; 244 X *Binder = me; 245 while(Binder->previous != NULL) 246 Binder = Binder->previous; 247 return Binder; 248 }; 249 249 250 250 /** Returns the last marker in a chain list. … … 254 254 template <typename X> X *GetLast(X *me) 255 255 { 256 X *Binder = me;257 while(Binder->next != NULL)258 Binder = Binder->next;259 return Binder;260 }; 256 X *Binder = me; 257 while(Binder->next != NULL) 258 Binder = Binder->next; 259 return Binder; 260 }; 261 261 262 262 /** Frees a two-dimensional array. … … 266 266 template <typename X> void Free2DArray(X **ptr, int dim) 267 267 { 268 int i;269 if (ptr != NULL) {270 for(i=dim;i--;)271 if (ptr[i] != NULL)272 free(ptr[i]);273 free(ptr);274 }268 int i; 269 if (ptr != NULL) { 270 for(i=dim;i--;) 271 if (ptr[i] != NULL) 272 free(ptr[i]); 273 free(ptr); 274 } 275 275 }; 276 276 … … 281 281 class Verbose 282 282 { 283 public:284 Verbose(int value) : Verbosity(value) { }285 286 ostream& print (ostream &ost) const;287 private:288 int Verbosity;283 public: 284 Verbose(int value) : Verbosity(value) { } 285 286 ostream& print (ostream &ost) const; 287 private: 288 int Verbosity; 289 289 }; 290 290 … … 295 295 class Binary 296 296 { 297 public:298 Binary(int value) : BinaryNumber(value) { }299 300 ostream& print (ostream &ost) const;301 private:302 int BinaryNumber;297 public: 298 Binary(int value) : BinaryNumber(value) { } 299 300 ostream& print (ostream &ost) const; 301 private: 302 int BinaryNumber; 303 303 }; 304 304 -
src/joiner.cpp
rce5ac3 rd067d45 2 2 * 3 3 * Takes evaluated fragments (energy and forces) and by reading the factors files determines total energy 4 * and each force for the whole molecule. 5 * 4 * and each force for the whole molecule. 5 * 6 6 */ 7 7 8 8 //============================ INCLUDES =========================== 9 9 10 #include "datacreator.hpp" 11 #include "helpers.hpp" 12 #include "parser.hpp" 13 #include "periodentafel.hpp" 10 #include "datacreator.hpp" 11 #include "helpers.hpp" 12 #include "parser.hpp" 13 #include "periodentafel.hpp" 14 14 15 15 //============================== MAIN ============================= … … 46 46 cout << "Joiner" << endl; 47 47 cout << "======" << endl; 48 48 49 49 // Get the command line options 50 50 if (argc < 3) { … … 63 63 periode->LoadPeriodentafel(argv[3]); 64 64 } 65 65 66 66 // Test the given directory 67 67 if (!TestParams(argc, argv)) 68 68 return 1; 69 69 70 70 // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++ 71 71 72 72 // ------------- Parse through all Fragment subdirs -------- 73 73 if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix, 0,0)) return 1; … … 124 124 if (!ChiPASFragments.AllocateMatrix(ChiPAS.Header, ChiPAS.MatrixCounter, ChiPAS.RowCounter, ChiPAS.ColumnCounter)) return 1; 125 125 } 126 126 127 127 // ----------- Resetting last matrices (where full QM values are stored right now) 128 128 if(!Energy.SetLastMatrix(0., 0)) return 1; … … 237 237 } 238 238 239 // exit 239 // exit 240 240 delete(periode); 241 241 Free((void **)&dir, "main: *dir"); -
src/moleculelist.cpp
rce5ac3 rd067d45 1 1 /** \file MoleculeListClass.cpp 2 * 2 * 3 3 * Function implementations for the class MoleculeListClass. 4 * 4 * 5 5 */ 6 6 … … 13 13 MoleculeListClass::MoleculeListClass() 14 14 { 15 }; 16 17 /** constructor for MoleculeListClass. 18 * \param NumMolecules number of molecules to allocate for 19 * \param NumAtoms number of atoms to allocate for 20 */ 21 MoleculeListClass::MoleculeListClass(int NumMolecules, int NumAtoms) 22 { 23 ListOfMolecules = (molecule **) Malloc(sizeof(molecule *)*NumMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules"); 24 for (int i=NumMolecules;i--;) 25 ListOfMolecules[i] = NULL; 26 NumberOfMolecules = NumMolecules; 27 NumberOfTopAtoms = NumAtoms; 28 }; 29 15 // empty lists 16 ListOfMolecules.clear(); 17 MaxIndex = 1; 18 }; 30 19 31 20 /** Destructor for MoleculeListClass. … … 34 23 { 35 24 cout << Verbose(3) << this << ": Freeing ListOfMolcules." << endl; 36 for (int i=NumberOfMolecules;i--;) { 37 if (ListOfMolecules[i] != NULL) { // if NULL don't free 38 cout << Verbose(4) << "ListOfMolecules: Freeing " << ListOfMolecules[i] << "." << endl; 39 delete(ListOfMolecules[i]); 40 ListOfMolecules[i] = NULL; 41 } 25 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) { 26 cout << Verbose(4) << "ListOfMolecules: Freeing " << *ListRunner << "." << endl; 27 delete (*ListRunner); 42 28 } 43 29 cout << Verbose(4) << "Freeing ListOfMolecules." << endl; 44 Free((void **)&ListOfMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules"); 30 ListOfMolecules.clear(); // empty list 31 }; 32 33 /** Insert a new molecule into the list and set its number. 34 * \param *mol molecule to add to list. 35 * \return true - add successful 36 */ 37 void MoleculeListClass::insert(molecule *mol) 38 { 39 mol->IndexNr = MaxIndex++; 40 ListOfMolecules.push_back(mol); 45 41 }; 46 42 … … 57 53 atom *aWalker = NULL; 58 54 atom *bWalker = NULL; 59 55 60 56 // sort each atom list and put the numbers into a list, then go through 61 57 //cout << "Comparing fragment no. " << *(molecule **)a << " to " << *(molecule **)b << "." << endl; 62 if ( (**(molecule **)a).AtomCount < (**(molecule **)b).AtomCount) {58 if ((**(molecule **) a).AtomCount < (**(molecule **) b).AtomCount) { 63 59 return -1; 64 } else { if ((**(molecule **)a).AtomCount > (**(molecule **)b).AtomCount) 65 return +1; 60 } else { 61 if ((**(molecule **) a).AtomCount > (**(molecule **) b).AtomCount) 62 return +1; 66 63 else { 67 Count = (**(molecule **) a).AtomCount;64 Count = (**(molecule **) a).AtomCount; 68 65 aList = new int[Count]; 69 66 bList = new int[Count]; 70 67 71 68 // fill the lists 72 aWalker = (**(molecule **) a).start;73 bWalker = (**(molecule **) b).start;69 aWalker = (**(molecule **) a).start; 70 bWalker = (**(molecule **) b).start; 74 71 Counter = 0; 75 72 aCounter = 0; 76 73 bCounter = 0; 77 while ((aWalker->next != (**(molecule **) a).end) && (bWalker->next != (**(molecule **)b).end)) {74 while ((aWalker->next != (**(molecule **) a).end) && (bWalker->next != (**(molecule **) b).end)) { 78 75 aWalker = aWalker->next; 79 76 bWalker = bWalker->next; … … 90 87 // check if AtomCount was for real 91 88 flag = 0; 92 if ((aWalker->next == (**(molecule **) a).end) && (bWalker->next != (**(molecule **)b).end)) {89 if ((aWalker->next == (**(molecule **) a).end) && (bWalker->next != (**(molecule **) b).end)) { 93 90 flag = -1; 94 91 } else { 95 if ((aWalker->next != (**(molecule **) a).end) && (bWalker->next == (**(molecule **)b).end))92 if ((aWalker->next != (**(molecule **) a).end) && (bWalker->next == (**(molecule **) b).end)) 96 93 flag = 1; 97 94 } 98 95 if (flag == 0) { 99 96 // sort the lists 100 gsl_heapsort(aList, Count, sizeof(int), CompareDoubles);101 gsl_heapsort(bList, Count, sizeof(int), CompareDoubles);102 // compare the lists 103 97 gsl_heapsort(aList, Count, sizeof(int), CompareDoubles); 98 gsl_heapsort(bList, Count, sizeof(int), CompareDoubles); 99 // compare the lists 100 104 101 flag = 0; 105 for (int i=0;i<Count;i++) {102 for (int i = 0; i < Count; i++) { 106 103 if (aList[i] < bList[i]) { 107 104 flag = -1; … … 114 111 } 115 112 } 116 delete[] (aList);117 delete[] (bList);113 delete[] (aList); 114 delete[] (bList); 118 115 return flag; 119 116 } 120 117 } 121 return -1; 118 return -1; 119 }; 120 121 /** Output of a list of all molecules. 122 * \param *out output stream 123 */ 124 void MoleculeListClass::Enumerate(ofstream *out) 125 { 126 element* Elemental = NULL; 127 atom *Walker = NULL; 128 int Counts[MAX_ELEMENTS]; 129 double size=0; 130 Vector Origin; 131 132 // header 133 *out << "Index\tName\t\tAtoms\tFormula\tCenter\tSize" << endl; 134 cout << Verbose(0) << "-----------------------------------------------" << endl; 135 if (ListOfMolecules.size() == 0) 136 *out << "\tNone" << endl; 137 else { 138 Origin.Zero(); 139 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) { 140 // reset element counts 141 for (int j = 0; j<MAX_ELEMENTS;j++) 142 Counts[j] = 0; 143 // count atoms per element and determine size of bounding sphere 144 size=0.; 145 Walker = (*ListRunner)->start; 146 while (Walker->next != (*ListRunner)->end) { 147 Walker = Walker->next; 148 Counts[Walker->type->Z]++; 149 if (Walker->x.DistanceSquared(&Origin) > size) 150 size = Walker->x.DistanceSquared(&Origin); 151 } 152 // output Index, Name, number of atoms, chemical formula 153 *out << ((*ListRunner)->ActiveFlag ? "*" : " ") << (*ListRunner)->IndexNr << "\t" << (*ListRunner)->name << "\t\t" << (*ListRunner)->AtomCount << "\t"; 154 Elemental = (*ListRunner)->elemente->end; 155 while(Elemental->previous != (*ListRunner)->elemente->start) { 156 Elemental = Elemental->previous; 157 if (Counts[Elemental->Z] != 0) 158 *out << Elemental->symbol << Counts[Elemental->Z]; 159 } 160 // Center and size 161 *out << "\t" << (*ListRunner)->Center << "\t" << sqrt(size) << endl; 162 } 163 } 164 }; 165 166 /** Returns the molecule with the given index \a index. 167 * \param index index of the desired molecule 168 * \return pointer to molecule structure, NULL if not found 169 */ 170 molecule * MoleculeListClass::ReturnIndex(int index) 171 { 172 for(MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) 173 if ((*ListRunner)->IndexNr == index) 174 return (*ListRunner); 175 return NULL; 176 }; 177 178 /** Simple merge of two molecules into one. 179 * \param *mol destination molecule 180 * \param *srcmol source molecule 181 * \return true - merge successful, false - merge failed (probably due to non-existant indices 182 */ 183 bool MoleculeListClass::SimpleMerge(molecule *mol, molecule *srcmol) 184 { 185 if (srcmol == NULL) 186 return false; 187 188 // put all molecules of src into mol 189 atom *Walker = srcmol->start; 190 atom *NextAtom = Walker->next; 191 while (NextAtom != srcmol->end) { 192 Walker = NextAtom; 193 NextAtom = Walker->next; 194 srcmol->UnlinkAtom(Walker); 195 mol->AddAtom(Walker); 196 } 197 198 // remove src 199 ListOfMolecules.remove(srcmol); 200 delete(srcmol); 201 return true; 202 }; 203 204 /** Simple add of one molecules into another. 205 * \param *mol destination molecule 206 * \param *srcmol source molecule 207 * \return true - merge successful, false - merge failed (probably due to non-existant indices 208 */ 209 bool MoleculeListClass::SimpleAdd(molecule *mol, molecule *srcmol) 210 { 211 if (srcmol == NULL) 212 return false; 213 214 // put all molecules of src into mol 215 atom *Walker = srcmol->start; 216 atom *NextAtom = Walker->next; 217 while (NextAtom != srcmol->end) { 218 Walker = NextAtom; 219 NextAtom = Walker->next; 220 Walker = mol->AddCopyAtom(Walker); 221 Walker->father = Walker; 222 } 223 224 return true; 225 }; 226 227 /** Simple merge of a given set of molecules into one. 228 * \param *mol destination molecule 229 * \param *src index of set of source molecule 230 * \param N number of source molecules 231 * \return true - merge successful, false - some merges failed (probably due to non-existant indices) 232 */ 233 bool MoleculeListClass::SimpleMultiMerge(molecule *mol, int *src, int N) 234 { 235 bool status = true; 236 // check presence of all source molecules 237 for (int i=0;i<N;i++) { 238 molecule *srcmol = ReturnIndex(src[i]); 239 status = status && SimpleMerge(mol, srcmol); 240 } 241 return status; 242 }; 243 244 /** Simple add of a given set of molecules into one. 245 * \param *mol destination molecule 246 * \param *src index of set of source molecule 247 * \param N number of source molecules 248 * \return true - merge successful, false - some merges failed (probably due to non-existant indices) 249 */ 250 bool MoleculeListClass::SimpleMultiAdd(molecule *mol, int *src, int N) 251 { 252 bool status = true; 253 // check presence of all source molecules 254 for (int i=0;i<N;i++) { 255 molecule *srcmol = ReturnIndex(src[i]); 256 status = status && SimpleAdd(mol, srcmol); 257 } 258 return status; 259 }; 260 261 /** Scatter merge of a given set of molecules into one. 262 * Scatter merge distributes the molecules in such a manner that they don't overlap. 263 * \param *mol destination molecule 264 * \param *src index of set of source molecule 265 * \param N number of source molecules 266 * \return true - merge successful, false - merge failed (probably due to non-existant indices 267 * \TODO find scatter center for each src molecule 268 */ 269 bool MoleculeListClass::ScatterMerge(molecule *mol, int *src, int N) 270 { 271 // check presence of all source molecules 272 for (int i=0;i<N;i++) { 273 // get pointer to src molecule 274 molecule *srcmol = ReturnIndex(src[i]); 275 if (srcmol == NULL) 276 return false; 277 } 278 // adapt each Center 279 for (int i=0;i<N;i++) { 280 // get pointer to src molecule 281 molecule *srcmol = ReturnIndex(src[i]); 282 //srcmol->Center.Zero(); 283 srcmol->Translate(&srcmol->Center); 284 } 285 // perform a simple multi merge 286 SimpleMultiMerge(mol, src, N); 287 return true; 288 }; 289 290 /** Embedding merge of a given set of molecules into one. 291 * Embedding merge inserts one molecule into the other. 292 * \param *mol destination molecule 293 * \param *srcmol source molecule 294 * \return true - merge successful, false - merge failed (probably due to non-existant indices 295 * \TODO find embedding center 296 */ 297 bool MoleculeListClass::EmbedMerge(molecule *mol, molecule *srcmol) 298 { 299 if (srcmol == NULL) 300 return false; 301 302 // calculate center for merge 303 srcmol->Center.CopyVector(mol->FindEmbeddingHole((ofstream *)&cout, srcmol)); 304 srcmol->Center.Zero(); 305 306 // perform simple merge 307 SimpleMerge(mol, srcmol); 308 return true; 122 309 }; 123 310 … … 127 314 void MoleculeListClass::Output(ofstream *out) 128 315 { 129 *out << Verbose(1) << "MoleculeList: ";130 for ( int i=0;i<NumberOfMolecules;i++)131 *out << ListOfMolecules[i]<< "\t";316 *out << Verbose(1) << "MoleculeList: "; 317 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) 318 *out << *ListRunner << "\t"; 132 319 *out << endl; 133 320 }; … … 145 332 atom *Runner = NULL; 146 333 double ***FitConstant = NULL, **correction = NULL; 147 int a, b;334 int a, b; 148 335 ofstream output; 149 336 ifstream input; … … 165 352 input.open(line.c_str()); 166 353 if (input == NULL) { 167 cerr << endl << "Unable to open " << line << ", is the directory correct?" << endl; 354 cerr << endl << "Unable to open " << line << ", is the directory correct?" 355 << endl; 168 356 return false; 169 357 } 170 a =0;171 b =-1; // we overcount by one358 a = 0; 359 b = -1; // we overcount by one 172 360 while (!input.eof()) { 173 361 input.getline(ParsedLine, 1023); 174 362 zeile.str(ParsedLine); 175 int i =0;363 int i = 0; 176 364 while (!zeile.eof()) { 177 365 zeile >> distance; 178 366 i++; 179 367 } 180 if (i > a) 181 a = i; 368 if (i > a) 369 a = i; 182 370 b++; 183 371 } 184 372 cout << "I recognized " << a << " columns and " << b << " rows, "; 185 373 input.close(); 186 374 187 375 // 0b. allocate memory for constants 188 FitConstant = (double ***) Malloc(sizeof(double **) *3, "MoleculeListClass::AddHydrogenCorrection: ***FitConstant");189 for (int k =0;k<3;k++) {190 FitConstant[k] = (double **) Malloc(sizeof(double *) *a, "MoleculeListClass::AddHydrogenCorrection: **FitConstant[]");191 for (int i =a;i--;) {192 FitConstant[k][i] = (double *) Malloc(sizeof(double) *b, "MoleculeListClass::AddHydrogenCorrection: *FitConstant[][]");376 FitConstant = (double ***) Malloc(sizeof(double **) * 3, "MoleculeListClass::AddHydrogenCorrection: ***FitConstant"); 377 for (int k = 0; k < 3; k++) { 378 FitConstant[k] = (double **) Malloc(sizeof(double *) * a, "MoleculeListClass::AddHydrogenCorrection: **FitConstant[]"); 379 for (int i = a; i--;) { 380 FitConstant[k][i] = (double *) Malloc(sizeof(double) * b, "MoleculeListClass::AddHydrogenCorrection: *FitConstant[][]"); 193 381 } 194 382 } 195 383 // 0c. parse in constants 196 for (int i =0;i<3;i++) {384 for (int i = 0; i < 3; i++) { 197 385 line = path; 198 386 line.append("/"); 199 387 line += FRAGMENTPREFIX; 200 sprintf(ParsedLine, "%d", i +1);388 sprintf(ParsedLine, "%d", i + 1); 201 389 line += ParsedLine; 202 390 line += FITCONSTANTSUFFIX; … … 206 394 return false; 207 395 } 208 int k = 0, l;396 int k = 0, l; 209 397 while ((!input.eof()) && (k < b)) { 210 398 input.getline(ParsedLine, 1023); … … 223 411 input.close(); 224 412 } 225 for (int k=0;k<3;k++) {413 for (int k = 0; k < 3; k++) { 226 414 cout << "Constants " << k << ":" << endl; 227 for (int j =0;j<b;j++) {228 for (int i =0;i<a;i++) {415 for (int j = 0; j < b; j++) { 416 for (int i = 0; i < a; i++) { 229 417 cout << FitConstant[k][i][j] << "\t"; 230 418 } … … 233 421 cout << endl; 234 422 } 235 423 236 424 // 0d. allocate final correction matrix 237 correction = (double **) Malloc(sizeof(double *) *a, "MoleculeListClass::AddHydrogenCorrection: **correction");238 for (int i =a;i--;)239 correction[i] = (double *) Malloc(sizeof(double) *b, "MoleculeListClass::AddHydrogenCorrection: *correction[]");240 425 correction = (double **) Malloc(sizeof(double *) * a, "MoleculeListClass::AddHydrogenCorrection: **correction"); 426 for (int i = a; i--;) 427 correction[i] = (double *) Malloc(sizeof(double) * b, "MoleculeListClass::AddHydrogenCorrection: *correction[]"); 428 241 429 // 1a. go through every molecule in the list 242 for (int i=NumberOfMolecules;i--;) {430 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) { 243 431 // 1b. zero final correction matrix 244 for (int k =a;k--;)245 for (int j =b;j--;)432 for (int k = a; k--;) 433 for (int j = b; j--;) 246 434 correction[k][j] = 0.; 247 435 // 2. take every hydrogen that is a saturated one 248 Walker = ListOfMolecules[i]->start;249 while (Walker->next != ListOfMolecules[i]->end) {436 Walker = (*ListRunner)->start; 437 while (Walker->next != (*ListRunner)->end) { 250 438 Walker = Walker->next; 251 //cout << Verbose(1) << "Walker: " << *Walker << " with first bond " << *ListOfMolecules[i]->ListOfBondsPerAtom[Walker->nr][0] << "." << endl; 252 if ((Walker->type->Z == 1) && ((Walker->father == NULL) || (Walker->father->type->Z != 1))) { // if it's a hydrogen 253 Runner = ListOfMolecules[i]->start; 254 while (Runner->next != ListOfMolecules[i]->end) { 439 //cout << Verbose(1) << "Walker: " << *Walker << " with first bond " << *(*Runner)->ListOfBondsPerAtom[Walker->nr][0] << "." << endl; 440 if ((Walker->type->Z == 1) && ((Walker->father == NULL) 441 || (Walker->father->type->Z != 1))) { // if it's a hydrogen 442 Runner = (*ListRunner)->start; 443 while (Runner->next != (*ListRunner)->end) { 255 444 Runner = Runner->next; 256 //cout << Verbose(2) << "Runner: " << *Runner << " with first bond " << * ListOfMolecules[i]->ListOfBondsPerAtom[Runner->nr][0] << "." << endl;445 //cout << Verbose(2) << "Runner: " << *Runner << " with first bond " << *(*Runner)->ListOfBondsPerAtom[Runner->nr][0] << "." << endl; 257 446 // 3. take every other hydrogen that is the not the first and not bound to same bonding partner 258 if ((Runner->type->Z == 1) && (Runner->nr > Walker->nr) && ( ListOfMolecules[i]->ListOfBondsPerAtom[Runner->nr][0]->GetOtherAtom(Runner) != ListOfMolecules[i]->ListOfBondsPerAtom[Walker->nr][0]->GetOtherAtom(Walker))) {// (hydrogens have only one bonding partner!)447 if ((Runner->type->Z == 1) && (Runner->nr > Walker->nr) && ((*ListRunner)->ListOfBondsPerAtom[Runner->nr][0]->GetOtherAtom(Runner) != (*ListRunner)->ListOfBondsPerAtom[Walker->nr][0]->GetOtherAtom(Walker))) { // (hydrogens have only one bonding partner!) 259 448 // 4. evaluate the morse potential for each matrix component and add up 260 distance = sqrt(Runner->x.Distance(&Walker->x));261 //cout << "Fragment " << i<< ": " << *Runner << "<= " << distance << "=>" << *Walker << ":" << endl;262 for (int k=0;k<a;k++) {263 for (int j =0;j<b;j++) {264 switch (k) {265 case 1:266 case 7:267 case 11:268 tmp = pow(FitConstant[0][k][j] * ( 1. - exp(-FitConstant[1][k][j] * (distance - FitConstant[2][k][j]) ) ),2);269 break;270 default:271 tmp = FitConstant[0][k][j] * pow( distance,FitConstant[1][k][j]) + FitConstant[2][k][j];449 distance = Runner->x.Distance(&Walker->x); 450 //cout << "Fragment " << (*ListRunner)->name << ": " << *Runner << "<= " << distance << "=>" << *Walker << ":" << endl; 451 for (int k = 0; k < a; k++) { 452 for (int j = 0; j < b; j++) { 453 switch (k) { 454 case 1: 455 case 7: 456 case 11: 457 tmp = pow(FitConstant[0][k][j] * (1. - exp(-FitConstant[1][k][j] * (distance - FitConstant[2][k][j]))), 2); 458 break; 459 default: 460 tmp = FitConstant[0][k][j] * pow(distance, FitConstant[1][k][j]) + FitConstant[2][k][j]; 272 461 }; 273 correction[k][j] -= tmp; // ground state is actually lower (disturbed by additional interaction)462 correction[k][j] -= tmp; // ground state is actually lower (disturbed by additional interaction) 274 463 //cout << tmp << "\t"; 275 464 } … … 285 474 line.append("/"); 286 475 line += FRAGMENTPREFIX; 287 FragmentNumber = FixedDigitNumber( NumberOfMolecules, i);476 FragmentNumber = FixedDigitNumber(ListOfMolecules.size(), (*ListRunner)->IndexNr); 288 477 line += FragmentNumber; 289 delete (FragmentNumber);478 delete (FragmentNumber); 290 479 line += HCORRECTIONSUFFIX; 291 480 output.open(line.c_str()); 292 481 output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl; 293 for (int j =0;j<b;j++) {294 for (int i=0;i<a;i++)482 for (int j = 0; j < b; j++) { 483 for (int i = 0; i < a; i++) 295 484 output << correction[i][j] << "\t"; 296 485 output << endl; … … 303 492 output.open(line.c_str()); 304 493 output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl; 305 for (int j =0;j<b;j++) {306 for (int i=0;i<a;i++)494 for (int j = 0; j < b; j++) { 495 for (int i = 0; i < a; i++) 307 496 output << 0 << "\t"; 308 497 output << endl; … … 310 499 output.close(); 311 500 // 6. free memory of parsed matrices 312 FitConstant = (double ***) Malloc(sizeof(double **) *a, "MoleculeListClass::AddHydrogenCorrection: ***FitConstant");313 for (int k =0;k<3;k++) {314 FitConstant[k] = (double **) Malloc(sizeof(double *) *a, "MoleculeListClass::AddHydrogenCorrection: **FitConstant[]");315 for (int i =a;i--;) {316 FitConstant[k][i] = (double *) Malloc(sizeof(double) *b, "MoleculeListClass::AddHydrogenCorrection: *FitConstant[][]");501 FitConstant = (double ***) Malloc(sizeof(double **) * a, "MoleculeListClass::AddHydrogenCorrection: ***FitConstant"); 502 for (int k = 0; k < 3; k++) { 503 FitConstant[k] = (double **) Malloc(sizeof(double *) * a, "MoleculeListClass::AddHydrogenCorrection: **FitConstant[]"); 504 for (int i = a; i--;) { 505 FitConstant[k][i] = (double *) Malloc(sizeof(double) * b, "MoleculeListClass::AddHydrogenCorrection: *FitConstant[][]"); 317 506 } 318 507 } … … 327 516 * \return true - file written successfully, false - writing failed 328 517 */ 329 bool MoleculeListClass::StoreForcesFile(ofstream *out, char *path, int *SortIndex) 518 bool MoleculeListClass::StoreForcesFile(ofstream *out, char *path, 519 int *SortIndex) 330 520 { 331 521 bool status = true; … … 342 532 //cout << Verbose(1) << "Final AtomicForcesList: "; 343 533 //output << prefix << "Forces" << endl; 344 for(int j=0;j<NumberOfMolecules;j++) { 345 //if (TEList[j] != 0) { 346 runner = ListOfMolecules[j]->elemente->start; 347 while (runner->next != ListOfMolecules[j]->elemente->end) { // go through every element 534 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) { 535 runner = (*ListRunner)->elemente->start; 536 while (runner->next != (*ListRunner)->elemente->end) { // go through every element 348 537 runner = runner->next; 349 if ( ListOfMolecules[j]->ElementsInMolecule[runner->Z]) { // if this element got atoms350 Walker = ListOfMolecules[j]->start;351 while (Walker->next != ListOfMolecules[j]->end) { // go through every atom of this element538 if ((*ListRunner)->ElementsInMolecule[runner->Z]) { // if this element got atoms 539 Walker = (*ListRunner)->start; 540 while (Walker->next != (*ListRunner)->end) { // go through every atom of this element 352 541 Walker = Walker->next; 353 542 if (Walker->type->Z == runner->Z) { 354 543 if ((Walker->GetTrueFather() != NULL) && (Walker->GetTrueFather() != Walker)) {// if there is a rea 355 544 //cout << "Walker is " << *Walker << " with true father " << *( Walker->GetTrueFather()) << ", it 356 ForcesFile << SortIndex[Walker->GetTrueFather()->nr] << "\t";357 } else // otherwise a -1 to indicate an added saturation hydrogen358 ForcesFile << "-1\t";359 }545 ForcesFile << SortIndex[Walker->GetTrueFather()->nr] << "\t"; 546 } else 547 // otherwise a -1 to indicate an added saturation hydrogen 548 ForcesFile << "-1\t"; 360 549 } 361 550 } 551 } 362 552 } 363 553 ForcesFile << endl; … … 370 560 } 371 561 ForcesFile.close(); 372 562 373 563 return status; 374 564 }; … … 382 572 * \return true - success (each file was written), false - something went wrong. 383 573 */ 384 bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, con st char *fragmentprefix, config *configuration, int *SortIndex, bool DoPeriodic, bool DoCentering)574 bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex) 385 575 { 386 576 ofstream outputFragment; … … 395 585 int FragmentCounter = 0; 396 586 ofstream output; 397 string basis("3-21G"); 398 587 399 588 // store the fragments as config and as xyz 400 for (int i=0;i<NumberOfMolecules;i++) {589 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) { 401 590 // save default path as it is changed for each fragment 402 591 path = configuration->GetDefaultPath(); … … 407 596 408 597 // correct periodic 409 if (DoPeriodic) 410 ListOfMolecules[i]->ScanForPeriodicCorrection(out); 598 (*ListRunner)->ScanForPeriodicCorrection(out); 411 599 412 600 // output xyz file 413 FragmentNumber = FixedDigitNumber( NumberOfMolecules, FragmentCounter++);414 sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, fragmentprefix, FragmentNumber);601 FragmentNumber = FixedDigitNumber(ListOfMolecules.size(), FragmentCounter++); 602 sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, FRAGMENTPREFIX, FragmentNumber); 415 603 outputFragment.open(FragmentName, ios::out); 416 *out << Verbose(2) << "Saving " << fragmentprefix << " No. " << FragmentNumber << "/" << FragmentCounter-1 << " as XYZ ...";417 if ((intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment)))604 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter - 1 << " as XYZ ..."; 605 if ((intermediateResult = (*ListRunner)->OutputXYZ(&outputFragment))) 418 606 *out << " done." << endl; 419 607 else … … 425 613 // list atoms in fragment for debugging 426 614 *out << Verbose(2) << "Contained atoms: "; 427 Walker = ListOfMolecules[i]->start;428 while (Walker->next != ListOfMolecules[i]->end) {615 Walker = (*ListRunner)->start; 616 while (Walker->next != (*ListRunner)->end) { 429 617 Walker = Walker->next; 430 618 *out << Walker->Name << " "; 431 619 } 432 620 *out << endl; 433 621 434 622 // center on edge 435 if (DoCentering) { 436 ListOfMolecules[i]->CenterEdge(out, &BoxDimension); 437 ListOfMolecules[i]->SetBoxDimension(&BoxDimension); // update Box of atoms by boundary 438 int j = -1; 439 for (int k=0;k<NDIM;k++) { 440 j += k+1; 441 BoxDimension.x[k] = 2.5* (configuration->GetIsAngstroem() ? 1. : 1./AtomicLengthToAngstroem); 442 ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.; 443 } 444 ListOfMolecules[i]->Translate(&BoxDimension); 445 } 623 (*ListRunner)->CenterEdge(out, &BoxDimension); 624 (*ListRunner)->SetBoxDimension(&BoxDimension); // update Box of atoms by boundary 625 int j = -1; 626 for (int k = 0; k < NDIM; k++) { 627 j += k + 1; 628 BoxDimension.x[k] = 2.5 * (configuration->GetIsAngstroem() ? 1. : 1. / AtomicLengthToAngstroem); 629 (*ListRunner)->cell_size[j] += BoxDimension.x[k] * 2.; 630 } 631 (*ListRunner)->Translate(&BoxDimension); 446 632 447 633 // also calculate necessary orbitals 448 ListOfMolecules[i]->CountElements(); // this is a bugfix, atoms should should actually be added correctly to this fragment449 ListOfMolecules[i]->CalculateOrbitals(*configuration);450 634 (*ListRunner)->CountElements(); // this is a bugfix, atoms should shoulds actually be added correctly to this fragment 635 (*ListRunner)->CalculateOrbitals(*configuration); 636 451 637 // change path in config 452 638 //strcpy(PathBackup, configuration->configpath); 453 sprintf(FragmentName, "%s/%s%s/", PathBackup, fragmentprefix, FragmentNumber);639 sprintf(FragmentName, "%s/%s%s/", PathBackup, FRAGMENTPREFIX, FragmentNumber); 454 640 configuration->SetDefaultPath(FragmentName); 455 641 456 642 // and save as config 457 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, fragmentprefix, FragmentNumber);458 *out << Verbose(2) << "Saving " << fragmentprefix << " No. " << FragmentNumber << "/" << FragmentCounter-1 << " as config ...";459 if ((intermediateResult = configuration->Save(FragmentName, ListOfMolecules[i]->elemente, ListOfMolecules[i])))643 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber); 644 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter - 1 << " as config ..."; 645 if ((intermediateResult = configuration->Save(FragmentName, (*ListRunner)->elemente, (*ListRunner)))) 460 646 *out << " done." << endl; 461 647 else … … 466 652 configuration->SetDefaultPath(PathBackup); 467 653 468 469 654 // and save as mpqc input file 470 sprintf(FragmentName, "%s/%s%s. in", configuration->configpath, fragmentprefix, FragmentNumber);471 *out << Verbose(2) << "Saving " << fragmentprefix << " No. " << FragmentNumber << "/" << FragmentCounter-1 << " as mpqc input ...";472 if ((intermediateResult = configuration->SaveMPQC(FragmentName, ListOfMolecules[i])))655 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber); 656 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter - 1 << " as mpqc input ..."; 657 if ((intermediateResult = configuration->SaveMPQC(FragmentName, (*ListRunner)))) 473 658 *out << " done." << endl; 474 659 else 475 660 *out << " failed." << endl; 476 661 477 662 result = result && intermediateResult; 478 663 //outputFragment.close(); 479 664 //outputFragment.clear(); 480 delete (FragmentNumber);665 delete (FragmentNumber); 481 666 //Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber"); 482 667 } 483 668 cout << " done." << endl; 484 669 485 670 // printing final number 486 671 *out << "Final number of fragments: " << FragmentCounter << "." << endl; 487 672 488 673 return result; 489 674 }; 675 676 /** Counts the number of molecules with the molecule::ActiveFlag set. 677 * \return number of molecules with ActiveFlag set to true. 678 */ 679 int MoleculeListClass::NumberOfActiveMolecules() 680 { 681 int count = 0; 682 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) 683 count += ((*ListRunner)->ActiveFlag ? 1 : 0); 684 return count; 685 }; 686 490 687 491 688 /******************************************* Class MoleculeLeafClass ************************************************/ … … 498 695 MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL) 499 696 { 500 // if (Up != NULL)501 // if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?502 // Up->DownLeaf = this;503 // UpLeaf = Up;504 // DownLeaf = NULL;697 // if (Up != NULL) 698 // if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf? 699 // Up->DownLeaf = this; 700 // UpLeaf = Up; 701 // DownLeaf = NULL; 505 702 Leaf = NULL; 506 703 previous = PreviousLeaf; … … 518 715 MoleculeLeafClass::~MoleculeLeafClass() 519 716 { 520 // if (DownLeaf != NULL) {// drop leaves further down521 // MoleculeLeafClass *Walker = DownLeaf;522 // MoleculeLeafClass *Next;523 // do {524 // Next = Walker->NextLeaf;525 // delete(Walker);526 // Walker = Next;527 // } while (Walker != NULL);528 // // Last Walker sets DownLeaf automatically to NULL529 // }717 // if (DownLeaf != NULL) {// drop leaves further down 718 // MoleculeLeafClass *Walker = DownLeaf; 719 // MoleculeLeafClass *Next; 720 // do { 721 // Next = Walker->NextLeaf; 722 // delete(Walker); 723 // Walker = Next; 724 // } while (Walker != NULL); 725 // // Last Walker sets DownLeaf automatically to NULL 726 // } 530 727 // remove the leaf itself 531 728 if (Leaf != NULL) { 532 delete (Leaf);729 delete (Leaf); 533 730 Leaf = NULL; 534 731 } 535 732 // remove this Leaf from level list 536 if (previous != NULL) 733 if (previous != NULL) 537 734 previous->next = next; 538 // } else { // we are first in list (connects to UpLeaf->DownLeaf)539 // if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))540 // NextLeaf->UpLeaf = UpLeaf; // either null as we are top level or the upleaf of the first node541 // if (UpLeaf != NULL)542 // UpLeaf->DownLeaf = NextLeaf; // either null as we are only leaf or NextLeaf if we are just the first543 // }544 // UpLeaf = NULL;735 // } else { // we are first in list (connects to UpLeaf->DownLeaf) 736 // if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL)) 737 // NextLeaf->UpLeaf = UpLeaf; // either null as we are top level or the upleaf of the first node 738 // if (UpLeaf != NULL) 739 // UpLeaf->DownLeaf = NextLeaf; // either null as we are only leaf or NextLeaf if we are just the first 740 // } 741 // UpLeaf = NULL; 545 742 if (next != NULL) // are we last in list 546 743 next->previous = previous; … … 581 778 return false; 582 779 } 583 780 584 781 if (status) { 585 *out << Verbose(1) << "Creating adjacency list for subgraph " << this << "." << endl; 782 *out << Verbose(1) << "Creating adjacency list for subgraph " << this 783 << "." << endl; 586 784 Walker = Leaf->start; 587 785 while (Walker->next != Leaf->end) { 588 786 Walker = Walker->next; 589 AtomNo = Walker->GetTrueFather()->nr; // global id of the current walker590 for (int i=0;i<reference->NumberOfBondsPerAtom[AtomNo];i++) { // go through father's bonds and copy them all787 AtomNo = Walker->GetTrueFather()->nr; // global id of the current walker 788 for (int i = 0; i < reference->NumberOfBondsPerAtom[AtomNo]; i++) { // go through father's bonds and copy them all 591 789 Binder = reference->ListOfBondsPerAtom[AtomNo][i]; 592 OtherWalker = ListOfLocalAtoms[FragmentCounter][Binder->GetOtherAtom(Walker->GetTrueFather())->nr]; // local copy of current bond partner of walker790 OtherWalker = ListOfLocalAtoms[FragmentCounter][Binder->GetOtherAtom(Walker->GetTrueFather())->nr]; // local copy of current bond partner of walker 593 791 if (OtherWalker != NULL) { 594 792 if (OtherWalker->nr > Walker->nr) 595 Leaf->AddBond(Walker, OtherWalker, Binder->BondDegree);793 Leaf->AddBond(Walker, OtherWalker, Binder->BondDegree); 596 794 } else { 597 795 *out << Verbose(1) << "OtherWalker = ListOfLocalAtoms[" << FragmentCounter << "][" << Binder->GetOtherAtom(Walker->GetTrueFather())->nr << "] is NULL!" << endl; … … 606 804 FragmentCounter--; 607 805 } 608 806 609 807 if ((FreeList) && (ListOfLocalAtoms != NULL)) { 610 808 // free the index lookup list 611 Free((void **) &ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::FillBondStructureFromReference - **ListOfLocalAtoms[]");809 Free((void **) &ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::FillBondStructureFromReference - **ListOfLocalAtoms[]"); 612 810 if (FragmentCounter == 0) // first fragments frees the initial pointer to list 613 Free((void **) &ListOfLocalAtoms, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");811 Free((void **) &ListOfLocalAtoms, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms"); 614 812 } 615 813 FragmentCounter--; … … 626 824 * \return true - stack is non-empty, fragmentation necessary, false - stack is empty, no more sites to update 627 825 */ 628 bool MoleculeLeafClass::FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter) 826 bool MoleculeLeafClass::FillRootStackForSubgraphs(ofstream *out, 827 KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter) 629 828 { 630 829 atom *Walker = NULL, *Father = NULL; 631 830 632 831 if (RootStack != NULL) { 633 // find first root candidates 832 // find first root candidates 634 833 if (&(RootStack[FragmentCounter]) != NULL) { 635 RootStack[FragmentCounter].clear(); 834 RootStack[FragmentCounter].clear(); 636 835 Walker = Leaf->start; 637 836 while (Walker->next != Leaf->end) { // go through all (non-hydrogen) atoms … … 639 838 Father = Walker->GetTrueFather(); 640 839 if (AtomMask[Father->nr]) // apply mask 641 #ifdef ADDHYDROGEN840 #ifdef ADDHYDROGEN 642 841 if (Walker->type->Z != 1) // skip hydrogen 643 #endif644 RootStack[FragmentCounter].push_front(Walker->nr);842 #endif 843 RootStack[FragmentCounter].push_front(Walker->nr); 645 844 } 646 845 if (next != NULL) 647 846 next->FillRootStackForSubgraphs(out, RootStack, AtomMask, ++FragmentCounter); 648 } else {649 *out << Verbose(1) << "Rootstack[" << FragmentCounter << "] is NULL." << endl;847 } else { 848 *out << Verbose(1) << "Rootstack[" << FragmentCounter << "] is NULL." << endl; 650 849 return false; 651 850 } … … 669 868 { 670 869 bool status = true; 671 870 672 871 int Counter = Count(); 673 872 if (ListOfLocalAtoms == NULL) { // allocated initial pointer 674 873 // allocate and set each field to NULL 675 ListOfLocalAtoms = (atom ***) Malloc(sizeof(atom **) *Counter, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");874 ListOfLocalAtoms = (atom ***) Malloc(sizeof(atom **) * Counter, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms"); 676 875 if (ListOfLocalAtoms != NULL) { 677 for (int i =Counter;i--;)876 for (int i = Counter; i--;) 678 877 ListOfLocalAtoms[i] = NULL; 679 878 FreeList = FreeList && true; … … 681 880 status = false; 682 881 } 683 882 684 883 if ((ListOfLocalAtoms != NULL) && (ListOfLocalAtoms[FragmentCounter] == NULL)) { // allocate and fill list of this fragment/subgraph 685 884 status = status && CreateFatherLookupTable(out, Leaf->start, Leaf->end, ListOfLocalAtoms[FragmentCounter], GlobalAtomCount); 686 885 FreeList = FreeList && true; 687 886 } 688 887 689 888 return status; 690 889 }; … … 700 899 * \retuen true - success, false - failure 701 900 */ 702 bool MoleculeLeafClass::AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList) 901 bool MoleculeLeafClass::AssignKeySetsToFragment(ofstream *out, 902 molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, 903 Graph **&FragmentList, int &FragmentCounter, bool FreeList) 703 904 { 704 905 bool status = true; 705 906 int KeySetCounter = 0; 706 907 707 908 *out << Verbose(1) << "Begin of AssignKeySetsToFragment." << endl; 708 909 // fill ListOfLocalAtoms if NULL was given … … 715 916 if (FragmentList == NULL) { 716 917 KeySetCounter = Count(); 717 FragmentList = (Graph **) Malloc(sizeof(Graph *) *KeySetCounter, "MoleculeLeafClass::AssignKeySetsToFragment - **FragmentList");718 for (int i=KeySetCounter;i--;)918 FragmentList = (Graph **) Malloc(sizeof(Graph *) * KeySetCounter, "MoleculeLeafClass::AssignKeySetsToFragment - **FragmentList"); 919 for (int i = KeySetCounter; i--;) 719 920 FragmentList[i] = NULL; 720 921 KeySetCounter = 0; 721 922 } 722 923 723 924 if ((KeySetList != NULL) && (KeySetList->size() != 0)) { // if there are some scanned keysets at all 724 925 // assign scanned keysets … … 726 927 FragmentList[FragmentCounter] = new Graph; 727 928 KeySet *TempSet = new KeySet; 728 for (Graph::iterator runner = KeySetList->begin();runner != KeySetList->end(); runner++) { // key sets contain global numbers!729 if ( ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*((*runner).first.begin()))->nr] != NULL) {// as we may assume that that bond structure is unchanged, we only test the first key in each set929 for (Graph::iterator runner = KeySetList->begin(); runner != KeySetList->end(); runner++) { // key sets contain global numbers! 930 if (ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*((*runner).first.begin()))->nr] != NULL) {// as we may assume that that bond structure is unchanged, we only test the first key in each set 730 931 // translate keyset to local numbers 731 for (KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)932 for (KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++) 732 933 TempSet->insert(ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*sprinter)->nr]->nr); 733 934 // insert into FragmentList 734 FragmentList[FragmentCounter]->insert(GraphPair (*TempSet, pair<int,double>(KeySetCounter++, (*runner).second.second)));935 FragmentList[FragmentCounter]->insert(GraphPair(*TempSet, pair<int, double> (KeySetCounter++, (*runner).second.second))); 735 936 } 736 937 TempSet->clear(); 737 938 } 738 delete (TempSet);939 delete (TempSet); 739 940 if (KeySetCounter == 0) {// if there are no keysets, delete the list 740 941 *out << Verbose(1) << "KeySetCounter is zero, deleting FragmentList." << endl; 741 delete (FragmentList[FragmentCounter]);942 delete (FragmentList[FragmentCounter]); 742 943 } else 743 944 *out << Verbose(1) << KeySetCounter << " keysets were assigned to subgraph " << FragmentCounter << "." << endl; … … 748 949 } else 749 950 *out << Verbose(1) << "KeySetList is NULL or empty." << endl; 750 951 751 952 if ((FreeList) && (ListOfLocalAtoms != NULL)) { 752 953 // free the index lookup list 753 Free((void **) &ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::AssignKeySetsToFragment - **ListOfLocalAtoms[]");954 Free((void **) &ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::AssignKeySetsToFragment - **ListOfLocalAtoms[]"); 754 955 if (FragmentCounter == 0) // first fragments frees the initial pointer to list 755 Free((void **) &ListOfLocalAtoms, "MoleculeLeafClass::AssignKeySetsToFragment - ***ListOfLocalAtoms");956 Free((void **) &ListOfLocalAtoms, "MoleculeLeafClass::AssignKeySetsToFragment - ***ListOfLocalAtoms"); 756 957 } 757 958 *out << Verbose(1) << "End of AssignKeySetsToFragment." << endl; … … 765 966 * \param &TotalNumberOfKeySets global key set counter 766 967 * \param &TotalGraph Graph to be filled with global numbers 767 */ 768 void MoleculeLeafClass::TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph) 968 */ 969 void MoleculeLeafClass::TranslateIndicesToGlobalIDs(ofstream *out, 970 Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, 971 Graph &TotalGraph) 769 972 { 770 973 *out << Verbose(1) << "Begin of TranslateIndicesToGlobalIDs." << endl; 771 974 KeySet *TempSet = new KeySet; 772 975 if (FragmentList[FragmentCounter] != NULL) { 773 for (Graph::iterator runner = FragmentList[FragmentCounter]->begin(); runner != FragmentList[FragmentCounter]->end(); runner++) {774 for (KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)976 for (Graph::iterator runner = FragmentList[FragmentCounter]->begin(); runner != FragmentList[FragmentCounter]->end(); runner++) { 977 for (KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++) 775 978 TempSet->insert((Leaf->FindAtom(*sprinter))->GetTrueFather()->nr); 776 TotalGraph.insert(GraphPair(*TempSet, pair<int, double>(TotalNumberOfKeySets++, (*runner).second.second)));979 TotalGraph.insert(GraphPair(*TempSet, pair<int, double> (TotalNumberOfKeySets++, (*runner).second.second))); 777 980 TempSet->clear(); 778 981 } 779 delete (TempSet);982 delete (TempSet); 780 983 } else { 781 984 *out << Verbose(1) << "FragmentList is NULL." << endl; … … 793 996 { 794 997 if (next != NULL) 795 return next->Count() +1;998 return next->Count() + 1; 796 999 else 797 return 1; 798 }; 1000 return 1; 1001 }; 1002 -
src/molecules.cpp
rce5ac3 rd067d45 62 62 cell_size[0] = cell_size[2] = cell_size[5]= 20.; 63 63 cell_size[1] = cell_size[3] = cell_size[4]= 0.; 64 strcpy(name,"none"); 65 IndexNr = -1; 66 ActiveFlag = false; 64 67 }; 65 68 … … 598 601 }; 599 602 603 /** Set molecule::name from the basename without suffix in the given \a *filename. 604 * \param *filename filename 605 */ 606 void molecule::SetNameFromFilename(const char *filename) 607 { 608 int length = 0; 609 char *molname = strrchr(filename, '/')+sizeof(char); // search for filename without dirs 610 char *endname = strchr(molname, '.'); 611 if ((endname == NULL) || (endname < molname)) 612 length = strlen(molname); 613 else 614 length = strlen(molname) - strlen(endname); 615 strncpy(name, molname, length); 616 name[length]='\0'; 617 }; 618 600 619 /** Sets the molecule::cell_size to the components of \a *dim (rectangular box) 601 620 * \param *dim vector class … … 652 671 max->Scale(0.5); 653 672 Translate(max); 673 Center.Zero(); 654 674 } 655 675 … … 691 711 max->AddVector(min); 692 712 Translate(min); 713 Center.Zero(); 693 714 } 694 715 delete(min); … … 700 721 * \param *center return vector for translation vector 701 722 */ 702 void molecule::CenterOrigin(ofstream *out , Vector *center)723 void molecule::CenterOrigin(ofstream *out) 703 724 { 704 725 int Num = 0; 705 726 atom *ptr = start->next; // start at first in list 706 727 707 for(int i=NDIM;i--;) // zero center vector 708 center->x[i] = 0.; 728 Center.Zero(); 709 729 710 730 if (ptr != end) { //list not empty? … … 712 732 ptr = ptr->next; 713 733 Num++; 714 center->AddVector(&ptr->x); 715 } 716 center->Scale(-1./Num); // divide through total number (and sign for direction) 717 Translate(center); 734 Center.AddVector(&ptr->x); 735 } 736 Center.Scale(-1./Num); // divide through total number (and sign for direction) 737 Translate(&Center); 738 Center.Zero(); 718 739 } 719 740 }; … … 780 801 * \param *center return vector for translation vector 781 802 */ 782 void molecule::CenterGravity(ofstream *out, Vector *center) 783 { 784 if (center == NULL) { 785 DetermineCenter(*center); 786 Translate(center); 787 delete(center); 788 } else { 789 Translate(center); 790 } 803 void molecule::CenterPeriodic(ofstream *out) 804 { 805 DeterminePeriodicCenter(Center); 806 }; 807 808 /** Centers the center of gravity of the atoms at (0,0,0). 809 * \param *out output stream for debugging 810 * \param *center return vector for translation vector 811 */ 812 void molecule::CenterAtVector(ofstream *out, Vector *newcenter) 813 { 814 Center.CopyVector(newcenter); 791 815 }; 792 816 … … 837 861 838 862 /** Determines center of molecule (yet not considering atom masses). 839 * \param Center reference to return vector840 */ 841 void molecule::Determine Center(Vector &Center)863 * \param center reference to return vector 864 */ 865 void molecule::DeterminePeriodicCenter(Vector ¢er) 842 866 { 843 867 atom *Walker = start; … … 849 873 850 874 do { 851 Center.Zero();875 center.Zero(); 852 876 flag = true; 853 877 while (Walker->next != end) { … … 876 900 Testvector.AddVector(&Translationvector); 877 901 Testvector.MatrixMultiplication(matrix); 878 Center.AddVector(&Testvector);902 center.AddVector(&Testvector); 879 903 cout << Verbose(1) << "vector is: "; 880 904 Testvector.Output((ofstream *)&cout); … … 889 913 Testvector.AddVector(&Translationvector); 890 914 Testvector.MatrixMultiplication(matrix); 891 Center.AddVector(&Testvector);915 center.AddVector(&Testvector); 892 916 cout << Verbose(1) << "Hydrogen vector is: "; 893 917 Testvector.Output((ofstream *)&cout); … … 900 924 } while (!flag); 901 925 Free((void **)&matrix, "molecule::DetermineCenter: *matrix"); 902 Center.Scale(1./(double)AtomCount);926 center.Scale(1./(double)AtomCount); 903 927 }; 904 928 … … 913 937 Vector *CenterOfGravity = DetermineCenterOfGravity(out); 914 938 915 Center Gravity(out, CenterOfGravity);939 CenterAtVector(out, CenterOfGravity); 916 940 917 941 // reset inertia tensor … … 1409 1433 bool molecule::LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration) 1410 1434 { 1435 molecule *mol = NULL; 1411 1436 bool status = true; 1412 1437 int MaxSteps = configuration.MaxOuterStep; 1413 MoleculeListClass *MoleculePerStep = new MoleculeListClass( MaxSteps+1, AtomCount);1438 MoleculeListClass *MoleculePerStep = new MoleculeListClass(); 1414 1439 // Get the Permutation Map by MinimiseConstrainedPotential 1415 1440 atom **PermutationMap = NULL; … … 1443 1468 *out << Verbose(1) << "Filling intermediate " << MaxSteps << " steps with MDSteps of " << MDSteps << "." << endl; 1444 1469 for (int step = 0; step <= MaxSteps; step++) { 1445 MoleculePerStep->ListOfMolecules[step] = new molecule(elemente); 1470 mol = new molecule(elemente); 1471 MoleculePerStep->insert(mol); 1446 1472 Walker = start; 1447 1473 while (Walker->next != end) { 1448 1474 Walker = Walker->next; 1449 1475 // add to molecule list 1450 Sprinter = MoleculePerStep->ListOfMolecules[step]->AddCopyAtom(Walker);1476 Sprinter = mol->AddCopyAtom(Walker); 1451 1477 for (int n=NDIM;n--;) { 1452 1478 Sprinter->x.x[n] = Trajectories[Walker].R.at(startstep).x[n] + (Trajectories[PermutationMap[Walker->nr]].R.at(endstep).x[n] - Trajectories[Walker].R.at(startstep).x[n])*((double)step/(double)MaxSteps); … … 1467 1493 for (int i=AtomCount; i--; ) 1468 1494 SortIndex[i] = i; 1469 status = MoleculePerStep->OutputConfigForListOfFragments(out, "ConstrainedStep", &configuration, SortIndex, false, false);1495 status = MoleculePerStep->OutputConfigForListOfFragments(out, &configuration, SortIndex); 1470 1496 1471 1497 // free and return … … 1828 1854 }; 1829 1855 1830 /** Removes atom from molecule list .1856 /** Removes atom from molecule list and deletes it. 1831 1857 * \param *pointer atom to be removed 1832 1858 * \return true - succeeded, false - atom not found in list … … 1842 1868 Trajectories.erase(pointer); 1843 1869 return remove(pointer, start, end); 1870 }; 1871 1872 /** Removes atom from molecule list, but does not delete it. 1873 * \param *pointer atom to be removed 1874 * \return true - succeeded, false - atom not found in list 1875 */ 1876 bool molecule::UnlinkAtom(atom *pointer) 1877 { 1878 if (pointer == NULL) 1879 return false; 1880 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1881 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1882 else 1883 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1884 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1885 ElementCount--; 1886 Trajectories.erase(pointer); 1887 unlink(pointer); 1888 return true; 1844 1889 }; 1845 1890 … … 2368 2413 }; 2369 2414 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices. 2370 2415 2371 2416 } 2372 2417 … … 2484 2529 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl; 2485 2530 /// \todo periodic check is missing here! 2486 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistance (&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;2531 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl; 2487 2532 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius; 2488 2533 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem; 2489 2534 MaxDistance = MinDistance + BONDTHRESHOLD; 2490 2535 MinDistance -= BONDTHRESHOLD; 2491 distance = OtherWalker->x.PeriodicDistance(&(Walker->x), cell_size);2536 distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size); 2492 2537 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller 2493 //*out << Verbose( 0) << "Adding Bond between " << *Walker << " and " << *OtherWalker<< "." << endl;2538 //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl; 2494 2539 AddBond(Walker->father, OtherWalker->father, 1); // also increases molecule::BondCount 2495 BondCount++;2496 2540 } else { 2497 2541 //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl; … … 2564 2608 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 2565 2609 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 2566 2610 2567 2611 // output bonds for debugging (if bond chain list was correctly installed) 2568 2612 *out << Verbose(1) << endl << "From contents of bond chain list:"; … … 3171 3215 cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl; 3172 3216 } 3173 //FragmentList->ListOfMolecules[NumberOfFragments++] = StoreFragmentFromKeySet(out, CurrentSet, IsAngstroem);3174 3217 } 3175 3218 } … … 3731 3774 //if (FragmentationToDo) { // we should always store the fragments again as coordination might have changed slightly without changing bond structure 3732 3775 // allocate memory for the pointer array and transmorph graphs into full molecular fragments 3733 BondFragments = new MoleculeListClass( TotalGraph.size(), AtomCount);3776 BondFragments = new MoleculeListClass(); 3734 3777 int k=0; 3735 3778 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) { 3736 3779 KeySet test = (*runner).first; 3737 3780 *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl; 3738 BondFragments-> ListOfMolecules[k] = StoreFragmentFromKeySet(out, test, configuration);3781 BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration)); 3739 3782 k++; 3740 3783 } 3741 *out << k << "/" << BondFragments-> NumberOfMolecules<< " fragments generated from the keysets." << endl;3784 *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl; 3742 3785 3743 3786 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3744 if (BondFragments-> NumberOfMolecules!= 0) {3787 if (BondFragments->ListOfMolecules.size() != 0) { 3745 3788 // create the SortIndex from BFS labels to order in the config file 3746 3789 CreateMappingLabelsToConfigSequence(out, SortIndex); 3747 3790 3748 *out << Verbose(1) << "Writing " << BondFragments-> NumberOfMolecules<< " possible bond fragmentation configs" << endl;3749 if (BondFragments->OutputConfigForListOfFragments(out, FRAGMENTPREFIX, configuration, SortIndex, true, true))3791 *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl; 3792 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) 3750 3793 *out << Verbose(1) << "All configs written." << endl; 3751 3794 else … … 5318 5361 if (result) { 5319 5362 *out << Verbose(5) << "Calculating Centers of Gravity" << endl; 5320 Determine Center(CenterOfGravity);5321 OtherMolecule->Determine Center(OtherCenterOfGravity);5363 DeterminePeriodicCenter(CenterOfGravity); 5364 OtherMolecule->DeterminePeriodicCenter(OtherCenterOfGravity); 5322 5365 *out << Verbose(5) << "Center of Gravity: "; 5323 5366 CenterOfGravity.Output(out); … … 5325 5368 OtherCenterOfGravity.Output(out); 5326 5369 *out << endl; 5327 if (CenterOfGravity.Distance (&OtherCenterOfGravity) >threshold) {5370 if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) { 5328 5371 *out << Verbose(4) << "Centers of gravity don't match." << endl; 5329 5372 result = false; … … 5339 5382 while (Walker->next != end) { 5340 5383 Walker = Walker->next; 5341 Distances[Walker->nr] = CenterOfGravity.Distance (&Walker->x);5384 Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x); 5342 5385 } 5343 5386 Walker = OtherMolecule->start; 5344 5387 while (Walker->next != OtherMolecule->end) { 5345 5388 Walker = Walker->next; 5346 OtherDistances[Walker->nr] = OtherCenterOfGravity.Distance (&Walker->x);5389 OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x); 5347 5390 } 5348 5391 … … 5362 5405 flag = 0; 5363 5406 for (int i=0;i<AtomCount;i++) { 5364 *out << Verbose(5) << "Distances : |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " << threshold << endl;5365 if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold )5407 *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " << threshold << endl; 5408 if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold) 5366 5409 flag = 1; 5367 5410 } -
src/molecules.hpp
rce5ac3 rd067d45 71 71 #define DistanceMultiMapPair pair <double, pair < PointMap::iterator, PointMap::iterator> > 72 72 73 #define MoleculeList list <molecule *> 74 #define MoleculeListTest pair <MoleculeList::iterator, bool> 75 73 76 /******************************** Some small functions and/or structures **********************************/ 74 77 … … 116 119 element *type; 117 120 }; 118 119 120 121 121 122 /** Single atom. … … 131 132 atom *father; //!< In many-body bond order fragmentations points to originating atom 132 133 atom *Ancestor; //!< "Father" in Depth-First-Search 133 char *Name; //!< unique name used during many-body bond-order fragmentation134 char *Name; //!< unique name used during many-body bond-order fragmentation 134 135 int FixedIon; //!< config variable that states whether forces act on the ion or not 135 136 int *sort; //!< sort criteria … … 146 147 ~atom(); 147 148 148 bool Output(int ElementNo, int AtomNo, ofstream *out ) const;149 bool Output(int ElementNo, int AtomNo, ofstream *out, const char *comment = NULL) const; 149 150 bool OutputXYZLine(ofstream *out) const; 150 151 atom *GetTrueFather(); … … 163 164 class bond { 164 165 public: 165 atom *leftatom;//!< first bond partner166 atom *rightatom;//!< second bond partner166 atom *leftatom; //!< first bond partner 167 atom *rightatom; //!< second bond partner 167 168 bond *previous; //!< previous atom in molecule list 168 169 bond *next; //!< next atom in molecule list 169 int HydrogenBond;//!< Number of hydrogen atoms in the bond170 int BondDegree;//!< single, double, triple, ... bond170 int HydrogenBond; //!< Number of hydrogen atoms in the bond 171 int BondDegree; //!< single, double, triple, ... bond 171 172 int nr; //!< unique number in a molecule, updated by molecule::CreateAdjacencyList() 172 173 bool Cyclic; //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis() … … 218 219 int MDSteps; //!< The number of MD steps in Trajectories 219 220 int *NumberOfBondsPerAtom; //!< Number of Bonds each atom has 220 int AtomCount; //!< number of atoms, brought up-to-date by CountAtoms()221 int BondCount; //!< number of atoms, brought up-to-date by CountBonds()221 int AtomCount; //!< number of atoms, brought up-to-date by CountAtoms() 222 int BondCount; //!< number of atoms, brought up-to-date by CountBonds() 222 223 int ElementCount; //!< how many unique elements are therein 223 224 int ElementsInMolecule[MAX_ELEMENTS]; //!< list whether element (sorted by atomic number) is alread present or not 224 int NoNonHydrogen; //!< number of non-hydrogen atoms in molecule225 int NoNonHydrogen; //!< number of non-hydrogen atoms in molecule 225 226 int NoNonBonds; //!< number of non-hydrogen bonds in molecule 226 227 int NoCyclicBonds; //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis() 227 228 double BondDistance; //!< typical bond distance used in CreateAdjacencyList() and furtheron 229 bool ActiveFlag; //!< in a MoleculeListClass used to discern active from inactive molecules 230 Vector Center; //!< Center of molecule in a global box 231 char name[MAXSTRINGSIZE]; //!< arbitrary name 232 int IndexNr; //!< index of molecule in a MoleculeListClass 228 233 229 234 molecule(periodentafel *teil); … … 233 238 bool AddAtom(atom *pointer); 234 239 bool RemoveAtom(atom *pointer); 240 bool UnlinkAtom(atom *pointer); 235 241 bool CleanupMolecule(); 236 242 … … 253 259 bool CenterInBox(ofstream *out, Vector *BoxLengths); 254 260 void CenterEdge(ofstream *out, Vector *max); 255 void CenterOrigin(ofstream *out, Vector *max); 256 void CenterGravity(ofstream *out, Vector *max); 261 void CenterOrigin(ofstream *out); 262 void CenterPeriodic(ofstream *out); 263 void CenterAtVector(ofstream *out, Vector *newcenter); 257 264 void Translate(const Vector *x); 258 265 void Mirror(const Vector *x); 259 266 void Align(Vector *n); 260 267 void Scale(double **factor); 261 void Determine Center(Vector ¢er);268 void DeterminePeriodicCenter(Vector ¢er); 262 269 Vector * DetermineCenterOfGravity(ofstream *out); 263 270 Vector * DetermineCenterOfAll(ofstream *out); 271 void SetNameFromFilename(const char *filename); 264 272 void SetBoxDimension(Vector *dim); 265 273 double * ReturnFullMatrixforSymmetric(double *cell_size); 266 274 void ScanForPeriodicCorrection(ofstream *out); 267 void PrincipalAxisSystem(ofstream *out, bool DoRotate);268 double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem);269 270 275 bool VerletForceIntegration(ofstream *out, char *file, config &configuration); 271 276 void Thermostats(config &configuration, double ActualTemp, int Thermostat); 277 void PrincipalAxisSystem(ofstream *out, bool DoRotate); 278 double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem); 279 Vector* FindEmbeddingHole(ofstream *out, molecule *srcmol); 280 272 281 273 282 double ConstrainedPotential(ofstream *out, atom **permutation, int start, int end, double *constants, bool IsAngstroem); … … 315 324 /// -# BOSSANOVA 316 325 void FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize); 317 int PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet);326 int PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet); 318 327 bool BuildInducedSubgraph(ofstream *out, const molecule *Father); 319 328 molecule * StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem); … … 343 352 class MoleculeListClass { 344 353 public: 345 molecule **ListOfMolecules; //!< pointer list of fragment molecules to check for equality 346 int NumberOfMolecules; //!< Number of entries in \a **FragmentList and of to be returned one. 347 int NumberOfTopAtoms; //!< Number of atoms in the molecule from which all fragments originate 354 MoleculeList ListOfMolecules; //!< List of the contained molecules 355 int MaxIndex; 348 356 349 357 MoleculeListClass(); 350 MoleculeListClass(int Num, int NumAtoms);351 358 ~MoleculeListClass(); 352 359 353 /// Output configs.354 360 bool AddHydrogenCorrection(ofstream *out, char *path); 355 361 bool StoreForcesFile(ofstream *out, char *path, int *SortIndex); 356 bool OutputConfigForListOfFragments(ofstream *out, const char *fragmentprefix, config *configuration, int *SortIndex, bool DoPeriodic, bool DoCentering); 362 void insert(molecule *mol); 363 molecule * ReturnIndex(int index); 364 bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex); 365 int NumberOfActiveMolecules(); 366 void Enumerate(ofstream *out); 357 367 void Output(ofstream *out); 368 369 // merging of molecules 370 bool SimpleMerge(molecule *mol, molecule *srcmol); 371 bool SimpleAdd(molecule *mol, molecule *srcmol); 372 bool SimpleMultiMerge(molecule *mol, int *src, int N); 373 bool SimpleMultiAdd(molecule *mol, int *src, int N); 374 bool ScatterMerge(molecule *mol, int *src, int N); 375 bool EmbedMerge(molecule *mol, molecule *srcmol); 358 376 359 377 private: … … 479 497 bool Save(const char *filename, periodentafel *periode, molecule *mol) const; 480 498 bool SaveMPQC(const char *filename, molecule *mol) const; 481 void Edit( molecule *mol);499 void Edit(); 482 500 bool GetIsAngstroem() const; 483 501 char *GetDefaultPath() const; -
src/parser.cpp
rce5ac3 rd067d45 2 2 * 3 3 * Declarations of various class functions for the parsing of value files. 4 * 4 * 5 5 */ 6 6 7 7 // ======================================= INCLUDES ========================================== 8 8 9 #include "helpers.hpp" 9 #include "helpers.hpp" 10 10 #include "parser.hpp" 11 11 … … 25 25 { 26 26 ifstream input; 27 27 28 28 input.open(filename, ios::in); 29 29 if (input == NULL) { … … 145 145 * \param skiplines number of inital columns to skip 146 146 * \param MatrixNr index number in Matrix array to parse into 147 * \return parsing successful 147 * \return parsing successful 148 148 */ 149 149 bool MatrixContainer::ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr) … … 183 183 // scan rest for number of rows/lines 184 184 RowCounter[MatrixNr]=-1; // counts one line too much 185 while (!input.eof()) { 185 while (!input.eof()) { 186 186 input.getline(filename, 1023); 187 187 //cout << "Comparing: " << strncmp(filename,"MeanForce",9) << endl; … … 194 194 if (RowCounter[MatrixNr] == 0) 195 195 cerr << "RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from file " << name << ", this is probably an error!" << endl; 196 196 197 197 // allocate matrix if it's not zero dimension in one direction 198 198 if ((ColumnCounter[MatrixNr] > 0) && (RowCounter[MatrixNr] > -1)) { … … 233 233 /** Parsing a number of matrices. 234 234 * -# First, count the number of matrices by counting lines in KEYSETFILE 235 * -# Then, 235 * -# Then, 236 236 * -# construct the fragment number 237 237 * -# open the matrix file … … 241 241 * -# allocate matrix 242 242 * -# loop over found column and row counts and parse in each entry 243 * -# Finally, allocate one additional matrix (\a MatrixCounter) containing combined or temporary values 243 * -# Finally, allocate one additional matrix (\a MatrixCounter) containing combined or temporary values 244 244 * \param *name directory with files 245 245 * \param *prefix prefix of each matrix file … … 247 247 * \param skiplines number of inital lines to skip 248 248 * \param skiplines number of inital columns to skip 249 * \return parsing successful 249 * \return parsing successful 250 250 */ 251 251 bool MatrixContainer::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) … … 256 256 stringstream file; 257 257 string token; 258 258 259 259 // count the number of matrices 260 260 MatrixCounter = -1; // we count one too much … … 270 270 MatrixCounter++; 271 271 } 272 input.close(); 272 input.close(); 273 273 cout << "Determined " << MatrixCounter << " fragments." << endl; 274 274 275 275 cout << "Parsing through each fragment and retrieving " << prefix << suffix << "." << endl; 276 276 Header = (char **) ReAlloc(Header, sizeof(char *)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: **Header"); // one more each for the total molecule … … 421 421 if (m == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l]) { 422 422 m = l; 423 break; 423 break; 424 424 } 425 425 } … … 447 447 //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 448 } 449 449 450 450 return true; 451 451 }; … … 512 512 513 513 // ======================================= CLASS EnergyMatrix ============================= 514 515 /** Create a trivial energy index mapping. 516 * This just maps 1 to 1, 2 to 2 and so on for all fragments. 517 * \return creation sucessful 518 */ 519 bool EnergyMatrix::ParseIndices() 520 { 521 cout << "Parsing energy indices." << endl; 522 Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "EnergyMatrix::ParseIndices: **Indices"); 523 for(int i=MatrixCounter+1;i--;) { 524 Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "EnergyMatrix::ParseIndices: *Indices[]"); 525 for(int j=RowCounter[i];j--;) 526 Indices[i][j] = j; 527 } 528 return true; 529 }; 514 530 515 531 /** Sums the energy with each factor and put into last element of \a EnergyMatrix::Matrix. … … 545 561 * \param skiplines number of inital columns to skip 546 562 * \return parsing successful 547 */ 563 */ 548 564 bool EnergyMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) 549 565 { … … 580 596 /** Parsing force Indices of each fragment 581 597 * \param *name directory with \a ForcesFile 582 * \return parsing successful 583 */ 584 bool ForceMatrix::ParseIndices(char *name) 598 * \return parsing successful 599 */ 600 bool ForceMatrix::ParseIndices(char *name) 585 601 { 586 602 ifstream input; … … 588 604 char filename[1023]; 589 605 stringstream line; 590 606 591 607 cout << "Parsing force indices for " << MatrixCounter << " matrices." << endl; 592 608 Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "ForceMatrix::ParseIndices: **Indices"); … … 659 675 * \param skiplines number of inital columns to skip 660 676 * \return parsing successful 661 */ 677 */ 662 678 bool ForceMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) 663 679 { … … 932 948 ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter); 933 949 } 934 950 935 951 936 952 return status; … … 974 990 stringstream file; 975 991 char filename[1023]; 976 992 977 993 FragmentCounter = FCounter; 978 994 cout << "Parsing key sets." << endl; … … 986 1002 return false; 987 1003 } 988 1004 989 1005 AtomCounter = (int *) Malloc(sizeof(int)*FragmentCounter, "KeySetsContainer::ParseKeySets: *RowCounter"); 990 1006 for(int i=0;(i<FragmentCounter) && (!input.eof());i++) { … … 1016 1032 { 1017 1033 int Counter; 1018 1034 1019 1035 cout << "Creating Fragment terms." << endl; 1020 1036 // scan through all to determine maximum order … … 1029 1045 } 1030 1046 cout << "Found Order is " << Order << "." << endl; 1031 1047 1032 1048 // scan through all to determine fragments per order 1033 1049 FragmentsPerOrder = (int *) Malloc(sizeof(int)*Order, "KeySetsContainer::ParseManyBodyTerms: *FragmentsPerOrder"); … … 1043 1059 for(int i=0;i<Order;i++) 1044 1060 cout << "Found No. of Fragments of Order " << i+1 << " is " << FragmentsPerOrder[i] << "." << endl; 1045 1061 1046 1062 // scan through all to gather indices to each order set 1047 1063 OrderSet = (int **) Malloc(sizeof(int *)*Order, "KeySetsContainer::ParseManyBodyTerms: **OrderSet"); … … 1066 1082 } 1067 1083 cout << endl; 1068 1069 1084 1085 1070 1086 return true; 1071 1087 }; -
src/parser.hpp
rce5ac3 rd067d45 2 2 * 3 3 * Definitions of various class functions for the parsing of value files. 4 * 4 * 5 5 */ 6 6 … … 71 71 bool WriteTotalFragments(const char *name, const char *prefix); 72 72 bool WriteLastMatrix(const char *name, const char *prefix, const char *suffix); 73 }; 73 }; 74 74 75 75 // ======================================= CLASS EnergyMatrix ============================= … … 77 77 class EnergyMatrix : public MatrixContainer { 78 78 public: 79 bool ParseIndices(); 79 80 bool SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign); 80 81 bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns); … … 84 85 85 86 class ForceMatrix : public MatrixContainer { 86 public: 87 public: 87 88 bool ParseIndices(char *name); 88 89 bool SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign); … … 114 115 int *FragmentsPerOrder; 115 116 int **OrderSet; 116 117 117 118 KeySetsContainer(); 118 119 ~KeySetsContainer(); 119 120 120 121 bool ParseKeySets(const char *name, const int *ACounter, const int FCounter); 121 122 bool ParseManyBodyTerms(); -
src/periodentafel.hpp
rce5ac3 rd067d45 21 21 */ 22 22 class element { 23 public:24 double mass;//!< mass in g/mol25 double CovalentRadius;//!< covalent radius26 double VanDerWaalsRadius;//!< can-der-Waals radius27 int Z;//!< atomic number28 char name[64];//!< atom name, i.e. "Hydrogren"29 char symbol[3]; //!< short form of the atom, i.e. "H"30 char period[8];//!< period: n quantum number31 char group[8];//!< group: l quantum number32 char block[8];//!< block: l quantum number33 element *previous;//!< previous item in list34 element *next;//!< next element in list35 int *sort;//!< sorc criteria36 int No;//!< number of element set on periodentafel::Output()37 double Valence;//!< number of valence electrons for this element38 int NoValenceOrbitals;//!< number of valence orbitals, used for determining bond degree in molecule::CreateConnectmatrix()39 double HBondDistance[NDIM]; //!< distance in Angstrom of this element to hydrogen(for single, double and triple bonds)40 double HBondAngle[NDIM];//!< typical angle for one, two, three bonded hydrogen (in degrees)23 public: 24 double mass; //!< mass in g/mol 25 double CovalentRadius; //!< covalent radius 26 double VanDerWaalsRadius; //!< can-der-Waals radius 27 int Z; //!< atomic number 28 char name[64]; //!< atom name, i.e. "Hydrogren" 29 char symbol[3]; //!< short form of the atom, i.e. "H" 30 char period[8]; //!< period: n quantum number 31 char group[8]; //!< group: l quantum number 32 char block[8]; //!< block: l quantum number 33 element *previous; //!< previous item in list 34 element *next; //!< next element in list 35 int *sort; //!< sorc criteria 36 int No; //!< number of element set on periodentafel::Output() 37 double Valence; //!< number of valence electrons for this element 38 int NoValenceOrbitals; //!< number of valence orbitals, used for determining bond degree in molecule::CreateConnectmatrix() 39 double HBondDistance[NDIM]; //!< distance in Angstrom of this element to hydrogen (for single, double and triple bonds) 40 double HBondAngle[NDIM]; //!< typical angle for one, two, three bonded hydrogen (in degrees) 41 41 42 element();43 ~element();42 element(); 43 ~element(); 44 44 45 //> print element entries to screen46 bool Output(ofstream *out) const;47 bool Checkout(ofstream *out, const int No, const int NoOfAtoms) const;48 49 private:45 //> print element entries to screen 46 bool Output(ofstream *out) const; 47 bool Checkout(ofstream *out, const int No, const int NoOfAtoms) const; 48 49 private: 50 50 }; 51 51 … … 53 53 */ 54 54 class periodentafel { 55 public:56 element *start; //!< start of element list57 element *end;//!< end of element list58 char header1[MAXSTRINGSIZE]; //!< store first header line59 char header2[MAXSTRINGSIZE]; //!< store second header line60 61 periodentafel();62 ~periodentafel(); 63 64 bool AddElement(element *pointer);65 bool RemoveElement(element *pointer);66 bool CleanupPeriodtable();67 element * FindElement(int Z);68 element * FindElement(char *shorthand) const;69 element * AskElement(); 70 bool Output(ofstream *output) const;71 bool Checkout(ofstream *output, const int *checkliste) const;72 bool LoadPeriodentafel(char *path = NULL);73 bool StorePeriodentafel(char *path = NULL) const;74 75 private:55 public: 56 element *start; //!< start of element list 57 element *end; //!< end of element list 58 char header1[MAXSTRINGSIZE]; //!< store first header line 59 char header2[MAXSTRINGSIZE]; //!< store second header line 60 61 periodentafel(); 62 ~periodentafel(); 63 64 bool AddElement(element *pointer); 65 bool RemoveElement(element *pointer); 66 bool CleanupPeriodtable(); 67 element * FindElement(int Z); 68 element * FindElement(char *shorthand) const; 69 element * AskElement(); 70 bool Output(ofstream *output) const; 71 bool Checkout(ofstream *output, const int *checkliste) const; 72 bool LoadPeriodentafel(char *path = NULL); 73 bool StorePeriodentafel(char *path = NULL) const; 74 75 private: 76 76 }; 77 77 -
src/stackclass.hpp
rce5ac3 rd067d45 10 10 */ 11 11 template <typename T> class StackClass { 12 public:13 StackClass<T>(int dimension);14 ~StackClass<T>();15 16 bool Push(T object);17 T PopFirst();18 T PopLast();19 bool RemoveItem(T ptr);20 void ClearStack();21 bool IsEmpty();22 bool IsFull();23 int ItemCount();24 void Output(ofstream *out) const;25 void TestImplementation(ofstream *out, T test);26 27 private:28 T *StackList;//!< the list containing the atom pointers29 int EntryCount;//!< number of entries in the stack30 int CurrentLastEntry;//!< Current last entry (newest item on stack)31 int CurrentFirstEntry;//!< Current first entry (oldest item on stack)32 int NextFreeField;//!< Current index of next free field12 public: 13 StackClass<T>(int dimension); 14 ~StackClass<T>(); 15 16 bool Push(T object); 17 T PopFirst(); 18 T PopLast(); 19 bool RemoveItem(T ptr); 20 void ClearStack(); 21 bool IsEmpty(); 22 bool IsFull(); 23 int ItemCount(); 24 void Output(ofstream *out) const; 25 void TestImplementation(ofstream *out, T test); 26 27 private: 28 T *StackList; //!< the list containing the atom pointers 29 int EntryCount; //!< number of entries in the stack 30 int CurrentLastEntry; //!< Current last entry (newest item on stack) 31 int CurrentFirstEntry; //!< Current first entry (oldest item on stack) 32 int NextFreeField; //!< Current index of next free field 33 33 }; 34 34 … … 37 37 template <typename T> StackClass<T>::StackClass(int dimension) 38 38 { 39 CurrentLastEntry = 0;40 CurrentFirstEntry = 0;41 NextFreeField = 0;42 EntryCount = dimension;43 StackList = (T *) Malloc(sizeof(T)*EntryCount, "StackClass::StackClass: **StackList");39 CurrentLastEntry = 0; 40 CurrentFirstEntry = 0; 41 NextFreeField = 0; 42 EntryCount = dimension; 43 StackList = (T *) Malloc(sizeof(T)*EntryCount, "StackClass::StackClass: **StackList"); 44 44 }; 45 45 … … 48 48 template <typename T> StackClass<T>::~StackClass() 49 49 { 50 Free((void **)&StackList, "StackClass::StackClass: **StackList");50 Free((void **)&StackList, "StackClass::StackClass: **StackList"); 51 51 }; 52 52 … … 57 57 template <typename T> bool StackClass<T>::Push(T object) 58 58 { 59 if (!IsFull()) {// check whether free field is really not occupied60 StackList[NextFreeField] = object;61 CurrentLastEntry = NextFreeField;62 NextFreeField = (NextFreeField + 1) % EntryCount; // step on to next free field63 return true;64 } else {65 cerr << "ERROR: Stack is full, " << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tNextFreeField " << NextFreeField << "\tEntryCount " << EntryCount << "!" << endl;66 return false;67 }59 if (!IsFull()) { // check whether free field is really not occupied 60 StackList[NextFreeField] = object; 61 CurrentLastEntry = NextFreeField; 62 NextFreeField = (NextFreeField + 1) % EntryCount; // step on to next free field 63 return true; 64 } else { 65 cerr << "ERROR: Stack is full, " << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tNextFreeField " << NextFreeField << "\tEntryCount " << EntryCount << "!" << endl; 66 return false; 67 } 68 68 }; 69 69 … … 74 74 template <typename T> T StackClass<T>::PopFirst() 75 75 { 76 T Walker = NULL;77 if (!IsEmpty()) {78 Walker = StackList[CurrentFirstEntry];79 if (Walker == NULL)80 cerr << "ERROR: Stack's field is empty!" << endl;81 StackList[CurrentFirstEntry] = NULL;82 if (CurrentFirstEntry != CurrentLastEntry) { // hasn't last item been popped as well?83 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)84 } else {85 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)86 CurrentLastEntry = CurrentFirstEntry;87 }88 } else89 cerr << "ERROR: Stack is empty!" << endl; 90 return Walker;76 T Walker = NULL; 77 if (!IsEmpty()) { 78 Walker = StackList[CurrentFirstEntry]; 79 if (Walker == NULL) 80 cerr << "ERROR: Stack's field is empty!" << endl; 81 StackList[CurrentFirstEntry] = NULL; 82 if (CurrentFirstEntry != CurrentLastEntry) { // hasn't last item been popped as well? 83 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1) 84 } else { 85 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1) 86 CurrentLastEntry = CurrentFirstEntry; 87 } 88 } else 89 cerr << "ERROR: Stack is empty!" << endl; 90 return Walker; 91 91 }; 92 92 … … 97 97 template <typename T> T StackClass<T>::PopLast() 98 98 { 99 T Walker = NULL;100 if (!IsEmpty()) {101 Walker = StackList[CurrentLastEntry];102 StackList[CurrentLastEntry] = NULL;103 if (Walker == NULL)104 cerr << "ERROR: Stack's field is empty!" << endl;105 NextFreeField = CurrentLastEntry;106 if (CurrentLastEntry != CurrentFirstEntry)// has there been more than one item on stack107 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; // step back from current free field to last (modulo does not work in -1, thus go EntryCount-1 instead)108 } else {109 cerr << "ERROR: Stack is empty!" << endl;110 } 111 return Walker;99 T Walker = NULL; 100 if (!IsEmpty()) { 101 Walker = StackList[CurrentLastEntry]; 102 StackList[CurrentLastEntry] = NULL; 103 if (Walker == NULL) 104 cerr << "ERROR: Stack's field is empty!" << endl; 105 NextFreeField = CurrentLastEntry; 106 if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack 107 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; // step back from current free field to last (modulo does not work in -1, thus go EntryCount-1 instead) 108 } else { 109 cerr << "ERROR: Stack is empty!" << endl; 110 } 111 return Walker; 112 112 }; 113 113 … … 120 120 template <typename T> bool StackClass<T>::RemoveItem(T ptr) 121 121 { 122 bool found = false;123 cout << Verbose(5) << "First " << CurrentFirstEntry<< "\tLast " << CurrentLastEntry<< "\tNext " << NextFreeField<< "\tCount " << EntryCount<< "." << endl;124 int i=CurrentFirstEntry;125 if (!IsEmpty())126 do {127 if (StackList[i] == ptr) {// if item found, remove128 cout << Verbose(5) << "Item " << *ptr << " was number " << i << " on stack, removing it." << endl;129 found = true;130 StackList[i] = NULL;131 }132 if ((found) && (StackList[i] != NULL)) {// means we have to shift (and not the removed item)133 if (i == 0) { // we are down to first item in stack, have to put onto last item134 cout << Verbose(5) << "Shifting item 0 to place " << EntryCount-1 << "." << endl;135 StackList[EntryCount-1] = StackList[0];136 } else {137 cout << Verbose(5) << "Shifting item " << i << " to place " << i-1 << "." << endl;138 StackList[i-1] = StackList[i];139 }140 }141 i=((i + 1) % EntryCount); // step on142 } while (i!=NextFreeField);143 else144 cerr << "ERROR: Stack is already empty!" << endl;145 if (found) {146 NextFreeField = CurrentLastEntry;147 if (CurrentLastEntry != CurrentFirstEntry)// has there been more than one item on stack148 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount;149 }150 return found;122 bool found = false; 123 cout << Verbose(5) << "First " << CurrentFirstEntry<< "\tLast " << CurrentLastEntry<< "\tNext " << NextFreeField<< "\tCount " << EntryCount<< "." << endl; 124 int i=CurrentFirstEntry; 125 if (!IsEmpty()) 126 do { 127 if (StackList[i] == ptr) { // if item found, remove 128 cout << Verbose(5) << "Item " << *ptr << " was number " << i << " on stack, removing it." << endl; 129 found = true; 130 StackList[i] = NULL; 131 } 132 if ((found) && (StackList[i] != NULL)) { // means we have to shift (and not the removed item) 133 if (i == 0) { // we are down to first item in stack, have to put onto last item 134 cout << Verbose(5) << "Shifting item 0 to place " << EntryCount-1 << "." << endl; 135 StackList[EntryCount-1] = StackList[0]; 136 } else { 137 cout << Verbose(5) << "Shifting item " << i << " to place " << i-1 << "." << endl; 138 StackList[i-1] = StackList[i]; 139 } 140 } 141 i=((i + 1) % EntryCount); // step on 142 } while (i!=NextFreeField); 143 else 144 cerr << "ERROR: Stack is already empty!" << endl; 145 if (found) { 146 NextFreeField = CurrentLastEntry; 147 if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack 148 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; 149 } 150 return found; 151 151 }; 152 152 153 153 /** Test the functionality of the stack. 154 154 * \param *out ofstream for debugging 155 * \param *test one item to put on stack 155 * \param *test one item to put on stack 156 156 * \return true - all tests worked correctly 157 157 */ 158 158 template <typename T> void StackClass<T>::TestImplementation(ofstream *out, T test) 159 159 { 160 T Walker = test;161 *out << Verbose(1) << "Testing the snake stack..." << endl;162 for (int i=0;i<EntryCount;i++) {163 *out << Verbose(2) << "Filling " << i << "th element of stack." << endl; 164 Push(Walker);165 Walker=Walker->next;166 }167 *out << endl;168 Output(out);169 if (IsFull())170 *out << "Stack is full as supposed to be!" << endl;171 else172 *out << "ERROR: Stack is not as full as supposed to be!" << endl;173 //if (StackList[(EntryCount+1)/2] != NULL) {174 *out << "Removing element in the middle ..." << endl;175 RemoveItem(StackList[(EntryCount+1)/2]);176 Output(out);177 //}178 //if (StackList[CurrentFirstEntry] != NULL) {179 *out << "Removing first element..." << endl;180 RemoveItem(StackList[CurrentFirstEntry]);181 Output(out);182 //}183 //if (StackList[CurrentLastEntry] != NULL) {184 *out << "Removing last element ..." << endl;185 RemoveItem(StackList[CurrentLastEntry]);186 Output(out);187 //}188 *out << "Clearing stack ... " << endl; 189 ClearStack();190 Output(out);191 if (IsEmpty())192 *out << "Stack is empty as supposed to be!" << endl;193 else194 *out << "ERROR: Stack is not as empty as supposed to be!" << endl;195 *out << "done." << endl;160 T Walker = test; 161 *out << Verbose(1) << "Testing the snake stack..." << endl; 162 for (int i=0;i<EntryCount;i++) { 163 *out << Verbose(2) << "Filling " << i << "th element of stack." << endl; 164 Push(Walker); 165 Walker=Walker->next; 166 } 167 *out << endl; 168 Output(out); 169 if (IsFull()) 170 *out << "Stack is full as supposed to be!" << endl; 171 else 172 *out << "ERROR: Stack is not as full as supposed to be!" << endl; 173 //if (StackList[(EntryCount+1)/2] != NULL) { 174 *out << "Removing element in the middle ..." << endl; 175 RemoveItem(StackList[(EntryCount+1)/2]); 176 Output(out); 177 //} 178 //if (StackList[CurrentFirstEntry] != NULL) { 179 *out << "Removing first element ..." << endl; 180 RemoveItem(StackList[CurrentFirstEntry]); 181 Output(out); 182 //} 183 //if (StackList[CurrentLastEntry] != NULL) { 184 *out << "Removing last element ..." << endl; 185 RemoveItem(StackList[CurrentLastEntry]); 186 Output(out); 187 //} 188 *out << "Clearing stack ... " << endl; 189 ClearStack(); 190 Output(out); 191 if (IsEmpty()) 192 *out << "Stack is empty as supposed to be!" << endl; 193 else 194 *out << "ERROR: Stack is not as empty as supposed to be!" << endl; 195 *out << "done." << endl; 196 196 }; 197 197 … … 201 201 template <typename T> void StackClass<T>::Output(ofstream *out) const 202 202 { 203 *out << "Contents of Stack: ";204 for(int i=0;i<EntryCount;i++) {205 *out << "\t";206 if (i == CurrentFirstEntry)207 *out << " 1";208 if(i == CurrentLastEntry)209 *out << " "<< EntryCount;210 if (i ==NextFreeField)211 *out << " F";212 *out << ": " << StackList[i];213 }214 *out << endl;203 *out << "Contents of Stack: "; 204 for(int i=0;i<EntryCount;i++) { 205 *out << "\t"; 206 if (i == CurrentFirstEntry) 207 *out << " 1"; 208 if (i == CurrentLastEntry) 209 *out << " "<< EntryCount; 210 if (i == NextFreeField) 211 *out << " F"; 212 *out << ": " << StackList[i]; 213 } 214 *out << endl; 215 215 }; 216 216 … … 222 222 template <typename T> bool StackClass<T>::IsEmpty() 223 223 { 224 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry == CurrentFirstEntry));224 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry == CurrentFirstEntry)); 225 225 }; 226 226 … … 232 232 template <typename T> bool StackClass<T>::IsFull() 233 233 { 234 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry != CurrentFirstEntry));234 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry != CurrentFirstEntry)); 235 235 }; 236 236 … … 242 242 template <typename T> int StackClass<T>::ItemCount() 243 243 { 244 //cout << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tEntryCount " << EntryCount << "." << endl;245 return((NextFreeField + (EntryCount - CurrentFirstEntry)) % EntryCount);244 //cout << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tEntryCount " << EntryCount << "." << endl; 245 return((NextFreeField + (EntryCount - CurrentFirstEntry)) % EntryCount); 246 246 }; 247 247 … … 251 251 template <typename T> void StackClass<T>::ClearStack() 252 252 { 253 for(int i=EntryCount; i--;)254 StackList[i] = NULL;255 CurrentFirstEntry = 0;256 CurrentLastEntry = 0;257 NextFreeField = 0;253 for(int i=EntryCount; i--;) 254 StackList[i] = NULL; 255 CurrentFirstEntry = 0; 256 CurrentLastEntry = 0; 257 NextFreeField = 0; 258 258 }; 259 259 -
src/vector.cpp
rce5ac3 rd067d45 28 28 double Vector::DistanceSquared(const Vector *y) const 29 29 { 30 double res = 0.;31 for (int i=NDIM;i--;)32 res += (x[i]-y->x[i])*(x[i]-y->x[i]);33 return (res);30 double res = 0.; 31 for (int i=NDIM;i--;) 32 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 33 return (res); 34 34 }; 35 35 … … 40 40 double Vector::Distance(const Vector *y) const 41 41 { 42 double res = 0.; 43 for (int i=NDIM;i--;) 44 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 45 return (sqrt(res)); 42 double res = 0.; 43 for (int i=NDIM;i--;) 44 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 45 return (sqrt(res)); 46 }; 47 48 /** Calculates distance between this and another vector in a periodic cell. 49 * \param *y array to second vector 50 * \param *cell_size 6-dimensional array with (xx, xy, yy, xz, yz, zz) entries specifying the periodic cell 51 * \return \f$| x - y |\f$ 52 */ 53 double Vector::PeriodicDistance(const Vector *y, const double *cell_size) const 54 { 55 double res = Distance(y), tmp, matrix[NDIM*NDIM]; 56 Vector Shiftedy, TranslationVector; 57 int N[NDIM]; 58 matrix[0] = cell_size[0]; 59 matrix[1] = cell_size[1]; 60 matrix[2] = cell_size[3]; 61 matrix[3] = cell_size[1]; 62 matrix[4] = cell_size[2]; 63 matrix[5] = cell_size[4]; 64 matrix[6] = cell_size[3]; 65 matrix[7] = cell_size[4]; 66 matrix[8] = cell_size[5]; 67 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells 68 for (N[0]=-1;N[0]<=1;N[0]++) 69 for (N[1]=-1;N[1]<=1;N[1]++) 70 for (N[2]=-1;N[2]<=1;N[2]++) { 71 // create the translation vector 72 TranslationVector.Zero(); 73 for (int i=NDIM;i--;) 74 TranslationVector.x[i] = (double)N[i]; 75 TranslationVector.MatrixMultiplication(matrix); 76 // add onto the original vector to compare with 77 Shiftedy.CopyVector(y); 78 Shiftedy.AddVector(&TranslationVector); 79 // get distance and compare with minimum so far 80 tmp = Distance(&Shiftedy); 81 if (tmp < res) res = tmp; 82 } 83 return (res); 46 84 }; 47 85 … … 51 89 * \return \f$| x - y |^2\f$ 52 90 */ 53 double Vector::PeriodicDistance (const Vector *y, const double *cell_size) const54 { 55 double res = Distance(y), tmp, matrix[NDIM*NDIM];56 Vector Shiftedy, TranslationVector;57 int N[NDIM];58 matrix[0] = cell_size[0];59 matrix[1] = cell_size[1];60 matrix[2] = cell_size[3];61 matrix[3] = cell_size[1];62 matrix[4] = cell_size[2];63 matrix[5] = cell_size[4];64 matrix[6] = cell_size[3];65 matrix[7] = cell_size[4];66 matrix[8] = cell_size[5];67 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells68 for (N[0]=-1;N[0]<=1;N[0]++)69 for (N[1]=-1;N[1]<=1;N[1]++)70 for (N[2]=-1;N[2]<=1;N[2]++) {71 // create the translation vector72 TranslationVector.Zero();73 for (int i=NDIM;i--;)74 TranslationVector.x[i] = (double)N[i];75 TranslationVector.MatrixMultiplication(matrix);76 // add onto the original vector to compare with77 Shiftedy.CopyVector(y);78 Shiftedy.AddVector(&TranslationVector);79 // get distance and compare with minimum so far80 tmp = Distance(&Shiftedy);81 if (tmp < res) res = tmp;82 }83 return (res);91 double Vector::PeriodicDistanceSquared(const Vector *y, const double *cell_size) const 92 { 93 double res = DistanceSquared(y), tmp, matrix[NDIM*NDIM]; 94 Vector Shiftedy, TranslationVector; 95 int N[NDIM]; 96 matrix[0] = cell_size[0]; 97 matrix[1] = cell_size[1]; 98 matrix[2] = cell_size[3]; 99 matrix[3] = cell_size[1]; 100 matrix[4] = cell_size[2]; 101 matrix[5] = cell_size[4]; 102 matrix[6] = cell_size[3]; 103 matrix[7] = cell_size[4]; 104 matrix[8] = cell_size[5]; 105 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells 106 for (N[0]=-1;N[0]<=1;N[0]++) 107 for (N[1]=-1;N[1]<=1;N[1]++) 108 for (N[2]=-1;N[2]<=1;N[2]++) { 109 // create the translation vector 110 TranslationVector.Zero(); 111 for (int i=NDIM;i--;) 112 TranslationVector.x[i] = (double)N[i]; 113 TranslationVector.MatrixMultiplication(matrix); 114 // add onto the original vector to compare with 115 Shiftedy.CopyVector(y); 116 Shiftedy.AddVector(&TranslationVector); 117 // get distance and compare with minimum so far 118 tmp = DistanceSquared(&Shiftedy); 119 if (tmp < res) res = tmp; 120 } 121 return (res); 84 122 }; 85 123 … … 90 128 void Vector::KeepPeriodic(ofstream *out, double *matrix) 91 129 { 92 // int N[NDIM];93 // bool flag = false;94 //vector Shifted, TranslationVector;95 Vector TestVector;96 // *out << Verbose(1) << "Begin of KeepPeriodic." << endl;97 // *out << Verbose(2) << "Vector is: ";98 // Output(out);99 // *out << endl;100 TestVector.CopyVector(this);101 TestVector.InverseMatrixMultiplication(matrix);102 for(int i=NDIM;i--;) { // correct periodically103 if (TestVector.x[i] < 0) {// get every coefficient into the interval [0,1)104 TestVector.x[i] += ceil(TestVector.x[i]);105 } else {106 TestVector.x[i] -= floor(TestVector.x[i]);107 }108 }109 TestVector.MatrixMultiplication(matrix);110 CopyVector(&TestVector);111 // *out << Verbose(2) << "New corrected vector is: ";112 // Output(out);113 // *out << endl;114 // *out << Verbose(1) << "End of KeepPeriodic." << endl;130 // int N[NDIM]; 131 // bool flag = false; 132 //vector Shifted, TranslationVector; 133 Vector TestVector; 134 // *out << Verbose(1) << "Begin of KeepPeriodic." << endl; 135 // *out << Verbose(2) << "Vector is: "; 136 // Output(out); 137 // *out << endl; 138 TestVector.CopyVector(this); 139 TestVector.InverseMatrixMultiplication(matrix); 140 for(int i=NDIM;i--;) { // correct periodically 141 if (TestVector.x[i] < 0) { // get every coefficient into the interval [0,1) 142 TestVector.x[i] += ceil(TestVector.x[i]); 143 } else { 144 TestVector.x[i] -= floor(TestVector.x[i]); 145 } 146 } 147 TestVector.MatrixMultiplication(matrix); 148 CopyVector(&TestVector); 149 // *out << Verbose(2) << "New corrected vector is: "; 150 // Output(out); 151 // *out << endl; 152 // *out << Verbose(1) << "End of KeepPeriodic." << endl; 115 153 }; 116 154 … … 121 159 double Vector::ScalarProduct(const Vector *y) const 122 160 { 123 double res = 0.;124 for (int i=NDIM;i--;)125 res += x[i]*y->x[i];126 return (res);161 double res = 0.; 162 for (int i=NDIM;i--;) 163 res += x[i]*y->x[i]; 164 return (res); 127 165 }; 128 166 129 167 130 168 /** Calculates VectorProduct between this and another vector. 131 * -# returns the Product in place of vector from which it was initiated132 * -# ATTENTION: Only three dim.133 * \param *y array to vector with which to calculate crossproduct134 * \return \f$ x \times y \f&169 * -# returns the Product in place of vector from which it was initiated 170 * -# ATTENTION: Only three dim. 171 * \param *y array to vector with which to calculate crossproduct 172 * \return \f$ x \times y \f& 135 173 */ 136 174 void Vector::VectorProduct(const Vector *y) 137 175 { 138 Vector tmp;139 tmp.x[0] = x[1]* (y->x[2]) - x[2]* (y->x[1]);140 tmp.x[1] = x[2]* (y->x[0]) - x[0]* (y->x[2]);141 tmp.x[2] = x[0]* (y->x[1]) - x[1]* (y->x[0]);142 this->CopyVector(&tmp);176 Vector tmp; 177 tmp.x[0] = x[1]* (y->x[2]) - x[2]* (y->x[1]); 178 tmp.x[1] = x[2]* (y->x[0]) - x[0]* (y->x[2]); 179 tmp.x[2] = x[0]* (y->x[1]) - x[1]* (y->x[0]); 180 this->CopyVector(&tmp); 143 181 144 182 }; … … 151 189 void Vector::ProjectOntoPlane(const Vector *y) 152 190 { 153 Vector tmp;154 tmp.CopyVector(y);155 tmp.Normalize();156 tmp.Scale(ScalarProduct(&tmp));157 this->SubtractVector(&tmp);191 Vector tmp; 192 tmp.CopyVector(y); 193 tmp.Normalize(); 194 tmp.Scale(ScalarProduct(&tmp)); 195 this->SubtractVector(&tmp); 158 196 }; 159 197 … … 164 202 double Vector::Projection(const Vector *y) const 165 203 { 166 return (ScalarProduct(y));204 return (ScalarProduct(y)); 167 205 }; 168 206 … … 172 210 double Vector::Norm() const 173 211 { 174 double res = 0.;175 for (int i=NDIM;i--;)176 res += this->x[i]*this->x[i];177 return (sqrt(res));212 double res = 0.; 213 for (int i=NDIM;i--;) 214 res += this->x[i]*this->x[i]; 215 return (sqrt(res)); 178 216 }; 179 217 … … 182 220 void Vector::Normalize() 183 221 { 184 double res = 0.;185 for (int i=NDIM;i--;)186 res += this->x[i]*this->x[i];187 if (fabs(res) > MYEPSILON)188 res = 1./sqrt(res);189 Scale(&res);222 double res = 0.; 223 for (int i=NDIM;i--;) 224 res += this->x[i]*this->x[i]; 225 if (fabs(res) > MYEPSILON) 226 res = 1./sqrt(res); 227 Scale(&res); 190 228 }; 191 229 … … 194 232 void Vector::Zero() 195 233 { 196 for (int i=NDIM;i--;)197 this->x[i] = 0.;234 for (int i=NDIM;i--;) 235 this->x[i] = 0.; 198 236 }; 199 237 … … 202 240 void Vector::One(double one) 203 241 { 204 for (int i=NDIM;i--;)205 this->x[i] = one;242 for (int i=NDIM;i--;) 243 this->x[i] = one; 206 244 }; 207 245 … … 210 248 void Vector::Init(double x1, double x2, double x3) 211 249 { 212 x[0] = x1;213 x[1] = x2;214 x[2] = x3;250 x[0] = x1; 251 x[1] = x2; 252 x[2] = x3; 215 253 }; 216 254 … … 221 259 double Vector::Angle(const Vector *y) const 222 260 { 223 return acos(this->ScalarProduct(y)/Norm()/y->Norm());261 return acos(this->ScalarProduct(y)/Norm()/y->Norm()); 224 262 }; 225 263 … … 230 268 void Vector::RotateVector(const Vector *axis, const double alpha) 231 269 { 232 Vector a,y;233 // normalise this vector with respect to axis234 a.CopyVector(this);235 a.Scale(Projection(axis));236 SubtractVector(&a);237 // construct normal vector238 y.MakeNormalVector(axis,this);239 y.Scale(Norm());240 // scale normal vector by sine and this vector by cosine241 y.Scale(sin(alpha));242 Scale(cos(alpha));243 // add scaled normal vector onto this vector244 AddVector(&y);245 // add part in axis direction246 AddVector(&a);270 Vector a,y; 271 // normalise this vector with respect to axis 272 a.CopyVector(this); 273 a.Scale(Projection(axis)); 274 SubtractVector(&a); 275 // construct normal vector 276 y.MakeNormalVector(axis,this); 277 y.Scale(Norm()); 278 // scale normal vector by sine and this vector by cosine 279 y.Scale(sin(alpha)); 280 Scale(cos(alpha)); 281 // add scaled normal vector onto this vector 282 AddVector(&y); 283 // add part in axis direction 284 AddVector(&a); 247 285 }; 248 286 … … 254 292 Vector& operator+=(Vector& a, const Vector& b) 255 293 { 256 a.AddVector(&b);257 return a;294 a.AddVector(&b); 295 return a; 258 296 }; 259 297 /** factor each component of \a a times a double \a m. … … 264 302 Vector& operator*=(Vector& a, const double m) 265 303 { 266 a.Scale(m);267 return a;268 }; 269 270 /** Sums two vectors \a and \b component-wise.304 a.Scale(m); 305 return a; 306 }; 307 308 /** Sums two vectors \a and \b component-wise. 271 309 * \param a first vector 272 310 * \param b second vector … … 275 313 Vector& operator+(const Vector& a, const Vector& b) 276 314 { 277 Vector *x = new Vector;278 x->CopyVector(&a);279 x->AddVector(&b);280 return *x;315 Vector *x = new Vector; 316 x->CopyVector(&a); 317 x->AddVector(&b); 318 return *x; 281 319 }; 282 320 … … 288 326 Vector& operator*(const Vector& a, const double m) 289 327 { 290 Vector *x = new Vector;291 x->CopyVector(&a);292 x->Scale(m);293 return *x;328 Vector *x = new Vector; 329 x->CopyVector(&a); 330 x->Scale(m); 331 return *x; 294 332 }; 295 333 … … 300 338 bool Vector::Output(ofstream *out) const 301 339 { 302 if (out != NULL) { 303 *out << "("; 304 for (int i=0;i<NDIM;i++) { 305 *out << x[i]; 306 if (i != 2) 307 *out << ","; 308 } 309 *out << ")"; 310 return true; 311 } else 312 return false; 313 }; 314 315 /** Prints a 3dim vector to a stream. 316 * \param ost output stream 317 * \param v Vector to be printed 318 * \return output stream 319 */ 340 if (out != NULL) { 341 *out << "("; 342 for (int i=0;i<NDIM;i++) { 343 *out << x[i]; 344 if (i != 2) 345 *out << ","; 346 } 347 *out << ")"; 348 return true; 349 } else 350 return false; 351 }; 352 320 353 ostream& operator<<(ostream& ost,Vector& m) 321 354 { 322 ost << "(";323 for (int i=0;i<NDIM;i++) {324 ost << m.x[i];325 if (i != 2)326 ost << ",";327 }328 ost << ")";329 return ost;355 ost << "("; 356 for (int i=0;i<NDIM;i++) { 357 ost << m.x[i]; 358 if (i != 2) 359 ost << ","; 360 } 361 ost << ")"; 362 return ost; 330 363 }; 331 364 … … 335 368 void Vector::Scale(double **factor) 336 369 { 337 for (int i=NDIM;i--;)338 x[i] *= (*factor)[i];370 for (int i=NDIM;i--;) 371 x[i] *= (*factor)[i]; 339 372 }; 340 373 341 374 void Vector::Scale(double *factor) 342 375 { 343 for (int i=NDIM;i--;)344 x[i] *= *factor;376 for (int i=NDIM;i--;) 377 x[i] *= *factor; 345 378 }; 346 379 347 380 void Vector::Scale(double factor) 348 381 { 349 for (int i=NDIM;i--;)350 x[i] *= factor;382 for (int i=NDIM;i--;) 383 x[i] *= factor; 351 384 }; 352 385 … … 356 389 void Vector::Translate(const Vector *trans) 357 390 { 358 for (int i=NDIM;i--;)359 x[i] += trans->x[i];391 for (int i=NDIM;i--;) 392 x[i] += trans->x[i]; 360 393 }; 361 394 … … 365 398 void Vector::MatrixMultiplication(double *M) 366 399 { 367 Vector C;368 // do the matrix multiplication369 C.x[0] = M[0]*x[0]+M[3]*x[1]+M[6]*x[2];370 C.x[1] = M[1]*x[0]+M[4]*x[1]+M[7]*x[2];371 C.x[2] = M[2]*x[0]+M[5]*x[1]+M[8]*x[2];372 // transfer the result into this373 for (int i=NDIM;i--;)374 x[i] = C.x[i];400 Vector C; 401 // do the matrix multiplication 402 C.x[0] = M[0]*x[0]+M[3]*x[1]+M[6]*x[2]; 403 C.x[1] = M[1]*x[0]+M[4]*x[1]+M[7]*x[2]; 404 C.x[2] = M[2]*x[0]+M[5]*x[1]+M[8]*x[2]; 405 // transfer the result into this 406 for (int i=NDIM;i--;) 407 x[i] = C.x[i]; 375 408 }; 376 409 … … 380 413 void Vector::InverseMatrixMultiplication(double *A) 381 414 { 382 Vector C;383 double B[NDIM*NDIM];384 double detA = RDET3(A);385 double detAReci;386 387 // calculate the inverse B388 if (fabs(detA) > MYEPSILON) {;// RDET3(A) yields precisely zero if A irregular389 detAReci = 1./detA;390 B[0] = detAReci*RDET2(A[4],A[5],A[7],A[8]);// A_11391 B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]);// A_12392 B[2] = detAReci*RDET2(A[1],A[2],A[4],A[5]);// A_13393 B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]);// A_21394 B[4] = detAReci*RDET2(A[0],A[2],A[6],A[8]);// A_22395 B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]);// A_23396 B[6] = detAReci*RDET2(A[3],A[4],A[6],A[7]);// A_31397 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]);// A_32398 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]);// A_33399 400 // do the matrix multiplication401 C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2];402 C.x[1] = B[1]*x[0]+B[4]*x[1]+B[7]*x[2];403 C.x[2] = B[2]*x[0]+B[5]*x[1]+B[8]*x[2];404 // transfer the result into this405 for (int i=NDIM;i--;)406 x[i] = C.x[i];407 } else {408 cerr << "ERROR: inverse of matrix does not exists!" << endl;409 }415 Vector C; 416 double B[NDIM*NDIM]; 417 double detA = RDET3(A); 418 double detAReci; 419 420 // calculate the inverse B 421 if (fabs(detA) > MYEPSILON) {; // RDET3(A) yields precisely zero if A irregular 422 detAReci = 1./detA; 423 B[0] = detAReci*RDET2(A[4],A[5],A[7],A[8]); // A_11 424 B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]); // A_12 425 B[2] = detAReci*RDET2(A[1],A[2],A[4],A[5]); // A_13 426 B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]); // A_21 427 B[4] = detAReci*RDET2(A[0],A[2],A[6],A[8]); // A_22 428 B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]); // A_23 429 B[6] = detAReci*RDET2(A[3],A[4],A[6],A[7]); // A_31 430 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]); // A_32 431 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]); // A_33 432 433 // do the matrix multiplication 434 C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2]; 435 C.x[1] = B[1]*x[0]+B[4]*x[1]+B[7]*x[2]; 436 C.x[2] = B[2]*x[0]+B[5]*x[1]+B[8]*x[2]; 437 // transfer the result into this 438 for (int i=NDIM;i--;) 439 x[i] = C.x[i]; 440 } else { 441 cerr << "ERROR: inverse of matrix does not exists!" << endl; 442 } 410 443 }; 411 444 … … 420 453 void Vector::LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors) 421 454 { 422 for(int i=NDIM;i--;)423 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i];455 for(int i=NDIM;i--;) 456 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i]; 424 457 }; 425 458 … … 429 462 void Vector::Mirror(const Vector *n) 430 463 { 431 double projection;432 projection = ScalarProduct(n)/n->ScalarProduct(n);// remove constancy from n (keep as logical one)433 // withdraw projected vector twice from original one434 cout << Verbose(1) << "Vector: ";435 Output((ofstream *)&cout);436 cout << "\t";437 for (int i=NDIM;i--;)438 x[i] -= 2.*projection*n->x[i];439 cout << "Projected vector: ";440 Output((ofstream *)&cout);441 cout << endl;464 double projection; 465 projection = ScalarProduct(n)/n->ScalarProduct(n); // remove constancy from n (keep as logical one) 466 // withdraw projected vector twice from original one 467 cout << Verbose(1) << "Vector: "; 468 Output((ofstream *)&cout); 469 cout << "\t"; 470 for (int i=NDIM;i--;) 471 x[i] -= 2.*projection*n->x[i]; 472 cout << "Projected vector: "; 473 Output((ofstream *)&cout); 474 cout << endl; 442 475 }; 443 476 … … 451 484 bool Vector::MakeNormalVector(const Vector *y1, const Vector *y2, const Vector *y3) 452 485 { 453 Vector x1, x2;454 455 x1.CopyVector(y1);456 x1.SubtractVector(y2);457 x2.CopyVector(y3);458 x2.SubtractVector(y2);459 if ((x1.Norm()==0) || (x2.Norm()==0)) {460 cout << Verbose(4) << "Given vectors are linear dependent." << endl;461 return false;462 }463 // cout << Verbose(4) << "relative, first plane coordinates:";464 // x1.Output((ofstream *)&cout);465 // cout << endl;466 // cout << Verbose(4) << "second plane coordinates:";467 // x2.Output((ofstream *)&cout);468 // cout << endl;469 470 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]);471 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]);472 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]);473 Normalize();474 475 return true;486 Vector x1, x2; 487 488 x1.CopyVector(y1); 489 x1.SubtractVector(y2); 490 x2.CopyVector(y3); 491 x2.SubtractVector(y2); 492 if ((fabs(x1.Norm()) < MYEPSILON) || (fabs(x2.Norm()) < MYEPSILON) || (fabs(x1.Angle(&x2)) < MYEPSILON)) { 493 cout << Verbose(4) << "Given vectors are linear dependent." << endl; 494 return false; 495 } 496 // cout << Verbose(4) << "relative, first plane coordinates:"; 497 // x1.Output((ofstream *)&cout); 498 // cout << endl; 499 // cout << Verbose(4) << "second plane coordinates:"; 500 // x2.Output((ofstream *)&cout); 501 // cout << endl; 502 503 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]); 504 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]); 505 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]); 506 Normalize(); 507 508 return true; 476 509 }; 477 510 … … 487 520 bool Vector::MakeNormalVector(const Vector *y1, const Vector *y2) 488 521 { 489 Vector x1,x2;490 x1.CopyVector(y1);491 x2.CopyVector(y2);492 Zero();493 if ((x1.Norm()==0) || (x2.Norm()==0)) {494 cout << Verbose(4) << "Given vectors are linear dependent." << endl;495 return false;496 }497 // cout << Verbose(4) << "relative, first plane coordinates:";498 // x1.Output((ofstream *)&cout);499 // cout << endl;500 // cout << Verbose(4) << "second plane coordinates:";501 // x2.Output((ofstream *)&cout);502 // cout << endl;503 504 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]);505 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]);506 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]);507 Normalize();508 509 return true;522 Vector x1,x2; 523 x1.CopyVector(y1); 524 x2.CopyVector(y2); 525 Zero(); 526 if ((fabs(x1.Norm()) < MYEPSILON) || (fabs(x2.Norm()) < MYEPSILON) || (fabs(x1.Angle(&x2)) < MYEPSILON)) { 527 cout << Verbose(4) << "Given vectors are linear dependent." << endl; 528 return false; 529 } 530 // cout << Verbose(4) << "relative, first plane coordinates:"; 531 // x1.Output((ofstream *)&cout); 532 // cout << endl; 533 // cout << Verbose(4) << "second plane coordinates:"; 534 // x2.Output((ofstream *)&cout); 535 // cout << endl; 536 537 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]); 538 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]); 539 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]); 540 Normalize(); 541 542 return true; 510 543 }; 511 544 … … 517 550 bool Vector::MakeNormalVector(const Vector *y1) 518 551 { 519 bool result = false;520 Vector x1;521 x1.CopyVector(y1);522 x1.Scale(x1.Projection(this));523 SubtractVector(&x1);524 for (int i=NDIM;i--;)525 result = result || (fabs(x[i]) > MYEPSILON);526 527 return result;552 bool result = false; 553 Vector x1; 554 x1.CopyVector(y1); 555 x1.Scale(x1.Projection(this)); 556 SubtractVector(&x1); 557 for (int i=NDIM;i--;) 558 result = result || (fabs(x[i]) > MYEPSILON); 559 560 return result; 528 561 }; 529 562 … … 536 569 bool Vector::GetOneNormalVector(const Vector *GivenVector) 537 570 { 538 int Components[NDIM]; // contains indices of non-zero components539 int Last = 0;// count the number of non-zero entries in vector540 int j;// loop variables541 double norm;542 543 cout << Verbose(4);544 GivenVector->Output((ofstream *)&cout);545 cout << endl;546 for (j=NDIM;j--;)547 Components[j] = -1;548 // find two components != 0549 for (j=0;j<NDIM;j++)550 if (fabs(GivenVector->x[j]) > MYEPSILON)551 Components[Last++] = j;552 cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl;553 554 switch(Last) {555 case 3:// threecomponent system556 case 2:// two component system557 norm = sqrt(1./(GivenVector->x[Components[1]]*GivenVector->x[Components[1]]) + 1./(GivenVector->x[Components[0]]*GivenVector->x[Components[0]]));558 x[Components[2]] = 0.;559 // in skp both remaining parts shall become zero but with opposite sign and third is zero560 x[Components[1]] = -1./GivenVector->x[Components[1]] / norm;561 x[Components[0]] = 1./GivenVector->x[Components[0]] / norm;562 return true;563 break;564 case 1: // one component system565 // set sole non-zero component to 0, and one of the other zero component pendants to 1566 x[(Components[0]+2)%NDIM] = 0.;567 x[(Components[0]+1)%NDIM] = 1.;568 x[Components[0]] = 0.;569 return true;570 break;571 default:572 return false;573 }571 int Components[NDIM]; // contains indices of non-zero components 572 int Last = 0; // count the number of non-zero entries in vector 573 int j; // loop variables 574 double norm; 575 576 cout << Verbose(4); 577 GivenVector->Output((ofstream *)&cout); 578 cout << endl; 579 for (j=NDIM;j--;) 580 Components[j] = -1; 581 // find two components != 0 582 for (j=0;j<NDIM;j++) 583 if (fabs(GivenVector->x[j]) > MYEPSILON) 584 Components[Last++] = j; 585 cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl; 586 587 switch(Last) { 588 case 3: // threecomponent system 589 case 2: // two component system 590 norm = sqrt(1./(GivenVector->x[Components[1]]*GivenVector->x[Components[1]]) + 1./(GivenVector->x[Components[0]]*GivenVector->x[Components[0]])); 591 x[Components[2]] = 0.; 592 // in skp both remaining parts shall become zero but with opposite sign and third is zero 593 x[Components[1]] = -1./GivenVector->x[Components[1]] / norm; 594 x[Components[0]] = 1./GivenVector->x[Components[0]] / norm; 595 return true; 596 break; 597 case 1: // one component system 598 // set sole non-zero component to 0, and one of the other zero component pendants to 1 599 x[(Components[0]+2)%NDIM] = 0.; 600 x[(Components[0]+1)%NDIM] = 1.; 601 x[Components[0]] = 0.; 602 return true; 603 break; 604 default: 605 return false; 606 } 574 607 }; 575 608 … … 582 615 double Vector::CutsPlaneAt(Vector *A, Vector *B, Vector *C) 583 616 { 584 // cout << Verbose(3) << "For comparison: ";585 // cout << "A " << A->Projection(this) << "\t";586 // cout << "B " << B->Projection(this) << "\t";587 // cout << "C " << C->Projection(this) << "\t";588 // cout << endl;589 return A->Projection(this);617 // cout << Verbose(3) << "For comparison: "; 618 // cout << "A " << A->Projection(this) << "\t"; 619 // cout << "B " << B->Projection(this) << "\t"; 620 // cout << "C " << C->Projection(this) << "\t"; 621 // cout << endl; 622 return A->Projection(this); 590 623 }; 591 624 … … 597 630 bool Vector::LSQdistance(Vector **vectors, int num) 598 631 { 599 int j;600 601 for (j=0;j<num;j++) {602 cout << Verbose(1) << j << "th atom's vector: ";603 (vectors[j])->Output((ofstream *)&cout);604 cout << endl;605 }606 607 int np = 3;608 struct LSQ_params par;609 610 const gsl_multimin_fminimizer_type *T =611 gsl_multimin_fminimizer_nmsimplex;612 gsl_multimin_fminimizer *s = NULL;613 gsl_vector *ss, *y;614 gsl_multimin_function minex_func;615 616 size_t iter = 0, i;617 int status;618 double size;619 620 /* Initial vertex size vector */621 ss = gsl_vector_alloc (np);622 y = gsl_vector_alloc (np);623 624 /* Set all step sizes to 1 */625 gsl_vector_set_all (ss, 1.0);626 627 /* Starting point */628 par.vectors = vectors;629 par.num = num;630 631 for (i=NDIM;i--;)632 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.);633 634 /* Initialize method and iterate */635 minex_func.f = &LSQ;636 minex_func.n = np;637 minex_func.params = (void *)∥638 639 s = gsl_multimin_fminimizer_alloc (T, np);640 gsl_multimin_fminimizer_set (s, &minex_func, y, ss);641 642 do643 {644 iter++;645 status = gsl_multimin_fminimizer_iterate(s);646 647 if (status)648 break;649 650 size = gsl_multimin_fminimizer_size (s);651 status = gsl_multimin_test_size (size, 1e-2);652 653 if (status == GSL_SUCCESS)654 {655 printf ("converged to minimum at\n");656 }657 658 printf ("%5d ", (int)iter);659 for (i = 0; i < (size_t)np; i++)660 {661 printf ("%10.3e ", gsl_vector_get (s->x, i));662 }663 printf ("f() = %7.3f size = %.3f\n", s->fval, size);664 }665 while (status == GSL_CONTINUE && iter < 100);666 667 for (i=(size_t)np;i--;)668 this->x[i] = gsl_vector_get(s->x, i);669 gsl_vector_free(y);670 gsl_vector_free(ss);671 gsl_multimin_fminimizer_free (s);672 673 return true;632 int j; 633 634 for (j=0;j<num;j++) { 635 cout << Verbose(1) << j << "th atom's vector: "; 636 (vectors[j])->Output((ofstream *)&cout); 637 cout << endl; 638 } 639 640 int np = 3; 641 struct LSQ_params par; 642 643 const gsl_multimin_fminimizer_type *T = 644 gsl_multimin_fminimizer_nmsimplex; 645 gsl_multimin_fminimizer *s = NULL; 646 gsl_vector *ss, *y; 647 gsl_multimin_function minex_func; 648 649 size_t iter = 0, i; 650 int status; 651 double size; 652 653 /* Initial vertex size vector */ 654 ss = gsl_vector_alloc (np); 655 y = gsl_vector_alloc (np); 656 657 /* Set all step sizes to 1 */ 658 gsl_vector_set_all (ss, 1.0); 659 660 /* Starting point */ 661 par.vectors = vectors; 662 par.num = num; 663 664 for (i=NDIM;i--;) 665 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.); 666 667 /* Initialize method and iterate */ 668 minex_func.f = &LSQ; 669 minex_func.n = np; 670 minex_func.params = (void *)∥ 671 672 s = gsl_multimin_fminimizer_alloc (T, np); 673 gsl_multimin_fminimizer_set (s, &minex_func, y, ss); 674 675 do 676 { 677 iter++; 678 status = gsl_multimin_fminimizer_iterate(s); 679 680 if (status) 681 break; 682 683 size = gsl_multimin_fminimizer_size (s); 684 status = gsl_multimin_test_size (size, 1e-2); 685 686 if (status == GSL_SUCCESS) 687 { 688 printf ("converged to minimum at\n"); 689 } 690 691 printf ("%5d ", (int)iter); 692 for (i = 0; i < (size_t)np; i++) 693 { 694 printf ("%10.3e ", gsl_vector_get (s->x, i)); 695 } 696 printf ("f() = %7.3f size = %.3f\n", s->fval, size); 697 } 698 while (status == GSL_CONTINUE && iter < 100); 699 700 for (i=(size_t)np;i--;) 701 this->x[i] = gsl_vector_get(s->x, i); 702 gsl_vector_free(y); 703 gsl_vector_free(ss); 704 gsl_multimin_fminimizer_free (s); 705 706 return true; 674 707 }; 675 708 … … 679 712 void Vector::AddVector(const Vector *y) 680 713 { 681 for (int i=NDIM;i--;)682 this->x[i] += y->x[i];714 for (int i=NDIM;i--;) 715 this->x[i] += y->x[i]; 683 716 } 684 717 … … 688 721 void Vector::SubtractVector(const Vector *y) 689 722 { 690 for (int i=NDIM;i--;)691 this->x[i] -= y->x[i];723 for (int i=NDIM;i--;) 724 this->x[i] -= y->x[i]; 692 725 } 693 726 … … 697 730 void Vector::CopyVector(const Vector *y) 698 731 { 699 for (int i=NDIM;i--;)700 this->x[i] = y->x[i];732 for (int i=NDIM;i--;) 733 this->x[i] = y->x[i]; 701 734 } 702 735 … … 708 741 void Vector::AskPosition(double *cell_size, bool check) 709 742 { 710 char coords[3] = {'x','y','z'};711 int j = -1;712 for (int i=0;i<3;i++) {713 j += i+1;714 do {715 cout << Verbose(0) << coords[i] << "[0.." << cell_size[j] << "]: ";716 cin >> x[i];717 } while (((x[i] < 0) || (x[i] >= cell_size[j])) && (check));718 }743 char coords[3] = {'x','y','z'}; 744 int j = -1; 745 for (int i=0;i<3;i++) { 746 j += i+1; 747 do { 748 cout << Verbose(0) << coords[i] << "[0.." << cell_size[j] << "]: "; 749 cin >> x[i]; 750 } while (((x[i] < 0) || (x[i] >= cell_size[j])) && (check)); 751 } 719 752 }; 720 753 … … 736 769 bool Vector::SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c) 737 770 { 738 double D1,D2,D3,E1,E2,F1,F2,F3,p,q=0., A, B1, B2, C;739 double ang; // angle on testing740 double sign[3];741 int i,j,k;742 A = cos(alpha) * x1->Norm() * c;743 B1 = cos(beta + M_PI/2.) * y->Norm() * c;744 B2 = cos(beta) * x2->Norm() * c;745 C = c * c;746 cout << Verbose(2) << "A " << A << "\tB " << B1 << "\tC " << C << endl;747 int flag = 0;748 if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping749 if (fabs(x1->x[1]) > MYEPSILON) {750 flag = 1;751 } else if (fabs(x1->x[2]) > MYEPSILON) {752 flag = 2;753 } else {754 return false;755 }756 }757 switch (flag) {758 default:759 case 0:760 break;761 case 2:762 flip(&x1->x[0],&x1->x[1]);763 flip(&x2->x[0],&x2->x[1]);764 flip(&y->x[0],&y->x[1]);765 //flip(&x[0],&x[1]);766 flip(&x1->x[1],&x1->x[2]);767 flip(&x2->x[1],&x2->x[2]);768 flip(&y->x[1],&y->x[2]);769 //flip(&x[1],&x[2]);770 case 1:771 flip(&x1->x[0],&x1->x[1]);772 flip(&x2->x[0],&x2->x[1]);773 flip(&y->x[0],&y->x[1]);774 //flip(&x[0],&x[1]);775 flip(&x1->x[1],&x1->x[2]);776 flip(&x2->x[1],&x2->x[2]);777 flip(&y->x[1],&y->x[2]);778 //flip(&x[1],&x[2]);779 break;780 }781 // now comes the case system782 D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1];783 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2];784 D3 = y->x[0]/x1->x[0]*A-B1;785 cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n";786 if (fabs(D1) < MYEPSILON) {787 cout << Verbose(2) << "D1 == 0!\n";788 if (fabs(D2) > MYEPSILON) {789 cout << Verbose(3) << "D2 != 0!\n";790 x[2] = -D3/D2;791 E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2;792 E2 = -x1->x[1]/x1->x[0];793 cout << Verbose(3) << "E1 " << E1 << "\tE2 " << E2 << "\n";794 F1 = E1*E1 + 1.;795 F2 = -E1*E2;796 F3 = E1*E1 + D3*D3/(D2*D2) - C;797 cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n";798 if (fabs(F1) < MYEPSILON) {799 cout << Verbose(4) << "F1 == 0!\n";800 cout << Verbose(4) << "Gleichungssystem linear\n";801 x[1] = F3/(2.*F2);802 } else {803 p = F2/F1;804 q = p*p - F3/F1;805 cout << Verbose(4) << "p " << p << "\tq " << q << endl;806 if (q < 0) {807 cout << Verbose(4) << "q < 0" << endl;808 return false;809 }810 x[1] = p + sqrt(q);811 }812 x[0] =A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];813 } else {814 cout << Verbose(2) << "Gleichungssystem unterbestimmt\n";815 return false;816 }817 } else {818 E1 = A/x1->x[0]+x1->x[1]/x1->x[0]*D3/D1;819 E2 = x1->x[1]/x1->x[0]*D2/D1 - x1->x[2];820 cout << Verbose(2) << "E1 " << E1 << "\tE2 " << E2 << "\n";821 F1 = E2*E2 + D2*D2/(D1*D1) + 1.;822 F2 = -(E1*E2 + D2*D3/(D1*D1));823 F3 = E1*E1 + D3*D3/(D1*D1) - C;824 cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n";825 if (fabs(F1) < MYEPSILON) {826 cout << Verbose(3) << "F1 == 0!\n";827 cout << Verbose(3) << "Gleichungssystem linear\n";828 x[2] = F3/(2.*F2);829 } else {830 p = F2/F1;831 q = p*p - F3/F1;832 cout << Verbose(3) << "p " << p << "\tq " << q << endl;833 if (q < 0) {834 cout << Verbose(3) << "q < 0" << endl;835 return false;836 }837 x[2] = p + sqrt(q);838 }839 x[1] = (-D2 * x[2] - D3)/D1;840 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];841 }842 switch (flag) { // back-flipping843 default:844 case 0:845 break;846 case 2:847 flip(&x1->x[0],&x1->x[1]);848 flip(&x2->x[0],&x2->x[1]);849 flip(&y->x[0],&y->x[1]);850 flip(&x[0],&x[1]);851 flip(&x1->x[1],&x1->x[2]);852 flip(&x2->x[1],&x2->x[2]);853 flip(&y->x[1],&y->x[2]);854 flip(&x[1],&x[2]);855 case 1:856 flip(&x1->x[0],&x1->x[1]);857 flip(&x2->x[0],&x2->x[1]);858 flip(&y->x[0],&y->x[1]);859 //flip(&x[0],&x[1]);860 flip(&x1->x[1],&x1->x[2]);861 flip(&x2->x[1],&x2->x[2]);862 flip(&y->x[1],&y->x[2]);863 flip(&x[1],&x[2]);864 break;865 }866 // one z component is only determined by its radius (without sign)867 // thus check eight possible sign flips and determine by checking angle with second vector868 for (i=0;i<8;i++) {869 // set sign vector accordingly870 for (j=2;j>=0;j--) {871 k = (i & pot(2,j)) << j;872 cout << Verbose(2) << "k " << k << "\tpot(2,j) " << pot(2,j) << endl;873 sign[j] = (k == 0) ? 1. : -1.;874 }875 cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n";876 // apply sign matrix877 for (j=NDIM;j--;)878 x[j] *= sign[j];879 // calculate angle and check880 ang = x2->Angle (this);881 cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t";882 if (fabs(ang - cos(beta)) < MYEPSILON) {883 break;884 }885 // unapply sign matrix (is its own inverse)886 for (j=NDIM;j--;)887 x[j] *= sign[j];888 }889 return true;890 }; 771 double D1,D2,D3,E1,E2,F1,F2,F3,p,q=0., A, B1, B2, C; 772 double ang; // angle on testing 773 double sign[3]; 774 int i,j,k; 775 A = cos(alpha) * x1->Norm() * c; 776 B1 = cos(beta + M_PI/2.) * y->Norm() * c; 777 B2 = cos(beta) * x2->Norm() * c; 778 C = c * c; 779 cout << Verbose(2) << "A " << A << "\tB " << B1 << "\tC " << C << endl; 780 int flag = 0; 781 if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping 782 if (fabs(x1->x[1]) > MYEPSILON) { 783 flag = 1; 784 } else if (fabs(x1->x[2]) > MYEPSILON) { 785 flag = 2; 786 } else { 787 return false; 788 } 789 } 790 switch (flag) { 791 default: 792 case 0: 793 break; 794 case 2: 795 flip(&x1->x[0],&x1->x[1]); 796 flip(&x2->x[0],&x2->x[1]); 797 flip(&y->x[0],&y->x[1]); 798 //flip(&x[0],&x[1]); 799 flip(&x1->x[1],&x1->x[2]); 800 flip(&x2->x[1],&x2->x[2]); 801 flip(&y->x[1],&y->x[2]); 802 //flip(&x[1],&x[2]); 803 case 1: 804 flip(&x1->x[0],&x1->x[1]); 805 flip(&x2->x[0],&x2->x[1]); 806 flip(&y->x[0],&y->x[1]); 807 //flip(&x[0],&x[1]); 808 flip(&x1->x[1],&x1->x[2]); 809 flip(&x2->x[1],&x2->x[2]); 810 flip(&y->x[1],&y->x[2]); 811 //flip(&x[1],&x[2]); 812 break; 813 } 814 // now comes the case system 815 D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1]; 816 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2]; 817 D3 = y->x[0]/x1->x[0]*A-B1; 818 cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n"; 819 if (fabs(D1) < MYEPSILON) { 820 cout << Verbose(2) << "D1 == 0!\n"; 821 if (fabs(D2) > MYEPSILON) { 822 cout << Verbose(3) << "D2 != 0!\n"; 823 x[2] = -D3/D2; 824 E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2; 825 E2 = -x1->x[1]/x1->x[0]; 826 cout << Verbose(3) << "E1 " << E1 << "\tE2 " << E2 << "\n"; 827 F1 = E1*E1 + 1.; 828 F2 = -E1*E2; 829 F3 = E1*E1 + D3*D3/(D2*D2) - C; 830 cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 831 if (fabs(F1) < MYEPSILON) { 832 cout << Verbose(4) << "F1 == 0!\n"; 833 cout << Verbose(4) << "Gleichungssystem linear\n"; 834 x[1] = F3/(2.*F2); 835 } else { 836 p = F2/F1; 837 q = p*p - F3/F1; 838 cout << Verbose(4) << "p " << p << "\tq " << q << endl; 839 if (q < 0) { 840 cout << Verbose(4) << "q < 0" << endl; 841 return false; 842 } 843 x[1] = p + sqrt(q); 844 } 845 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2]; 846 } else { 847 cout << Verbose(2) << "Gleichungssystem unterbestimmt\n"; 848 return false; 849 } 850 } else { 851 E1 = A/x1->x[0]+x1->x[1]/x1->x[0]*D3/D1; 852 E2 = x1->x[1]/x1->x[0]*D2/D1 - x1->x[2]; 853 cout << Verbose(2) << "E1 " << E1 << "\tE2 " << E2 << "\n"; 854 F1 = E2*E2 + D2*D2/(D1*D1) + 1.; 855 F2 = -(E1*E2 + D2*D3/(D1*D1)); 856 F3 = E1*E1 + D3*D3/(D1*D1) - C; 857 cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 858 if (fabs(F1) < MYEPSILON) { 859 cout << Verbose(3) << "F1 == 0!\n"; 860 cout << Verbose(3) << "Gleichungssystem linear\n"; 861 x[2] = F3/(2.*F2); 862 } else { 863 p = F2/F1; 864 q = p*p - F3/F1; 865 cout << Verbose(3) << "p " << p << "\tq " << q << endl; 866 if (q < 0) { 867 cout << Verbose(3) << "q < 0" << endl; 868 return false; 869 } 870 x[2] = p + sqrt(q); 871 } 872 x[1] = (-D2 * x[2] - D3)/D1; 873 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2]; 874 } 875 switch (flag) { // back-flipping 876 default: 877 case 0: 878 break; 879 case 2: 880 flip(&x1->x[0],&x1->x[1]); 881 flip(&x2->x[0],&x2->x[1]); 882 flip(&y->x[0],&y->x[1]); 883 flip(&x[0],&x[1]); 884 flip(&x1->x[1],&x1->x[2]); 885 flip(&x2->x[1],&x2->x[2]); 886 flip(&y->x[1],&y->x[2]); 887 flip(&x[1],&x[2]); 888 case 1: 889 flip(&x1->x[0],&x1->x[1]); 890 flip(&x2->x[0],&x2->x[1]); 891 flip(&y->x[0],&y->x[1]); 892 //flip(&x[0],&x[1]); 893 flip(&x1->x[1],&x1->x[2]); 894 flip(&x2->x[1],&x2->x[2]); 895 flip(&y->x[1],&y->x[2]); 896 flip(&x[1],&x[2]); 897 break; 898 } 899 // one z component is only determined by its radius (without sign) 900 // thus check eight possible sign flips and determine by checking angle with second vector 901 for (i=0;i<8;i++) { 902 // set sign vector accordingly 903 for (j=2;j>=0;j--) { 904 k = (i & pot(2,j)) << j; 905 cout << Verbose(2) << "k " << k << "\tpot(2,j) " << pot(2,j) << endl; 906 sign[j] = (k == 0) ? 1. : -1.; 907 } 908 cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n"; 909 // apply sign matrix 910 for (j=NDIM;j--;) 911 x[j] *= sign[j]; 912 // calculate angle and check 913 ang = x2->Angle (this); 914 cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t"; 915 if (fabs(ang - cos(beta)) < MYEPSILON) { 916 break; 917 } 918 // unapply sign matrix (is its own inverse) 919 for (j=NDIM;j--;) 920 x[j] *= sign[j]; 921 } 922 return true; 923 }; -
src/vector.hpp
rce5ac3 rd067d45 8 8 */ 9 9 class Vector { 10 public:11 double x[NDIM];10 public: 11 double x[NDIM]; 12 12 13 Vector();14 Vector(double x1, double x2, double x3);15 ~Vector();13 Vector(); 14 Vector(double x1, double x2, double x3); 15 ~Vector(); 16 16 17 double Distance(const Vector *y) const; 18 double DistanceSquared(const Vector *y) const; 19 double PeriodicDistance(const Vector *y, const double *cell_size) const; 20 double ScalarProduct(const Vector *y) const; 21 double Projection(const Vector *y) const; 22 double Norm() const ; 23 double Angle(const Vector *y) const; 17 double Distance(const Vector *y) const; 18 double DistanceSquared(const Vector *y) const; 19 double PeriodicDistance(const Vector *y, const double *cell_size) const; 20 double PeriodicDistanceSquared(const Vector *y, const double *cell_size) const; 21 double ScalarProduct(const Vector *y) const; 22 double Projection(const Vector *y) const; 23 double Norm() const ; 24 double Angle(const Vector *y) const; 24 25 25 void AddVector(const Vector *y); 26 void SubtractVector(const Vector *y); 27 void CopyVector(const Vector *y); 28 void RotateVector(const Vector *y, const double alpha); 29 void VectorProduct(const Vector *y); 30 void ProjectOntoPlane(const Vector *y); 31 void Zero(); 32 void One(double one); 33 void Init(double x1, double x2, double x3); 34 void Normalize(); 35 void Translate(const Vector *x); 36 void Mirror(const Vector *x); 37 void Scale(double **factor); 38 void Scale(double *factor); 39 void Scale(double factor); 40 void MatrixMultiplication(double *M); 41 void InverseMatrixMultiplication(double *M); 42 void KeepPeriodic(ofstream *out, double *matrix); 43 void LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors); 44 45 double CutsPlaneAt(Vector *A, Vector *B, Vector *C); 46 bool GetOneNormalVector(const Vector *x1); 47 bool MakeNormalVector(const Vector *y1); 48 bool MakeNormalVector(const Vector *y1, const Vector *y2); 49 bool MakeNormalVector(const Vector *x1, const Vector *x2, const Vector *x3); 50 bool SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c); 51 bool LSQdistance(Vector **vectors, int dim); 52 53 void AskPosition(double *cell_size, bool check); 54 bool Output(ofstream *out) const; 26 void AddVector(const Vector *y); 27 void SubtractVector(const Vector *y); 28 void CopyVector(const Vector *y); 29 void RotateVector(const Vector *y, const double alpha); 30 void VectorProduct(const Vector *y); 31 void ProjectOntoPlane(const Vector *y); 32 void Zero(); 33 void One(double one); 34 void Init(double x1, double x2, double x3); 35 void Normalize(); 36 void Translate(const Vector *x); 37 void Mirror(const Vector *x); 38 void Scale(double **factor); 39 void Scale(double *factor); 40 void Scale(double factor); 41 void MatrixMultiplication(double *M); 42 void InverseMatrixMultiplication(double *M); 43 void KeepPeriodic(ofstream *out, double *matrix); 44 void LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors); 45 double CutsPlaneAt(Vector *A, Vector *B, Vector *C); 46 bool GetOneNormalVector(const Vector *x1); 47 bool MakeNormalVector(const Vector *y1); 48 bool MakeNormalVector(const Vector *y1, const Vector *y2); 49 bool MakeNormalVector(const Vector *x1, const Vector *x2, const Vector *x3); 50 bool SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c); 51 bool LSQdistance(Vector **vectors, int dim); 52 void AskPosition(double *cell_size, bool check); 53 bool Output(ofstream *out) const; 55 54 }; 56 55 -
src/verbose.cpp
rce5ac3 rd067d45 7 7 ostream& Verbose::print (ostream &ost) const 8 8 { 9 for (int i=Verbosity;i--;)10 ost.put('\t');11 //cout << "Verbose(.) called." << endl;12 return ost;9 for (int i=Verbosity;i--;) 10 ost.put('\t'); 11 //cout << "Verbose(.) called." << endl; 12 return ost; 13 13 }; 14 14
Note:
See TracChangeset
for help on using the changeset viewer.
