- Timestamp:
- Feb 9, 2009, 2:18:13 PM (16 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
- Children:
- 5bc4d0
- Parents:
- 674220 (diff), cc2ee5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src
- Files:
-
- 5 added
- 32 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Hbondangle.db ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/Hbonddistance.db ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/Makefile.am ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/analyzer.cpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/atom.cpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/bond.cpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
TabularUnified src/boundary.cpp ¶
-
Property mode
changed from
100644
to100755
r674220 ra98603 2 2 #include "boundary.hpp" 3 3 4 #define DEBUG 1 5 #define DoTecplotOutput 0 6 #define DoRaster3DOutput 1 7 #define TecplotSuffix ".dat" 8 #define Raster3DSuffix ".r3d" 9 4 10 // ======================================== Points on Boundary ================================= 5 11 … … 8 14 LinesCount = 0; 9 15 Nr = -1; 10 }; 16 } 17 ; 11 18 12 19 BoundaryPointSet::BoundaryPointSet(atom *Walker) … … 15 22 LinesCount = 0; 16 23 Nr = Walker->nr; 17 }; 24 } 25 ; 18 26 19 27 BoundaryPointSet::~BoundaryPointSet() … … 21 29 cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl; 22 30 node = NULL; 23 }; 24 25 void BoundaryPointSet::AddLine(class BoundaryLineSet *line) 26 { 27 cout << Verbose(6) << "Adding line " << *line << " to " << *this << "." << endl; 28 if (line->endpoints[0] == this) { 29 lines.insert ( LinePair( line->endpoints[1]->Nr, line) ); 30 } else { 31 lines.insert ( LinePair( line->endpoints[0]->Nr, line) ); 32 } 31 lines.clear(); 32 } 33 ; 34 35 void 36 BoundaryPointSet::AddLine(class BoundaryLineSet *line) 37 { 38 cout << Verbose(6) << "Adding " << *this << " to line " << *line << "." 39 << endl; 40 if (line->endpoints[0] == this) 41 { 42 lines.insert(LinePair(line->endpoints[1]->Nr, line)); 43 } 44 else 45 { 46 lines.insert(LinePair(line->endpoints[0]->Nr, line)); 47 } 33 48 LinesCount++; 34 }; 35 36 ostream & operator << (ostream &ost, BoundaryPointSet &a) 49 } 50 ; 51 52 ostream & 53 operator <<(ostream &ost, BoundaryPointSet &a) 37 54 { 38 55 ost << "[" << a.Nr << "|" << a.node->Name << "]"; 39 56 return ost; 40 }; 57 } 58 ; 41 59 42 60 // ======================================== Lines on Boundary ================================= … … 44 62 BoundaryLineSet::BoundaryLineSet() 45 63 { 46 for (int i =0;i<2;i++)64 for (int i = 0; i < 2; i++) 47 65 endpoints[i] = NULL; 48 66 TrianglesCount = 0; 49 67 Nr = -1; 50 }; 68 } 69 ; 51 70 52 71 BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number) … … 57 76 SetEndpointsOrdered(endpoints, Point[0], Point[1]); 58 77 // add this line to the hash maps of both endpoints 59 Point[0]->AddLine(this); 60 Point[1]->AddLine(this); 78 Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding. 79 Point[1]->AddLine(this); // 61 80 // clear triangles list 62 81 TrianglesCount = 0; 63 82 cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl; 64 }; 83 } 84 ; 65 85 66 86 BoundaryLineSet::~BoundaryLineSet() 67 87 { 68 for (int i=0;i<2;i++) { 69 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 70 endpoints[i]->lines.erase(Nr); 71 LineMap::iterator tester = endpoints[i]->lines.begin(); 72 tester++; 73 if (tester == endpoints[i]->lines.end()) { 74 cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl; 75 delete(endpoints[i]); 76 } else 77 cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl; 78 } 79 }; 80 81 void BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 82 { 83 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." << endl; 84 triangles.insert ( TrianglePair( TrianglesCount, triangle) ); 88 for (int i = 0; i < 2; i++) { 89 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 90 endpoints[i]->lines.erase(Nr); 91 LineMap::iterator tester = endpoints[i]->lines.begin(); 92 tester++; 93 if (tester == endpoints[i]->lines.end()) { 94 cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl; 95 if (endpoints[i] != NULL) { 96 delete(endpoints[i]); 97 endpoints[i] = NULL; 98 } else 99 cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl; 100 } else 101 cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl; 102 } 103 } 104 ; 105 106 void 107 BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 108 { 109 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." 110 << endl; 111 triangles.insert(TrianglePair(TrianglesCount, triangle)); 85 112 TrianglesCount++; 86 }; 87 88 ostream & operator << (ostream &ost, BoundaryLineSet &a) 89 { 90 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "]"; 113 } 114 ; 115 116 ostream & 117 operator <<(ostream &ost, BoundaryLineSet &a) 118 { 119 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 120 << a.endpoints[1]->node->Name << "]"; 91 121 return ost; 92 }; 122 } 123 ; 93 124 94 125 // ======================================== Triangles on Boundary ================================= … … 97 128 BoundaryTriangleSet::BoundaryTriangleSet() 98 129 { 99 for (int i=0;i<3;i++) { 100 endpoints[i] = NULL; 101 lines[i] = NULL; 102 } 130 for (int i = 0; i < 3; i++) 131 { 132 endpoints[i] = NULL; 133 lines[i] = NULL; 134 } 103 135 Nr = -1; 104 }; 105 106 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], int number) 136 } 137 ; 138 139 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], 140 int number) 107 141 { 108 142 // set number … … 110 144 // set lines 111 145 cout << Verbose(5) << "New triangle " << Nr << ":" << endl; 112 for (int i=0;i<3;i++) { 113 lines[i] = line[i]; 114 lines[i]->AddTriangle(this); 115 } 146 for (int i = 0; i < 3; i++) 147 { 148 lines[i] = line[i]; 149 lines[i]->AddTriangle(this); 150 } 116 151 // get ascending order of endpoints 117 map <int, class BoundaryPointSet * > OrderMap; 118 for(int i=0;i<3;i++) // for all three lines 119 for (int j=0;j<2;j++) { // for both endpoints 120 OrderMap.insert ( pair <int, class BoundaryPointSet * >( line[i]->endpoints[j]->Nr, line[i]->endpoints[j]) ); 121 // and we don't care whether insertion fails 122 } 152 map<int, class BoundaryPointSet *> OrderMap; 153 for (int i = 0; i < 3; i++) 154 // for all three lines 155 for (int j = 0; j < 2; j++) 156 { // for both endpoints 157 OrderMap.insert(pair<int, class BoundaryPointSet *> ( 158 line[i]->endpoints[j]->Nr, line[i]->endpoints[j])); 159 // and we don't care whether insertion fails 160 } 123 161 // set endpoints 124 162 int Counter = 0; 125 163 cout << Verbose(6) << " with end points "; 126 for (map <int, class BoundaryPointSet * >::iterator runner = OrderMap.begin(); runner != OrderMap.end(); runner++) { 127 endpoints[Counter] = runner->second; 128 cout << " " << *endpoints[Counter]; 129 Counter++; 130 } 131 if (Counter < 3) { 132 cerr << "ERROR! We have a triangle with only two distinct endpoints!" << endl; 133 //exit(1); 134 } 164 for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner 165 != OrderMap.end(); runner++) 166 { 167 endpoints[Counter] = runner->second; 168 cout << " " << *endpoints[Counter]; 169 Counter++; 170 } 171 if (Counter < 3) 172 { 173 cerr << "ERROR! We have a triangle with only two distinct endpoints!" 174 << endl; 175 //exit(1); 176 } 135 177 cout << "." << endl; 136 }; 178 } 179 ; 137 180 138 181 BoundaryTriangleSet::~BoundaryTriangleSet() 139 182 { 140 for (int i=0;i<3;i++) { 141 cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl; 142 lines[i]->triangles.erase(Nr); 143 TriangleMap::iterator tester = lines[i]->triangles.begin(); 144 tester++; 145 if (tester == lines[i]->triangles.end()) { 146 cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl; 147 delete(lines[i]); 148 } else 149 cout << Verbose(5) << *lines[i] << " is still attached to a triangle." << endl; 150 } 151 }; 152 153 void BoundaryTriangleSet::GetNormalVector(Vector &NormalVector) 183 for (int i = 0; i < 3; i++) { 184 cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl; 185 lines[i]->triangles.erase(Nr); 186 if (lines[i]->triangles.empty()) { 187 cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl; 188 if (lines[i] != NULL) { 189 delete (lines[i]); 190 lines[i] = NULL; 191 } else 192 cerr << "ERROR: This line " << i << " has already been free'd." << endl; 193 } else 194 cout << Verbose(5) << *lines[i] << " is still attached to a triangle." << endl; 195 } 196 } 197 ; 198 199 void 200 BoundaryTriangleSet::GetNormalVector(Vector &OtherVector) 154 201 { 155 202 // get normal vector 156 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, &endpoints[2]->node->x); 157 203 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, 204 &endpoints[2]->node->x); 205 158 206 // make it always point inward (any offset vector onto plane projected onto normal vector suffices) 159 if (endpoints[0]->node->x.Projection(& NormalVector) > 0)207 if (endpoints[0]->node->x.Projection(&OtherVector) > 0) 160 208 NormalVector.Scale(-1.); 161 }; 162 163 ostream & operator << (ostream &ost, BoundaryTriangleSet &a) 164 { 165 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]"; 209 } 210 ; 211 212 ostream & 213 operator <<(ostream &ost, BoundaryTriangleSet &a) 214 { 215 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 216 << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]"; 166 217 return ost; 167 }; 218 } 219 ; 168 220 169 221 // ========================================== F U N C T I O N S ================================= … … 174 226 * \return point which is shared or NULL if none 175 227 */ 176 class BoundaryPointSet * GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2) 177 { 178 class BoundaryLineSet * lines[2] = {line1, line2}; 228 class BoundaryPointSet * 229 GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2) 230 { 231 class BoundaryLineSet * lines[2] = 232 { line1, line2 }; 179 233 class BoundaryPointSet *node = NULL; 180 map <int, class BoundaryPointSet * > OrderMap; 181 pair < map <int, class BoundaryPointSet * >::iterator, bool > OrderTest; 182 for(int i=0;i<2;i++) // for both lines 183 for (int j=0;j<2;j++) { // for both endpoints 184 OrderTest = OrderMap.insert ( pair <int, class BoundaryPointSet * >( lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]) ); 185 if (!OrderTest.second) { // if insertion fails, we have common endpoint 186 node = OrderTest.first->second; 187 cout << Verbose(5) << "Common endpoint of lines " << *line1 << " and " << *line2 << " is: " << *node << "." << endl; 188 j=2; 189 i=2; 190 break; 234 map<int, class BoundaryPointSet *> OrderMap; 235 pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest; 236 for (int i = 0; i < 2; i++) 237 // for both lines 238 for (int j = 0; j < 2; j++) 239 { // for both endpoints 240 OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> ( 241 lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j])); 242 if (!OrderTest.second) 243 { // if insertion fails, we have common endpoint 244 node = OrderTest.first->second; 245 cout << Verbose(5) << "Common endpoint of lines " << *line1 246 << " and " << *line2 << " is: " << *node << "." << endl; 247 j = 2; 248 i = 2; 249 break; 250 } 191 251 } 192 }193 252 return node; 194 }; 253 } 254 ; 195 255 196 256 /** Determines the boundary points of a cluster. … … 201 261 * \param *mol molecule structure representing the cluster 202 262 */ 203 Boundaries * GetBoundaryPoints(ofstream *out, molecule *mol) 263 Boundaries * 264 GetBoundaryPoints(ofstream *out, molecule *mol) 204 265 { 205 266 atom *Walker = NULL; … … 207 268 LineMap LinesOnBoundary; 208 269 TriangleMap TrianglesOnBoundary; 209 270 210 271 *out << Verbose(1) << "Finding all boundary points." << endl; 211 Boundaries *BoundaryPoints = new Boundaries [NDIM];// first is alpha, second is (r, nr)272 Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr) 212 273 BoundariesTestPair BoundaryTestPair; 213 274 Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector; 214 275 double radius, angle; 215 276 // 3a. Go through every axis 216 for (int axis=0; axis<NDIM; axis++) { 217 AxisVector.Zero(); 218 AngleReferenceVector.Zero(); 219 AngleReferenceNormalVector.Zero(); 220 AxisVector.x[axis] = 1.; 221 AngleReferenceVector.x[(axis+1)%NDIM] = 1.; 222 AngleReferenceNormalVector.x[(axis+2)%NDIM] = 1.; 223 // *out << Verbose(1) << "Axisvector is "; 224 // AxisVector.Output(out); 225 // *out << " and AngleReferenceVector is "; 226 // AngleReferenceVector.Output(out); 227 // *out << "." << endl; 228 // *out << " and AngleReferenceNormalVector is "; 229 // AngleReferenceNormalVector.Output(out); 230 // *out << "." << endl; 231 // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours 232 Walker = mol->start; 233 while (Walker->next != mol->end) { 234 Walker = Walker->next; 235 Vector ProjectedVector; 236 ProjectedVector.CopyVector(&Walker->x); 237 ProjectedVector.ProjectOntoPlane(&AxisVector); 238 // correct for negative side 239 //if (Projection(y) < 0) 240 //angle = 2.*M_PI - angle; 241 radius = ProjectedVector.Norm(); 242 if (fabs(radius) > MYEPSILON) 243 angle = ProjectedVector.Angle(&AngleReferenceVector); 244 else 245 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues 246 247 //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl; 248 if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) { 249 angle = 2.*M_PI - angle; 250 } 251 //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): "; 252 //ProjectedVector.Output(out); 253 //*out << endl; 254 BoundaryTestPair = BoundaryPoints[axis].insert( BoundariesPair (angle, DistancePair (radius, Walker) ) ); 255 if (BoundaryTestPair.second) { // successfully inserted 256 } else { // same point exists, check first r, then distance of original vectors to center of gravity 257 *out << Verbose(2) << "Encountered two vectors whose projection onto axis " << axis << " is equal: " << endl; 258 *out << Verbose(2) << "Present vector: "; 259 BoundaryTestPair.first->second.second->x.Output(out); 260 *out << endl; 261 *out << Verbose(2) << "New vector: "; 262 Walker->x.Output(out); 263 *out << endl; 264 double tmp = ProjectedVector.Norm(); 265 if (tmp > BoundaryTestPair.first->second.first) { 266 BoundaryTestPair.first->second.first = tmp; 267 BoundaryTestPair.first->second.second = Walker; 268 *out << Verbose(2) << "Keeping new vector." << endl; 269 } else if (tmp == BoundaryTestPair.first->second.first) { 270 if (BoundaryTestPair.first->second.second->x.ScalarProduct(&BoundaryTestPair.first->second.second->x) < Walker->x.ScalarProduct(&Walker->x)) { // Norm() does a sqrt, which makes it a lot slower 271 BoundaryTestPair.first->second.second = Walker; 272 *out << Verbose(2) << "Keeping new vector." << endl; 273 } else { 274 *out << Verbose(2) << "Keeping present vector." << endl; 275 } 276 } else { 277 *out << Verbose(2) << "Keeping present vector." << endl; 277 for (int axis = 0; axis < NDIM; axis++) 278 { 279 AxisVector.Zero(); 280 AngleReferenceVector.Zero(); 281 AngleReferenceNormalVector.Zero(); 282 AxisVector.x[axis] = 1.; 283 AngleReferenceVector.x[(axis + 1) % NDIM] = 1.; 284 AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.; 285 // *out << Verbose(1) << "Axisvector is "; 286 // AxisVector.Output(out); 287 // *out << " and AngleReferenceVector is "; 288 // AngleReferenceVector.Output(out); 289 // *out << "." << endl; 290 // *out << " and AngleReferenceNormalVector is "; 291 // AngleReferenceNormalVector.Output(out); 292 // *out << "." << endl; 293 // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours 294 Walker = mol->start; 295 while (Walker->next != mol->end) 296 { 297 Walker = Walker->next; 298 Vector ProjectedVector; 299 ProjectedVector.CopyVector(&Walker->x); 300 ProjectedVector.ProjectOntoPlane(&AxisVector); 301 // correct for negative side 302 //if (Projection(y) < 0) 303 //angle = 2.*M_PI - angle; 304 radius = ProjectedVector.Norm(); 305 if (fabs(radius) > MYEPSILON) 306 angle = ProjectedVector.Angle(&AngleReferenceVector); 307 else 308 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues 309 310 //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl; 311 if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) 312 { 313 angle = 2. * M_PI - angle; 314 } 315 //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): "; 316 //ProjectedVector.Output(out); 317 //*out << endl; 318 BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle, 319 DistancePair (radius, Walker))); 320 if (BoundaryTestPair.second) 321 { // successfully inserted 322 } 323 else 324 { // same point exists, check first r, then distance of original vectors to center of gravity 325 *out << Verbose(2) 326 << "Encountered two vectors whose projection onto axis " 327 << axis << " is equal: " << endl; 328 *out << Verbose(2) << "Present vector: "; 329 BoundaryTestPair.first->second.second->x.Output(out); 330 *out << endl; 331 *out << Verbose(2) << "New vector: "; 332 Walker->x.Output(out); 333 *out << endl; 334 double tmp = ProjectedVector.Norm(); 335 if (tmp > BoundaryTestPair.first->second.first) 336 { 337 BoundaryTestPair.first->second.first = tmp; 338 BoundaryTestPair.first->second.second = Walker; 339 *out << Verbose(2) << "Keeping new vector." << endl; 340 } 341 else if (tmp == BoundaryTestPair.first->second.first) 342 { 343 if (BoundaryTestPair.first->second.second->x.ScalarProduct( 344 &BoundaryTestPair.first->second.second->x) 345 < Walker->x.ScalarProduct(&Walker->x)) 346 { // Norm() does a sqrt, which makes it a lot slower 347 BoundaryTestPair.first->second.second = Walker; 348 *out << Verbose(2) << "Keeping new vector." << endl; 349 } 350 else 351 { 352 *out << Verbose(2) << "Keeping present vector." << endl; 353 } 354 } 355 else 356 { 357 *out << Verbose(2) << "Keeping present vector." << endl; 358 } 359 } 278 360 } 279 } 280 } 281 // printing all inserted for debugging 282 // { 283 // *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl; 284 // int i=0; 285 // for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 286 // if (runner != BoundaryPoints[axis].begin()) 287 // *out << ", " << i << ": " << *runner->second.second; 288 // else 289 // *out << i << ": " << *runner->second.second; 290 // i++; 291 // } 292 // *out << endl; 293 // } 294 // 3c. throw out points whose distance is less than the mean of left and right neighbours 295 bool flag = false; 296 do { // do as long as we still throw one out per round 297 *out << Verbose(1) << "Looking for candidates to kick out by convex condition ... " << endl; 298 flag = false; 299 Boundaries::iterator left = BoundaryPoints[axis].end(); 300 Boundaries::iterator right = BoundaryPoints[axis].end(); 301 for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 302 // set neighbours correctly 303 if (runner == BoundaryPoints[axis].begin()) { 304 left = BoundaryPoints[axis].end(); 305 } else { 306 left = runner; 361 // printing all inserted for debugging 362 // { 363 // *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl; 364 // int i=0; 365 // for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 366 // if (runner != BoundaryPoints[axis].begin()) 367 // *out << ", " << i << ": " << *runner->second.second; 368 // else 369 // *out << i << ": " << *runner->second.second; 370 // i++; 371 // } 372 // *out << endl; 373 // } 374 // 3c. throw out points whose distance is less than the mean of left and right neighbours 375 bool flag = false; 376 do 377 { // do as long as we still throw one out per round 378 *out << Verbose(1) 379 << "Looking for candidates to kick out by convex condition ... " 380 << endl; 381 flag = false; 382 Boundaries::iterator left = BoundaryPoints[axis].end(); 383 Boundaries::iterator right = BoundaryPoints[axis].end(); 384 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 385 != BoundaryPoints[axis].end(); runner++) 386 { 387 // set neighbours correctly 388 if (runner == BoundaryPoints[axis].begin()) 389 { 390 left = BoundaryPoints[axis].end(); 391 } 392 else 393 { 394 left = runner; 395 } 396 left--; 397 right = runner; 398 right++; 399 if (right == BoundaryPoints[axis].end()) 400 { 401 right = BoundaryPoints[axis].begin(); 402 } 403 // check distance 404 405 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector) 406 { 407 Vector SideA, SideB, SideC, SideH; 408 SideA.CopyVector(&left->second.second->x); 409 SideA.ProjectOntoPlane(&AxisVector); 410 // *out << "SideA: "; 411 // SideA.Output(out); 412 // *out << endl; 413 414 SideB.CopyVector(&right->second.second->x); 415 SideB.ProjectOntoPlane(&AxisVector); 416 // *out << "SideB: "; 417 // SideB.Output(out); 418 // *out << endl; 419 420 SideC.CopyVector(&left->second.second->x); 421 SideC.SubtractVector(&right->second.second->x); 422 SideC.ProjectOntoPlane(&AxisVector); 423 // *out << "SideC: "; 424 // SideC.Output(out); 425 // *out << endl; 426 427 SideH.CopyVector(&runner->second.second->x); 428 SideH.ProjectOntoPlane(&AxisVector); 429 // *out << "SideH: "; 430 // SideH.Output(out); 431 // *out << endl; 432 433 // calculate each length 434 double a = SideA.Norm(); 435 //double b = SideB.Norm(); 436 //double c = SideC.Norm(); 437 double h = SideH.Norm(); 438 // calculate the angles 439 double alpha = SideA.Angle(&SideH); 440 double beta = SideA.Angle(&SideC); 441 double gamma = SideB.Angle(&SideH); 442 double delta = SideC.Angle(&SideH); 443 double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha 444 < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.); 445 // *out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl; 446 //*out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl; 447 if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance)) 448 < MYEPSILON) && (h < MinDistance)) 449 { 450 // throw out point 451 //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl; 452 BoundaryPoints[axis].erase(runner); 453 flag = true; 454 } 455 } 456 } 307 457 } 308 left--; 309 right = runner; 310 right++; 311 if (right == BoundaryPoints[axis].end()) { 312 right = BoundaryPoints[axis].begin(); 313 } 314 // check distance 315 316 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector) 317 { 318 Vector SideA, SideB, SideC, SideH; 319 SideA.CopyVector(&left->second.second->x); 320 SideA.ProjectOntoPlane(&AxisVector); 321 // *out << "SideA: "; 322 // SideA.Output(out); 323 // *out << endl; 324 325 SideB.CopyVector(&right->second.second->x); 326 SideB.ProjectOntoPlane(&AxisVector); 327 // *out << "SideB: "; 328 // SideB.Output(out); 329 // *out << endl; 330 331 SideC.CopyVector(&left->second.second->x); 332 SideC.SubtractVector(&right->second.second->x); 333 SideC.ProjectOntoPlane(&AxisVector); 334 // *out << "SideC: "; 335 // SideC.Output(out); 336 // *out << endl; 337 338 SideH.CopyVector(&runner->second.second->x); 339 SideH.ProjectOntoPlane(&AxisVector); 340 // *out << "SideH: "; 341 // SideH.Output(out); 342 // *out << endl; 343 344 // calculate each length 345 double a = SideA.Norm(); 346 //double b = SideB.Norm(); 347 //double c = SideC.Norm(); 348 double h = SideH.Norm(); 349 // calculate the angles 350 double alpha = SideA.Angle(&SideH); 351 double beta = SideA.Angle(&SideC); 352 double gamma = SideB.Angle(&SideH); 353 double delta = SideC.Angle(&SideH); 354 double MinDistance = a * sin(beta)/(sin(delta)) * (((alpha < M_PI/2.) || (gamma < M_PI/2.)) ? 1. : -1.); 355 // *out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl; 356 //*out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl; 357 if ((fabs(h/fabs(h) - MinDistance/fabs(MinDistance)) < MYEPSILON) && (h < MinDistance)) { 358 // throw out point 359 //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl; 360 BoundaryPoints[axis].erase(runner); 361 flag = true; 362 } 363 } 364 } 365 } while (flag); 366 } 458 while (flag); 459 } 367 460 return BoundaryPoints; 368 }; 461 } 462 ; 369 463 370 464 /** Determines greatest diameters of a cluster defined by its convex envelope. … … 375 469 * \param IsAngstroem whether we have angstroem or atomic units 376 470 * \return NDIM array of the diameters 377 */ 378 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem) 471 */ 472 double * 473 GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, 474 bool IsAngstroem) 379 475 { 380 476 // get points on boundary of NULL was given as parameter 381 477 bool BoundaryFreeFlag = false; 382 478 Boundaries *BoundaryPoints = BoundaryPtr; 383 if (BoundaryPoints == NULL) { 384 BoundaryFreeFlag = true; 385 BoundaryPoints = GetBoundaryPoints(out, mol); 386 } else { 387 *out << Verbose(1) << "Using given boundary points set." << endl; 388 } 389 479 if (BoundaryPoints == NULL) 480 { 481 BoundaryFreeFlag = true; 482 BoundaryPoints = GetBoundaryPoints(out, mol); 483 } 484 else 485 { 486 *out << Verbose(1) << "Using given boundary points set." << endl; 487 } 390 488 // determine biggest "diameter" of cluster for each axis 391 489 Boundaries::iterator Neighbour, OtherNeighbour; 392 490 double *GreatestDiameter = new double[NDIM]; 393 for (int i=0;i<NDIM;i++)491 for (int i = 0; i < NDIM; i++) 394 492 GreatestDiameter[i] = 0.; 395 493 double OldComponent, tmp, w1, w2; 396 494 Vector DistanceVector, OtherVector; 397 495 int component, Othercomponent; 398 for(int axis=0;axis<NDIM;axis++) { // regard each projected plane 399 //*out << Verbose(1) << "Current axis is " << axis << "." << endl; 400 for (int j=0;j<2;j++) { // and for both axis on the current plane 401 component = (axis+j+1)%NDIM; 402 Othercomponent = (axis+1+((j+1) & 1))%NDIM; 403 //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl; 404 for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 405 //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl; 406 // seek for the neighbours pair where the Othercomponent sign flips 407 Neighbour = runner; 408 Neighbour++; 409 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 410 Neighbour = BoundaryPoints[axis].begin(); 411 DistanceVector.CopyVector(&runner->second.second->x); 412 DistanceVector.SubtractVector(&Neighbour->second.second->x); 413 do { // seek for neighbour pair where it flips 414 OldComponent = DistanceVector.x[Othercomponent]; 415 Neighbour++; 416 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 417 Neighbour = BoundaryPoints[axis].begin(); 418 DistanceVector.CopyVector(&runner->second.second->x); 419 DistanceVector.SubtractVector(&Neighbour->second.second->x); 420 //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl; 421 } while ((runner != Neighbour) && ( fabs( OldComponent/fabs(OldComponent) - DistanceVector.x[Othercomponent]/fabs(DistanceVector.x[Othercomponent]) ) < MYEPSILON)); // as long as sign does not flip 422 if (runner != Neighbour) { 423 OtherNeighbour = Neighbour; 424 if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around 425 OtherNeighbour = BoundaryPoints[axis].end(); 426 OtherNeighbour--; 427 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl; 428 // now we have found the pair: Neighbour and OtherNeighbour 429 OtherVector.CopyVector(&runner->second.second->x); 430 OtherVector.SubtractVector(&OtherNeighbour->second.second->x); 431 //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl; 432 //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl; 433 // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour 434 w1 = fabs(OtherVector.x[Othercomponent]); 435 w2 = fabs(DistanceVector.x[Othercomponent]); 436 tmp = fabs((w1*DistanceVector.x[component] + w2*OtherVector.x[component])/(w1+w2)); 437 // mark if it has greater diameter 438 //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl; 439 GreatestDiameter[component] = (GreatestDiameter[component] > tmp) ? GreatestDiameter[component] : tmp; 440 } //else 441 //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl; 442 } 443 } 444 } 445 *out << Verbose(0) << "RESULT: The biggest diameters are " << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and " << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "." << endl; 496 for (int axis = 0; axis < NDIM; axis++) 497 { // regard each projected plane 498 //*out << Verbose(1) << "Current axis is " << axis << "." << endl; 499 for (int j = 0; j < 2; j++) 500 { // and for both axis on the current plane 501 component = (axis + j + 1) % NDIM; 502 Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM; 503 //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl; 504 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 505 != BoundaryPoints[axis].end(); runner++) 506 { 507 //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl; 508 // seek for the neighbours pair where the Othercomponent sign flips 509 Neighbour = runner; 510 Neighbour++; 511 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 512 Neighbour = BoundaryPoints[axis].begin(); 513 DistanceVector.CopyVector(&runner->second.second->x); 514 DistanceVector.SubtractVector(&Neighbour->second.second->x); 515 do 516 { // seek for neighbour pair where it flips 517 OldComponent = DistanceVector.x[Othercomponent]; 518 Neighbour++; 519 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 520 Neighbour = BoundaryPoints[axis].begin(); 521 DistanceVector.CopyVector(&runner->second.second->x); 522 DistanceVector.SubtractVector(&Neighbour->second.second->x); 523 //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl; 524 } 525 while ((runner != Neighbour) && (fabs(OldComponent / fabs( 526 OldComponent) - DistanceVector.x[Othercomponent] / fabs( 527 DistanceVector.x[Othercomponent])) < MYEPSILON)); // as long as sign does not flip 528 if (runner != Neighbour) 529 { 530 OtherNeighbour = Neighbour; 531 if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around 532 OtherNeighbour = BoundaryPoints[axis].end(); 533 OtherNeighbour--; 534 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl; 535 // now we have found the pair: Neighbour and OtherNeighbour 536 OtherVector.CopyVector(&runner->second.second->x); 537 OtherVector.SubtractVector(&OtherNeighbour->second.second->x); 538 //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl; 539 //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl; 540 // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour 541 w1 = fabs(OtherVector.x[Othercomponent]); 542 w2 = fabs(DistanceVector.x[Othercomponent]); 543 tmp = fabs((w1 * DistanceVector.x[component] + w2 544 * OtherVector.x[component]) / (w1 + w2)); 545 // mark if it has greater diameter 546 //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl; 547 GreatestDiameter[component] = (GreatestDiameter[component] 548 > tmp) ? GreatestDiameter[component] : tmp; 549 } //else 550 //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl; 551 } 552 } 553 } 554 *out << Verbose(0) << "RESULT: The biggest diameters are " 555 << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and " 556 << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom" 557 : "atomiclength") << "." << endl; 446 558 447 559 // free reference lists 448 560 if (BoundaryFreeFlag) 449 delete[] (BoundaryPoints);561 delete[] (BoundaryPoints); 450 562 451 563 return GreatestDiameter; 564 } 565 ; 566 567 /** Creates the objects in a raster3d file (renderable with a header.r3d) 568 * \param *out output stream for debugging 569 * \param *tecplot output stream for tecplot data 570 * \param *Tess Tesselation structure with constructed triangles 571 * \param *mol molecule structure with atom positions 572 */ 573 void write_raster3d_file(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, class molecule *mol) 574 { 575 atom *Walker = mol->start; 576 bond *Binder = mol->first; 577 int i; 578 Vector *center = mol->DetermineCenterOfAll(out); 579 if (rasterfile != NULL) { 580 //cout << Verbose(1) << "Writing Raster3D file ... "; 581 *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl; 582 *rasterfile << "@header.r3d" << endl; 583 *rasterfile << "# All atoms as spheres" << endl; 584 while (Walker->next != mol->end) { 585 Walker = Walker->next; 586 *rasterfile << "2" << endl << " "; // 2 is sphere type 587 for (i=0;i<NDIM;i++) 588 *rasterfile << Walker->x.x[i]+center->x[i] << " "; 589 *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour 590 } 591 592 *rasterfile << "# All bonds as vertices" << endl; 593 while (Binder->next != mol->last) { 594 Binder = Binder->next; 595 *rasterfile << "3" << endl << " "; // 2 is round-ended cylinder type 596 for (i=0;i<NDIM;i++) 597 *rasterfile << Binder->leftatom->x.x[i]+center->x[i] << " "; 598 *rasterfile << "\t0.03\t"; 599 for (i=0;i<NDIM;i++) 600 *rasterfile << Binder->rightatom->x.x[i]+center->x[i] << " "; 601 *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour 602 } 603 604 *rasterfile << "# All tesselation triangles" << endl; 605 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) { 606 *rasterfile << "1" << endl << " "; // 1 is triangle type 607 for (i=0;i<3;i++) { // print each node 608 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates 609 *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " "; 610 *rasterfile << "\t"; 611 } 612 *rasterfile << "1. 0. 0." << endl; // red as colour 613 *rasterfile << "18" << endl << " 0.5 0.5 0.5" << endl; // 18 is transparency type for previous object 614 } 615 } else { 616 cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl; 617 } 618 delete(center); 452 619 }; 453 620 621 /** This function creates the tecplot file, displaying the tesselation of the hull. 622 * \param *out output stream for debugging 623 * \param *tecplot output stream for tecplot data 624 * \param N arbitrary number to differentiate various zones in the tecplot format 625 */ 626 void 627 write_tecplot_file(ofstream *out, ofstream *tecplot, 628 class Tesselation *TesselStruct, class molecule *mol, int N) 629 { 630 if (tecplot != NULL) 631 { 632 *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl; 633 *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl; 634 *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N=" 635 << TesselStruct->PointsOnBoundaryCount << ", E=" 636 << TesselStruct->TrianglesOnBoundaryCount 637 << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl; 638 int *LookupList = new int[mol->AtomCount]; 639 for (int i = 0; i < mol->AtomCount; i++) 640 LookupList[i] = -1; 641 642 // print atom coordinates 643 *out << Verbose(2) << "The following triangles were created:"; 644 int Counter = 1; 645 atom *Walker = NULL; 646 for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target 647 != TesselStruct->PointsOnBoundary.end(); target++) 648 { 649 Walker = target->second->node; 650 LookupList[Walker->nr] = Counter++; 651 *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " " 652 << Walker->x.x[2] << " " << endl; 653 } 654 *tecplot << endl; 655 // print connectivity 656 for (TriangleMap::iterator runner = 657 TesselStruct->TrianglesOnBoundary.begin(); runner 658 != TesselStruct->TrianglesOnBoundary.end(); runner++) 659 { 660 *out << " " << runner->second->endpoints[0]->node->Name << "<->" 661 << runner->second->endpoints[1]->node->Name << "<->" 662 << runner->second->endpoints[2]->node->Name; 663 *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " 664 << LookupList[runner->second->endpoints[1]->node->nr] << " " 665 << LookupList[runner->second->endpoints[2]->node->nr] << endl; 666 } 667 delete[] (LookupList); 668 *out << endl; 669 } 670 } 454 671 455 672 /** Determines the volume of a cluster. … … 460 677 * \param *BoundaryPoints NDIM set of boundary points on the projected plane per axis, on return if desired 461 678 * \param *mol molecule structure representing the cluster 462 * \return determined volume of the cluster in cubed config:GetIsAngstroem() 679 * \return determined volume of the cluster in cubed config:GetIsAngstroem() 463 680 */ 464 double VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, Boundaries *BoundaryPtr, molecule *mol) 681 double 682 VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, 683 Boundaries *BoundaryPtr, molecule *mol) 465 684 { 466 685 bool IsAngstroem = configuration->GetIsAngstroem(); … … 471 690 double volume = 0.; 472 691 double PyramidVolume = 0.; 473 double G,h; 474 Vector x,y; 475 double a,b,c; 692 double G, h; 693 Vector x, y; 694 double a, b, c; 695 696 //Find_non_convex_border(out, tecplot, *TesselStruct, mol); // Is now called from command line. 476 697 477 698 // 1. calculate center of gravity 478 699 *out << endl; 479 700 Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out); 480 701 481 702 // 2. translate all points into CoG 482 703 *out << Verbose(1) << "Translating system to Center of Gravity." << endl; 483 704 Walker = mol->start; 484 while (Walker->next != mol->end) { 485 Walker = Walker->next; 486 Walker->x.Translate(CenterOfGravity); 487 } 488 705 while (Walker->next != mol->end) 706 { 707 Walker = Walker->next; 708 Walker->x.Translate(CenterOfGravity); 709 } 710 489 711 // 3. Find all points on the boundary 490 if (BoundaryPoints == NULL) { 491 BoundaryFreeFlag = true; 492 BoundaryPoints = GetBoundaryPoints(out, mol); 493 } else { 494 *out << Verbose(1) << "Using given boundary points set." << endl; 495 } 496 712 if (BoundaryPoints == NULL) 713 { 714 BoundaryFreeFlag = true; 715 BoundaryPoints = GetBoundaryPoints(out, mol); 716 } 717 else 718 { 719 *out << Verbose(1) << "Using given boundary points set." << endl; 720 } 721 497 722 // 4. fill the boundary point list 498 for (int axis=0;axis<NDIM;axis++) 499 for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 500 TesselStruct->AddPoint(runner->second.second); 501 } 502 503 *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount << " points on the convex boundary." << endl; 723 for (int axis = 0; axis < NDIM; axis++) 724 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 725 != BoundaryPoints[axis].end(); runner++) 726 { 727 TesselStruct->AddPoint(runner->second.second); 728 } 729 730 *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount 731 << " points on the convex boundary." << endl; 504 732 // now we have the whole set of edge points in the BoundaryList 505 733 506 734 // listing for debugging 507 // *out << Verbose(1) << "Listing PointsOnBoundary:";508 // for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {509 // *out << " " << *runner->second;510 // }511 // *out << endl;512 735 // *out << Verbose(1) << "Listing PointsOnBoundary:"; 736 // for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) { 737 // *out << " " << *runner->second; 738 // } 739 // *out << endl; 740 513 741 // 5a. guess starting triangle 514 742 TesselStruct->GuessStartingTriangle(out); 515 743 516 744 // 5b. go through all lines, that are not yet part of two triangles (only of one so far) 517 745 TesselStruct->TesselateOnBoundary(out, configuration, mol); 518 746 519 *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount << " triangles with " << TesselStruct->LinesOnBoundaryCount << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." << endl; 747 *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount 748 << " triangles with " << TesselStruct->LinesOnBoundaryCount 749 << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." 750 << endl; 520 751 521 752 // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes 522 *out << Verbose(1) << "Calculating the volume of the pyramids formed out of triangles and center of gravity." << endl; 523 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) { // go through every triangle, calculate volume of its pyramid with CoG as peak 524 x.CopyVector(&runner->second->endpoints[0]->node->x); 525 x.SubtractVector(&runner->second->endpoints[1]->node->x); 526 y.CopyVector(&runner->second->endpoints[0]->node->x); 527 y.SubtractVector(&runner->second->endpoints[2]->node->x); 528 a = sqrt(runner->second->endpoints[0]->node->x.Distance(&runner->second->endpoints[1]->node->x)); 529 b = sqrt(runner->second->endpoints[0]->node->x.Distance(&runner->second->endpoints[2]->node->x)); 530 c = sqrt(runner->second->endpoints[2]->node->x.Distance(&runner->second->endpoints[1]->node->x)); 531 G = sqrt( ( (a*a+b*b+c*c)*(a*a+b*b+c*c) - 2*(a*a*a*a + b*b*b*b + c*c*c*c) )/16.); // area of tesselated triangle 532 x.MakeNormalVector(&runner->second->endpoints[0]->node->x, &runner->second->endpoints[1]->node->x, &runner->second->endpoints[2]->node->x); 533 x.Scale(runner->second->endpoints[1]->node->x.Projection(&x)); 534 h = x.Norm(); // distance of CoG to triangle 535 PyramidVolume = (1./3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak) 536 *out << Verbose(2) << "Area of triangle is " << G << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is " << h << " and the volume is " << PyramidVolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 537 volume += PyramidVolume; 538 } 539 *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10) << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 540 753 *out << Verbose(1) 754 << "Calculating the volume of the pyramids formed out of triangles and center of gravity." 755 << endl; 756 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner 757 != TesselStruct->TrianglesOnBoundary.end(); runner++) 758 { // go through every triangle, calculate volume of its pyramid with CoG as peak 759 x.CopyVector(&runner->second->endpoints[0]->node->x); 760 x.SubtractVector(&runner->second->endpoints[1]->node->x); 761 y.CopyVector(&runner->second->endpoints[0]->node->x); 762 y.SubtractVector(&runner->second->endpoints[2]->node->x); 763 a = sqrt(runner->second->endpoints[0]->node->x.Distance( 764 &runner->second->endpoints[1]->node->x)); 765 b = sqrt(runner->second->endpoints[0]->node->x.Distance( 766 &runner->second->endpoints[2]->node->x)); 767 c = sqrt(runner->second->endpoints[2]->node->x.Distance( 768 &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 771 x.MakeNormalVector(&runner->second->endpoints[0]->node->x, 772 &runner->second->endpoints[1]->node->x, 773 &runner->second->endpoints[2]->node->x); 774 x.Scale(runner->second->endpoints[1]->node->x.Projection(&x)); 775 h = x.Norm(); // distance of CoG to triangle 776 PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak) 777 *out << Verbose(2) << "Area of triangle is " << G << " " 778 << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is " 779 << h << " and the volume is " << PyramidVolume << " " 780 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 781 volume += PyramidVolume; 782 } 783 *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10) 784 << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." 785 << endl; 541 786 542 787 // 7. translate all points back from CoG 543 *out << Verbose(1) << "Translating system back from Center of Gravity." << endl; 788 *out << Verbose(1) << "Translating system back from Center of Gravity." 789 << endl; 544 790 CenterOfGravity->Scale(-1); 545 791 Walker = mol->start; 546 while (Walker->next != mol->end) { 547 Walker = Walker->next; 548 Walker->x.Translate(CenterOfGravity); 549 } 550 792 while (Walker->next != mol->end) 793 { 794 Walker = Walker->next; 795 Walker->x.Translate(CenterOfGravity); 796 } 797 551 798 // 8. Store triangles in tecplot file 552 if (tecplot != NULL) { 553 *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl; 554 *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl; 555 *tecplot << "ZONE T=\"TRIANGLES\", N=" << TesselStruct->PointsOnBoundaryCount << ", E=" << TesselStruct->TrianglesOnBoundaryCount << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl; 556 int *LookupList = new int[mol->AtomCount]; 557 for (int i=0;i<mol->AtomCount;i++) 558 LookupList[i] = -1; 559 560 // print atom coordinates 561 *out << Verbose(2) << "The following triangles were created:"; 562 int Counter = 1; 563 atom *Walker = NULL; 564 for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target != TesselStruct->PointsOnBoundary.end(); target++) { 565 Walker = target->second->node; 566 LookupList[Walker->nr] = Counter++; 567 *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " " << Walker->x.x[2] << " " << endl; 568 } 569 *tecplot << endl; 570 // print connectivity 571 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) { 572 *out << " " << runner->second->endpoints[0]->node->Name << "<->" << runner->second->endpoints[1]->node->Name << "<->" << runner->second->endpoints[2]->node->Name; 573 *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl; 574 } 575 delete[](LookupList); 576 *out << endl; 577 } 799 write_tecplot_file(out, tecplot, TesselStruct, mol, 0); 578 800 579 801 // free reference lists 580 802 if (BoundaryFreeFlag) 581 delete[] (BoundaryPoints);582 803 delete[] (BoundaryPoints); 804 583 805 return volume; 584 } ;585 806 } 807 ; 586 808 587 809 /** Creates multiples of the by \a *mol given cluster and suspends them in water with a given final density. … … 593 815 * \param celldensity desired average density in final cell 594 816 */ 595 void PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, double ClusterVolume, double celldensity) 817 void 818 PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, 819 double ClusterVolume, double celldensity) 596 820 { 597 821 // transform to PAS 598 822 mol->PrincipalAxisSystem(out, true); 599 823 600 824 // some preparations beforehand 601 825 bool IsAngstroem = configuration->GetIsAngstroem(); … … 603 827 double clustervolume; 604 828 if (ClusterVolume == 0) 605 clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration, BoundaryPoints, mol); 606 else 829 clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration, 830 BoundaryPoints, mol); 831 else 607 832 clustervolume = ClusterVolume; 608 double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, IsAngstroem); 833 double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, 834 IsAngstroem); 609 835 Vector BoxLengths; 610 int repetition[NDIM] = {1, 1, 1}; 836 int repetition[NDIM] = 837 { 1, 1, 1 }; 611 838 int TotalNoClusters = 1; 612 for (int i =0;i<NDIM;i++)839 for (int i = 0; i < NDIM; i++) 613 840 TotalNoClusters *= repetition[i]; 614 841 … … 616 843 double totalmass = 0.; 617 844 atom *Walker = mol->start; 618 while (Walker->next != mol->end) { 619 Walker = Walker->next; 620 totalmass += Walker->type->mass; 621 } 622 *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10) << totalmass << " atomicmassunit." << endl; 623 624 *out << Verbose(0) << "RESULT: The average density is " << setprecision(10) << totalmass/clustervolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 625 845 while (Walker->next != mol->end) 846 { 847 Walker = Walker->next; 848 totalmass += Walker->type->mass; 849 } 850 *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10) 851 << totalmass << " atomicmassunit." << endl; 852 853 *out << Verbose(0) << "RESULT: The average density is " << setprecision(10) 854 << totalmass / clustervolume << " atomicmassunit/" 855 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 856 626 857 // solve cubic polynomial 627 *out << Verbose(1) << "Solving equidistant suspension in water problem ..." << endl; 858 *out << Verbose(1) << "Solving equidistant suspension in water problem ..." 859 << endl; 628 860 double cellvolume; 629 861 if (IsAngstroem) 630 cellvolume = (TotalNoClusters*totalmass/SOLVENTDENSITY_A - (totalmass/clustervolume))/(celldensity-1); 862 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass 863 / clustervolume)) / (celldensity - 1); 631 864 else 632 cellvolume = (TotalNoClusters*totalmass/SOLVENTDENSITY_a0 - (totalmass/clustervolume))/(celldensity-1); 633 *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 634 635 double minimumvolume = TotalNoClusters*(GreatestDiameter[0]*GreatestDiameter[1]*GreatestDiameter[2]); 636 *out << Verbose(1) << "Minimum volume of the convex envelope contained in a rectangular box is " << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 637 if (minimumvolume > cellvolume) { 638 cerr << Verbose(0) << "ERROR: the containing box already has a greater volume than the envisaged cell volume!" << endl; 639 cout << Verbose(0) << "Setting Box dimensions to minimum possible, the greatest diameters." << endl; 640 for(int i=0;i<NDIM;i++) 641 BoxLengths.x[i] = GreatestDiameter[i]; 642 mol->CenterEdge(out, &BoxLengths); 643 } else { 644 BoxLengths.x[0] = (repetition[0]*GreatestDiameter[0] + repetition[1]*GreatestDiameter[1] + repetition[2]*GreatestDiameter[2]); 645 BoxLengths.x[1] = (repetition[0]*repetition[1]*GreatestDiameter[0]*GreatestDiameter[1] 646 + repetition[0]*repetition[2]*GreatestDiameter[0]*GreatestDiameter[2] 647 + repetition[1]*repetition[2]*GreatestDiameter[1]*GreatestDiameter[2]); 648 BoxLengths.x[2] = minimumvolume - cellvolume; 649 double x0 = 0.,x1 = 0.,x2 = 0.; 650 if (gsl_poly_solve_cubic(BoxLengths.x[0],BoxLengths.x[1],BoxLengths.x[2],&x0,&x1,&x2) == 1) // either 1 or 3 on return 651 *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0 << " ." << endl; 652 else { 653 *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0 << " and " << x1 << " and " << x2 << " ." << endl; 654 x0 = x2; // sorted in ascending order 655 } 656 657 cellvolume = 1; 658 for(int i=0;i<NDIM;i++) { 659 BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]); 660 cellvolume *= BoxLengths.x[i]; 661 } 662 663 // set new box dimensions 664 *out << Verbose(0) << "Translating to box with these boundaries." << endl; 665 mol->CenterInBox((ofstream *)&cout, &BoxLengths); 666 } 865 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass 866 / clustervolume)) / (celldensity - 1); 867 *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity 868 << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom" 869 : "atomiclength") << "^3." << endl; 870 871 double minimumvolume = TotalNoClusters * (GreatestDiameter[0] 872 * GreatestDiameter[1] * GreatestDiameter[2]); 873 *out << Verbose(1) 874 << "Minimum volume of the convex envelope contained in a rectangular box is " 875 << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" 876 : "atomiclength") << "^3." << endl; 877 if (minimumvolume > cellvolume) 878 { 879 cerr << Verbose(0) 880 << "ERROR: the containing box already has a greater volume than the envisaged cell volume!" 881 << endl; 882 cout << Verbose(0) 883 << "Setting Box dimensions to minimum possible, the greatest diameters." 884 << endl; 885 for (int i = 0; i < NDIM; i++) 886 BoxLengths.x[i] = GreatestDiameter[i]; 887 mol->CenterEdge(out, &BoxLengths); 888 } 889 else 890 { 891 BoxLengths.x[0] = (repetition[0] * GreatestDiameter[0] + repetition[1] 892 * GreatestDiameter[1] + repetition[2] * GreatestDiameter[2]); 893 BoxLengths.x[1] = (repetition[0] * repetition[1] * GreatestDiameter[0] 894 * GreatestDiameter[1] + repetition[0] * repetition[2] 895 * GreatestDiameter[0] * GreatestDiameter[2] + repetition[1] 896 * repetition[2] * GreatestDiameter[1] * GreatestDiameter[2]); 897 BoxLengths.x[2] = minimumvolume - cellvolume; 898 double x0 = 0., x1 = 0., x2 = 0.; 899 if (gsl_poly_solve_cubic(BoxLengths.x[0], BoxLengths.x[1], 900 BoxLengths.x[2], &x0, &x1, &x2) == 1) // either 1 or 3 on return 901 *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0 902 << " ." << endl; 903 else 904 { 905 *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0 906 << " and " << x1 << " and " << x2 << " ." << endl; 907 x0 = x2; // sorted in ascending order 908 } 909 910 cellvolume = 1; 911 for (int i = 0; i < NDIM; i++) 912 { 913 BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]); 914 cellvolume *= BoxLengths.x[i]; 915 } 916 917 // set new box dimensions 918 *out << Verbose(0) << "Translating to box with these boundaries." << endl; 919 mol->CenterInBox((ofstream *) &cout, &BoxLengths); 920 } 667 921 // update Box of atoms by boundary 668 922 mol->SetBoxDimension(&BoxLengths); 669 *out << Verbose(0) << "RESULT: The resulting cell dimensions are: " << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and " << BoxLengths.x[2] << " with total volume of " << cellvolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 670 }; 671 923 *out << Verbose(0) << "RESULT: The resulting cell dimensions are: " 924 << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and " 925 << BoxLengths.x[2] << " with total volume of " << cellvolume << " " 926 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 927 } 928 ; 672 929 673 930 // =========================================================== class TESSELATION =========================================== … … 677 934 Tesselation::Tesselation() 678 935 { 679 PointsOnBoundaryCount = 0; 680 LinesOnBoundaryCount = 0; 936 PointsOnBoundaryCount = 0; 937 LinesOnBoundaryCount = 0; 681 938 TrianglesOnBoundaryCount = 0; 682 }; 939 TriangleFilesWritten = 0; 940 } 941 ; 683 942 684 943 /** Constructor of class Tesselation. … … 687 946 Tesselation::~Tesselation() 688 947 { 689 for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) { 690 delete(runner->second); 691 } 692 }; 948 cout << Verbose(1) << "Free'ing TesselStruct ... " << endl; 949 for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) { 950 if (runner->second != NULL) { 951 delete (runner->second); 952 runner->second = NULL; 953 } else 954 cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl; 955 } 956 for (LineMap::iterator runner = LinesOnBoundary.begin(); runner != LinesOnBoundary.end(); runner++) { 957 if (runner->second != NULL) { 958 delete (runner->second); 959 runner->second = NULL; 960 } else 961 cerr << "ERROR: The line " << runner->first << " has already been free'd." << endl; 962 } 963 for (PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) { 964 if (runner->second != NULL) { 965 delete (runner->second); 966 runner->second = NULL; 967 } else 968 cerr << "ERROR: The point " << runner->first << " has already been free'd." << endl; 969 } 970 } 971 ; 693 972 694 973 /** Gueses first starting triangle of the convex envelope. … … 696 975 * \param *out output stream for debugging 697 976 * \param PointsOnBoundary set of boundary points defining the convex envelope of the cluster 698 */ 699 void Tesselation::GuessStartingTriangle(ofstream *out) 977 */ 978 void 979 Tesselation::GuessStartingTriangle(ofstream *out) 700 980 { 701 981 // 4b. create a starting triangle … … 707 987 A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily 708 988 709 // with A chosen, take each pair B,C and sort 710 if (A != PointsOnBoundary.end()) { 711 B = A; 712 B++; 713 for (; B != PointsOnBoundary.end(); B++) { 714 C = B; 715 C++; 716 for (; C != PointsOnBoundary.end(); C++) { 717 tmp = A->second->node->x.Distance(&B->second->node->x); 718 distance = tmp*tmp; 719 tmp = A->second->node->x.Distance(&C->second->node->x); 720 distance += tmp*tmp; 721 tmp = B->second->node->x.Distance(&C->second->node->x); 722 distance += tmp*tmp; 723 DistanceMMap.insert( DistanceMultiMapPair(distance, pair<PointMap::iterator, PointMap::iterator>(B,C) ) ); 724 } 725 } 726 } 727 // // listing distances 728 // *out << Verbose(1) << "Listing DistanceMMap:"; 729 // for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) { 730 // *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")"; 731 // } 732 // *out << endl; 733 989 // with A chosen, take each pair B,C and sort 990 if (A != PointsOnBoundary.end()) 991 { 992 B = A; 993 B++; 994 for (; B != PointsOnBoundary.end(); B++) 995 { 996 C = B; 997 C++; 998 for (; C != PointsOnBoundary.end(); C++) 999 { 1000 tmp = A->second->node->x.Distance(&B->second->node->x); 1001 distance = tmp * tmp; 1002 tmp = A->second->node->x.Distance(&C->second->node->x); 1003 distance += tmp * tmp; 1004 tmp = B->second->node->x.Distance(&C->second->node->x); 1005 distance += tmp * tmp; 1006 DistanceMMap.insert(DistanceMultiMapPair(distance, pair< 1007 PointMap::iterator, PointMap::iterator> (B, C))); 1008 } 1009 } 1010 } 1011 // // listing distances 1012 // *out << Verbose(1) << "Listing DistanceMMap:"; 1013 // for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) { 1014 // *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")"; 1015 // } 1016 // *out << endl; 734 1017 // 4b2. pick three baselines forming a triangle 735 1018 // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate 736 1019 DistanceMultiMap::iterator baseline = DistanceMMap.begin(); 737 for (; baseline != DistanceMMap.end(); baseline++) { 738 // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate 739 // 2. next, we have to check whether all points reside on only one side of the triangle 740 // 3. construct plane vector 741 PlaneVector.MakeNormalVector(&A->second->node->x, &baseline->second.first->second->node->x, &baseline->second.second->second->node->x); 742 *out << Verbose(2) << "Plane vector of candidate triangle is "; 743 PlaneVector.Output(out); 744 *out << endl; 745 // 4. loop over all points 746 double sign = 0.; 747 PointMap::iterator checker = PointsOnBoundary.begin(); 748 for (; checker != PointsOnBoundary.end(); checker++) { 749 // (neglecting A,B,C) 750 if ((checker == A) || (checker == baseline->second.first) || (checker == baseline->second.second)) 751 continue; 752 // 4a. project onto plane vector 753 TrialVector.CopyVector(&checker->second->node->x); 754 TrialVector.SubtractVector(&A->second->node->x); 755 distance = TrialVector.Projection(&PlaneVector); 756 if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok 757 continue; 758 *out << Verbose(3) << "Projection of " << checker->second->node->Name << " yields distance of " << distance << "." << endl; 759 tmp = distance/fabs(distance); 760 // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle) 761 if ((sign != 0) && (tmp != sign)) { 762 // 4c. If so, break 4. loop and continue with next candidate in 1. loop 763 *out << Verbose(2) << "Current candidates: " << A->second->node->Name << "," << baseline->second.first->second->node->Name << "," << baseline->second.second->second->node->Name << " leave " << checker->second->node->Name << " outside the convex hull." << endl; 764 break; 765 } else { // note the sign for later 766 *out << Verbose(2) << "Current candidates: " << A->second->node->Name << "," << baseline->second.first->second->node->Name << "," << baseline->second.second->second->node->Name << " leave " << checker->second->node->Name << " inside the convex hull." << endl; 767 sign = tmp; 768 } 769 // 4d. Check whether the point is inside the triangle (check distance to each node 770 tmp = checker->second->node->x.Distance(&A->second->node->x); 771 int innerpoint = 0; 772 if ((tmp < A->second->node->x.Distance(&baseline->second.first->second->node->x)) 773 && (tmp < A->second->node->x.Distance(&baseline->second.second->second->node->x))) 774 innerpoint++; 775 tmp = checker->second->node->x.Distance(&baseline->second.first->second->node->x); 776 if ((tmp < baseline->second.first->second->node->x.Distance(&A->second->node->x)) 777 && (tmp < baseline->second.first->second->node->x.Distance(&baseline->second.second->second->node->x))) 778 innerpoint++; 779 tmp = checker->second->node->x.Distance(&baseline->second.second->second->node->x); 780 if ((tmp < baseline->second.second->second->node->x.Distance(&baseline->second.first->second->node->x)) 781 && (tmp < baseline->second.second->second->node->x.Distance(&A->second->node->x))) 782 innerpoint++; 783 // 4e. If so, break 4. loop and continue with next candidate in 1. loop 784 if (innerpoint == 3) 785 break; 786 } 787 // 5. come this far, all on same side? Then break 1. loop and construct triangle 788 if (checker == PointsOnBoundary.end()) { 789 *out << "Looks like we have a candidate!" << endl; 790 break; 791 } 792 } 793 if (baseline != DistanceMMap.end()) { 794 BPS[0] = baseline->second.first->second; 795 BPS[1] = baseline->second.second->second; 796 BLS[0] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 797 BPS[0] = A->second; 798 BPS[1] = baseline->second.second->second; 799 BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 800 BPS[0] = baseline->second.first->second; 801 BPS[1] = A->second; 802 BLS[2] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 803 804 // 4b3. insert created triangle 805 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 806 TrianglesOnBoundary.insert( TrianglePair(TrianglesOnBoundaryCount, BTS) ); 807 TrianglesOnBoundaryCount++; 808 for(int i=0;i<NDIM;i++) { 809 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]) ); 810 LinesOnBoundaryCount++; 811 } 812 813 *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl; 814 } else { 815 *out << Verbose(1) << "No starting triangle found." << endl; 816 exit(255); 817 } 818 }; 819 1020 for (; baseline != DistanceMMap.end(); baseline++) 1021 { 1022 // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate 1023 // 2. next, we have to check whether all points reside on only one side of the triangle 1024 // 3. construct plane vector 1025 PlaneVector.MakeNormalVector(&A->second->node->x, 1026 &baseline->second.first->second->node->x, 1027 &baseline->second.second->second->node->x); 1028 *out << Verbose(2) << "Plane vector of candidate triangle is "; 1029 PlaneVector.Output(out); 1030 *out << endl; 1031 // 4. loop over all points 1032 double sign = 0.; 1033 PointMap::iterator checker = PointsOnBoundary.begin(); 1034 for (; checker != PointsOnBoundary.end(); checker++) 1035 { 1036 // (neglecting A,B,C) 1037 if ((checker == A) || (checker == baseline->second.first) || (checker 1038 == baseline->second.second)) 1039 continue; 1040 // 4a. project onto plane vector 1041 TrialVector.CopyVector(&checker->second->node->x); 1042 TrialVector.SubtractVector(&A->second->node->x); 1043 distance = TrialVector.Projection(&PlaneVector); 1044 if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok 1045 continue; 1046 *out << Verbose(3) << "Projection of " << checker->second->node->Name 1047 << " yields distance of " << distance << "." << endl; 1048 tmp = distance / fabs(distance); 1049 // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle) 1050 if ((sign != 0) && (tmp != sign)) 1051 { 1052 // 4c. If so, break 4. loop and continue with next candidate in 1. loop 1053 *out << Verbose(2) << "Current candidates: " 1054 << A->second->node->Name << "," 1055 << baseline->second.first->second->node->Name << "," 1056 << baseline->second.second->second->node->Name << " leave " 1057 << checker->second->node->Name << " outside the convex hull." 1058 << endl; 1059 break; 1060 } 1061 else 1062 { // note the sign for later 1063 *out << Verbose(2) << "Current candidates: " 1064 << A->second->node->Name << "," 1065 << baseline->second.first->second->node->Name << "," 1066 << baseline->second.second->second->node->Name << " leave " 1067 << checker->second->node->Name << " inside the convex hull." 1068 << endl; 1069 sign = tmp; 1070 } 1071 // 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); 1073 int innerpoint = 0; 1074 if ((tmp < A->second->node->x.Distance( 1075 &baseline->second.first->second->node->x)) && (tmp 1076 < A->second->node->x.Distance( 1077 &baseline->second.second->second->node->x))) 1078 innerpoint++; 1079 tmp = checker->second->node->x.Distance( 1080 &baseline->second.first->second->node->x); 1081 if ((tmp < baseline->second.first->second->node->x.Distance( 1082 &A->second->node->x)) && (tmp 1083 < baseline->second.first->second->node->x.Distance( 1084 &baseline->second.second->second->node->x))) 1085 innerpoint++; 1086 tmp = checker->second->node->x.Distance( 1087 &baseline->second.second->second->node->x); 1088 if ((tmp < baseline->second.second->second->node->x.Distance( 1089 &baseline->second.first->second->node->x)) && (tmp 1090 < baseline->second.second->second->node->x.Distance( 1091 &A->second->node->x))) 1092 innerpoint++; 1093 // 4e. If so, break 4. loop and continue with next candidate in 1. loop 1094 if (innerpoint == 3) 1095 break; 1096 } 1097 // 5. come this far, all on same side? Then break 1. loop and construct triangle 1098 if (checker == PointsOnBoundary.end()) 1099 { 1100 *out << "Looks like we have a candidate!" << endl; 1101 break; 1102 } 1103 } 1104 if (baseline != DistanceMMap.end()) 1105 { 1106 BPS[0] = baseline->second.first->second; 1107 BPS[1] = baseline->second.second->second; 1108 BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1109 BPS[0] = A->second; 1110 BPS[1] = baseline->second.second->second; 1111 BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1112 BPS[0] = baseline->second.first->second; 1113 BPS[1] = A->second; 1114 BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1115 1116 // 4b3. insert created triangle 1117 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 1118 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1119 TrianglesOnBoundaryCount++; 1120 for (int i = 0; i < NDIM; i++) 1121 { 1122 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i])); 1123 LinesOnBoundaryCount++; 1124 } 1125 1126 *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl; 1127 } 1128 else 1129 { 1130 *out << Verbose(1) << "No starting triangle found." << endl; 1131 exit(255); 1132 } 1133 } 1134 ; 820 1135 821 1136 /** Tesselates the convex envelope of a cluster from a single starting triangle. … … 832 1147 * \param *mol the cluster as a molecule structure 833 1148 */ 834 void Tesselation::TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol) 1149 void 1150 Tesselation::TesselateOnBoundary(ofstream *out, config *configuration, 1151 molecule *mol) 835 1152 { 836 1153 bool flag; … … 838 1155 class BoundaryPointSet *peak = NULL; 839 1156 double SmallestAngle, TempAngle; 840 Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, PropagationVector; 1157 Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, 1158 PropagationVector; 841 1159 LineMap::iterator LineChecker[2]; 842 do { 843 flag = false; 844 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++) 845 if (baseline->second->TrianglesCount == 1) { 846 *out << Verbose(2) << "Current baseline is between " << *(baseline->second) << "." << endl; 847 // 5a. go through each boundary point if not _both_ edges between either endpoint of the current line and this point exist (and belong to 2 triangles) 848 SmallestAngle = M_PI; 849 BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far 850 // get peak point with respect to this base line's only triangle 851 for(int i=0;i<3;i++) 852 if ((BTS->endpoints[i] != baseline->second->endpoints[0]) && (BTS->endpoints[i] != baseline->second->endpoints[1])) 853 peak = BTS->endpoints[i]; 854 *out << Verbose(3) << " and has peak " << *peak << "." << endl; 855 // normal vector of triangle 856 BTS->GetNormalVector(NormalVector); 857 *out << Verbose(4) << "NormalVector of base triangle is "; 858 NormalVector.Output(out); 859 *out << endl; 860 // offset to center of triangle 861 CenterVector.Zero(); 862 for(int i=0;i<3;i++) 863 CenterVector.AddVector(&BTS->endpoints[i]->node->x); 864 CenterVector.Scale(1./3.); 865 *out << Verbose(4) << "CenterVector of base triangle is "; 866 CenterVector.Output(out); 867 *out << endl; 868 // vector in propagation direction (out of triangle) 869 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection) 870 TempVector.CopyVector(&baseline->second->endpoints[0]->node->x); 871 TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x); 872 PropagationVector.MakeNormalVector(&TempVector, &NormalVector); 873 TempVector.CopyVector(&CenterVector); 874 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center! 875 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl; 876 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline 877 PropagationVector.Scale(-1.); 878 *out << Verbose(4) << "PropagationVector of base triangle is "; 879 PropagationVector.Output(out); 880 *out << endl; 881 winner = PointsOnBoundary.end(); 882 for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++) 883 if ((target->second != baseline->second->endpoints[0]) && (target->second != baseline->second->endpoints[1])) { // don't take the same endpoints 884 *out << Verbose(3) << "Target point is " << *(target->second) << ":"; 885 bool continueflag = true; 886 887 VirtualNormalVector.CopyVector(&baseline->second->endpoints[0]->node->x); 888 VirtualNormalVector.AddVector(&baseline->second->endpoints[0]->node->x); 889 VirtualNormalVector.Scale(-1./2.); // points now to center of base line 890 VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target 891 TempAngle = VirtualNormalVector.Angle(&PropagationVector); 892 continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees) 893 if (!continueflag) { 894 *out << Verbose(4) << "Angle between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", bad direction!" << endl; 895 continue; 896 } else 897 *out << Verbose(4) << "Angle between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", good direction!" << endl; 898 LineChecker[0] = baseline->second->endpoints[0]->lines.find(target->first); 899 LineChecker[1] = baseline->second->endpoints[1]->lines.find(target->first); 900 // if (LineChecker[0] != baseline->second->endpoints[0]->lines.end()) 901 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl; 902 // else 903 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl; 904 // if (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 905 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl; 906 // else 907 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl; 908 // check first endpoint (if any connecting line goes to target or at least not more than 1) 909 continueflag = continueflag && (( (LineChecker[0] == baseline->second->endpoints[0]->lines.end()) || (LineChecker[0]->second->TrianglesCount == 1))); 910 if (!continueflag) { 911 *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl; 912 continue; 913 } 914 // check second endpoint (if any connecting line goes to target or at least not more than 1) 915 continueflag = continueflag && (( (LineChecker[1] == baseline->second->endpoints[1]->lines.end()) || (LineChecker[1]->second->TrianglesCount == 1))); 916 if (!continueflag) { 917 *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl; 918 continue; 919 } 920 // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint) 921 continueflag = continueflag && (!( 922 ((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 923 && (GetCommonEndpoint(LineChecker[0]->second, LineChecker[1]->second) == peak)) 924 )); 925 if (!continueflag) { 926 *out << Verbose(4) << "Current target is peak!" << endl; 927 continue; 928 } 929 // in case NOT both were found 930 if (continueflag) { // create virtually this triangle, get its normal vector, calculate angle 931 flag = true; 932 VirtualNormalVector.MakeNormalVector(&baseline->second->endpoints[0]->node->x, &baseline->second->endpoints[1]->node->x, &target->second->node->x); 933 // make it always point inward 934 if (baseline->second->endpoints[0]->node->x.Projection(&VirtualNormalVector) > 0) 935 VirtualNormalVector.Scale(-1.); 936 // calculate angle 937 TempAngle = NormalVector.Angle(&VirtualNormalVector); 938 *out << Verbose(4) << "NormalVector is "; 939 VirtualNormalVector.Output(out); 940 *out << " and the angle is " << TempAngle << "." << endl; 941 if (SmallestAngle > TempAngle) { // set to new possible winner 942 SmallestAngle = TempAngle; 943 winner = target; 1160 do 1161 { 1162 flag = false; 1163 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline 1164 != LinesOnBoundary.end(); baseline++) 1165 if (baseline->second->TrianglesCount == 1) 1166 { 1167 *out << Verbose(2) << "Current baseline is between " 1168 << *(baseline->second) << "." << endl; 1169 // 5a. go through each boundary point if not _both_ edges between either endpoint of the current line and this point exist (and belong to 2 triangles) 1170 SmallestAngle = M_PI; 1171 BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far 1172 // get peak point with respect to this base line's only triangle 1173 for (int i = 0; i < 3; i++) 1174 if ((BTS->endpoints[i] != baseline->second->endpoints[0]) 1175 && (BTS->endpoints[i] != baseline->second->endpoints[1])) 1176 peak = BTS->endpoints[i]; 1177 *out << Verbose(3) << " and has peak " << *peak << "." << endl; 1178 // normal vector of triangle 1179 BTS->GetNormalVector(NormalVector); 1180 *out << Verbose(4) << "NormalVector of base triangle is "; 1181 NormalVector.Output(out); 1182 *out << endl; 1183 // offset to center of triangle 1184 CenterVector.Zero(); 1185 for (int i = 0; i < 3; i++) 1186 CenterVector.AddVector(&BTS->endpoints[i]->node->x); 1187 CenterVector.Scale(1. / 3.); 1188 *out << Verbose(4) << "CenterVector of base triangle is "; 1189 CenterVector.Output(out); 1190 *out << endl; 1191 // vector in propagation direction (out of triangle) 1192 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection) 1193 TempVector.CopyVector(&baseline->second->endpoints[0]->node->x); 1194 TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x); 1195 PropagationVector.MakeNormalVector(&TempVector, &NormalVector); 1196 TempVector.CopyVector(&CenterVector); 1197 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center! 1198 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl; 1199 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline 1200 PropagationVector.Scale(-1.); 1201 *out << Verbose(4) << "PropagationVector of base triangle is "; 1202 PropagationVector.Output(out); 1203 *out << endl; 1204 winner = PointsOnBoundary.end(); 1205 for (PointMap::iterator target = PointsOnBoundary.begin(); target 1206 != PointsOnBoundary.end(); target++) 1207 if ((target->second != baseline->second->endpoints[0]) 1208 && (target->second != baseline->second->endpoints[1])) 1209 { // don't take the same endpoints 1210 *out << Verbose(3) << "Target point is " << *(target->second) 1211 << ":"; 1212 bool continueflag = true; 1213 1214 VirtualNormalVector.CopyVector( 1215 &baseline->second->endpoints[0]->node->x); 1216 VirtualNormalVector.AddVector( 1217 &baseline->second->endpoints[0]->node->x); 1218 VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line 1219 VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target 1220 TempAngle = VirtualNormalVector.Angle(&PropagationVector); 1221 continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees) 1222 if (!continueflag) 1223 { 1224 *out << Verbose(4) 1225 << "Angle between propagation direction and base line to " 1226 << *(target->second) << " is " << TempAngle 1227 << ", bad direction!" << endl; 1228 continue; 1229 } 1230 else 1231 *out << Verbose(4) 1232 << "Angle between propagation direction and base line to " 1233 << *(target->second) << " is " << TempAngle 1234 << ", good direction!" << endl; 1235 LineChecker[0] = baseline->second->endpoints[0]->lines.find( 1236 target->first); 1237 LineChecker[1] = baseline->second->endpoints[1]->lines.find( 1238 target->first); 1239 // if (LineChecker[0] != baseline->second->endpoints[0]->lines.end()) 1240 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl; 1241 // else 1242 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl; 1243 // if (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 1244 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl; 1245 // else 1246 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl; 1247 // check first endpoint (if any connecting line goes to target or at least not more than 1) 1248 continueflag = continueflag && (((LineChecker[0] 1249 == baseline->second->endpoints[0]->lines.end()) 1250 || (LineChecker[0]->second->TrianglesCount == 1))); 1251 if (!continueflag) 1252 { 1253 *out << Verbose(4) << *(baseline->second->endpoints[0]) 1254 << " has line " << *(LineChecker[0]->second) 1255 << " to " << *(target->second) 1256 << " as endpoint with " 1257 << LineChecker[0]->second->TrianglesCount 1258 << " triangles." << endl; 1259 continue; 1260 } 1261 // check second endpoint (if any connecting line goes to target or at least not more than 1) 1262 continueflag = continueflag && (((LineChecker[1] 1263 == baseline->second->endpoints[1]->lines.end()) 1264 || (LineChecker[1]->second->TrianglesCount == 1))); 1265 if (!continueflag) 1266 { 1267 *out << Verbose(4) << *(baseline->second->endpoints[1]) 1268 << " has line " << *(LineChecker[1]->second) 1269 << " to " << *(target->second) 1270 << " as endpoint with " 1271 << LineChecker[1]->second->TrianglesCount 1272 << " triangles." << endl; 1273 continue; 1274 } 1275 // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint) 1276 continueflag = continueflag && (!(((LineChecker[0] 1277 != baseline->second->endpoints[0]->lines.end()) 1278 && (LineChecker[1] 1279 != baseline->second->endpoints[1]->lines.end()) 1280 && (GetCommonEndpoint(LineChecker[0]->second, 1281 LineChecker[1]->second) == peak)))); 1282 if (!continueflag) 1283 { 1284 *out << Verbose(4) << "Current target is peak!" << endl; 1285 continue; 1286 } 1287 // in case NOT both were found 1288 if (continueflag) 1289 { // create virtually this triangle, get its normal vector, calculate angle 1290 flag = true; 1291 VirtualNormalVector.MakeNormalVector( 1292 &baseline->second->endpoints[0]->node->x, 1293 &baseline->second->endpoints[1]->node->x, 1294 &target->second->node->x); 1295 // make it always point inward 1296 if (baseline->second->endpoints[0]->node->x.Projection( 1297 &VirtualNormalVector) > 0) 1298 VirtualNormalVector.Scale(-1.); 1299 // calculate angle 1300 TempAngle = NormalVector.Angle(&VirtualNormalVector); 1301 *out << Verbose(4) << "NormalVector is "; 1302 VirtualNormalVector.Output(out); 1303 *out << " and the angle is " << TempAngle << "." << endl; 1304 if (SmallestAngle > TempAngle) 1305 { // set to new possible winner 1306 SmallestAngle = TempAngle; 1307 winner = target; 1308 } 1309 } 1310 } 1311 // 5b. The point of the above whose triangle has the greatest angle with the triangle the current line belongs to (it only belongs to one, remember!): New triangle 1312 if (winner != PointsOnBoundary.end()) 1313 { 1314 *out << Verbose(2) << "Winning target point is " 1315 << *(winner->second) << " with angle " << SmallestAngle 1316 << "." << endl; 1317 // create the lins of not yet present 1318 BLS[0] = baseline->second; 1319 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles) 1320 LineChecker[0] = baseline->second->endpoints[0]->lines.find( 1321 winner->first); 1322 LineChecker[1] = baseline->second->endpoints[1]->lines.find( 1323 winner->first); 1324 if (LineChecker[0] 1325 == baseline->second->endpoints[0]->lines.end()) 1326 { // create 1327 BPS[0] = baseline->second->endpoints[0]; 1328 BPS[1] = winner->second; 1329 BLS[1] = new class BoundaryLineSet(BPS, 1330 LinesOnBoundaryCount); 1331 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, 1332 BLS[1])); 1333 LinesOnBoundaryCount++; 1334 } 1335 else 1336 BLS[1] = LineChecker[0]->second; 1337 if (LineChecker[1] 1338 == baseline->second->endpoints[1]->lines.end()) 1339 { // create 1340 BPS[0] = baseline->second->endpoints[1]; 1341 BPS[1] = winner->second; 1342 BLS[2] = new class BoundaryLineSet(BPS, 1343 LinesOnBoundaryCount); 1344 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, 1345 BLS[2])); 1346 LinesOnBoundaryCount++; 1347 } 1348 else 1349 BLS[2] = LineChecker[1]->second; 1350 BTS = new class BoundaryTriangleSet(BLS, 1351 TrianglesOnBoundaryCount); 1352 TrianglesOnBoundary.insert(TrianglePair( 1353 TrianglesOnBoundaryCount, BTS)); 1354 TrianglesOnBoundaryCount++; 944 1355 } 945 } 1356 else 1357 { 1358 *out << Verbose(1) 1359 << "I could not determine a winner for this baseline " 1360 << *(baseline->second) << "." << endl; 1361 } 1362 1363 // 5d. If the set of lines is not yet empty, go to 5. and continue 946 1364 } 947 // 5b. The point of the above whose triangle has the greatest angle with the triangle the current line belongs to (it only belongs to one, remember!): New triangle 948 if (winner != PointsOnBoundary.end()) { 949 *out << Verbose(2) << "Winning target point is " << *(winner->second) << " with angle " << SmallestAngle << "." << endl; 950 // create the lins of not yet present 951 BLS[0] = baseline->second; 952 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles) 953 LineChecker[0] = baseline->second->endpoints[0]->lines.find(winner->first); 954 LineChecker[1] = baseline->second->endpoints[1]->lines.find(winner->first); 955 if (LineChecker[0] == baseline->second->endpoints[0]->lines.end()) { // create 956 BPS[0] = baseline->second->endpoints[0]; 957 BPS[1] = winner->second; 958 BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 959 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BLS[1]) ); 960 LinesOnBoundaryCount++; 961 } else 962 BLS[1] = LineChecker[0]->second; 963 if (LineChecker[1] == baseline->second->endpoints[1]->lines.end()) { // create 964 BPS[0] = baseline->second->endpoints[1]; 965 BPS[1] = winner->second; 966 BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 967 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BLS[2]) ); 968 LinesOnBoundaryCount++; 969 } else 970 BLS[2] = LineChecker[1]->second; 971 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 972 TrianglesOnBoundary.insert( TrianglePair(TrianglesOnBoundaryCount, BTS) ); 973 TrianglesOnBoundaryCount++; 974 } else { 975 *out << Verbose(1) << "I could not determine a winner for this baseline " << *(baseline->second) << "." << endl; 976 } 977 978 // 5d. If the set of lines is not yet empty, go to 5. and continue 979 } else 980 *out << Verbose(2) << "Baseline candidate " << *(baseline->second) << " has a triangle count of " << baseline->second->TrianglesCount << "." << endl; 981 } while (flag); 982 983 }; 1365 else 1366 *out << Verbose(2) << "Baseline candidate " << *(baseline->second) 1367 << " has a triangle count of " 1368 << baseline->second->TrianglesCount << "." << endl; 1369 } 1370 while (flag); 1371 1372 } 1373 ; 984 1374 985 1375 /** Adds an atom to the tesselation::PointsOnBoundary list. 986 1376 * \param *Walker atom to add 987 1377 */ 988 void Tesselation::AddPoint(atom *Walker) 1378 void 1379 Tesselation::AddPoint(atom *Walker) 989 1380 { 990 1381 PointTestPair InsertUnique; 991 1382 BPS[0] = new class BoundaryPointSet(Walker); 992 InsertUnique = PointsOnBoundary.insert( PointPair(Walker->nr, BPS[0]));993 if (InsertUnique.second) 1383 InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0])); 1384 if (InsertUnique.second) // if new point was not present before, increase counter 994 1385 PointsOnBoundaryCount++; 1386 } 1387 ; 1388 1389 /** Adds point to Tesselation::PointsOnBoundary if not yet present. 1390 * Tesselation::TPS is set to either this new BoundaryPointSet or to the existing one of not unique. 1391 * @param Candidate point to add 1392 * @param n index for this point in Tesselation::TPS array 1393 */ 1394 void 1395 Tesselation::AddTrianglePoint(atom* Candidate, int n) 1396 { 1397 PointTestPair InsertUnique; 1398 TPS[n] = new class BoundaryPointSet(Candidate); 1399 InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n])); 1400 if (InsertUnique.second) // if new point was not present before, increase counter 1401 { 1402 PointsOnBoundaryCount++; 1403 } 1404 else 1405 { 1406 delete TPS[n]; 1407 cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node) 1408 << " gibt's schon in der PointMap." << endl; 1409 TPS[n] = (InsertUnique.first)->second; 1410 } 1411 } 1412 ; 1413 1414 /** Function tries to add line from current Points in BPS to BoundaryLineSet. 1415 * If succesful it raises the line count and inserts the new line into the BLS, 1416 * if unsuccesful, it writes the line which had been present into the BLS, deleting the new constructed one. 1417 * @param *a first endpoint 1418 * @param *b second endpoint 1419 * @param n index of Tesselation::BLS giving the line with both endpoints 1420 */ 1421 void 1422 Tesselation::AddTriangleLine(class BoundaryPointSet *a, 1423 class BoundaryPointSet *b, int n) 1424 { 1425 LineMap::iterator LineWalker; 1426 //cout << "Manually checking endpoints for line." << endl; 1427 if ((a->lines.find(b->node->nr)) != a->lines.end()) // ->first == b->node->nr) 1428 //If a line is there, how do I recognize that beyond a shadow of a doubt? 1429 { 1430 //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl; 1431 1432 LineWalker = LinesOnBoundary.end(); 1433 LineWalker--; 1434 1435 while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr, 1436 b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max( 1437 a->node->nr, b->node->nr)) 1438 { 1439 //cout << Verbose(1) << "Looking for line which already exists"<< endl; 1440 LineWalker--; 1441 } 1442 BPS[0] = LineWalker->second->endpoints[0]; 1443 BPS[1] = LineWalker->second->endpoints[1]; 1444 BLS[n] = LineWalker->second; 1445 1446 } 1447 else 1448 { 1449 cout << Verbose(2) 1450 << "Adding line which has not been used before between " 1451 << *(a->node) << " and " << *(b->node) << "." << endl; 1452 BPS[0] = a; 1453 BPS[1] = b; 1454 BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1455 1456 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n])); 1457 LinesOnBoundaryCount++; 1458 1459 } 1460 } 1461 ; 1462 1463 /** Function tries to add Triangle just created to Triangle and remarks if already existent (Failure of algorithm). 1464 * Furthermore it adds the triangle to all of its lines, in order to recognize those which are saturated later. 1465 */ 1466 void 1467 Tesselation::AddTriangleToLines() 1468 { 1469 1470 cout << Verbose(1) << "Adding triangle to its lines" << endl; 1471 int i = 0; 1472 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1473 TrianglesOnBoundaryCount++; 1474 1475 /* 1476 * this is apparently done when constructing triangle 1477 1478 for (i=0; i<3; i++) 1479 { 1480 BLS[i]->AddTriangle(BTS); 1481 } 1482 */ 1483 } 1484 ; 1485 1486 /** 1487 * Function returns center of sphere with RADIUS, which rests on points a, b, c 1488 * @param Center this vector will be used for return 1489 * @param a vector first point of triangle 1490 * @param b vector second point of triangle 1491 * @param c vector third point of triangle 1492 * @param *Umkreismittelpunkt new cneter point of circumference 1493 * @param Direction vector indicates up/down 1494 * @param AlternativeDirection vecotr, needed in case the triangles have 90 deg angle 1495 * @param Halfplaneindicator double indicates whether Direction is up or down 1496 * @param AlternativeIndicator doube indicates in case of orthogonal triangles which direction of AlternativeDirection is suitable 1497 * @param alpha double angle at a 1498 * @param beta double, angle at b 1499 * @param gamma, double, angle at c 1500 * @param Radius, double 1501 * @param Umkreisradius double radius of circumscribing circle 1502 */ 1503 1504 void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection, 1505 double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius) 1506 { 1507 Vector TempNormal, helper; 1508 double Restradius; 1509 cout << Verbose(3) << "Begin of Get_center_of_sphere.\n"; 1510 Center->Zero(); 1511 helper.CopyVector(&a); 1512 helper.Scale(sin(2.*alpha)); 1513 Center->AddVector(&helper); 1514 helper.CopyVector(&b); 1515 helper.Scale(sin(2.*beta)); 1516 Center->AddVector(&helper); 1517 helper.CopyVector(&c); 1518 helper.Scale(sin(2.*gamma)); 1519 Center->AddVector(&helper); 1520 //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ; 1521 Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma))); 1522 NewUmkreismittelpunkt->CopyVector(Center); 1523 cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n"; 1524 // Here we calculated center of circumscribing circle, using barycentric coordinates 1525 cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n"; 1526 1527 TempNormal.CopyVector(&a); 1528 TempNormal.SubtractVector(&b); 1529 helper.CopyVector(&a); 1530 helper.SubtractVector(&c); 1531 TempNormal.VectorProduct(&helper); 1532 if (fabs(HalfplaneIndicator) < MYEPSILON) 1533 { 1534 if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0)) 1535 { 1536 TempNormal.Scale(-1); 1537 } 1538 } 1539 else 1540 { 1541 if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0) 1542 { 1543 TempNormal.Scale(-1); 1544 } 1545 } 1546 1547 TempNormal.Normalize(); 1548 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius); 1549 cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n"; 1550 TempNormal.Scale(Restradius); 1551 cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n"; 1552 1553 Center->AddVector(&TempNormal); 1554 cout << Verbose(4) << "Center of sphere of circumference is " << *Center << ".\n"; 1555 cout << Verbose(3) << "End of Get_center_of_sphere.\n"; 1556 } 1557 ; 1558 1559 1560 /** This recursive function finds a third point, to form a triangle with two given ones. 1561 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \ 1562 * supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \ 1563 * upon which we operate. 1564 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \ 1565 * direction and angle into Storage. 1566 * We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \ 1567 * with all neighbours of the candidate. 1568 * @param a first point 1569 * @param b second point 1570 * *param c atom old third point of old triangle 1571 * @param Candidate base point along whose bonds to start looking from 1572 * @param Parent point to avoid during search as its wrong direction 1573 * @param RecursionLevel contains current recursion depth 1574 * @param Chord baseline vector of first and second point 1575 * @param direction1 second in plane vector (along with \a Chord) of the triangle the baseline belongs to 1576 * @param OldNormal normal of the triangle which the baseline belongs to 1577 * @param ReferencePoint Vector of center of circumscribing circle from which we look towards center of sphere 1578 * @param Opt_Candidate candidate reference to return 1579 * @param Storage array containing two angles of current Opt_Candidate 1580 * @param RADIUS radius of ball 1581 * @param mol molecule structure with atoms and bonds 1582 */ 1583 1584 void Tesselation::Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent, 1585 int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint, 1586 atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol) 1587 { 1588 cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n"; 1589 cout << Verbose(3) << "Candidate is "<< *Candidate << endl; 1590 cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl; 1591 cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl; 1592 cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl; 1593 cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl; 1594 /* OldNormal is normal vector on the old triangle 1595 * direction1 is normal on the triangle line, from which we come, as well as on OldNormal. 1596 * Chord points from b to a!!! 1597 */ 1598 Vector dif_a; //Vector from a to candidate 1599 Vector dif_b; //Vector from b to candidate 1600 Vector AngleCheck; 1601 Vector TempNormal, Umkreismittelpunkt; 1602 Vector Mittelpunkt; 1603 1604 double CurrentEpsilon = 0.1; 1605 double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance; 1606 double BallAngle, AlternativeSign; 1607 atom *Walker; // variable atom point 1608 1609 Vector NewUmkreismittelpunkt; 1610 1611 if (a != Candidate and b != Candidate and c != Candidate) { 1612 cout << Verbose(3) << "We have a unique candidate!" << endl; 1613 dif_a.CopyVector(&(a->x)); 1614 dif_a.SubtractVector(&(Candidate->x)); 1615 dif_b.CopyVector(&(b->x)); 1616 dif_b.SubtractVector(&(Candidate->x)); 1617 AngleCheck.CopyVector(&(Candidate->x)); 1618 AngleCheck.SubtractVector(&(a->x)); 1619 AngleCheck.ProjectOntoPlane(Chord); 1620 1621 SideA = dif_b.Norm(); 1622 SideB = dif_a.Norm(); 1623 SideC = Chord->Norm(); 1624 //Chord->Scale(-1); 1625 1626 alpha = Chord->Angle(&dif_a); 1627 beta = M_PI - Chord->Angle(&dif_b); 1628 gamma = dif_a.Angle(&dif_b); 1629 1630 cout << Verbose(2) << "Base triangle has sides " << dif_a << ", " << dif_b << ", " << *Chord << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl; 1631 1632 if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) { 1633 cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n"; 1634 cout << Verbose(1) << "Base triangle has sides " << dif_a << ", " << dif_b << ", " << *Chord << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl; 1635 } 1636 1637 if ((M_PI*4. > alpha*5.) && (M_PI*4. > beta*5.) && (M_PI*4 > gamma*5.)) { 1638 Umkreisradius = SideA / 2.0 / sin(alpha); 1639 //cout << Umkreisradius << endl; 1640 //cout << SideB / 2.0 / sin(beta) << endl; 1641 //cout << SideC / 2.0 / sin(gamma) << endl; 1642 1643 if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points. 1644 cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl; 1645 cout << Verbose(2) << "Candidate is "<< *Candidate << endl; 1646 sign = AngleCheck.ScalarProduct(direction1); 1647 if (fabs(sign)<MYEPSILON) { 1648 if (AngleCheck.ScalarProduct(OldNormal)<0) { 1649 sign =0; 1650 AlternativeSign=1; 1651 } else { 1652 sign =0; 1653 AlternativeSign=-1; 1654 } 1655 } else { 1656 sign /= fabs(sign); 1657 cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl; 1658 } 1659 1660 Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius); 1661 1662 AngleCheck.CopyVector(&ReferencePoint); 1663 AngleCheck.Scale(-1); 1664 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl; 1665 AngleCheck.AddVector(&Mittelpunkt); 1666 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl; 1667 cout << Verbose(4) << "Reference vector to sphere's center is " << AngleCheck << "." << endl; 1668 1669 BallAngle = AngleCheck.Angle(OldNormal); 1670 cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl; 1671 1672 //cout << "direction1 is " << direction1->x[0] <<" "<< direction1->x[1] <<" "<< direction1->x[2] <<" " << endl; 1673 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl; 1674 1675 cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl; 1676 1677 NewUmkreismittelpunkt.SubtractVector(&ReferencePoint); 1678 1679 if ((AngleCheck.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) { 1680 if (Storage[0]< -1.5) { // first Candidate at all 1681 if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) { 1682 cout << Verbose(2) << "First good candidate is " << *Candidate << " with "; 1683 Opt_Candidate = Candidate; 1684 Storage[0] = sign; 1685 Storage[1] = AlternativeSign; 1686 Storage[2] = BallAngle; 1687 cout << " angle " << Storage[2] << " and Up/Down " 1688 << Storage[0] << endl; 1689 } else 1690 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl; 1691 } else { 1692 if ( Storage[2] > BallAngle) { 1693 if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) { 1694 cout << Verbose(2) << "Next better candidate is " << *Candidate << " with "; 1695 Opt_Candidate = Candidate; 1696 Storage[0] = sign; 1697 Storage[1] = AlternativeSign; 1698 Storage[2] = BallAngle; 1699 cout << " angle " << Storage[2] << " and Up/Down " 1700 << Storage[0] << endl; 1701 } else 1702 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl; 1703 } else { 1704 if (DEBUG) { 1705 cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl; 1706 } 1707 } 1708 } 1709 } else { 1710 if (DEBUG) { 1711 cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl; 1712 } 1713 } 1714 } else { 1715 if (DEBUG) { 1716 cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl; 1717 } 1718 } 1719 } else { 1720 if (DEBUG) { 1721 cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl; 1722 } 1723 } 1724 } else { 1725 if (DEBUG) { 1726 cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl; 1727 } 1728 } 1729 1730 if (RecursionLevel < 5) { // Seven is the recursion level threshold. 1731 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond 1732 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate); 1733 if (Walker == Parent) { // don't go back the same bond 1734 continue; 1735 } else { 1736 Find_next_suitable_point_via_Angle_of_Sphere(a, b, c, Walker, Candidate, RecursionLevel+1, Chord, direction1, OldNormal, ReferencePoint, Opt_Candidate, Storage, RADIUS, mol); //call function again 1737 } 1738 } 1739 } 1740 cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n"; 1741 } 1742 ; 1743 1744 1745 /** This recursive function finds a third point, to form a triangle with two given ones. 1746 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \ 1747 * supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \ 1748 * upon which we operate. 1749 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \ 1750 * direction and angle into Storage. 1751 * We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \ 1752 * with all neighbours of the candidate. 1753 * @param a first point 1754 * @param b second point 1755 * @param Candidate base point along whose bonds to start looking from 1756 * @param Parent point to avoid during search as its wrong direction 1757 * @param RecursionLevel contains current recursion depth 1758 * @param Chord baseline vector of first and second point 1759 * @param d1 second in plane vector (along with \a Chord) of the triangle the baseline belongs to 1760 * @param OldNormal normal of the triangle which the baseline belongs to 1761 * @param Opt_Candidate candidate reference to return 1762 * @param Opt_Mittelpunkt Centerpoint of ball, when resting on Opt_Candidate 1763 * @param Storage array containing two angles of current Opt_Candidate 1764 * @param RADIUS radius of ball 1765 * @param mol molecule structure with atoms and bonds 1766 */ 1767 void Find_next_suitable_point(atom* a, atom* b, atom* Candidate, atom* Parent, 1768 int RecursionLevel, Vector *Chord, Vector *d1, Vector *OldNormal, 1769 atom*& Opt_Candidate, Vector *Opt_Mittelpunkt, double *Storage, const double RADIUS, molecule* mol) 1770 { 1771 /* OldNormal is normal vector on the old triangle 1772 * d1 is normal on the triangle line, from which we come, as well as on OldNormal. 1773 * Chord points from b to a!!! 1774 */ 1775 Vector dif_a; //Vector from a to candidate 1776 Vector dif_b; //Vector from b to candidate 1777 Vector AngleCheck, AngleCheckReference, DirectionCheckPoint; 1778 Vector TempNormal, Umkreismittelpunkt, Mittelpunkt, helper; 1779 1780 double CurrentEpsilon = 0.1; 1781 double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance; 1782 double BallAngle; 1783 atom *Walker; // variable atom point 1784 1785 1786 dif_a.CopyVector(&(a->x)); 1787 dif_a.SubtractVector(&(Candidate->x)); 1788 dif_b.CopyVector(&(b->x)); 1789 dif_b.SubtractVector(&(Candidate->x)); 1790 DirectionCheckPoint.CopyVector(&dif_a); 1791 DirectionCheckPoint.Scale(-1); 1792 DirectionCheckPoint.ProjectOntoPlane(Chord); 1793 1794 SideA = dif_b.Norm(); 1795 SideB = dif_a.Norm(); 1796 SideC = Chord->Norm(); 1797 //Chord->Scale(-1); 1798 1799 alpha = Chord->Angle(&dif_a); 1800 beta = M_PI - Chord->Angle(&dif_b); 1801 gamma = dif_a.Angle(&dif_b); 1802 1803 1804 if (DEBUG) { 1805 cout << "Atom number" << Candidate->nr << endl; 1806 Candidate->x.Output((ofstream *) &cout); 1807 cout << "number of bonds " << mol->NumberOfBondsPerAtom[Candidate->nr] << endl; 1808 } 1809 1810 if (a != Candidate and b != Candidate) { 1811 // alpha = dif_a.Angle(&dif_b) / 2.; 1812 // SideA = Chord->Norm() / 2.;// (Chord->Norm()/2.) / sin(0.5*alpha); 1813 // SideB = dif_a.Norm(); 1814 // centerline = SideA * SideA + SideB * SideB - 2. * SideA * SideB * cos( 1815 // alpha); // note this is squared of center line length 1816 // centerline = (Chord->Norm()/2.) / sin(0.5*alpha); 1817 // Those are remains from Freddie. Needed? 1818 1819 Umkreisradius = SideA / 2.0 / sin(alpha); 1820 //cout << Umkreisradius << endl; 1821 //cout << SideB / 2.0 / sin(beta) << endl; 1822 //cout << SideC / 2.0 / sin(gamma) << endl; 1823 1824 if (Umkreisradius < RADIUS && DirectionCheckPoint.ScalarProduct(&(Candidate->x))>0) { //Checking whether ball will at least rest o points. 1825 // intermediate calculations to aquire centre of sphere, called Mittelpunkt: 1826 Umkreismittelpunkt.Zero(); 1827 helper.CopyVector(&a->x); 1828 helper.Scale(sin(2.*alpha)); 1829 Umkreismittelpunkt.AddVector(&helper); 1830 helper.CopyVector(&b->x); 1831 helper.Scale(sin(2.*beta)); 1832 Umkreismittelpunkt.AddVector(&helper); 1833 helper.CopyVector(&Candidate->x); 1834 helper.Scale(sin(2.*gamma)); 1835 Umkreismittelpunkt.AddVector(&helper); 1836 //Umkreismittelpunkt = (a->x) * sin(2.*alpha) + b->x * sin(2.*beta) + (Candidate->x) * sin(2.*gamma) ; 1837 Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma))); 1838 1839 TempNormal.CopyVector(&dif_a); 1840 TempNormal.VectorProduct(&dif_b); 1841 if (TempNormal.ScalarProduct(OldNormal)<0 && sign>0 || TempNormal.ScalarProduct(OldNormal)>0 && sign<0) { 1842 TempNormal.Scale(-1); 1843 } 1844 TempNormal.Normalize(); 1845 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius); 1846 TempNormal.Scale(Restradius); 1847 1848 Mittelpunkt.CopyVector(&Umkreismittelpunkt); 1849 Mittelpunkt.AddVector(&TempNormal); //this is center of sphere supported by a, b and Candidate 1850 1851 AngleCheck.CopyVector(Chord); 1852 AngleCheck.Scale(-0.5); 1853 AngleCheck.SubtractVector(&(b->x)); 1854 AngleCheckReference.CopyVector(&AngleCheck); 1855 AngleCheckReference.AddVector(Opt_Mittelpunkt); 1856 AngleCheck.AddVector(&Mittelpunkt); 1857 1858 BallAngle = AngleCheck.Angle(&AngleCheckReference); 1859 1860 d1->ProjectOntoPlane(&AngleCheckReference); 1861 sign = AngleCheck.ScalarProduct(d1); 1862 if (fabs(sign) < MYEPSILON) 1863 sign = 0; 1864 else 1865 sign /= fabs(sign); // +1 if in direction of triangle plane, -1 if in other direction... 1866 1867 1868 if (Storage[0]< -1.5) { // first Candidate at all 1869 cout << "Next better candidate is " << *Candidate << " with "; 1870 Opt_Candidate = Candidate; 1871 Storage[0] = sign; 1872 Storage[1] = BallAngle; 1873 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1874 cout << "Angle is " << Storage[1] << ", Halbraum ist " << Storage[0] << endl; 1875 } else { 1876 /* 1877 * removed due to change in criterium, now checking angle of ball to old normal. 1878 //We will now check for non interference, that is if the new candidate would have the Opt_Candidate 1879 //within the ball. 1880 1881 Distance = Opt_Candidate->x.Distance(&Mittelpunkt); 1882 //cout << "Opt_Candidate " << Opt_Candidate << " has distance " << Distance << " to Center of Candidate " << endl; 1883 1884 1885 if (Distance >RADIUS) { // We have no interference and may now check whether the new point is better. 1886 */ 1887 //cout << "Atom " << Candidate << " has distance " << Candidate->x.Distance(Opt_Mittelpunkt) << " to Center of Candidate " << endl; 1888 1889 if (((Storage[0] < 0 && fabs(sign - Storage[0]) > CurrentEpsilon))) { //This will give absolute preference to those in "right-hand" quadrants 1890 //(Candidate->x.Distance(Opt_Mittelpunkt) < RADIUS)) //and those where Candidate would be within old Sphere. 1891 cout << "Next better candidate is " << *Candidate << " with "; 1892 Opt_Candidate = Candidate; 1893 Storage[0] = sign; 1894 Storage[1] = BallAngle; 1895 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1896 cout << "Angle is " << Storage[1] << ", Halbraum ist " << Storage[0] << endl; 1897 } else { 1898 if ((fabs(sign - Storage[0]) < CurrentEpsilon && sign > 0 && Storage[1] > BallAngle) || (fabs(sign - Storage[0]) < CurrentEpsilon && sign < 0 && Storage[1] < BallAngle)) { 1899 //Depending on quadrant we prefer higher or lower atom with respect to Triangle normal first. 1900 cout << "Next better candidate is " << *Candidate << " with "; 1901 Opt_Candidate = Candidate; 1902 Storage[0] = sign; 1903 Storage[1] = BallAngle; 1904 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1905 cout << "Angle is " << Storage[1] << ", Halbraum ist " << Storage[0] << endl; 1906 } 1907 } 1908 } 1909 /* 1910 * This is for checking point-angle and presence of Candidates in Ball, currently we are checking the ball Angle. 1911 * 1912 else 1913 { 1914 if (sign>0 && BallAngle>0 && Storage[0]<0) 1915 { 1916 cout << "Next better candidate is " << *Candidate << " with "; 1917 Opt_Candidate = Candidate; 1918 Storage[0] = sign; 1919 Storage[1] = BallAngle; 1920 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1921 cout << "Angle is " << Storage[1] << ", Halbraum ist " 1922 << Storage[0] << endl; 1923 1924 //Debugging purposes only 1925 cout << "Umkreismittelpunkt has coordinates" << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] <<" "<<Umkreismittelpunkt.x[2] << endl; 1926 cout << "Candidate has coordinates" << Candidate->x.x[0]<< " " << Candidate->x.x[1] << " " << Candidate->x.x[2] << endl; 1927 cout << "a has coordinates" << a->x.x[0]<< " " << a->x.x[1] << " " << a->x.x[2] << endl; 1928 cout << "b has coordinates" << b->x.x[0]<< " " << b->x.x[1] << " " << b->x.x[2] << endl; 1929 cout << "Mittelpunkt has coordinates" << Mittelpunkt.x[0] << " " << Mittelpunkt.x[1]<< " " <<Mittelpunkt.x[2] << endl; 1930 cout << "Umkreisradius ist " << Umkreisradius << endl; 1931 cout << "Restradius ist " << Restradius << endl; 1932 cout << "TempNormal has coordinates " << TempNormal.x[0] << " " << TempNormal.x[1] << " " << TempNormal.x[2] << " " << endl; 1933 cout << "OldNormal has coordinates " << OldNormal->x[0] << " " << OldNormal->x[1] << " " << OldNormal->x[2] << " " << endl; 1934 cout << "Dist a to UmkreisMittelpunkt " << a->x.Distance(&Umkreismittelpunkt) << endl; 1935 cout << "Dist b to UmkreisMittelpunkt " << b->x.Distance(&Umkreismittelpunkt) << endl; 1936 cout << "Dist Candidate to UmkreisMittelpunkt " << Candidate->x.Distance(&Umkreismittelpunkt) << endl; 1937 cout << "Dist a to Mittelpunkt " << a->x.Distance(&Mittelpunkt) << endl; 1938 cout << "Dist b to Mittelpunkt " << b->x.Distance(&Mittelpunkt) << endl; 1939 cout << "Dist Candidate to Mittelpunkt " << Candidate->x.Distance(&Mittelpunkt) << endl; 1940 1941 1942 1943 } 1944 else 1945 { 1946 if (DEBUG) 1947 cout << "Looses to better candidate" << endl; 1948 } 1949 } 1950 */ 1951 } else { 1952 if (DEBUG) { 1953 cout << "Doesn't satisfy requirements for circumscribing circle" << endl; 1954 } 1955 } 1956 } else { 1957 if (DEBUG) { 1958 cout << "identisch mit Ursprungslinie" << endl; 1959 } 1960 } 1961 1962 if (RecursionLevel < 9) { // Five is the recursion level threshold. 1963 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond 1964 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate); 1965 if (Walker == Parent) { // don't go back the same bond 1966 continue; 1967 } else { 1968 Find_next_suitable_point(a, b, Walker, Candidate, RecursionLevel+1, Chord, d1, OldNormal, Opt_Candidate, Opt_Mittelpunkt, Storage, RADIUS, mol); //call function again 1969 } 1970 } 1971 } 995 1972 }; 1973 1974 /** This function finds a triangle to a line, adjacent to an existing one. 1975 * @param out output stream for debugging 1976 * @param tecplot output stream for writing found triangles in TecPlot format 1977 * @param mol molecule structure with all atoms and bonds 1978 * @param Line current baseline to search from 1979 * @param T current triangle which \a Line is edge of 1980 * @param RADIUS radius of the rolling ball 1981 * @param N number of found triangles 1982 * @param *filename filename base for intermediate envelopes 1983 */ 1984 bool Tesselation::Find_next_suitable_triangle(ofstream *out, ofstream *tecplot, 1985 molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, 1986 const double& RADIUS, int N, const char *tempbasename) 1987 { 1988 cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n"; 1989 Vector direction1; 1990 Vector helper; 1991 Vector Chord; 1992 ofstream *tempstream = NULL; 1993 char NumberName[255]; 1994 double tmp; 1995 //atom* Walker; 1996 atom* OldThirdPoint; 1997 1998 double Storage[3]; 1999 Storage[0] = -2.; // This direction is either +1 or -1 one, so any result will take precedence over initial values 2000 Storage[1] = -2.; // This is also lower then any value produced by an eligible atom, which are all positive 2001 Storage[2] = 9999999.; 2002 atom* Opt_Candidate = NULL; 2003 Vector Opt_Mittelpunkt; 2004 2005 cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl; 2006 2007 helper.CopyVector(&(Line.endpoints[0]->node->x)); 2008 for (int i = 0; i < 3; i++) { 2009 if (T.endpoints[i]->node->nr != Line.endpoints[0]->node->nr && T.endpoints[i]->node->nr != Line.endpoints[1]->node->nr) { 2010 OldThirdPoint = T.endpoints[i]->node; 2011 helper.SubtractVector(&T.endpoints[i]->node->x); 2012 break; 2013 } 2014 } 2015 2016 direction1.CopyVector(&Line.endpoints[0]->node->x); 2017 direction1.SubtractVector(&Line.endpoints[1]->node->x); 2018 direction1.VectorProduct(&(T.NormalVector)); 2019 2020 if (direction1.ScalarProduct(&helper) < 0) { 2021 direction1.Scale(-1); 2022 } 2023 cout << Verbose(2) << "Looking in direction " << direction1 << " for candidates.\n"; 2024 2025 Chord.CopyVector(&(Line.endpoints[0]->node->x)); // bring into calling function 2026 Chord.SubtractVector(&(Line.endpoints[1]->node->x)); 2027 cout << Verbose(2) << "Baseline vector is " << Chord << ".\n"; 2028 2029 2030 Vector Umkreismittelpunkt, a, b, c; 2031 double alpha, beta, gamma; 2032 a.CopyVector(&(T.endpoints[0]->node->x)); 2033 b.CopyVector(&(T.endpoints[1]->node->x)); 2034 c.CopyVector(&(T.endpoints[2]->node->x)); 2035 a.SubtractVector(&(T.endpoints[1]->node->x)); 2036 b.SubtractVector(&(T.endpoints[2]->node->x)); 2037 c.SubtractVector(&(T.endpoints[0]->node->x)); 2038 2039 alpha = M_PI - a.Angle(&c); 2040 beta = M_PI - b.Angle(&a); 2041 gamma = M_PI - c.Angle(&b); 2042 if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) 2043 cerr << Verbose(0) << "WARNING: sum of angles for candidate triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n"; 2044 2045 Umkreismittelpunkt.Zero(); 2046 helper.CopyVector(&T.endpoints[0]->node->x); 2047 helper.Scale(sin(2.*alpha)); 2048 Umkreismittelpunkt.AddVector(&helper); 2049 helper.CopyVector(&T.endpoints[1]->node->x); 2050 helper.Scale(sin(2.*beta)); 2051 Umkreismittelpunkt.AddVector(&helper); 2052 helper.CopyVector(&T.endpoints[2]->node->x); 2053 helper.Scale(sin(2.*gamma)); 2054 Umkreismittelpunkt.AddVector(&helper); 2055 //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) ; 2056 //cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl; 2057 Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma))); 2058 //cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl; 2059 cout << " We look over line " << Line << " in direction " << direction1.x[0] << " " << direction1.x[1] << " " << direction1.x[2] << " " << endl; 2060 cout << " Old Normal is " << (T.NormalVector.x)[0] << " " << T.NormalVector.x[1] << " " << (T.NormalVector.x)[2] << " " << endl; 2061 2062 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; 2063 cout << Verbose(2) << "Center of circumference is " << Umkreismittelpunkt << "." << endl; 2064 if (DEBUG) 2065 cout << Verbose(3) << "Check of relative endpoints (same distance, equally spreaded): "<< endl; 2066 tmp = 0; 2067 for (int i=0;i<NDIM;i++) { 2068 helper.CopyVector(&T.endpoints[i]->node->x); 2069 helper.SubtractVector(&Umkreismittelpunkt); 2070 if (DEBUG) 2071 cout << Verbose(3) << "Endpoint[" << i << "]: " << helper << " with length " << helper.Norm() << "." << endl; 2072 if (tmp == 0) // set on first time for comparison against next ones 2073 tmp = helper.Norm(); 2074 if (fabs(helper.Norm() - tmp) > MYEPSILON) 2075 cerr << Verbose(1) << "WARNING: center of circumference is wrong!" << endl; 2076 } 2077 2078 cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl; 2079 2080 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); 2081 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); 2082 if (Opt_Candidate == NULL) { 2083 cerr << "WARNING: Could not find a suitable candidate." << endl; 2084 return false; 2085 } 2086 cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << endl; 2087 2088 // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2) 2089 bool flag = CheckPresenceOfTriangle(out, Opt_Candidate, Line.endpoints[0]->node, Line.endpoints[1]->node); 2090 2091 if (flag) { // if so, add 2092 AddTrianglePoint(Opt_Candidate, 0); 2093 AddTrianglePoint(Line.endpoints[0]->node, 1); 2094 AddTrianglePoint(Line.endpoints[1]->node, 2); 2095 2096 AddTriangleLine(TPS[0], TPS[1], 0); 2097 AddTriangleLine(TPS[0], TPS[2], 1); 2098 AddTriangleLine(TPS[1], TPS[2], 2); 2099 2100 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 2101 AddTriangleToLines(); 2102 2103 BTS->GetNormalVector(BTS->NormalVector); 2104 2105 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) ) { 2106 BTS->NormalVector.Scale(-1); 2107 }; 2108 cout << Verbose(1) << "New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl; 2109 cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl; 2110 } else { // else, yell and do nothing 2111 cout << Verbose(1) << "This triangle consisting of "; 2112 cout << *Opt_Candidate << ", "; 2113 cout << *Line.endpoints[0]->node << " and "; 2114 cout << *Line.endpoints[1]->node << " "; 2115 cout << "is invalid!" << endl; 2116 return false; 2117 } 2118 2119 if ((TrianglesOnBoundaryCount % 10) == 0) { 2120 sprintf(NumberName, "-%d", TriangleFilesWritten); 2121 if (DoTecplotOutput) { 2122 string NameofTempFile(tempbasename); 2123 NameofTempFile.append(NumberName); 2124 NameofTempFile.append(TecplotSuffix); 2125 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2126 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2127 write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten); 2128 tempstream->close(); 2129 tempstream->flush(); 2130 delete(tempstream); 2131 } 2132 2133 if (DoRaster3DOutput) { 2134 string NameofTempFile(tempbasename); 2135 NameofTempFile.append(NumberName); 2136 NameofTempFile.append(Raster3DSuffix); 2137 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2138 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2139 write_raster3d_file(out, tempstream, this, mol); 2140 tempstream->close(); 2141 tempstream->flush(); 2142 delete(tempstream); 2143 } 2144 if (DoTecplotOutput || DoRaster3DOutput) 2145 TriangleFilesWritten++; 2146 } 2147 2148 cout << Verbose(1) << "End of Find_next_suitable_triangle\n"; 2149 return true; 2150 }; 2151 2152 /** Checks whether the triangle consisting of the three atoms is already present. 2153 * Searches for the points in Tesselation::PointsOnBoundary and checks their 2154 * lines. If any of the three edges already has two triangles attached, false is 2155 * returned. 2156 * \param *out output stream for debugging 2157 * \param *a first endpoint 2158 * \param *b second endpoint 2159 * \param *c third endpoint 2160 * \return false - triangle invalid due to edge criteria, true - triangle may be added. 2161 */ 2162 bool Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *a, atom *b, atom *c) { 2163 LineMap::iterator TryAndError; 2164 PointTestPair InsertPoint; 2165 bool Present[3]; 2166 2167 *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl; 2168 TPS[0] = new class BoundaryPointSet(a); 2169 TPS[1] = new class BoundaryPointSet(b); 2170 TPS[2] = new class BoundaryPointSet(c); 2171 for (int i=0;i<3;i++) { // check through all endpoints 2172 InsertPoint = PointsOnBoundary.insert(PointPair(TPS[i]->node->nr, TPS[i])); 2173 Present[i] = !InsertPoint.second; 2174 if (Present[i]) { // if new point was not present before, increase counter 2175 delete TPS[i]; 2176 *out << Verbose(2) << "Atom " << *((InsertPoint.first)->second->node) << " gibt's schon in der PointMap." << endl; 2177 TPS[i] = (InsertPoint.first)->second; 2178 } 2179 } 2180 2181 // check lines 2182 for (int i=0;i<3;i++) 2183 if (Present[i]) 2184 for (int j=i;j<3;j++) 2185 if (Present[j]) { 2186 TryAndError = TPS[i]->lines.find(TPS[j]->node->nr); 2187 if ((TryAndError != TPS[i]->lines.end()) && (TryAndError->second->TrianglesCount > 1)) { 2188 *out << "WARNING: Line " << *TryAndError->second << " already present with " << TryAndError->second->TrianglesCount << " triangles attached." << endl; 2189 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl; 2190 return false; 2191 } 2192 } 2193 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl; 2194 return true; 2195 }; 2196 2197 2198 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, atom* Parent, 2199 int RecursionLevel, Vector Oben, atom*& Opt_Candidate, double Storage[3], 2200 molecule* mol, double RADIUS) 2201 { 2202 cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation, recursive level " << RecursionLevel << endl; 2203 int i; 2204 Vector AngleCheck; 2205 atom* Walker; 2206 double norm = -1., angle; 2207 2208 // check if we only have one unique point yet ... 2209 if (a != Candidate) { 2210 cout << Verbose(3) << "Current candidate is " << *Candidate << ": "; 2211 AngleCheck.CopyVector(&(Candidate->x)); 2212 AngleCheck.SubtractVector(&(a->x)); 2213 norm = AngleCheck.Norm(); 2214 // second point shall have smallest angle with respect to Oben vector 2215 if (norm < RADIUS) { 2216 angle = AngleCheck.Angle(&Oben); 2217 if (angle < Storage[0]) { 2218 //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]); 2219 cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n"; 2220 Opt_Candidate = Candidate; 2221 Storage[0] = AngleCheck.Angle(&Oben); 2222 //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]); 2223 } else { 2224 cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl; 2225 } 2226 } else { 2227 cout << "Refused due to Radius " << norm << endl; 2228 } 2229 } 2230 2231 // if not recursed to deeply, look at all its bonds 2232 if (RecursionLevel < 7) { 2233 for (i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { 2234 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate); 2235 if (Walker == Parent) // don't go back along the bond we came from 2236 continue; 2237 else 2238 Find_second_point_for_Tesselation(a, Walker, Candidate, RecursionLevel + 1, Oben, Opt_Candidate, Storage, mol, RADIUS); 2239 } 2240 } 2241 cout << Verbose(2) << "End of Find_second_point_for_Tesselation, recursive level " << RecursionLevel << endl; 2242 }; 2243 2244 void Tesselation::Find_starting_triangle(molecule* mol, const double RADIUS) 2245 { 2246 cout << Verbose(1) << "Begin of Find_starting_triangle\n"; 2247 int i = 0; 2248 atom* Walker; 2249 atom* FirstPoint; 2250 atom* SecondPoint; 2251 atom* max_index[NDIM]; 2252 double max_coordinate[NDIM]; 2253 Vector Oben; 2254 Vector helper; 2255 Vector Chord; 2256 Vector CenterOfFirstLine; 2257 2258 Oben.Zero(); 2259 2260 for (i = 0; i < 3; i++) { 2261 max_index[i] = NULL; 2262 max_coordinate[i] = -1; 2263 } 2264 cout << Verbose(2) << "Molecule mol is there and has " << mol->AtomCount << " Atoms \n"; 2265 2266 // 1. searching topmost atom with respect to each axis 2267 Walker = mol->start; 2268 while (Walker->next != mol->end) { 2269 Walker = Walker->next; 2270 for (i = 0; i < 3; i++) { 2271 if (Walker->x.x[i] > max_coordinate[i]) { 2272 max_coordinate[i] = Walker->x.x[i]; 2273 max_index[i] = Walker; 2274 } 2275 } 2276 } 2277 2278 cout << Verbose(2) << "Found maximum coordinates: "; 2279 for (int i=0;i<NDIM;i++) 2280 cout << i << ": " << *max_index[i] << "\t"; 2281 cout << endl; 2282 //Koennen dies fuer alle Richtungen, legen hier erstmal Richtung auf k=0 2283 const int k = 1; 2284 Oben.x[k] = 1.; 2285 FirstPoint = max_index[k]; 2286 2287 cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << " with " << mol->NumberOfBondsPerAtom[FirstPoint->nr] << " bonds." << endl; 2288 double Storage[3]; 2289 atom* Opt_Candidate = NULL; 2290 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. 2291 Storage[1] = 999999.; // This will be an angle looking for the third point. 2292 Storage[2] = 999999.; 2293 2294 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_... 2295 SecondPoint = Opt_Candidate; 2296 cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n"; 2297 2298 helper.CopyVector(&(FirstPoint->x)); 2299 helper.SubtractVector(&(SecondPoint->x)); 2300 helper.Normalize(); 2301 Oben.ProjectOntoPlane(&helper); 2302 Oben.Normalize(); 2303 helper.VectorProduct(&Oben); 2304 Storage[0] = -2.; // This will indicate the quadrant. 2305 Storage[1] = 9999999.; // This will be an angle looking for the third point. 2306 Storage[2] = 9999999.; 2307 2308 Chord.CopyVector(&(FirstPoint->x)); // bring into calling function 2309 Chord.SubtractVector(&(SecondPoint->x)); 2310 // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized) 2311 2312 cout << Verbose(2) << "Looking for third point candidates \n"; 2313 // look in one direction of baseline for initial candidate 2314 Opt_Candidate = NULL; 2315 CenterOfFirstLine.CopyVector(&Chord); 2316 CenterOfFirstLine.Scale(0.5); 2317 CenterOfFirstLine.AddVector(&(SecondPoint->x)); 2318 2319 cout << Verbose(1) << "Looking for third point candidates from " << *FirstPoint << " onward ...\n"; 2320 Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, SecondPoint, FirstPoint, 0, &Chord, &helper, &Oben, CenterOfFirstLine, Opt_Candidate, Storage, RADIUS, mol); 2321 // look in other direction of baseline for possible better candidate 2322 cout << Verbose(1) << "Looking for third point candidates from " << *SecondPoint << " onward ...\n"; 2323 Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, FirstPoint, SecondPoint, 0, &Chord, &helper, &Oben, CenterOfFirstLine, Opt_Candidate, Storage, RADIUS, mol); 2324 cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl; 2325 2326 // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate 2327 2328 // Finally, we only have to add the found points 2329 AddTrianglePoint(FirstPoint, 0); 2330 AddTrianglePoint(SecondPoint, 1); 2331 AddTrianglePoint(Opt_Candidate, 2); 2332 // ... and respective lines 2333 AddTriangleLine(TPS[0], TPS[1], 0); 2334 AddTriangleLine(TPS[1], TPS[2], 1); 2335 AddTriangleLine(TPS[0], TPS[2], 2); 2336 // ... and triangles to the Maps of the Tesselation class 2337 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 2338 AddTriangleToLines(); 2339 // ... and calculate its normal vector (with correct orientation) 2340 Oben.Scale(-1.); 2341 BTS->GetNormalVector(Oben); 2342 cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n"; 2343 cout << Verbose(1) << "End of Find_starting_triangle\n"; 2344 }; 2345 2346 void Find_non_convex_border(ofstream *out, ofstream *tecplot, molecule* mol, const char *filename, const double RADIUS) 2347 { 2348 int N = 0; 2349 struct Tesselation *Tess = new Tesselation; 2350 cout << Verbose(1) << "Entering search for non convex hull. " << endl; 2351 cout << flush; 2352 LineMap::iterator baseline; 2353 cout << Verbose(0) << "Begin of Find_non_convex_border\n"; 2354 bool flag = false; // marks whether we went once through all baselines without finding any without two triangles 2355 bool failflag = false; 2356 if ((mol->first->next == mol->last) || (mol->last->previous == mol->first)) 2357 mol->CreateAdjacencyList((ofstream *)&cout, 1.6, true); 2358 2359 Tess->Find_starting_triangle(mol, RADIUS); 2360 2361 baseline = Tess->LinesOnBoundary.begin(); 2362 while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) { 2363 if (baseline->second->TrianglesCount == 1) { 2364 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. 2365 flag = flag || failflag; 2366 if (!failflag) 2367 cerr << "WARNING: Find_next_suitable_triangle failed." << endl; 2368 } else { 2369 cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl; 2370 } 2371 N++; 2372 baseline++; 2373 if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) { 2374 baseline = Tess->LinesOnBoundary.begin(); // restart if we reach end due to newly inserted lines 2375 flag = false; 2376 } 2377 } 2378 if (failflag) { 2379 cout << Verbose(1) << "Writing final tecplot file\n"; 2380 if (DoTecplotOutput) 2381 write_tecplot_file(out, tecplot, Tess, mol, -1); 2382 if (DoRaster3DOutput) 2383 write_raster3d_file(out, tecplot, Tess, mol); 2384 } else { 2385 cerr << "ERROR: Could definately not find all necessary triangles!" << endl; 2386 } 2387 2388 cout << Verbose(0) << "End of Find_non_convex_border\n"; 2389 delete(Tess); 2390 }; 2391 -
Property mode
changed from
-
TabularUnified src/boundary.hpp ¶
-
Property mode
changed from
100644
to100755
r674220 ra98603 36 36 BoundaryPointSet(atom *Walker); 37 37 ~BoundaryPointSet(); 38 38 39 39 void AddLine(class BoundaryLineSet *line); 40 40 41 41 LineMap lines; 42 42 int LinesCount; … … 64 64 BoundaryTriangleSet(class BoundaryLineSet *line[3], int number); 65 65 ~BoundaryTriangleSet(); 66 66 67 67 void GetNormalVector(Vector &NormalVector); 68 68 69 69 class BoundaryPointSet *endpoints[3]; 70 70 class BoundaryLineSet *lines[3]; 71 Vector NormalVector; 71 72 int Nr; 72 73 }; … … 74 75 class Tesselation { 75 76 public: 76 77 77 78 Tesselation(); 78 79 ~Tesselation(); 79 80 80 81 void TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol); 81 82 void GuessStartingTriangle(ofstream *out); 82 83 void AddPoint(atom * Walker); 83 84 void AddTrianglePoint(atom* Candidate, int n); 85 void AddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n); 86 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); 89 bool CheckPresenceOfTriangle(ofstream *out, atom *a, atom *b, atom *c); 90 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); 91 84 92 PointMap PointsOnBoundary; 85 93 LineMap LinesOnBoundary; 86 94 TriangleMap TrianglesOnBoundary; 95 class BoundaryPointSet *TPS[3]; //this is a Storage for pointers to triangle points, this and BPS[2] needed due to AddLine restrictions 87 96 class BoundaryPointSet *BPS[2]; 88 97 class BoundaryLineSet *BLS[3]; … … 91 100 int LinesOnBoundaryCount; 92 101 int TrianglesOnBoundaryCount; 102 int TriangleFilesWritten; 93 103 }; 94 104 … … 102 112 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem); 103 113 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); 104 116 105 117 -
Property mode
changed from
-
TabularUnified src/builder.cpp ¶
-
Property mode
changed from
100644
to100755
r674220 ra98603 1 1 /** \file builder.cpp 2 * 2 * 3 3 * By stating absolute positions or binding angles and distances atomic positions of a molecule can be constructed. 4 4 * The output is the complete configuration file for PCP for direct use. … … 6 6 * -# Atomic data is retrieved from a file, if not found requested and stored there for later re-use 7 7 * -# step-by-step construction of the molecule beginning either at a centre of with a certain atom 8 * 8 * 9 9 */ 10 10 11 11 /*! \mainpage Molecuilder - a molecular set builder 12 * 12 * 13 13 * This introductory shall briefly make aquainted with the program, helping in installing and a first run. 14 * 14 * 15 15 * \section about About the Program 16 * 16 * 17 17 * Molecuilder is a short program, written in C++, that enables the construction of a coordinate set for the 18 18 * atoms making up an molecule by the successive statement of binding angles and distances and referencing to 19 19 * already constructed atoms. 20 * 20 * 21 21 * A configuration file may be written that is compatible to the format used by PCP - a parallel Car-Parrinello 22 22 * molecular dynamics implementation. 23 * 23 * 24 24 * \section install Installation 25 * 25 * 26 26 * Installation should without problems succeed as follows: 27 27 * -# ./configure (or: mkdir build;mkdir run;cd build; ../configure --bindir=../run) 28 28 * -# make 29 29 * -# make install 30 * 30 * 31 31 * Further useful commands are 32 32 * -# make clean uninstall: deletes .o-files and removes executable from the given binary directory\n 33 * -# make doxygen-doc: Creates these html pages out of the documented source 34 * 33 * -# make doxygen-doc: Creates these html pages out of the documented source 34 * 35 35 * \section run Running 36 * 36 * 37 37 * The program can be executed by running: ./molecuilder 38 * 38 * 39 39 * Note, that it uses a database, called "elements.db", in the executable's directory. If the file is not found, 40 40 * it is created and any given data on elements of the periodic table will be stored therein and re-used on 41 * later re-execution. 42 * 41 * later re-execution. 42 * 43 43 * \section ref References 44 * 44 * 45 45 * For the special configuration file format, see the documentation of pcp. 46 * 46 * 47 47 */ 48 48 … … 80 80 cout << Verbose(0) << "INPUT: "; 81 81 cin >> choice; 82 82 83 83 switch (choice) { 84 84 case 'a': // absolute coordinates of atom … … 89 89 mol->AddAtom(first); // add to molecule 90 90 break; 91 91 92 92 case 'b': // relative coordinates of atom wrt to reference point 93 93 first = new atom; … … 105 105 mol->AddAtom(first); // add to molecule 106 106 break; 107 107 108 108 case 'c': // relative coordinates of atom wrt to already placed atom 109 109 first = new atom; … … 111 111 do { 112 112 if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl; 113 second = mol->AskAtom("Enter atom number: "); 113 second = mol->AskAtom("Enter atom number: "); 114 114 cout << Verbose(0) << "Enter relative coordinates." << endl; 115 115 first->x.AskPosition(mol->cell_size, false); … … 121 121 mol->AddAtom(first); // add to molecule 122 122 break; 123 123 124 124 case 'd': // two atoms, two angles and a distance 125 125 first = new atom; … … 152 152 x.Copyvector(&fourth->x); 153 153 x.SubtractVector(&third->x); 154 154 155 155 if (!z.SolveSystem(&x,&y,&n, b, c, a)) { 156 156 cout << Verbose(0) << "Failure solving self-dependent linear system!" << endl; … … 167 167 cout << "x: ", 168 168 x.Output((ofstream *)&cout); 169 cout << endl; 169 cout << endl; 170 170 z.MakeNormalVector(&second->x,&third->x,&fourth->x); 171 171 cout << "z: ", 172 172 z.Output((ofstream *)&cout); 173 cout << endl; 173 cout << endl; 174 174 y.MakeNormalVector(&x,&z); 175 175 cout << "y: ", 176 176 y.Output((ofstream *)&cout); 177 cout << endl; 178 177 cout << endl; 178 179 179 // rotate vector around first angle 180 180 first->x.CopyVector(&x); … … 182 182 cout << "Rotated vector: ", 183 183 first->x.Output((ofstream *)&cout); 184 cout << endl; 184 cout << endl; 185 185 // remove the projection onto the rotation plane of the second angle 186 186 n.CopyVector(&y); … … 188 188 cout << "N1: ", 189 189 n.Output((ofstream *)&cout); 190 cout << endl; 190 cout << endl; 191 191 first->x.SubtractVector(&n); 192 192 cout << "Subtracted vector: ", 193 193 first->x.Output((ofstream *)&cout); 194 cout << endl; 194 cout << endl; 195 195 n.CopyVector(&z); 196 196 n.Scale(first->x.Projection(&z)); 197 197 cout << "N2: ", 198 198 n.Output((ofstream *)&cout); 199 cout << endl; 199 cout << endl; 200 200 first->x.SubtractVector(&n); 201 201 cout << "2nd subtracted vector: ", 202 202 first->x.Output((ofstream *)&cout); 203 cout << endl; 204 203 cout << endl; 204 205 205 // rotate another vector around second angle 206 206 n.CopyVector(&y); … … 208 208 cout << "2nd Rotated vector: ", 209 209 n.Output((ofstream *)&cout); 210 cout << endl; 211 210 cout << endl; 211 212 212 // add the two linear independent vectors 213 213 first->x.AddVector(&n); 214 first->x.Normalize(); 214 first->x.Normalize(); 215 215 first->x.Scale(a); 216 216 first->x.AddVector(&second->x); 217 217 218 218 cout << Verbose(0) << "resulting coordinates: "; 219 219 first->x.Output((ofstream *)&cout); … … 241 241 } while ((j != -1) && (i<128)); 242 242 if (i >= 2) { 243 first->x.LSQdistance(atoms, i); 243 first->x.LSQdistance(atoms, i); 244 244 245 245 first->x.Output((ofstream *)&cout); … … 259 259 static void CenterAtoms(molecule *mol) 260 260 { 261 Vector x, y ;261 Vector x, y, helper; 262 262 char choice; // menu choice char 263 263 264 264 cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl; 265 265 cout << Verbose(0) << " a - on origin" << endl; … … 271 271 cout << Verbose(0) << "INPUT: "; 272 272 cin >> choice; 273 273 274 274 switch (choice) { 275 275 default: … … 292 292 mol->CenterEdge((ofstream *)&cout, &x); // make every coordinate positive 293 293 mol->Translate(&y); // translate by boundary 294 mol->SetBoxDimension(&(x+y*2)); // update Box of atoms by boundary 294 helper.CopyVector(&y); 295 helper.Scale(2.); 296 helper.AddVector(&x); 297 mol->SetBoxDimension(&helper); // update Box of atoms by boundary 295 298 break; 296 299 case 'd': … … 327 330 cout << Verbose(0) << "INPUT: "; 328 331 cin >> choice; 329 332 330 333 switch (choice) { 331 334 default: … … 346 349 second = mol->AskAtom("Enter second atom: "); 347 350 348 n.CopyVector((const Vector *)&first->x); 349 n.SubtractVector((const Vector *)&second->x); 351 n.CopyVector((const Vector *)&first->x); 352 n.SubtractVector((const Vector *)&second->x); 350 353 n.Normalize(); 351 break; 354 break; 352 355 case 'd': 353 356 char shorthand[4]; … … 363 366 x.x[i] = gsl_vector_get(param.x,i); 364 367 n.x[i] = gsl_vector_get(param.x,i+NDIM); 365 } 368 } 366 369 gsl_vector_free(param.x); 367 370 cout << Verbose(0) << "Offset vector: "; … … 369 372 cout << Verbose(0) << endl; 370 373 n.Normalize(); 371 break; 374 break; 372 375 }; 373 376 cout << Verbose(0) << "Alignment vector: "; … … 385 388 Vector n; 386 389 char choice; // menu choice char 387 390 388 391 cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl; 389 392 cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl; … … 394 397 cout << Verbose(0) << "INPUT: "; 395 398 cin >> choice; 396 399 397 400 switch (choice) { 398 401 default: … … 413 416 second = mol->AskAtom("Enter second atom: "); 414 417 415 n.CopyVector((const Vector *)&first->x); 416 n.SubtractVector((const Vector *)&second->x); 418 n.CopyVector((const Vector *)&first->x); 419 n.SubtractVector((const Vector *)&second->x); 417 420 n.Normalize(); 418 break; 421 break; 419 422 }; 420 423 cout << Verbose(0) << "Normal vector: "; … … 433 436 double tmp1, tmp2; 434 437 char choice; // menu choice char 435 438 436 439 cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl; 437 440 cout << Verbose(0) << " a - state atom for removal by number" << endl; … … 442 445 cout << Verbose(0) << "INPUT: "; 443 446 cin >> choice; 444 447 445 448 switch (choice) { 446 449 default: … … 475 478 mol->RemoveAtom(first); 476 479 } 477 break; 480 break; 478 481 }; 479 482 //mol->Output((ofstream *)&cout); … … 492 495 int Z; 493 496 char choice; // menu choice char 494 497 495 498 cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl; 496 499 cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl; … … 514 517 for (int i=MAX_ELEMENTS;i--;) 515 518 min[i] = 0.; 516 517 second = mol->start; 519 520 second = mol->start; 518 521 while ((second->next != mol->end)) { 519 522 second = second->next; // advance … … 526 529 } 527 530 if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1; 528 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl; 531 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl; 529 532 } 530 533 for (int i=MAX_ELEMENTS;i--;) 531 534 if (min[i] != 0.) cout << Verbose(0) << "Minimum Bond length between " << first->type->name << " Atom " << first->nr << " and next Ion of type " << (periode->FindElement(i))->name << ": " << min[i] << " a.u." << endl; 532 535 break; 533 536 534 537 case 'b': 535 538 first = mol->AskAtom("Enter first atom: "); … … 556 559 y.SubtractVector((const Vector *)&second->x); 557 560 cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": "; 558 cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl; 561 cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl; 559 562 break; 560 563 case 'd': … … 600 603 int Order1; 601 604 clock_t start, end; 602 605 603 606 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl; 604 607 cout << Verbose(0) << "What's the desired bond order: "; … … 609 612 end = clock(); 610 613 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 611 } else 614 } else 612 615 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl; 613 616 }; … … 623 626 atom *Walker = mol->start; 624 627 int i, comp, counter=0; 625 628 626 629 // generate some KeySets 627 630 cout << "Generating KeySets." << endl; … … 637 640 cout << "Testing insertion of already present item in KeySets." << endl; 638 641 KeySetTestPair test; 639 test = TestSets[mol->AtomCount-1].insert(Walker->nr); 642 test = TestSets[mol->AtomCount-1].insert(Walker->nr); 640 643 if (test.second) { 641 644 cout << Verbose(1) << "Insertion worked?!" << endl; … … 646 649 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr); 647 650 648 // constructing Graph structure 651 // constructing Graph structure 649 652 cout << "Generating Subgraph class." << endl; 650 653 Graph Subgraphs; … … 657 660 cout << "Testing insertion of already present item in Subgraph." << endl; 658 661 GraphTestPair test2; 659 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.))); 662 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.))); 660 663 if (test2.second) { 661 664 cout << Verbose(1) << "Insertion worked?!" << endl; … … 663 666 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl; 664 667 } 665 668 666 669 // show graphs 667 670 cout << "Showing Subgraph's contents, checking that it's sorted." << endl; … … 674 677 if ((*key) > comp) 675 678 cout << (*key) << " "; 676 else 679 else 677 680 cout << (*key) << "! "; 678 681 comp = (*key); … … 716 719 else 717 720 cout << "failed." << endl; 718 721 719 722 // and save to xyz file 720 723 if (ConfigFileName != NULL) { … … 727 730 strcat(filename, ".xyz"); 728 731 output.open(filename, ios::trunc); 729 } 732 } 730 733 cout << Verbose(0) << "Saving of XYZ file "; 731 734 if (mol->MDSteps <= 1) { … … 742 745 output.close(); 743 746 output.clear(); 744 747 745 748 // and save as MPQC configuration 746 749 if (ConfigFileName != NULL) … … 753 756 else 754 757 cout << "failed." << endl; 755 758 756 759 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) { 757 760 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl; … … 785 788 int argptr; 786 789 PathToDatabases = LocalPath; 787 790 788 791 if (argc > 1) { // config file specified as option 789 792 // 1. : Parse options that just set variables or print help … … 798 801 case '?': 799 802 cout << "MoleCuilder suite" << endl << "==================" << endl << endl; 800 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl; 803 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl; 801 804 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl; 802 805 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl; 806 cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl; 803 807 cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl; 804 808 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl; … … 812 816 cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl; 813 817 cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl; 814 cout << "\t-o\tGet volume of the convex envelope (and store to tecplot file)." << endl; 818 cout << "\t-N\tGet non-convex-envelope." << endl; 819 cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl; 815 820 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl; 816 821 cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl; 817 822 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl; 818 823 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl; 819 cout << "\t-T <file> Store temperatures from the config file in <file>." << endl; 824 cout << "\t-T <file> Store temperatures from the config file in <file>." << endl; 820 825 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl; 821 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl; 826 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl; 822 827 cout << "\t-v/-V\t\tGives version information." << endl; 823 828 cout << "Note: config files must not begin with '-' !" << endl; … … 854 859 argptr++; 855 860 } while (argptr < argc); 856 861 857 862 // 2. Parse the element database 858 863 if (periode->LoadPeriodentafel(PathToDatabases)) { … … 863 868 return 1; 864 869 } 865 870 866 871 // 3. Find config file name and parse if possible 867 872 if (argv[1][0] != '-') { … … 902 907 } else 903 908 config_present = absent; 904 909 905 910 // 4. parse again through options, now for those depending on elements db and config presence 906 911 argptr = 1; … … 946 951 config_present = present; 947 952 } else 948 cerr << Verbose(1) << "Could not find the specified element." << endl; 953 cerr << Verbose(1) << "Could not find the specified element." << endl; 949 954 argptr+=4; 950 955 } … … 956 961 if (config_present == present) { 957 962 switch(argv[argptr-1][1]) { 958 case 'D': 963 case 'D': 959 964 ExitFlag = 1; 960 965 { … … 1002 1007 } 1003 1008 break; 1009 case 'A': 1010 ExitFlag = 1; 1011 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr][0] == '-')) { 1012 ExitFlag =255; 1013 cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl; 1014 } else { 1015 cout << "Parsing bonds from " << argv[argptr] << "." << endl; 1016 ifstream *input = new ifstream(argv[argptr]); 1017 mol->CreateAdjacencyList2((ofstream *)&cout, input); 1018 input->close(); 1019 } 1020 break; 1021 case 'N': 1022 ExitFlag = 1; 1023 if ((argptr+1 >= argc) || (argv[argptr+1][0] == '-')){ 1024 ExitFlag = 255; 1025 cerr << "Not enough or invalid arguments given for non-convex envelope: -o <radius> <tecplot output file>" << endl; 1026 } else { 1027 cout << Verbose(0) << "Evaluating npn-convex envelope."; 1028 string TempName(argv[argptr+1]); 1029 TempName.append(".r3d"); 1030 ofstream *output = new ofstream(TempName.c_str(), ios::trunc); 1031 cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl; 1032 Find_non_convex_border((ofstream *)&cout, output, mol, argv[argptr+1], atof(argv[argptr])); 1033 output->close(); 1034 delete(output); 1035 argptr+=2; 1036 } 1037 break; 1004 1038 case 'T': 1005 1039 ExitFlag = 1; … … 1168 1202 case 'o': 1169 1203 ExitFlag = 1; 1170 if ((argptr >= argc) || (argv[argptr][0] == '-')) 1204 if ((argptr >= argc) || (argv[argptr][0] == '-')){ 1171 1205 ExitFlag = 255; 1172 1206 cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl; 1173 1207 } else { 1174 1208 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 1209 ofstream *output = new ofstream(argv[argptr], ios::trunc); 1210 //$$$ 1175 1211 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl; 1176 ofstream *output = new ofstream(argv[argptr], ios::trunc);1177 1212 VolumeOfConvexEnvelope((ofstream *)&cout, output, &configuration, NULL, mol); 1178 1213 output->close(); … … 1269 1304 mol->Translate(&x); 1270 1305 } 1271 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1306 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1272 1307 } 1273 1308 } … … 1332 1367 if (j == 1) return 0; // just for -v and -h options 1333 1368 if (j) return j; // something went wrong 1334 1369 1335 1370 // General stuff 1336 1371 if (mol->cell_size[0] == 0.) { … … 1346 1381 // now the main construction loop 1347 1382 cout << Verbose(0) << endl << "Now comes the real construction..." << endl; 1348 do { 1383 do { 1349 1384 cout << Verbose(0) << endl << endl; 1350 1385 cout << Verbose(0) << "============Element list=======================" << endl; … … 1365 1400 cout << Verbose(0) << "-----------------------------------------------" << endl; 1366 1401 cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl; 1367 cout << Verbose(0) << "i - realign molecule" << endl; 1368 cout << Verbose(0) << "m - mirror all molecules" << endl; 1402 cout << Verbose(0) << "i - realign molecule" << endl; 1403 cout << Verbose(0) << "m - mirror all molecules" << endl; 1369 1404 cout << Verbose(0) << "t - translate molecule by vector" << endl; 1370 1405 cout << Verbose(0) << "c - scale by unit transformation" << endl; … … 1377 1412 cout << Verbose(0) << "Input: "; 1378 1413 cin >> choice; 1379 1414 1380 1415 switch (choice) { 1381 1416 default: 1382 1417 case 'a': // add atom 1383 1418 AddAtoms(periode, mol); 1384 choice = 'a'; 1385 break; 1386 1419 choice = 'a'; 1420 break; 1421 1387 1422 case 'b': // scale a bond 1388 1423 cout << Verbose(0) << "Scaling bond length between two atoms." << endl; … … 1400 1435 } 1401 1436 //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: "; 1402 //second->Output(second->type->No, 1, (ofstream *)&cout); 1403 break; 1404 1405 case 'c': // unit scaling of the metric 1437 //second->Output(second->type->No, 1, (ofstream *)&cout); 1438 break; 1439 1440 case 'c': // unit scaling of the metric 1406 1441 cout << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl; 1407 1442 cout << Verbose(0) << "Enter three factors: "; … … 1414 1449 delete[](factor); 1415 1450 break; 1416 1451 1417 1452 case 'd': // duplicate the periodic cell along a given axis, given times 1418 1453 cout << Verbose(0) << "State the axis [(+-)123]: "; … … 1420 1455 cout << Verbose(0) << "State the factor: "; 1421 1456 cin >> faktor; 1422 1457 1423 1458 mol->CountAtoms((ofstream *)&cout); // recount atoms 1424 1459 if (mol->AtomCount != 0) { // if there is more than none … … 1461 1496 mol->Translate(&x); 1462 1497 } 1463 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1498 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1464 1499 } 1465 1500 break; 1466 1501 1467 1502 case 'e': // edit each field of the configuration 1468 1503 configuration.Edit(mol); 1469 1504 break; 1470 1505 1471 1506 case 'f': 1472 1507 FragmentAtoms(mol, &configuration); 1473 1508 break; 1474 1509 1475 1510 case 'g': // center the atoms 1476 1511 CenterAtoms(mol); 1477 1512 break; 1478 1479 case 'i': // align all atoms 1513 1514 case 'i': // align all atoms 1480 1515 AlignAtoms(periode, mol); 1481 1516 break; … … 1488 1523 MirrorAtoms(mol); 1489 1524 break; 1490 1525 1491 1526 case 'o': // create the connection matrix 1492 1527 { … … 1509 1544 } 1510 1545 break; 1511 1546 1512 1547 case 'p': // parse and XYZ file 1513 1548 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl; … … 1518 1553 break; 1519 1554 1520 case 'q': // quit 1521 break; 1522 1555 case 'q': // quit 1556 break; 1557 1523 1558 case 'r': // remove atom 1524 RemoveAtoms(mol); 1525 break; 1526 1559 RemoveAtoms(mol); 1560 break; 1561 1527 1562 case 's': // save to config file 1528 1563 SaveConfig(ConfigFileName, &configuration, periode, mol); … … 1530 1565 1531 1566 case 't': // translate all atoms 1532 cout << Verbose(0) << "Enter translation vector." << endl; 1567 cout << Verbose(0) << "Enter translation vector." << endl; 1533 1568 x.AskPosition(mol->cell_size,0); 1534 1569 mol->Translate((const Vector *)&x); 1535 1570 break; 1536 1571 1537 1572 case 'T': 1538 1573 testroutine(mol); 1539 1574 break; 1540 1575 1541 1576 case 'u': // change an atom's element 1542 1577 first = NULL; … … 1545 1580 cin >> Z; 1546 1581 } while ((first = mol->FindAtom(Z)) == NULL); 1547 cout << Verbose(0) << "New element by atomic number Z: "; 1582 cout << Verbose(0) << "New element by atomic number Z: "; 1548 1583 cin >> Z; 1549 1584 first->type = periode->FindElement(Z); 1550 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl; 1585 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl; 1551 1586 break; 1552 1587 }; 1553 1588 } while (choice != 'q'); 1554 1589 1555 1590 // save element data base 1556 1591 if (periode->StorePeriodentafel(ElementsFileName)) //ElementsFileName -
Property mode
changed from
-
src/config.cpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/datacreator.cpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/datacreator.hpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/defs.hpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/element.cpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/elements.db ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/graph.cpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/helpers.cpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/helpers.hpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/joiner.cpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/moleculelist.cpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
TabularUnified src/molecules.cpp ¶
-
Property mode
changed from
100644
to100755
r674220 ra98603 1 1 /** \file molecules.cpp 2 * 2 * 3 3 * Functions for the class molecule. 4 * 4 * 5 5 */ 6 6 … … 25 25 sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]); 26 26 } 27 27 28 28 return sum; 29 29 }; … … 34 34 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero. 35 35 */ 36 molecule::molecule(periodentafel *teil) 37 { 36 molecule::molecule(periodentafel *teil) 37 { 38 38 // init atom chain list 39 start = new atom; 39 start = new atom; 40 40 end = new atom; 41 start->father = NULL; 41 start->father = NULL; 42 42 end->father = NULL; 43 43 link(start,end); … … 46 46 last = new bond(start, end, 1, -1); 47 47 link(first,last); 48 // other stuff 48 // other stuff 49 49 MDSteps = 0; 50 last_atom = 0; 50 last_atom = 0; 51 51 elemente = teil; 52 52 AtomCount = 0; … … 67 67 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero. 68 68 */ 69 molecule::~molecule() 69 molecule::~molecule() 70 70 { 71 71 if (ListOfBondsPerAtom != NULL) … … 78 78 delete(last); 79 79 delete(end); 80 delete(start); 80 delete(start); 81 81 }; 82 82 83 83 /** Adds given atom \a *pointer from molecule list. 84 * Increases molecule::last_atom and gives last number to added atom and names it according to its element::abbrev and molecule::AtomCount 84 * Increases molecule::last_atom and gives last number to added atom and names it according to its element::abbrev and molecule::AtomCount 85 85 * \param *pointer allocated and set atom 86 86 * \return true - succeeded, false - atom not found in list 87 87 */ 88 88 bool molecule::AddAtom(atom *pointer) 89 { 89 { 90 90 if (pointer != NULL) { 91 pointer->sort = &pointer->nr; 91 pointer->sort = &pointer->nr; 92 92 pointer->nr = last_atom++; // increase number within molecule 93 93 AtomCount++; … … 106 106 return add(pointer, end); 107 107 } else 108 return false; 108 return false; 109 109 }; 110 110 … … 115 115 */ 116 116 atom * molecule::AddCopyAtom(atom *pointer) 117 { 117 { 118 118 if (pointer != NULL) { 119 119 atom *walker = new atom(); … … 122 122 walker->v.CopyVector(&pointer->v); // copy velocity 123 123 walker->FixedIon = pointer->FixedIon; 124 walker->sort = &walker->nr; 124 walker->sort = &walker->nr; 125 125 walker->nr = last_atom++; // increase number within molecule 126 126 walker->father = pointer; //->GetTrueFather(); … … 133 133 return walker; 134 134 } else 135 return NULL; 135 return NULL; 136 136 }; 137 137 … … 156 156 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that 157 157 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1. 158 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 158 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 159 159 * \f] 160 * as the coordination of all three atoms in the coordinate system of these three vectors: 160 * as the coordination of all three atoms in the coordinate system of these three vectors: 161 161 * \f$\pmatrix{d & f & 0}\f$, \f$\pmatrix{d & -0.5 \cdot f & g}\f$ and \f$\pmatrix{d & -0.5 \cdot f & -g}\f$. 162 * 162 * 163 163 * \param *out output stream for debugging 164 * \param *Bond pointer to bond between \a *origin and \a *replacement 165 * \param *TopOrigin son of \a *origin of upper level molecule (the atom added to this molecule as a copy of \a *origin) 164 * \param *Bond pointer to bond between \a *origin and \a *replacement 165 * \param *TopOrigin son of \a *origin of upper level molecule (the atom added to this molecule as a copy of \a *origin) 166 166 * \param *origin pointer to atom which acts as the origin for scaling the added hydrogen to correct bond length 167 167 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule … … 191 191 InBondvector.SubtractVector(&TopOrigin->x); 192 192 bondlength = InBondvector.Norm(); 193 193 194 194 // is greater than typical bond distance? Then we have to correct periodically 195 195 // the problem is not the H being out of the box, but InBondvector have the wrong direction 196 // due to TopReplacement or Origin being on the wrong side! 197 if (bondlength > BondDistance) { 196 // due to TopReplacement or Origin being on the wrong side! 197 if (bondlength > BondDistance) { 198 198 // *out << Verbose(4) << "InBondvector is: "; 199 199 // InBondvector.Output(out); … … 215 215 // *out << endl; 216 216 } // periodic correction finished 217 217 218 218 InBondvector.Normalize(); 219 219 // get typical bond length and store as scale factor for later … … 222 222 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 223 223 return false; 224 BondRescale = bondlength; 224 BondRescale = bondlength; 225 225 } else { 226 226 if (!IsAngstroem) … … 273 273 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 274 274 // *out << Verbose(3) << "Regarding the double bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") to be constructed: Taking " << FirstOtherAtom->Name << " and " << SecondOtherAtom->Name << " along with " << TopOrigin->Name << " to determine orthogonal plane." << endl; 275 275 276 276 // determine the plane of these two with the *origin 277 277 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x); … … 286 286 Orthovector1.Normalize(); 287 287 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl; 288 288 289 289 // create the two Hydrogens ... 290 290 FirstOtherAtom = new atom(); … … 318 318 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle)); 319 319 } 320 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 320 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 321 321 SecondOtherAtom->x.Scale(&BondRescale); 322 322 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl; 323 323 for(int i=NDIM;i--;) { // and make relative to origin atom 324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 325 325 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i]; 326 326 } … … 365 365 // *out << endl; 366 366 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1); 367 // *out << Verbose(3) << "Orthovector2: "; 367 // *out << Verbose(3) << "Orthovector2: "; 368 368 // Orthovector2.Output(out); 369 369 // *out << endl; 370 370 371 371 // create correct coordination for the three atoms 372 372 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.; // retrieve triple bond angle from database … … 380 380 factors[0] = d; 381 381 factors[1] = f; 382 factors[2] = 0.; 382 factors[2] = 0.; 383 383 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 384 384 factors[1] = -0.5*f; 385 factors[2] = g; 385 factors[2] = g; 386 386 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 387 factors[2] = -g; 387 factors[2] = -g; 388 388 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 389 389 … … 437 437 */ 438 438 bool molecule::AddXYZFile(string filename) 439 { 439 { 440 440 istringstream *input = NULL; 441 441 int NumberOfAtoms = 0; // atom number in xyz read … … 446 446 string line; // currently parsed line 447 447 double x[3]; // atom coordinates 448 448 449 449 xyzfile.open(filename.c_str()); 450 450 if (!xyzfile) … … 454 454 input = new istringstream(line); 455 455 *input >> NumberOfAtoms; 456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 457 457 getline(xyzfile,line,'\n'); // Read comment 458 458 cout << Verbose(1) << "Comment: " << line << endl; 459 459 460 460 if (MDSteps == 0) // no atoms yet present 461 461 MDSteps++; … … 491 491 xyzfile.close(); 492 492 delete(input); 493 return true; 493 return true; 494 494 }; 495 495 … … 503 503 atom *LeftAtom = NULL, *RightAtom = NULL; 504 504 atom *Walker = NULL; 505 505 506 506 // copy all atoms 507 507 Walker = start; … … 510 510 CurrentAtom = copy->AddCopyAtom(Walker); 511 511 } 512 512 513 513 // copy all bonds 514 514 bond *Binder = first; … … 534 534 copy->NoCyclicBonds++; 535 535 NewBond->Type = Binder->Type; 536 } 536 } 537 537 // correct fathers 538 538 Walker = copy->start; … … 551 551 copy->CreateListOfBondsPerAtom((ofstream *)&cout); 552 552 } 553 553 554 554 return copy; 555 555 }; … … 576 576 577 577 /** Remove bond from bond chain list. 578 * \todo Function not implemented yet 578 * \todo Function not implemented yet 579 579 * \param *pointer bond pointer 580 580 * \return true - bound found and removed, false - bond not found/removed … … 588 588 589 589 /** Remove every bond from bond chain list that atom \a *BondPartner is a constituent of. 590 * \todo Function not implemented yet 590 * \todo Function not implemented yet 591 591 * \param *BondPartner atom to be removed 592 592 * \return true - bounds found and removed, false - bonds not found/removed … … 621 621 Vector *min = new Vector; 622 622 Vector *max = new Vector; 623 623 624 624 // gather min and max for each axis 625 625 ptr = start->next; // start at first in list … … 667 667 { 668 668 Vector *min = new Vector; 669 669 670 670 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 671 671 atom *ptr = start->next; // start at first in list … … 683 683 } 684 684 } 685 // *out << Verbose(4) << "Maximum is "; 685 // *out << Verbose(4) << "Maximum is "; 686 686 // max->Output(out); 687 687 // *out << ", Minimum is "; … … 691 691 max->AddVector(min); 692 692 Translate(min); 693 } 693 } 694 694 delete(min); 695 695 // *out << Verbose(3) << "End of CenterEdge." << endl; 696 }; 696 }; 697 697 698 698 /** Centers the center of the atoms at (0,0,0). … … 704 704 int Num = 0; 705 705 atom *ptr = start->next; // start at first in list 706 706 707 707 for(int i=NDIM;i--;) // zero center vector 708 708 center->x[i] = 0.; 709 709 710 710 if (ptr != end) { //list not empty? 711 711 while (ptr->next != end) { // continue with second if present 712 712 ptr = ptr->next; 713 713 Num++; 714 center->AddVector(&ptr->x); 714 center->AddVector(&ptr->x); 715 715 } 716 716 center->Scale(-1./Num); // divide through total number (and sign for direction) 717 717 Translate(center); 718 718 } 719 }; 719 }; 720 720 721 721 /** Returns vector pointing to center of gravity. … … 729 729 Vector tmp; 730 730 double Num = 0; 731 731 732 732 a->Zero(); 733 733 … … 737 737 Num += 1.; 738 738 tmp.CopyVector(&ptr->x); 739 a->AddVector(&tmp); 739 a->AddVector(&tmp); 740 740 } 741 741 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 757 757 Vector tmp; 758 758 double Num = 0; 759 759 760 760 a->Zero(); 761 761 … … 766 766 tmp.CopyVector(&ptr->x); 767 767 tmp.Scale(ptr->type->mass); // scale by mass 768 a->AddVector(&tmp); 768 a->AddVector(&tmp); 769 769 } 770 770 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 789 789 Translate(center); 790 790 } 791 }; 791 }; 792 792 793 793 /** Scales all atoms by \a *factor. … … 803 803 Trajectories[ptr].R.at(j).Scale(factor); 804 804 ptr->x.Scale(factor); 805 } 806 }; 807 808 /** Translate all atoms by given vector. 805 } 806 }; 807 808 /** Translate all atoms by given vector. 809 809 * \param trans[] translation vector. 810 810 */ … … 818 818 Trajectories[ptr].R.at(j).Translate(trans); 819 819 ptr->x.Translate(trans); 820 } 821 }; 822 823 /** Mirrors all atoms against a given plane. 820 } 821 }; 822 823 /** Mirrors all atoms against a given plane. 824 824 * \param n[] normal vector of mirror plane. 825 825 */ … … 833 833 Trajectories[ptr].R.at(j).Mirror(n); 834 834 ptr->x.Mirror(n); 835 } 835 } 836 836 }; 837 837 … … 847 847 bool flag; 848 848 Vector Testvector, Translationvector; 849 849 850 850 do { 851 851 Center.Zero(); … … 863 863 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 864 864 for (int j=0;j<NDIM;j++) { 865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 866 866 if ((fabs(tmp)) > BondDistance) { 867 867 flag = false; … … 879 879 cout << Verbose(1) << "vector is: "; 880 880 Testvector.Output((ofstream *)&cout); 881 cout << endl; 881 cout << endl; 882 882 #ifdef ADDHYDROGEN 883 883 // now also change all hydrogens … … 892 892 cout << Verbose(1) << "Hydrogen vector is: "; 893 893 Testvector.Output((ofstream *)&cout); 894 cout << endl; 894 cout << endl; 895 895 } 896 896 } … … 914 914 915 915 CenterGravity(out, CenterOfGravity); 916 917 // reset inertia tensor 916 917 // reset inertia tensor 918 918 for(int i=0;i<NDIM*NDIM;i++) 919 919 InertiaTensor[i] = 0.; 920 920 921 921 // sum up inertia tensor 922 922 while (ptr->next != end) { … … 943 943 } 944 944 *out << endl; 945 945 946 946 // diagonalize to determine principal axis system 947 947 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM); … … 952 952 gsl_eigen_symmv_free(T); 953 953 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); 954 954 955 955 for(int i=0;i<NDIM;i++) { 956 956 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i); 957 957 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl; 958 958 } 959 959 960 960 // check whether we rotate or not 961 961 if (DoRotate) { 962 *out << Verbose(1) << "Transforming molecule into PAS ... "; 962 *out << Verbose(1) << "Transforming molecule into PAS ... "; 963 963 // the eigenvectors specify the transformation matrix 964 964 ptr = start; … … 972 972 973 973 // summing anew for debugging (resulting matrix has to be diagonal!) 974 // reset inertia tensor 974 // reset inertia tensor 975 975 for(int i=0;i<NDIM*NDIM;i++) 976 976 InertiaTensor[i] = 0.; 977 977 978 978 // sum up inertia tensor 979 979 ptr = start; … … 1002 1002 *out << endl; 1003 1003 } 1004 1004 1005 1005 // free everything 1006 1006 delete(CenterOfGravity); … … 1031 1031 1032 1032 CountElements(); // make sure ElementsInMolecule is up to date 1033 1033 1034 1034 // check file 1035 1035 if (input == NULL) { … … 1087 1087 Trajectories[walker].U.at(MDSteps).x[d] += 0.5*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d]+Trajectories[walker].F.at(MDSteps).x[d])/IonMass; 1088 1088 } 1089 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1089 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1090 1090 // for (int d=0;d<NDIM;d++) 1091 1091 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step … … 1121 1121 MDSteps++; 1122 1122 1123 1123 1124 1124 // exit 1125 1125 return true; 1126 1126 }; 1127 1127 1128 /** Align all atoms in such a manner that given vector \a *n is along z axis. 1128 /** Align all atoms in such a manner that given vector \a *n is along z axis. 1129 1129 * \param n[] alignment vector. 1130 1130 */ … … 1145 1145 ptr = ptr->next; 1146 1146 tmp = ptr->x.x[0]; 1147 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1147 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1148 1148 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1149 1149 for (int j=0;j<MDSteps;j++) { 1150 1150 tmp = Trajectories[ptr].R.at(j).x[0]; 1151 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1151 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1152 1152 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1153 1153 } 1154 } 1154 } 1155 1155 // rotate n vector 1156 1156 tmp = n->x[0]; … … 1160 1160 n->Output((ofstream *)&cout); 1161 1161 cout << endl; 1162 1162 1163 1163 // rotate on z-y plane 1164 1164 ptr = start; … … 1168 1168 ptr = ptr->next; 1169 1169 tmp = ptr->x.x[1]; 1170 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1170 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1171 1171 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1172 1172 for (int j=0;j<MDSteps;j++) { 1173 1173 tmp = Trajectories[ptr].R.at(j).x[1]; 1174 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1174 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1175 1175 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1176 1176 } 1177 } 1177 } 1178 1178 // rotate n vector (for consistency check) 1179 1179 tmp = n->x[1]; 1180 1180 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1181 1181 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1182 1182 1183 1183 cout << Verbose(1) << "alignment vector after second rotation: "; 1184 1184 n->Output((ofstream *)&cout); … … 1191 1191 * \return true - succeeded, false - atom not found in list 1192 1192 */ 1193 bool molecule::RemoveAtom(atom *pointer) 1194 { 1193 bool molecule::RemoveAtom(atom *pointer) 1194 { 1195 1195 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1196 1196 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1197 1197 else 1198 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1198 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1199 1199 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1200 1200 ElementCount--; … … 1206 1206 * \return true - succeeded, false - atom not found in list 1207 1207 */ 1208 bool molecule::CleanupMolecule() 1209 { 1210 return (cleanup(start,end) && cleanup(first,last)); 1208 bool molecule::CleanupMolecule() 1209 { 1210 return (cleanup(start,end) && cleanup(first,last)); 1211 1211 }; 1212 1212 … … 1222 1222 } else { 1223 1223 cout << Verbose(0) << "Atom not found in list." << endl; 1224 return NULL; 1224 return NULL; 1225 1225 } 1226 1226 }; … … 1271 1271 struct lsq_params *par = (struct lsq_params *)params; 1272 1272 atom *ptr = par->mol->start; 1273 1273 1274 1274 // initialize vectors 1275 1275 a.x[0] = gsl_vector_get(x,0); … … 1301 1301 { 1302 1302 int np = 6; 1303 1303 1304 1304 const gsl_multimin_fminimizer_type *T = 1305 1305 gsl_multimin_fminimizer_nmsimplex; … … 1307 1307 gsl_vector *ss; 1308 1308 gsl_multimin_function minex_func; 1309 1309 1310 1310 size_t iter = 0, i; 1311 1311 int status; 1312 1312 double size; 1313 1313 1314 1314 /* Initial vertex size vector */ 1315 1315 ss = gsl_vector_alloc (np); 1316 1316 1317 1317 /* Set all step sizes to 1 */ 1318 1318 gsl_vector_set_all (ss, 1.0); 1319 1319 1320 1320 /* Starting point */ 1321 1321 par->x = gsl_vector_alloc (np); 1322 1322 par->mol = this; 1323 1323 1324 1324 gsl_vector_set (par->x, 0, 0.0); // offset 1325 1325 gsl_vector_set (par->x, 1, 0.0); … … 1328 1328 gsl_vector_set (par->x, 4, 0.0); 1329 1329 gsl_vector_set (par->x, 5, 1.0); 1330 1330 1331 1331 /* Initialize method and iterate */ 1332 1332 minex_func.f = &LeastSquareDistance; 1333 1333 minex_func.n = np; 1334 1334 minex_func.params = (void *)par; 1335 1335 1336 1336 s = gsl_multimin_fminimizer_alloc (T, np); 1337 1337 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1338 1338 1339 1339 do 1340 1340 { 1341 1341 iter++; 1342 1342 status = gsl_multimin_fminimizer_iterate(s); 1343 1343 1344 1344 if (status) 1345 1345 break; 1346 1346 1347 1347 size = gsl_multimin_fminimizer_size (s); 1348 1348 status = gsl_multimin_test_size (size, 1e-2); 1349 1349 1350 1350 if (status == GSL_SUCCESS) 1351 1351 { 1352 1352 printf ("converged to minimum at\n"); 1353 1353 } 1354 1354 1355 1355 printf ("%5d ", (int)iter); 1356 1356 for (i = 0; i < (size_t)np; i++) … … 1361 1361 } 1362 1362 while (status == GSL_CONTINUE && iter < 100); 1363 1363 1364 1364 for (i=0;i<(size_t)np;i++) 1365 1365 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); … … 1378 1378 int ElementNo, AtomNo; 1379 1379 CountElements(); 1380 1380 1381 1381 if (out == NULL) { 1382 1382 return false; … … 1413 1413 int ElementNo, AtomNo; 1414 1414 CountElements(); 1415 1415 1416 1416 if (out == NULL) { 1417 1417 return false; … … 1460 1460 atom *Walker = start; 1461 1461 while (Walker->next != end) { 1462 Walker = Walker->next; 1462 Walker = Walker->next; 1463 1463 #ifdef ADDHYDROGEN 1464 1464 if (Walker->type->Z != 1) { // regard only non-hydrogen … … 1491 1491 int No = 0; 1492 1492 time_t now; 1493 1493 1494 1494 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1495 1495 walker = start; … … 1518 1518 { 1519 1519 atom *walker = NULL; 1520 int No = 0;1520 int AtomNo = 0, ElementNo; 1521 1521 time_t now; 1522 1522 element *runner = NULL; 1523 1523 1524 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1524 1525 walker = start; 1525 1526 while (walker->next != end) { // go through every atom and count 1526 1527 walker = walker->next; 1527 No++;1528 AtomNo++; 1528 1529 } 1529 1530 if (out != NULL) { 1530 *out << No << "\n\tCreated by molecuilder on " << ctime(&now); 1531 walker = start; 1532 while (walker->next != end) { // go through every atom of this element 1533 walker = walker->next; 1534 walker->OutputXYZLine(out); 1531 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now); 1532 ElementNo = 0; 1533 runner = elemente->start; 1534 while (runner->next != elemente->end) { // go through every element 1535 runner = runner->next; 1536 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1537 ElementNo++; 1538 walker = start; 1539 while (walker->next != end) { // go through every atom of this element 1540 walker = walker->next; 1541 if (walker->type == runner) { // if this atom fits to element 1542 walker->OutputXYZLine(out); 1543 } 1544 } 1545 } 1535 1546 } 1536 1547 return true; … … 1563 1574 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 1564 1575 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 1565 NoNonHydrogen++; 1576 NoNonHydrogen++; 1566 1577 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 1567 1578 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); … … 1571 1582 } 1572 1583 } else 1573 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1584 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1574 1585 } 1575 1586 }; … … 1583 1594 ElementsInMolecule[i] = 0; 1584 1595 ElementCount = 0; 1585 1596 1586 1597 atom *walker = start; 1587 1598 while (walker->next != end) { … … 1619 1630 Binder = Binder->next; 1620 1631 if (Binder->Cyclic) 1621 No++; 1632 No++; 1622 1633 } 1623 1634 delete(BackEdgeStack); … … 1677 1688 1678 1689 /** Creates an adjacency list of the molecule. 1690 * We obtain an outside file with the indices of atoms which are bondmembers. 1691 */ 1692 void molecule::CreateAdjacencyList2(ofstream *out, ifstream *input) 1693 { 1694 1695 // 1 We will parse bonds out of the dbond file created by tremolo. 1696 int atom1, atom2, temp; 1697 atom *Walker, *OtherWalker; 1698 1699 if (!input) 1700 { 1701 cout << Verbose(1) << "Opening silica failed \n"; 1702 }; 1703 1704 *input >> ws >> atom1; 1705 *input >> ws >> atom2; 1706 cout << Verbose(1) << "Scanning file\n"; 1707 while (!input->eof()) // Check whether we read everything already 1708 { 1709 *input >> ws >> atom1; 1710 *input >> ws >> atom2; 1711 if(atom2<atom1) //Sort indices of atoms in order 1712 { 1713 temp=atom1; 1714 atom1=atom2; 1715 atom2=temp; 1716 }; 1717 1718 Walker=start; 1719 while(Walker-> nr != atom1) // Find atom corresponding to first index 1720 { 1721 Walker = Walker->next; 1722 }; 1723 OtherWalker = Walker->next; 1724 while(OtherWalker->nr != atom2) // Find atom corresponding to second index 1725 { 1726 OtherWalker= OtherWalker->next; 1727 }; 1728 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices. 1729 1730 } 1731 1732 CreateListOfBondsPerAtom(out); 1733 1734 }; 1735 1736 1737 /** Creates an adjacency list of the molecule. 1679 1738 * Generally, we use the CSD approach to bond recognition, that is the the distance 1680 1739 * between two atoms A and B must be within [Rcov(A)+Rcov(B)-t,Rcov(A)+Rcov(B)+t] with 1681 * a threshold t = 0.4 Angstroem. 1740 * a threshold t = 0.4 Angstroem. 1682 1741 * To make it O(N log N) the function uses the linked-cell technique as follows: 1683 1742 * The procedure is step-wise: … … 1696 1755 void molecule::CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem) 1697 1756 { 1757 1698 1758 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 1699 1759 int No, NoBonds, CandidateBondNo; … … 1704 1764 Vector x; 1705 1765 int FalseBondDegree = 0; 1706 1766 1707 1767 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 1708 1768 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; … … 1711 1771 cleanup(first,last); 1712 1772 } 1713 1773 1714 1774 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 1715 1775 CountAtoms(out); … … 1730 1790 for (int i=NumberCells;i--;) 1731 1791 CellList[i] = NULL; 1732 1792 1733 1793 // 2b. put all atoms into its corresponding list 1734 1794 Walker = start; … … 1751 1811 if (CellList[index] == NULL) // allocate molecule if not done 1752 1812 CellList[index] = new molecule(elemente); 1753 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1754 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 1813 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1814 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 1755 1815 } 1756 1816 //for (int i=0;i<NumberCells;i++) 1757 1817 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 1758 1818 1819 1759 1820 // 3a. go through every cell 1760 1821 for (N[0]=divisor[0];N[0]--;) … … 1769 1830 Walker = Walker->next; 1770 1831 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 1771 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1832 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1772 1833 for (n[0]=-1;n[0]<=1;n[0]++) 1773 1834 for (n[1]=-1;n[1]<=1;n[1]++) … … 1801 1862 } 1802 1863 } 1864 1865 1866 1803 1867 // 4. free the cell again 1804 1868 for (int i=NumberCells;i--;) … … 1807 1871 } 1808 1872 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 1809 1873 1810 1874 // create the adjacency list per atom 1811 1875 CreateListOfBondsPerAtom(out); 1812 1876 1813 1877 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 1814 1878 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene … … 1859 1923 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 1860 1924 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 1861 1925 1862 1926 // output bonds for debugging (if bond chain list was correctly installed) 1863 1927 *out << Verbose(1) << endl << "From contents of bond chain list:"; … … 1869 1933 *out << endl; 1870 1934 } else 1871 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1935 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1872 1936 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 1873 1937 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 1874 }; 1938 1939 }; 1940 1941 1875 1942 1876 1943 /** Performs a Depth-First search on this molecule. … … 1893 1960 bond *Binder = NULL; 1894 1961 bool BackStepping = false; 1895 1962 1896 1963 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 1897 1964 1898 1965 ResetAllBondsToUnused(); 1899 1966 ResetAllAtomNumbers(); … … 1908 1975 LeafWalker->Leaf = new molecule(elemente); 1909 1976 LeafWalker->Leaf->AddCopyAtom(Root); 1910 1977 1911 1978 OldGraphNr = CurrentGraphNr; 1912 1979 Walker = Root; … … 1919 1986 AtomStack->Push(Walker); 1920 1987 CurrentGraphNr++; 1921 } 1988 } 1922 1989 do { // (3) if Walker has no unused egdes, go to (5) 1923 1990 BackStepping = false; // reset backstepping flag for (8) … … 1953 2020 Binder = NULL; 1954 2021 } while (1); // (2) 1955 2022 1956 2023 // if we came from backstepping, yet there were no more unused bonds, we end up here with no Ancestor, because Walker is Root! Then we are finished! 1957 2024 if ((Walker == Root) && (Binder == NULL)) 1958 2025 break; 1959 1960 // (5) if Ancestor of Walker is ... 2026 2027 // (5) if Ancestor of Walker is ... 1961 2028 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 1962 2029 if (Walker->Ancestor->GraphNr != Root->GraphNr) { … … 2001 2068 } while (OtherAtom != Walker); 2002 2069 ComponentNumber++; 2003 2070 2004 2071 // (11) Root is separation vertex, set Walker to Root and go to (4) 2005 2072 Walker = Root; … … 2014 2081 2015 2082 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2016 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2083 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2017 2084 LeafWalker->Leaf->Output(out); 2018 2085 *out << endl; … … 2022 2089 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2023 2090 if (Root->GraphNr != -1) // if already discovered, step on 2024 Root = Root->next; 2091 Root = Root->next; 2025 2092 } 2026 2093 } … … 2044 2111 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2045 2112 } 2046 2113 2047 2114 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2048 2115 Binder = first; … … 2055 2122 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2056 2123 OutputComponentNumber(out, Binder->rightatom); 2057 *out << ">." << endl; 2124 *out << ">." << endl; 2058 2125 if (Binder->Cyclic) // cyclic ?? 2059 2126 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; … … 2070 2137 * the other our initial Walker - and do a Breadth First Search for the Root. We mark down each Predecessor and as soon as 2071 2138 * we have found the Root via BFS, we may climb back the closed cycle via the Predecessors. Thereby we mark atoms and bonds 2072 * as cyclic and print out the cycles. 2139 * as cyclic and print out the cycles. 2073 2140 * \param *out output stream for debugging 2074 2141 * \param *BackEdgeStack stack with all back edges found during DFS scan. Beware: This stack contains the bonds from the total molecule, not from the subgraph! … … 2081 2148 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2082 2149 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2083 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2150 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2084 2151 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2085 2152 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; … … 2093 2160 ColorList[i] = white; 2094 2161 } 2095 2162 2096 2163 *out << Verbose(1) << "Back edge list - "; 2097 2164 BackEdgeStack->Output(out); 2098 2165 2099 2166 *out << Verbose(1) << "Analysing cycles ... " << endl; 2100 2167 NumCycles = 0; … … 2102 2169 BackEdge = BackEdgeStack->PopFirst(); 2103 2170 // this is the target 2104 Root = BackEdge->leftatom; 2171 Root = BackEdge->leftatom; 2105 2172 // this is the source point 2106 Walker = BackEdge->rightatom; 2173 Walker = BackEdge->rightatom; 2107 2174 ShortestPathList[Walker->nr] = 0; 2108 2175 BFSStack->ClearStack(); // start with empty BFS stack … … 2118 2185 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2119 2186 OtherAtom = Binder->GetOtherAtom(Walker); 2120 #ifdef ADDHYDROGEN 2187 #ifdef ADDHYDROGEN 2121 2188 if (OtherAtom->type->Z != 1) { 2122 2189 #endif … … 2127 2194 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2128 2195 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2129 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 2196 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 2130 2197 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2131 2198 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; … … 2137 2204 if (OtherAtom == Root) 2138 2205 break; 2139 #ifdef ADDHYDROGEN 2206 #ifdef ADDHYDROGEN 2140 2207 } else { 2141 2208 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; … … 2175 2242 } 2176 2243 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2177 2244 2178 2245 if (OtherAtom == Root) { 2179 2246 // now climb back the predecessor list and thus find the cycle members … … 2203 2270 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2204 2271 } 2205 2272 2206 2273 // now clean the lists 2207 2274 while (!TouchedStack->IsEmpty()){ … … 2213 2280 } 2214 2281 if (MinRingSize != -1) { 2215 // go over all atoms 2282 // go over all atoms 2216 2283 Root = start; 2217 2284 while(Root->next != end) { 2218 2285 Root = Root->next; 2219 2286 2220 2287 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2221 2288 Walker = Root; … … 2254 2321 } 2255 2322 ColorList[Walker->nr] = black; 2256 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2323 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2257 2324 } 2258 2325 2259 2326 // now clean the lists 2260 2327 while (!TouchedStack->IsEmpty()){ … … 2305 2372 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2306 2373 { 2307 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2374 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2308 2375 *out << vertex->ComponentNr[i] << " "; 2309 2376 }; … … 2383 2450 { 2384 2451 int c = 0; 2385 int FragmentCount; 2452 int FragmentCount; 2386 2453 // get maximum bond degree 2387 2454 atom *Walker = start; … … 2393 2460 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 2394 2461 return FragmentCount; 2395 }; 2462 }; 2396 2463 2397 2464 /** Scans a single line for number and puts them into \a KeySet. 2398 2465 * \param *out output stream for debugging 2399 2466 * \param *buffer buffer to scan 2400 * \param &CurrentSet filled KeySet on return 2467 * \param &CurrentSet filled KeySet on return 2401 2468 * \return true - at least one valid atom id parsed, false - CurrentSet is empty 2402 2469 */ … … 2406 2473 int AtomNr; 2407 2474 int status = 0; 2408 2475 2409 2476 line.str(buffer); 2410 2477 while (!line.eof()) { … … 2442 2509 double TEFactor; 2443 2510 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 2444 2511 2445 2512 if (FragmentList == NULL) { // check list pointer 2446 2513 FragmentList = new Graph; 2447 2514 } 2448 2515 2449 2516 // 1st pass: open file and read 2450 2517 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; … … 2475 2542 status = false; 2476 2543 } 2477 2544 2478 2545 // 2nd pass: open TEFactors file and read 2479 2546 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; … … 2487 2554 InputFile >> TEFactor; 2488 2555 (*runner).second.second = TEFactor; 2489 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2556 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2490 2557 } else { 2491 2558 status = false; … … 2528 2595 if(output != NULL) { 2529 2596 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 2530 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2597 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2531 2598 if (sprinter != (*runner).first.begin()) 2532 2599 output << "\t"; … … 2594 2661 status = false; 2595 2662 } 2596 2663 2597 2664 return status; 2598 2665 }; … … 2603 2670 * \param **ListOfAtoms allocated (molecule::AtomCount) and filled lookup table for ids (Atom::nr) to *Atom 2604 2671 * \return true - structure is equal, false - not equivalence 2605 */ 2672 */ 2606 2673 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 2607 2674 { … … 2610 2677 bool status = true; 2611 2678 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2612 2679 2613 2680 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2614 2681 File.open(filename.str().c_str(), ios::out); … … 2669 2736 *out << endl; 2670 2737 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2671 2738 2672 2739 return status; 2673 2740 }; … … 2691 2758 for(int i=AtomCount;i--;) 2692 2759 AtomMask[i] = false; 2693 2760 2694 2761 if (Order < 0) { // adaptive increase of BondOrder per site 2695 2762 if (AtomMask[AtomCount] == true) // break after one step … … 2731 2798 line >> ws >> Value; // skip time entry 2732 2799 line >> ws >> Value; 2733 No -= 1; // indices start at 1 in file, not 0 2800 No -= 1; // indices start at 1 in file, not 0 2734 2801 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 2735 2802 … … 2740 2807 // as the smallest number in each set has always been the root (we use global id to keep the doubles away), seek smallest and insert into AtomMask 2741 2808 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 2742 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2809 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2743 2810 if (!InsertedElement.second) { // this root is already present 2744 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2745 //if ((*PresentItem).second.first < (*runner).first) // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase) 2811 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2812 //if ((*PresentItem).second.first < (*runner).first) // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase) 2746 2813 { // if value is smaller, update value and order 2747 2814 (*PresentItem).second.first = fabs(Value); … … 2781 2848 Walker = FindAtom(No); 2782 2849 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 2783 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2850 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2784 2851 AtomMask[No] = true; 2785 2852 status = true; 2786 2853 //} else 2787 //*out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->nr] << " does not allow further adaptive increase." << endl; 2854 //*out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->nr] << " does not allow further adaptive increase." << endl; 2788 2855 } 2789 2856 // close and done … … 2819 2886 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 2820 2887 status = true; 2821 2888 2822 2889 if (!status) { 2823 2890 if (Order == 0) … … 2827 2894 } 2828 2895 } 2829 2896 2830 2897 // print atom mask for debugging 2831 2898 *out << " "; … … 2836 2903 *out << (AtomMask[i] ? "t" : "f"); 2837 2904 *out << endl; 2838 2905 2839 2906 return status; 2840 2907 }; … … 2850 2917 int AtomNo = 0; 2851 2918 atom *Walker = NULL; 2852 2919 2853 2920 if (SortIndex != NULL) { 2854 2921 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; … … 2908 2975 atom **ListOfAtoms = NULL; 2909 2976 atom ***ListOfLocalAtoms = NULL; 2910 bool *AtomMask = NULL; 2911 2977 bool *AtomMask = NULL; 2978 2912 2979 *out << endl; 2913 2980 #ifdef ADDHYDROGEN … … 2918 2985 2919 2986 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 2920 2987 2921 2988 // ===== 1. Check whether bond structure is same as stored in files ==== 2922 2989 2923 2990 // fill the adjacency list 2924 2991 CreateListOfBondsPerAtom(out); … … 2926 2993 // create lookup table for Atom::nr 2927 2994 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 2928 2995 2929 2996 // === compare it with adjacency file === 2930 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 2997 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 2931 2998 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 2932 2999 … … 2957 3024 delete(LocalBackEdgeStack); 2958 3025 } 2959 3026 2960 3027 // ===== 3. if structure still valid, parse key set file and others ===== 2961 3028 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); … … 2963 3030 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 2964 3031 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 2965 2966 // =================================== Begin of FRAGMENTATION =============================== 2967 // ===== 6a. assign each keyset to its respective subgraph ===== 3032 3033 // =================================== Begin of FRAGMENTATION =============================== 3034 // ===== 6a. assign each keyset to its respective subgraph ===== 2968 3035 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 2969 3036 … … 2976 3043 FragmentationToDo = FragmentationToDo || CheckOrder; 2977 3044 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 2978 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3045 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 2979 3046 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 2980 3047 … … 3000 3067 delete(ParsedFragmentList); 3001 3068 delete[](MinimumRingSize); 3002 3069 3003 3070 3004 3071 // ==================================== End of FRAGMENTATION ============================================ … … 3006 3073 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3007 3074 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3008 3075 3009 3076 // free subgraph memory again 3010 3077 FragmentCounter = 0; … … 3031 3098 } 3032 3099 *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl; 3033 3100 3034 3101 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3035 3102 if (BondFragments->NumberOfMolecules != 0) { 3036 3103 // create the SortIndex from BFS labels to order in the config file 3037 3104 CreateMappingLabelsToConfigSequence(out, SortIndex); 3038 3105 3039 3106 *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl; 3040 3107 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) … … 3042 3109 else 3043 3110 *out << Verbose(1) << "Some config writing failed." << endl; 3044 3111 3045 3112 // store force index reference file 3046 3113 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3047 3048 // store keysets file 3114 3115 // store keysets file 3049 3116 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3050 3051 // store Adjacency file 3117 3118 // store Adjacency file 3052 3119 StoreAdjacencyToFile(out, configuration->configpath); 3053 3120 3054 3121 // store Hydrogen saturation correction file 3055 3122 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3056 3123 3057 3124 // store adaptive orders into file 3058 3125 StoreOrderAtSiteFile(out, configuration->configpath); 3059 3126 3060 3127 // restore orbital and Stop values 3061 3128 CalculateOrbitals(*configuration); 3062 3129 3063 3130 // free memory for bond part 3064 3131 *out << Verbose(1) << "Freeing bond memory" << endl; 3065 3132 delete(FragmentList); // remove bond molecule from memory 3066 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3133 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3067 3134 } else 3068 3135 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3069 //} else 3136 //} else 3070 3137 // *out << Verbose(1) << "No fragments to store." << endl; 3071 3138 *out << Verbose(0) << "End of bond fragmentation." << endl; … … 3093 3160 atom *Walker = NULL, *OtherAtom = NULL; 3094 3161 ReferenceStack->Push(Binder); 3095 3162 3096 3163 do { // go through all bonds and push local ones 3097 3164 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3098 if (Walker != NULL) // if this Walker exists in the subgraph ... 3165 if (Walker != NULL) // if this Walker exists in the subgraph ... 3099 3166 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds 3100 3167 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); … … 3109 3176 ReferenceStack->Push(Binder); 3110 3177 } while (FirstBond != Binder); 3111 3178 3112 3179 return status; 3113 3180 }; … … 3185 3252 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3186 3253 Walker->MaxOrder = MaxArray[Walker->nr]; 3187 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3254 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3188 3255 } 3189 3256 file.close(); … … 3196 3263 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3197 3264 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3198 3265 3199 3266 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3200 3267 return status; … … 3254 3321 Walker = start; 3255 3322 while (Walker->next != end) { 3256 Walker = Walker->next; 3323 Walker = Walker->next; 3257 3324 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: "; 3258 3325 TotalDegree = 0; … … 3262 3329 } 3263 3330 *out << " -- TotalDegree: " << TotalDegree << endl; 3264 } 3331 } 3265 3332 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3266 3333 }; … … 3268 3335 /** Adds atoms up to \a BondCount distance from \a *Root and notes them down in \a **AddedAtomList. 3269 3336 * Gray vertices are always enqueued in an StackClass<atom *> FIFO queue, the rest is usual BFS with adding vertices found was 3270 * white and putting into queue. 3337 * white and putting into queue. 3271 3338 * \param *out output stream for debugging 3272 3339 * \param *Mol Molecule class to add atoms to … … 3277 3344 * \param BondOrder maximum distance for vertices to add 3278 3345 * \param IsAngstroem lengths are in angstroem or bohrradii 3279 */ 3346 */ 3280 3347 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3281 3348 { … … 3303 3370 } 3304 3371 ShortestPathList[Root->nr] = 0; 3305 3372 3306 3373 // and go on ... Queue always contains all lightgray vertices 3307 3374 while (!AtomStack->IsEmpty()) { … … 3311 3378 // followed by n+1 till top of stack. 3312 3379 Walker = AtomStack->PopFirst(); // pop oldest added 3313 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3380 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3314 3381 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3315 3382 Binder = ListOfBondsPerAtom[Walker->nr][i]; … … 3318 3385 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3319 3386 if (ColorList[OtherAtom->nr] == white) { 3320 if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem) 3387 if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem) 3321 3388 ColorList[OtherAtom->nr] = lightgray; 3322 3389 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3323 3390 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3324 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 3391 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 3325 3392 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3326 3393 *out << Verbose(3); … … 3370 3437 // This has to be a cyclic bond, check whether it's present ... 3371 3438 if (AddedBondList[Binder->nr] == NULL) { 3372 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3439 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3373 3440 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3374 3441 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; … … 3385 3452 } 3386 3453 ColorList[Walker->nr] = black; 3387 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3454 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3388 3455 } 3389 3456 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); … … 3409 3476 3410 3477 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 3411 3478 3412 3479 // reset parent list 3413 3480 *out << Verbose(3) << "Resetting ParentList." << endl; 3414 3481 for (int i=Father->AtomCount;i--;) 3415 3482 ParentList[i] = NULL; 3416 3483 3417 3484 // fill parent list with sons 3418 3485 *out << Verbose(3) << "Filling Parent List." << endl; … … 3455 3522 * \param *&Leaf KeySet to look through 3456 3523 * \param *&ShortestPathList list of the shortest path to decide which atom to suggest as removal candidate in the end 3457 * \param index of the atom suggested for removal 3524 * \param index of the atom suggested for removal 3458 3525 */ 3459 3526 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) … … 3461 3528 atom *Runner = NULL; 3462 3529 int SP, Removal; 3463 3530 3464 3531 *out << Verbose(2) << "Looking for removal candidate." << endl; 3465 3532 SP = -1; //0; // not -1, so that Root is never removed … … 3479 3546 /** Stores a fragment from \a KeySet into \a molecule. 3480 3547 * First creates the minimal set of atoms from the KeySet, then creates the bond structure from the complete 3481 * molecule and adds missing hydrogen where bonds were cut. 3548 * molecule and adds missing hydrogen where bonds were cut. 3482 3549 * \param *out output stream for debugging messages 3483 * \param &Leaflet pointer to KeySet structure 3550 * \param &Leaflet pointer to KeySet structure 3484 3551 * \param IsAngstroem whether we have Ansgtroem or bohrradius 3485 3552 * \return pointer to constructed molecule … … 3492 3559 bool LonelyFlag = false; 3493 3560 int size; 3494 3561 3495 3562 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 3496 3563 3497 3564 Leaf->BondDistance = BondDistance; 3498 3565 for(int i=NDIM*2;i--;) 3499 Leaf->cell_size[i] = cell_size[i]; 3566 Leaf->cell_size[i] = cell_size[i]; 3500 3567 3501 3568 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) … … 3510 3577 size++; 3511 3578 } 3512 3579 3513 3580 // create the bonds between all: Make it an induced subgraph and add hydrogen 3514 3581 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; … … 3520 3587 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 3521 3588 // create all bonds 3522 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3589 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3523 3590 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 3524 3591 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 3525 3592 if (SonList[OtherFather->nr] != NULL) { 3526 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3593 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3527 3594 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 3528 3595 // *out << Verbose(3) << "Adding Bond: "; 3529 // *out << 3596 // *out << 3530 3597 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 3531 3598 // *out << "." << endl; 3532 3599 //NumBonds[Runner->nr]++; 3533 } else { 3600 } else { 3534 3601 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 3535 3602 } 3536 3603 LonelyFlag = false; 3537 3604 } else { 3538 // *out << ", who has no son in this fragment molecule." << endl; 3605 // *out << ", who has no son in this fragment molecule." << endl; 3539 3606 #ifdef ADDHYDROGEN 3540 3607 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; … … 3554 3621 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 3555 3622 Runner = Runner->next; 3556 #endif 3623 #endif 3557 3624 } 3558 3625 Leaf->CreateListOfBondsPerAtom(out); … … 3587 3654 StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself 3588 3655 StackClass<atom *> *SnakeStack = new StackClass<atom *>(Order+1); // equal to Order is not possible, as then the StackClass<atom *> cannot discern between full and empty stack! 3589 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 3656 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 3590 3657 MoleculeListClass *FragmentList = NULL; 3591 3658 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL; … … 3637 3704 // clear snake stack 3638 3705 SnakeStack->ClearStack(); 3639 //SnakeStack->TestImplementation(out, start->next); 3706 //SnakeStack->TestImplementation(out, start->next); 3640 3707 3641 3708 ///// INNER LOOP //////////// … … 3658 3725 } 3659 3726 if (ShortestPathList[Walker->nr] == -1) { 3660 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 3727 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 3661 3728 TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed 3662 3729 } … … 3696 3763 OtherAtom = Binder->GetOtherAtom(Walker); 3697 3764 if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us 3698 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 3765 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 3699 3766 //ColorVertexList[OtherAtom->nr] = lightgray; // mark as explored 3700 3767 } else { // otherwise check its colour and element 3701 3768 if ( 3702 3769 #ifdef ADDHYDROGEN 3703 (OtherAtom->type->Z != 1) && 3770 (OtherAtom->type->Z != 1) && 3704 3771 #endif 3705 3772 (ColorEdgeList[Binder->nr] == white)) { // skip hydrogen, look for unexplored vertices … … 3711 3778 //} else { 3712 3779 // *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl; 3713 //} 3780 //} 3714 3781 Walker = OtherAtom; 3715 3782 break; 3716 3783 } else { 3717 if (OtherAtom->type->Z == 1) 3784 if (OtherAtom->type->Z == 1) 3718 3785 *out << "Links to a hydrogen atom." << endl; 3719 else 3786 else 3720 3787 *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl; 3721 3788 } … … 3727 3794 *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl; 3728 3795 } 3729 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 3796 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 3730 3797 *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl; 3731 3798 ColorVertexList[Walker->nr] = black; … … 3734 3801 } 3735 3802 } while ((Walker != Root) || (ColorVertexList[Root->nr] != black)); 3736 *out << Verbose(2) << "Inner Looping is finished." << endl; 3803 *out << Verbose(2) << "Inner Looping is finished." << endl; 3737 3804 3738 3805 // if we reset all AtomCount atoms, we have again technically O(N^2) ... … … 3750 3817 } 3751 3818 } 3752 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 3819 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 3753 3820 3754 3821 // copy together 3755 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 3822 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 3756 3823 FragmentList = new MoleculeListClass(FragmentCounter, AtomCount); 3757 3824 RunningIndex = 0; … … 3824 3891 3825 3892 NumCombinations = 1 << SetDimension; 3826 3893 3827 3894 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 3828 3895 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 3829 3896 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 3830 3897 3831 3898 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 3832 3899 *out << Verbose(1+verbosity) << "We are " << RootDistance << " away from Root, which is " << *FragmentSearch->Root << ", SubOrder is " << SubOrder << ", SetDimension is " << SetDimension << " and this means " << NumCombinations-1 << " combination(s)." << endl; 3833 3900 3834 // initialised touched list (stores added atoms on this level) 3901 // initialised touched list (stores added atoms on this level) 3835 3902 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 3836 3903 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 3837 3904 TouchedList[TouchedIndex] = -1; 3838 3905 TouchedIndex = 0; 3839 3906 3840 3907 // create every possible combination of the endpieces 3841 3908 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; … … 3845 3912 for (int j=SetDimension;j--;) 3846 3913 bits += (i & (1 << j)) >> j; 3847 3914 3848 3915 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 3849 3916 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue … … 3853 3920 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 3854 3921 if (bit) { // if bit is set, we add this bond partner 3855 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3922 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3856 3923 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 3857 3924 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 3858 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3925 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3859 3926 if (TestKeySetInsert.second) { 3860 3927 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added … … 3869 3936 } 3870 3937 } 3871 3872 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3938 3939 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3873 3940 if (SpaceLeft > 0) { 3874 3941 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; … … 3898 3965 } 3899 3966 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 3900 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3967 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3901 3968 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 3902 3969 } … … 3907 3974 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 3908 3975 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3909 *out << (*runner) << " "; 3976 *out << (*runner) << " "; 3910 3977 *out << endl; 3911 3978 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) … … 3915 3982 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 3916 3983 } 3917 3984 3918 3985 // --3-- remove all added items in this level from snake stack 3919 3986 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; … … 3926 3993 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 3927 3994 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3928 *out << (*runner) << " "; 3995 *out << (*runner) << " "; 3929 3996 *out << endl; 3930 3997 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level … … 3933 4000 } 3934 4001 } 3935 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 4002 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 3936 4003 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 3937 4004 }; … … 3942 4009 * \return true - connected, false - disconnected 3943 4010 * \note this is O(n^2) for it's just a bug checker not meant for permanent use! 3944 */ 4011 */ 3945 4012 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 3946 4013 { … … 3948 4015 bool BondStatus = false; 3949 4016 int size; 3950 4017 3951 4018 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 3952 4019 *out << Verbose(2) << "Disconnected atom: "; 3953 4020 3954 4021 // count number of atoms in graph 3955 4022 size = 0; … … 3997 4064 * \param *out output stream for debugging 3998 4065 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation 3999 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4066 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4000 4067 * \param RestrictedKeySet Restricted vertex set to use in context of molecule 4001 4068 * \return number of inserted fragments 4002 4069 * \note ShortestPathList in FragmentSearch structure is probably due to NumberOfAtomsSPLevel and SP not needed anymore 4003 4070 */ 4004 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4071 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4005 4072 { 4006 4073 int SP, AtomKeyNr; … … 4023 4090 FragmentSearch.BondsPerSPCount[i] = 0; 4024 4091 FragmentSearch.BondsPerSPCount[0] = 1; 4025 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4092 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4026 4093 add(Binder, FragmentSearch.BondsPerSPList[1]); 4027 4094 4028 4095 // do a BFS search to fill the SP lists and label the found vertices 4029 4096 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 4030 4097 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 4031 4098 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 4032 // (EdgeinSPLevel) of this tree ... 4099 // (EdgeinSPLevel) of this tree ... 4033 4100 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 4034 4101 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. … … 4083 4150 } 4084 4151 } 4085 4152 4086 4153 // outputting all list for debugging 4087 4154 *out << Verbose(0) << "Printing all found lists." << endl; … … 4092 4159 Binder = Binder->next; 4093 4160 *out << Verbose(2) << *Binder << endl; 4094 } 4095 } 4096 4161 } 4162 } 4163 4097 4164 // creating fragments with the found edge sets (may be done in reverse order, faster) 4098 4165 SP = -1; // the Root <-> Root edge must be subtracted! … … 4101 4168 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4102 4169 Binder = Binder->next; 4103 SP ++; 4170 SP ++; 4104 4171 } 4105 4172 } … … 4108 4175 // start with root (push on fragment stack) 4109 4176 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4110 FragmentSearch.FragmentSet->clear(); 4177 FragmentSearch.FragmentSet->clear(); 4111 4178 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4112 4179 // prepare the subset and call the generator 4113 4180 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4114 4181 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4115 4182 4116 4183 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4117 4184 4118 4185 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4119 4186 } else { … … 4124 4191 // remove root from stack 4125 4192 *out << Verbose(0) << "Removing root again from stack." << endl; 4126 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4193 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4127 4194 4128 4195 // free'ing the bonds lists … … 4143 4210 } 4144 4211 4145 // return list 4212 // return list 4146 4213 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4147 4214 return (FragmentSearch.FragmentCounter - Counter); … … 4174 4241 // remove bonds that are beyond bonddistance 4175 4242 for(int i=NDIM;i--;) 4176 Translationvector.x[i] = 0.; 4243 Translationvector.x[i] = 0.; 4177 4244 // scan all bonds 4178 4245 Binder = first; … … 4221 4288 } 4222 4289 } 4223 // re-add bond 4290 // re-add bond 4224 4291 link(Binder, OtherBinder); 4225 4292 } else { … … 4275 4342 IteratorB++; 4276 4343 } // end of while loop 4277 }// end of check in case of equal sizes 4344 }// end of check in case of equal sizes 4278 4345 } 4279 4346 return false; // if we reach this point, they are equal … … 4319 4386 * \param graph1 first (dest) graph 4320 4387 * \param graph2 second (source) graph 4321 * \param *counter keyset counter that gets increased 4388 * \param *counter keyset counter that gets increased 4322 4389 */ 4323 4390 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) … … 4364 4431 int RootKeyNr, RootNr; 4365 4432 struct UniqueFragments FragmentSearch; 4366 4433 4367 4434 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 4368 4435 … … 4387 4454 Walker = Walker->next; 4388 4455 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 4389 } 4456 } 4390 4457 4391 4458 // this can easily be seen: if Order is 5, then the number of levels for each lower order is the total sum of the number of levels above, as … … 4401 4468 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 4402 4469 // *out << Verbose(0) << "Bond order " << Walker->GetTrueFather()->AdaptiveOrder << " of Root " << *Walker << " greater than or equal to Minimum Ring size of " << MinimumRingSize << " found is not allowed." << endl; 4403 //} else 4470 //} else 4404 4471 { 4405 4472 // increase adaptive order by one 4406 4473 Walker->GetTrueFather()->AdaptiveOrder++; 4407 4474 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 4408 4475 4409 4476 // initialise Order-dependent entries of UniqueFragments structure 4410 4477 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); … … 4413 4480 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 4414 4481 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 4415 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4482 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4416 4483 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 4417 4484 FragmentSearch.BondsPerSPCount[i] = 0; 4418 } 4419 4485 } 4486 4420 4487 // allocate memory for all lower level orders in this 1D-array of ptrs 4421 4488 NumLevels = 1 << (Order-1); // (int)pow(2,Order); … … 4423 4490 for (int i=0;i<NumLevels;i++) 4424 4491 FragmentLowerOrdersList[RootNr][i] = NULL; 4425 4492 4426 4493 // create top order where nothing is reduced 4427 4494 *out << Verbose(0) << "==============================================================================================================" << endl; 4428 4495 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 4429 4496 4430 4497 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 4431 4498 FragmentLowerOrdersList[RootNr][0] = new Graph; … … 4440 4507 // we don't have to dive into suborders! These keysets are all already created on lower orders! 4441 4508 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 4442 4509 4443 4510 // if ((NumLevels >> 1) > 0) { 4444 4511 // // create lower order fragments … … 4447 4514 // for (int source=0;source<(NumLevels >> 1);source++) { // 1-terms don't need any more splitting, that's why only half is gone through (shift again) 4448 4515 // // step down to next order at (virtual) boundary of powers of 2 in array 4449 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4516 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4450 4517 // Order--; 4451 4518 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; … … 4454 4521 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 4455 4522 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 4456 // 4523 // 4457 4524 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 4458 4525 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; … … 4485 4552 RootStack.push_back(RootKeyNr); // put back on stack 4486 4553 RootNr++; 4487 4554 4488 4555 // free Order-dependent entries of UniqueFragments structure for next loop cycle 4489 4556 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); … … 4491 4558 delete(FragmentSearch.BondsPerSPList[2*i]); 4492 4559 delete(FragmentSearch.BondsPerSPList[2*i+1]); 4493 } 4560 } 4494 4561 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4495 4562 } … … 4502 4569 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 4503 4570 delete(FragmentSearch.FragmentSet); 4504 4505 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4571 4572 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4506 4573 // 5433222211111111 4507 4574 // 43221111 … … 4523 4590 RootKeyNr = RootStack.front(); 4524 4591 RootStack.pop_front(); 4525 Walker = FindAtom(RootKeyNr); 4592 Walker = FindAtom(RootKeyNr); 4526 4593 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 4527 4594 for(int i=0;i<NumLevels;i++) { … … 4536 4603 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4537 4604 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4538 4605 4539 4606 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 4540 4607 }; … … 4570 4637 atom *Walker = NULL; 4571 4638 bool result = true; // status of comparison 4572 4573 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4639 4640 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4574 4641 /// first count both their atoms and elements and update lists thereby ... 4575 4642 //*out << Verbose(0) << "Counting atoms, updating list" << endl; … … 4618 4685 if (CenterOfGravity.Distance(&OtherCenterOfGravity) > threshold) { 4619 4686 *out << Verbose(4) << "Centers of gravity don't match." << endl; 4620 result = false; 4621 } 4622 } 4623 4687 result = false; 4688 } 4689 } 4690 4624 4691 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 4625 4692 if (result) { … … 4637 4704 OtherDistances[Walker->nr] = OtherCenterOfGravity.Distance(&Walker->x); 4638 4705 } 4639 4706 4640 4707 /// ... sort each list (using heapsort (o(N log N)) from GSL) 4641 4708 *out << Verbose(5) << "Sorting distances" << endl; … … 4648 4715 for(int i=AtomCount;i--;) 4649 4716 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 4650 4717 4651 4718 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 4652 4719 *out << Verbose(4) << "Comparing distances" << endl; … … 4659 4726 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 4660 4727 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4661 4728 4662 4729 /// free memory 4663 4730 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); … … 4667 4734 result = false; 4668 4735 } 4669 } 4736 } 4670 4737 /// return pointer to map if all distances were below \a threshold 4671 4738 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; … … 4676 4743 *out << Verbose(3) << "Result: Not equal." << endl; 4677 4744 return NULL; 4678 } 4745 } 4679 4746 }; 4680 4747 … … 4731 4798 * \param *output output stream of temperature file 4732 4799 * \return file written (true), failure on writing file (false) 4733 */ 4800 */ 4734 4801 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 4735 4802 { … … 4739 4806 if (output == NULL) 4740 4807 return false; 4741 else 4808 else 4742 4809 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 4743 4810 for (int step=startstep;step < endstep; step++) { // loop over all time steps -
Property mode
changed from
-
TabularUnified src/molecules.hpp ¶
-
Property mode
changed from
100644
to100755
r674220 ra98603 1 1 /** \file molecules.hpp 2 2 * 3 * Class definitions of atom and molecule, element and periodentafel 3 * Class definitions of atom and molecule, element and periodentafel 4 4 */ 5 5 … … 54 54 #define BoundariesTestPair pair< Boundaries::iterator, bool> 55 55 56 #define PointMap map < int, class BoundaryPointSet * > 57 #define PointPair pair < int, class BoundaryPointSet * > 58 #define PointTestPair pair < PointMap::iterator, bool > 59 60 #define LineMap map < int, class BoundaryLineSet * > 61 #define LinePair pair < int, class BoundaryLineSet * > 62 #define LineTestPair pair < Line Pair::iterator, bool >63 64 #define TriangleMap map < int, class BoundaryTriangleSet * > 65 #define TrianglePair pair < int, class BoundaryTriangleSet * > 66 #define TriangleTestPair pair < TrianglePair::iterator, bool > 56 #define PointMap map < int, class BoundaryPointSet * > 57 #define PointPair pair < int, class BoundaryPointSet * > 58 #define PointTestPair pair < PointMap::iterator, bool > 59 60 #define LineMap map < int, class BoundaryLineSet * > 61 #define LinePair pair < int, class BoundaryLineSet * > 62 #define LineTestPair pair < LineMap::iterator, bool > 63 64 #define TriangleMap map < int, class BoundaryTriangleSet * > 65 #define TrianglePair pair < int, class BoundaryTriangleSet * > 66 #define TriangleTestPair pair < TrianglePair::iterator, bool > 67 67 68 68 #define DistanceMultiMap multimap <double, pair < PointMap::iterator, PointMap::iterator> > … … 86 86 //bool operator < (KeySet SubgraphA, KeySet SubgraphB); //note: this declaration is important, otherwise normal < is used (producing wrong order) 87 87 inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment); // Insert a KeySet into a Graph 88 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter); // Insert all KeySet's in a Graph into another Graph 88 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter); // Insert all KeySet's in a Graph into another Graph 89 89 int CompareDoubles (const void * a, const void * b); 90 90 … … 140 140 unsigned char AdaptiveOrder; //!< current present bond order at site (0 means "not set") 141 141 bool MaxOrder; //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not 142 142 143 143 atom(); 144 144 ~atom(); 145 145 146 146 bool Output(int ElementNo, int AtomNo, ofstream *out) const; 147 147 bool OutputXYZLine(ofstream *out) const; 148 148 atom *GetTrueFather(); 149 149 bool Compare(atom &ptr); 150 150 151 151 private: 152 152 }; … … 169 169 int nr; //!< unique number in a molecule, updated by molecule::CreateAdjacencyList() 170 170 bool Cyclic; //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis() 171 enum EdgeType Type;//!< whether this is a tree or back edge 172 171 enum EdgeType Type;//!< whether this is a tree or back edge 172 173 173 atom * GetOtherAtom(atom *Atom) const; 174 174 bond * GetFirstBond(); 175 175 bond * GetLastBond(); 176 176 177 177 bool MarkUsed(enum Shading color); 178 178 enum Shading IsUsed(); … … 180 180 bool Contains(const atom *ptr); 181 181 bool Contains(const int nr); 182 182 183 183 bond(); 184 184 bond(atom *left, atom *right); … … 186 186 bond(atom *left, atom *right, int degree, int number); 187 187 ~bond(); 188 189 private: 188 189 private: 190 190 enum Shading Used; //!< marker in depth-first search, DepthFirstSearchAnalysis() 191 191 }; … … 218 218 int NoCyclicBonds; //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis() 219 219 double BondDistance; //!< typical bond distance used in CreateAdjacencyList() and furtheron 220 220 221 221 molecule(periodentafel *teil); 222 222 ~molecule(); 223 223 224 224 /// remove atoms from molecule. 225 225 bool AddAtom(atom *pointer); … … 230 230 atom * AddCopyAtom(atom *pointer); 231 231 bool AddXYZFile(string filename); 232 bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem); 232 bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem); 233 233 bond * AddBond(atom *first, atom *second, int degree); 234 234 bool RemoveBond(bond *pointer); 235 235 bool RemoveBonds(atom *BondPartner); 236 236 237 237 /// Find atoms. 238 atom * FindAtom(int Nr) const; 238 atom * FindAtom(int Nr) const; 239 239 atom * AskAtom(string text); 240 240 … … 244 244 void CalculateOrbitals(class config &configuration); 245 245 bool CenterInBox(ofstream *out, Vector *BoxLengths); 246 void CenterEdge(ofstream *out, Vector *max); 247 void CenterOrigin(ofstream *out, Vector *max); 246 void CenterEdge(ofstream *out, Vector *max); 247 void CenterOrigin(ofstream *out, Vector *max); 248 248 void CenterGravity(ofstream *out, Vector *max); 249 249 void Translate(const Vector *x); … … 260 260 double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem); 261 261 bool VerletForceIntegration(char *file, double delta_t, bool IsAngstroem); 262 262 263 263 bool CheckBounds(const Vector *x) const; 264 264 void GetAlignvector(struct lsq_params * par) const; 265 265 266 /// Initialising routines in fragmentation 266 /// Initialising routines in fragmentation 267 void CreateAdjacencyList2(ofstream *out, ifstream *output); 267 268 void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem); 268 269 void CreateListOfBondsPerAtom(ofstream *out); 269 270 270 271 // Graph analysis 271 272 MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack); … … 283 284 284 285 molecule *CopyMolecule(); 285 286 286 287 /// Fragment molecule by two different approaches: 287 288 int FragmentMolecule(ofstream *out, int Order, config *configuration); … … 305 306 int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList); 306 307 int GuesstimateFragmentCount(ofstream *out, int order); 307 308 // Recognize doubly appearing molecules in a list of them 308 309 // Recognize doubly appearing molecules in a list of them 309 310 int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold); 310 311 int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule); 311 312 312 313 // Output routines. 313 314 bool Output(ofstream *out); … … 330 331 int NumberOfMolecules; //!< Number of entries in \a **FragmentList and of to be returned one. 331 332 int NumberOfTopAtoms; //!< Number of atoms in the molecule from which all fragments originate 332 333 333 334 MoleculeListClass(); 334 335 MoleculeListClass(int Num, int NumAtoms); … … 340 341 bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex); 341 342 void Output(ofstream *out); 342 343 343 344 private: 344 345 }; … … 350 351 class MoleculeLeafClass { 351 352 public: 352 molecule *Leaf; //!< molecule of this leaf 353 molecule *Leaf; //!< molecule of this leaf 353 354 //MoleculeLeafClass *UpLeaf; //!< Leaf one level up 354 355 //MoleculeLeafClass *DownLeaf; //!< First leaf one level down … … 386 387 bool FastParsing; 387 388 double Deltat; 388 389 389 390 private: 390 391 char *mainname; 391 392 char *defaultpath; 392 393 char *pseudopotpath; 393 394 394 395 int DoOutVis; 395 396 int DoOutMes; … … 406 407 int UseAddGramSch; 407 408 int Seed; 408 409 409 410 int MaxOuterStep; 410 411 int OutVisStep; … … 414 415 int MaxPsiStep; 415 416 double EpsWannier; 416 417 417 418 int MaxMinStep; 418 419 double RelEpsTotalEnergy; … … 423 424 double InitRelEpsKineticEnergy; 424 425 int InitMaxMinGapStopStep; 425 426 426 427 //double BoxLength[NDIM*NDIM]; 427 428 428 429 double ECut; 429 430 int MaxLevel; … … 434 435 int RTActualUse; 435 436 int AddPsis; 436 437 437 438 double RCut; 438 439 int StructOpt; … … 441 442 int MaxTypes; 442 443 443 444 444 445 int ParseForParameter(int verbose, ifstream *file, const char *name, int sequential, int const xth, int const yth, int type, void *value, int repetition, int critical); 445 446 446 447 public: 447 448 config(); -
Property mode
changed from
-
src/orbitals.db ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/parser.cpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/parser.hpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
TabularUnified src/periodentafel.cpp ¶
-
Property mode
changed from
100644
to100755
r674220 ra98603 1 1 /** \file periodentafel.cpp 2 * 2 * 3 3 * Function implementations for the class periodentafel. 4 * 4 * 5 5 */ 6 6 … … 14 14 * Initialises start and end of list and resets periodentafel::checkliste to false. 15 15 */ 16 periodentafel::periodentafel() 17 { 18 start = new element; 19 end = new element; 20 start->previous = NULL; 21 start->next = end; 22 end->previous = start; 16 periodentafel::periodentafel() 17 { 18 start = new element; 19 end = new element; 20 start->previous = NULL; 21 start->next = end; 22 end->previous = start; 23 23 end->next = NULL; 24 24 }; … … 27 27 * Removes every element and afterwards deletes start and end of list. 28 28 */ 29 periodentafel::~periodentafel() 30 { 31 CleanupPeriodtable(); 32 delete(end); 33 delete(start); 34 }; 29 periodentafel::~periodentafel() 30 { 31 CleanupPeriodtable(); 32 delete(end); 33 delete(start); 34 }; 35 35 36 36 /** Adds element to period table list … … 38 38 * \return true - succeeded, false - does not occur 39 39 */ 40 bool periodentafel::AddElement(element *pointer) 41 { 40 bool periodentafel::AddElement(element *pointer) 41 { 42 42 pointer->sort = &pointer->Z; 43 43 if (pointer->Z < 1 && pointer->Z >= MAX_ELEMENTS) 44 44 cout << Verbose(0) << "Invalid Z number!\n"; 45 return add(pointer, end); 45 return add(pointer, end); 46 46 }; 47 47 … … 50 50 * \return true - succeeded, false - element not found 51 51 */ 52 bool periodentafel::RemoveElement(element *pointer) 53 { 54 return remove(pointer, start, end); 52 bool periodentafel::RemoveElement(element *pointer) 53 { 54 return remove(pointer, start, end); 55 55 }; 56 56 … … 58 58 * \return true - succeeded, false - does not occur 59 59 */ 60 bool periodentafel::CleanupPeriodtable() 61 { 62 return cleanup(start,end); 60 bool periodentafel::CleanupPeriodtable() 61 { 62 return cleanup(start,end); 63 63 }; 64 64 … … 76 76 cout << Verbose(0) << "Mass: " << endl; 77 77 cin >> walker->mass; 78 walker->Z = Z; 79 cout << Verbose(0) << "Atomic number: " << walker->Z << endl; 78 walker->Z = Z; 79 cout << Verbose(0) << "Atomic number: " << walker->Z << endl; 80 80 cout << Verbose(0) << "Name [max 64 chars]: " << endl; 81 81 cin >> walker->name; … … 105 105 /** Asks for element number and returns pointer to element 106 106 */ 107 element * periodentafel::AskElement() 107 element * periodentafel::AskElement() 108 108 { 109 109 element *walker = NULL; … … 117 117 }; 118 118 119 120 119 /** Prints period table to given stream. 121 120 * \param output stream 122 */ 121 */ 123 122 bool periodentafel::Output(ofstream *output) const 124 123 { … … 131 130 } 132 131 return result; 133 } else 132 } else 134 133 return false; 135 134 }; … … 138 137 * \param *output output stream 139 138 * \param *checkliste elements table for this molecule 140 */ 139 */ 141 140 bool periodentafel::Checkout(ofstream *output, const int *checkliste) const 142 141 { … … 152 151 if ((walker != NULL) && (walker->Z > 0) && (walker->Z < MAX_ELEMENTS) && (checkliste[walker->Z])) { 153 152 walker->No = No; 154 result = result && walker->Checkout(output, No++, checkliste[walker->Z]); 153 result = result && walker->Checkout(output, No++, checkliste[walker->Z]); 155 154 } 156 155 } 157 156 return result; 158 } else 157 } else 159 158 return false; 160 159 }; 161 162 160 163 161 /** Loads element list from file. … … 171 169 bool status = true; 172 170 bool otherstatus = true; 173 char *filename = new char[MAXSTRINGSIZE];174 171 char filename[255]; 172 175 173 // fill elements DB 176 174 strncpy(filename, path, MAXSTRINGSIZE); … … 225 223 if (infile != NULL) { 226 224 while (!infile.eof()) { 227 228 229 230 231 225 infile >> tmp; 226 infile >> ws; 227 infile >> FindElement((int)tmp)->Valence; 228 infile >> ws; 229 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->Valence << " valence electrons." << endl; 232 230 } 233 231 infile.close(); … … 253 251 } else 254 252 otherstatus = false; 255 253 256 254 // fill H-BondDistance DB per element 257 255 strncpy(filename, path, MAXSTRINGSIZE); … … 261 259 if (infile != NULL) { 262 260 while (!infile.eof()) { 263 261 infile >> tmp; 264 262 ptr = FindElement((int)tmp); 265 263 infile >> ws; 266 264 infile >> ptr->HBondDistance[0]; 267 265 infile >> ptr->HBondDistance[1]; 268 266 infile >> ptr->HBondDistance[2]; 269 267 infile >> ws; 270 268 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->HBondDistance[0] << " Angstrom typical distance to hydrogen." << endl; 271 269 } … … 274 272 } else 275 273 otherstatus = false; 276 274 277 275 // fill H-BondAngle DB per element 278 276 strncpy(filename, path, MAXSTRINGSIZE); … … 294 292 } else 295 293 otherstatus = false; 296 294 297 295 if (!otherstatus) 298 296 cerr << "WARNING: Something went wrong while parsing the other databases!" << endl; 299 297 300 298 return status; 301 299 }; … … 308 306 ofstream f; 309 307 char filename[MAXSTRINGSIZE]; 310 308 311 309 strncpy(filename, path, MAXSTRINGSIZE); 312 310 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename)); -
Property mode
changed from
-
src/periodentafel.hpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/stackclass.hpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/valence.db ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
TabularUnified src/vector.cpp ¶
-
Property mode
changed from
100644
to100755
r674220 ra98603 1 1 /** \file vector.cpp 2 * 2 * 3 3 * Function implementations for the class vector. 4 * 5 */ 6 4 * 5 */ 6 7 7 #include "molecules.hpp" 8 8 9 9 10 10 /************************************ Functions for class vector ************************************/ … … 21 21 */ 22 22 Vector::~Vector() {}; 23 24 /** Calculates square of distance between this and another vector. 25 * \param *y array to second vector 26 * \return \f$| x - y |^2\f$ 27 */ 28 double Vector::DistanceSquared(const Vector *y) const 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); 34 }; 23 35 24 36 /** Calculates distance between this and another vector. 25 37 * \param *y array to second vector 26 * \return \f$| x - y | ^2\f$38 * \return \f$| x - y |\f$ 27 39 */ 28 40 double Vector::Distance(const Vector *y) const … … 31 43 for (int i=NDIM;i--;) 32 44 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 33 return ( res);45 return (sqrt(res)); 34 46 }; 35 47 … … 69 81 if (tmp < res) res = tmp; 70 82 } 71 return (res); 83 return (res); 72 84 }; 73 85 … … 112 124 for (int i=NDIM;i--;) 113 125 res += x[i]*y->x[i]; 114 return (res); 115 }; 126 return (res); 127 }; 128 129 130 /** Calculates VectorProduct between this and another vector. 131 * -# returns the Product in place of vector from which it was initiated 132 * -# ATTENTION: Only three dim. 133 * \param *y array to vector with which to calculate crossproduct 134 * \return \f$ x \times y \f& 135 */ 136 void Vector::VectorProduct(const Vector *y) 137 { 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); 143 144 }; 145 116 146 117 147 /** projects this vector onto plane defined by \a *y. 118 * \param *y array tonormal vector of plane148 * \param *y normal vector of plane 119 149 * \return \f$\langle x, y \rangle\f$ 120 150 */ … … 123 153 Vector tmp; 124 154 tmp.CopyVector(y); 125 tmp.Scale(Projection(y)); 155 tmp.Normalize(); 156 tmp.Scale(ScalarProduct(&tmp)); 126 157 this->SubtractVector(&tmp); 127 158 }; … … 144 175 for (int i=NDIM;i--;) 145 176 res += this->x[i]*this->x[i]; 146 return (sqrt(res)); 177 return (sqrt(res)); 147 178 }; 148 179 … … 178 209 */ 179 210 void Vector::Init(double x1, double x2, double x3) 180 { 211 { 181 212 x[0] = x1; 182 213 x[1] = x2; … … 188 219 * \return \f$\acos\bigl(frac{\langle x, y \rangle}{|x||y|}\bigr)\f$ 189 220 */ 190 double Vector::Angle( Vector *y) const191 { 192 return acos(this->ScalarProduct(y)/Norm()/y->Norm()); 221 double Vector::Angle(const Vector *y) const 222 { 223 return acos(this->ScalarProduct(y)/Norm()/y->Norm()); 193 224 }; 194 225 … … 238 269 239 270 /** Sums two vectors \a and \b component-wise. 240 * \param a first vector 271 * \param a first vector 241 272 * \param b second vector 242 273 * \return a + b … … 251 282 252 283 /** Factors given vector \a a times \a m. 253 * \param a vector 284 * \param a vector 254 285 * \param m factor 255 286 * \return a + b … … 282 313 }; 283 314 284 ofstream& operator<<(ofstream& ost,Vector& m) 285 { 286 m.Output(&ost); 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 */ 320 ostream& operator<<(ostream& ost,Vector& m) 321 { 322 ost << "("; 323 for (int i=0;i<NDIM;i++) { 324 ost << m.x[i]; 325 if (i != 2) 326 ost << ","; 327 } 328 ost << ")"; 287 329 return ost; 288 330 }; … … 309 351 }; 310 352 311 /** Translate atom by given vector. 353 /** Translate atom by given vector. 312 354 * \param trans[] translation vector. 313 355 */ … … 316 358 for (int i=NDIM;i--;) 317 359 x[i] += trans->x[i]; 318 }; 360 }; 319 361 320 362 /** Do a matrix multiplication. … … 355 397 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]); // A_32 356 398 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]); // A_33 357 399 358 400 // do the matrix multiplication 359 401 C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2]; … … 379 421 { 380 422 for(int i=NDIM;i--;) 381 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i]; 382 }; 383 384 /** Mirrors atom against a given plane. 423 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i]; 424 }; 425 426 /** Mirrors atom against a given plane. 385 427 * \param n[] normal vector of mirror plane. 386 428 */ … … 398 440 Output((ofstream *)&cout); 399 441 cout << endl; 400 }; 442 }; 401 443 402 444 /** Calculates normal vector for three given vectors (being three points in space). … … 430 472 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]); 431 473 Normalize(); 432 474 433 475 return true; 434 476 }; … … 488 530 /** Creates this vector as one of the possible orthonormal ones to the given one. 489 531 * Just scan how many components of given *vector are unequal to zero and 490 * try to get the skp of both to be zero accordingly. 532 * try to get the skp of both to be zero accordingly. 491 533 * \param *vector given vector 492 534 * \return true - success, false - failure (null vector given) … … 509 551 Components[Last++] = j; 510 552 cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl; 511 553 512 554 switch(Last) { 513 555 case 3: // threecomponent system … … 522 564 case 1: // one component system 523 565 // set sole non-zero component to 0, and one of the other zero component pendants to 1 524 x[(Components[0]+2)%NDIM] = 0.; 525 x[(Components[0]+1)%NDIM] = 1.; 526 x[Components[0]] = 0.; 566 x[(Components[0]+2)%NDIM] = 0.; 567 x[(Components[0]+1)%NDIM] = 1.; 568 x[Components[0]] = 0.; 527 569 return true; 528 570 break; … … 541 583 { 542 584 // cout << Verbose(3) << "For comparison: "; 543 // cout << "A " << A->Projection(this) << "\t"; 544 // cout << "B " << B->Projection(this) << "\t"; 545 // cout << "C " << C->Projection(this) << "\t"; 585 // cout << "A " << A->Projection(this) << "\t"; 586 // cout << "B " << B->Projection(this) << "\t"; 587 // cout << "C " << C->Projection(this) << "\t"; 546 588 // cout << endl; 547 589 return A->Projection(this); … … 553 595 * \return true if success, false if failed due to linear dependency 554 596 */ 555 bool Vector::LSQdistance(Vector **vectors, int num) 597 bool Vector::LSQdistance(Vector **vectors, int num) 556 598 { 557 599 int j; 558 600 559 601 for (j=0;j<num;j++) { 560 602 cout << Verbose(1) << j << "th atom's vector: "; … … 565 607 int np = 3; 566 608 struct LSQ_params par; 567 609 568 610 const gsl_multimin_fminimizer_type *T = 569 611 gsl_multimin_fminimizer_nmsimplex; … … 571 613 gsl_vector *ss, *y; 572 614 gsl_multimin_function minex_func; 573 615 574 616 size_t iter = 0, i; 575 617 int status; 576 618 double size; 577 619 578 620 /* Initial vertex size vector */ 579 621 ss = gsl_vector_alloc (np); 580 622 y = gsl_vector_alloc (np); 581 623 582 624 /* Set all step sizes to 1 */ 583 625 gsl_vector_set_all (ss, 1.0); 584 626 585 627 /* Starting point */ 586 628 par.vectors = vectors; 587 629 par.num = num; 588 630 589 631 for (i=NDIM;i--;) 590 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.); 591 632 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.); 633 592 634 /* Initialize method and iterate */ 593 635 minex_func.f = &LSQ; 594 636 minex_func.n = np; 595 637 minex_func.params = (void *)∥ 596 638 597 639 s = gsl_multimin_fminimizer_alloc (T, np); 598 640 gsl_multimin_fminimizer_set (s, &minex_func, y, ss); 599 641 600 642 do 601 643 { 602 644 iter++; 603 645 status = gsl_multimin_fminimizer_iterate(s); 604 646 605 647 if (status) 606 648 break; 607 649 608 650 size = gsl_multimin_fminimizer_size (s); 609 651 status = gsl_multimin_test_size (size, 1e-2); 610 652 611 653 if (status == GSL_SUCCESS) 612 654 { 613 655 printf ("converged to minimum at\n"); 614 656 } 615 657 616 658 printf ("%5d ", (int)iter); 617 659 for (i = 0; i < (size_t)np; i++) … … 622 664 } 623 665 while (status == GSL_CONTINUE && iter < 100); 624 666 625 667 for (i=(size_t)np;i--;) 626 668 this->x[i] = gsl_vector_get(s->x, i); … … 688 730 * \param alpha first angle 689 731 * \param beta second angle 690 * \param c norm of final vector 732 * \param c norm of final vector 691 733 * \return a vector with \f$\langle x1,x2 \rangle=A\f$, \f$\langle x1,y \rangle = B\f$ and with norm \a c. 692 * \bug this is not yet working properly 734 * \bug this is not yet working properly 693 735 */ 694 736 bool Vector::SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c) … … 706 748 if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping 707 749 if (fabs(x1->x[1]) > MYEPSILON) { 708 flag = 1; 750 flag = 1; 709 751 } else if (fabs(x1->x[2]) > MYEPSILON) { 710 752 flag = 2; … … 739 781 // now comes the case system 740 782 D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1]; 741 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2]; 783 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2]; 742 784 D3 = y->x[0]/x1->x[0]*A-B1; 743 785 cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n"; 744 786 if (fabs(D1) < MYEPSILON) { 745 cout << Verbose(2) << "D1 == 0!\n"; 787 cout << Verbose(2) << "D1 == 0!\n"; 746 788 if (fabs(D2) > MYEPSILON) { 747 cout << Verbose(3) << "D2 != 0!\n"; 789 cout << Verbose(3) << "D2 != 0!\n"; 748 790 x[2] = -D3/D2; 749 791 E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2; … … 755 797 cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 756 798 if (fabs(F1) < MYEPSILON) { 757 cout << Verbose(4) << "F1 == 0!\n"; 799 cout << Verbose(4) << "F1 == 0!\n"; 758 800 cout << Verbose(4) << "Gleichungssystem linear\n"; 759 x[1] = F3/(2.*F2); 801 x[1] = F3/(2.*F2); 760 802 } else { 761 803 p = F2/F1; 762 804 q = p*p - F3/F1; 763 cout << Verbose(4) << "p " << p << "\tq " << q << endl; 805 cout << Verbose(4) << "p " << p << "\tq " << q << endl; 764 806 if (q < 0) { 765 807 cout << Verbose(4) << "q < 0" << endl; … … 782 824 cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 783 825 if (fabs(F1) < MYEPSILON) { 784 cout << Verbose(3) << "F1 == 0!\n"; 826 cout << Verbose(3) << "F1 == 0!\n"; 785 827 cout << Verbose(3) << "Gleichungssystem linear\n"; 786 x[2] = F3/(2.*F2); 828 x[2] = F3/(2.*F2); 787 829 } else { 788 830 p = F2/F1; 789 831 q = p*p - F3/F1; 790 cout << Verbose(3) << "p " << p << "\tq " << q << endl; 832 cout << Verbose(3) << "p " << p << "\tq " << q << endl; 791 833 if (q < 0) { 792 834 cout << Verbose(3) << "q < 0" << endl; … … 832 874 } 833 875 cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n"; 834 // apply sign matrix 876 // apply sign matrix 835 877 for (j=NDIM;j--;) 836 878 x[j] *= sign[j]; … … 838 880 ang = x2->Angle (this); 839 881 cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t"; 840 if (fabs(ang - cos(beta)) < MYEPSILON) { 882 if (fabs(ang - cos(beta)) < MYEPSILON) { 841 883 break; 842 884 } -
Property mode
changed from
-
TabularUnified src/vector.hpp ¶
-
Property mode
changed from
100644
to100755
r674220 ra98603 7 7 * basically, just a x[3] but with helpful functions 8 8 */ 9 class Vector { 9 class Vector { 10 10 public: 11 11 double x[NDIM]; … … 16 16 17 17 double Distance(const Vector *y) const; 18 double DistanceSquared(const Vector *y) const; 18 19 double PeriodicDistance(const Vector *y, const double *cell_size) const; 19 20 double ScalarProduct(const Vector *y) const; 20 21 double Projection(const Vector *y) const; 21 22 double Norm() const ; 22 double Angle( Vector *y) const;23 double Angle(const Vector *y) const; 23 24 24 25 void AddVector(const Vector *y); … … 26 27 void CopyVector(const Vector *y); 27 28 void RotateVector(const Vector *y, const double alpha); 29 void VectorProduct(const Vector *y); 28 30 void ProjectOntoPlane(const Vector *y); 29 void Zero(); 31 void Zero(); 30 32 void One(double one); 31 33 void Init(double x1, double x2, double x3); … … 40 42 void KeepPeriodic(ofstream *out, double *matrix); 41 43 void LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors); 42 44 43 45 double CutsPlaneAt(Vector *A, Vector *B, Vector *C); 44 46 bool GetOneNormalVector(const Vector *x1); … … 53 55 }; 54 56 55 o fstream& operator<<(ofstream& ost, Vector&m);56 Vector& operator+=(Vector& a, const Vector& b);57 Vector& operator*=(Vector& a, const double m);58 Vector& operator*(const Vector& a, const double m);59 Vector& operator+(const Vector& a, const Vector& b);57 ostream & operator << (ostream& ost, Vector &m); 58 //Vector& operator+=(Vector& a, const Vector& b); 59 //Vector& operator*=(Vector& a, const double m); 60 //Vector& operator*(const Vector& a, const double m); 61 //Vector& operator+(const Vector& a, const Vector& b); 60 62 61 63 #endif /*VECTOR_HPP_*/ -
Property mode
changed from
-
src/verbose.cpp ¶
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
Note:
See TracChangeset
for help on using the changeset viewer.