- Timestamp:
- Feb 9, 2009, 5:24:10 PM (17 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, Candidate_v1.7.0, Candidate_v1.7.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:
- d8b94a
- Parents:
- 124df1
- git-author:
- Frederik Heber <heber@…> (02/09/09 15:55:37)
- git-committer:
- Frederik Heber <heber@…> (02/09/09 17:24:10)
- Location:
- src
- Files:
-
- 2 added
- 2 deleted
- 34 edited
-
.#border.cpp (deleted)
-
.#molecules.hpp (deleted)
-
Hbondangle.db (modified) (1 prop)
-
Hbonddistance.db (modified) (1 prop)
-
Makefile.am (modified) (1 diff, 1 prop)
-
analyzer.cpp (modified) (3 diffs, 1 prop)
-
atom.cpp (modified) (6 diffs, 1 prop)
-
bond.cpp (modified) (11 diffs, 1 prop)
-
boundary.cpp (modified) (33 diffs, 1 prop)
-
boundary.hpp (modified) (2 diffs, 1 prop)
-
builder.cpp (modified) (13 diffs, 1 prop)
-
config.cpp (modified) (14 diffs, 1 prop)
-
datacreator.cpp (modified) (28 diffs, 1 prop)
-
datacreator.hpp (modified) (3 diffs, 1 prop)
-
defs.hpp (modified) (4 diffs, 1 prop)
-
element.cpp (modified) (2 diffs, 1 prop)
-
elements.db (modified) (1 prop)
-
ellipsoid.cpp (added)
-
ellipsoid.hpp (added)
-
graph.cpp (modified) (2 diffs, 1 prop)
-
helpers.cpp (modified) (13 diffs, 1 prop)
-
helpers.hpp (modified) (12 diffs, 1 prop)
-
joiner.cpp (modified) (2 diffs, 1 prop)
-
linkedcell.cpp (modified) (7 diffs)
-
linkedcell.hpp (modified) (1 diff)
-
moleculelist.cpp (modified) (16 diffs, 1 prop)
-
molecules.cpp (modified) (93 diffs, 1 prop)
-
molecules.hpp (modified) (11 diffs, 1 prop)
-
orbitals.db (modified) (1 prop)
-
parser.cpp (modified) (26 diffs, 1 prop)
-
parser.hpp (modified) (4 diffs, 1 prop)
-
periodentafel.cpp (modified) (11 diffs, 1 prop)
-
periodentafel.hpp (modified) (2 diffs, 1 prop)
-
stackclass.hpp (modified) (12 diffs, 1 prop)
-
valence.db (modified) (1 prop)
-
vector.cpp (modified) (37 diffs, 1 prop)
-
vector.hpp (modified) (1 diff, 1 prop)
-
verbose.cpp (modified) (2 diffs, 1 prop)
Legend:
- Unmodified
- Added
- Removed
-
src/Hbondangle.db
-
Property mode
changed from
100644to100755
-
Property mode
changed from
-
src/Hbonddistance.db
-
Property mode
changed from
100644to100755
-
Property mode
changed from
-
src/Makefile.am
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 1 SOURCE = atom.cpp bond.cpp boundary.cpp builder.cpp config.cpp element.cpp helpers.cpp molecules.cpp moleculelist.cpp parser.cpp periodentafel.cpp vector.cpp verbose.cpp2 HEADER = boundary.hpp defs.hpp helpers.hpp molecules.hpp parser.hpp periodentafel.hpp stackclass.hpp vector.hpp1 SOURCE = atom.cpp bond.cpp boundary.cpp builder.cpp config.cpp element.cpp ellipsoid.cpp helpers.cpp molecules.cpp linkedcell.cpp moleculelist.cpp parser.cpp periodentafel.cpp vector.cpp verbose.cpp 2 HEADER = boundary.hpp defs.hpp ellipsoid.hpp helpers.hpp linkedcell.hpp molecules.hpp parser.hpp periodentafel.hpp stackclass.hpp vector.hpp 3 3 4 4 bin_PROGRAMS = molecuilder joiner analyzer 5 5 molecuilderdir = ${bindir} 6 molecuilder_DATA = elements.db valence.db orbitals.db Hbonddistance.db Hbondangle.db6 molecuilder_DATA = elements.db valence.db orbitals.db Hbonddistance.db Hbondangle.db 7 7 molecuilder_SOURCES = ${SOURCE} ${HEADER} 8 8 joiner_SOURCES = joiner.cpp datacreator.cpp element.cpp helpers.cpp periodentafel.cpp parser.cpp verbose.cpp datacreator.hpp helpers.hpp parser.hpp periodentafel.hpp -
Property mode
changed from
-
src/analyzer.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 3 3 * Takes evaluated fragments (energy and forces) and does evaluation of how sensible the BOSSANOVA 4 4 * approach was, e.g. in the decay of the many-body-contributions. 5 * 5 * 6 6 */ 7 7 … … 9 9 10 10 #include "datacreator.hpp" 11 #include "helpers.hpp" 11 #include "helpers.hpp" 12 12 #include "parser.hpp" 13 #include "periodentafel.hpp" 13 #include "periodentafel.hpp" 14 14 15 15 // include config.h … … 23 23 int main(int argc, char **argv) 24 24 { 25 periodentafel *periode = NULL; // and a period table of all elements26 EnergyMatrix Energy;27 EnergyMatrix Hcorrection;28 ForceMatrix Force;29 ForceMatrix Shielding;30 ForceMatrix ShieldingPAS;31 EnergyMatrix Time;32 EnergyMatrix EnergyFragments;33 EnergyMatrix HcorrectionFragments;34 ForceMatrix ForceFragments;35 ForceMatrix ShieldingFragments;36 ForceMatrix ShieldingPASFragments;37 KeySetsContainer KeySet;38 ofstream output;39 ofstream output2;40 ofstream output3;41 ofstream output4;42 ifstream input;43 stringstream filename;44 time_t t = time(NULL);45 struct tm *ts = localtime(&t);46 char *datum = asctime(ts);47 stringstream Orderxrange;48 stringstream Fragmentxrange;49 stringstream yrange;50 char *dir = NULL;51 bool Hcorrected = true;52 double norm;53 int counter;54 55 cout << "ANOVA Analyzer" << endl;56 cout << "==============" << endl;57 58 // Get the command line options59 if (argc < 4) {60 cout << "Usage: " << argv[0] << " <inputdir> <prefix> <outputdir> [elementsdb]" << endl;61 cout << "<inputdir>\ttherein the output of a molecuilder fragmentation is expected, each fragment with a subdir containing an energy.all and a forces.all file." << endl;62 cout << "<prefix>\tprefix of energy and forces file." << endl;63 cout << "<outputdir>\tcreated plotfiles and datafiles are placed into this directory " << endl;64 cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl;65 return 1;66 } else {67 dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir");68 strcpy(dir, "/");69 strcat(dir, argv[2]);70 }71 72 if (argc > 4) {73 cout << "Loading periodentafel." << endl;74 periode = new periodentafel;75 periode->LoadPeriodentafel(argv[4]);76 }77 78 // Test the given directory79 if (!TestParams(argc, argv))80 return 1;81 82 // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++83 84 // ------------- Parse through all Fragment subdirs --------85 if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix,0,0)) return 1;86 Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX,0,0);87 if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix,0,0)) return 1;88 if (!Time.ParseFragmentMatrix(argv[1], dir, TimeSuffix, 10,1)) return 1;89 if (periode != NULL) { // also look for PAS values90 if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1;91 if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1;92 }93 94 // ---------- Parse the TE Factors into an array -----------------95 if (!Energy.ParseIndices()) return 1;96 if (Hcorrected) Hcorrection.ParseIndices();97 98 // ---------- Parse the Force indices into an array ---------------99 if (!Force.ParseIndices(argv[1])) return 1;100 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1;101 if (!ForceFragments.ParseIndices(argv[1])) return 1;102 103 // ---------- Parse the shielding indices into an array ---------------104 if (periode != NULL) { // also look for PAS values105 if(!Shielding.ParseIndices(argv[1])) return 1;106 if(!ShieldingPAS.ParseIndices(argv[1])) return 1;107 if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1;108 if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1;109 if(!ShieldingFragments.ParseIndices(argv[1])) return 1;110 if(!ShieldingPASFragments.ParseIndices(argv[1])) return 1;111 }112 113 // ---------- Parse the KeySets into an array ---------------114 if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1;115 if (!KeySet.ParseManyBodyTerms()) return 1;116 117 // ---------- Parse fragment files created by 'joiner' into an array -------------118 if (!EnergyFragments.ParseFragmentMatrix(argv[1], dir, EnergyFragmentSuffix,0,0)) return 1;119 if (Hcorrected) HcorrectionFragments.ParseFragmentMatrix(argv[1], dir, HcorrectionFragmentSuffix,0,0);120 if (!ForceFragments.ParseFragmentMatrix(argv[1], dir, ForceFragmentSuffix,0,0)) return 1;121 if (periode != NULL) { // also look for PAS values122 if (!ShieldingFragments.ParseFragmentMatrix(argv[1], dir, ShieldingFragmentSuffix, 1, 0)) return 1;123 if (!ShieldingPASFragments.ParseFragmentMatrix(argv[1], dir, ShieldingPASFragmentSuffix, 1, 0)) return 1;124 }125 126 // +++++++++++++++ TESTING ++++++++++++++++++++++++++++++127 128 // print energy and forces to file129 filename.str("");130 filename << argv[3] << "/" << "energy-forces.all";131 output.open(filename.str().c_str(), ios::out);132 output << endl << "Total Energy" << endl << "==============" << endl << Energy.Header << endl;133 for(int j=0;j<Energy.RowCounter[Energy.MatrixCounter];j++) {134 for(int k=0;k<Energy.ColumnCounter;k++)135 output << scientific << Energy.Matrix[ Energy.MatrixCounter ][j][k] << "\t";136 output << endl;137 }138 output << endl;139 140 output << endl << "Total Forces" << endl << "===============" << endl << Force.Header << endl;141 for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) {142 for(int k=0;k<Force.ColumnCounter;k++)143 output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t";144 output << endl;145 }146 output << endl;147 148 if (periode != NULL) { // also look for PAS values149 output << endl << "Total Shieldings" << endl << "===============" << endl << Shielding.Header << endl;150 for(int j=0;j<Shielding.RowCounter[Shielding.MatrixCounter];j++) {151 for(int k=0;k<Shielding.ColumnCounter;k++)152 output << scientific << Shielding.Matrix[ Shielding.MatrixCounter ][j][k] << "\t";153 output << endl;154 }155 output << endl;156 157 output << endl << "Total Shieldings PAS" << endl << "===============" << endl << ShieldingPAS.Header << endl;158 for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) {159 for(int k=0;k<ShieldingPAS.ColumnCounter;k++)160 output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t";161 output << endl;162 }163 output << endl;164 }165 166 output << endl << "Total Times" << endl << "===============" << endl << Time.Header << endl;167 for(int j=0;j<Time.RowCounter[Time.MatrixCounter];j++) {168 for(int k=0;k<Time.ColumnCounter;k++) {169 output << scientific << Time.Matrix[ Time.MatrixCounter ][j][k] << "\t";170 }171 output << endl;172 }173 output << endl;174 output.close();175 for(int k=0;k<Time.ColumnCounter;k++)176 Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k] = Time.Matrix[ Time.MatrixCounter ][Time.RowCounter[Time.MatrixCounter]-1][k];177 178 // +++++++++++++++ ANALYZING ++++++++++++++++++++++++++++++179 180 cout << "Analyzing ..." << endl;181 182 // ======================================= Creating the data files ==============================================================183 184 // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order185 // +++++++++++++++++++++++++++++++++++++++ Plotting Delta Simtime vs Bond Order186 if (!OpenOutputFile(output, argv[3], "SimTime-Order.dat" )) return false;187 if (!OpenOutputFile(output2, argv[3], "DeltaSimTime-Order.dat" )) return false;188 for(int j=Time.RowCounter[Time.MatrixCounter];j--;)189 for(int k=Time.ColumnCounter;k--;) {190 Time.Matrix[ Time.MatrixCounter ][j][k] = 0.;191 }192 counter = 0;193 output << "#Order\tFrag.No.\t" << Time.Header << endl;194 output2 << "#Order\tFrag.No.\t" << Time.Header << endl;195 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {196 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;)197 for(int j=Time.RowCounter[Time.MatrixCounter];j--;)198 for(int k=Time.ColumnCounter;k--;) {199 Time.Matrix[ Time.MatrixCounter ][j][k] += Time.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];200 }201 counter += KeySet.FragmentsPerOrder[BondOrder];202 output << BondOrder+1 << "\t" << counter;203 output2 << BondOrder+1 << "\t" << counter;204 for(int k=0;k<Time.ColumnCounter;k++) {205 output << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k];206 if (fabs(Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]) > MYEPSILON)207 output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k] / Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k];208 else209 output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k];210 }211 output << endl;212 output2 << endl;213 }214 output.close();215 output2.close();216 217 // +++++++++++++++++++++++++++++++++++++++ Plotting shieldings218 219 if (periode != NULL) { // also look for PAS values220 if (!CreateDataDeltaForcesOrderPerAtom(ShieldingPAS, ShieldingPASFragments, KeySet, argv[3], "DeltaShieldingsPAS-Order", "Plot of error between approximated shieldings and full shieldings versus the Bond Order", datum)) return 1;221 if (!CreateDataForcesOrderPerAtom(ShieldingPASFragments, KeySet, argv[3], "ShieldingsPAS-Order", "Plot of approximated shieldings versus the Bond Order", datum)) return 1;222 if (!AppendOutputFile(output, argv[3], "ShieldingsPAS-Order.dat" )) return false;223 output << endl << "# Full" << endl;224 for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) {225 output << j << "\t";226 for(int k=0;k<ShieldingPAS.ColumnCounter;k++)227 output << scientific <<ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; //*(((k>1) && (k<6))? 1.e6 : 1.) << "\t";228 output << endl;229 }230 }231 output.close();232 233 234 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM235 if (!CreateDataDeltaEnergyOrder(Energy, EnergyFragments, KeySet, argv[3], "DeltaEnergies-Order", "Plot of error between approximated and full energies energies versus the Bond Order", datum)) return 1;236 237 // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order238 if (!CreateDataEnergyOrder(EnergyFragments, KeySet, argv[3], "Energies-Order", "Plot of approximated energies versus the Bond Order", datum)) return 1;239 240 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM241 if (!CreateDataDeltaForcesOrderPerAtom(Force, ForceFragments, KeySet, argv[3], "DeltaForces-Order", "Plot of error between approximated forces and full forces versus the Bond Order", datum)) return 1;242 243 // min force244 if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMinForces-Order", "Plot of min error between approximated forces and full forces versus the Bond Order", datum, CreateMinimumForce)) return 1;245 246 // mean force247 if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMeanForces-Order", "Plot of mean error between approximated forces and full forces versus the Bond Order", datum, CreateMeanForce)) return 1;248 249 // max force250 if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMaxForces-Order", "Plot of max error between approximated forces and full forces versus the Bond Order", datum, CreateMaximumForce)) return 1;251 252 // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order253 if (!CreateDataForcesOrderPerAtom(ForceFragments, KeySet, argv[3], "Forces-Order", "Plot of approximated forces versus the Bond Order", datum)) return 1;254 if (!AppendOutputFile(output, argv[3], "Forces-Order.dat" )) return false;255 output << endl << "# Full" << endl;256 for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) {257 output << j << "\t";258 for(int k=0;k<Force.ColumnCounter;k++)259 output << scientific <<Force.Matrix[ Force.MatrixCounter ][j][k] << "\t";260 output << endl;261 }262 output.close();263 // min force264 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MinForces-Order", "Plot of min approximated forces versus the Bond Order", datum, CreateMinimumForce)) return 1;265 266 // mean force267 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MeanForces-Order", "Plot of mean approximated forces versus the Bond Order", datum, CreateMeanForce)) return 1;268 269 // max force270 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MaxForces-Order", "Plot of max approximated forces versus the Bond Order", datum, CreateMaximumForce)) return 1;271 272 // ++++++++++++++++++++++++++++++++++++++Plotting vector sum (should be 0) vs. bond order273 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "VectorSum-Order", "Plot of vector sum of the approximated forces versus the Bond Order", datum, CreateVectorSumForce)) return 1;274 275 // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order276 if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-Fragment", "Plot of fragment energy versus the Fragment No", datum, CreateEnergy)) return 1;277 if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", "Plot of fragment energy of each Fragment No vs. Bond Order", datum, CreateEnergy)) return 1;278 if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", "Plot of maximum of fragment energy vs. Bond Order", datum, CreateMaxFragmentOrder)) return 1;279 if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", "Plot of minimum of fragment energy vs. Bond Order", datum, CreateMinFragmentOrder)) return 1;280 281 // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment282 // min force283 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-Fragment", "Plot of min approximated forces versus the Fragment No", datum, CreateMinimumForce)) return 1;284 285 // mean force286 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", "Plot of mean approximated forces versus the Fragment No", datum, CreateMeanForce)) return 1;287 288 // max force289 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", "Plot of max approximated forces versus the Fragment No", datum, CreateMaximumForce)) return 1;290 291 // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment per order292 // min force293 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", "Plot of min approximated forces of each Fragment No vs. Bond Order", datum, CreateMinimumForce)) return 1;294 295 // mean force296 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", "Plot of mean approximated forces of each Fragment No vs. Bond Order", datum, CreateMeanForce)) return 1;297 298 // max force299 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", "Plot of max approximated forces of each Fragment No vs. Bond Order", datum, CreateMaximumForce)) return 1;300 301 // ======================================= Creating the plot files ==============================================================302 303 Orderxrange << "[1:" << KeySet.Order << "]";304 Fragmentxrange << "[0:" << KeySet.FragmentCounter+1 << "]";305 yrange.str("[1e-8:1e+1]");306 307 // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order308 if (!CreatePlotOrder(Time, KeySet, argv[3], "SimTime-Order", 1, "below", "y", "",1, 1, "bond order k", "Evaluation time [s]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1;309 310 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM311 if (!CreatePlotOrder(Energy, KeySet, argv[3], "DeltaEnergies-Order", 1, "outside", "y", "",1, 1, "bond order k", "absolute error in energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;312 313 // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order314 if (!CreatePlotOrder(Energy, KeySet, argv[3], "Energies-Order", 1, "outside", "", "",1, 1, "bond order k", "approximate energy [Ht]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1;315 316 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM317 yrange.str("[1e-8:1e+0]");318 // min force319 if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMinForces-Order", 2, "top right", "y", "",1, 1, "bond order k", "absolute error in min force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;320 321 // mean force322 if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMeanForces-Order", 2, "top right", "y", "",1, 1, "bond order k", "absolute error in mean force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1;323 324 // max force325 if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMaxForces-Order", 2, "top right", "y", "",1, 1, "bond order k", "absolute error in max force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;326 327 // min/mean/max comparison for total force328 if(!OpenOutputFile(output, argv[3], "DeltaMinMeanMaxTotalForce-Order.pyx")) return 1;329 CreatePlotHeader(output, "DeltaMinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL,1, 1, "bond order k", "absolute error in total forces [Ht/a.u.]");330 output << "plot " << Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl; 331 output << "'DeltaMinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl;332 output << "'DeltaMeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl;333 output << "'DeltaMaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl;334 output.close(); 335 336 // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order337 // min force338 if (!CreatePlotOrder(Force, KeySet, argv[3], "MinForces-Order", 2, "bottom right", "y", "",1, 1, "bond order k", "absolute approximated min force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;339 340 // mean force341 if (!CreatePlotOrder(Force, KeySet, argv[3], "MeanForces-Order", 2, "bottom right", "y", "",1, 1, "bond order k", "absolute approximated mean force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1;342 343 // max force344 if (!CreatePlotOrder(Force, KeySet, argv[3], "MaxForces-Order", 2, "bottom right", "y", "",1, 1, "bond order k", "absolute approximated max force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;345 346 // min/mean/max comparison for total force347 if(!OpenOutputFile(output, argv[3],"MinMeanMaxTotalForce-Order.pyx")) return 1;348 CreatePlotHeader(output, "MinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL, 1, 1, "bond order k", "absolute total force [Ht/a.u.]");349 output << "plot "<< Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl; 350 output << "'MinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl;351 output << "'MeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl;352 output << "'MaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl;353 output.close(); 354 355 // ++++++++++++++++++++++++++++++++++++++Plotting vector sum vs. Order356 357 if (!CreatePlotOrder(Force, KeySet, argv[3], "VectorSum-Order", 2, "bottom right", "y" ,"", 1, 1, "bond order k", "vector sum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1;358 359 // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order360 yrange.str("");361 yrange << "[" << EnergyFragments.FindMinValue() << ":" << EnergyFragments.FindMaxValue() << "]";362 if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "Energies-Fragment", 5, "below", "y", "", 1, 5, "fragment number", "Energies of each fragment [Ht]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with points", AbsEnergyPlotLine)) return 1;363 if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Energies of each fragment [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with points", AbsEnergyPlotLine)) return 1;364 if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Maximum fragment energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;365 if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Minimum fragment energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1;366 367 // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment368 yrange.str("");369 yrange << "[" << ForceFragments.FindMinValue() << ":" << ForceFragments.FindMaxValue()<< "]";370 // min371 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "minimum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;372 373 // mean374 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "mean of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1;375 376 // max377 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "maximum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;378 379 // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment per bond order380 // min381 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "minimum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;382 383 // mean384 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "mean of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1;385 386 // max387 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "maximum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1;388 389 // +++++++++++++++++++++++++++++++=Ploting approximated and true shielding for each atom390 if (periode != NULL) { // also look for PAS values391 if(!OpenOutputFile(output, argv[3], "ShieldingsPAS-Order.pyx")) return 1;392 if(!OpenOutputFile(output2, argv[3], "DeltaShieldingsPAS-Order.pyx")) return 1;393 CreatePlotHeader(output, "ShieldingsPAS-Order", 1, "top right", NULL, NULL,1, 5, "nuclei index", "iso chemical shielding value [ppm]");394 CreatePlotHeader(output2, "DeltaShieldingsPAS-Order", 1, "top right", NULL, NULL,1, 5, "nuclei index", "iso chemical shielding value [ppm]");395 double step=0.8/KeySet.Order;396 output << "set boxwidth " << step << endl;397 output << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl;398 output2 << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl;399 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {400 output << "'ShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1+" << step*(double)BondOrder << "):7 with boxes, \\" << endl;401 output2 << "'DeltaShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1):7 with linespoints";402 if (BondOrder-1 != KeySet.Order)403 output2 << ", \\" << endl;404 }405 output << "'ShieldingsPAS-Order.dat' index " << KeySet.Order << " title 'Full' using ($1+" << step*(double)KeySet.Order << "):7 with boxes" << endl;406 output.close(); 407 output2.close(); 408 }409 410 // create Makefile411 if(!OpenOutputFile(output, argv[3], "Makefile")) return 1;412 output << "PYX = $(shell ls *.pyx)" << endl << endl;413 output << "EPS = $(PYX:.pyx=.eps)" << endl << endl;414 output << "%.eps: %.pyx" << endl;415 output << "\t~/build/pyxplot/pyxplot $<" << endl << endl;416 output << "all: $(EPS)" << endl << endl;417 output << ".PHONY: clean" << endl;418 output << "clean:" << endl;419 output << "\trm -rf $(EPS)" << endl;420 output.close();421 422 // ++++++++++++++++ exit ++++++++++++++++++++++++++++++++++423 delete(periode);424 Free((void **)&dir, "main: *dir");425 cout << "done." << endl;426 return 0;25 periodentafel *periode = NULL; // and a period table of all elements 26 EnergyMatrix Energy; 27 EnergyMatrix Hcorrection; 28 ForceMatrix Force; 29 ForceMatrix Shielding; 30 ForceMatrix ShieldingPAS; 31 EnergyMatrix Time; 32 EnergyMatrix EnergyFragments; 33 EnergyMatrix HcorrectionFragments; 34 ForceMatrix ForceFragments; 35 ForceMatrix ShieldingFragments; 36 ForceMatrix ShieldingPASFragments; 37 KeySetsContainer KeySet; 38 ofstream output; 39 ofstream output2; 40 ofstream output3; 41 ofstream output4; 42 ifstream input; 43 stringstream filename; 44 time_t t = time(NULL); 45 struct tm *ts = localtime(&t); 46 char *datum = asctime(ts); 47 stringstream Orderxrange; 48 stringstream Fragmentxrange; 49 stringstream yrange; 50 char *dir = NULL; 51 bool Hcorrected = true; 52 double norm; 53 int counter; 54 55 cout << "ANOVA Analyzer" << endl; 56 cout << "==============" << endl; 57 58 // Get the command line options 59 if (argc < 4) { 60 cout << "Usage: " << argv[0] << " <inputdir> <prefix> <outputdir> [elementsdb]" << endl; 61 cout << "<inputdir>\ttherein the output of a molecuilder fragmentation is expected, each fragment with a subdir containing an energy.all and a forces.all file." << endl; 62 cout << "<prefix>\tprefix of energy and forces file." << endl; 63 cout << "<outputdir>\tcreated plotfiles and datafiles are placed into this directory " << endl; 64 cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl; 65 return 1; 66 } else { 67 dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir"); 68 strcpy(dir, "/"); 69 strcat(dir, argv[2]); 70 } 71 72 if (argc > 4) { 73 cout << "Loading periodentafel." << endl; 74 periode = new periodentafel; 75 periode->LoadPeriodentafel(argv[4]); 76 } 77 78 // Test the given directory 79 if (!TestParams(argc, argv)) 80 return 1; 81 82 // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++ 83 84 // ------------- Parse through all Fragment subdirs -------- 85 if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix,0,0)) return 1; 86 Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX,0,0); 87 if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix,0,0)) return 1; 88 if (!Time.ParseFragmentMatrix(argv[1], dir, TimeSuffix, 10,1)) return 1; 89 if (periode != NULL) { // also look for PAS values 90 if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1; 91 if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1; 92 } 93 94 // ---------- Parse the TE Factors into an array ----------------- 95 if (!Energy.ParseIndices()) return 1; 96 if (Hcorrected) Hcorrection.ParseIndices(); 97 98 // ---------- Parse the Force indices into an array --------------- 99 if (!Force.ParseIndices(argv[1])) return 1; 100 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1; 101 if (!ForceFragments.ParseIndices(argv[1])) return 1; 102 103 // ---------- Parse the shielding indices into an array --------------- 104 if (periode != NULL) { // also look for PAS values 105 if(!Shielding.ParseIndices(argv[1])) return 1; 106 if(!ShieldingPAS.ParseIndices(argv[1])) return 1; 107 if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1; 108 if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1; 109 if(!ShieldingFragments.ParseIndices(argv[1])) return 1; 110 if(!ShieldingPASFragments.ParseIndices(argv[1])) return 1; 111 } 112 113 // ---------- Parse the KeySets into an array --------------- 114 if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1; 115 if (!KeySet.ParseManyBodyTerms()) return 1; 116 117 // ---------- Parse fragment files created by 'joiner' into an array ------------- 118 if (!EnergyFragments.ParseFragmentMatrix(argv[1], dir, EnergyFragmentSuffix,0,0)) return 1; 119 if (Hcorrected) HcorrectionFragments.ParseFragmentMatrix(argv[1], dir, HcorrectionFragmentSuffix,0,0); 120 if (!ForceFragments.ParseFragmentMatrix(argv[1], dir, ForceFragmentSuffix,0,0)) return 1; 121 if (periode != NULL) { // also look for PAS values 122 if (!ShieldingFragments.ParseFragmentMatrix(argv[1], dir, ShieldingFragmentSuffix, 1, 0)) return 1; 123 if (!ShieldingPASFragments.ParseFragmentMatrix(argv[1], dir, ShieldingPASFragmentSuffix, 1, 0)) return 1; 124 } 125 126 // +++++++++++++++ TESTING ++++++++++++++++++++++++++++++ 127 128 // print energy and forces to file 129 filename.str(""); 130 filename << argv[3] << "/" << "energy-forces.all"; 131 output.open(filename.str().c_str(), ios::out); 132 output << endl << "Total Energy" << endl << "==============" << endl << Energy.Header << endl; 133 for(int j=0;j<Energy.RowCounter[Energy.MatrixCounter];j++) { 134 for(int k=0;k<Energy.ColumnCounter;k++) 135 output << scientific << Energy.Matrix[ Energy.MatrixCounter ][j][k] << "\t"; 136 output << endl; 137 } 138 output << endl; 139 140 output << endl << "Total Forces" << endl << "===============" << endl << Force.Header << endl; 141 for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) { 142 for(int k=0;k<Force.ColumnCounter;k++) 143 output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t"; 144 output << endl; 145 } 146 output << endl; 147 148 if (periode != NULL) { // also look for PAS values 149 output << endl << "Total Shieldings" << endl << "===============" << endl << Shielding.Header << endl; 150 for(int j=0;j<Shielding.RowCounter[Shielding.MatrixCounter];j++) { 151 for(int k=0;k<Shielding.ColumnCounter;k++) 152 output << scientific << Shielding.Matrix[ Shielding.MatrixCounter ][j][k] << "\t"; 153 output << endl; 154 } 155 output << endl; 156 157 output << endl << "Total Shieldings PAS" << endl << "===============" << endl << ShieldingPAS.Header << endl; 158 for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) { 159 for(int k=0;k<ShieldingPAS.ColumnCounter;k++) 160 output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; 161 output << endl; 162 } 163 output << endl; 164 } 165 166 output << endl << "Total Times" << endl << "===============" << endl << Time.Header << endl; 167 for(int j=0;j<Time.RowCounter[Time.MatrixCounter];j++) { 168 for(int k=0;k<Time.ColumnCounter;k++) { 169 output << scientific << Time.Matrix[ Time.MatrixCounter ][j][k] << "\t"; 170 } 171 output << endl; 172 } 173 output << endl; 174 output.close(); 175 for(int k=0;k<Time.ColumnCounter;k++) 176 Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k] = Time.Matrix[ Time.MatrixCounter ][Time.RowCounter[Time.MatrixCounter]-1][k]; 177 178 // +++++++++++++++ ANALYZING ++++++++++++++++++++++++++++++ 179 180 cout << "Analyzing ..." << endl; 181 182 // ======================================= Creating the data files ============================================================== 183 184 // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order 185 // +++++++++++++++++++++++++++++++++++++++ Plotting Delta Simtime vs Bond Order 186 if (!OpenOutputFile(output, argv[3], "SimTime-Order.dat" )) return false; 187 if (!OpenOutputFile(output2, argv[3], "DeltaSimTime-Order.dat" )) return false; 188 for(int j=Time.RowCounter[Time.MatrixCounter];j--;) 189 for(int k=Time.ColumnCounter;k--;) { 190 Time.Matrix[ Time.MatrixCounter ][j][k] = 0.; 191 } 192 counter = 0; 193 output << "#Order\tFrag.No.\t" << Time.Header << endl; 194 output2 << "#Order\tFrag.No.\t" << Time.Header << endl; 195 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 196 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) 197 for(int j=Time.RowCounter[Time.MatrixCounter];j--;) 198 for(int k=Time.ColumnCounter;k--;) { 199 Time.Matrix[ Time.MatrixCounter ][j][k] += Time.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 200 } 201 counter += KeySet.FragmentsPerOrder[BondOrder]; 202 output << BondOrder+1 << "\t" << counter; 203 output2 << BondOrder+1 << "\t" << counter; 204 for(int k=0;k<Time.ColumnCounter;k++) { 205 output << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k]; 206 if (fabs(Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]) > MYEPSILON) 207 output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k] / Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter] ][k]; 208 else 209 output2 << "\t" << scientific << Time.Matrix[ Time.MatrixCounter ][ Time.RowCounter[Time.MatrixCounter]-1 ][k]; 210 } 211 output << endl; 212 output2 << endl; 213 } 214 output.close(); 215 output2.close(); 216 217 // +++++++++++++++++++++++++++++++++++++++ Plotting shieldings 218 219 if (periode != NULL) { // also look for PAS values 220 if (!CreateDataDeltaForcesOrderPerAtom(ShieldingPAS, ShieldingPASFragments, KeySet, argv[3], "DeltaShieldingsPAS-Order", "Plot of error between approximated shieldings and full shieldings versus the Bond Order", datum)) return 1; 221 if (!CreateDataForcesOrderPerAtom(ShieldingPASFragments, KeySet, argv[3], "ShieldingsPAS-Order", "Plot of approximated shieldings versus the Bond Order", datum)) return 1; 222 if (!AppendOutputFile(output, argv[3], "ShieldingsPAS-Order.dat" )) return false; 223 output << endl << "# Full" << endl; 224 for(int j=0;j<ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter];j++) { 225 output << j << "\t"; 226 for(int k=0;k<ShieldingPAS.ColumnCounter;k++) 227 output << scientific << ShieldingPAS.Matrix[ ShieldingPAS.MatrixCounter ][j][k] << "\t"; //*(((k>1) && (k<6))? 1.e6 : 1.) << "\t"; 228 output << endl; 229 } 230 } 231 output.close(); 232 233 234 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM 235 if (!CreateDataDeltaEnergyOrder(Energy, EnergyFragments, KeySet, argv[3], "DeltaEnergies-Order", "Plot of error between approximated and full energies energies versus the Bond Order", datum)) return 1; 236 237 // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order 238 if (!CreateDataEnergyOrder(EnergyFragments, KeySet, argv[3], "Energies-Order", "Plot of approximated energies versus the Bond Order", datum)) return 1; 239 240 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM 241 if (!CreateDataDeltaForcesOrderPerAtom(Force, ForceFragments, KeySet, argv[3], "DeltaForces-Order", "Plot of error between approximated forces and full forces versus the Bond Order", datum)) return 1; 242 243 // min force 244 if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMinForces-Order", "Plot of min error between approximated forces and full forces versus the Bond Order", datum, CreateMinimumForce)) return 1; 245 246 // mean force 247 if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMeanForces-Order", "Plot of mean error between approximated forces and full forces versus the Bond Order", datum, CreateMeanForce)) return 1; 248 249 // max force 250 if (!CreateDataDeltaForcesOrder(Force, ForceFragments, KeySet, argv[3], "DeltaMaxForces-Order", "Plot of max error between approximated forces and full forces versus the Bond Order", datum, CreateMaximumForce)) return 1; 251 252 // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order 253 if (!CreateDataForcesOrderPerAtom(ForceFragments, KeySet, argv[3], "Forces-Order", "Plot of approximated forces versus the Bond Order", datum)) return 1; 254 if (!AppendOutputFile(output, argv[3], "Forces-Order.dat" )) return false; 255 output << endl << "# Full" << endl; 256 for(int j=0;j<Force.RowCounter[Force.MatrixCounter];j++) { 257 output << j << "\t"; 258 for(int k=0;k<Force.ColumnCounter;k++) 259 output << scientific << Force.Matrix[ Force.MatrixCounter ][j][k] << "\t"; 260 output << endl; 261 } 262 output.close(); 263 // min force 264 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MinForces-Order", "Plot of min approximated forces versus the Bond Order", datum, CreateMinimumForce)) return 1; 265 266 // mean force 267 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MeanForces-Order", "Plot of mean approximated forces versus the Bond Order", datum, CreateMeanForce)) return 1; 268 269 // max force 270 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "MaxForces-Order", "Plot of max approximated forces versus the Bond Order", datum, CreateMaximumForce)) return 1; 271 272 // ++++++++++++++++++++++++++++++++++++++Plotting vector sum (should be 0) vs. bond order 273 if (!CreateDataForcesOrder(ForceFragments, KeySet, argv[3], "VectorSum-Order", "Plot of vector sum of the approximated forces versus the Bond Order", datum, CreateVectorSumForce)) return 1; 274 275 // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order 276 if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-Fragment", "Plot of fragment energy versus the Fragment No", datum, CreateEnergy)) return 1; 277 if (!CreateDataFragment(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", "Plot of fragment energy of each Fragment No vs. Bond Order", datum, CreateEnergy)) return 1; 278 if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", "Plot of maximum of fragment energy vs. Bond Order", datum, CreateMaxFragmentOrder)) return 1; 279 if (!CreateDataFragmentOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", "Plot of minimum of fragment energy vs. Bond Order", datum, CreateMinFragmentOrder)) return 1; 280 281 // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment 282 // min force 283 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-Fragment", "Plot of min approximated forces versus the Fragment No", datum, CreateMinimumForce)) return 1; 284 285 // mean force 286 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", "Plot of mean approximated forces versus the Fragment No", datum, CreateMeanForce)) return 1; 287 288 // max force 289 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", "Plot of max approximated forces versus the Fragment No", datum, CreateMaximumForce)) return 1; 290 291 // +++++++++++++++++++++++++++++++Ploting min/mean/max forces for each fragment per order 292 // min force 293 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", "Plot of min approximated forces of each Fragment No vs. Bond Order", datum, CreateMinimumForce)) return 1; 294 295 // mean force 296 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", "Plot of mean approximated forces of each Fragment No vs. Bond Order", datum, CreateMeanForce)) return 1; 297 298 // max force 299 if (!CreateDataFragment(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", "Plot of max approximated forces of each Fragment No vs. Bond Order", datum, CreateMaximumForce)) return 1; 300 301 // ======================================= Creating the plot files ============================================================== 302 303 Orderxrange << "[1:" << KeySet.Order << "]"; 304 Fragmentxrange << "[0:" << KeySet.FragmentCounter+1 << "]"; 305 yrange.str("[1e-8:1e+1]"); 306 307 // +++++++++++++++++++++++++++++++++++++++ Plotting Simtime vs Bond Order 308 if (!CreatePlotOrder(Time, KeySet, argv[3], "SimTime-Order", 1, "below", "y", "", 1, 1, "bond order k", "Evaluation time [s]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1; 309 310 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in energy to full QM 311 if (!CreatePlotOrder(Energy, KeySet, argv[3], "DeltaEnergies-Order", 1, "outside", "y", "", 1, 1, "bond order k", "absolute error in energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1; 312 313 // +++++++++++++++++++++++++++++++++++Plotting Energies vs. Order 314 if (!CreatePlotOrder(Energy, KeySet, argv[3], "Energies-Order", 1, "outside", "", "", 1, 1, "bond order k", "approximate energy [Ht]", Orderxrange.str().c_str(), "", "1" , "with linespoints", EnergyPlotLine)) return 1; 315 316 // +++++++++++++++++++++++++++++++++++++++ Plotting deviation in forces to full QM 317 yrange.str("[1e-8:1e+0]"); 318 // min force 319 if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMinForces-Order", 2, "top right", "y", "", 1, 1, "bond order k", "absolute error in min force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1; 320 321 // mean force 322 if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMeanForces-Order", 2, "top right", "y", "", 1, 1, "bond order k", "absolute error in mean force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1; 323 324 // max force 325 if (!CreatePlotOrder(Force, KeySet, argv[3], "DeltaMaxForces-Order", 2, "top right", "y", "", 1, 1, "bond order k", "absolute error in max force [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", ForceMagnitudePlotLine)) return 1; 326 327 // min/mean/max comparison for total force 328 if(!OpenOutputFile(output, argv[3], "DeltaMinMeanMaxTotalForce-Order.pyx")) return 1; 329 CreatePlotHeader(output, "DeltaMinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL, 1, 1, "bond order k", "absolute error in total forces [Ht/a.u.]"); 330 output << "plot " << Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl; 331 output << "'DeltaMinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl; 332 output << "'DeltaMeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl; 333 output << "'DeltaMaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl; 334 output.close(); 335 336 // ++++++++++++++++++++++++++++++++++++++Plotting Forces vs. Order 337 // min force 338 if (!CreatePlotOrder(Force, KeySet, argv[3], "MinForces-Order", 2, "bottom right", "y", "", 1, 1, "bond order k", "absolute approximated min force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1; 339 340 // mean force 341 if (!CreatePlotOrder(Force, KeySet, argv[3], "MeanForces-Order", 2, "bottom right", "y", "", 1, 1, "bond order k", "absolute approximated mean force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", AbsFirstForceValuePlotLine)) return 1; 342 343 // max force 344 if (!CreatePlotOrder(Force, KeySet, argv[3], "MaxForces-Order", 2, "bottom right", "y", "", 1, 1, "bond order k", "absolute approximated max force [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1; 345 346 // min/mean/max comparison for total force 347 if(!OpenOutputFile(output, argv[3],"MinMeanMaxTotalForce-Order.pyx")) return 1; 348 CreatePlotHeader(output, "MinMeanMaxTotalForce-Order", 1, "bottom left", "y", NULL, 1, 1, "bond order k", "absolute total force [Ht/a.u.]"); 349 output << "plot "<< Orderxrange.str().c_str() << " [1e-8:1e+0] \\" << endl; 350 output << "'MinForces-Order.dat' title 'minimum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints, \\" << endl; 351 output << "'MeanForces-Order.dat' title 'mean' using 1:(abs($" << 8 << ")) with linespoints, \\" << endl; 352 output << "'MaxForces-Order.dat' title 'maximum' using 1:(sqrt($" << 8 << "*$" << 8 << "+$" << 8+1 << "*$" << 8+1 << "+$" << 8+2 << "*$" << 8+2 << ")) with linespoints" << endl; 353 output.close(); 354 355 // ++++++++++++++++++++++++++++++++++++++Plotting vector sum vs. Order 356 357 if (!CreatePlotOrder(Force, KeySet, argv[3], "VectorSum-Order", 2, "bottom right", "y" ,"", 1, 1, "bond order k", "vector sum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), "", "1" , "with linespoints", ForceMagnitudePlotLine)) return 1; 358 359 // +++++++++++++++++++++++++++++++Plotting energyfragments vs. order 360 yrange.str(""); 361 yrange << "[" << EnergyFragments.FindMinValue() << ":" << EnergyFragments.FindMaxValue() << "]"; 362 if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "Energies-Fragment", 5, "below", "y", "", 1, 5, "fragment number", "Energies of each fragment [Ht]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with points", AbsEnergyPlotLine)) return 1; 363 if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "Energies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Energies of each fragment [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with points", AbsEnergyPlotLine)) return 1; 364 if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "MaxEnergies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Maximum fragment energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1; 365 if (!CreatePlotOrder(EnergyFragments, KeySet, argv[3], "MinEnergies-FragmentOrder", 5, "below", "y", "", 1, 1, "bond order", "Minimum fragment energy [Ht]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with linespoints", AbsEnergyPlotLine)) return 1; 366 367 // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment 368 yrange.str(""); 369 yrange << "[" << ForceFragments.FindMinValue() << ":" << ForceFragments.FindMaxValue()<< "]"; 370 // min 371 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "minimum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; 372 373 // mean 374 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "mean of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1; 375 376 // max 377 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-Fragment", 5, "below", "y", "set boxwidth 0.2", 1, 5, "fragment number", "maximum of approximated forces [Ht/a.u.]", Fragmentxrange.str().c_str(), yrange.str().c_str(), "2" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; 378 379 // +++++++++++++++++++++++++++++++=Ploting min/mean/max forces for each fragment per bond order 380 // min 381 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MinForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "minimum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; 382 383 // mean 384 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MeanForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "mean of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesFirstForceValuePlotLine)) return 1; 385 386 // max 387 if (!CreatePlotOrder(ForceFragments, KeySet, argv[3], "MaxForces-FragmentOrder", 5, "below", "y", "set boxwidth 0.2", 1, 1, "bond order", "maximum of approximated forces [Ht/a.u.]", Orderxrange.str().c_str(), yrange.str().c_str(), "1" , "with boxes fillcolor", BoxesForcePlotLine)) return 1; 388 389 // +++++++++++++++++++++++++++++++=Ploting approximated and true shielding for each atom 390 if (periode != NULL) { // also look for PAS values 391 if(!OpenOutputFile(output, argv[3], "ShieldingsPAS-Order.pyx")) return 1; 392 if(!OpenOutputFile(output2, argv[3], "DeltaShieldingsPAS-Order.pyx")) return 1; 393 CreatePlotHeader(output, "ShieldingsPAS-Order", 1, "top right", NULL, NULL, 1, 5, "nuclei index", "iso chemical shielding value [ppm]"); 394 CreatePlotHeader(output2, "DeltaShieldingsPAS-Order", 1, "top right", NULL, NULL, 1, 5, "nuclei index", "iso chemical shielding value [ppm]"); 395 double step=0.8/KeySet.Order; 396 output << "set boxwidth " << step << endl; 397 output << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl; 398 output2 << "plot [0:" << ShieldingPAS.RowCounter[ShieldingPAS.MatrixCounter]+10 << "]\\" << endl; 399 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 400 output << "'ShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1+" << step*(double)BondOrder << "):7 with boxes, \\" << endl; 401 output2 << "'DeltaShieldingsPAS-Order.dat' index " << BondOrder << " title 'Order " << BondOrder+1 << "' using ($1):7 with linespoints"; 402 if (BondOrder-1 != KeySet.Order) 403 output2 << ", \\" << endl; 404 } 405 output << "'ShieldingsPAS-Order.dat' index " << KeySet.Order << " title 'Full' using ($1+" << step*(double)KeySet.Order << "):7 with boxes" << endl; 406 output.close(); 407 output2.close(); 408 } 409 410 // create Makefile 411 if(!OpenOutputFile(output, argv[3], "Makefile")) return 1; 412 output << "PYX = $(shell ls *.pyx)" << endl << endl; 413 output << "EPS = $(PYX:.pyx=.eps)" << endl << endl; 414 output << "%.eps: %.pyx" << endl; 415 output << "\t~/build/pyxplot/pyxplot $<" << endl << endl; 416 output << "all: $(EPS)" << endl << endl; 417 output << ".PHONY: clean" << endl; 418 output << "clean:" << endl; 419 output << "\trm -rf $(EPS)" << endl; 420 output.close(); 421 422 // ++++++++++++++++ exit ++++++++++++++++++++++++++++++++++ 423 delete(periode); 424 Free((void **)&dir, "main: *dir"); 425 cout << "done." << endl; 426 return 0; 427 427 }; 428 428 -
Property mode
changed from
-
src/atom.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 14 14 { 15 15 Name = NULL; 16 previous = NULL;17 next = NULL;18 father = this;// generally, father is itself19 Ancestor = NULL;20 type = NULL;21 sort = NULL;22 FixedIon = 0;23 nr = -1;24 GraphNr = -1;25 ComponentNr = NULL;26 IsCyclic = false;27 SeparationVertex = false;28 LowpointNr = -1;29 AdaptiveOrder = 0;30 MaxOrder = false;16 previous = NULL; 17 next = NULL; 18 father = this; // generally, father is itself 19 Ancestor = NULL; 20 type = NULL; 21 sort = NULL; 22 FixedIon = 0; 23 nr = -1; 24 GraphNr = -1; 25 ComponentNr = NULL; 26 IsCyclic = false; 27 SeparationVertex = false; 28 LowpointNr = -1; 29 AdaptiveOrder = 0; 30 MaxOrder = false; 31 31 }; 32 32 … … 36 36 { 37 37 Free((void **)&Name, "atom::~atom: *Name"); 38 Free((void **)&ComponentNr, "atom::~atom: *ComponentNr");38 Free((void **)&ComponentNr, "atom::~atom: *ComponentNr"); 39 39 }; 40 40 … … 45 45 atom *atom::GetTrueFather() 46 46 { 47 atom *walker = this;48 do {49 if (walker == walker->father) // top most father is the one that points on itself50 break;51 walker = walker->father;52 } while (walker != NULL);53 return walker;47 atom *walker = this; 48 do { 49 if (walker == walker->father) // top most father is the one that points on itself 50 break; 51 walker = walker->father; 52 } while (walker != NULL); 53 return walker; 54 54 }; 55 55 … … 61 61 bool atom::Output(int ElementNo, int AtomNo, ofstream *out) const 62 62 { 63 if (out != NULL) {64 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"<< fixed << setprecision(9) << showpoint;65 *out << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2];66 *out << "\t" << FixedIon;67 if (v.Norm() > MYEPSILON)68 *out << "\t" << scientific << setprecision(6) << v.x[0] << "\t" << v.x[1] << "\t" << v.x[2] << "\t";69 *out << " # Number in molecule " << nr << endl;70 return true;71 } else72 return false;63 if (out != NULL) { 64 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t" << fixed << setprecision(9) << showpoint; 65 *out << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2]; 66 *out << "\t" << FixedIon; 67 if (v.Norm() > MYEPSILON) 68 *out << "\t" << scientific << setprecision(6) << v.x[0] << "\t" << v.x[1] << "\t" << v.x[2] << "\t"; 69 *out << " # Number in molecule " << nr << endl; 70 return true; 71 } else 72 return false; 73 73 }; 74 74 … … 78 78 bool atom::OutputXYZLine(ofstream *out) const 79 79 { 80 if (out != NULL) {81 *out << type->symbol << "\t" << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2] << "\t" << endl;82 return true;83 } else84 return false;80 if (out != NULL) { 81 *out << type->symbol << "\t" << x.x[0] << "\t" << x.x[1] << "\t" << x.x[2] << "\t" << endl; 82 return true; 83 } else 84 return false; 85 85 }; 86 86 87 87 ostream & operator << (ostream &ost, atom &a) 88 88 { 89 ost << "[" << a.Name << "|" << &a << "]";90 return ost;89 ost << "[" << a.Name << "|" << &a << "]"; 90 return ost; 91 91 }; 92 92 … … 97 97 bool atom::Compare(atom &ptr) 98 98 { 99 if (nr < ptr.nr)100 return true;101 else102 return false;99 if (nr < ptr.nr) 100 return true; 101 else 102 return false; 103 103 }; 104 104 105 105 bool operator < (atom &a, atom &b) 106 106 { 107 return a.Compare(b);107 return a.Compare(b); 108 108 }; 109 109 -
Property mode
changed from
-
src/bond.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 16 16 leftatom = NULL; 17 17 rightatom = NULL; 18 previous = NULL;19 next = NULL;18 previous = NULL; 19 next = NULL; 20 20 nr = -1; 21 21 HydrogenBond = 0; 22 22 BondDegree = 0; 23 Used = white;24 Cyclic = false;25 Type = Undetermined;23 Used = white; 24 Cyclic = false; 25 Type = Undetermined; 26 26 }; 27 27 … … 36 36 leftatom = left; 37 37 rightatom = right; 38 previous = NULL;39 next = NULL;38 previous = NULL; 39 next = NULL; 40 40 HydrogenBond = 0; 41 if ((left != NULL) && (right != NULL)) {42 if ((left->type != NULL) && (left->type->Z == 1))43 HydrogenBond++;44 if ((right->type != NULL) && (right->type->Z == 1))45 HydrogenBond++;46 }47 BondDegree = degree;48 nr = number;49 Used = white;50 Cyclic = false;41 if ((left != NULL) && (right != NULL)) { 42 if ((left->type != NULL) && (left->type->Z == 1)) 43 HydrogenBond++; 44 if ((right->type != NULL) && (right->type->Z == 1)) 45 HydrogenBond++; 46 } 47 BondDegree = degree; 48 nr = number; 49 Used = white; 50 Cyclic = false; 51 51 }; 52 52 bond::bond(atom *left, atom *right) 53 53 { 54 leftatom = left;55 rightatom = right;56 previous = NULL;57 next = NULL;58 HydrogenBond = 0;59 if ((left != NULL) && (right != NULL)) {60 if ((left->type != NULL) && (left->type->Z == 1))61 HydrogenBond++;62 if ((right->type != NULL) && (right->type->Z == 1))63 HydrogenBond++;64 }65 BondDegree = 1;66 nr = 0;67 Used = white;68 Cyclic = false;54 leftatom = left; 55 rightatom = right; 56 previous = NULL; 57 next = NULL; 58 HydrogenBond = 0; 59 if ((left != NULL) && (right != NULL)) { 60 if ((left->type != NULL) && (left->type->Z == 1)) 61 HydrogenBond++; 62 if ((right->type != NULL) && (right->type->Z == 1)) 63 HydrogenBond++; 64 } 65 BondDegree = 1; 66 nr = 0; 67 Used = white; 68 Cyclic = false; 69 69 }; 70 70 … … 73 73 bond::~bond() 74 74 { 75 // remove this node from the list structure76 if (previous != NULL) {77 previous->next = next;78 }79 if (next != NULL) {80 next->previous = previous;81 }75 // remove this node from the list structure 76 if (previous != NULL) { 77 previous->next = next; 78 } 79 if (next != NULL) { 80 next->previous = previous; 81 } 82 82 }; 83 83 84 84 ostream & operator << (ostream &ost, bond &b) 85 85 { 86 ost << "[" << b.leftatom->Name << " <" << b.BondDegree << "(H" << b.HydrogenBond << ")>" << b.rightatom->Name << "]";87 return ost;86 ost << "[" << b.leftatom->Name << " <" << b.BondDegree << "(H" << b.HydrogenBond << ")>" << b.rightatom->Name << "]"; 87 return ost; 88 88 }; 89 89 … … 94 94 atom * bond::GetOtherAtom(atom *Atom) const 95 95 { 96 if(leftatom == Atom)97 return rightatom;98 if(rightatom == Atom)99 return leftatom;100 return NULL;96 if(leftatom == Atom) 97 return rightatom; 98 if(rightatom == Atom) 99 return leftatom; 100 return NULL; 101 101 }; 102 102 … … 107 107 bond * bond::GetFirstBond() 108 108 { 109 return GetFirst(this);109 return GetFirst(this); 110 110 }; 111 111 … … 116 116 bond * bond::GetLastBond() 117 117 { 118 return GetLast(this);118 return GetLast(this); 119 119 }; 120 120 … … 124 124 enum Shading bond::IsUsed() 125 125 { 126 return Used;126 return Used; 127 127 }; 128 128 … … 133 133 bool bond::Contains(const atom *ptr) 134 134 { 135 return ((leftatom == ptr) || (rightatom == ptr));135 return ((leftatom == ptr) || (rightatom == ptr)); 136 136 }; 137 137 … … 142 142 bool bond::Contains(const int number) 143 143 { 144 return ((leftatom->nr == number) || (rightatom->nr == number));144 return ((leftatom->nr == number) || (rightatom->nr == number)); 145 145 }; 146 146 … … 149 149 */ 150 150 bool bond::MarkUsed(enum Shading color) { 151 if (Used == black) {152 cerr << "ERROR: Bond " << this << " was already marked black!." << endl;153 return false;154 } else {155 Used = color;156 return true;157 }151 if (Used == black) { 152 cerr << "ERROR: Bond " << this << " was already marked black!." << endl; 153 return false; 154 } else { 155 Used = color; 156 return true; 157 } 158 158 }; 159 159 … … 162 162 */ 163 163 void bond::ResetUsed() { 164 Used = white;164 Used = white; 165 165 }; -
Property mode
changed from
-
src/boundary.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 1 #include "molecules.hpp"2 1 #include "boundary.hpp" 3 2 4 3 #define DEBUG 1 5 #define DoTecplotOutput 0 4 #define DoSingleStepOutput 0 5 #define DoTecplotOutput 1 6 6 #define DoRaster3DOutput 1 7 #define DoVRMLOutput 1 7 8 #define TecplotSuffix ".dat" 8 9 #define Raster3DSuffix ".r3d" 10 #define VRMLSUffix ".wrl" 11 #define HULLEPSILON MYEPSILON 9 12 10 13 // ======================================== Points on Boundary ================================= … … 12 15 BoundaryPointSet::BoundaryPointSet() 13 16 { 14 LinesCount = 0;15 Nr = -1;17 LinesCount = 0; 18 Nr = -1; 16 19 } 17 20 ; … … 19 22 BoundaryPointSet::BoundaryPointSet(atom *Walker) 20 23 { 21 node = Walker;22 LinesCount = 0;23 Nr = Walker->nr;24 node = Walker; 25 LinesCount = 0; 26 Nr = Walker->nr; 24 27 } 25 28 ; … … 27 30 BoundaryPointSet::~BoundaryPointSet() 28 31 { 29 cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl; 30 node = NULL; 31 } 32 ; 33 34 void 35 BoundaryPointSet::AddLine(class BoundaryLineSet *line) 36 { 37 cout << Verbose(6) << "Adding " << *this << " to line " << *line << "." 38 << endl; 39 if (line->endpoints[0] == this) 40 { 41 lines.insert(LinePair(line->endpoints[1]->Nr, line)); 42 } 43 else 44 { 45 lines.insert(LinePair(line->endpoints[0]->Nr, line)); 46 } 47 LinesCount++; 32 cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl; 33 if (!lines.empty()) 34 cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl; 35 node = NULL; 36 } 37 ; 38 39 void BoundaryPointSet::AddLine(class BoundaryLineSet *line) 40 { 41 cout << Verbose(6) << "Adding " << *this << " to line " << *line << "." 42 << endl; 43 if (line->endpoints[0] == this) 44 { 45 lines.insert(LinePair(line->endpoints[1]->Nr, line)); 46 } 47 else 48 { 49 lines.insert(LinePair(line->endpoints[0]->Nr, line)); 50 } 51 LinesCount++; 48 52 } 49 53 ; … … 52 56 operator <<(ostream &ost, BoundaryPointSet &a) 53 57 { 54 ost << "[" << a.Nr << "|" << a.node->Name << "]";55 return ost;58 ost << "[" << a.Nr << "|" << a.node->Name << "]"; 59 return ost; 56 60 } 57 61 ; … … 61 65 BoundaryLineSet::BoundaryLineSet() 62 66 { 63 for (int i = 0; i < 2; i++)64 endpoints[i] = NULL;65 TrianglesCount = 0;66 Nr = -1;67 for (int i = 0; i < 2; i++) 68 endpoints[i] = NULL; 69 TrianglesCount = 0; 70 Nr = -1; 67 71 } 68 72 ; … … 70 74 BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number) 71 75 { 72 // set number73 Nr = number;74 // set endpoints in ascending order75 SetEndpointsOrdered(endpoints, Point[0], Point[1]);76 // add this line to the hash maps of both endpoints77 Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding.78 Point[1]->AddLine(this); //79 // clear triangles list80 TrianglesCount = 0;81 cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl;76 // set number 77 Nr = number; 78 // set endpoints in ascending order 79 SetEndpointsOrdered(endpoints, Point[0], Point[1]); 80 // add this line to the hash maps of both endpoints 81 Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding. 82 Point[1]->AddLine(this); // 83 // clear triangles list 84 TrianglesCount = 0; 85 cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl; 82 86 } 83 87 ; … … 85 89 BoundaryLineSet::~BoundaryLineSet() 86 90 { 87 for (int i = 0; i < 2; i++) 88 { 89 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " 90 << *endpoints[i] << "." << endl; 91 endpoints[i]->lines.erase(Nr); 92 LineMap::iterator tester = endpoints[i]->lines.begin(); 93 tester++; 94 if (tester == endpoints[i]->lines.end()) 95 { 96 cout << Verbose(5) << *endpoints[i] 97 << " has no more lines it's attached to, erasing." << endl; 98 //delete(endpoints[i]); 99 } 100 else 101 cout << Verbose(5) << *endpoints[i] 102 << " has still lines it's attached to." << endl; 103 } 91 int Numbers[2]; 92 Numbers[0] = endpoints[1]->Nr; 93 Numbers[1] = endpoints[0]->Nr; 94 for (int i = 0; i < 2; i++) { 95 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 96 endpoints[i]->lines.erase(Numbers[i]); 97 if (endpoints[i]->lines.empty()) { 98 cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl; 99 if (endpoints[i] != NULL) { 100 delete(endpoints[i]); 101 endpoints[i] = NULL; 102 } else 103 cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl; 104 } else 105 cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl; 106 } 107 if (!triangles.empty()) 108 cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some triangles." << endl; 104 109 } 105 110 ; … … 108 113 BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 109 114 { 110 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "."111 << endl;112 triangles.insert(TrianglePair(TrianglesCount, triangle));113 TrianglesCount++;115 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." 116 << endl; 117 triangles.insert(TrianglePair(triangle->Nr, triangle)); 118 TrianglesCount++; 114 119 } 115 120 ; … … 118 123 operator <<(ostream &ost, BoundaryLineSet &a) 119 124 { 120 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","121 << a.endpoints[1]->node->Name << "]";122 return ost;125 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 126 << a.endpoints[1]->node->Name << "]"; 127 return ost; 123 128 } 124 129 ; … … 129 134 BoundaryTriangleSet::BoundaryTriangleSet() 130 135 { 131 for (int i = 0; i < 3; i++)132 {133 endpoints[i] = NULL;134 lines[i] = NULL;135 }136 Nr = -1;136 for (int i = 0; i < 3; i++) 137 { 138 endpoints[i] = NULL; 139 lines[i] = NULL; 140 } 141 Nr = -1; 137 142 } 138 143 ; 139 144 140 145 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], 141 int number)142 { 143 // set number144 Nr = number;145 // set lines146 cout << Verbose(5) << "New triangle " << Nr << ":" << endl;147 for (int i = 0; i < 3; i++)148 {149 lines[i] = line[i];150 lines[i]->AddTriangle(this);151 }152 // get ascending order of endpoints153 map<int, class BoundaryPointSet *> OrderMap;154 for (int i = 0; i < 3; i++)155 // for all three lines156 for (int j = 0; j < 2; j++)157 { // for both endpoints158 OrderMap.insert(pair<int, class BoundaryPointSet *> (159 line[i]->endpoints[j]->Nr, line[i]->endpoints[j]));160 // and we don't care whether insertion fails161 }162 // set endpoints163 int Counter = 0;164 cout << Verbose(6) << " with end points ";165 for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner166 != OrderMap.end(); runner++)167 {168 endpoints[Counter] = runner->second;169 cout << " " << *endpoints[Counter];170 Counter++;171 }172 if (Counter < 3)173 {174 cerr << "ERROR! We have a triangle with only two distinct endpoints!"175 << endl;176 //exit(1);177 }178 cout << "." << endl;146 int number) 147 { 148 // set number 149 Nr = number; 150 // set lines 151 cout << Verbose(5) << "New triangle " << Nr << ":" << endl; 152 for (int i = 0; i < 3; i++) 153 { 154 lines[i] = line[i]; 155 lines[i]->AddTriangle(this); 156 } 157 // get ascending order of endpoints 158 map<int, class BoundaryPointSet *> OrderMap; 159 for (int i = 0; i < 3; i++) 160 // for all three lines 161 for (int j = 0; j < 2; j++) 162 { // for both endpoints 163 OrderMap.insert(pair<int, class BoundaryPointSet *> ( 164 line[i]->endpoints[j]->Nr, line[i]->endpoints[j])); 165 // and we don't care whether insertion fails 166 } 167 // set endpoints 168 int Counter = 0; 169 cout << Verbose(6) << " with end points "; 170 for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner 171 != OrderMap.end(); runner++) 172 { 173 endpoints[Counter] = runner->second; 174 cout << " " << *endpoints[Counter]; 175 Counter++; 176 } 177 if (Counter < 3) 178 { 179 cerr << "ERROR! We have a triangle with only two distinct endpoints!" 180 << endl; 181 //exit(1); 182 } 183 cout << "." << endl; 179 184 } 180 185 ; … … 182 187 BoundaryTriangleSet::~BoundaryTriangleSet() 183 188 { 184 for (int i = 0; i < 3; i++) 185 { 186 cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl; 187 lines[i]->triangles.erase(Nr); 188 TriangleMap::iterator tester = lines[i]->triangles.begin(); 189 tester++; 190 if (tester == lines[i]->triangles.end()) 191 { 192 cout << Verbose(5) << *lines[i] 193 << " is no more attached to any triangle, erasing." << endl; 194 delete (lines[i]); 195 } 196 else 197 cout << Verbose(5) << *lines[i] << " is still attached to a triangle." 198 << endl; 199 } 189 for (int i = 0; i < 3; i++) { 190 cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl; 191 lines[i]->triangles.erase(Nr); 192 if (lines[i]->triangles.empty()) { 193 cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl; 194 if (lines[i] != NULL) { 195 delete (lines[i]); 196 lines[i] = NULL; 197 } else 198 cerr << "ERROR: This line " << i << " has already been free'd." << endl; 199 } else 200 cout << Verbose(5) << *lines[i] << " is still attached to a triangle." << endl; 201 } 200 202 } 201 203 ; … … 204 206 BoundaryTriangleSet::GetNormalVector(Vector &OtherVector) 205 207 { 206 // get normal vector207 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x,208 &endpoints[2]->node->x);209 210 // make it always point inward (any offset vector onto plane projected onto normal vector suffices)211 if (endpoints[0]->node->x.Projection(&OtherVector) > 0)212 NormalVector.Scale(-1.);208 // get normal vector 209 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, 210 &endpoints[2]->node->x); 211 212 // make it always point inward (any offset vector onto plane projected onto normal vector suffices) 213 if (NormalVector.Projection(&OtherVector) > 0) 214 NormalVector.Scale(-1.); 213 215 } 214 216 ; … … 217 219 operator <<(ostream &ost, BoundaryTriangleSet &a) 218 220 { 219 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","220 << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]";221 return ost;221 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 222 << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]"; 223 return ost; 222 224 } 223 225 ; … … 233 235 GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2) 234 236 { 235 class BoundaryLineSet * lines[2] =236 { line1, line2 };237 class BoundaryPointSet *node = NULL;238 map<int, class BoundaryPointSet *> OrderMap;239 pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest;240 for (int i = 0; i < 2; i++)241 // for both lines242 for (int j = 0; j < 2; j++)243 { // for both endpoints244 OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> (245 lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]));246 if (!OrderTest.second)247 { // if insertion fails, we have common endpoint248 node = OrderTest.first->second;249 cout << Verbose(5) << "Common endpoint of lines " << *line1250 << " and " << *line2 << " is: " << *node << "." << endl;251 j = 2;252 i = 2;253 break;254 }255 }256 return node;237 class BoundaryLineSet * lines[2] = 238 { line1, line2 }; 239 class BoundaryPointSet *node = NULL; 240 map<int, class BoundaryPointSet *> OrderMap; 241 pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest; 242 for (int i = 0; i < 2; i++) 243 // for both lines 244 for (int j = 0; j < 2; j++) 245 { // for both endpoints 246 OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> ( 247 lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j])); 248 if (!OrderTest.second) 249 { // if insertion fails, we have common endpoint 250 node = OrderTest.first->second; 251 cout << Verbose(5) << "Common endpoint of lines " << *line1 252 << " and " << *line2 << " is: " << *node << "." << endl; 253 j = 2; 254 i = 2; 255 break; 256 } 257 } 258 return node; 257 259 } 258 260 ; … … 268 270 GetBoundaryPoints(ofstream *out, molecule *mol) 269 271 { 270 atom *Walker = NULL;271 PointMap PointsOnBoundary;272 LineMap LinesOnBoundary;273 TriangleMap TrianglesOnBoundary;274 275 *out << Verbose(1) << "Finding all boundary points." << endl;276 Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr)277 BoundariesTestPair BoundaryTestPair;278 Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector;279 double radius, angle;280 // 3a. Go through every axis281 for (int axis = 0; axis < NDIM; axis++)282 {283 AxisVector.Zero();284 AngleReferenceVector.Zero();285 AngleReferenceNormalVector.Zero();286 AxisVector.x[axis] = 1.;287 AngleReferenceVector.x[(axis + 1) % NDIM] = 1.;288 AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.;289 //*out << Verbose(1) << "Axisvector is ";290 //AxisVector.Output(out);291 //*out << " and AngleReferenceVector is ";292 //AngleReferenceVector.Output(out);293 //*out << "." << endl;294 //*out << " and AngleReferenceNormalVector is ";295 //AngleReferenceNormalVector.Output(out);296 //*out << "." << endl;297 // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours298 Walker = mol->start;299 while (Walker->next != mol->end)300 {301 Walker = Walker->next;302 Vector ProjectedVector;303 ProjectedVector.CopyVector(&Walker->x);304 ProjectedVector.ProjectOntoPlane(&AxisVector);305 // correct for negative side306 //if (Projection(y) < 0)307 //angle = 2.*M_PI - angle;308 radius = ProjectedVector.Norm();309 if (fabs(radius) > MYEPSILON)310 angle = ProjectedVector.Angle(&AngleReferenceVector);311 else312 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues313 314 //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;315 if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0)316 {317 angle = 2. * M_PI - angle;318 }319 //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): ";320 //ProjectedVector.Output(out);321 //*out << endl;322 BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle,323 DistancePair (radius, Walker)));324 if (BoundaryTestPair.second)325 { // successfully inserted326 }327 else328 { // same point exists, check first r, then distance of original vectors to center of gravity329 *out << Verbose(2)330 << "Encountered two vectors whose projection onto axis "331 << axis << " is equal: " << endl;332 *out << Verbose(2) << "Present vector: ";333 BoundaryTestPair.first->second.second->x.Output(out);334 *out << endl;335 *out << Verbose(2) << "New vector: ";336 Walker->x.Output(out);337 *out << endl;338 double tmp = ProjectedVector.Norm();339 if (tmp > BoundaryTestPair.first->second.first)340 {341 BoundaryTestPair.first->second.first = tmp;342 BoundaryTestPair.first->second.second = Walker;343 *out << Verbose(2) << "Keeping new vector." << endl;344 }345 else if (tmp == BoundaryTestPair.first->second.first)346 {347 if (BoundaryTestPair.first->second.second->x.ScalarProduct(348 &BoundaryTestPair.first->second.second->x)349 < Walker->x.ScalarProduct(&Walker->x))350 { // Norm() does a sqrt, which makes it a lot slower351 BoundaryTestPair.first->second.second = Walker;352 *out << Verbose(2) << "Keeping new vector." << endl;353 }354 else355 {356 *out << Verbose(2) << "Keeping present vector." << endl;357 }358 }359 else360 {361 *out << Verbose(2) << "Keeping present vector." << endl;362 }363 }364 }365 // printing all inserted for debugging366 //{367 //*out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;368 //int i=0;369 //for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {370 //if (runner != BoundaryPoints[axis].begin())371 //*out << ", " << i << ": " << *runner->second.second;372 //else373 //*out << i << ": " << *runner->second.second;374 //i++;375 //}376 //*out << endl;377 //}378 // 3c. throw out points whose distance is less than the mean of left and right neighbours379 bool flag = false;380 do381 { // do as long as we still throw one out per round382 *out << Verbose(1)383 << "Looking for candidates to kick out by convex condition ... "384 << endl;385 flag = false;386 Boundaries::iterator left = BoundaryPoints[axis].end();387 Boundaries::iterator right = BoundaryPoints[axis].end();388 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner389 != BoundaryPoints[axis].end(); runner++)390 {391 // set neighbours correctly392 if (runner == BoundaryPoints[axis].begin())393 {394 left = BoundaryPoints[axis].end();395 }396 else397 {398 left = runner;399 }400 left--;401 right = runner;402 right++;403 if (right == BoundaryPoints[axis].end())404 {405 right = BoundaryPoints[axis].begin();406 }407 // check distance408 409 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)410 {411 Vector SideA, SideB, SideC, SideH;412 SideA.CopyVector(&left->second.second->x);413 SideA.ProjectOntoPlane(&AxisVector);414 //*out << "SideA: ";415 //SideA.Output(out);416 //*out << endl;417 418 SideB.CopyVector(&right->second.second->x);419 SideB.ProjectOntoPlane(&AxisVector);420 //*out << "SideB: ";421 //SideB.Output(out);422 //*out << endl;423 424 SideC.CopyVector(&left->second.second->x);425 SideC.SubtractVector(&right->second.second->x);426 SideC.ProjectOntoPlane(&AxisVector);427 //*out << "SideC: ";428 //SideC.Output(out);429 //*out << endl;430 431 SideH.CopyVector(&runner->second.second->x);432 SideH.ProjectOntoPlane(&AxisVector);433 //*out << "SideH: ";434 //SideH.Output(out);435 //*out << endl;436 437 // calculate each length438 double a = SideA.Norm();439 //double b = SideB.Norm();440 //double c = SideC.Norm();441 double h = SideH.Norm();442 // calculate the angles443 double alpha = SideA.Angle(&SideH);444 double beta = SideA.Angle(&SideC);445 double gamma = SideB.Angle(&SideH);446 double delta = SideC.Angle(&SideH);447 double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha448 < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);449 //*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;450 //*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;451 if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance))452 < MYEPSILON) && (h < MinDistance))453 {454 // throw out point455 //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;456 BoundaryPoints[axis].erase(runner);457 flag = true;458 }459 }460 }461 }462 while (flag);463 }464 return BoundaryPoints;272 atom *Walker = NULL; 273 PointMap PointsOnBoundary; 274 LineMap LinesOnBoundary; 275 TriangleMap TrianglesOnBoundary; 276 277 *out << Verbose(1) << "Finding all boundary points." << endl; 278 Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr) 279 BoundariesTestPair BoundaryTestPair; 280 Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector; 281 double radius, angle; 282 // 3a. Go through every axis 283 for (int axis = 0; axis < NDIM; axis++) 284 { 285 AxisVector.Zero(); 286 AngleReferenceVector.Zero(); 287 AngleReferenceNormalVector.Zero(); 288 AxisVector.x[axis] = 1.; 289 AngleReferenceVector.x[(axis + 1) % NDIM] = 1.; 290 AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.; 291 // *out << Verbose(1) << "Axisvector is "; 292 // AxisVector.Output(out); 293 // *out << " and AngleReferenceVector is "; 294 // AngleReferenceVector.Output(out); 295 // *out << "." << endl; 296 // *out << " and AngleReferenceNormalVector is "; 297 // AngleReferenceNormalVector.Output(out); 298 // *out << "." << endl; 299 // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours 300 Walker = mol->start; 301 while (Walker->next != mol->end) 302 { 303 Walker = Walker->next; 304 Vector ProjectedVector; 305 ProjectedVector.CopyVector(&Walker->x); 306 ProjectedVector.ProjectOntoPlane(&AxisVector); 307 // correct for negative side 308 //if (Projection(y) < 0) 309 //angle = 2.*M_PI - angle; 310 radius = ProjectedVector.Norm(); 311 if (fabs(radius) > MYEPSILON) 312 angle = ProjectedVector.Angle(&AngleReferenceVector); 313 else 314 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues 315 316 //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl; 317 if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) 318 { 319 angle = 2. * M_PI - angle; 320 } 321 //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): "; 322 //ProjectedVector.Output(out); 323 //*out << endl; 324 BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle, 325 DistancePair (radius, Walker))); 326 if (BoundaryTestPair.second) 327 { // successfully inserted 328 } 329 else 330 { // same point exists, check first r, then distance of original vectors to center of gravity 331 *out << Verbose(2) 332 << "Encountered two vectors whose projection onto axis " 333 << axis << " is equal: " << endl; 334 *out << Verbose(2) << "Present vector: "; 335 BoundaryTestPair.first->second.second->x.Output(out); 336 *out << endl; 337 *out << Verbose(2) << "New vector: "; 338 Walker->x.Output(out); 339 *out << endl; 340 double tmp = ProjectedVector.Norm(); 341 if (tmp > BoundaryTestPair.first->second.first) 342 { 343 BoundaryTestPair.first->second.first = tmp; 344 BoundaryTestPair.first->second.second = Walker; 345 *out << Verbose(2) << "Keeping new vector." << endl; 346 } 347 else if (tmp == BoundaryTestPair.first->second.first) 348 { 349 if (BoundaryTestPair.first->second.second->x.ScalarProduct( 350 &BoundaryTestPair.first->second.second->x) 351 < Walker->x.ScalarProduct(&Walker->x)) 352 { // Norm() does a sqrt, which makes it a lot slower 353 BoundaryTestPair.first->second.second = Walker; 354 *out << Verbose(2) << "Keeping new vector." << endl; 355 } 356 else 357 { 358 *out << Verbose(2) << "Keeping present vector." << endl; 359 } 360 } 361 else 362 { 363 *out << Verbose(2) << "Keeping present vector." << endl; 364 } 365 } 366 } 367 // printing all inserted for debugging 368 // { 369 // *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl; 370 // int i=0; 371 // for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 372 // if (runner != BoundaryPoints[axis].begin()) 373 // *out << ", " << i << ": " << *runner->second.second; 374 // else 375 // *out << i << ": " << *runner->second.second; 376 // i++; 377 // } 378 // *out << endl; 379 // } 380 // 3c. throw out points whose distance is less than the mean of left and right neighbours 381 bool flag = false; 382 do 383 { // do as long as we still throw one out per round 384 *out << Verbose(1) 385 << "Looking for candidates to kick out by convex condition ... " 386 << endl; 387 flag = false; 388 Boundaries::iterator left = BoundaryPoints[axis].end(); 389 Boundaries::iterator right = BoundaryPoints[axis].end(); 390 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 391 != BoundaryPoints[axis].end(); runner++) 392 { 393 // set neighbours correctly 394 if (runner == BoundaryPoints[axis].begin()) 395 { 396 left = BoundaryPoints[axis].end(); 397 } 398 else 399 { 400 left = runner; 401 } 402 left--; 403 right = runner; 404 right++; 405 if (right == BoundaryPoints[axis].end()) 406 { 407 right = BoundaryPoints[axis].begin(); 408 } 409 // check distance 410 411 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector) 412 { 413 Vector SideA, SideB, SideC, SideH; 414 SideA.CopyVector(&left->second.second->x); 415 SideA.ProjectOntoPlane(&AxisVector); 416 // *out << "SideA: "; 417 // SideA.Output(out); 418 // *out << endl; 419 420 SideB.CopyVector(&right->second.second->x); 421 SideB.ProjectOntoPlane(&AxisVector); 422 // *out << "SideB: "; 423 // SideB.Output(out); 424 // *out << endl; 425 426 SideC.CopyVector(&left->second.second->x); 427 SideC.SubtractVector(&right->second.second->x); 428 SideC.ProjectOntoPlane(&AxisVector); 429 // *out << "SideC: "; 430 // SideC.Output(out); 431 // *out << endl; 432 433 SideH.CopyVector(&runner->second.second->x); 434 SideH.ProjectOntoPlane(&AxisVector); 435 // *out << "SideH: "; 436 // SideH.Output(out); 437 // *out << endl; 438 439 // calculate each length 440 double a = SideA.Norm(); 441 //double b = SideB.Norm(); 442 //double c = SideC.Norm(); 443 double h = SideH.Norm(); 444 // calculate the angles 445 double alpha = SideA.Angle(&SideH); 446 double beta = SideA.Angle(&SideC); 447 double gamma = SideB.Angle(&SideH); 448 double delta = SideC.Angle(&SideH); 449 double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha 450 < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.); 451 // *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; 452 //*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; 453 if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance)) 454 < MYEPSILON) && (h < MinDistance)) 455 { 456 // throw out point 457 //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl; 458 BoundaryPoints[axis].erase(runner); 459 flag = true; 460 } 461 } 462 } 463 } 464 while (flag); 465 } 466 return BoundaryPoints; 465 467 } 466 468 ; … … 476 478 double * 477 479 GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, 478 bool IsAngstroem)479 { 480 // get points on boundary of NULL was given as parameter481 bool BoundaryFreeFlag = false;482 Boundaries *BoundaryPoints = BoundaryPtr;483 if (BoundaryPoints == NULL)484 {485 BoundaryFreeFlag = true;486 BoundaryPoints = GetBoundaryPoints(out, mol);487 }488 else489 {490 *out << Verbose(1) << "Using given boundary points set." << endl;491 }492 // determine biggest "diameter" of cluster for each axis493 Boundaries::iterator Neighbour, OtherNeighbour;494 double *GreatestDiameter = new double[NDIM];495 for (int i = 0; i < NDIM; i++)496 GreatestDiameter[i] = 0.;497 double OldComponent, tmp, w1, w2;498 Vector DistanceVector, OtherVector;499 int component, Othercomponent;500 for (int axis = 0; axis < NDIM; axis++)501 { // regard each projected plane502 //*out << Verbose(1) << "Current axis is " << axis << "." << endl;503 for (int j = 0; j < 2; j++)504 { // and for both axis on the current plane505 component = (axis + j + 1) % NDIM;506 Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM;507 //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl;508 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner509 != BoundaryPoints[axis].end(); runner++)510 {511 //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl;512 // seek for the neighbours pair where the Othercomponent sign flips513 Neighbour = runner;514 Neighbour++;515 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around516 Neighbour = BoundaryPoints[axis].begin();517 DistanceVector.CopyVector(&runner->second.second->x);518 DistanceVector.SubtractVector(&Neighbour->second.second->x);519 do520 { // seek for neighbour pair where it flips521 OldComponent = DistanceVector.x[Othercomponent];522 Neighbour++;523 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around524 Neighbour = BoundaryPoints[axis].begin();525 DistanceVector.CopyVector(&runner->second.second->x);526 DistanceVector.SubtractVector(&Neighbour->second.second->x);527 //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl;528 }529 while ((runner != Neighbour) && (fabs(OldComponent / fabs(530 OldComponent) - DistanceVector.x[Othercomponent] / fabs(531 DistanceVector.x[Othercomponent])) < MYEPSILON)); // as long as sign does not flip532 if (runner != Neighbour)533 {534 OtherNeighbour = Neighbour;535 if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around536 OtherNeighbour = BoundaryPoints[axis].end();537 OtherNeighbour--;538 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl;539 // now we have found the pair: Neighbour and OtherNeighbour540 OtherVector.CopyVector(&runner->second.second->x);541 OtherVector.SubtractVector(&OtherNeighbour->second.second->x);542 //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl;543 //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl;544 // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour545 w1 = fabs(OtherVector.x[Othercomponent]);546 w2 = fabs(DistanceVector.x[Othercomponent]);547 tmp = fabs((w1 * DistanceVector.x[component] + w2548 * OtherVector.x[component]) / (w1 + w2));549 // mark if it has greater diameter550 //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl;551 GreatestDiameter[component] = (GreatestDiameter[component]552 > tmp) ? GreatestDiameter[component] : tmp;553 } //else554 //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl;555 }556 }557 }558 *out << Verbose(0) << "RESULT: The biggest diameters are "559 << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and "560 << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom"561 : "atomiclength") << "." << endl;562 563 // free reference lists564 if (BoundaryFreeFlag)565 delete[] (BoundaryPoints);566 567 return GreatestDiameter;568 } 569 ; 570 571 /** Creates the objects in a raster3d file (renderable with a header.r3d)480 bool IsAngstroem) 481 { 482 // get points on boundary of NULL was given as parameter 483 bool BoundaryFreeFlag = false; 484 Boundaries *BoundaryPoints = BoundaryPtr; 485 if (BoundaryPoints == NULL) 486 { 487 BoundaryFreeFlag = true; 488 BoundaryPoints = GetBoundaryPoints(out, mol); 489 } 490 else 491 { 492 *out << Verbose(1) << "Using given boundary points set." << endl; 493 } 494 // determine biggest "diameter" of cluster for each axis 495 Boundaries::iterator Neighbour, OtherNeighbour; 496 double *GreatestDiameter = new double[NDIM]; 497 for (int i = 0; i < NDIM; i++) 498 GreatestDiameter[i] = 0.; 499 double OldComponent, tmp, w1, w2; 500 Vector DistanceVector, OtherVector; 501 int component, Othercomponent; 502 for (int axis = 0; axis < NDIM; axis++) 503 { // regard each projected plane 504 //*out << Verbose(1) << "Current axis is " << axis << "." << endl; 505 for (int j = 0; j < 2; j++) 506 { // and for both axis on the current plane 507 component = (axis + j + 1) % NDIM; 508 Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM; 509 //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl; 510 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 511 != BoundaryPoints[axis].end(); runner++) 512 { 513 //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl; 514 // seek for the neighbours pair where the Othercomponent sign flips 515 Neighbour = runner; 516 Neighbour++; 517 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 518 Neighbour = BoundaryPoints[axis].begin(); 519 DistanceVector.CopyVector(&runner->second.second->x); 520 DistanceVector.SubtractVector(&Neighbour->second.second->x); 521 do 522 { // seek for neighbour pair where it flips 523 OldComponent = DistanceVector.x[Othercomponent]; 524 Neighbour++; 525 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 526 Neighbour = BoundaryPoints[axis].begin(); 527 DistanceVector.CopyVector(&runner->second.second->x); 528 DistanceVector.SubtractVector(&Neighbour->second.second->x); 529 //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl; 530 } 531 while ((runner != Neighbour) && (fabs(OldComponent / fabs( 532 OldComponent) - DistanceVector.x[Othercomponent] / fabs( 533 DistanceVector.x[Othercomponent])) < MYEPSILON)); // as long as sign does not flip 534 if (runner != Neighbour) 535 { 536 OtherNeighbour = Neighbour; 537 if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around 538 OtherNeighbour = BoundaryPoints[axis].end(); 539 OtherNeighbour--; 540 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl; 541 // now we have found the pair: Neighbour and OtherNeighbour 542 OtherVector.CopyVector(&runner->second.second->x); 543 OtherVector.SubtractVector(&OtherNeighbour->second.second->x); 544 //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl; 545 //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl; 546 // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour 547 w1 = fabs(OtherVector.x[Othercomponent]); 548 w2 = fabs(DistanceVector.x[Othercomponent]); 549 tmp = fabs((w1 * DistanceVector.x[component] + w2 550 * OtherVector.x[component]) / (w1 + w2)); 551 // mark if it has greater diameter 552 //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl; 553 GreatestDiameter[component] = (GreatestDiameter[component] 554 > tmp) ? GreatestDiameter[component] : tmp; 555 } //else 556 //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl; 557 } 558 } 559 } 560 *out << Verbose(0) << "RESULT: The biggest diameters are " 561 << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and " 562 << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom" 563 : "atomiclength") << "." << endl; 564 565 // free reference lists 566 if (BoundaryFreeFlag) 567 delete[] (BoundaryPoints); 568 569 return GreatestDiameter; 570 } 571 ; 572 573 /** Creates the objects in a VRML file. 572 574 * \param *out output stream for debugging 573 * \param *tecplot output stream for tecplot data 575 * \param *vrmlfile output stream for tecplot data 576 * \param *Tess Tesselation structure with constructed triangles 577 * \param *mol molecule structure with atom positions 578 */ 579 void write_vrml_file(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, class molecule *mol) 580 { 581 atom *Walker = mol->start; 582 bond *Binder = mol->first; 583 int i; 584 Vector *center = mol->DetermineCenterOfAll(out); 585 if (vrmlfile != NULL) { 586 //cout << Verbose(1) << "Writing Raster3D file ... "; 587 *vrmlfile << "#VRML V2.0 utf8" << endl; 588 *vrmlfile << "#Created by molecuilder" << endl; 589 *vrmlfile << "#All atoms as spheres" << endl; 590 while (Walker->next != mol->end) { 591 Walker = Walker->next; 592 *vrmlfile << "Sphere {" << endl << " "; // 2 is sphere type 593 for (i=0;i<NDIM;i++) 594 *vrmlfile << Walker->x.x[i]+center->x[i] << " "; 595 *vrmlfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour 596 } 597 598 *vrmlfile << "# All bonds as vertices" << endl; 599 while (Binder->next != mol->last) { 600 Binder = Binder->next; 601 *vrmlfile << "3" << endl << " "; // 2 is round-ended cylinder type 602 for (i=0;i<NDIM;i++) 603 *vrmlfile << Binder->leftatom->x.x[i]+center->x[i] << " "; 604 *vrmlfile << "\t0.03\t"; 605 for (i=0;i<NDIM;i++) 606 *vrmlfile << Binder->rightatom->x.x[i]+center->x[i] << " "; 607 *vrmlfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour 608 } 609 610 *vrmlfile << "# All tesselation triangles" << endl; 611 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) { 612 *vrmlfile << "1" << endl << " "; // 1 is triangle type 613 for (i=0;i<3;i++) { // print each node 614 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates 615 *vrmlfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " "; 616 *vrmlfile << "\t"; 617 } 618 *vrmlfile << "1. 0. 0." << endl; // red as colour 619 *vrmlfile << "18" << endl << " 0.5 0.5 0.5" << endl; // 18 is transparency type for previous object 620 } 621 } else { 622 cerr << "ERROR: Given vrmlfile is " << vrmlfile << "." << endl; 623 } 624 delete(center); 625 }; 626 627 /** Creates the objects in a raster3d file (renderable with a header.r3d). 628 * \param *out output stream for debugging 629 * \param *rasterfile output stream for tecplot data 574 630 * \param *Tess Tesselation structure with constructed triangles 575 631 * \param *mol molecule structure with atom positions … … 577 633 void write_raster3d_file(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, class molecule *mol) 578 634 { 579 atom *Walker = mol->start; 580 bond *Binder = mol->first; 581 int i; 582 Vector *center = mol->DetermineCenterOfAll(out); 583 if (rasterfile != NULL) { 584 //cout << Verbose(1) << "Writing Raster3D file ... "; 585 *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl; 586 *rasterfile << "@header.r3d" << endl; 587 *rasterfile << "# All atoms as spheres" << endl; 588 while (Walker->next != mol->end) { 589 Walker = Walker->next; 590 *rasterfile << "2" << endl << " "; // 2 is sphere type 591 for (i=0;i<NDIM;i++) 592 *rasterfile << Walker->x.x[i]+center->x[i] << " "; 593 *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour 594 } 595 596 *rasterfile << "# All bonds as vertices" << endl; 597 while (Binder->next != mol->last) { 598 Binder = Binder->next; 599 *rasterfile << "3" << endl << " "; // 2 is round-ended cylinder type 600 for (i=0;i<NDIM;i++) 601 *rasterfile << Binder->leftatom->x.x[i]+center->x[i] << " "; 602 *rasterfile << "\t0.03\t"; 603 for (i=0;i<NDIM;i++) 604 *rasterfile << Binder->rightatom->x.x[i]+center->x[i] << " "; 605 *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour 606 } 607 608 *rasterfile << "# All tesselation triangles" << endl; 609 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) { 610 *rasterfile << "1" << endl << " "; // 1 is triangle type 611 for (i=0;i<3;i++) { // print each node 612 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates 613 *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " "; 614 *rasterfile << "\t"; 615 } 616 *rasterfile << "1. 0. 0." << endl; // red as colour 617 *rasterfile << "18" << endl << " 0.5 0.5 0.5" << endl; // 18 is transparency type for previous object 618 } 619 } else { 620 cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl; 621 } 622 delete(center); 635 atom *Walker = mol->start; 636 bond *Binder = mol->first; 637 int i; 638 Vector *center = mol->DetermineCenterOfAll(out); 639 if (rasterfile != NULL) { 640 //cout << Verbose(1) << "Writing Raster3D file ... "; 641 *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl; 642 *rasterfile << "@header.r3d" << endl; 643 *rasterfile << "# All atoms as spheres" << endl; 644 while (Walker->next != mol->end) { 645 Walker = Walker->next; 646 *rasterfile << "2" << endl << " "; // 2 is sphere type 647 for (i=0;i<NDIM;i++) 648 *rasterfile << Walker->x.x[i]+center->x[i] << " "; 649 *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour 650 } 651 652 *rasterfile << "# All bonds as vertices" << endl; 653 while (Binder->next != mol->last) { 654 Binder = Binder->next; 655 *rasterfile << "3" << endl << " "; // 2 is round-ended cylinder type 656 for (i=0;i<NDIM;i++) 657 *rasterfile << Binder->leftatom->x.x[i]+center->x[i] << " "; 658 *rasterfile << "\t0.03\t"; 659 for (i=0;i<NDIM;i++) 660 *rasterfile << Binder->rightatom->x.x[i]+center->x[i] << " "; 661 *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour 662 } 663 664 *rasterfile << "# All tesselation triangles" << endl; 665 *rasterfile << "8\n 25. -1. 1. 1. 1. 0.0 0 0 0 2\n SOLID 1.0 0.0 0.0\n BACKFACE 0.3 0.3 1.0 0 0\n"; 666 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) { 667 *rasterfile << "1" << endl << " "; // 1 is triangle type 668 for (i=0;i<3;i++) { // print each node 669 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates 670 *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " "; 671 *rasterfile << "\t"; 672 } 673 *rasterfile << "1. 0. 0." << endl; // red as colour 674 //*rasterfile << "18" << endl << " 0.5 0.5 0.5" << endl; // 18 is transparency type for previous object 675 } 676 *rasterfile << "9\n terminating special property\n"; 677 } else { 678 cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl; 679 } 680 delete(center); 623 681 }; 624 682 625 /* 626 * This function creates the tecplot file, displaying the tesselation of the hull. 683 /** This function creates the tecplot file, displaying the tesselation of the hull. 627 684 * \param *out output stream for debugging 628 685 * \param *tecplot output stream for tecplot data … … 631 688 void 632 689 write_tecplot_file(ofstream *out, ofstream *tecplot, 633 class Tesselation *TesselStruct, class molecule *mol, int N)634 { 635 if (tecplot != NULL)636 {637 *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;638 *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl;639 *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N="640 << TesselStruct->PointsOnBoundaryCount << ", E="641 << TesselStruct->TrianglesOnBoundaryCount642 << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;643 int *LookupList = new int[mol->AtomCount];644 for (int i = 0; i < mol->AtomCount; i++)645 LookupList[i] = -1;646 647 // print atom coordinates648 *out << Verbose(2) << "The following triangles were created:";649 int Counter = 1;650 atom *Walker = NULL;651 for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target652 != TesselStruct->PointsOnBoundary.end(); target++)653 {654 Walker = target->second->node;655 LookupList[Walker->nr] = Counter++;656 *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " "657 << Walker->x.x[2] << " " << endl;658 }659 *tecplot << endl;660 // print connectivity661 for (TriangleMap::iterator runner =662 TesselStruct->TrianglesOnBoundary.begin(); runner663 != TesselStruct->TrianglesOnBoundary.end(); runner++)664 {665 *out << " " << runner->second->endpoints[0]->node->Name << "<->"666 << runner->second->endpoints[1]->node->Name << "<->"667 << runner->second->endpoints[2]->node->Name;668 *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " "669 << LookupList[runner->second->endpoints[1]->node->nr] << " "670 << LookupList[runner->second->endpoints[2]->node->nr] << endl;671 }672 delete[] (LookupList);673 *out << endl;674 }690 class Tesselation *TesselStruct, class molecule *mol, int N) 691 { 692 if (tecplot != NULL) 693 { 694 *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl; 695 *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl; 696 *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N=" 697 << TesselStruct->PointsOnBoundaryCount << ", E=" 698 << TesselStruct->TrianglesOnBoundaryCount 699 << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl; 700 int *LookupList = new int[mol->AtomCount]; 701 for (int i = 0; i < mol->AtomCount; i++) 702 LookupList[i] = -1; 703 704 // print atom coordinates 705 *out << Verbose(2) << "The following triangles were created:"; 706 int Counter = 1; 707 atom *Walker = NULL; 708 for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target 709 != TesselStruct->PointsOnBoundary.end(); target++) 710 { 711 Walker = target->second->node; 712 LookupList[Walker->nr] = Counter++; 713 *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " " 714 << Walker->x.x[2] << " " << endl; 715 } 716 *tecplot << endl; 717 // print connectivity 718 for (TriangleMap::iterator runner = 719 TesselStruct->TrianglesOnBoundary.begin(); runner 720 != TesselStruct->TrianglesOnBoundary.end(); runner++) 721 { 722 *out << " " << runner->second->endpoints[0]->node->Name << "<->" 723 << runner->second->endpoints[1]->node->Name << "<->" 724 << runner->second->endpoints[2]->node->Name; 725 *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " 726 << LookupList[runner->second->endpoints[1]->node->nr] << " " 727 << LookupList[runner->second->endpoints[2]->node->nr] << endl; 728 } 729 delete[] (LookupList); 730 *out << endl; 731 } 675 732 } 676 733 … … 678 735 * Determines first the convex envelope, then tesselates it and calculates its volume. 679 736 * \param *out output stream for debugging 680 * \param * tecplot output stream for tecplotdata737 * \param *filename filename prefix for output of vertex data 681 738 * \param *configuration needed for path to store convex envelope file 682 739 * \param *BoundaryPoints NDIM set of boundary points on the projected plane per axis, on return if desired … … 685 742 */ 686 743 double 687 VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, 688 Boundaries *BoundaryPtr, molecule *mol) 689 { 690 bool IsAngstroem = configuration->GetIsAngstroem(); 691 atom *Walker = NULL; 692 struct Tesselation *TesselStruct = new Tesselation; 693 bool BoundaryFreeFlag = false; 694 Boundaries *BoundaryPoints = BoundaryPtr; 695 double volume = 0.; 696 double PyramidVolume = 0.; 697 double G, h; 698 Vector x, y; 699 double a, b, c; 700 701 //Find_non_convex_border(out, tecplot, *TesselStruct, mol); // Is now called from command line. 702 703 // 1. calculate center of gravity 704 *out << endl; 705 Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out); 706 707 // 2. translate all points into CoG 708 *out << Verbose(1) << "Translating system to Center of Gravity." << endl; 709 Walker = mol->start; 710 while (Walker->next != mol->end) 711 { 712 Walker = Walker->next; 713 Walker->x.Translate(CenterOfGravity); 714 } 715 716 // 3. Find all points on the boundary 717 if (BoundaryPoints == NULL) 718 { 719 BoundaryFreeFlag = true; 720 BoundaryPoints = GetBoundaryPoints(out, mol); 721 } 722 else 723 { 724 *out << Verbose(1) << "Using given boundary points set." << endl; 725 } 726 727 // 4. fill the boundary point list 728 for (int axis = 0; axis < NDIM; axis++) 729 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 730 != BoundaryPoints[axis].end(); runner++) 731 { 732 TesselStruct->AddPoint(runner->second.second); 733 } 734 735 *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount 736 << " points on the convex boundary." << endl; 737 // now we have the whole set of edge points in the BoundaryList 738 739 // listing for debugging 740 // *out << Verbose(1) << "Listing PointsOnBoundary:"; 741 // for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) { 742 // *out << " " << *runner->second; 743 // } 744 // *out << endl; 745 746 // 5a. guess starting triangle 747 TesselStruct->GuessStartingTriangle(out); 748 749 // 5b. go through all lines, that are not yet part of two triangles (only of one so far) 750 TesselStruct->TesselateOnBoundary(out, configuration, mol); 751 752 *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount 753 << " triangles with " << TesselStruct->LinesOnBoundaryCount 754 << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." 755 << endl; 756 757 // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes 758 *out << Verbose(1) 759 << "Calculating the volume of the pyramids formed out of triangles and center of gravity." 760 << endl; 761 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner 762 != TesselStruct->TrianglesOnBoundary.end(); runner++) 763 { // go through every triangle, calculate volume of its pyramid with CoG as peak 764 x.CopyVector(&runner->second->endpoints[0]->node->x); 765 x.SubtractVector(&runner->second->endpoints[1]->node->x); 766 y.CopyVector(&runner->second->endpoints[0]->node->x); 767 y.SubtractVector(&runner->second->endpoints[2]->node->x); 768 a = sqrt(runner->second->endpoints[0]->node->x.Distance( 769 &runner->second->endpoints[1]->node->x)); 770 b = sqrt(runner->second->endpoints[0]->node->x.Distance( 771 &runner->second->endpoints[2]->node->x)); 772 c = sqrt(runner->second->endpoints[2]->node->x.Distance( 773 &runner->second->endpoints[1]->node->x)); 774 G = sqrt(((a * a + b * b + c * c) * (a * a + b * b + c * c) - 2 * (a * a 775 * a * a + b * b * b * b + c * c * c * c)) / 16.); // area of tesselated triangle 776 x.MakeNormalVector(&runner->second->endpoints[0]->node->x, 777 &runner->second->endpoints[1]->node->x, 778 &runner->second->endpoints[2]->node->x); 779 x.Scale(runner->second->endpoints[1]->node->x.Projection(&x)); 780 h = x.Norm(); // distance of CoG to triangle 781 PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak) 782 *out << Verbose(2) << "Area of triangle is " << G << " " 783 << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is " 784 << h << " and the volume is " << PyramidVolume << " " 785 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 786 volume += PyramidVolume; 787 } 788 *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10) 789 << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." 790 << endl; 791 792 // 7. translate all points back from CoG 793 *out << Verbose(1) << "Translating system back from Center of Gravity." 794 << endl; 795 CenterOfGravity->Scale(-1); 796 Walker = mol->start; 797 while (Walker->next != mol->end) 798 { 799 Walker = Walker->next; 800 Walker->x.Translate(CenterOfGravity); 801 } 802 803 // 8. Store triangles in tecplot file 804 write_tecplot_file(out, tecplot, TesselStruct, mol, 0); 805 806 // free reference lists 807 if (BoundaryFreeFlag) 808 delete[] (BoundaryPoints); 809 810 return volume; 744 VolumeOfConvexEnvelope(ofstream *out, const char *filename, config *configuration, 745 Boundaries *BoundaryPtr, molecule *mol) 746 { 747 bool IsAngstroem = configuration->GetIsAngstroem(); 748 atom *Walker = NULL; 749 struct Tesselation *TesselStruct = new Tesselation; 750 bool BoundaryFreeFlag = false; 751 Boundaries *BoundaryPoints = BoundaryPtr; 752 double volume = 0.; 753 double PyramidVolume = 0.; 754 double G, h; 755 Vector x, y; 756 double a, b, c; 757 758 //Find_non_convex_border(out, tecplot, *TesselStruct, mol); // Is now called from command line. 759 760 // 1. calculate center of gravity 761 *out << endl; 762 Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out); 763 764 // 2. translate all points into CoG 765 *out << Verbose(1) << "Translating system to Center of Gravity." << endl; 766 Walker = mol->start; 767 while (Walker->next != mol->end) 768 { 769 Walker = Walker->next; 770 Walker->x.Translate(CenterOfGravity); 771 } 772 773 // 3. Find all points on the boundary 774 if (BoundaryPoints == NULL) 775 { 776 BoundaryFreeFlag = true; 777 BoundaryPoints = GetBoundaryPoints(out, mol); 778 } 779 else 780 { 781 *out << Verbose(1) << "Using given boundary points set." << endl; 782 } 783 784 // 4. fill the boundary point list 785 for (int axis = 0; axis < NDIM; axis++) 786 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 787 != BoundaryPoints[axis].end(); runner++) 788 { 789 TesselStruct->AddPoint(runner->second.second); 790 } 791 792 *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount 793 << " points on the convex boundary." << endl; 794 // now we have the whole set of edge points in the BoundaryList 795 796 // listing for debugging 797 // *out << Verbose(1) << "Listing PointsOnBoundary:"; 798 // for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) { 799 // *out << " " << *runner->second; 800 // } 801 // *out << endl; 802 803 // 5a. guess starting triangle 804 TesselStruct->GuessStartingTriangle(out); 805 806 // 5b. go through all lines, that are not yet part of two triangles (only of one so far) 807 TesselStruct->TesselateOnBoundary(out, configuration, mol); 808 809 *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount 810 << " triangles with " << TesselStruct->LinesOnBoundaryCount 811 << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." 812 << endl; 813 814 // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes 815 *out << Verbose(1) 816 << "Calculating the volume of the pyramids formed out of triangles and center of gravity." 817 << endl; 818 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner 819 != TesselStruct->TrianglesOnBoundary.end(); runner++) 820 { // go through every triangle, calculate volume of its pyramid with CoG as peak 821 x.CopyVector(&runner->second->endpoints[0]->node->x); 822 x.SubtractVector(&runner->second->endpoints[1]->node->x); 823 y.CopyVector(&runner->second->endpoints[0]->node->x); 824 y.SubtractVector(&runner->second->endpoints[2]->node->x); 825 a = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared( 826 &runner->second->endpoints[1]->node->x)); 827 b = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared( 828 &runner->second->endpoints[2]->node->x)); 829 c = sqrt(runner->second->endpoints[2]->node->x.DistanceSquared( 830 &runner->second->endpoints[1]->node->x)); 831 G = sqrt(((a + b + c) * (a + b + c) - 2 * (a * a + b * b + c * c)) / 16.); // area of tesselated triangle 832 x.MakeNormalVector(&runner->second->endpoints[0]->node->x, 833 &runner->second->endpoints[1]->node->x, 834 &runner->second->endpoints[2]->node->x); 835 x.Scale(runner->second->endpoints[1]->node->x.Projection(&x)); 836 h = x.Norm(); // distance of CoG to triangle 837 PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak) 838 *out << Verbose(2) << "Area of triangle is " << G << " " 839 << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is " 840 << h << " and the volume is " << PyramidVolume << " " 841 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 842 volume += PyramidVolume; 843 } 844 *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10) 845 << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." 846 << endl; 847 848 // 7. translate all points back from CoG 849 *out << Verbose(1) << "Translating system back from Center of Gravity." 850 << endl; 851 CenterOfGravity->Scale(-1); 852 Walker = mol->start; 853 while (Walker->next != mol->end) 854 { 855 Walker = Walker->next; 856 Walker->x.Translate(CenterOfGravity); 857 } 858 859 // 8. Store triangles in tecplot file 860 string OutputName(filename); 861 OutputName.append(TecplotSuffix); 862 ofstream *tecplot = new ofstream(OutputName.c_str()); 863 write_tecplot_file(out, tecplot, TesselStruct, mol, 0); 864 tecplot->close(); 865 delete(tecplot); 866 867 // free reference lists 868 if (BoundaryFreeFlag) 869 delete[] (BoundaryPoints); 870 871 return volume; 811 872 } 812 873 ; … … 822 883 void 823 884 PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, 824 double ClusterVolume, double celldensity)825 { 826 // transform to PAS827 mol->PrincipalAxisSystem(out, true);828 829 // some preparations beforehand830 bool IsAngstroem = configuration->GetIsAngstroem();831 Boundaries *BoundaryPoints = GetBoundaryPoints(out, mol);832 double clustervolume;833 if (ClusterVolume == 0)834 clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration,835 BoundaryPoints, mol);836 else837 clustervolume = ClusterVolume;838 double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol,839 IsAngstroem);840 Vector BoxLengths;841 int repetition[NDIM] =842 { 1, 1, 1 };843 int TotalNoClusters = 1;844 for (int i = 0; i < NDIM; i++)845 TotalNoClusters *= repetition[i];846 847 // sum up the atomic masses848 double totalmass = 0.;849 atom *Walker = mol->start;850 while (Walker->next != mol->end)851 {852 Walker = Walker->next;853 totalmass += Walker->type->mass;854 }855 *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10)856 << totalmass << " atomicmassunit." << endl;857 858 *out << Verbose(0) << "RESULT: The average density is " << setprecision(10)859 << totalmass / clustervolume << " atomicmassunit/"860 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;861 862 // solve cubic polynomial863 *out << Verbose(1) << "Solving equidistant suspension in water problem ..."864 << endl;865 double cellvolume;866 if (IsAngstroem)867 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass868 / clustervolume)) / (celldensity - 1);869 else870 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass871 / clustervolume)) / (celldensity - 1);872 *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity873 << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom"874 : "atomiclength") << "^3." << endl;875 876 double minimumvolume = TotalNoClusters * (GreatestDiameter[0]877 * GreatestDiameter[1] * GreatestDiameter[2]);878 *out << Verbose(1)879 << "Minimum volume of the convex envelope contained in a rectangular box is "880 << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom"881 : "atomiclength") << "^3." << endl;882 if (minimumvolume > cellvolume)883 {884 cerr << Verbose(0)885 << "ERROR: the containing box already has a greater volume than the envisaged cell volume!"886 << endl;887 cout << Verbose(0)888 << "Setting Box dimensions to minimum possible, the greatest diameters."889 << endl;890 for (int i = 0; i < NDIM; i++)891 BoxLengths.x[i] = GreatestDiameter[i];892 mol->CenterEdge(out, &BoxLengths);893 }894 else895 {896 BoxLengths.x[0] = (repetition[0] * GreatestDiameter[0] + repetition[1]897 * GreatestDiameter[1] + repetition[2] * GreatestDiameter[2]);898 BoxLengths.x[1] = (repetition[0] * repetition[1] * GreatestDiameter[0]899 * GreatestDiameter[1] + repetition[0] * repetition[2]900 * GreatestDiameter[0] * GreatestDiameter[2] + repetition[1]901 * repetition[2] * GreatestDiameter[1] * GreatestDiameter[2]);902 BoxLengths.x[2] = minimumvolume - cellvolume;903 double x0 = 0., x1 = 0., x2 = 0.;904 if (gsl_poly_solve_cubic(BoxLengths.x[0], BoxLengths.x[1],905 BoxLengths.x[2], &x0, &x1, &x2) == 1) // either 1 or 3 on return906 *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0907 << " ." << endl;908 else909 {910 *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0911 << " and " << x1 << " and " << x2 << " ." << endl;912 x0 = x2; // sorted in ascending order913 }914 915 cellvolume = 1;916 for (int i = 0; i < NDIM; i++)917 {918 BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]);919 cellvolume *= BoxLengths.x[i];920 }921 922 // set new box dimensions923 *out << Verbose(0) << "Translating to box with these boundaries." << endl;924 mol->CenterInBox((ofstream *) &cout, &BoxLengths);925 }926 // update Box of atoms by boundary927 mol->SetBoxDimension(&BoxLengths);928 *out << Verbose(0) << "RESULT: The resulting cell dimensions are: "929 << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and "930 << BoxLengths.x[2] << " with total volume of " << cellvolume << " "931 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;885 double ClusterVolume, double celldensity) 886 { 887 // transform to PAS 888 mol->PrincipalAxisSystem(out, true); 889 890 // some preparations beforehand 891 bool IsAngstroem = configuration->GetIsAngstroem(); 892 Boundaries *BoundaryPoints = GetBoundaryPoints(out, mol); 893 double clustervolume; 894 if (ClusterVolume == 0) 895 clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration, 896 BoundaryPoints, mol); 897 else 898 clustervolume = ClusterVolume; 899 double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, 900 IsAngstroem); 901 Vector BoxLengths; 902 int repetition[NDIM] = 903 { 1, 1, 1 }; 904 int TotalNoClusters = 1; 905 for (int i = 0; i < NDIM; i++) 906 TotalNoClusters *= repetition[i]; 907 908 // sum up the atomic masses 909 double totalmass = 0.; 910 atom *Walker = mol->start; 911 while (Walker->next != mol->end) 912 { 913 Walker = Walker->next; 914 totalmass += Walker->type->mass; 915 } 916 *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10) 917 << totalmass << " atomicmassunit." << endl; 918 919 *out << Verbose(0) << "RESULT: The average density is " << setprecision(10) 920 << totalmass / clustervolume << " atomicmassunit/" 921 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 922 923 // solve cubic polynomial 924 *out << Verbose(1) << "Solving equidistant suspension in water problem ..." 925 << endl; 926 double cellvolume; 927 if (IsAngstroem) 928 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass 929 / clustervolume)) / (celldensity - 1); 930 else 931 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass 932 / clustervolume)) / (celldensity - 1); 933 *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity 934 << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom" 935 : "atomiclength") << "^3." << endl; 936 937 double minimumvolume = TotalNoClusters * (GreatestDiameter[0] 938 * GreatestDiameter[1] * GreatestDiameter[2]); 939 *out << Verbose(1) 940 << "Minimum volume of the convex envelope contained in a rectangular box is " 941 << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" 942 : "atomiclength") << "^3." << endl; 943 if (minimumvolume > cellvolume) 944 { 945 cerr << Verbose(0) 946 << "ERROR: the containing box already has a greater volume than the envisaged cell volume!" 947 << endl; 948 cout << Verbose(0) 949 << "Setting Box dimensions to minimum possible, the greatest diameters." 950 << endl; 951 for (int i = 0; i < NDIM; i++) 952 BoxLengths.x[i] = GreatestDiameter[i]; 953 mol->CenterEdge(out, &BoxLengths); 954 } 955 else 956 { 957 BoxLengths.x[0] = (repetition[0] * GreatestDiameter[0] + repetition[1] 958 * GreatestDiameter[1] + repetition[2] * GreatestDiameter[2]); 959 BoxLengths.x[1] = (repetition[0] * repetition[1] * GreatestDiameter[0] 960 * GreatestDiameter[1] + repetition[0] * repetition[2] 961 * GreatestDiameter[0] * GreatestDiameter[2] + repetition[1] 962 * repetition[2] * GreatestDiameter[1] * GreatestDiameter[2]); 963 BoxLengths.x[2] = minimumvolume - cellvolume; 964 double x0 = 0., x1 = 0., x2 = 0.; 965 if (gsl_poly_solve_cubic(BoxLengths.x[0], BoxLengths.x[1], 966 BoxLengths.x[2], &x0, &x1, &x2) == 1) // either 1 or 3 on return 967 *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0 968 << " ." << endl; 969 else 970 { 971 *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0 972 << " and " << x1 << " and " << x2 << " ." << endl; 973 x0 = x2; // sorted in ascending order 974 } 975 976 cellvolume = 1; 977 for (int i = 0; i < NDIM; i++) 978 { 979 BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]); 980 cellvolume *= BoxLengths.x[i]; 981 } 982 983 // set new box dimensions 984 *out << Verbose(0) << "Translating to box with these boundaries." << endl; 985 mol->CenterInBox((ofstream *) &cout, &BoxLengths); 986 } 987 // update Box of atoms by boundary 988 mol->SetBoxDimension(&BoxLengths); 989 *out << Verbose(0) << "RESULT: The resulting cell dimensions are: " 990 << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and " 991 << BoxLengths.x[2] << " with total volume of " << cellvolume << " " 992 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 932 993 } 933 994 ; … … 939 1000 Tesselation::Tesselation() 940 1001 { 941 PointsOnBoundaryCount = 0;942 LinesOnBoundaryCount = 0;943 TrianglesOnBoundaryCount = 0;944 TriangleFilesWritten = 0;1002 PointsOnBoundaryCount = 0; 1003 LinesOnBoundaryCount = 0; 1004 TrianglesOnBoundaryCount = 0; 1005 TriangleFilesWritten = 0; 945 1006 } 946 1007 ; … … 951 1012 Tesselation::~Tesselation() 952 1013 { 953 cout << Verbose(1) << "Free'ing TesselStruct ... " << endl; 954 for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner 955 != TrianglesOnBoundary.end(); runner++) 956 { 957 delete (runner->second); 958 } 1014 cout << Verbose(1) << "Free'ing TesselStruct ... " << endl; 1015 for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) { 1016 if (runner->second != NULL) { 1017 delete (runner->second); 1018 runner->second = NULL; 1019 } else 1020 cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl; 1021 } 959 1022 } 960 1023 ; … … 968 1031 Tesselation::GuessStartingTriangle(ofstream *out) 969 1032 { 970 // 4b. create a starting triangle971 // 4b1. create all distances972 DistanceMultiMap DistanceMMap;973 double distance, tmp;974 Vector PlaneVector, TrialVector;975 PointMap::iterator A, B, C; // three nodes of the first triangle976 A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily977 978 // with A chosen, take each pair B,C and sort979 if (A != PointsOnBoundary.end())980 {981 B = A;982 B++;983 for (; B != PointsOnBoundary.end(); B++)984 {985 C = B;986 C++;987 for (; C != PointsOnBoundary.end(); C++)988 {989 tmp = A->second->node->x.Distance(&B->second->node->x);990 distance = tmp * tmp;991 tmp = A->second->node->x.Distance(&C->second->node->x);992 distance += tmp * tmp;993 tmp = B->second->node->x.Distance(&C->second->node->x);994 distance += tmp * tmp;995 DistanceMMap.insert(DistanceMultiMapPair(distance, pair<996 PointMap::iterator, PointMap::iterator> (B, C)));997 }998 }999 }1000 //// listing distances1001 //*out << Verbose(1) << "Listing DistanceMMap:";1002 //for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) {1003 //*out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")";1004 //}1005 //*out << endl;1006 // 4b2. pick three baselines forming a triangle1007 // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate1008 DistanceMultiMap::iterator baseline = DistanceMMap.begin();1009 for (; baseline != DistanceMMap.end(); baseline++)1010 {1011 // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate1012 // 2. next, we have to check whether all points reside on only one side of the triangle1013 // 3. construct plane vector1014 PlaneVector.MakeNormalVector(&A->second->node->x,1015 &baseline->second.first->second->node->x,1016 &baseline->second.second->second->node->x);1017 *out << Verbose(2) << "Plane vector of candidate triangle is ";1018 PlaneVector.Output(out);1019 *out << endl;1020 // 4. loop over all points1021 double sign = 0.;1022 PointMap::iterator checker = PointsOnBoundary.begin();1023 for (; checker != PointsOnBoundary.end(); checker++)1024 {1025 // (neglecting A,B,C)1026 if ((checker == A) || (checker == baseline->second.first) || (checker1027 == baseline->second.second))1028 continue;1029 // 4a. project onto plane vector1030 TrialVector.CopyVector(&checker->second->node->x);1031 TrialVector.SubtractVector(&A->second->node->x);1032 distance = TrialVector.Projection(&PlaneVector);1033 if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok1034 continue;1035 *out << Verbose(3) << "Projection of " << checker->second->node->Name1036 << " yields distance of " << distance << "." << endl;1037 tmp = distance / fabs(distance);1038 // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle)1039 if ((sign != 0) && (tmp != sign))1040 {1041 // 4c. If so, break 4. loop and continue with next candidate in 1. loop1042 *out << Verbose(2) << "Current candidates: "1043 << A->second->node->Name << ","1044 << baseline->second.first->second->node->Name << ","1045 << baseline->second.second->second->node->Name << " leave "1046 << checker->second->node->Name << " outside the convex hull."1047 << endl;1048 break;1049 }1050 else1051 { // note the sign for later1052 *out << Verbose(2) << "Current candidates: "1053 << A->second->node->Name << ","1054 << baseline->second.first->second->node->Name << ","1055 << baseline->second.second->second->node->Name << " leave "1056 << checker->second->node->Name << " inside the convex hull."1057 << endl;1058 sign = tmp;1059 }1060 // 4d. Check whether the point is inside the triangle (check distance to each node1061 tmp = checker->second->node->x.Distance(&A->second->node->x);1062 int innerpoint = 0;1063 if ((tmp < A->second->node->x.Distance(1064 &baseline->second.first->second->node->x)) && (tmp1065 < A->second->node->x.Distance(1066 &baseline->second.second->second->node->x)))1067 innerpoint++;1068 tmp = checker->second->node->x.Distance(1069 &baseline->second.first->second->node->x);1070 if ((tmp < baseline->second.first->second->node->x.Distance(1071 &A->second->node->x)) && (tmp1072 < baseline->second.first->second->node->x.Distance(1073 &baseline->second.second->second->node->x)))1074 innerpoint++;1075 tmp = checker->second->node->x.Distance(1076 &baseline->second.second->second->node->x);1077 if ((tmp < baseline->second.second->second->node->x.Distance(1078 &baseline->second.first->second->node->x)) && (tmp1079 < baseline->second.second->second->node->x.Distance(1080 &A->second->node->x)))1081 innerpoint++;1082 // 4e. If so, break 4. loop and continue with next candidate in 1. loop1083 if (innerpoint == 3)1084 break;1085 }1086 // 5. come this far, all on same side? Then break 1. loop and construct triangle1087 if (checker == PointsOnBoundary.end())1088 {1089 *out << "Looks like we have a candidate!" << endl;1090 break;1091 }1092 }1093 if (baseline != DistanceMMap.end())1094 {1095 BPS[0] = baseline->second.first->second;1096 BPS[1] = baseline->second.second->second;1097 BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);1098 BPS[0] = A->second;1099 BPS[1] = baseline->second.second->second;1100 BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);1101 BPS[0] = baseline->second.first->second;1102 BPS[1] = A->second;1103 BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);1104 1105 // 4b3. insert created triangle1106 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);1107 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));1108 TrianglesOnBoundaryCount++;1109 for (int i = 0; i < NDIM; i++)1110 {1111 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i]));1112 LinesOnBoundaryCount++;1113 }1114 1115 *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl;1116 }1117 else1118 {1119 *out << Verbose(1) << "No starting triangle found." << endl;1120 exit(255);1121 }1033 // 4b. create a starting triangle 1034 // 4b1. create all distances 1035 DistanceMultiMap DistanceMMap; 1036 double distance, tmp; 1037 Vector PlaneVector, TrialVector; 1038 PointMap::iterator A, B, C; // three nodes of the first triangle 1039 A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily 1040 1041 // with A chosen, take each pair B,C and sort 1042 if (A != PointsOnBoundary.end()) 1043 { 1044 B = A; 1045 B++; 1046 for (; B != PointsOnBoundary.end(); B++) 1047 { 1048 C = B; 1049 C++; 1050 for (; C != PointsOnBoundary.end(); C++) 1051 { 1052 tmp = A->second->node->x.DistanceSquared(&B->second->node->x); 1053 distance = tmp * tmp; 1054 tmp = A->second->node->x.DistanceSquared(&C->second->node->x); 1055 distance += tmp * tmp; 1056 tmp = B->second->node->x.DistanceSquared(&C->second->node->x); 1057 distance += tmp * tmp; 1058 DistanceMMap.insert(DistanceMultiMapPair(distance, pair< 1059 PointMap::iterator, PointMap::iterator> (B, C))); 1060 } 1061 } 1062 } 1063 // // listing distances 1064 // *out << Verbose(1) << "Listing DistanceMMap:"; 1065 // for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) { 1066 // *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")"; 1067 // } 1068 // *out << endl; 1069 // 4b2. pick three baselines forming a triangle 1070 // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate 1071 DistanceMultiMap::iterator baseline = DistanceMMap.begin(); 1072 for (; baseline != DistanceMMap.end(); baseline++) 1073 { 1074 // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate 1075 // 2. next, we have to check whether all points reside on only one side of the triangle 1076 // 3. construct plane vector 1077 PlaneVector.MakeNormalVector(&A->second->node->x, 1078 &baseline->second.first->second->node->x, 1079 &baseline->second.second->second->node->x); 1080 *out << Verbose(2) << "Plane vector of candidate triangle is "; 1081 PlaneVector.Output(out); 1082 *out << endl; 1083 // 4. loop over all points 1084 double sign = 0.; 1085 PointMap::iterator checker = PointsOnBoundary.begin(); 1086 for (; checker != PointsOnBoundary.end(); checker++) 1087 { 1088 // (neglecting A,B,C) 1089 if ((checker == A) || (checker == baseline->second.first) || (checker 1090 == baseline->second.second)) 1091 continue; 1092 // 4a. project onto plane vector 1093 TrialVector.CopyVector(&checker->second->node->x); 1094 TrialVector.SubtractVector(&A->second->node->x); 1095 distance = TrialVector.Projection(&PlaneVector); 1096 if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok 1097 continue; 1098 *out << Verbose(3) << "Projection of " << checker->second->node->Name 1099 << " yields distance of " << distance << "." << endl; 1100 tmp = distance / fabs(distance); 1101 // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle) 1102 if ((sign != 0) && (tmp != sign)) 1103 { 1104 // 4c. If so, break 4. loop and continue with next candidate in 1. loop 1105 *out << Verbose(2) << "Current candidates: " 1106 << A->second->node->Name << "," 1107 << baseline->second.first->second->node->Name << "," 1108 << baseline->second.second->second->node->Name << " leave " 1109 << checker->second->node->Name << " outside the convex hull." 1110 << endl; 1111 break; 1112 } 1113 else 1114 { // note the sign for later 1115 *out << Verbose(2) << "Current candidates: " 1116 << A->second->node->Name << "," 1117 << baseline->second.first->second->node->Name << "," 1118 << baseline->second.second->second->node->Name << " leave " 1119 << checker->second->node->Name << " inside the convex hull." 1120 << endl; 1121 sign = tmp; 1122 } 1123 // 4d. Check whether the point is inside the triangle (check distance to each node 1124 tmp = checker->second->node->x.DistanceSquared(&A->second->node->x); 1125 int innerpoint = 0; 1126 if ((tmp < A->second->node->x.DistanceSquared( 1127 &baseline->second.first->second->node->x)) && (tmp 1128 < A->second->node->x.DistanceSquared( 1129 &baseline->second.second->second->node->x))) 1130 innerpoint++; 1131 tmp = checker->second->node->x.DistanceSquared( 1132 &baseline->second.first->second->node->x); 1133 if ((tmp < baseline->second.first->second->node->x.DistanceSquared( 1134 &A->second->node->x)) && (tmp 1135 < baseline->second.first->second->node->x.DistanceSquared( 1136 &baseline->second.second->second->node->x))) 1137 innerpoint++; 1138 tmp = checker->second->node->x.DistanceSquared( 1139 &baseline->second.second->second->node->x); 1140 if ((tmp < baseline->second.second->second->node->x.DistanceSquared( 1141 &baseline->second.first->second->node->x)) && (tmp 1142 < baseline->second.second->second->node->x.DistanceSquared( 1143 &A->second->node->x))) 1144 innerpoint++; 1145 // 4e. If so, break 4. loop and continue with next candidate in 1. loop 1146 if (innerpoint == 3) 1147 break; 1148 } 1149 // 5. come this far, all on same side? Then break 1. loop and construct triangle 1150 if (checker == PointsOnBoundary.end()) 1151 { 1152 *out << "Looks like we have a candidate!" << endl; 1153 break; 1154 } 1155 } 1156 if (baseline != DistanceMMap.end()) 1157 { 1158 BPS[0] = baseline->second.first->second; 1159 BPS[1] = baseline->second.second->second; 1160 BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1161 BPS[0] = A->second; 1162 BPS[1] = baseline->second.second->second; 1163 BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1164 BPS[0] = baseline->second.first->second; 1165 BPS[1] = A->second; 1166 BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1167 1168 // 4b3. insert created triangle 1169 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 1170 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1171 TrianglesOnBoundaryCount++; 1172 for (int i = 0; i < NDIM; i++) 1173 { 1174 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i])); 1175 LinesOnBoundaryCount++; 1176 } 1177 1178 *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl; 1179 } 1180 else 1181 { 1182 *out << Verbose(1) << "No starting triangle found." << endl; 1183 exit(255); 1184 } 1122 1185 } 1123 1186 ; … … 1128 1191 * -# if the lines contains to only one triangle 1129 1192 * -# We search all points in the boundary 1130 * -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors1131 * -# if the triangle is in forward direction of the baseline (at most 90 degrees angle between vector orthogonal to1132 * baseline in triangle plane pointing out of the triangle and normal vector of new triangle)1133 * -# then we have a new triangle, whose baselines we again add (or increase their TriangleCount)1193 * -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors 1194 * -# if the triangle is in forward direction of the baseline (at most 90 degrees angle between vector orthogonal to 1195 * baseline in triangle plane pointing out of the triangle and normal vector of new triangle) 1196 * -# then we have a new triangle, whose baselines we again add (or increase their TriangleCount) 1134 1197 * \param *out output stream for debugging 1135 1198 * \param *configuration for IsAngstroem … … 1138 1201 void 1139 1202 Tesselation::TesselateOnBoundary(ofstream *out, config *configuration, 1140 molecule *mol)1141 { 1142 bool flag;1143 PointMap::iterator winner;1144 class BoundaryPointSet *peak = NULL;1145 double SmallestAngle, TempAngle;1146 Vector NormalVector, VirtualNormalVector, CenterVector, TempVector,1147 PropagationVector;1148 LineMap::iterator LineChecker[2];1149 do1150 {1151 flag = false;1152 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline1153 != LinesOnBoundary.end(); baseline++)1154 if (baseline->second->TrianglesCount == 1)1155 {1156 *out << Verbose(2) << "Current baseline is between "1157 << *(baseline->second) << "." << endl;1158 // 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)1159 SmallestAngle = M_PI;1160 BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far1161 // get peak point with respect to this base line's only triangle1162 for (int i = 0; i < 3; i++)1163 if ((BTS->endpoints[i] != baseline->second->endpoints[0])1164 && (BTS->endpoints[i] != baseline->second->endpoints[1]))1165 peak = BTS->endpoints[i];1166 *out << Verbose(3) << " and has peak " << *peak << "." << endl;1167 // normal vector of triangle1168 BTS->GetNormalVector(NormalVector);1169 *out << Verbose(4) << "NormalVector of base triangle is ";1170 NormalVector.Output(out);1171 *out << endl;1172 // offset to center of triangle1173 CenterVector.Zero();1174 for (int i = 0; i < 3; i++)1175 CenterVector.AddVector(&BTS->endpoints[i]->node->x);1176 CenterVector.Scale(1. / 3.);1177 *out << Verbose(4) << "CenterVector of base triangle is ";1178 CenterVector.Output(out);1179 *out << endl;1180 // vector in propagation direction (out of triangle)1181 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)1182 TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);1183 TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x);1184 PropagationVector.MakeNormalVector(&TempVector, &NormalVector);1185 TempVector.CopyVector(&CenterVector);1186 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center!1187 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;1188 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline1189 PropagationVector.Scale(-1.);1190 *out << Verbose(4) << "PropagationVector of base triangle is ";1191 PropagationVector.Output(out);1192 *out << endl;1193 winner = PointsOnBoundary.end();1194 for (PointMap::iterator target = PointsOnBoundary.begin(); target1195 != PointsOnBoundary.end(); target++)1196 if ((target->second != baseline->second->endpoints[0])1197 && (target->second != baseline->second->endpoints[1]))1198 { // don't take the same endpoints1199 *out << Verbose(3) << "Target point is " << *(target->second)1200 << ":";1201 bool continueflag = true;1202 1203 VirtualNormalVector.CopyVector(1204 &baseline->second->endpoints[0]->node->x);1205 VirtualNormalVector.AddVector(1206 &baseline->second->endpoints[0]->node->x);1207 VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line1208 VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target1209 TempAngle = VirtualNormalVector.Angle(&PropagationVector);1210 continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees)1211 if (!continueflag)1212 {1213 *out << Verbose(4)1214 << "Angle between propagation direction and base line to "1215 << *(target->second) << " is " << TempAngle1216 << ", bad direction!" << endl;1217 continue;1218 }1219 else1220 *out << Verbose(4)1221 << "Angle between propagation direction and base line to "1222 << *(target->second) << " is " << TempAngle1223 << ", good direction!" << endl;1224 LineChecker[0] = baseline->second->endpoints[0]->lines.find(1225 target->first);1226 LineChecker[1] = baseline->second->endpoints[1]->lines.find(1227 target->first);1228 //if (LineChecker[0] != baseline->second->endpoints[0]->lines.end())1229 //*out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;1230 //else1231 //*out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl;1232 //if (LineChecker[1] != baseline->second->endpoints[1]->lines.end())1233 //*out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;1234 //else1235 //*out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl;1236 // check first endpoint (if any connecting line goes to target or at least not more than 1)1237 continueflag = continueflag && (((LineChecker[0]1238 == baseline->second->endpoints[0]->lines.end())1239 || (LineChecker[0]->second->TrianglesCount == 1)));1240 if (!continueflag)1241 {1242 *out << Verbose(4) << *(baseline->second->endpoints[0])1243 << " has line " << *(LineChecker[0]->second)1244 << " to " << *(target->second)1245 << " as endpoint with "1246 << LineChecker[0]->second->TrianglesCount1247 << " triangles." << endl;1248 continue;1249 }1250 // check second endpoint (if any connecting line goes to target or at least not more than 1)1251 continueflag = continueflag && (((LineChecker[1]1252 == baseline->second->endpoints[1]->lines.end())1253 || (LineChecker[1]->second->TrianglesCount == 1)));1254 if (!continueflag)1255 {1256 *out << Verbose(4) << *(baseline->second->endpoints[1])1257 << " has line " << *(LineChecker[1]->second)1258 << " to " << *(target->second)1259 << " as endpoint with "1260 << LineChecker[1]->second->TrianglesCount1261 << " triangles." << endl;1262 continue;1263 }1264 // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)1265 continueflag = continueflag && (!(((LineChecker[0]1266 != baseline->second->endpoints[0]->lines.end())1267 && (LineChecker[1]1268 != baseline->second->endpoints[1]->lines.end())1269 && (GetCommonEndpoint(LineChecker[0]->second,1270 LineChecker[1]->second) == peak))));1271 if (!continueflag)1272 {1273 *out << Verbose(4) << "Current target is peak!" << endl;1274 continue;1275 }1276 // in case NOT both were found1277 if (continueflag)1278 { // create virtually this triangle, get its normal vector, calculate angle1279 flag = true;1280 VirtualNormalVector.MakeNormalVector(1281 &baseline->second->endpoints[0]->node->x,1282 &baseline->second->endpoints[1]->node->x,1283 &target->second->node->x);1284 // make it always point inward1285 if (baseline->second->endpoints[0]->node->x.Projection(1286 &VirtualNormalVector) > 0)1287 VirtualNormalVector.Scale(-1.);1288 // calculate angle1289 TempAngle = NormalVector.Angle(&VirtualNormalVector);1290 *out << Verbose(4) << "NormalVector is ";1291 VirtualNormalVector.Output(out);1292 *out << " and the angle is " << TempAngle << "." << endl;1293 if (SmallestAngle > TempAngle)1294 { // set to new possible winner1295 SmallestAngle = TempAngle;1296 winner = target;1297 }1298 }1299 }1300 // 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 triangle1301 if (winner != PointsOnBoundary.end())1302 {1303 *out << Verbose(2) << "Winning target point is "1304 << *(winner->second) << " with angle " << SmallestAngle1305 << "." << endl;1306 // create the lins of not yet present1307 BLS[0] = baseline->second;1308 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)1309 LineChecker[0] = baseline->second->endpoints[0]->lines.find(1310 winner->first);1311 LineChecker[1] = baseline->second->endpoints[1]->lines.find(1312 winner->first);1313 if (LineChecker[0]1314 == baseline->second->endpoints[0]->lines.end())1315 { // create1316 BPS[0] = baseline->second->endpoints[0];1317 BPS[1] = winner->second;1318 BLS[1] = new class BoundaryLineSet(BPS,1319 LinesOnBoundaryCount);1320 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,1321 BLS[1]));1322 LinesOnBoundaryCount++;1323 }1324 else1325 BLS[1] = LineChecker[0]->second;1326 if (LineChecker[1]1327 == baseline->second->endpoints[1]->lines.end())1328 { // create1329 BPS[0] = baseline->second->endpoints[1];1330 BPS[1] = winner->second;1331 BLS[2] = new class BoundaryLineSet(BPS,1332 LinesOnBoundaryCount);1333 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,1334 BLS[2]));1335 LinesOnBoundaryCount++;1336 }1337 else1338 BLS[2] = LineChecker[1]->second;1339 BTS = new class BoundaryTriangleSet(BLS,1340 TrianglesOnBoundaryCount);1341 TrianglesOnBoundary.insert(TrianglePair(1342 TrianglesOnBoundaryCount, BTS));1343 TrianglesOnBoundaryCount++;1344 }1345 else1346 {1347 *out << Verbose(1)1348 << "I could not determine a winner for this baseline "1349 << *(baseline->second) << "." << endl;1350 }1351 1352 // 5d. If the set of lines is not yet empty, go to 5. and continue1353 }1354 else1355 *out << Verbose(2) << "Baseline candidate " << *(baseline->second)1356 << " has a triangle count of "1357 << baseline->second->TrianglesCount << "." << endl;1358 }1359 while (flag);1203 molecule *mol) 1204 { 1205 bool flag; 1206 PointMap::iterator winner; 1207 class BoundaryPointSet *peak = NULL; 1208 double SmallestAngle, TempAngle; 1209 Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, 1210 PropagationVector; 1211 LineMap::iterator LineChecker[2]; 1212 do 1213 { 1214 flag = false; 1215 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline 1216 != LinesOnBoundary.end(); baseline++) 1217 if (baseline->second->TrianglesCount == 1) 1218 { 1219 *out << Verbose(2) << "Current baseline is between " 1220 << *(baseline->second) << "." << endl; 1221 // 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) 1222 SmallestAngle = M_PI; 1223 BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far 1224 // get peak point with respect to this base line's only triangle 1225 for (int i = 0; i < 3; i++) 1226 if ((BTS->endpoints[i] != baseline->second->endpoints[0]) 1227 && (BTS->endpoints[i] != baseline->second->endpoints[1])) 1228 peak = BTS->endpoints[i]; 1229 *out << Verbose(3) << " and has peak " << *peak << "." << endl; 1230 // normal vector of triangle 1231 BTS->GetNormalVector(NormalVector); 1232 *out << Verbose(4) << "NormalVector of base triangle is "; 1233 NormalVector.Output(out); 1234 *out << endl; 1235 // offset to center of triangle 1236 CenterVector.Zero(); 1237 for (int i = 0; i < 3; i++) 1238 CenterVector.AddVector(&BTS->endpoints[i]->node->x); 1239 CenterVector.Scale(1. / 3.); 1240 *out << Verbose(4) << "CenterVector of base triangle is "; 1241 CenterVector.Output(out); 1242 *out << endl; 1243 // vector in propagation direction (out of triangle) 1244 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection) 1245 TempVector.CopyVector(&baseline->second->endpoints[0]->node->x); 1246 TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x); 1247 PropagationVector.MakeNormalVector(&TempVector, &NormalVector); 1248 TempVector.CopyVector(&CenterVector); 1249 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center! 1250 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl; 1251 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline 1252 PropagationVector.Scale(-1.); 1253 *out << Verbose(4) << "PropagationVector of base triangle is "; 1254 PropagationVector.Output(out); 1255 *out << endl; 1256 winner = PointsOnBoundary.end(); 1257 for (PointMap::iterator target = PointsOnBoundary.begin(); target 1258 != PointsOnBoundary.end(); target++) 1259 if ((target->second != baseline->second->endpoints[0]) 1260 && (target->second != baseline->second->endpoints[1])) 1261 { // don't take the same endpoints 1262 *out << Verbose(3) << "Target point is " << *(target->second) 1263 << ":"; 1264 bool continueflag = true; 1265 1266 VirtualNormalVector.CopyVector( 1267 &baseline->second->endpoints[0]->node->x); 1268 VirtualNormalVector.AddVector( 1269 &baseline->second->endpoints[0]->node->x); 1270 VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line 1271 VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target 1272 TempAngle = VirtualNormalVector.Angle(&PropagationVector); 1273 continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees) 1274 if (!continueflag) 1275 { 1276 *out << Verbose(4) 1277 << "Angle between propagation direction and base line to " 1278 << *(target->second) << " is " << TempAngle 1279 << ", bad direction!" << endl; 1280 continue; 1281 } 1282 else 1283 *out << Verbose(4) 1284 << "Angle between propagation direction and base line to " 1285 << *(target->second) << " is " << TempAngle 1286 << ", good direction!" << endl; 1287 LineChecker[0] = baseline->second->endpoints[0]->lines.find( 1288 target->first); 1289 LineChecker[1] = baseline->second->endpoints[1]->lines.find( 1290 target->first); 1291 // if (LineChecker[0] != baseline->second->endpoints[0]->lines.end()) 1292 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl; 1293 // else 1294 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl; 1295 // if (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 1296 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl; 1297 // else 1298 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl; 1299 // check first endpoint (if any connecting line goes to target or at least not more than 1) 1300 continueflag = continueflag && (((LineChecker[0] 1301 == baseline->second->endpoints[0]->lines.end()) 1302 || (LineChecker[0]->second->TrianglesCount == 1))); 1303 if (!continueflag) 1304 { 1305 *out << Verbose(4) << *(baseline->second->endpoints[0]) 1306 << " has line " << *(LineChecker[0]->second) 1307 << " to " << *(target->second) 1308 << " as endpoint with " 1309 << LineChecker[0]->second->TrianglesCount 1310 << " triangles." << endl; 1311 continue; 1312 } 1313 // check second endpoint (if any connecting line goes to target or at least not more than 1) 1314 continueflag = continueflag && (((LineChecker[1] 1315 == baseline->second->endpoints[1]->lines.end()) 1316 || (LineChecker[1]->second->TrianglesCount == 1))); 1317 if (!continueflag) 1318 { 1319 *out << Verbose(4) << *(baseline->second->endpoints[1]) 1320 << " has line " << *(LineChecker[1]->second) 1321 << " to " << *(target->second) 1322 << " as endpoint with " 1323 << LineChecker[1]->second->TrianglesCount 1324 << " triangles." << endl; 1325 continue; 1326 } 1327 // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint) 1328 continueflag = continueflag && (!(((LineChecker[0] 1329 != baseline->second->endpoints[0]->lines.end()) 1330 && (LineChecker[1] 1331 != baseline->second->endpoints[1]->lines.end()) 1332 && (GetCommonEndpoint(LineChecker[0]->second, 1333 LineChecker[1]->second) == peak)))); 1334 if (!continueflag) 1335 { 1336 *out << Verbose(4) << "Current target is peak!" << endl; 1337 continue; 1338 } 1339 // in case NOT both were found 1340 if (continueflag) 1341 { // create virtually this triangle, get its normal vector, calculate angle 1342 flag = true; 1343 VirtualNormalVector.MakeNormalVector( 1344 &baseline->second->endpoints[0]->node->x, 1345 &baseline->second->endpoints[1]->node->x, 1346 &target->second->node->x); 1347 // make it always point inward 1348 if (baseline->second->endpoints[0]->node->x.Projection( 1349 &VirtualNormalVector) > 0) 1350 VirtualNormalVector.Scale(-1.); 1351 // calculate angle 1352 TempAngle = NormalVector.Angle(&VirtualNormalVector); 1353 *out << Verbose(4) << "NormalVector is "; 1354 VirtualNormalVector.Output(out); 1355 *out << " and the angle is " << TempAngle << "." << endl; 1356 if (SmallestAngle > TempAngle) 1357 { // set to new possible winner 1358 SmallestAngle = TempAngle; 1359 winner = target; 1360 } 1361 } 1362 } 1363 // 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 1364 if (winner != PointsOnBoundary.end()) 1365 { 1366 *out << Verbose(2) << "Winning target point is " 1367 << *(winner->second) << " with angle " << SmallestAngle 1368 << "." << endl; 1369 // create the lins of not yet present 1370 BLS[0] = baseline->second; 1371 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles) 1372 LineChecker[0] = baseline->second->endpoints[0]->lines.find( 1373 winner->first); 1374 LineChecker[1] = baseline->second->endpoints[1]->lines.find( 1375 winner->first); 1376 if (LineChecker[0] 1377 == baseline->second->endpoints[0]->lines.end()) 1378 { // create 1379 BPS[0] = baseline->second->endpoints[0]; 1380 BPS[1] = winner->second; 1381 BLS[1] = new class BoundaryLineSet(BPS, 1382 LinesOnBoundaryCount); 1383 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, 1384 BLS[1])); 1385 LinesOnBoundaryCount++; 1386 } 1387 else 1388 BLS[1] = LineChecker[0]->second; 1389 if (LineChecker[1] 1390 == baseline->second->endpoints[1]->lines.end()) 1391 { // create 1392 BPS[0] = baseline->second->endpoints[1]; 1393 BPS[1] = winner->second; 1394 BLS[2] = new class BoundaryLineSet(BPS, 1395 LinesOnBoundaryCount); 1396 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, 1397 BLS[2])); 1398 LinesOnBoundaryCount++; 1399 } 1400 else 1401 BLS[2] = LineChecker[1]->second; 1402 BTS = new class BoundaryTriangleSet(BLS, 1403 TrianglesOnBoundaryCount); 1404 TrianglesOnBoundary.insert(TrianglePair( 1405 TrianglesOnBoundaryCount, BTS)); 1406 TrianglesOnBoundaryCount++; 1407 } 1408 else 1409 { 1410 *out << Verbose(1) 1411 << "I could not determine a winner for this baseline " 1412 << *(baseline->second) << "." << endl; 1413 } 1414 1415 // 5d. If the set of lines is not yet empty, go to 5. and continue 1416 } 1417 else 1418 *out << Verbose(2) << "Baseline candidate " << *(baseline->second) 1419 << " has a triangle count of " 1420 << baseline->second->TrianglesCount << "." << endl; 1421 } 1422 while (flag); 1360 1423 1361 1424 } … … 1368 1431 Tesselation::AddPoint(atom *Walker) 1369 1432 { 1370 PointTestPair InsertUnique;1371 BPS[0] = new class BoundaryPointSet(Walker);1372 InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0]));1373 if (InsertUnique.second) // if new point was not present before, increase counter1374 PointsOnBoundaryCount++;1433 PointTestPair InsertUnique; 1434 BPS[0] = new class BoundaryPointSet(Walker); 1435 InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0])); 1436 if (InsertUnique.second) // if new point was not present before, increase counter 1437 PointsOnBoundaryCount++; 1375 1438 } 1376 1439 ; … … 1384 1447 Tesselation::AddTrianglePoint(atom* Candidate, int n) 1385 1448 { 1386 PointTestPair InsertUnique;1387 TPS[n] = new class BoundaryPointSet(Candidate);1388 InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n]));1389 if (InsertUnique.second) // if new point was not present before, increase counter1390 {1391 PointsOnBoundaryCount++;1392 }1393 else1394 {1395 delete TPS[n];1396 cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node)1397 << " gibt's schon in der PointMap." << endl;1398 TPS[n] = (InsertUnique.first)->second;1399 }1449 PointTestPair InsertUnique; 1450 TPS[n] = new class BoundaryPointSet(Candidate); 1451 InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n])); 1452 if (InsertUnique.second) // if new point was not present before, increase counter 1453 { 1454 PointsOnBoundaryCount++; 1455 } 1456 else 1457 { 1458 delete TPS[n]; 1459 cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node) 1460 << " gibt's schon in der PointMap." << endl; 1461 TPS[n] = (InsertUnique.first)->second; 1462 } 1400 1463 } 1401 1464 ; … … 1410 1473 void 1411 1474 Tesselation::AddTriangleLine(class BoundaryPointSet *a, 1412 class BoundaryPointSet *b, int n)1413 { 1414 LineMap::iterator LineWalker;1415 //cout << "Manually checking endpoints for line." << endl;1416 if ((a->lines.find(b->node->nr))->first == b->node->nr)1417 //If a line is there, how do I recognize that beyond a shadow of a doubt?1418 {1419 //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl;1420 1421 LineWalker = LinesOnBoundary.end();1422 LineWalker--;1423 1424 while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr,1425 b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max(1426 a->node->nr, b->node->nr))1427 {1428 //cout << Verbose(1) << "Looking for line which already exists"<< endl;1429 LineWalker--;1430 }1431 BPS[0] = LineWalker->second->endpoints[0];1432 BPS[1] = LineWalker->second->endpoints[1];1433 BLS[n] = LineWalker->second;1434 1435 }1436 else1437 {1438 cout << Verbose(2)1439 << "Adding line which has not been used before between "1440 << *(a->node) << " and " << *(b->node) << "." << endl;1441 BPS[0] = a;1442 BPS[1] = b;1443 BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);1444 1445 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n]));1446 LinesOnBoundaryCount++;1447 1448 }1475 class BoundaryPointSet *b, int n) 1476 { 1477 LineMap::iterator LineWalker; 1478 //cout << "Manually checking endpoints for line." << endl; 1479 if ((a->lines.find(b->node->nr)) != a->lines.end()) // ->first == b->node->nr) 1480 //If a line is there, how do I recognize that beyond a shadow of a doubt? 1481 { 1482 //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl; 1483 1484 LineWalker = LinesOnBoundary.end(); 1485 LineWalker--; 1486 1487 while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr, 1488 b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max( 1489 a->node->nr, b->node->nr)) 1490 { 1491 //cout << Verbose(1) << "Looking for line which already exists"<< endl; 1492 LineWalker--; 1493 } 1494 BPS[0] = LineWalker->second->endpoints[0]; 1495 BPS[1] = LineWalker->second->endpoints[1]; 1496 BLS[n] = LineWalker->second; 1497 1498 } 1499 else 1500 { 1501 cout << Verbose(2) 1502 << "Adding line which has not been used before between " 1503 << *(a->node) << " and " << *(b->node) << "." << endl; 1504 BPS[0] = a; 1505 BPS[1] = b; 1506 BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1507 1508 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n])); 1509 LinesOnBoundaryCount++; 1510 1511 } 1449 1512 } 1450 1513 ; … … 1457 1520 { 1458 1521 1459 cout << Verbose(1) << "Adding triangle to its lines" << endl; 1460 int i = 0; 1461 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1462 TrianglesOnBoundaryCount++; 1463 1464 /* 1465 * this is apparently done when constructing triangle 1466 1467 for (i=0; i<3; i++) 1468 { 1469 BLS[i]->AddTriangle(BTS); 1470 } 1471 */ 1472 } 1473 ; 1522 cout << Verbose(1) << "Adding triangle to its lines" << endl; 1523 int i = 0; 1524 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1525 TrianglesOnBoundaryCount++; 1526 1527 /* 1528 * this is apparently done when constructing triangle 1529 1530 for (i=0; i<3; i++) 1531 { 1532 BLS[i]->AddTriangle(BTS); 1533 } 1534 */ 1535 } 1536 ; 1537 1538 1539 double det_get(gsl_matrix *A, int inPlace) { 1540 /* 1541 inPlace = 1 => A is replaced with the LU decomposed copy. 1542 inPlace = 0 => A is retained, and a copy is used for LU. 1543 */ 1544 1545 double det; 1546 int signum; 1547 gsl_permutation *p = gsl_permutation_alloc(A->size1); 1548 gsl_matrix *tmpA; 1549 1550 if (inPlace) 1551 tmpA = A; 1552 else { 1553 gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2); 1554 gsl_matrix_memcpy(tmpA , A); 1555 } 1556 1557 1558 gsl_linalg_LU_decomp(tmpA , p , &signum); 1559 det = gsl_linalg_LU_det(tmpA , signum); 1560 gsl_permutation_free(p); 1561 if (! inPlace) 1562 gsl_matrix_free(tmpA); 1563 1564 return det; 1565 }; 1566 1567 void get_sphere(Vector *center, Vector &a, Vector &b, Vector &c, double RADIUS) 1568 { 1569 gsl_matrix *A = gsl_matrix_calloc(3,3); 1570 double m11, m12, m13, m14; 1571 1572 for(int i=0;i<3;i++) { 1573 gsl_matrix_set(A, i, 0, a.x[i]); 1574 gsl_matrix_set(A, i, 1, b.x[i]); 1575 gsl_matrix_set(A, i, 2, c.x[i]); 1576 } 1577 m11 = det_get(A, 1); 1578 1579 for(int i=0;i<3;i++) { 1580 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]); 1581 gsl_matrix_set(A, i, 1, b.x[i]); 1582 gsl_matrix_set(A, i, 2, c.x[i]); 1583 } 1584 m12 = det_get(A, 1); 1585 1586 for(int i=0;i<3;i++) { 1587 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]); 1588 gsl_matrix_set(A, i, 1, a.x[i]); 1589 gsl_matrix_set(A, i, 2, c.x[i]); 1590 } 1591 m13 = det_get(A, 1); 1592 1593 for(int i=0;i<3;i++) { 1594 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]); 1595 gsl_matrix_set(A, i, 1, a.x[i]); 1596 gsl_matrix_set(A, i, 2, b.x[i]); 1597 } 1598 m14 = det_get(A, 1); 1599 1600 if (fabs(m11) < MYEPSILON) 1601 cerr << "ERROR: three points are colinear." << endl; 1602 1603 center->x[0] = 0.5 * m12/ m11; 1604 center->x[1] = -0.5 * m13/ m11; 1605 center->x[2] = 0.5 * m14/ m11; 1606 1607 if (fabs(a.Distance(center) - RADIUS) > MYEPSILON) 1608 cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl; 1609 1610 gsl_matrix_free(A); 1611 }; 1612 1613 1474 1614 1475 1615 /** … … 1489 1629 * @param Umkreisradius double radius of circumscribing circle 1490 1630 */ 1491 1492 void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector* Direction, Vector* AlternativeDirection, 1493 double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius) 1494 { 1495 Vector TempNormal, helper; 1496 double Restradius; 1497 1498 *Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ; 1499 Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma))); 1500 // Here we calculated center of circumscribing circle, using barycentric coordinates 1501 1502 TempNormal.CopyVector(&a); 1503 TempNormal.SubtractVector(&b); 1504 helper.CopyVector(&a); 1505 helper.SubtractVector(&c); 1506 TempNormal.VectorProduct(&helper); 1507 if (fabs(HalfplaneIndicator) < MYEPSILON) 1508 { 1509 if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0)) 1510 { 1511 TempNormal.Scale(-1); 1512 } 1513 } 1514 else 1515 { 1516 if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0) 1517 { 1518 TempNormal.Scale(-1); 1519 } 1520 } 1521 1522 TempNormal.Normalize(); 1523 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius); 1524 TempNormal.Scale(Restradius); 1525 1526 Center->AddVector(&TempNormal); 1527 } 1528 ; 1529 1631 void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection, 1632 double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius) 1633 { 1634 Vector TempNormal, helper; 1635 double Restradius; 1636 Vector OtherCenter; 1637 cout << Verbose(3) << "Begin of Get_center_of_sphere.\n"; 1638 Center->Zero(); 1639 helper.CopyVector(&a); 1640 helper.Scale(sin(2.*alpha)); 1641 Center->AddVector(&helper); 1642 helper.CopyVector(&b); 1643 helper.Scale(sin(2.*beta)); 1644 Center->AddVector(&helper); 1645 helper.CopyVector(&c); 1646 helper.Scale(sin(2.*gamma)); 1647 Center->AddVector(&helper); 1648 //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ; 1649 Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma))); 1650 NewUmkreismittelpunkt->CopyVector(Center); 1651 cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n"; 1652 // Here we calculated center of circumscribing circle, using barycentric coordinates 1653 cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n"; 1654 1655 TempNormal.CopyVector(&a); 1656 TempNormal.SubtractVector(&b); 1657 helper.CopyVector(&a); 1658 helper.SubtractVector(&c); 1659 TempNormal.VectorProduct(&helper); 1660 if (fabs(HalfplaneIndicator) < MYEPSILON) 1661 { 1662 if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0)) 1663 { 1664 TempNormal.Scale(-1); 1665 } 1666 } 1667 else 1668 { 1669 if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0) 1670 { 1671 TempNormal.Scale(-1); 1672 } 1673 } 1674 1675 TempNormal.Normalize(); 1676 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius); 1677 cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n"; 1678 TempNormal.Scale(Restradius); 1679 cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n"; 1680 1681 Center->AddVector(&TempNormal); 1682 cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n"; 1683 get_sphere(&OtherCenter, a, b, c, RADIUS); 1684 cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n"; 1685 cout << Verbose(3) << "End of Get_center_of_sphere.\n"; 1686 }; 1530 1687 1531 1688 /** This recursive function finds a third point, to form a triangle with two given ones. 1532 1689 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \ 1533 * supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \1534 * upon which we operate.1535 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \1536 * direction and angle into Storage.1537 * We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \1538 * with all neighbours of the candidate.1690 * supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \ 1691 * upon which we operate. 1692 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \ 1693 * direction and angle into Storage. 1694 * We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \ 1695 * with all neighbours of the candidate. 1539 1696 * @param a first point 1540 1697 * @param b second point … … 1552 1709 * @param mol molecule structure with atoms and bonds 1553 1710 */ 1554 1555 void Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent, 1556 int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint, 1557 atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol) 1558 { 1559 //cout << "ReferencePoint is " << ReferencePoint.x[0] << " "<< ReferencePoint.x[1] << " "<< ReferencePoint.x[2] << " "<< endl; 1560 /* OldNormal is normal vector on the old triangle 1561 * direction1 is normal on the triangle line, from which we come, as well as on OldNormal. 1562 * Chord points from b to a!!! 1563 */ 1564 Vector dif_a; //Vector from a to candidate 1565 Vector dif_b; //Vector from b to candidate 1566 Vector AngleCheck; 1567 Vector TempNormal, Umkreismittelpunkt; 1568 Vector Mittelpunkt; 1569 1570 double CurrentEpsilon = 0.1; 1571 double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance; 1572 double BallAngle, AlternativeSign; 1573 atom *Walker; // variable atom point 1574 1575 1576 dif_a.CopyVector(&(a->x)); 1577 dif_a.SubtractVector(&(Candidate->x)); 1578 dif_b.CopyVector(&(b->x)); 1579 dif_b.SubtractVector(&(Candidate->x)); 1580 AngleCheck.CopyVector(&(Candidate->x)); 1581 AngleCheck.SubtractVector(&(a->x)); 1582 AngleCheck.ProjectOntoPlane(Chord); 1583 1584 SideA = dif_b.Norm(); 1585 SideB = dif_a.Norm(); 1586 SideC = Chord->Norm(); 1587 //Chord->Scale(-1); 1588 1589 alpha = Chord->Angle(&dif_a); 1590 beta = M_PI - Chord->Angle(&dif_b); 1591 gamma = dif_a.Angle(&dif_b); 1592 1593 1594 if (a != Candidate and b != Candidate and c != Candidate) 1595 { 1596 1597 Umkreisradius = SideA / 2.0 / sin(alpha); 1598 //cout << Umkreisradius << endl; 1599 //cout << SideB / 2.0 / sin(beta) << endl; 1600 //cout << SideC / 2.0 / sin(gamma) << endl; 1601 1602 if (Umkreisradius < RADIUS) //Checking whether ball will at least rest on points. 1603 { 1604 cout << Verbose(1) << "Candidate is "<< *Candidate << endl; 1605 sign = AngleCheck.ScalarProduct(direction1); 1606 if (fabs(sign)<MYEPSILON) 1607 { 1608 if (AngleCheck.ScalarProduct(OldNormal)<0) 1609 { 1610 sign =0; 1611 AlternativeSign=1; 1612 } 1613 else 1614 { 1615 sign =0; 1616 AlternativeSign=-1; 1617 } 1618 } 1619 else 1620 { 1621 sign /= fabs(sign); 1622 } 1623 1624 1625 1626 Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius); 1627 1628 AngleCheck.CopyVector(&ReferencePoint); 1629 AngleCheck.Scale(-1); 1630 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl; 1631 AngleCheck.AddVector(&Mittelpunkt); 1632 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl; 1633 1634 BallAngle = AngleCheck.Angle(OldNormal); 1635 1636 //cout << "direction1 is " << direction1->x[0] <<" "<< direction1->x[1] <<" "<< direction1->x[2] <<" " << endl; 1637 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl; 1638 1639 cout << Verbose(1) << "BallAngle is " << BallAngle << " Sign is " << sign << endl; 1640 1641 if (AngleCheck.ScalarProduct(direction1) >=0) 1642 { 1643 if (Storage[0]< -1.5) // first Candidate at all 1644 { 1645 1646 cout << "Next better candidate is " << *Candidate << " with "; 1647 Opt_Candidate = Candidate; 1648 Storage[0] = sign; 1649 Storage[1] = AlternativeSign; 1650 Storage[2] = BallAngle; 1651 cout << "Angle is " << Storage[2] << ", Halbraum ist " 1652 << Storage[0] << endl; 1653 1654 1655 } 1656 else 1657 { 1658 if ( Storage[2] > BallAngle) 1659 { 1660 cout << "Next better candidate is " << *Candidate << " with "; 1661 Opt_Candidate = Candidate; 1662 Storage[0] = sign; 1663 Storage[1] = AlternativeSign; 1664 Storage[2] = BallAngle; 1665 cout << "Angle is " << Storage[2] << ", Halbraum ist " 1666 << Storage[0] << endl; 1667 } 1668 else 1669 { 1670 //if (DEBUG) 1671 cout << "Looses to better candidate" << endl; 1672 1673 } 1674 } 1675 } 1676 else 1677 { 1678 //if (DEBUG) 1679 cout << "Refused due to bad direction of ball centre." << endl; 1680 } 1681 } 1682 else 1683 { 1684 //if (DEBUG) 1685 cout << "Doesn't satisfy requirements for circumscribing circle" << endl; 1686 } 1687 } 1688 else 1689 { 1690 //if (DEBUG) 1691 cout << "identisch mit Ursprungslinie" << endl; 1692 1693 } 1694 1695 1696 1697 if (RecursionLevel < 9) // Seven is the recursion level threshold. 1698 { 1699 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) // go through all bond 1700 { 1701 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom( 1702 Candidate); 1703 if (Walker == Parent) 1704 { // don't go back the same bond 1705 continue; 1706 } 1707 else 1708 { 1709 Find_next_suitable_point_via_Angle_of_Sphere(a, b, c, Walker, Candidate, RecursionLevel 1710 + 1, Chord, direction1, OldNormal, ReferencePoint, Opt_Candidate, Storage, RADIUS, 1711 mol); //call function again 1712 } 1713 } 1714 } 1715 } 1716 ; 1717 1718 1719 /** This recursive function finds a third point, to form a triangle with two given ones. 1720 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \ 1721 * supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \ 1722 * upon which we operate. 1723 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \ 1724 * direction and angle into Storage. 1725 * We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \ 1726 * with all neighbours of the candidate. 1727 * @param a first point 1728 * @param b second point 1729 * @param Candidate base point along whose bonds to start looking from 1730 * @param Parent point to avoid during search as its wrong direction 1731 * @param RecursionLevel contains current recursion depth 1732 * @param Chord baseline vector of first and second point 1733 * @param d1 second in plane vector (along with \a Chord) of the triangle the baseline belongs to 1734 * @param OldNormal normal of the triangle which the baseline belongs to 1735 * @param Opt_Candidate candidate reference to return 1736 * @param Opt_Mittelpunkt Centerpoint of ball, when resting on Opt_Candidate 1737 * @param Storage array containing two angles of current Opt_Candidate 1738 * @param RADIUS radius of ball 1739 * @param mol molecule structure with atoms and bonds 1740 */ 1741 1742 void Find_next_suitable_point(atom* a, atom* b, atom* Candidate, atom* Parent, 1743 int RecursionLevel, Vector *Chord, Vector *d1, Vector *OldNormal, 1744 atom*& Opt_Candidate, Vector *Opt_Mittelpunkt, double *Storage, const double RADIUS, molecule* mol) 1745 { 1746 /* OldNormal is normal vector on the old triangle 1747 * d1 is normal on the triangle line, from which we come, as well as on OldNormal. 1748 * Chord points from b to a!!! 1749 */ 1750 Vector dif_a; //Vector from a to candidate 1751 Vector dif_b; //Vector from b to candidate 1752 Vector AngleCheck, AngleCheckReference, DirectionCheckPoint; 1753 Vector TempNormal, Umkreismittelpunkt, Mittelpunkt; 1754 1755 double CurrentEpsilon = 0.1; 1756 double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance; 1757 double BallAngle; 1758 atom *Walker; // variable atom point 1759 1760 1761 dif_a.CopyVector(&(a->x)); 1762 dif_a.SubtractVector(&(Candidate->x)); 1763 dif_b.CopyVector(&(b->x)); 1764 dif_b.SubtractVector(&(Candidate->x)); 1765 DirectionCheckPoint.CopyVector(&dif_a); 1766 DirectionCheckPoint.Scale(-1); 1767 DirectionCheckPoint.ProjectOntoPlane(Chord); 1768 1769 SideA = dif_b.Norm(); 1770 SideB = dif_a.Norm(); 1771 SideC = Chord->Norm(); 1772 //Chord->Scale(-1); 1773 1774 alpha = Chord->Angle(&dif_a); 1775 beta = M_PI - Chord->Angle(&dif_b); 1776 gamma = dif_a.Angle(&dif_b); 1777 1778 1779 if (DEBUG) 1780 { 1781 cout << "Atom number" << Candidate->nr << endl; 1782 Candidate->x.Output((ofstream *) &cout); 1783 cout << "number of bonds " << mol->NumberOfBondsPerAtom[Candidate->nr] 1784 << endl; 1785 } 1786 1787 if (a != Candidate and b != Candidate) 1788 { 1789 // alpha = dif_a.Angle(&dif_b) / 2.; 1790 // SideA = Chord->Norm() / 2.;// (Chord->Norm()/2.) / sin(0.5*alpha); 1791 // SideB = dif_a.Norm(); 1792 // centerline = SideA * SideA + SideB * SideB - 2. * SideA * SideB * cos( 1793 // alpha); // note this is squared of center line length 1794 // centerline = (Chord->Norm()/2.) / sin(0.5*alpha); 1795 // Those are remains from Freddie. Needed? 1796 1797 1798 1799 Umkreisradius = SideA / 2.0 / sin(alpha); 1800 //cout << Umkreisradius << endl; 1801 //cout << SideB / 2.0 / sin(beta) << endl; 1802 //cout << SideC / 2.0 / sin(gamma) << endl; 1803 1804 if (Umkreisradius < RADIUS && DirectionCheckPoint.ScalarProduct(&(Candidate->x))>0) //Checking whether ball will at least rest o points. 1805 { 1806 1807 // intermediate calculations to aquire centre of sphere, called Mittelpunkt: 1808 1809 Umkreismittelpunkt = (a->x) * sin(2.*alpha) + b->x * sin(2.*beta) + (Candidate->x) * sin(2.*gamma) ; 1810 Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma))); 1811 1812 TempNormal.CopyVector(&dif_a); 1813 TempNormal.VectorProduct(&dif_b); 1814 if (TempNormal.ScalarProduct(OldNormal)<0 && sign>0 || TempNormal.ScalarProduct(OldNormal)>0 && sign<0) 1815 { 1816 TempNormal.Scale(-1); 1817 } 1818 TempNormal.Normalize(); 1819 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius); 1820 TempNormal.Scale(Restradius); 1821 1822 Mittelpunkt.CopyVector(&Umkreismittelpunkt); 1823 Mittelpunkt.AddVector(&TempNormal); //this is center of sphere supported by a, b and Candidate 1824 1825 AngleCheck.CopyVector(Chord); 1826 AngleCheck.Scale(-0.5); 1827 AngleCheck.SubtractVector(&(b->x)); 1828 AngleCheckReference.CopyVector(&AngleCheck); 1829 AngleCheckReference.AddVector(Opt_Mittelpunkt); 1830 AngleCheck.AddVector(&Mittelpunkt); 1831 1832 BallAngle = AngleCheck.Angle(&AngleCheckReference); 1833 1834 d1->ProjectOntoPlane(&AngleCheckReference); 1835 sign = AngleCheck.ScalarProduct(d1); 1836 sign /= fabs(sign); // +1 if in direction of triangle plane, -1 if in other direction... 1837 1838 1839 if (Storage[0]< -1.5) // first Candidate at all 1840 { 1841 1842 cout << "Next better candidate is " << *Candidate << " with "; 1843 Opt_Candidate = Candidate; 1844 Storage[0] = sign; 1845 Storage[1] = BallAngle; 1846 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1847 cout << "Angle is " << Storage[1] << ", Halbraum ist " 1848 << Storage[0] << endl; 1849 1850 1851 } 1852 else 1853 { 1854 /* 1855 * removed due to change in criterium, now checking angle of ball to old normal. 1856 //We will now check for non interference, that is if the new candidate would have the Opt_Candidate 1857 //within the ball. 1858 1859 Distance = Opt_Candidate->x.Distance(&Mittelpunkt); 1860 //cout << "Opt_Candidate " << Opt_Candidate << " has distance " << Distance << " to Center of Candidate " << endl; 1861 1862 1863 if (Distance >RADIUS) // We have no interference and may now check whether the new point is better. 1864 */ 1865 { 1866 //cout << "Atom " << Candidate << " has distance " << Candidate->x.Distance(Opt_Mittelpunkt) << " to Center of Candidate " << endl; 1867 1868 if (((Storage[0] < 0 && fabs(sign - Storage[0]) > CurrentEpsilon))) //This will give absolute preference to those in "right-hand" quadrants 1869 //(Candidate->x.Distance(Opt_Mittelpunkt) < RADIUS)) //and those where Candidate would be within old Sphere. 1870 { 1871 cout << "Next better candidate is " << *Candidate << " with "; 1872 Opt_Candidate = Candidate; 1873 Storage[0] = sign; 1874 Storage[1] = BallAngle; 1875 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1876 cout << "Angle is " << Storage[1] << ", Halbraum ist " 1877 << Storage[0] << endl; 1878 1879 1880 } 1881 else 1882 { 1883 if ((fabs(sign - Storage[0]) < CurrentEpsilon && sign > 0 1884 && Storage[1] > BallAngle) || 1885 (fabs(sign - Storage[0]) < CurrentEpsilon && sign < 0 1886 && Storage[1] < BallAngle)) 1887 //Depending on quadrant we prefer higher or lower atom with respect to Triangle normal first. 1888 { 1889 cout << "Next better candidate is " << *Candidate << " with "; 1890 Opt_Candidate = Candidate; 1891 Storage[0] = sign; 1892 Storage[1] = BallAngle; 1893 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1894 cout << "Angle is " << Storage[1] << ", Halbraum ist " 1895 << Storage[0] << endl; 1896 } 1897 1898 } 1899 } 1900 /* 1901 * This is for checking point-angle and presence of Candidates in Ball, currently we are checking the ball Angle. 1902 * 1903 else 1904 { 1905 if (sign>0 && BallAngle>0 && Storage[0]<0) 1906 { 1907 cout << "Next better candidate is " << *Candidate << " with "; 1908 Opt_Candidate = Candidate; 1909 Storage[0] = sign; 1910 Storage[1] = BallAngle; 1911 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1912 cout << "Angle is " << Storage[1] << ", Halbraum ist " 1913 << Storage[0] << endl; 1914 1915 //Debugging purposes only 1916 cout << "Umkreismittelpunkt has coordinates" << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] <<" "<<Umkreismittelpunkt.x[2] << endl; 1917 cout << "Candidate has coordinates" << Candidate->x.x[0]<< " " << Candidate->x.x[1] << " " << Candidate->x.x[2] << endl; 1918 cout << "a has coordinates" << a->x.x[0]<< " " << a->x.x[1] << " " << a->x.x[2] << endl; 1919 cout << "b has coordinates" << b->x.x[0]<< " " << b->x.x[1] << " " << b->x.x[2] << endl; 1920 cout << "Mittelpunkt has coordinates" << Mittelpunkt.x[0] << " " << Mittelpunkt.x[1]<< " " <<Mittelpunkt.x[2] << endl; 1921 cout << "Umkreisradius ist " << Umkreisradius << endl; 1922 cout << "Restradius ist " << Restradius << endl; 1923 cout << "TempNormal has coordinates " << TempNormal.x[0] << " " << TempNormal.x[1] << " " << TempNormal.x[2] << " " << endl; 1924 cout << "OldNormal has coordinates " << OldNormal->x[0] << " " << OldNormal->x[1] << " " << OldNormal->x[2] << " " << endl; 1925 cout << "Dist a to UmkreisMittelpunkt " << a->x.Distance(&Umkreismittelpunkt) << endl; 1926 cout << "Dist b to UmkreisMittelpunkt " << b->x.Distance(&Umkreismittelpunkt) << endl; 1927 cout << "Dist Candidate to UmkreisMittelpunkt " << Candidate->x.Distance(&Umkreismittelpunkt) << endl; 1928 cout << "Dist a to Mittelpunkt " << a->x.Distance(&Mittelpunkt) << endl; 1929 cout << "Dist b to Mittelpunkt " << b->x.Distance(&Mittelpunkt) << endl; 1930 cout << "Dist Candidate to Mittelpunkt " << Candidate->x.Distance(&Mittelpunkt) << endl; 1931 1932 1933 1934 } 1935 else 1936 { 1937 if (DEBUG) 1938 cout << "Looses to better candidate" << endl; 1939 } 1940 } 1941 */ 1942 } 1943 } 1944 else 1945 { 1946 if (DEBUG) 1947 { 1948 cout << "Doesn't satisfy requirements for circumscribing circle" << endl; 1949 } 1950 } 1951 } 1952 1953 else 1954 { 1955 if (DEBUG) 1956 cout << "identisch mit Ursprungslinie" << endl; 1957 } 1958 1959 if (RecursionLevel < 9) // Five is the recursion level threshold. 1960 { 1961 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) // go through all bond 1962 { 1963 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom( 1964 Candidate); 1965 if (Walker == Parent) 1966 { // don't go back the same bond 1967 continue; 1968 } 1969 else 1970 { 1971 Find_next_suitable_point(a, b, Walker, Candidate, RecursionLevel 1972 + 1, Chord, d1, OldNormal, Opt_Candidate, Opt_Mittelpunkt, Storage, RADIUS, 1973 mol); //call function again 1974 1975 } 1976 } 1977 } 1978 } 1979 ; 1711 void Tesselation::Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent, 1712 int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint, 1713 atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol) 1714 { 1715 cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n"; 1716 cout << Verbose(3) << "Candidate is "<< *Candidate << endl; 1717 cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl; 1718 cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl; 1719 cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl; 1720 cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl; 1721 /* OldNormal is normal vector on the old triangle 1722 * direction1 is normal on the triangle line, from which we come, as well as on OldNormal. 1723 * Chord points from b to a!!! 1724 */ 1725 Vector dif_a; //Vector from a to candidate 1726 Vector dif_b; //Vector from b to candidate 1727 Vector AngleCheck; 1728 Vector TempNormal, Umkreismittelpunkt; 1729 Vector Mittelpunkt; 1730 1731 double CurrentEpsilon = 0.1; 1732 double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance; 1733 double BallAngle, AlternativeSign; 1734 atom *Walker; // variable atom point 1735 1736 Vector NewUmkreismittelpunkt; 1737 1738 if (a != Candidate and b != Candidate and c != Candidate) { 1739 cout << Verbose(3) << "We have a unique candidate!" << endl; 1740 dif_a.CopyVector(&(a->x)); 1741 dif_a.SubtractVector(&(Candidate->x)); 1742 dif_b.CopyVector(&(b->x)); 1743 dif_b.SubtractVector(&(Candidate->x)); 1744 AngleCheck.CopyVector(&(Candidate->x)); 1745 AngleCheck.SubtractVector(&(a->x)); 1746 AngleCheck.ProjectOntoPlane(Chord); 1747 1748 SideA = dif_b.Norm(); 1749 SideB = dif_a.Norm(); 1750 SideC = Chord->Norm(); 1751 //Chord->Scale(-1); 1752 1753 alpha = Chord->Angle(&dif_a); 1754 beta = M_PI - Chord->Angle(&dif_b); 1755 gamma = dif_a.Angle(&dif_b); 1756 1757 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; 1758 1759 if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) { 1760 cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n"; 1761 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; 1762 } 1763 1764 if ((M_PI*179./180. > alpha) && (M_PI*179./180. > beta) && (M_PI*179./180. > gamma)) { 1765 Umkreisradius = SideA / 2.0 / sin(alpha); 1766 //cout << Umkreisradius << endl; 1767 //cout << SideB / 2.0 / sin(beta) << endl; 1768 //cout << SideC / 2.0 / sin(gamma) << endl; 1769 1770 if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points. 1771 cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl; 1772 cout << Verbose(2) << "Candidate is "<< *Candidate << endl; 1773 sign = AngleCheck.ScalarProduct(direction1); 1774 if (fabs(sign)<MYEPSILON) { 1775 if (AngleCheck.ScalarProduct(OldNormal)<0) { 1776 sign =0; 1777 AlternativeSign=1; 1778 } else { 1779 sign =0; 1780 AlternativeSign=-1; 1781 } 1782 } else { 1783 sign /= fabs(sign); 1784 } 1785 if (sign >= 0) { 1786 cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl; 1787 Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius); 1788 Mittelpunkt.SubtractVector(&ReferencePoint); 1789 cout << Verbose(3) << "Reference vector to sphere's center is " << Mittelpunkt << "." << endl; 1790 BallAngle = Mittelpunkt.Angle(OldNormal); 1791 cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl; 1792 1793 //cout << "direction1 is " << *direction1 << "." << endl; 1794 //cout << "Mittelpunkt is " << Mittelpunkt << "."<< endl; 1795 //cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl; 1796 1797 NewUmkreismittelpunkt.SubtractVector(&ReferencePoint); 1798 1799 if ((Mittelpunkt.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) { 1800 if (Storage[0]< -1.5) { // first Candidate at all 1801 if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) { 1802 cout << Verbose(2) << "First good candidate is " << *Candidate << " with "; 1803 Opt_Candidate = Candidate; 1804 Storage[0] = sign; 1805 Storage[1] = AlternativeSign; 1806 Storage[2] = BallAngle; 1807 cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl; 1808 } else 1809 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl; 1810 } else { 1811 if ( Storage[2] > BallAngle) { 1812 if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) { 1813 cout << Verbose(2) << "Next better candidate is " << *Candidate << " with "; 1814 Opt_Candidate = Candidate; 1815 Storage[0] = sign; 1816 Storage[1] = AlternativeSign; 1817 Storage[2] = BallAngle; 1818 cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl; 1819 } else 1820 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl; 1821 } else { 1822 if (DEBUG) { 1823 cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl; 1824 } 1825 } 1826 } 1827 } else { 1828 if (DEBUG) { 1829 cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl; 1830 } 1831 } 1832 } else { 1833 if (DEBUG) { 1834 cout << Verbose(3) << *Candidate << " is not in search direction." << endl; 1835 } 1836 } 1837 } else { 1838 if (DEBUG) { 1839 cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl; 1840 } 1841 } 1842 } else { 1843 if (DEBUG) { 1844 cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl; 1845 } 1846 } 1847 } else { 1848 if (DEBUG) { 1849 cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl; 1850 } 1851 } 1852 1853 if (RecursionLevel < 5) { // Seven is the recursion level threshold. 1854 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond 1855 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate); 1856 if (Walker == Parent) { // don't go back the same bond 1857 continue; 1858 } else { 1859 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 1860 } 1861 } 1862 } 1863 cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n"; 1864 } 1865 ; 1866 1867 1868 /** Constructs the center of the circumcircle defined by three points \a *a, \a *b and \a *c. 1869 * \param *Center new center on return 1870 * \param *a first point 1871 * \param *b second point 1872 * \param *c third point 1873 */ 1874 void GetCenterofCircumcircle(Vector *Center, Vector *a, Vector *b, Vector *c) 1875 { 1876 Vector helper; 1877 double alpha, beta, gamma; 1878 Vector SideA, SideB, SideC; 1879 SideA.CopyVector(b); 1880 SideA.SubtractVector(c); 1881 SideB.CopyVector(c); 1882 SideB.SubtractVector(a); 1883 SideC.CopyVector(a); 1884 SideC.SubtractVector(b); 1885 alpha = M_PI - SideB.Angle(&SideC); 1886 beta = M_PI - SideC.Angle(&SideA); 1887 gamma = M_PI - SideA.Angle(&SideB); 1888 cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl; 1889 if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON) 1890 cerr << "Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl; 1891 1892 Center->Zero(); 1893 helper.CopyVector(a); 1894 helper.Scale(sin(2.*alpha)); 1895 Center->AddVector(&helper); 1896 helper.CopyVector(b); 1897 helper.Scale(sin(2.*beta)); 1898 Center->AddVector(&helper); 1899 helper.CopyVector(c); 1900 helper.Scale(sin(2.*gamma)); 1901 Center->AddVector(&helper); 1902 Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma))); 1903 }; 1904 1905 /** Returns the parameter "path length" for a given \a NewSphereCenter relative to \a OldSphereCenter on a circle on the plane \a CirclePlaneNormal with center \a CircleCenter and radius \a CircleRadius. 1906 * Test whether the \a NewSphereCenter is really on the given plane and in distance \a CircleRadius from \a CircleCenter. 1907 * It calculates the angle, making it unique on [0,2.*M_PI) by comparing to SearchDirection. 1908 * Also the new center is invalid if it the same as the old one and does not lie right above (\a NormalVector) the base line (\a CircleCenter). 1909 * \param CircleCenter Center of the parameter circle 1910 * \param CirclePlaneNormal normal vector to plane of the parameter circle 1911 * \param CircleRadius radius of the parameter circle 1912 * \param NewSphereCenter new center of a circumcircle 1913 * \param OldSphereCenter old center of a circumcircle, defining the zero "path length" on the parameter circle 1914 * \param NormalVector normal vector 1915 * \param SearchDirection search direction to make angle unique on return. 1916 * \return Angle between \a NewSphereCenter and \a OldSphereCenter relative to \a CircleCenter, 2.*M_PI if one test fails 1917 */ 1918 double GetPathLengthonCircumCircle(Vector &CircleCenter, Vector &CirclePlaneNormal, double CircleRadius, Vector &NewSphereCenter, Vector &OldSphereCenter, Vector &NormalVector, Vector &SearchDirection) 1919 { 1920 Vector helper; 1921 double radius, alpha; 1922 1923 helper.CopyVector(&NewSphereCenter); 1924 // test whether new center is on the parameter circle's plane 1925 if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) { 1926 cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal)) << "!" << endl; 1927 helper.ProjectOntoPlane(&CirclePlaneNormal); 1928 } 1929 radius = helper.ScalarProduct(&helper); 1930 // test whether the new center vector has length of CircleRadius 1931 if (fabs(radius - CircleRadius) > HULLEPSILON) 1932 cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl; 1933 alpha = helper.Angle(&OldSphereCenter); 1934 // make the angle unique by checking the halfplanes/search direction 1935 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON) // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals 1936 alpha = 2.*M_PI - alpha; 1937 cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl; 1938 radius = helper.Distance(&OldSphereCenter); 1939 helper.ProjectOntoPlane(&NormalVector); 1940 // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles 1941 if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) { 1942 cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl; 1943 return alpha; 1944 } else { 1945 cout << Verbose(1) << "ERROR: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl; 1946 return 2.*M_PI; 1947 } 1948 }; 1949 1950 1951 /** This recursive function finds a third point, to form a triangle with two given ones. 1952 * The idea is as follows: A sphere with fixed radius is (almost) uniquely defined in space by three points 1953 * that sit on its boundary. Hence, when two points are given and we look for the (next) third point, then 1954 * the center of the sphere is still fixed up to a single parameter. The band of possible values 1955 * describes a circle in 3D-space. The old center of the sphere for the current base triangle gives 1956 * us the "null" on this circle, the new center of the candidate point will be some way along this 1957 * circle. The shorter the way the better is the candidate. Note that the direction is clearly given 1958 * by the normal vector of the base triangle that always points outwards by construction. 1959 * Hence, we construct a Center of this circle which sits right in the middle of the current base line. 1960 * We construct the normal vector that defines the plane this circle lies in, it is just in the 1961 * direction of the baseline. And finally, we need the radius of the circle, which is given by the rest 1962 * with respect to the length of the baseline and the sphere's fixed \a RADIUS. 1963 * Note that there is one difficulty: The circumcircle is uniquely defined, but for the circumsphere's center 1964 * there are two possibilities which becomes clear from the construction as seen below. Hence, we must check 1965 * both. 1966 * Note also that the acos() function is not unique on [0, 2.*M_PI). Hence, we need an additional check 1967 * to decide for one of the two possible angles. Therefore we need a SearchDirection and to make this check 1968 * sensible we need OldSphereCenter to be orthogonal to it. Either we construct SearchDirection orthogonal 1969 * right away, or -- what we do here -- we rotate the relative sphere centers such that this orthogonality 1970 * holds. Then, the normalized projection onto the SearchDirection is either +1 or -1 and thus states whether 1971 * the angle is uniquely in either (0,M_PI] or [M_PI, 2.*M_PI). 1972 * @param BaseTriangle BoundaryTriangleSet of the current base triangle with all three points 1973 * @param BaseLine BoundaryLineSet of BaseTriangle with the current base line 1974 * @param OptCandidate candidate reference on return 1975 * @param OptCandidateCenter candidate's sphere center on return 1976 * @param ShortestAngle the current path length on this circle band for the current Opt_Candidate 1977 * @param RADIUS radius of sphere 1978 * @param *LC LinkedCell structure with neighbouring atoms 1979 */ 1980 // void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC) 1981 // { 1982 // atom *Walker = NULL; 1983 // Vector CircleCenter; // center of the circle, i.e. of the band of sphere's centers 1984 // Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in 1985 // Vector OldSphereCenter; // center of the sphere defined by the three points of BaseTriangle 1986 // Vector NewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility 1987 // Vector OtherNewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility 1988 // Vector NewNormalVector; // normal vector of the Candidate's triangle 1989 // Vector SearchDirection; // vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate) 1990 // Vector helper; 1991 // LinkedAtoms *List = NULL; 1992 // double CircleRadius; // radius of this circle 1993 // double radius; 1994 // double alpha, Otheralpha; // angles (i.e. parameter for the circle). 1995 // double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle 1996 // int N[NDIM], Nlower[NDIM], Nupper[NDIM]; 1997 // atom *Candidate = NULL; 1998 // 1999 // cout << Verbose(1) << "Begin of Find_next_suitable_point" << endl; 2000 // 2001 // cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << BaseTriangle->NormalVector << "." << endl; 2002 // 2003 // // construct center of circle 2004 // CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x)); 2005 // CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x); 2006 // CircleCenter.Scale(0.5); 2007 // 2008 // // construct normal vector of circle 2009 // CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x); 2010 // CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x); 2011 // 2012 // // calculate squared radius of circle 2013 // radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal); 2014 // if (radius/4. < RADIUS*RADIUS) { 2015 // CircleRadius = RADIUS*RADIUS - radius/4.; 2016 // CirclePlaneNormal.Normalize(); 2017 // cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl; 2018 // 2019 // // construct old center 2020 // GetCenterofCircumcircle(&OldSphereCenter, &(BaseTriangle->endpoints[0]->node->x), &(BaseTriangle->endpoints[1]->node->x), &(BaseTriangle->endpoints[2]->node->x)); 2021 // helper.CopyVector(&BaseTriangle->NormalVector); // normal vector ensures that this is correct center of the two possible ones 2022 // radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&OldSphereCenter); 2023 // helper.Scale(sqrt(RADIUS*RADIUS - radius)); 2024 // OldSphereCenter.AddVector(&helper); 2025 // OldSphereCenter.SubtractVector(&CircleCenter); 2026 // cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl; 2027 // 2028 // // test whether old center is on the band's plane 2029 // if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) { 2030 // cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl; 2031 // OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal); 2032 // } 2033 // radius = OldSphereCenter.ScalarProduct(&OldSphereCenter); 2034 // if (fabs(radius - CircleRadius) < HULLEPSILON) { 2035 // 2036 // // construct SearchDirection 2037 // SearchDirection.MakeNormalVector(&BaseTriangle->NormalVector, &CirclePlaneNormal); 2038 // helper.CopyVector(&BaseLine->endpoints[0]->node->x); 2039 // for(int i=0;i<3;i++) // just take next different endpoint 2040 // if ((BaseTriangle->endpoints[i]->node != BaseLine->endpoints[0]->node) && (BaseTriangle->endpoints[i]->node != BaseLine->endpoints[1]->node)) { 2041 // helper.SubtractVector(&BaseTriangle->endpoints[i]->node->x); 2042 // } 2043 // if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON) // ohoh, SearchDirection points inwards! 2044 // SearchDirection.Scale(-1.); 2045 // SearchDirection.ProjectOntoPlane(&OldSphereCenter); 2046 // SearchDirection.Normalize(); 2047 // cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl; 2048 // if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) { // rotated the wrong way! 2049 // cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl; 2050 // } 2051 // 2052 // if (LC->SetIndexToVector(&CircleCenter)) { // get cell for the starting atom 2053 // for(int i=0;i<NDIM;i++) // store indices of this cell 2054 // N[i] = LC->n[i]; 2055 // cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl; 2056 // } else { 2057 // cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl; 2058 // return; 2059 // } 2060 // // then go through the current and all neighbouring cells and check the contained atoms for possible candidates 2061 // cout << Verbose(2) << "LC Intervals:"; 2062 // for (int i=0;i<NDIM;i++) { 2063 // Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0; 2064 // Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1; 2065 // cout << " [" << Nlower[i] << "," << Nupper[i] << "] "; 2066 // } 2067 // cout << endl; 2068 // for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 2069 // for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 2070 // for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 2071 // List = LC->GetCurrentCell(); 2072 // cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 2073 // if (List != NULL) { 2074 // for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 2075 // Candidate = (*Runner); 2076 // 2077 // // check for three unique points 2078 // if ((Candidate != BaseTriangle->endpoints[0]->node) && (Candidate != BaseTriangle->endpoints[1]->node) && (Candidate != BaseTriangle->endpoints[2]->node)) { 2079 // cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl; 2080 // 2081 // // construct both new centers 2082 // GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x)); 2083 // OtherNewSphereCenter.CopyVector(&NewSphereCenter); 2084 // 2085 // if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) { 2086 // helper.CopyVector(&NewNormalVector); 2087 // cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl; 2088 // radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter); 2089 // if (radius < RADIUS*RADIUS) { 2090 // helper.Scale(sqrt(RADIUS*RADIUS - radius)); 2091 // cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl; 2092 // NewSphereCenter.AddVector(&helper); 2093 // NewSphereCenter.SubtractVector(&CircleCenter); 2094 // cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl; 2095 // 2096 // helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction 2097 // OtherNewSphereCenter.AddVector(&helper); 2098 // OtherNewSphereCenter.SubtractVector(&CircleCenter); 2099 // cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl; 2100 // 2101 // // check both possible centers 2102 // alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection); 2103 // Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection); 2104 // alpha = min(alpha, Otheralpha); 2105 // if (*ShortestAngle > alpha) { 2106 // OptCandidate = Candidate; 2107 // *ShortestAngle = alpha; 2108 // if (alpha != Otheralpha) 2109 // OptCandidateCenter->CopyVector(&NewSphereCenter); 2110 // else 2111 // OptCandidateCenter->CopyVector(&OtherNewSphereCenter); 2112 // cout << Verbose(1) << "We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl; 2113 // } else { 2114 // if (OptCandidate != NULL) 2115 // cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl; 2116 // else 2117 // cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl; 2118 // } 2119 // 2120 // } else { 2121 // cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl; 2122 // } 2123 // } else { 2124 // cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl; 2125 // } 2126 // } else { 2127 // cout << Verbose(1) << "REJECT: Base triangle " << *BaseTriangle << " contains Candidate " << *Candidate << "." << endl; 2128 // } 2129 // } 2130 // } 2131 // } 2132 // } else { 2133 // cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl; 2134 // } 2135 // } else { 2136 // cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and base triangle " << *BaseTriangle << " is too big!" << endl; 2137 // } 2138 // 2139 // cout << Verbose(1) << "End of Find_next_suitable_point" << endl; 2140 // }; 2141 2142 2143 /** Checks whether the triangle consisting of the three atoms is already present. 2144 * Searches for the points in Tesselation::PointsOnBoundary and checks their 2145 * lines. If any of the three edges already has two triangles attached, false is 2146 * returned. 2147 * \param *out output stream for debugging 2148 * \param *Candidates endpoints of the triangle candidate 2149 * \return false - triangle invalid due to edge criteria, true - triangle may be added. 2150 */ 2151 bool Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]) { 2152 LineMap::iterator FindLine; 2153 PointMap::iterator FindPoint; 2154 bool Present[3]; 2155 2156 *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl; 2157 for (int i=0;i<3;i++) { // check through all endpoints 2158 FindPoint = PointsOnBoundary.find(Candidates[i]->nr); 2159 if (FindPoint != PointsOnBoundary.end()) 2160 TPS[i] = FindPoint->second; 2161 else 2162 TPS[i] = NULL; 2163 } 2164 2165 // check lines 2166 for (int i=0;i<3;i++) 2167 if (TPS[i] != NULL) 2168 for (int j=i;j<3;j++) 2169 if (TPS[j] != NULL) { 2170 FindLine = TPS[i]->lines.find(TPS[j]->node->nr); 2171 if ((FindLine != TPS[i]->lines.end()) && (FindLine->second->TrianglesCount > 1)) { 2172 *out << "WARNING: Line " << *FindLine->second << " already present with " << FindLine->second->TrianglesCount << " triangles attached." << endl; 2173 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl; 2174 return false; 2175 } 2176 } 2177 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl; 2178 return true; 2179 }; 2180 2181 /** This recursive function finds a third point, to form a triangle with two given ones. 2182 * Note that this function is for the starting triangle. 2183 * The idea is as follows: A sphere with fixed radius is (almost) uniquely defined in space by three points 2184 * that sit on its boundary. Hence, when two points are given and we look for the (next) third point, then 2185 * the center of the sphere is still fixed up to a single parameter. The band of possible values 2186 * describes a circle in 3D-space. The old center of the sphere for the current base triangle gives 2187 * us the "null" on this circle, the new center of the candidate point will be some way along this 2188 * circle. The shorter the way the better is the candidate. Note that the direction is clearly given 2189 * by the normal vector of the base triangle that always points outwards by construction. 2190 * Hence, we construct a Center of this circle which sits right in the middle of the current base line. 2191 * We construct the normal vector that defines the plane this circle lies in, it is just in the 2192 * direction of the baseline. And finally, we need the radius of the circle, which is given by the rest 2193 * with respect to the length of the baseline and the sphere's fixed \a RADIUS. 2194 * Note that there is one difficulty: The circumcircle is uniquely defined, but for the circumsphere's center 2195 * there are two possibilities which becomes clear from the construction as seen below. Hence, we must check 2196 * both. 2197 * Note also that the acos() function is not unique on [0, 2.*M_PI). Hence, we need an additional check 2198 * to decide for one of the two possible angles. Therefore we need a SearchDirection and to make this check 2199 * sensible we need OldSphereCenter to be orthogonal to it. Either we construct SearchDirection orthogonal 2200 * right away, or -- what we do here -- we rotate the relative sphere centers such that this orthogonality 2201 * holds. Then, the normalized projection onto the SearchDirection is either +1 or -1 and thus states whether 2202 * the angle is uniquely in either (0,M_PI] or [M_PI, 2.*M_PI). 2203 * @param NormalVector normal direction of the base triangle (here the unit axis vector, \sa Find_starting_triangle()) 2204 * @param SearchDirection general direction where to search for the next point, relative to center of BaseLine 2205 * @param OldSphereCenter center of sphere for base triangle, relative to center of BaseLine, giving null angle for the parameter circle 2206 * @param BaseLine BoundaryLineSet with the current base line 2207 * @param ThirdNode third atom to avoid in search 2208 * @param OptCandidate candidate reference on return 2209 * @param OptCandidateCenter candidate's sphere center on return 2210 * @param ShortestAngle the current path length on this circle band for the current Opt_Candidate 2211 * @param RADIUS radius of sphere 2212 * @param *LC LinkedCell structure with neighbouring atoms 2213 */ 2214 void Find_third_point_for_Tesselation(Vector NormalVector, Vector SearchDirection, Vector OldSphereCenter, class BoundaryLineSet *BaseLine, atom *ThirdNode, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC) 2215 { 2216 atom *Walker = NULL; 2217 Vector CircleCenter; // center of the circle, i.e. of the band of sphere's centers 2218 Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in 2219 Vector NewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility 2220 Vector OtherNewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility 2221 Vector NewNormalVector; // normal vector of the Candidate's triangle 2222 Vector helper; 2223 LinkedAtoms *List = NULL; 2224 double CircleRadius; // radius of this circle 2225 double radius; 2226 double alpha, Otheralpha; // angles (i.e. parameter for the circle). 2227 double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle 2228 int N[NDIM], Nlower[NDIM], Nupper[NDIM]; 2229 atom *Candidate = NULL; 2230 2231 cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl; 2232 2233 cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl; 2234 2235 // construct center of circle 2236 CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x)); 2237 CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x); 2238 CircleCenter.Scale(0.5); 2239 2240 // construct normal vector of circle 2241 CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x); 2242 CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x); 2243 2244 // calculate squared radius of circle 2245 radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal); 2246 if (radius/4. < RADIUS*RADIUS) { 2247 CircleRadius = RADIUS*RADIUS - radius/4.; 2248 CirclePlaneNormal.Normalize(); 2249 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl; 2250 2251 // test whether old center is on the band's plane 2252 if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) { 2253 cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl; 2254 OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal); 2255 } 2256 radius = OldSphereCenter.ScalarProduct(&OldSphereCenter); 2257 if (fabs(radius - CircleRadius) < HULLEPSILON) { 2258 2259 // check SearchDirection 2260 cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl; 2261 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) { // rotated the wrong way! 2262 cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl; 2263 } 2264 // get cell for the starting atom 2265 if (LC->SetIndexToVector(&CircleCenter)) { 2266 for(int i=0;i<NDIM;i++) // store indices of this cell 2267 N[i] = LC->n[i]; 2268 cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl; 2269 } else { 2270 cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl; 2271 return; 2272 } 2273 // then go through the current and all neighbouring cells and check the contained atoms for possible candidates 2274 cout << Verbose(2) << "LC Intervals:"; 2275 for (int i=0;i<NDIM;i++) { 2276 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0; 2277 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1; 2278 cout << " [" << Nlower[i] << "," << Nupper[i] << "] "; 2279 } 2280 cout << endl; 2281 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 2282 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 2283 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 2284 List = LC->GetCurrentCell(); 2285 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 2286 if (List != NULL) { 2287 for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 2288 Candidate = (*Runner); 2289 2290 // check for three unique points 2291 if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) && (Candidate != ThirdNode)) { 2292 cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl; 2293 2294 // construct both new centers 2295 GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x)); 2296 OtherNewSphereCenter.CopyVector(&NewSphereCenter); 2297 2298 if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) { 2299 helper.CopyVector(&NewNormalVector); 2300 cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl; 2301 radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter); 2302 if (radius < RADIUS*RADIUS) { 2303 helper.Scale(sqrt(RADIUS*RADIUS - radius)); 2304 cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl; 2305 NewSphereCenter.AddVector(&helper); 2306 NewSphereCenter.SubtractVector(&CircleCenter); 2307 cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl; 2308 2309 helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction 2310 OtherNewSphereCenter.AddVector(&helper); 2311 OtherNewSphereCenter.SubtractVector(&CircleCenter); 2312 cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl; 2313 2314 // check both possible centers 2315 alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection); 2316 Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection); 2317 alpha = min(alpha, Otheralpha); 2318 if (*ShortestAngle > alpha) { 2319 OptCandidate = Candidate; 2320 *ShortestAngle = alpha; 2321 if (alpha != Otheralpha) 2322 OptCandidateCenter->CopyVector(&NewSphereCenter); 2323 else 2324 OptCandidateCenter->CopyVector(&OtherNewSphereCenter); 2325 cout << Verbose(1) << "ACCEPT: We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl; 2326 } else { 2327 if (OptCandidate != NULL) 2328 cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl; 2329 else 2330 cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl; 2331 } 2332 2333 } else { 2334 cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl; 2335 } 2336 } else { 2337 cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl; 2338 } 2339 } else { 2340 if (ThirdNode != NULL) 2341 cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl; 2342 else 2343 cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl; 2344 } 2345 } 2346 } 2347 } 2348 } else { 2349 cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl; 2350 } 2351 } else { 2352 if (ThirdNode != NULL) 2353 cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl; 2354 else 2355 cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl; 2356 } 2357 2358 cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl; 2359 }; 2360 2361 /** Finds the second point of starting triangle. 2362 * \param *a first atom 2363 * \param *Candidate pointer to candidate atom on return 2364 * \param Oben vector indicating the outside 2365 * \param Opt_Candidate reference to recommended candidate on return 2366 * \param Storage[3] array storing angles and other candidate information 2367 * \param RADIUS radius of virtual sphere 2368 * \param *LC LinkedCell structure with neighbouring atoms 2369 */ 2370 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, Vector Oben, atom*& Opt_Candidate, double Storage[3], double RADIUS, LinkedCell *LC) 2371 { 2372 cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl; 2373 int i; 2374 Vector AngleCheck; 2375 atom* Walker; 2376 double norm = -1., angle; 2377 LinkedAtoms *List = NULL; 2378 int N[NDIM], Nlower[NDIM], Nupper[NDIM]; 2379 2380 if (LC->SetIndexToAtom(a)) { // get cell for the starting atom 2381 for(int i=0;i<NDIM;i++) // store indices of this cell 2382 N[i] = LC->n[i]; 2383 } else { 2384 cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl; 2385 return; 2386 } 2387 // then go through the current and all neighbouring cells and check the contained atoms for possible candidates 2388 cout << Verbose(2) << "LC Intervals:"; 2389 for (int i=0;i<NDIM;i++) { 2390 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0; 2391 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1; 2392 cout << " [" << Nlower[i] << "," << Nupper[i] << "] "; 2393 } 2394 cout << endl; 2395 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 2396 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 2397 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 2398 List = LC->GetCurrentCell(); 2399 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 2400 if (List != NULL) { 2401 for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 2402 Candidate = (*Runner); 2403 // check if we only have one unique point yet ... 2404 if (a != Candidate) { 2405 cout << Verbose(3) << "Current candidate is " << *Candidate << ": "; 2406 AngleCheck.CopyVector(&(Candidate->x)); 2407 AngleCheck.SubtractVector(&(a->x)); 2408 norm = AngleCheck.Norm(); 2409 // second point shall have smallest angle with respect to Oben vector 2410 if (norm < RADIUS) { 2411 angle = AngleCheck.Angle(&Oben); 2412 if (angle < Storage[0]) { 2413 //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]); 2414 cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n"; 2415 Opt_Candidate = Candidate; 2416 Storage[0] = AngleCheck.Angle(&Oben); 2417 //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]); 2418 } else { 2419 cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl; 2420 } 2421 } else { 2422 cout << "Refused due to Radius " << norm << endl; 2423 } 2424 } 2425 } 2426 } 2427 } 2428 cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl; 2429 }; 2430 2431 /** Finds the starting triangle for find_non_convex_border(). 2432 * Looks at the outermost atom per axis, then Find_second_point_for_Tesselation() 2433 * for the second and Find_next_suitable_point_via_Angle_of_Sphere() for the third 2434 * point are called. 2435 * \param RADIUS radius of virtual rolling sphere 2436 * \param *LC LinkedCell structure with neighbouring atoms 2437 */ 2438 void Tesselation::Find_starting_triangle(ofstream *out, molecule *mol, const double RADIUS, LinkedCell *LC) 2439 { 2440 cout << Verbose(1) << "Begin of Find_starting_triangle\n"; 2441 int i = 0; 2442 LinkedAtoms *List = NULL; 2443 atom* Walker; 2444 atom* FirstPoint; 2445 atom* SecondPoint; 2446 atom* MaxAtom[NDIM]; 2447 double max_coordinate[NDIM]; 2448 Vector Oben; 2449 Vector helper; 2450 Vector Chord; 2451 Vector SearchDirection; 2452 Vector OptCandidateCenter; 2453 2454 Oben.Zero(); 2455 2456 for (i = 0; i < 3; i++) { 2457 MaxAtom[i] = NULL; 2458 max_coordinate[i] = -1; 2459 } 2460 2461 // 1. searching topmost atom with respect to each axis 2462 for (int i=0;i<NDIM;i++) { // each axis 2463 LC->n[i] = LC->N[i]-1; // current axis is topmost cell 2464 for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++) 2465 for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) { 2466 List = LC->GetCurrentCell(); 2467 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 2468 if (List != NULL) { 2469 for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) { 2470 cout << Verbose(2) << "Current atom is " << *(*Runner) << "." << endl; 2471 if ((*Runner)->x.x[i] > max_coordinate[i]) { 2472 max_coordinate[i] = (*Runner)->x.x[i]; 2473 MaxAtom[i] = (*Runner); 2474 } 2475 } 2476 } else { 2477 cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl; 2478 } 2479 } 2480 } 2481 2482 cout << Verbose(2) << "Found maximum coordinates: "; 2483 for (int i=0;i<NDIM;i++) 2484 cout << i << ": " << *MaxAtom[i] << "\t"; 2485 cout << endl; 2486 const int k = 1; // arbitrary choice 2487 Oben.x[k] = 1.; 2488 FirstPoint = MaxAtom[k]; 2489 cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl; 2490 2491 // add first point 2492 AddTrianglePoint(FirstPoint, 0); 2493 2494 double ShortestAngle; 2495 atom* Opt_Candidate = NULL; 2496 ShortestAngle = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant. 2497 2498 Find_second_point_for_Tesselation(FirstPoint, NULL, Oben, Opt_Candidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_... 2499 SecondPoint = Opt_Candidate; 2500 cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n"; 2501 2502 // add second point and first baseline 2503 AddTrianglePoint(SecondPoint, 1); 2504 AddTriangleLine(TPS[0], TPS[1], 0); 2505 2506 helper.CopyVector(&(FirstPoint->x)); 2507 helper.SubtractVector(&(SecondPoint->x)); 2508 helper.Normalize(); 2509 Oben.ProjectOntoPlane(&helper); 2510 Oben.Normalize(); 2511 helper.VectorProduct(&Oben); 2512 ShortestAngle = 2.*M_PI; // This will indicate the quadrant. 2513 2514 Chord.CopyVector(&(FirstPoint->x)); // bring into calling function 2515 Chord.SubtractVector(&(SecondPoint->x)); 2516 double radius = Chord.ScalarProduct(&Chord); 2517 double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.); 2518 helper.CopyVector(&Oben); 2519 helper.Scale(CircleRadius); 2520 // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized) 2521 2522 cout << Verbose(2) << "Looking for third point candidates \n"; 2523 // look in one direction of baseline for initial candidate 2524 Opt_Candidate = NULL; 2525 SearchDirection.MakeNormalVector(&Chord, &Oben); // whether we look "left" first or "right" first is not important ... 2526 2527 cout << Verbose(1) << "Looking for third point candidates ...\n"; 2528 Find_third_point_for_Tesselation(Oben, SearchDirection, helper, BLS[0], NULL, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC); 2529 cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl; 2530 2531 // add third point 2532 AddTrianglePoint(Opt_Candidate, 2); 2533 2534 // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate 2535 2536 // Finally, we only have to add the found further lines 2537 AddTriangleLine(TPS[1], TPS[2], 1); 2538 AddTriangleLine(TPS[0], TPS[2], 2); 2539 // ... and triangles to the Maps of the Tesselation class 2540 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 2541 AddTriangleToLines(); 2542 // ... and calculate its normal vector (with correct orientation) 2543 OptCandidateCenter.Scale(-1.); 2544 cout << Verbose(2) << "Oben is currently " << OptCandidateCenter << "." << endl; 2545 BTS->GetNormalVector(OptCandidateCenter); 2546 cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n"; 2547 cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl; 2548 cout << Verbose(1) << "End of Find_starting_triangle\n"; 2549 }; 1980 2550 1981 2551 /** This function finds a triangle to a line, adjacent to an existing one. 1982 * @param out output stream for debugging1983 * @param mol molecule structure with all atoms and bonds2552 * @param out output stream for debugging 2553 * @param *mol molecule with Atom's and Bond's 1984 2554 * @param Line current baseline to search from 1985 2555 * @param T current triangle which \a Line is edge of 1986 2556 * @param RADIUS radius of the rolling ball 1987 2557 * @param N number of found triangles 2558 * @param *filename filename base for intermediate envelopes 2559 * @param *LC LinkedCell structure with neighbouring atoms 1988 2560 */ 1989 void Tesselation::Find_next_suitable_triangle(ofstream *out, 1990 molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, 1991 const double& RADIUS, int N, const char *tempbasename) 1992 { 1993 cout << Verbose(1) << "Looking for next suitable triangle \n"; 1994 Vector direction1; 1995 Vector helper; 1996 Vector Chord; 1997 ofstream *tempstream = NULL; 1998 char NumberName[255]; 1999 double tmp; 2000 //atom* Walker; 2001 atom* OldThirdPoint; 2002 2003 double Storage[3]; 2004 Storage[0] = -2.; // This direction is either +1 or -1 one, so any result will take precedence over initial values 2005 Storage[1] = -2.; // This is also lower then any value produced by an eligible atom, which are all positive 2006 Storage[2] = 9999999.; 2007 atom* Opt_Candidate = NULL; 2008 Vector Opt_Mittelpunkt; 2009 2010 cout << Verbose(1) << "Constructing helpful vectors ... " << endl; 2011 helper.CopyVector(&(Line.endpoints[0]->node->x)); 2012 for (int i = 0; i < 3; i++) 2013 { 2014 if (T.endpoints[i]->node->nr != Line.endpoints[0]->node->nr 2015 && T.endpoints[i]->node->nr != Line.endpoints[1]->node->nr) 2016 { 2017 OldThirdPoint = T.endpoints[i]->node; 2018 helper.SubtractVector(&T.endpoints[i]->node->x); 2019 break; 2020 } 2021 } 2022 2023 direction1.CopyVector(&Line.endpoints[0]->node->x); 2024 direction1.SubtractVector(&Line.endpoints[1]->node->x); 2025 direction1.VectorProduct(&(T.NormalVector)); 2026 2027 if (direction1.ScalarProduct(&helper) < 0) 2028 { 2029 direction1.Scale(-1); 2030 } 2031 2032 Chord.CopyVector(&(Line.endpoints[0]->node->x)); // bring into calling function 2033 Chord.SubtractVector(&(Line.endpoints[1]->node->x)); 2034 2035 2036 Vector Umkreismittelpunkt, a, b, c; 2037 double alpha, beta, gamma; 2038 a.CopyVector(&(T.endpoints[0]->node->x)); 2039 b.CopyVector(&(T.endpoints[1]->node->x)); 2040 c.CopyVector(&(T.endpoints[2]->node->x)); 2041 a.SubtractVector(&(T.endpoints[1]->node->x)); 2042 b.SubtractVector(&(T.endpoints[2]->node->x)); 2043 c.SubtractVector(&(T.endpoints[0]->node->x)); 2044 2045 alpha = M_PI - a.Angle(&c); 2046 beta = M_PI - b.Angle(&a); 2047 gamma = M_PI - c.Angle(&b); 2048 2049 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) ; 2050 //cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl; 2051 Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma))); 2052 cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl; 2053 cout << " We look over line " << Line << " in direction " << direction1.x[0] << " " << direction1.x[1] << " " << direction1.x[2] << " " << endl; 2054 cout << " Old Normal is " << (T.NormalVector.x)[0] << " " << T.NormalVector.x[1] << " " << (T.NormalVector.x)[2] << " " << endl; 2055 2056 2057 cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl; 2058 2059 Find_next_suitable_point_via_Angle_of_Sphere(Line.endpoints[0]->node, Line.endpoints[1]->node, OldThirdPoint, 2060 Line.endpoints[0]->node, Line.endpoints[1]->node, 0, &Chord, &direction1, 2061 &(T.NormalVector), Umkreismittelpunkt, Opt_Candidate, Storage, RADIUS, mol); 2062 Find_next_suitable_point_via_Angle_of_Sphere(Line.endpoints[0]->node, Line.endpoints[1]->node, OldThirdPoint, 2063 Line.endpoints[1]->node, Line.endpoints[0]->node, 0, &Chord, &direction1, 2064 &(T.NormalVector), Umkreismittelpunkt, Opt_Candidate, Storage, RADIUS, mol); 2065 2066 2067 cout << "Letzter Winkel bei " << TrianglesOnBoundaryCount << " Winkel ist " << Storage[2] << endl; 2068 2069 if ((TrianglesOnBoundaryCount % 10) == 0) { 2070 sprintf(NumberName, "-%d", TriangleFilesWritten); 2071 if (DoTecplotOutput) { 2072 string NameofTempFile(tempbasename); 2073 NameofTempFile.append(NumberName); 2074 NameofTempFile.append(TecplotSuffix); 2075 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2076 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2077 write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten); 2078 tempstream->close(); 2079 tempstream->flush(); 2080 delete(tempstream); 2081 } 2082 if (DoRaster3DOutput) { 2083 string NameofTempFile(tempbasename); 2084 NameofTempFile.append(NumberName); 2085 NameofTempFile.append(Raster3DSuffix); 2086 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2087 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2088 write_raster3d_file(out, tempstream, this, mol); 2089 tempstream->close(); 2090 tempstream->flush(); 2091 delete(tempstream); 2092 } 2093 if (DoTecplotOutput || DoRaster3DOutput) 2094 TriangleFilesWritten++; 2095 } 2096 2097 // Konstruiere nun neues Dreieck am Ende der Liste der Dreiecke 2098 2099 cout << " Optimal candidate is " << *Opt_Candidate << endl; 2100 2101 AddTrianglePoint(Opt_Candidate, 0); 2102 AddTrianglePoint(Line.endpoints[0]->node, 1); 2103 AddTrianglePoint(Line.endpoints[1]->node, 2); 2104 2105 AddTriangleLine(TPS[0], TPS[1], 0); 2106 AddTriangleLine(TPS[0], TPS[2], 1); 2107 AddTriangleLine(TPS[1], TPS[2], 2); 2108 2109 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 2110 AddTriangleToLines(); 2111 cout << "New triangle with " << *BTS << endl; 2112 cout << "We have "<< TrianglesOnBoundaryCount << endl; 2113 cout << Verbose(1) << "Constructing normal vector for this triangle ... " << endl; 2114 2115 BTS->GetNormalVector(BTS->NormalVector); 2116 2117 if ((BTS->NormalVector.ScalarProduct(&(T.NormalVector)) < 0 && Storage[0] > 0) || 2118 (BTS->NormalVector.ScalarProduct(&(T.NormalVector)) > 0 && Storage[0] < 0) || 2119 (fabs(Storage[0]) < MYEPSILON && Storage[1]*BTS->NormalVector.ScalarProduct(&direction1) < 0) ) 2120 2121 { 2122 BTS->NormalVector.Scale(-1); 2123 }; 2124 2125 } 2126 ; 2127 2128 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, atom* Parent, 2129 int RecursionLevel, Vector Oben, atom*& Opt_Candidate, double Storage[3], 2130 molecule* mol, double RADIUS) 2131 { 2132 cout << Verbose(1) 2133 << "Looking for second point of starting triangle, recursive level " 2134 << RecursionLevel << endl;; 2135 int i; 2136 Vector AngleCheck; 2137 atom* Walker; 2138 double norm = -1.; 2139 2140 // check if we only have one unique point yet ... 2141 if (a != Candidate) 2142 { 2143 AngleCheck.CopyVector(&(Candidate->x)); 2144 AngleCheck.SubtractVector(&(a->x)); 2145 norm = AngleCheck.Norm(); 2146 // second point shall have smallest angle with respect to Oben vector 2147 if (norm < RADIUS) 2148 { 2149 if (AngleCheck.Angle(&Oben) < Storage[0]) 2150 { 2151 //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[2]); 2152 cout << "Next better candidate is " << *Candidate 2153 << " with distance " << norm << ".\n"; 2154 Opt_Candidate = Candidate; 2155 Storage[0] = AngleCheck.Angle(&Oben); 2156 //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]); 2157 } 2158 else 2159 { 2160 cout << Verbose(1) << "Supposedly looses to a better candidate " 2161 << *Opt_Candidate << endl; 2162 } 2163 } 2164 else 2165 { 2166 cout << Verbose(1) << *Candidate << " refused due to Radius " << norm 2167 << endl; 2168 } 2169 } 2170 2171 // if not recursed to deeply, look at all its bonds 2172 if (RecursionLevel < 7) 2173 { 2174 for (i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) 2175 { 2176 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom( 2177 Candidate); 2178 if (Walker == Parent) // don't go back along the bond we came from 2179 continue; 2180 else 2181 Find_second_point_for_Tesselation(a, Walker, Candidate, 2182 RecursionLevel + 1, Oben, Opt_Candidate, Storage, mol, RADIUS); 2183 }; 2184 }; 2185 } 2186 ; 2187 2188 void Tesselation::Find_starting_triangle(molecule* mol, const double RADIUS) 2189 { 2190 cout << Verbose(1) << "Looking for starting triangle \n"; 2191 int i = 0; 2192 atom* Walker; 2193 atom* FirstPoint; 2194 atom* SecondPoint; 2195 atom* max_index[3]; 2196 double max_coordinate[3]; 2197 Vector Oben; 2198 Vector helper; 2199 Vector Chord; 2200 Vector CenterOfFirstLine; 2201 2202 Oben.Zero(); 2203 2204 for (i = 0; i < 3; i++) 2205 { 2206 max_index[i] = NULL; 2207 max_coordinate[i] = -1; 2208 } 2209 cout << Verbose(1) << "Molecule mol is there and has " << mol->AtomCount 2210 << " Atoms \n"; 2211 2212 // 1. searching topmost atom with respect to each axis 2213 Walker = mol->start; 2214 while (Walker->next != mol->end) 2215 { 2216 Walker = Walker->next; 2217 for (i = 0; i < 3; i++) 2218 { 2219 if (Walker->x.x[i] > max_coordinate[i]) 2220 { 2221 max_coordinate[i] = Walker->x.x[i]; 2222 max_index[i] = Walker; 2223 } 2224 } 2225 } 2226 2227 cout << Verbose(1) << "Found maximum coordinates. " << endl; 2228 //Koennen dies fuer alle Richtungen, legen hier erstmal Richtung auf k=0 2229 const int k = 1; 2230 Oben.x[k] = 1.; 2231 FirstPoint = max_index[k]; 2232 2233 cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << ": " 2234 << FirstPoint->x.x[0] << endl; 2235 double Storage[3]; 2236 atom* Opt_Candidate = NULL; 2237 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. 2238 Storage[1] = 999999.; // This will be an angle looking for the third point. 2239 Storage[2] = 999999.; 2240 cout << Verbose(1) << "Number of Bonds: " 2241 << mol->NumberOfBondsPerAtom[FirstPoint->nr] << endl; 2242 2243 Find_second_point_for_Tesselation(FirstPoint, FirstPoint, FirstPoint, 0, 2244 Oben, Opt_Candidate, Storage, mol, RADIUS); // we give same point as next candidate as its bonds are looked into in find_second_... 2245 SecondPoint = Opt_Candidate; 2246 cout << Verbose(1) << "Found second point is " << *SecondPoint << ".\n"; 2247 2248 helper.CopyVector(&(FirstPoint->x)); 2249 helper.SubtractVector(&(SecondPoint->x)); 2250 helper.Normalize(); 2251 Oben.ProjectOntoPlane(&helper); 2252 Oben.Normalize(); 2253 helper.VectorProduct(&Oben); 2254 Storage[0] = -2.; // This will indicate the quadrant. 2255 Storage[1] = 9999999.; // This will be an angle looking for the third point. 2256 Storage[2] = 9999999.; 2257 2258 Chord.CopyVector(&(FirstPoint->x)); // bring into calling function 2259 Chord.SubtractVector(&(SecondPoint->x)); 2260 // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized) 2261 2262 cout << Verbose(1) << "Looking for third point candidates \n"; 2263 cout << Verbose(1) << " In direction " << helper.x[0] << " " << helper.x[1] << " " << helper.x[2] << " " << endl; 2264 // look in one direction of baseline for initial candidate 2265 Opt_Candidate = NULL; 2266 CenterOfFirstLine.CopyVector(&Chord); 2267 CenterOfFirstLine.Scale(0.5); 2268 CenterOfFirstLine.AddVector(&(SecondPoint->x)); 2269 2270 Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, SecondPoint, FirstPoint, 0, 2271 &Chord, &helper, &Oben, CenterOfFirstLine, Opt_Candidate, Storage, RADIUS, mol); 2272 // look in other direction of baseline for possible better candidate 2273 Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, FirstPoint, SecondPoint, 0, 2274 &Chord, &helper, &Oben, CenterOfFirstLine, Opt_Candidate, Storage, RADIUS, mol); 2275 cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl; 2276 2277 // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate 2278 2279 cout << Verbose(1) << "The found starting triangle consists of " 2280 << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate 2281 << "." << endl; 2282 2283 // Finally, we only have to add the found points 2284 AddTrianglePoint(FirstPoint, 0); 2285 AddTrianglePoint(SecondPoint, 1); 2286 AddTrianglePoint(Opt_Candidate, 2); 2287 // ... and respective lines 2288 AddTriangleLine(TPS[0], TPS[1], 0); 2289 AddTriangleLine(TPS[1], TPS[2], 1); 2290 AddTriangleLine(TPS[0], TPS[2], 2); 2291 // ... and triangles to the Maps of the Tesselation class 2292 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 2293 AddTriangleToLines(); 2294 // ... and calculate its normal vector (with correct orientation) 2295 Oben.Scale(-1.); 2296 BTS->GetNormalVector(Oben); 2297 } 2298 ; 2299 2300 void Find_non_convex_border(ofstream *out, const char *filename, molecule* mol) 2301 { 2302 int N = 0; 2303 struct Tesselation *Tess = new Tesselation; 2304 cout << Verbose(1) << "Entering search for non convex hull. " << endl; 2305 cout << flush; 2306 const double RADIUS = 6.; 2307 LineMap::iterator baseline; 2308 cout << Verbose(0) << "Begin of Find_non_convex_border\n"; 2309 bool flag = false; // marks whether we went once through all baselines without finding any without two triangles 2310 2311 if ((mol->first->next == mol->last) || (mol->last->previous == mol->first)) 2312 mol->CreateAdjacencyList((ofstream *)&cout, 1.6, true); 2313 2314 Tess->Find_starting_triangle(mol, RADIUS); 2315 2316 baseline = Tess->LinesOnBoundary.begin(); 2317 while (baseline != Tess->LinesOnBoundary.end()) 2318 { 2319 if (baseline->second->TrianglesCount == 1) 2320 { 2321 cout << Verbose(1) << "Begin of Tesselation ... " << endl; 2322 Tess->Find_next_suitable_triangle(out, mol, 2323 *(baseline->second), 2324 *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename); //the line is there, so there is a triangle, but only one. 2325 flag = true; 2326 cout << Verbose(1) << "End of Tesselation ... " << endl; 2327 } 2328 else 2329 { 2330 cout << Verbose(1) << "There is a line with " 2331 << baseline->second->TrianglesCount << " triangles adjacent" 2332 << endl; 2333 } 2334 N++; 2335 baseline++; 2336 } 2337 cout << Verbose(1) << "Writing final tecplot file\n"; 2338 if (DoTecplotOutput) { 2339 string Name(filename); 2340 Name.append(TecplotSuffix); 2341 ofstream tecplot(Name.c_str(), ios::trunc); 2342 write_tecplot_file(out, &tecplot, Tess, mol, -1); 2343 tecplot.close(); 2344 } 2345 if (DoRaster3DOutput) { 2346 string Name(filename); 2347 Name.append(Raster3DSuffix); 2348 ofstream raster(Name.c_str(), ios::trunc); 2349 write_raster3d_file(out, &raster, Tess, mol); 2350 raster.close(); 2351 } 2352 } 2353 ; 2561 bool Tesselation::Find_next_suitable_triangle(ofstream *out, 2562 molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, 2563 const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC) 2564 { 2565 cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n"; 2566 ofstream *tempstream = NULL; 2567 char NumberName[255]; 2568 double tmp; 2569 2570 atom* Opt_Candidate = NULL; 2571 Vector OptCandidateCenter; 2572 2573 Vector CircleCenter; 2574 Vector CirclePlaneNormal; 2575 Vector OldSphereCenter; 2576 Vector SearchDirection; 2577 Vector helper; 2578 atom *ThirdNode = NULL; 2579 double ShortestAngle = 2.*M_PI; // This will indicate the quadrant. 2580 double radius, CircleRadius; 2581 2582 cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl; 2583 for (int i=0;i<3;i++) 2584 if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node)) 2585 ThirdNode = T.endpoints[i]->node; 2586 2587 // construct center of circle 2588 CircleCenter.CopyVector(&Line.endpoints[0]->node->x); 2589 CircleCenter.AddVector(&Line.endpoints[1]->node->x); 2590 CircleCenter.Scale(0.5); 2591 2592 // construct normal vector of circle 2593 CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x); 2594 CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x); 2595 2596 // calculate squared radius of circle 2597 radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal); 2598 if (radius/4. < RADIUS*RADIUS) { 2599 CircleRadius = RADIUS*RADIUS - radius/4.; 2600 CirclePlaneNormal.Normalize(); 2601 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl; 2602 2603 // construct old center 2604 GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x)); 2605 helper.CopyVector(&T.NormalVector); // normal vector ensures that this is correct center of the two possible ones 2606 radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter); 2607 helper.Scale(sqrt(RADIUS*RADIUS - radius)); 2608 OldSphereCenter.AddVector(&helper); 2609 OldSphereCenter.SubtractVector(&CircleCenter); 2610 cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl; 2611 2612 // construct SearchDirection 2613 SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal); 2614 helper.CopyVector(&Line.endpoints[0]->node->x); 2615 helper.SubtractVector(&ThirdNode->x); 2616 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON) // ohoh, SearchDirection points inwards! 2617 SearchDirection.Scale(-1.); 2618 SearchDirection.ProjectOntoPlane(&OldSphereCenter); 2619 SearchDirection.Normalize(); 2620 cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl; 2621 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) { // rotated the wrong way! 2622 cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl; 2623 } 2624 2625 // add third point 2626 cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl; 2627 Find_third_point_for_Tesselation(T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC); 2628 2629 } else { 2630 cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl; 2631 } 2632 2633 if (Opt_Candidate == NULL) { 2634 cerr << "WARNING: Could not find a suitable candidate." << endl; 2635 return false; 2636 } 2637 cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << " with circumsphere's center at " << OptCandidateCenter << "." << endl; 2638 2639 // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2) 2640 atom *AtomCandidates[3]; 2641 AtomCandidates[0] = Opt_Candidate; 2642 AtomCandidates[1] = Line.endpoints[0]->node; 2643 AtomCandidates[2] = Line.endpoints[1]->node; 2644 bool flag = CheckPresenceOfTriangle(out, AtomCandidates); 2645 2646 if (flag) { // if so, add 2647 AddTrianglePoint(Opt_Candidate, 0); 2648 AddTrianglePoint(Line.endpoints[0]->node, 1); 2649 AddTrianglePoint(Line.endpoints[1]->node, 2); 2650 2651 AddTriangleLine(TPS[0], TPS[1], 0); 2652 AddTriangleLine(TPS[0], TPS[2], 1); 2653 AddTriangleLine(TPS[1], TPS[2], 2); 2654 2655 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 2656 AddTriangleToLines(); 2657 2658 OptCandidateCenter.Scale(-1.); 2659 BTS->GetNormalVector(OptCandidateCenter); 2660 OptCandidateCenter.Scale(-1.); 2661 2662 cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl; 2663 cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl; 2664 } else { // else, yell and do nothing 2665 cout << Verbose(1) << "This triangle consisting of "; 2666 cout << *Opt_Candidate << ", "; 2667 cout << *Line.endpoints[0]->node << " and "; 2668 cout << *Line.endpoints[1]->node << " "; 2669 cout << "is invalid!" << endl; 2670 return false; 2671 } 2672 2673 if (flag && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 10 == 0))) { // if we have a new triangle and want to output each new triangle configuration 2674 sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name); 2675 if (DoTecplotOutput) { 2676 string NameofTempFile(tempbasename); 2677 NameofTempFile.append(NumberName); 2678 for(size_t npos = NameofTempFile.find_first_of(' '); npos != -1; npos = NameofTempFile.find(' ', npos)) 2679 NameofTempFile.erase(npos, 1); 2680 NameofTempFile.append(TecplotSuffix); 2681 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2682 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2683 write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten); 2684 tempstream->close(); 2685 tempstream->flush(); 2686 delete(tempstream); 2687 } 2688 2689 if (DoRaster3DOutput) { 2690 string NameofTempFile(tempbasename); 2691 NameofTempFile.append(NumberName); 2692 for(size_t npos = NameofTempFile.find_first_of(' '); npos != -1; npos = NameofTempFile.find(' ', npos)) 2693 NameofTempFile.erase(npos, 1); 2694 NameofTempFile.append(Raster3DSuffix); 2695 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 2696 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 2697 write_raster3d_file(out, tempstream, this, mol); 2698 // include the current position of the virtual sphere in the temporary raster3d file 2699 // make the circumsphere's center absolute again 2700 helper.CopyVector(&Line.endpoints[0]->node->x); 2701 helper.AddVector(&Line.endpoints[1]->node->x); 2702 helper.Scale(0.5); 2703 OptCandidateCenter.AddVector(&helper); 2704 Vector *center = mol->DetermineCenterOfAll(out); 2705 OptCandidateCenter.AddVector(center); 2706 delete(center); 2707 // and add to file plus translucency object 2708 *tempstream << "# current virtual sphere\n"; 2709 *tempstream << "8\n 25.0 0.6 -1.0 -1.0 -1.0 0.2 0 0 0 0\n"; 2710 *tempstream << "2\n " << OptCandidateCenter.x[0] << " " << OptCandidateCenter.x[1] << " " << OptCandidateCenter.x[2] << "\t" << RADIUS << "\t1 0 0\n"; 2711 *tempstream << "9\n terminating special property\n"; 2712 tempstream->close(); 2713 tempstream->flush(); 2714 delete(tempstream); 2715 } 2716 if (DoTecplotOutput || DoRaster3DOutput) 2717 TriangleFilesWritten++; 2718 } 2719 2720 cout << Verbose(1) << "End of Find_next_suitable_triangle\n"; 2721 return true; 2722 }; 2723 2724 /** Tesselates the non convex boundary by rolling a virtual sphere along the surface of the molecule. 2725 * \param *out output stream for debugging 2726 * \param *mol molecule structure with Atom's and Bond's 2727 * \param *Tess Tesselation filled with points, lines and triangles on boundary on return 2728 * \param *LCList linked cell list of all atoms 2729 * \param *filename filename prefix for output of vertex data 2730 * \para RADIUS radius of the virtual sphere 2731 */ 2732 void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *Tess, class LinkedCell *LCList, const char *filename, const double RADIUS) 2733 { 2734 int N = 0; 2735 bool freeTess = false; 2736 *out << Verbose(1) << "Entering search for non convex hull. " << endl; 2737 if (Tess == NULL) { 2738 *out << Verbose(1) << "Allocating Tesselation struct ..." << endl; 2739 Tess = new Tesselation; 2740 freeTess = true; 2741 } 2742 bool freeLC = false; 2743 LineMap::iterator baseline; 2744 *out << Verbose(0) << "Begin of Find_non_convex_border\n"; 2745 bool flag = false; // marks whether we went once through all baselines without finding any without two triangles 2746 bool failflag = false; 2747 2748 if (LCList == NULL) { 2749 LCList = new LinkedCell(mol, 2.*RADIUS); 2750 freeLC = true; 2751 } 2752 2753 Tess->Find_starting_triangle(out, mol, RADIUS, LCList); 2754 2755 baseline = Tess->LinesOnBoundary.begin(); 2756 while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) { 2757 if (baseline->second->TrianglesCount == 1) { 2758 failflag = Tess->Find_next_suitable_triangle(out, mol, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename, LCList); //the line is there, so there is a triangle, but only one. 2759 flag = flag || failflag; 2760 if (!failflag) 2761 cerr << "WARNING: Find_next_suitable_triangle failed." << endl; 2762 } else { 2763 cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl; 2764 } 2765 N++; 2766 baseline++; 2767 if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) { 2768 baseline = Tess->LinesOnBoundary.begin(); // restart if we reach end due to newly inserted lines 2769 flag = false; 2770 } 2771 } 2772 if (1) { //failflag) { 2773 *out << Verbose(1) << "Writing final tecplot file\n"; 2774 if (DoTecplotOutput) { 2775 string OutputName(filename); 2776 OutputName.append(TecplotSuffix); 2777 ofstream *tecplot = new ofstream(OutputName.c_str()); 2778 write_tecplot_file(out, tecplot, Tess, mol, -1); 2779 tecplot->close(); 2780 delete(tecplot); 2781 } 2782 if (DoRaster3DOutput) { 2783 string OutputName(filename); 2784 OutputName.append(Raster3DSuffix); 2785 ofstream *raster = new ofstream(OutputName.c_str()); 2786 write_raster3d_file(out, raster, Tess, mol); 2787 raster->close(); 2788 delete(raster); 2789 } 2790 } else { 2791 cerr << "ERROR: Could definately not find all necessary triangles!" << endl; 2792 } 2793 if (freeTess) 2794 delete(Tess); 2795 if (freeLC) 2796 delete(LCList); 2797 *out << Verbose(0) << "End of Find_non_convex_border\n"; 2798 }; 2799 -
Property mode
changed from
-
src/boundary.hpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 17 17 18 18 #include <gsl/gsl_poly.h> 19 #include <gsl/gsl_matrix.h> 20 #include <gsl/gsl_linalg.h> 21 #include <gsl/gsl_multimin.h> 22 #include <gsl/gsl_permutation.h> 19 23 24 #include "linkedcell.hpp" 20 25 #include "molecules.hpp" 21 26 22 27 template <typename T> void SetEndpointsOrdered(T endpoints[2], T endpoint1, T endpoint2) 23 28 { 24 if (endpoint1->Nr < endpoint2->Nr) {25 endpoints[0] = endpoint1;26 endpoints[1] = endpoint2;27 } else {28 endpoints[0] = endpoint2;29 endpoints[1] = endpoint1;30 }29 if (endpoint1->Nr < endpoint2->Nr) { 30 endpoints[0] = endpoint1; 31 endpoints[1] = endpoint2; 32 } else { 33 endpoints[0] = endpoint2; 34 endpoints[1] = endpoint1; 35 } 31 36 }; 32 37 33 38 class BoundaryPointSet { 34 public:35 BoundaryPointSet();36 BoundaryPointSet(atom *Walker);37 ~BoundaryPointSet();39 public: 40 BoundaryPointSet(); 41 BoundaryPointSet(atom *Walker); 42 ~BoundaryPointSet(); 38 43 39 void AddLine(class BoundaryLineSet *line);44 void AddLine(class BoundaryLineSet *line); 40 45 41 LineMap lines;42 int LinesCount;43 atom *node;44 int Nr;46 LineMap lines; 47 int LinesCount; 48 atom *node; 49 int Nr; 45 50 }; 46 51 47 52 class BoundaryLineSet { 48 public:49 BoundaryLineSet();50 BoundaryLineSet(class BoundaryPointSet *Point[2], int number);51 ~BoundaryLineSet();53 public: 54 BoundaryLineSet(); 55 BoundaryLineSet(class BoundaryPointSet *Point[2], int number); 56 ~BoundaryLineSet(); 52 57 53 void AddTriangle(class BoundaryTriangleSet *triangle);58 void AddTriangle(class BoundaryTriangleSet *triangle); 54 59 55 class BoundaryPointSet *endpoints[2];56 TriangleMap triangles;57 int TrianglesCount;58 int Nr;60 class BoundaryPointSet *endpoints[2]; 61 TriangleMap triangles; 62 int TrianglesCount; 63 int Nr; 59 64 }; 60 65 61 66 class BoundaryTriangleSet { 62 public:63 BoundaryTriangleSet();64 BoundaryTriangleSet(class BoundaryLineSet *line[3], int number);65 ~BoundaryTriangleSet();67 public: 68 BoundaryTriangleSet(); 69 BoundaryTriangleSet(class BoundaryLineSet *line[3], int number); 70 ~BoundaryTriangleSet(); 66 71 67 void GetNormalVector(Vector &NormalVector);72 void GetNormalVector(Vector &NormalVector); 68 73 69 class BoundaryPointSet *endpoints[3];70 class BoundaryLineSet *lines[3];71 Vector NormalVector;72 int Nr;74 class BoundaryPointSet *endpoints[3]; 75 class BoundaryLineSet *lines[3]; 76 Vector NormalVector; 77 int Nr; 73 78 }; 74 79 75 80 class Tesselation { 76 public:81 public: 77 82 78 Tesselation();79 ~Tesselation();83 Tesselation(); 84 ~Tesselation(); 80 85 81 void TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol); 82 void GuessStartingTriangle(ofstream *out); 83 void AddPoint(atom * Walker); 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 void Find_next_suitable_triangle(ofstream *out, molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, const char *tempbasename); 86 void TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol); 87 void GuessStartingTriangle(ofstream *out); 88 void AddPoint(atom * Walker); 89 void AddTrianglePoint(atom* Candidate, int n); 90 void AddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n); 91 void AddTriangleToLines(); 92 void Find_starting_triangle(ofstream *out, molecule* mol, const double RADIUS, LinkedCell *LC); 93 bool Find_next_suitable_triangle(ofstream *out, molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, const char *filename, LinkedCell *LC); 94 bool CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]); 95 void Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent, int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint, atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol); 89 96 90 PointMap PointsOnBoundary;91 LineMap LinesOnBoundary;92 TriangleMap TrianglesOnBoundary;93 class BoundaryPointSet *TPS[3]; //this is a Storage for pointers to triangle points, this and BPS[2] needed due to AddLine restrictions94 class BoundaryPointSet *BPS[2];95 class BoundaryLineSet *BLS[3];96 class BoundaryTriangleSet *BTS;97 int PointsOnBoundaryCount;98 int LinesOnBoundaryCount;99 int TrianglesOnBoundaryCount;100 int TriangleFilesWritten;97 PointMap PointsOnBoundary; 98 LineMap LinesOnBoundary; 99 TriangleMap TrianglesOnBoundary; 100 class BoundaryPointSet *TPS[3]; //this is a Storage for pointers to triangle points, this and BPS[2] needed due to AddLine restrictions 101 class BoundaryPointSet *BPS[2]; 102 class BoundaryLineSet *BLS[3]; 103 class BoundaryTriangleSet *BTS; 104 int PointsOnBoundaryCount; 105 int LinesOnBoundaryCount; 106 int TrianglesOnBoundaryCount; 107 int TriangleFilesWritten; 101 108 }; 102 109 … … 107 114 108 115 109 double VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, Boundaries *BoundaryPoints, molecule *mol);116 double VolumeOfConvexEnvelope(ofstream *out, const char *filename, config *configuration, Boundaries *BoundaryPoints, molecule *mol); 110 117 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem); 111 118 void PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, double ClusterVolume, double celldensity); 112 void Find_n ext_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);113 void Find_n on_convex_border(ofstream *out, const char *filename, molecule* mol);119 void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *T, class LinkedCell *LCList, const char *tempbasename, const double RADIUS); 120 void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC); 114 121 115 122 -
Property mode
changed from
-
src/builder.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 15 15 * \section about About the Program 16 16 * 17 * Molecuilder is a short program, written in C++, that enables the construction of a coordinate set for the18 * atoms making up an molecule by the successive statement of binding angles and distances and referencing to19 * already constructed atoms.17 * Molecuilder is a short program, written in C++, that enables the construction of a coordinate set for the 18 * atoms making up an molecule by the successive statement of binding angles and distances and referencing to 19 * already constructed atoms. 20 20 * 21 * A configuration file may be written that is compatible to the format used by PCP - a parallel Car-Parrinello22 * molecular dynamics implementation.21 * A configuration file may be written that is compatible to the format used by PCP - a parallel Car-Parrinello 22 * molecular dynamics implementation. 23 23 * 24 24 * \section install Installation 25 25 * 26 * Installation should without problems succeed as follows:27 * -# ./configure (or: mkdir build;mkdir run;cd build; ../configure --bindir=../run)28 * -# make29 * -# make install26 * Installation should without problems succeed as follows: 27 * -# ./configure (or: mkdir build;mkdir run;cd build; ../configure --bindir=../run) 28 * -# make 29 * -# make install 30 30 * 31 * Further useful commands are32 * -# make clean uninstall: deletes .o-files and removes executable from the given binary directory\n33 * -# make doxygen-doc: Creates these html pages out of the documented source31 * Further useful commands are 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 34 * 35 35 * \section run Running 36 36 * 37 * The program can be executed by running: ./molecuilder37 * The program can be executed by running: ./molecuilder 38 38 * 39 * Note, that it uses a database, called "elements.db", in the executable's directory. If the file is not found,40 * it is created and any given data on elements of the periodic table will be stored therein and re-used on41 * later re-execution.39 * Note, that it uses a database, called "elements.db", in the executable's directory. If the file is not found, 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 42 * 43 43 * \section ref References 44 44 * 45 * For the special configuration file format, see the documentation of pcp.45 * For the special configuration file format, see the documentation of pcp. 46 46 * 47 47 */ … … 50 50 using namespace std; 51 51 52 #include "boundary.hpp" 53 #include "ellipsoid.hpp" 52 54 #include "helpers.hpp" 53 55 #include "molecules.hpp" 54 #include "boundary.hpp"55 56 56 57 /********************************************** Submenu routine **************************************/ … … 62 63 static void AddAtoms(periodentafel *periode, molecule *mol) 63 64 { 64 atom *first, *second, *third, *fourth;65 Vector **atoms;66 Vector x,y,z,n;// coordinates for absolute point in cell volume67 double a,b,c;68 char choice;// menu choice char69 bool valid;70 71 cout << Verbose(0) << "===========ADD ATOM============================" << endl;72 cout << Verbose(0) << " a - state absolute coordinates of atom" << endl;73 cout << Verbose(0) << " b - state relative coordinates of atom wrt to reference point" << endl;74 cout << Verbose(0) << " c - state relative coordinates of atom wrt to already placed atom" << endl;75 cout << Verbose(0) << " d - state two atoms, two angles and a distance" << endl;76 cout << Verbose(0) << " e - least square distance position to a set of atoms" << endl;77 cout << Verbose(0) << "all else - go back" << endl;78 cout << Verbose(0) << "===============================================" << endl;79 cout << Verbose(0) << "Note: Specifiy angles in degrees not multiples of Pi!" << endl;80 cout << Verbose(0) << "INPUT: ";81 cin >> choice;82 83 switch (choice) {84 case 'a': // absolute coordinates of atom85 cout << Verbose(0) << "Enter absolute coordinates." << endl;86 first = new atom;87 first->x.AskPosition(mol->cell_size, false);88 first->type = periode->AskElement();// give type89 mol->AddAtom(first);// add to molecule90 break;91 92 case 'b': // relative coordinates of atom wrt to reference point93 first = new atom;94 valid = true;95 do {96 if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl;97 cout << Verbose(0) << "Enter reference coordinates." << endl;98 x.AskPosition(mol->cell_size, true);99 cout << Verbose(0) << "Enter relative coordinates." << endl;100 first->x.AskPosition(mol->cell_size, false);101 first->x.AddVector((const Vector *)&x);102 cout << Verbose(0) << "\n";103 } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));104 first->type = periode->AskElement();// give type105 mol->AddAtom(first);// add to molecule106 break;107 108 case 'c': // relative coordinates of atom wrt to already placed atom109 first = new atom;110 valid = true;111 do {112 if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl;113 second = mol->AskAtom("Enter atom number: ");114 cout << Verbose(0) << "Enter relative coordinates." << endl;115 first->x.AskPosition(mol->cell_size, false);116 for (int i=NDIM;i--;) {117 first->x.x[i] += second->x.x[i];118 }119 } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));120 first->type = periode->AskElement();// give type121 mol->AddAtom(first);// add to molecule122 break;123 124 case 'd': // two atoms, two angles and a distance125 first = new atom;126 valid = true;127 do {128 if (!valid) {129 cout << Verbose(0) << "Resulting coordinates out of cell - ";130 first->x.Output((ofstream *)&cout);131 cout << Verbose(0) << endl;132 }133 cout << Verbose(0) << "First, we need two atoms, the first atom is the central, while the second is the outer one." << endl;134 second = mol->AskAtom("Enter central atom: ");135 third = mol->AskAtom("Enter second atom (specifying the axis for first angle): ");136 fourth = mol->AskAtom("Enter third atom (specifying a plane for second angle): ");137 a = ask_value("Enter distance between central (first) and new atom: ");138 b = ask_value("Enter angle between new, first and second atom (degrees): ");139 b *= M_PI/180.;140 bound(&b, 0., 2.*M_PI);141 c = ask_value("Enter second angle between new and normal vector of plane defined by first, second and third atom (degrees): ");142 c *= M_PI/180.;143 bound(&c, -M_PI, M_PI);144 cout << Verbose(0) << "radius: " << a << "\t phi: " << b*180./M_PI << "\t theta: " << c*180./M_PI << endl;65 atom *first, *second, *third, *fourth; 66 Vector **atoms; 67 Vector x,y,z,n; // coordinates for absolute point in cell volume 68 double a,b,c; 69 char choice; // menu choice char 70 bool valid; 71 72 cout << Verbose(0) << "===========ADD ATOM============================" << endl; 73 cout << Verbose(0) << " a - state absolute coordinates of atom" << endl; 74 cout << Verbose(0) << " b - state relative coordinates of atom wrt to reference point" << endl; 75 cout << Verbose(0) << " c - state relative coordinates of atom wrt to already placed atom" << endl; 76 cout << Verbose(0) << " d - state two atoms, two angles and a distance" << endl; 77 cout << Verbose(0) << " e - least square distance position to a set of atoms" << endl; 78 cout << Verbose(0) << "all else - go back" << endl; 79 cout << Verbose(0) << "===============================================" << endl; 80 cout << Verbose(0) << "Note: Specifiy angles in degrees not multiples of Pi!" << endl; 81 cout << Verbose(0) << "INPUT: "; 82 cin >> choice; 83 84 switch (choice) { 85 case 'a': // absolute coordinates of atom 86 cout << Verbose(0) << "Enter absolute coordinates." << endl; 87 first = new atom; 88 first->x.AskPosition(mol->cell_size, false); 89 first->type = periode->AskElement(); // give type 90 mol->AddAtom(first); // add to molecule 91 break; 92 93 case 'b': // relative coordinates of atom wrt to reference point 94 first = new atom; 95 valid = true; 96 do { 97 if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl; 98 cout << Verbose(0) << "Enter reference coordinates." << endl; 99 x.AskPosition(mol->cell_size, true); 100 cout << Verbose(0) << "Enter relative coordinates." << endl; 101 first->x.AskPosition(mol->cell_size, false); 102 first->x.AddVector((const Vector *)&x); 103 cout << Verbose(0) << "\n"; 104 } while (!(valid = mol->CheckBounds((const Vector *)&first->x))); 105 first->type = periode->AskElement(); // give type 106 mol->AddAtom(first); // add to molecule 107 break; 108 109 case 'c': // relative coordinates of atom wrt to already placed atom 110 first = new atom; 111 valid = true; 112 do { 113 if (!valid) cout << Verbose(0) << "Resulting position out of cell." << endl; 114 second = mol->AskAtom("Enter atom number: "); 115 cout << Verbose(0) << "Enter relative coordinates." << endl; 116 first->x.AskPosition(mol->cell_size, false); 117 for (int i=NDIM;i--;) { 118 first->x.x[i] += second->x.x[i]; 119 } 120 } while (!(valid = mol->CheckBounds((const Vector *)&first->x))); 121 first->type = periode->AskElement(); // give type 122 mol->AddAtom(first); // add to molecule 123 break; 124 125 case 'd': // two atoms, two angles and a distance 126 first = new atom; 127 valid = true; 128 do { 129 if (!valid) { 130 cout << Verbose(0) << "Resulting coordinates out of cell - "; 131 first->x.Output((ofstream *)&cout); 132 cout << Verbose(0) << endl; 133 } 134 cout << Verbose(0) << "First, we need two atoms, the first atom is the central, while the second is the outer one." << endl; 135 second = mol->AskAtom("Enter central atom: "); 136 third = mol->AskAtom("Enter second atom (specifying the axis for first angle): "); 137 fourth = mol->AskAtom("Enter third atom (specifying a plane for second angle): "); 138 a = ask_value("Enter distance between central (first) and new atom: "); 139 b = ask_value("Enter angle between new, first and second atom (degrees): "); 140 b *= M_PI/180.; 141 bound(&b, 0., 2.*M_PI); 142 c = ask_value("Enter second angle between new and normal vector of plane defined by first, second and third atom (degrees): "); 143 c *= M_PI/180.; 144 bound(&c, -M_PI, M_PI); 145 cout << Verbose(0) << "radius: " << a << "\t phi: " << b*180./M_PI << "\t theta: " << c*180./M_PI << endl; 145 146 /* 146 second->Output(1,1,(ofstream *)&cout);147 third->Output(1,2,(ofstream *)&cout);148 fourth->Output(1,3,(ofstream *)&cout);149 n.MakeNormalvector((const vector *)&second->x, (const vector *)&third->x, (const vector *)&fourth->x);150 x.Copyvector(&second->x);151 x.SubtractVector(&third->x);152 x.Copyvector(&fourth->x);153 x.SubtractVector(&third->x);154 155 if (!z.SolveSystem(&x,&y,&n, b, c, a)) {156 cout << Verbose(0) << "Failure solving self-dependent linear system!" << endl;157 continue;158 }159 cout << Verbose(0) << "resulting relative coordinates: ";160 z.Output((ofstream *)&cout);161 cout << Verbose(0) << endl;162 */163 // calc axis vector164 x.CopyVector(&second->x);165 x.SubtractVector(&third->x);166 x.Normalize();167 cout << "x: ",168 x.Output((ofstream *)&cout);169 cout << endl;170 z.MakeNormalVector(&second->x,&third->x,&fourth->x);171 cout << "z: ",172 z.Output((ofstream *)&cout);173 cout << endl;174 y.MakeNormalVector(&x,&z);175 cout << "y: ",176 y.Output((ofstream *)&cout);177 cout << endl;178 179 // rotate vector around first angle180 first->x.CopyVector(&x);181 first->x.RotateVector(&z,b - M_PI);182 cout << "Rotated vector: ",183 first->x.Output((ofstream *)&cout);184 cout << endl;185 // remove the projection onto the rotation plane of the second angle186 n.CopyVector(&y);187 n.Scale(first->x.Projection(&y));188 cout << "N1: ",189 n.Output((ofstream *)&cout);190 cout << endl;191 first->x.SubtractVector(&n);192 cout << "Subtracted vector: ",193 first->x.Output((ofstream *)&cout);194 cout << endl;195 n.CopyVector(&z);196 n.Scale(first->x.Projection(&z));197 cout << "N2: ",198 n.Output((ofstream *)&cout);199 cout << endl;200 first->x.SubtractVector(&n);201 cout << "2nd subtracted vector: ",202 first->x.Output((ofstream *)&cout);203 cout << endl;204 205 // rotate another vector around second angle206 n.CopyVector(&y);207 n.RotateVector(&x,c - M_PI);208 cout << "2nd Rotated vector: ",209 n.Output((ofstream *)&cout);210 cout << endl;211 212 // add the two linear independent vectors213 first->x.AddVector(&n);214 first->x.Normalize();215 first->x.Scale(a);216 first->x.AddVector(&second->x);217 218 cout << Verbose(0) << "resulting coordinates: ";219 first->x.Output((ofstream *)&cout);220 cout << Verbose(0) << endl;221 } while (!(valid = mol->CheckBounds((const Vector *)&first->x)));222 first->type = periode->AskElement();// give type223 mol->AddAtom(first);// add to molecule224 break;225 226 case 'e': // least square distance position to a set of atoms227 first = new atom;228 atoms = new (Vector*[128]);229 valid = true;230 for(int i=128;i--;)231 atoms[i] = NULL;232 int i=0, j=0;233 cout << Verbose(0) << "Now we need at least three molecules.\n";234 do {235 cout << Verbose(0) << "Enter " << i+1 << "th atom: ";236 cin >> j;237 if (j != -1) {238 second = mol->FindAtom(j);239 atoms[i++] = &(second->x);240 }241 } while ((j != -1) && (i<128));242 if (i >= 2) {243 first->x.LSQdistance(atoms, i);244 245 first->x.Output((ofstream *)&cout);246 first->type = periode->AskElement();// give type247 mol->AddAtom(first);// add to molecule248 } else {249 delete first;250 cout << Verbose(0) << "Please enter at least two vectors!\n";251 }252 break;253 };147 second->Output(1,1,(ofstream *)&cout); 148 third->Output(1,2,(ofstream *)&cout); 149 fourth->Output(1,3,(ofstream *)&cout); 150 n.MakeNormalvector((const vector *)&second->x, (const vector *)&third->x, (const vector *)&fourth->x); 151 x.Copyvector(&second->x); 152 x.SubtractVector(&third->x); 153 x.Copyvector(&fourth->x); 154 x.SubtractVector(&third->x); 155 156 if (!z.SolveSystem(&x,&y,&n, b, c, a)) { 157 cout << Verbose(0) << "Failure solving self-dependent linear system!" << endl; 158 continue; 159 } 160 cout << Verbose(0) << "resulting relative coordinates: "; 161 z.Output((ofstream *)&cout); 162 cout << Verbose(0) << endl; 163 */ 164 // calc axis vector 165 x.CopyVector(&second->x); 166 x.SubtractVector(&third->x); 167 x.Normalize(); 168 cout << "x: ", 169 x.Output((ofstream *)&cout); 170 cout << endl; 171 z.MakeNormalVector(&second->x,&third->x,&fourth->x); 172 cout << "z: ", 173 z.Output((ofstream *)&cout); 174 cout << endl; 175 y.MakeNormalVector(&x,&z); 176 cout << "y: ", 177 y.Output((ofstream *)&cout); 178 cout << endl; 179 180 // rotate vector around first angle 181 first->x.CopyVector(&x); 182 first->x.RotateVector(&z,b - M_PI); 183 cout << "Rotated vector: ", 184 first->x.Output((ofstream *)&cout); 185 cout << endl; 186 // remove the projection onto the rotation plane of the second angle 187 n.CopyVector(&y); 188 n.Scale(first->x.Projection(&y)); 189 cout << "N1: ", 190 n.Output((ofstream *)&cout); 191 cout << endl; 192 first->x.SubtractVector(&n); 193 cout << "Subtracted vector: ", 194 first->x.Output((ofstream *)&cout); 195 cout << endl; 196 n.CopyVector(&z); 197 n.Scale(first->x.Projection(&z)); 198 cout << "N2: ", 199 n.Output((ofstream *)&cout); 200 cout << endl; 201 first->x.SubtractVector(&n); 202 cout << "2nd subtracted vector: ", 203 first->x.Output((ofstream *)&cout); 204 cout << endl; 205 206 // rotate another vector around second angle 207 n.CopyVector(&y); 208 n.RotateVector(&x,c - M_PI); 209 cout << "2nd Rotated vector: ", 210 n.Output((ofstream *)&cout); 211 cout << endl; 212 213 // add the two linear independent vectors 214 first->x.AddVector(&n); 215 first->x.Normalize(); 216 first->x.Scale(a); 217 first->x.AddVector(&second->x); 218 219 cout << Verbose(0) << "resulting coordinates: "; 220 first->x.Output((ofstream *)&cout); 221 cout << Verbose(0) << endl; 222 } while (!(valid = mol->CheckBounds((const Vector *)&first->x))); 223 first->type = periode->AskElement(); // give type 224 mol->AddAtom(first); // add to molecule 225 break; 226 227 case 'e': // least square distance position to a set of atoms 228 first = new atom; 229 atoms = new (Vector*[128]); 230 valid = true; 231 for(int i=128;i--;) 232 atoms[i] = NULL; 233 int i=0, j=0; 234 cout << Verbose(0) << "Now we need at least three molecules.\n"; 235 do { 236 cout << Verbose(0) << "Enter " << i+1 << "th atom: "; 237 cin >> j; 238 if (j != -1) { 239 second = mol->FindAtom(j); 240 atoms[i++] = &(second->x); 241 } 242 } while ((j != -1) && (i<128)); 243 if (i >= 2) { 244 first->x.LSQdistance(atoms, i); 245 246 first->x.Output((ofstream *)&cout); 247 first->type = periode->AskElement(); // give type 248 mol->AddAtom(first); // add to molecule 249 } else { 250 delete first; 251 cout << Verbose(0) << "Please enter at least two vectors!\n"; 252 } 253 break; 254 }; 254 255 }; 255 256 … … 259 260 static void CenterAtoms(molecule *mol) 260 261 { 261 Vector x, y; 262 char choice; // menu choice char 263 264 cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl; 265 cout << Verbose(0) << " a - on origin" << endl; 266 cout << Verbose(0) << " b - on center of gravity" << endl; 267 cout << Verbose(0) << " c - within box with additional boundary" << endl; 268 cout << Verbose(0) << " d - within given simulation box" << endl; 269 cout << Verbose(0) << "all else - go back" << endl; 270 cout << Verbose(0) << "===============================================" << endl; 271 cout << Verbose(0) << "INPUT: "; 272 cin >> choice; 273 274 switch (choice) { 275 default: 276 cout << Verbose(0) << "Not a valid choice." << endl; 277 break; 278 case 'a': 279 cout << Verbose(0) << "Centering atoms in config file on origin." << endl; 280 mol->CenterOrigin((ofstream *)&cout, &x); 281 break; 282 case 'b': 283 cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl; 284 mol->CenterGravity((ofstream *)&cout, &x); 285 break; 286 case 'c': 287 cout << Verbose(0) << "Centering atoms in config file within given additional boundary." << endl; 288 for (int i=0;i<NDIM;i++) { 289 cout << Verbose(0) << "Enter axis " << i << " boundary: "; 290 cin >> y.x[i]; 291 } 292 mol->CenterEdge((ofstream *)&cout, &x); // make every coordinate positive 293 mol->Translate(&y); // translate by boundary 294 mol->SetBoxDimension(&(x+y*2)); // update Box of atoms by boundary 295 break; 296 case 'd': 297 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl; 298 for (int i=0;i<NDIM;i++) { 299 cout << Verbose(0) << "Enter axis " << i << " boundary: "; 300 cin >> x.x[i]; 301 } 302 // center 303 mol->CenterInBox((ofstream *)&cout, &x); 304 // update Box of atoms by boundary 305 mol->SetBoxDimension(&x); 306 break; 307 } 262 Vector x, y, helper; 263 char choice; // menu choice char 264 265 cout << Verbose(0) << "===========CENTER ATOMS=========================" << endl; 266 cout << Verbose(0) << " a - on origin" << endl; 267 cout << Verbose(0) << " b - on center of gravity" << endl; 268 cout << Verbose(0) << " c - within box with additional boundary" << endl; 269 cout << Verbose(0) << " d - within given simulation box" << endl; 270 cout << Verbose(0) << "all else - go back" << endl; 271 cout << Verbose(0) << "===============================================" << endl; 272 cout << Verbose(0) << "INPUT: "; 273 cin >> choice; 274 275 switch (choice) { 276 default: 277 cout << Verbose(0) << "Not a valid choice." << endl; 278 break; 279 case 'a': 280 cout << Verbose(0) << "Centering atoms in config file on origin." << endl; 281 mol->CenterOrigin((ofstream *)&cout, &x); 282 break; 283 case 'b': 284 cout << Verbose(0) << "Centering atoms in config file on center of gravity." << endl; 285 mol->CenterGravity((ofstream *)&cout, &x); 286 break; 287 case 'c': 288 cout << Verbose(0) << "Centering atoms in config file within given additional boundary." << endl; 289 for (int i=0;i<NDIM;i++) { 290 cout << Verbose(0) << "Enter axis " << i << " boundary: "; 291 cin >> y.x[i]; 292 } 293 mol->CenterEdge((ofstream *)&cout, &x); // make every coordinate positive 294 mol->Translate(&y); // translate by boundary 295 helper.CopyVector(&y); 296 helper.Scale(2.); 297 helper.AddVector(&x); 298 mol->SetBoxDimension(&helper); // update Box of atoms by boundary 299 break; 300 case 'd': 301 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl; 302 for (int i=0;i<NDIM;i++) { 303 cout << Verbose(0) << "Enter axis " << i << " boundary: "; 304 cin >> x.x[i]; 305 } 306 // center 307 mol->CenterInBox((ofstream *)&cout, &x); 308 // update Box of atoms by boundary 309 mol->SetBoxDimension(&x); 310 break; 311 } 308 312 }; 309 313 … … 314 318 static void AlignAtoms(periodentafel *periode, molecule *mol) 315 319 { 316 atom *first, *second, *third;317 Vector x,n;318 char choice;// menu choice char319 320 cout << Verbose(0) << "===========ALIGN ATOMS=========================" << endl;321 cout << Verbose(0) << " a - state three atoms defining align plane" << endl;322 cout << Verbose(0) << " b - state alignment vector" << endl;323 cout << Verbose(0) << " c - state two atoms in alignment direction" << endl;324 cout << Verbose(0) << " d - align automatically by least square fit" << endl;325 cout << Verbose(0) << "all else - go back" << endl;326 cout << Verbose(0) << "===============================================" << endl;327 cout << Verbose(0) << "INPUT: ";328 cin >> choice;329 330 switch (choice) {331 default:332 case 'a': // three atoms defining mirror plane333 first = mol->AskAtom("Enter first atom: ");334 second = mol->AskAtom("Enter second atom: ");335 third = mol->AskAtom("Enter third atom: ");336 337 n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);338 break;339 case 'b': // normal vector of mirror plane340 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;341 n.AskPosition(mol->cell_size,0);342 n.Normalize();343 break;344 case 'c': // three atoms defining mirror plane345 first = mol->AskAtom("Enter first atom: ");346 second = mol->AskAtom("Enter second atom: ");347 348 n.CopyVector((const Vector *)&first->x);349 n.SubtractVector((const Vector *)&second->x);350 n.Normalize();351 break;352 case 'd':353 char shorthand[4];354 Vector a;355 struct lsq_params param;356 do {357 fprintf(stdout, "Enter the element of atoms to be chosen: ");358 fscanf(stdin, "%3s", shorthand);359 } while ((param.type = periode->FindElement(shorthand)) == NULL);360 cout << Verbose(0) << "Element is " << param.type->name << endl;361 mol->GetAlignvector(¶m);362 for (int i=NDIM;i--;) {363 x.x[i] = gsl_vector_get(param.x,i);364 n.x[i] = gsl_vector_get(param.x,i+NDIM);365 }366 gsl_vector_free(param.x);367 cout << Verbose(0) << "Offset vector: ";368 x.Output((ofstream *)&cout);369 cout << Verbose(0) << endl;370 n.Normalize();371 break;372 };373 cout << Verbose(0) << "Alignment vector: ";374 n.Output((ofstream *)&cout);375 cout << Verbose(0) << endl;376 mol->Align(&n);320 atom *first, *second, *third; 321 Vector x,n; 322 char choice; // menu choice char 323 324 cout << Verbose(0) << "===========ALIGN ATOMS=========================" << endl; 325 cout << Verbose(0) << " a - state three atoms defining align plane" << endl; 326 cout << Verbose(0) << " b - state alignment vector" << endl; 327 cout << Verbose(0) << " c - state two atoms in alignment direction" << endl; 328 cout << Verbose(0) << " d - align automatically by least square fit" << endl; 329 cout << Verbose(0) << "all else - go back" << endl; 330 cout << Verbose(0) << "===============================================" << endl; 331 cout << Verbose(0) << "INPUT: "; 332 cin >> choice; 333 334 switch (choice) { 335 default: 336 case 'a': // three atoms defining mirror plane 337 first = mol->AskAtom("Enter first atom: "); 338 second = mol->AskAtom("Enter second atom: "); 339 third = mol->AskAtom("Enter third atom: "); 340 341 n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x); 342 break; 343 case 'b': // normal vector of mirror plane 344 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl; 345 n.AskPosition(mol->cell_size,0); 346 n.Normalize(); 347 break; 348 case 'c': // three atoms defining mirror plane 349 first = mol->AskAtom("Enter first atom: "); 350 second = mol->AskAtom("Enter second atom: "); 351 352 n.CopyVector((const Vector *)&first->x); 353 n.SubtractVector((const Vector *)&second->x); 354 n.Normalize(); 355 break; 356 case 'd': 357 char shorthand[4]; 358 Vector a; 359 struct lsq_params param; 360 do { 361 fprintf(stdout, "Enter the element of atoms to be chosen: "); 362 fscanf(stdin, "%3s", shorthand); 363 } while ((param.type = periode->FindElement(shorthand)) == NULL); 364 cout << Verbose(0) << "Element is " << param.type->name << endl; 365 mol->GetAlignvector(¶m); 366 for (int i=NDIM;i--;) { 367 x.x[i] = gsl_vector_get(param.x,i); 368 n.x[i] = gsl_vector_get(param.x,i+NDIM); 369 } 370 gsl_vector_free(param.x); 371 cout << Verbose(0) << "Offset vector: "; 372 x.Output((ofstream *)&cout); 373 cout << Verbose(0) << endl; 374 n.Normalize(); 375 break; 376 }; 377 cout << Verbose(0) << "Alignment vector: "; 378 n.Output((ofstream *)&cout); 379 cout << Verbose(0) << endl; 380 mol->Align(&n); 377 381 }; 378 382 … … 382 386 static void MirrorAtoms(molecule *mol) 383 387 { 384 atom *first, *second, *third;385 Vector n;386 char choice;// menu choice char387 388 cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl;389 cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl;390 cout << Verbose(0) << " b - state normal vector of mirror plane" << endl;391 cout << Verbose(0) << " c - state two atoms in normal direction" << endl;392 cout << Verbose(0) << "all else - go back" << endl;393 cout << Verbose(0) << "===============================================" << endl;394 cout << Verbose(0) << "INPUT: ";395 cin >> choice;396 397 switch (choice) {398 default:399 case 'a': // three atoms defining mirror plane400 first = mol->AskAtom("Enter first atom: ");401 second = mol->AskAtom("Enter second atom: ");402 third = mol->AskAtom("Enter third atom: ");403 404 n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x);405 break;406 case 'b': // normal vector of mirror plane407 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl;408 n.AskPosition(mol->cell_size,0);409 n.Normalize();410 break;411 case 'c': // three atoms defining mirror plane412 first = mol->AskAtom("Enter first atom: ");413 second = mol->AskAtom("Enter second atom: ");414 415 n.CopyVector((const Vector *)&first->x);416 n.SubtractVector((const Vector *)&second->x);417 n.Normalize();418 break;419 };420 cout << Verbose(0) << "Normal vector: ";421 n.Output((ofstream *)&cout);422 cout << Verbose(0) << endl;423 mol->Mirror((const Vector *)&n);388 atom *first, *second, *third; 389 Vector n; 390 char choice; // menu choice char 391 392 cout << Verbose(0) << "===========MIRROR ATOMS=========================" << endl; 393 cout << Verbose(0) << " a - state three atoms defining mirror plane" << endl; 394 cout << Verbose(0) << " b - state normal vector of mirror plane" << endl; 395 cout << Verbose(0) << " c - state two atoms in normal direction" << endl; 396 cout << Verbose(0) << "all else - go back" << endl; 397 cout << Verbose(0) << "===============================================" << endl; 398 cout << Verbose(0) << "INPUT: "; 399 cin >> choice; 400 401 switch (choice) { 402 default: 403 case 'a': // three atoms defining mirror plane 404 first = mol->AskAtom("Enter first atom: "); 405 second = mol->AskAtom("Enter second atom: "); 406 third = mol->AskAtom("Enter third atom: "); 407 408 n.MakeNormalVector((const Vector *)&first->x,(const Vector *)&second->x,(const Vector *)&third->x); 409 break; 410 case 'b': // normal vector of mirror plane 411 cout << Verbose(0) << "Enter normal vector of mirror plane." << endl; 412 n.AskPosition(mol->cell_size,0); 413 n.Normalize(); 414 break; 415 case 'c': // three atoms defining mirror plane 416 first = mol->AskAtom("Enter first atom: "); 417 second = mol->AskAtom("Enter second atom: "); 418 419 n.CopyVector((const Vector *)&first->x); 420 n.SubtractVector((const Vector *)&second->x); 421 n.Normalize(); 422 break; 423 }; 424 cout << Verbose(0) << "Normal vector: "; 425 n.Output((ofstream *)&cout); 426 cout << Verbose(0) << endl; 427 mol->Mirror((const Vector *)&n); 424 428 }; 425 429 … … 429 433 static void RemoveAtoms(molecule *mol) 430 434 { 431 atom *first, *second;432 int axis;433 double tmp1, tmp2;434 char choice;// menu choice char435 436 cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl;437 cout << Verbose(0) << " a - state atom for removal by number" << endl;438 cout << Verbose(0) << " b - keep only in radius around atom" << endl;439 cout << Verbose(0) << " c - remove this with one axis greater value" << endl;440 cout << Verbose(0) << "all else - go back" << endl;441 cout << Verbose(0) << "===============================================" << endl;442 cout << Verbose(0) << "INPUT: ";443 cin >> choice;444 445 switch (choice) {446 default:447 case 'a':448 if (mol->RemoveAtom(mol->AskAtom("Enter number of atom within molecule: ")))449 cout << Verbose(1) << "Atom removed." << endl;450 else451 cout << Verbose(1) << "Atom not found." << endl;452 break;453 case 'b':454 second = mol->AskAtom("Enter number of atom as reference point: ");455 cout << Verbose(0) << "Enter radius: ";456 cin >> tmp1;457 first = mol->start;458 while(first->next != mol->end) {459 first = first->next;460 if (first->x.Distance((const Vector *)&second->x) > tmp1*tmp1) // distance to first above radius ...461 mol->RemoveAtom(first);462 }463 break;464 case 'c':465 cout << Verbose(0) << "Which axis is it: ";466 cin >> axis;467 cout << Verbose(0) << "Left inward boundary: ";468 cin >> tmp1;469 cout << Verbose(0) << "Right inward boundary: ";470 cin >> tmp2;471 first = mol->start;472 while(first->next != mol->end) {473 first = first->next;474 if ((first->x.x[axis] > tmp2) || (first->x.x[axis] < tmp1)) // out of boundary ...475 mol->RemoveAtom(first);476 }477 break;478 };479 //mol->Output((ofstream *)&cout);480 choice = 'r';435 atom *first, *second; 436 int axis; 437 double tmp1, tmp2; 438 char choice; // menu choice char 439 440 cout << Verbose(0) << "===========REMOVE ATOMS=========================" << endl; 441 cout << Verbose(0) << " a - state atom for removal by number" << endl; 442 cout << Verbose(0) << " b - keep only in radius around atom" << endl; 443 cout << Verbose(0) << " c - remove this with one axis greater value" << endl; 444 cout << Verbose(0) << "all else - go back" << endl; 445 cout << Verbose(0) << "===============================================" << endl; 446 cout << Verbose(0) << "INPUT: "; 447 cin >> choice; 448 449 switch (choice) { 450 default: 451 case 'a': 452 if (mol->RemoveAtom(mol->AskAtom("Enter number of atom within molecule: "))) 453 cout << Verbose(1) << "Atom removed." << endl; 454 else 455 cout << Verbose(1) << "Atom not found." << endl; 456 break; 457 case 'b': 458 second = mol->AskAtom("Enter number of atom as reference point: "); 459 cout << Verbose(0) << "Enter radius: "; 460 cin >> tmp1; 461 first = mol->start; 462 while(first->next != mol->end) { 463 first = first->next; 464 if (first->x.DistanceSquared((const Vector *)&second->x) > tmp1*tmp1) // distance to first above radius ... 465 mol->RemoveAtom(first); 466 } 467 break; 468 case 'c': 469 cout << Verbose(0) << "Which axis is it: "; 470 cin >> axis; 471 cout << Verbose(0) << "Left inward boundary: "; 472 cin >> tmp1; 473 cout << Verbose(0) << "Right inward boundary: "; 474 cin >> tmp2; 475 first = mol->start; 476 while(first->next != mol->end) { 477 first = first->next; 478 if ((first->x.x[axis] > tmp2) || (first->x.x[axis] < tmp1)) // out of boundary ... 479 mol->RemoveAtom(first); 480 } 481 break; 482 }; 483 //mol->Output((ofstream *)&cout); 484 choice = 'r'; 481 485 }; 482 486 … … 487 491 static void MeasureAtoms(periodentafel *periode, molecule *mol, config *configuration) 488 492 { 489 atom *first, *second, *third;490 Vector x,y;491 double min[256], tmp1, tmp2, tmp3;492 int Z;493 char choice;// menu choice char494 495 cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl;496 cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl;497 cout << Verbose(0) << " b - calculate bond length between two atoms" << endl;498 cout << Verbose(0) << " c - calculate bond angle" << endl;499 cout << Verbose(0) << " d - calculate principal axis of the system" << endl;500 cout << Verbose(0) << " e - calculate volume of the convex envelope" << endl;501 cout << Verbose(0) << " f - calculate temperature from current velocity" << endl;502 cout << Verbose(0) << " g - output all temperatures per step from velocities" << endl;503 cout << Verbose(0) << "all else - go back" << endl;504 cout << Verbose(0) << "===============================================" << endl;505 cout << Verbose(0) << "INPUT: ";506 cin >> choice;507 508 switch(choice) {509 default:510 cout << Verbose(1) << "Not a valid choice." << endl;511 break;512 case 'a':513 first = mol->AskAtom("Enter first atom: ");514 for (int i=MAX_ELEMENTS;i--;)515 min[i] = 0.;516 517 second = mol->start;518 while ((second->next != mol->end)) {519 second = second->next; // advance520 Z = second->type->Z;521 tmp1 = 0.;522 if (first != second) {523 x.CopyVector((const Vector *)&first->x);524 x.SubtractVector((const Vector *)&second->x);525 tmp1 = x.Norm();526 }527 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;529 }530 for (int i=MAX_ELEMENTS;i--;)531 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 break;533 534 case 'b':535 first = mol->AskAtom("Enter first atom: ");536 second = mol->AskAtom("Enter second atom: ");537 for (int i=NDIM;i--;)538 min[i] = 0.;539 x.CopyVector((const Vector *)&first->x);540 x.SubtractVector((const Vector *)&second->x);541 tmp1 = x.Norm();542 cout << Verbose(1) << "Distance vector is ";543 x.Output((ofstream *)&cout);544 cout << "." << endl << "Norm of distance is " << tmp1 << "." << endl;545 break;546 547 case 'c':548 cout << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl;549 first = mol->AskAtom("Enter first atom: ");550 second = mol->AskAtom("Enter central atom: ");551 third= mol->AskAtom("Enter last atom: ");552 tmp1 = tmp2 = tmp3 = 0.;553 x.CopyVector((const Vector *)&first->x);554 x.SubtractVector((const Vector *)&second->x);555 y.CopyVector((const Vector *)&third->x);556 y.SubtractVector((const Vector *)&second->x);557 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;559 break;560 case 'd':561 cout << Verbose(0) << "Evaluating prinicipal axis." << endl;562 cout << Verbose(0) << "Shall we rotate? [0/1]: ";563 cin >> Z;564 if ((Z >=0) && (Z <=1))565 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)Z);566 else567 mol->PrincipalAxisSystem((ofstream *)&cout, false);568 break;569 case 'e':570 cout << Verbose(0) << "Evaluating volume of the convex envelope.";571 VolumeOfConvexEnvelope((ofstream *)&cout, NULL, configuration, NULL, mol);572 break;573 case 'f':574 mol->OutputTemperatureFromTrajectories((ofstream *)&cout, mol->MDSteps-1, mol->MDSteps, (ofstream *)&cout);575 break;576 case 'g':577 {578 char filename[255];579 cout << "Please enter filename: " << endl;580 cin >> filename;581 cout << Verbose(1) << "Storing temperatures in " << filename << "." << endl;582 ofstream *output = new ofstream(filename, ios::trunc);583 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output))584 cout << Verbose(2) << "File could not be written." << endl;585 else586 cout << Verbose(2) << "File stored." << endl;587 output->close();588 delete(output);589 }590 break;591 }493 atom *first, *second, *third; 494 Vector x,y; 495 double min[256], tmp1, tmp2, tmp3; 496 int Z; 497 char choice; // menu choice char 498 499 cout << Verbose(0) << "===========MEASURE ATOMS=========================" << endl; 500 cout << Verbose(0) << " a - calculate bond length between one atom and all others" << endl; 501 cout << Verbose(0) << " b - calculate bond length between two atoms" << endl; 502 cout << Verbose(0) << " c - calculate bond angle" << endl; 503 cout << Verbose(0) << " d - calculate principal axis of the system" << endl; 504 cout << Verbose(0) << " e - calculate volume of the convex envelope" << endl; 505 cout << Verbose(0) << " f - calculate temperature from current velocity" << endl; 506 cout << Verbose(0) << " g - output all temperatures per step from velocities" << endl; 507 cout << Verbose(0) << "all else - go back" << endl; 508 cout << Verbose(0) << "===============================================" << endl; 509 cout << Verbose(0) << "INPUT: "; 510 cin >> choice; 511 512 switch(choice) { 513 default: 514 cout << Verbose(1) << "Not a valid choice." << endl; 515 break; 516 case 'a': 517 first = mol->AskAtom("Enter first atom: "); 518 for (int i=MAX_ELEMENTS;i--;) 519 min[i] = 0.; 520 521 second = mol->start; 522 while ((second->next != mol->end)) { 523 second = second->next; // advance 524 Z = second->type->Z; 525 tmp1 = 0.; 526 if (first != second) { 527 x.CopyVector((const Vector *)&first->x); 528 x.SubtractVector((const Vector *)&second->x); 529 tmp1 = x.Norm(); 530 } 531 if ((tmp1 != 0.) && ((min[Z] == 0.) || (tmp1 < min[Z]))) min[Z] = tmp1; 532 //cout << Verbose(0) << "Bond length between Atom " << first->nr << " and " << second->nr << ": " << tmp1 << " a.u." << endl; 533 } 534 for (int i=MAX_ELEMENTS;i--;) 535 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; 536 break; 537 538 case 'b': 539 first = mol->AskAtom("Enter first atom: "); 540 second = mol->AskAtom("Enter second atom: "); 541 for (int i=NDIM;i--;) 542 min[i] = 0.; 543 x.CopyVector((const Vector *)&first->x); 544 x.SubtractVector((const Vector *)&second->x); 545 tmp1 = x.Norm(); 546 cout << Verbose(1) << "Distance vector is "; 547 x.Output((ofstream *)&cout); 548 cout << "." << endl << "Norm of distance is " << tmp1 << "." << endl; 549 break; 550 551 case 'c': 552 cout << Verbose(0) << "Evaluating bond angle between three - first, central, last - atoms." << endl; 553 first = mol->AskAtom("Enter first atom: "); 554 second = mol->AskAtom("Enter central atom: "); 555 third = mol->AskAtom("Enter last atom: "); 556 tmp1 = tmp2 = tmp3 = 0.; 557 x.CopyVector((const Vector *)&first->x); 558 x.SubtractVector((const Vector *)&second->x); 559 y.CopyVector((const Vector *)&third->x); 560 y.SubtractVector((const Vector *)&second->x); 561 cout << Verbose(0) << "Bond angle between first atom Nr." << first->nr << ", central atom Nr." << second->nr << " and last atom Nr." << third->nr << ": "; 562 cout << Verbose(0) << (acos(x.ScalarProduct((const Vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl; 563 break; 564 case 'd': 565 cout << Verbose(0) << "Evaluating prinicipal axis." << endl; 566 cout << Verbose(0) << "Shall we rotate? [0/1]: "; 567 cin >> Z; 568 if ((Z >=0) && (Z <=1)) 569 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)Z); 570 else 571 mol->PrincipalAxisSystem((ofstream *)&cout, false); 572 break; 573 case 'e': 574 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 575 VolumeOfConvexEnvelope((ofstream *)&cout, NULL, configuration, NULL, mol); 576 break; 577 case 'f': 578 mol->OutputTemperatureFromTrajectories((ofstream *)&cout, mol->MDSteps-1, mol->MDSteps, (ofstream *)&cout); 579 break; 580 case 'g': 581 { 582 char filename[255]; 583 cout << "Please enter filename: " << endl; 584 cin >> filename; 585 cout << Verbose(1) << "Storing temperatures in " << filename << "." << endl; 586 ofstream *output = new ofstream(filename, ios::trunc); 587 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output)) 588 cout << Verbose(2) << "File could not be written." << endl; 589 else 590 cout << Verbose(2) << "File stored." << endl; 591 output->close(); 592 delete(output); 593 } 594 break; 595 } 592 596 }; 593 597 … … 598 602 static void FragmentAtoms(molecule *mol, config *configuration) 599 603 { 600 int Order1;601 clock_t start, end;602 603 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;604 cout << Verbose(0) << "What's the desired bond order: ";605 cin >> Order1;606 if (mol->first->next != mol->last) {// there are bonds607 start = clock();608 mol->FragmentMolecule((ofstream *)&cout, Order1, configuration);609 end = clock();610 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;611 } else612 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl;604 int Order1; 605 clock_t start, end; 606 607 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl; 608 cout << Verbose(0) << "What's the desired bond order: "; 609 cin >> Order1; 610 if (mol->first->next != mol->last) { // there are bonds 611 start = clock(); 612 mol->FragmentMolecule((ofstream *)&cout, Order1, configuration); 613 end = clock(); 614 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 615 } else 616 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl; 613 617 }; 614 618 … … 619 623 static void testroutine(molecule *mol) 620 624 { 621 // the current test routine checks the functionality of the KeySet&Graph concept:622 // We want to have a multiindex (the KeySet) describing a unique subgraph623 atom *Walker = mol->start;624 int i, comp, counter=0;625 626 // generate some KeySets627 cout << "Generating KeySets." << endl;628 KeySet TestSets[mol->AtomCount+1];629 i=1;630 while (Walker->next != mol->end) {631 Walker = Walker->next;632 for (int j=0;j<i;j++) {633 TestSets[j].insert(Walker->nr);634 }635 i++;636 }637 cout << "Testing insertion of already present item in KeySets." << endl;638 KeySetTestPair test;639 test = TestSets[mol->AtomCount-1].insert(Walker->nr);640 if (test.second) {641 cout << Verbose(1) << "Insertion worked?!" << endl;642 } else {643 cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl;644 }645 TestSets[mol->AtomCount].insert(mol->end->previous->nr);646 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr);647 648 // constructing Graph structure649 cout << "Generating Subgraph class." << endl;650 Graph Subgraphs;651 652 // insert KeySets into Subgraphs653 cout << "Inserting KeySets into Subgraph class." << endl;654 for (int j=0;j<mol->AtomCount;j++) {655 Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.)));656 }657 cout << "Testing insertion of already present item in Subgraph." << endl;658 GraphTestPair test2;659 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.)));660 if (test2.second) {661 cout << Verbose(1) << "Insertion worked?!" << endl;662 } else {663 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl;664 }665 666 // show graphs667 cout << "Showing Subgraph's contents, checking that it's sorted." << endl;668 Graph::iterator A = Subgraphs.begin();669 while (A !=Subgraphs.end()) {670 cout << (*A).second.first << ": ";671 KeySet::iterator key = (*A).first.begin();672 comp = -1;673 while (key != (*A).first.end()) {674 if ((*key) > comp)675 cout << (*key) << " ";676 else677 cout << (*key) << "! ";678 comp = (*key);679 key++;680 }681 cout << endl;682 A++;683 }625 // the current test routine checks the functionality of the KeySet&Graph concept: 626 // We want to have a multiindex (the KeySet) describing a unique subgraph 627 atom *Walker = mol->start; 628 int i, comp, counter=0; 629 630 // generate some KeySets 631 cout << "Generating KeySets." << endl; 632 KeySet TestSets[mol->AtomCount+1]; 633 i=1; 634 while (Walker->next != mol->end) { 635 Walker = Walker->next; 636 for (int j=0;j<i;j++) { 637 TestSets[j].insert(Walker->nr); 638 } 639 i++; 640 } 641 cout << "Testing insertion of already present item in KeySets." << endl; 642 KeySetTestPair test; 643 test = TestSets[mol->AtomCount-1].insert(Walker->nr); 644 if (test.second) { 645 cout << Verbose(1) << "Insertion worked?!" << endl; 646 } else { 647 cout << Verbose(1) << "Insertion rejected: Present object is " << (*test.first) << "." << endl; 648 } 649 TestSets[mol->AtomCount].insert(mol->end->previous->nr); 650 TestSets[mol->AtomCount].insert(mol->end->previous->previous->previous->nr); 651 652 // constructing Graph structure 653 cout << "Generating Subgraph class." << endl; 654 Graph Subgraphs; 655 656 // insert KeySets into Subgraphs 657 cout << "Inserting KeySets into Subgraph class." << endl; 658 for (int j=0;j<mol->AtomCount;j++) { 659 Subgraphs.insert(GraphPair (TestSets[j],pair<int, double>(counter++, 1.))); 660 } 661 cout << "Testing insertion of already present item in Subgraph." << endl; 662 GraphTestPair test2; 663 test2 = Subgraphs.insert(GraphPair (TestSets[mol->AtomCount],pair<int, double>(counter++, 1.))); 664 if (test2.second) { 665 cout << Verbose(1) << "Insertion worked?!" << endl; 666 } else { 667 cout << Verbose(1) << "Insertion rejected: Present object is " << (*(test2.first)).second.first << "." << endl; 668 } 669 670 // show graphs 671 cout << "Showing Subgraph's contents, checking that it's sorted." << endl; 672 Graph::iterator A = Subgraphs.begin(); 673 while (A != Subgraphs.end()) { 674 cout << (*A).second.first << ": "; 675 KeySet::iterator key = (*A).first.begin(); 676 comp = -1; 677 while (key != (*A).first.end()) { 678 if ((*key) > comp) 679 cout << (*key) << " "; 680 else 681 cout << (*key) << "! "; 682 comp = (*key); 683 key++; 684 } 685 cout << endl; 686 A++; 687 } 684 688 }; 685 689 … … 692 696 static void SaveConfig(char *ConfigFileName, config *configuration, periodentafel *periode, molecule *mol) 693 697 { 694 char filename[MAXSTRINGSIZE];695 ofstream output;696 697 cout << Verbose(0) << "Storing configuration ... " << endl;698 // get correct valence orbitals699 mol->CalculateOrbitals(*configuration);700 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble;701 strcpy(filename, ConfigFileName);702 if (ConfigFileName != NULL) { // test the file name703 output.open(ConfigFileName, ios::trunc);704 } else if (strlen(configuration->configname) != 0) {705 strcpy(filename, configuration->configname);706 output.open(configuration->configname, ios::trunc);707 } else {708 strcpy(filename, DEFAULTCONFIG);709 output.open(DEFAULTCONFIG, ios::trunc);710 }711 output.close();712 output.clear();713 cout << Verbose(0) << "Saving of config file ";714 if (configuration->Save(filename, periode, mol))715 cout << "successful." << endl;716 else717 cout << "failed." << endl;718 719 // and save to xyz file720 if (ConfigFileName != NULL) {721 strcpy(filename, ConfigFileName);722 strcat(filename, ".xyz");723 output.open(filename, ios::trunc);724 }725 if (output == NULL) {726 strcpy(filename,"main_pcp_linux");727 strcat(filename, ".xyz");728 output.open(filename, ios::trunc);729 }730 cout << Verbose(0) << "Saving of XYZ file ";731 if (mol->MDSteps <= 1) {732 if (mol->OutputXYZ(&output))733 cout << "successful." << endl;734 else735 cout << "failed." << endl;736 } else {737 if (mol->OutputTrajectoriesXYZ(&output))738 cout << "successful." << endl;739 else740 cout << "failed." << endl;741 }742 output.close();743 output.clear();744 745 // and save as MPQC configuration746 if (ConfigFileName != NULL)747 strcpy(filename, ConfigFileName);748 if (output == NULL)749 strcpy(filename,"main_pcp_linux");750 cout << Verbose(0) << "Saving as mpqc input ";751 if (configuration->SaveMPQC(filename, mol))752 cout << "done." << endl;753 else754 cout << "failed." << endl;755 756 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) {757 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl;758 }698 char filename[MAXSTRINGSIZE]; 699 ofstream output; 700 701 cout << Verbose(0) << "Storing configuration ... " << endl; 702 // get correct valence orbitals 703 mol->CalculateOrbitals(*configuration); 704 configuration->InitMaxMinStopStep = configuration->MaxMinStopStep = configuration->MaxPsiDouble; 705 strcpy(filename, ConfigFileName); 706 if (ConfigFileName != NULL) { // test the file name 707 output.open(ConfigFileName, ios::trunc); 708 } else if (strlen(configuration->configname) != 0) { 709 strcpy(filename, configuration->configname); 710 output.open(configuration->configname, ios::trunc); 711 } else { 712 strcpy(filename, DEFAULTCONFIG); 713 output.open(DEFAULTCONFIG, ios::trunc); 714 } 715 output.close(); 716 output.clear(); 717 cout << Verbose(0) << "Saving of config file "; 718 if (configuration->Save(filename, periode, mol)) 719 cout << "successful." << endl; 720 else 721 cout << "failed." << endl; 722 723 // and save to xyz file 724 if (ConfigFileName != NULL) { 725 strcpy(filename, ConfigFileName); 726 strcat(filename, ".xyz"); 727 output.open(filename, ios::trunc); 728 } 729 if (output == NULL) { 730 strcpy(filename,"main_pcp_linux"); 731 strcat(filename, ".xyz"); 732 output.open(filename, ios::trunc); 733 } 734 cout << Verbose(0) << "Saving of XYZ file "; 735 if (mol->MDSteps <= 1) { 736 if (mol->OutputXYZ(&output)) 737 cout << "successful." << endl; 738 else 739 cout << "failed." << endl; 740 } else { 741 if (mol->OutputTrajectoriesXYZ(&output)) 742 cout << "successful." << endl; 743 else 744 cout << "failed." << endl; 745 } 746 output.close(); 747 output.clear(); 748 749 // and save as MPQC configuration 750 if (ConfigFileName != NULL) 751 strcpy(filename, ConfigFileName); 752 if (output == NULL) 753 strcpy(filename,"main_pcp_linux"); 754 cout << Verbose(0) << "Saving as mpqc input "; 755 if (configuration->SaveMPQC(filename, mol)) 756 cout << "done." << endl; 757 else 758 cout << "failed." << endl; 759 760 if (!strcmp(configuration->configpath, configuration->GetDefaultPath())) { 761 cerr << "WARNING: config is found under different path then stated in config file::defaultpath!" << endl; 762 } 759 763 }; 760 764 … … 771 775 static int ParseCommandLineOptions(int argc, char **argv, molecule *&mol, periodentafel *&periode, config& configuration, char *&ConfigFileName, char *&PathToDatabases) 772 776 { 773 Vector x,y,z,n;// coordinates for absolute point in cell volume774 double *factor; // unit factor if desired775 ifstream test;776 ofstream output;777 string line;778 atom *first;779 bool SaveFlag = false;780 int ExitFlag = 0;781 int j;782 double volume = 0.;783 enum ConfigStatus config_present = absent;784 clock_t start,end;785 int argptr;786 PathToDatabases = LocalPath;787 788 if (argc > 1) { // config file specified as option789 // 1. : Parse options that just set variables or print help790 argptr = 1;791 do {792 if (argv[argptr][0] == '-') {793 cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n";794 argptr++;795 switch(argv[argptr-1][1]) {796 case 'h':797 case 'H':798 case '?':799 cout << "MoleCuilder suite" << endl << "==================" << endl << endl;800 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl;801 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl;802 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl;803 cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl;804 cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl;805 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl;806 cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl;807 cout << "\t-O\tCenter atoms in origin." << endl;808 cout << "\t-d x1 x2 x3\tDuplicate cell along each axis by given factor." << endl;809 cout << "\t-e <file>\tSets the databases path to be parsed (default: ./)." << endl;810 cout << "\t-E <id> <Z>\tChange atom <id>'s element to <Z>, <id> begins at 0." << endl;811 cout << "\t-f/F <dist> <order>\tFragments the molecule in BOSSANOVA manner (with/out rings compressed) and stores config files in same dir as config (return code 0 - fragmented, 2 - no fragmentation necessary)." << endl;812 cout << "\t-h/-H/-?\tGive this help screen." << endl;813 cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl;814 cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl;815 cout << "\t-N\tGet non-convex-envelope." << endl;816 cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl;817 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;818 cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl;819 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;820 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl;821 cout << "\t-T <file> Store temperatures from the config file in <file>." << endl;822 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl;823 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl;824 cout << "\t-v/-V\t\tGives version information." << endl;825 cout << "Note: config files must not begin with '-' !" << endl;826 delete(mol);827 delete(periode);828 return (1);829 break;830 case 'v':831 case 'V':832 cout << argv[0] << " " << VERSIONSTRING << endl;833 cout << "Build your own molecule position set." << endl;834 delete(mol);835 delete(periode);836 return (1);837 break;838 case 'e':839 if ((argptr >= argc) || (argv[argptr][0] == '-')) {840 cerr << "Not enough or invalid arguments for specifying element db: -e <db file>" << endl;841 } else {842 cout << "Using " << argv[argptr] << " as elements database." << endl;843 PathToDatabases = argv[argptr];844 argptr+=1;845 }846 break;847 case 'n':848 cout << "I won't parse trajectories." << endl;849 configuration.FastParsing = true;850 break;851 default:// no match? Step on852 argptr++;853 break;854 }855 } else856 argptr++;857 } while (argptr < argc);858 859 // 2. Parse the element database860 if (periode->LoadPeriodentafel(PathToDatabases)) {861 cout << Verbose(0) << "Element list loaded successfully." << endl;862 //periode->Output((ofstream *)&cout);863 } else {864 cout << Verbose(0) << "Element list loading failed." << endl;865 return 1;866 }867 868 // 3. Find config file name and parse if possible 869 if (argv[1][0] != '-') { 870 cout << Verbose(0) << "Config file given." << endl;871 test.open(argv[1], ios::in); 872 if (test == NULL) { 873 //return (1);874 output.open(argv[1], ios::out); 875 if (output == NULL) { 876 cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl;877 config_present = absent; 878 } else { 879 cout << "Empty configuration file." << endl;880 ConfigFileName = argv[1];881 config_present = empty;882 output.close(); 883 } 884 } else { 885 test.close();886 ConfigFileName = argv[1];887 cout << Verbose(1) << "Specified config file found, parsing ... "; 888 switch (configuration.TestSyntax(ConfigFileName, periode, mol)) { 889 case 1: 890 cout << "new syntax." << endl;891 configuration.Load(ConfigFileName, periode, mol);892 config_present = present;893 break; 894 case 0: 895 cout << "old syntax." << endl;896 configuration.LoadOld(ConfigFileName, periode, mol);897 config_present = present;898 break; 899 default: 900 cout << "Unknown syntax or empty, yet present file." << endl;901 config_present = empty; 902 }903 } 904 } else 905 config_present = absent; 906 907 // 4. parse again through options, now for those depending on elements db and config presence 908 argptr = 1;909 do{910 cout << "Current Command line argument: " << argv[argptr] << "." << endl;911 if (argv[argptr][0] == '-') {912 argptr++; 913 if ((config_present == present) || (config_present == empty)) { 914 switch(argv[argptr-1][1]) { 915 case 'p': 916 ExitFlag = 1;917 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 918 ExitFlag = 255; 919 cerr << "Not enough arguments for parsing: -p <xyz file>" << endl;920 } else { 921 SaveFlag = true; 922 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl;923 if (!mol->AddXYZFile(argv[argptr])) 924 cout << Verbose(2) << "File not found." << endl;925 else { 926 cout << Verbose(2) << "File found and parsed." << endl; 927 config_present = present; 928 } 929 } 930 break;931 case 'a': 932 ExitFlag = 1;933 if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) { 934 ExitFlag = 255; 935 cerr << "Not enough or invalid arguments for adding atom: -a <element> <x> <y> <z>" << endl;936 } else { 937 SaveFlag = true;938 cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), ";939 first = new atom; 940 first->type = periode->FindElement(atoi(argv[argptr]));941 if (first->type != NULL)942 cout << Verbose(2) << "found element " << first->type->name << endl;943 for (int i=NDIM;i--;) 944 first->x.x[i] = atof(argv[argptr+1+i]); 945 if (first->type != NULL) { 946 mol->AddAtom(first); // add to molecule 947 if ((config_present == empty) && (mol->AtomCount != 0)) 948 config_present = present;949 } else 950 cerr << Verbose(1) << "Could not find the specified element." << endl; 951 argptr+=4;952 } 953 break;954 default: // no match? Don't step on (this is done in next switch's default) 955 break; 956 } 957 } 958 if (config_present == present) { 959 switch(argv[argptr-1][1]) { 960 case 'D': 961 ExitFlag = 1;962 { 963 cout << Verbose(1) << "Depth-First-Search Analysis." << endl;964 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 965 int *MinimumRingSize = new int[mol->AtomCount];966 atom ***ListOfLocalAtoms= NULL;967 int FragmentCounter = 0;968 class StackClass<bond *> *BackEdgeStack = NULL;969 class StackClass<bond *> *LocalBackEdgeStack = NULL;970 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr]), configuration.GetIsAngstroem());971 mol->CreateListOfBondsPerAtom((ofstream *)&cout); 972 Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack); 973 if (Subgraphs!= NULL) {974 Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false); // we want to keep the created ListOfLocalAtoms 975 while (Subgraphs->next != NULL) { 976 Subgraphs = Subgraphs->next;977 LocalBackEdgeStack = new StackClass<bond *> (Subgraphs->Leaf->BondCount);978 Subgraphs->Leaf->PickLocalBackEdges((ofstream *)&cout, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack,LocalBackEdgeStack);979 Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize);980 delete(LocalBackEdgeStack); 981 delete(Subgraphs->previous);982 } 983 delete(Subgraphs);984 for (int i=0;i<FragmentCounter;i++) 985 Free((void **)&ListOfLocalAtoms[FragmentCounter], "ParseCommandLineOptions: **ListOfLocalAtoms[]"); 986 Free((void **)&ListOfLocalAtoms, "ParseCommandLineOptions: ***ListOfLocalAtoms");987 } 988 delete(BackEdgeStack); 989 delete[](MinimumRingSize);990 } 991 //argptr+=1; 992 break;993 case 'E': 994 ExitFlag = 1;995 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) { 996 ExitFlag = 255; 997 cerr << "Not enough or invalid arguments given for changing element: -E <atom nr.> <element>" << endl;998 } else { 999 SaveFlag = true;1000 cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl;1001 first = mol->FindAtom(atoi(argv[argptr]));1002 first->type = periode->FindElement(atoi(argv[argptr+1])); 1003 argptr+=2;1004 } 1005 break;1006 case 'A': 1007 ExitFlag = 1;1008 if ((argptr >= argc) || (argv[argptr][0] == '-')){ 1009 ExitFlag =255; 1010 cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl;1011 } 1012 else{ 1013 cout << "Parsing bonds from " << argv[argptr] << "." << endl;1014 ifstream *input = new ifstream(argv[argptr]);1015 mol->CreateAdjacencyList2((ofstream *)&cout, input); 1016 input->close();1017 } 1018 break;1019 case 'N': 1020 ExitFlag = 1;1021 if ((argptr >= argc) || (argv[argptr][0] == '-')){ 1022 ExitFlag = 255; 1023 cerr << "Not enough or invalid arguments given for non-convex envelope: -o <tecplot output file>" << endl;1024 } 1025 else { 1026 cout << Verbose(0) << "Evaluating npn-convex envelope.";1027 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl;1028 Find_non_convex_border((ofstream *)&cout, argv[argptr], mol);1029 argptr+=1;1030 } 1031 break;1032 case 'T': 1033 ExitFlag = 1;1034 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1035 ExitFlag = 255;1036 cerr << "Not enough or invalid arguments given for storing temperature: -T <temperature file>" << endl; 1037 } else { 1038 cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl; 1039 ofstream *output = new ofstream(argv[argptr], ios::trunc);1040 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output)) 1041 cout << Verbose(2) << "File could not be written." << endl; 1042 else 1043 cout << Verbose(2) << "File stored." << endl;1044 output->close(); 1045 delete(output);1046 argptr+=1; 1047 } 1048 break;1049 case 'P': 1050 ExitFlag =1;1051 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1052 ExitFlag = 255;1053 cerr << "Not enough or invalid arguments given for parsing and integrating forces: -P <forces file>" << endl; 1054 } else { 1055 SaveFlag = true; 1056 cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl;1057 if (!mol->VerletForceIntegration(argv[argptr], configuration.Deltat, configuration.GetIsAngstroem())) 1058 cout << Verbose(2) << "File not found." << endl; 1059 else 1060 cout << Verbose(2) << "File found and parsed." << endl;1061 argptr+=1; 1062 } 1063 break; 1064 case 't': 1065 ExitFlag =1;1066 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1067 ExitFlag = 255;1068 cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl; 1069 } else { 1070 ExitFlag = 1; 1071 SaveFlag = true;1072 cout << Verbose(1) << "Translating all ions to new origin." << endl;1073 for (int i=NDIM;i--;) 1074 x.x[i] = atof(argv[argptr+i]);1075 mol->Translate((const Vector *)&x);1076 argptr+=3;1077 } 1078 break;1079 case 's': 1080 ExitFlag = 1;1081 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) { 1082 ExitFlag = 255;1083 cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl; 1084 } else { 1085 SaveFlag = true; 1086 j = -1;1087 cout << Verbose(1) << "Scaling all ion positions by factor." << endl;1088 factor = new double[NDIM]; 1089 factor[0] = atof(argv[argptr]);1090 if ((argptr < argc) && (IsValidNumber(argv[argptr]))) 1091 argptr++;1092 factor[1] = atof(argv[argptr]);1093 if ((argptr < argc) && (IsValidNumber(argv[argptr]))) 1094 argptr++; 1095 factor[2] = atof(argv[argptr]);1096 mol->Scale(&factor);1097 for (int i=0;i<NDIM;i++) { 1098 j += i+1;1099 x.x[i] = atof(argv[NDIM+i]);1100 mol->cell_size[j]*=factor[i];1101 } 1102 delete[](factor);1103 argptr+=1;1104 } 1105 break; 1106 case 'b': 1107 ExitFlag =1;1108 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1109 ExitFlag = 255;1110 cerr << "Not enough or invalid arguments given for centering in box: -b <length_x> <length_y> <length_z>" << endl; 1111 } else { 1112 SaveFlag = true; 1113 j = -1;1114 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl;1115 j=-1; 1116 for (int i=0;i<NDIM;i++) { 1117 j += i+1;1118 x.x[i] = atof(argv[argptr++]);1119 mol->cell_size[j] += x.x[i]*2.;1120 } 1121 // center 1122 mol->CenterInBox((ofstream *)&cout, &x);1123 // update Box of atoms by boundary 1124 mol->SetBoxDimension(&x); 1125 } 1126 break;1127 case 'c': 1128 ExitFlag = 1;1129 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1130 ExitFlag = 255;1131 cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl; 1132 } else { 1133 SaveFlag = true; 1134 j = -1;1135 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl;1136 // make every coordinate positive 1137 mol->CenterEdge((ofstream *)&cout, &x);1138 // update Box of atoms by boundary 1139 mol->SetBoxDimension(&x);1140 // translate each coordinate by boundary 1141 j=-1;1142 for (int i=0;i<NDIM;i++) { 1143 j += i+1;1144 x.x[i] = atof(argv[argptr++]); 1145 mol->cell_size[j] += x.x[i]*2.;1146 } 1147 mol->Translate((const Vector *)&x);1148 } 1149 break;1150 case 'O': 1151 ExitFlag = 1;1152 SaveFlag = true; 1153 cout << Verbose(1) << "Centering atoms in origin." << endl;1154 mol->CenterOrigin((ofstream *)&cout, &x); 1155 mol->SetBoxDimension(&x);1156 break;1157 case 'r': 1158 ExitFlag = 1;1159 SaveFlag = true;1160 cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl;1161 break; 1162 case 'F': 1163 case 'f': 1164 ExitFlag = 1;1165 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) { 1166 ExitFlag = 255; 1167 cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl; 1168 } else { 1169 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl; 1170 cout << Verbose(0) << "Creating connection matrix..." << endl;1171 start = clock();1172 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem()); 1173 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl;1174 if (mol->first->next != mol->last) { 1175 ExitFlag = mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration);1176 } 1177 end = clock();1178 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 1179 argptr+=2;1180 }1181 break;1182 case 'm': 1183 ExitFlag = 1;1184 j = atoi(argv[argptr++]); 1185 if ((j<0) || (j>1)) { 1186 cerr << Verbose(1) << "ERROR: Argument of '-m' should be either 0 for no-rotate or 1 for rotate." << endl; 1187 j = 0;1188 } 1189 if (j) {1190 SaveFlag = true;1191 cout << Verbose(0) << "Converting to prinicipal axis system." << endl;1192 } else 1193 cout << Verbose(0) << "Evaluating prinicipal axis." << endl; 1194 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)j);1195 break;1196 case 'o': 1197 ExitFlag = 1;1198 if ((argptr >= argc) || (argv[argptr][0] == '-')){ 1199 ExitFlag = 255;1200 cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl; 1201 } else { 1202 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 1203 ofstream *output = new ofstream(argv[argptr], ios::trunc);1204 //$$$ 1205 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl; 1206 VolumeOfConvexEnvelope((ofstream *)&cout, output, &configuration, NULL, mol);1207 output->close();1208 delete(output);1209 argptr+=1;1210 }1211 break;1212 case 'U':1213 ExitFlag = 1;1214 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) {1215 ExitFlag = 255;1216 cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl;1217 volume = -1; // for case 'u': don't print error again1218 } else {1219 volume = atof(argv[argptr++]);1220 cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl;1221 }1222 case 'u':1223 ExitFlag = 1;1224 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) {1225 if (volume != -1)1226 ExitFlag = 255;1227 cerr << "Not enough arguments given for suspension: -u <density>" << endl;1228 } else {1229 double density;1230 SaveFlag = true;1231 cout << Verbose(0) << "Evaluating necessary cell volume for a cluster suspended in water.";1232 density = atof(argv[argptr++]);1233 if (density < 1.0) {1234 cerr << Verbose(0) << "Density must be greater than 1.0g/cm^3 !" << endl;1235 density = 1.3;1236 }1237 // for(int i=0;i<NDIM;i++) {1238 // repetition[i] = atoi(argv[argptr++]);1239 // if (repetition[i] < 1)1240 // cerr << Verbose(0) << "ERROR: repetition value must be greater 1!" << endl;1241 // repetition[i] = 1;1242 // }1243 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density);// if volume == 0, will calculate from ConvexEnvelope1244 }1245 break;1246 case 'd':1247 ExitFlag = 1;1248 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) {1249 ExitFlag = 255;1250 cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl;1251 } else {1252 SaveFlag = true;1253 for (int axis = 1; axis <= NDIM; axis++) {1254 int faktor = atoi(argv[argptr++]);1255 int count;1256 element ** Elements;1257 Vector ** vectors;1258 if (faktor < 1) {1259 cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl;1260 faktor = 1;1261 }1262 mol->CountAtoms((ofstream *)&cout);// recount atoms1263 if (mol->AtomCount != 0) {// if there is more than none1264 count = mol->AtomCount;// is changed becausing of adding, thus has to be stored away beforehand1265 Elements = new element *[count];1266 vectors = new Vector *[count];1267 j = 0;1268 first = mol->start;1269 while (first->next != mol->end) {// make a list of all atoms with coordinates and element1270 first = first->next;1271 Elements[j] = first->type;1272 vectors[j] = &first->x;1273 j++;1274 }1275 if (count != j)1276 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;1277 x.Zero();1278 y.Zero();1279 y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude1280 for (int i=1;i<faktor;i++) {// then add this list with respective translation factor times1281 x.AddVector(&y); // per factor one cell width further1282 for (int k=count;k--;) { // go through every atom of the original cell1283 first = new atom(); // create a new body1284 first->x.CopyVector(vectors[k]);// use coordinate of original atom1285 first->x.AddVector(&x);// translate the coordinates1286 first->type = Elements[k];// insert original element1287 mol->AddAtom(first);// and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)1288 }1289 }1290 // free memory1291 delete[](Elements);1292 delete[](vectors);1293 // correct cell size1294 if (axis < 0) { // if sign was negative, we have to translate everything1295 x.Zero();1296 x.AddVector(&y);1297 x.Scale(-(faktor-1));1298 mol->Translate(&x);1299 }1300 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;1301 }1302 }1303 }1304 break;1305 default:// no match? Step on1306 if ((argptr < argc) && (argv[argptr][0] != '-')) // if it started with a '-' we've already made a step!1307 argptr++;1308 break;1309 }1310 }1311 } else argptr++;1312 } while (argptr < argc);1313 if (SaveFlag)1314 SaveConfig(ConfigFileName, &configuration, periode, mol);1315 if ((ExitFlag >= 1)) {1316 delete(mol);1317 delete(periode);1318 return (ExitFlag);1319 }1320 } else {// no arguments, hence scan the elements db1321 if (periode->LoadPeriodentafel(PathToDatabases))1322 cout << Verbose(0) << "Element list loaded successfully." << endl;1323 else1324 cout << Verbose(0) << "Element list loading failed." << endl;1325 configuration.RetrieveConfigPathAndName("main_pcp_linux");1326 }1327 return(0);777 Vector x,y,z,n; // coordinates for absolute point in cell volume 778 double *factor; // unit factor if desired 779 ifstream test; 780 ofstream output; 781 string line; 782 atom *first; 783 bool SaveFlag = false; 784 int ExitFlag = 0; 785 int j; 786 double volume = 0.; 787 enum ConfigStatus config_present = absent; 788 clock_t start,end; 789 int argptr; 790 PathToDatabases = LocalPath; 791 792 if (argc > 1) { // config file specified as option 793 // 1. : Parse options that just set variables or print help 794 argptr = 1; 795 do { 796 if (argv[argptr][0] == '-') { 797 cout << Verbose(0) << "Recognized command line argument: " << argv[argptr][1] << ".\n"; 798 argptr++; 799 switch(argv[argptr-1][1]) { 800 case 'h': 801 case 'H': 802 case '?': 803 cout << "MoleCuilder suite" << endl << "==================" << endl << endl; 804 cout << "Usage: " << argv[0] << "[config file] [-{acefpsthH?vfrp}] [further arguments]" << endl; 805 cout << "or simply " << argv[0] << " without arguments for interactive session." << endl; 806 cout << "\t-a Z x1 x2 x3\tAdd new atom of element Z at coordinates (x1,x2,x3)." << endl; 807 cout << "\t-A <source>\tCreate adjacency list from bonds parsed from 'dbond'-style file." <<endl; 808 cout << "\t-b x1 x2 x3\tCenter atoms in domain with given edge lengths of (x1,x2,x3)." << endl; 809 cout << "\t-c x1 x2 x3\tCenter atoms in domain with a minimum distance to boundary of (x1,x2,x3)." << endl; 810 cout << "\t-D <bond distance>\tDepth-First-Search Analysis of the molecule, giving cycles and tree/back edges." << endl; 811 cout << "\t-O\tCenter atoms in origin." << endl; 812 cout << "\t-d x1 x2 x3\tDuplicate cell along each axis by given factor." << endl; 813 cout << "\t-e <file>\tSets the databases path to be parsed (default: ./)." << endl; 814 cout << "\t-E <id> <Z>\tChange atom <id>'s element to <Z>, <id> begins at 0." << endl; 815 cout << "\t-f/F <dist> <order>\tFragments the molecule in BOSSANOVA manner (with/out rings compressed) and stores config files in same dir as config (return code 0 - fragmented, 2 - no fragmentation necessary)." << endl; 816 cout << "\t-h/-H/-?\tGive this help screen." << endl; 817 cout << "\t-m <0/1>\tCalculate (0)/ Align in(1) PAS with greatest EV along z axis." << endl; 818 cout << "\t-n\tFast parsing (i.e. no trajectories are looked for)." << endl; 819 cout << "\t-N\tGet non-convex-envelope." << endl; 820 cout << "\t-o <out>\tGet volume of the convex envelope (and store to tecplot file)." << endl; 821 cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl; 822 cout << "\t-P <file>\tParse given forces file and append as an MD step to config file via Verlet." << endl; 823 cout << "\t-r\t\tConvert file from an old pcp syntax." << endl; 824 cout << "\t-t x1 x2 x3\tTranslate all atoms by this vector (x1,x2,x3)." << endl; 825 cout << "\t-T <file> Store temperatures from the config file in <file>." << endl; 826 cout << "\t-s x1 x2 x3\tScale all atom coordinates by this vector (x1,x2,x3)." << endl; 827 cout << "\t-u rho\tsuspend in water solution and output necessary cell lengths, average density rho and repetition." << endl; 828 cout << "\t-v/-V\t\tGives version information." << endl; 829 cout << "Note: config files must not begin with '-' !" << endl; 830 delete(mol); 831 delete(periode); 832 return (1); 833 break; 834 case 'v': 835 case 'V': 836 cout << argv[0] << " " << VERSIONSTRING << endl; 837 cout << "Build your own molecule position set." << endl; 838 delete(mol); 839 delete(periode); 840 return (1); 841 break; 842 case 'e': 843 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 844 cerr << "Not enough or invalid arguments for specifying element db: -e <db file>" << endl; 845 } else { 846 cout << "Using " << argv[argptr] << " as elements database." << endl; 847 PathToDatabases = argv[argptr]; 848 argptr+=1; 849 } 850 break; 851 case 'n': 852 cout << "I won't parse trajectories." << endl; 853 configuration.FastParsing = true; 854 break; 855 default: // no match? Step on 856 argptr++; 857 break; 858 } 859 } else 860 argptr++; 861 } while (argptr < argc); 862 863 // 2. Parse the element database 864 if (periode->LoadPeriodentafel(PathToDatabases)) { 865 cout << Verbose(0) << "Element list loaded successfully." << endl; 866 //periode->Output((ofstream *)&cout); 867 } else { 868 cout << Verbose(0) << "Element list loading failed." << endl; 869 return 1; 870 } 871 // 3. Find config file name and parse if possible 872 if (argv[1][0] != '-') { 873 cout << Verbose(0) << "Config file given." << endl; 874 test.open(argv[1], ios::in); 875 if (test == NULL) { 876 //return (1); 877 output.open(argv[1], ios::out); 878 if (output == NULL) { 879 cout << Verbose(1) << "Specified config file " << argv[1] << " not found." << endl; 880 config_present = absent; 881 } else { 882 cout << "Empty configuration file." << endl; 883 ConfigFileName = argv[1]; 884 config_present = empty; 885 output.close(); 886 } 887 } else { 888 test.close(); 889 ConfigFileName = argv[1]; 890 cout << Verbose(1) << "Specified config file found, parsing ... "; 891 switch (configuration.TestSyntax(ConfigFileName, periode, mol)) { 892 case 1: 893 cout << "new syntax." << endl; 894 configuration.Load(ConfigFileName, periode, mol); 895 config_present = present; 896 break; 897 case 0: 898 cout << "old syntax." << endl; 899 configuration.LoadOld(ConfigFileName, periode, mol); 900 config_present = present; 901 break; 902 default: 903 cout << "Unknown syntax or empty, yet present file." << endl; 904 config_present = empty; 905 } 906 } 907 } else 908 config_present = absent; 909 // 4. parse again through options, now for those depending on elements db and config presence 910 argptr = 1; 911 do { 912 cout << "Current Command line argument: " << argv[argptr] << "." << endl; 913 if (argv[argptr][0] == '-') { 914 argptr++; 915 if ((config_present == present) || (config_present == empty)) { 916 switch(argv[argptr-1][1]) { 917 case 'p': 918 ExitFlag = 1; 919 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 920 ExitFlag = 255; 921 cerr << "Not enough arguments for parsing: -p <xyz file>" << endl; 922 } else { 923 SaveFlag = true; 924 cout << Verbose(1) << "Parsing xyz file for new atoms." << endl; 925 if (!mol->AddXYZFile(argv[argptr])) 926 cout << Verbose(2) << "File not found." << endl; 927 else { 928 cout << Verbose(2) << "File found and parsed." << endl; 929 config_present = present; 930 } 931 } 932 break; 933 case 'a': 934 ExitFlag = 1; 935 if ((argptr >= argc) || (argv[argptr][0] == '-') || (!IsValidNumber(argv[argptr+1]))) { 936 ExitFlag = 255; 937 cerr << "Not enough or invalid arguments for adding atom: -a <element> <x> <y> <z>" << endl; 938 } else { 939 SaveFlag = true; 940 cout << Verbose(1) << "Adding new atom with element " << argv[argptr] << " at (" << argv[argptr+1] << "," << argv[argptr+2] << "," << argv[argptr+3] << "), "; 941 first = new atom; 942 first->type = periode->FindElement(atoi(argv[argptr])); 943 if (first->type != NULL) 944 cout << Verbose(2) << "found element " << first->type->name << endl; 945 for (int i=NDIM;i--;) 946 first->x.x[i] = atof(argv[argptr+1+i]); 947 if (first->type != NULL) { 948 mol->AddAtom(first); // add to molecule 949 if ((config_present == empty) && (mol->AtomCount != 0)) 950 config_present = present; 951 } else 952 cerr << Verbose(1) << "Could not find the specified element." << endl; 953 argptr+=4; 954 } 955 break; 956 default: // no match? Don't step on (this is done in next switch's default) 957 break; 958 } 959 } 960 if (config_present == present) { 961 switch(argv[argptr-1][1]) { 962 case 'D': 963 ExitFlag = 1; 964 { 965 cout << Verbose(1) << "Depth-First-Search Analysis." << endl; 966 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 967 int *MinimumRingSize = new int[mol->AtomCount]; 968 atom ***ListOfLocalAtoms = NULL; 969 int FragmentCounter = 0; 970 class StackClass<bond *> *BackEdgeStack = NULL; 971 class StackClass<bond *> *LocalBackEdgeStack = NULL; 972 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr]), configuration.GetIsAngstroem()); 973 mol->CreateListOfBondsPerAtom((ofstream *)&cout); 974 Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack); 975 if (Subgraphs != NULL) { 976 Subgraphs->next->FillBondStructureFromReference((ofstream *)&cout, mol, (FragmentCounter = 0), ListOfLocalAtoms, false); // we want to keep the created ListOfLocalAtoms 977 while (Subgraphs->next != NULL) { 978 Subgraphs = Subgraphs->next; 979 LocalBackEdgeStack = new StackClass<bond *> (Subgraphs->Leaf->BondCount); 980 Subgraphs->Leaf->PickLocalBackEdges((ofstream *)&cout, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 981 Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize); 982 delete(LocalBackEdgeStack); 983 delete(Subgraphs->previous); 984 } 985 delete(Subgraphs); 986 for (int i=0;i<FragmentCounter;i++) 987 Free((void **)&ListOfLocalAtoms[FragmentCounter], "ParseCommandLineOptions: **ListOfLocalAtoms[]"); 988 Free((void **)&ListOfLocalAtoms, "ParseCommandLineOptions: ***ListOfLocalAtoms"); 989 } 990 delete(BackEdgeStack); 991 delete[](MinimumRingSize); 992 } 993 //argptr+=1; 994 break; 995 case 'E': 996 ExitFlag = 1; 997 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (argv[argptr+1][0] == '-')) { 998 ExitFlag = 255; 999 cerr << "Not enough or invalid arguments given for changing element: -E <atom nr.> <element>" << endl; 1000 } else { 1001 SaveFlag = true; 1002 cout << Verbose(1) << "Changing atom " << argv[argptr] << " to element " << argv[argptr+1] << "." << endl; 1003 first = mol->FindAtom(atoi(argv[argptr])); 1004 first->type = periode->FindElement(atoi(argv[argptr+1])); 1005 argptr+=2; 1006 } 1007 break; 1008 case 'A': 1009 ExitFlag = 1; 1010 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1011 ExitFlag =255; 1012 cerr << "Missing source file for bonds in molecule: -A <bond sourcefile>" << endl; 1013 } else { 1014 cout << "Parsing bonds from " << argv[argptr] << "." << endl; 1015 ifstream *input = new ifstream(argv[argptr]); 1016 mol->CreateAdjacencyList2((ofstream *)&cout, input); 1017 input->close(); 1018 argptr+=1; 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 class Tesselation T; 1028 int N = 15; 1029 int number = 100; 1030 string filename(argv[argptr+1]); 1031 filename.append(".csv"); 1032 cout << Verbose(0) << "Evaluating non-convex envelope."; 1033 cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl; 1034 LinkedCell LCList(mol, atof(argv[argptr])); // \NOTE not twice the radius?? 1035 Find_non_convex_border((ofstream *)&cout, mol, &T, &LCList, argv[argptr+1], atof(argv[argptr])); 1036 FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str()); 1037 argptr+=2; 1038 } 1039 break; 1040 case 'T': 1041 ExitFlag = 1; 1042 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1043 ExitFlag = 255; 1044 cerr << "Not enough or invalid arguments given for storing tempature: -T <temperature file>" << endl; 1045 } else { 1046 cout << Verbose(1) << "Storing temperatures in " << argv[argptr] << "." << endl; 1047 ofstream *output = new ofstream(argv[argptr], ios::trunc); 1048 if (!mol->OutputTemperatureFromTrajectories((ofstream *)&cout, 0, mol->MDSteps, output)) 1049 cout << Verbose(2) << "File could not be written." << endl; 1050 else 1051 cout << Verbose(2) << "File stored." << endl; 1052 output->close(); 1053 delete(output); 1054 argptr+=1; 1055 } 1056 break; 1057 case 'P': 1058 ExitFlag = 1; 1059 if ((argptr >= argc) || (argv[argptr][0] == '-')) { 1060 ExitFlag = 255; 1061 cerr << "Not enough or invalid arguments given for parsing and integrating forces: -P <forces file>" << endl; 1062 } else { 1063 SaveFlag = true; 1064 cout << Verbose(1) << "Parsing forces file and Verlet integrating." << endl; 1065 if (!mol->VerletForceIntegration(argv[argptr], configuration.Deltat, configuration.GetIsAngstroem())) 1066 cout << Verbose(2) << "File not found." << endl; 1067 else 1068 cout << Verbose(2) << "File found and parsed." << endl; 1069 argptr+=1; 1070 } 1071 break; 1072 case 't': 1073 ExitFlag = 1; 1074 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1075 ExitFlag = 255; 1076 cerr << "Not enough or invalid arguments given for translation: -t <x> <y> <z>" << endl; 1077 } else { 1078 ExitFlag = 1; 1079 SaveFlag = true; 1080 cout << Verbose(1) << "Translating all ions to new origin." << endl; 1081 for (int i=NDIM;i--;) 1082 x.x[i] = atof(argv[argptr+i]); 1083 mol->Translate((const Vector *)&x); 1084 argptr+=3; 1085 } 1086 break; 1087 case 's': 1088 ExitFlag = 1; 1089 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) { 1090 ExitFlag = 255; 1091 cerr << "Not enough or invalid arguments given for scaling: -s <factor/[factor_x]> [factor_y] [factor_z]" << endl; 1092 } else { 1093 SaveFlag = true; 1094 j = -1; 1095 cout << Verbose(1) << "Scaling all ion positions by factor." << endl; 1096 factor = new double[NDIM]; 1097 factor[0] = atof(argv[argptr]); 1098 if ((argptr < argc) && (IsValidNumber(argv[argptr]))) 1099 argptr++; 1100 factor[1] = atof(argv[argptr]); 1101 if ((argptr < argc) && (IsValidNumber(argv[argptr]))) 1102 argptr++; 1103 factor[2] = atof(argv[argptr]); 1104 mol->Scale(&factor); 1105 for (int i=0;i<NDIM;i++) { 1106 j += i+1; 1107 x.x[i] = atof(argv[NDIM+i]); 1108 mol->cell_size[j]*=factor[i]; 1109 } 1110 delete[](factor); 1111 argptr+=1; 1112 } 1113 break; 1114 case 'b': 1115 ExitFlag = 1; 1116 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1117 ExitFlag = 255; 1118 cerr << "Not enough or invalid arguments given for centering in box: -b <length_x> <length_y> <length_z>" << endl; 1119 } else { 1120 SaveFlag = true; 1121 j = -1; 1122 cout << Verbose(1) << "Centering atoms in config file within given simulation box." << endl; 1123 j=-1; 1124 for (int i=0;i<NDIM;i++) { 1125 j += i+1; 1126 x.x[i] = atof(argv[argptr++]); 1127 mol->cell_size[j] += x.x[i]*2.; 1128 } 1129 // center 1130 mol->CenterInBox((ofstream *)&cout, &x); 1131 // update Box of atoms by boundary 1132 mol->SetBoxDimension(&x); 1133 } 1134 break; 1135 case 'c': 1136 ExitFlag = 1; 1137 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1138 ExitFlag = 255; 1139 cerr << "Not enough or invalid arguments given for centering with boundary: -c <boundary_x> <boundary_y> <boundary_z>" << endl; 1140 } else { 1141 SaveFlag = true; 1142 j = -1; 1143 cout << Verbose(1) << "Centering atoms in config file within given additional boundary." << endl; 1144 // make every coordinate positive 1145 mol->CenterEdge((ofstream *)&cout, &x); 1146 // update Box of atoms by boundary 1147 mol->SetBoxDimension(&x); 1148 // translate each coordinate by boundary 1149 j=-1; 1150 for (int i=0;i<NDIM;i++) { 1151 j += i+1; 1152 x.x[i] = atof(argv[argptr++]); 1153 mol->cell_size[j] += x.x[i]*2.; 1154 } 1155 mol->Translate((const Vector *)&x); 1156 } 1157 break; 1158 case 'O': 1159 ExitFlag = 1; 1160 SaveFlag = true; 1161 cout << Verbose(1) << "Centering atoms in origin." << endl; 1162 mol->CenterOrigin((ofstream *)&cout, &x); 1163 mol->SetBoxDimension(&x); 1164 break; 1165 case 'r': 1166 ExitFlag = 1; 1167 SaveFlag = true; 1168 cout << Verbose(1) << "Converting config file from supposed old to new syntax." << endl; 1169 break; 1170 case 'F': 1171 case 'f': 1172 ExitFlag = 1; 1173 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1]))) { 1174 ExitFlag = 255; 1175 cerr << "Not enough or invalid arguments for fragmentation: -f <max. bond distance> <bond order>" << endl; 1176 } else { 1177 cout << "Fragmenting molecule with bond distance " << argv[argptr] << " angstroem, order of " << argv[argptr+1] << "." << endl; 1178 cout << Verbose(0) << "Creating connection matrix..." << endl; 1179 start = clock(); 1180 mol->CreateAdjacencyList((ofstream *)&cout, atof(argv[argptr++]), configuration.GetIsAngstroem()); 1181 cout << Verbose(0) << "Fragmenting molecule with current connection matrix ..." << endl; 1182 if (mol->first->next != mol->last) { 1183 ExitFlag = mol->FragmentMolecule((ofstream *)&cout, atoi(argv[argptr]), &configuration); 1184 } 1185 end = clock(); 1186 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 1187 argptr+=2; 1188 } 1189 break; 1190 case 'm': 1191 ExitFlag = 1; 1192 j = atoi(argv[argptr++]); 1193 if ((j<0) || (j>1)) { 1194 cerr << Verbose(1) << "ERROR: Argument of '-m' should be either 0 for no-rotate or 1 for rotate." << endl; 1195 j = 0; 1196 } 1197 if (j) { 1198 SaveFlag = true; 1199 cout << Verbose(0) << "Converting to prinicipal axis system." << endl; 1200 } else 1201 cout << Verbose(0) << "Evaluating prinicipal axis." << endl; 1202 mol->PrincipalAxisSystem((ofstream *)&cout, (bool)j); 1203 break; 1204 case 'o': 1205 ExitFlag = 1; 1206 if ((argptr >= argc) || (argv[argptr][0] == '-')){ 1207 ExitFlag = 255; 1208 cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl; 1209 } else { 1210 cout << Verbose(0) << "Evaluating volume of the convex envelope."; 1211 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl; 1212 VolumeOfConvexEnvelope((ofstream *)&cout, argv[argptr], &configuration, NULL, mol); 1213 argptr+=1; 1214 } 1215 break; 1216 case 'U': 1217 ExitFlag = 1; 1218 if ((argptr+1 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) ) { 1219 ExitFlag = 255; 1220 cerr << "Not enough or invalid arguments given for suspension with specified volume: -U <volume> <density>" << endl; 1221 volume = -1; // for case 'u': don't print error again 1222 } else { 1223 volume = atof(argv[argptr++]); 1224 cout << Verbose(0) << "Using " << volume << " angstrom^3 as the volume instead of convex envelope one's." << endl; 1225 } 1226 case 'u': 1227 ExitFlag = 1; 1228 if ((argptr >= argc) || (!IsValidNumber(argv[argptr])) ) { 1229 if (volume != -1) 1230 ExitFlag = 255; 1231 cerr << "Not enough arguments given for suspension: -u <density>" << endl; 1232 } else { 1233 double density; 1234 SaveFlag = true; 1235 cout << Verbose(0) << "Evaluating necessary cell volume for a cluster suspended in water."; 1236 density = atof(argv[argptr++]); 1237 if (density < 1.0) { 1238 cerr << Verbose(0) << "Density must be greater than 1.0g/cm^3 !" << endl; 1239 density = 1.3; 1240 } 1241 // for(int i=0;i<NDIM;i++) { 1242 // repetition[i] = atoi(argv[argptr++]); 1243 // if (repetition[i] < 1) 1244 // cerr << Verbose(0) << "ERROR: repetition value must be greater 1!" << endl; 1245 // repetition[i] = 1; 1246 // } 1247 PrepareClustersinWater((ofstream *)&cout, &configuration, mol, volume, density); // if volume == 0, will calculate from ConvexEnvelope 1248 } 1249 break; 1250 case 'd': 1251 ExitFlag = 1; 1252 if ((argptr+2 >= argc) || (!IsValidNumber(argv[argptr])) || (!IsValidNumber(argv[argptr+1])) || (!IsValidNumber(argv[argptr+2])) ) { 1253 ExitFlag = 255; 1254 cerr << "Not enough or invalid arguments given for repeating cells: -d <repeat_x> <repeat_y> <repeat_z>" << endl; 1255 } else { 1256 SaveFlag = true; 1257 for (int axis = 1; axis <= NDIM; axis++) { 1258 int faktor = atoi(argv[argptr++]); 1259 int count; 1260 element ** Elements; 1261 Vector ** vectors; 1262 if (faktor < 1) { 1263 cerr << Verbose(0) << "ERROR: Repetition faktor mus be greater than 1!" << endl; 1264 faktor = 1; 1265 } 1266 mol->CountAtoms((ofstream *)&cout); // recount atoms 1267 if (mol->AtomCount != 0) { // if there is more than none 1268 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand 1269 Elements = new element *[count]; 1270 vectors = new Vector *[count]; 1271 j = 0; 1272 first = mol->start; 1273 while (first->next != mol->end) { // make a list of all atoms with coordinates and element 1274 first = first->next; 1275 Elements[j] = first->type; 1276 vectors[j] = &first->x; 1277 j++; 1278 } 1279 if (count != j) 1280 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl; 1281 x.Zero(); 1282 y.Zero(); 1283 y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude 1284 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times 1285 x.AddVector(&y); // per factor one cell width further 1286 for (int k=count;k--;) { // go through every atom of the original cell 1287 first = new atom(); // create a new body 1288 first->x.CopyVector(vectors[k]); // use coordinate of original atom 1289 first->x.AddVector(&x); // translate the coordinates 1290 first->type = Elements[k]; // insert original element 1291 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...) 1292 } 1293 } 1294 // free memory 1295 delete[](Elements); 1296 delete[](vectors); 1297 // correct cell size 1298 if (axis < 0) { // if sign was negative, we have to translate everything 1299 x.Zero(); 1300 x.AddVector(&y); 1301 x.Scale(-(faktor-1)); 1302 mol->Translate(&x); 1303 } 1304 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1305 } 1306 } 1307 } 1308 break; 1309 default: // no match? Step on 1310 if ((argptr < argc) && (argv[argptr][0] != '-')) // if it started with a '-' we've already made a step! 1311 argptr++; 1312 break; 1313 } 1314 } 1315 } else argptr++; 1316 } while (argptr < argc); 1317 if (SaveFlag) 1318 SaveConfig(ConfigFileName, &configuration, periode, mol); 1319 if ((ExitFlag >= 1)) { 1320 delete(mol); 1321 delete(periode); 1322 return (ExitFlag); 1323 } 1324 } else { // no arguments, hence scan the elements db 1325 if (periode->LoadPeriodentafel(PathToDatabases)) 1326 cout << Verbose(0) << "Element list loaded successfully." << endl; 1327 else 1328 cout << Verbose(0) << "Element list loading failed." << endl; 1329 configuration.RetrieveConfigPathAndName("main_pcp_linux"); 1330 } 1331 return(0); 1328 1332 }; 1329 1333 … … 1332 1336 int main(int argc, char **argv) 1333 1337 { 1334 periodentafel *periode = new periodentafel; // and a period table of all elements1335 molecule *mol = new molecule(periode);// first we need an empty molecule1336 config configuration;1337 double tmp1;1338 double bond, min_bond;1339 atom *first, *second;1340 char choice;// menu choice char1341 Vector x,y,z,n;// coordinates for absolute point in cell volume1338 periodentafel *periode = new periodentafel; // and a period table of all elements 1339 molecule *mol = new molecule(periode); // first we need an empty molecule 1340 config configuration; 1341 double tmp1; 1342 double bond, min_bond; 1343 atom *first, *second; 1344 char choice; // menu choice char 1345 Vector x,y,z,n; // coordinates for absolute point in cell volume 1342 1346 double *factor; // unit factor if desired 1343 bool valid; // flag if input was valid or not1344 ifstream test;1345 ofstream output;1346 string line;1347 char filename[MAXSTRINGSIZE];1348 char *ConfigFileName = NULL;1349 char *ElementsFileName = NULL;1350 int Z;1351 int j, axis, count, faktor;1352 clock_t start,end;1353 // int *MinimumRingSize = NULL;1354 MoleculeLeafClass *Subgraphs = NULL;1355 // class StackClass<bond *> *BackEdgeStack = NULL;1356 element **Elements;1357 Vector **vectors;1358 1359 // =========================== PARSE COMMAND LINE OPTIONS ====================================1360 j = ParseCommandLineOptions(argc, argv, mol, periode, configuration, ConfigFileName, ElementsFileName);1361 if (j == 1) return 0; // just for -v and -h options1362 if (j) return j;// something went wrong1363 1364 // General stuff1365 if (mol->cell_size[0] == 0.) {1366 cout << Verbose(0) << "enter lower triadiagonal form of basis matrix" << endl << endl;1367 for (int i=0;i<6;i++) {1368 cout << Verbose(1) << "Cell size" << i << ": ";1369 cin >> mol->cell_size[i];1370 }1371 }1372 1373 // =========================== START INTERACTIVE SESSION ====================================1374 1375 // now the main construction loop1376 cout << Verbose(0) << endl << "Now comes the real construction..." << endl;1377 do {1378 cout << Verbose(0) << endl << endl;1379 cout << Verbose(0) << "============Element list=======================" << endl;1380 mol->Checkout((ofstream *)&cout);1381 cout << Verbose(0) << "============Atom list==========================" << endl;1382 mol->Output((ofstream *)&cout);1383 cout << Verbose(0) << "============Menu===============================" << endl;1384 cout << Verbose(0) << "a - add an atom" << endl;1385 cout << Verbose(0) << "r - remove an atom" << endl;1386 cout << Verbose(0) << "b - scale a bond between atoms" << endl;1387 cout << Verbose(0) << "u - change an atoms element" << endl;1388 cout << Verbose(0) << "l - measure lengths, angles, ... for an atom" << endl;1389 cout << Verbose(0) << "-----------------------------------------------" << endl;1390 cout << Verbose(0) << "p - Parse xyz file" << endl;1391 cout << Verbose(0) << "e - edit the current configuration" << endl;1392 cout << Verbose(0) << "o - create connection matrix" << endl;1393 cout << Verbose(0) << "f - fragment molecule many-body bond order style" << endl;1394 cout << Verbose(0) << "-----------------------------------------------" << endl;1395 cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl;1396 cout << Verbose(0) << "i - realign molecule" << endl;1397 cout << Verbose(0) << "m - mirror all molecules" << endl;1398 cout << Verbose(0) << "t - translate molecule by vector" << endl;1399 cout << Verbose(0) << "c - scale by unit transformation" << endl;1400 cout << Verbose(0) << "g - center atoms in box" << endl;1401 cout << Verbose(0) << "-----------------------------------------------" << endl;1402 cout << Verbose(0) << "s - save current setup to config file" << endl;1403 cout << Verbose(0) << "T - call the current test routine" << endl;1404 cout << Verbose(0) << "q - quit" << endl;1405 cout << Verbose(0) << "===============================================" << endl;1406 cout << Verbose(0) << "Input: ";1407 cin >> choice;1408 1409 switch (choice) {1410 default:1411 case 'a': // add atom1412 AddAtoms(periode, mol);1413 choice = 'a';1414 break;1415 1416 case 'b': // scale a bond1417 cout << Verbose(0) << "Scaling bond length between two atoms." << endl;1418 first = mol->AskAtom("Enter first (fixed) atom: ");1419 second = mol->AskAtom("Enter second (shifting) atom: ");1420 min_bond = 0.;1421 for (int i=NDIM;i--;)1422 min_bond += (first->x.x[i]-second->x.x[i])*(first->x.x[i] - second->x.x[i]);1423 min_bond = sqrt(min_bond);1424 cout << Verbose(0) << "Current Bond length between " << first->type->name << " Atom " << first->nr << " and " << second->type->name << " Atom " << second->nr << ": " << min_bond << " a.u." << endl;1425 cout << Verbose(0) << "Enter new bond length [a.u.]: ";1426 cin >> bond;1427 for (int i=NDIM;i--;) {1428 second->x.x[i] -= (second->x.x[i]-first->x.x[i])/min_bond*(min_bond-bond);1429 }1430 //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: ";1431 //second->Output(second->type->No, 1, (ofstream *)&cout);1432 break;1433 1434 case 'c': // unit scaling of the metric1435 cout << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl;1436 cout << Verbose(0) << "Enter three factors: ";1437 factor = new double[NDIM];1438 cin >> factor[0];1439 cin >> factor[1];1440 cin >> factor[2];1441 valid = true;1442 mol->Scale(&factor);1443 delete[](factor);1444 break;1445 1446 case 'd': // duplicate the periodic cell along a given axis, given times1447 cout << Verbose(0) << "State the axis [(+-)123]: ";1448 cin >> axis;1449 cout << Verbose(0) << "State the factor: ";1450 cin >> faktor;1451 1452 mol->CountAtoms((ofstream *)&cout);// recount atoms1453 if (mol->AtomCount != 0) {// if there is more than none1454 count = mol->AtomCount;// is changed becausing of adding, thus has to be stored away beforehand1455 Elements = new element *[count];1456 vectors = new Vector *[count];1457 j = 0;1458 first = mol->start;1459 while (first->next != mol->end) {// make a list of all atoms with coordinates and element1460 first = first->next;1461 Elements[j] = first->type;1462 vectors[j] = &first->x;1463 j++;1464 }1465 if (count != j)1466 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl;1467 x.Zero();1468 y.Zero();1469 y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude1470 for (int i=1;i<faktor;i++) {// then add this list with respective translation factor times1471 x.AddVector(&y); // per factor one cell width further1472 for (int k=count;k--;) { // go through every atom of the original cell1473 first = new atom(); // create a new body1474 first->x.CopyVector(vectors[k]);// use coordinate of original atom1475 first->x.AddVector(&x);// translate the coordinates1476 first->type = Elements[k];// insert original element1477 mol->AddAtom(first);// and add to the molecule (which increments ElementsInMolecule, AtomCount, ...)1478 }1479 }1480 if (mol->first->next != mol->last) // if connect matrix is present already, redo it1481 mol->CreateAdjacencyList((ofstream *)&cout, mol->BondDistance, configuration.GetIsAngstroem());1482 // free memory1483 delete[](Elements);1484 delete[](vectors);1485 // correct cell size1486 if (axis < 0) { // if sign was negative, we have to translate everything1487 x.Zero();1488 x.AddVector(&y);1489 x.Scale(-(faktor-1));1490 mol->Translate(&x);1491 }1492 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor;1493 }1494 break;1495 1496 case 'e': // edit each field of the configuration1497 configuration.Edit(mol);1498 break;1499 1500 case 'f':1501 FragmentAtoms(mol, &configuration);1502 break;1503 1504 case 'g': // center the atoms1505 CenterAtoms(mol);1506 break;1507 1508 case 'i': // align all atoms1509 AlignAtoms(periode, mol);1510 break;1511 1512 case 'l': // measure distances or angles1513 MeasureAtoms(periode, mol, &configuration);1514 break;1515 1516 case 'm': // mirror atoms along a given axis1517 MirrorAtoms(mol);1518 break;1519 1520 case 'o': // create the connection matrix1521 {1522 cout << Verbose(0) << "What's the maximum bond distance: ";1523 cin >> tmp1;1524 start = clock();1525 mol->CreateAdjacencyList((ofstream *)&cout, tmp1, configuration.GetIsAngstroem());1526 mol->CreateListOfBondsPerAtom((ofstream *)&cout);1527 // Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack);1528 // while (Subgraphs->next != NULL) {1529 // Subgraphs = Subgraphs->next;1530 // Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize);1531 // delete(Subgraphs->previous);1532 // }1533 // delete(Subgraphs);// we don't need the list here, so free everything1534 // delete[](MinimumRingSize);1535 // Subgraphs = NULL;1536 end = clock();1537 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;1538 }1539 break;1540 1541 case 'p': // parse and XYZ file1542 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;1543 do {1544 cout << Verbose(0) << "Enter file name: ";1545 cin >> filename;1546 } while (!mol->AddXYZFile(filename));1547 break;1548 1549 case 'q': // quit1550 break;1551 1552 case 'r': // remove atom1553 RemoveAtoms(mol);1554 break;1555 1556 case 's': // save to config file1557 SaveConfig(ConfigFileName, &configuration, periode, mol);1558 break;1559 1560 case 't': // translate all atoms1561 cout << Verbose(0) << "Enter translation vector." << endl;1562 x.AskPosition(mol->cell_size,0);1563 mol->Translate((const Vector *)&x);1564 break;1565 1566 case 'T':1567 testroutine(mol);1568 break;1569 1570 case 'u': // change an atom's element1571 first = NULL;1572 do {1573 cout << Verbose(0) << "Change the element of which atom: ";1574 cin >> Z;1575 } while ((first = mol->FindAtom(Z)) == NULL);1576 cout << Verbose(0) << "New element by atomic number Z: ";1577 cin >> Z;1578 first->type = periode->FindElement(Z);1579 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl;1580 break;1581 };1582 } while (choice != 'q');1583 1584 // save element data base1585 if (periode->StorePeriodentafel(ElementsFileName)) //ElementsFileName1586 cout << Verbose(0) << "Saving of elements.db successful." << endl;1587 else1588 cout << Verbose(0) << "Saving of elements.db failed." << endl;1589 1590 // Free all1591 if (Subgraphs != NULL) {// free disconnected subgraph list of DFS analysis was performed1592 while (Subgraphs->next != NULL) {1593 Subgraphs = Subgraphs->next;1594 delete(Subgraphs->previous);1595 }1596 delete(Subgraphs);1597 }1598 delete(mol);1599 delete(periode);1600 return (0);1347 bool valid; // flag if input was valid or not 1348 ifstream test; 1349 ofstream output; 1350 string line; 1351 char filename[MAXSTRINGSIZE]; 1352 char *ConfigFileName = NULL; 1353 char *ElementsFileName = NULL; 1354 int Z; 1355 int j, axis, count, faktor; 1356 clock_t start,end; 1357 // int *MinimumRingSize = NULL; 1358 MoleculeLeafClass *Subgraphs = NULL; 1359 // class StackClass<bond *> *BackEdgeStack = NULL; 1360 element **Elements; 1361 Vector **vectors; 1362 1363 // =========================== PARSE COMMAND LINE OPTIONS ==================================== 1364 j = ParseCommandLineOptions(argc, argv, mol, periode, configuration, ConfigFileName, ElementsFileName); 1365 if (j == 1) return 0; // just for -v and -h options 1366 if (j) return j; // something went wrong 1367 1368 // General stuff 1369 if (mol->cell_size[0] == 0.) { 1370 cout << Verbose(0) << "enter lower triadiagonal form of basis matrix" << endl << endl; 1371 for (int i=0;i<6;i++) { 1372 cout << Verbose(1) << "Cell size" << i << ": "; 1373 cin >> mol->cell_size[i]; 1374 } 1375 } 1376 1377 // =========================== START INTERACTIVE SESSION ==================================== 1378 1379 // now the main construction loop 1380 cout << Verbose(0) << endl << "Now comes the real construction..." << endl; 1381 do { 1382 cout << Verbose(0) << endl << endl; 1383 cout << Verbose(0) << "============Element list=======================" << endl; 1384 mol->Checkout((ofstream *)&cout); 1385 cout << Verbose(0) << "============Atom list==========================" << endl; 1386 mol->Output((ofstream *)&cout); 1387 cout << Verbose(0) << "============Menu===============================" << endl; 1388 cout << Verbose(0) << "a - add an atom" << endl; 1389 cout << Verbose(0) << "r - remove an atom" << endl; 1390 cout << Verbose(0) << "b - scale a bond between atoms" << endl; 1391 cout << Verbose(0) << "u - change an atoms element" << endl; 1392 cout << Verbose(0) << "l - measure lengths, angles, ... for an atom" << endl; 1393 cout << Verbose(0) << "-----------------------------------------------" << endl; 1394 cout << Verbose(0) << "p - Parse xyz file" << endl; 1395 cout << Verbose(0) << "e - edit the current configuration" << endl; 1396 cout << Verbose(0) << "o - create connection matrix" << endl; 1397 cout << Verbose(0) << "f - fragment molecule many-body bond order style" << endl; 1398 cout << Verbose(0) << "-----------------------------------------------" << endl; 1399 cout << Verbose(0) << "d - duplicate molecule/periodic cell" << endl; 1400 cout << Verbose(0) << "i - realign molecule" << endl; 1401 cout << Verbose(0) << "m - mirror all molecules" << endl; 1402 cout << Verbose(0) << "t - translate molecule by vector" << endl; 1403 cout << Verbose(0) << "c - scale by unit transformation" << endl; 1404 cout << Verbose(0) << "g - center atoms in box" << endl; 1405 cout << Verbose(0) << "-----------------------------------------------" << endl; 1406 cout << Verbose(0) << "s - save current setup to config file" << endl; 1407 cout << Verbose(0) << "T - call the current test routine" << endl; 1408 cout << Verbose(0) << "q - quit" << endl; 1409 cout << Verbose(0) << "===============================================" << endl; 1410 cout << Verbose(0) << "Input: "; 1411 cin >> choice; 1412 1413 switch (choice) { 1414 default: 1415 case 'a': // add atom 1416 AddAtoms(periode, mol); 1417 choice = 'a'; 1418 break; 1419 1420 case 'b': // scale a bond 1421 cout << Verbose(0) << "Scaling bond length between two atoms." << endl; 1422 first = mol->AskAtom("Enter first (fixed) atom: "); 1423 second = mol->AskAtom("Enter second (shifting) atom: "); 1424 min_bond = 0.; 1425 for (int i=NDIM;i--;) 1426 min_bond += (first->x.x[i]-second->x.x[i])*(first->x.x[i] - second->x.x[i]); 1427 min_bond = sqrt(min_bond); 1428 cout << Verbose(0) << "Current Bond length between " << first->type->name << " Atom " << first->nr << " and " << second->type->name << " Atom " << second->nr << ": " << min_bond << " a.u." << endl; 1429 cout << Verbose(0) << "Enter new bond length [a.u.]: "; 1430 cin >> bond; 1431 for (int i=NDIM;i--;) { 1432 second->x.x[i] -= (second->x.x[i]-first->x.x[i])/min_bond*(min_bond-bond); 1433 } 1434 //cout << Verbose(0) << "New coordinates of Atom " << second->nr << " are: "; 1435 //second->Output(second->type->No, 1, (ofstream *)&cout); 1436 break; 1437 1438 case 'c': // unit scaling of the metric 1439 cout << Verbose(0) << "Angstroem -> Bohrradius: 1.8897261\t\tBohrradius -> Angstroem: 0.52917721" << endl; 1440 cout << Verbose(0) << "Enter three factors: "; 1441 factor = new double[NDIM]; 1442 cin >> factor[0]; 1443 cin >> factor[1]; 1444 cin >> factor[2]; 1445 valid = true; 1446 mol->Scale(&factor); 1447 delete[](factor); 1448 break; 1449 1450 case 'd': // duplicate the periodic cell along a given axis, given times 1451 cout << Verbose(0) << "State the axis [(+-)123]: "; 1452 cin >> axis; 1453 cout << Verbose(0) << "State the factor: "; 1454 cin >> faktor; 1455 1456 mol->CountAtoms((ofstream *)&cout); // recount atoms 1457 if (mol->AtomCount != 0) { // if there is more than none 1458 count = mol->AtomCount; // is changed becausing of adding, thus has to be stored away beforehand 1459 Elements = new element *[count]; 1460 vectors = new Vector *[count]; 1461 j = 0; 1462 first = mol->start; 1463 while (first->next != mol->end) { // make a list of all atoms with coordinates and element 1464 first = first->next; 1465 Elements[j] = first->type; 1466 vectors[j] = &first->x; 1467 j++; 1468 } 1469 if (count != j) 1470 cout << Verbose(0) << "ERROR: AtomCount " << count << " is not equal to number of atoms in molecule " << j << "!" << endl; 1471 x.Zero(); 1472 y.Zero(); 1473 y.x[abs(axis)-1] = mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] * abs(axis)/axis; // last term is for sign, first is for magnitude 1474 for (int i=1;i<faktor;i++) { // then add this list with respective translation factor times 1475 x.AddVector(&y); // per factor one cell width further 1476 for (int k=count;k--;) { // go through every atom of the original cell 1477 first = new atom(); // create a new body 1478 first->x.CopyVector(vectors[k]); // use coordinate of original atom 1479 first->x.AddVector(&x); // translate the coordinates 1480 first->type = Elements[k]; // insert original element 1481 mol->AddAtom(first); // and add to the molecule (which increments ElementsInMolecule, AtomCount, ...) 1482 } 1483 } 1484 if (mol->first->next != mol->last) // if connect matrix is present already, redo it 1485 mol->CreateAdjacencyList((ofstream *)&cout, mol->BondDistance, configuration.GetIsAngstroem()); 1486 // free memory 1487 delete[](Elements); 1488 delete[](vectors); 1489 // correct cell size 1490 if (axis < 0) { // if sign was negative, we have to translate everything 1491 x.Zero(); 1492 x.AddVector(&y); 1493 x.Scale(-(faktor-1)); 1494 mol->Translate(&x); 1495 } 1496 mol->cell_size[(abs(axis) == 2) ? 2 : ((abs(axis) == 3) ? 5 : 0)] *= faktor; 1497 } 1498 break; 1499 1500 case 'e': // edit each field of the configuration 1501 configuration.Edit(mol); 1502 break; 1503 1504 case 'f': 1505 FragmentAtoms(mol, &configuration); 1506 break; 1507 1508 case 'g': // center the atoms 1509 CenterAtoms(mol); 1510 break; 1511 1512 case 'i': // align all atoms 1513 AlignAtoms(periode, mol); 1514 break; 1515 1516 case 'l': // measure distances or angles 1517 MeasureAtoms(periode, mol, &configuration); 1518 break; 1519 1520 case 'm': // mirror atoms along a given axis 1521 MirrorAtoms(mol); 1522 break; 1523 1524 case 'o': // create the connection matrix 1525 { 1526 cout << Verbose(0) << "What's the maximum bond distance: "; 1527 cin >> tmp1; 1528 start = clock(); 1529 mol->CreateAdjacencyList((ofstream *)&cout, tmp1, configuration.GetIsAngstroem()); 1530 mol->CreateListOfBondsPerAtom((ofstream *)&cout); 1531 // Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, BackEdgeStack); 1532 // while (Subgraphs->next != NULL) { 1533 // Subgraphs = Subgraphs->next; 1534 // Subgraphs->Leaf->CyclicStructureAnalysis((ofstream *)&cout, BackEdgeStack, MinimumRingSize); 1535 // delete(Subgraphs->previous); 1536 // } 1537 // delete(Subgraphs); // we don't need the list here, so free everything 1538 // delete[](MinimumRingSize); 1539 // Subgraphs = NULL; 1540 end = clock(); 1541 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 1542 } 1543 break; 1544 1545 case 'p': // parse and XYZ file 1546 cout << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl; 1547 do { 1548 cout << Verbose(0) << "Enter file name: "; 1549 cin >> filename; 1550 } while (!mol->AddXYZFile(filename)); 1551 break; 1552 1553 case 'q': // quit 1554 break; 1555 1556 case 'r': // remove atom 1557 RemoveAtoms(mol); 1558 break; 1559 1560 case 's': // save to config file 1561 SaveConfig(ConfigFileName, &configuration, periode, mol); 1562 break; 1563 1564 case 't': // translate all atoms 1565 cout << Verbose(0) << "Enter translation vector." << endl; 1566 x.AskPosition(mol->cell_size,0); 1567 mol->Translate((const Vector *)&x); 1568 break; 1569 1570 case 'T': 1571 testroutine(mol); 1572 break; 1573 1574 case 'u': // change an atom's element 1575 first = NULL; 1576 do { 1577 cout << Verbose(0) << "Change the element of which atom: "; 1578 cin >> Z; 1579 } while ((first = mol->FindAtom(Z)) == NULL); 1580 cout << Verbose(0) << "New element by atomic number Z: "; 1581 cin >> Z; 1582 first->type = periode->FindElement(Z); 1583 cout << Verbose(0) << "Atom " << first->nr << "'s element is " << first->type->name << "." << endl; 1584 break; 1585 }; 1586 } while (choice != 'q'); 1587 1588 // save element data base 1589 if (periode->StorePeriodentafel(ElementsFileName)) //ElementsFileName 1590 cout << Verbose(0) << "Saving of elements.db successful." << endl; 1591 else 1592 cout << Verbose(0) << "Saving of elements.db failed." << endl; 1593 1594 // Free all 1595 if (Subgraphs != NULL) { // free disconnected subgraph list of DFS analysis was performed 1596 while (Subgraphs->next != NULL) { 1597 Subgraphs = Subgraphs->next; 1598 delete(Subgraphs->previous); 1599 } 1600 delete(Subgraphs); 1601 } 1602 delete(mol); 1603 delete(periode); 1604 return (0); 1601 1605 } 1602 1606 -
Property mode
changed from
-
src/config.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 13 13 config::config() 14 14 { 15 mainname = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");16 defaultpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");17 pseudopotpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");18 configpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");19 configname = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname");20 strcpy(mainname,"pcp");21 strcpy(defaultpath,"not specified");22 strcpy(pseudopotpath,"not specified");23 configpath[0]='\0';24 configname[0]='\0';25 26 FastParsing = false;27 ProcPEGamma=8;28 ProcPEPsi=1;29 DoOutVis=0;30 DoOutMes=1;31 DoOutNICS=0;32 DoOutOrbitals=0;33 DoOutCurrent=0;34 DoPerturbation=0;35 DoFullCurrent=0;36 DoWannier=0;37 CommonWannier=0;38 SawtoothStart=0.01;39 VectorPlane=0;40 VectorCut=0;41 UseAddGramSch=1;42 Seed=1;43 44 MaxOuterStep=0;45 Deltat=1;46 OutVisStep=10;47 OutSrcStep=5;48 TargetTemp=0.00095004455;49 ScaleTempStep=25;50 MaxPsiStep=0;51 EpsWannier=1e-7;52 53 MaxMinStep=100;54 RelEpsTotalEnergy=1e-7;55 RelEpsKineticEnergy=1e-5;56 MaxMinStopStep=1;57 MaxMinGapStopStep=0;58 MaxInitMinStep=100;59 InitRelEpsTotalEnergy=1e-5;60 InitRelEpsKineticEnergy=1e-4;61 InitMaxMinStopStep=1;62 InitMaxMinGapStopStep=0;63 64 //BoxLength[NDIM*NDIM];65 66 ECut=128.;67 MaxLevel=5;68 RiemannTensor=0;69 LevRFactor=0;70 RiemannLevel=0;71 Lev0Factor=2;72 RTActualUse=0;73 PsiType=0;74 MaxPsiDouble=0;75 PsiMaxNoUp=0;76 PsiMaxNoDown=0;77 AddPsis=0;78 79 RCut=20.;80 StructOpt=0;81 IsAngstroem=1;82 RelativeCoord=0;83 MaxTypes=0;15 mainname = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname"); 16 defaultpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname"); 17 pseudopotpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname"); 18 configpath = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname"); 19 configname = (char *) MallocString(sizeof(char)*MAXSTRINGSIZE,"config constructor: mainname"); 20 strcpy(mainname,"pcp"); 21 strcpy(defaultpath,"not specified"); 22 strcpy(pseudopotpath,"not specified"); 23 configpath[0]='\0'; 24 configname[0]='\0'; 25 26 FastParsing = false; 27 ProcPEGamma=8; 28 ProcPEPsi=1; 29 DoOutVis=0; 30 DoOutMes=1; 31 DoOutNICS=0; 32 DoOutOrbitals=0; 33 DoOutCurrent=0; 34 DoPerturbation=0; 35 DoFullCurrent=0; 36 DoWannier=0; 37 CommonWannier=0; 38 SawtoothStart=0.01; 39 VectorPlane=0; 40 VectorCut=0; 41 UseAddGramSch=1; 42 Seed=1; 43 44 MaxOuterStep=0; 45 Deltat=1; 46 OutVisStep=10; 47 OutSrcStep=5; 48 TargetTemp=0.00095004455; 49 ScaleTempStep=25; 50 MaxPsiStep=0; 51 EpsWannier=1e-7; 52 53 MaxMinStep=100; 54 RelEpsTotalEnergy=1e-7; 55 RelEpsKineticEnergy=1e-5; 56 MaxMinStopStep=1; 57 MaxMinGapStopStep=0; 58 MaxInitMinStep=100; 59 InitRelEpsTotalEnergy=1e-5; 60 InitRelEpsKineticEnergy=1e-4; 61 InitMaxMinStopStep=1; 62 InitMaxMinGapStopStep=0; 63 64 //BoxLength[NDIM*NDIM]; 65 66 ECut=128.; 67 MaxLevel=5; 68 RiemannTensor=0; 69 LevRFactor=0; 70 RiemannLevel=0; 71 Lev0Factor=2; 72 RTActualUse=0; 73 PsiType=0; 74 MaxPsiDouble=0; 75 PsiMaxNoUp=0; 76 PsiMaxNoDown=0; 77 AddPsis=0; 78 79 RCut=20.; 80 StructOpt=0; 81 IsAngstroem=1; 82 RelativeCoord=0; 83 MaxTypes=0; 84 84 }; 85 85 … … 89 89 config::~config() 90 90 { 91 Free((void **)&mainname, "config::~config: *mainname");92 Free((void **)&defaultpath, "config::~config: *defaultpath");93 Free((void **)&pseudopotpath, "config::~config: *pseudopotpath");94 Free((void **)&configpath, "config::~config: *configpath");95 Free((void **)&configname, "config::~config: *configname");91 Free((void **)&mainname, "config::~config: *mainname"); 92 Free((void **)&defaultpath, "config::~config: *defaultpath"); 93 Free((void **)&pseudopotpath, "config::~config: *pseudopotpath"); 94 Free((void **)&configpath, "config::~config: *configpath"); 95 Free((void **)&configname, "config::~config: *configname"); 96 96 }; 97 97 … … 102 102 void config::Edit(molecule *mol) 103 103 { 104 char choice;105 106 do {107 cout << Verbose(0) << "===========EDIT CONFIGURATION============================" << endl;108 cout << Verbose(0) << " A - mainname (prefix for all runtime files)" << endl;109 cout << Verbose(0) << " B - Default path (for runtime files)" << endl;110 cout << Verbose(0) << " C - Path of pseudopotential files" << endl;111 cout << Verbose(0) << " D - Number of coefficient sharing processes" << endl;112 cout << Verbose(0) << " E - Number of wave function sharing processes" << endl;113 cout << Verbose(0) << " F - 0: Don't output density for OpenDX, 1: do" << endl;114 cout << Verbose(0) << " G - 0: Don't output physical data, 1: do" << endl;115 cout << Verbose(0) << " H - 0: Don't output densities of each unperturbed orbital for OpenDX, 1: do" << endl;116 cout << Verbose(0) << " I - 0: Don't output current density for OpenDX, 1: do" << endl;117 cout << Verbose(0) << " J - 0: Don't do the full current calculation, 1: do" << endl;118 cout << Verbose(0) << " K - 0: Don't do perturbation calculation to obtain susceptibility and shielding, 1: do" << endl;119 cout << Verbose(0) << " L - 0: Wannier centres as calculated, 1: common centre for all, 2: unite centres according to spread, 3: cell centre, 4: shifted to nearest grid point" << endl;120 cout << Verbose(0) << " M - Absolute begin of unphysical sawtooth transfer for position operator within cell" << endl;121 cout << Verbose(0) << " N - (0,1,2) x,y,z-plane to do two-dimensional current vector cut" << endl;122 cout << Verbose(0) << " O - Absolute position along vector cut axis for cut plane" << endl;123 cout << Verbose(0) << " P - Additional Gram-Schmidt-Orthonormalization to stabilize numerics" << endl;124 cout << Verbose(0) << " Q - Initial integer value of random number generator" << endl;125 cout << Verbose(0) << " R - for perturbation 0, for structure optimization defines upper limit of iterations" << endl;126 cout << Verbose(0) << " T - Output visual after ...th step" << endl;127 cout << Verbose(0) << " U - Output source densities of wave functions after ...th step" << endl;128 cout << Verbose(0) << " X - minimization iterations per wave function, if unsure leave at default value 0" << endl;129 cout << Verbose(0) << " Y - tolerance value for total spread in iterative Jacobi diagonalization" << endl;130 cout << Verbose(0) << " Z - Maximum number of minimization iterations" << endl;131 cout << Verbose(0) << " a - Relative change in total energy to stop min. iteration" << endl;132 cout << Verbose(0) << " b - Relative change in kinetic energy to stop min. iteration" << endl;133 cout << Verbose(0) << " c - Check stop conditions every ..th step during min. iteration" << endl;134 cout << Verbose(0) << " e - Maximum number of minimization iterations during initial level" << endl;135 cout << Verbose(0) << " f - Relative change in total energy to stop min. iteration during initial level" << endl;136 cout << Verbose(0) << " g - Relative change in kinetic energy to stop min. iteration during initial level" << endl;137 cout << Verbose(0) << " h - Check stop conditions every ..th step during min. iteration during initial level" << endl;138 cout << Verbose(0) << " j - six lower diagonal entries of matrix, defining the unit cell" << endl;139 cout << Verbose(0) << " k - Energy cutoff of plane wave basis in Hartree" << endl;140 cout << Verbose(0) << " l - Maximum number of levels in multi-level-ansatz" << endl;141 cout << Verbose(0) << " m - Factor by which grid nodes increase between standard and upper level" << endl;142 cout << Verbose(0) << " n - 0: Don't use RiemannTensor, 1: Do" << endl;143 cout << Verbose(0) << " o - Factor by which grid nodes increase between Riemann and standard(?) level" << endl;144 cout << Verbose(0) << " p - Number of Riemann levels" << endl;145 cout << Verbose(0) << " r - 0: Don't Use RiemannTensor, 1: Do" << endl;146 cout << Verbose(0) << " s - 0: Doubly occupied orbitals, 1: Up-/Down-Orbitals" << endl;147 cout << Verbose(0) << " t - Number of orbitals (depends pn SpinType)" << endl;148 cout << Verbose(0) << " u - Number of SpinUp orbitals (depends on SpinType)" << endl;149 cout << Verbose(0) << " v - Number of SpinDown orbitals (depends on SpinType)" << endl;150 cout << Verbose(0) << " w - Number of additional, unoccupied orbitals" << endl;151 cout << Verbose(0) << " x - radial cutoff for ewald summation in Bohrradii" << endl;152 cout << Verbose(0) << " y - 0: Don't do structure optimization beforehand, 1: Do" << endl;153 cout << Verbose(0) << " z - 0: Units are in Bohr radii, 1: units are in Aengstrom" << endl;154 cout << Verbose(0) << " i - 0: Coordinates given in file are absolute, 1: ... are relative to unit cell" << endl;155 cout << Verbose(0) << "=========================================================" << endl;156 cout << Verbose(0) << "INPUT: ";157 cin >> choice;158 159 switch (choice) {160 case 'A': // mainname161 cout << Verbose(0) << "Old: " << config::mainname << "\t new: ";162 cin >> config::mainname;163 break;164 case 'B': // defaultpath165 cout << Verbose(0) << "Old: " << config::defaultpath << "\t new: ";166 cin >> config::defaultpath;167 break;168 case 'C': // pseudopotpath169 cout << Verbose(0) << "Old: " << config::pseudopotpath << "\t new: ";170 cin >> config::pseudopotpath;171 break;172 173 case 'D': // ProcPEGamma174 cout << Verbose(0) << "Old: " << config::ProcPEGamma << "\t new: ";175 cin >> config::ProcPEGamma;176 break;177 case 'E': // ProcPEPsi178 cout << Verbose(0) << "Old: " << config::ProcPEPsi << "\t new: ";179 cin >> config::ProcPEPsi;180 break;181 case 'F': // DoOutVis182 cout << Verbose(0) << "Old: " << config::DoOutVis << "\t new: ";183 cin >> config::DoOutVis;184 break;185 case 'G': // DoOutMes186 cout << Verbose(0) << "Old: " << config::DoOutMes << "\t new: ";187 cin >> config::DoOutMes;188 break;189 case 'H': // DoOutOrbitals190 cout << Verbose(0) << "Old: " << config::DoOutOrbitals << "\t new: ";191 cin >> config::DoOutOrbitals;192 break;193 case 'I': // DoOutCurrent194 cout << Verbose(0) << "Old: " << config::DoOutCurrent << "\t new: ";195 cin >> config::DoOutCurrent;196 break;197 case 'J': // DoFullCurrent198 cout << Verbose(0) << "Old: " << config::DoFullCurrent << "\t new: ";199 cin >> config::DoFullCurrent;200 break;201 case 'K': // DoPerturbation202 cout << Verbose(0) << "Old: " << config::DoPerturbation << "\t new: ";203 cin >> config::DoPerturbation;204 break;205 case 'L': // CommonWannier206 cout << Verbose(0) << "Old: " << config::CommonWannier << "\t new: ";207 cin >> config::CommonWannier;208 break;209 case 'M': // SawtoothStart210 cout << Verbose(0) << "Old: " << config::SawtoothStart << "\t new: ";211 cin >> config::SawtoothStart;212 break;213 case 'N': // VectorPlane214 cout << Verbose(0) << "Old: " << config::VectorPlane << "\t new: ";215 cin >> config::VectorPlane;216 break;217 case 'O': // VectorCut218 cout << Verbose(0) << "Old: " << config::VectorCut << "\t new: ";219 cin >> config::VectorCut;220 break;221 case 'P': // UseAddGramSch222 cout << Verbose(0) << "Old: " << config::UseAddGramSch << "\t new: ";223 cin >> config::UseAddGramSch;224 break;225 case 'Q': // Seed226 cout << Verbose(0) << "Old: " << config::Seed << "\t new: ";227 cin >> config::Seed;228 break;229 230 case 'R': // MaxOuterStep231 cout << Verbose(0) << "Old: " << config::MaxOuterStep << "\t new: ";232 cin >> config::MaxOuterStep;233 break;234 case 'T': // OutVisStep235 cout << Verbose(0) << "Old: " << config::OutVisStep << "\t new: ";236 cin >> config::OutVisStep;237 break;238 case 'U': // OutSrcStep239 cout << Verbose(0) << "Old: " << config::OutSrcStep << "\t new: ";240 cin >> config::OutSrcStep;241 break;242 case 'X': // MaxPsiStep243 cout << Verbose(0) << "Old: " << config::MaxPsiStep << "\t new: ";244 cin >> config::MaxPsiStep;245 break;246 case 'Y': // EpsWannier247 cout << Verbose(0) << "Old: " << config::EpsWannier << "\t new: ";248 cin >> config::EpsWannier;249 break;250 251 case 'Z': // MaxMinStep252 cout << Verbose(0) << "Old: " << config::MaxMinStep << "\t new: ";253 cin >> config::MaxMinStep;254 break;255 case 'a': // RelEpsTotalEnergy256 cout << Verbose(0) << "Old: " << config::RelEpsTotalEnergy << "\t new: ";257 cin >> config::RelEpsTotalEnergy;258 break;259 case 'b': // RelEpsKineticEnergy260 cout << Verbose(0) << "Old: " << config::RelEpsKineticEnergy << "\t new: ";261 cin >> config::RelEpsKineticEnergy;262 break;263 case 'c': // MaxMinStopStep264 cout << Verbose(0) << "Old: " << config::MaxMinStopStep << "\t new: ";265 cin >> config::MaxMinStopStep;266 break;267 case 'e': // MaxInitMinStep268 cout << Verbose(0) << "Old: " << config::MaxInitMinStep << "\t new: ";269 cin >> config::MaxInitMinStep;270 break;271 case 'f': // InitRelEpsTotalEnergy272 cout << Verbose(0) << "Old: " << config::InitRelEpsTotalEnergy << "\t new: ";273 cin >> config::InitRelEpsTotalEnergy;274 break;275 case 'g': // InitRelEpsKineticEnergy276 cout << Verbose(0) << "Old: " << config::InitRelEpsKineticEnergy << "\t new: ";277 cin >> config::InitRelEpsKineticEnergy;278 break;279 case 'h': // InitMaxMinStopStep280 cout << Verbose(0) << "Old: " << config::InitMaxMinStopStep << "\t new: ";281 cin >> config::InitMaxMinStopStep;282 break;283 284 case 'j': // BoxLength285 cout << Verbose(0) << "enter lower triadiagonalo form of basis matrix" << endl << endl;286 for (int i=0;i<6;i++) {287 cout << Verbose(0) << "Cell size" << i << ": ";288 cin >> mol->cell_size[i];289 }290 break;291 292 case 'k': // ECut293 cout << Verbose(0) << "Old: " << config::ECut << "\t new: ";294 cin >> config::ECut;295 break;296 case 'l': // MaxLevel297 cout << Verbose(0) << "Old: " << config::MaxLevel << "\t new: ";298 cin >> config::MaxLevel;299 break;300 case 'm': // RiemannTensor301 cout << Verbose(0) << "Old: " << config::RiemannTensor << "\t new: ";302 cin >> config::RiemannTensor;303 break;304 case 'n': // LevRFactor305 cout << Verbose(0) << "Old: " << config::LevRFactor << "\t new: ";306 cin >> config::LevRFactor;307 break;308 case 'o': // RiemannLevel309 cout << Verbose(0) << "Old: " << config::RiemannLevel << "\t new: ";310 cin >> config::RiemannLevel;311 break;312 case 'p': // Lev0Factor313 cout << Verbose(0) << "Old: " << config::Lev0Factor << "\t new: ";314 cin >> config::Lev0Factor;315 break;316 case 'r': // RTActualUse317 cout << Verbose(0) << "Old: " << config::RTActualUse << "\t new: ";318 cin >> config::RTActualUse;319 break;320 case 's': // PsiType321 cout << Verbose(0) << "Old: " << config::PsiType << "\t new: ";322 cin >> config::PsiType;323 break;324 case 't': // MaxPsiDouble325 cout << Verbose(0) << "Old: " << config::MaxPsiDouble << "\t new: ";326 cin >> config::MaxPsiDouble;327 break;328 case 'u': // PsiMaxNoUp329 cout << Verbose(0) << "Old: " << config::PsiMaxNoUp << "\t new: ";330 cin >> config::PsiMaxNoUp;331 break;332 case 'v': // PsiMaxNoDown333 cout << Verbose(0) << "Old: " << config::PsiMaxNoDown << "\t new: ";334 cin >> config::PsiMaxNoDown;335 break;336 case 'w': // AddPsis337 cout << Verbose(0) << "Old: " << config::AddPsis << "\t new: ";338 cin >> config::AddPsis;339 break;340 341 case 'x': // RCut342 cout << Verbose(0) << "Old: " << config::RCut << "\t new: ";343 cin >> config::RCut;344 break;345 case 'y': // StructOpt346 cout << Verbose(0) << "Old: " << config::StructOpt << "\t new: ";347 cin >> config::StructOpt;348 break;349 case 'z': // IsAngstroem350 cout << Verbose(0) << "Old: " << config::IsAngstroem << "\t new: ";351 cin >> config::IsAngstroem;352 break;353 case 'i': // RelativeCoord354 cout << Verbose(0) << "Old: " << config::RelativeCoord << "\t new: ";355 cin >> config::RelativeCoord;356 break;357 };358 } while (choice != 'q');104 char choice; 105 106 do { 107 cout << Verbose(0) << "===========EDIT CONFIGURATION============================" << endl; 108 cout << Verbose(0) << " A - mainname (prefix for all runtime files)" << endl; 109 cout << Verbose(0) << " B - Default path (for runtime files)" << endl; 110 cout << Verbose(0) << " C - Path of pseudopotential files" << endl; 111 cout << Verbose(0) << " D - Number of coefficient sharing processes" << endl; 112 cout << Verbose(0) << " E - Number of wave function sharing processes" << endl; 113 cout << Verbose(0) << " F - 0: Don't output density for OpenDX, 1: do" << endl; 114 cout << Verbose(0) << " G - 0: Don't output physical data, 1: do" << endl; 115 cout << Verbose(0) << " H - 0: Don't output densities of each unperturbed orbital for OpenDX, 1: do" << endl; 116 cout << Verbose(0) << " I - 0: Don't output current density for OpenDX, 1: do" << endl; 117 cout << Verbose(0) << " J - 0: Don't do the full current calculation, 1: do" << endl; 118 cout << Verbose(0) << " K - 0: Don't do perturbation calculation to obtain susceptibility and shielding, 1: do" << endl; 119 cout << Verbose(0) << " L - 0: Wannier centres as calculated, 1: common centre for all, 2: unite centres according to spread, 3: cell centre, 4: shifted to nearest grid point" << endl; 120 cout << Verbose(0) << " M - Absolute begin of unphysical sawtooth transfer for position operator within cell" << endl; 121 cout << Verbose(0) << " N - (0,1,2) x,y,z-plane to do two-dimensional current vector cut" << endl; 122 cout << Verbose(0) << " O - Absolute position along vector cut axis for cut plane" << endl; 123 cout << Verbose(0) << " P - Additional Gram-Schmidt-Orthonormalization to stabilize numerics" << endl; 124 cout << Verbose(0) << " Q - Initial integer value of random number generator" << endl; 125 cout << Verbose(0) << " R - for perturbation 0, for structure optimization defines upper limit of iterations" << endl; 126 cout << Verbose(0) << " T - Output visual after ...th step" << endl; 127 cout << Verbose(0) << " U - Output source densities of wave functions after ...th step" << endl; 128 cout << Verbose(0) << " X - minimization iterations per wave function, if unsure leave at default value 0" << endl; 129 cout << Verbose(0) << " Y - tolerance value for total spread in iterative Jacobi diagonalization" << endl; 130 cout << Verbose(0) << " Z - Maximum number of minimization iterations" << endl; 131 cout << Verbose(0) << " a - Relative change in total energy to stop min. iteration" << endl; 132 cout << Verbose(0) << " b - Relative change in kinetic energy to stop min. iteration" << endl; 133 cout << Verbose(0) << " c - Check stop conditions every ..th step during min. iteration" << endl; 134 cout << Verbose(0) << " e - Maximum number of minimization iterations during initial level" << endl; 135 cout << Verbose(0) << " f - Relative change in total energy to stop min. iteration during initial level" << endl; 136 cout << Verbose(0) << " g - Relative change in kinetic energy to stop min. iteration during initial level" << endl; 137 cout << Verbose(0) << " h - Check stop conditions every ..th step during min. iteration during initial level" << endl; 138 cout << Verbose(0) << " j - six lower diagonal entries of matrix, defining the unit cell" << endl; 139 cout << Verbose(0) << " k - Energy cutoff of plane wave basis in Hartree" << endl; 140 cout << Verbose(0) << " l - Maximum number of levels in multi-level-ansatz" << endl; 141 cout << Verbose(0) << " m - Factor by which grid nodes increase between standard and upper level" << endl; 142 cout << Verbose(0) << " n - 0: Don't use RiemannTensor, 1: Do" << endl; 143 cout << Verbose(0) << " o - Factor by which grid nodes increase between Riemann and standard(?) level" << endl; 144 cout << Verbose(0) << " p - Number of Riemann levels" << endl; 145 cout << Verbose(0) << " r - 0: Don't Use RiemannTensor, 1: Do" << endl; 146 cout << Verbose(0) << " s - 0: Doubly occupied orbitals, 1: Up-/Down-Orbitals" << endl; 147 cout << Verbose(0) << " t - Number of orbitals (depends pn SpinType)" << endl; 148 cout << Verbose(0) << " u - Number of SpinUp orbitals (depends on SpinType)" << endl; 149 cout << Verbose(0) << " v - Number of SpinDown orbitals (depends on SpinType)" << endl; 150 cout << Verbose(0) << " w - Number of additional, unoccupied orbitals" << endl; 151 cout << Verbose(0) << " x - radial cutoff for ewald summation in Bohrradii" << endl; 152 cout << Verbose(0) << " y - 0: Don't do structure optimization beforehand, 1: Do" << endl; 153 cout << Verbose(0) << " z - 0: Units are in Bohr radii, 1: units are in Aengstrom" << endl; 154 cout << Verbose(0) << " i - 0: Coordinates given in file are absolute, 1: ... are relative to unit cell" << endl; 155 cout << Verbose(0) << "=========================================================" << endl; 156 cout << Verbose(0) << "INPUT: "; 157 cin >> choice; 158 159 switch (choice) { 160 case 'A': // mainname 161 cout << Verbose(0) << "Old: " << config::mainname << "\t new: "; 162 cin >> config::mainname; 163 break; 164 case 'B': // defaultpath 165 cout << Verbose(0) << "Old: " << config::defaultpath << "\t new: "; 166 cin >> config::defaultpath; 167 break; 168 case 'C': // pseudopotpath 169 cout << Verbose(0) << "Old: " << config::pseudopotpath << "\t new: "; 170 cin >> config::pseudopotpath; 171 break; 172 173 case 'D': // ProcPEGamma 174 cout << Verbose(0) << "Old: " << config::ProcPEGamma << "\t new: "; 175 cin >> config::ProcPEGamma; 176 break; 177 case 'E': // ProcPEPsi 178 cout << Verbose(0) << "Old: " << config::ProcPEPsi << "\t new: "; 179 cin >> config::ProcPEPsi; 180 break; 181 case 'F': // DoOutVis 182 cout << Verbose(0) << "Old: " << config::DoOutVis << "\t new: "; 183 cin >> config::DoOutVis; 184 break; 185 case 'G': // DoOutMes 186 cout << Verbose(0) << "Old: " << config::DoOutMes << "\t new: "; 187 cin >> config::DoOutMes; 188 break; 189 case 'H': // DoOutOrbitals 190 cout << Verbose(0) << "Old: " << config::DoOutOrbitals << "\t new: "; 191 cin >> config::DoOutOrbitals; 192 break; 193 case 'I': // DoOutCurrent 194 cout << Verbose(0) << "Old: " << config::DoOutCurrent << "\t new: "; 195 cin >> config::DoOutCurrent; 196 break; 197 case 'J': // DoFullCurrent 198 cout << Verbose(0) << "Old: " << config::DoFullCurrent << "\t new: "; 199 cin >> config::DoFullCurrent; 200 break; 201 case 'K': // DoPerturbation 202 cout << Verbose(0) << "Old: " << config::DoPerturbation << "\t new: "; 203 cin >> config::DoPerturbation; 204 break; 205 case 'L': // CommonWannier 206 cout << Verbose(0) << "Old: " << config::CommonWannier << "\t new: "; 207 cin >> config::CommonWannier; 208 break; 209 case 'M': // SawtoothStart 210 cout << Verbose(0) << "Old: " << config::SawtoothStart << "\t new: "; 211 cin >> config::SawtoothStart; 212 break; 213 case 'N': // VectorPlane 214 cout << Verbose(0) << "Old: " << config::VectorPlane << "\t new: "; 215 cin >> config::VectorPlane; 216 break; 217 case 'O': // VectorCut 218 cout << Verbose(0) << "Old: " << config::VectorCut << "\t new: "; 219 cin >> config::VectorCut; 220 break; 221 case 'P': // UseAddGramSch 222 cout << Verbose(0) << "Old: " << config::UseAddGramSch << "\t new: "; 223 cin >> config::UseAddGramSch; 224 break; 225 case 'Q': // Seed 226 cout << Verbose(0) << "Old: " << config::Seed << "\t new: "; 227 cin >> config::Seed; 228 break; 229 230 case 'R': // MaxOuterStep 231 cout << Verbose(0) << "Old: " << config::MaxOuterStep << "\t new: "; 232 cin >> config::MaxOuterStep; 233 break; 234 case 'T': // OutVisStep 235 cout << Verbose(0) << "Old: " << config::OutVisStep << "\t new: "; 236 cin >> config::OutVisStep; 237 break; 238 case 'U': // OutSrcStep 239 cout << Verbose(0) << "Old: " << config::OutSrcStep << "\t new: "; 240 cin >> config::OutSrcStep; 241 break; 242 case 'X': // MaxPsiStep 243 cout << Verbose(0) << "Old: " << config::MaxPsiStep << "\t new: "; 244 cin >> config::MaxPsiStep; 245 break; 246 case 'Y': // EpsWannier 247 cout << Verbose(0) << "Old: " << config::EpsWannier << "\t new: "; 248 cin >> config::EpsWannier; 249 break; 250 251 case 'Z': // MaxMinStep 252 cout << Verbose(0) << "Old: " << config::MaxMinStep << "\t new: "; 253 cin >> config::MaxMinStep; 254 break; 255 case 'a': // RelEpsTotalEnergy 256 cout << Verbose(0) << "Old: " << config::RelEpsTotalEnergy << "\t new: "; 257 cin >> config::RelEpsTotalEnergy; 258 break; 259 case 'b': // RelEpsKineticEnergy 260 cout << Verbose(0) << "Old: " << config::RelEpsKineticEnergy << "\t new: "; 261 cin >> config::RelEpsKineticEnergy; 262 break; 263 case 'c': // MaxMinStopStep 264 cout << Verbose(0) << "Old: " << config::MaxMinStopStep << "\t new: "; 265 cin >> config::MaxMinStopStep; 266 break; 267 case 'e': // MaxInitMinStep 268 cout << Verbose(0) << "Old: " << config::MaxInitMinStep << "\t new: "; 269 cin >> config::MaxInitMinStep; 270 break; 271 case 'f': // InitRelEpsTotalEnergy 272 cout << Verbose(0) << "Old: " << config::InitRelEpsTotalEnergy << "\t new: "; 273 cin >> config::InitRelEpsTotalEnergy; 274 break; 275 case 'g': // InitRelEpsKineticEnergy 276 cout << Verbose(0) << "Old: " << config::InitRelEpsKineticEnergy << "\t new: "; 277 cin >> config::InitRelEpsKineticEnergy; 278 break; 279 case 'h': // InitMaxMinStopStep 280 cout << Verbose(0) << "Old: " << config::InitMaxMinStopStep << "\t new: "; 281 cin >> config::InitMaxMinStopStep; 282 break; 283 284 case 'j': // BoxLength 285 cout << Verbose(0) << "enter lower triadiagonalo form of basis matrix" << endl << endl; 286 for (int i=0;i<6;i++) { 287 cout << Verbose(0) << "Cell size" << i << ": "; 288 cin >> mol->cell_size[i]; 289 } 290 break; 291 292 case 'k': // ECut 293 cout << Verbose(0) << "Old: " << config::ECut << "\t new: "; 294 cin >> config::ECut; 295 break; 296 case 'l': // MaxLevel 297 cout << Verbose(0) << "Old: " << config::MaxLevel << "\t new: "; 298 cin >> config::MaxLevel; 299 break; 300 case 'm': // RiemannTensor 301 cout << Verbose(0) << "Old: " << config::RiemannTensor << "\t new: "; 302 cin >> config::RiemannTensor; 303 break; 304 case 'n': // LevRFactor 305 cout << Verbose(0) << "Old: " << config::LevRFactor << "\t new: "; 306 cin >> config::LevRFactor; 307 break; 308 case 'o': // RiemannLevel 309 cout << Verbose(0) << "Old: " << config::RiemannLevel << "\t new: "; 310 cin >> config::RiemannLevel; 311 break; 312 case 'p': // Lev0Factor 313 cout << Verbose(0) << "Old: " << config::Lev0Factor << "\t new: "; 314 cin >> config::Lev0Factor; 315 break; 316 case 'r': // RTActualUse 317 cout << Verbose(0) << "Old: " << config::RTActualUse << "\t new: "; 318 cin >> config::RTActualUse; 319 break; 320 case 's': // PsiType 321 cout << Verbose(0) << "Old: " << config::PsiType << "\t new: "; 322 cin >> config::PsiType; 323 break; 324 case 't': // MaxPsiDouble 325 cout << Verbose(0) << "Old: " << config::MaxPsiDouble << "\t new: "; 326 cin >> config::MaxPsiDouble; 327 break; 328 case 'u': // PsiMaxNoUp 329 cout << Verbose(0) << "Old: " << config::PsiMaxNoUp << "\t new: "; 330 cin >> config::PsiMaxNoUp; 331 break; 332 case 'v': // PsiMaxNoDown 333 cout << Verbose(0) << "Old: " << config::PsiMaxNoDown << "\t new: "; 334 cin >> config::PsiMaxNoDown; 335 break; 336 case 'w': // AddPsis 337 cout << Verbose(0) << "Old: " << config::AddPsis << "\t new: "; 338 cin >> config::AddPsis; 339 break; 340 341 case 'x': // RCut 342 cout << Verbose(0) << "Old: " << config::RCut << "\t new: "; 343 cin >> config::RCut; 344 break; 345 case 'y': // StructOpt 346 cout << Verbose(0) << "Old: " << config::StructOpt << "\t new: "; 347 cin >> config::StructOpt; 348 break; 349 case 'z': // IsAngstroem 350 cout << Verbose(0) << "Old: " << config::IsAngstroem << "\t new: "; 351 cin >> config::IsAngstroem; 352 break; 353 case 'i': // RelativeCoord 354 cout << Verbose(0) << "Old: " << config::RelativeCoord << "\t new: "; 355 cin >> config::RelativeCoord; 356 break; 357 }; 358 } while (choice != 'q'); 359 359 }; 360 360 … … 367 367 int config::TestSyntax(char *filename, periodentafel *periode, molecule *mol) 368 368 { 369 int test;370 ifstream file(filename);371 372 // search file for keyword: ProcPEGamma (new syntax)373 if (ParseForParameter(1,&file,"ProcPEGamma", 0, 1, 1, int_type, &test, 1, optional)) {374 file.close();375 return 1;376 }377 // search file for keyword: ProcsGammaPsi (old syntax)378 if (ParseForParameter(1,&file,"ProcsGammaPsi", 0, 1, 1, int_type, &test, 1, optional)) {379 file.close();380 return 0;381 }382 file.close();383 return -1;369 int test; 370 ifstream file(filename); 371 372 // search file for keyword: ProcPEGamma (new syntax) 373 if (ParseForParameter(1,&file,"ProcPEGamma", 0, 1, 1, int_type, &test, 1, optional)) { 374 file.close(); 375 return 1; 376 } 377 // search file for keyword: ProcsGammaPsi (old syntax) 378 if (ParseForParameter(1,&file,"ProcsGammaPsi", 0, 1, 1, int_type, &test, 1, optional)) { 379 file.close(); 380 return 0; 381 } 382 file.close(); 383 return -1; 384 384 } 385 385 … … 389 389 bool config::GetIsAngstroem() const 390 390 { 391 return (IsAngstroem == 1);391 return (IsAngstroem == 1); 392 392 }; 393 393 … … 397 397 char * config::GetDefaultPath() const 398 398 { 399 return defaultpath;399 return defaultpath; 400 400 }; 401 401 … … 406 406 void config::SetDefaultPath(const char *path) 407 407 { 408 strcpy(defaultpath, path);408 strcpy(defaultpath, path); 409 409 }; 410 410 … … 414 414 void config::RetrieveConfigPathAndName(string filename) 415 415 { 416 char *ptr = NULL;417 char *buffer = new char[MAXSTRINGSIZE];418 strncpy(buffer, filename.c_str(), MAXSTRINGSIZE);419 int last = -1;420 for(last=MAXSTRINGSIZE;last--;) {421 if (buffer[last] == '/')422 break;423 }424 if (last == -1) { // no path in front, set to local directory.425 strcpy(configpath, "./");426 ptr = buffer;427 } else {428 strncpy(configpath, buffer, last+1);429 ptr = &buffer[last+1];430 if (last < 254)431 configpath[last+1]='\0';432 }433 strcpy(configname, ptr);434 cout << "Found configpath: " << configpath << ", dir slash was found at " << last << ", config name is " << configname << "." << endl;435 delete[](buffer);416 char *ptr = NULL; 417 char *buffer = new char[MAXSTRINGSIZE]; 418 strncpy(buffer, filename.c_str(), MAXSTRINGSIZE); 419 int last = -1; 420 for(last=MAXSTRINGSIZE;last--;) { 421 if (buffer[last] == '/') 422 break; 423 } 424 if (last == -1) { // no path in front, set to local directory. 425 strcpy(configpath, "./"); 426 ptr = buffer; 427 } else { 428 strncpy(configpath, buffer, last+1); 429 ptr = &buffer[last+1]; 430 if (last < 254) 431 configpath[last+1]='\0'; 432 } 433 strcpy(configname, ptr); 434 cout << "Found configpath: " << configpath << ", dir slash was found at " << last << ", config name is " << configname << "." << endl; 435 delete[](buffer); 436 436 }; 437 437 … … 444 444 void config::Load(char *filename, periodentafel *periode, molecule *mol) 445 445 { 446 ifstream *file = new ifstream(filename);447 if (file == NULL) {448 cerr << "ERROR: config file " << filename << " missing!" << endl;449 return;450 }451 RetrieveConfigPathAndName(filename);452 // ParseParameters453 454 /* Oeffne Hauptparameterdatei */455 int di;456 double BoxLength[9];457 string zeile;458 string dummy;459 element *elementhash[MAX_ELEMENTS];460 char name[MAX_ELEMENTS];461 char keyword[MAX_ELEMENTS];462 int Z, No[MAX_ELEMENTS];463 int verbose = 0;464 double value[3];465 466 /* Namen einlesen */467 468 ParseForParameter(verbose,file, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical);469 ParseForParameter(verbose,file, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical);470 ParseForParameter(verbose,file, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical);471 ParseForParameter(verbose,file,"ProcPEGamma", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical);472 ParseForParameter(verbose,file,"ProcPEPsi", 0, 1, 1, int_type, &(config::ProcPEPsi), 1, critical);473 474 if (!ParseForParameter(verbose,file,"Seed", 0, 1, 1, int_type, &(config::Seed), 1, optional))475 config::Seed = 1;476 477 if(!ParseForParameter(verbose,file,"DoOutOrbitals", 0, 1, 1, int_type, &(config::DoOutOrbitals), 1, optional)) {478 config::DoOutOrbitals = 0;479 } else {480 if (config::DoOutOrbitals < 0) config::DoOutOrbitals = 0;481 if (config::DoOutOrbitals > 1) config::DoOutOrbitals = 1;482 }483 ParseForParameter(verbose,file,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical);484 if (config::DoOutVis < 0) config::DoOutVis = 0;485 if (config::DoOutVis > 1) config::DoOutVis = 1;486 if (!ParseForParameter(verbose,file,"VectorPlane", 0, 1, 1, int_type, &(config::VectorPlane), 1, optional))487 config::VectorPlane = -1;488 if (!ParseForParameter(verbose,file,"VectorCut", 0, 1, 1, double_type, &(config::VectorCut), 1, optional))489 config::VectorCut = 0.;490 ParseForParameter(verbose,file,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical);491 if (config::DoOutMes < 0) config::DoOutMes = 0;492 if (config::DoOutMes > 1) config::DoOutMes = 1;493 if (!ParseForParameter(verbose,file,"DoOutCurr", 0, 1, 1, int_type, &(config::DoOutCurrent), 1, optional))494 config::DoOutCurrent = 0;495 if (config::DoOutCurrent < 0) config::DoOutCurrent = 0;496 if (config::DoOutCurrent > 1) config::DoOutCurrent = 1;497 ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical);498 if (config::UseAddGramSch < 0) config::UseAddGramSch = 0;499 if (config::UseAddGramSch > 2) config::UseAddGramSch = 2;500 if(!ParseForParameter(verbose,file,"DoWannier", 0, 1, 1, int_type, &(config::DoWannier), 1, optional)) {501 config::DoWannier = 0;502 } else {503 if (config::DoWannier < 0) config::DoWannier = 0;504 if (config::DoWannier > 1) config::DoWannier = 1;505 }506 if(!ParseForParameter(verbose,file,"CommonWannier", 0, 1, 1, int_type, &(config::CommonWannier), 1, optional)) {507 config::CommonWannier = 0;508 } else {509 if (config::CommonWannier < 0) config::CommonWannier = 0;510 if (config::CommonWannier > 4) config::CommonWannier = 4;511 }512 if(!ParseForParameter(verbose,file,"SawtoothStart", 0, 1, 1, double_type, &(config::SawtoothStart), 1, optional)) {513 config::SawtoothStart = 0.01;514 } else {515 if (config::SawtoothStart < 0.) config::SawtoothStart = 0.;516 if (config::SawtoothStart > 1.) config::SawtoothStart = 1.;517 }518 519 ParseForParameter(verbose,file,"MaxOuterStep", 0, 1, 1, int_type, &(config::MaxOuterStep), 1, critical);520 if (!ParseForParameter(verbose,file,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional))521 config::Deltat = 1;522 ParseForParameter(verbose,file,"OutVisStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional);523 ParseForParameter(verbose,file,"OutSrcStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional);524 ParseForParameter(verbose,file,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional);525 //ParseForParameter(verbose,file,"Thermostat", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional);526 if (!ParseForParameter(verbose,file,"EpsWannier", 0, 1, 1, double_type, &(config::EpsWannier), 1, optional))527 config::EpsWannier = 1e-8;528 529 // stop conditions530 //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1;531 ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical);532 if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3;533 534 ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical);535 ParseForParameter(verbose,file,"RelEpsTotalE", 0, 1, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical);536 ParseForParameter(verbose,file,"RelEpsKineticE", 0, 1, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical);537 ParseForParameter(verbose,file,"MaxMinStopStep", 0, 1, 1, int_type, &(config::MaxMinStopStep), 1, critical);538 ParseForParameter(verbose,file,"MaxMinGapStopStep", 0, 1, 1, int_type, &(config::MaxMinGapStopStep), 1, critical);539 if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep;540 if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1;541 if (config::MaxMinGapStopStep < 1) config::MaxMinGapStopStep = 1;542 543 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical);544 ParseForParameter(verbose,file,"InitRelEpsTotalE", 0, 1, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical);545 ParseForParameter(verbose,file,"InitRelEpsKineticE", 0, 1, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical);546 ParseForParameter(verbose,file,"InitMaxMinStopStep", 0, 1, 1, int_type, &(config::InitMaxMinStopStep), 1, critical);547 ParseForParameter(verbose,file,"InitMaxMinGapStopStep", 0, 1, 1, int_type, &(config::InitMaxMinGapStopStep), 1, critical);548 if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep;549 if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1;550 if (config::InitMaxMinGapStopStep < 1) config::InitMaxMinGapStopStep = 1;551 552 // Unit cell and magnetic field553 ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */554 mol->cell_size[0] = BoxLength[0];555 mol->cell_size[1] = BoxLength[3];556 mol->cell_size[2] = BoxLength[4];557 mol->cell_size[3] = BoxLength[6];558 mol->cell_size[4] = BoxLength[7];559 mol->cell_size[5] = BoxLength[8];560 if (1) fprintf(stderr,"\n");561 562 ParseForParameter(verbose,file,"DoPerturbation", 0, 1, 1, int_type, &(config::DoPerturbation), 1, optional);563 ParseForParameter(verbose,file,"DoOutNICS", 0, 1, 1, int_type, &(config::DoOutNICS), 1, optional);564 if (!ParseForParameter(verbose,file,"DoFullCurrent", 0, 1, 1, int_type, &(config::DoFullCurrent), 1, optional))565 config::DoFullCurrent = 0;566 if (config::DoFullCurrent < 0) config::DoFullCurrent = 0;567 if (config::DoFullCurrent > 2) config::DoFullCurrent = 2;568 if (config::DoOutNICS < 0) config::DoOutNICS = 0;569 if (config::DoOutNICS > 2) config::DoOutNICS = 2;570 if (config::DoPerturbation == 0) {571 config::DoFullCurrent = 0;572 config::DoOutNICS = 0;573 }574 575 ParseForParameter(verbose,file,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical);576 ParseForParameter(verbose,file,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical);577 ParseForParameter(verbose,file,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical);578 if (config::Lev0Factor < 2) {579 config::Lev0Factor = 2;580 }581 ParseForParameter(verbose,file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical);582 if (di >= 0 && di < 2) {583 config::RiemannTensor = di;584 } else {585 fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT");586 exit(1);587 }588 switch (config::RiemannTensor) {589 case 0: //UseNoRT590 if (config::MaxLevel < 2) {591 config::MaxLevel = 2;592 }593 config::LevRFactor = 2;594 config::RTActualUse = 0;595 break;596 case 1: // UseRT597 if (config::MaxLevel < 3) {598 config::MaxLevel = 3;599 }600 ParseForParameter(verbose,file,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical);601 if (config::RiemannLevel < 2) {602 config::RiemannLevel = 2;603 }604 if (config::RiemannLevel > config::MaxLevel-1) {605 config::RiemannLevel = config::MaxLevel-1;606 }607 ParseForParameter(verbose,file,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical);608 if (config::LevRFactor < 2) {609 config::LevRFactor = 2;610 }611 config::Lev0Factor = 2;612 config::RTActualUse = 2;613 break;614 }615 ParseForParameter(verbose,file,"PsiType", 0, 1, 1, int_type, &di, 1, critical);616 if (di >= 0 && di < 2) {617 config::PsiType = di;618 } else {619 fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown");620 exit(1);621 }622 switch (config::PsiType) {623 case 0: // SpinDouble624 ParseForParameter(verbose,file,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical);625 ParseForParameter(verbose,file,"AddPsis", 0, 1, 1, int_type, &(config::AddPsis), 1, optional);626 break;627 case 1: // SpinUpDown628 if (config::ProcPEGamma % 2) config::ProcPEGamma*=2;629 ParseForParameter(verbose,file,"PsiMaxNoUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical);630 ParseForParameter(verbose,file,"PsiMaxNoDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical);631 ParseForParameter(verbose,file,"AddPsis", 0, 1, 1, int_type, &(config::AddPsis), 1, optional);632 break;633 }634 635 // IonsInitRead636 637 ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical);638 ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical);639 ParseForParameter(verbose,file,"MaxTypes", 0, 1, 1, int_type, &(config::MaxTypes), 1, critical);640 if (!ParseForParameter(verbose,file,"RelativeCoord", 0, 1, 1, int_type, &(config::RelativeCoord) , 1, optional))641 config::RelativeCoord = 0;642 if (!ParseForParameter(verbose,file,"StructOpt", 0, 1, 1, int_type, &(config::StructOpt), 1, optional))643 config::StructOpt = 0;644 if (MaxTypes == 0) {645 cerr << "There are no atoms according to MaxTypes in this config file." << endl;646 } else {647 // prescan number of ions per type648 cout << Verbose(0) << "Prescanning ions per type: " << endl;649 for (int i=0; i < config::MaxTypes; i++) {650 sprintf(name,"Ion_Type%i",i+1);651 ParseForParameter(verbose,file, (const char*)name, 0, 1, 1, int_type, &No[i], 1, critical);652 ParseForParameter(verbose,file, name, 0, 2, 1, int_type, &Z, 1, critical);653 elementhash[i] = periode->FindElement(Z);654 cout << Verbose(1) << i << ". Z = " << elementhash[i]->Z << " with " << No[i] << " ions." << endl;655 }656 int repetition = 0; // which repeated keyword shall be read657 658 map<int, atom *> AtomList[config::MaxTypes];659 if (!FastParsing) {660 // parse in trajectories661 bool status = true;662 atom *neues = NULL;663 while (status) {664 cout << "Currently parsing MD step " << repetition << "." << endl;665 for (int i=0; i < config::MaxTypes; i++) {666 sprintf(name,"Ion_Type%i",i+1);667 for(int j=0;j<No[i];j++) {668 sprintf(keyword,"%s_%i",name, j+1);669 if (repetition == 0) {670 neues = new atom();671 AtomList[i][j] = neues;672 neues->type = elementhash[i]; // find element type673 mol->AddAtom(neues);674 } else675 neues = AtomList[i][j];676 status = (status &&677 ParseForParameter(verbose,file, keyword, 0, 1, 1, double_type, &neues->x.x[0], 1, (repetition == 0) ? critical : optional) &&678 ParseForParameter(verbose,file, keyword, 0, 2, 1, double_type, &neues->x.x[1], 1, (repetition == 0) ? critical : optional) &&679 ParseForParameter(verbose,file, keyword, 0, 3, 1, double_type, &neues->x.x[2], 1, (repetition == 0) ? critical : optional) &&680 ParseForParameter(verbose,file, keyword, 0, 4, 1, int_type, &neues->FixedIon, 1, (repetition == 0) ? critical : optional));681 if (!status) break;682 683 // check size of vectors684 if (mol->Trajectories[neues].R.size() <= (unsigned int)(repetition)) {685 //cout << "Increasing size for trajectory array of " << keyword << " to " << (repetition+10) << "." << endl;686 mol->Trajectories[neues].R.resize(repetition+10);687 mol->Trajectories[neues].U.resize(repetition+10);688 mol->Trajectories[neues].F.resize(repetition+10);689 }690 691 // put into trajectories list692 for (int d=0;d<NDIM;d++)693 mol->Trajectories[neues].R.at(repetition).x[d] = neues->x.x[d];694 695 // parse velocities if present696 if(!ParseForParameter(verbose,file, keyword, 0, 5, 1, double_type, &neues->v.x[0], 1,optional))697 neues->v.x[0] = 0.;698 if(!ParseForParameter(verbose,file, keyword, 0, 6, 1, double_type, &neues->v.x[1], 1,optional))699 neues->v.x[1] = 0.;700 if(!ParseForParameter(verbose,file, keyword, 0, 7, 1, double_type, &neues->v.x[2], 1,optional))701 neues->v.x[2] = 0.;702 for (int d=0;d<NDIM;d++)703 mol->Trajectories[neues].U.at(repetition).x[d] = neues->v.x[d];704 705 // parse forces if present706 if(!ParseForParameter(verbose,file, keyword, 0, 8, 1, double_type, &value[0], 1,optional))707 value[0] = 0.;708 if(!ParseForParameter(verbose,file, keyword, 0, 9, 1, double_type, &value[1], 1,optional))709 value[1] = 0.;710 if(!ParseForParameter(verbose,file, keyword, 1, 10, 1, double_type, &value[2], 1,optional))711 value[2] = 0.;712 for (int d=0;d<NDIM;d++)713 mol->Trajectories[neues].F.at(repetition).x[d] = value[d];714 715 //cout << "Parsed position of step " << (repetition) << ": (";716 //for (int d=0;d<NDIM;d++)717 // cout << mol->Trajectories[neues].R.at(repetition).x[d] << " ";// next step718 //cout << ")\t(";719 //for (int d=0;d<NDIM;d++)720 // cout << mol->Trajectories[neues].U.at(repetition).x[d] << " ";// next step721 //cout << ")\t(";722 //for (int d=0;d<NDIM;d++)723 // cout << mol->Trajectories[neues].F.at(repetition).x[d] << " ";// next step724 //cout << ")" << endl;725 }726 }727 repetition++;728 }729 repetition--;730 cout << "Found " << repetition << " trajectory steps." << endl;731 mol->MDSteps = repetition;732 } else {733 // find the maximum number of MD steps so that we may parse last one (Ion_Type1_1 must always be present, because is the first atom)734 repetition = 0;735 while ( ParseForParameter(verbose,file, "Ion_Type1_1", 0, 1, 1, double_type, &value[0], repetition, (repetition == 0) ? critical : optional) &&736 ParseForParameter(verbose,file, "Ion_Type1_1", 0, 2, 1, double_type, &value[1], repetition, (repetition == 0) ? critical : optional) &&737 ParseForParameter(verbose,file, "Ion_Type1_1", 0, 3, 1, double_type, &value[2], repetition, (repetition == 0) ? critical : optional))738 repetition++;739 cout << "I found " << repetition << " times the keyword Ion_Type1_1." << endl;740 // parse in molecule coordinates741 for (int i=0; i < config::MaxTypes; i++) {742 sprintf(name,"Ion_Type%i",i+1);743 for(int j=0;j<No[i];j++) {744 sprintf(keyword,"%s_%i",name, j+1);745 atom *neues = new atom();746 // then parse for each atom the coordinates as often as present747 ParseForParameter(verbose,file, keyword, 0, 1, 1, double_type, &neues->x.x[0], repetition,critical);748 ParseForParameter(verbose,file, keyword, 0, 2, 1, double_type, &neues->x.x[1], repetition,critical);749 ParseForParameter(verbose,file, keyword, 0, 3, 1, double_type, &neues->x.x[2], repetition,critical);750 ParseForParameter(verbose,file, keyword, 0, 4, 1, int_type, &neues->FixedIon, repetition,critical);751 if(!ParseForParameter(verbose,file, keyword, 0, 5, 1, double_type, &neues->v.x[0], repetition,optional))752 neues->v.x[0] = 0.;753 if(!ParseForParameter(verbose,file, keyword, 0, 6, 1, double_type, &neues->v.x[1], repetition,optional))754 neues->v.x[1] = 0.;755 if(!ParseForParameter(verbose,file, keyword, 0, 7, 1, double_type, &neues->v.x[2], repetition,optional))756 neues->v.x[2] = 0.;757 // here we don't care if forces are present (last in trajectories is always equal to current position)758 neues->type = elementhash[i]; // find element type759 mol->AddAtom(neues);760 }761 }762 }763 }764 file->close();765 delete(file);446 ifstream *file = new ifstream(filename); 447 if (file == NULL) { 448 cerr << "ERROR: config file " << filename << " missing!" << endl; 449 return; 450 } 451 RetrieveConfigPathAndName(filename); 452 // ParseParameters 453 454 /* Oeffne Hauptparameterdatei */ 455 int di; 456 double BoxLength[9]; 457 string zeile; 458 string dummy; 459 element *elementhash[MAX_ELEMENTS]; 460 char name[MAX_ELEMENTS]; 461 char keyword[MAX_ELEMENTS]; 462 int Z, No[MAX_ELEMENTS]; 463 int verbose = 0; 464 double value[3]; 465 466 /* Namen einlesen */ 467 468 ParseForParameter(verbose,file, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical); 469 ParseForParameter(verbose,file, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical); 470 ParseForParameter(verbose,file, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical); 471 ParseForParameter(verbose,file,"ProcPEGamma", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical); 472 ParseForParameter(verbose,file,"ProcPEPsi", 0, 1, 1, int_type, &(config::ProcPEPsi), 1, critical); 473 474 if (!ParseForParameter(verbose,file,"Seed", 0, 1, 1, int_type, &(config::Seed), 1, optional)) 475 config::Seed = 1; 476 477 if(!ParseForParameter(verbose,file,"DoOutOrbitals", 0, 1, 1, int_type, &(config::DoOutOrbitals), 1, optional)) { 478 config::DoOutOrbitals = 0; 479 } else { 480 if (config::DoOutOrbitals < 0) config::DoOutOrbitals = 0; 481 if (config::DoOutOrbitals > 1) config::DoOutOrbitals = 1; 482 } 483 ParseForParameter(verbose,file,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical); 484 if (config::DoOutVis < 0) config::DoOutVis = 0; 485 if (config::DoOutVis > 1) config::DoOutVis = 1; 486 if (!ParseForParameter(verbose,file,"VectorPlane", 0, 1, 1, int_type, &(config::VectorPlane), 1, optional)) 487 config::VectorPlane = -1; 488 if (!ParseForParameter(verbose,file,"VectorCut", 0, 1, 1, double_type, &(config::VectorCut), 1, optional)) 489 config::VectorCut = 0.; 490 ParseForParameter(verbose,file,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical); 491 if (config::DoOutMes < 0) config::DoOutMes = 0; 492 if (config::DoOutMes > 1) config::DoOutMes = 1; 493 if (!ParseForParameter(verbose,file,"DoOutCurr", 0, 1, 1, int_type, &(config::DoOutCurrent), 1, optional)) 494 config::DoOutCurrent = 0; 495 if (config::DoOutCurrent < 0) config::DoOutCurrent = 0; 496 if (config::DoOutCurrent > 1) config::DoOutCurrent = 1; 497 ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical); 498 if (config::UseAddGramSch < 0) config::UseAddGramSch = 0; 499 if (config::UseAddGramSch > 2) config::UseAddGramSch = 2; 500 if(!ParseForParameter(verbose,file,"DoWannier", 0, 1, 1, int_type, &(config::DoWannier), 1, optional)) { 501 config::DoWannier = 0; 502 } else { 503 if (config::DoWannier < 0) config::DoWannier = 0; 504 if (config::DoWannier > 1) config::DoWannier = 1; 505 } 506 if(!ParseForParameter(verbose,file,"CommonWannier", 0, 1, 1, int_type, &(config::CommonWannier), 1, optional)) { 507 config::CommonWannier = 0; 508 } else { 509 if (config::CommonWannier < 0) config::CommonWannier = 0; 510 if (config::CommonWannier > 4) config::CommonWannier = 4; 511 } 512 if(!ParseForParameter(verbose,file,"SawtoothStart", 0, 1, 1, double_type, &(config::SawtoothStart), 1, optional)) { 513 config::SawtoothStart = 0.01; 514 } else { 515 if (config::SawtoothStart < 0.) config::SawtoothStart = 0.; 516 if (config::SawtoothStart > 1.) config::SawtoothStart = 1.; 517 } 518 519 ParseForParameter(verbose,file,"MaxOuterStep", 0, 1, 1, int_type, &(config::MaxOuterStep), 1, critical); 520 if (!ParseForParameter(verbose,file,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional)) 521 config::Deltat = 1; 522 ParseForParameter(verbose,file,"OutVisStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional); 523 ParseForParameter(verbose,file,"OutSrcStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional); 524 ParseForParameter(verbose,file,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional); 525 //ParseForParameter(verbose,file,"Thermostat", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional); 526 if (!ParseForParameter(verbose,file,"EpsWannier", 0, 1, 1, double_type, &(config::EpsWannier), 1, optional)) 527 config::EpsWannier = 1e-8; 528 529 // stop conditions 530 //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1; 531 ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical); 532 if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3; 533 534 ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical); 535 ParseForParameter(verbose,file,"RelEpsTotalE", 0, 1, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical); 536 ParseForParameter(verbose,file,"RelEpsKineticE", 0, 1, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical); 537 ParseForParameter(verbose,file,"MaxMinStopStep", 0, 1, 1, int_type, &(config::MaxMinStopStep), 1, critical); 538 ParseForParameter(verbose,file,"MaxMinGapStopStep", 0, 1, 1, int_type, &(config::MaxMinGapStopStep), 1, critical); 539 if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep; 540 if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1; 541 if (config::MaxMinGapStopStep < 1) config::MaxMinGapStopStep = 1; 542 543 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical); 544 ParseForParameter(verbose,file,"InitRelEpsTotalE", 0, 1, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical); 545 ParseForParameter(verbose,file,"InitRelEpsKineticE", 0, 1, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical); 546 ParseForParameter(verbose,file,"InitMaxMinStopStep", 0, 1, 1, int_type, &(config::InitMaxMinStopStep), 1, critical); 547 ParseForParameter(verbose,file,"InitMaxMinGapStopStep", 0, 1, 1, int_type, &(config::InitMaxMinGapStopStep), 1, critical); 548 if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep; 549 if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1; 550 if (config::InitMaxMinGapStopStep < 1) config::InitMaxMinGapStopStep = 1; 551 552 // Unit cell and magnetic field 553 ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */ 554 mol->cell_size[0] = BoxLength[0]; 555 mol->cell_size[1] = BoxLength[3]; 556 mol->cell_size[2] = BoxLength[4]; 557 mol->cell_size[3] = BoxLength[6]; 558 mol->cell_size[4] = BoxLength[7]; 559 mol->cell_size[5] = BoxLength[8]; 560 if (1) fprintf(stderr,"\n"); 561 562 ParseForParameter(verbose,file,"DoPerturbation", 0, 1, 1, int_type, &(config::DoPerturbation), 1, optional); 563 ParseForParameter(verbose,file,"DoOutNICS", 0, 1, 1, int_type, &(config::DoOutNICS), 1, optional); 564 if (!ParseForParameter(verbose,file,"DoFullCurrent", 0, 1, 1, int_type, &(config::DoFullCurrent), 1, optional)) 565 config::DoFullCurrent = 0; 566 if (config::DoFullCurrent < 0) config::DoFullCurrent = 0; 567 if (config::DoFullCurrent > 2) config::DoFullCurrent = 2; 568 if (config::DoOutNICS < 0) config::DoOutNICS = 0; 569 if (config::DoOutNICS > 2) config::DoOutNICS = 2; 570 if (config::DoPerturbation == 0) { 571 config::DoFullCurrent = 0; 572 config::DoOutNICS = 0; 573 } 574 575 ParseForParameter(verbose,file,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical); 576 ParseForParameter(verbose,file,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical); 577 ParseForParameter(verbose,file,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical); 578 if (config::Lev0Factor < 2) { 579 config::Lev0Factor = 2; 580 } 581 ParseForParameter(verbose,file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical); 582 if (di >= 0 && di < 2) { 583 config::RiemannTensor = di; 584 } else { 585 fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT"); 586 exit(1); 587 } 588 switch (config::RiemannTensor) { 589 case 0: //UseNoRT 590 if (config::MaxLevel < 2) { 591 config::MaxLevel = 2; 592 } 593 config::LevRFactor = 2; 594 config::RTActualUse = 0; 595 break; 596 case 1: // UseRT 597 if (config::MaxLevel < 3) { 598 config::MaxLevel = 3; 599 } 600 ParseForParameter(verbose,file,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical); 601 if (config::RiemannLevel < 2) { 602 config::RiemannLevel = 2; 603 } 604 if (config::RiemannLevel > config::MaxLevel-1) { 605 config::RiemannLevel = config::MaxLevel-1; 606 } 607 ParseForParameter(verbose,file,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical); 608 if (config::LevRFactor < 2) { 609 config::LevRFactor = 2; 610 } 611 config::Lev0Factor = 2; 612 config::RTActualUse = 2; 613 break; 614 } 615 ParseForParameter(verbose,file,"PsiType", 0, 1, 1, int_type, &di, 1, critical); 616 if (di >= 0 && di < 2) { 617 config::PsiType = di; 618 } else { 619 fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown"); 620 exit(1); 621 } 622 switch (config::PsiType) { 623 case 0: // SpinDouble 624 ParseForParameter(verbose,file,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical); 625 ParseForParameter(verbose,file,"AddPsis", 0, 1, 1, int_type, &(config::AddPsis), 1, optional); 626 break; 627 case 1: // SpinUpDown 628 if (config::ProcPEGamma % 2) config::ProcPEGamma*=2; 629 ParseForParameter(verbose,file,"PsiMaxNoUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical); 630 ParseForParameter(verbose,file,"PsiMaxNoDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical); 631 ParseForParameter(verbose,file,"AddPsis", 0, 1, 1, int_type, &(config::AddPsis), 1, optional); 632 break; 633 } 634 635 // IonsInitRead 636 637 ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical); 638 ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical); 639 ParseForParameter(verbose,file,"MaxTypes", 0, 1, 1, int_type, &(config::MaxTypes), 1, critical); 640 if (!ParseForParameter(verbose,file,"RelativeCoord", 0, 1, 1, int_type, &(config::RelativeCoord) , 1, optional)) 641 config::RelativeCoord = 0; 642 if (!ParseForParameter(verbose,file,"StructOpt", 0, 1, 1, int_type, &(config::StructOpt), 1, optional)) 643 config::StructOpt = 0; 644 if (MaxTypes == 0) { 645 cerr << "There are no atoms according to MaxTypes in this config file." << endl; 646 } else { 647 // prescan number of ions per type 648 cout << Verbose(0) << "Prescanning ions per type: " << endl; 649 for (int i=0; i < config::MaxTypes; i++) { 650 sprintf(name,"Ion_Type%i",i+1); 651 ParseForParameter(verbose,file, (const char*)name, 0, 1, 1, int_type, &No[i], 1, critical); 652 ParseForParameter(verbose,file, name, 0, 2, 1, int_type, &Z, 1, critical); 653 elementhash[i] = periode->FindElement(Z); 654 cout << Verbose(1) << i << ". Z = " << elementhash[i]->Z << " with " << No[i] << " ions." << endl; 655 } 656 int repetition = 0; // which repeated keyword shall be read 657 658 map<int, atom *> AtomList[config::MaxTypes]; 659 if (!FastParsing) { 660 // parse in trajectories 661 bool status = true; 662 atom *neues = NULL; 663 while (status) { 664 cout << "Currently parsing MD step " << repetition << "." << endl; 665 for (int i=0; i < config::MaxTypes; i++) { 666 sprintf(name,"Ion_Type%i",i+1); 667 for(int j=0;j<No[i];j++) { 668 sprintf(keyword,"%s_%i",name, j+1); 669 if (repetition == 0) { 670 neues = new atom(); 671 AtomList[i][j] = neues; 672 neues->type = elementhash[i]; // find element type 673 mol->AddAtom(neues); 674 } else 675 neues = AtomList[i][j]; 676 status = (status && 677 ParseForParameter(verbose,file, keyword, 0, 1, 1, double_type, &neues->x.x[0], 1, (repetition == 0) ? critical : optional) && 678 ParseForParameter(verbose,file, keyword, 0, 2, 1, double_type, &neues->x.x[1], 1, (repetition == 0) ? critical : optional) && 679 ParseForParameter(verbose,file, keyword, 0, 3, 1, double_type, &neues->x.x[2], 1, (repetition == 0) ? critical : optional) && 680 ParseForParameter(verbose,file, keyword, 0, 4, 1, int_type, &neues->FixedIon, 1, (repetition == 0) ? critical : optional)); 681 if (!status) break; 682 683 // check size of vectors 684 if (mol->Trajectories[neues].R.size() <= (unsigned int)(repetition)) { 685 //cout << "Increasing size for trajectory array of " << keyword << " to " << (repetition+10) << "." << endl; 686 mol->Trajectories[neues].R.resize(repetition+10); 687 mol->Trajectories[neues].U.resize(repetition+10); 688 mol->Trajectories[neues].F.resize(repetition+10); 689 } 690 691 // put into trajectories list 692 for (int d=0;d<NDIM;d++) 693 mol->Trajectories[neues].R.at(repetition).x[d] = neues->x.x[d]; 694 695 // parse velocities if present 696 if(!ParseForParameter(verbose,file, keyword, 0, 5, 1, double_type, &neues->v.x[0], 1,optional)) 697 neues->v.x[0] = 0.; 698 if(!ParseForParameter(verbose,file, keyword, 0, 6, 1, double_type, &neues->v.x[1], 1,optional)) 699 neues->v.x[1] = 0.; 700 if(!ParseForParameter(verbose,file, keyword, 0, 7, 1, double_type, &neues->v.x[2], 1,optional)) 701 neues->v.x[2] = 0.; 702 for (int d=0;d<NDIM;d++) 703 mol->Trajectories[neues].U.at(repetition).x[d] = neues->v.x[d]; 704 705 // parse forces if present 706 if(!ParseForParameter(verbose,file, keyword, 0, 8, 1, double_type, &value[0], 1,optional)) 707 value[0] = 0.; 708 if(!ParseForParameter(verbose,file, keyword, 0, 9, 1, double_type, &value[1], 1,optional)) 709 value[1] = 0.; 710 if(!ParseForParameter(verbose,file, keyword, 1, 10, 1, double_type, &value[2], 1,optional)) 711 value[2] = 0.; 712 for (int d=0;d<NDIM;d++) 713 mol->Trajectories[neues].F.at(repetition).x[d] = value[d]; 714 715 // cout << "Parsed position of step " << (repetition) << ": ("; 716 // for (int d=0;d<NDIM;d++) 717 // cout << mol->Trajectories[neues].R.at(repetition).x[d] << " "; // next step 718 // cout << ")\t("; 719 // for (int d=0;d<NDIM;d++) 720 // cout << mol->Trajectories[neues].U.at(repetition).x[d] << " "; // next step 721 // cout << ")\t("; 722 // for (int d=0;d<NDIM;d++) 723 // cout << mol->Trajectories[neues].F.at(repetition).x[d] << " "; // next step 724 // cout << ")" << endl; 725 } 726 } 727 repetition++; 728 } 729 repetition--; 730 cout << "Found " << repetition << " trajectory steps." << endl; 731 mol->MDSteps = repetition; 732 } else { 733 // find the maximum number of MD steps so that we may parse last one (Ion_Type1_1 must always be present, because is the first atom) 734 repetition = 0; 735 while ( ParseForParameter(verbose,file, "Ion_Type1_1", 0, 1, 1, double_type, &value[0], repetition, (repetition == 0) ? critical : optional) && 736 ParseForParameter(verbose,file, "Ion_Type1_1", 0, 2, 1, double_type, &value[1], repetition, (repetition == 0) ? critical : optional) && 737 ParseForParameter(verbose,file, "Ion_Type1_1", 0, 3, 1, double_type, &value[2], repetition, (repetition == 0) ? critical : optional)) 738 repetition++; 739 cout << "I found " << repetition << " times the keyword Ion_Type1_1." << endl; 740 // parse in molecule coordinates 741 for (int i=0; i < config::MaxTypes; i++) { 742 sprintf(name,"Ion_Type%i",i+1); 743 for(int j=0;j<No[i];j++) { 744 sprintf(keyword,"%s_%i",name, j+1); 745 atom *neues = new atom(); 746 // then parse for each atom the coordinates as often as present 747 ParseForParameter(verbose,file, keyword, 0, 1, 1, double_type, &neues->x.x[0], repetition,critical); 748 ParseForParameter(verbose,file, keyword, 0, 2, 1, double_type, &neues->x.x[1], repetition,critical); 749 ParseForParameter(verbose,file, keyword, 0, 3, 1, double_type, &neues->x.x[2], repetition,critical); 750 ParseForParameter(verbose,file, keyword, 0, 4, 1, int_type, &neues->FixedIon, repetition,critical); 751 if(!ParseForParameter(verbose,file, keyword, 0, 5, 1, double_type, &neues->v.x[0], repetition,optional)) 752 neues->v.x[0] = 0.; 753 if(!ParseForParameter(verbose,file, keyword, 0, 6, 1, double_type, &neues->v.x[1], repetition,optional)) 754 neues->v.x[1] = 0.; 755 if(!ParseForParameter(verbose,file, keyword, 0, 7, 1, double_type, &neues->v.x[2], repetition,optional)) 756 neues->v.x[2] = 0.; 757 // here we don't care if forces are present (last in trajectories is always equal to current position) 758 neues->type = elementhash[i]; // find element type 759 mol->AddAtom(neues); 760 } 761 } 762 } 763 } 764 file->close(); 765 delete(file); 766 766 }; 767 767 … … 773 773 void config::LoadOld(char *filename, periodentafel *periode, molecule *mol) 774 774 { 775 ifstream *file = new ifstream(filename);776 if (file == NULL) {777 cerr << "ERROR: config file " << filename << " missing!" << endl;778 return;779 }780 RetrieveConfigPathAndName(filename);781 // ParseParameters782 783 /* Oeffne Hauptparameterdatei */784 int l, i, di;785 double a,b;786 double BoxLength[9];787 string zeile;788 string dummy;789 element *elementhash[128];790 int Z, No, AtomNo, found;791 int verbose = 0;792 793 /* Namen einlesen */794 795 ParseForParameter(verbose,file, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical);796 ParseForParameter(verbose,file, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical);797 ParseForParameter(verbose,file, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical);798 ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical);799 ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 2, 1, int_type, &(config::ProcPEPsi), 1, critical);800 config::Seed = 1;801 config::DoOutOrbitals = 0;802 ParseForParameter(verbose,file,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical);803 if (config::DoOutVis < 0) config::DoOutVis = 0;804 if (config::DoOutVis > 1) config::DoOutVis = 1;805 config::VectorPlane = -1;806 config::VectorCut = 0.;807 ParseForParameter(verbose,file,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical);808 if (config::DoOutMes < 0) config::DoOutMes = 0;809 if (config::DoOutMes > 1) config::DoOutMes = 1;810 config::DoOutCurrent = 0;811 ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical);812 if (config::UseAddGramSch < 0) config::UseAddGramSch = 0;813 if (config::UseAddGramSch > 2) config::UseAddGramSch = 2;814 config::CommonWannier = 0;815 config::SawtoothStart = 0.01;816 817 ParseForParameter(verbose,file,"MaxOuterStep", 0, 1, 1, double_type, &(config::MaxOuterStep), 1, critical);818 ParseForParameter(verbose,file,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional);819 ParseForParameter(verbose,file,"VisOuterStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional);820 ParseForParameter(verbose,file,"VisSrcOuterStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional);821 ParseForParameter(verbose,file,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional);822 ParseForParameter(verbose,file,"ScaleTempStep", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional);823 config::EpsWannier = 1e-8;824 825 // stop conditions826 //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1;827 ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical);828 if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3;829 830 ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical);831 ParseForParameter(verbose,file,"MaxMinStep", 0, 2, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical);832 ParseForParameter(verbose,file,"MaxMinStep", 0, 3, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical);833 ParseForParameter(verbose,file,"MaxMinStep", 0, 4, 1, int_type, &(config::MaxMinStopStep), 1, critical);834 if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep;835 if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1;836 config::MaxMinGapStopStep = 1;837 838 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical);839 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 2, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical);840 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 3, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical);841 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 4, 1, int_type, &(config::InitMaxMinStopStep), 1, critical);842 if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep;843 if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1;844 config::InitMaxMinGapStopStep = 1;845 846 ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */847 mol->cell_size[0] = BoxLength[0];848 mol->cell_size[1] = BoxLength[3];849 mol->cell_size[2] = BoxLength[4];850 mol->cell_size[3] = BoxLength[6];851 mol->cell_size[4] = BoxLength[7];852 mol->cell_size[5] = BoxLength[8];853 if (1) fprintf(stderr,"\n");854 config::DoPerturbation = 0;855 config::DoFullCurrent = 0;856 857 ParseForParameter(verbose,file,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical);858 ParseForParameter(verbose,file,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical);859 ParseForParameter(verbose,file,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical);860 if (config::Lev0Factor < 2) {861 config::Lev0Factor = 2;862 }863 ParseForParameter(verbose,file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical);864 if (di >= 0 && di < 2) {865 config::RiemannTensor = di;866 } else {867 fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT");868 exit(1);869 }870 switch (config::RiemannTensor) {871 case 0: //UseNoRT872 if (config::MaxLevel < 2) {873 config::MaxLevel = 2;874 }875 config::LevRFactor = 2;876 config::RTActualUse = 0;877 break;878 case 1: // UseRT879 if (config::MaxLevel < 3) {880 config::MaxLevel = 3;881 }882 ParseForParameter(verbose,file,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical);883 if (config::RiemannLevel < 2) {884 config::RiemannLevel = 2;885 }886 if (config::RiemannLevel > config::MaxLevel-1) {887 config::RiemannLevel = config::MaxLevel-1;888 }889 ParseForParameter(verbose,file,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical);890 if (config::LevRFactor < 2) {891 config::LevRFactor = 2;892 }893 config::Lev0Factor = 2;894 config::RTActualUse = 2;895 break;896 }897 ParseForParameter(verbose,file,"PsiType", 0, 1, 1, int_type, &di, 1, critical);898 if (di >= 0 && di < 2) {899 config::PsiType = di;900 } else {901 fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown");902 exit(1);903 }904 switch (config::PsiType) {905 case 0: // SpinDouble906 ParseForParameter(verbose,file,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical);907 config::AddPsis = 0;908 break;909 case 1: // SpinUpDown910 if (config::ProcPEGamma % 2) config::ProcPEGamma*=2;911 ParseForParameter(verbose,file,"MaxPsiUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical);912 ParseForParameter(verbose,file,"MaxPsiDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical);913 config::AddPsis = 0;914 break;915 }916 917 // IonsInitRead918 919 ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical);920 ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical);921 config::RelativeCoord = 0;922 config::StructOpt = 0;923 924 // Routine from builder.cpp925 926 927 for (i=MAX_ELEMENTS;i--;)928 elementhash[i] = NULL;929 cout << Verbose(0) << "Parsing Ions ..." << endl;930 No=0;931 found = 0;932 while (getline(*file,zeile,'\n')) {933 if (zeile.find("Ions_Data") == 0) {934 cout << Verbose(1) << "found Ions_Data...begin parsing" << endl;935 found ++;936 }937 if (found > 0) {938 if (zeile.find("Ions_Data") == 0)939 getline(*file,zeile,'\n'); // read next line and parse this one940 istringstream input(zeile);941 input >> AtomNo;// number of atoms942 input >> Z;// atomic number943 input >> a;944 input >> l;945 input >> l;946 input >> b;// element mass947 elementhash[No] = periode->FindElement(Z);948 cout << Verbose(1) << "AtomNo: " << AtomNo << "\tZ: " << Z << "\ta:" << a << "\tl:"<< l << "\b:" << b << "\tElement:" << elementhash[No] << "\t:" << endl;949 for(i=0;i<AtomNo;i++) {950 if (!getline(*file,zeile,'\n')) {// parse on and on951 cout << Verbose(2) << "Error: Too few items in ionic list of element" << elementhash[No] << "." << endl << "Exiting." << endl;952 // return 1;953 } else {954 //cout << Verbose(2) << "Reading line: " << zeile << endl;955 }956 istringstream input2(zeile);957 atom *neues = new atom();958 input2 >> neues->x.x[0]; // x959 input2 >> neues->x.x[1]; // y960 input2 >> neues->x.x[2]; // z961 input2 >> l;962 neues->type = elementhash[No]; // find element type963 mol->AddAtom(neues);964 }965 No++;966 }967 }968 file->close();969 delete(file);775 ifstream *file = new ifstream(filename); 776 if (file == NULL) { 777 cerr << "ERROR: config file " << filename << " missing!" << endl; 778 return; 779 } 780 RetrieveConfigPathAndName(filename); 781 // ParseParameters 782 783 /* Oeffne Hauptparameterdatei */ 784 int l, i, di; 785 double a,b; 786 double BoxLength[9]; 787 string zeile; 788 string dummy; 789 element *elementhash[128]; 790 int Z, No, AtomNo, found; 791 int verbose = 0; 792 793 /* Namen einlesen */ 794 795 ParseForParameter(verbose,file, "mainname", 0, 1, 1, string_type, (config::mainname), 1, critical); 796 ParseForParameter(verbose,file, "defaultpath", 0, 1, 1, string_type, (config::defaultpath), 1, critical); 797 ParseForParameter(verbose,file, "pseudopotpath", 0, 1, 1, string_type, (config::pseudopotpath), 1, critical); 798 ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 1, 1, int_type, &(config::ProcPEGamma), 1, critical); 799 ParseForParameter(verbose,file, "ProcsGammaPsi", 0, 2, 1, int_type, &(config::ProcPEPsi), 1, critical); 800 config::Seed = 1; 801 config::DoOutOrbitals = 0; 802 ParseForParameter(verbose,file,"DoOutVis", 0, 1, 1, int_type, &(config::DoOutVis), 1, critical); 803 if (config::DoOutVis < 0) config::DoOutVis = 0; 804 if (config::DoOutVis > 1) config::DoOutVis = 1; 805 config::VectorPlane = -1; 806 config::VectorCut = 0.; 807 ParseForParameter(verbose,file,"DoOutMes", 0, 1, 1, int_type, &(config::DoOutMes), 1, critical); 808 if (config::DoOutMes < 0) config::DoOutMes = 0; 809 if (config::DoOutMes > 1) config::DoOutMes = 1; 810 config::DoOutCurrent = 0; 811 ParseForParameter(verbose,file,"AddGramSch", 0, 1, 1, int_type, &(config::UseAddGramSch), 1, critical); 812 if (config::UseAddGramSch < 0) config::UseAddGramSch = 0; 813 if (config::UseAddGramSch > 2) config::UseAddGramSch = 2; 814 config::CommonWannier = 0; 815 config::SawtoothStart = 0.01; 816 817 ParseForParameter(verbose,file,"MaxOuterStep", 0, 1, 1, double_type, &(config::MaxOuterStep), 1, critical); 818 ParseForParameter(verbose,file,"Deltat", 0, 1, 1, double_type, &(config::Deltat), 1, optional); 819 ParseForParameter(verbose,file,"VisOuterStep", 0, 1, 1, int_type, &(config::OutVisStep), 1, optional); 820 ParseForParameter(verbose,file,"VisSrcOuterStep", 0, 1, 1, int_type, &(config::OutSrcStep), 1, optional); 821 ParseForParameter(verbose,file,"TargetTemp", 0, 1, 1, double_type, &(config::TargetTemp), 1, optional); 822 ParseForParameter(verbose,file,"ScaleTempStep", 0, 1, 1, int_type, &(config::ScaleTempStep), 1, optional); 823 config::EpsWannier = 1e-8; 824 825 // stop conditions 826 //if (config::MaxOuterStep <= 0) config::MaxOuterStep = 1; 827 ParseForParameter(verbose,file,"MaxPsiStep", 0, 1, 1, int_type, &(config::MaxPsiStep), 1, critical); 828 if (config::MaxPsiStep <= 0) config::MaxPsiStep = 3; 829 830 ParseForParameter(verbose,file,"MaxMinStep", 0, 1, 1, int_type, &(config::MaxMinStep), 1, critical); 831 ParseForParameter(verbose,file,"MaxMinStep", 0, 2, 1, double_type, &(config::RelEpsTotalEnergy), 1, critical); 832 ParseForParameter(verbose,file,"MaxMinStep", 0, 3, 1, double_type, &(config::RelEpsKineticEnergy), 1, critical); 833 ParseForParameter(verbose,file,"MaxMinStep", 0, 4, 1, int_type, &(config::MaxMinStopStep), 1, critical); 834 if (config::MaxMinStep <= 0) config::MaxMinStep = config::MaxPsiStep; 835 if (config::MaxMinStopStep < 1) config::MaxMinStopStep = 1; 836 config::MaxMinGapStopStep = 1; 837 838 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 1, 1, int_type, &(config::MaxInitMinStep), 1, critical); 839 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 2, 1, double_type, &(config::InitRelEpsTotalEnergy), 1, critical); 840 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 3, 1, double_type, &(config::InitRelEpsKineticEnergy), 1, critical); 841 ParseForParameter(verbose,file,"MaxInitMinStep", 0, 4, 1, int_type, &(config::InitMaxMinStopStep), 1, critical); 842 if (config::MaxInitMinStep <= 0) config::MaxInitMinStep = config::MaxPsiStep; 843 if (config::InitMaxMinStopStep < 1) config::InitMaxMinStopStep = 1; 844 config::InitMaxMinGapStopStep = 1; 845 846 ParseForParameter(verbose,file, "BoxLength", 0, 3, 3, lower_trigrid, BoxLength, 1, critical); /* Lattice->RealBasis */ 847 mol->cell_size[0] = BoxLength[0]; 848 mol->cell_size[1] = BoxLength[3]; 849 mol->cell_size[2] = BoxLength[4]; 850 mol->cell_size[3] = BoxLength[6]; 851 mol->cell_size[4] = BoxLength[7]; 852 mol->cell_size[5] = BoxLength[8]; 853 if (1) fprintf(stderr,"\n"); 854 config::DoPerturbation = 0; 855 config::DoFullCurrent = 0; 856 857 ParseForParameter(verbose,file,"ECut", 0, 1, 1, double_type, &(config::ECut), 1, critical); 858 ParseForParameter(verbose,file,"MaxLevel", 0, 1, 1, int_type, &(config::MaxLevel), 1, critical); 859 ParseForParameter(verbose,file,"Level0Factor", 0, 1, 1, int_type, &(config::Lev0Factor), 1, critical); 860 if (config::Lev0Factor < 2) { 861 config::Lev0Factor = 2; 862 } 863 ParseForParameter(verbose,file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical); 864 if (di >= 0 && di < 2) { 865 config::RiemannTensor = di; 866 } else { 867 fprintf(stderr, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT"); 868 exit(1); 869 } 870 switch (config::RiemannTensor) { 871 case 0: //UseNoRT 872 if (config::MaxLevel < 2) { 873 config::MaxLevel = 2; 874 } 875 config::LevRFactor = 2; 876 config::RTActualUse = 0; 877 break; 878 case 1: // UseRT 879 if (config::MaxLevel < 3) { 880 config::MaxLevel = 3; 881 } 882 ParseForParameter(verbose,file,"RiemannLevel", 0, 1, 1, int_type, &(config::RiemannLevel), 1, critical); 883 if (config::RiemannLevel < 2) { 884 config::RiemannLevel = 2; 885 } 886 if (config::RiemannLevel > config::MaxLevel-1) { 887 config::RiemannLevel = config::MaxLevel-1; 888 } 889 ParseForParameter(verbose,file,"LevRFactor", 0, 1, 1, int_type, &(config::LevRFactor), 1, critical); 890 if (config::LevRFactor < 2) { 891 config::LevRFactor = 2; 892 } 893 config::Lev0Factor = 2; 894 config::RTActualUse = 2; 895 break; 896 } 897 ParseForParameter(verbose,file,"PsiType", 0, 1, 1, int_type, &di, 1, critical); 898 if (di >= 0 && di < 2) { 899 config::PsiType = di; 900 } else { 901 fprintf(stderr, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown"); 902 exit(1); 903 } 904 switch (config::PsiType) { 905 case 0: // SpinDouble 906 ParseForParameter(verbose,file,"MaxPsiDouble", 0, 1, 1, int_type, &(config::MaxPsiDouble), 1, critical); 907 config::AddPsis = 0; 908 break; 909 case 1: // SpinUpDown 910 if (config::ProcPEGamma % 2) config::ProcPEGamma*=2; 911 ParseForParameter(verbose,file,"MaxPsiUp", 0, 1, 1, int_type, &(config::PsiMaxNoUp), 1, critical); 912 ParseForParameter(verbose,file,"MaxPsiDown", 0, 1, 1, int_type, &(config::PsiMaxNoDown), 1, critical); 913 config::AddPsis = 0; 914 break; 915 } 916 917 // IonsInitRead 918 919 ParseForParameter(verbose,file,"RCut", 0, 1, 1, double_type, &(config::RCut), 1, critical); 920 ParseForParameter(verbose,file,"IsAngstroem", 0, 1, 1, int_type, &(config::IsAngstroem), 1, critical); 921 config::RelativeCoord = 0; 922 config::StructOpt = 0; 923 924 // Routine from builder.cpp 925 926 927 for (i=MAX_ELEMENTS;i--;) 928 elementhash[i] = NULL; 929 cout << Verbose(0) << "Parsing Ions ..." << endl; 930 No=0; 931 found = 0; 932 while (getline(*file,zeile,'\n')) { 933 if (zeile.find("Ions_Data") == 0) { 934 cout << Verbose(1) << "found Ions_Data...begin parsing" << endl; 935 found ++; 936 } 937 if (found > 0) { 938 if (zeile.find("Ions_Data") == 0) 939 getline(*file,zeile,'\n'); // read next line and parse this one 940 istringstream input(zeile); 941 input >> AtomNo; // number of atoms 942 input >> Z; // atomic number 943 input >> a; 944 input >> l; 945 input >> l; 946 input >> b; // element mass 947 elementhash[No] = periode->FindElement(Z); 948 cout << Verbose(1) << "AtomNo: " << AtomNo << "\tZ: " << Z << "\ta:" << a << "\tl:" << l << "\b:" << b << "\tElement:" << elementhash[No] << "\t:" << endl; 949 for(i=0;i<AtomNo;i++) { 950 if (!getline(*file,zeile,'\n')) {// parse on and on 951 cout << Verbose(2) << "Error: Too few items in ionic list of element" << elementhash[No] << "." << endl << "Exiting." << endl; 952 // return 1; 953 } else { 954 //cout << Verbose(2) << "Reading line: " << zeile << endl; 955 } 956 istringstream input2(zeile); 957 atom *neues = new atom(); 958 input2 >> neues->x.x[0]; // x 959 input2 >> neues->x.x[1]; // y 960 input2 >> neues->x.x[2]; // z 961 input2 >> l; 962 neues->type = elementhash[No]; // find element type 963 mol->AddAtom(neues); 964 } 965 No++; 966 } 967 } 968 file->close(); 969 delete(file); 970 970 }; 971 971 … … 977 977 bool config::Save(const char *filename, periodentafel *periode, molecule *mol) const 978 978 { 979 bool result = true;979 bool result = true; 980 980 // bring MaxTypes up to date 981 981 mol->CountElements(); 982 ofstream *output = NULL;983 output = new ofstream(filename, ios::out);984 if (output != NULL) {985 *output << "# ParallelCarParinello - main configuration file - created with molecuilder" << endl;986 *output << endl;987 *output << "mainname\t" << config::mainname << "\t# programm name (for runtime files)" << endl;988 *output << "defaultpath\t" << config::defaultpath << "\t# where to put files during runtime" << endl;989 *output << "pseudopotpath\t" << config::pseudopotpath << "\t# where to find pseudopotentials" << endl;990 *output << endl;991 *output << "ProcPEGamma\t" << config::ProcPEGamma << "\t# for parallel computing: share constants" << endl;992 *output << "ProcPEPsi\t" << config::ProcPEPsi << "\t# for parallel computing: share wave functions" << endl;993 *output << "DoOutVis\t" << config::DoOutVis << "\t# Output data for OpenDX" << endl;994 *output << "DoOutMes\t" << config::DoOutMes << "\t# Output data for measurements" << endl;995 *output << "DoOutOrbitals\t" << config::DoOutOrbitals << "\t# Output all Orbitals" << endl;996 *output << "DoOutCurr\t" << config::DoOutCurrent << "\t# Ouput current density for OpenDx" << endl;997 *output << "DoOutNICS\t" << config::DoOutNICS << "\t# Output Nucleus independent current shieldings" << endl;998 *output << "DoPerturbation\t" << config::DoPerturbation << "\t# Do perturbation calculate and determine susceptibility and shielding" << endl;999 *output << "DoFullCurrent\t" << config::DoFullCurrent << "\t# Do full perturbation" << endl;1000 *output << "CommonWannier\t" << config::CommonWannier << "\t# Put virtual centers at indivual orbits, all common, merged by variance, to grid point, to cell center" << endl;1001 *output << "SawtoothStart\t" << config::SawtoothStart << "\t# Absolute value for smooth transition at cell border " << endl;1002 *output << "VectorPlane\t" << config::VectorPlane << "\t# Cut plane axis (x, y or z: 0,1,2) for two-dim current vector plot" << endl;1003 *output << "VectorCut\t" << config::VectorCut << "\t# Cut plane axis value" << endl;1004 *output << "AddGramSch\t" << config::UseAddGramSch << "\t# Additional GramSchmidtOrtogonalization to be safe" << endl;1005 *output << "Seed\t\t" << config::Seed << "\t# initial value for random seed for Psi coefficients" << endl;1006 *output << endl;1007 *output << "MaxOuterStep\t" << config::MaxOuterStep << "\t# number of MolecularDynamics/Structure optimization steps" << endl;1008 *output << "Deltat\t" << config::Deltat << "\t# time per MD step" << endl;1009 *output << "OutVisStep\t" << config::OutVisStep << "\t# Output visual data every ...th step" << endl;1010 *output << "OutSrcStep\t" << config::OutSrcStep << "\t# Output \"restart\" data every ..th step" << endl;1011 *output << "TargetTemp\t" << config::TargetTemp << "\t# Target temperature" << endl;1012 *output << "MaxPsiStep\t" << config::MaxPsiStep << "\t# number of Minimisation steps per state (0 - default)" << endl;1013 *output << "EpsWannier\t" << config::EpsWannier << "\t# tolerance value for spread minimisation of orbitals" << endl;1014 *output << endl;1015 *output << "# Values specifying when to stop" << endl;1016 *output << "MaxMinStep\t" << config::MaxMinStep << "\t# Maximum number of steps" << endl;1017 *output << "RelEpsTotalE\t" << config::RelEpsTotalEnergy << "\t# relative change in total energy" << endl;1018 *output << "RelEpsKineticE\t" << config::RelEpsKineticEnergy << "\t# relative change in kinetic energy" << endl;1019 *output << "MaxMinStopStep\t" << config::MaxMinStopStep << "\t# check every ..th steps" << endl;1020 *output << "MaxMinGapStopStep\t" << config::MaxMinGapStopStep << "\t# check every ..th steps" << endl;1021 *output << endl;1022 *output << "# Values specifying when to stop for INIT, otherwise same as above" << endl;1023 *output << "MaxInitMinStep\t" << config::MaxInitMinStep << "\t# Maximum number of steps" << endl;1024 *output << "InitRelEpsTotalE\t" << config::InitRelEpsTotalEnergy << "\t# relative change in total energy" << endl;1025 *output << "InitRelEpsKineticE\t" << config::InitRelEpsKineticEnergy << "\t# relative change in kinetic energy" << endl;1026 *output << "InitMaxMinStopStep\t" << config::InitMaxMinStopStep << "\t# check every ..th steps" << endl;1027 *output << "InitMaxMinGapStopStep\t" << config::InitMaxMinGapStopStep << "\t# check every ..th steps" << endl;1028 *output << endl;1029 *output << "BoxLength\t\t\t# (Length of a unit cell)" << endl;1030 *output << mol->cell_size[0] << "\t" << endl;1031 *output << mol->cell_size[1] << "\t" << mol->cell_size[2] << "\t" << endl;1032 *output << mol->cell_size[3] << "\t" << mol->cell_size[4] << "\t" << mol->cell_size[5] << "\t" << endl;1033 // FIXME1034 *output << endl;1035 *output << "ECut\t\t" << config::ECut << "\t# energy cutoff for discretization in Hartrees" << endl;1036 *output << "MaxLevel\t" << config::MaxLevel << "\t# number of different levels in the code, >=2" << endl;1037 *output << "Level0Factor\t" << config::Lev0Factor << "\t# factor by which node number increases from S to 0 level" << endl;1038 *output << "RiemannTensor\t" << config::RiemannTensor << "\t# (Use metric)" << endl;1039 switch (config::RiemannTensor) {1040 case 0: //UseNoRT1041 break;1042 case 1: // UseRT1043 *output << "RiemannLevel\t" << config::RiemannLevel << "\t# Number of Riemann Levels" << endl;1044 *output << "LevRFactor\t" << config::LevRFactor << "\t# factor by which node number increases from 0 to R level from" << endl;1045 break;1046 }1047 *output << "PsiType\t\t" << config::PsiType << "\t# 0 - doubly occupied, 1 - SpinUp,SpinDown" << endl;1048 // write out both types for easier changing afterwards1049 //switch (PsiType) {1050 //case 0:1051 *output << "MaxPsiDouble\t" << config::MaxPsiDouble << "\t# here: specifying both maximum number of SpinUp- and -Down-states" << endl;1052 //break;1053 //case 1:1054 *output << "PsiMaxNoUp\t" << config::PsiMaxNoUp << "\t# here: specifying maximum number of SpinUp-states" << endl;1055 *output << "PsiMaxNoDown\t" << config::PsiMaxNoDown << "\t# here: specifying maximum number of SpinDown-states" << endl;1056 //break;1057 //}1058 *output << "AddPsis\t\t" << config::AddPsis << "\t# Additional unoccupied Psis for bandgap determination" << endl;1059 *output << endl;1060 *output << "RCut\t\t" << config::RCut << "\t# R-cut for the ewald summation" << endl;1061 *output << "StructOpt\t" << config::StructOpt << "\t# Do structure optimization beforehand" << endl;1062 *output << "IsAngstroem\t" << config::IsAngstroem << "\t# 0 - Bohr, 1 - Angstroem" << endl;1063 *output << "RelativeCoord\t" << config::RelativeCoord << "\t# whether ion coordinates are relative (1) or absolute (0)" << endl;1064 *output << "MaxTypes\t" << mol->ElementCount <<"\t# maximum number of different ion types" << endl;1065 *output << endl;1066 result = result && mol->Checkout(output);1067 if (mol->MDSteps <=1 )1068 result = result && mol->Output(output);1069 else1070 result = result && mol->OutputTrajectories(output);1071 output->close();1072 output->clear();1073 delete(output);1074 return result;1075 } else1076 return false;982 ofstream *output = NULL; 983 output = new ofstream(filename, ios::out); 984 if (output != NULL) { 985 *output << "# ParallelCarParinello - main configuration file - created with molecuilder" << endl; 986 *output << endl; 987 *output << "mainname\t" << config::mainname << "\t# programm name (for runtime files)" << endl; 988 *output << "defaultpath\t" << config::defaultpath << "\t# where to put files during runtime" << endl; 989 *output << "pseudopotpath\t" << config::pseudopotpath << "\t# where to find pseudopotentials" << endl; 990 *output << endl; 991 *output << "ProcPEGamma\t" << config::ProcPEGamma << "\t# for parallel computing: share constants" << endl; 992 *output << "ProcPEPsi\t" << config::ProcPEPsi << "\t# for parallel computing: share wave functions" << endl; 993 *output << "DoOutVis\t" << config::DoOutVis << "\t# Output data for OpenDX" << endl; 994 *output << "DoOutMes\t" << config::DoOutMes << "\t# Output data for measurements" << endl; 995 *output << "DoOutOrbitals\t" << config::DoOutOrbitals << "\t# Output all Orbitals" << endl; 996 *output << "DoOutCurr\t" << config::DoOutCurrent << "\t# Ouput current density for OpenDx" << endl; 997 *output << "DoOutNICS\t" << config::DoOutNICS << "\t# Output Nucleus independent current shieldings" << endl; 998 *output << "DoPerturbation\t" << config::DoPerturbation << "\t# Do perturbation calculate and determine susceptibility and shielding" << endl; 999 *output << "DoFullCurrent\t" << config::DoFullCurrent << "\t# Do full perturbation" << endl; 1000 *output << "CommonWannier\t" << config::CommonWannier << "\t# Put virtual centers at indivual orbits, all common, merged by variance, to grid point, to cell center" << endl; 1001 *output << "SawtoothStart\t" << config::SawtoothStart << "\t# Absolute value for smooth transition at cell border " << endl; 1002 *output << "VectorPlane\t" << config::VectorPlane << "\t# Cut plane axis (x, y or z: 0,1,2) for two-dim current vector plot" << endl; 1003 *output << "VectorCut\t" << config::VectorCut << "\t# Cut plane axis value" << endl; 1004 *output << "AddGramSch\t" << config::UseAddGramSch << "\t# Additional GramSchmidtOrtogonalization to be safe" << endl; 1005 *output << "Seed\t\t" << config::Seed << "\t# initial value for random seed for Psi coefficients" << endl; 1006 *output << endl; 1007 *output << "MaxOuterStep\t" << config::MaxOuterStep << "\t# number of MolecularDynamics/Structure optimization steps" << endl; 1008 *output << "Deltat\t" << config::Deltat << "\t# time per MD step" << endl; 1009 *output << "OutVisStep\t" << config::OutVisStep << "\t# Output visual data every ...th step" << endl; 1010 *output << "OutSrcStep\t" << config::OutSrcStep << "\t# Output \"restart\" data every ..th step" << endl; 1011 *output << "TargetTemp\t" << config::TargetTemp << "\t# Target temperature" << endl; 1012 *output << "MaxPsiStep\t" << config::MaxPsiStep << "\t# number of Minimisation steps per state (0 - default)" << endl; 1013 *output << "EpsWannier\t" << config::EpsWannier << "\t# tolerance value for spread minimisation of orbitals" << endl; 1014 *output << endl; 1015 *output << "# Values specifying when to stop" << endl; 1016 *output << "MaxMinStep\t" << config::MaxMinStep << "\t# Maximum number of steps" << endl; 1017 *output << "RelEpsTotalE\t" << config::RelEpsTotalEnergy << "\t# relative change in total energy" << endl; 1018 *output << "RelEpsKineticE\t" << config::RelEpsKineticEnergy << "\t# relative change in kinetic energy" << endl; 1019 *output << "MaxMinStopStep\t" << config::MaxMinStopStep << "\t# check every ..th steps" << endl; 1020 *output << "MaxMinGapStopStep\t" << config::MaxMinGapStopStep << "\t# check every ..th steps" << endl; 1021 *output << endl; 1022 *output << "# Values specifying when to stop for INIT, otherwise same as above" << endl; 1023 *output << "MaxInitMinStep\t" << config::MaxInitMinStep << "\t# Maximum number of steps" << endl; 1024 *output << "InitRelEpsTotalE\t" << config::InitRelEpsTotalEnergy << "\t# relative change in total energy" << endl; 1025 *output << "InitRelEpsKineticE\t" << config::InitRelEpsKineticEnergy << "\t# relative change in kinetic energy" << endl; 1026 *output << "InitMaxMinStopStep\t" << config::InitMaxMinStopStep << "\t# check every ..th steps" << endl; 1027 *output << "InitMaxMinGapStopStep\t" << config::InitMaxMinGapStopStep << "\t# check every ..th steps" << endl; 1028 *output << endl; 1029 *output << "BoxLength\t\t\t# (Length of a unit cell)" << endl; 1030 *output << mol->cell_size[0] << "\t" << endl; 1031 *output << mol->cell_size[1] << "\t" << mol->cell_size[2] << "\t" << endl; 1032 *output << mol->cell_size[3] << "\t" << mol->cell_size[4] << "\t" << mol->cell_size[5] << "\t" << endl; 1033 // FIXME 1034 *output << endl; 1035 *output << "ECut\t\t" << config::ECut << "\t# energy cutoff for discretization in Hartrees" << endl; 1036 *output << "MaxLevel\t" << config::MaxLevel << "\t# number of different levels in the code, >=2" << endl; 1037 *output << "Level0Factor\t" << config::Lev0Factor << "\t# factor by which node number increases from S to 0 level" << endl; 1038 *output << "RiemannTensor\t" << config::RiemannTensor << "\t# (Use metric)" << endl; 1039 switch (config::RiemannTensor) { 1040 case 0: //UseNoRT 1041 break; 1042 case 1: // UseRT 1043 *output << "RiemannLevel\t" << config::RiemannLevel << "\t# Number of Riemann Levels" << endl; 1044 *output << "LevRFactor\t" << config::LevRFactor << "\t# factor by which node number increases from 0 to R level from" << endl; 1045 break; 1046 } 1047 *output << "PsiType\t\t" << config::PsiType << "\t# 0 - doubly occupied, 1 - SpinUp,SpinDown" << endl; 1048 // write out both types for easier changing afterwards 1049 // switch (PsiType) { 1050 // case 0: 1051 *output << "MaxPsiDouble\t" << config::MaxPsiDouble << "\t# here: specifying both maximum number of SpinUp- and -Down-states" << endl; 1052 // break; 1053 // case 1: 1054 *output << "PsiMaxNoUp\t" << config::PsiMaxNoUp << "\t# here: specifying maximum number of SpinUp-states" << endl; 1055 *output << "PsiMaxNoDown\t" << config::PsiMaxNoDown << "\t# here: specifying maximum number of SpinDown-states" << endl; 1056 // break; 1057 // } 1058 *output << "AddPsis\t\t" << config::AddPsis << "\t# Additional unoccupied Psis for bandgap determination" << endl; 1059 *output << endl; 1060 *output << "RCut\t\t" << config::RCut << "\t# R-cut for the ewald summation" << endl; 1061 *output << "StructOpt\t" << config::StructOpt << "\t# Do structure optimization beforehand" << endl; 1062 *output << "IsAngstroem\t" << config::IsAngstroem << "\t# 0 - Bohr, 1 - Angstroem" << endl; 1063 *output << "RelativeCoord\t" << config::RelativeCoord << "\t# whether ion coordinates are relative (1) or absolute (0)" << endl; 1064 *output << "MaxTypes\t" << mol->ElementCount << "\t# maximum number of different ion types" << endl; 1065 *output << endl; 1066 result = result && mol->Checkout(output); 1067 if (mol->MDSteps <=1 ) 1068 result = result && mol->Output(output); 1069 else 1070 result = result && mol->OutputTrajectories(output); 1071 output->close(); 1072 output->clear(); 1073 delete(output); 1074 return result; 1075 } else 1076 return false; 1077 1077 }; 1078 1078 … … 1084 1084 bool config::SaveMPQC(const char *filename, molecule *mol) const 1085 1085 { 1086 int ElementNo = 0; 1087 int AtomNo; 1088 atom *Walker = NULL; 1089 element *runner = NULL; 1090 Vector *center = NULL; 1091 ofstream *output = NULL; 1092 stringstream *fname = NULL; 1093 1094 // first without hessian 1095 fname = new stringstream; 1096 *fname << filename << ".in"; 1097 output = new ofstream(fname->str().c_str(), ios::out); 1098 *output << "% Created by MoleCuilder" << endl; 1099 *output << "mpqc: (" << endl; 1100 *output << "\tsavestate = no" << endl; 1101 *output << "\tdo_gradient = yes" << endl; 1102 *output << "\tmole<CLHF>: (" << endl; 1103 *output << "\t\tmaxiter = 200" << endl; 1104 *output << "\t\tbasis = $:basis" << endl; 1105 *output << "\t\tmolecule = $:molecule" << endl; 1106 *output << "\t)" << endl; 1107 *output << ")" << endl; 1108 *output << "molecule<Molecule>: (" << endl; 1109 *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl; 1110 *output << "\t{ atoms geometry } = {" << endl; 1111 center = mol->DetermineCenterOfAll(output); 1112 // output of atoms 1113 runner = mol->elemente->start; 1114 while (runner->next != mol->elemente->end) { // go through every element 1115 runner = runner->next; 1116 if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms 1117 ElementNo++; 1118 AtomNo = 0; 1119 Walker = mol->start; 1120 while (Walker->next != mol->end) { // go through every atom of this element 1121 Walker = Walker->next; 1122 if (Walker->type == runner) { // if this atom fits to element 1123 AtomNo++; 1124 *output << "\t\t" << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl; 1125 } 1126 } 1127 } 1128 } 1129 delete(center); 1130 *output << "\t}" << endl; 1131 *output << ")" << endl; 1132 *output << "basis<GaussianBasisSet>: (" << endl; 1133 *output << "\tname = \"3-21G\"" << endl; 1134 *output << "\tmolecule = $:molecule" << endl; 1135 *output << ")" << endl; 1136 output->close(); 1137 delete(output); 1138 delete(fname); 1139 1140 // second with hessian 1141 fname = new stringstream; 1142 *fname << filename << ".hess.in"; 1143 output = new ofstream(fname->str().c_str(), ios::out); 1144 *output << "% Created by MoleCuilder" << endl; 1145 *output << "mpqc: (" << endl; 1146 *output << "\tsavestate = no" << endl; 1147 *output << "\tdo_gradient = yes" << endl; 1148 *output << "\tmole<CLHF>: (" << endl; 1149 *output << "\t\tmaxiter = 200" << endl; 1150 *output << "\t\tbasis = $:basis" << endl; 1151 *output << "\t\tmolecule = $:molecule" << endl; 1152 *output << "\t)" << endl; 1153 *output << "\tfreq<MolecularFrequencies>: (" << endl; 1154 *output << "\t\tmolecule=$:molecule" << endl; 1155 *output << "\t)" << endl; 1156 *output << ")" << endl; 1157 *output << "molecule<Molecule>: (" << endl; 1158 *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl; 1159 *output << "\t{ atoms geometry } = {" << endl; 1160 center = mol->DetermineCenterOfAll(output); 1161 // output of atoms 1162 runner = mol->elemente->start; 1163 while (runner->next != mol->elemente->end) { // go through every element 1164 runner = runner->next; 1165 if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms 1166 ElementNo++; 1167 AtomNo = 0; 1168 Walker = mol->start; 1169 while (Walker->next != mol->end) { // go through every atom of this element 1170 Walker = Walker->next; 1171 if (Walker->type == runner) { // if this atom fits to element 1172 AtomNo++; 1173 *output << "\t\t" << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl; 1174 } 1175 } 1176 } 1177 } 1178 delete(center); 1179 *output << "\t}" << endl; 1180 *output << ")" << endl; 1181 *output << "basis<GaussianBasisSet>: (" << endl; 1182 *output << "\tname = \"3-21G\"" << endl; 1183 *output << "\tmolecule = $:molecule" << endl; 1184 *output << ")" << endl; 1185 output->close(); 1186 delete(output); 1187 delete(fname); 1188 1189 return true; 1086 int ElementNo = 0; 1087 int AtomNo; 1088 atom *Walker = NULL; 1089 element *runner = NULL; 1090 Vector *center = NULL; 1091 ofstream *output = NULL; 1092 stringstream *fname = NULL; 1093 1094 // first without hessian 1095 fname = new stringstream; 1096 *fname << filename << ".in"; 1097 output = new ofstream(fname->str().c_str(), ios::out); 1098 *output << "% Created by MoleCuilder" << endl; 1099 *output << "mpqc: (" << endl; 1100 *output << "\tsavestate = no" << endl; 1101 *output << "\tdo_gradient = yes" << endl; 1102 *output << "\tmole<MBPT2>: (" << endl; 1103 *output << "\t\tmaxiter = 200" << endl; 1104 *output << "\t\tbasis = $:basis" << endl; 1105 *output << "\t\tmolecule = $:molecule" << endl; 1106 *output << "\t\treference<CLHF>: (" << endl; 1107 *output << "\t\t\tbasis = $:basis" << endl; 1108 *output << "\t\t\tmolecule = $:molecule" << endl; 1109 *output << "\t\t)" << endl; 1110 *output << "\t)" << endl; 1111 *output << ")" << endl; 1112 *output << "molecule<Molecule>: (" << endl; 1113 *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl; 1114 *output << "\t{ atoms geometry } = {" << endl; 1115 center = mol->DetermineCenterOfAll(output); 1116 // output of atoms 1117 runner = mol->elemente->start; 1118 while (runner->next != mol->elemente->end) { // go through every element 1119 runner = runner->next; 1120 if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms 1121 ElementNo++; 1122 AtomNo = 0; 1123 Walker = mol->start; 1124 while (Walker->next != mol->end) { // go through every atom of this element 1125 Walker = Walker->next; 1126 if (Walker->type == runner) { // if this atom fits to element 1127 AtomNo++; 1128 *output << "\t\t" << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl; 1129 } 1130 } 1131 } 1132 } 1133 delete(center); 1134 *output << "\t}" << endl; 1135 *output << ")" << endl; 1136 *output << "basis<GaussianBasisSet>: (" << endl; 1137 *output << "\tname = \"3-21G\"" << endl; 1138 *output << "\tmolecule = $:molecule" << endl; 1139 *output << ")" << endl; 1140 output->close(); 1141 delete(output); 1142 delete(fname); 1143 1144 // second with hessian 1145 fname = new stringstream; 1146 *fname << filename << ".hess.in"; 1147 output = new ofstream(fname->str().c_str(), ios::out); 1148 *output << "% Created by MoleCuilder" << endl; 1149 *output << "mpqc: (" << endl; 1150 *output << "\tsavestate = no" << endl; 1151 *output << "\tdo_gradient = yes" << endl; 1152 *output << "\tmole<CLHF>: (" << endl; 1153 *output << "\t\tmaxiter = 200" << endl; 1154 *output << "\t\tbasis = $:basis" << endl; 1155 *output << "\t\tmolecule = $:molecule" << endl; 1156 *output << "\t)" << endl; 1157 *output << "\tfreq<MolecularFrequencies>: (" << endl; 1158 *output << "\t\tmolecule=$:molecule" << endl; 1159 *output << "\t)" << endl; 1160 *output << ")" << endl; 1161 *output << "molecule<Molecule>: (" << endl; 1162 *output << "\tunit = " << (IsAngstroem ? "angstrom" : "bohr" ) << endl; 1163 *output << "\t{ atoms geometry } = {" << endl; 1164 center = mol->DetermineCenterOfAll(output); 1165 // output of atoms 1166 runner = mol->elemente->start; 1167 while (runner->next != mol->elemente->end) { // go through every element 1168 runner = runner->next; 1169 if (mol->ElementsInMolecule[runner->Z]) { // if this element got atoms 1170 ElementNo++; 1171 AtomNo = 0; 1172 Walker = mol->start; 1173 while (Walker->next != mol->end) { // go through every atom of this element 1174 Walker = Walker->next; 1175 if (Walker->type == runner) { // if this atom fits to element 1176 AtomNo++; 1177 *output << "\t\t" << Walker->type->symbol << " [ " << Walker->x.x[0]-center->x[0] << "\t" << Walker->x.x[1]-center->x[1] << "\t" << Walker->x.x[2]-center->x[2] << " ]" << endl; 1178 } 1179 } 1180 } 1181 } 1182 delete(center); 1183 *output << "\t}" << endl; 1184 *output << ")" << endl; 1185 *output << "basis<GaussianBasisSet>: (" << endl; 1186 *output << "\tname = \"3-21G\"" << endl; 1187 *output << "\tmolecule = $:molecule" << endl; 1188 *output << ")" << endl; 1189 output->close(); 1190 delete(output); 1191 delete(fname); 1192 1193 return true; 1190 1194 }; 1191 1195 … … 1199 1203 * \param name Name of value in file (at least 3 chars!) 1200 1204 * \param sequential 1 - do not reset file pointer to begin of file, 0 - set to beginning 1201 * (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read -1202 * best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now1203 * counted from this unresetted position!)1205 * (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read - 1206 * best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now 1207 * counted from this unresetted position!) 1204 1208 * \param xth Which among a number of parameters it is (in grid case it's row number as grid is read as a whole!) 1205 1209 * \param yth In grid case specifying column number, otherwise the yth \a name matching line … … 1212 1216 */ 1213 1217 int config::ParseForParameter(int verbose, ifstream *file, const char *name, int sequential, int const xth, int const yth, int type, void *value, int repetition, int critical) { 1214 int i,j;// loop variables1215 int length = 0, maxlength = -1;1216 long file_position = file->tellg(); // mark current position1217 char *dummy1, *dummy, *free_dummy;// pointers in the line that is read in per step1218 dummy1 = free_dummy = (char *) Malloc(256 * sizeof(char), "config::ParseForParameter: *free_dummy");1219 1220 //fprintf(stderr,"Parsing for %s\n",name); 1221 if (repetition == 0)1222 //Error(SomeError, "ParseForParameter(): argument repetition must not be 0!");1223 return 0;1224 1225 int line = 0; // marks line where parameter was found1226 int found = (type >= grid) ? 0 : (-yth + 1);// marks if yth parameter name was found1227 while((found != repetition)) {1228 dummy1 = dummy = free_dummy;1229 do {1230 file->getline(dummy1, 256); // Read the whole line1231 if (file->eof()) {1232 if ((critical) && (found == 0)) {1233 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");1234 //Error(InitReading, name);1235 fprintf(stderr,"Error:InitReading, critical %s not found\n", name);1236 exit(255);1237 } else {1238 //if (!sequential)1239 file->clear();1240 file->seekg(file_position, ios::beg);// rewind to start position1241 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1242 return 0;1243 }1244 }1245 line++;1246 } while (dummy != NULL && dummy1 != NULL && ((dummy1[0] == '#') || (dummy1[0] == '\0'))); // skip commentary and empty lines1247 1248 // C++ getline removes newline at end, thus re-add1249 if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {1250 i = strlen(dummy1);1251 dummy1[i] = '\n';1252 dummy1[i+1] = '\0';1253 }1254 //fprintf(stderr,"line %i ends at %i, newline at %i\n", line, strlen(dummy1), strchr(dummy1,'\n')-free_dummy);1255 1256 if (dummy1 == NULL) {1257 if (verbose) fprintf(stderr,"Error reading line %i\n",line);1258 } else {1259 //fprintf(stderr,"Now parsing the line %i: %s\n", line, dummy1);1260 }1261 // Seek for possible end of keyword on line if given ...1262 if (name != NULL) {1263 dummy = strchr(dummy1,'\t');// set dummy on first tab or space which ever's nearer1264 if (dummy == NULL) {1265 dummy = strchr(dummy1, ' ');// if not found seek for space1266 while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' ')))// skip some more tabs and spaces if necessary1267 dummy++;1268 }1269 if (dummy == NULL) {1270 dummy = strchr(dummy1, '\n'); // set on line end then (whole line = keyword)1271 //fprintf(stderr,"Error: Cannot find tabs or spaces on line %i in search for %s\n", line, name);1272 //Free((void **)&free_dummy);1273 //Error(FileOpenParams, NULL); 1274 } else {1275 //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)dummy1);1276 }1277 } else dummy = dummy1;1278 // ... and check if it is the keyword!1279 //fprintf(stderr,"name %p, dummy %i/%c, dummy1 %i/%c, strlen(name) %i\n", &name, dummy, *dummy, dummy1, *dummy1, strlen(name));1280 if ((name == NULL) || (((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0)) && ((unsigned int)(dummy-dummy1) == strlen(name)))) {1281 found++; // found the parameter!1282 //fprintf(stderr,"found %s at line %i between %i and %i\n", name, line, dummy1, dummy); 1283 1284 if (found == repetition) {1285 for (i=0;i<xth;i++) { // i = rows1286 if (type >= grid) {1287 // grid structure means that grid starts on the next line, not right after keyword1288 dummy1 = dummy = free_dummy;1289 do {1290 file->getline(dummy1, 256); // Read the whole line, skip commentary and empty ones1291 if (file->eof()) {1292 if ((critical) && (found == 0)) {1293 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");1294 //Error(InitReading, name);1295 fprintf(stderr,"Error:InitReading, critical %s not found\n", name);1296 exit(255);1297 } else {1298 //if (!sequential)1299 file->clear();1300 file->seekg(file_position, ios::beg);// rewind to start position1301 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");1302 return 0;1303 }1304 }1305 line++;1306 } while ((dummy1[0] == '#') || (dummy1[0] == '\n'));1307 if (dummy1 == NULL){1308 if (verbose) fprintf(stderr,"Error reading line %i\n", line);1309 } else {1310 //fprintf(stderr,"Reading next line %i: %s\n", line, dummy1);1311 }1312 } else { // simple int, strings or doubles start in the same line1313 while ((*dummy == '\t') || (*dummy == ' '))// skip interjacent tabs and spaces1314 dummy++;1315 }1316 // C++ getline removes newline at end, thus re-add1317 if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {1318 j = strlen(dummy1);1319 dummy1[j] = '\n';1320 dummy1[j+1] = '\0';1321 }1322 1323 int start = (type >= grid) ? 0 : yth-1 ;1324 for (j=start;j<yth;j++) { // j = columns1325 // check for lower triangular area and upper triangular area1326 if ( ((i > j) && (type == upper_trigrid)) || ((j > i) && (type == lower_trigrid))) {1327 *((double *)value) = 0.0;1328 fprintf(stderr,"%f\t",*((double *)value));1329 value = (void *)((long)value + sizeof(double));1330 //value += sizeof(double);1331 } else {1332 // otherwise we must skip all interjacent tabs and spaces and find next value1333 dummy1 = dummy;1334 dummy = strchr(dummy1, '\t'); // seek for tab or space1335 if (dummy == NULL)1336 dummy = strchr(dummy1, ' ');// if not found seek for space1337 if (dummy == NULL) { // if still zero returned ...1338 dummy = strchr(dummy1, '\n');// ... at line end then1339 if ((j < yth-1) && (type < 4)) {// check if xth value or not yet1340 if (critical) {1341 if (verbose) fprintf(stderr,"Error: EoL at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);1342 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");1343 //return 0;1344 exit(255);1345 //Error(FileOpenParams, NULL); 1346 } else {1347 //if (!sequential)1348 file->clear();1349 file->seekg(file_position, ios::beg);// rewind to start position1350 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");1351 return 0;1352 }1353 }1354 } else {1355 //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)free_dummy);1356 }1357 if (*dummy1 == '#') {1358 // found comment, skipping rest of line1359 //if (verbose) fprintf(stderr,"Error: '#' at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);1360 if (!sequential) { // here we need it!1361 file->seekg(file_position, ios::beg);// rewind to start position1362 }1363 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");1364 return 0;1365 }1366 //fprintf(stderr,"value from %i to %i\n",(char *)dummy1-(char *)free_dummy,(char *)dummy-(char *)free_dummy);1367 switch(type) {1368 case (row_int):1369 *((int *)value) = atoi(dummy1);1370 if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);1371 if (verbose) fprintf(stderr,"%i\t",*((int *)value));1372 value = (void *)((long)value + sizeof(int));1373 //value += sizeof(int);1374 break;1375 case(row_double):1376 case(grid):1377 case(lower_trigrid):1378 case(upper_trigrid):1379 *((double *)value) = atof(dummy1);1380 if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);1381 if (verbose) fprintf(stderr,"%lg\t",*((double *)value));1382 value = (void *)((long)value + sizeof(double));1383 //value += sizeof(double);1384 break;1385 case(double_type):1386 *((double *)value) = atof(dummy1);1387 if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %lg\n", name, *((double *) value));1388 //value += sizeof(double);1389 break;1390 case(int_type):1391 *((int *)value) = atoi(dummy1);1392 if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %i\n", name, *((int *) value));1393 //value += sizeof(int);1394 break;1395 default:1396 case(string_type):1397 if (value != NULL) {1398 //if (maxlength == -1) maxlength = strlen((char *)value); // get maximum size of string array1399 maxlength = MAXSTRINGSIZE;1400 length = maxlength > (dummy-dummy1) ? (dummy-dummy1) : maxlength; // cap at maximum1401 strncpy((char *)value, dummy1, length);// copy as much1402 ((char *)value)[length] = '\0';// and set end marker1403 if ((verbose) && (i == xth-1)) fprintf(stderr,"%s is '%s' (%i chars)\n",name,((char *) value), length);1404 //value += sizeof(char);1405 } else {1406 }1407 break;1408 }1409 }1410 while (*dummy == '\t')1411 dummy++;1412 }1413 }1414 }1415 }1416 }1417 if ((type >= row_int) && (verbose)) fprintf(stderr,"\n");1418 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy");1419 if (!sequential) {1420 file->clear();1421 file->seekg(file_position, ios::beg);// rewind to start position1422 }1423 //fprintf(stderr, "End of Parsing\n\n");1424 1425 return (found); // true if found, false if not1218 int i,j; // loop variables 1219 int length = 0, maxlength = -1; 1220 long file_position = file->tellg(); // mark current position 1221 char *dummy1, *dummy, *free_dummy; // pointers in the line that is read in per step 1222 dummy1 = free_dummy = (char *) Malloc(256 * sizeof(char), "config::ParseForParameter: *free_dummy"); 1223 1224 //fprintf(stderr,"Parsing for %s\n",name); 1225 if (repetition == 0) 1226 //Error(SomeError, "ParseForParameter(): argument repetition must not be 0!"); 1227 return 0; 1228 1229 int line = 0; // marks line where parameter was found 1230 int found = (type >= grid) ? 0 : (-yth + 1); // marks if yth parameter name was found 1231 while((found != repetition)) { 1232 dummy1 = dummy = free_dummy; 1233 do { 1234 file->getline(dummy1, 256); // Read the whole line 1235 if (file->eof()) { 1236 if ((critical) && (found == 0)) { 1237 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1238 //Error(InitReading, name); 1239 fprintf(stderr,"Error:InitReading, critical %s not found\n", name); 1240 exit(255); 1241 } else { 1242 //if (!sequential) 1243 file->clear(); 1244 file->seekg(file_position, ios::beg); // rewind to start position 1245 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1246 return 0; 1247 } 1248 } 1249 line++; 1250 } while (dummy != NULL && dummy1 != NULL && ((dummy1[0] == '#') || (dummy1[0] == '\0'))); // skip commentary and empty lines 1251 1252 // C++ getline removes newline at end, thus re-add 1253 if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) { 1254 i = strlen(dummy1); 1255 dummy1[i] = '\n'; 1256 dummy1[i+1] = '\0'; 1257 } 1258 //fprintf(stderr,"line %i ends at %i, newline at %i\n", line, strlen(dummy1), strchr(dummy1,'\n')-free_dummy); 1259 1260 if (dummy1 == NULL) { 1261 if (verbose) fprintf(stderr,"Error reading line %i\n",line); 1262 } else { 1263 //fprintf(stderr,"Now parsing the line %i: %s\n", line, dummy1); 1264 } 1265 // Seek for possible end of keyword on line if given ... 1266 if (name != NULL) { 1267 dummy = strchr(dummy1,'\t'); // set dummy on first tab or space which ever's nearer 1268 if (dummy == NULL) { 1269 dummy = strchr(dummy1, ' '); // if not found seek for space 1270 while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' '))) // skip some more tabs and spaces if necessary 1271 dummy++; 1272 } 1273 if (dummy == NULL) { 1274 dummy = strchr(dummy1, '\n'); // set on line end then (whole line = keyword) 1275 //fprintf(stderr,"Error: Cannot find tabs or spaces on line %i in search for %s\n", line, name); 1276 //Free((void **)&free_dummy); 1277 //Error(FileOpenParams, NULL); 1278 } else { 1279 //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)dummy1); 1280 } 1281 } else dummy = dummy1; 1282 // ... and check if it is the keyword! 1283 //fprintf(stderr,"name %p, dummy %i/%c, dummy1 %i/%c, strlen(name) %i\n", &name, dummy, *dummy, dummy1, *dummy1, strlen(name)); 1284 if ((name == NULL) || (((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0)) && ((unsigned int)(dummy-dummy1) == strlen(name)))) { 1285 found++; // found the parameter! 1286 //fprintf(stderr,"found %s at line %i between %i and %i\n", name, line, dummy1, dummy); 1287 1288 if (found == repetition) { 1289 for (i=0;i<xth;i++) { // i = rows 1290 if (type >= grid) { 1291 // grid structure means that grid starts on the next line, not right after keyword 1292 dummy1 = dummy = free_dummy; 1293 do { 1294 file->getline(dummy1, 256); // Read the whole line, skip commentary and empty ones 1295 if (file->eof()) { 1296 if ((critical) && (found == 0)) { 1297 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1298 //Error(InitReading, name); 1299 fprintf(stderr,"Error:InitReading, critical %s not found\n", name); 1300 exit(255); 1301 } else { 1302 //if (!sequential) 1303 file->clear(); 1304 file->seekg(file_position, ios::beg); // rewind to start position 1305 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1306 return 0; 1307 } 1308 } 1309 line++; 1310 } while ((dummy1[0] == '#') || (dummy1[0] == '\n')); 1311 if (dummy1 == NULL){ 1312 if (verbose) fprintf(stderr,"Error reading line %i\n", line); 1313 } else { 1314 //fprintf(stderr,"Reading next line %i: %s\n", line, dummy1); 1315 } 1316 } else { // simple int, strings or doubles start in the same line 1317 while ((*dummy == '\t') || (*dummy == ' ')) // skip interjacent tabs and spaces 1318 dummy++; 1319 } 1320 // C++ getline removes newline at end, thus re-add 1321 if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) { 1322 j = strlen(dummy1); 1323 dummy1[j] = '\n'; 1324 dummy1[j+1] = '\0'; 1325 } 1326 1327 int start = (type >= grid) ? 0 : yth-1 ; 1328 for (j=start;j<yth;j++) { // j = columns 1329 // check for lower triangular area and upper triangular area 1330 if ( ((i > j) && (type == upper_trigrid)) || ((j > i) && (type == lower_trigrid))) { 1331 *((double *)value) = 0.0; 1332 fprintf(stderr,"%f\t",*((double *)value)); 1333 value = (void *)((long)value + sizeof(double)); 1334 //value += sizeof(double); 1335 } else { 1336 // otherwise we must skip all interjacent tabs and spaces and find next value 1337 dummy1 = dummy; 1338 dummy = strchr(dummy1, '\t'); // seek for tab or space 1339 if (dummy == NULL) 1340 dummy = strchr(dummy1, ' '); // if not found seek for space 1341 if (dummy == NULL) { // if still zero returned ... 1342 dummy = strchr(dummy1, '\n'); // ... at line end then 1343 if ((j < yth-1) && (type < 4)) { // check if xth value or not yet 1344 if (critical) { 1345 if (verbose) fprintf(stderr,"Error: EoL at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name); 1346 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1347 //return 0; 1348 exit(255); 1349 //Error(FileOpenParams, NULL); 1350 } else { 1351 //if (!sequential) 1352 file->clear(); 1353 file->seekg(file_position, ios::beg); // rewind to start position 1354 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1355 return 0; 1356 } 1357 } 1358 } else { 1359 //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)free_dummy); 1360 } 1361 if (*dummy1 == '#') { 1362 // found comment, skipping rest of line 1363 //if (verbose) fprintf(stderr,"Error: '#' at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name); 1364 if (!sequential) { // here we need it! 1365 file->seekg(file_position, ios::beg); // rewind to start position 1366 } 1367 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1368 return 0; 1369 } 1370 //fprintf(stderr,"value from %i to %i\n",(char *)dummy1-(char *)free_dummy,(char *)dummy-(char *)free_dummy); 1371 switch(type) { 1372 case (row_int): 1373 *((int *)value) = atoi(dummy1); 1374 if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name); 1375 if (verbose) fprintf(stderr,"%i\t",*((int *)value)); 1376 value = (void *)((long)value + sizeof(int)); 1377 //value += sizeof(int); 1378 break; 1379 case(row_double): 1380 case(grid): 1381 case(lower_trigrid): 1382 case(upper_trigrid): 1383 *((double *)value) = atof(dummy1); 1384 if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name); 1385 if (verbose) fprintf(stderr,"%lg\t",*((double *)value)); 1386 value = (void *)((long)value + sizeof(double)); 1387 //value += sizeof(double); 1388 break; 1389 case(double_type): 1390 *((double *)value) = atof(dummy1); 1391 if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %lg\n", name, *((double *) value)); 1392 //value += sizeof(double); 1393 break; 1394 case(int_type): 1395 *((int *)value) = atoi(dummy1); 1396 if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %i\n", name, *((int *) value)); 1397 //value += sizeof(int); 1398 break; 1399 default: 1400 case(string_type): 1401 if (value != NULL) { 1402 //if (maxlength == -1) maxlength = strlen((char *)value); // get maximum size of string array 1403 maxlength = MAXSTRINGSIZE; 1404 length = maxlength > (dummy-dummy1) ? (dummy-dummy1) : maxlength; // cap at maximum 1405 strncpy((char *)value, dummy1, length); // copy as much 1406 ((char *)value)[length] = '\0'; // and set end marker 1407 if ((verbose) && (i == xth-1)) fprintf(stderr,"%s is '%s' (%i chars)\n",name,((char *) value), length); 1408 //value += sizeof(char); 1409 } else { 1410 } 1411 break; 1412 } 1413 } 1414 while (*dummy == '\t') 1415 dummy++; 1416 } 1417 } 1418 } 1419 } 1420 } 1421 if ((type >= row_int) && (verbose)) fprintf(stderr,"\n"); 1422 Free((void **)&free_dummy, "config::ParseForParameter: *free_dummy"); 1423 if (!sequential) { 1424 file->clear(); 1425 file->seekg(file_position, ios::beg); // rewind to start position 1426 } 1427 //fprintf(stderr, "End of Parsing\n\n"); 1428 1429 return (found); // true if found, false if not 1426 1430 } -
Property mode
changed from
-
src/datacreator.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 1 1 /** \file datacreator.cpp 2 2 * 3 * Declarations of assisting functions in creating data and plot files. 4 * 3 * Declarations of assisting functions in creating data and plot files. 4 * 5 5 */ 6 6 … … 19 19 bool OpenOutputFile(ofstream &output, const char *dir, const char *filename) 20 20 { 21 stringstream name;22 name << dir << "/" << filename;23 output.open(name.str().c_str(), ios::out);24 if (output == NULL) {25 cout << "Unable to open " << name.str() << " for writing, is directory correct?" << endl;26 return false;27 }28 return true;29 }; 21 stringstream name; 22 name << dir << "/" << filename; 23 output.open(name.str().c_str(), ios::out); 24 if (output == NULL) { 25 cout << "Unable to open " << name.str() << " for writing, is directory correct?" << endl; 26 return false; 27 } 28 return true; 29 }; 30 30 31 31 /** Opens a file for appending with \a *filename in \a *dir. … … 37 37 bool AppendOutputFile(ofstream &output, const char *dir, const char *filename) 38 38 { 39 stringstream name;40 name << dir << "/" << filename;41 output.open(name.str().c_str(), ios::app);42 if (output == NULL) {43 cout << "Unable to open " << name.str() << " for writing, is directory correct?" << endl;44 return false;45 }46 return true;47 }; 39 stringstream name; 40 name << dir << "/" << filename; 41 output.open(name.str().c_str(), ios::app); 42 if (output == NULL) { 43 cout << "Unable to open " << name.str() << " for writing, is directory correct?" << endl; 44 return false; 45 } 46 return true; 47 }; 48 48 49 49 /** Plots an energy vs. order. … … 54 54 * \return true if file was written successfully 55 55 */ 56 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 57 { 58 stringstream filename;59 ofstream output;60 61 filename << prefix << ".dat";62 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 63 cout << msg << endl;64 output << "# " << msg << ", created on " << datum;65 output << "#Order\tFrag.No.\t" << Fragments.Header << endl;66 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {67 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {68 for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;)69 for(int k=Fragments.ColumnCounter;k--;)70 Fragments.Matrix[Fragments.MatrixCounter][j][k] += Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];71 }72 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];73 for (int l=0;l<Fragments.ColumnCounter;l++)74 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l];75 output << endl;76 }77 output.close();78 return true;56 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 57 { 58 stringstream filename; 59 ofstream output; 60 61 filename << prefix << ".dat"; 62 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 63 cout << msg << endl; 64 output << "# " << msg << ", created on " << datum; 65 output << "#Order\tFrag.No.\t" << Fragments.Header << endl; 66 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 67 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) { 68 for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;) 69 for(int k=Fragments.ColumnCounter;k--;) 70 Fragments.Matrix[Fragments.MatrixCounter][j][k] += Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 71 } 72 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 73 for (int l=0;l<Fragments.ColumnCounter;l++) 74 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l]; 75 output << endl; 76 } 77 output.close(); 78 return true; 79 79 }; 80 80 … … 87 87 * \return true if file was written successfully 88 88 */ 89 bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 90 { 91 stringstream filename;92 ofstream output;93 94 filename << prefix << ".dat";95 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 96 cout << msg << endl;97 output << "# " << msg << ", created on " << datum;98 output << "#Order\tFrag.No.\t" << Fragments.Header << endl;99 Fragments.SetLastMatrix(Energy.Matrix[Energy.MatrixCounter],0);100 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {101 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {102 for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;)103 for(int k=Fragments.ColumnCounter;k--;)104 Fragments.Matrix[Fragments.MatrixCounter][j][k] -= Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];105 }106 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];107 for (int l=0;l<Fragments.ColumnCounter;l++)108 if (fabs(Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]) < MYEPSILON)109 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l];110 else111 output << scientific << "\t" << (Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l] / Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]);112 output << endl;113 }114 output.close();115 return true;89 bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 90 { 91 stringstream filename; 92 ofstream output; 93 94 filename << prefix << ".dat"; 95 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 96 cout << msg << endl; 97 output << "# " << msg << ", created on " << datum; 98 output << "#Order\tFrag.No.\t" << Fragments.Header << endl; 99 Fragments.SetLastMatrix(Energy.Matrix[Energy.MatrixCounter],0); 100 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 101 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) { 102 for(int j=Fragments.RowCounter[ KeySet.OrderSet[BondOrder][i] ];j--;) 103 for(int k=Fragments.ColumnCounter;k--;) 104 Fragments.Matrix[Fragments.MatrixCounter][j][k] -= Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 105 } 106 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 107 for (int l=0;l<Fragments.ColumnCounter;l++) 108 if (fabs(Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]) < MYEPSILON) 109 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l]; 110 else 111 output << scientific << "\t" << (Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l] / Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]); 112 output << endl; 113 } 114 output.close(); 115 return true; 116 116 }; 117 117 … … 126 126 bool CreateDataForcesOrder(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)) 127 127 { 128 stringstream filename;129 ofstream output;130 131 filename << prefix << ".dat";132 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 133 cout << msg << endl;134 output << "# " << msg << ", created on " << datum;135 output << "# Order\tFrag.No.\t" << Fragments.Header << endl;136 Fragments.SetLastMatrix(0.,0);137 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {138 Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.);139 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];140 CreateForce(Fragments, Fragments.MatrixCounter);141 for (int l=0;l<Fragments.ColumnCounter;l++)142 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l];143 output << endl;144 }145 output.close();146 return true;128 stringstream filename; 129 ofstream output; 130 131 filename << prefix << ".dat"; 132 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 133 cout << msg << endl; 134 output << "# " << msg << ", created on " << datum; 135 output << "# Order\tFrag.No.\t" << Fragments.Header << endl; 136 Fragments.SetLastMatrix(0.,0); 137 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 138 Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.); 139 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 140 CreateForce(Fragments, Fragments.MatrixCounter); 141 for (int l=0;l<Fragments.ColumnCounter;l++) 142 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l]; 143 output << endl; 144 } 145 output.close(); 146 return true; 147 147 }; 148 148 … … 158 158 bool CreateDataDeltaForcesOrder(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)) 159 159 { 160 stringstream filename;161 ofstream output;162 163 filename << prefix << ".dat";164 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 165 cout << msg << endl;166 output << "# " << msg << ", created on " << datum;167 output << "# Order\tFrag.No.\t" << Fragments.Header << endl;168 Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter],0);169 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {170 Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.);171 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];172 CreateForce(Fragments, Fragments.MatrixCounter);173 for (int l=0;l<Fragments.ColumnCounter;l++)174 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l];175 output << endl;176 }177 output.close();178 return true;160 stringstream filename; 161 ofstream output; 162 163 filename << prefix << ".dat"; 164 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 165 cout << msg << endl; 166 output << "# " << msg << ", created on " << datum; 167 output << "# Order\tFrag.No.\t" << Fragments.Header << endl; 168 Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter],0); 169 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 170 Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.); 171 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 172 CreateForce(Fragments, Fragments.MatrixCounter); 173 for (int l=0;l<Fragments.ColumnCounter;l++) 174 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l]; 175 output << endl; 176 } 177 output.close(); 178 return true; 179 179 }; 180 180 … … 188 188 * \return true if file was written successfully 189 189 */ 190 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 191 { 192 stringstream filename;193 ofstream output;194 double norm = 0.;195 196 filename << prefix << ".dat";197 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 198 cout << msg << endl;199 output << "# " << msg << ", created on " << datum;200 output << "# AtomNo\t" << Fragments.Header << endl;201 Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter], 0);202 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {203 //cout << "Current order is " << BondOrder << "." << endl;204 Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.);205 // errors per atom206 output << endl << "#Order\t" << BondOrder+1 << endl;207 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 208 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";209 for (int l=0;l<Fragments.ColumnCounter;l++) {210 if (((l+1) % 3) == 0) {211 norm = 0.;212 for (int m=0;m<NDIM;m++)213 norm += Force.Matrix[Force.MatrixCounter][ j ][l+m]*Force.Matrix[Force.MatrixCounter][ j ][l+m];214 norm = sqrt(norm);215 } 216 // if (norm < MYEPSILON)217 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";218 // else219 // output << scientific << (Fragments.Matrix[Fragments.MatrixCounter][ j ][l] / norm) << "\t";220 }221 output << endl;222 }223 output << endl;224 }225 output.close();226 return true;190 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 191 { 192 stringstream filename; 193 ofstream output; 194 double norm = 0.; 195 196 filename << prefix << ".dat"; 197 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 198 cout << msg << endl; 199 output << "# " << msg << ", created on " << datum; 200 output << "# AtomNo\t" << Fragments.Header << endl; 201 Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter], 0); 202 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 203 //cout << "Current order is " << BondOrder << "." << endl; 204 Fragments.SumSubForces(Fragments, KeySet, BondOrder, -1.); 205 // errors per atom 206 output << endl << "#Order\t" << BondOrder+1 << endl; 207 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 208 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t"; 209 for (int l=0;l<Fragments.ColumnCounter;l++) { 210 if (((l+1) % 3) == 0) { 211 norm = 0.; 212 for (int m=0;m<NDIM;m++) 213 norm += Force.Matrix[Force.MatrixCounter][ j ][l+m]*Force.Matrix[Force.MatrixCounter][ j ][l+m]; 214 norm = sqrt(norm); 215 } 216 // if (norm < MYEPSILON) 217 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t"; 218 // else 219 // output << scientific << (Fragments.Matrix[Fragments.MatrixCounter][ j ][l] / norm) << "\t"; 220 } 221 output << endl; 222 } 223 output << endl; 224 } 225 output.close(); 226 return true; 227 227 }; 228 228 … … 235 235 * \return true if file was written successfully 236 236 */ 237 bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 238 { 239 stringstream filename;240 ofstream output;241 242 filename << prefix << ".dat";243 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 244 cout << msg << endl;245 output << "# " << msg << ", created on " << datum;246 output << "# AtomNo\t" << Fragments.Header << endl;247 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {248 //cout << "Current order is " << BondOrder << "." << endl;249 Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.);250 // errors per atom251 output << endl << "#Order\t" << BondOrder+1 << endl;252 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 253 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";254 for (int l=0;l<Fragments.ColumnCounter;l++)255 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";256 output << endl;257 }258 output << endl;259 }260 output.close();261 return true;237 bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum) 238 { 239 stringstream filename; 240 ofstream output; 241 242 filename << prefix << ".dat"; 243 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 244 cout << msg << endl; 245 output << "# " << msg << ", created on " << datum; 246 output << "# AtomNo\t" << Fragments.Header << endl; 247 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 248 //cout << "Current order is " << BondOrder << "." << endl; 249 Fragments.SumSubForces(Fragments, KeySet, BondOrder, 1.); 250 // errors per atom 251 output << endl << "#Order\t" << BondOrder+1 << endl; 252 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 253 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t"; 254 for (int l=0;l<Fragments.ColumnCounter;l++) 255 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t"; 256 output << endl; 257 } 258 output << endl; 259 } 260 output.close(); 261 return true; 262 262 }; 263 263 … … 266 266 bool CreateDataFragment(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragment)(class MatrixContainer &, int)) 267 267 { 268 stringstream filename;269 ofstream output;270 271 filename << prefix << ".dat";272 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 273 cout << msg << endl;274 output << "# " << msg << ", created on " << datum << endl;275 output << "#Order\tFrag.No.\t" << Fragment.Header << endl;276 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {277 for(int i=0;i<KeySet.FragmentsPerOrder[BondOrder];i++) {278 output << BondOrder+1 << "\t" << KeySet.OrderSet[BondOrder][i]+1;279 CreateFragment(Fragment, KeySet.OrderSet[BondOrder][i]);280 for (int l=0;l<Fragment.ColumnCounter;l++)281 output << scientific << "\t" << Fragment.Matrix[ KeySet.OrderSet[BondOrder][i] ][ Fragment.RowCounter[ KeySet.OrderSet[BondOrder][i] ] ][l];282 output << endl;283 }284 }285 output.close();286 return true;268 stringstream filename; 269 ofstream output; 270 271 filename << prefix << ".dat"; 272 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 273 cout << msg << endl; 274 output << "# " << msg << ", created on " << datum << endl; 275 output << "#Order\tFrag.No.\t" << Fragment.Header << endl; 276 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 277 for(int i=0;i<KeySet.FragmentsPerOrder[BondOrder];i++) { 278 output << BondOrder+1 << "\t" << KeySet.OrderSet[BondOrder][i]+1; 279 CreateFragment(Fragment, KeySet.OrderSet[BondOrder][i]); 280 for (int l=0;l<Fragment.ColumnCounter;l++) 281 output << scientific << "\t" << Fragment.Matrix[ KeySet.OrderSet[BondOrder][i] ][ Fragment.RowCounter[ KeySet.OrderSet[BondOrder][i] ] ][l]; 282 output << endl; 283 } 284 } 285 output.close(); 286 return true; 287 287 }; 288 288 … … 291 291 * \param &KeySet KeySetsContainer with associations of each fragment to a bond order 292 292 * \param BondOrder current bond order 293 */ 293 */ 294 294 void CreateMaxFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder) 295 295 { 296 for(int j=Fragments.RowCounter[ Fragments.MatrixCounter ];j--;) {297 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) {298 if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) {299 for (int k=Fragments.ColumnCounter;k--;)300 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];301 }302 } 303 }296 for(int j=Fragments.RowCounter[ Fragments.MatrixCounter ];j--;) { 297 for(int i=KeySet.FragmentsPerOrder[BondOrder];i--;) { 298 if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) { 299 for (int k=Fragments.ColumnCounter;k--;) 300 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 301 } 302 } 303 } 304 304 }; 305 305 … … 308 308 * \param &KeySet KeySetsContainer with associations of each fragment to a bond order 309 309 * \param BondOrder current bond order 310 */ 310 */ 311 311 void CreateMinFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySet, int BondOrder) 312 312 { 313 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {314 int i=0;315 do {// first get a minimum value unequal to 0316 for (int k=Fragments.ColumnCounter;k--;)317 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];318 i++;319 } while ((fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < MYEPSILON) && (i<KeySet.FragmentsPerOrder[BondOrder]));320 for(;i<KeySet.FragmentsPerOrder[BondOrder];i++) { // then find lowest321 if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) > fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) {322 for (int k=Fragments.ColumnCounter;k--;)323 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k];324 }325 } 326 }313 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) { 314 int i=0; 315 do { // first get a minimum value unequal to 0 316 for (int k=Fragments.ColumnCounter;k--;) 317 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 318 i++; 319 } while ((fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < MYEPSILON) && (i<KeySet.FragmentsPerOrder[BondOrder])); 320 for(;i<KeySet.FragmentsPerOrder[BondOrder];i++) { // then find lowest 321 if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) > fabs(Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][1])) { 322 for (int k=Fragments.ColumnCounter;k--;) 323 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySet.OrderSet[BondOrder][i] ][j][k]; 324 } 325 } 326 } 327 327 }; 328 328 … … 331 331 bool CreateDataFragmentOrder(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragmentOrder)(class MatrixContainer &, class KeySetsContainer &, int)) 332 332 { 333 stringstream filename;334 ofstream output;335 336 filename << prefix << ".dat";337 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 338 cout << msg << endl;339 output << "# " << msg << ", created on " << datum;340 output << "#Order\tFrag.No.\t" << Fragment.Header << endl;341 // max342 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {343 Fragment.SetLastMatrix(0.,0);344 CreateFragmentOrder(Fragment, KeySet, BondOrder);345 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder];346 for (int l=0;l<Fragment.ColumnCounter;l++)347 output << scientific << "\t" << Fragment.Matrix[ Fragment.MatrixCounter ][ Fragment.RowCounter[ Fragment.MatrixCounter ]-1 ][l];348 output << endl;349 }350 output.close();351 return true;333 stringstream filename; 334 ofstream output; 335 336 filename << prefix << ".dat"; 337 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 338 cout << msg << endl; 339 output << "# " << msg << ", created on " << datum; 340 output << "#Order\tFrag.No.\t" << Fragment.Header << endl; 341 // max 342 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 343 Fragment.SetLastMatrix(0.,0); 344 CreateFragmentOrder(Fragment, KeySet, BondOrder); 345 output << BondOrder+1 << "\t" << KeySet.FragmentsPerOrder[BondOrder]; 346 for (int l=0;l<Fragment.ColumnCounter;l++) 347 output << scientific << "\t" << Fragment.Matrix[ Fragment.MatrixCounter ][ Fragment.RowCounter[ Fragment.MatrixCounter ]-1 ][l]; 348 output << endl; 349 } 350 output.close(); 351 return true; 352 352 }; 353 353 … … 358 358 void CreateEnergy(class MatrixContainer &Energy, int MatrixNumber) 359 359 { 360 for(int k=0;k<Energy.ColumnCounter;k++)361 Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber] ] [k] =Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber]-1 ] [k];360 for(int k=0;k<Energy.ColumnCounter;k++) 361 Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber] ] [k] = Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber]-1 ] [k]; 362 362 }; 363 363 … … 369 369 void CreateMinimumForce(class MatrixContainer &Force, int MatrixNumber) 370 370 { 371 for (int l=Force.ColumnCounter;l--;)372 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;373 for (int l=5;l<Force.ColumnCounter;l+=3) {374 double stored = 0;375 int k=0;376 do {377 for (int m=NDIM;m--;) {378 stored += Force.Matrix[MatrixNumber][ k ][l+m] 379 * Force.Matrix[MatrixNumber][ k ][l+m];380 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 381 }382 k++;383 } while ((fabs(stored) < MYEPSILON) && (k<Force.RowCounter[MatrixNumber]));384 for (;k<Force.RowCounter[MatrixNumber];k++) {385 double tmp = 0;386 for (int m=NDIM;m--;)387 tmp += Force.Matrix[MatrixNumber][ k ][l+m] 388 * Force.Matrix[MatrixNumber][ k ][l+m];389 if ((fabs(tmp) > MYEPSILON) && (tmp < stored)) {// current force is greater than stored390 for (int m=NDIM;m--;)391 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 392 stored = tmp;393 }394 }395 }371 for (int l=Force.ColumnCounter;l--;) 372 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.; 373 for (int l=5;l<Force.ColumnCounter;l+=3) { 374 double stored = 0; 375 int k=0; 376 do { 377 for (int m=NDIM;m--;) { 378 stored += Force.Matrix[MatrixNumber][ k ][l+m] 379 * Force.Matrix[MatrixNumber][ k ][l+m]; 380 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 381 } 382 k++; 383 } while ((fabs(stored) < MYEPSILON) && (k<Force.RowCounter[MatrixNumber])); 384 for (;k<Force.RowCounter[MatrixNumber];k++) { 385 double tmp = 0; 386 for (int m=NDIM;m--;) 387 tmp += Force.Matrix[MatrixNumber][ k ][l+m] 388 * Force.Matrix[MatrixNumber][ k ][l+m]; 389 if ((fabs(tmp) > MYEPSILON) && (tmp < stored)) { // current force is greater than stored 390 for (int m=NDIM;m--;) 391 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 392 stored = tmp; 393 } 394 } 395 } 396 396 }; 397 397 … … 399 399 * Results are stored in the matrix ForceMatrix::MatrixCounter of \a Force. 400 400 * \param Force ForceMatrix class containing matrix values 401 * \param MatrixNumber the index for the ForceMatrix::matrix array401 * \param MatrixNumber the index for the ForceMatrix::matrix array 402 402 */ 403 403 void CreateMeanForce(class MatrixContainer &Force, int MatrixNumber) 404 404 { 405 int divisor = 0;406 for (int l=Force.ColumnCounter;l--;)407 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;408 for (int l=5;l<Force.ColumnCounter;l+=3) {409 double tmp = 0;410 for (int k=Force.RowCounter[MatrixNumber];k--;) {411 double norm = 0.;412 for (int m=NDIM;m--;)413 norm += Force.Matrix[MatrixNumber][ k ][l+m] 414 * Force.Matrix[MatrixNumber][ k ][l+m];415 tmp += sqrt(norm);416 if (fabs(norm) > MYEPSILON) divisor++;417 }418 tmp /= (double)divisor;419 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = tmp;420 }405 int divisor = 0; 406 for (int l=Force.ColumnCounter;l--;) 407 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.; 408 for (int l=5;l<Force.ColumnCounter;l+=3) { 409 double tmp = 0; 410 for (int k=Force.RowCounter[MatrixNumber];k--;) { 411 double norm = 0.; 412 for (int m=NDIM;m--;) 413 norm += Force.Matrix[MatrixNumber][ k ][l+m] 414 * Force.Matrix[MatrixNumber][ k ][l+m]; 415 tmp += sqrt(norm); 416 if (fabs(norm) > MYEPSILON) divisor++; 417 } 418 tmp /= (double)divisor; 419 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = tmp; 420 } 421 421 }; 422 422 … … 428 428 void CreateMaximumForce(class MatrixContainer &Force, int MatrixNumber) 429 429 { 430 for (int l=5;l<Force.ColumnCounter;l+=3) {431 double stored = 0;432 for (int k=Force.RowCounter[MatrixNumber];k--;) {433 double tmp = 0;434 for (int m=NDIM;m--;)435 tmp += Force.Matrix[MatrixNumber][ k ][l+m] 436 * Force.Matrix[MatrixNumber][ k ][l+m];437 if (tmp > stored) {// current force is greater than stored438 for (int m=NDIM;m--;)439 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 440 stored = tmp;441 }442 }443 }430 for (int l=5;l<Force.ColumnCounter;l+=3) { 431 double stored = 0; 432 for (int k=Force.RowCounter[MatrixNumber];k--;) { 433 double tmp = 0; 434 for (int m=NDIM;m--;) 435 tmp += Force.Matrix[MatrixNumber][ k ][l+m] 436 * Force.Matrix[MatrixNumber][ k ][l+m]; 437 if (tmp > stored) { // current force is greater than stored 438 for (int m=NDIM;m--;) 439 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m]; 440 stored = tmp; 441 } 442 } 443 } 444 444 }; 445 445 … … 450 450 void CreateSameForce(class MatrixContainer &Force, int MatrixNumber) 451 451 { 452 // does nothing452 // does nothing 453 453 }; 454 454 … … 460 460 void CreateVectorSumForce(class MatrixContainer &Force, int MatrixNumber) 461 461 { 462 for (int l=Force.ColumnCounter;l--;)463 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;464 for (int l=0;l<Force.ColumnCounter;l++) {465 for (int k=Force.RowCounter[MatrixNumber];k--;)466 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] += Force.Matrix[MatrixNumber][k][l];467 }462 for (int l=Force.ColumnCounter;l--;) 463 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.; 464 for (int l=0;l<Force.ColumnCounter;l++) { 465 for (int k=Force.RowCounter[MatrixNumber];k--;) 466 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] += Force.Matrix[MatrixNumber][k][l]; 467 } 468 468 }; 469 469 … … 472 472 * \param *key position of key 473 473 * \param *logscale axis for logscale 474 * \param *extraline extra set lines if desired 474 * \param *extraline extra set lines if desired 475 475 * \param mxtics small tics at ... 476 476 * \param xtics large tics at ... 477 * \param *xlabel label for x axis 477 * \param *xlabel label for x axis 478 478 * \param *ylabel label for y axis 479 */ 479 */ 480 480 void CreatePlotHeader(ofstream &output, const char *prefix, const int keycolumns, const char *key, const char *logscale, const char *extraline, const int mxtics, const int xtics, const char *xlabel, const char *ylabel) 481 481 { 482 //output << "#!/home/heber/build/pyxplot/pyxplot" << endl << endl;483 output << "reset" << endl;484 output << "set keycolumns "<< keycolumns << endl;485 output << "set key " << key << endl;486 output << "set mxtics "<< mxtics << endl;487 output << "set xtics "<< xtics << endl;488 if (logscale != NULL)489 output << "set logscale " << logscale << endl;490 if (extraline != NULL)491 output << extraline << endl;492 output << "set xlabel '" << xlabel << "'" << endl;493 output << "set ylabel '" << ylabel << "'" << endl;494 output << "set terminal eps color" << endl;495 output << "set output '"<< prefix << ".eps'" << endl;482 //output << "#!/home/heber/build/pyxplot/pyxplot" << endl << endl; 483 output << "reset" << endl; 484 output << "set keycolumns "<< keycolumns << endl; 485 output << "set key " << key << endl; 486 output << "set mxtics "<< mxtics << endl; 487 output << "set xtics "<< xtics << endl; 488 if (logscale != NULL) 489 output << "set logscale " << logscale << endl; 490 if (extraline != NULL) 491 output << extraline << endl; 492 output << "set xlabel '" << xlabel << "'" << endl; 493 output << "set ylabel '" << ylabel << "'" << endl; 494 output << "set terminal eps color" << endl; 495 output << "set output '"<< prefix << ".eps'" << endl; 496 496 }; 497 497 … … 506 506 * \param mxtics small tics at ... 507 507 * \param xtics large tics at ... 508 * \param xlabel label for x axis 508 * \param xlabel label for x axis 509 509 * \param xlabel label for x axis 510 510 * \param *xrange xrange … … 514 514 * \param (*CreatePlotLines) function reference that writes a single plot line 515 515 * \return true if file was written successfully 516 */ 516 */ 517 517 bool CreatePlotOrder(class MatrixContainer &Matrix, const class KeySetsContainer &KeySet, const char *dir, const char *prefix, const int keycolumns, const char *key, const char *logscale, const char *extraline, const int mxtics, const int xtics, const char *xlabel, const char *ylabel, const char *xrange, const char *yrange, const char *xargument, const char *uses, void (*CreatePlotLines)(ofstream &, class MatrixContainer &, const char *, const char *, const char *)) 518 518 { 519 stringstream filename;520 ofstream output;521 522 filename << prefix << ".pyx";523 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 524 CreatePlotHeader(output, prefix, keycolumns, key, logscale, extraline, mxtics, xtics, xlabel, ylabel);525 output << "plot " << xrange << " " << yrange << " \\" << endl;526 CreatePlotLines(output, Matrix, prefix, xargument, uses);527 output.close(); 528 return true;519 stringstream filename; 520 ofstream output; 521 522 filename << prefix << ".pyx"; 523 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false; 524 CreatePlotHeader(output, prefix, keycolumns, key, logscale, extraline, mxtics, xtics, xlabel, ylabel); 525 output << "plot " << xrange << " " << yrange << " \\" << endl; 526 CreatePlotLines(output, Matrix, prefix, xargument, uses); 527 output.close(); 528 return true; 529 529 }; 530 530 … … 538 538 void AbsEnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses) 539 539 { 540 stringstream line(Energy.Header);541 string token;542 543 getline(line, token, '\t');544 for (int i=2; i<= Energy.ColumnCounter;i++) {545 getline(line, token, '\t');546 while (token[0] == ' ') // remove leading white spaces547 token.erase(0,1);548 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+2 << ")) " << uses;549 if (i != (Energy.ColumnCounter))550 output << ", \\";551 output << endl;552 }540 stringstream line(Energy.Header); 541 string token; 542 543 getline(line, token, '\t'); 544 for (int i=2; i<= Energy.ColumnCounter;i++) { 545 getline(line, token, '\t'); 546 while (token[0] == ' ') // remove leading white spaces 547 token.erase(0,1); 548 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+2 << ")) " << uses; 549 if (i != (Energy.ColumnCounter)) 550 output << ", \\"; 551 output << endl; 552 } 553 553 }; 554 554 … … 562 562 void EnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses) 563 563 { 564 stringstream line(Energy.Header);565 string token;566 567 getline(line, token, '\t');568 for (int i=1; i<= Energy.ColumnCounter;i++) {569 getline(line, token, '\t');570 while (token[0] == ' ') // remove leading white spaces571 token.erase(0,1);572 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":" << i+2 << " " << uses;573 if (i != (Energy.ColumnCounter))574 output << ", \\";575 output << endl;576 }564 stringstream line(Energy.Header); 565 string token; 566 567 getline(line, token, '\t'); 568 for (int i=1; i<= Energy.ColumnCounter;i++) { 569 getline(line, token, '\t'); 570 while (token[0] == ' ') // remove leading white spaces 571 token.erase(0,1); 572 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":" << i+2 << " " << uses; 573 if (i != (Energy.ColumnCounter)) 574 output << ", \\"; 575 output << endl; 576 } 577 577 }; 578 578 … … 586 586 void ForceMagnitudePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 587 587 { 588 stringstream line(Force.Header);589 string token;590 591 getline(line, token, '\t');592 getline(line, token, '\t');593 getline(line, token, '\t');594 getline(line, token, '\t');595 getline(line, token, '\t');596 for (int i=7; i< Force.ColumnCounter;i+=NDIM) {597 getline(line, token, '\t');598 while (token[0] == ' ') // remove leading white spaces599 token.erase(0,1);600 token.erase(token.length(), 1);// kill residual index char (the '0')601 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses;602 if (i != (Force.ColumnCounter-1))603 output << ", \\";604 output << endl;605 getline(line, token, '\t');606 getline(line, token, '\t');607 }588 stringstream line(Force.Header); 589 string token; 590 591 getline(line, token, '\t'); 592 getline(line, token, '\t'); 593 getline(line, token, '\t'); 594 getline(line, token, '\t'); 595 getline(line, token, '\t'); 596 for (int i=7; i< Force.ColumnCounter;i+=NDIM) { 597 getline(line, token, '\t'); 598 while (token[0] == ' ') // remove leading white spaces 599 token.erase(0,1); 600 token.erase(token.length(), 1); // kill residual index char (the '0') 601 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses; 602 if (i != (Force.ColumnCounter-1)) 603 output << ", \\"; 604 output << endl; 605 getline(line, token, '\t'); 606 getline(line, token, '\t'); 607 } 608 608 }; 609 609 … … 617 617 void AbsFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 618 618 { 619 stringstream line(Force.Header);620 string token;621 622 getline(line, token, '\t');623 getline(line, token, '\t');624 getline(line, token, '\t');625 getline(line, token, '\t');626 getline(line, token, '\t');627 for (int i=7; i< Force.ColumnCounter;i+=NDIM) {628 getline(line, token, '\t');629 while (token[0] == ' ') // remove leading white spaces630 token.erase(0,1);631 token.erase(token.length(), 1);// kill residual index char (the '0')632 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+1 << ")) " << uses;633 if (i != (Force.ColumnCounter-1))634 output << ", \\";635 output << endl;636 getline(line, token, '\t');637 getline(line, token, '\t');638 }619 stringstream line(Force.Header); 620 string token; 621 622 getline(line, token, '\t'); 623 getline(line, token, '\t'); 624 getline(line, token, '\t'); 625 getline(line, token, '\t'); 626 getline(line, token, '\t'); 627 for (int i=7; i< Force.ColumnCounter;i+=NDIM) { 628 getline(line, token, '\t'); 629 while (token[0] == ' ') // remove leading white spaces 630 token.erase(0,1); 631 token.erase(token.length(), 1); // kill residual index char (the '0') 632 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+1 << ")) " << uses; 633 if (i != (Force.ColumnCounter-1)) 634 output << ", \\"; 635 output << endl; 636 getline(line, token, '\t'); 637 getline(line, token, '\t'); 638 } 639 639 }; 640 640 … … 648 648 void BoxesForcePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 649 649 { 650 stringstream line(Force.Header);651 char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"};652 string token;653 654 getline(line, token, '\t');655 getline(line, token, '\t');656 getline(line, token, '\t');657 getline(line, token, '\t');658 getline(line, token, '\t');659 for (int i=7; i< Force.ColumnCounter;i+=NDIM) {660 getline(line, token, '\t');661 while (token[0] == ' ') // remove leading white spaces662 token.erase(0,1);663 token.erase(token.length(), 1);// kill residual index char (the '0')664 output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses << " " << fillcolor[(i-7)/3];665 if (i != (Force.ColumnCounter-1))666 output << ", \\";667 output << endl;668 getline(line, token, '\t');669 getline(line, token, '\t');670 }650 stringstream line(Force.Header); 651 char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"}; 652 string token; 653 654 getline(line, token, '\t'); 655 getline(line, token, '\t'); 656 getline(line, token, '\t'); 657 getline(line, token, '\t'); 658 getline(line, token, '\t'); 659 for (int i=7; i< Force.ColumnCounter;i+=NDIM) { 660 getline(line, token, '\t'); 661 while (token[0] == ' ') // remove leading white spaces 662 token.erase(0,1); 663 token.erase(token.length(), 1); // kill residual index char (the '0') 664 output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses << " " << fillcolor[(i-7)/3]; 665 if (i != (Force.ColumnCounter-1)) 666 output << ", \\"; 667 output << endl; 668 getline(line, token, '\t'); 669 getline(line, token, '\t'); 670 } 671 671 }; 672 672 … … 680 680 void BoxesFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses) 681 681 { 682 stringstream line(Force.Header);683 char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"};684 string token;685 686 getline(line, token, '\t');687 getline(line, token, '\t');688 getline(line, token, '\t');689 getline(line, token, '\t');690 getline(line, token, '\t');691 for (int i=7; i< Force.ColumnCounter;i+=NDIM) {692 getline(line, token, '\t');693 while (token[0] == ' ') // remove leading white spaces694 token.erase(0,1);695 token.erase(token.length(), 1);// kill residual index char (the '0')696 output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):" << i+1 << " " << uses << " " << fillcolor[(i-7)/3];697 if (i != (Force.ColumnCounter-1))698 output << ", \\";699 output << endl;700 getline(line, token, '\t');701 getline(line, token, '\t');702 }703 }; 682 stringstream line(Force.Header); 683 char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"}; 684 string token; 685 686 getline(line, token, '\t'); 687 getline(line, token, '\t'); 688 getline(line, token, '\t'); 689 getline(line, token, '\t'); 690 getline(line, token, '\t'); 691 for (int i=7; i< Force.ColumnCounter;i+=NDIM) { 692 getline(line, token, '\t'); 693 while (token[0] == ' ') // remove leading white spaces 694 token.erase(0,1); 695 token.erase(token.length(), 1); // kill residual index char (the '0') 696 output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):" << i+1 << " " << uses << " " << fillcolor[(i-7)/3]; 697 if (i != (Force.ColumnCounter-1)) 698 output << ", \\"; 699 output << endl; 700 getline(line, token, '\t'); 701 getline(line, token, '\t'); 702 } 703 }; -
Property mode
changed from
-
src/datacreator.hpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 1 1 /** \file datacreator.cpp 2 2 * 3 * Definitions of assisting functions in creating data and plot files. 4 * 3 * Definitions of assisting functions in creating data and plot files. 4 * 5 5 */ 6 6 … … 12 12 //============================ INCLUDES =========================== 13 13 14 #include "helpers.hpp" 14 #include "helpers.hpp" 15 15 #include "parser.hpp" 16 16 … … 20 20 bool AppendOutputFile(ofstream &output, const char *dir, const char *filename); 21 21 22 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 23 bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 22 bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 23 bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 24 24 bool CreateDataForcesOrder(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)); 25 25 bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 26 26 bool CreateDataDeltaForcesOrder(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)); 27 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 27 bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum); 28 28 bool CreateDataFragment(class MatrixContainer &ForceFragments, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateForce)(class MatrixContainer &, int)); 29 29 bool CreateDataFragmentOrder(class MatrixContainer &Fragment, class KeySetsContainer &KeySet, char *dir, char *prefix, char *msg, char *datum, void (*CreateFragmentOrder)(class MatrixContainer &, class KeySetsContainer &, int)); -
Property mode
changed from
-
src/defs.hpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 10 10 using namespace std; 11 11 12 #define MYEPSILON 1e-13 //!< machine epsilon precision13 #define NDIM 3//!< number of spatial dimensions14 #define MAX_ELEMENTS 128 //!< maximum number of elements for certain lookup tables15 #define AtomicLengthToAngstroem 0.52917721 //!< conversion factor from atomic length/bohrradius to angstroem16 #define BONDTHRESHOLD 0.5 //!< CSD threshold in bond check which is the width of the interval whose center is the sum of the covalent radii17 #define AtomicEnergyToKelvin 315774.67 //!< conversion factor from atomic energy to kelvin via boltzmann factor12 #define MYEPSILON 1e-13 //!< machine epsilon precision 13 #define NDIM 3 //!< number of spatial dimensions 14 #define MAX_ELEMENTS 128 //!< maximum number of elements for certain lookup tables 15 #define AtomicLengthToAngstroem 0.52917721 //!< conversion factor from atomic length/bohrradius to angstroem 16 #define BONDTHRESHOLD 0.5 //!< CSD threshold in bond check which is the width of the interval whose center is the sum of the covalent radii 17 #define AtomicEnergyToKelvin 315774.67 //!< conversion factor from atomic energy to kelvin via boltzmann factor 18 18 #define VERSIONSTRING "v1.0" 19 19 … … 24 24 enum EdgeType { Undetermined, TreeEdge, BackEdge }; //!< edge type in a graph after Depth-First-Search analysis. 25 25 26 enum Shading { white, lightgray, darkgray, black }; //!< color in Breadth-First-Search analysis26 enum Shading { white, lightgray, darkgray, black }; //!< color in Breadth-First-Search analysis 27 27 28 //enum CutCyclicBond { KeepBond, SaturateBond }; //!< Saturation scheme either atom- or bondwise28 //enum CutCyclicBond { KeepBond, SaturateBond }; //!< Saturation scheme either atom- or bondwise 29 29 30 30 // Specifting whether a value in the parameter file must be specified or is optional 31 enum necessity { optional, //!< parameter is optional, if not given sensible value is chosen32 critical//!< parameter must be given or programme won't initiate33 };31 enum necessity { optional, //!< parameter is optional, if not given sensible value is chosen 32 critical //!< parameter must be given or programme won't initiate 33 }; 34 34 35 35 // Specifying the status of the on command line given config file … … 43 43 44 44 // various standard filenames 45 #define DEFAULTCONFIG "main_pcp_linux" //!< default filename of config file46 #define CONVEXENVELOPE "ConvexEnvelope.dat" //!< default filename of convex envelope tecplot data file47 #define KEYSETFILE "KeySets.dat" //!< default filename of BOSSANOVA key sets file48 #define ADJACENCYFILE "Adjacency.dat" //!< default filename of BOSSANOVA adjacancy file49 #define TEFACTORSFILE "TE-Factors.dat" //!< default filename of BOSSANOVA total energy factors file50 #define FORCESFILE "Forces-Factors.dat" //!< default filename of BOSSANOVA force factors file51 #define HCORRECTIONSUFFIX "Hcorrection.dat" //!< default filename of BOSSANOVA H correction file (unwanted saturation interaction)52 #define FITCONSTANTSUFFIX "FitConstant.dat" //!< suffix of default filename of BOSSANOVA fit constants file (unwanted saturation interaction)53 #define SHIELDINGSUFFIX "sigma_all.csv" //!< default filename of BOSSANOVA shieldings file54 #define SHIELDINGPASSUFFIX "sigma_all_PAS.csv" //!< default filename of BOSSANOVA shieldings PAS file55 #define ORDERATSITEFILE "OrderAtSite.dat" //!< default filename of BOSSANOVA Bond Order at each atom file56 #define ENERGYPERFRAGMENT "EnergyPerFragment" //!< default filename of BOSSANOVA Energy contribution Per Fragment file57 #define FRAGMENTPREFIX "BondFragment" //!< default filename prefix of BOSSANOVA fragment config and directories58 #define STANDARDCONFIG "unknown.conf" //!< default filename of standard config file59 #define STANDARDELEMENTSDB "elements.db" //!< default filename of elements data base with masses, Z, VanDerWaals radii, ...60 #define STANDARDVALENCEDB "valence.db" //!< default filename of valence number per element database61 #define STANDARDORBITALDB "orbitals.db" //!< default filename of orbitals per element database62 #define STANDARDHBONDDISTANCEDB "Hbonddistance.db" //!< default filename of typial bond distance to hydrogen database63 #define STANDARDHBONDANGLEDB "Hbondangle.db" //!< default filename of typial bond angle to hydrogen database45 #define DEFAULTCONFIG "main_pcp_linux" //!< default filename of config file 46 #define CONVEXENVELOPE "ConvexEnvelope.dat" //!< default filename of convex envelope tecplot data file 47 #define KEYSETFILE "KeySets.dat" //!< default filename of BOSSANOVA key sets file 48 #define ADJACENCYFILE "Adjacency.dat" //!< default filename of BOSSANOVA adjacancy file 49 #define TEFACTORSFILE "TE-Factors.dat" //!< default filename of BOSSANOVA total energy factors file 50 #define FORCESFILE "Forces-Factors.dat" //!< default filename of BOSSANOVA force factors file 51 #define HCORRECTIONSUFFIX "Hcorrection.dat" //!< default filename of BOSSANOVA H correction file (unwanted saturation interaction) 52 #define FITCONSTANTSUFFIX "FitConstant.dat" //!< suffix of default filename of BOSSANOVA fit constants file (unwanted saturation interaction) 53 #define SHIELDINGSUFFIX "sigma_all.csv" //!< default filename of BOSSANOVA shieldings file 54 #define SHIELDINGPASSUFFIX "sigma_all_PAS.csv" //!< default filename of BOSSANOVA shieldings PAS file 55 #define ORDERATSITEFILE "OrderAtSite.dat" //!< default filename of BOSSANOVA Bond Order at each atom file 56 #define ENERGYPERFRAGMENT "EnergyPerFragment" //!< default filename of BOSSANOVA Energy contribution Per Fragment file 57 #define FRAGMENTPREFIX "BondFragment" //!< default filename prefix of BOSSANOVA fragment config and directories 58 #define STANDARDCONFIG "unknown.conf" //!< default filename of standard config file 59 #define STANDARDELEMENTSDB "elements.db" //!< default filename of elements data base with masses, Z, VanDerWaals radii, ... 60 #define STANDARDVALENCEDB "valence.db" //!< default filename of valence number per element database 61 #define STANDARDORBITALDB "orbitals.db" //!< default filename of orbitals per element database 62 #define STANDARDHBONDDISTANCEDB "Hbonddistance.db" //!< default filename of typial bond distance to hydrogen database 63 #define STANDARDHBONDANGLEDB "Hbondangle.db" //!< default filename of typial bond angle to hydrogen database 64 64 65 65 // some values … … 68 68 69 69 70 #define UPDATECOUNT 10 //!< update ten sites per BOSSANOVA interval70 #define UPDATECOUNT 10 //!< update ten sites per BOSSANOVA interval 71 71 72 72 #endif /*DEFS_HPP_*/ -
Property mode
changed from
-
src/element.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 12 12 */ 13 13 element::element() { 14 Z = -1;15 No = -1;16 previous = NULL;17 next = NULL;18 sort = NULL;14 Z = -1; 15 No = -1; 16 previous = NULL; 17 next = NULL; 18 sort = NULL; 19 19 }; 20 20 … … 28 28 bool element::Output(ofstream *out) const 29 29 { 30 if (out != NULL) {31 *out << name << "\t" << symbol << "\t" << period << "\t" << group << "\t" << block << "\t" << Z << "\t" << mass << "\t" << CovalentRadius << "\t" << VanDerWaalsRadius << endl;32 //*out << Z << "\t"<< fixed << setprecision(11) << showpoint << mass << "g/mol\t" << name << "\t" << symbol << "\t" << endl;33 return true;34 } else35 return false;30 if (out != NULL) { 31 *out << name << "\t" << symbol << "\t" << period << "\t" << group << "\t" << block << "\t" << Z << "\t" << mass << "\t" << CovalentRadius << "\t" << VanDerWaalsRadius << endl; 32 //*out << Z << "\t" << fixed << setprecision(11) << showpoint << mass << "g/mol\t" << name << "\t" << symbol << "\t" << endl; 33 return true; 34 } else 35 return false; 36 36 }; 37 37 38 38 /** Prints element data to \a *out. 39 39 * \param *out outstream 40 * \param No cardinal number of element40 * \param No cardinal number of element 41 41 * \param NoOfAtoms total number of atom of this element type 42 42 */ 43 43 bool element::Checkout(ofstream *out, const int Number, const int NoOfAtoms) const 44 44 { 45 if (out != NULL) {46 *out << "Ion_Type" << Number << "\t" << NoOfAtoms << "\t" << Z << "\t1.0\t3\t3\t" << fixed << setprecision(11) << showpoint << mass << "\t" << name << "\t" << symbol <<endl;47 return true;48 } else49 return false;45 if (out != NULL) { 46 *out << "Ion_Type" << Number << "\t" << NoOfAtoms << "\t" << Z << "\t1.0\t3\t3\t" << fixed << setprecision(11) << showpoint << mass << "\t" << name << "\t" << symbol <<endl; 47 return true; 48 } else 49 return false; 50 50 }; -
Property mode
changed from
-
src/elements.db
-
Property mode
changed from
100644to100755
-
Property mode
changed from
-
src/graph.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 1 1 /** \file graph.cpp 2 * 2 * 3 3 * Function implementations for the class graph. 4 * 4 * 5 5 */ 6 6 … … 15 15 16 16 17 -
Property mode
changed from
-
src/helpers.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 1 1 /** \file helpers.cpp 2 2 * 3 * Implementation of some auxiliary functions for memory dis-/allocation and so on 3 * Implementation of some auxiliary functions for memory dis-/allocation and so on 4 4 */ 5 5 … … 15 15 double ask_value(const char *text) 16 16 { 17 double test = 0.1439851348959832147598734598273456723948652983045928346598365;18 do {19 cout << Verbose(0) << text;20 cin >> test;21 } while (test == 0.1439851348959832147598734598273456723948652983045928346598365);22 return test; 17 double test = 0.1439851348959832147598734598273456723948652983045928346598365; 18 do { 19 cout << Verbose(0) << text; 20 cin >> test; 21 } while (test == 0.1439851348959832147598734598273456723948652983045928346598365); 22 return test; 23 23 }; 24 24 … … 29 29 #ifdef HAVE_DEBUG 30 30 void debug_in(const char *output, const char *file, const int line) { 31 if (output) fprintf(stderr,"DEBUG: in %s at line %i: %s\n", file, line, output);31 if (output) fprintf(stderr,"DEBUG: in %s at line %i: %s\n", file, line, output); 32 32 } 33 33 #else 34 void debug_in(const char *output, const char *file, const int line) {} // print nothing34 void debug_in(const char *output, const char *file, const int line) {} // print nothing 35 35 #endif 36 36 … … 40 40 * \return pointer to memory range 41 41 */ 42 void * Malloc(size_t size, const char* output) 42 void * Malloc(size_t size, const char* output) 43 43 { 44 void *buffer = NULL;45 buffer = (void *)malloc(size); // alloc46 if (buffer == NULL)47 cout << Verbose(0) << "Malloc failed - pointer is NULL: " << output << endl;48 return(buffer);44 void *buffer = NULL; 45 buffer = (void *)malloc(size); // alloc 46 if (buffer == NULL) 47 cout << Verbose(0) << "Malloc failed - pointer is NULL: " << output << endl; 48 return(buffer); 49 49 }; 50 50 … … 54 54 * \return pointer to memory range 55 55 */ 56 void * Calloc(size_t size, const char* output) 56 void * Calloc(size_t size, const char* output) 57 57 { 58 void *buffer = NULL;59 buffer = (void *)calloc(size, (size_t)0); // alloc60 if (buffer == NULL)61 cout << Verbose(0) << "Calloc failed - pointer is NULL: " << output << endl;62 return(buffer);58 void *buffer = NULL; 59 buffer = (void *)calloc(size, (size_t)0); // alloc 60 if (buffer == NULL) 61 cout << Verbose(0) << "Calloc failed - pointer is NULL: " << output << endl; 62 return(buffer); 63 63 }; 64 64 … … 69 69 * \return pointer to memory range 70 70 */ 71 void * ReAlloc(void * OldPointer, size_t size, const char* output) 71 void * ReAlloc(void * OldPointer, size_t size, const char* output) 72 72 { 73 void *buffer = NULL;74 if (OldPointer == NULL)75 //cout << Verbose(0) << "ReAlloc impossible - old is NULL: " << output << endl;76 buffer = (void *)malloc(size); // malloc77 else78 buffer = (void *)realloc(OldPointer, size); // realloc79 if (buffer == NULL)80 cout << Verbose(0) << "ReAlloc failed - new is NULL: " << output << endl;81 return(buffer);73 void *buffer = NULL; 74 if (OldPointer == NULL) 75 //cout << Verbose(0) << "ReAlloc impossible - old is NULL: " << output << endl; 76 buffer = (void *)malloc(size); // malloc 77 else 78 buffer = (void *)realloc(OldPointer, size); // realloc 79 if (buffer == NULL) 80 cout << Verbose(0) << "ReAlloc failed - new is NULL: " << output << endl; 81 return(buffer); 82 82 }; 83 83 … … 86 86 * \param *output message if free fails 87 87 */ 88 void Free(void ** buffer, const char* output) 88 void Free(void ** buffer, const char* output) 89 89 { 90 if (*buffer == NULL) {91 //cout << Verbose(5) << "Free not necesary: " << output << endl;92 } else {93 free(*buffer);94 *buffer = NULL;95 }90 if (*buffer == NULL) { 91 //cout << Verbose(5) << "Free not necesary: " << output << endl; 92 } else { 93 free(*buffer); 94 *buffer = NULL; 95 } 96 96 }; 97 97 … … 101 101 * \return pointer to string array 102 102 */ 103 char* MallocString(size_t size, const char* output) 103 char* MallocString(size_t size, const char* output) 104 104 { 105 size_t i;106 char *buffer;107 buffer = (char *)malloc(sizeof(char) * (size+1)); // alloc108 if (buffer == NULL)109 cout << Verbose(0) << output << endl;110 for (i=size;i--;)// reset111 buffer[i] = i % 2 == 0 ? 'p': 'c';112 buffer[size] = '\0'; // and set length marker on its end113 return(buffer);105 size_t i; 106 char *buffer; 107 buffer = (char *)malloc(sizeof(char) * (size+1)); // alloc 108 if (buffer == NULL) 109 cout << Verbose(0) << output << endl; 110 for (i=size;i--;) // reset 111 buffer[i] = i % 2 == 0 ? 'p': 'c'; 112 buffer[size] = '\0'; // and set length marker on its end 113 return(buffer); 114 114 } 115 115 … … 121 121 void bound(double *b, double lower_bound, double upper_bound) 122 122 { 123 double step = (upper_bound - lower_bound);124 while (*b >= upper_bound)125 *b -= step; 126 while (*b < lower_bound)127 *b += step; 128 }; 123 double step = (upper_bound - lower_bound); 124 while (*b >= upper_bound) 125 *b -= step; 126 while (*b < lower_bound) 127 *b += step; 128 }; 129 129 130 130 /** Flips two doubles. … … 134 134 void flip(double *x, double *y) 135 135 { 136 double tmp;137 tmp = *x;138 *x = *y;139 *y = tmp;136 double tmp; 137 tmp = *x; 138 *x = *y; 139 *y = tmp; 140 140 }; 141 141 … … 147 147 int pot(int base, int n) 148 148 { 149 int res = 1;150 int j;151 for (j=n;j--;)152 res *= base;153 return res;149 int res = 1; 150 int j; 151 for (j=n;j--;) 152 res *= base; 153 return res; 154 154 }; 155 155 … … 161 161 char *FixedDigitNumber(const int FragmentNumber, const int digits) 162 162 { 163 char *returnstring;164 int number = FragmentNumber;165 int order = 0;166 while (number != 0) { // determine number of digits needed167 number = (int)floor(((double)number / 10.));168 order++;169 //cout << "Number is " << number << ", order is " << order << "." << endl;170 }171 // allocate string172 returnstring = (char *) Malloc(sizeof(char)*(order+2), "MoleculeListClass::CreateFragmentNumberForOutput: *returnstring");173 // terminateand fill string array from end backward174 returnstring[order] = '\0';175 number = digits;176 for (int i=order;i--;) {177 returnstring[i] = '0' + (char)(number % 10);178 number = (int)floor(((double)number / 10.));179 }180 //cout << returnstring << endl;181 return returnstring;163 char *returnstring; 164 int number = FragmentNumber; 165 int order = 0; 166 while (number != 0) { // determine number of digits needed 167 number = (int)floor(((double)number / 10.)); 168 order++; 169 //cout << "Number is " << number << ", order is " << order << "." << endl; 170 } 171 // allocate string 172 returnstring = (char *) Malloc(sizeof(char)*(order+2), "MoleculeListClass::CreateFragmentNumberForOutput: *returnstring"); 173 // terminate and fill string array from end backward 174 returnstring[order] = '\0'; 175 number = digits; 176 for (int i=order;i--;) { 177 returnstring[i] = '0' + (char)(number % 10); 178 number = (int)floor(((double)number / 10.)); 179 } 180 //cout << returnstring << endl; 181 return returnstring; 182 182 }; 183 183 … … 186 186 * \return true - is a number, false - is not a valid number 187 187 */ 188 bool IsValidNumber( const char *string) 188 bool IsValidNumber( const char *string) 189 189 { 190 int ptr = 0;191 if ((string[ptr] == '.') || (string[ptr] == '-')) // number may be negative or start with dot192 ptr++;193 if ((string[ptr] >= '0') && (string[ptr] <= '9'))194 return true;195 return false;190 int ptr = 0; 191 if ((string[ptr] == '.') || (string[ptr] == '-')) // number may be negative or start with dot 192 ptr++; 193 if ((string[ptr] >= '0') && (string[ptr] <= '9')) 194 return true; 195 return false; 196 196 }; 197 197 -
Property mode
changed from
-
src/helpers.hpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 1 1 /** \file helpers.hpp 2 2 * 3 * Declaration of some auxiliary functions for memory dis-/allocation and so on 3 * Declaration of some auxiliary functions for memory dis-/allocation and so on 4 4 */ 5 5 … … 38 38 39 39 /* Behandelt aufgetretene Fehler. error ist der Fehlertyp(enum Errors) 40 void *SpecialData ist ein untypisierter Zeiger auf Spezielle Daten zur Fehlerbehandlung.41 Man koennte auch noch einen Zeiger auf eine Funktion uebergeben */40 void *SpecialData ist ein untypisierter Zeiger auf Spezielle Daten zur Fehlerbehandlung. 41 Man koennte auch noch einen Zeiger auf eine Funktion uebergeben */ 42 42 extern void /*@exits@*/ debug(const char *output); 43 //__attribute__ ((__return__));43 //__attribute__ ((__return__)); 44 44 #define debug(data) debug_in((data), __FILE__, __LINE__) 45 45 46 46 extern void /*@exits@*/ debug_in(const char *output, 47 const char *file, const int line);48 //__attribute__ ((__return__));47 const char *file, const int line); 48 //__attribute__ ((__return__)); 49 49 50 50 double ask_value(const char *text); … … 73 73 template <typename T> bool CreateFatherLookupTable(ofstream *out, T *start, T *end, T **&LookupTable, int count = 0) 74 74 { 75 bool status = true;76 T *Walker = NULL;77 int AtomNo;78 79 if (LookupTable != NULL) {80 *out << "Pointer for Lookup table is not NULL! Aborting ..." <<endl;81 return false;82 }83 84 // count them85 if (count == 0) {86 Walker = start;87 while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron 88 Walker = Walker->next;89 count = (count < Walker->GetTrueFather()->nr) ? Walker->GetTrueFather()->nr : count;90 }91 }92 if (count <= 0) {93 *out << "Count of lookup list is 0 or less." << endl;94 return false;95 }96 97 // allocat and fill98 LookupTable = (T **) Malloc(sizeof(T *)*count, "CreateFatherLookupTable - **LookupTable");99 if (LookupTable == NULL) {100 cerr << "LookupTable memory allocation failed!" << endl;101 status = false;102 } else {103 for (int i=0;i<count;i++)104 LookupTable[i] = NULL;105 Walker = start;106 while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron 107 Walker = Walker->next;108 AtomNo = Walker->GetTrueFather()->nr;109 if ((AtomNo >= 0) && (AtomNo < count)) {110 //*out << "Setting LookupTable[" << AtomNo << "] to " << *Walker << endl;111 LookupTable[AtomNo] = Walker;112 } else {113 *out << "Walker " << *Walker << " exceeded range of nuclear ids [0, " << count << ")." << endl; 114 status = false;115 break;116 }117 }118 }119 120 return status; 75 bool status = true; 76 T *Walker = NULL; 77 int AtomNo; 78 79 if (LookupTable != NULL) { 80 *out << "Pointer for Lookup table is not NULL! Aborting ..." <<endl; 81 return false; 82 } 83 84 // count them 85 if (count == 0) { 86 Walker = start; 87 while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron 88 Walker = Walker->next; 89 count = (count < Walker->GetTrueFather()->nr) ? Walker->GetTrueFather()->nr : count; 90 } 91 } 92 if (count <= 0) { 93 *out << "Count of lookup list is 0 or less." << endl; 94 return false; 95 } 96 97 // allocat and fill 98 LookupTable = (T **) Malloc(sizeof(T *)*count, "CreateFatherLookupTable - **LookupTable"); 99 if (LookupTable == NULL) { 100 cerr << "LookupTable memory allocation failed!" << endl; 101 status = false; 102 } else { 103 for (int i=0;i<count;i++) 104 LookupTable[i] = NULL; 105 Walker = start; 106 while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron 107 Walker = Walker->next; 108 AtomNo = Walker->GetTrueFather()->nr; 109 if ((AtomNo >= 0) && (AtomNo < count)) { 110 //*out << "Setting LookupTable[" << AtomNo << "] to " << *Walker << endl; 111 LookupTable[AtomNo] = Walker; 112 } else { 113 *out << "Walker " << *Walker << " exceeded range of nuclear ids [0, " << count << ")." << endl; 114 status = false; 115 break; 116 } 117 } 118 } 119 120 return status; 121 121 }; 122 122 … … 129 129 template <typename X> void link(X *walker, X *end) 130 130 { 131 X *vorher = end->previous;132 if (vorher != NULL)133 vorher->next = walker;134 end->previous = walker;135 walker->previous = vorher;136 walker->next = end;131 X *vorher = end->previous; 132 if (vorher != NULL) 133 vorher->next = walker; 134 end->previous = walker; 135 walker->previous = vorher; 136 walker->next = end; 137 137 }; 138 138 … … 143 143 template <typename X> void unlink(X *walker) 144 144 { 145 if (walker->next != NULL) 146 walker->next->previous = walker->previous;147 if (walker->previous != NULL)148 walker->previous->next = walker->next;145 if (walker->next != NULL) 146 walker->next->previous = walker->previous; 147 if (walker->previous != NULL) 148 walker->previous->next = walker->next; 149 149 }; 150 150 151 151 /** Adds new item before an item \a *end in a list. 152 * \param *pointer item to be added153 * \param *end end of list152 * \param *pointer item to be added 153 * \param *end end of list 154 154 * \return true - addition succeeded, false - unable to add item to list 155 155 */ 156 template <typename X> bool add(X *pointer, X *end)157 { 158 if (end != NULL) {159 link(pointer, end);160 } else {161 pointer->previous = NULL;162 pointer->next = NULL; 163 }164 return true;156 template <typename X> bool add(X *pointer, X *end) 157 { 158 if (end != NULL) { 159 link(pointer, end); 160 } else { 161 pointer->previous = NULL; 162 pointer->next = NULL; 163 } 164 return true; 165 165 }; 166 166 167 167 /** Finds item in list 168 * \param *suche search criteria169 * \param *start begin of list170 * \param *end end of list168 * \param *suche search criteria 169 * \param *start begin of list 170 * \param *end end of list 171 171 * \return X - if found, NULL - if not found 172 172 */ 173 173 template <typename X, typename Y> X * find(Y *suche, X *start, X *end) 174 174 { 175 X *walker = start;176 while (walker->next != end) { // go through list177 walker = walker->next; // step onward beforehand178 if (*walker->sort == *suche) return (walker);179 }180 return NULL;175 X *walker = start; 176 while (walker->next != end) { // go through list 177 walker = walker->next; // step onward beforehand 178 if (*walker->sort == *suche) return (walker); 179 } 180 return NULL; 181 181 }; 182 182 … … 187 187 template <typename X> void removewithoutcheck(X *walker) 188 188 { 189 if (walker != NULL) {190 unlink(walker);191 delete(walker);192 walker = NULL;193 }189 if (walker != NULL) { 190 unlink(walker); 191 delete(walker); 192 walker = NULL; 193 } 194 194 }; 195 195 196 196 /** Removes an item from the list, checks if exists. 197 197 * Checks beforehand if atom is really within molecule list. 198 * \param *pointer item to be removed199 * \param *start begin of list200 * \param *end end of list198 * \param *pointer item to be removed 199 * \param *start begin of list 200 * \param *end end of list 201 201 * \return true - removing succeeded, false - given item not found in list 202 202 */ 203 203 template <typename X> bool remove(X *pointer, X *start, X *end) 204 204 { 205 X *walker = find (pointer->sort, start, end);206 /* while (walker->next != pointer) { // search through list207 walker = walker->next;208 if (walker == end) return false;// item not found in list209 }*/210 // atom found, now unlink211 if (walker != NULL)212 removewithoutcheck(walker);213 else214 return false;215 return true;205 X *walker = find (pointer->sort, start, end); 206 /* while (walker->next != pointer) { // search through list 207 walker = walker->next; 208 if (walker == end) return false; // item not found in list 209 }*/ 210 // atom found, now unlink 211 if (walker != NULL) 212 removewithoutcheck(walker); 213 else 214 return false; 215 return true; 216 216 }; 217 217 … … 223 223 template <typename X> bool cleanup(X *start, X *end) 224 224 { 225 X *pointer = start->next;226 X *walker;227 while (pointer != end) { // go through list228 walker = pointer; // mark current229 pointer = pointer->next; // step onward beforehand230 // remove walker231 unlink(walker);232 delete(walker);233 walker = NULL;234 }235 return true;225 X *pointer = start->next; 226 X *walker; 227 while (pointer != end) { // go through list 228 walker = pointer; // mark current 229 pointer = pointer->next; // step onward beforehand 230 // remove walker 231 unlink(walker); 232 delete(walker); 233 walker = NULL; 234 } 235 return true; 236 236 }; 237 237 … … 242 242 template <typename X> X *GetFirst(X *me) 243 243 { 244 X *Binder = me;245 while(Binder->previous != NULL)246 Binder = Binder->previous;247 return Binder;248 }; 244 X *Binder = me; 245 while(Binder->previous != NULL) 246 Binder = Binder->previous; 247 return Binder; 248 }; 249 249 250 250 /** Returns the last marker in a chain list. … … 254 254 template <typename X> X *GetLast(X *me) 255 255 { 256 X *Binder = me;257 while(Binder->next != NULL)258 Binder = Binder->next;259 return Binder;260 }; 256 X *Binder = me; 257 while(Binder->next != NULL) 258 Binder = Binder->next; 259 return Binder; 260 }; 261 261 262 262 /** Frees a two-dimensional array. … … 266 266 template <typename X> void Free2DArray(X **ptr, int dim) 267 267 { 268 int i;269 if (ptr != NULL) {270 for(i=dim;i--;)271 if (ptr[i] != NULL)272 free(ptr[i]);273 free(ptr);274 }268 int i; 269 if (ptr != NULL) { 270 for(i=dim;i--;) 271 if (ptr[i] != NULL) 272 free(ptr[i]); 273 free(ptr); 274 } 275 275 }; 276 276 … … 281 281 class Verbose 282 282 { 283 public:284 Verbose(int value) : Verbosity(value) { }285 286 ostream& print (ostream &ost) const;287 private:288 int Verbosity;283 public: 284 Verbose(int value) : Verbosity(value) { } 285 286 ostream& print (ostream &ost) const; 287 private: 288 int Verbosity; 289 289 }; 290 290 … … 295 295 class Binary 296 296 { 297 public:298 Binary(int value) : BinaryNumber(value) { }299 300 ostream& print (ostream &ost) const;301 private:302 int BinaryNumber;297 public: 298 Binary(int value) : BinaryNumber(value) { } 299 300 ostream& print (ostream &ost) const; 301 private: 302 int BinaryNumber; 303 303 }; 304 304 -
Property mode
changed from
-
src/joiner.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 2 2 * 3 3 * Takes evaluated fragments (energy and forces) and by reading the factors files determines total energy 4 * and each force for the whole molecule. 5 * 4 * and each force for the whole molecule. 5 * 6 6 */ 7 7 8 8 //============================ INCLUDES =========================== 9 9 10 #include "datacreator.hpp" 11 #include "helpers.hpp" 12 #include "parser.hpp" 13 #include "periodentafel.hpp" 10 #include "datacreator.hpp" 11 #include "helpers.hpp" 12 #include "parser.hpp" 13 #include "periodentafel.hpp" 14 14 15 15 //============================== MAIN ============================= … … 17 17 int main(int argc, char **argv) 18 18 { 19 periodentafel *periode = NULL; // and a period table of all elements20 EnergyMatrix Energy;21 EnergyMatrix Hcorrection;22 ForceMatrix Force;23 EnergyMatrix EnergyFragments;24 EnergyMatrix HcorrectionFragments;25 ForceMatrix ForceFragments;26 ForceMatrix Shielding;27 ForceMatrix ShieldingPAS;28 ForceMatrix ShieldingFragments;29 ForceMatrix ShieldingPASFragments;30 KeySetsContainer KeySet; 31 stringstream prefix;32 char *dir = NULL;33 bool Hcorrected = true;19 periodentafel *periode = NULL; // and a period table of all elements 20 EnergyMatrix Energy; 21 EnergyMatrix Hcorrection; 22 ForceMatrix Force; 23 EnergyMatrix EnergyFragments; 24 EnergyMatrix HcorrectionFragments; 25 ForceMatrix ForceFragments; 26 ForceMatrix Shielding; 27 ForceMatrix ShieldingPAS; 28 ForceMatrix ShieldingFragments; 29 ForceMatrix ShieldingPASFragments; 30 KeySetsContainer KeySet; 31 stringstream prefix; 32 char *dir = NULL; 33 bool Hcorrected = true; 34 34 35 cout << "Joiner" << endl; 36 cout << "======" << endl; 37 38 // Get the command line options 39 if (argc < 3) { 40 cout << "Usage: " << argv[0] << " <inputdir> <prefix> [elementsdb]" << endl; 41 cout << "<inputdir>\ttherein the output of a molecuilder fragmentation is expected, each fragment with a subdir containing an energy.all and a forces.all file." << endl; 42 cout << "<prefix>\tprefix of energy and forces file." << endl; 43 cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl; 44 return 1; 45 } else { 46 dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir"); 47 strcpy(dir, "/"); 48 strcat(dir, argv[2]); 49 } 50 if (argc > 3) { 51 periode = new periodentafel; 52 periode->LoadPeriodentafel(argv[3]); 53 } 54 55 // Test the given directory 56 if (!TestParams(argc, argv)) 57 return 1; 58 59 // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++ 60 61 // ------------- Parse through all Fragment subdirs -------- 62 if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix, 0,0)) return 1; 63 Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX, 0,0); 64 if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix, 0,0)) return 1; 65 if (periode != NULL) { // also look for PAS values 66 if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1; 67 if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1; 68 } 35 cout << "Joiner" << endl; 36 cout << "======" << endl; 69 37 70 // ---------- Parse the TE Factors into an array ----------------- 71 if (!Energy.ParseIndices()) return 1; 72 if (Hcorrected) Hcorrection.ParseIndices(); 73 74 // ---------- Parse the Force indices into an array --------------- 75 if (!Force.ParseIndices(argv[1])) return 1; 38 // Get the command line options 39 if (argc < 3) { 40 cout << "Usage: " << argv[0] << " <inputdir> <prefix> [elementsdb]" << endl; 41 cout << "<inputdir>\ttherein the output of a molecuilder fragmentation is expected, each fragment with a subdir containing an energy.all and a forces.all file." << endl; 42 cout << "<prefix>\tprefix of energy and forces file." << endl; 43 cout << "[elementsdb]\tpath to elements database, needed for shieldings." << endl; 44 return 1; 45 } else { 46 dir = (char *) Malloc(sizeof(char)*(strlen(argv[2])+2), "main: *dir"); 47 strcpy(dir, "/"); 48 strcat(dir, argv[2]); 49 } 50 if (argc > 3) { 51 periode = new periodentafel; 52 periode->LoadPeriodentafel(argv[3]); 53 } 76 54 77 // ---------- Parse the shielding indices into an array --------------- 78 if (periode != NULL) { // also look for PAS values 79 if(!Shielding.ParseIndices(argv[1])) return 1; 80 if(!ShieldingPAS.ParseIndices(argv[1])) return 1; 81 } 55 // Test the given directory 56 if (!TestParams(argc, argv)) 57 return 1; 82 58 83 // ---------- Parse the KeySets into an array --------------- 84 if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1; 59 // +++++++++++++++++ PARSING +++++++++++++++++++++++++++++++ 85 60 86 if (!KeySet.ParseManyBodyTerms()) return 1; 87 if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return 1; 88 if (Hcorrected) HcorrectionFragments.AllocateMatrix(Hcorrection.Header, Hcorrection.MatrixCounter, Hcorrection.RowCounter, Hcorrection.ColumnCounter); 89 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1; 90 if (periode != NULL) { // also look for PAS values 91 if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1; 92 if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1; 93 } 94 95 // ----------- Resetting last matrices (where full QM values are stored right now) 96 if(!Energy.SetLastMatrix(0., 0)) return 1; 97 if(!Force.SetLastMatrix(0., 2)) return 1; 98 if (periode != NULL) { // also look for PAS values 99 if(!Shielding.SetLastMatrix(0., 2)) return 1; 100 if(!ShieldingPAS.SetLastMatrix(0., 2)) return 1; 101 } 61 // ------------- Parse through all Fragment subdirs -------- 62 if (!Energy.ParseFragmentMatrix(argv[1], dir, EnergySuffix, 0,0)) return 1; 63 Hcorrected = Hcorrection.ParseFragmentMatrix(argv[1], "", HCORRECTIONSUFFIX, 0,0); 64 if (!Force.ParseFragmentMatrix(argv[1], dir, ForcesSuffix, 0,0)) return 1; 65 if (periode != NULL) { // also look for PAS values 66 if (!Shielding.ParseFragmentMatrix(argv[1], dir, ShieldingSuffix, 1, 0)) return 1; 67 if (!ShieldingPAS.ParseFragmentMatrix(argv[1], dir, ShieldingPASSuffix, 1, 0)) return 1; 68 } 102 69 103 // +++++++++++++++++ SUMMING +++++++++++++++++++++++++++++++ 70 // ---------- Parse the TE Factors into an array ----------------- 71 if (!Energy.ParseIndices()) return 1; 72 if (Hcorrected) Hcorrection.ParseIndices(); 104 73 105 // --------- sum up and write for each order---------------- 106 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 107 // --------- sum up energy -------------------- 108 cout << "Summing energy of order " << BondOrder+1 << " ..." << endl; 109 if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return 1; 110 if (Hcorrected) { 111 HcorrectionFragments.SumSubManyBodyTerms(Hcorrection, KeySet, BondOrder); 112 if (!Energy.SumSubEnergy(EnergyFragments, &HcorrectionFragments, KeySet, BondOrder, 1.)) return 1; 113 if (Hcorrected) Hcorrection.SumSubEnergy(HcorrectionFragments, NULL, KeySet, BondOrder, 1.); 114 } else 115 if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return 1; 116 // --------- sum up Forces -------------------- 117 cout << "Summing forces of order " << BondOrder+1 << " ..." << endl; 118 if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return 1; 119 if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return 1; 120 if (periode != NULL) { // also look for PAS values 121 cout << "Summing shieldings of order " << BondOrder+1 << " ..." << endl; 122 if (!ShieldingFragments.SumSubManyBodyTerms(Shielding, KeySet, BondOrder)) return 1; 123 if (!Shielding.SumSubForces(ShieldingFragments, KeySet, BondOrder, 1.)) return 1; 124 if (!ShieldingPASFragments.SumSubManyBodyTerms(ShieldingPAS, KeySet, BondOrder)) return 1; 125 if (!ShieldingPAS.SumSubForces(ShieldingPASFragments, KeySet, BondOrder, 1.)) return 1; 126 } 74 // ---------- Parse the Force indices into an array --------------- 75 if (!Force.ParseIndices(argv[1])) return 1; 127 76 128 // --------- write the energy and forces file -------------------- 129 prefix.str(" "); 130 prefix << dir << OrderSuffix << (BondOrder+1); 131 cout << "Writing files " << argv[1] << prefix.str() << ". ..." << endl; 132 // energy 133 if (!Energy.WriteLastMatrix(argv[1], (prefix.str()).c_str(), EnergySuffix)) return 1; 134 // forces 135 if (!Force.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ForcesSuffix)) return 1; 136 // shieldings 137 if (periode != NULL) { // also look for PAS values 138 if (!Shielding.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingSuffix)) return 1; 139 if (!ShieldingPAS.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingPASSuffix)) return 1; 140 } 141 } 142 // fragments 143 prefix.str(" "); 144 prefix << dir << EnergyFragmentSuffix; 145 if (!EnergyFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 146 if (Hcorrected) { 147 prefix.str(" "); 148 prefix << dir << HcorrectionFragmentSuffix; 149 if (!HcorrectionFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 150 } 151 prefix.str(" "); 152 prefix << dir << ForceFragmentSuffix; 153 if (!ForceFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 154 if (!CreateDataFragment(EnergyFragments, KeySet, argv[1], FRAGMENTPREFIX ENERGYPERFRAGMENT, "fragment energy versus the Fragment No", "today", CreateEnergy)) return 1; 155 if (periode != NULL) { // also look for PAS values 156 prefix.str(" "); 157 prefix << dir << ShieldingFragmentSuffix; 158 if (!ShieldingFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 159 prefix.str(" "); 160 prefix << dir << ShieldingPASFragmentSuffix; 161 if (!ShieldingPASFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 162 } 77 // ---------- Parse the shielding indices into an array --------------- 78 if (periode != NULL) { // also look for PAS values 79 if(!Shielding.ParseIndices(argv[1])) return 1; 80 if(!ShieldingPAS.ParseIndices(argv[1])) return 1; 81 } 163 82 164 // write last matrices as fragments into central dir (not subdir as above), for analyzer to know index bounds 165 if (!Energy.WriteLastMatrix(argv[1], dir, EnergyFragmentSuffix)) return 1; 166 if (Hcorrected) Hcorrection.WriteLastMatrix(argv[1], dir, HcorrectionFragmentSuffix); 167 if (!Force.WriteLastMatrix(argv[1], dir, ForceFragmentSuffix)) return 1; 168 if (periode != NULL) { // also look for PAS values 169 if (!Shielding.WriteLastMatrix(argv[1], dir, ShieldingFragmentSuffix)) return 1; 170 if (!ShieldingPAS.WriteLastMatrix(argv[1], dir, ShieldingPASFragmentSuffix)) return 1; 171 } 83 // ---------- Parse the KeySets into an array --------------- 84 if (!KeySet.ParseKeySets(argv[1], Force.RowCounter, Force.MatrixCounter)) return 1; 172 85 173 // exit 174 delete(periode); 175 Free((void **)&dir, "main: *dir"); 176 cout << "done." << endl; 177 return 0; 86 if (!KeySet.ParseManyBodyTerms()) return 1; 87 if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return 1; 88 if (Hcorrected) HcorrectionFragments.AllocateMatrix(Hcorrection.Header, Hcorrection.MatrixCounter, Hcorrection.RowCounter, Hcorrection.ColumnCounter); 89 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return 1; 90 if (periode != NULL) { // also look for PAS values 91 if (!ShieldingFragments.AllocateMatrix(Shielding.Header, Shielding.MatrixCounter, Shielding.RowCounter, Shielding.ColumnCounter)) return 1; 92 if (!ShieldingPASFragments.AllocateMatrix(ShieldingPAS.Header, ShieldingPAS.MatrixCounter, ShieldingPAS.RowCounter, ShieldingPAS.ColumnCounter)) return 1; 93 } 94 95 // ----------- Resetting last matrices (where full QM values are stored right now) 96 if(!Energy.SetLastMatrix(0., 0)) return 1; 97 if(!Force.SetLastMatrix(0., 2)) return 1; 98 if (periode != NULL) { // also look for PAS values 99 if(!Shielding.SetLastMatrix(0., 2)) return 1; 100 if(!ShieldingPAS.SetLastMatrix(0., 2)) return 1; 101 } 102 103 // +++++++++++++++++ SUMMING +++++++++++++++++++++++++++++++ 104 105 // --------- sum up and write for each order---------------- 106 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) { 107 // --------- sum up energy -------------------- 108 cout << "Summing energy of order " << BondOrder+1 << " ..." << endl; 109 if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return 1; 110 if (Hcorrected) { 111 HcorrectionFragments.SumSubManyBodyTerms(Hcorrection, KeySet, BondOrder); 112 if (!Energy.SumSubEnergy(EnergyFragments, &HcorrectionFragments, KeySet, BondOrder, 1.)) return 1; 113 if (Hcorrected) Hcorrection.SumSubEnergy(HcorrectionFragments, NULL, KeySet, BondOrder, 1.); 114 } else 115 if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return 1; 116 // --------- sum up Forces -------------------- 117 cout << "Summing forces of order " << BondOrder+1 << " ..." << endl; 118 if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return 1; 119 if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return 1; 120 if (periode != NULL) { // also look for PAS values 121 cout << "Summing shieldings of order " << BondOrder+1 << " ..." << endl; 122 if (!ShieldingFragments.SumSubManyBodyTerms(Shielding, KeySet, BondOrder)) return 1; 123 if (!Shielding.SumSubForces(ShieldingFragments, KeySet, BondOrder, 1.)) return 1; 124 if (!ShieldingPASFragments.SumSubManyBodyTerms(ShieldingPAS, KeySet, BondOrder)) return 1; 125 if (!ShieldingPAS.SumSubForces(ShieldingPASFragments, KeySet, BondOrder, 1.)) return 1; 126 } 127 128 // --------- write the energy and forces file -------------------- 129 prefix.str(" "); 130 prefix << dir << OrderSuffix << (BondOrder+1); 131 cout << "Writing files " << argv[1] << prefix.str() << ". ..." << endl; 132 // energy 133 if (!Energy.WriteLastMatrix(argv[1], (prefix.str()).c_str(), EnergySuffix)) return 1; 134 // forces 135 if (!Force.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ForcesSuffix)) return 1; 136 // shieldings 137 if (periode != NULL) { // also look for PAS values 138 if (!Shielding.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingSuffix)) return 1; 139 if (!ShieldingPAS.WriteLastMatrix(argv[1], (prefix.str()).c_str(), ShieldingPASSuffix)) return 1; 140 } 141 } 142 // fragments 143 prefix.str(" "); 144 prefix << dir << EnergyFragmentSuffix; 145 if (!EnergyFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 146 if (Hcorrected) { 147 prefix.str(" "); 148 prefix << dir << HcorrectionFragmentSuffix; 149 if (!HcorrectionFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 150 } 151 prefix.str(" "); 152 prefix << dir << ForceFragmentSuffix; 153 if (!ForceFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 154 if (!CreateDataFragment(EnergyFragments, KeySet, argv[1], FRAGMENTPREFIX ENERGYPERFRAGMENT, "fragment energy versus the Fragment No", "today", CreateEnergy)) return 1; 155 if (periode != NULL) { // also look for PAS values 156 prefix.str(" "); 157 prefix << dir << ShieldingFragmentSuffix; 158 if (!ShieldingFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 159 prefix.str(" "); 160 prefix << dir << ShieldingPASFragmentSuffix; 161 if (!ShieldingPASFragments.WriteTotalFragments(argv[1], (prefix.str()).c_str())) return 1; 162 } 163 164 // write last matrices as fragments into central dir (not subdir as above), for analyzer to know index bounds 165 if (!Energy.WriteLastMatrix(argv[1], dir, EnergyFragmentSuffix)) return 1; 166 if (Hcorrected) Hcorrection.WriteLastMatrix(argv[1], dir, HcorrectionFragmentSuffix); 167 if (!Force.WriteLastMatrix(argv[1], dir, ForceFragmentSuffix)) return 1; 168 if (periode != NULL) { // also look for PAS values 169 if (!Shielding.WriteLastMatrix(argv[1], dir, ShieldingFragmentSuffix)) return 1; 170 if (!ShieldingPAS.WriteLastMatrix(argv[1], dir, ShieldingPASFragmentSuffix)) return 1; 171 } 172 173 // exit 174 delete(periode); 175 Free((void **)&dir, "main: *dir"); 176 cout << "done." << endl; 177 return 0; 178 178 }; 179 179 -
Property mode
changed from
-
src/linkedcell.cpp
r124df1 r6ac7ee 6 6 LinkedCell::LinkedCell() 7 7 { 8 LC = NULL;9 for(int i=0;i<NDIM;i++)10 N[i] = 0;11 index = -1;12 RADIUS = 0.;13 max.Zero();14 min.Zero();8 LC = NULL; 9 for(int i=0;i<NDIM;i++) 10 N[i] = 0; 11 index = -1; 12 RADIUS = 0.; 13 max.Zero(); 14 min.Zero(); 15 15 }; 16 16 … … 21 21 LinkedCell::LinkedCell(molecule *mol, double radius) 22 22 { 23 atom *Walker = NULL;23 atom *Walker = NULL; 24 24 25 RADIUS = radius;26 LC = NULL;27 for(int i=0;i<NDIM;i++)28 N[i] = 0;29 index = -1;30 max.Zero();31 min.Zero();32 cout << Verbose(1) << "Begin of LinkedCell" << endl;33 if (mol->start->next == mol->end) {34 cerr << "ERROR: molecule contains no atoms!" << endl;35 return;36 }37 // 1. find max and min per axis of atoms38 Walker = mol->start->next;39 for (int i=0;i<NDIM;i++) {40 max.x[i] = Walker->x.x[i];41 min.x[i] = Walker->x.x[i];42 }43 while (Walker != mol->end) {44 for (int i=0;i<NDIM;i++) {45 if (max.x[i] < Walker->x.x[i])46 max.x[i] = Walker->x.x[i];47 if (min.x[i] > Walker->x.x[i])48 min.x[i] = Walker->x.x[i];49 }50 Walker = Walker->next;51 }52 cout << Verbose(2) << "Bounding box is " << min << " and " << max << "." << endl;53 54 // 2. find then umber of cells per axis55 for (int i=0;i<NDIM;i++) {56 N[i] = (int)floor((max.x[i] - min.x[i])/RADIUS)+1;57 }58 cout << Verbose(2) << "Number of cells per axis are " << N[0] << ", " << N[1] << " and " << N[2] << "." << endl;59 60 // 3. allocate the lists 61 cout << Verbose(2) << "Allocating cells ... " << endl;62 if (LC != NULL) {63 cout << Verbose(1) << "ERROR: Linked Cell list is already allocated, I do nothing." << endl;64 return;65 }66 LC = new LinkedAtoms[N[0]*N[1]*N[2]]; 67 for (index=0;index<N[0]*N[1]*N[2];index++) {68 LC [index].clear(); 69 }70 71 // 4. put each atom into its respective cell 72 Walker = mol->start;73 while (Walker->next != mol->end) {74 Walker = Walker->next;75 for (int i=0;i<NDIM;i++) {76 n[i] = (int)floor((Walker->x.x[i] - min.x[i])/RADIUS);77 }78 index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];79 LC[index].push_back(Walker);80 cout << Verbose(2) << *Walker << " goes into cell " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl;81 }82 cout << Verbose(1) << "End of LinkedCell" << endl;25 RADIUS = radius; 26 LC = NULL; 27 for(int i=0;i<NDIM;i++) 28 N[i] = 0; 29 index = -1; 30 max.Zero(); 31 min.Zero(); 32 cout << Verbose(1) << "Begin of LinkedCell" << endl; 33 if (mol->start->next == mol->end) { 34 cerr << "ERROR: molecule contains no atoms!" << endl; 35 return; 36 } 37 // 1. find max and min per axis of atoms 38 Walker = mol->start->next; 39 for (int i=0;i<NDIM;i++) { 40 max.x[i] = Walker->x.x[i]; 41 min.x[i] = Walker->x.x[i]; 42 } 43 while (Walker != mol->end) { 44 for (int i=0;i<NDIM;i++) { 45 if (max.x[i] < Walker->x.x[i]) 46 max.x[i] = Walker->x.x[i]; 47 if (min.x[i] > Walker->x.x[i]) 48 min.x[i] = Walker->x.x[i]; 49 } 50 Walker = Walker->next; 51 } 52 cout << Verbose(2) << "Bounding box is " << min << " and " << max << "." << endl; 53 54 // 2. find then umber of cells per axis 55 for (int i=0;i<NDIM;i++) { 56 N[i] = (int)floor((max.x[i] - min.x[i])/RADIUS)+1; 57 } 58 cout << Verbose(2) << "Number of cells per axis are " << N[0] << ", " << N[1] << " and " << N[2] << "." << endl; 59 60 // 3. allocate the lists 61 cout << Verbose(2) << "Allocating cells ... " << endl; 62 if (LC != NULL) { 63 cout << Verbose(1) << "ERROR: Linked Cell list is already allocated, I do nothing." << endl; 64 return; 65 } 66 LC = new LinkedAtoms[N[0]*N[1]*N[2]]; 67 for (index=0;index<N[0]*N[1]*N[2];index++) { 68 LC [index].clear(); 69 } 70 71 // 4. put each atom into its respective cell 72 Walker = mol->start; 73 while (Walker->next != mol->end) { 74 Walker = Walker->next; 75 for (int i=0;i<NDIM;i++) { 76 n[i] = (int)floor((Walker->x.x[i] - min.x[i])/RADIUS); 77 } 78 index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2]; 79 LC[index].push_back(Walker); 80 cout << Verbose(2) << *Walker << " goes into cell " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl; 81 } 82 cout << Verbose(1) << "End of LinkedCell" << endl; 83 83 }; 84 84 … … 87 87 LinkedCell::~LinkedCell() 88 88 { 89 if (LC != NULL)90 for (index=0;index<N[0]*N[1]*N[2];index++)91 LC[index].clear();92 delete[](LC);93 for(int i=0;i<NDIM;i++)94 N[i] = 0;95 index = -1;96 max.Zero();97 min.Zero();89 if (LC != NULL) 90 for (index=0;index<N[0]*N[1]*N[2];index++) 91 LC[index].clear(); 92 delete[](LC); 93 for(int i=0;i<NDIM;i++) 94 N[i] = 0; 95 index = -1; 96 max.Zero(); 97 min.Zero(); 98 98 }; 99 99 … … 103 103 bool LinkedCell::CheckBounds() 104 104 { 105 bool status = true;106 for(int i=0;i<NDIM;i++)107 status = status && ((n[i] >=0) && (n[i] < N[i]));108 if (!status)109 cerr << "ERROR: indices are out of bounds!" << endl;110 return status;105 bool status = true; 106 for(int i=0;i<NDIM;i++) 107 status = status && ((n[i] >=0) && (n[i] < N[i])); 108 if (!status) 109 cerr << "ERROR: indices are out of bounds!" << endl; 110 return status; 111 111 }; 112 112 … … 117 117 LinkedAtoms* LinkedCell::GetCurrentCell() 118 118 { 119 if (CheckBounds()) {120 index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];121 return (&(LC[index]));122 } else {123 return NULL;124 }119 if (CheckBounds()) { 120 index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2]; 121 return (&(LC[index])); 122 } else { 123 return NULL; 124 } 125 125 }; 126 126 … … 131 131 bool LinkedCell::SetIndexToAtom(atom *Walker) 132 132 { 133 bool status = false;134 for (int i=0;i<NDIM;i++) {135 n[i] = (int)floor((Walker->x.x[i] - min.x[i])/RADIUS);136 }137 index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];138 if (CheckBounds()) {139 for (LinkedAtoms::iterator Runner = LC[index].begin(); Runner != LC[index].end(); Runner++)140 status = status || ((*Runner) == Walker);141 return status;142 } else {143 cerr << Verbose(1) << "ERROR: Atom "<< *Walker << " at " << Walker->x << " is out of bounds." << endl;144 return false;145 }133 bool status = false; 134 for (int i=0;i<NDIM;i++) { 135 n[i] = (int)floor((Walker->x.x[i] - min.x[i])/RADIUS); 136 } 137 index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2]; 138 if (CheckBounds()) { 139 for (LinkedAtoms::iterator Runner = LC[index].begin(); Runner != LC[index].end(); Runner++) 140 status = status || ((*Runner) == Walker); 141 return status; 142 } else { 143 cerr << Verbose(1) << "ERROR: Atom "<< *Walker << " at " << Walker->x << " is out of bounds." << endl; 144 return false; 145 } 146 146 }; 147 147 … … 152 152 bool LinkedCell::SetIndexToVector(Vector *x) 153 153 { 154 bool status = true;155 for (int i=0;i<NDIM;i++) {156 n[i] = (int)floor((x->x[i] - min.x[i])/RADIUS);157 if (max.x[i] < x->x[i])158 status = false;159 if (min.x[i] > x->x[i])160 status = false;161 }162 return status;154 bool status = true; 155 for (int i=0;i<NDIM;i++) { 156 n[i] = (int)floor((x->x[i] - min.x[i])/RADIUS); 157 if (max.x[i] < x->x[i]) 158 status = false; 159 if (min.x[i] > x->x[i]) 160 status = false; 161 } 162 return status; 163 163 }; 164 -
src/linkedcell.hpp
r124df1 r6ac7ee 9 9 #include "molecules.hpp" 10 10 11 #define LinkedAtoms list <atom *> 12 11 13 class LinkedCell{ 12 public: 13 Vector max; // upper boundary 14 Vector min; // lower boundary 15 LinkedAtoms *LC; // linked cell list 16 double RADIUS; // cell edge length 17 int N[NDIM]; // number of cells per axis 18 int n[NDIM]; // temporary variable for current cell per axis 19 int index; // temporary index variable , access by index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2]; 20 21 LinkedCell(); 22 LinkedCell(molecule *mol, double RADIUS); 23 ~LinkedCell(); 24 LinkedAtoms* GetCurrentCell(); 25 bool SetIndexToAtom(atom *Walker); 26 bool SetIndexToVector(Vector *x); 27 bool CheckBounds(); 14 public: 15 Vector max; // upper boundary 16 Vector min; // lower boundary 17 LinkedAtoms *LC; // linked cell list 18 double RADIUS; // cell edge length 19 int N[NDIM]; // number of cells per axis 20 int n[NDIM]; // temporary variable for current cell per axis 21 int index; // temporary index variable , access by index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2]; 22 23 LinkedCell(); 24 LinkedCell(molecule *mol, double RADIUS); 25 ~LinkedCell(); 26 LinkedAtoms* GetCurrentCell(); 27 bool SetIndexToAtom(atom *Walker); 28 bool SetIndexToVector(Vector *x); 29 bool CheckBounds(); 30 31 // not implemented yet 32 bool AddAtom(atom *Walker); 33 bool DeleteAtom(atom *Walker); 34 bool MoveAtom(atom *Walker); 28 35 }; 29 36 -
src/moleculelist.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 21 21 MoleculeListClass::MoleculeListClass(int NumMolecules, int NumAtoms) 22 22 { 23 ListOfMolecules = (molecule **) Malloc(sizeof(molecule *)*NumMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");24 for (int i=NumMolecules;i--;)25 ListOfMolecules[i] = NULL;26 NumberOfMolecules = NumMolecules;27 NumberOfTopAtoms = NumAtoms;23 ListOfMolecules = (molecule **) Malloc(sizeof(molecule *)*NumMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules"); 24 for (int i=NumMolecules;i--;) 25 ListOfMolecules[i] = NULL; 26 NumberOfMolecules = NumMolecules; 27 NumberOfTopAtoms = NumAtoms; 28 28 }; 29 29 … … 33 33 MoleculeListClass::~MoleculeListClass() 34 34 { 35 cout << Verbose(3) << this << ": Freeing ListOfMolcules." << endl;36 for (int i=NumberOfMolecules;i--;) {37 if (ListOfMolecules[i] != NULL) { // if NULL don't free38 cout << Verbose(4) << "ListOfMolecules: Freeing " << ListOfMolecules[i] << "." << endl;39 delete(ListOfMolecules[i]);40 ListOfMolecules[i] = NULL;41 }42 }43 cout << Verbose(4) << "Freeing ListOfMolecules." << endl;44 Free((void **)&ListOfMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");35 cout << Verbose(3) << this << ": Freeing ListOfMolcules." << endl; 36 for (int i=NumberOfMolecules;i--;) { 37 if (ListOfMolecules[i] != NULL) { // if NULL don't free 38 cout << Verbose(4) << "ListOfMolecules: Freeing " << ListOfMolecules[i] << "." << endl; 39 delete(ListOfMolecules[i]); 40 ListOfMolecules[i] = NULL; 41 } 42 } 43 cout << Verbose(4) << "Freeing ListOfMolecules." << endl; 44 Free((void **)&ListOfMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules"); 45 45 }; 46 46 … … 52 52 int MolCompare(const void *a, const void *b) 53 53 { 54 int *aList = NULL, *bList = NULL;55 int Count, Counter, aCounter, bCounter;56 int flag;57 atom *aWalker = NULL;58 atom *bWalker = NULL;59 60 // sort each atom list and put the numbers into a list, then go through61 //cout << "Comparing fragment no. " << *(molecule **)a << " to " << *(molecule **)b << "." << endl;62 if ( (**(molecule **)a).AtomCount < (**(molecule **)b).AtomCount ) {63 return -1;64 } else { if ((**(molecule **)a).AtomCount > (**(molecule **)b).AtomCount)65 return +1;66 else {67 Count = (**(molecule **)a).AtomCount;68 aList = new int[Count];69 bList = new int[Count];70 71 // fill the lists72 aWalker = (**(molecule **)a).start;73 bWalker = (**(molecule **)b).start;74 Counter = 0;75 aCounter = 0;76 bCounter = 0;77 while ((aWalker->next != (**(molecule **)a).end) && (bWalker->next != (**(molecule **)b).end)) {78 aWalker = aWalker->next;79 bWalker = bWalker->next;80 if (aWalker->GetTrueFather() == NULL)81 aList[Counter] = Count + (aCounter++);82 else83 aList[Counter] = aWalker->GetTrueFather()->nr;84 if (bWalker->GetTrueFather() == NULL)85 bList[Counter] = Count + (bCounter++);86 else87 bList[Counter] = bWalker->GetTrueFather()->nr;88 Counter++;89 }90 // check if AtomCount was for real91 flag = 0;92 if ((aWalker->next == (**(molecule **)a).end) && (bWalker->next != (**(molecule **)b).end)) {93 flag = -1;94 } else {95 if ((aWalker->next != (**(molecule **)a).end) && (bWalker->next == (**(molecule **)b).end))96 flag = 1;97 }98 if (flag == 0) {99 // sort the lists100 gsl_heapsort(aList,Count, sizeof(int), CompareDoubles);101 gsl_heapsort(bList,Count, sizeof(int), CompareDoubles);102 // compare the lists103 104 flag = 0;105 for(int i=0;i<Count;i++) {106 if (aList[i] < bList[i]) {107 flag = -1;108 } else {109 if (aList[i] > bList[i])110 flag = 1;111 }112 if (flag != 0)113 break;114 }115 }116 delete[](aList);117 delete[](bList);118 return flag;119 }120 }121 return-1;54 int *aList = NULL, *bList = NULL; 55 int Count, Counter, aCounter, bCounter; 56 int flag; 57 atom *aWalker = NULL; 58 atom *bWalker = NULL; 59 60 // sort each atom list and put the numbers into a list, then go through 61 //cout << "Comparing fragment no. " << *(molecule **)a << " to " << *(molecule **)b << "." << endl; 62 if ( (**(molecule **)a).AtomCount < (**(molecule **)b).AtomCount ) { 63 return -1; 64 } else { if ((**(molecule **)a).AtomCount > (**(molecule **)b).AtomCount) 65 return +1; 66 else { 67 Count = (**(molecule **)a).AtomCount; 68 aList = new int[Count]; 69 bList = new int[Count]; 70 71 // fill the lists 72 aWalker = (**(molecule **)a).start; 73 bWalker = (**(molecule **)b).start; 74 Counter = 0; 75 aCounter = 0; 76 bCounter = 0; 77 while ((aWalker->next != (**(molecule **)a).end) && (bWalker->next != (**(molecule **)b).end)) { 78 aWalker = aWalker->next; 79 bWalker = bWalker->next; 80 if (aWalker->GetTrueFather() == NULL) 81 aList[Counter] = Count + (aCounter++); 82 else 83 aList[Counter] = aWalker->GetTrueFather()->nr; 84 if (bWalker->GetTrueFather() == NULL) 85 bList[Counter] = Count + (bCounter++); 86 else 87 bList[Counter] = bWalker->GetTrueFather()->nr; 88 Counter++; 89 } 90 // check if AtomCount was for real 91 flag = 0; 92 if ((aWalker->next == (**(molecule **)a).end) && (bWalker->next != (**(molecule **)b).end)) { 93 flag = -1; 94 } else { 95 if ((aWalker->next != (**(molecule **)a).end) && (bWalker->next == (**(molecule **)b).end)) 96 flag = 1; 97 } 98 if (flag == 0) { 99 // sort the lists 100 gsl_heapsort(aList,Count, sizeof(int), CompareDoubles); 101 gsl_heapsort(bList,Count, sizeof(int), CompareDoubles); 102 // compare the lists 103 104 flag = 0; 105 for(int i=0;i<Count;i++) { 106 if (aList[i] < bList[i]) { 107 flag = -1; 108 } else { 109 if (aList[i] > bList[i]) 110 flag = 1; 111 } 112 if (flag != 0) 113 break; 114 } 115 } 116 delete[](aList); 117 delete[](bList); 118 return flag; 119 } 120 } 121 return -1; 122 122 }; 123 123 … … 127 127 void MoleculeListClass::Output(ofstream *out) 128 128 { 129 *out<< Verbose(1) << "MoleculeList: ";130 for (int i=0;i<NumberOfMolecules;i++)131 *out << ListOfMolecules[i] << "\t";132 *out << endl;129 *out<< Verbose(1) << "MoleculeList: "; 130 for (int i=0;i<NumberOfMolecules;i++) 131 *out << ListOfMolecules[i] << "\t"; 132 *out << endl; 133 133 }; 134 134 … … 142 142 bool MoleculeListClass::AddHydrogenCorrection(ofstream *out, char *path) 143 143 { 144 atom *Walker = NULL;145 atom *Runner = NULL;146 double ***FitConstant = NULL, **correction = NULL;147 int a,b;148 ofstream output;149 ifstream input;150 string line;151 stringstream zeile;152 double distance;153 char ParsedLine[1023];154 double tmp;155 char *FragmentNumber = NULL;156 157 cout << Verbose(1) << "Saving hydrogen saturation correction ... ";158 // 0. parse in fit constant files that should have the same dimension as the final energy files159 // 0a. find dimension of matrices with constants160 line = path;161 line.append("/");162 line += FRAGMENTPREFIX;163 line += "1";164 line += FITCONSTANTSUFFIX;165 input.open(line.c_str());166 if (input == NULL) {167 cerr << endl << "Unable to open " << line << ", is the directory correct?" << endl;168 return false;169 }170 a=0;171 b=-1; // we overcount by one172 while (!input.eof()) {173 input.getline(ParsedLine, 1023);174 zeile.str(ParsedLine);175 int i=0;176 while (!zeile.eof()) {177 zeile >> distance;178 i++;179 }180 if (i > a)181 a = i;182 b++;183 }184 cout << "I recognized " << a << " columns and " << b << " rows, ";185 input.close();186 187 // 0b. allocate memory for constants188 FitConstant = (double ***) Malloc(sizeof(double **)*3, "MoleculeListClass::AddHydrogenCorrection: ***FitConstant");189 for (int k=0;k<3;k++) {190 FitConstant[k] = (double **) Malloc(sizeof(double *)*a, "MoleculeListClass::AddHydrogenCorrection: **FitConstant[]");191 for (int i=a;i--;) {192 FitConstant[k][i] = (double *) Malloc(sizeof(double)*b, "MoleculeListClass::AddHydrogenCorrection: *FitConstant[][]");193 }194 }195 // 0c. parse in constants196 for (int i=0;i<3;i++) {197 line = path;198 line.append("/");199 line += FRAGMENTPREFIX;200 sprintf(ParsedLine, "%d", i+1);201 line += ParsedLine;202 line += FITCONSTANTSUFFIX;203 input.open(line.c_str());204 if (input == NULL) {205 cerr << endl << "Unable to open " << line << ", is the directory correct?" << endl;206 return false;207 }208 int k = 0,l;209 while ((!input.eof()) && (k < b)) {210 input.getline(ParsedLine, 1023);211 //cout << "Current Line: " << ParsedLine << endl;212 zeile.str(ParsedLine);213 zeile.clear();214 l = 0;215 while ((!zeile.eof()) && (l < a)) {216 zeile >> FitConstant[i][l][k];217 //cout << FitConstant[i][l][k] << "\t";218 l++;219 }220 //cout << endl;221 k++;222 }223 input.close();224 }225 for(int k=0;k<3;k++) {226 cout << "Constants " << k << ":" << endl;227 for (int j=0;j<b;j++) {228 for (int i=0;i<a;i++) {229 cout << FitConstant[k][i][j] << "\t";230 }231 cout << endl;232 }233 cout << endl;234 }235 236 // 0d. allocate final correction matrix237 correction = (double **) Malloc(sizeof(double *)*a, "MoleculeListClass::AddHydrogenCorrection: **correction");238 for (int i=a;i--;)239 correction[i] = (double *) Malloc(sizeof(double)*b, "MoleculeListClass::AddHydrogenCorrection: *correction[]");240 241 // 1a. go through every molecule in the list242 for(int i=NumberOfMolecules;i--;) {243 // 1b. zero final correction matrix244 for (int k=a;k--;)245 for (int j=b;j--;)246 correction[k][j] = 0.;247 // 2. take every hydrogen that is a saturated one248 Walker = ListOfMolecules[i]->start;249 while (Walker->next != ListOfMolecules[i]->end) {250 Walker = Walker->next;251 //cout << Verbose(1) << "Walker: " << *Walker << " with first bond " << *ListOfMolecules[i]->ListOfBondsPerAtom[Walker->nr][0] << "." << endl;252 if ((Walker->type->Z == 1) && ((Walker->father == NULL) || (Walker->father->type->Z != 1))) { // if it's a hydrogen253 Runner = ListOfMolecules[i]->start;254 while (Runner->next != ListOfMolecules[i]->end) {255 Runner = Runner->next;256 //cout << Verbose(2) << "Runner: " << *Runner << " with first bond " << *ListOfMolecules[i]->ListOfBondsPerAtom[Runner->nr][0] << "." << endl;257 // 3. take every other hydrogen that is the not the first and not bound to same bonding partner258 if ((Runner->type->Z == 1) && (Runner->nr > Walker->nr) && (ListOfMolecules[i]->ListOfBondsPerAtom[Runner->nr][0]->GetOtherAtom(Runner) != ListOfMolecules[i]->ListOfBondsPerAtom[Walker->nr][0]->GetOtherAtom(Walker))) {// (hydrogens have only one bonding partner!)259 // 4. evaluate the morse potential for each matrix component and add up260 distance = sqrt(Runner->x.Distance(&Walker->x));261 //cout << "Fragment " << i << ": " << *Runner << "<= " << distance << "=>" << *Walker << ":" << endl;262 for(int k=0;k<a;k++) {263 for (int j=0;j<b;j++) {264 switch(k) {265 case 1:266 case 7:267 case 11:268 tmp = pow(FitConstant[0][k][j] * ( 1. - exp(-FitConstant[1][k][j] * (distance - FitConstant[2][k][j]) ) ),2);269 break;270 default:271 tmp = FitConstant[0][k][j] * pow( distance,FitConstant[1][k][j]) + FitConstant[2][k][j];272 };273 correction[k][j] -= tmp;// ground state is actually lower (disturbed by additional interaction)274 //cout << tmp << "\t";275 }276 //cout << endl;277 }278 //cout << endl;279 }280 }281 }282 }283 // 5. write final matrix to file284 line = path;285 line.append("/");286 line += FRAGMENTPREFIX;287 FragmentNumber = FixedDigitNumber(NumberOfMolecules, i);288 line += FragmentNumber;289 delete(FragmentNumber);290 line += HCORRECTIONSUFFIX;291 output.open(line.c_str());292 output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl;293 for (int j=0;j<b;j++) {294 for(int i=0;i<a;i++)295 output << correction[i][j] << "\t";296 output << endl;297 }298 output.close();299 }300 line = path;301 line.append("/");302 line += HCORRECTIONSUFFIX;303 output.open(line.c_str());304 output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl;305 for (int j=0;j<b;j++) {306 for(int i=0;i<a;i++)307 output << 0 << "\t";308 output << endl;309 }310 output.close();311 // 6. free memory of parsed matrices312 FitConstant = (double ***) Malloc(sizeof(double **)*a, "MoleculeListClass::AddHydrogenCorrection: ***FitConstant");313 for (int k=0;k<3;k++) {314 FitConstant[k] = (double **) Malloc(sizeof(double *)*a, "MoleculeListClass::AddHydrogenCorrection: **FitConstant[]");315 for (int i=a;i--;) {316 FitConstant[k][i] = (double *) Malloc(sizeof(double)*b, "MoleculeListClass::AddHydrogenCorrection: *FitConstant[][]");317 }318 }319 cout << "done." << endl;320 return true;144 atom *Walker = NULL; 145 atom *Runner = NULL; 146 double ***FitConstant = NULL, **correction = NULL; 147 int a,b; 148 ofstream output; 149 ifstream input; 150 string line; 151 stringstream zeile; 152 double distance; 153 char ParsedLine[1023]; 154 double tmp; 155 char *FragmentNumber = NULL; 156 157 cout << Verbose(1) << "Saving hydrogen saturation correction ... "; 158 // 0. parse in fit constant files that should have the same dimension as the final energy files 159 // 0a. find dimension of matrices with constants 160 line = path; 161 line.append("/"); 162 line += FRAGMENTPREFIX; 163 line += "1"; 164 line += FITCONSTANTSUFFIX; 165 input.open(line.c_str()); 166 if (input == NULL) { 167 cerr << endl << "Unable to open " << line << ", is the directory correct?" << endl; 168 return false; 169 } 170 a=0; 171 b=-1; // we overcount by one 172 while (!input.eof()) { 173 input.getline(ParsedLine, 1023); 174 zeile.str(ParsedLine); 175 int i=0; 176 while (!zeile.eof()) { 177 zeile >> distance; 178 i++; 179 } 180 if (i > a) 181 a = i; 182 b++; 183 } 184 cout << "I recognized " << a << " columns and " << b << " rows, "; 185 input.close(); 186 187 // 0b. allocate memory for constants 188 FitConstant = (double ***) Malloc(sizeof(double **)*3, "MoleculeListClass::AddHydrogenCorrection: ***FitConstant"); 189 for (int k=0;k<3;k++) { 190 FitConstant[k] = (double **) Malloc(sizeof(double *)*a, "MoleculeListClass::AddHydrogenCorrection: **FitConstant[]"); 191 for (int i=a;i--;) { 192 FitConstant[k][i] = (double *) Malloc(sizeof(double)*b, "MoleculeListClass::AddHydrogenCorrection: *FitConstant[][]"); 193 } 194 } 195 // 0c. parse in constants 196 for (int i=0;i<3;i++) { 197 line = path; 198 line.append("/"); 199 line += FRAGMENTPREFIX; 200 sprintf(ParsedLine, "%d", i+1); 201 line += ParsedLine; 202 line += FITCONSTANTSUFFIX; 203 input.open(line.c_str()); 204 if (input == NULL) { 205 cerr << endl << "Unable to open " << line << ", is the directory correct?" << endl; 206 return false; 207 } 208 int k = 0,l; 209 while ((!input.eof()) && (k < b)) { 210 input.getline(ParsedLine, 1023); 211 //cout << "Current Line: " << ParsedLine << endl; 212 zeile.str(ParsedLine); 213 zeile.clear(); 214 l = 0; 215 while ((!zeile.eof()) && (l < a)) { 216 zeile >> FitConstant[i][l][k]; 217 //cout << FitConstant[i][l][k] << "\t"; 218 l++; 219 } 220 //cout << endl; 221 k++; 222 } 223 input.close(); 224 } 225 for(int k=0;k<3;k++) { 226 cout << "Constants " << k << ":" << endl; 227 for (int j=0;j<b;j++) { 228 for (int i=0;i<a;i++) { 229 cout << FitConstant[k][i][j] << "\t"; 230 } 231 cout << endl; 232 } 233 cout << endl; 234 } 235 236 // 0d. allocate final correction matrix 237 correction = (double **) Malloc(sizeof(double *)*a, "MoleculeListClass::AddHydrogenCorrection: **correction"); 238 for (int i=a;i--;) 239 correction[i] = (double *) Malloc(sizeof(double)*b, "MoleculeListClass::AddHydrogenCorrection: *correction[]"); 240 241 // 1a. go through every molecule in the list 242 for(int i=NumberOfMolecules;i--;) { 243 // 1b. zero final correction matrix 244 for (int k=a;k--;) 245 for (int j=b;j--;) 246 correction[k][j] = 0.; 247 // 2. take every hydrogen that is a saturated one 248 Walker = ListOfMolecules[i]->start; 249 while (Walker->next != ListOfMolecules[i]->end) { 250 Walker = Walker->next; 251 //cout << Verbose(1) << "Walker: " << *Walker << " with first bond " << *ListOfMolecules[i]->ListOfBondsPerAtom[Walker->nr][0] << "." << endl; 252 if ((Walker->type->Z == 1) && ((Walker->father == NULL) || (Walker->father->type->Z != 1))) { // if it's a hydrogen 253 Runner = ListOfMolecules[i]->start; 254 while (Runner->next != ListOfMolecules[i]->end) { 255 Runner = Runner->next; 256 //cout << Verbose(2) << "Runner: " << *Runner << " with first bond " << *ListOfMolecules[i]->ListOfBondsPerAtom[Runner->nr][0] << "." << endl; 257 // 3. take every other hydrogen that is the not the first and not bound to same bonding partner 258 if ((Runner->type->Z == 1) && (Runner->nr > Walker->nr) && (ListOfMolecules[i]->ListOfBondsPerAtom[Runner->nr][0]->GetOtherAtom(Runner) != ListOfMolecules[i]->ListOfBondsPerAtom[Walker->nr][0]->GetOtherAtom(Walker))) { // (hydrogens have only one bonding partner!) 259 // 4. evaluate the morse potential for each matrix component and add up 260 distance = Runner->x.Distance(&Walker->x); 261 //cout << "Fragment " << i << ": " << *Runner << "<= " << distance << "=>" << *Walker << ":" << endl; 262 for(int k=0;k<a;k++) { 263 for (int j=0;j<b;j++) { 264 switch(k) { 265 case 1: 266 case 7: 267 case 11: 268 tmp = pow(FitConstant[0][k][j] * ( 1. - exp(-FitConstant[1][k][j] * (distance - FitConstant[2][k][j]) ) ),2); 269 break; 270 default: 271 tmp = FitConstant[0][k][j] * pow( distance, FitConstant[1][k][j]) + FitConstant[2][k][j]; 272 }; 273 correction[k][j] -= tmp; // ground state is actually lower (disturbed by additional interaction) 274 //cout << tmp << "\t"; 275 } 276 //cout << endl; 277 } 278 //cout << endl; 279 } 280 } 281 } 282 } 283 // 5. write final matrix to file 284 line = path; 285 line.append("/"); 286 line += FRAGMENTPREFIX; 287 FragmentNumber = FixedDigitNumber(NumberOfMolecules, i); 288 line += FragmentNumber; 289 delete(FragmentNumber); 290 line += HCORRECTIONSUFFIX; 291 output.open(line.c_str()); 292 output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl; 293 for (int j=0;j<b;j++) { 294 for(int i=0;i<a;i++) 295 output << correction[i][j] << "\t"; 296 output << endl; 297 } 298 output.close(); 299 } 300 line = path; 301 line.append("/"); 302 line += HCORRECTIONSUFFIX; 303 output.open(line.c_str()); 304 output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl; 305 for (int j=0;j<b;j++) { 306 for(int i=0;i<a;i++) 307 output << 0 << "\t"; 308 output << endl; 309 } 310 output.close(); 311 // 6. free memory of parsed matrices 312 FitConstant = (double ***) Malloc(sizeof(double **)*a, "MoleculeListClass::AddHydrogenCorrection: ***FitConstant"); 313 for (int k=0;k<3;k++) { 314 FitConstant[k] = (double **) Malloc(sizeof(double *)*a, "MoleculeListClass::AddHydrogenCorrection: **FitConstant[]"); 315 for (int i=a;i--;) { 316 FitConstant[k][i] = (double *) Malloc(sizeof(double)*b, "MoleculeListClass::AddHydrogenCorrection: *FitConstant[][]"); 317 } 318 } 319 cout << "done." << endl; 320 return true; 321 321 }; 322 322 … … 329 329 bool MoleculeListClass::StoreForcesFile(ofstream *out, char *path, int *SortIndex) 330 330 { 331 bool status = true;332 ofstream ForcesFile;333 stringstream line;334 atom *Walker = NULL;335 element *runner = NULL;336 337 // open file for the force factors338 *out << Verbose(1) << "Savingforce factors ... ";339 line << path << "/" << FRAGMENTPREFIX << FORCESFILE;340 ForcesFile.open(line.str().c_str(), ios::out);341 if (ForcesFile != NULL) {342 //cout << Verbose(1) << "Final AtomicForcesList: ";343 //output << prefix << "Forces" << endl;344 for(int j=0;j<NumberOfMolecules;j++) {345 //if (TEList[j] != 0) {346 runner = ListOfMolecules[j]->elemente->start;347 while (runner->next != ListOfMolecules[j]->elemente->end) { // go through every element348 runner = runner->next;349 if (ListOfMolecules[j]->ElementsInMolecule[runner->Z]) { // if this element got atoms350 Walker = ListOfMolecules[j]->start;351 while (Walker->next != ListOfMolecules[j]->end) { // go through every atom of this element352 Walker = Walker->next;353 if (Walker->type->Z == runner->Z) {354 if ((Walker->GetTrueFather() != NULL) && (Walker->GetTrueFather() != Walker)) {// if there is a rea355 //cout << "Walker is " << *Walker << " with true father " << *( Walker->GetTrueFather()) << ", it356 ForcesFile <<SortIndex[Walker->GetTrueFather()->nr] << "\t";357 } else// otherwise a -1 to indicate an added saturation hydrogen358 ForcesFile << "-1\t";359 }360 }361 }362 }363 ForcesFile << endl;364 }365 ForcesFile.close();366 *out << Verbose(1) << "done." << endl;367 } else {368 status = false;369 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;370 }371 ForcesFile.close();372 373 return status;331 bool status = true; 332 ofstream ForcesFile; 333 stringstream line; 334 atom *Walker = NULL; 335 element *runner = NULL; 336 337 // open file for the force factors 338 *out << Verbose(1) << "Saving force factors ... "; 339 line << path << "/" << FRAGMENTPREFIX << FORCESFILE; 340 ForcesFile.open(line.str().c_str(), ios::out); 341 if (ForcesFile != NULL) { 342 //cout << Verbose(1) << "Final AtomicForcesList: "; 343 //output << prefix << "Forces" << endl; 344 for(int j=0;j<NumberOfMolecules;j++) { 345 //if (TEList[j] != 0) { 346 runner = ListOfMolecules[j]->elemente->start; 347 while (runner->next != ListOfMolecules[j]->elemente->end) { // go through every element 348 runner = runner->next; 349 if (ListOfMolecules[j]->ElementsInMolecule[runner->Z]) { // if this element got atoms 350 Walker = ListOfMolecules[j]->start; 351 while (Walker->next != ListOfMolecules[j]->end) { // go through every atom of this element 352 Walker = Walker->next; 353 if (Walker->type->Z == runner->Z) { 354 if ((Walker->GetTrueFather() != NULL) && (Walker->GetTrueFather() != Walker)) {// if there is a rea 355 //cout << "Walker is " << *Walker << " with true father " << *( Walker->GetTrueFather()) << ", it 356 ForcesFile << SortIndex[Walker->GetTrueFather()->nr] << "\t"; 357 } else // otherwise a -1 to indicate an added saturation hydrogen 358 ForcesFile << "-1\t"; 359 } 360 } 361 } 362 } 363 ForcesFile << endl; 364 } 365 ForcesFile.close(); 366 *out << Verbose(1) << "done." << endl; 367 } else { 368 status = false; 369 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 370 } 371 ForcesFile.close(); 372 373 return status; 374 374 }; 375 375 … … 382 382 bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex) 383 383 { 384 ofstream outputFragment;385 char FragmentName[MAXSTRINGSIZE];386 char PathBackup[MAXSTRINGSIZE];387 bool result = true;388 bool intermediateResult = true;389 atom *Walker = NULL;390 Vector BoxDimension;391 char *FragmentNumber = NULL;392 char *path = NULL;393 int FragmentCounter = 0;394 ofstream output;395 396 // store the fragments as config and as xyz397 for(int i=0;i<NumberOfMolecules;i++) {398 // save default path as it is changed for each fragment399 path = configuration->GetDefaultPath();400 if (path != NULL)401 strcpy(PathBackup, path);402 else403 cerr << "OutputConfigForListOfFragments: NULL default path obtained from config!" << endl;404 405 // correct periodic406 ListOfMolecules[i]->ScanForPeriodicCorrection(out);407 408 // output xyz file409 FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++);410 sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);411 outputFragment.open(FragmentName, ios::out);412 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as XYZ ...";413 if ((intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment)))414 *out << " done." << endl;415 else416 *out << " failed." << endl;417 result = result && intermediateResult;418 outputFragment.close();419 outputFragment.clear();420 421 // list atoms in fragment for debugging422 *out << Verbose(2) << "Contained atoms: ";423 Walker = ListOfMolecules[i]->start;424 while (Walker->next != ListOfMolecules[i]->end) {425 Walker = Walker->next;426 *out << Walker->Name << " ";427 }428 *out << endl;429 430 // center on edge431 ListOfMolecules[i]->CenterEdge(out, &BoxDimension);432 ListOfMolecules[i]->SetBoxDimension(&BoxDimension);// update Box of atoms by boundary433 int j = -1;434 for (int k=0;k<NDIM;k++) {435 j += k+1;436 BoxDimension.x[k] = 2.5* (configuration->GetIsAngstroem() ? 1. : 1./AtomicLengthToAngstroem);437 ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.;438 }439 ListOfMolecules[i]->Translate(&BoxDimension);440 441 // also calculate necessary orbitals442 ListOfMolecules[i]->CountElements();// this is a bugfix, atoms should should actually be added correctly to this fragment443 ListOfMolecules[i]->CalculateOrbitals(*configuration);444 445 // change path in config446 //strcpy(PathBackup, configuration->configpath);447 sprintf(FragmentName, "%s/%s%s/", PathBackup, FRAGMENTPREFIX, FragmentNumber);448 configuration->SetDefaultPath(FragmentName);449 450 // and save as config451 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);452 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as config ...";453 if ((intermediateResult = configuration->Save(FragmentName, ListOfMolecules[i]->elemente, ListOfMolecules[i])))454 *out << " done." << endl;455 else456 *out << " failed." << endl;457 result = result && intermediateResult;458 459 // restore old config460 configuration->SetDefaultPath(PathBackup);461 462 463 // and save as mpqc input file464 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);465 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as mpqc input ...";466 if ((intermediateResult = configuration->SaveMPQC(FragmentName, ListOfMolecules[i])))467 *out << " done." << endl;468 else469 *out << " failed." << endl;470 471 result = result && intermediateResult;472 //outputFragment.close();473 //outputFragment.clear();474 delete(FragmentNumber);475 //Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber");476 }477 cout << " done." << endl;478 479 // printing final number480 *out << "Final number of fragments: " << FragmentCounter << "." << endl;481 482 return result;384 ofstream outputFragment; 385 char FragmentName[MAXSTRINGSIZE]; 386 char PathBackup[MAXSTRINGSIZE]; 387 bool result = true; 388 bool intermediateResult = true; 389 atom *Walker = NULL; 390 Vector BoxDimension; 391 char *FragmentNumber = NULL; 392 char *path = NULL; 393 int FragmentCounter = 0; 394 ofstream output; 395 396 // store the fragments as config and as xyz 397 for(int i=0;i<NumberOfMolecules;i++) { 398 // save default path as it is changed for each fragment 399 path = configuration->GetDefaultPath(); 400 if (path != NULL) 401 strcpy(PathBackup, path); 402 else 403 cerr << "OutputConfigForListOfFragments: NULL default path obtained from config!" << endl; 404 405 // correct periodic 406 ListOfMolecules[i]->ScanForPeriodicCorrection(out); 407 408 // output xyz file 409 FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++); 410 sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, FRAGMENTPREFIX, FragmentNumber); 411 outputFragment.open(FragmentName, ios::out); 412 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as XYZ ..."; 413 if ((intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment))) 414 *out << " done." << endl; 415 else 416 *out << " failed." << endl; 417 result = result && intermediateResult; 418 outputFragment.close(); 419 outputFragment.clear(); 420 421 // list atoms in fragment for debugging 422 *out << Verbose(2) << "Contained atoms: "; 423 Walker = ListOfMolecules[i]->start; 424 while (Walker->next != ListOfMolecules[i]->end) { 425 Walker = Walker->next; 426 *out << Walker->Name << " "; 427 } 428 *out << endl; 429 430 // center on edge 431 ListOfMolecules[i]->CenterEdge(out, &BoxDimension); 432 ListOfMolecules[i]->SetBoxDimension(&BoxDimension); // update Box of atoms by boundary 433 int j = -1; 434 for (int k=0;k<NDIM;k++) { 435 j += k+1; 436 BoxDimension.x[k] = 2.5* (configuration->GetIsAngstroem() ? 1. : 1./AtomicLengthToAngstroem); 437 ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.; 438 } 439 ListOfMolecules[i]->Translate(&BoxDimension); 440 441 // also calculate necessary orbitals 442 ListOfMolecules[i]->CountElements(); // this is a bugfix, atoms should should actually be added correctly to this fragment 443 ListOfMolecules[i]->CalculateOrbitals(*configuration); 444 445 // change path in config 446 //strcpy(PathBackup, configuration->configpath); 447 sprintf(FragmentName, "%s/%s%s/", PathBackup, FRAGMENTPREFIX, FragmentNumber); 448 configuration->SetDefaultPath(FragmentName); 449 450 // and save as config 451 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber); 452 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as config ..."; 453 if ((intermediateResult = configuration->Save(FragmentName, ListOfMolecules[i]->elemente, ListOfMolecules[i]))) 454 *out << " done." << endl; 455 else 456 *out << " failed." << endl; 457 result = result && intermediateResult; 458 459 // restore old config 460 configuration->SetDefaultPath(PathBackup); 461 462 463 // and save as mpqc input file 464 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber); 465 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter-1 << " as mpqc input ..."; 466 if ((intermediateResult = configuration->SaveMPQC(FragmentName, ListOfMolecules[i]))) 467 *out << " done." << endl; 468 else 469 *out << " failed." << endl; 470 471 result = result && intermediateResult; 472 //outputFragment.close(); 473 //outputFragment.clear(); 474 delete(FragmentNumber); 475 //Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber"); 476 } 477 cout << " done." << endl; 478 479 // printing final number 480 *out << "Final number of fragments: " << FragmentCounter << "." << endl; 481 482 return result; 483 483 }; 484 484 … … 492 492 MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL) 493 493 { 494 // if (Up != NULL)495 // if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?496 // Up->DownLeaf = this;497 // UpLeaf = Up;498 // DownLeaf = NULL;499 Leaf = NULL;500 previous = PreviousLeaf;501 if (previous != NULL) {502 MoleculeLeafClass *Walker = previous->next;503 previous->next = this;504 next = Walker;505 } else {506 next = NULL;507 }494 // if (Up != NULL) 495 // if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf? 496 // Up->DownLeaf = this; 497 // UpLeaf = Up; 498 // DownLeaf = NULL; 499 Leaf = NULL; 500 previous = PreviousLeaf; 501 if (previous != NULL) { 502 MoleculeLeafClass *Walker = previous->next; 503 previous->next = this; 504 next = Walker; 505 } else { 506 next = NULL; 507 } 508 508 }; 509 509 … … 512 512 MoleculeLeafClass::~MoleculeLeafClass() 513 513 { 514 // if (DownLeaf != NULL) {// drop leaves further down515 // MoleculeLeafClass *Walker = DownLeaf;516 // MoleculeLeafClass *Next;517 // do {518 // Next = Walker->NextLeaf;519 // delete(Walker);520 // Walker = Next;521 // } while (Walker != NULL);522 // // Last Walker sets DownLeaf automatically to NULL523 // }524 // remove the leaf itself525 if (Leaf != NULL) {526 delete(Leaf);527 Leaf = NULL;528 }529 // remove this Leaf from level list530 if (previous != NULL)531 previous->next = next;532 // } else { // we are first in list (connects to UpLeaf->DownLeaf)533 // if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))534 // NextLeaf->UpLeaf = UpLeaf;// either null as we are top level or the upleaf of the first node535 // if (UpLeaf != NULL)536 // UpLeaf->DownLeaf = NextLeaf;// either null as we are only leaf or NextLeaf if we are just the first537 // }538 // UpLeaf = NULL;539 if (next != NULL) // are we last in list540 next->previous = previous;541 next = NULL;542 previous = NULL;514 // if (DownLeaf != NULL) {// drop leaves further down 515 // MoleculeLeafClass *Walker = DownLeaf; 516 // MoleculeLeafClass *Next; 517 // do { 518 // Next = Walker->NextLeaf; 519 // delete(Walker); 520 // Walker = Next; 521 // } while (Walker != NULL); 522 // // Last Walker sets DownLeaf automatically to NULL 523 // } 524 // remove the leaf itself 525 if (Leaf != NULL) { 526 delete(Leaf); 527 Leaf = NULL; 528 } 529 // remove this Leaf from level list 530 if (previous != NULL) 531 previous->next = next; 532 // } else { // we are first in list (connects to UpLeaf->DownLeaf) 533 // if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL)) 534 // NextLeaf->UpLeaf = UpLeaf; // either null as we are top level or the upleaf of the first node 535 // if (UpLeaf != NULL) 536 // UpLeaf->DownLeaf = NextLeaf; // either null as we are only leaf or NextLeaf if we are just the first 537 // } 538 // UpLeaf = NULL; 539 if (next != NULL) // are we last in list 540 next->previous = previous; 541 next = NULL; 542 previous = NULL; 543 543 }; 544 544 … … 550 550 bool MoleculeLeafClass::AddLeaf(molecule *ptr, MoleculeLeafClass *Previous) 551 551 { 552 return false;552 return false; 553 553 }; 554 554 … … 564 564 bool MoleculeLeafClass::FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList) 565 565 { 566 atom *Walker = NULL, *OtherWalker = NULL;567 bond *Binder = NULL;568 bool status = true;569 int AtomNo;570 571 *out << Verbose(1) << "Begin of FillBondStructureFromReference." << endl;572 // fill ListOfLocalAtoms if NULL was given573 if (!FillListOfLocalAtoms(out, ListOfLocalAtoms, FragmentCounter, reference->AtomCount, FreeList)) {574 *out << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl;575 return false;576 }577 578 if (status) {579 *out << Verbose(1) << "Creating adjacency list for subgraph " << this << "." << endl;580 Walker = Leaf->start;581 while (Walker->next != Leaf->end) {582 Walker = Walker->next;583 AtomNo = Walker->GetTrueFather()->nr;// global id of the current walker584 for(int i=0;i<reference->NumberOfBondsPerAtom[AtomNo];i++) { // go through father's bonds and copy them all585 Binder = reference->ListOfBondsPerAtom[AtomNo][i];586 OtherWalker = ListOfLocalAtoms[FragmentCounter][Binder->GetOtherAtom(Walker->GetTrueFather())->nr];// local copy of current bond partner of walker587 if (OtherWalker != NULL) {588 if (OtherWalker->nr > Walker->nr)589 Leaf->AddBond(Walker, OtherWalker, Binder->BondDegree);590 } else {591 *out << Verbose(1) << "OtherWalker = ListOfLocalAtoms[" << FragmentCounter << "][" << Binder->GetOtherAtom(Walker->GetTrueFather())->nr << "] is NULL!" << endl;592 status = false;593 }594 }595 }596 Leaf->CreateListOfBondsPerAtom(out);597 FragmentCounter++;598 if (next != NULL)599 status = next->FillBondStructureFromReference(out, reference, FragmentCounter, ListOfLocalAtoms);600 FragmentCounter--;601 }602 603 if ((FreeList) && (ListOfLocalAtoms != NULL)) {604 // free the index lookup list605 Free((void **)&ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::FillBondStructureFromReference - **ListOfLocalAtoms[]");606 if (FragmentCounter == 0) // first fragments frees the initial pointer to list607 Free((void **)&ListOfLocalAtoms, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");608 }609 FragmentCounter--;610 *out << Verbose(1) << "End of FillBondStructureFromReference." << endl;611 return status;566 atom *Walker = NULL, *OtherWalker = NULL; 567 bond *Binder = NULL; 568 bool status = true; 569 int AtomNo; 570 571 *out << Verbose(1) << "Begin of FillBondStructureFromReference." << endl; 572 // fill ListOfLocalAtoms if NULL was given 573 if (!FillListOfLocalAtoms(out, ListOfLocalAtoms, FragmentCounter, reference->AtomCount, FreeList)) { 574 *out << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl; 575 return false; 576 } 577 578 if (status) { 579 *out << Verbose(1) << "Creating adjacency list for subgraph " << this << "." << endl; 580 Walker = Leaf->start; 581 while (Walker->next != Leaf->end) { 582 Walker = Walker->next; 583 AtomNo = Walker->GetTrueFather()->nr; // global id of the current walker 584 for(int i=0;i<reference->NumberOfBondsPerAtom[AtomNo];i++) { // go through father's bonds and copy them all 585 Binder = reference->ListOfBondsPerAtom[AtomNo][i]; 586 OtherWalker = ListOfLocalAtoms[FragmentCounter][Binder->GetOtherAtom(Walker->GetTrueFather())->nr]; // local copy of current bond partner of walker 587 if (OtherWalker != NULL) { 588 if (OtherWalker->nr > Walker->nr) 589 Leaf->AddBond(Walker, OtherWalker, Binder->BondDegree); 590 } else { 591 *out << Verbose(1) << "OtherWalker = ListOfLocalAtoms[" << FragmentCounter << "][" << Binder->GetOtherAtom(Walker->GetTrueFather())->nr << "] is NULL!" << endl; 592 status = false; 593 } 594 } 595 } 596 Leaf->CreateListOfBondsPerAtom(out); 597 FragmentCounter++; 598 if (next != NULL) 599 status = next->FillBondStructureFromReference(out, reference, FragmentCounter, ListOfLocalAtoms); 600 FragmentCounter--; 601 } 602 603 if ((FreeList) && (ListOfLocalAtoms != NULL)) { 604 // free the index lookup list 605 Free((void **)&ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::FillBondStructureFromReference - **ListOfLocalAtoms[]"); 606 if (FragmentCounter == 0) // first fragments frees the initial pointer to list 607 Free((void **)&ListOfLocalAtoms, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms"); 608 } 609 FragmentCounter--; 610 *out << Verbose(1) << "End of FillBondStructureFromReference." << endl; 611 return status; 612 612 }; 613 613 … … 622 622 bool MoleculeLeafClass::FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter) 623 623 { 624 atom *Walker = NULL, *Father = NULL;625 626 if (RootStack != NULL) {627 // find first root candidates628 if (&(RootStack[FragmentCounter]) != NULL) {629 RootStack[FragmentCounter].clear(); 630 Walker = Leaf->start;631 while (Walker->next != Leaf->end) { // go through all (non-hydrogen) atoms632 Walker = Walker->next;633 Father = Walker->GetTrueFather();634 if (AtomMask[Father->nr]) // apply mask635 #ifdef ADDHYDROGEN636 if (Walker->type->Z != 1) // skip hydrogen637 #endif638 RootStack[FragmentCounter].push_front(Walker->nr);639 }640 if (next != NULL)641 next->FillRootStackForSubgraphs(out, RootStack, AtomMask, ++FragmentCounter);642 }else {643 *out << Verbose(1) << "Rootstack[" << FragmentCounter<< "] is NULL." << endl;644 return false;645 }646 FragmentCounter--;647 return true;648 } else {649 *out << Verbose(1) << "Rootstack is NULL." << endl;650 return false;651 }624 atom *Walker = NULL, *Father = NULL; 625 626 if (RootStack != NULL) { 627 // find first root candidates 628 if (&(RootStack[FragmentCounter]) != NULL) { 629 RootStack[FragmentCounter].clear(); 630 Walker = Leaf->start; 631 while (Walker->next != Leaf->end) { // go through all (non-hydrogen) atoms 632 Walker = Walker->next; 633 Father = Walker->GetTrueFather(); 634 if (AtomMask[Father->nr]) // apply mask 635 #ifdef ADDHYDROGEN 636 if (Walker->type->Z != 1) // skip hydrogen 637 #endif 638 RootStack[FragmentCounter].push_front(Walker->nr); 639 } 640 if (next != NULL) 641 next->FillRootStackForSubgraphs(out, RootStack, AtomMask, ++FragmentCounter); 642 } else { 643 *out << Verbose(1) << "Rootstack[" << FragmentCounter << "] is NULL." << endl; 644 return false; 645 } 646 FragmentCounter--; 647 return true; 648 } else { 649 *out << Verbose(1) << "Rootstack is NULL." << endl; 650 return false; 651 } 652 652 }; 653 653 … … 662 662 bool MoleculeLeafClass::FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList) 663 663 { 664 bool status = true;665 666 int Counter = Count();667 if (ListOfLocalAtoms == NULL) { // allocated initial pointer668 // allocate and set each field to NULL669 ListOfLocalAtoms = (atom ***) Malloc(sizeof(atom **)*Counter, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");670 if (ListOfLocalAtoms != NULL) {671 for (int i=Counter;i--;)672 ListOfLocalAtoms[i] = NULL;673 FreeList = FreeList && true;674 } else675 status = false;676 }677 678 if ((ListOfLocalAtoms != NULL) && (ListOfLocalAtoms[FragmentCounter] == NULL)) { // allocate and fill list of this fragment/subgraph679 status = status && CreateFatherLookupTable(out, Leaf->start, Leaf->end, ListOfLocalAtoms[FragmentCounter], GlobalAtomCount);680 FreeList = FreeList && true;681 }682 683 return status;664 bool status = true; 665 666 int Counter = Count(); 667 if (ListOfLocalAtoms == NULL) { // allocated initial pointer 668 // allocate and set each field to NULL 669 ListOfLocalAtoms = (atom ***) Malloc(sizeof(atom **)*Counter, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms"); 670 if (ListOfLocalAtoms != NULL) { 671 for (int i=Counter;i--;) 672 ListOfLocalAtoms[i] = NULL; 673 FreeList = FreeList && true; 674 } else 675 status = false; 676 } 677 678 if ((ListOfLocalAtoms != NULL) && (ListOfLocalAtoms[FragmentCounter] == NULL)) { // allocate and fill list of this fragment/subgraph 679 status = status && CreateFatherLookupTable(out, Leaf->start, Leaf->end, ListOfLocalAtoms[FragmentCounter], GlobalAtomCount); 680 FreeList = FreeList && true; 681 } 682 683 return status; 684 684 }; 685 685 … … 696 696 bool MoleculeLeafClass::AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList) 697 697 { 698 bool status = true;699 int KeySetCounter = 0;700 701 *out << Verbose(1) << "Begin of AssignKeySetsToFragment." << endl;702 // fill ListOfLocalAtoms if NULL was given703 if (!FillListOfLocalAtoms(out, ListOfLocalAtoms, FragmentCounter, reference->AtomCount, FreeList)) {704 *out << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl;705 return false;706 }707 708 // allocate fragment list709 if (FragmentList == NULL) {710 KeySetCounter = Count();711 FragmentList = (Graph **) Malloc(sizeof(Graph *)*KeySetCounter, "MoleculeLeafClass::AssignKeySetsToFragment - **FragmentList");712 for(int i=KeySetCounter;i--;)713 FragmentList[i] = NULL;714 KeySetCounter = 0;715 }716 717 if ((KeySetList != NULL) && (KeySetList->size() != 0)) { // if there are some scanned keysets at all718 // assign scanned keysets719 if (FragmentList[FragmentCounter] == NULL)720 FragmentList[FragmentCounter] = new Graph;721 KeySet *TempSet = new KeySet;722 for(Graph::iterator runner = KeySetList->begin();runner != KeySetList->end(); runner++) { // key sets contain global numbers!723 if ( ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*((*runner).first.begin()))->nr] != NULL) {// as we may assume that that bond structure is unchanged, we only test the first key in each set724 // translate keyset to local numbers725 for(KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)726 TempSet->insert(ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*sprinter)->nr]->nr);727 // insert into FragmentList728 FragmentList[FragmentCounter]->insert(GraphPair (*TempSet, pair<int,double>(KeySetCounter++, (*runner).second.second)));729 }730 TempSet->clear();731 }732 delete(TempSet);733 if (KeySetCounter == 0) {// if there are no keysets, delete the list734 *out << Verbose(1) << "KeySetCounter is zero, deleting FragmentList." << endl;735 delete(FragmentList[FragmentCounter]);736 } else737 *out << Verbose(1) << KeySetCounter << " keysets were assigned to subgraph " << FragmentCounter << "." << endl;738 FragmentCounter++;739 if (next != NULL)740 next->AssignKeySetsToFragment(out, reference, KeySetList, ListOfLocalAtoms, FragmentList, FragmentCounter, FreeList);741 FragmentCounter--;742 } else743 *out << Verbose(1) << "KeySetList is NULL or empty." << endl;744 745 if ((FreeList) && (ListOfLocalAtoms != NULL)) {746 // free the index lookup list747 Free((void **)&ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::AssignKeySetsToFragment - **ListOfLocalAtoms[]");748 if (FragmentCounter == 0) // first fragments frees the initial pointer to list749 Free((void **)&ListOfLocalAtoms, "MoleculeLeafClass::AssignKeySetsToFragment - ***ListOfLocalAtoms");750 }751 *out << Verbose(1) << "End of AssignKeySetsToFragment." << endl;752 return status;698 bool status = true; 699 int KeySetCounter = 0; 700 701 *out << Verbose(1) << "Begin of AssignKeySetsToFragment." << endl; 702 // fill ListOfLocalAtoms if NULL was given 703 if (!FillListOfLocalAtoms(out, ListOfLocalAtoms, FragmentCounter, reference->AtomCount, FreeList)) { 704 *out << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl; 705 return false; 706 } 707 708 // allocate fragment list 709 if (FragmentList == NULL) { 710 KeySetCounter = Count(); 711 FragmentList = (Graph **) Malloc(sizeof(Graph *)*KeySetCounter, "MoleculeLeafClass::AssignKeySetsToFragment - **FragmentList"); 712 for(int i=KeySetCounter;i--;) 713 FragmentList[i] = NULL; 714 KeySetCounter = 0; 715 } 716 717 if ((KeySetList != NULL) && (KeySetList->size() != 0)) { // if there are some scanned keysets at all 718 // assign scanned keysets 719 if (FragmentList[FragmentCounter] == NULL) 720 FragmentList[FragmentCounter] = new Graph; 721 KeySet *TempSet = new KeySet; 722 for(Graph::iterator runner = KeySetList->begin();runner != KeySetList->end(); runner++) { // key sets contain global numbers! 723 if ( ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*((*runner).first.begin()))->nr] != NULL) {// as we may assume that that bond structure is unchanged, we only test the first key in each set 724 // translate keyset to local numbers 725 for(KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++) 726 TempSet->insert(ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*sprinter)->nr]->nr); 727 // insert into FragmentList 728 FragmentList[FragmentCounter]->insert(GraphPair (*TempSet, pair<int,double>(KeySetCounter++, (*runner).second.second))); 729 } 730 TempSet->clear(); 731 } 732 delete(TempSet); 733 if (KeySetCounter == 0) {// if there are no keysets, delete the list 734 *out << Verbose(1) << "KeySetCounter is zero, deleting FragmentList." << endl; 735 delete(FragmentList[FragmentCounter]); 736 } else 737 *out << Verbose(1) << KeySetCounter << " keysets were assigned to subgraph " << FragmentCounter << "." << endl; 738 FragmentCounter++; 739 if (next != NULL) 740 next->AssignKeySetsToFragment(out, reference, KeySetList, ListOfLocalAtoms, FragmentList, FragmentCounter, FreeList); 741 FragmentCounter--; 742 } else 743 *out << Verbose(1) << "KeySetList is NULL or empty." << endl; 744 745 if ((FreeList) && (ListOfLocalAtoms != NULL)) { 746 // free the index lookup list 747 Free((void **)&ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::AssignKeySetsToFragment - **ListOfLocalAtoms[]"); 748 if (FragmentCounter == 0) // first fragments frees the initial pointer to list 749 Free((void **)&ListOfLocalAtoms, "MoleculeLeafClass::AssignKeySetsToFragment - ***ListOfLocalAtoms"); 750 } 751 *out << Verbose(1) << "End of AssignKeySetsToFragment." << endl; 752 return status; 753 753 }; 754 754 … … 762 762 void MoleculeLeafClass::TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph) 763 763 { 764 *out << Verbose(1) << "Begin of TranslateIndicesToGlobalIDs." << endl;765 KeySet *TempSet = new KeySet;766 if (FragmentList[FragmentCounter] != NULL) {767 for(Graph::iterator runner = FragmentList[FragmentCounter]->begin(); runner != FragmentList[FragmentCounter]->end(); runner++) {768 for(KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)769 TempSet->insert((Leaf->FindAtom(*sprinter))->GetTrueFather()->nr);770 TotalGraph.insert(GraphPair(*TempSet, pair<int,double>(TotalNumberOfKeySets++, (*runner).second.second)));771 TempSet->clear();772 }773 delete(TempSet);774 } else {775 *out << Verbose(1) << "FragmentList is NULL." << endl;776 }777 if (next != NULL)778 next->TranslateIndicesToGlobalIDs(out, FragmentList, ++FragmentCounter, TotalNumberOfKeySets, TotalGraph);779 FragmentCounter--;780 *out << Verbose(1) << "End of TranslateIndicesToGlobalIDs." << endl;764 *out << Verbose(1) << "Begin of TranslateIndicesToGlobalIDs." << endl; 765 KeySet *TempSet = new KeySet; 766 if (FragmentList[FragmentCounter] != NULL) { 767 for(Graph::iterator runner = FragmentList[FragmentCounter]->begin(); runner != FragmentList[FragmentCounter]->end(); runner++) { 768 for(KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++) 769 TempSet->insert((Leaf->FindAtom(*sprinter))->GetTrueFather()->nr); 770 TotalGraph.insert(GraphPair(*TempSet, pair<int,double>(TotalNumberOfKeySets++, (*runner).second.second))); 771 TempSet->clear(); 772 } 773 delete(TempSet); 774 } else { 775 *out << Verbose(1) << "FragmentList is NULL." << endl; 776 } 777 if (next != NULL) 778 next->TranslateIndicesToGlobalIDs(out, FragmentList, ++FragmentCounter, TotalNumberOfKeySets, TotalGraph); 779 FragmentCounter--; 780 *out << Verbose(1) << "End of TranslateIndicesToGlobalIDs." << endl; 781 781 }; 782 782 … … 786 786 int MoleculeLeafClass::Count() const 787 787 { 788 if (next != NULL)789 return next->Count()+1;790 else791 return 1;792 }; 788 if (next != NULL) 789 return next->Count()+1; 790 else 791 return 1; 792 }; -
Property mode
changed from
-
src/molecules.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 16 16 double LSQ (const gsl_vector * x, void * params) 17 17 { 18 double sum = 0.;19 struct LSQ_params *par = (struct LSQ_params *)params;20 Vector **vectors = par->vectors;21 int num = par->num;22 23 for (int i=num;i--;) {24 for(int j=NDIM;j--;)25 sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]);26 }27 28 return sum;18 double sum = 0.; 19 struct LSQ_params *par = (struct LSQ_params *)params; 20 Vector **vectors = par->vectors; 21 int num = par->num; 22 23 for (int i=num;i--;) { 24 for(int j=NDIM;j--;) 25 sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]); 26 } 27 28 return sum; 29 29 }; 30 30 … … 36 36 molecule::molecule(periodentafel *teil) 37 37 { 38 // init atom chain list39 start = new atom;40 end = new atom;41 start->father = NULL;42 end->father = NULL;43 link(start,end);44 // init bond chain list45 first = new bond(start, end, 1, -1);46 last = new bond(start, end, 1, -1);47 link(first,last);48 // other stuff49 MDSteps = 0;50 last_atom = 0;51 elemente = teil;52 AtomCount = 0;53 BondCount = 0;54 NoNonBonds = 0;38 // init atom chain list 39 start = new atom; 40 end = new atom; 41 start->father = NULL; 42 end->father = NULL; 43 link(start,end); 44 // init bond chain list 45 first = new bond(start, end, 1, -1); 46 last = new bond(start, end, 1, -1); 47 link(first,last); 48 // other stuff 49 MDSteps = 0; 50 last_atom = 0; 51 elemente = teil; 52 AtomCount = 0; 53 BondCount = 0; 54 NoNonBonds = 0; 55 55 NoNonHydrogen = 0; 56 NoCyclicBonds = 0;57 ListOfBondsPerAtom = NULL;58 NumberOfBondsPerAtom = NULL;59 ElementCount = 0;60 for(int i=MAX_ELEMENTS;i--;)61 ElementsInMolecule[i] = 0;62 cell_size[0] = cell_size[2] = cell_size[5]= 20.;63 cell_size[1] = cell_size[3] = cell_size[4]= 0.;56 NoCyclicBonds = 0; 57 ListOfBondsPerAtom = NULL; 58 NumberOfBondsPerAtom = NULL; 59 ElementCount = 0; 60 for(int i=MAX_ELEMENTS;i--;) 61 ElementsInMolecule[i] = 0; 62 cell_size[0] = cell_size[2] = cell_size[5]= 20.; 63 cell_size[1] = cell_size[3] = cell_size[4]= 0.; 64 64 }; 65 65 … … 69 69 molecule::~molecule() 70 70 { 71 if (ListOfBondsPerAtom != NULL)72 for(int i=AtomCount;i--;)73 Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]");74 Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom");75 Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom");76 CleanupMolecule();77 delete(first);78 delete(last);79 delete(end);80 delete(start);71 if (ListOfBondsPerAtom != NULL) 72 for(int i=AtomCount;i--;) 73 Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]"); 74 Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom"); 75 Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom"); 76 CleanupMolecule(); 77 delete(first); 78 delete(last); 79 delete(end); 80 delete(start); 81 81 }; 82 82 … … 88 88 bool molecule::AddAtom(atom *pointer) 89 89 { 90 if (pointer != NULL) {91 pointer->sort = &pointer->nr;92 pointer->nr = last_atom++;// increase number within molecule93 AtomCount++;94 if (pointer->type != NULL) {95 if (ElementsInMolecule[pointer->type->Z] == 0)96 ElementCount++;97 ElementsInMolecule[pointer->type->Z]++; // increase number of elements98 if (pointer->type->Z != 1)99 NoNonHydrogen++;100 if (pointer->Name == NULL) {101 Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name");102 pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name");103 sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1);104 }105 }106 return add(pointer, end);107 } else108 return false;90 if (pointer != NULL) { 91 pointer->sort = &pointer->nr; 92 pointer->nr = last_atom++; // increase number within molecule 93 AtomCount++; 94 if (pointer->type != NULL) { 95 if (ElementsInMolecule[pointer->type->Z] == 0) 96 ElementCount++; 97 ElementsInMolecule[pointer->type->Z]++; // increase number of elements 98 if (pointer->type->Z != 1) 99 NoNonHydrogen++; 100 if (pointer->Name == NULL) { 101 Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name"); 102 pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name"); 103 sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1); 104 } 105 } 106 return add(pointer, end); 107 } else 108 return false; 109 109 }; 110 110 … … 116 116 atom * molecule::AddCopyAtom(atom *pointer) 117 117 { 118 if (pointer != NULL) {119 atom *walker = new atom();120 walker->type = pointer->type; // copy element of atom121 walker->x.CopyVector(&pointer->x); // copy coordination122 walker->v.CopyVector(&pointer->v); // copy velocity123 walker->FixedIon = pointer->FixedIon;124 walker->sort = &walker->nr;125 walker->nr = last_atom++;// increase number within molecule126 walker->father = pointer; //->GetTrueFather();127 walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name");128 strcpy (walker->Name, pointer->Name);129 add(walker, end);130 if ((pointer->type != NULL) && (pointer->type->Z != 1))131 NoNonHydrogen++;132 AtomCount++;133 return walker;134 } else135 return NULL;118 if (pointer != NULL) { 119 atom *walker = new atom(); 120 walker->type = pointer->type; // copy element of atom 121 walker->x.CopyVector(&pointer->x); // copy coordination 122 walker->v.CopyVector(&pointer->v); // copy velocity 123 walker->FixedIon = pointer->FixedIon; 124 walker->sort = &walker->nr; 125 walker->nr = last_atom++; // increase number within molecule 126 walker->father = pointer; //->GetTrueFather(); 127 walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name"); 128 strcpy (walker->Name, pointer->Name); 129 add(walker, end); 130 if ((pointer->type != NULL) && (pointer->type->Z != 1)) 131 NoNonHydrogen++; 132 AtomCount++; 133 return walker; 134 } else 135 return NULL; 136 136 }; 137 137 … … 141 141 * -# Single Bond: Simply add new atom with bond distance rescaled to typical hydrogen one 142 142 * -# Double Bond: Here, we need the **BondList of the \a *origin atom, by scanning for the other bonds instead of 143 * *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector().144 * The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two145 * replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the146 * element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two147 * hydrogens forming this angle with *origin.143 * *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector(). 144 * The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two 145 * replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the 146 * element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two 147 * hydrogens forming this angle with *origin. 148 148 * -# Triple Bond: The idea is to set up a tetraoid (C1-H1-H2-H3) (however the lengths \f$b\f$ of the sides of the base 149 * triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be150 * determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin):151 * We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2).152 * \f[ h = l \cdot \cos{\left (\frac{\alpha}{2} \right )} \qquad b = 2l \cdot \sin{\left (\frac{\alpha}{2} \right)} \quad \rightarrow \quad d = l \cdot \sqrt{\cos^2{\left (\frac{\alpha}{2} \right)}-\frac{1}{3}\cdot\sin^2{\left (\frac{\alpha}{2}\right )}}153 * \f]154 * vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates155 * the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above.156 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that157 * 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}159 * \f]160 * as the coordination of all three atoms in the coordinate system of these three vectors: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$.149 * triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be 150 * determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin): 151 * We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2). 152 * \f[ h = l \cdot \cos{\left (\frac{\alpha}{2} \right )} \qquad b = 2l \cdot \sin{\left (\frac{\alpha}{2} \right)} \quad \rightarrow \quad d = l \cdot \sqrt{\cos^2{\left (\frac{\alpha}{2} \right)}-\frac{1}{3}\cdot\sin^2{\left (\frac{\alpha}{2}\right )}} 153 * \f] 154 * vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates 155 * the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above. 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 * 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} 159 * \f] 160 * as the coordination of all three atoms in the coordinate system of these three vectors: 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 … … 167 167 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule 168 168 * \param **BondList list of bonds \a *replacement has (necessary to determine plane for double and triple bonds) 169 * \param NumBond number of bonds in \a **BondList169 * \param NumBond number of bonds in \a **BondList 170 170 * \param isAngstroem whether the coordination of the given atoms is in AtomicLength (false) or Angstrom(true) 171 171 * \return number of atoms added, if < bond::BondDegree then something went wrong … … 174 174 bool molecule::AddHydrogenReplacementAtom(ofstream *out, bond *TopBond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem) 175 175 { 176 double bondlength;// bond length of the bond to be replaced/cut177 double bondangle;// bond angle of the bond to be replaced/cut178 double BondRescale;// rescale value for the hydrogen bond length179 bool AllWentWell = true;// flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit180 bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane181 atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added182 double b,l,d,f,g, alpha, factors[NDIM];// hold temporary values in triple bond case for coordination determination183 Vector Orthovector1, Orthovector2;// temporary vectors in coordination construction184 Vector InBondvector;// vector in direction of *Bond185 bond *Binder = NULL;186 double *matrix;176 double bondlength; // bond length of the bond to be replaced/cut 177 double bondangle; // bond angle of the bond to be replaced/cut 178 double BondRescale; // rescale value for the hydrogen bond length 179 bool AllWentWell = true; // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit 180 bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane 181 atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added 182 double b,l,d,f,g, alpha, factors[NDIM]; // hold temporary values in triple bond case for coordination determination 183 Vector Orthovector1, Orthovector2; // temporary vectors in coordination construction 184 Vector InBondvector; // vector in direction of *Bond 185 bond *Binder = NULL; 186 double *matrix; 187 187 188 188 // *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl; 189 // create vector in direction of bond190 InBondvector.CopyVector(&TopReplacement->x);191 InBondvector.SubtractVector(&TopOrigin->x);192 bondlength = InBondvector.Norm();193 194 // is greater than typical bond distance? Then we have to correct periodically195 // the problem is not the H being out of the box, but InBondvector have the wrong direction196 // due to TopReplacement or Origin being on the wrong side!197 if (bondlength > BondDistance) {198 // *out << Verbose(4) << "InBondvector is: ";199 // InBondvector.Output(out);200 // *out << endl;201 Orthovector1.Zero();202 for (int i=NDIM;i--;) {203 l = TopReplacement->x.x[i] - TopOrigin->x.x[i];204 if (fabs(l) > BondDistance) { // is component greater than bond distance205 Orthovector1.x[i] = (l < 0) ? -1. : +1.;206 } // (signs are correct, was tested!)207 }208 matrix = ReturnFullMatrixforSymmetric(cell_size);209 Orthovector1.MatrixMultiplication(matrix);210 InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation211 Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix");212 bondlength = InBondvector.Norm();213 // *out << Verbose(4) << "Corrected InBondvector is now: ";214 // InBondvector.Output(out);215 // *out << endl;216 } // periodic correction finished217 218 InBondvector.Normalize();219 // get typical bond length and store as scale factor for later220 BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1];221 if (BondRescale == -1) {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 return false;224 BondRescale = bondlength;225 } else {226 if (!IsAngstroem)227 BondRescale /= (1.*AtomicLengthToAngstroem);228 }229 230 // discern single, double and triple bonds231 switch(TopBond->BondDegree) {232 case 1:233 FirstOtherAtom = new atom();// new atom234 FirstOtherAtom->type = elemente->FindElement(1);// element is Hydrogen235 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity236 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;237 if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen238 FirstOtherAtom->father = TopReplacement;239 BondRescale = bondlength;240 } else {241 FirstOtherAtom->father = NULL;// if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father242 }243 InBondvector.Scale(&BondRescale);// rescale the distance vector to Hydrogen bond length244 FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ...245 FirstOtherAtom->x.AddVector(&InBondvector);// ... and add distance vector to replacement atom246 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);247 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";248 // FirstOtherAtom->x.Output(out);249 // *out << endl;250 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);251 Binder->Cyclic = false;252 Binder->Type = TreeEdge;253 break;254 case 2:255 // determine two other bonds (warning if there are more than two other) plus valence sanity check256 for (int i=0;i<NumBond;i++) {257 if (BondList[i] != TopBond) {258 if (FirstBond == NULL) {259 FirstBond = BondList[i];260 FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);261 } else if (SecondBond == NULL) {262 SecondBond = BondList[i];263 SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);264 } else {265 *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name;266 }267 }268 }269 if (SecondOtherAtom == NULL) {// then we have an atom with valence four, but only 3 bonds: one to replace and one which is TopBond (third is FirstBond)270 SecondBond = TopBond;271 SecondOtherAtom = TopReplacement;272 }273 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all274 // *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 276 // determine the plane of these two with the *origin277 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x);278 } else {279 Orthovector1.GetOneNormalVector(&InBondvector);280 }281 //*out << Verbose(3)<< "Orthovector1: ";282 //Orthovector1.Output(out);283 //*out << endl;284 // orthogonal vector and bond vector between origin and replacement form the new plane285 Orthovector1.MakeNormalVector(&InBondvector);286 Orthovector1.Normalize();287 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl;288 289 // create the two Hydrogens ...290 FirstOtherAtom = new atom();291 SecondOtherAtom = new atom();292 FirstOtherAtom->type = elemente->FindElement(1);293 SecondOtherAtom->type = elemente->FindElement(1);294 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity295 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;296 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity297 SecondOtherAtom->FixedIon = TopReplacement->FixedIon;298 FirstOtherAtom->father = NULL;// we are just an added hydrogen with no father299 SecondOtherAtom->father = NULL; //we are just an added hydrogen with no father300 bondangle = TopOrigin->type->HBondAngle[1];301 if (bondangle == -1) {302 *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;303 return false;304 bondangle = 0;305 }306 bondangle *= M_PI/180./2.;307 // *out << Verbose(3) << "ReScaleCheck: InBondvector ";308 // InBondvector.Output(out);309 // *out << endl;310 // *out << Verbose(3) << "ReScaleCheck: Orthovector ";311 // Orthovector1.Output(out);312 // *out << endl;313 // *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl;314 FirstOtherAtom->x.Zero();315 SecondOtherAtom->x.Zero();316 for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction)317 FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle));318 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle));319 }320 FirstOtherAtom->x.Scale(&BondRescale);// rescale by correct BondDistance321 SecondOtherAtom->x.Scale(&BondRescale);322 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;323 for(int i=NDIM;i--;) { // and make relative to origin atom324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i];325 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i];326 }327 // ... and add to molecule328 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);329 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);330 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";331 // FirstOtherAtom->x.Output(out);332 // *out << endl;333 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";334 // SecondOtherAtom->x.Output(out);335 // *out << endl;336 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);337 Binder->Cyclic = false;338 Binder->Type = TreeEdge;339 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);340 Binder->Cyclic = false;341 Binder->Type = TreeEdge;342 break;343 case 3:344 // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid)345 FirstOtherAtom = new atom();346 SecondOtherAtom = new atom();347 ThirdOtherAtom = new atom();348 FirstOtherAtom->type = elemente->FindElement(1);349 SecondOtherAtom->type = elemente->FindElement(1);350 ThirdOtherAtom->type = elemente->FindElement(1);351 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity352 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;353 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity354 SecondOtherAtom->FixedIon = TopReplacement->FixedIon;355 ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity356 ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;357 FirstOtherAtom->father = NULL; //we are just an added hydrogen with no father358 SecondOtherAtom->father = NULL; //we are just an added hydrogen with no father359 ThirdOtherAtom->father = NULL; //we are just an added hydrogen with no father360 361 // we need to vectors orthonormal the InBondvector362 AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector);363 // *out << Verbose(3) << "Orthovector1: ";364 // Orthovector1.Output(out);365 // *out << endl;366 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1);367 // *out << Verbose(3) << "Orthovector2: ";368 // Orthovector2.Output(out);369 // *out << endl;370 371 // create correct coordination for the three atoms372 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;// retrieve triple bond angle from database373 l = BondRescale;// desired bond length374 b = 2.*l*sin(alpha);// base length of isosceles triangle375 d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.);// length for InBondvector376 f = b/sqrt(3.);// length for Orthvector1377 g = b/2.;// length for Orthvector2378 // *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl;379 // *out << Verbose(3) << "The three Bond lengths: " << sqrt(d*d+f*f) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << ", "<< sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << endl;380 factors[0] = d;381 factors[1] = f;382 factors[2] = 0.;383 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);384 factors[1] = -0.5*f;385 factors[2] = g;386 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);387 factors[2] = -g;388 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);389 390 // rescale each to correct BondDistance391 // FirstOtherAtom->x.Scale(&BondRescale);392 // SecondOtherAtom->x.Scale(&BondRescale);393 // ThirdOtherAtom->x.Scale(&BondRescale);394 395 // and relative to *origin atom396 FirstOtherAtom->x.AddVector(&TopOrigin->x);397 SecondOtherAtom->x.AddVector(&TopOrigin->x);398 ThirdOtherAtom->x.AddVector(&TopOrigin->x);399 400 // ... and add to molecule401 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);402 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);403 AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom);404 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";405 // FirstOtherAtom->x.Output(out);406 // *out << endl;407 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";408 // SecondOtherAtom->x.Output(out);409 // *out << endl;410 // *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: ";411 // ThirdOtherAtom->x.Output(out);412 // *out << endl;413 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);414 Binder->Cyclic = false;415 Binder->Type = TreeEdge;416 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);417 Binder->Cyclic = false;418 Binder->Type = TreeEdge;419 Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1);420 Binder->Cyclic = false;421 Binder->Type = TreeEdge;422 break;423 default:424 cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl;425 AllWentWell = false;426 break;427 }189 // create vector in direction of bond 190 InBondvector.CopyVector(&TopReplacement->x); 191 InBondvector.SubtractVector(&TopOrigin->x); 192 bondlength = InBondvector.Norm(); 193 194 // is greater than typical bond distance? Then we have to correct periodically 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) { 198 // *out << Verbose(4) << "InBondvector is: "; 199 // InBondvector.Output(out); 200 // *out << endl; 201 Orthovector1.Zero(); 202 for (int i=NDIM;i--;) { 203 l = TopReplacement->x.x[i] - TopOrigin->x.x[i]; 204 if (fabs(l) > BondDistance) { // is component greater than bond distance 205 Orthovector1.x[i] = (l < 0) ? -1. : +1.; 206 } // (signs are correct, was tested!) 207 } 208 matrix = ReturnFullMatrixforSymmetric(cell_size); 209 Orthovector1.MatrixMultiplication(matrix); 210 InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation 211 Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix"); 212 bondlength = InBondvector.Norm(); 213 // *out << Verbose(4) << "Corrected InBondvector is now: "; 214 // InBondvector.Output(out); 215 // *out << endl; 216 } // periodic correction finished 217 218 InBondvector.Normalize(); 219 // get typical bond length and store as scale factor for later 220 BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1]; 221 if (BondRescale == -1) { 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 return false; 224 BondRescale = bondlength; 225 } else { 226 if (!IsAngstroem) 227 BondRescale /= (1.*AtomicLengthToAngstroem); 228 } 229 230 // discern single, double and triple bonds 231 switch(TopBond->BondDegree) { 232 case 1: 233 FirstOtherAtom = new atom(); // new atom 234 FirstOtherAtom->type = elemente->FindElement(1); // element is Hydrogen 235 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 236 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 237 if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen 238 FirstOtherAtom->father = TopReplacement; 239 BondRescale = bondlength; 240 } else { 241 FirstOtherAtom->father = NULL; // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father 242 } 243 InBondvector.Scale(&BondRescale); // rescale the distance vector to Hydrogen bond length 244 FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ... 245 FirstOtherAtom->x.AddVector(&InBondvector); // ... and add distance vector to replacement atom 246 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 247 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 248 // FirstOtherAtom->x.Output(out); 249 // *out << endl; 250 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 251 Binder->Cyclic = false; 252 Binder->Type = TreeEdge; 253 break; 254 case 2: 255 // determine two other bonds (warning if there are more than two other) plus valence sanity check 256 for (int i=0;i<NumBond;i++) { 257 if (BondList[i] != TopBond) { 258 if (FirstBond == NULL) { 259 FirstBond = BondList[i]; 260 FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin); 261 } else if (SecondBond == NULL) { 262 SecondBond = BondList[i]; 263 SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin); 264 } else { 265 *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name; 266 } 267 } 268 } 269 if (SecondOtherAtom == NULL) { // then we have an atom with valence four, but only 3 bonds: one to replace and one which is TopBond (third is FirstBond) 270 SecondBond = TopBond; 271 SecondOtherAtom = TopReplacement; 272 } 273 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 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 276 // determine the plane of these two with the *origin 277 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x); 278 } else { 279 Orthovector1.GetOneNormalVector(&InBondvector); 280 } 281 //*out << Verbose(3)<< "Orthovector1: "; 282 //Orthovector1.Output(out); 283 //*out << endl; 284 // orthogonal vector and bond vector between origin and replacement form the new plane 285 Orthovector1.MakeNormalVector(&InBondvector); 286 Orthovector1.Normalize(); 287 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl; 288 289 // create the two Hydrogens ... 290 FirstOtherAtom = new atom(); 291 SecondOtherAtom = new atom(); 292 FirstOtherAtom->type = elemente->FindElement(1); 293 SecondOtherAtom->type = elemente->FindElement(1); 294 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 295 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 296 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 297 SecondOtherAtom->FixedIon = TopReplacement->FixedIon; 298 FirstOtherAtom->father = NULL; // we are just an added hydrogen with no father 299 SecondOtherAtom->father = NULL; // we are just an added hydrogen with no father 300 bondangle = TopOrigin->type->HBondAngle[1]; 301 if (bondangle == -1) { 302 *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 303 return false; 304 bondangle = 0; 305 } 306 bondangle *= M_PI/180./2.; 307 // *out << Verbose(3) << "ReScaleCheck: InBondvector "; 308 // InBondvector.Output(out); 309 // *out << endl; 310 // *out << Verbose(3) << "ReScaleCheck: Orthovector "; 311 // Orthovector1.Output(out); 312 // *out << endl; 313 // *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl; 314 FirstOtherAtom->x.Zero(); 315 SecondOtherAtom->x.Zero(); 316 for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction) 317 FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle)); 318 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle)); 319 } 320 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 321 SecondOtherAtom->x.Scale(&BondRescale); 322 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl; 323 for(int i=NDIM;i--;) { // and make relative to origin atom 324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 325 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i]; 326 } 327 // ... and add to molecule 328 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 329 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom); 330 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 331 // FirstOtherAtom->x.Output(out); 332 // *out << endl; 333 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: "; 334 // SecondOtherAtom->x.Output(out); 335 // *out << endl; 336 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 337 Binder->Cyclic = false; 338 Binder->Type = TreeEdge; 339 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1); 340 Binder->Cyclic = false; 341 Binder->Type = TreeEdge; 342 break; 343 case 3: 344 // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid) 345 FirstOtherAtom = new atom(); 346 SecondOtherAtom = new atom(); 347 ThirdOtherAtom = new atom(); 348 FirstOtherAtom->type = elemente->FindElement(1); 349 SecondOtherAtom->type = elemente->FindElement(1); 350 ThirdOtherAtom->type = elemente->FindElement(1); 351 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 352 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 353 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 354 SecondOtherAtom->FixedIon = TopReplacement->FixedIon; 355 ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 356 ThirdOtherAtom->FixedIon = TopReplacement->FixedIon; 357 FirstOtherAtom->father = NULL; // we are just an added hydrogen with no father 358 SecondOtherAtom->father = NULL; // we are just an added hydrogen with no father 359 ThirdOtherAtom->father = NULL; // we are just an added hydrogen with no father 360 361 // we need to vectors orthonormal the InBondvector 362 AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector); 363 // *out << Verbose(3) << "Orthovector1: "; 364 // Orthovector1.Output(out); 365 // *out << endl; 366 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1); 367 // *out << Verbose(3) << "Orthovector2: "; 368 // Orthovector2.Output(out); 369 // *out << endl; 370 371 // create correct coordination for the three atoms 372 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.; // retrieve triple bond angle from database 373 l = BondRescale; // desired bond length 374 b = 2.*l*sin(alpha); // base length of isosceles triangle 375 d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.); // length for InBondvector 376 f = b/sqrt(3.); // length for Orthvector1 377 g = b/2.; // length for Orthvector2 378 // *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl; 379 // *out << Verbose(3) << "The three Bond lengths: " << sqrt(d*d+f*f) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << endl; 380 factors[0] = d; 381 factors[1] = f; 382 factors[2] = 0.; 383 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 384 factors[1] = -0.5*f; 385 factors[2] = g; 386 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 387 factors[2] = -g; 388 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 389 390 // rescale each to correct BondDistance 391 // FirstOtherAtom->x.Scale(&BondRescale); 392 // SecondOtherAtom->x.Scale(&BondRescale); 393 // ThirdOtherAtom->x.Scale(&BondRescale); 394 395 // and relative to *origin atom 396 FirstOtherAtom->x.AddVector(&TopOrigin->x); 397 SecondOtherAtom->x.AddVector(&TopOrigin->x); 398 ThirdOtherAtom->x.AddVector(&TopOrigin->x); 399 400 // ... and add to molecule 401 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 402 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom); 403 AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom); 404 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 405 // FirstOtherAtom->x.Output(out); 406 // *out << endl; 407 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: "; 408 // SecondOtherAtom->x.Output(out); 409 // *out << endl; 410 // *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: "; 411 // ThirdOtherAtom->x.Output(out); 412 // *out << endl; 413 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 414 Binder->Cyclic = false; 415 Binder->Type = TreeEdge; 416 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1); 417 Binder->Cyclic = false; 418 Binder->Type = TreeEdge; 419 Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1); 420 Binder->Cyclic = false; 421 Binder->Type = TreeEdge; 422 break; 423 default: 424 cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl; 425 AllWentWell = false; 426 break; 427 } 428 428 429 429 // *out << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl; 430 return AllWentWell;430 return AllWentWell; 431 431 }; 432 432 … … 438 438 bool molecule::AddXYZFile(string filename) 439 439 { 440 istringstream *input = NULL;441 int NumberOfAtoms = 0; // atom number in xyz read442 int i, j; // loop variables443 atom *Walker = NULL;// pointer to added atom444 char shorthand[3];// shorthand for atom name445 ifstream xyzfile;// xyz file446 string line;// currently parsed line447 double x[3];// atom coordinates448 449 xyzfile.open(filename.c_str());450 if (!xyzfile)451 return false;452 453 getline(xyzfile,line,'\n'); // Read numer of atoms in file454 input = new istringstream(line);455 *input >> NumberOfAtoms;456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl;457 getline(xyzfile,line,'\n'); // Read comment458 cout << Verbose(1) << "Comment: " << line << endl;459 460 if (MDSteps == 0) // no atoms yet present461 MDSteps++;462 for(i=0;i<NumberOfAtoms;i++){463 Walker = new atom;464 getline(xyzfile,line,'\n');465 istringstream *item = new istringstream(line);466 //istringstream input(line);467 //cout << Verbose(1) << "Reading: " << line << endl;468 *item >> shorthand;469 *item >> x[0];470 *item >> x[1];471 *item >> x[2];472 Walker->type = elemente->FindElement(shorthand);473 if (Walker->type == NULL) {474 cerr << "Could not parse the element at line: '" << line << "', setting to H.";475 Walker->type = elemente->FindElement(1);476 }477 if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) {478 Trajectories[Walker].R.resize(MDSteps+10);479 Trajectories[Walker].U.resize(MDSteps+10);480 Trajectories[Walker].F.resize(MDSteps+10);481 }482 for(j=NDIM;j--;) {483 Walker->x.x[j] = x[j];484 Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j];485 Trajectories[Walker].U.at(MDSteps-1).x[j] = 0;486 Trajectories[Walker].F.at(MDSteps-1).x[j] = 0;487 }488 AddAtom(Walker);// add to molecule489 delete(item);490 }491 xyzfile.close();492 delete(input);493 return true;440 istringstream *input = NULL; 441 int NumberOfAtoms = 0; // atom number in xyz read 442 int i, j; // loop variables 443 atom *Walker = NULL; // pointer to added atom 444 char shorthand[3]; // shorthand for atom name 445 ifstream xyzfile; // xyz file 446 string line; // currently parsed line 447 double x[3]; // atom coordinates 448 449 xyzfile.open(filename.c_str()); 450 if (!xyzfile) 451 return false; 452 453 getline(xyzfile,line,'\n'); // Read numer of atoms in file 454 input = new istringstream(line); 455 *input >> NumberOfAtoms; 456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 457 getline(xyzfile,line,'\n'); // Read comment 458 cout << Verbose(1) << "Comment: " << line << endl; 459 460 if (MDSteps == 0) // no atoms yet present 461 MDSteps++; 462 for(i=0;i<NumberOfAtoms;i++){ 463 Walker = new atom; 464 getline(xyzfile,line,'\n'); 465 istringstream *item = new istringstream(line); 466 //istringstream input(line); 467 //cout << Verbose(1) << "Reading: " << line << endl; 468 *item >> shorthand; 469 *item >> x[0]; 470 *item >> x[1]; 471 *item >> x[2]; 472 Walker->type = elemente->FindElement(shorthand); 473 if (Walker->type == NULL) { 474 cerr << "Could not parse the element at line: '" << line << "', setting to H."; 475 Walker->type = elemente->FindElement(1); 476 } 477 if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) { 478 Trajectories[Walker].R.resize(MDSteps+10); 479 Trajectories[Walker].U.resize(MDSteps+10); 480 Trajectories[Walker].F.resize(MDSteps+10); 481 } 482 for(j=NDIM;j--;) { 483 Walker->x.x[j] = x[j]; 484 Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j]; 485 Trajectories[Walker].U.at(MDSteps-1).x[j] = 0; 486 Trajectories[Walker].F.at(MDSteps-1).x[j] = 0; 487 } 488 AddAtom(Walker); // add to molecule 489 delete(item); 490 } 491 xyzfile.close(); 492 delete(input); 493 return true; 494 494 }; 495 495 … … 499 499 molecule *molecule::CopyMolecule() 500 500 { 501 molecule *copy = new molecule(elemente);502 atom *CurrentAtom = NULL;503 atom *LeftAtom = NULL, *RightAtom = NULL;504 atom *Walker = NULL;505 506 // copy all atoms507 Walker = start;508 while(Walker->next != end) {509 Walker = Walker->next;510 CurrentAtom = copy->AddCopyAtom(Walker);511 }512 513 // copy all bonds514 bond *Binder = first;515 bond *NewBond = NULL;516 while(Binder->next != last) {517 Binder = Binder->next;518 // get the pendant atoms of current bond in the copy molecule519 LeftAtom = copy->start;520 while (LeftAtom->next != copy->end) {521 LeftAtom = LeftAtom->next;522 if (LeftAtom->father == Binder->leftatom)523 break;524 }525 RightAtom = copy->start;526 while (RightAtom->next != copy->end) {527 RightAtom = RightAtom->next;528 if (RightAtom->father == Binder->rightatom)529 break;530 }531 NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);532 NewBond->Cyclic = Binder->Cyclic;533 if (Binder->Cyclic)534 copy->NoCyclicBonds++;535 NewBond->Type = Binder->Type;536 }537 // correct fathers538 Walker = copy->start;539 while(Walker->next != copy->end) {540 Walker = Walker->next;541 if (Walker->father->father == Walker->father)// same atom in copy's father points to itself542 Walker->father = Walker;// set father to itself (copy of a whole molecule)543 else544 Walker->father = Walker->father->father;// set father to original's father545 }546 // copy values547 copy->CountAtoms((ofstream *)&cout);548 copy->CountElements();549 if (first->next != last) {// if adjaceny list is present550 copy->BondDistance = BondDistance;551 copy->CreateListOfBondsPerAtom((ofstream *)&cout);552 }553 554 return copy;501 molecule *copy = new molecule(elemente); 502 atom *CurrentAtom = NULL; 503 atom *LeftAtom = NULL, *RightAtom = NULL; 504 atom *Walker = NULL; 505 506 // copy all atoms 507 Walker = start; 508 while(Walker->next != end) { 509 Walker = Walker->next; 510 CurrentAtom = copy->AddCopyAtom(Walker); 511 } 512 513 // copy all bonds 514 bond *Binder = first; 515 bond *NewBond = NULL; 516 while(Binder->next != last) { 517 Binder = Binder->next; 518 // get the pendant atoms of current bond in the copy molecule 519 LeftAtom = copy->start; 520 while (LeftAtom->next != copy->end) { 521 LeftAtom = LeftAtom->next; 522 if (LeftAtom->father == Binder->leftatom) 523 break; 524 } 525 RightAtom = copy->start; 526 while (RightAtom->next != copy->end) { 527 RightAtom = RightAtom->next; 528 if (RightAtom->father == Binder->rightatom) 529 break; 530 } 531 NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree); 532 NewBond->Cyclic = Binder->Cyclic; 533 if (Binder->Cyclic) 534 copy->NoCyclicBonds++; 535 NewBond->Type = Binder->Type; 536 } 537 // correct fathers 538 Walker = copy->start; 539 while(Walker->next != copy->end) { 540 Walker = Walker->next; 541 if (Walker->father->father == Walker->father) // same atom in copy's father points to itself 542 Walker->father = Walker; // set father to itself (copy of a whole molecule) 543 else 544 Walker->father = Walker->father->father; // set father to original's father 545 } 546 // copy values 547 copy->CountAtoms((ofstream *)&cout); 548 copy->CountElements(); 549 if (first->next != last) { // if adjaceny list is present 550 copy->BondDistance = BondDistance; 551 copy->CreateListOfBondsPerAtom((ofstream *)&cout); 552 } 553 554 return copy; 555 555 }; 556 556 … … 563 563 bond * molecule::AddBond(atom *atom1, atom *atom2, int degree=1) 564 564 { 565 bond *Binder = NULL;566 if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) {567 Binder = new bond(atom1, atom2, degree, BondCount++);568 if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))569 NoNonBonds++;570 add(Binder, last);571 } else {572 cerr << Verbose(1) << "ERROR: Could not add bond between " << atom1->Name << " and " << atom2->Name << " as one or both are not present in the molecule." << endl;573 }574 return Binder;565 bond *Binder = NULL; 566 if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) { 567 Binder = new bond(atom1, atom2, degree, BondCount++); 568 if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1)) 569 NoNonBonds++; 570 add(Binder, last); 571 } else { 572 cerr << Verbose(1) << "ERROR: Could not add bond between " << atom1->Name << " and " << atom2->Name << " as one or both are not present in the molecule." << endl; 573 } 574 return Binder; 575 575 }; 576 576 … … 582 582 bool molecule::RemoveBond(bond *pointer) 583 583 { 584 //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;585 removewithoutcheck(pointer);586 return true;584 //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl; 585 removewithoutcheck(pointer); 586 return true; 587 587 }; 588 588 … … 594 594 bool molecule::RemoveBonds(atom *BondPartner) 595 595 { 596 cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;597 return false;596 cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl; 597 return false; 598 598 }; 599 599 … … 603 603 void molecule::SetBoxDimension(Vector *dim) 604 604 { 605 cell_size[0] = dim->x[0];606 cell_size[1] = 0.;607 cell_size[2] = dim->x[1];608 cell_size[3] = 0.;609 cell_size[4] = 0.;610 cell_size[5] = dim->x[2];605 cell_size[0] = dim->x[0]; 606 cell_size[1] = 0.; 607 cell_size[2] = dim->x[1]; 608 cell_size[3] = 0.; 609 cell_size[4] = 0.; 610 cell_size[5] = dim->x[2]; 611 611 }; 612 612 … … 617 617 bool molecule::CenterInBox(ofstream *out, Vector *BoxLengths) 618 618 { 619 bool status = true;620 atom *ptr = NULL;621 Vector *min = new Vector;622 Vector *max = new Vector;623 624 // gather min and max for each axis625 ptr = start->next;// start at first in list626 if (ptr != end) {//list not empty?627 for (int i=NDIM;i--;) {628 max->x[i] = ptr->x.x[i];629 min->x[i] = ptr->x.x[i];630 }631 while (ptr->next != end) {// continue with second if present632 ptr = ptr->next;633 //ptr->Output(1,1,out);634 for (int i=NDIM;i--;) {635 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];636 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];637 }638 }639 }640 // sanity check641 for(int i=NDIM;i--;) {642 if (max->x[i] - min->x[i] > BoxLengths->x[i])643 status = false;644 }645 // warn if check failed646 if (!status)647 *out << "WARNING: molecule is bigger than defined box!" << endl;648 else {// else center in box649 max->AddVector(min);650 max->Scale(-1.);651 max->AddVector(BoxLengths);652 max->Scale(0.5);653 Translate(max);654 }655 656 // free and exit657 delete(min);658 delete(max);659 return status;619 bool status = true; 620 atom *ptr = NULL; 621 Vector *min = new Vector; 622 Vector *max = new Vector; 623 624 // gather min and max for each axis 625 ptr = start->next; // start at first in list 626 if (ptr != end) { //list not empty? 627 for (int i=NDIM;i--;) { 628 max->x[i] = ptr->x.x[i]; 629 min->x[i] = ptr->x.x[i]; 630 } 631 while (ptr->next != end) { // continue with second if present 632 ptr = ptr->next; 633 //ptr->Output(1,1,out); 634 for (int i=NDIM;i--;) { 635 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i]; 636 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i]; 637 } 638 } 639 } 640 // sanity check 641 for(int i=NDIM;i--;) { 642 if (max->x[i] - min->x[i] > BoxLengths->x[i]) 643 status = false; 644 } 645 // warn if check failed 646 if (!status) 647 *out << "WARNING: molecule is bigger than defined box!" << endl; 648 else { // else center in box 649 max->AddVector(min); 650 max->Scale(-1.); 651 max->AddVector(BoxLengths); 652 max->Scale(0.5); 653 Translate(max); 654 } 655 656 // free and exit 657 delete(min); 658 delete(max); 659 return status; 660 660 }; 661 661 … … 666 666 void molecule::CenterEdge(ofstream *out, Vector *max) 667 667 { 668 Vector *min = new Vector;669 670 // *out << Verbose(3) << "Begin of CenterEdge." << endl;671 atom *ptr = start->next;// start at first in list672 if (ptr != end) {//list not empty?673 for (int i=NDIM;i--;) {674 max->x[i] = ptr->x.x[i];675 min->x[i] = ptr->x.x[i];676 }677 while (ptr->next != end) {// continue with second if present678 ptr = ptr->next;679 //ptr->Output(1,1,out);680 for (int i=NDIM;i--;) {681 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];682 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];683 }684 }685 // *out << Verbose(4) << "Maximum is ";686 // max->Output(out);687 // *out << ", Minimum is ";688 // min->Output(out);689 // *out << endl;690 min->Scale(-1.);691 max->AddVector(min);692 Translate(min);693 }694 delete(min);695 // *out << Verbose(3) << "End of CenterEdge." << endl;668 Vector *min = new Vector; 669 670 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 671 atom *ptr = start->next; // start at first in list 672 if (ptr != end) { //list not empty? 673 for (int i=NDIM;i--;) { 674 max->x[i] = ptr->x.x[i]; 675 min->x[i] = ptr->x.x[i]; 676 } 677 while (ptr->next != end) { // continue with second if present 678 ptr = ptr->next; 679 //ptr->Output(1,1,out); 680 for (int i=NDIM;i--;) { 681 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i]; 682 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i]; 683 } 684 } 685 // *out << Verbose(4) << "Maximum is "; 686 // max->Output(out); 687 // *out << ", Minimum is "; 688 // min->Output(out); 689 // *out << endl; 690 min->Scale(-1.); 691 max->AddVector(min); 692 Translate(min); 693 } 694 delete(min); 695 // *out << Verbose(3) << "End of CenterEdge." << endl; 696 696 }; 697 697 … … 702 702 void molecule::CenterOrigin(ofstream *out, Vector *center) 703 703 { 704 int Num = 0;705 atom *ptr = start->next;// start at first in list706 707 for(int i=NDIM;i--;) // zero center vector708 center->x[i] = 0.;709 710 if (ptr != end) {//list not empty?711 while (ptr->next != end) {// continue with second if present712 ptr = ptr->next;713 Num++;714 center->AddVector(&ptr->x);715 }716 center->Scale(-1./Num); // divide through total number (and sign for direction)717 Translate(center);718 }704 int Num = 0; 705 atom *ptr = start->next; // start at first in list 706 707 for(int i=NDIM;i--;) // zero center vector 708 center->x[i] = 0.; 709 710 if (ptr != end) { //list not empty? 711 while (ptr->next != end) { // continue with second if present 712 ptr = ptr->next; 713 Num++; 714 center->AddVector(&ptr->x); 715 } 716 center->Scale(-1./Num); // divide through total number (and sign for direction) 717 Translate(center); 718 } 719 719 }; 720 720 … … 725 725 Vector * molecule::DetermineCenterOfAll(ofstream *out) 726 726 { 727 atom *ptr = start->next;// start at first in list728 Vector *a = new Vector();729 Vector tmp;730 double Num = 0;731 732 a->Zero();733 734 if (ptr != end) {//list not empty?735 while (ptr->next != end) {// continue with second if present736 ptr = ptr->next;737 Num += 1.;738 tmp.CopyVector(&ptr->x);739 a->AddVector(&tmp);740 }741 a->Scale(-1./Num); // divide through total mass (and sign for direction)742 }743 //cout << Verbose(1) << "Resulting center of gravity: ";744 //a->Output(out);745 //cout << endl;746 return a;727 atom *ptr = start->next; // start at first in list 728 Vector *a = new Vector(); 729 Vector tmp; 730 double Num = 0; 731 732 a->Zero(); 733 734 if (ptr != end) { //list not empty? 735 while (ptr->next != end) { // continue with second if present 736 ptr = ptr->next; 737 Num += 1.; 738 tmp.CopyVector(&ptr->x); 739 a->AddVector(&tmp); 740 } 741 a->Scale(-1./Num); // divide through total mass (and sign for direction) 742 } 743 //cout << Verbose(1) << "Resulting center of gravity: "; 744 //a->Output(out); 745 //cout << endl; 746 return a; 747 747 }; 748 748 … … 753 753 Vector * molecule::DetermineCenterOfGravity(ofstream *out) 754 754 { 755 atom *ptr = start->next; // start at first in list755 atom *ptr = start->next; // start at first in list 756 756 Vector *a = new Vector(); 757 757 Vector tmp; 758 double Num = 0;758 double Num = 0; 759 759 760 760 a->Zero(); 761 761 762 if (ptr != end) {//list not empty?763 while (ptr->next != end) {// continue with second if present764 ptr = ptr->next;765 Num += ptr->type->mass;766 tmp.CopyVector(&ptr->x);767 tmp.Scale(ptr->type->mass);// scale by mass768 a->AddVector(&tmp);769 }770 a->Scale(-1./Num); // divide through total mass (and sign for direction)771 }772 // *out << Verbose(1) << "Resulting center of gravity: ";773 // a->Output(out);774 // *out << endl;775 return a;762 if (ptr != end) { //list not empty? 763 while (ptr->next != end) { // continue with second if present 764 ptr = ptr->next; 765 Num += ptr->type->mass; 766 tmp.CopyVector(&ptr->x); 767 tmp.Scale(ptr->type->mass); // scale by mass 768 a->AddVector(&tmp); 769 } 770 a->Scale(-1./Num); // divide through total mass (and sign for direction) 771 } 772 // *out << Verbose(1) << "Resulting center of gravity: "; 773 // a->Output(out); 774 // *out << endl; 775 return a; 776 776 }; 777 777 … … 782 782 void molecule::CenterGravity(ofstream *out, Vector *center) 783 783 { 784 if (center == NULL) {785 DetermineCenter(*center);786 Translate(center);787 delete(center);788 } else {789 Translate(center);790 }784 if (center == NULL) { 785 DetermineCenter(*center); 786 Translate(center); 787 delete(center); 788 } else { 789 Translate(center); 790 } 791 791 }; 792 792 … … 796 796 void molecule::Scale(double **factor) 797 797 { 798 atom *ptr = start;799 800 while (ptr->next != end) {801 ptr = ptr->next;802 for (int j=0;j<MDSteps;j++)803 Trajectories[ptr].R.at(j).Scale(factor);804 ptr->x.Scale(factor);805 }798 atom *ptr = start; 799 800 while (ptr->next != end) { 801 ptr = ptr->next; 802 for (int j=0;j<MDSteps;j++) 803 Trajectories[ptr].R.at(j).Scale(factor); 804 ptr->x.Scale(factor); 805 } 806 806 }; 807 807 … … 811 811 void molecule::Translate(const Vector *trans) 812 812 { 813 atom *ptr = start;814 815 while (ptr->next != end) {816 ptr = ptr->next;817 for (int j=0;j<MDSteps;j++)818 Trajectories[ptr].R.at(j).Translate(trans);819 ptr->x.Translate(trans);820 }813 atom *ptr = start; 814 815 while (ptr->next != end) { 816 ptr = ptr->next; 817 for (int j=0;j<MDSteps;j++) 818 Trajectories[ptr].R.at(j).Translate(trans); 819 ptr->x.Translate(trans); 820 } 821 821 }; 822 822 … … 826 826 void molecule::Mirror(const Vector *n) 827 827 { 828 atom *ptr = start;829 830 while (ptr->next != end) {831 ptr = ptr->next;832 for (int j=0;j<MDSteps;j++)833 Trajectories[ptr].R.at(j).Mirror(n);834 ptr->x.Mirror(n);835 }828 atom *ptr = start; 829 830 while (ptr->next != end) { 831 ptr = ptr->next; 832 for (int j=0;j<MDSteps;j++) 833 Trajectories[ptr].R.at(j).Mirror(n); 834 ptr->x.Mirror(n); 835 } 836 836 }; 837 837 … … 841 841 void molecule::DetermineCenter(Vector &Center) 842 842 { 843 atom *Walker = start;844 bond *Binder = NULL;845 double *matrix = ReturnFullMatrixforSymmetric(cell_size);846 double tmp;847 bool flag;848 Vector Testvector, Translationvector;849 850 do {851 Center.Zero();852 flag = true;853 while (Walker->next != end) {854 Walker = Walker->next;843 atom *Walker = start; 844 bond *Binder = NULL; 845 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 846 double tmp; 847 bool flag; 848 Vector Testvector, Translationvector; 849 850 do { 851 Center.Zero(); 852 flag = true; 853 while (Walker->next != end) { 854 Walker = Walker->next; 855 855 #ifdef ADDHYDROGEN 856 if (Walker->type->Z != 1) {856 if (Walker->type->Z != 1) { 857 857 #endif 858 Testvector.CopyVector(&Walker->x);859 Testvector.InverseMatrixMultiplication(matrix);860 Translationvector.Zero();861 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {862 Binder = ListOfBondsPerAtom[Walker->nr][i];863 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing864 for (int j=0;j<NDIM;j++) {865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j];866 if ((fabs(tmp)) > BondDistance) {867 flag = false;868 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl;869 if (tmp > 0)870 Translationvector.x[j] -= 1.;871 else872 Translationvector.x[j] += 1.;873 }874 }875 }876 Testvector.AddVector(&Translationvector);877 Testvector.MatrixMultiplication(matrix);878 Center.AddVector(&Testvector);879 cout << Verbose(1) << "vector is: ";880 Testvector.Output((ofstream *)&cout);881 cout << endl;858 Testvector.CopyVector(&Walker->x); 859 Testvector.InverseMatrixMultiplication(matrix); 860 Translationvector.Zero(); 861 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 862 Binder = ListOfBondsPerAtom[Walker->nr][i]; 863 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 864 for (int j=0;j<NDIM;j++) { 865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 866 if ((fabs(tmp)) > BondDistance) { 867 flag = false; 868 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl; 869 if (tmp > 0) 870 Translationvector.x[j] -= 1.; 871 else 872 Translationvector.x[j] += 1.; 873 } 874 } 875 } 876 Testvector.AddVector(&Translationvector); 877 Testvector.MatrixMultiplication(matrix); 878 Center.AddVector(&Testvector); 879 cout << Verbose(1) << "vector is: "; 880 Testvector.Output((ofstream *)&cout); 881 cout << endl; 882 882 #ifdef ADDHYDROGEN 883 // now also change all hydrogens884 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {885 Binder = ListOfBondsPerAtom[Walker->nr][i];886 if (Binder->GetOtherAtom(Walker)->type->Z == 1) {887 Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x);888 Testvector.InverseMatrixMultiplication(matrix);889 Testvector.AddVector(&Translationvector);890 Testvector.MatrixMultiplication(matrix);891 Center.AddVector(&Testvector);892 cout << Verbose(1) << "Hydrogen vector is: ";893 Testvector.Output((ofstream *)&cout);894 cout << endl;895 }896 }897 }883 // now also change all hydrogens 884 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 885 Binder = ListOfBondsPerAtom[Walker->nr][i]; 886 if (Binder->GetOtherAtom(Walker)->type->Z == 1) { 887 Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x); 888 Testvector.InverseMatrixMultiplication(matrix); 889 Testvector.AddVector(&Translationvector); 890 Testvector.MatrixMultiplication(matrix); 891 Center.AddVector(&Testvector); 892 cout << Verbose(1) << "Hydrogen vector is: "; 893 Testvector.Output((ofstream *)&cout); 894 cout << endl; 895 } 896 } 897 } 898 898 #endif 899 }900 } while (!flag);901 Free((void **)&matrix, "molecule::DetermineCenter: *matrix");902 Center.Scale(1./(double)AtomCount);899 } 900 } while (!flag); 901 Free((void **)&matrix, "molecule::DetermineCenter: *matrix"); 902 Center.Scale(1./(double)AtomCount); 903 903 }; 904 904 … … 909 909 void molecule::PrincipalAxisSystem(ofstream *out, bool DoRotate) 910 910 { 911 atom *ptr = start; // start at first in list911 atom *ptr = start; // start at first in list 912 912 double InertiaTensor[NDIM*NDIM]; 913 913 Vector *CenterOfGravity = DetermineCenterOfGravity(out); … … 938 938 *out << "The inertia tensor is:" << endl; 939 939 for(int i=0;i<NDIM;i++) { 940 for(int j=0;j<NDIM;j++)941 *out << InertiaTensor[i*NDIM+j] << " ";942 *out << endl;940 for(int j=0;j<NDIM;j++) 941 *out << InertiaTensor[i*NDIM+j] << " "; 942 *out << endl; 943 943 } 944 944 *out << endl; … … 960 960 // check whether we rotate or not 961 961 if (DoRotate) { 962 *out << Verbose(1) << "Transforming molecule into PAS ... ";963 // the eigenvectors specify the transformation matrix964 ptr = start;965 while (ptr->next != end) {966 ptr = ptr->next;967 for (int j=0;j<MDSteps;j++)968 Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data);969 ptr->x.MatrixMultiplication(evec->data);970 }971 *out << "done." << endl;972 973 // summing anew for debugging (resulting matrix has to be diagonal!)974 // reset inertia tensor975 for(int i=0;i<NDIM*NDIM;i++)976 InertiaTensor[i] = 0.;977 978 // sum up inertia tensor979 ptr = start;980 while (ptr->next != end) {981 ptr = ptr->next;982 Vector x;983 x.CopyVector(&ptr->x);984 //x.SubtractVector(CenterOfGravity);985 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);986 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);987 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);988 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);989 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);990 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);991 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);992 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);993 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);994 }995 // print InertiaTensor for debugging996 *out << "The inertia tensor is:" << endl;997 for(int i=0;i<NDIM;i++) {998 for(int j=0;j<NDIM;j++)999 *out << InertiaTensor[i*NDIM+j] << " ";1000 *out << endl;1001 }1002 *out << endl;962 *out << Verbose(1) << "Transforming molecule into PAS ... "; 963 // the eigenvectors specify the transformation matrix 964 ptr = start; 965 while (ptr->next != end) { 966 ptr = ptr->next; 967 for (int j=0;j<MDSteps;j++) 968 Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data); 969 ptr->x.MatrixMultiplication(evec->data); 970 } 971 *out << "done." << endl; 972 973 // summing anew for debugging (resulting matrix has to be diagonal!) 974 // reset inertia tensor 975 for(int i=0;i<NDIM*NDIM;i++) 976 InertiaTensor[i] = 0.; 977 978 // sum up inertia tensor 979 ptr = start; 980 while (ptr->next != end) { 981 ptr = ptr->next; 982 Vector x; 983 x.CopyVector(&ptr->x); 984 //x.SubtractVector(CenterOfGravity); 985 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]); 986 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]); 987 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]); 988 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]); 989 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]); 990 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]); 991 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]); 992 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]); 993 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]); 994 } 995 // print InertiaTensor for debugging 996 *out << "The inertia tensor is:" << endl; 997 for(int i=0;i<NDIM;i++) { 998 for(int j=0;j<NDIM;j++) 999 *out << InertiaTensor[i*NDIM+j] << " "; 1000 *out << endl; 1001 } 1002 *out << endl; 1003 1003 } 1004 1004 … … 1020 1020 bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem) 1021 1021 { 1022 element *runner = elemente->start;1023 atom *walker = NULL;1024 int AtomNo;1025 ifstream input(file);1026 string token;1027 stringstream item;1028 double a, IonMass;1029 ForceMatrix Force;1030 Vector tmpvector;1031 1032 CountElements();// make sure ElementsInMolecule is up to date1033 1034 // check file1035 if (input == NULL) {1036 return false;1037 } else {1038 // parse file into ForceMatrix1039 if (!Force.ParseMatrix(file, 0,0,0)) {1040 cerr << "Could not parse Force Matrix file " << file << "." << endl;1041 return false;1042 }1043 if (Force.RowCounter[0] != AtomCount) {1044 cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl;1045 return false;1046 }1047 // correct Forces1048 // for(int d=0;d<NDIM;d++)1049 // tmpvector.x[d] = 0.;1050 // for(int i=0;i<AtomCount;i++)1051 // for(int d=0;d<NDIM;d++) {1052 // tmpvector.x[d] += Force.Matrix[0][i][d+5];1053 // }1054 // for(int i=0;i<AtomCount;i++)1055 // for(int d=0;d<NDIM;d++) {1056 // Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount;1057 // }1058 // and perform Verlet integration for each atom with position, velocity and force vector1059 runner = elemente->start;1060 while (runner->next != elemente->end) { // go through every element1061 runner = runner->next;1062 IonMass = runner->mass;1063 a = delta_t*0.5/IonMass;// (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a1064 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1065 AtomNo = 0;1066 walker = start;1067 while (walker->next != end) { // go through every atom of this element1068 walker = walker->next;1069 if (walker->type == runner) { // if this atom fits to element1070 // check size of vectors1071 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {1072 //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;1073 Trajectories[walker].R.resize(MDSteps+10);1074 Trajectories[walker].U.resize(MDSteps+10);1075 Trajectories[walker].F.resize(MDSteps+10);1076 }1077 // 1. calculate x(t+\delta t)1078 for (int d=0; d<NDIM; d++) {1079 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5];1080 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];1081 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]);1082 Trajectories[walker].R.at(MDSteps).x[d] += 0.5*delta_t*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d])/IonMass;// F = m * a and s = 0.5 * F/m * t^2 = F * a * t1083 }1084 // 2. Calculate v(t+\delta t)1085 for (int d=0; d<NDIM; d++) {1086 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];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 }1089 // cout << "Integrated position&velocity of step " << (MDSteps) << ": (";1090 // for (int d=0;d<NDIM;d++)1091 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";// next step1092 // cout << ")\t(";1093 // for (int d=0;d<NDIM;d++)1094 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";// next step1095 // cout << ")" << endl;1096 // next atom1097 AtomNo++;1098 }1099 }1100 }1101 }1102 }1103 // // correct velocities (rather momenta) so that center of mass remains motionless1104 // tmpvector.zero()1105 // IonMass = 0.;1106 // walker = start;1107 // while (walker->next != end) { // go through every atom1108 // walker = walker->next;1109 // IonMass += walker->type->mass;// sum up total mass1110 // for(int d=0;d<NDIM;d++) {1111 // tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;1112 // }1113 // }1114 // walker = start;1115 // while (walker->next != end) { // go through every atom of this element1116 // walker = walker->next;1117 // for(int d=0;d<NDIM;d++) {1118 // Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass;1119 // }1120 // }1121 MDSteps++;1122 1123 1124 // exit1125 return true;1022 element *runner = elemente->start; 1023 atom *walker = NULL; 1024 int AtomNo; 1025 ifstream input(file); 1026 string token; 1027 stringstream item; 1028 double a, IonMass; 1029 ForceMatrix Force; 1030 Vector tmpvector; 1031 1032 CountElements(); // make sure ElementsInMolecule is up to date 1033 1034 // check file 1035 if (input == NULL) { 1036 return false; 1037 } else { 1038 // parse file into ForceMatrix 1039 if (!Force.ParseMatrix(file, 0,0,0)) { 1040 cerr << "Could not parse Force Matrix file " << file << "." << endl; 1041 return false; 1042 } 1043 if (Force.RowCounter[0] != AtomCount) { 1044 cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl; 1045 return false; 1046 } 1047 // correct Forces 1048 // for(int d=0;d<NDIM;d++) 1049 // tmpvector.x[d] = 0.; 1050 // for(int i=0;i<AtomCount;i++) 1051 // for(int d=0;d<NDIM;d++) { 1052 // tmpvector.x[d] += Force.Matrix[0][i][d+5]; 1053 // } 1054 // for(int i=0;i<AtomCount;i++) 1055 // for(int d=0;d<NDIM;d++) { 1056 // Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount; 1057 // } 1058 // and perform Verlet integration for each atom with position, velocity and force vector 1059 runner = elemente->start; 1060 while (runner->next != elemente->end) { // go through every element 1061 runner = runner->next; 1062 IonMass = runner->mass; 1063 a = delta_t*0.5/IonMass; // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a 1064 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1065 AtomNo = 0; 1066 walker = start; 1067 while (walker->next != end) { // go through every atom of this element 1068 walker = walker->next; 1069 if (walker->type == runner) { // if this atom fits to element 1070 // check size of vectors 1071 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) { 1072 //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl; 1073 Trajectories[walker].R.resize(MDSteps+10); 1074 Trajectories[walker].U.resize(MDSteps+10); 1075 Trajectories[walker].F.resize(MDSteps+10); 1076 } 1077 // 1. calculate x(t+\delta t) 1078 for (int d=0; d<NDIM; d++) { 1079 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5]; 1080 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d]; 1081 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]); 1082 Trajectories[walker].R.at(MDSteps).x[d] += 0.5*delta_t*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d])/IonMass; // F = m * a and s = 0.5 * F/m * t^2 = F * a * t 1083 } 1084 // 2. Calculate v(t+\delta t) 1085 for (int d=0; d<NDIM; d++) { 1086 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d]; 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 } 1089 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1090 // for (int d=0;d<NDIM;d++) 1091 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step 1092 // cout << ")\t("; 1093 // for (int d=0;d<NDIM;d++) 1094 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " "; // next step 1095 // cout << ")" << endl; 1096 // next atom 1097 AtomNo++; 1098 } 1099 } 1100 } 1101 } 1102 } 1103 // // correct velocities (rather momenta) so that center of mass remains motionless 1104 // tmpvector.zero() 1105 // IonMass = 0.; 1106 // walker = start; 1107 // while (walker->next != end) { // go through every atom 1108 // walker = walker->next; 1109 // IonMass += walker->type->mass; // sum up total mass 1110 // for(int d=0;d<NDIM;d++) { 1111 // tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass; 1112 // } 1113 // } 1114 // walker = start; 1115 // while (walker->next != end) { // go through every atom of this element 1116 // walker = walker->next; 1117 // for(int d=0;d<NDIM;d++) { 1118 // Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass; 1119 // } 1120 // } 1121 MDSteps++; 1122 1123 1124 // exit 1125 return true; 1126 1126 }; 1127 1127 … … 1131 1131 void molecule::Align(Vector *n) 1132 1132 { 1133 atom *ptr = start;1134 double alpha, tmp;1135 Vector z_axis;1136 z_axis.x[0] = 0.;1137 z_axis.x[1] = 0.;1138 z_axis.x[2] = 1.;1139 1140 // rotate on z-x plane1141 cout << Verbose(0) << "Begin of Aligning all atoms." << endl;1142 alpha = atan(-n->x[0]/n->x[2]);1143 cout << Verbose(1) << "Z-X-angle: " << alpha << " ... ";1144 while (ptr->next != end) {1145 ptr = ptr->next;1146 tmp = ptr->x.x[0];1147 ptr->x.x[0] =cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];1148 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];1149 for (int j=0;j<MDSteps;j++) {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];1152 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];1153 }1154 }1155 // rotate n vector1156 tmp = n->x[0];1157 n->x[0] = cos(alpha) * tmp +sin(alpha) * n->x[2];1158 n->x[2] = -sin(alpha) * tmp +cos(alpha) * n->x[2];1159 cout << Verbose(1) << "alignment vector after first rotation: ";1160 n->Output((ofstream *)&cout);1161 cout << endl;1162 1163 // rotate on z-y plane1164 ptr = start;1165 alpha = atan(-n->x[1]/n->x[2]);1166 cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... ";1167 while (ptr->next != end) {1168 ptr = ptr->next;1169 tmp = ptr->x.x[1];1170 ptr->x.x[1] =cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];1171 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];1172 for (int j=0;j<MDSteps;j++) {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];1175 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];1176 }1177 }1178 // rotate n vector (for consistency check)1179 tmp = n->x[1];1180 n->x[1] = cos(alpha) * tmp +sin(alpha) * n->x[2];1181 n->x[2] = -sin(alpha) * tmp +cos(alpha) * n->x[2];1182 1183 cout << Verbose(1) << "alignment vector after second rotation: ";1184 n->Output((ofstream *)&cout);1185 cout << Verbose(1) << endl;1186 cout << Verbose(0) << "End of Aligning all atoms." << endl;1133 atom *ptr = start; 1134 double alpha, tmp; 1135 Vector z_axis; 1136 z_axis.x[0] = 0.; 1137 z_axis.x[1] = 0.; 1138 z_axis.x[2] = 1.; 1139 1140 // rotate on z-x plane 1141 cout << Verbose(0) << "Begin of Aligning all atoms." << endl; 1142 alpha = atan(-n->x[0]/n->x[2]); 1143 cout << Verbose(1) << "Z-X-angle: " << alpha << " ... "; 1144 while (ptr->next != end) { 1145 ptr = ptr->next; 1146 tmp = ptr->x.x[0]; 1147 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1148 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1149 for (int j=0;j<MDSteps;j++) { 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]; 1152 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1153 } 1154 } 1155 // rotate n vector 1156 tmp = n->x[0]; 1157 n->x[0] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1158 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1159 cout << Verbose(1) << "alignment vector after first rotation: "; 1160 n->Output((ofstream *)&cout); 1161 cout << endl; 1162 1163 // rotate on z-y plane 1164 ptr = start; 1165 alpha = atan(-n->x[1]/n->x[2]); 1166 cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... "; 1167 while (ptr->next != end) { 1168 ptr = ptr->next; 1169 tmp = ptr->x.x[1]; 1170 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1171 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1172 for (int j=0;j<MDSteps;j++) { 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]; 1175 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1176 } 1177 } 1178 // rotate n vector (for consistency check) 1179 tmp = n->x[1]; 1180 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1181 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1182 1183 cout << Verbose(1) << "alignment vector after second rotation: "; 1184 n->Output((ofstream *)&cout); 1185 cout << Verbose(1) << endl; 1186 cout << Verbose(0) << "End of Aligning all atoms." << endl; 1187 1187 }; 1188 1188 … … 1193 1193 bool molecule::RemoveAtom(atom *pointer) 1194 1194 { 1195 if (ElementsInMolecule[pointer->type->Z] != 0)// this would indicate an error1196 ElementsInMolecule[pointer->type->Z]--;// decrease number of atom of this element1197 else1198 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl;1199 if (ElementsInMolecule[pointer->type->Z] == 0)// was last atom of this element?1200 ElementCount--;1201 Trajectories.erase(pointer);1202 return remove(pointer, start, end);1195 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1196 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 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; 1199 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1200 ElementCount--; 1201 Trajectories.erase(pointer); 1202 return remove(pointer, start, end); 1203 1203 }; 1204 1204 … … 1208 1208 bool molecule::CleanupMolecule() 1209 1209 { 1210 return (cleanup(start,end) && cleanup(first,last));1210 return (cleanup(start,end) && cleanup(first,last)); 1211 1211 }; 1212 1212 … … 1215 1215 * \return pointer to atom or NULL 1216 1216 */ 1217 atom * molecule::FindAtom(int Nr) const{1218 atom * walker = find(&Nr, start,end);1219 if (walker != NULL) {1220 //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl;1221 return walker;1222 } else {1223 cout << Verbose(0) << "Atom not found in list." << endl;1224 return NULL;1225 }1217 atom * molecule::FindAtom(int Nr) const{ 1218 atom * walker = find(&Nr, start,end); 1219 if (walker != NULL) { 1220 //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl; 1221 return walker; 1222 } else { 1223 cout << Verbose(0) << "Atom not found in list." << endl; 1224 return NULL; 1225 } 1226 1226 }; 1227 1227 … … 1231 1231 atom * molecule::AskAtom(string text) 1232 1232 { 1233 int No;1234 atom *ion = NULL;1235 do {1236 //cout << Verbose(0) << "============Atom list==========================" << endl;1237 //mol->Output((ofstream *)&cout);1238 //cout << Verbose(0) << "===============================================" << endl;1239 cout << Verbose(0) << text;1240 cin >> No;1241 ion = this->FindAtom(No);1242 } while (ion == NULL);1243 return ion;1233 int No; 1234 atom *ion = NULL; 1235 do { 1236 //cout << Verbose(0) << "============Atom list==========================" << endl; 1237 //mol->Output((ofstream *)&cout); 1238 //cout << Verbose(0) << "===============================================" << endl; 1239 cout << Verbose(0) << text; 1240 cin >> No; 1241 ion = this->FindAtom(No); 1242 } while (ion == NULL); 1243 return ion; 1244 1244 }; 1245 1245 … … 1250 1250 bool molecule::CheckBounds(const Vector *x) const 1251 1251 { 1252 bool result = true;1253 int j =-1;1254 for (int i=0;i<NDIM;i++) {1255 j += i+1;1256 result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j]));1257 }1258 //return result;1259 return true; /// probably not gonna use the check no more1252 bool result = true; 1253 int j =-1; 1254 for (int i=0;i<NDIM;i++) { 1255 j += i+1; 1256 result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j])); 1257 } 1258 //return result; 1259 return true; /// probably not gonna use the check no more 1260 1260 }; 1261 1261 … … 1267 1267 double LeastSquareDistance (const gsl_vector * x, void * params) 1268 1268 { 1269 double res = 0, t;1270 Vector a,b,c,d;1271 struct lsq_params *par = (struct lsq_params *)params;1272 atom *ptr = par->mol->start;1273 1274 // initialize vectors1275 a.x[0] = gsl_vector_get(x,0);1276 a.x[1] = gsl_vector_get(x,1);1277 a.x[2] = gsl_vector_get(x,2);1278 b.x[0] = gsl_vector_get(x,3);1279 b.x[1] = gsl_vector_get(x,4);1280 b.x[2] = gsl_vector_get(x,5);1281 // go through all atoms1282 while (ptr != par->mol->end) {1283 ptr = ptr->next;1284 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type1285 c.CopyVector(&ptr->x);// copy vector to temporary one1286 c.SubtractVector(&a);// subtract offset vector1287 t = c.ScalarProduct(&b);// get direction parameter1288 d.CopyVector(&b);// and create vector1289 d.Scale(&t);1290 c.SubtractVector(&d);// ... yielding distance vector1291 res += d.ScalarProduct((const Vector *)&d);// add squared distance1292 }1293 }1294 return res;1269 double res = 0, t; 1270 Vector a,b,c,d; 1271 struct lsq_params *par = (struct lsq_params *)params; 1272 atom *ptr = par->mol->start; 1273 1274 // initialize vectors 1275 a.x[0] = gsl_vector_get(x,0); 1276 a.x[1] = gsl_vector_get(x,1); 1277 a.x[2] = gsl_vector_get(x,2); 1278 b.x[0] = gsl_vector_get(x,3); 1279 b.x[1] = gsl_vector_get(x,4); 1280 b.x[2] = gsl_vector_get(x,5); 1281 // go through all atoms 1282 while (ptr != par->mol->end) { 1283 ptr = ptr->next; 1284 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type 1285 c.CopyVector(&ptr->x); // copy vector to temporary one 1286 c.SubtractVector(&a); // subtract offset vector 1287 t = c.ScalarProduct(&b); // get direction parameter 1288 d.CopyVector(&b); // and create vector 1289 d.Scale(&t); 1290 c.SubtractVector(&d); // ... yielding distance vector 1291 res += d.ScalarProduct((const Vector *)&d); // add squared distance 1292 } 1293 } 1294 return res; 1295 1295 }; 1296 1296 … … 1300 1300 void molecule::GetAlignvector(struct lsq_params * par) const 1301 1301 { 1302 int np = 6;1303 1304 const gsl_multimin_fminimizer_type *T =1305 gsl_multimin_fminimizer_nmsimplex;1306 gsl_multimin_fminimizer *s = NULL;1307 gsl_vector *ss;1308 gsl_multimin_function minex_func;1309 1310 size_t iter = 0, i;1311 int status;1312 double size;1313 1314 /* Initial vertex size vector */1315 ss = gsl_vector_alloc (np);1316 1317 /* Set all step sizes to 1 */1318 gsl_vector_set_all (ss, 1.0);1319 1320 /* Starting point */1321 par->x = gsl_vector_alloc (np);1322 par->mol = this;1323 1324 gsl_vector_set (par->x, 0, 0.0);// offset1325 gsl_vector_set (par->x, 1, 0.0);1326 gsl_vector_set (par->x, 2, 0.0);1327 gsl_vector_set (par->x, 3, 0.0);// direction1328 gsl_vector_set (par->x, 4, 0.0);1329 gsl_vector_set (par->x, 5, 1.0);1330 1331 /* Initialize method and iterate */1332 minex_func.f = &LeastSquareDistance;1333 minex_func.n = np;1334 minex_func.params = (void *)par;1335 1336 s = gsl_multimin_fminimizer_alloc (T, np);1337 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss);1338 1339 do1340 {1341 iter++;1342 status = gsl_multimin_fminimizer_iterate(s);1343 1344 if (status)1345 break;1346 1347 size = gsl_multimin_fminimizer_size (s);1348 status = gsl_multimin_test_size (size, 1e-2);1349 1350 if (status == GSL_SUCCESS)1351 {1352 printf ("converged to minimum at\n");1353 }1354 1355 printf ("%5d ", (int)iter);1356 for (i = 0; i < (size_t)np; i++)1357 {1358 printf ("%10.3e ", gsl_vector_get (s->x, i));1359 }1360 printf ("f() = %7.3f size = %.3f\n", s->fval, size);1361 }1362 while (status == GSL_CONTINUE && iter < 100);1363 1364 for (i=0;i<(size_t)np;i++)1365 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i));1366 //gsl_vector_free(par->x);1367 gsl_vector_free(ss);1368 gsl_multimin_fminimizer_free (s);1302 int np = 6; 1303 1304 const gsl_multimin_fminimizer_type *T = 1305 gsl_multimin_fminimizer_nmsimplex; 1306 gsl_multimin_fminimizer *s = NULL; 1307 gsl_vector *ss; 1308 gsl_multimin_function minex_func; 1309 1310 size_t iter = 0, i; 1311 int status; 1312 double size; 1313 1314 /* Initial vertex size vector */ 1315 ss = gsl_vector_alloc (np); 1316 1317 /* Set all step sizes to 1 */ 1318 gsl_vector_set_all (ss, 1.0); 1319 1320 /* Starting point */ 1321 par->x = gsl_vector_alloc (np); 1322 par->mol = this; 1323 1324 gsl_vector_set (par->x, 0, 0.0); // offset 1325 gsl_vector_set (par->x, 1, 0.0); 1326 gsl_vector_set (par->x, 2, 0.0); 1327 gsl_vector_set (par->x, 3, 0.0); // direction 1328 gsl_vector_set (par->x, 4, 0.0); 1329 gsl_vector_set (par->x, 5, 1.0); 1330 1331 /* Initialize method and iterate */ 1332 minex_func.f = &LeastSquareDistance; 1333 minex_func.n = np; 1334 minex_func.params = (void *)par; 1335 1336 s = gsl_multimin_fminimizer_alloc (T, np); 1337 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1338 1339 do 1340 { 1341 iter++; 1342 status = gsl_multimin_fminimizer_iterate(s); 1343 1344 if (status) 1345 break; 1346 1347 size = gsl_multimin_fminimizer_size (s); 1348 status = gsl_multimin_test_size (size, 1e-2); 1349 1350 if (status == GSL_SUCCESS) 1351 { 1352 printf ("converged to minimum at\n"); 1353 } 1354 1355 printf ("%5d ", (int)iter); 1356 for (i = 0; i < (size_t)np; i++) 1357 { 1358 printf ("%10.3e ", gsl_vector_get (s->x, i)); 1359 } 1360 printf ("f() = %7.3f size = %.3f\n", s->fval, size); 1361 } 1362 while (status == GSL_CONTINUE && iter < 100); 1363 1364 for (i=0;i<(size_t)np;i++) 1365 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); 1366 //gsl_vector_free(par->x); 1367 gsl_vector_free(ss); 1368 gsl_multimin_fminimizer_free (s); 1369 1369 }; 1370 1370 … … 1374 1374 bool molecule::Output(ofstream *out) 1375 1375 { 1376 element *runner;1377 atom *walker = NULL;1378 int ElementNo, AtomNo;1379 CountElements();1380 1381 if (out == NULL) {1382 return false;1383 } else {1384 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2]MoveType (0 MoveIon, 1 FixedIon)" << endl;1385 ElementNo = 0;1386 runner = elemente->start;1387 while (runner->next != elemente->end) { // go through every element1388 runner = runner->next;1389 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1390 ElementNo++;1391 AtomNo = 0;1392 walker = start;1393 while (walker->next != end) { // go through every atom of this element1394 walker = walker->next;1395 if (walker->type == runner) { // if this atom fits to element1396 AtomNo++;1397 walker->Output(ElementNo, AtomNo, out); // removed due to trajectories1398 }1399 }1400 }1401 }1402 return true;1403 }1376 element *runner; 1377 atom *walker = NULL; 1378 int ElementNo, AtomNo; 1379 CountElements(); 1380 1381 if (out == NULL) { 1382 return false; 1383 } else { 1384 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl; 1385 ElementNo = 0; 1386 runner = elemente->start; 1387 while (runner->next != elemente->end) { // go through every element 1388 runner = runner->next; 1389 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1390 ElementNo++; 1391 AtomNo = 0; 1392 walker = start; 1393 while (walker->next != end) { // go through every atom of this element 1394 walker = walker->next; 1395 if (walker->type == runner) { // if this atom fits to element 1396 AtomNo++; 1397 walker->Output(ElementNo, AtomNo, out); // removed due to trajectories 1398 } 1399 } 1400 } 1401 } 1402 return true; 1403 } 1404 1404 }; 1405 1405 … … 1409 1409 bool molecule::OutputTrajectories(ofstream *out) 1410 1410 { 1411 element *runner = NULL;1412 atom *walker = NULL;1413 int ElementNo, AtomNo;1414 CountElements();1415 1416 if (out == NULL) {1417 return false;1418 } else {1419 for (int step = 0; step < MDSteps; step++) {1420 if (step == 0) {1421 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2]MoveType (0 MoveIon, 1 FixedIon)" << endl;1422 } else {1423 *out << "# ====== MD step " << step << " =========" << endl;1424 }1425 ElementNo = 0;1426 runner = elemente->start;1427 while (runner->next != elemente->end) { // go through every element1428 runner = runner->next;1429 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1430 ElementNo++;1431 AtomNo = 0;1432 walker = start;1433 while (walker->next != end) { // go through every atom of this element1434 walker = walker->next;1435 if (walker->type == runner) { // if this atom fits to element1436 AtomNo++;1437 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"<< fixed << setprecision(9) << showpoint;1438 *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2];1439 *out << "\t" << walker->FixedIon;1440 if (Trajectories[walker].U.at(step).Norm() > MYEPSILON)1441 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].U.at(step).x[0] << "\t" << Trajectories[walker].U.at(step).x[1] << "\t" << Trajectories[walker].U.at(step).x[2] << "\t";1442 if (Trajectories[walker].F.at(step).Norm() > MYEPSILON)1443 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].F.at(step).x[0] << "\t" << Trajectories[walker].F.at(step).x[1] << "\t" << Trajectories[walker].F.at(step).x[2] << "\t";1444 *out << "\t# Number in molecule " << walker->nr << endl;1445 }1446 }1447 }1448 }1449 }1450 return true;1451 }1411 element *runner = NULL; 1412 atom *walker = NULL; 1413 int ElementNo, AtomNo; 1414 CountElements(); 1415 1416 if (out == NULL) { 1417 return false; 1418 } else { 1419 for (int step = 0; step < MDSteps; step++) { 1420 if (step == 0) { 1421 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl; 1422 } else { 1423 *out << "# ====== MD step " << step << " =========" << endl; 1424 } 1425 ElementNo = 0; 1426 runner = elemente->start; 1427 while (runner->next != elemente->end) { // go through every element 1428 runner = runner->next; 1429 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1430 ElementNo++; 1431 AtomNo = 0; 1432 walker = start; 1433 while (walker->next != end) { // go through every atom of this element 1434 walker = walker->next; 1435 if (walker->type == runner) { // if this atom fits to element 1436 AtomNo++; 1437 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t" << fixed << setprecision(9) << showpoint; 1438 *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2]; 1439 *out << "\t" << walker->FixedIon; 1440 if (Trajectories[walker].U.at(step).Norm() > MYEPSILON) 1441 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].U.at(step).x[0] << "\t" << Trajectories[walker].U.at(step).x[1] << "\t" << Trajectories[walker].U.at(step).x[2] << "\t"; 1442 if (Trajectories[walker].F.at(step).Norm() > MYEPSILON) 1443 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].F.at(step).x[0] << "\t" << Trajectories[walker].F.at(step).x[1] << "\t" << Trajectories[walker].F.at(step).x[2] << "\t"; 1444 *out << "\t# Number in molecule " << walker->nr << endl; 1445 } 1446 } 1447 } 1448 } 1449 } 1450 return true; 1451 } 1452 1452 }; 1453 1453 … … 1457 1457 void molecule::OutputListOfBonds(ofstream *out) const 1458 1458 { 1459 *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl;1460 atom *Walker = start;1461 while (Walker->next != end) {1462 Walker = Walker->next;1459 *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl; 1460 atom *Walker = start; 1461 while (Walker->next != end) { 1462 Walker = Walker->next; 1463 1463 #ifdef ADDHYDROGEN 1464 if (Walker->type->Z != 1) {// regard only non-hydrogen1464 if (Walker->type->Z != 1) { // regard only non-hydrogen 1465 1465 #endif 1466 *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl;1467 for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {1468 *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl;1469 }1466 *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl; 1467 for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) { 1468 *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl; 1469 } 1470 1470 #ifdef ADDHYDROGEN 1471 }1471 } 1472 1472 #endif 1473 }1474 *out << endl;1473 } 1474 *out << endl; 1475 1475 }; 1476 1476 … … 1478 1478 * \param *out stream pointer 1479 1479 */ 1480 bool molecule::Checkout(ofstream *out) const1480 bool molecule::Checkout(ofstream *out) const 1481 1481 { 1482 1482 return elemente->Checkout(out, ElementsInMolecule); … … 1488 1488 bool molecule::OutputTrajectoriesXYZ(ofstream *out) 1489 1489 { 1490 atom *walker = NULL;1491 int No = 0;1492 time_t now;1493 1494 now = time((time_t *)NULL);// Get the system time and put it into 'now' as 'calender time'1495 walker = start;1496 while (walker->next != end) { // go through every atom and count1497 walker = walker->next;1498 No++;1499 }1500 if (out != NULL) {1501 for (int step=0;step<MDSteps;step++) {1502 *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);1503 walker = start;1504 while (walker->next != end) { // go through every atom of this element1505 walker = walker->next;1506 *out << walker->type->symbol << "\t" << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2] << endl;1507 }1508 }1509 return true;1510 } else1511 return false;1490 atom *walker = NULL; 1491 int No = 0; 1492 time_t now; 1493 1494 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1495 walker = start; 1496 while (walker->next != end) { // go through every atom and count 1497 walker = walker->next; 1498 No++; 1499 } 1500 if (out != NULL) { 1501 for (int step=0;step<MDSteps;step++) { 1502 *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now); 1503 walker = start; 1504 while (walker->next != end) { // go through every atom of this element 1505 walker = walker->next; 1506 *out << walker->type->symbol << "\t" << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2] << endl; 1507 } 1508 } 1509 return true; 1510 } else 1511 return false; 1512 1512 }; 1513 1513 … … 1517 1517 bool molecule::OutputXYZ(ofstream *out) const 1518 1518 { 1519 atom *walker = NULL;1520 int AtomNo = 0, ElementNo;1521 time_t now;1522 element *runner = NULL;1523 1524 now = time((time_t *)NULL);// Get the system time and put it into 'now' as 'calender time'1525 walker = start;1526 while (walker->next != end) { // go through every atom and count1527 walker = walker->next;1528 AtomNo++;1529 }1530 if (out != NULL) {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 element1535 runner = runner->next;1536 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1537 ElementNo++;1538 walker = start;1539 while (walker->next != end) { // go through every atom of this element1540 walker = walker->next;1541 if (walker->type == runner) { // if this atom fits to element1542 walker->OutputXYZLine(out);1543 }1544 }1545 }1546 }1547 return true;1548 } else1549 return false;1519 atom *walker = NULL; 1520 int AtomNo = 0, ElementNo; 1521 time_t now; 1522 element *runner = NULL; 1523 1524 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1525 walker = start; 1526 while (walker->next != end) { // go through every atom and count 1527 walker = walker->next; 1528 AtomNo++; 1529 } 1530 if (out != NULL) { 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 } 1546 } 1547 return true; 1548 } else 1549 return false; 1550 1550 }; 1551 1551 … … 1557 1557 int i = 0; 1558 1558 atom *Walker = start; 1559 while (Walker->next != end) {1560 Walker = Walker->next;1561 i++;1562 }1563 if ((AtomCount == 0) || (i != AtomCount)) {1564 *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl;1565 AtomCount = i;1566 1567 // count NonHydrogen atoms and give each atom a unique name1568 if (AtomCount != 0) {1569 i=0;1570 NoNonHydrogen = 0;1571 Walker = start;1572 while (Walker->next != end) {1573 Walker = Walker->next;1574 Walker->nr = i;// update number in molecule (for easier referencing in FragmentMolecule lateron)1575 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it1576 NoNonHydrogen++;1577 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name");1578 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name");1579 sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1);1580 *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl;1581 i++;1582 }1583 } else1584 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl;1585 }1559 while (Walker->next != end) { 1560 Walker = Walker->next; 1561 i++; 1562 } 1563 if ((AtomCount == 0) || (i != AtomCount)) { 1564 *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl; 1565 AtomCount = i; 1566 1567 // count NonHydrogen atoms and give each atom a unique name 1568 if (AtomCount != 0) { 1569 i=0; 1570 NoNonHydrogen = 0; 1571 Walker = start; 1572 while (Walker->next != end) { 1573 Walker = Walker->next; 1574 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 1575 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 1576 NoNonHydrogen++; 1577 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 1578 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); 1579 sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1); 1580 *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl; 1581 i++; 1582 } 1583 } else 1584 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1585 } 1586 1586 }; 1587 1587 … … 1591 1591 { 1592 1592 int i = 0; 1593 for(i=MAX_ELEMENTS;i--;)1594 ElementsInMolecule[i] = 0;1593 for(i=MAX_ELEMENTS;i--;) 1594 ElementsInMolecule[i] = 0; 1595 1595 ElementCount = 0; 1596 1596 1597 atom *walker = start;1598 while (walker->next != end) {1599 walker = walker->next;1600 ElementsInMolecule[walker->type->Z]++;1601 i++;1602 }1603 for(i=MAX_ELEMENTS;i--;)1604 ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0);1597 atom *walker = start; 1598 while (walker->next != end) { 1599 walker = walker->next; 1600 ElementsInMolecule[walker->type->Z]++; 1601 i++; 1602 } 1603 for(i=MAX_ELEMENTS;i--;) 1604 ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0); 1605 1605 }; 1606 1606 … … 1612 1612 int molecule::CountCyclicBonds(ofstream *out) 1613 1613 { 1614 int No = 0;1615 int *MinimumRingSize = NULL;1616 MoleculeLeafClass *Subgraphs = NULL;1617 class StackClass<bond *> *BackEdgeStack = NULL;1618 bond *Binder = first;1619 if ((Binder->next != last) && (Binder->next->Type == Undetermined)) {1620 *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl;1621 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);1622 while (Subgraphs->next != NULL) {1623 Subgraphs = Subgraphs->next;1624 delete(Subgraphs->previous);1625 }1626 delete(Subgraphs);1627 delete[](MinimumRingSize);1628 }1629 while(Binder->next != last) {1630 Binder = Binder->next;1631 if (Binder->Cyclic)1632 No++;1633 }1634 delete(BackEdgeStack);1635 return No;1614 int No = 0; 1615 int *MinimumRingSize = NULL; 1616 MoleculeLeafClass *Subgraphs = NULL; 1617 class StackClass<bond *> *BackEdgeStack = NULL; 1618 bond *Binder = first; 1619 if ((Binder->next != last) && (Binder->next->Type == Undetermined)) { 1620 *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl; 1621 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack); 1622 while (Subgraphs->next != NULL) { 1623 Subgraphs = Subgraphs->next; 1624 delete(Subgraphs->previous); 1625 } 1626 delete(Subgraphs); 1627 delete[](MinimumRingSize); 1628 } 1629 while(Binder->next != last) { 1630 Binder = Binder->next; 1631 if (Binder->Cyclic) 1632 No++; 1633 } 1634 delete(BackEdgeStack); 1635 return No; 1636 1636 }; 1637 1637 /** Returns Shading as a char string. … … 1641 1641 string molecule::GetColor(enum Shading color) 1642 1642 { 1643 switch(color) {1644 case white:1645 return "white";1646 break;1647 case lightgray:1648 return "lightgray";1649 break;1650 case darkgray:1651 return "darkgray";1652 break;1653 case black:1654 return "black";1655 break;1656 default:1657 return "uncolored";1658 break;1659 };1643 switch(color) { 1644 case white: 1645 return "white"; 1646 break; 1647 case lightgray: 1648 return "lightgray"; 1649 break; 1650 case darkgray: 1651 return "darkgray"; 1652 break; 1653 case black: 1654 return "black"; 1655 break; 1656 default: 1657 return "uncolored"; 1658 break; 1659 }; 1660 1660 }; 1661 1661 … … 1666 1666 void molecule::CalculateOrbitals(class config &configuration) 1667 1667 { 1668 configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0;1669 for(int i=MAX_ELEMENTS;i--;) {1670 if (ElementsInMolecule[i] != 0) {1671 //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl;1672 configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence);1673 }1674 }1675 configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2);1676 configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2;1677 configuration.MaxPsiDouble /= 2;1678 configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1;1679 if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) {1680 configuration.ProcPEGamma /= 2;1681 configuration.ProcPEPsi *= 2;1682 } else {1683 configuration.ProcPEGamma *= configuration.ProcPEPsi;1684 configuration.ProcPEPsi = 1;1685 }1686 configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble;1668 configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0; 1669 for(int i=MAX_ELEMENTS;i--;) { 1670 if (ElementsInMolecule[i] != 0) { 1671 //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl; 1672 configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence); 1673 } 1674 } 1675 configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2); 1676 configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2; 1677 configuration.MaxPsiDouble /= 2; 1678 configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1; 1679 if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) { 1680 configuration.ProcPEGamma /= 2; 1681 configuration.ProcPEPsi *= 2; 1682 } else { 1683 configuration.ProcPEGamma *= configuration.ProcPEPsi; 1684 configuration.ProcPEPsi = 1; 1685 } 1686 configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble; 1687 1687 }; 1688 1688 … … 1697 1697 atom *Walker, *OtherWalker; 1698 1698 1699 if (!input)1700 {1701 cout << Verbose(1) << "Opening silica failed \n";1702 };1699 if (!input) 1700 { 1701 cout << Verbose(1) << "Opening silica failed \n"; 1702 }; 1703 1703 1704 1704 *input >> ws >> atom1; 1705 1705 *input >> ws >> atom2; 1706 cout << Verbose(1) << "Scanning file\n";1707 while (!input->eof()) // Check whether we read everything already1708 {1706 cout << Verbose(1) << "Scanning file\n"; 1707 while (!input->eof()) // Check whether we read everything already 1708 { 1709 1709 *input >> ws >> atom1; 1710 1710 *input >> ws >> atom2; 1711 if(atom2<atom1) //Sort indices of atoms in order1712 {1713 temp=atom1;1714 atom1=atom2;1715 atom2=temp;1716 };1717 1718 Walker=start;1719 while(Walker-> nr != atom1) // Find atom corresponding to first index1720 {1721 Walker = Walker->next;1722 };1723 OtherWalker = Walker->next;1724 while(OtherWalker->nr != atom2) // Find atom corresponding to second index1725 {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);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 1733 1734 1734 }; … … 1741 1741 * To make it O(N log N) the function uses the linked-cell technique as follows: 1742 1742 * The procedure is step-wise: 1743 * -# Remove every bond in list1744 * -# Count the atoms in the molecule with CountAtoms()1745 * -# partition cell into smaller linked cells of size \a bonddistance1746 * -# put each atom into its corresponding cell1747 * -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true1748 * -# create the list of bonds via CreateListOfBondsPerAtom()1749 * -# correct the bond degree iteratively (single->double->triple bond)1750 * -# finally print the bond list to \a *out if desired1743 * -# Remove every bond in list 1744 * -# Count the atoms in the molecule with CountAtoms() 1745 * -# partition cell into smaller linked cells of size \a bonddistance 1746 * -# put each atom into its corresponding cell 1747 * -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true 1748 * -# create the list of bonds via CreateListOfBondsPerAtom() 1749 * -# correct the bond degree iteratively (single->double->triple bond) 1750 * -# finally print the bond list to \a *out if desired 1751 1751 * \param *out out stream for printing the matrix, NULL if no output 1752 1752 * \param bonddistance length of linked cells (i.e. maximum minimal length checked) … … 1756 1756 { 1757 1757 1758 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 1759 int No, NoBonds, CandidateBondNo; 1760 int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j; 1761 molecule **CellList; 1762 double distance, MinDistance, MaxDistance; 1763 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 1764 Vector x; 1765 int FalseBondDegree = 0; 1766 1767 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 1768 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; 1769 // remove every bond from the list 1770 if ((first->next != last) && (last->previous != first)) { // there are bonds present 1771 cleanup(first,last); 1772 } 1773 1774 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 1775 CountAtoms(out); 1776 *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl; 1777 1778 if (AtomCount != 0) { 1779 // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell 1780 j=-1; 1781 for (int i=0;i<NDIM;i++) { 1782 j += i+1; 1783 divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance 1784 //*out << Verbose(1) << "divisor[" << i << "] = " << divisor[i] << "." << endl; 1785 } 1786 // 2a. allocate memory for the cell list 1787 NumberCells = divisor[0]*divisor[1]*divisor[2]; 1788 *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl; 1789 CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList"); 1790 for (int i=NumberCells;i--;) 1791 CellList[i] = NULL; 1792 1793 // 2b. put all atoms into its corresponding list 1794 Walker = start; 1795 while(Walker->next != end) { 1796 Walker = Walker->next; 1797 //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates "; 1798 //Walker->x.Output(out); 1799 //*out << "." << endl; 1800 // compute the cell by the atom's coordinates 1801 j=-1; 1802 for (int i=0;i<NDIM;i++) { 1803 j += i+1; 1804 x.CopyVector(&(Walker->x)); 1805 x.KeepPeriodic(out, matrix); 1806 n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]); 1807 } 1808 index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2]; 1809 //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl; 1810 // add copy atom to this cell 1811 if (CellList[index] == NULL) // allocate molecule if not done 1812 CellList[index] = new molecule(elemente); 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; 1815 } 1816 //for (int i=0;i<NumberCells;i++) 1817 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 1818 1819 1820 // 3a. go through every cell 1821 for (N[0]=divisor[0];N[0]--;) 1822 for (N[1]=divisor[1];N[1]--;) 1823 for (N[2]=divisor[2];N[2]--;) { 1824 Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2]; 1825 if (CellList[Index] != NULL) { // if there atoms in this cell 1826 //*out << Verbose(1) << "Current cell is " << Index << "." << endl; 1827 // 3b. for every atom therein 1828 Walker = CellList[Index]->start; 1829 while (Walker->next != CellList[Index]->end) { // go through every atom 1830 Walker = Walker->next; 1831 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 1832 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1833 for (n[0]=-1;n[0]<=1;n[0]++) 1834 for (n[1]=-1;n[1]<=1;n[1]++) 1835 for (n[2]=-1;n[2]<=1;n[2]++) { 1836 // compute the index of this comparison cell and make it periodic 1837 index = ((N[2]+n[2]+divisor[2])%divisor[2]) + (((N[1]+n[1]+divisor[1])%divisor[1]) + ((N[0]+n[0]+divisor[0])%divisor[0]) * divisor[1]) * divisor[2]; 1838 //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl; 1839 if (CellList[index] != NULL) { // if there are any atoms in this cell 1840 OtherWalker = CellList[index]->start; 1841 while(OtherWalker->next != CellList[index]->end) { // go through every atom in this cell 1842 OtherWalker = OtherWalker->next; 1843 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl; 1844 /// \todo periodic check is missing here! 1845 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistance(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl; 1846 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius; 1847 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem; 1848 MaxDistance = MinDistance + BONDTHRESHOLD; 1849 MinDistance -= BONDTHRESHOLD; 1850 distance = OtherWalker->x.PeriodicDistance(&(Walker->x), cell_size); 1851 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller 1852 //*out << Verbose(0) << "Adding Bond between " << *Walker << " and " << *OtherWalker << "." << endl; 1853 AddBond(Walker->father, OtherWalker->father, 1); // also increases molecule::BondCount 1854 BondCount++; 1855 } else { 1856 //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl; 1857 } 1858 } 1859 } 1860 } 1861 } 1862 } 1863 } 1864 1865 1866 1867 // 4. free the cell again 1868 for (int i=NumberCells;i--;) 1869 if (CellList[i] != NULL) { 1870 delete(CellList[i]); 1871 } 1872 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 1873 1874 // create the adjacency list per atom 1875 CreateListOfBondsPerAtom(out); 1876 1877 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 1878 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene 1879 // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of 1880 // double bonds as was expected. 1758 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 1759 int No, NoBonds, CandidateBondNo; 1760 int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j; 1761 molecule **CellList; 1762 double distance, MinDistance, MaxDistance; 1763 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 1764 Vector x; 1765 int FalseBondDegree = 0; 1766 1767 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 1768 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; 1769 // remove every bond from the list 1770 if ((first->next != last) && (last->previous != first)) { // there are bonds present 1771 cleanup(first,last); 1772 } 1773 1774 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 1775 CountAtoms(out); 1776 *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl; 1777 1778 if (AtomCount != 0) { 1779 // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell 1780 j=-1; 1781 for (int i=0;i<NDIM;i++) { 1782 j += i+1; 1783 divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance 1784 //*out << Verbose(1) << "divisor[" << i << "] = " << divisor[i] << "." << endl; 1785 } 1786 // 2a. allocate memory for the cell list 1787 NumberCells = divisor[0]*divisor[1]*divisor[2]; 1788 *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl; 1789 CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList"); 1790 for (int i=NumberCells;i--;) 1791 CellList[i] = NULL; 1792 1793 // 2b. put all atoms into its corresponding list 1794 Walker = start; 1795 while(Walker->next != end) { 1796 Walker = Walker->next; 1797 //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates "; 1798 //Walker->x.Output(out); 1799 //*out << "." << endl; 1800 // compute the cell by the atom's coordinates 1801 j=-1; 1802 for (int i=0;i<NDIM;i++) { 1803 j += i+1; 1804 x.CopyVector(&(Walker->x)); 1805 x.KeepPeriodic(out, matrix); 1806 n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]); 1807 } 1808 index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2]; 1809 //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl; 1810 // add copy atom to this cell 1811 if (CellList[index] == NULL) // allocate molecule if not done 1812 CellList[index] = new molecule(elemente); 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; 1815 } 1816 //for (int i=0;i<NumberCells;i++) 1817 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 1818 1819 1820 // 3a. go through every cell 1821 for (N[0]=divisor[0];N[0]--;) 1822 for (N[1]=divisor[1];N[1]--;) 1823 for (N[2]=divisor[2];N[2]--;) { 1824 Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2]; 1825 if (CellList[Index] != NULL) { // if there atoms in this cell 1826 //*out << Verbose(1) << "Current cell is " << Index << "." << endl; 1827 // 3b. for every atom therein 1828 Walker = CellList[Index]->start; 1829 while (Walker->next != CellList[Index]->end) { // go through every atom 1830 Walker = Walker->next; 1831 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 1832 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1833 for (n[0]=-1;n[0]<=1;n[0]++) 1834 for (n[1]=-1;n[1]<=1;n[1]++) 1835 for (n[2]=-1;n[2]<=1;n[2]++) { 1836 // compute the index of this comparison cell and make it periodic 1837 index = ((N[2]+n[2]+divisor[2])%divisor[2]) + (((N[1]+n[1]+divisor[1])%divisor[1]) + ((N[0]+n[0]+divisor[0])%divisor[0]) * divisor[1]) * divisor[2]; 1838 //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl; 1839 if (CellList[index] != NULL) { // if there are any atoms in this cell 1840 OtherWalker = CellList[index]->start; 1841 while(OtherWalker->next != CellList[index]->end) { // go through every atom in this cell 1842 OtherWalker = OtherWalker->next; 1843 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl; 1844 /// \todo periodic check is missing here! 1845 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl; 1846 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius; 1847 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem; 1848 MaxDistance = MinDistance + BONDTHRESHOLD; 1849 MinDistance -= BONDTHRESHOLD; 1850 distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size); 1851 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller 1852 //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl; 1853 AddBond(Walker->father, OtherWalker->father, 1); // also increases molecule::BondCount 1854 } else { 1855 //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl; 1856 } 1857 } 1858 } 1859 } 1860 } 1861 } 1862 } 1863 1864 1865 1866 // 4. free the cell again 1867 for (int i=NumberCells;i--;) 1868 if (CellList[i] != NULL) { 1869 delete(CellList[i]); 1870 } 1871 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 1872 1873 // create the adjacency list per atom 1874 CreateListOfBondsPerAtom(out); 1875 1876 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 1877 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene 1878 // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of 1879 // double bonds as was expected. 1881 1880 if (BondCount != 0) { 1882 NoCyclicBonds = 0;1883 *out << Verbose(1) << "Correcting Bond degree of each bond ... ";1884 do {1885 No = 0; // No acts as breakup flag (if 1 we still continue)1886 Walker = start;1887 while (Walker->next != end) { // go through every atom1888 Walker = Walker->next;1889 // count valence of first partner1890 NoBonds = 0;1891 for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)1892 NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;1893 *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;1894 if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch1895 Candidate = NULL;1896 CandidateBondNo = -1;1897 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners1898 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);1899 // count valence of second partner1900 NoBonds = 0;1901 for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++)1902 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree;1903 *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;1904 if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate1905 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first1906 Candidate = OtherWalker;1907 CandidateBondNo = i;1908 *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl;1909 }1910 }1911 }1912 if ((Candidate != NULL) && (CandidateBondNo != -1)) {1913 ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++;1914 *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl;1915 } else1916 *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl;1917 FalseBondDegree++;1918 }1919 }1920 } while (No);1881 NoCyclicBonds = 0; 1882 *out << Verbose(1) << "Correcting Bond degree of each bond ... "; 1883 do { 1884 No = 0; // No acts as breakup flag (if 1 we still continue) 1885 Walker = start; 1886 while (Walker->next != end) { // go through every atom 1887 Walker = Walker->next; 1888 // count valence of first partner 1889 NoBonds = 0; 1890 for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) 1891 NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree; 1892 *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl; 1893 if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch 1894 Candidate = NULL; 1895 CandidateBondNo = -1; 1896 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners 1897 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 1898 // count valence of second partner 1899 NoBonds = 0; 1900 for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++) 1901 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree; 1902 *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl; 1903 if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate 1904 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first 1905 Candidate = OtherWalker; 1906 CandidateBondNo = i; 1907 *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl; 1908 } 1909 } 1910 } 1911 if ((Candidate != NULL) && (CandidateBondNo != -1)) { 1912 ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++; 1913 *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl; 1914 } else 1915 *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl; 1916 FalseBondDegree++; 1917 } 1918 } 1919 } while (No); 1921 1920 *out << " done." << endl; 1922 1921 } else 1923 1922 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 1924 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl;1925 1926 // output bonds for debugging (if bond chain list was correctly installed)1927 *out << Verbose(1) << endl << "From contents of bond chain list:";1928 bond *Binder = first;1929 while(Binder->next != last) {1930 Binder = Binder->next;1923 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 1924 1925 // output bonds for debugging (if bond chain list was correctly installed) 1926 *out << Verbose(1) << endl << "From contents of bond chain list:"; 1927 bond *Binder = first; 1928 while(Binder->next != last) { 1929 Binder = Binder->next; 1931 1930 *out << *Binder << "\t" << endl; 1932 }1933 *out << endl;1934 } else1935 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl;1936 *out << Verbose(0) << "End of CreateAdjacencyList." << endl;1937 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix");1931 } 1932 *out << endl; 1933 } else 1934 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1935 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 1936 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 1938 1937 1939 1938 }; … … 1951 1950 MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack) 1952 1951 { 1953 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);1954 BackEdgeStack = new StackClass<bond *> (BondCount);1955 MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL);1956 MoleculeLeafClass *LeafWalker = SubGraphs;1957 int CurrentGraphNr = 0, OldGraphNr;1958 int ComponentNumber = 0;1959 atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next;1960 bond *Binder = NULL;1961 bool BackStepping = false;1962 1963 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl;1964 1965 ResetAllBondsToUnused();1966 ResetAllAtomNumbers();1967 InitComponentNumbers();1968 BackEdgeStack->ClearStack();1969 while (Root != end) { // if there any atoms at all1970 // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all1971 AtomStack->ClearStack();1972 1973 // put into new subgraph molecule and add this to list of subgraphs1974 LeafWalker = new MoleculeLeafClass(LeafWalker);1975 LeafWalker->Leaf = new molecule(elemente);1976 LeafWalker->Leaf->AddCopyAtom(Root);1977 1978 OldGraphNr = CurrentGraphNr;1979 Walker = Root;1980 do { // (10)1981 do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom1982 if (!BackStepping) { // if we don't just return from (8)1983 Walker->GraphNr = CurrentGraphNr;1984 Walker->LowpointNr = CurrentGraphNr;1985 *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl;1986 AtomStack->Push(Walker);1987 CurrentGraphNr++;1988 }1989 do { // (3) if Walker has no unused egdes, go to (5)1990 BackStepping = false; // reset backstepping flag for (8)1991 if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused1992 Binder = FindNextUnused(Walker);1993 if (Binder == NULL)1994 break;1995 *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl;1996 // (4) Mark Binder used, ...1997 Binder->MarkUsed(black);1998 OtherAtom = Binder->GetOtherAtom(Walker);1999 *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl;2000 if (OtherAtom->GraphNr != -1) {2001 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)2002 Binder->Type = BackEdge;2003 BackEdgeStack->Push(Binder);2004 Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr;2005 *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl;2006 } else {2007 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)2008 Binder->Type = TreeEdge;2009 OtherAtom->Ancestor = Walker;2010 Walker = OtherAtom;2011 *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl;2012 break;2013 }2014 Binder = NULL;2015 } while (1);// (3)2016 if (Binder == NULL) {2017 *out << Verbose(2) << "No more Unused Bonds." << endl;2018 break;2019 } else2020 Binder = NULL;2021 } while (1);// (2)2022 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!2024 if ((Walker == Root) && (Binder == NULL))2025 break;2026 2027 // (5) if Ancestor of Walker is ...2028 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl;2029 if (Walker->Ancestor->GraphNr != Root->GraphNr) {2030 // (6)(Ancestor of Walker is not Root)2031 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {2032 // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)2033 Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;2034 *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl;2035 } else {2036 // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component2037 Walker->Ancestor->SeparationVertex = true;2038 *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl;2039 SetNextComponentNumber(Walker->Ancestor, ComponentNumber);2040 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl;2041 SetNextComponentNumber(Walker, ComponentNumber);2042 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl;2043 do {2044 OtherAtom = AtomStack->PopLast();2045 LeafWalker->Leaf->AddCopyAtom(OtherAtom);2046 SetNextComponentNumber(OtherAtom, ComponentNumber);2047 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;2048 } while (OtherAtom != Walker);2049 ComponentNumber++;2050 }2051 // (8) Walker becomes its Ancestor, go to (3)2052 *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl;2053 Walker = Walker->Ancestor;2054 BackStepping = true;2055 }2056 if (!BackStepping) {// coming from (8) want to go to (3)2057 // (9) remove all from stack till Walker (including), these and Root form a component2058 AtomStack->Output(out);2059 SetNextComponentNumber(Root, ComponentNumber);2060 *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl;2061 SetNextComponentNumber(Walker, ComponentNumber);2062 *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl;2063 do {2064 OtherAtom = AtomStack->PopLast();2065 LeafWalker->Leaf->AddCopyAtom(OtherAtom);2066 SetNextComponentNumber(OtherAtom, ComponentNumber);2067 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;2068 } while (OtherAtom != Walker);2069 ComponentNumber++;2070 2071 // (11) Root is separation vertex,set Walker to Root and go to (4)2072 Walker = Root;2073 Binder = FindNextUnused(Walker);2074 *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl;2075 if (Binder != NULL) { // Root is separation vertex2076 *out << Verbose(1) << "(11) Root is a separation vertex." << endl;2077 Walker->SeparationVertex = true;2078 }2079 }2080 } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges2081 2082 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph2083 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl;2084 LeafWalker->Leaf->Output(out);2085 *out << endl;2086 2087 // step on to next root2088 while ((Root != end) && (Root->GraphNr != -1)) {2089 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl;2090 if (Root->GraphNr != -1) // if already discovered, step on2091 Root = Root->next;2092 }2093 }2094 // set cyclic bond criterium on "same LP" basis2095 Binder = first;2096 while(Binder->next != last) {2097 Binder = Binder->next;2098 if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ??2099 Binder->Cyclic = true;2100 NoCyclicBonds++;2101 }2102 }2103 2104 2105 *out << Verbose(1) << "Final graph info for each atom is:" << endl;2106 Walker = start;2107 while (Walker->next != end) {2108 Walker = Walker->next;2109 *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are ";2110 OutputComponentNumber(out, Walker);2111 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl;2112 }2113 2114 *out << Verbose(1) << "Final graph info for each bond is:" << endl;2115 Binder = first;2116 while(Binder->next != last) {2117 Binder = Binder->next;2118 *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <";2119 *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp.";2120 OutputComponentNumber(out, Binder->leftatom);2121 *out << " ===";2122 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp.";2123 OutputComponentNumber(out, Binder->rightatom);2124 *out << ">." << endl;2125 if (Binder->Cyclic) // cyclic ??2126 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl;2127 }2128 2129 // free all and exit2130 delete(AtomStack);2131 *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl;2132 return SubGraphs;1952 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 1953 BackEdgeStack = new StackClass<bond *> (BondCount); 1954 MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL); 1955 MoleculeLeafClass *LeafWalker = SubGraphs; 1956 int CurrentGraphNr = 0, OldGraphNr; 1957 int ComponentNumber = 0; 1958 atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next; 1959 bond *Binder = NULL; 1960 bool BackStepping = false; 1961 1962 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 1963 1964 ResetAllBondsToUnused(); 1965 ResetAllAtomNumbers(); 1966 InitComponentNumbers(); 1967 BackEdgeStack->ClearStack(); 1968 while (Root != end) { // if there any atoms at all 1969 // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all 1970 AtomStack->ClearStack(); 1971 1972 // put into new subgraph molecule and add this to list of subgraphs 1973 LeafWalker = new MoleculeLeafClass(LeafWalker); 1974 LeafWalker->Leaf = new molecule(elemente); 1975 LeafWalker->Leaf->AddCopyAtom(Root); 1976 1977 OldGraphNr = CurrentGraphNr; 1978 Walker = Root; 1979 do { // (10) 1980 do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom 1981 if (!BackStepping) { // if we don't just return from (8) 1982 Walker->GraphNr = CurrentGraphNr; 1983 Walker->LowpointNr = CurrentGraphNr; 1984 *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl; 1985 AtomStack->Push(Walker); 1986 CurrentGraphNr++; 1987 } 1988 do { // (3) if Walker has no unused egdes, go to (5) 1989 BackStepping = false; // reset backstepping flag for (8) 1990 if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused 1991 Binder = FindNextUnused(Walker); 1992 if (Binder == NULL) 1993 break; 1994 *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl; 1995 // (4) Mark Binder used, ... 1996 Binder->MarkUsed(black); 1997 OtherAtom = Binder->GetOtherAtom(Walker); 1998 *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl; 1999 if (OtherAtom->GraphNr != -1) { 2000 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3) 2001 Binder->Type = BackEdge; 2002 BackEdgeStack->Push(Binder); 2003 Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr; 2004 *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl; 2005 } else { 2006 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2) 2007 Binder->Type = TreeEdge; 2008 OtherAtom->Ancestor = Walker; 2009 Walker = OtherAtom; 2010 *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl; 2011 break; 2012 } 2013 Binder = NULL; 2014 } while (1); // (3) 2015 if (Binder == NULL) { 2016 *out << Verbose(2) << "No more Unused Bonds." << endl; 2017 break; 2018 } else 2019 Binder = NULL; 2020 } while (1); // (2) 2021 2022 // 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! 2023 if ((Walker == Root) && (Binder == NULL)) 2024 break; 2025 2026 // (5) if Ancestor of Walker is ... 2027 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 2028 if (Walker->Ancestor->GraphNr != Root->GraphNr) { 2029 // (6) (Ancestor of Walker is not Root) 2030 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) { 2031 // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8) 2032 Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr; 2033 *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl; 2034 } else { 2035 // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component 2036 Walker->Ancestor->SeparationVertex = true; 2037 *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl; 2038 SetNextComponentNumber(Walker->Ancestor, ComponentNumber); 2039 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl; 2040 SetNextComponentNumber(Walker, ComponentNumber); 2041 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2042 do { 2043 OtherAtom = AtomStack->PopLast(); 2044 LeafWalker->Leaf->AddCopyAtom(OtherAtom); 2045 SetNextComponentNumber(OtherAtom, ComponentNumber); 2046 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2047 } while (OtherAtom != Walker); 2048 ComponentNumber++; 2049 } 2050 // (8) Walker becomes its Ancestor, go to (3) 2051 *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl; 2052 Walker = Walker->Ancestor; 2053 BackStepping = true; 2054 } 2055 if (!BackStepping) { // coming from (8) want to go to (3) 2056 // (9) remove all from stack till Walker (including), these and Root form a component 2057 AtomStack->Output(out); 2058 SetNextComponentNumber(Root, ComponentNumber); 2059 *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl; 2060 SetNextComponentNumber(Walker, ComponentNumber); 2061 *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl; 2062 do { 2063 OtherAtom = AtomStack->PopLast(); 2064 LeafWalker->Leaf->AddCopyAtom(OtherAtom); 2065 SetNextComponentNumber(OtherAtom, ComponentNumber); 2066 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2067 } while (OtherAtom != Walker); 2068 ComponentNumber++; 2069 2070 // (11) Root is separation vertex, set Walker to Root and go to (4) 2071 Walker = Root; 2072 Binder = FindNextUnused(Walker); 2073 *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl; 2074 if (Binder != NULL) { // Root is separation vertex 2075 *out << Verbose(1) << "(11) Root is a separation vertex." << endl; 2076 Walker->SeparationVertex = true; 2077 } 2078 } 2079 } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges 2080 2081 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2082 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2083 LeafWalker->Leaf->Output(out); 2084 *out << endl; 2085 2086 // step on to next root 2087 while ((Root != end) && (Root->GraphNr != -1)) { 2088 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2089 if (Root->GraphNr != -1) // if already discovered, step on 2090 Root = Root->next; 2091 } 2092 } 2093 // set cyclic bond criterium on "same LP" basis 2094 Binder = first; 2095 while(Binder->next != last) { 2096 Binder = Binder->next; 2097 if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ?? 2098 Binder->Cyclic = true; 2099 NoCyclicBonds++; 2100 } 2101 } 2102 2103 2104 *out << Verbose(1) << "Final graph info for each atom is:" << endl; 2105 Walker = start; 2106 while (Walker->next != end) { 2107 Walker = Walker->next; 2108 *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are "; 2109 OutputComponentNumber(out, Walker); 2110 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2111 } 2112 2113 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2114 Binder = first; 2115 while(Binder->next != last) { 2116 Binder = Binder->next; 2117 *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <"; 2118 *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp."; 2119 OutputComponentNumber(out, Binder->leftatom); 2120 *out << " === "; 2121 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2122 OutputComponentNumber(out, Binder->rightatom); 2123 *out << ">." << endl; 2124 if (Binder->Cyclic) // cyclic ?? 2125 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; 2126 } 2127 2128 // free all and exit 2129 delete(AtomStack); 2130 *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl; 2131 return SubGraphs; 2133 2132 }; 2134 2133 … … 2143 2142 * \todo BFS from the not-same-LP to find back to starting point of tributary cycle over more than one bond 2144 2143 */ 2145 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * BackEdgeStack, int *&MinimumRingSize)2146 { 2147 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList");2148 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList");2149 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList");2150 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);// will hold the current ring2151 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);// contains all "touched" atoms (that need to be reset after BFS loop)2152 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL;2153 bond *Binder = NULL, *BackEdge = NULL;2154 int RingSize, NumCycles, MinRingSize = -1;2155 2156 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray2157 for (int i=AtomCount;i--;) {2158 PredecessorList[i] = NULL;2159 ShortestPathList[i] = -1;2160 ColorList[i] = white;2161 }2162 2163 *out << Verbose(1) << "Back edge list - ";2164 BackEdgeStack->Output(out);2165 2166 *out << Verbose(1) << "Analysing cycles ... " << endl;2167 NumCycles = 0;2168 while (!BackEdgeStack->IsEmpty()) {2169 BackEdge = BackEdgeStack->PopFirst();2170 // this is the target2171 Root = BackEdge->leftatom;2172 // this is the source point2173 Walker = BackEdge->rightatom;2174 ShortestPathList[Walker->nr] = 0;2175 BFSStack->ClearStack();// start with empty BFS stack2176 BFSStack->Push(Walker);2177 TouchedStack->Push(Walker);2178 *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;2179 OtherAtom = NULL;2180 do {// look for Root2181 Walker = BFSStack->PopFirst();2182 *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;2183 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {2184 Binder = ListOfBondsPerAtom[Walker->nr][i];2185 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)2186 OtherAtom = Binder->GetOtherAtom(Walker);2144 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * BackEdgeStack, int *&MinimumRingSize) 2145 { 2146 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList"); 2147 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2148 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2149 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2150 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2151 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; 2152 bond *Binder = NULL, *BackEdge = NULL; 2153 int RingSize, NumCycles, MinRingSize = -1; 2154 2155 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 2156 for (int i=AtomCount;i--;) { 2157 PredecessorList[i] = NULL; 2158 ShortestPathList[i] = -1; 2159 ColorList[i] = white; 2160 } 2161 2162 *out << Verbose(1) << "Back edge list - "; 2163 BackEdgeStack->Output(out); 2164 2165 *out << Verbose(1) << "Analysing cycles ... " << endl; 2166 NumCycles = 0; 2167 while (!BackEdgeStack->IsEmpty()) { 2168 BackEdge = BackEdgeStack->PopFirst(); 2169 // this is the target 2170 Root = BackEdge->leftatom; 2171 // this is the source point 2172 Walker = BackEdge->rightatom; 2173 ShortestPathList[Walker->nr] = 0; 2174 BFSStack->ClearStack(); // start with empty BFS stack 2175 BFSStack->Push(Walker); 2176 TouchedStack->Push(Walker); 2177 *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 2178 OtherAtom = NULL; 2179 do { // look for Root 2180 Walker = BFSStack->PopFirst(); 2181 *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 2182 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 2183 Binder = ListOfBondsPerAtom[Walker->nr][i]; 2184 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2185 OtherAtom = Binder->GetOtherAtom(Walker); 2187 2186 #ifdef ADDHYDROGEN 2188 if (OtherAtom->type->Z != 1) {2187 if (OtherAtom->type->Z != 1) { 2189 2188 #endif 2190 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;2191 if (ColorList[OtherAtom->nr] == white) {2192 TouchedStack->Push(OtherAtom);2193 ColorList[OtherAtom->nr] = lightgray;2194 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor2195 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;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;2197 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance2198 *out << Verbose(3) << "Putting OtherAtom into queue." << endl;2199 BFSStack->Push(OtherAtom);2200 //}2201 } else {2202 *out << Verbose(3) << "Not Adding, has already been visited." << endl;2203 }2204 if (OtherAtom == Root)2205 break;2189 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 2190 if (ColorList[OtherAtom->nr] == white) { 2191 TouchedStack->Push(OtherAtom); 2192 ColorList[OtherAtom->nr] = lightgray; 2193 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2194 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2195 *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 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2197 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; 2198 BFSStack->Push(OtherAtom); 2199 //} 2200 } else { 2201 *out << Verbose(3) << "Not Adding, has already been visited." << endl; 2202 } 2203 if (OtherAtom == Root) 2204 break; 2206 2205 #ifdef ADDHYDROGEN 2207 } else {2208 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;2209 ColorList[OtherAtom->nr] = black;2210 }2206 } else { 2207 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; 2208 ColorList[OtherAtom->nr] = black; 2209 } 2211 2210 #endif 2212 } else {2213 *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl;2214 }2215 }2216 ColorList[Walker->nr] = black;2217 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;2218 if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand2219 // step through predecessor list2220 while (OtherAtom != BackEdge->rightatom) {2221 if (!OtherAtom->GetTrueFather()->IsCyclic)// if one bond in the loop is not marked as cyclic, we haven't found this cycle yet2222 break;2223 else2224 OtherAtom = PredecessorList[OtherAtom->nr];2225 }2226 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already2227 *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\2228 do {2229 OtherAtom = TouchedStack->PopLast();2230 if (PredecessorList[OtherAtom->nr] == Walker) {2231 *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;2232 PredecessorList[OtherAtom->nr] = NULL;2233 ShortestPathList[OtherAtom->nr] = -1;2234 ColorList[OtherAtom->nr] = white;2235 BFSStack->RemoveItem(OtherAtom);2236 }2237 } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL));2238 TouchedStack->Push(OtherAtom);// last was wrongly popped2239 OtherAtom = BackEdge->rightatom; // set to not Root2240 } else2241 OtherAtom = Root;2242 }2243 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));2244 2245 if (OtherAtom == Root) {2246 // now climb back the predecessor list and thus find the cycle members2247 NumCycles++;2248 RingSize = 1;2249 Root->GetTrueFather()->IsCyclic = true;2250 *out << Verbose(1) << "Found ring contains: ";2251 Walker = Root;2252 while (Walker != BackEdge->rightatom) {2253 *out << Walker->Name << " <-> ";2254 Walker = PredecessorList[Walker->nr];2255 Walker->GetTrueFather()->IsCyclic = true;2256 RingSize++;2257 }2258 *out << Walker->Name << "with a length of " << RingSize << "." << endl << endl;2259 // walk through all and set MinimumRingSize2260 Walker = Root;2261 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;2262 while (Walker != BackEdge->rightatom) {2263 Walker = PredecessorList[Walker->nr];2264 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr])2265 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;2266 }2267 if ((RingSize < MinRingSize) || (MinRingSize == -1))2268 MinRingSize = RingSize;2269 } else {2270 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl;2271 }2272 2273 // now clean the lists2274 while (!TouchedStack->IsEmpty()){2275 Walker = TouchedStack->PopFirst();2276 PredecessorList[Walker->nr] = NULL;2277 ShortestPathList[Walker->nr] = -1;2278 ColorList[Walker->nr] = white;2279 }2280 }2281 if (MinRingSize != -1) {2282 // go over all atoms2283 Root = start;2284 while(Root->next != end) {2285 Root = Root->next;2286 2287 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is2288 Walker = Root;2289 ShortestPathList[Walker->nr] = 0;2290 BFSStack->ClearStack();// start with empty BFS stack2291 BFSStack->Push(Walker);2292 TouchedStack->Push(Walker);2293 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;2294 OtherAtom = Walker;2295 while (OtherAtom != NULL) {// look for Root2296 Walker = BFSStack->PopFirst();2297 //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;2298 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {2299 Binder = ListOfBondsPerAtom[Walker->nr][i];2300 if ((Binder != BackEdge) || (NumberOfBondsPerAtom[Walker->nr] == 1)) { // only walk along DFS spanning tree (otherwise we always find SP of 1 being backedge Binder), but terminal hydrogens may be connected via backedge, hence extra check2301 OtherAtom = Binder->GetOtherAtom(Walker);2302 //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;2303 if (ColorList[OtherAtom->nr] == white) {2304 TouchedStack->Push(OtherAtom);2305 ColorList[OtherAtom->nr] = lightgray;2306 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor2307 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;2308 //*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;2309 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring2310 MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr];2311 OtherAtom = NULL; //break;2312 break;2313 } else2314 BFSStack->Push(OtherAtom);2315 } else {2316 //*out << Verbose(3) << "Not Adding, has already been visited." << endl;2317 }2318 } else {2319 //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;2320 }2321 }2322 ColorList[Walker->nr] = black;2323 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;2324 }2325 2326 // now clean the lists2327 while (!TouchedStack->IsEmpty()){2328 Walker = TouchedStack->PopFirst();2329 PredecessorList[Walker->nr] = NULL;2330 ShortestPathList[Walker->nr] = -1;2331 ColorList[Walker->nr] = white;2332 }2333 }2334 *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl;2335 }2336 *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl;2337 } else2338 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl;2339 2340 Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList");2341 Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList");2342 Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList");2343 delete(BFSStack);2211 } else { 2212 *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl; 2213 } 2214 } 2215 ColorList[Walker->nr] = black; 2216 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2217 if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand 2218 // step through predecessor list 2219 while (OtherAtom != BackEdge->rightatom) { 2220 if (!OtherAtom->GetTrueFather()->IsCyclic) // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet 2221 break; 2222 else 2223 OtherAtom = PredecessorList[OtherAtom->nr]; 2224 } 2225 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already 2226 *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\ 2227 do { 2228 OtherAtom = TouchedStack->PopLast(); 2229 if (PredecessorList[OtherAtom->nr] == Walker) { 2230 *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl; 2231 PredecessorList[OtherAtom->nr] = NULL; 2232 ShortestPathList[OtherAtom->nr] = -1; 2233 ColorList[OtherAtom->nr] = white; 2234 BFSStack->RemoveItem(OtherAtom); 2235 } 2236 } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL)); 2237 TouchedStack->Push(OtherAtom); // last was wrongly popped 2238 OtherAtom = BackEdge->rightatom; // set to not Root 2239 } else 2240 OtherAtom = Root; 2241 } 2242 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2243 2244 if (OtherAtom == Root) { 2245 // now climb back the predecessor list and thus find the cycle members 2246 NumCycles++; 2247 RingSize = 1; 2248 Root->GetTrueFather()->IsCyclic = true; 2249 *out << Verbose(1) << "Found ring contains: "; 2250 Walker = Root; 2251 while (Walker != BackEdge->rightatom) { 2252 *out << Walker->Name << " <-> "; 2253 Walker = PredecessorList[Walker->nr]; 2254 Walker->GetTrueFather()->IsCyclic = true; 2255 RingSize++; 2256 } 2257 *out << Walker->Name << " with a length of " << RingSize << "." << endl << endl; 2258 // walk through all and set MinimumRingSize 2259 Walker = Root; 2260 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize; 2261 while (Walker != BackEdge->rightatom) { 2262 Walker = PredecessorList[Walker->nr]; 2263 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr]) 2264 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize; 2265 } 2266 if ((RingSize < MinRingSize) || (MinRingSize == -1)) 2267 MinRingSize = RingSize; 2268 } else { 2269 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2270 } 2271 2272 // now clean the lists 2273 while (!TouchedStack->IsEmpty()){ 2274 Walker = TouchedStack->PopFirst(); 2275 PredecessorList[Walker->nr] = NULL; 2276 ShortestPathList[Walker->nr] = -1; 2277 ColorList[Walker->nr] = white; 2278 } 2279 } 2280 if (MinRingSize != -1) { 2281 // go over all atoms 2282 Root = start; 2283 while(Root->next != end) { 2284 Root = Root->next; 2285 2286 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2287 Walker = Root; 2288 ShortestPathList[Walker->nr] = 0; 2289 BFSStack->ClearStack(); // start with empty BFS stack 2290 BFSStack->Push(Walker); 2291 TouchedStack->Push(Walker); 2292 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 2293 OtherAtom = Walker; 2294 while (OtherAtom != NULL) { // look for Root 2295 Walker = BFSStack->PopFirst(); 2296 //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 2297 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 2298 Binder = ListOfBondsPerAtom[Walker->nr][i]; 2299 if ((Binder != BackEdge) || (NumberOfBondsPerAtom[Walker->nr] == 1)) { // only walk along DFS spanning tree (otherwise we always find SP of 1 being backedge Binder), but terminal hydrogens may be connected via backedge, hence extra check 2300 OtherAtom = Binder->GetOtherAtom(Walker); 2301 //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 2302 if (ColorList[OtherAtom->nr] == white) { 2303 TouchedStack->Push(OtherAtom); 2304 ColorList[OtherAtom->nr] = lightgray; 2305 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2306 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2307 //*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; 2308 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring 2309 MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr]; 2310 OtherAtom = NULL; //break; 2311 break; 2312 } else 2313 BFSStack->Push(OtherAtom); 2314 } else { 2315 //*out << Verbose(3) << "Not Adding, has already been visited." << endl; 2316 } 2317 } else { 2318 //*out << Verbose(3) << "Not Visiting, is a back edge." << endl; 2319 } 2320 } 2321 ColorList[Walker->nr] = black; 2322 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2323 } 2324 2325 // now clean the lists 2326 while (!TouchedStack->IsEmpty()){ 2327 Walker = TouchedStack->PopFirst(); 2328 PredecessorList[Walker->nr] = NULL; 2329 ShortestPathList[Walker->nr] = -1; 2330 ColorList[Walker->nr] = white; 2331 } 2332 } 2333 *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl; 2334 } 2335 *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl; 2336 } else 2337 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl; 2338 2339 Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList"); 2340 Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList"); 2341 Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList"); 2342 delete(BFSStack); 2344 2343 }; 2345 2344 … … 2351 2350 void molecule::SetNextComponentNumber(atom *vertex, int nr) 2352 2351 { 2353 int i=0;2354 if (vertex != NULL) {2355 for(;i<NumberOfBondsPerAtom[vertex->nr];i++) {2356 if (vertex->ComponentNr[i] == -1) {// check if not yet used2357 vertex->ComponentNr[i] = nr;2358 break;2359 }2360 else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time2361 break;// breaking here will not cause error!2362 }2363 if (i == NumberOfBondsPerAtom[vertex->nr])2364 cerr << "Error: All Component entries are already occupied!" << endl;2365 } else2366 cerr << "Error: Given vertex is NULL!" << endl;2352 int i=0; 2353 if (vertex != NULL) { 2354 for(;i<NumberOfBondsPerAtom[vertex->nr];i++) { 2355 if (vertex->ComponentNr[i] == -1) { // check if not yet used 2356 vertex->ComponentNr[i] = nr; 2357 break; 2358 } 2359 else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time 2360 break; // breaking here will not cause error! 2361 } 2362 if (i == NumberOfBondsPerAtom[vertex->nr]) 2363 cerr << "Error: All Component entries are already occupied!" << endl; 2364 } else 2365 cerr << "Error: Given vertex is NULL!" << endl; 2367 2366 }; 2368 2367 … … 2372 2371 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2373 2372 { 2374 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)2375 *out << vertex->ComponentNr[i] << "";2373 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2374 *out << vertex->ComponentNr[i] << " "; 2376 2375 }; 2377 2376 … … 2380 2379 void molecule::InitComponentNumbers() 2381 2380 { 2382 atom *Walker = start;2383 while(Walker->next != end) {2384 Walker = Walker->next;2385 if (Walker->ComponentNr != NULL)2386 Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr");2387 Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr");2388 for (int i=NumberOfBondsPerAtom[Walker->nr];i--;)2389 Walker->ComponentNr[i] = -1;2390 }2381 atom *Walker = start; 2382 while(Walker->next != end) { 2383 Walker = Walker->next; 2384 if (Walker->ComponentNr != NULL) 2385 Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr"); 2386 Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr"); 2387 for (int i=NumberOfBondsPerAtom[Walker->nr];i--;) 2388 Walker->ComponentNr[i] = -1; 2389 } 2391 2390 }; 2392 2391 … … 2397 2396 bond * molecule::FindNextUnused(atom *vertex) 2398 2397 { 2399 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)2400 if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white)2401 return(ListOfBondsPerAtom[vertex->nr][i]);2402 return NULL;2398 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2399 if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white) 2400 return(ListOfBondsPerAtom[vertex->nr][i]); 2401 return NULL; 2403 2402 }; 2404 2403 … … 2408 2407 void molecule::ResetAllBondsToUnused() 2409 2408 { 2410 bond *Binder = first;2411 while (Binder->next != last) {2412 Binder = Binder->next;2413 Binder->ResetUsed();2414 }2409 bond *Binder = first; 2410 while (Binder->next != last) { 2411 Binder = Binder->next; 2412 Binder->ResetUsed(); 2413 } 2415 2414 }; 2416 2415 … … 2419 2418 void molecule::ResetAllAtomNumbers() 2420 2419 { 2421 atom *Walker = start;2422 while (Walker->next != end) {2423 Walker = Walker->next;2424 Walker->GraphNr= -1;2425 }2420 atom *Walker = start; 2421 while (Walker->next != end) { 2422 Walker = Walker->next; 2423 Walker->GraphNr = -1; 2424 } 2426 2425 }; 2427 2426 … … 2432 2431 void OutputAlreadyVisited(ofstream *out, int *list) 2433 2432 { 2434 *out << Verbose(4) << "Already Visited Bonds:\t";2435 for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "";2436 *out << endl;2433 *out << Verbose(4) << "Already Visited Bonds:\t"; 2434 for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << " "; 2435 *out << endl; 2437 2436 }; 2438 2437 … … 2440 2439 * The upper limit is 2441 2440 * \f[ 2442 * n = N \cdot C^k2441 * n = N \cdot C^k 2443 2442 * \f] 2444 2443 * where \f$C=2^c\f$ and c is the maximum bond degree over N number of atoms. … … 2449 2448 int molecule::GuesstimateFragmentCount(ofstream *out, int order) 2450 2449 { 2451 int c = 0;2452 int FragmentCount;2453 // get maximum bond degree2454 atom *Walker = start;2455 while (Walker->next != end) {2456 Walker = Walker->next;2457 c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c;2458 }2459 FragmentCount = NoNonHydrogen*(1 << (c*order));2460 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl;2461 return FragmentCount;2450 int c = 0; 2451 int FragmentCount; 2452 // get maximum bond degree 2453 atom *Walker = start; 2454 while (Walker->next != end) { 2455 Walker = Walker->next; 2456 c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c; 2457 } 2458 FragmentCount = NoNonHydrogen*(1 << (c*order)); 2459 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 2460 return FragmentCount; 2462 2461 }; 2463 2462 … … 2470 2469 bool molecule::ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet) 2471 2470 { 2472 stringstream line;2473 int AtomNr;2474 int status = 0;2475 2476 line.str(buffer);2477 while (!line.eof()) {2478 line >> AtomNr;2479 if ((AtomNr >= 0) && (AtomNr < AtomCount)) {2480 CurrentSet.insert(AtomNr);// insert at end, hence in same order as in file!2481 status++;2482 } // else it's "-1" or else and thus must not be added2483 }2484 *out << Verbose(1) << "The scanned KeySet is ";2485 for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) {2486 *out << (*runner) << "\t";2487 }2488 *out << endl;2489 return (status != 0);2471 stringstream line; 2472 int AtomNr; 2473 int status = 0; 2474 2475 line.str(buffer); 2476 while (!line.eof()) { 2477 line >> AtomNr; 2478 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2479 CurrentSet.insert(AtomNr); // insert at end, hence in same order as in file! 2480 status++; 2481 } // else it's "-1" or else and thus must not be added 2482 } 2483 *out << Verbose(1) << "The scanned KeySet is "; 2484 for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) { 2485 *out << (*runner) << "\t"; 2486 } 2487 *out << endl; 2488 return (status != 0); 2490 2489 }; 2491 2490 … … 2502 2501 bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList) 2503 2502 { 2504 bool status = true;2505 ifstream InputFile;2506 stringstream line;2507 GraphTestPair testGraphInsert;2508 int NumberOfFragments = 0;2509 double TEFactor;2510 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename");2511 2512 if (FragmentList == NULL) { // check list pointer2513 FragmentList = new Graph;2514 }2515 2516 // 1st pass: open file and read2517 *out << Verbose(1) << "Parsing the KeySet file ... " << endl;2518 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE);2519 InputFile.open(filename);2520 if (InputFile != NULL) {2521 // each line represents a new fragment2522 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer");2523 // 1. parse keysets and insert into temp. graph2524 while (!InputFile.eof()) {2525 InputFile.getline(buffer, MAXSTRINGSIZE);2526 KeySet CurrentSet;2527 if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) {// if at least one valid atom was added, write config2528 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1)));// store fragment number and current factor2529 if (!testGraphInsert.second) {2530 cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl;2531 }2532 //FragmentList->ListOfMolecules[NumberOfFragments++] = StoreFragmentFromKeySet(out, CurrentSet, IsAngstroem);2533 }2534 }2535 // 2. Free and done2536 InputFile.close();2537 InputFile.clear();2538 Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer");2539 *out << Verbose(1) << "done." << endl;2540 } else {2541 *out << Verbose(1) << "File " << filename << " not found." << endl;2542 status = false;2543 }2544 2545 // 2nd pass: open TEFactors file and read2546 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl;2547 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE);2548 InputFile.open(filename);2549 if (InputFile != NULL) {2550 // 3. add found TEFactors to each keyset2551 NumberOfFragments = 0;2552 for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) {2553 if (!InputFile.eof()) {2554 InputFile >> TEFactor;2555 (*runner).second.second = TEFactor;2556 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl;2557 } else {2558 status = false;2559 break;2560 }2561 }2562 // 4. Free and done2563 InputFile.close();2564 *out << Verbose(1) << "done." << endl;2565 } else {2566 *out << Verbose(1) << "File " << filename << " not found." << endl;2567 status = false;2568 }2569 2570 // free memory2571 Free((void **)&filename, "molecule::ParseKeySetFile - filename");2572 2573 return status;2503 bool status = true; 2504 ifstream InputFile; 2505 stringstream line; 2506 GraphTestPair testGraphInsert; 2507 int NumberOfFragments = 0; 2508 double TEFactor; 2509 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 2510 2511 if (FragmentList == NULL) { // check list pointer 2512 FragmentList = new Graph; 2513 } 2514 2515 // 1st pass: open file and read 2516 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; 2517 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE); 2518 InputFile.open(filename); 2519 if (InputFile != NULL) { 2520 // each line represents a new fragment 2521 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer"); 2522 // 1. parse keysets and insert into temp. graph 2523 while (!InputFile.eof()) { 2524 InputFile.getline(buffer, MAXSTRINGSIZE); 2525 KeySet CurrentSet; 2526 if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) { // if at least one valid atom was added, write config 2527 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1))); // store fragment number and current factor 2528 if (!testGraphInsert.second) { 2529 cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl; 2530 } 2531 //FragmentList->ListOfMolecules[NumberOfFragments++] = StoreFragmentFromKeySet(out, CurrentSet, IsAngstroem); 2532 } 2533 } 2534 // 2. Free and done 2535 InputFile.close(); 2536 InputFile.clear(); 2537 Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer"); 2538 *out << Verbose(1) << "done." << endl; 2539 } else { 2540 *out << Verbose(1) << "File " << filename << " not found." << endl; 2541 status = false; 2542 } 2543 2544 // 2nd pass: open TEFactors file and read 2545 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; 2546 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE); 2547 InputFile.open(filename); 2548 if (InputFile != NULL) { 2549 // 3. add found TEFactors to each keyset 2550 NumberOfFragments = 0; 2551 for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) { 2552 if (!InputFile.eof()) { 2553 InputFile >> TEFactor; 2554 (*runner).second.second = TEFactor; 2555 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2556 } else { 2557 status = false; 2558 break; 2559 } 2560 } 2561 // 4. Free and done 2562 InputFile.close(); 2563 *out << Verbose(1) << "done." << endl; 2564 } else { 2565 *out << Verbose(1) << "File " << filename << " not found." << endl; 2566 status = false; 2567 } 2568 2569 // free memory 2570 Free((void **)&filename, "molecule::ParseKeySetFile - filename"); 2571 2572 return status; 2574 2573 }; 2575 2574 … … 2582 2581 bool molecule::StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path) 2583 2582 { 2584 ofstream output;2585 bool status =true;2586 string line;2587 2588 // open KeySet file2589 line = path;2590 line.append("/");2591 line += FRAGMENTPREFIX;2592 line += KEYSETFILE;2593 output.open(line.c_str(), ios::out);2594 *out << Verbose(1) << "Saving key sets of the total graph ... ";2595 if(output != NULL) {2596 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) {2597 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {2598 if (sprinter != (*runner).first.begin())2599 output << "\t";2600 output << *sprinter;2601 }2602 output << endl;2603 }2604 *out << "done." << endl;2605 } else {2606 cerr << "Unable to open " << line << " for writing keysets!" << endl;2607 status = false;2608 }2609 output.close();2610 output.clear();2611 2612 // open TEFactors file2613 line = path;2614 line.append("/");2615 line += FRAGMENTPREFIX;2616 line += TEFACTORSFILE;2617 output.open(line.c_str(), ios::out);2618 *out << Verbose(1) << "Saving TEFactors of the total graph ... ";2619 if(output != NULL) {2620 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++)2621 output << (*runner).second.second << endl;2622 *out << Verbose(1) << "done." << endl;2623 } else {2624 *out << Verbose(1) << "failed to open " << line << "." << endl;2625 status = false;2626 }2627 output.close();2628 2629 return status;2583 ofstream output; 2584 bool status = true; 2585 string line; 2586 2587 // open KeySet file 2588 line = path; 2589 line.append("/"); 2590 line += FRAGMENTPREFIX; 2591 line += KEYSETFILE; 2592 output.open(line.c_str(), ios::out); 2593 *out << Verbose(1) << "Saving key sets of the total graph ... "; 2594 if(output != NULL) { 2595 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 2596 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2597 if (sprinter != (*runner).first.begin()) 2598 output << "\t"; 2599 output << *sprinter; 2600 } 2601 output << endl; 2602 } 2603 *out << "done." << endl; 2604 } else { 2605 cerr << "Unable to open " << line << " for writing keysets!" << endl; 2606 status = false; 2607 } 2608 output.close(); 2609 output.clear(); 2610 2611 // open TEFactors file 2612 line = path; 2613 line.append("/"); 2614 line += FRAGMENTPREFIX; 2615 line += TEFACTORSFILE; 2616 output.open(line.c_str(), ios::out); 2617 *out << Verbose(1) << "Saving TEFactors of the total graph ... "; 2618 if(output != NULL) { 2619 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) 2620 output << (*runner).second.second << endl; 2621 *out << Verbose(1) << "done." << endl; 2622 } else { 2623 *out << Verbose(1) << "failed to open " << line << "." << endl; 2624 status = false; 2625 } 2626 output.close(); 2627 2628 return status; 2630 2629 }; 2631 2630 … … 2638 2637 bool molecule::StoreAdjacencyToFile(ofstream *out, char *path) 2639 2638 { 2640 ofstream AdjacencyFile;2641 atom *Walker = NULL;2642 stringstream line;2643 bool status = true;2644 2645 line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;2646 AdjacencyFile.open(line.str().c_str(), ios::out);2647 *out << Verbose(1) << "Saving adjacency list ... ";2648 if (AdjacencyFile != NULL) {2649 Walker = start;2650 while(Walker->next != end) {2651 Walker = Walker->next;2652 AdjacencyFile << Walker->nr << "\t";2653 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)2654 AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t";2655 AdjacencyFile << endl;2656 }2657 AdjacencyFile.close();2658 *out << Verbose(1) << "done." << endl;2659 } else {2660 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;2661 status = false;2662 }2663 2664 return status;2639 ofstream AdjacencyFile; 2640 atom *Walker = NULL; 2641 stringstream line; 2642 bool status = true; 2643 2644 line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2645 AdjacencyFile.open(line.str().c_str(), ios::out); 2646 *out << Verbose(1) << "Saving adjacency list ... "; 2647 if (AdjacencyFile != NULL) { 2648 Walker = start; 2649 while(Walker->next != end) { 2650 Walker = Walker->next; 2651 AdjacencyFile << Walker->nr << "\t"; 2652 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) 2653 AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t"; 2654 AdjacencyFile << endl; 2655 } 2656 AdjacencyFile.close(); 2657 *out << Verbose(1) << "done." << endl; 2658 } else { 2659 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 2660 status = false; 2661 } 2662 2663 return status; 2665 2664 }; 2666 2665 … … 2673 2672 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 2674 2673 { 2675 ifstream File;2676 stringstream filename;2677 bool status = true;2678 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");2679 2680 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;2681 File.open(filename.str().c_str(), ios::out);2682 *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";2683 if (File != NULL) {2684 // allocate storage structure2685 int NonMatchNumber = 0;// will number of atoms with differing bond structure2686 int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom2687 int CurrentBondsOfAtom;2688 2689 // Parse the file line by line and count the bonds2690 while (!File.eof()) {2691 File.getline(buffer, MAXSTRINGSIZE);2692 stringstream line;2693 line.str(buffer);2694 int AtomNr = -1;2695 line >> AtomNr;2696 CurrentBondsOfAtom = -1; // we count one too far due to line end2697 // parse into structure2698 if ((AtomNr >= 0) && (AtomNr < AtomCount)) {2699 while (!line.eof())2700 line >> CurrentBonds[ ++CurrentBondsOfAtom ];2701 // compare against present bonds2702 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: ";2703 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) {2704 for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) {2705 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr;2706 int j = 0;2707 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds2708 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms2709 ListOfAtoms[AtomNr] = NULL;2710 NonMatchNumber++;2711 status = false;2712 //out << "[" << id << "]\t";2713 } else {2714 //out << id << "\t";2715 }2716 }2717 //out << endl;2718 } else {2719 *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl;2720 status = false;2721 }2722 }2723 }2724 File.close();2725 File.clear();2726 if (status) { // if equal we parse the KeySetFile2727 *out << Verbose(1) << "done: Equal." << endl;2728 status = true;2729 } else2730 *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl;2731 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds");2732 } else {2733 *out << Verbose(1) << "Adjacency file not found." << endl;2734 status = false;2735 }2736 *out << endl;2737 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");2738 2739 return status;2674 ifstream File; 2675 stringstream filename; 2676 bool status = true; 2677 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2678 2679 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2680 File.open(filename.str().c_str(), ios::out); 2681 *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... "; 2682 if (File != NULL) { 2683 // allocate storage structure 2684 int NonMatchNumber = 0; // will number of atoms with differing bond structure 2685 int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom 2686 int CurrentBondsOfAtom; 2687 2688 // Parse the file line by line and count the bonds 2689 while (!File.eof()) { 2690 File.getline(buffer, MAXSTRINGSIZE); 2691 stringstream line; 2692 line.str(buffer); 2693 int AtomNr = -1; 2694 line >> AtomNr; 2695 CurrentBondsOfAtom = -1; // we count one too far due to line end 2696 // parse into structure 2697 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2698 while (!line.eof()) 2699 line >> CurrentBonds[ ++CurrentBondsOfAtom ]; 2700 // compare against present bonds 2701 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: "; 2702 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) { 2703 for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) { 2704 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr; 2705 int j = 0; 2706 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds 2707 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms 2708 ListOfAtoms[AtomNr] = NULL; 2709 NonMatchNumber++; 2710 status = false; 2711 //out << "[" << id << "]\t"; 2712 } else { 2713 //out << id << "\t"; 2714 } 2715 } 2716 //out << endl; 2717 } else { 2718 *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl; 2719 status = false; 2720 } 2721 } 2722 } 2723 File.close(); 2724 File.clear(); 2725 if (status) { // if equal we parse the KeySetFile 2726 *out << Verbose(1) << "done: Equal." << endl; 2727 status = true; 2728 } else 2729 *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl; 2730 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds"); 2731 } else { 2732 *out << Verbose(1) << "Adjacency file not found." << endl; 2733 status = false; 2734 } 2735 *out << endl; 2736 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2737 2738 return status; 2740 2739 }; 2741 2740 … … 2751 2750 bool molecule::CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path) 2752 2751 { 2753 atom *Walker = start;2754 bool status = false;2755 ifstream InputFile;2756 2757 // initialize mask list2758 for(int i=AtomCount;i--;)2759 AtomMask[i] = false;2760 2761 if (Order < 0) { // adaptive increase of BondOrder per site2762 if (AtomMask[AtomCount] == true)// break after one step2763 return false;2764 // parse the EnergyPerFragment file2765 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer");2766 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT);2767 InputFile.open(buffer, ios::in);2768 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) {2769 // transmorph graph keyset list into indexed KeySetList2770 map<int,KeySet> IndexKeySetList;2771 for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) {2772 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) );2773 }2774 int lines = 0;2775 // count the number of lines, i.e. the number of fragments2776 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines2777 InputFile.getline(buffer, MAXSTRINGSIZE);2778 while(!InputFile.eof()) {2779 InputFile.getline(buffer, MAXSTRINGSIZE);2780 lines++;2781 }2782 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl;// one endline too much2783 InputFile.clear();2784 InputFile.seekg(ios::beg);2785 map<int, pair<double,int> > AdaptiveCriteriaList;// (Root No., (Value, Order)) !2786 int No, FragOrder;2787 double Value;2788 // each line represents a fragment root (Atom::nr) id and its energy contribution2789 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines2790 InputFile.getline(buffer, MAXSTRINGSIZE);2791 while(!InputFile.eof()) {2792 InputFile.getline(buffer, MAXSTRINGSIZE);2793 if (strlen(buffer) > 2) {2794 //*out << Verbose(2) << "Scanning: " << buffer << endl;2795 stringstream line(buffer);2796 line >> FragOrder;2797 line >> ws >> No;2798 line >> ws >> Value; // skip time entry2799 line >> ws >> Value;2800 No -= 1;// indices start at 1 in file, not 02801 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;2802 2803 // clean the list of those entries that have been superceded by higher order terms already2804 map<int,KeySet>::iterator marker = IndexKeySetList.find(No);// find keyset to Frag No.2805 if (marker != IndexKeySetList.end()) {// if found2806 Value *= 1 + MYEPSILON*(*((*marker).second.begin()));// in case of equal energies this makes em not equal without changing anything actually2807 // 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 AtomMask2808 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));2809 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;2810 if (!InsertedElement.second) { // this root is already present2811 if ((*PresentItem).second.second < FragOrder)// if order there is lower, update entry with higher-order term2812 //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)2813 {// if value is smaller, update value and order2814 (*PresentItem).second.first = fabs(Value);2815 (*PresentItem).second.second = FragOrder;2816 *out << Verbose(2) << "Updated element (" <<(*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;2817 } else {2818 *out << Verbose(2) << "Did not update element " <<(*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl;2819 }2820 } else {2821 *out << Verbose(2) << "Inserted element (" <<(*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;2822 }2823 } else {2824 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl;2825 }2826 }2827 }2828 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones)2829 map<double, pair<int,int> > FinalRootCandidates;2830 *out << Verbose(1) << "Root candidate list is: " << endl;2831 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) {2832 Walker = FindAtom((*runner).first);2833 if (Walker != NULL) {2834 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order2835 if (!Walker->MaxOrder) {2836 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl;2837 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );2838 } else {2839 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl;2840 }2841 } else {2842 cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl;2843 }2844 }2845 // pick the ones still below threshold and mark as to be adaptively updated2846 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) {2847 No = (*runner).second.first;2848 Walker = FindAtom(No);2849 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) {2850 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl;2851 AtomMask[No] = true;2852 status = true;2853 //} else2854 //*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;2855 }2856 // close and done2857 InputFile.close();2858 InputFile.clear();2859 } else {2860 cerr << "Unable to parse " << buffer << " file, incrementing all." << endl;2861 while (Walker->next != end) {2862 Walker = Walker->next;2863 #ifdef ADDHYDROGEN2864 if (Walker->type->Z != 1) // skip hydrogen2865 #endif2866 {2867 AtomMask[Walker->nr] = true;// include all (non-hydrogen) atoms2868 status = true;2869 }2870 }2871 }2872 Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer");2873 // pick a given number of highest values and set AtomMask2874 } else { // global increase of Bond Order2875 while (Walker->next != end) {2876 Walker = Walker->next;2877 #ifdef ADDHYDROGEN2878 if (Walker->type->Z != 1) // skip hydrogen2879 #endif2880 {2881 AtomMask[Walker->nr] = true;// include all (non-hydrogen) atoms2882 if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]))2883 status = true;2884 }2885 }2886 if ((Order == 0) && (AtomMask[AtomCount] == false))// single stepping, just check2887 status = true;2888 2889 if (!status) {2890 if (Order == 0)2891 *out << Verbose(1) << "Single stepping done." << endl;2892 else2893 *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl;2894 }2895 }2896 2897 // print atom mask for debugging2898 *out << "";2899 for(int i=0;i<AtomCount;i++)2900 *out << (i % 10);2901 *out << endl << "Atom mask is: ";2902 for(int i=0;i<AtomCount;i++)2903 *out << (AtomMask[i] ? "t" : "f");2904 *out << endl;2905 2906 return status;2752 atom *Walker = start; 2753 bool status = false; 2754 ifstream InputFile; 2755 2756 // initialize mask list 2757 for(int i=AtomCount;i--;) 2758 AtomMask[i] = false; 2759 2760 if (Order < 0) { // adaptive increase of BondOrder per site 2761 if (AtomMask[AtomCount] == true) // break after one step 2762 return false; 2763 // parse the EnergyPerFragment file 2764 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer"); 2765 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT); 2766 InputFile.open(buffer, ios::in); 2767 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) { 2768 // transmorph graph keyset list into indexed KeySetList 2769 map<int,KeySet> IndexKeySetList; 2770 for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) { 2771 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) ); 2772 } 2773 int lines = 0; 2774 // count the number of lines, i.e. the number of fragments 2775 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 2776 InputFile.getline(buffer, MAXSTRINGSIZE); 2777 while(!InputFile.eof()) { 2778 InputFile.getline(buffer, MAXSTRINGSIZE); 2779 lines++; 2780 } 2781 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl; // one endline too much 2782 InputFile.clear(); 2783 InputFile.seekg(ios::beg); 2784 map<int, pair<double,int> > AdaptiveCriteriaList; // (Root No., (Value, Order)) ! 2785 int No, FragOrder; 2786 double Value; 2787 // each line represents a fragment root (Atom::nr) id and its energy contribution 2788 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 2789 InputFile.getline(buffer, MAXSTRINGSIZE); 2790 while(!InputFile.eof()) { 2791 InputFile.getline(buffer, MAXSTRINGSIZE); 2792 if (strlen(buffer) > 2) { 2793 //*out << Verbose(2) << "Scanning: " << buffer << endl; 2794 stringstream line(buffer); 2795 line >> FragOrder; 2796 line >> ws >> No; 2797 line >> ws >> Value; // skip time entry 2798 line >> ws >> Value; 2799 No -= 1; // indices start at 1 in file, not 0 2800 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 2801 2802 // clean the list of those entries that have been superceded by higher order terms already 2803 map<int,KeySet>::iterator marker = IndexKeySetList.find(No); // find keyset to Frag No. 2804 if (marker != IndexKeySetList.end()) { // if found 2805 Value *= 1 + MYEPSILON*(*((*marker).second.begin())); // in case of equal energies this makes em not equal without changing anything actually 2806 // 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 2807 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 2808 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2809 if (!InsertedElement.second) { // this root is already present 2810 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2811 //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) 2812 { // if value is smaller, update value and order 2813 (*PresentItem).second.first = fabs(Value); 2814 (*PresentItem).second.second = FragOrder; 2815 *out << Verbose(2) << "Updated element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 2816 } else { 2817 *out << Verbose(2) << "Did not update element " << (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl; 2818 } 2819 } else { 2820 *out << Verbose(2) << "Inserted element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 2821 } 2822 } else { 2823 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl; 2824 } 2825 } 2826 } 2827 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones) 2828 map<double, pair<int,int> > FinalRootCandidates; 2829 *out << Verbose(1) << "Root candidate list is: " << endl; 2830 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) { 2831 Walker = FindAtom((*runner).first); 2832 if (Walker != NULL) { 2833 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order 2834 if (!Walker->MaxOrder) { 2835 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl; 2836 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) ); 2837 } else { 2838 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl; 2839 } 2840 } else { 2841 cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl; 2842 } 2843 } 2844 // pick the ones still below threshold and mark as to be adaptively updated 2845 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) { 2846 No = (*runner).second.first; 2847 Walker = FindAtom(No); 2848 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 2849 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2850 AtomMask[No] = true; 2851 status = true; 2852 //} else 2853 //*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 } 2855 // close and done 2856 InputFile.close(); 2857 InputFile.clear(); 2858 } else { 2859 cerr << "Unable to parse " << buffer << " file, incrementing all." << endl; 2860 while (Walker->next != end) { 2861 Walker = Walker->next; 2862 #ifdef ADDHYDROGEN 2863 if (Walker->type->Z != 1) // skip hydrogen 2864 #endif 2865 { 2866 AtomMask[Walker->nr] = true; // include all (non-hydrogen) atoms 2867 status = true; 2868 } 2869 } 2870 } 2871 Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer"); 2872 // pick a given number of highest values and set AtomMask 2873 } else { // global increase of Bond Order 2874 while (Walker->next != end) { 2875 Walker = Walker->next; 2876 #ifdef ADDHYDROGEN 2877 if (Walker->type->Z != 1) // skip hydrogen 2878 #endif 2879 { 2880 AtomMask[Walker->nr] = true; // include all (non-hydrogen) atoms 2881 if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr])) 2882 status = true; 2883 } 2884 } 2885 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 2886 status = true; 2887 2888 if (!status) { 2889 if (Order == 0) 2890 *out << Verbose(1) << "Single stepping done." << endl; 2891 else 2892 *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl; 2893 } 2894 } 2895 2896 // print atom mask for debugging 2897 *out << " "; 2898 for(int i=0;i<AtomCount;i++) 2899 *out << (i % 10); 2900 *out << endl << "Atom mask is: "; 2901 for(int i=0;i<AtomCount;i++) 2902 *out << (AtomMask[i] ? "t" : "f"); 2903 *out << endl; 2904 2905 return status; 2907 2906 }; 2908 2907 … … 2914 2913 bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex) 2915 2914 { 2916 element *runner = elemente->start;2917 int AtomNo = 0;2918 atom *Walker = NULL;2919 2920 if (SortIndex != NULL) {2921 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl;2922 return false;2923 }2924 SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex");2925 for(int i=AtomCount;i--;)2926 SortIndex[i] = -1;2927 while (runner->next != elemente->end) { // go through every element2928 runner = runner->next;2929 if (ElementsInMolecule[runner->Z]) { // if this element got atoms2930 Walker = start;2931 while (Walker->next != end) { // go through every atom of this element2932 Walker = Walker->next;2933 if (Walker->type->Z == runner->Z) // if this atom fits to element2934 SortIndex[Walker->nr] = AtomNo++;2935 }2936 }2937 }2938 return true;2915 element *runner = elemente->start; 2916 int AtomNo = 0; 2917 atom *Walker = NULL; 2918 2919 if (SortIndex != NULL) { 2920 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; 2921 return false; 2922 } 2923 SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex"); 2924 for(int i=AtomCount;i--;) 2925 SortIndex[i] = -1; 2926 while (runner->next != elemente->end) { // go through every element 2927 runner = runner->next; 2928 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 2929 Walker = start; 2930 while (Walker->next != end) { // go through every atom of this element 2931 Walker = Walker->next; 2932 if (Walker->type->Z == runner->Z) // if this atom fits to element 2933 SortIndex[Walker->nr] = AtomNo++; 2934 } 2935 } 2936 } 2937 return true; 2939 2938 }; 2940 2939 … … 2945 2944 y contribution", and that's why this consciously not done in the following loop) 2946 2945 * -# in a loop over all subgraphs 2947 * -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure2948 * -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)2946 * -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure 2947 * -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet) 2949 2948 * -# combines the generated molecule lists from all subgraphs 2950 2949 * -# saves to disk: fragment configs, adjacency, orderatsite, keyset files … … 2960 2959 { 2961 2960 MoleculeListClass *BondFragments = NULL; 2962 int *SortIndex = NULL;2963 int *MinimumRingSize = new int[AtomCount];2964 int FragmentCounter;2965 MoleculeLeafClass *MolecularWalker = NULL;2966 MoleculeLeafClass *Subgraphs = NULL;// list of subgraphs from DFS analysis2967 fstream File;2968 bool FragmentationToDo = true;2969 class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL;2970 bool CheckOrder = false;2971 Graph **FragmentList = NULL;2972 Graph *ParsedFragmentList = NULL;2973 Graph TotalGraph;// graph with all keysets however local numbers2974 int TotalNumberOfKeySets = 0;2975 atom **ListOfAtoms = NULL;2976 atom ***ListOfLocalAtoms = NULL;2977 bool *AtomMask = NULL;2978 2979 *out << endl;2961 int *SortIndex = NULL; 2962 int *MinimumRingSize = new int[AtomCount]; 2963 int FragmentCounter; 2964 MoleculeLeafClass *MolecularWalker = NULL; 2965 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 2966 fstream File; 2967 bool FragmentationToDo = true; 2968 class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL; 2969 bool CheckOrder = false; 2970 Graph **FragmentList = NULL; 2971 Graph *ParsedFragmentList = NULL; 2972 Graph TotalGraph; // graph with all keysets however local numbers 2973 int TotalNumberOfKeySets = 0; 2974 atom **ListOfAtoms = NULL; 2975 atom ***ListOfLocalAtoms = NULL; 2976 bool *AtomMask = NULL; 2977 2978 *out << endl; 2980 2979 #ifdef ADDHYDROGEN 2981 *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl;2980 *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl; 2982 2981 #else 2983 *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl;2982 *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl; 2984 2983 #endif 2985 2984 2986 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++2987 2988 // ===== 1. Check whether bond structure is same as stored in files ====2989 2990 // fill the adjacency list2991 CreateListOfBondsPerAtom(out);2992 2993 // create lookup table for Atom::nr2994 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount);2995 2996 // === compare it with adjacency file ===2997 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms);2998 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms");2999 3000 // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs =====3001 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);3002 // fill the bond structure of the individually stored subgraphs3003 Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);// we want to keep the created ListOfLocalAtoms3004 // analysis of the cycles (print rings, get minimum cycle length) for each subgraph3005 for(int i=AtomCount;i--;)3006 MinimumRingSize[i] = AtomCount;3007 MolecularWalker = Subgraphs;3008 FragmentCounter = 0;3009 while (MolecularWalker->next != NULL) {3010 MolecularWalker = MolecularWalker->next;3011 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount);3012 // // check the list of local atoms for debugging3013 // *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl;3014 // for (int i=0;i<AtomCount;i++)3015 // if (ListOfLocalAtoms[FragmentCounter][i] == NULL)3016 // *out << "\tNULL";3017 // else3018 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name;3019 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3020 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);3021 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3022 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize);3023 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3024 delete(LocalBackEdgeStack);3025 }3026 3027 // ===== 3. if structure still valid, parse key set file and others =====3028 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);3029 3030 // ===== 4. check globally whether there's something to do actually (first adaptivity check)3031 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath);3032 3033 // =================================== Begin of FRAGMENTATION ===============================3034 // ===== 6a. assign each keyset to its respective subgraph =====3035 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true);3036 3037 // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle3038 KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()];3039 AtomMask = new bool[AtomCount+1];3040 AtomMask[AtomCount] = false;3041 FragmentationToDo = false;// if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards3042 while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) {3043 FragmentationToDo = FragmentationToDo || CheckOrder;3044 AtomMask[AtomCount] = true;// last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()3045 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) =====3046 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0));3047 3048 // ===== 7. fill the bond fragment list =====3049 FragmentCounter = 0;3050 MolecularWalker = Subgraphs;3051 while (MolecularWalker->next != NULL) {3052 MolecularWalker = MolecularWalker->next;3053 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl;3054 //MolecularWalker->Leaf->OutputListOfBonds(out);// output ListOfBondsPerAtom for debugging3055 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) {3056 // call BOSSANOVA method3057 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl;3058 MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize);3059 } else {3060 cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl;3061 }3062 FragmentCounter++;// next fragment list3063 }3064 }3065 delete[](RootStack);3066 delete[](AtomMask);3067 delete(ParsedFragmentList);3068 delete[](MinimumRingSize);3069 3070 3071 // ==================================== End of FRAGMENTATION ============================================3072 3073 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)3074 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph);3075 3076 // free subgraph memory again3077 FragmentCounter = 0;3078 if (Subgraphs != NULL) {3079 while (Subgraphs->next != NULL) {3080 Subgraphs = Subgraphs->next;3081 delete(FragmentList[FragmentCounter++]);3082 delete(Subgraphs->previous);3083 }3084 delete(Subgraphs);3085 }3086 Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList");3087 3088 // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass =====3089 //if (FragmentationToDo) {// we should always store the fragments again as coordination might have changed slightly without changing bond structure3090 // allocate memory for the pointer array and transmorph graphs into full molecular fragments3091 BondFragments = new MoleculeListClass(TotalGraph.size(), AtomCount);3092 int k=0;3093 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) {3094 KeySet test = (*runner).first;3095 *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl;3096 BondFragments->ListOfMolecules[k] = StoreFragmentFromKeySet(out, test, configuration);3097 k++;3098 }3099 *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl;3100 3101 // ===== 9. Save fragments' configuration and keyset files et al to disk ===3102 if (BondFragments->NumberOfMolecules != 0) {3103 // create the SortIndex from BFS labels to order in the config file3104 CreateMappingLabelsToConfigSequence(out, SortIndex);3105 3106 *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl;3107 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex))3108 *out << Verbose(1) << "All configs written." << endl;3109 else3110 *out << Verbose(1) << "Some config writing failed." << endl;3111 3112 // store force index reference file3113 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex);3114 3115 // store keysets file3116 StoreKeySetFile(out, TotalGraph, configuration->configpath);3117 3118 // store Adjacency file3119 StoreAdjacencyToFile(out, configuration->configpath);3120 3121 // store Hydrogen saturation correction file3122 BondFragments->AddHydrogenCorrection(out, configuration->configpath);3123 3124 // store adaptive orders into file3125 StoreOrderAtSiteFile(out, configuration->configpath);3126 3127 // restore orbital and Stop values3128 CalculateOrbitals(*configuration);3129 3130 // free memory for bond part3131 *out << Verbose(1) << "Freeing bond memory" << endl;3132 delete(FragmentList); // remove bond molecule from memory3133 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex");3134 } else3135 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl;3136 //} else3137 //*out << Verbose(1) << "No fragments to store." << endl;3138 *out << Verbose(0) << "End of bond fragmentation." << endl;3139 3140 return ((int)(!FragmentationToDo)+1);// 1 - continue, 2 - stop (no fragmentation occured)2985 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 2986 2987 // ===== 1. Check whether bond structure is same as stored in files ==== 2988 2989 // fill the adjacency list 2990 CreateListOfBondsPerAtom(out); 2991 2992 // create lookup table for Atom::nr 2993 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 2994 2995 // === compare it with adjacency file === 2996 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 2997 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 2998 2999 // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs ===== 3000 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack); 3001 // fill the bond structure of the individually stored subgraphs 3002 Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false); // we want to keep the created ListOfLocalAtoms 3003 // analysis of the cycles (print rings, get minimum cycle length) for each subgraph 3004 for(int i=AtomCount;i--;) 3005 MinimumRingSize[i] = AtomCount; 3006 MolecularWalker = Subgraphs; 3007 FragmentCounter = 0; 3008 while (MolecularWalker->next != NULL) { 3009 MolecularWalker = MolecularWalker->next; 3010 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount); 3011 // // check the list of local atoms for debugging 3012 // *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl; 3013 // for (int i=0;i<AtomCount;i++) 3014 // if (ListOfLocalAtoms[FragmentCounter][i] == NULL) 3015 // *out << "\tNULL"; 3016 // else 3017 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name; 3018 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3019 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 3020 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3021 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize); 3022 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3023 delete(LocalBackEdgeStack); 3024 } 3025 3026 // ===== 3. if structure still valid, parse key set file and others ===== 3027 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); 3028 3029 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 3030 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 3031 3032 // =================================== Begin of FRAGMENTATION =============================== 3033 // ===== 6a. assign each keyset to its respective subgraph ===== 3034 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 3035 3036 // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle 3037 KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()]; 3038 AtomMask = new bool[AtomCount+1]; 3039 AtomMask[AtomCount] = false; 3040 FragmentationToDo = false; // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards 3041 while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) { 3042 FragmentationToDo = FragmentationToDo || CheckOrder; 3043 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 3044 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3045 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 3046 3047 // ===== 7. fill the bond fragment list ===== 3048 FragmentCounter = 0; 3049 MolecularWalker = Subgraphs; 3050 while (MolecularWalker->next != NULL) { 3051 MolecularWalker = MolecularWalker->next; 3052 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl; 3053 //MolecularWalker->Leaf->OutputListOfBonds(out); // output ListOfBondsPerAtom for debugging 3054 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) { 3055 // call BOSSANOVA method 3056 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl; 3057 MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize); 3058 } else { 3059 cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl; 3060 } 3061 FragmentCounter++; // next fragment list 3062 } 3063 } 3064 delete[](RootStack); 3065 delete[](AtomMask); 3066 delete(ParsedFragmentList); 3067 delete[](MinimumRingSize); 3068 3069 3070 // ==================================== End of FRAGMENTATION ============================================ 3071 3072 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3073 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3074 3075 // free subgraph memory again 3076 FragmentCounter = 0; 3077 if (Subgraphs != NULL) { 3078 while (Subgraphs->next != NULL) { 3079 Subgraphs = Subgraphs->next; 3080 delete(FragmentList[FragmentCounter++]); 3081 delete(Subgraphs->previous); 3082 } 3083 delete(Subgraphs); 3084 } 3085 Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList"); 3086 3087 // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass ===== 3088 //if (FragmentationToDo) { // we should always store the fragments again as coordination might have changed slightly without changing bond structure 3089 // allocate memory for the pointer array and transmorph graphs into full molecular fragments 3090 BondFragments = new MoleculeListClass(TotalGraph.size(), AtomCount); 3091 int k=0; 3092 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) { 3093 KeySet test = (*runner).first; 3094 *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl; 3095 BondFragments->ListOfMolecules[k] = StoreFragmentFromKeySet(out, test, configuration); 3096 k++; 3097 } 3098 *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl; 3099 3100 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3101 if (BondFragments->NumberOfMolecules != 0) { 3102 // create the SortIndex from BFS labels to order in the config file 3103 CreateMappingLabelsToConfigSequence(out, SortIndex); 3104 3105 *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl; 3106 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) 3107 *out << Verbose(1) << "All configs written." << endl; 3108 else 3109 *out << Verbose(1) << "Some config writing failed." << endl; 3110 3111 // store force index reference file 3112 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3113 3114 // store keysets file 3115 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3116 3117 // store Adjacency file 3118 StoreAdjacencyToFile(out, configuration->configpath); 3119 3120 // store Hydrogen saturation correction file 3121 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3122 3123 // store adaptive orders into file 3124 StoreOrderAtSiteFile(out, configuration->configpath); 3125 3126 // restore orbital and Stop values 3127 CalculateOrbitals(*configuration); 3128 3129 // free memory for bond part 3130 *out << Verbose(1) << "Freeing bond memory" << endl; 3131 delete(FragmentList); // remove bond molecule from memory 3132 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3133 } else 3134 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3135 //} else 3136 // *out << Verbose(1) << "No fragments to store." << endl; 3137 *out << Verbose(0) << "End of bond fragmentation." << endl; 3138 3139 return ((int)(!FragmentationToDo)+1); // 1 - continue, 2 - stop (no fragmentation occured) 3141 3140 }; 3142 3141 … … 3151 3150 bool molecule::PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack) 3152 3151 { 3153 bool status = true;3154 if (ReferenceStack->IsEmpty()) {3155 cerr << "ReferenceStack is empty!" << endl;3156 return false;3157 }3158 bond *Binder = ReferenceStack->PopFirst();3159 bond *FirstBond = Binder;// mark the first bond, so that we don't loop through the stack indefinitely3160 atom *Walker = NULL, *OtherAtom = NULL;3161 ReferenceStack->Push(Binder);3162 3163 do {// go through all bonds and push local ones3164 Walker = ListOfLocalAtoms[Binder->leftatom->nr];// get one atom in the reference molecule3165 if (Walker != NULL) // if this Walker exists in the subgraph ...3166 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {// go through the local list of bonds3167 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);3168 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond3169 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);3152 bool status = true; 3153 if (ReferenceStack->IsEmpty()) { 3154 cerr << "ReferenceStack is empty!" << endl; 3155 return false; 3156 } 3157 bond *Binder = ReferenceStack->PopFirst(); 3158 bond *FirstBond = Binder; // mark the first bond, so that we don't loop through the stack indefinitely 3159 atom *Walker = NULL, *OtherAtom = NULL; 3160 ReferenceStack->Push(Binder); 3161 3162 do { // go through all bonds and push local ones 3163 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3164 if (Walker != NULL) // if this Walker exists in the subgraph ... 3165 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds 3166 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3167 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond 3168 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]); 3170 3169 *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl; 3171 break;3172 }3173 }3174 Binder = ReferenceStack->PopFirst();// loop the stack for next item3170 break; 3171 } 3172 } 3173 Binder = ReferenceStack->PopFirst(); // loop the stack for next item 3175 3174 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl; 3176 ReferenceStack->Push(Binder);3177 } while (FirstBond != Binder);3178 3179 return status;3175 ReferenceStack->Push(Binder); 3176 } while (FirstBond != Binder); 3177 3178 return status; 3180 3179 }; 3181 3180 … … 3188 3187 bool molecule::StoreOrderAtSiteFile(ofstream *out, char *path) 3189 3188 { 3190 stringstream line;3191 ofstream file;3192 3193 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;3194 file.open(line.str().c_str());3195 *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl;3196 if (file != NULL) {3197 atom *Walker = start;3198 while (Walker->next != end) {3199 Walker = Walker->next;3200 file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl;3201 *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl;3202 }3203 file.close();3204 *out << Verbose(1) << "done." << endl;3205 return true;3206 } else {3207 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;3208 return false;3209 }3189 stringstream line; 3190 ofstream file; 3191 3192 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 3193 file.open(line.str().c_str()); 3194 *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl; 3195 if (file != NULL) { 3196 atom *Walker = start; 3197 while (Walker->next != end) { 3198 Walker = Walker->next; 3199 file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl; 3200 *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl; 3201 } 3202 file.close(); 3203 *out << Verbose(1) << "done." << endl; 3204 return true; 3205 } else { 3206 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 3207 return false; 3208 } 3210 3209 }; 3211 3210 … … 3219 3218 bool molecule::ParseOrderAtSiteFromFile(ofstream *out, char *path) 3220 3219 { 3221 unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray");3222 bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray");3223 bool status;3224 int AtomNr, value;3225 stringstream line;3226 ifstream file;3227 3228 *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl;3229 for(int i=AtomCount;i--;)3230 OrderArray[i] = 0;3231 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;3232 file.open(line.str().c_str());3233 if (file != NULL) {3234 for (int i=AtomCount;i--;) { // initialise with 03235 OrderArray[i] = 0;3236 MaxArray[i] = 0;3237 }3238 while (!file.eof()) { // parse from file3239 AtomNr = -1;3240 file >> AtomNr;3241 if (AtomNr != -1) {// test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)3242 file >> value;3243 OrderArray[AtomNr] = value;3244 file >> value;3245 MaxArray[AtomNr] = value;3246 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl;3247 }3248 }3249 atom *Walker = start;3250 while (Walker->next != end) { // fill into atom classes3251 Walker = Walker->next;3252 Walker->AdaptiveOrder = OrderArray[Walker->nr];3253 Walker->MaxOrder = MaxArray[Walker->nr];3254 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl;3255 }3256 file.close();3257 *out << Verbose(1) << "done." << endl;3258 status = true;3259 } else {3260 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;3261 status = false;3262 }3263 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray");3264 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray");3265 3266 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl;3267 return status;3220 unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3221 bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3222 bool status; 3223 int AtomNr, value; 3224 stringstream line; 3225 ifstream file; 3226 3227 *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl; 3228 for(int i=AtomCount;i--;) 3229 OrderArray[i] = 0; 3230 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 3231 file.open(line.str().c_str()); 3232 if (file != NULL) { 3233 for (int i=AtomCount;i--;) { // initialise with 0 3234 OrderArray[i] = 0; 3235 MaxArray[i] = 0; 3236 } 3237 while (!file.eof()) { // parse from file 3238 AtomNr = -1; 3239 file >> AtomNr; 3240 if (AtomNr != -1) { // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time) 3241 file >> value; 3242 OrderArray[AtomNr] = value; 3243 file >> value; 3244 MaxArray[AtomNr] = value; 3245 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl; 3246 } 3247 } 3248 atom *Walker = start; 3249 while (Walker->next != end) { // fill into atom classes 3250 Walker = Walker->next; 3251 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3252 Walker->MaxOrder = MaxArray[Walker->nr]; 3253 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3254 } 3255 file.close(); 3256 *out << Verbose(1) << "done." << endl; 3257 status = true; 3258 } else { 3259 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 3260 status = false; 3261 } 3262 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3263 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3264 3265 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3266 return status; 3268 3267 }; 3269 3268 … … 3276 3275 void molecule::CreateListOfBondsPerAtom(ofstream *out) 3277 3276 { 3278 bond *Binder = NULL;3279 atom *Walker = NULL;3280 int TotalDegree;3281 *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl;3282 3283 // re-allocate memory3284 *out << Verbose(2) << "(Re-)Allocating memory." << endl;3285 if (ListOfBondsPerAtom != NULL) {3286 for(int i=AtomCount;i--;)3287 Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]");3288 Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom");3289 }3290 if (NumberOfBondsPerAtom != NULL)3291 Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom");3292 ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom");3293 NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom");3294 3295 // reset bond counts per atom3296 for(int i=AtomCount;i--;)3297 NumberOfBondsPerAtom[i] = 0;3298 // count bonds per atom3299 Binder = first;3300 while (Binder->next != last) {3301 Binder = Binder->next;3302 NumberOfBondsPerAtom[Binder->leftatom->nr]++;3303 NumberOfBondsPerAtom[Binder->rightatom->nr]++;3304 }3305 for(int i=AtomCount;i--;) {3306 // allocate list of bonds per atom3307 ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]");3308 // clear the list again, now each NumberOfBondsPerAtom marks current free field3309 NumberOfBondsPerAtom[i] = 0;3310 }3311 // fill the list3312 Binder = first;3313 while (Binder->next != last) {3314 Binder = Binder->next;3315 ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder;3316 ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder;3317 }3318 3319 // output list for debugging3320 *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl;3321 Walker = start;3322 while (Walker->next != end) {3323 Walker = Walker->next;3324 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: ";3325 TotalDegree = 0;3326 for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {3327 *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t";3328 TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;3329 }3330 *out << " -- TotalDegree: " << TotalDegree << endl;3331 }3332 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl;3277 bond *Binder = NULL; 3278 atom *Walker = NULL; 3279 int TotalDegree; 3280 *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl; 3281 3282 // re-allocate memory 3283 *out << Verbose(2) << "(Re-)Allocating memory." << endl; 3284 if (ListOfBondsPerAtom != NULL) { 3285 for(int i=AtomCount;i--;) 3286 Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]"); 3287 Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom"); 3288 } 3289 if (NumberOfBondsPerAtom != NULL) 3290 Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom"); 3291 ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom"); 3292 NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom"); 3293 3294 // reset bond counts per atom 3295 for(int i=AtomCount;i--;) 3296 NumberOfBondsPerAtom[i] = 0; 3297 // count bonds per atom 3298 Binder = first; 3299 while (Binder->next != last) { 3300 Binder = Binder->next; 3301 NumberOfBondsPerAtom[Binder->leftatom->nr]++; 3302 NumberOfBondsPerAtom[Binder->rightatom->nr]++; 3303 } 3304 for(int i=AtomCount;i--;) { 3305 // allocate list of bonds per atom 3306 ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]"); 3307 // clear the list again, now each NumberOfBondsPerAtom marks current free field 3308 NumberOfBondsPerAtom[i] = 0; 3309 } 3310 // fill the list 3311 Binder = first; 3312 while (Binder->next != last) { 3313 Binder = Binder->next; 3314 ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder; 3315 ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder; 3316 } 3317 3318 // output list for debugging 3319 *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl; 3320 Walker = start; 3321 while (Walker->next != end) { 3322 Walker = Walker->next; 3323 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: "; 3324 TotalDegree = 0; 3325 for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) { 3326 *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t"; 3327 TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree; 3328 } 3329 *out << " -- TotalDegree: " << TotalDegree << endl; 3330 } 3331 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3333 3332 }; 3334 3333 … … 3347 3346 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3348 3347 { 3349 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList");3350 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList");3351 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList");3352 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);3353 atom *Walker = NULL, *OtherAtom = NULL;3354 bond *Binder = NULL;3355 3356 // add Root if not done yet3357 AtomStack->ClearStack();3358 if (AddedAtomList[Root->nr] == NULL)// add Root if not yet present3359 AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root);3360 AtomStack->Push(Root);3361 3362 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray3363 for (int i=AtomCount;i--;) {3364 PredecessorList[i] = NULL;3365 ShortestPathList[i] = -1;3366 if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited3367 ColorList[i] = lightgray;3368 else3369 ColorList[i] = white;3370 }3371 ShortestPathList[Root->nr] = 0;3372 3373 // and go on ... Queue always contains all lightgray vertices3374 while (!AtomStack->IsEmpty()) {3375 // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance.3376 // e.g. if current atom is 2, push to end of stack are of length 3, but first all of length 2 would be popped. They again3377 // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and3378 // followed by n+1 till top of stack.3379 Walker = AtomStack->PopFirst(); // pop oldest added3380 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl;3381 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {3382 Binder = ListOfBondsPerAtom[Walker->nr][i];3383 if (Binder != NULL) { // don't look at bond equal NULL3384 OtherAtom = Binder->GetOtherAtom(Walker);3385 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;3386 if (ColorList[OtherAtom->nr] == white) {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)3388 ColorList[OtherAtom->nr] = lightgray;3389 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor3390 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;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;3392 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance3393 *out << Verbose(3);3394 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far3395 AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);3396 *out << "Added OtherAtom " << OtherAtom->Name;3397 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3398 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3399 AddedBondList[Binder->nr]->Type = Binder->Type;3400 *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";3401 } else {// this code should actually never come into play (all white atoms are not yet present in BondMolecule, that's why they are white in the first place)3402 *out << "Not adding OtherAtom " << OtherAtom->Name;3403 if (AddedBondList[Binder->nr] == NULL) {3404 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3405 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3406 AddedBondList[Binder->nr]->Type = Binder->Type;3407 *out << ", added Bond " << *(AddedBondList[Binder->nr]);3408 } else3409 *out << ", not added Bond ";3410 }3411 *out << ", putting OtherAtom into queue." << endl;3412 AtomStack->Push(OtherAtom);3413 } else { // out of bond order, then replace3414 if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))3415 ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)3416 if (Binder == Bond)3417 *out << Verbose(3) << "Not Queueing, is the Root bond";3418 else if (ShortestPathList[OtherAtom->nr] >= BondOrder)3419 *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder;3420 if (!Binder->Cyclic)3421 *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;3422 if (AddedBondList[Binder->nr] == NULL) {3423 if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate3424 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3425 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3426 AddedBondList[Binder->nr]->Type = Binder->Type;3427 } else {3348 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList"); 3349 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList"); 3350 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList"); 3351 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 3352 atom *Walker = NULL, *OtherAtom = NULL; 3353 bond *Binder = NULL; 3354 3355 // add Root if not done yet 3356 AtomStack->ClearStack(); 3357 if (AddedAtomList[Root->nr] == NULL) // add Root if not yet present 3358 AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root); 3359 AtomStack->Push(Root); 3360 3361 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 3362 for (int i=AtomCount;i--;) { 3363 PredecessorList[i] = NULL; 3364 ShortestPathList[i] = -1; 3365 if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited 3366 ColorList[i] = lightgray; 3367 else 3368 ColorList[i] = white; 3369 } 3370 ShortestPathList[Root->nr] = 0; 3371 3372 // and go on ... Queue always contains all lightgray vertices 3373 while (!AtomStack->IsEmpty()) { 3374 // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance. 3375 // e.g. if current atom is 2, push to end of stack are of length 3, but first all of length 2 would be popped. They again 3376 // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and 3377 // followed by n+1 till top of stack. 3378 Walker = AtomStack->PopFirst(); // pop oldest added 3379 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3380 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3381 Binder = ListOfBondsPerAtom[Walker->nr][i]; 3382 if (Binder != NULL) { // don't look at bond equal NULL 3383 OtherAtom = Binder->GetOtherAtom(Walker); 3384 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3385 if (ColorList[OtherAtom->nr] == white) { 3386 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 ColorList[OtherAtom->nr] = lightgray; 3388 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3389 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3390 *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 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3392 *out << Verbose(3); 3393 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far 3394 AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom); 3395 *out << "Added OtherAtom " << OtherAtom->Name; 3396 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3397 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3398 AddedBondList[Binder->nr]->Type = Binder->Type; 3399 *out << " and bond " << *(AddedBondList[Binder->nr]) << ", "; 3400 } else { // this code should actually never come into play (all white atoms are not yet present in BondMolecule, that's why they are white in the first place) 3401 *out << "Not adding OtherAtom " << OtherAtom->Name; 3402 if (AddedBondList[Binder->nr] == NULL) { 3403 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3404 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3405 AddedBondList[Binder->nr]->Type = Binder->Type; 3406 *out << ", added Bond " << *(AddedBondList[Binder->nr]); 3407 } else 3408 *out << ", not added Bond "; 3409 } 3410 *out << ", putting OtherAtom into queue." << endl; 3411 AtomStack->Push(OtherAtom); 3412 } else { // out of bond order, then replace 3413 if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic)) 3414 ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic) 3415 if (Binder == Bond) 3416 *out << Verbose(3) << "Not Queueing, is the Root bond"; 3417 else if (ShortestPathList[OtherAtom->nr] >= BondOrder) 3418 *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder; 3419 if (!Binder->Cyclic) 3420 *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl; 3421 if (AddedBondList[Binder->nr] == NULL) { 3422 if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate 3423 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3424 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3425 AddedBondList[Binder->nr]->Type = Binder->Type; 3426 } else { 3428 3427 #ifdef ADDHYDROGEN 3429 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))3430 exit(1);3428 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3429 exit(1); 3431 3430 #endif 3432 }3433 }3434 }3435 } else {3436 *out << Verbose(3) << "Not Adding, has already been visited." << endl;3437 // This has to be a cyclic bond, check whether it's present ...3438 if (AddedBondList[Binder->nr] == NULL) {3439 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) {3440 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3441 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3442 AddedBondList[Binder->nr]->Type = Binder->Type;3443 } else { // if it's root bond it has to broken (otherwise we would not create the fragments)3431 } 3432 } 3433 } 3434 } else { 3435 *out << Verbose(3) << "Not Adding, has already been visited." << endl; 3436 // This has to be a cyclic bond, check whether it's present ... 3437 if (AddedBondList[Binder->nr] == NULL) { 3438 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3439 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3440 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3441 AddedBondList[Binder->nr]->Type = Binder->Type; 3442 } else { // if it's root bond it has to broken (otherwise we would not create the fragments) 3444 3443 #ifdef ADDHYDROGEN 3445 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))3446 exit(1);3444 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3445 exit(1); 3447 3446 #endif 3448 }3449 }3450 }3451 }3452 }3453 ColorList[Walker->nr] = black;3454 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;3455 }3456 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList");3457 Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList");3458 Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList");3459 delete(AtomStack);3447 } 3448 } 3449 } 3450 } 3451 } 3452 ColorList[Walker->nr] = black; 3453 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3454 } 3455 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); 3456 Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList"); 3457 Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList"); 3458 delete(AtomStack); 3460 3459 }; 3461 3460 … … 3471 3470 bool molecule::BuildInducedSubgraph(ofstream *out, const molecule *Father) 3472 3471 { 3473 atom *Walker = NULL, *OtherAtom = NULL;3474 bool status = true;3475 atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList");3476 3477 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl;3478 3479 // reset parent list3480 *out << Verbose(3) << "Resetting ParentList." << endl;3481 for (int i=Father->AtomCount;i--;)3482 ParentList[i] = NULL;3483 3484 // fill parent list with sons3485 *out << Verbose(3) << "Filling Parent List." << endl;3486 Walker = start;3487 while (Walker->next != end) {3488 Walker = Walker->next;3489 ParentList[Walker->father->nr] = Walker;3490 // Outputting List for debugging3491 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<" is " << ParentList[Walker->father->nr] << "." << endl;3492 }3493 3494 // check each entry of parent list and if ok (one-to-and-onto matching) create bonds3495 *out << Verbose(3) << "Creating bonds." << endl;3496 Walker = Father->start;3497 while (Walker->next != Father->end) {3498 Walker = Walker->next;3499 if (ParentList[Walker->nr] != NULL) {3500 if (ParentList[Walker->nr]->father != Walker) {3501 status = false;3502 } else {3503 for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) {3504 OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);3505 if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond3506 *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl;3507 AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree);3508 }3509 }3510 }3511 }3512 }3513 3514 Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList");3515 *out << Verbose(2) << "End of BuildInducedSubgraph." << endl;3516 return status;3472 atom *Walker = NULL, *OtherAtom = NULL; 3473 bool status = true; 3474 atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList"); 3475 3476 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 3477 3478 // reset parent list 3479 *out << Verbose(3) << "Resetting ParentList." << endl; 3480 for (int i=Father->AtomCount;i--;) 3481 ParentList[i] = NULL; 3482 3483 // fill parent list with sons 3484 *out << Verbose(3) << "Filling Parent List." << endl; 3485 Walker = start; 3486 while (Walker->next != end) { 3487 Walker = Walker->next; 3488 ParentList[Walker->father->nr] = Walker; 3489 // Outputting List for debugging 3490 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father << " is " << ParentList[Walker->father->nr] << "." << endl; 3491 } 3492 3493 // check each entry of parent list and if ok (one-to-and-onto matching) create bonds 3494 *out << Verbose(3) << "Creating bonds." << endl; 3495 Walker = Father->start; 3496 while (Walker->next != Father->end) { 3497 Walker = Walker->next; 3498 if (ParentList[Walker->nr] != NULL) { 3499 if (ParentList[Walker->nr]->father != Walker) { 3500 status = false; 3501 } else { 3502 for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) { 3503 OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3504 if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond 3505 *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl; 3506 AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree); 3507 } 3508 } 3509 } 3510 } 3511 } 3512 3513 Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList"); 3514 *out << Verbose(2) << "End of BuildInducedSubgraph." << endl; 3515 return status; 3517 3516 }; 3518 3517 … … 3526 3525 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) 3527 3526 { 3528 atom *Runner = NULL;3529 int SP, Removal;3530 3531 *out << Verbose(2) << "Looking for removal candidate." << endl;3532 SP = -1; //0;// not -1, so that Root is never removed3533 Removal = -1;3534 for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) {3535 Runner = FindAtom((*runner));3536 if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack3537 if (ShortestPathList[(*runner)] > SP) {// remove the oldest one with longest shortest path3538 SP = ShortestPathList[(*runner)];3539 Removal = (*runner);3540 }3541 }3542 }3543 return Removal;3527 atom *Runner = NULL; 3528 int SP, Removal; 3529 3530 *out << Verbose(2) << "Looking for removal candidate." << endl; 3531 SP = -1; //0; // not -1, so that Root is never removed 3532 Removal = -1; 3533 for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) { 3534 Runner = FindAtom((*runner)); 3535 if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack 3536 if (ShortestPathList[(*runner)] > SP) { // remove the oldest one with longest shortest path 3537 SP = ShortestPathList[(*runner)]; 3538 Removal = (*runner); 3539 } 3540 } 3541 } 3542 return Removal; 3544 3543 }; 3545 3544 … … 3554 3553 molecule * molecule::StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem) 3555 3554 { 3556 atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL;3557 atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList");3558 molecule *Leaf = new molecule(elemente);3559 bool LonelyFlag = false;3560 int size;3561 3562 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl;3563 3564 Leaf->BondDistance = BondDistance;3565 for(int i=NDIM*2;i--;)3566 Leaf->cell_size[i] = cell_size[i];3567 3568 // initialise SonList (indicates when we need to replace a bond with hydrogen instead)3569 for(int i=AtomCount;i--;)3570 SonList[i] = NULL;3571 3572 // first create the minimal set of atoms from the KeySet3573 size = 0;3574 for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) {3575 FatherOfRunner = FindAtom((*runner));// find the id3576 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner);3577 size++;3578 }3579 3580 // create the bonds between all: Make it an induced subgraph and add hydrogen3581 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl;3582 Runner = Leaf->start;3583 while (Runner->next != Leaf->end) {3584 Runner = Runner->next;3585 LonelyFlag = true;3586 FatherOfRunner = Runner->father;3587 if (SonList[FatherOfRunner->nr] != NULL) {// check if this, our father, is present in list3588 // create all bonds3589 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father3590 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner);3591 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather;3592 if (SonList[OtherFather->nr] != NULL) {3593 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl;3594 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba)3595 // *out << Verbose(3) << "Adding Bond: ";3596 // *out <<3597 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree);3598 // *out << "." << endl;3599 //NumBonds[Runner->nr]++;3600 } else {3601 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl;3602 }3603 LonelyFlag = false;3604 } else {3605 // *out << ", who has no son in this fragment molecule." << endl;3555 atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL; 3556 atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList"); 3557 molecule *Leaf = new molecule(elemente); 3558 bool LonelyFlag = false; 3559 int size; 3560 3561 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 3562 3563 Leaf->BondDistance = BondDistance; 3564 for(int i=NDIM*2;i--;) 3565 Leaf->cell_size[i] = cell_size[i]; 3566 3567 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) 3568 for(int i=AtomCount;i--;) 3569 SonList[i] = NULL; 3570 3571 // first create the minimal set of atoms from the KeySet 3572 size = 0; 3573 for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) { 3574 FatherOfRunner = FindAtom((*runner)); // find the id 3575 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner); 3576 size++; 3577 } 3578 3579 // create the bonds between all: Make it an induced subgraph and add hydrogen 3580 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; 3581 Runner = Leaf->start; 3582 while (Runner->next != Leaf->end) { 3583 Runner = Runner->next; 3584 LonelyFlag = true; 3585 FatherOfRunner = Runner->father; 3586 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 3587 // create all bonds 3588 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3589 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 3590 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 3591 if (SonList[OtherFather->nr] != NULL) { 3592 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3593 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 3594 // *out << Verbose(3) << "Adding Bond: "; 3595 // *out << 3596 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 3597 // *out << "." << endl; 3598 //NumBonds[Runner->nr]++; 3599 } else { 3600 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 3601 } 3602 LonelyFlag = false; 3603 } else { 3604 // *out << ", who has no son in this fragment molecule." << endl; 3606 3605 #ifdef ADDHYDROGEN 3607 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl;3608 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem))3609 exit(1);3606 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; 3607 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem)) 3608 exit(1); 3610 3609 #endif 3611 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree;3612 }3613 }3614 } else {3615 *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl;3616 }3617 if ((LonelyFlag) && (size > 1)) {3618 *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl;3619 }3610 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree; 3611 } 3612 } 3613 } else { 3614 *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl; 3615 } 3616 if ((LonelyFlag) && (size > 1)) { 3617 *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl; 3618 } 3620 3619 #ifdef ADDHYDROGEN 3621 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen3622 Runner = Runner->next;3620 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 3621 Runner = Runner->next; 3623 3622 #endif 3624 }3625 Leaf->CreateListOfBondsPerAtom(out);3626 //Leaflet->Leaf->ScanForPeriodicCorrection(out);3627 Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList");3628 // *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl;3629 return Leaf;3623 } 3624 Leaf->CreateListOfBondsPerAtom(out); 3625 //Leaflet->Leaf->ScanForPeriodicCorrection(out); 3626 Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList"); 3627 // *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl; 3628 return Leaf; 3630 3629 }; 3631 3630 … … 3646 3645 MoleculeListClass * molecule::CreateListOfUniqueFragmentsOfOrder(ofstream *out, int Order, config *configuration) 3647 3646 { 3648 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList");3649 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");3650 int *Labels = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels");3651 enum Shading *ColorVertexList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList");3652 enum Shading *ColorEdgeList = (enum Shading *) Malloc(sizeof(enum Shading)*BondCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorBondList");3653 StackClass<atom *> *RootStack = new StackClass<atom *>(AtomCount);3654 StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself3655 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!3656 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL;3657 MoleculeListClass *FragmentList = NULL;3658 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL;3659 bond *Binder = NULL;3660 int RunningIndex = 0, FragmentCounter = 0;3661 3662 *out << Verbose(1) << "Begin of CreateListOfUniqueFragmentsOfOrder." << endl;3663 3664 // reset parent list3665 *out << Verbose(3) << "Resetting labels, parent, predecessor, color and shortest path lists." << endl;3666 for (int i=0;i<AtomCount;i++) { // reset all atom labels3667 // initialise each vertex as white with no predecessor, empty queue, color lightgray, not labelled, no sons3647 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList"); 3648 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList"); 3649 int *Labels = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels"); 3650 enum Shading *ColorVertexList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList"); 3651 enum Shading *ColorEdgeList = (enum Shading *) Malloc(sizeof(enum Shading)*BondCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorBondList"); 3652 StackClass<atom *> *RootStack = new StackClass<atom *>(AtomCount); 3653 StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself 3654 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! 3655 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 3656 MoleculeListClass *FragmentList = NULL; 3657 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL; 3658 bond *Binder = NULL; 3659 int RunningIndex = 0, FragmentCounter = 0; 3660 3661 *out << Verbose(1) << "Begin of CreateListOfUniqueFragmentsOfOrder." << endl; 3662 3663 // reset parent list 3664 *out << Verbose(3) << "Resetting labels, parent, predecessor, color and shortest path lists." << endl; 3665 for (int i=0;i<AtomCount;i++) { // reset all atom labels 3666 // initialise each vertex as white with no predecessor, empty queue, color lightgray, not labelled, no sons 3668 3667 Labels[i] = -1; 3669 SonList[i] = NULL;3670 PredecessorList[i] = NULL;3671 ColorVertexList[i] = white;3672 ShortestPathList[i] = -1;3673 }3674 for (int i=0;i<BondCount;i++)3675 ColorEdgeList[i] = white;3668 SonList[i] = NULL; 3669 PredecessorList[i] = NULL; 3670 ColorVertexList[i] = white; 3671 ShortestPathList[i] = -1; 3672 } 3673 for (int i=0;i<BondCount;i++) 3674 ColorEdgeList[i] = white; 3676 3675 RootStack->ClearStack(); // clearstack and push first atom if exists 3677 TouchedStack->ClearStack();3678 Walker = start->next;3679 while ((Walker != end)3676 TouchedStack->ClearStack(); 3677 Walker = start->next; 3678 while ((Walker != end) 3680 3679 #ifdef ADDHYDROGEN 3681 && (Walker->type->Z == 1)3680 && (Walker->type->Z == 1) 3682 3681 #endif 3683 ) { // search for first non-hydrogen atom3684 *out << Verbose(4) << "Current Root candidate is " << Walker->Name << "." << endl;3685 Walker = Walker->next;3686 }3687 if (Walker != end)3688 RootStack->Push(Walker);3689 else3690 *out << Verbose(0) << "ERROR: Could not find an appropriate Root atom!" << endl;3691 *out << Verbose(3) << "Root " << Walker->Name << " is on AtomStack, beginning loop through all vertices ..." << endl;3692 3693 ///// OUTER LOOP ////////////3694 while (!RootStack->IsEmpty()) {3695 // get new root vertex from atom stack3696 Root = RootStack->PopFirst();3697 ShortestPathList[Root->nr] = 0;3698 if (Labels[Root->nr] == -1)3699 Labels[Root->nr] = RunningIndex++; // prevent it from getting again on AtomStack3700 PredecessorList[Root->nr] = Root;3701 TouchedStack->Push(Root);3702 *out << Verbose(0) << "Root for this loop is: " << Root->Name << ".\n";3682 ) { // search for first non-hydrogen atom 3683 *out << Verbose(4) << "Current Root candidate is " << Walker->Name << "." << endl; 3684 Walker = Walker->next; 3685 } 3686 if (Walker != end) 3687 RootStack->Push(Walker); 3688 else 3689 *out << Verbose(0) << "ERROR: Could not find an appropriate Root atom!" << endl; 3690 *out << Verbose(3) << "Root " << Walker->Name << " is on AtomStack, beginning loop through all vertices ..." << endl; 3691 3692 ///// OUTER LOOP //////////// 3693 while (!RootStack->IsEmpty()) { 3694 // get new root vertex from atom stack 3695 Root = RootStack->PopFirst(); 3696 ShortestPathList[Root->nr] = 0; 3697 if (Labels[Root->nr] == -1) 3698 Labels[Root->nr] = RunningIndex++; // prevent it from getting again on AtomStack 3699 PredecessorList[Root->nr] = Root; 3700 TouchedStack->Push(Root); 3701 *out << Verbose(0) << "Root for this loop is: " << Root->Name << ".\n"; 3703 3702 3704 3703 // clear snake stack 3705 SnakeStack->ClearStack();3706 //SnakeStack->TestImplementation(out, start->next);3707 3708 ///// INNER LOOP ////////////3709 // Problems:3710 // - what about cyclic bonds?3711 Walker = Root;3712 do {3713 *out << Verbose(1) << "Current Walker is: " << Walker->Name;3714 // initial setting of the new Walker: label, color, shortest path and put on stacks3715 if (Labels[Walker->nr] == -1) { // give atom a unique, monotonely increasing number3716 Labels[Walker->nr] = RunningIndex++;3717 RootStack->Push(Walker);3718 }3719 *out << ", has label " << Labels[Walker->nr];3720 if ((ColorVertexList[Walker->nr] == white) || ((Binder != NULL) && (ColorEdgeList[Binder->nr] == white))) { // color it if newly discovered and push on stacks (and if within reach!)3721 if ((Binder != NULL) && (ColorEdgeList[Binder->nr] == white)) {3722 // Binder ought to be set still from last neighbour search3723 *out << ", coloring bond " << *Binder << " black";3724 ColorEdgeList[Binder->nr] = black; // mark this bond as used3725 }3726 if (ShortestPathList[Walker->nr] == -1) {3727 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1;3728 TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed3729 }3730 if ((ShortestPathList[Walker->nr] < Order) && (ColorVertexList[Walker->nr] != darkgray)) {// if not already on snake stack3731 SnakeStack->Push(Walker);3732 ColorVertexList[Walker->nr] = darkgray; // mark as dark gray of on snake stack3733 }3734 }3735 *out << ", SP of " << ShortestPathList[Walker->nr]<< " and its color is " << GetColor(ColorVertexList[Walker->nr]) << "." << endl;3736 3737 // then check the stack for a newly stumbled upon fragment3738 if (SnakeStack->ItemCount() == Order) { // is stack full?3739 // store the fragment if it is one and get a removal candidate3740 Removal = StoreFragmentFromStack(out, Root, Walker, Leaflet, SnakeStack, ShortestPathList, SonList, Labels, &FragmentCounter, configuration);3741 // remove the candidate if one was found3742 if (Removal != NULL) {3743 *out << Verbose(2) << "Removing item " << Removal->Name << " with SP of " << ShortestPathList[Removal->nr] << " from snake stack." << endl;3744 SnakeStack->RemoveItem(Removal);3745 ColorVertexList[Removal->nr] = lightgray; // return back to not on snake stack but explored marking3746 if (Walker == Removal) { // if the current atom is to be removed, we also have to take a step back3747 Walker = PredecessorList[Removal->nr];3748 *out << Verbose(2) << "Stepping back to " << Walker->Name << "." << endl;3749 }3750 }3751 } else3752 Removal = NULL;3753 3754 // finally, look for a white neighbour as the next Walker3755 Binder = NULL;3756 if ((Removal == NULL) || (Walker != PredecessorList[Removal->nr])) {// don't look, if a new walker has been set above3757 *out << Verbose(2) << "Snake has currently " << SnakeStack->ItemCount() << " item(s)." << endl;3758 OtherAtom = NULL; // this is actually not needed, every atom has at least one neighbour3759 if (ShortestPathList[Walker->nr] < Order) {3760 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {3761 Binder = ListOfBondsPerAtom[Walker->nr][i];3762 *out << Verbose(2) << "Current bond is " << *Binder << ": ";3763 OtherAtom = Binder->GetOtherAtom(Walker);3764 if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us3765 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl;3766 //ColorVertexList[OtherAtom->nr] = lightgray;// mark as explored3767 } else { // otherwise check its colour and element3768 if (3704 SnakeStack->ClearStack(); 3705 //SnakeStack->TestImplementation(out, start->next); 3706 3707 ///// INNER LOOP //////////// 3708 // Problems: 3709 // - what about cyclic bonds? 3710 Walker = Root; 3711 do { 3712 *out << Verbose(1) << "Current Walker is: " << Walker->Name; 3713 // initial setting of the new Walker: label, color, shortest path and put on stacks 3714 if (Labels[Walker->nr] == -1) { // give atom a unique, monotonely increasing number 3715 Labels[Walker->nr] = RunningIndex++; 3716 RootStack->Push(Walker); 3717 } 3718 *out << ", has label " << Labels[Walker->nr]; 3719 if ((ColorVertexList[Walker->nr] == white) || ((Binder != NULL) && (ColorEdgeList[Binder->nr] == white))) { // color it if newly discovered and push on stacks (and if within reach!) 3720 if ((Binder != NULL) && (ColorEdgeList[Binder->nr] == white)) { 3721 // Binder ought to be set still from last neighbour search 3722 *out << ", coloring bond " << *Binder << " black"; 3723 ColorEdgeList[Binder->nr] = black; // mark this bond as used 3724 } 3725 if (ShortestPathList[Walker->nr] == -1) { 3726 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 3727 TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed 3728 } 3729 if ((ShortestPathList[Walker->nr] < Order) && (ColorVertexList[Walker->nr] != darkgray)) { // if not already on snake stack 3730 SnakeStack->Push(Walker); 3731 ColorVertexList[Walker->nr] = darkgray; // mark as dark gray of on snake stack 3732 } 3733 } 3734 *out << ", SP of " << ShortestPathList[Walker->nr] << " and its color is " << GetColor(ColorVertexList[Walker->nr]) << "." << endl; 3735 3736 // then check the stack for a newly stumbled upon fragment 3737 if (SnakeStack->ItemCount() == Order) { // is stack full? 3738 // store the fragment if it is one and get a removal candidate 3739 Removal = StoreFragmentFromStack(out, Root, Walker, Leaflet, SnakeStack, ShortestPathList, SonList, Labels, &FragmentCounter, configuration); 3740 // remove the candidate if one was found 3741 if (Removal != NULL) { 3742 *out << Verbose(2) << "Removing item " << Removal->Name << " with SP of " << ShortestPathList[Removal->nr] << " from snake stack." << endl; 3743 SnakeStack->RemoveItem(Removal); 3744 ColorVertexList[Removal->nr] = lightgray; // return back to not on snake stack but explored marking 3745 if (Walker == Removal) { // if the current atom is to be removed, we also have to take a step back 3746 Walker = PredecessorList[Removal->nr]; 3747 *out << Verbose(2) << "Stepping back to " << Walker->Name << "." << endl; 3748 } 3749 } 3750 } else 3751 Removal = NULL; 3752 3753 // finally, look for a white neighbour as the next Walker 3754 Binder = NULL; 3755 if ((Removal == NULL) || (Walker != PredecessorList[Removal->nr])) { // don't look, if a new walker has been set above 3756 *out << Verbose(2) << "Snake has currently " << SnakeStack->ItemCount() << " item(s)." << endl; 3757 OtherAtom = NULL; // this is actually not needed, every atom has at least one neighbour 3758 if (ShortestPathList[Walker->nr] < Order) { 3759 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3760 Binder = ListOfBondsPerAtom[Walker->nr][i]; 3761 *out << Verbose(2) << "Current bond is " << *Binder << ": "; 3762 OtherAtom = Binder->GetOtherAtom(Walker); 3763 if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us 3764 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 3765 //ColorVertexList[OtherAtom->nr] = lightgray; // mark as explored 3766 } else { // otherwise check its colour and element 3767 if ( 3769 3768 #ifdef ADDHYDROGEN 3770 (OtherAtom->type->Z != 1) &&3769 (OtherAtom->type->Z != 1) && 3771 3770 #endif 3772 (ColorEdgeList[Binder->nr] == white)) {// skip hydrogen, look for unexplored vertices3773 *out << "Moving along " << GetColor(ColorEdgeList[Binder->nr]) << " bond " << Binder << " to " << ((ColorVertexList[OtherAtom->nr] == white) ? "unexplored" : "explored") << " item: " << OtherAtom->Name << "." << endl;3774 // i find it currently rather sensible to always set the predecessor in order to find one's way back3775 //if (PredecessorList[OtherAtom->nr] == NULL) {3776 PredecessorList[OtherAtom->nr] = Walker;3777 *out << Verbose(3) << "Setting Predecessor of " << OtherAtom->Name << " to " << PredecessorList[OtherAtom->nr]->Name << "." << endl;3778 //} else {3779 //*out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl;3780 //}3781 Walker = OtherAtom;3782 break;3783 } else {3784 if (OtherAtom->type->Z == 1)3785 *out << "Links to a hydrogen atom." << endl;3786 else3787 *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl;3788 }3789 }3790 }3791 } else {// means we have stepped beyond the horizon: Return!3792 Walker = PredecessorList[Walker->nr];3793 OtherAtom = Walker;3794 *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl;3795 }3796 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black3797 *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl;3798 ColorVertexList[Walker->nr] = black;3799 Walker = PredecessorList[Walker->nr];3800 }3801 }3802 } while ((Walker != Root) || (ColorVertexList[Root->nr] != black));3803 *out << Verbose(2) << "Inner Looping is finished." << endl;3804 3805 // if we reset all AtomCount atoms, we have again technically O(N^2) ...3806 *out << Verbose(2) << "Resetting lists." << endl;3807 Walker = NULL;3808 Binder = NULL;3809 while (!TouchedStack->IsEmpty()) {3810 Walker = TouchedStack->PopLast();3811 *out << Verbose(3) << "Re-initialising entries of " << *Walker << "." << endl;3812 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)3813 ColorEdgeList[ListOfBondsPerAtom[Walker->nr][i]->nr] = white;3814 PredecessorList[Walker->nr] = NULL;3815 ColorVertexList[Walker->nr] = white;3816 ShortestPathList[Walker->nr] = -1;3817 }3818 }3819 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl;3820 3821 // copy together3822 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl;3823 FragmentList = new MoleculeListClass(FragmentCounter, AtomCount);3824 RunningIndex = 0;3825 while ((Leaflet != NULL) && (RunningIndex < FragmentCounter)){3826 FragmentList->ListOfMolecules[RunningIndex++] = Leaflet->Leaf;3827 Leaflet->Leaf = NULL; // prevent molecule from being removed3828 TempLeaf = Leaflet;3829 Leaflet = Leaflet->previous;3830 delete(TempLeaf);3831 };3832 3833 // free memory and exit3834 Free((void **)&PredecessorList, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList");3835 Free((void **)&ShortestPathList, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");3836 Free((void **)&Labels, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels");3837 Free((void **)&ColorVertexList, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList");3838 delete(RootStack);3839 delete(TouchedStack);3840 delete(SnakeStack);3841 3842 *out << Verbose(1) << "End of CreateListOfUniqueFragmentsOfOrder." << endl;3843 return FragmentList;3771 (ColorEdgeList[Binder->nr] == white)) { // skip hydrogen, look for unexplored vertices 3772 *out << "Moving along " << GetColor(ColorEdgeList[Binder->nr]) << " bond " << Binder << " to " << ((ColorVertexList[OtherAtom->nr] == white) ? "unexplored" : "explored") << " item: " << OtherAtom->Name << "." << endl; 3773 // i find it currently rather sensible to always set the predecessor in order to find one's way back 3774 //if (PredecessorList[OtherAtom->nr] == NULL) { 3775 PredecessorList[OtherAtom->nr] = Walker; 3776 *out << Verbose(3) << "Setting Predecessor of " << OtherAtom->Name << " to " << PredecessorList[OtherAtom->nr]->Name << "." << endl; 3777 //} else { 3778 // *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl; 3779 //} 3780 Walker = OtherAtom; 3781 break; 3782 } else { 3783 if (OtherAtom->type->Z == 1) 3784 *out << "Links to a hydrogen atom." << endl; 3785 else 3786 *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl; 3787 } 3788 } 3789 } 3790 } else { // means we have stepped beyond the horizon: Return! 3791 Walker = PredecessorList[Walker->nr]; 3792 OtherAtom = Walker; 3793 *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl; 3794 } 3795 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 3796 *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl; 3797 ColorVertexList[Walker->nr] = black; 3798 Walker = PredecessorList[Walker->nr]; 3799 } 3800 } 3801 } while ((Walker != Root) || (ColorVertexList[Root->nr] != black)); 3802 *out << Verbose(2) << "Inner Looping is finished." << endl; 3803 3804 // if we reset all AtomCount atoms, we have again technically O(N^2) ... 3805 *out << Verbose(2) << "Resetting lists." << endl; 3806 Walker = NULL; 3807 Binder = NULL; 3808 while (!TouchedStack->IsEmpty()) { 3809 Walker = TouchedStack->PopLast(); 3810 *out << Verbose(3) << "Re-initialising entries of " << *Walker << "." << endl; 3811 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) 3812 ColorEdgeList[ListOfBondsPerAtom[Walker->nr][i]->nr] = white; 3813 PredecessorList[Walker->nr] = NULL; 3814 ColorVertexList[Walker->nr] = white; 3815 ShortestPathList[Walker->nr] = -1; 3816 } 3817 } 3818 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 3819 3820 // copy together 3821 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 3822 FragmentList = new MoleculeListClass(FragmentCounter, AtomCount); 3823 RunningIndex = 0; 3824 while ((Leaflet != NULL) && (RunningIndex < FragmentCounter)) { 3825 FragmentList->ListOfMolecules[RunningIndex++] = Leaflet->Leaf; 3826 Leaflet->Leaf = NULL; // prevent molecule from being removed 3827 TempLeaf = Leaflet; 3828 Leaflet = Leaflet->previous; 3829 delete(TempLeaf); 3830 }; 3831 3832 // free memory and exit 3833 Free((void **)&PredecessorList, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList"); 3834 Free((void **)&ShortestPathList, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList"); 3835 Free((void **)&Labels, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels"); 3836 Free((void **)&ColorVertexList, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList"); 3837 delete(RootStack); 3838 delete(TouchedStack); 3839 delete(SnakeStack); 3840 3841 *out << Verbose(1) << "End of CreateListOfUniqueFragmentsOfOrder." << endl; 3842 return FragmentList; 3844 3843 }; 3845 3844 */ … … 3848 3847 */ 3849 3848 struct UniqueFragments { 3850 config *configuration;3851 atom *Root;3852 Graph *Leaflet;3853 KeySet *FragmentSet;3854 int ANOVAOrder;3855 int FragmentCounter;3856 int CurrentIndex;3857 double TEFactor;3858 int *ShortestPathList;3859 bool **UsedList;3860 bond **BondsPerSPList;3861 int *BondsPerSPCount;3849 config *configuration; 3850 atom *Root; 3851 Graph *Leaflet; 3852 KeySet *FragmentSet; 3853 int ANOVAOrder; 3854 int FragmentCounter; 3855 int CurrentIndex; 3856 double TEFactor; 3857 int *ShortestPathList; 3858 bool **UsedList; 3859 bond **BondsPerSPList; 3860 int *BondsPerSPCount; 3862 3861 }; 3863 3862 3864 3863 /** From a given set of Bond sorted by Shortest Path distance, create all possible fragments of size \a SetDimension. 3865 3864 * -# loops over every possible combination (2^dimension of edge set) 3866 * -# inserts current set, if there's still space left3867 * -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist3865 * -# inserts current set, if there's still space left 3866 * -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist 3868 3867 ance+1 3869 * -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph3870 * -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root3868 * -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph 3869 * -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root 3871 3870 distance) and current set 3872 3871 * \param *out output stream for debugging … … 3878 3877 void molecule::SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder) 3879 3878 { 3880 atom *OtherWalker = NULL;3881 int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder;3882 int NumCombinations;3883 bool bit;3884 int bits, TouchedIndex, SubSetDimension, SP, Added;3885 int Removal;3886 int SpaceLeft;3887 int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList");3888 bond *Binder = NULL;3889 bond **BondsList = NULL;3890 KeySetTestPair TestKeySetInsert;3891 3892 NumCombinations = 1 << SetDimension;3893 3894 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen3895 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder3896 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden3897 3898 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl;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;3900 3901 // initialised touched list (stores added atoms on this level)3902 *out << Verbose(1+verbosity) << "Clearing touched list." << endl;3903 for (TouchedIndex=SubOrder+1;TouchedIndex--;)// empty touched list3904 TouchedList[TouchedIndex] = -1;3905 TouchedIndex = 0;3906 3907 // create every possible combination of the endpieces3908 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl;3909 for (int i=1;i<NumCombinations;i++) {// sweep through all power set combinations (skip empty set!)3910 // count the set bit of i3911 bits = 0;3912 for (int j=SetDimension;j--;)3913 bits += (i & (1 << j)) >> j;3914 3915 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl;3916 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue3917 // --1-- add this set of the power set of bond partners to the snake stack3918 Added = 0;3919 for (int j=0;j<SetDimension;j++) {// pull out every bit by shifting3920 bit = ((i & (1 << j)) != 0);// mask the bit for the j-th bond3921 if (bit) {// if bit is set, we add this bond partner3922 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add3923 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl;3924 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl;3925 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr);3926 if (TestKeySetInsert.second) {3927 TouchedList[TouchedIndex++] = OtherWalker->nr;// note as added3928 Added++;3929 } else {3930 *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl;3931 }3932 //FragmentSearch->UsedList[OtherWalker->nr][i] = true;3933 //}3934 } else {3935 *out << Verbose(2+verbosity) << "Not adding." << endl;3936 }3937 }3938 3939 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore3940 if (SpaceLeft > 0) {3941 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl;3942 if (SubOrder > 1) {// Due to Added above we have to check extra whether we're not already reaching beyond the desired Order3943 // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion3944 SP = RootDistance+1; // this is the next level3945 // first count the members in the subset3946 SubSetDimension = 0;3947 Binder = FragmentSearch->BondsPerSPList[2*SP]; // start node for this level3948 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { // compare to end node of this level3949 Binder = Binder->next;3950 for (int k=TouchedIndex;k--;) {3951 if (Binder->Contains(TouchedList[k]))// if we added this very endpiece3952 SubSetDimension++;3953 }3954 }3955 // then allocate and fill the list3956 BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList");3957 SubSetDimension = 0;3958 Binder = FragmentSearch->BondsPerSPList[2*SP];3959 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {3960 Binder = Binder->next;3961 for (int k=0;k<TouchedIndex;k++) {3962 if (Binder->leftatom->nr == TouchedList[k])// leftatom is always the close one3963 BondsList[SubSetDimension++] = Binder;3964 }3965 }3966 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl;3967 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits);3968 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList");3969 }3970 } else {3971 // --2-- otherwise store the complete fragment3972 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl;3973 // store fragment as a KeySet3974 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: ";3975 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)3976 *out << (*runner) << " ";3977 *out << endl;3978 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet))3979 //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl;3980 InsertFragmentIntoGraph(out, FragmentSearch);3981 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList);3982 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration);3983 }3984 3985 // --3-- remove all added items in this level from snake stack3986 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl;3987 for(int j=0;j<TouchedIndex;j++) {3988 Removal = TouchedList[j];3989 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl;3990 FragmentSearch->FragmentSet->erase(Removal);3991 TouchedList[j] = -1;3992 }3993 *out << Verbose(2) << "Remaining local nr.s on snake stack are: ";3994 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)3995 *out << (*runner) << " ";3996 *out << endl;3997 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level3998 } else {3999 *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl;4000 }4001 }4002 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList");4003 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl;3879 atom *OtherWalker = NULL; 3880 int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder; 3881 int NumCombinations; 3882 bool bit; 3883 int bits, TouchedIndex, SubSetDimension, SP, Added; 3884 int Removal; 3885 int SpaceLeft; 3886 int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList"); 3887 bond *Binder = NULL; 3888 bond **BondsList = NULL; 3889 KeySetTestPair TestKeySetInsert; 3890 3891 NumCombinations = 1 << SetDimension; 3892 3893 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 3894 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 3895 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 3896 3897 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 3898 *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; 3899 3900 // initialised touched list (stores added atoms on this level) 3901 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 3902 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 3903 TouchedList[TouchedIndex] = -1; 3904 TouchedIndex = 0; 3905 3906 // create every possible combination of the endpieces 3907 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; 3908 for (int i=1;i<NumCombinations;i++) { // sweep through all power set combinations (skip empty set!) 3909 // count the set bit of i 3910 bits = 0; 3911 for (int j=SetDimension;j--;) 3912 bits += (i & (1 << j)) >> j; 3913 3914 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 3915 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue 3916 // --1-- add this set of the power set of bond partners to the snake stack 3917 Added = 0; 3918 for (int j=0;j<SetDimension;j++) { // pull out every bit by shifting 3919 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 3920 if (bit) { // if bit is set, we add this bond partner 3921 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3922 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 3923 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 3924 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3925 if (TestKeySetInsert.second) { 3926 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added 3927 Added++; 3928 } else { 3929 *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl; 3930 } 3931 //FragmentSearch->UsedList[OtherWalker->nr][i] = true; 3932 //} 3933 } else { 3934 *out << Verbose(2+verbosity) << "Not adding." << endl; 3935 } 3936 } 3937 3938 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3939 if (SpaceLeft > 0) { 3940 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; 3941 if (SubOrder > 1) { // Due to Added above we have to check extra whether we're not already reaching beyond the desired Order 3942 // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion 3943 SP = RootDistance+1; // this is the next level 3944 // first count the members in the subset 3945 SubSetDimension = 0; 3946 Binder = FragmentSearch->BondsPerSPList[2*SP]; // start node for this level 3947 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { // compare to end node of this level 3948 Binder = Binder->next; 3949 for (int k=TouchedIndex;k--;) { 3950 if (Binder->Contains(TouchedList[k])) // if we added this very endpiece 3951 SubSetDimension++; 3952 } 3953 } 3954 // then allocate and fill the list 3955 BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList"); 3956 SubSetDimension = 0; 3957 Binder = FragmentSearch->BondsPerSPList[2*SP]; 3958 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { 3959 Binder = Binder->next; 3960 for (int k=0;k<TouchedIndex;k++) { 3961 if (Binder->leftatom->nr == TouchedList[k]) // leftatom is always the close one 3962 BondsList[SubSetDimension++] = Binder; 3963 } 3964 } 3965 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 3966 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3967 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 3968 } 3969 } else { 3970 // --2-- otherwise store the complete fragment 3971 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl; 3972 // store fragment as a KeySet 3973 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 3974 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3975 *out << (*runner) << " "; 3976 *out << endl; 3977 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) 3978 //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl; 3979 InsertFragmentIntoGraph(out, FragmentSearch); 3980 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList); 3981 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 3982 } 3983 3984 // --3-- remove all added items in this level from snake stack 3985 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; 3986 for(int j=0;j<TouchedIndex;j++) { 3987 Removal = TouchedList[j]; 3988 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl; 3989 FragmentSearch->FragmentSet->erase(Removal); 3990 TouchedList[j] = -1; 3991 } 3992 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 3993 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3994 *out << (*runner) << " "; 3995 *out << endl; 3996 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level 3997 } else { 3998 *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl; 3999 } 4000 } 4001 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 4002 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 4004 4003 }; 4005 4004 … … 4012 4011 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 4013 4012 { 4014 atom *Walker = NULL, *Walker2 = NULL;4015 bool BondStatus = false;4016 int size;4017 4018 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl;4019 *out << Verbose(2) << "Disconnected atom: ";4020 4021 // count number of atoms in graph4022 size = 0;4023 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++)4024 size++;4025 if (size > 1)4026 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) {4027 Walker = FindAtom(*runner);4028 BondStatus = false;4029 for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) {4030 Walker2 = FindAtom(*runners);4031 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {4032 if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) {4033 BondStatus = true;4034 break;4035 }4036 if (BondStatus)4037 break;4038 }4039 }4040 if (!BondStatus) {4041 *out << (*Walker) << endl;4042 return false;4043 }4044 }4045 else {4046 *out << "none." << endl;4047 return true;4048 }4049 *out << "none." << endl;4050 4051 *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl;4052 4053 return true;4013 atom *Walker = NULL, *Walker2 = NULL; 4014 bool BondStatus = false; 4015 int size; 4016 4017 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 4018 *out << Verbose(2) << "Disconnected atom: "; 4019 4020 // count number of atoms in graph 4021 size = 0; 4022 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) 4023 size++; 4024 if (size > 1) 4025 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) { 4026 Walker = FindAtom(*runner); 4027 BondStatus = false; 4028 for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) { 4029 Walker2 = FindAtom(*runners); 4030 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 4031 if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) { 4032 BondStatus = true; 4033 break; 4034 } 4035 if (BondStatus) 4036 break; 4037 } 4038 } 4039 if (!BondStatus) { 4040 *out << (*Walker) << endl; 4041 return false; 4042 } 4043 } 4044 else { 4045 *out << "none." << endl; 4046 return true; 4047 } 4048 *out << "none." << endl; 4049 4050 *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl; 4051 4052 return true; 4054 4053 } 4055 4054 … … 4071 4070 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4072 4071 { 4073 int SP, AtomKeyNr;4074 atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL;4075 bond *Binder = NULL;4076 bond *CurrentEdge = NULL;4077 bond **BondsList = NULL;4078 int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr;4079 int Counter = FragmentSearch.FragmentCounter;4080 int RemainingWalkers;4081 4082 *out << endl;4083 *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl;4084 4085 // prepare Label and SP arrays of the BFS search4086 FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0;4087 4088 // prepare root level (SP = 0) and a loop bond denoting Root4089 for (int i=1;i<Order;i++)4090 FragmentSearch.BondsPerSPCount[i] = 0;4091 FragmentSearch.BondsPerSPCount[0] = 1;4092 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root);4093 add(Binder, FragmentSearch.BondsPerSPList[1]);4094 4095 // do a BFS search to fill the SP lists and label the found vertices4096 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into4097 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning4098 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth4099 // (EdgeinSPLevel) of this tree ...4100 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence4101 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction.4102 *out << endl;4103 *out << Verbose(0) << "Starting BFS analysis ..." << endl;4104 for (SP = 0; SP < (Order-1); SP++) {4105 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)";4106 if (SP > 0) {4107 *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl;4108 FragmentSearch.BondsPerSPCount[SP] = 0;4109 } else4110 *out << "." << endl;4111 4112 RemainingWalkers = FragmentSearch.BondsPerSPCount[SP];4113 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP];/// start of this SP level's list4114 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) {/// end of this SP level's list4115 CurrentEdge = CurrentEdge->next;4116 RemainingWalkers--;4117 Walker = CurrentEdge->rightatom;// rightatom is always the one more distant4118 Predecessor = CurrentEdge->leftatom;// ... and leftatom is predecessor4119 AtomKeyNr = Walker->nr;4120 *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl;4121 // check for new sp level4122 // go through all its bonds4123 *out << Verbose(1) << "Going through all bonds of Walker." << endl;4124 for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) {4125 Binder = ListOfBondsPerAtom[AtomKeyNr][i];4126 OtherWalker = Binder->GetOtherAtom(Walker);4127 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end())4128 #ifdef ADDHYDROGEN4129 && (OtherWalker->type->Z != 1)4130 #endif4131 ) {// skip hydrogens and restrict to fragment4132 *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl;4133 // set the label if not set (and push on root stack as well)4134 if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's4135 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1;4136 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl;4137 // add the bond in between to the SP list4138 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant4139 add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]);4140 FragmentSearch.BondsPerSPCount[SP+1]++;4141 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl;4142 } else {4143 if (OtherWalker != Predecessor)4144 *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl;4145 else4146 *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl;4147 }4148 } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl;4149 }4150 }4151 }4152 4153 // outputting all list for debugging4154 *out << Verbose(0) << "Printing all found lists." << endl;4155 for(int i=1;i<Order;i++) {// skip the root edge in the printing4156 Binder = FragmentSearch.BondsPerSPList[2*i];4157 *out << Verbose(1) << "Current SP level is " << i << "." << endl;4158 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {4159 Binder = Binder->next;4160 *out << Verbose(2) << *Binder << endl;4161 }4162 }4163 4164 // creating fragments with the found edge sets(may be done in reverse order, faster)4165 SP = -1;// the Root <-> Root edge must be subtracted!4166 for(int i=Order;i--;) { // sum up all found edges4167 Binder = FragmentSearch.BondsPerSPList[2*i];4168 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {4169 Binder = Binder->next;4170 SP ++;4171 }4172 }4173 *out << Verbose(0) << "Total number of edges is " << SP << "." << endl;4174 if (SP >= (Order-1)) {4175 // start with root (push on fragment stack)4176 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl;4177 FragmentSearch.FragmentSet->clear();4178 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl;4179 // prepare the subset and call the generator4180 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList");4181 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next;// on SP level 0 there's only the root bond4182 4183 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order);4184 4185 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList");4186 } else {4187 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl;4188 }4189 4190 // as FragmentSearch structure is used only once, we don't have to clean it anymore4191 // remove root from stack4192 *out << Verbose(0) << "Removing root again from stack." << endl;4193 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr);4194 4195 // free'ing the bonds lists4196 *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl;4197 for(int i=Order;i--;) {4198 *out << Verbose(1) << "Current SP level is " << i << ": ";4199 Binder = FragmentSearch.BondsPerSPList[2*i];4200 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {4201 Binder = Binder->next;4202 // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local4203 FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1;4204 FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1;4205 }4206 // delete added bonds4207 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]);4208 // also start and end node4209 *out << "cleaned." << endl;4210 }4211 4212 // return list4213 *out << Verbose(0) << "End of PowerSetGenerator." << endl;4214 return (FragmentSearch.FragmentCounter - Counter);4072 int SP, AtomKeyNr; 4073 atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL; 4074 bond *Binder = NULL; 4075 bond *CurrentEdge = NULL; 4076 bond **BondsList = NULL; 4077 int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr; 4078 int Counter = FragmentSearch.FragmentCounter; 4079 int RemainingWalkers; 4080 4081 *out << endl; 4082 *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl; 4083 4084 // prepare Label and SP arrays of the BFS search 4085 FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0; 4086 4087 // prepare root level (SP = 0) and a loop bond denoting Root 4088 for (int i=1;i<Order;i++) 4089 FragmentSearch.BondsPerSPCount[i] = 0; 4090 FragmentSearch.BondsPerSPCount[0] = 1; 4091 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4092 add(Binder, FragmentSearch.BondsPerSPList[1]); 4093 4094 // do a BFS search to fill the SP lists and label the found vertices 4095 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 4096 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 4097 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 4098 // (EdgeinSPLevel) of this tree ... 4099 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 4100 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. 4101 *out << endl; 4102 *out << Verbose(0) << "Starting BFS analysis ..." << endl; 4103 for (SP = 0; SP < (Order-1); SP++) { 4104 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)"; 4105 if (SP > 0) { 4106 *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl; 4107 FragmentSearch.BondsPerSPCount[SP] = 0; 4108 } else 4109 *out << "." << endl; 4110 4111 RemainingWalkers = FragmentSearch.BondsPerSPCount[SP]; 4112 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP]; /// start of this SP level's list 4113 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) { /// end of this SP level's list 4114 CurrentEdge = CurrentEdge->next; 4115 RemainingWalkers--; 4116 Walker = CurrentEdge->rightatom; // rightatom is always the one more distant 4117 Predecessor = CurrentEdge->leftatom; // ... and leftatom is predecessor 4118 AtomKeyNr = Walker->nr; 4119 *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl; 4120 // check for new sp level 4121 // go through all its bonds 4122 *out << Verbose(1) << "Going through all bonds of Walker." << endl; 4123 for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) { 4124 Binder = ListOfBondsPerAtom[AtomKeyNr][i]; 4125 OtherWalker = Binder->GetOtherAtom(Walker); 4126 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end()) 4127 #ifdef ADDHYDROGEN 4128 && (OtherWalker->type->Z != 1) 4129 #endif 4130 ) { // skip hydrogens and restrict to fragment 4131 *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl; 4132 // set the label if not set (and push on root stack as well) 4133 if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's 4134 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1; 4135 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl; 4136 // add the bond in between to the SP list 4137 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant 4138 add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]); 4139 FragmentSearch.BondsPerSPCount[SP+1]++; 4140 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl; 4141 } else { 4142 if (OtherWalker != Predecessor) 4143 *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl; 4144 else 4145 *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl; 4146 } 4147 } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl; 4148 } 4149 } 4150 } 4151 4152 // outputting all list for debugging 4153 *out << Verbose(0) << "Printing all found lists." << endl; 4154 for(int i=1;i<Order;i++) { // skip the root edge in the printing 4155 Binder = FragmentSearch.BondsPerSPList[2*i]; 4156 *out << Verbose(1) << "Current SP level is " << i << "." << endl; 4157 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4158 Binder = Binder->next; 4159 *out << Verbose(2) << *Binder << endl; 4160 } 4161 } 4162 4163 // creating fragments with the found edge sets (may be done in reverse order, faster) 4164 SP = -1; // the Root <-> Root edge must be subtracted! 4165 for(int i=Order;i--;) { // sum up all found edges 4166 Binder = FragmentSearch.BondsPerSPList[2*i]; 4167 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4168 Binder = Binder->next; 4169 SP ++; 4170 } 4171 } 4172 *out << Verbose(0) << "Total number of edges is " << SP << "." << endl; 4173 if (SP >= (Order-1)) { 4174 // start with root (push on fragment stack) 4175 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4176 FragmentSearch.FragmentSet->clear(); 4177 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4178 // prepare the subset and call the generator 4179 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4180 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4181 4182 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4183 4184 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4185 } else { 4186 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl; 4187 } 4188 4189 // as FragmentSearch structure is used only once, we don't have to clean it anymore 4190 // remove root from stack 4191 *out << Verbose(0) << "Removing root again from stack." << endl; 4192 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4193 4194 // free'ing the bonds lists 4195 *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl; 4196 for(int i=Order;i--;) { 4197 *out << Verbose(1) << "Current SP level is " << i << ": "; 4198 Binder = FragmentSearch.BondsPerSPList[2*i]; 4199 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4200 Binder = Binder->next; 4201 // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local 4202 FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1; 4203 FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1; 4204 } 4205 // delete added bonds 4206 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]); 4207 // also start and end node 4208 *out << "cleaned." << endl; 4209 } 4210 4211 // return list 4212 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4213 return (FragmentSearch.FragmentCounter - Counter); 4215 4214 }; 4216 4215 … … 4223 4222 void molecule::ScanForPeriodicCorrection(ofstream *out) 4224 4223 { 4225 bond *Binder = NULL;4226 bond *OtherBinder = NULL;4227 atom *Walker = NULL;4228 atom *OtherWalker = NULL;4229 double *matrix = ReturnFullMatrixforSymmetric(cell_size);4230 enum Shading *ColorList = NULL;4231 double tmp;4232 Vector Translationvector;4233 //class StackClass<atom *> *CompStack = NULL;4234 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);4235 bool flag = true;4236 4237 *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl;4238 4239 ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList");4240 while (flag) {4241 // remove bonds that are beyond bonddistance4242 for(int i=NDIM;i--;)4243 Translationvector.x[i] = 0.;4244 // scan all bonds4245 Binder = first;4246 flag = false;4247 while ((!flag) && (Binder->next != last)) {4248 Binder = Binder->next;4249 for (int i=NDIM;i--;) {4250 tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]);4251 //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl;4252 if (tmp > BondDistance) {4253 OtherBinder = Binder->next; // note down binding partner for later re-insertion4254 unlink(Binder);// unlink bond4255 *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl;4256 flag = true;4257 break;4258 }4259 }4260 }4261 if (flag) {4262 // create translation vector from their periodically modified distance4263 for (int i=NDIM;i--;) {4264 tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i];4265 if (fabs(tmp) > BondDistance)4266 Translationvector.x[i] = (tmp < 0) ? +1. : -1.;4267 }4268 Translationvector.MatrixMultiplication(matrix);4269 //*out << Verbose(3) << "Translation vector is ";4270 Translationvector.Output(out);4271 *out << endl;4272 // apply to all atoms of first component via BFS4273 for (int i=AtomCount;i--;)4274 ColorList[i] = white;4275 AtomStack->Push(Binder->leftatom);4276 while (!AtomStack->IsEmpty()) {4277 Walker = AtomStack->PopFirst();4278 //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl;4279 ColorList[Walker->nr] = black;// mark as explored4280 Walker->x.AddVector(&Translationvector); // translate4281 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {// go through all binding partners4282 if (ListOfBondsPerAtom[Walker->nr][i] != Binder) {4283 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);4284 if (ColorList[OtherWalker->nr] == white) {4285 AtomStack->Push(OtherWalker); // push if yet unexplored4286 }4287 }4288 }4289 }4290 // re-add bond4291 link(Binder, OtherBinder);4292 } else {4293 *out << Verbose(3) << "No corrections for this fragment." << endl;4294 }4295 //delete(CompStack);4296 }4297 4298 // free allocated space from ReturnFullMatrixforSymmetric()4299 delete(AtomStack);4300 Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList");4301 Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix");4302 *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl;4224 bond *Binder = NULL; 4225 bond *OtherBinder = NULL; 4226 atom *Walker = NULL; 4227 atom *OtherWalker = NULL; 4228 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 4229 enum Shading *ColorList = NULL; 4230 double tmp; 4231 Vector Translationvector; 4232 //class StackClass<atom *> *CompStack = NULL; 4233 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 4234 bool flag = true; 4235 4236 *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl; 4237 4238 ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList"); 4239 while (flag) { 4240 // remove bonds that are beyond bonddistance 4241 for(int i=NDIM;i--;) 4242 Translationvector.x[i] = 0.; 4243 // scan all bonds 4244 Binder = first; 4245 flag = false; 4246 while ((!flag) && (Binder->next != last)) { 4247 Binder = Binder->next; 4248 for (int i=NDIM;i--;) { 4249 tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]); 4250 //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl; 4251 if (tmp > BondDistance) { 4252 OtherBinder = Binder->next; // note down binding partner for later re-insertion 4253 unlink(Binder); // unlink bond 4254 *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl; 4255 flag = true; 4256 break; 4257 } 4258 } 4259 } 4260 if (flag) { 4261 // create translation vector from their periodically modified distance 4262 for (int i=NDIM;i--;) { 4263 tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]; 4264 if (fabs(tmp) > BondDistance) 4265 Translationvector.x[i] = (tmp < 0) ? +1. : -1.; 4266 } 4267 Translationvector.MatrixMultiplication(matrix); 4268 //*out << Verbose(3) << "Translation vector is "; 4269 Translationvector.Output(out); 4270 *out << endl; 4271 // apply to all atoms of first component via BFS 4272 for (int i=AtomCount;i--;) 4273 ColorList[i] = white; 4274 AtomStack->Push(Binder->leftatom); 4275 while (!AtomStack->IsEmpty()) { 4276 Walker = AtomStack->PopFirst(); 4277 //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl; 4278 ColorList[Walker->nr] = black; // mark as explored 4279 Walker->x.AddVector(&Translationvector); // translate 4280 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through all binding partners 4281 if (ListOfBondsPerAtom[Walker->nr][i] != Binder) { 4282 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 4283 if (ColorList[OtherWalker->nr] == white) { 4284 AtomStack->Push(OtherWalker); // push if yet unexplored 4285 } 4286 } 4287 } 4288 } 4289 // re-add bond 4290 link(Binder, OtherBinder); 4291 } else { 4292 *out << Verbose(3) << "No corrections for this fragment." << endl; 4293 } 4294 //delete(CompStack); 4295 } 4296 4297 // free allocated space from ReturnFullMatrixforSymmetric() 4298 delete(AtomStack); 4299 Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList"); 4300 Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix"); 4301 *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl; 4303 4302 }; 4304 4303 … … 4309 4308 double * molecule::ReturnFullMatrixforSymmetric(double *symm) 4310 4309 { 4311 double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix");4312 matrix[0] = symm[0];4313 matrix[1] = symm[1];4314 matrix[2] = symm[3];4315 matrix[3] = symm[1];4316 matrix[4] = symm[2];4317 matrix[5] = symm[4];4318 matrix[6] = symm[3];4319 matrix[7] = symm[4];4320 matrix[8] = symm[5];4321 return matrix;4310 double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix"); 4311 matrix[0] = symm[0]; 4312 matrix[1] = symm[1]; 4313 matrix[2] = symm[3]; 4314 matrix[3] = symm[1]; 4315 matrix[4] = symm[2]; 4316 matrix[5] = symm[4]; 4317 matrix[6] = symm[3]; 4318 matrix[7] = symm[4]; 4319 matrix[8] = symm[5]; 4320 return matrix; 4322 4321 }; 4323 4322 4324 4323 bool KeyCompare::operator() (const KeySet SubgraphA, const KeySet SubgraphB) const 4325 4324 { 4326 //cout << "my check is used." << endl;4327 if (SubgraphA.size() < SubgraphB.size()) {4328 return true;4329 } else {4330 if (SubgraphA.size() > SubgraphB.size()) {4331 return false;4332 } else {4333 KeySet::iterator IteratorA = SubgraphA.begin();4334 KeySet::iterator IteratorB = SubgraphB.begin();4335 while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) {4336 if ((*IteratorA) <(*IteratorB))4337 return true;4338 else if ((*IteratorA) > (*IteratorB)) {4339 return false;4340 } // else, go on to next index4341 IteratorA++;4342 IteratorB++;4343 } // end of while loop4344 }// end of check in case of equal sizes4345 }4346 return false; // if we reach this point, they are equal4325 //cout << "my check is used." << endl; 4326 if (SubgraphA.size() < SubgraphB.size()) { 4327 return true; 4328 } else { 4329 if (SubgraphA.size() > SubgraphB.size()) { 4330 return false; 4331 } else { 4332 KeySet::iterator IteratorA = SubgraphA.begin(); 4333 KeySet::iterator IteratorB = SubgraphB.begin(); 4334 while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) { 4335 if ((*IteratorA) < (*IteratorB)) 4336 return true; 4337 else if ((*IteratorA) > (*IteratorB)) { 4338 return false; 4339 } // else, go on to next index 4340 IteratorA++; 4341 IteratorB++; 4342 } // end of while loop 4343 }// end of check in case of equal sizes 4344 } 4345 return false; // if we reach this point, they are equal 4347 4346 }; 4348 4347 4349 4348 //bool operator < (KeySet SubgraphA, KeySet SubgraphB) 4350 4349 //{ 4351 // return KeyCompare(SubgraphA, SubgraphB);4350 // return KeyCompare(SubgraphA, SubgraphB); 4352 4351 //}; 4353 4352 … … 4361 4360 inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment) 4362 4361 { 4363 GraphTestPair testGraphInsert;4364 4365 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor)));// store fragment number and current factor4366 if (testGraphInsert.second) {4367 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl;4368 Fragment->FragmentCounter++;4369 } else {4370 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;4371 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;// increase the "created" counter4372 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl;4373 }4362 GraphTestPair testGraphInsert; 4363 4364 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor))); // store fragment number and current factor 4365 if (testGraphInsert.second) { 4366 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl; 4367 Fragment->FragmentCounter++; 4368 } else { 4369 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 4370 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor; // increase the "created" counter 4371 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl; 4372 } 4374 4373 }; 4375 4374 //void inline InsertIntoGraph(ofstream *out, KeyStack &stack, Graph &graph, int *counter, double factor) 4376 4375 //{ 4377 // // copy stack contents to set and call overloaded function again4378 // KeySet set;4379 // for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++)4380 // set.insert((*runner));4381 // InsertIntoGraph(out, set, graph, counter, factor);4376 // // copy stack contents to set and call overloaded function again 4377 // KeySet set; 4378 // for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++) 4379 // set.insert((*runner)); 4380 // InsertIntoGraph(out, set, graph, counter, factor); 4382 4381 //}; 4383 4382 … … 4390 4389 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) 4391 4390 { 4392 GraphTestPair testGraphInsert;4393 4394 for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) {4395 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));// store fragment number and current factor4396 if (testGraphInsert.second) {4397 *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl;4398 } else {4399 *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;4400 ((*(testGraphInsert.first)).second).second += (*runner).second.second;4401 *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl;4402 }4403 }4391 GraphTestPair testGraphInsert; 4392 4393 for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) { 4394 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second))); // store fragment number and current factor 4395 if (testGraphInsert.second) { 4396 *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl; 4397 } else { 4398 *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 4399 ((*(testGraphInsert.first)).second).second += (*runner).second.second; 4400 *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl; 4401 } 4402 } 4404 4403 }; 4405 4404 … … 4408 4407 * -# constructs a complete keyset of the molecule 4409 4408 * -# In a loop over all possible roots from the given rootstack 4410 * -# increases order of root site4411 * -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr4412 * -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset4409 * -# increases order of root site 4410 * -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr 4411 * -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset 4413 4412 as the restricted one and each site in the set as the root) 4414 * -# these are merged into a fragment list of keysets4413 * -# these are merged into a fragment list of keysets 4415 4414 * -# All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return 4416 4415 * Important only is that we create all fragments, it is not important if we create them more than once … … 4424 4423 void molecule::FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize) 4425 4424 { 4426 Graph ***FragmentLowerOrdersList = NULL;4427 int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL;4428 int counter = 0, Order;4429 int UpgradeCount = RootStack.size();4430 KeyStack FragmentRootStack;4431 int RootKeyNr, RootNr;4432 struct UniqueFragments FragmentSearch;4433 4434 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl;4435 4436 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5)4437 // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5)4438 NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");4439 FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");4440 4441 // initialise the fragments structure4442 FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList");4443 FragmentSearch.FragmentCounter = 0;4444 FragmentSearch.FragmentSet = new KeySet;4445 FragmentSearch.Root = FindAtom(RootKeyNr);4446 for (int i=AtomCount;i--;) {4447 FragmentSearch.ShortestPathList[i] = -1;4448 }4449 4450 // Construct the complete KeySet which we need for topmost level only (but for all Roots)4451 atom *Walker = start;4452 KeySet CompleteMolecule;4453 while (Walker->next != end) {4454 Walker = Walker->next;4455 CompleteMolecule.insert(Walker->GetTrueFather()->nr);4456 }4457 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, as4459 // each has to be split up. E.g. for the second level we have one from 5th, one from 4th, two from 3th (which in turn is one from 5th, one from 4th),4460 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[])4461 // with the order along the cells as this: 5433222211111111 for BondOrder 5 needing 16=pow(2,5-1) cells (only we use bit-shifting which is faster)4462 RootNr = 0;// counts through the roots in RootStack4463 while ((RootNr < UpgradeCount) && (!RootStack.empty())) {4464 RootKeyNr = RootStack.front();4465 RootStack.pop_front();4466 Walker = FindAtom(RootKeyNr);4467 // check cyclic lengths4468 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) {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;4470 //} else4471 {4472 // increase adaptive order by one4473 Walker->GetTrueFather()->AdaptiveOrder++;4474 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder;4475 4476 // initialise Order-dependent entries of UniqueFragments structure4477 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList");4478 FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount");4479 for (int i=Order;i--;) {4480 FragmentSearch.BondsPerSPList[2*i] = new bond();// start node4481 FragmentSearch.BondsPerSPList[2*i+1] = new bond();// end node4482 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1];// intertwine these two4483 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i];4484 FragmentSearch.BondsPerSPCount[i] = 0;4485 }4486 4487 // allocate memory for all lower level orders in this 1D-array of ptrs4488 NumLevels = 1 << (Order-1); // (int)pow(2,Order);4489 FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");4490 for (int i=0;i<NumLevels;i++)4491 FragmentLowerOrdersList[RootNr][i] = NULL;4492 4493 // create top order where nothing is reduced4494 *out << Verbose(0) << "==============================================================================================================" << endl;4495 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << "4496 4497 // Create list of Graphs of current Bond Order (i.e. F_{ij})4498 FragmentLowerOrdersList[RootNr][0] =new Graph;4499 FragmentSearch.TEFactor = 1.;4500 FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0];// set to insertion graph4501 FragmentSearch.Root = Walker;4502 NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule);4503 *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl;4504 if (NumMoleculesOfOrder[RootNr] != 0) {4505 NumMolecules = 0;4506 4507 // we don't have to dive into suborders! These keysets are all already created on lower orders!4508 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed)4509 4510 // if ((NumLevels >> 1) > 0) {4511 // // create lower order fragments4512 // *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl;4513 // Order = Walker->AdaptiveOrder;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)4515 // // step down to next order at (virtual) boundary of powers of 2 in array4516 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order))4517 // Order--;4518 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl;4519 // for (int SubOrder=Order-1;SubOrder>0;SubOrder--) {4520 // int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1)));4521 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl;4522 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl;4425 Graph ***FragmentLowerOrdersList = NULL; 4426 int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL; 4427 int counter = 0, Order; 4428 int UpgradeCount = RootStack.size(); 4429 KeyStack FragmentRootStack; 4430 int RootKeyNr, RootNr; 4431 struct UniqueFragments FragmentSearch; 4432 4433 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 4434 4435 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5) 4436 // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5) 4437 NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4438 FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4439 4440 // initialise the fragments structure 4441 FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList"); 4442 FragmentSearch.FragmentCounter = 0; 4443 FragmentSearch.FragmentSet = new KeySet; 4444 FragmentSearch.Root = FindAtom(RootKeyNr); 4445 for (int i=AtomCount;i--;) { 4446 FragmentSearch.ShortestPathList[i] = -1; 4447 } 4448 4449 // Construct the complete KeySet which we need for topmost level only (but for all Roots) 4450 atom *Walker = start; 4451 KeySet CompleteMolecule; 4452 while (Walker->next != end) { 4453 Walker = Walker->next; 4454 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 4455 } 4456 4457 // 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 4458 // each has to be split up. E.g. for the second level we have one from 5th, one from 4th, two from 3th (which in turn is one from 5th, one from 4th), 4459 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[]) 4460 // with the order along the cells as this: 5433222211111111 for BondOrder 5 needing 16=pow(2,5-1) cells (only we use bit-shifting which is faster) 4461 RootNr = 0; // counts through the roots in RootStack 4462 while ((RootNr < UpgradeCount) && (!RootStack.empty())) { 4463 RootKeyNr = RootStack.front(); 4464 RootStack.pop_front(); 4465 Walker = FindAtom(RootKeyNr); 4466 // check cyclic lengths 4467 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 4468 // *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; 4469 //} else 4470 { 4471 // increase adaptive order by one 4472 Walker->GetTrueFather()->AdaptiveOrder++; 4473 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 4474 4475 // initialise Order-dependent entries of UniqueFragments structure 4476 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4477 FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount"); 4478 for (int i=Order;i--;) { 4479 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 4480 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 4481 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4482 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 4483 FragmentSearch.BondsPerSPCount[i] = 0; 4484 } 4485 4486 // allocate memory for all lower level orders in this 1D-array of ptrs 4487 NumLevels = 1 << (Order-1); // (int)pow(2,Order); 4488 FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 4489 for (int i=0;i<NumLevels;i++) 4490 FragmentLowerOrdersList[RootNr][i] = NULL; 4491 4492 // create top order where nothing is reduced 4493 *out << Verbose(0) << "==============================================================================================================" << endl; 4494 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 4495 4496 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 4497 FragmentLowerOrdersList[RootNr][0] = new Graph; 4498 FragmentSearch.TEFactor = 1.; 4499 FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0]; // set to insertion graph 4500 FragmentSearch.Root = Walker; 4501 NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule); 4502 *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 4503 if (NumMoleculesOfOrder[RootNr] != 0) { 4504 NumMolecules = 0; 4505 4506 // we don't have to dive into suborders! These keysets are all already created on lower orders! 4507 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 4508 4509 // if ((NumLevels >> 1) > 0) { 4510 // // create lower order fragments 4511 // *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl; 4512 // Order = Walker->AdaptiveOrder; 4513 // 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) 4514 // // step down to next order at (virtual) boundary of powers of 2 in array 4515 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4516 // Order--; 4517 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; 4518 // for (int SubOrder=Order-1;SubOrder>0;SubOrder--) { 4519 // int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1))); 4520 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 4521 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 4523 4522 // 4524 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules4525 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl;4526 // //NumMolecules = 0;4527 // FragmentLowerOrdersList[RootNr][dest] = new Graph;4528 // for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) {4529 // for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {4530 // Graph TempFragmentList;4531 // FragmentSearch.TEFactor = -(*runner).second.second;4532 // FragmentSearch.Leaflet = &TempFragmentList;// set to insertion graph4533 // FragmentSearch.Root = FindAtom(*sprinter);4534 // NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first);4535 // // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest]4536 // *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl;4537 // InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules);4538 // }4539 // }4540 // *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl;4541 // }4542 // }4543 // }4544 } else {4545 Walker->GetTrueFather()->MaxOrder = true;4546 // *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl;4547 }4548 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder4549 //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules;4550 TotalNumMolecules += NumMoleculesOfOrder[RootNr];4551 // *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl;4552 RootStack.push_back(RootKeyNr); // put back on stack4553 RootNr++;4554 4555 // free Order-dependent entries of UniqueFragments structure for next loop cycle4556 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount");4557 for (int i=Order;i--;) {4558 delete(FragmentSearch.BondsPerSPList[2*i]);4559 delete(FragmentSearch.BondsPerSPList[2*i+1]);4560 }4561 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList");4562 }4563 }4564 *out << Verbose(0) << "==============================================================================================================" << endl;4565 *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl;4566 *out << Verbose(0) << "==============================================================================================================" << endl;4567 4568 // cleanup FragmentSearch structure4569 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList");4570 delete(FragmentSearch.FragmentSet);4571 4572 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein)4573 // 54332222111111114574 // 432211114575 // 32114576 // 214577 // 14578 4579 // Subsequently, we combine all into a single list (FragmentList)4580 4581 *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl;4582 if (FragmentList == NULL) {4583 FragmentList = new Graph;4584 counter = 0;4585 } else {4586 counter = FragmentList->size();4587 }4588 RootNr = 0;4589 while (!RootStack.empty()) {4590 RootKeyNr = RootStack.front();4591 RootStack.pop_front();4592 Walker = FindAtom(RootKeyNr);4593 NumLevels = 1 << (Walker->AdaptiveOrder - 1);4594 for(int i=0;i<NumLevels;i++) {4595 if (FragmentLowerOrdersList[RootNr][i] != NULL) {4596 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter);4597 delete(FragmentLowerOrdersList[RootNr][i]);4598 }4599 }4600 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");4601 RootNr++;4602 }4603 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");4604 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");4605 4606 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl;4523 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 4524 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; 4525 // //NumMolecules = 0; 4526 // FragmentLowerOrdersList[RootNr][dest] = new Graph; 4527 // for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) { 4528 // for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 4529 // Graph TempFragmentList; 4530 // FragmentSearch.TEFactor = -(*runner).second.second; 4531 // FragmentSearch.Leaflet = &TempFragmentList; // set to insertion graph 4532 // FragmentSearch.Root = FindAtom(*sprinter); 4533 // NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first); 4534 // // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest] 4535 // *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl; 4536 // InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules); 4537 // } 4538 // } 4539 // *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl; 4540 // } 4541 // } 4542 // } 4543 } else { 4544 Walker->GetTrueFather()->MaxOrder = true; 4545 // *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl; 4546 } 4547 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder 4548 //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules; 4549 TotalNumMolecules += NumMoleculesOfOrder[RootNr]; 4550 // *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 4551 RootStack.push_back(RootKeyNr); // put back on stack 4552 RootNr++; 4553 4554 // free Order-dependent entries of UniqueFragments structure for next loop cycle 4555 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); 4556 for (int i=Order;i--;) { 4557 delete(FragmentSearch.BondsPerSPList[2*i]); 4558 delete(FragmentSearch.BondsPerSPList[2*i+1]); 4559 } 4560 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4561 } 4562 } 4563 *out << Verbose(0) << "==============================================================================================================" << endl; 4564 *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl; 4565 *out << Verbose(0) << "==============================================================================================================" << endl; 4566 4567 // cleanup FragmentSearch structure 4568 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 4569 delete(FragmentSearch.FragmentSet); 4570 4571 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4572 // 5433222211111111 4573 // 43221111 4574 // 3211 4575 // 21 4576 // 1 4577 4578 // Subsequently, we combine all into a single list (FragmentList) 4579 4580 *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl; 4581 if (FragmentList == NULL) { 4582 FragmentList = new Graph; 4583 counter = 0; 4584 } else { 4585 counter = FragmentList->size(); 4586 } 4587 RootNr = 0; 4588 while (!RootStack.empty()) { 4589 RootKeyNr = RootStack.front(); 4590 RootStack.pop_front(); 4591 Walker = FindAtom(RootKeyNr); 4592 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 4593 for(int i=0;i<NumLevels;i++) { 4594 if (FragmentLowerOrdersList[RootNr][i] != NULL) { 4595 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter); 4596 delete(FragmentLowerOrdersList[RootNr][i]); 4597 } 4598 } 4599 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 4600 RootNr++; 4601 } 4602 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4603 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4604 4605 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 4607 4606 }; 4608 4607 … … 4614 4613 inline int CompareDoubles (const void * a, const void * b) 4615 4614 { 4616 if (*(double *)a > *(double *)b)4617 return -1;4618 else if (*(double *)a < *(double *)b)4619 return 1;4620 else4621 return 0;4615 if (*(double *)a > *(double *)b) 4616 return -1; 4617 else if (*(double *)a < *(double *)b) 4618 return 1; 4619 else 4620 return 0; 4622 4621 }; 4623 4622 … … 4630 4629 int * molecule::IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold) 4631 4630 { 4632 int flag;4633 double *Distances = NULL, *OtherDistances = NULL;4634 Vector CenterOfGravity, OtherCenterOfGravity;4635 size_t *PermMap = NULL, *OtherPermMap = NULL;4636 int *PermutationMap = NULL;4637 atom *Walker = NULL;4638 bool result = true; // status of comparison4639 4640 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl;4641 /// first count both their atoms and elements and update lists thereby ...4642 //*out << Verbose(0) << "Counting atoms, updating list" << endl;4643 CountAtoms(out);4644 OtherMolecule->CountAtoms(out);4645 CountElements();4646 OtherMolecule->CountElements();4647 4648 /// ... and compare:4649 /// -# AtomCount4650 if (result) {4651 if (AtomCount != OtherMolecule->AtomCount) {4652 *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;4653 result = false;4654 } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;4655 }4656 /// -# ElementCount4657 if (result) {4658 if (ElementCount != OtherMolecule->ElementCount) {4659 *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;4660 result = false;4661 } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;4662 }4663 /// -# ElementsInMolecule4664 if (result) {4665 for (flag=MAX_ELEMENTS;flag--;) {4666 //*out << Verbose(5) << "Element " <<flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;4667 if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag])4668 break;4669 }4670 if (flag < MAX_ELEMENTS) {4671 *out << Verbose(4) << "ElementsInMolecule don't match." << endl;4672 result = false;4673 } else *out << Verbose(4) << "ElementsInMolecule match." << endl;4674 }4675 /// then determine and compare center of gravity for each molecule ...4676 if (result) {4677 *out << Verbose(5) << "Calculating Centers of Gravity" << endl;4678 DetermineCenter(CenterOfGravity);4679 OtherMolecule->DetermineCenter(OtherCenterOfGravity);4680 *out << Verbose(5) << "Center of Gravity: ";4681 CenterOfGravity.Output(out);4682 *out << endl << Verbose(5) << "Other Center of Gravity: ";4683 OtherCenterOfGravity.Output(out);4684 *out << endl;4685 if (CenterOfGravity.Distance(&OtherCenterOfGravity) >threshold) {4686 *out << Verbose(4) << "Centers of gravity don't match." << endl;4687 result = false;4688 }4689 }4690 4691 /// ... then make a list with the euclidian distance to this center for each atom of both molecules4692 if (result) {4693 *out << Verbose(5) << "Calculating distances" << endl;4694 Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances");4695 OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances");4696 Walker = start;4697 while (Walker->next != end) {4698 Walker = Walker->next;4699 Distances[Walker->nr] = CenterOfGravity.Distance(&Walker->x);4700 }4701 Walker = OtherMolecule->start;4702 while (Walker->next != OtherMolecule->end) {4703 Walker = Walker->next;4704 OtherDistances[Walker->nr] = OtherCenterOfGravity.Distance(&Walker->x);4705 }4706 4707 /// ... sort each list (using heapsort (o(N log N)) from GSL)4708 *out << Verbose(5) << "Sorting distances" << endl;4709 PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap");4710 OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap");4711 gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles);4712 gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles);4713 PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap");4714 *out << Verbose(5) << "Combining Permutation Maps" << endl;4715 for(int i=AtomCount;i--;)4716 PermutationMap[PermMap[i]] = (int) OtherPermMap[i];4717 4718 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all4719 *out << Verbose(4) << "Comparing distances" << endl;4720 flag = 0;4721 for (int i=0;i<AtomCount;i++) {4722 *out << Verbose(5) << "Distances: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<threshold << endl;4723 if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) >threshold)4724 flag = 1;4725 }4726 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap");4727 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap");4728 4729 /// free memory4730 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances");4731 Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances");4732 if (flag) { // if not equal4733 Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap");4734 result = false;4735 }4736 }4737 /// return pointer to map if all distances were below \a threshold4738 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl;4739 if (result) {4740 *out << Verbose(3) << "Result: Equal." << endl;4741 return PermutationMap;4742 } else {4743 *out << Verbose(3) << "Result: Not equal." << endl;4744 return NULL;4745 }4631 int flag; 4632 double *Distances = NULL, *OtherDistances = NULL; 4633 Vector CenterOfGravity, OtherCenterOfGravity; 4634 size_t *PermMap = NULL, *OtherPermMap = NULL; 4635 int *PermutationMap = NULL; 4636 atom *Walker = NULL; 4637 bool result = true; // status of comparison 4638 4639 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4640 /// first count both their atoms and elements and update lists thereby ... 4641 //*out << Verbose(0) << "Counting atoms, updating list" << endl; 4642 CountAtoms(out); 4643 OtherMolecule->CountAtoms(out); 4644 CountElements(); 4645 OtherMolecule->CountElements(); 4646 4647 /// ... and compare: 4648 /// -# AtomCount 4649 if (result) { 4650 if (AtomCount != OtherMolecule->AtomCount) { 4651 *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl; 4652 result = false; 4653 } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl; 4654 } 4655 /// -# ElementCount 4656 if (result) { 4657 if (ElementCount != OtherMolecule->ElementCount) { 4658 *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl; 4659 result = false; 4660 } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl; 4661 } 4662 /// -# ElementsInMolecule 4663 if (result) { 4664 for (flag=MAX_ELEMENTS;flag--;) { 4665 //*out << Verbose(5) << "Element " << flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl; 4666 if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag]) 4667 break; 4668 } 4669 if (flag < MAX_ELEMENTS) { 4670 *out << Verbose(4) << "ElementsInMolecule don't match." << endl; 4671 result = false; 4672 } else *out << Verbose(4) << "ElementsInMolecule match." << endl; 4673 } 4674 /// then determine and compare center of gravity for each molecule ... 4675 if (result) { 4676 *out << Verbose(5) << "Calculating Centers of Gravity" << endl; 4677 DetermineCenter(CenterOfGravity); 4678 OtherMolecule->DetermineCenter(OtherCenterOfGravity); 4679 *out << Verbose(5) << "Center of Gravity: "; 4680 CenterOfGravity.Output(out); 4681 *out << endl << Verbose(5) << "Other Center of Gravity: "; 4682 OtherCenterOfGravity.Output(out); 4683 *out << endl; 4684 if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) { 4685 *out << Verbose(4) << "Centers of gravity don't match." << endl; 4686 result = false; 4687 } 4688 } 4689 4690 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 4691 if (result) { 4692 *out << Verbose(5) << "Calculating distances" << endl; 4693 Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances"); 4694 OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances"); 4695 Walker = start; 4696 while (Walker->next != end) { 4697 Walker = Walker->next; 4698 Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x); 4699 } 4700 Walker = OtherMolecule->start; 4701 while (Walker->next != OtherMolecule->end) { 4702 Walker = Walker->next; 4703 OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x); 4704 } 4705 4706 /// ... sort each list (using heapsort (o(N log N)) from GSL) 4707 *out << Verbose(5) << "Sorting distances" << endl; 4708 PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap"); 4709 OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4710 gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles); 4711 gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles); 4712 PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap"); 4713 *out << Verbose(5) << "Combining Permutation Maps" << endl; 4714 for(int i=AtomCount;i--;) 4715 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 4716 4717 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 4718 *out << Verbose(4) << "Comparing distances" << endl; 4719 flag = 0; 4720 for (int i=0;i<AtomCount;i++) { 4721 *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " << threshold << endl; 4722 if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold) 4723 flag = 1; 4724 } 4725 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 4726 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4727 4728 /// free memory 4729 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); 4730 Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances"); 4731 if (flag) { // if not equal 4732 Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap"); 4733 result = false; 4734 } 4735 } 4736 /// return pointer to map if all distances were below \a threshold 4737 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; 4738 if (result) { 4739 *out << Verbose(3) << "Result: Equal." << endl; 4740 return PermutationMap; 4741 } else { 4742 *out << Verbose(3) << "Result: Not equal." << endl; 4743 return NULL; 4744 } 4746 4745 }; 4747 4746 … … 4755 4754 int * molecule::GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule) 4756 4755 { 4757 atom *Walker = NULL, *OtherWalker = NULL;4758 *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl;4759 int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap");//Calloc4760 for (int i=AtomCount;i--;)4761 AtomicMap[i] = -1;4762 if (OtherMolecule == this) {// same molecule4763 for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence4764 AtomicMap[i] = i;4765 *out << Verbose(4) << "Map is trivial." << endl;4766 } else {4767 *out << Verbose(4) << "Map is ";4768 Walker = start;4769 while (Walker->next != end) {4770 Walker = Walker->next;4771 if (Walker->father == NULL) {4772 AtomicMap[Walker->nr] = -2;4773 } else {4774 OtherWalker = OtherMolecule->start;4775 while (OtherWalker->next != OtherMolecule->end) {4776 OtherWalker = OtherWalker->next;4777 //for (int i=0;i<AtomCount;i++) { // search atom4778 //for (int j=0;j<OtherMolecule->AtomCount;j++) {4779 //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl;4780 if (Walker->father == OtherWalker)4781 AtomicMap[Walker->nr] = OtherWalker->nr;4782 }4783 }4784 *out << AtomicMap[Walker->nr] << "\t";4785 }4786 *out << endl;4787 }4788 *out << Verbose(3) << "End of GetFatherAtomicMap." << endl;4789 return AtomicMap;4756 atom *Walker = NULL, *OtherWalker = NULL; 4757 *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl; 4758 int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap"); //Calloc 4759 for (int i=AtomCount;i--;) 4760 AtomicMap[i] = -1; 4761 if (OtherMolecule == this) { // same molecule 4762 for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence 4763 AtomicMap[i] = i; 4764 *out << Verbose(4) << "Map is trivial." << endl; 4765 } else { 4766 *out << Verbose(4) << "Map is "; 4767 Walker = start; 4768 while (Walker->next != end) { 4769 Walker = Walker->next; 4770 if (Walker->father == NULL) { 4771 AtomicMap[Walker->nr] = -2; 4772 } else { 4773 OtherWalker = OtherMolecule->start; 4774 while (OtherWalker->next != OtherMolecule->end) { 4775 OtherWalker = OtherWalker->next; 4776 //for (int i=0;i<AtomCount;i++) { // search atom 4777 //for (int j=0;j<OtherMolecule->AtomCount;j++) { 4778 //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl; 4779 if (Walker->father == OtherWalker) 4780 AtomicMap[Walker->nr] = OtherWalker->nr; 4781 } 4782 } 4783 *out << AtomicMap[Walker->nr] << "\t"; 4784 } 4785 *out << endl; 4786 } 4787 *out << Verbose(3) << "End of GetFatherAtomicMap." << endl; 4788 return AtomicMap; 4790 4789 }; 4791 4790 … … 4801 4800 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 4802 4801 { 4803 double temperature;4804 atom *Walker = NULL;4805 // test stream4806 if (output == NULL)4807 return false;4808 else4809 *output << "# Step Temperature [K] Temperature [a.u.]" << endl;4810 for (int step=startstep;step < endstep; step++) { // loop over all time steps4811 temperature = 0.;4812 Walker = start;4813 while (Walker->next != end) {4814 Walker = Walker->next;4815 for (int i=NDIM;i--;)4816 temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i];4817 }4818 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl;4819 }4820 return true;4821 }; 4802 double temperature; 4803 atom *Walker = NULL; 4804 // test stream 4805 if (output == NULL) 4806 return false; 4807 else 4808 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 4809 for (int step=startstep;step < endstep; step++) { // loop over all time steps 4810 temperature = 0.; 4811 Walker = start; 4812 while (Walker->next != end) { 4813 Walker = Walker->next; 4814 for (int i=NDIM;i--;) 4815 temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i]; 4816 } 4817 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl; 4818 } 4819 return true; 4820 }; -
Property mode
changed from
-
src/molecules.hpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 60 60 #define LineMap map < int, class BoundaryLineSet * > 61 61 #define LinePair pair < int, class BoundaryLineSet * > 62 #define LineTestPair pair < Line Pair::iterator, bool >62 #define LineTestPair pair < LineMap::iterator, bool > 63 63 64 64 #define TriangleMap map < int, class BoundaryTriangleSet * > … … 73 73 struct KeyCompare 74 74 { 75 bool operator() (const KeySet SubgraphA, const KeySet SubgraphB) const;75 bool operator() (const KeySet SubgraphA, const KeySet SubgraphB) const; 76 76 }; 77 77 78 78 struct Trajectory 79 79 { 80 vector<Vector> R;//!< position vector81 vector<Vector> U;//!< velocity vector82 vector<Vector> F;//!< last force vector83 atom *ptr;//!< pointer to atom whose trajectory we contain84 }; 85 86 //bool operator < (KeySet SubgraphA, KeySet SubgraphB); //note: this declaration is important, otherwise normal < is used (producing wrong order)80 vector<Vector> R; //!< position vector 81 vector<Vector> U; //!< velocity vector 82 vector<Vector> F; //!< last force vector 83 atom *ptr; //!< pointer to atom whose trajectory we contain 84 }; 85 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 Graph88 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 … … 94 94 95 95 // some algebraic matrix stuff 96 #define RDET3(a) ((a)[0]*(a)[4]*(a)[8] + (a)[3]*(a)[7]*(a)[2] + (a)[6]*(a)[1]*(a)[5] - (a)[2]*(a)[4]*(a)[6] - (a)[5]*(a)[7]*(a)[0] - (a)[8]*(a)[1]*(a)[3]) //!< hard-coded determinant of a 3x3 matrix97 #define RDET2(a0,a1,a2,a3) ((a0)*(a3)-(a1)*(a2)) //!< hard-coded determinant of a 2x2 matrix96 #define RDET3(a) ((a)[0]*(a)[4]*(a)[8] + (a)[3]*(a)[7]*(a)[2] + (a)[6]*(a)[1]*(a)[5] - (a)[2]*(a)[4]*(a)[6] - (a)[5]*(a)[7]*(a)[0] - (a)[8]*(a)[1]*(a)[3]) //!< hard-coded determinant of a 3x3 matrix 97 #define RDET2(a0,a1,a2,a3) ((a0)*(a3)-(a1)*(a2)) //!< hard-coded determinant of a 2x2 matrix 98 98 99 99 … … 101 101 */ 102 102 struct LSQ_params { 103 Vector **vectors;104 int num;103 Vector **vectors; 104 int num; 105 105 }; 106 106 … … 110 110 */ 111 111 struct lsq_params { 112 gsl_vector *x; 113 const molecule *mol; 114 element *type; 115 }; 116 117 112 gsl_vector *x; 113 const molecule *mol; 114 element *type; 115 }; 118 116 119 117 /** Single atom. … … 121 119 */ 122 120 class atom { 123 public:124 Vector x;//!< coordinate array of atom, giving position within cell125 Vector v;//!< velocity array of atom126 element *type;//!< pointing to element127 atom *previous; //!< previous atom in molecule list128 atom *next;//!< next atom in molecule list129 atom *father;//!< In many-body bond order fragmentations points to originating atom130 atom *Ancestor; //!< "Father" in Depth-First-Search131 char *Name; //!< unique name used during many-body bond-order fragmentation132 int FixedIon;//!< config variable that states whether forces act on the ion or not133 int *sort;//!< sort criteria134 int nr;//!< continuous, unique number135 int GraphNr;//!< unique number, given in DepthFirstSearchAnalysis()136 int *ComponentNr;//!< belongs to this nonseparable components, given in DepthFirstSearchAnalysis() (if more than one, then is SeparationVertex)137 int LowpointNr; //!< needed in DepthFirstSearchAnalysis() to detect nonseparable components, is the lowest possible number of an atom to reach via tree edges only followed by at most one back edge.138 bool SeparationVertex; //!< whether this atom separates off subsets of atoms or not, determined in DepthFirstSearchAnalysis()139 bool IsCyclic;//!< whether atom belong to as cycle or not, determined in DepthFirstSearchAnalysis()140 unsigned char AdaptiveOrder;//!< current present bond order at site (0 means "not set")141 bool MaxOrder;//!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not142 143 atom();144 ~atom();145 146 bool Output(int ElementNo, int AtomNo, ofstream *out) const;147 bool OutputXYZLine(ofstream *out) const;148 atom *GetTrueFather();149 bool Compare(atom &ptr);150 151 private:121 public: 122 Vector x; //!< coordinate array of atom, giving position within cell 123 Vector v; //!< velocity array of atom 124 element *type; //!< pointing to element 125 atom *previous; //!< previous atom in molecule list 126 atom *next; //!< next atom in molecule list 127 atom *father; //!< In many-body bond order fragmentations points to originating atom 128 atom *Ancestor; //!< "Father" in Depth-First-Search 129 char *Name; //!< unique name used during many-body bond-order fragmentation 130 int FixedIon; //!< config variable that states whether forces act on the ion or not 131 int *sort; //!< sort criteria 132 int nr; //!< continuous, unique number 133 int GraphNr; //!< unique number, given in DepthFirstSearchAnalysis() 134 int *ComponentNr;//!< belongs to this nonseparable components, given in DepthFirstSearchAnalysis() (if more than one, then is SeparationVertex) 135 int LowpointNr; //!< needed in DepthFirstSearchAnalysis() to detect nonseparable components, is the lowest possible number of an atom to reach via tree edges only followed by at most one back edge. 136 bool SeparationVertex; //!< whether this atom separates off subsets of atoms or not, determined in DepthFirstSearchAnalysis() 137 bool IsCyclic; //!< whether atom belong to as cycle or not, determined in DepthFirstSearchAnalysis() 138 unsigned char AdaptiveOrder; //!< current present bond order at site (0 means "not set") 139 bool MaxOrder; //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not 140 141 atom(); 142 ~atom(); 143 144 bool Output(int ElementNo, int AtomNo, ofstream *out) const; 145 bool OutputXYZLine(ofstream *out) const; 146 atom *GetTrueFather(); 147 bool Compare(atom &ptr); 148 149 private: 152 150 }; 153 151 … … 160 158 */ 161 159 class bond { 162 public:163 atom *leftatom; //!< first bond partner164 atom *rightatom; //!< second bond partner165 bond *previous; //!< previous atom in molecule list166 bond *next;//!< next atom in molecule list167 int HydrogenBond; //!< Number of hydrogen atoms in the bond168 int BondDegree; //!< single, double, triple, ... bond169 int nr;//!< unique number in a molecule, updated by molecule::CreateAdjacencyList()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 edge172 173 atom * GetOtherAtom(atom *Atom) const;174 bond * GetFirstBond();175 bond * GetLastBond();176 177 bool MarkUsed(enum Shading color);178 enum Shading IsUsed();179 void ResetUsed();180 bool Contains(const atom *ptr);181 bool Contains(const int nr);182 183 bond();184 bond(atom *left, atom *right);185 bond(atom *left, atom *right, int degree);186 bond(atom *left, atom *right, int degree, int number);187 ~bond();188 189 private:190 enum Shading Used;//!< marker in depth-first search, DepthFirstSearchAnalysis()160 public: 161 atom *leftatom; //!< first bond partner 162 atom *rightatom; //!< second bond partner 163 bond *previous; //!< previous atom in molecule list 164 bond *next; //!< next atom in molecule list 165 int HydrogenBond; //!< Number of hydrogen atoms in the bond 166 int BondDegree; //!< single, double, triple, ... bond 167 int nr; //!< unique number in a molecule, updated by molecule::CreateAdjacencyList() 168 bool Cyclic; //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis() 169 enum EdgeType Type;//!< whether this is a tree or back edge 170 171 atom * GetOtherAtom(atom *Atom) const; 172 bond * GetFirstBond(); 173 bond * GetLastBond(); 174 175 bool MarkUsed(enum Shading color); 176 enum Shading IsUsed(); 177 void ResetUsed(); 178 bool Contains(const atom *ptr); 179 bool Contains(const int nr); 180 181 bond(); 182 bond(atom *left, atom *right); 183 bond(atom *left, atom *right, int degree); 184 bond(atom *left, atom *right, int degree, int number); 185 ~bond(); 186 187 private: 188 enum Shading Used; //!< marker in depth-first search, DepthFirstSearchAnalysis() 191 189 }; 192 190 … … 199 197 */ 200 198 class molecule { 201 public:202 double cell_size[6];//!< cell size203 periodentafel *elemente; //!< periodic table with each element204 atom *start;//!< start of atom list205 atom *end;//!< end of atom list206 bond *first;//!< start of bond list207 bond *last;//!< end of bond list208 bond ***ListOfBondsPerAtom; //!< pointer list for each atom and each bond it has209 map<atom *, struct Trajectory> Trajectories; //!< contains old trajectory points210 int MDSteps;//!< The number of MD steps in Trajectories211 int *NumberOfBondsPerAtom;//!< Number of Bonds each atom has212 int AtomCount; //!< number of atoms, brought up-to-date by CountAtoms()213 int BondCount; //!< number of atoms, brought up-to-date by CountBonds()214 int ElementCount;//!< how many unique elements are therein215 int ElementsInMolecule[MAX_ELEMENTS]; //!< list whether element (sorted by atomic number) is alread present or not216 int NoNonHydrogen; //!< number of non-hydrogen atoms in molecule217 int NoNonBonds;//!< number of non-hydrogen bonds in molecule218 int NoCyclicBonds;//!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis()219 double BondDistance;//!< typical bond distance used in CreateAdjacencyList() and furtheron220 221 molecule(periodentafel *teil);222 ~molecule();223 224 /// remove atoms from molecule.225 bool AddAtom(atom *pointer);226 bool RemoveAtom(atom *pointer);227 bool CleanupMolecule();228 229 /// Add/remove atoms to/from molecule.230 atom * AddCopyAtom(atom *pointer);231 bool AddXYZFile(string filename);232 bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem);233 bond * AddBond(atom *first, atom *second, int degree);234 bool RemoveBond(bond *pointer);235 bool RemoveBonds(atom *BondPartner);236 237 /// Find atoms.238 atom * FindAtom(int Nr) const;239 atom * AskAtom(string text);240 241 /// Count and change present atoms' coordination.242 void CountAtoms(ofstream *out);243 void CountElements();244 void CalculateOrbitals(class config &configuration);245 bool CenterInBox(ofstream *out, Vector *BoxLengths);246 void CenterEdge(ofstream *out, Vector *max);247 void CenterOrigin(ofstream *out, Vector *max);248 void CenterGravity(ofstream *out, Vector *max);249 void Translate(const Vector *x);250 void Mirror(const Vector *x);251 void Align(Vector *n);252 void Scale(double **factor);253 void DetermineCenter(Vector ¢er);254 Vector * DetermineCenterOfGravity(ofstream *out);255 Vector * DetermineCenterOfAll(ofstream *out);256 void SetBoxDimension(Vector *dim);257 double * ReturnFullMatrixforSymmetric(double *cell_size);258 void ScanForPeriodicCorrection(ofstream *out);199 public: 200 double cell_size[6];//!< cell size 201 periodentafel *elemente; //!< periodic table with each element 202 atom *start; //!< start of atom list 203 atom *end; //!< end of atom list 204 bond *first; //!< start of bond list 205 bond *last; //!< end of bond list 206 bond ***ListOfBondsPerAtom; //!< pointer list for each atom and each bond it has 207 map<atom *, struct Trajectory> Trajectories; //!< contains old trajectory points 208 int MDSteps; //!< The number of MD steps in Trajectories 209 int *NumberOfBondsPerAtom; //!< Number of Bonds each atom has 210 int AtomCount; //!< number of atoms, brought up-to-date by CountAtoms() 211 int BondCount; //!< number of atoms, brought up-to-date by CountBonds() 212 int ElementCount; //!< how many unique elements are therein 213 int ElementsInMolecule[MAX_ELEMENTS]; //!< list whether element (sorted by atomic number) is alread present or not 214 int NoNonHydrogen; //!< number of non-hydrogen atoms in molecule 215 int NoNonBonds; //!< number of non-hydrogen bonds in molecule 216 int NoCyclicBonds; //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis() 217 double BondDistance; //!< typical bond distance used in CreateAdjacencyList() and furtheron 218 219 molecule(periodentafel *teil); 220 ~molecule(); 221 222 /// remove atoms from molecule. 223 bool AddAtom(atom *pointer); 224 bool RemoveAtom(atom *pointer); 225 bool CleanupMolecule(); 226 227 /// Add/remove atoms to/from molecule. 228 atom * AddCopyAtom(atom *pointer); 229 bool AddXYZFile(string filename); 230 bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem); 231 bond * AddBond(atom *first, atom *second, int degree); 232 bool RemoveBond(bond *pointer); 233 bool RemoveBonds(atom *BondPartner); 234 235 /// Find atoms. 236 atom * FindAtom(int Nr) const; 237 atom * AskAtom(string text); 238 239 /// Count and change present atoms' coordination. 240 void CountAtoms(ofstream *out); 241 void CountElements(); 242 void CalculateOrbitals(class config &configuration); 243 bool CenterInBox(ofstream *out, Vector *BoxLengths); 244 void CenterEdge(ofstream *out, Vector *max); 245 void CenterOrigin(ofstream *out, Vector *max); 246 void CenterGravity(ofstream *out, Vector *max); 247 void Translate(const Vector *x); 248 void Mirror(const Vector *x); 249 void Align(Vector *n); 250 void Scale(double **factor); 251 void DetermineCenter(Vector ¢er); 252 Vector * DetermineCenterOfGravity(ofstream *out); 253 Vector * DetermineCenterOfAll(ofstream *out); 254 void SetBoxDimension(Vector *dim); 255 double * ReturnFullMatrixforSymmetric(double *cell_size); 256 void ScanForPeriodicCorrection(ofstream *out); 259 257 void PrincipalAxisSystem(ofstream *out, bool DoRotate); 260 258 double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem); 261 259 bool VerletForceIntegration(char *file, double delta_t, bool IsAngstroem); 262 260 263 bool CheckBounds(const Vector *x) const;264 void GetAlignvector(struct lsq_params * par) const;265 266 /// Initialising routines in fragmentation267 void CreateAdjacencyList2(ofstream *out, ifstream *output);268 void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem);269 void CreateListOfBondsPerAtom(ofstream *out);270 271 // Graph analysis272 MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack);273 void CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *BackEdgeStack, int *&MinimumRingSize);274 bool PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack);275 bond * FindNextUnused(atom *vertex);276 void SetNextComponentNumber(atom *vertex, int nr);277 void InitComponentNumbers();278 void OutputComponentNumber(ofstream *out, atom *vertex);279 void ResetAllBondsToUnused();280 void ResetAllAtomNumbers();281 int CountCyclicBonds(ofstream *out);282 bool CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment);283 string GetColor(enum Shading color);284 285 molecule *CopyMolecule();286 287 /// Fragment molecule by two different approaches:288 int FragmentMolecule(ofstream *out, int Order, config *configuration);289 bool CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path = NULL);290 bool StoreAdjacencyToFile(ofstream *out, char *path);291 bool CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms);292 bool ParseOrderAtSiteFromFile(ofstream *out, char *path);293 bool StoreOrderAtSiteFile(ofstream *out, char *path);294 bool ParseKeySetFile(ofstream *out, char *filename, Graph *&FragmentList);295 bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path);296 bool StoreForcesFile(ofstream *out, MoleculeListClass *BondFragments, char *path, int *SortIndex);297 bool CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex);298 bool ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet);299 void BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem);300 /// -# BOSSANOVA301 void FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize);261 bool CheckBounds(const Vector *x) const; 262 void GetAlignvector(struct lsq_params * par) const; 263 264 /// Initialising routines in fragmentation 265 void CreateAdjacencyList2(ofstream *out, ifstream *output); 266 void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem); 267 void CreateListOfBondsPerAtom(ofstream *out); 268 269 // Graph analysis 270 MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack); 271 void CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *BackEdgeStack, int *&MinimumRingSize); 272 bool PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack); 273 bond * FindNextUnused(atom *vertex); 274 void SetNextComponentNumber(atom *vertex, int nr); 275 void InitComponentNumbers(); 276 void OutputComponentNumber(ofstream *out, atom *vertex); 277 void ResetAllBondsToUnused(); 278 void ResetAllAtomNumbers(); 279 int CountCyclicBonds(ofstream *out); 280 bool CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment); 281 string GetColor(enum Shading color); 282 283 molecule *CopyMolecule(); 284 285 /// Fragment molecule by two different approaches: 286 int FragmentMolecule(ofstream *out, int Order, config *configuration); 287 bool CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path = NULL); 288 bool StoreAdjacencyToFile(ofstream *out, char *path); 289 bool CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms); 290 bool ParseOrderAtSiteFromFile(ofstream *out, char *path); 291 bool StoreOrderAtSiteFile(ofstream *out, char *path); 292 bool ParseKeySetFile(ofstream *out, char *filename, Graph *&FragmentList); 293 bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path); 294 bool StoreForcesFile(ofstream *out, MoleculeListClass *BondFragments, char *path, int *SortIndex); 295 bool CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex); 296 bool ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet); 297 void BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem); 298 /// -# BOSSANOVA 299 void FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize); 302 300 int PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet); 303 bool BuildInducedSubgraph(ofstream *out, const molecule *Father);304 molecule * StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem);305 void SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder);306 int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList);307 int GuesstimateFragmentCount(ofstream *out, int order);308 309 // Recognize doubly appearing molecules in a list of them310 int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold);311 int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule);312 313 // Output routines.314 bool Output(ofstream *out);315 bool OutputTrajectories(ofstream *out);316 void OutputListOfBonds(ofstream *out) const;317 bool OutputXYZ(ofstream *out) const;318 bool OutputTrajectoriesXYZ(ofstream *out);319 bool Checkout(ofstream *out) const;320 bool OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output);321 322 private:323 int last_atom;//!< number given to last atom301 bool BuildInducedSubgraph(ofstream *out, const molecule *Father); 302 molecule * StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem); 303 void SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder); 304 int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList); 305 int GuesstimateFragmentCount(ofstream *out, int order); 306 307 // Recognize doubly appearing molecules in a list of them 308 int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold); 309 int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule); 310 311 // Output routines. 312 bool Output(ofstream *out); 313 bool OutputTrajectories(ofstream *out); 314 void OutputListOfBonds(ofstream *out) const; 315 bool OutputXYZ(ofstream *out) const; 316 bool OutputTrajectoriesXYZ(ofstream *out); 317 bool Checkout(ofstream *out) const; 318 bool OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output); 319 320 private: 321 int last_atom; //!< number given to last atom 324 322 }; 325 323 … … 327 325 */ 328 326 class MoleculeListClass { 329 public:330 molecule **ListOfMolecules;//!< pointer list of fragment molecules to check for equality331 int NumberOfMolecules;//!< Number of entries in \a **FragmentList and of to be returned one.332 int NumberOfTopAtoms;//!< Number of atoms in the molecule from which all fragments originate333 334 MoleculeListClass();335 MoleculeListClass(int Num, int NumAtoms);336 ~MoleculeListClass();337 338 /// Output configs.339 bool AddHydrogenCorrection(ofstream *out, char *path);340 bool StoreForcesFile(ofstream *out, char *path, int *SortIndex);341 bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex);342 void Output(ofstream *out);343 344 private:327 public: 328 molecule **ListOfMolecules; //!< pointer list of fragment molecules to check for equality 329 int NumberOfMolecules; //!< Number of entries in \a **FragmentList and of to be returned one. 330 int NumberOfTopAtoms; //!< Number of atoms in the molecule from which all fragments originate 331 332 MoleculeListClass(); 333 MoleculeListClass(int Num, int NumAtoms); 334 ~MoleculeListClass(); 335 336 /// Output configs. 337 bool AddHydrogenCorrection(ofstream *out, char *path); 338 bool StoreForcesFile(ofstream *out, char *path, int *SortIndex); 339 bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex); 340 void Output(ofstream *out); 341 342 private: 345 343 }; 346 344 … … 350 348 */ 351 349 class MoleculeLeafClass { 352 public:353 molecule *Leaf;//!< molecule of this leaf354 //MoleculeLeafClass *UpLeaf;//!< Leaf one level up355 //MoleculeLeafClass *DownLeaf;//!< First leaf one level down356 MoleculeLeafClass *previous;//!< Previous leaf on this level357 MoleculeLeafClass *next;//!< Next leaf on this level358 359 //MoleculeLeafClass(MoleculeLeafClass *Up, MoleculeLeafClass *Previous);360 MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf);361 ~MoleculeLeafClass();362 363 bool AddLeaf(molecule *ptr, MoleculeLeafClass *Previous);364 bool FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList = false);365 bool FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter);366 bool AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList = false);367 bool FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList);368 void TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph);369 int Count() const;350 public: 351 molecule *Leaf; //!< molecule of this leaf 352 //MoleculeLeafClass *UpLeaf; //!< Leaf one level up 353 //MoleculeLeafClass *DownLeaf; //!< First leaf one level down 354 MoleculeLeafClass *previous; //!< Previous leaf on this level 355 MoleculeLeafClass *next; //!< Next leaf on this level 356 357 //MoleculeLeafClass(MoleculeLeafClass *Up, MoleculeLeafClass *Previous); 358 MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf); 359 ~MoleculeLeafClass(); 360 361 bool AddLeaf(molecule *ptr, MoleculeLeafClass *Previous); 362 bool FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList = false); 363 bool FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter); 364 bool AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList = false); 365 bool FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList); 366 void TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph); 367 int Count() const; 370 368 }; 371 369 … … 374 372 */ 375 373 class config { 376 public:377 int PsiType;378 int MaxPsiDouble;379 int PsiMaxNoUp;380 int PsiMaxNoDown;381 int MaxMinStopStep;382 int InitMaxMinStopStep;383 int ProcPEGamma;384 int ProcPEPsi;385 char *configpath;386 char *configname;387 bool FastParsing;388 double Deltat;389 390 private:391 char *mainname;392 char *defaultpath;393 char *pseudopotpath;394 395 int DoOutVis;396 int DoOutMes;397 int DoOutNICS;398 int DoOutOrbitals;399 int DoOutCurrent;400 int DoFullCurrent;401 int DoPerturbation;402 int DoWannier;403 int CommonWannier;404 double SawtoothStart;405 int VectorPlane;406 double VectorCut;407 int UseAddGramSch;408 int Seed;409 410 int MaxOuterStep;411 int OutVisStep;412 int OutSrcStep;413 double TargetTemp;414 int ScaleTempStep;415 int MaxPsiStep;416 double EpsWannier;417 418 int MaxMinStep;419 double RelEpsTotalEnergy;420 double RelEpsKineticEnergy;421 int MaxMinGapStopStep;422 int MaxInitMinStep;423 double InitRelEpsTotalEnergy;424 double InitRelEpsKineticEnergy;425 int InitMaxMinGapStopStep;426 427 //double BoxLength[NDIM*NDIM];428 429 double ECut;430 int MaxLevel;431 int RiemannTensor;432 int LevRFactor;433 int RiemannLevel;434 int Lev0Factor;435 int RTActualUse;436 int AddPsis;437 438 double RCut;439 int StructOpt;440 int IsAngstroem;441 int RelativeCoord;442 int MaxTypes;443 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);446 447 public:448 config();449 ~config();450 451 int TestSyntax(char *filename, periodentafel *periode, molecule *mol);452 void Load(char *filename, periodentafel *periode, molecule *mol);453 void LoadOld(char *filename, periodentafel *periode, molecule *mol);454 void RetrieveConfigPathAndName(string filename);455 bool Save(const char *filename, periodentafel *periode, molecule *mol) const;456 bool SaveMPQC(const char *filename, molecule *mol) const;457 void Edit(molecule *mol);458 bool GetIsAngstroem() const;459 char *GetDefaultPath() const;460 void SetDefaultPath(const char *path);374 public: 375 int PsiType; 376 int MaxPsiDouble; 377 int PsiMaxNoUp; 378 int PsiMaxNoDown; 379 int MaxMinStopStep; 380 int InitMaxMinStopStep; 381 int ProcPEGamma; 382 int ProcPEPsi; 383 char *configpath; 384 char *configname; 385 bool FastParsing; 386 double Deltat; 387 388 private: 389 char *mainname; 390 char *defaultpath; 391 char *pseudopotpath; 392 393 int DoOutVis; 394 int DoOutMes; 395 int DoOutNICS; 396 int DoOutOrbitals; 397 int DoOutCurrent; 398 int DoFullCurrent; 399 int DoPerturbation; 400 int DoWannier; 401 int CommonWannier; 402 double SawtoothStart; 403 int VectorPlane; 404 double VectorCut; 405 int UseAddGramSch; 406 int Seed; 407 408 int MaxOuterStep; 409 int OutVisStep; 410 int OutSrcStep; 411 double TargetTemp; 412 int ScaleTempStep; 413 int MaxPsiStep; 414 double EpsWannier; 415 416 int MaxMinStep; 417 double RelEpsTotalEnergy; 418 double RelEpsKineticEnergy; 419 int MaxMinGapStopStep; 420 int MaxInitMinStep; 421 double InitRelEpsTotalEnergy; 422 double InitRelEpsKineticEnergy; 423 int InitMaxMinGapStopStep; 424 425 //double BoxLength[NDIM*NDIM]; 426 427 double ECut; 428 int MaxLevel; 429 int RiemannTensor; 430 int LevRFactor; 431 int RiemannLevel; 432 int Lev0Factor; 433 int RTActualUse; 434 int AddPsis; 435 436 double RCut; 437 int StructOpt; 438 int IsAngstroem; 439 int RelativeCoord; 440 int MaxTypes; 441 442 443 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); 444 445 public: 446 config(); 447 ~config(); 448 449 int TestSyntax(char *filename, periodentafel *periode, molecule *mol); 450 void Load(char *filename, periodentafel *periode, molecule *mol); 451 void LoadOld(char *filename, periodentafel *periode, molecule *mol); 452 void RetrieveConfigPathAndName(string filename); 453 bool Save(const char *filename, periodentafel *periode, molecule *mol) const; 454 bool SaveMPQC(const char *filename, molecule *mol) const; 455 void Edit(molecule *mol); 456 bool GetIsAngstroem() const; 457 char *GetDefaultPath() const; 458 void SetDefaultPath(const char *path); 461 459 }; 462 460 -
Property mode
changed from
-
src/orbitals.db
-
Property mode
changed from
100644to100755
-
Property mode
changed from
-
src/parser.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 2 2 * 3 3 * Declarations of various class functions for the parsing of value files. 4 * 4 * 5 5 */ 6 6 7 7 // ======================================= INCLUDES ========================================== 8 8 9 #include "helpers.hpp" 9 #include "helpers.hpp" 10 10 #include "parser.hpp" 11 11 … … 24 24 bool FilePresent(const char *filename, bool test) 25 25 { 26 ifstream input;27 28 input.open(filename, ios::in);29 if (input == NULL) {30 if (!test)31 cout << endl << "Unable to open " << filename << ", is the directory correct?" << endl;32 return false;33 }34 input.close();35 return true;26 ifstream input; 27 28 input.open(filename, ios::in); 29 if (input == NULL) { 30 if (!test) 31 cout << endl << "Unable to open " << filename << ", is the directory correct?" << endl; 32 return false; 33 } 34 input.close(); 35 return true; 36 36 }; 37 37 … … 43 43 bool TestParams(int argc, char **argv) 44 44 { 45 ifstream input;46 stringstream line;47 48 line << argv[1] << FRAGMENTPREFIX << KEYSETFILE;49 return FilePresent(line.str().c_str(), false);45 ifstream input; 46 stringstream line; 47 48 line << argv[1] << FRAGMENTPREFIX << KEYSETFILE; 49 return FilePresent(line.str().c_str(), false); 50 50 }; 51 51 … … 55 55 */ 56 56 MatrixContainer::MatrixContainer() { 57 Indices = NULL;58 Header = (char *) Malloc(sizeof(char)*1023, "MatrixContainer::MatrixContainer: *Header");59 Matrix = (double ***) Malloc(sizeof(double **)*(1), "MatrixContainer::MatrixContainer: ***Matrix"); // one more each for the total molecule60 RowCounter = (int *) Malloc(sizeof(int)*(1), "MatrixContainer::MatrixContainer: *RowCounter");61 Matrix[0] = NULL;62 RowCounter[0] = -1;63 MatrixCounter = 0;64 ColumnCounter = 0;57 Indices = NULL; 58 Header = (char *) Malloc(sizeof(char)*1023, "MatrixContainer::MatrixContainer: *Header"); 59 Matrix = (double ***) Malloc(sizeof(double **)*(1), "MatrixContainer::MatrixContainer: ***Matrix"); // one more each for the total molecule 60 RowCounter = (int *) Malloc(sizeof(int)*(1), "MatrixContainer::MatrixContainer: *RowCounter"); 61 Matrix[0] = NULL; 62 RowCounter[0] = -1; 63 MatrixCounter = 0; 64 ColumnCounter = 0; 65 65 }; 66 66 … … 68 68 */ 69 69 MatrixContainer::~MatrixContainer() { 70 if (Matrix != NULL) {71 for(int i=MatrixCounter;i--;) {72 if (RowCounter != NULL) {73 for(int j=RowCounter[i]+1;j--;)74 Free((void **)&Matrix[i][j], "MatrixContainer::~MatrixContainer: *Matrix[][]");75 Free((void **)&Matrix[i], "MatrixContainer::~MatrixContainer: **Matrix[]");76 }77 }78 if ((RowCounter != NULL) && (Matrix[MatrixCounter] != NULL))79 for(int j=RowCounter[MatrixCounter]+1;j--;)80 Free((void **)&Matrix[MatrixCounter][j], "MatrixContainer::~MatrixContainer: *Matrix[MatrixCounter][]");81 if (MatrixCounter != 0)82 Free((void **)&Matrix[MatrixCounter], "MatrixContainer::~MatrixContainer: **Matrix[MatrixCounter]");83 Free((void **)&Matrix, "MatrixContainer::~MatrixContainer: ***Matrix");84 }85 if (Indices != NULL)86 for(int i=MatrixCounter+1;i--;) {87 Free((void **)&Indices[i], "MatrixContainer::~MatrixContainer: *Indices[]");88 }89 Free((void **)&Indices, "MatrixContainer::~MatrixContainer: **Indices"); 90 91 Free((void **)&Header, "MatrixContainer::~MatrixContainer: *Header");92 Free((void **)&RowCounter, "MatrixContainer::~MatrixContainer: *RowCounter");70 if (Matrix != NULL) { 71 for(int i=MatrixCounter;i--;) { 72 if (RowCounter != NULL) { 73 for(int j=RowCounter[i]+1;j--;) 74 Free((void **)&Matrix[i][j], "MatrixContainer::~MatrixContainer: *Matrix[][]"); 75 Free((void **)&Matrix[i], "MatrixContainer::~MatrixContainer: **Matrix[]"); 76 } 77 } 78 if ((RowCounter != NULL) && (Matrix[MatrixCounter] != NULL)) 79 for(int j=RowCounter[MatrixCounter]+1;j--;) 80 Free((void **)&Matrix[MatrixCounter][j], "MatrixContainer::~MatrixContainer: *Matrix[MatrixCounter][]"); 81 if (MatrixCounter != 0) 82 Free((void **)&Matrix[MatrixCounter], "MatrixContainer::~MatrixContainer: **Matrix[MatrixCounter]"); 83 Free((void **)&Matrix, "MatrixContainer::~MatrixContainer: ***Matrix"); 84 } 85 if (Indices != NULL) 86 for(int i=MatrixCounter+1;i--;) { 87 Free((void **)&Indices[i], "MatrixContainer::~MatrixContainer: *Indices[]"); 88 } 89 Free((void **)&Indices, "MatrixContainer::~MatrixContainer: **Indices"); 90 91 Free((void **)&Header, "MatrixContainer::~MatrixContainer: *Header"); 92 Free((void **)&RowCounter, "MatrixContainer::~MatrixContainer: *RowCounter"); 93 93 }; 94 94 95 95 96 96 /** Parsing a number of matrices. 97 * -# open the matrix file98 * -# skip some lines (\a skiplines)99 * -# scan header lines for number of columns100 * -# scan lines for number of rows101 * -# allocate matrix102 * -# loop over found column and row counts and parse in each entry97 * -# open the matrix file 98 * -# skip some lines (\a skiplines) 99 * -# scan header lines for number of columns 100 * -# scan lines for number of rows 101 * -# allocate matrix 102 * -# loop over found column and row counts and parse in each entry 103 103 * \param *name directory with files 104 104 * \param skiplines number of inital lines to skip 105 105 * \param skiplines number of inital columns to skip 106 106 * \param MatrixNr index number in Matrix array to parse into 107 * \return parsing successful 107 * \return parsing successful 108 108 */ 109 109 bool MatrixContainer::ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr) 110 110 { 111 ifstream input;112 stringstream line;113 string token;114 char filename[1023];115 116 input.open(name, ios::in);117 //cout << "Opening " << name << " ... "<< input << endl;118 if (input == NULL) {119 cerr << endl << "Unable to open " << name << ", is the directory correct?" << endl;120 return false;121 }122 123 // skip some initial lines124 for (int m=skiplines+1;m--;)125 input.getline(Header, 1023);126 127 // scan header for number of columns128 line.str(Header);129 for(int k=skipcolumns;k--;)130 line >> Header;131 //cout << line.str() << endl;132 ColumnCounter=0;133 while ( getline(line,token, '\t') ) {134 if (token.length() > 0)135 ColumnCounter++;136 }137 //cout << line.str() << endl;138 //cout << "ColumnCounter: " << ColumnCounter << "." << endl;139 if (ColumnCounter == 0)140 cerr << "ColumnCounter: " << ColumnCounter << " from file " << name << ", this is probably an error!" << endl;141 142 // scan rest for number of rows/lines143 RowCounter[MatrixNr]=-1;// counts one line too much144 while (!input.eof()) { 145 input.getline(filename, 1023);146 //cout << "Comparing: " << strncmp(filename,"MeanForce",9) << endl;147 RowCounter[MatrixNr]++; // then line was not last MeanForce148 if (strncmp(filename,"MeanForce", 9) == 0) {149 break;150 }151 }152 //cout << "RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from file " << name << "." << endl;153 if (RowCounter[MatrixNr] == 0)154 cerr << "RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from file " << name << ", this is probably an error!" << endl;155 156 // allocate matrix if it's not zero dimension in one direction157 if ((ColumnCounter > 0) && (RowCounter[MatrixNr] > -1)) {158 Matrix[MatrixNr] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixNr]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");159 160 // parse in each entry for this matrix161 input.clear();162 input.seekg(ios::beg);163 for (int m=skiplines+1;m--;)164 input.getline(Header, 1023);// skip header165 line.str(Header);166 for(int k=skipcolumns;k--;)// skip columns in header too167 line >> filename;168 strncpy(Header, line.str().c_str(), 1023); 169 for(int j=0;j<RowCounter[MatrixNr];j++) {170 Matrix[MatrixNr][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");171 input.getline(filename, 1023);172 stringstream lines(filename);173 //cout << "Matrix at level " << j << ":";// << filename << endl;174 for(int k=skipcolumns;k--;)175 lines >> filename;176 for(int k=0;(k<ColumnCounter) && (!lines.eof());k++) {177 lines >> Matrix[MatrixNr][j][k];178 //cout << " " << setprecision(2) << Matrix[MatrixNr][j][k];;179 }180 //cout << endl;181 Matrix[MatrixNr][ RowCounter[MatrixNr] ] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[RowCounter[MatrixNr]][]");182 for(int j=ColumnCounter;j--;)183 Matrix[MatrixNr][ RowCounter[MatrixNr] ][j] = 0.;184 }185 } else {186 cerr << "ERROR: Matrix nr. " << MatrixNr << " has column and row count of (" << ColumnCounter << "," << RowCounter[MatrixNr] << "), could not allocate nor parse!" << endl; 187 }188 input.close();189 return true;111 ifstream input; 112 stringstream line; 113 string token; 114 char filename[1023]; 115 116 input.open(name, ios::in); 117 //cout << "Opening " << name << " ... " << input << endl; 118 if (input == NULL) { 119 cerr << endl << "Unable to open " << name << ", is the directory correct?" << endl; 120 return false; 121 } 122 123 // skip some initial lines 124 for (int m=skiplines+1;m--;) 125 input.getline(Header, 1023); 126 127 // scan header for number of columns 128 line.str(Header); 129 for(int k=skipcolumns;k--;) 130 line >> Header; 131 //cout << line.str() << endl; 132 ColumnCounter=0; 133 while ( getline(line,token, '\t') ) { 134 if (token.length() > 0) 135 ColumnCounter++; 136 } 137 //cout << line.str() << endl; 138 //cout << "ColumnCounter: " << ColumnCounter << "." << endl; 139 if (ColumnCounter == 0) 140 cerr << "ColumnCounter: " << ColumnCounter << " from file " << name << ", this is probably an error!" << endl; 141 142 // scan rest for number of rows/lines 143 RowCounter[MatrixNr]=-1; // counts one line too much 144 while (!input.eof()) { 145 input.getline(filename, 1023); 146 //cout << "Comparing: " << strncmp(filename,"MeanForce",9) << endl; 147 RowCounter[MatrixNr]++; // then line was not last MeanForce 148 if (strncmp(filename,"MeanForce", 9) == 0) { 149 break; 150 } 151 } 152 //cout << "RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from file " << name << "." << endl; 153 if (RowCounter[MatrixNr] == 0) 154 cerr << "RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from file " << name << ", this is probably an error!" << endl; 155 156 // allocate matrix if it's not zero dimension in one direction 157 if ((ColumnCounter > 0) && (RowCounter[MatrixNr] > -1)) { 158 Matrix[MatrixNr] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixNr]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 159 160 // parse in each entry for this matrix 161 input.clear(); 162 input.seekg(ios::beg); 163 for (int m=skiplines+1;m--;) 164 input.getline(Header, 1023); // skip header 165 line.str(Header); 166 for(int k=skipcolumns;k--;) // skip columns in header too 167 line >> filename; 168 strncpy(Header, line.str().c_str(), 1023); 169 for(int j=0;j<RowCounter[MatrixNr];j++) { 170 Matrix[MatrixNr][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]"); 171 input.getline(filename, 1023); 172 stringstream lines(filename); 173 //cout << "Matrix at level " << j << ":";// << filename << endl; 174 for(int k=skipcolumns;k--;) 175 lines >> filename; 176 for(int k=0;(k<ColumnCounter) && (!lines.eof());k++) { 177 lines >> Matrix[MatrixNr][j][k]; 178 //cout << " " << setprecision(2) << Matrix[MatrixNr][j][k];; 179 } 180 //cout << endl; 181 Matrix[MatrixNr][ RowCounter[MatrixNr] ] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[RowCounter[MatrixNr]][]"); 182 for(int j=ColumnCounter;j--;) 183 Matrix[MatrixNr][ RowCounter[MatrixNr] ][j] = 0.; 184 } 185 } else { 186 cerr << "ERROR: Matrix nr. " << MatrixNr << " has column and row count of (" << ColumnCounter << "," << RowCounter[MatrixNr] << "), could not allocate nor parse!" << endl; 187 } 188 input.close(); 189 return true; 190 190 }; 191 191 192 192 /** Parsing a number of matrices. 193 193 * -# First, count the number of matrices by counting lines in KEYSETFILE 194 * -# Then, 195 * -# construct the fragment number196 * -# open the matrix file197 * -# skip some lines (\a skiplines)198 * -# scan header lines for number of columns199 * -# scan lines for number of rows200 * -# allocate matrix201 * -# loop over found column and row counts and parse in each entry202 * -# Finally, allocate one additional matrix (\a MatrixCounter) containing combined or temporary values 194 * -# Then, 195 * -# construct the fragment number 196 * -# open the matrix file 197 * -# skip some lines (\a skiplines) 198 * -# scan header lines for number of columns 199 * -# scan lines for number of rows 200 * -# allocate matrix 201 * -# loop over found column and row counts and parse in each entry 202 * -# Finally, allocate one additional matrix (\a MatrixCounter) containing combined or temporary values 203 203 * \param *name directory with files 204 204 * \param *prefix prefix of each matrix file … … 206 206 * \param skiplines number of inital lines to skip 207 207 * \param skiplines number of inital columns to skip 208 * \return parsing successful 208 * \return parsing successful 209 209 */ 210 210 bool MatrixContainer::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) 211 211 { 212 char filename[1023];213 ifstream input;214 char *FragmentNumber = NULL;215 stringstream file;216 string token;217 218 // count the number of matrices219 MatrixCounter = -1; // we count one too much220 file << name << FRAGMENTPREFIX << KEYSETFILE;221 input.open(file.str().c_str(), ios::in);222 if (input == NULL) {223 cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;224 return false;225 }226 while (!input.eof()) {227 input.getline(filename, 1023);228 stringstream zeile(filename);229 MatrixCounter++;230 }231 input.close(); 232 cout << "Determined " << MatrixCounter << " fragments." << endl;233 234 cout << "Parsing through each fragment and retrieving " << prefix << suffix << "." << endl;235 Matrix = (double ***) ReAlloc(Matrix, sizeof(double **)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: ***Matrix"); // one more each for the total molecule236 RowCounter = (int *) ReAlloc(RowCounter, sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *RowCounter");237 for(int i=MatrixCounter+1;i--;) {238 Matrix[i] = NULL;239 RowCounter[i] = -1;240 }241 for(int i=0; i < MatrixCounter;i++) {242 // open matrix file243 FragmentNumber = FixedDigitNumber(MatrixCounter, i);244 file.str(" ");245 file << name << FRAGMENTPREFIX << FragmentNumber << prefix << suffix;246 if (!ParseMatrix(file.str().c_str(), skiplines, skipcolumns, i))247 return false;248 Free((void **)&FragmentNumber, "MatrixContainer::ParseFragmentMatrix: *FragmentNumber");249 }250 return true;212 char filename[1023]; 213 ifstream input; 214 char *FragmentNumber = NULL; 215 stringstream file; 216 string token; 217 218 // count the number of matrices 219 MatrixCounter = -1; // we count one too much 220 file << name << FRAGMENTPREFIX << KEYSETFILE; 221 input.open(file.str().c_str(), ios::in); 222 if (input == NULL) { 223 cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl; 224 return false; 225 } 226 while (!input.eof()) { 227 input.getline(filename, 1023); 228 stringstream zeile(filename); 229 MatrixCounter++; 230 } 231 input.close(); 232 cout << "Determined " << MatrixCounter << " fragments." << endl; 233 234 cout << "Parsing through each fragment and retrieving " << prefix << suffix << "." << endl; 235 Matrix = (double ***) ReAlloc(Matrix, sizeof(double **)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: ***Matrix"); // one more each for the total molecule 236 RowCounter = (int *) ReAlloc(RowCounter, sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *RowCounter"); 237 for(int i=MatrixCounter+1;i--;) { 238 Matrix[i] = NULL; 239 RowCounter[i] = -1; 240 } 241 for(int i=0; i < MatrixCounter;i++) { 242 // open matrix file 243 FragmentNumber = FixedDigitNumber(MatrixCounter, i); 244 file.str(" "); 245 file << name << FRAGMENTPREFIX << FragmentNumber << prefix << suffix; 246 if (!ParseMatrix(file.str().c_str(), skiplines, skipcolumns, i)) 247 return false; 248 Free((void **)&FragmentNumber, "MatrixContainer::ParseFragmentMatrix: *FragmentNumber"); 249 } 250 return true; 251 251 }; 252 252 … … 256 256 * \param *RCounter number of rows for each matrix 257 257 * \param CCounter number of columns for all matrices 258 * \return Allocation successful 258 * \return Allocation successful 259 259 */ 260 260 bool MatrixContainer::AllocateMatrix(char *GivenHeader, int MCounter, int *RCounter, int CCounter) 261 261 { 262 Header = (char *) Malloc(sizeof(char)*1024, "MatrixContainer::ParseFragmentMatrix: *EnergyHeader");263 strncpy(Header, GivenHeader, 1023);264 265 MatrixCounter = MCounter;266 ColumnCounter = CCounter;267 Matrix = (double ***) Malloc(sizeof(double **)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: ***Matrix"); // one more each for the total molecule268 RowCounter = (int *) Malloc(sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *RowCounter");269 for(int i=MatrixCounter+1;i--;) {270 RowCounter[i] = RCounter[i];271 Matrix[i] = (double **) Malloc(sizeof(double *)*(RowCounter[i]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 272 for(int j=RowCounter[i]+1;j--;) {273 Matrix[i][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");274 for(int k=ColumnCounter;k--;)275 Matrix[i][j][k] = 0.;276 }277 }278 return true;262 Header = (char *) Malloc(sizeof(char)*1024, "MatrixContainer::ParseFragmentMatrix: *EnergyHeader"); 263 strncpy(Header, GivenHeader, 1023); 264 265 MatrixCounter = MCounter; 266 ColumnCounter = CCounter; 267 Matrix = (double ***) Malloc(sizeof(double **)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: ***Matrix"); // one more each for the total molecule 268 RowCounter = (int *) Malloc(sizeof(int)*(MatrixCounter+1), "MatrixContainer::ParseFragmentMatrix: *RowCounter"); 269 for(int i=MatrixCounter+1;i--;) { 270 RowCounter[i] = RCounter[i]; 271 Matrix[i] = (double **) Malloc(sizeof(double *)*(RowCounter[i]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 272 for(int j=RowCounter[i]+1;j--;) { 273 Matrix[i][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]"); 274 for(int k=ColumnCounter;k--;) 275 Matrix[i][j][k] = 0.; 276 } 277 } 278 return true; 279 279 }; 280 280 … … 284 284 bool MatrixContainer::ResetMatrix() 285 285 { 286 for(int i=MatrixCounter+1;i--;)287 for(int j=RowCounter[i]+1;j--;)288 for(int k=ColumnCounter;k--;)289 Matrix[i][j][k] = 0.;290 return true;286 for(int i=MatrixCounter+1;i--;) 287 for(int j=RowCounter[i]+1;j--;) 288 for(int k=ColumnCounter;k--;) 289 Matrix[i][j][k] = 0.; 290 return true; 291 291 }; 292 292 … … 296 296 double MatrixContainer::FindMaxValue() 297 297 { 298 double max = Matrix[0][0][0];299 for(int i=MatrixCounter+1;i--;)300 for(int j=RowCounter[i]+1;j--;)301 for(int k=ColumnCounter;k--;)302 if (fabs(Matrix[i][j][k]) > max)303 max = fabs(Matrix[i][j][k]);304 if (fabs(max) < MYEPSILON)305 max += MYEPSILON;298 double max = Matrix[0][0][0]; 299 for(int i=MatrixCounter+1;i--;) 300 for(int j=RowCounter[i]+1;j--;) 301 for(int k=ColumnCounter;k--;) 302 if (fabs(Matrix[i][j][k]) > max) 303 max = fabs(Matrix[i][j][k]); 304 if (fabs(max) < MYEPSILON) 305 max += MYEPSILON; 306 306 return max; 307 307 }; … … 312 312 double MatrixContainer::FindMinValue() 313 313 { 314 double min = Matrix[0][0][0];315 for(int i=MatrixCounter+1;i--;)316 for(int j=RowCounter[i]+1;j--;)317 for(int k=ColumnCounter;k--;)318 if (fabs(Matrix[i][j][k]) < min)319 min = fabs(Matrix[i][j][k]);320 if (fabs(min) < MYEPSILON)321 min += MYEPSILON;322 return min;314 double min = Matrix[0][0][0]; 315 for(int i=MatrixCounter+1;i--;) 316 for(int j=RowCounter[i]+1;j--;) 317 for(int k=ColumnCounter;k--;) 318 if (fabs(Matrix[i][j][k]) < min) 319 min = fabs(Matrix[i][j][k]); 320 if (fabs(min) < MYEPSILON) 321 min += MYEPSILON; 322 return min; 323 323 }; 324 324 … … 330 330 bool MatrixContainer::SetLastMatrix(double value, int skipcolumns) 331 331 { 332 for(int j=RowCounter[MatrixCounter]+1;j--;)333 for(int k=skipcolumns;k<ColumnCounter;k++)334 Matrix[MatrixCounter][j][k] = value;335 return true;332 for(int j=RowCounter[MatrixCounter]+1;j--;) 333 for(int k=skipcolumns;k<ColumnCounter;k++) 334 Matrix[MatrixCounter][j][k] = value; 335 return true; 336 336 }; 337 337 … … 343 343 bool MatrixContainer::SetLastMatrix(double **values, int skipcolumns) 344 344 { 345 for(int j=RowCounter[MatrixCounter]+1;j--;)346 for(int k=skipcolumns;k<ColumnCounter;k++)347 Matrix[MatrixCounter][j][k] = values[j][k];348 return true;345 for(int j=RowCounter[MatrixCounter]+1;j--;) 346 for(int k=skipcolumns;k<ColumnCounter;k++) 347 Matrix[MatrixCounter][j][k] = values[j][k]; 348 return true; 349 349 }; 350 350 … … 358 358 bool MatrixContainer::SumSubManyBodyTerms(class MatrixContainer &MatrixValues, class KeySetsContainer &KeySet, int Order) 359 359 { 360 // go through each order361 for (int CurrentFragment=0;CurrentFragment<KeySet.FragmentsPerOrder[Order];CurrentFragment++) {362 //cout << "Current Fragment is " << CurrentFragment << "/" << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;363 // then go per order through each suborder and pick together all the terms that contain this fragment364 for(int SubOrder=0;SubOrder<=Order;SubOrder++) { // go through all suborders up to the desired order365 for (int j=0;j<KeySet.FragmentsPerOrder[SubOrder];j++) { // go through all possible fragments of size suborder366 if (KeySet.Contains(KeySet.OrderSet[Order][CurrentFragment], KeySet.OrderSet[SubOrder][j])) {367 //cout << "Current other fragment is " << j << "/" << KeySet.OrderSet[SubOrder][j] << "." << endl;368 // if the fragment's indices are all in the current fragment369 for(int k=0;k<RowCounter[ KeySet.OrderSet[SubOrder][j] ];k++) { // go through all atoms in this fragment370 int m = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][k];371 //cout << "Current index is " << k << "/" << m << "." << endl;372 if (m != -1) { // if it's not an added hydrogen373 for (int l=0;l<RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ];l++) { // look for the corresponding index in the current fragment374 //cout << "Comparing " << m << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l] << "." << endl;375 if (m == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l]) {376 m = l;377 break; 378 }379 }380 //cout << "Corresponding index in CurrentFragment is " << m << "." << endl;381 if (m > RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) {382 cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment]<< " current force index " << m << " is greater than " << RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl;383 return false;384 }385 if (Order == SubOrder) { // equal order is always copy from Energies386 for(int l=ColumnCounter;l--;) // then adds/subtract each column 387 Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] += MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];388 } else {389 for(int l=ColumnCounter;l--;)390 Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] -= Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l];391 }392 }393 //if ((ColumnCounter>1) && (RowCounter[0]-1 >= 1))394 //cout << "Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " <<Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl;395 }396 } else {397 //cout << "Fragment " << KeySet.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySet.OrderSet[Order][CurrentFragment] << "." << endl;398 }399 }400 }401 //cout << "Final Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << KeySet.AtomCounter[0]-1 << "][" << 1 << "] = " <<Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][KeySet.AtomCounter[0]-1][1] << endl;402 }403 404 return true;360 // go through each order 361 for (int CurrentFragment=0;CurrentFragment<KeySet.FragmentsPerOrder[Order];CurrentFragment++) { 362 //cout << "Current Fragment is " << CurrentFragment << "/" << KeySet.OrderSet[Order][CurrentFragment] << "." << endl; 363 // then go per order through each suborder and pick together all the terms that contain this fragment 364 for(int SubOrder=0;SubOrder<=Order;SubOrder++) { // go through all suborders up to the desired order 365 for (int j=0;j<KeySet.FragmentsPerOrder[SubOrder];j++) { // go through all possible fragments of size suborder 366 if (KeySet.Contains(KeySet.OrderSet[Order][CurrentFragment], KeySet.OrderSet[SubOrder][j])) { 367 //cout << "Current other fragment is " << j << "/" << KeySet.OrderSet[SubOrder][j] << "." << endl; 368 // if the fragment's indices are all in the current fragment 369 for(int k=0;k<RowCounter[ KeySet.OrderSet[SubOrder][j] ];k++) { // go through all atoms in this fragment 370 int m = MatrixValues.Indices[ KeySet.OrderSet[SubOrder][j] ][k]; 371 //cout << "Current index is " << k << "/" << m << "." << endl; 372 if (m != -1) { // if it's not an added hydrogen 373 for (int l=0;l<RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ];l++) { // look for the corresponding index in the current fragment 374 //cout << "Comparing " << m << " with " << MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l] << "." << endl; 375 if (m == MatrixValues.Indices[ KeySet.OrderSet[Order][CurrentFragment] ][l]) { 376 m = l; 377 break; 378 } 379 } 380 //cout << "Corresponding index in CurrentFragment is " << m << "." << endl; 381 if (m > RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ]) { 382 cerr << "In fragment No. " << KeySet.OrderSet[Order][CurrentFragment] << " current force index " << m << " is greater than " << RowCounter[ KeySet.OrderSet[Order][CurrentFragment] ] << "!" << endl; 383 return false; 384 } 385 if (Order == SubOrder) { // equal order is always copy from Energies 386 for(int l=ColumnCounter;l--;) // then adds/subtract each column 387 Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] += MatrixValues.Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l]; 388 } else { 389 for(int l=ColumnCounter;l--;) 390 Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][m][l] -= Matrix[ KeySet.OrderSet[SubOrder][j] ][k][l]; 391 } 392 } 393 //if ((ColumnCounter>1) && (RowCounter[0]-1 >= 1)) 394 //cout << "Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " << Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1] << endl; 395 } 396 } else { 397 //cout << "Fragment " << KeySet.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySet.OrderSet[Order][CurrentFragment] << "." << endl; 398 } 399 } 400 } 401 //cout << "Final Fragments[ KeySet.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySet.OrderSet[Order][CurrentFragment] << " ][" << KeySet.AtomCounter[0]-1 << "][" << 1 << "] = " << Matrix[ KeySet.OrderSet[Order][CurrentFragment] ][KeySet.AtomCounter[0]-1][1] << endl; 402 } 403 404 return true; 405 405 }; 406 406 … … 412 412 bool MatrixContainer::WriteTotalFragments(const char *name, const char *prefix) 413 413 { 414 ofstream output;415 char *FragmentNumber = NULL;416 417 cout << "Writing fragment files." << endl;418 for(int i=0;i<MatrixCounter;i++) {419 stringstream line;420 FragmentNumber = FixedDigitNumber(MatrixCounter, i);421 line << name << FRAGMENTPREFIX << FragmentNumber << "/" << prefix;422 Free((void **)&FragmentNumber, "*FragmentNumber");423 output.open(line.str().c_str(), ios::out);424 if (output == NULL) {425 cerr << "Unable to open output energy file " << line.str() << "!" << endl;426 return false;427 }428 output << Header << endl;429 for(int j=0;j<RowCounter[i];j++) {430 for(int k=0;k<ColumnCounter;k++)431 output << scientific << Matrix[i][j][k] << "\t";432 output << endl;433 }434 output.close();435 }436 return true;414 ofstream output; 415 char *FragmentNumber = NULL; 416 417 cout << "Writing fragment files." << endl; 418 for(int i=0;i<MatrixCounter;i++) { 419 stringstream line; 420 FragmentNumber = FixedDigitNumber(MatrixCounter, i); 421 line << name << FRAGMENTPREFIX << FragmentNumber << "/" << prefix; 422 Free((void **)&FragmentNumber, "*FragmentNumber"); 423 output.open(line.str().c_str(), ios::out); 424 if (output == NULL) { 425 cerr << "Unable to open output energy file " << line.str() << "!" << endl; 426 return false; 427 } 428 output << Header << endl; 429 for(int j=0;j<RowCounter[i];j++) { 430 for(int k=0;k<ColumnCounter;k++) 431 output << scientific << Matrix[i][j][k] << "\t"; 432 output << endl; 433 } 434 output.close(); 435 } 436 return true; 437 437 }; 438 438 … … 445 445 bool MatrixContainer::WriteLastMatrix(const char *name, const char *prefix, const char *suffix) 446 446 { 447 ofstream output;448 stringstream line;449 450 cout << "Writing matrix values of " << suffix << "." << endl;451 line << name << prefix << suffix;452 output.open(line.str().c_str(), ios::out);453 if (output == NULL) {454 cerr << "Unable to open output matrix file " << line.str() << "!" << endl;455 return false;456 }457 output << Header << endl;458 for(int j=0;j<RowCounter[MatrixCounter];j++) {459 for(int k=0;k<ColumnCounter;k++)460 output << scientific << Matrix[MatrixCounter][j][k] << "\t";461 output << endl;462 }463 output.close();464 return true;447 ofstream output; 448 stringstream line; 449 450 cout << "Writing matrix values of " << suffix << "." << endl; 451 line << name << prefix << suffix; 452 output.open(line.str().c_str(), ios::out); 453 if (output == NULL) { 454 cerr << "Unable to open output matrix file " << line.str() << "!" << endl; 455 return false; 456 } 457 output << Header << endl; 458 for(int j=0;j<RowCounter[MatrixCounter];j++) { 459 for(int k=0;k<ColumnCounter;k++) 460 output << scientific << Matrix[MatrixCounter][j][k] << "\t"; 461 output << endl; 462 } 463 output.close(); 464 return true; 465 465 }; 466 466 … … 471 471 * \return creation sucessful 472 472 */ 473 bool EnergyMatrix::ParseIndices() 474 { 475 cout << "Parsing energy indices." << endl;476 Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "EnergyMatrix::ParseIndices: **Indices");477 for(int i=MatrixCounter+1;i--;) {478 Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "EnergyMatrix::ParseIndices: *Indices[]");479 for(int j=RowCounter[i];j--;)480 Indices[i][j] = j;481 } 482 return true; 473 bool EnergyMatrix::ParseIndices() 474 { 475 cout << "Parsing energy indices." << endl; 476 Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "EnergyMatrix::ParseIndices: **Indices"); 477 for(int i=MatrixCounter+1;i--;) { 478 Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "EnergyMatrix::ParseIndices: *Indices[]"); 479 for(int j=RowCounter[i];j--;) 480 Indices[i][j] = j; 481 } 482 return true; 483 483 }; 484 484 … … 494 494 bool EnergyMatrix::SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign) 495 495 { 496 // sum energy497 if (CorrectionFragments == NULL)498 for(int i=KeySet.FragmentsPerOrder[Order];i--;)499 for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;)500 for(int k=ColumnCounter;k--;)501 Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k];502 else503 for(int i=KeySet.FragmentsPerOrder[Order];i--;)504 for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;)505 for(int k=ColumnCounter;k--;)506 Matrix[MatrixCounter][j][k] += sign*(Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k] + CorrectionFragments->Matrix[ KeySet.OrderSet[Order][i] ][j][k]);507 return true;496 // sum energy 497 if (CorrectionFragments == NULL) 498 for(int i=KeySet.FragmentsPerOrder[Order];i--;) 499 for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;) 500 for(int k=ColumnCounter;k--;) 501 Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k]; 502 else 503 for(int i=KeySet.FragmentsPerOrder[Order];i--;) 504 for(int j=RowCounter[ KeySet.OrderSet[Order][i] ];j--;) 505 for(int k=ColumnCounter;k--;) 506 Matrix[MatrixCounter][j][k] += sign*(Fragments.Matrix[ KeySet.OrderSet[Order][i] ][j][k] + CorrectionFragments->Matrix[ KeySet.OrderSet[Order][i] ][j][k]); 507 return true; 508 508 }; 509 509 … … 515 515 * \param skiplines number of inital columns to skip 516 516 * \return parsing successful 517 */ 517 */ 518 518 bool EnergyMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) 519 519 { 520 char filename[1024];521 bool status = MatrixContainer::ParseFragmentMatrix(name, prefix, suffix, skiplines, skipcolumns);522 523 if (status) {524 // count maximum of columns525 RowCounter[MatrixCounter] = 0;526 for(int j=0; j < MatrixCounter;j++) // (energy matrix might be bigger than number of atoms in terms of rows)527 if (RowCounter[j] > RowCounter[MatrixCounter])528 RowCounter[MatrixCounter] = RowCounter[j];529 // allocate last plus one matrix530 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter << " columns." << endl;531 Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");532 for(int j=0;j<=RowCounter[MatrixCounter];j++)533 Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");534 535 // try independently to parse global energysuffix file if present536 strncpy(filename, name, 1023);537 strncat(filename, prefix, 1023-strlen(filename));538 strncat(filename, suffix.c_str(), 1023-strlen(filename));539 ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter);540 }541 return status;520 char filename[1024]; 521 bool status = MatrixContainer::ParseFragmentMatrix(name, prefix, suffix, skiplines, skipcolumns); 522 523 if (status) { 524 // count maximum of columns 525 RowCounter[MatrixCounter] = 0; 526 for(int j=0; j < MatrixCounter;j++) // (energy matrix might be bigger than number of atoms in terms of rows) 527 if (RowCounter[j] > RowCounter[MatrixCounter]) 528 RowCounter[MatrixCounter] = RowCounter[j]; 529 // allocate last plus one matrix 530 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter << " columns." << endl; 531 Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 532 for(int j=0;j<=RowCounter[MatrixCounter];j++) 533 Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]"); 534 535 // try independently to parse global energysuffix file if present 536 strncpy(filename, name, 1023); 537 strncat(filename, prefix, 1023-strlen(filename)); 538 strncat(filename, suffix.c_str(), 1023-strlen(filename)); 539 ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter); 540 } 541 return status; 542 542 }; 543 543 … … 546 546 /** Parsing force Indices of each fragment 547 547 * \param *name directory with \a ForcesFile 548 * \return parsing successful 549 */ 550 bool ForceMatrix::ParseIndices(char *name) 551 { 552 ifstream input;553 char *FragmentNumber = NULL;554 char filename[1023];555 stringstream line;556 557 cout << "Parsing force indices for " << MatrixCounter << " matrices." << endl;558 Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "ForceMatrix::ParseIndices: **Indices");559 line << name << FRAGMENTPREFIX << FORCESFILE;560 input.open(line.str().c_str(), ios::in);561 //cout << "Opening " << line.str() << " ... "<< input << endl;562 if (input == NULL) {563 cout << endl << "Unable to open " << line.str() << ", is the directory correct?" << endl;564 return false;565 }566 for (int i=0;(i<MatrixCounter) && (!input.eof());i++) {567 // get the number of atoms for this fragment568 input.getline(filename, 1023);569 line.str(filename);570 // parse the values571 Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "ForceMatrix::ParseIndices: *Indices[]");572 FragmentNumber = FixedDigitNumber(MatrixCounter, i);573 //cout << FRAGMENTPREFIX << FragmentNumber << "[" << RowCounter[i] << "]:";574 Free((void **)&FragmentNumber, "ForceMatrix::ParseIndices: *FragmentNumber");575 for(int j=0;(j<RowCounter[i]) && (!line.eof());j++) {576 line >> Indices[i][j];577 //cout << " " << Indices[i][j];578 }579 //cout << endl;580 }581 Indices[MatrixCounter] = (int *) Malloc(sizeof(int)*RowCounter[MatrixCounter], "ForceMatrix::ParseIndices: *Indices[]");582 for(int j=RowCounter[MatrixCounter];j--;) {583 Indices[MatrixCounter][j] = j;584 }585 input.close();586 return true;548 * \return parsing successful 549 */ 550 bool ForceMatrix::ParseIndices(char *name) 551 { 552 ifstream input; 553 char *FragmentNumber = NULL; 554 char filename[1023]; 555 stringstream line; 556 557 cout << "Parsing force indices for " << MatrixCounter << " matrices." << endl; 558 Indices = (int **) Malloc(sizeof(int *)*(MatrixCounter+1), "ForceMatrix::ParseIndices: **Indices"); 559 line << name << FRAGMENTPREFIX << FORCESFILE; 560 input.open(line.str().c_str(), ios::in); 561 //cout << "Opening " << line.str() << " ... " << input << endl; 562 if (input == NULL) { 563 cout << endl << "Unable to open " << line.str() << ", is the directory correct?" << endl; 564 return false; 565 } 566 for (int i=0;(i<MatrixCounter) && (!input.eof());i++) { 567 // get the number of atoms for this fragment 568 input.getline(filename, 1023); 569 line.str(filename); 570 // parse the values 571 Indices[i] = (int *) Malloc(sizeof(int)*RowCounter[i], "ForceMatrix::ParseIndices: *Indices[]"); 572 FragmentNumber = FixedDigitNumber(MatrixCounter, i); 573 //cout << FRAGMENTPREFIX << FragmentNumber << "[" << RowCounter[i] << "]:"; 574 Free((void **)&FragmentNumber, "ForceMatrix::ParseIndices: *FragmentNumber"); 575 for(int j=0;(j<RowCounter[i]) && (!line.eof());j++) { 576 line >> Indices[i][j]; 577 //cout << " " << Indices[i][j]; 578 } 579 //cout << endl; 580 } 581 Indices[MatrixCounter] = (int *) Malloc(sizeof(int)*RowCounter[MatrixCounter], "ForceMatrix::ParseIndices: *Indices[]"); 582 for(int j=RowCounter[MatrixCounter];j--;) { 583 Indices[MatrixCounter][j] = j; 584 } 585 input.close(); 586 return true; 587 587 }; 588 588 … … 592 592 * \param KeySet KeySetContainer with bond Order and association mapping of each fragment to an order 593 593 * \param Order bond order 594 * \param sign +1 or -1594 * \param sign +1 or -1 595 595 * \return true if summing was successful 596 596 */ 597 597 bool ForceMatrix::SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign) 598 598 { 599 int FragmentNr;600 // sum forces601 for(int i=0;i<KeySet.FragmentsPerOrder[Order];i++) {602 FragmentNr = KeySet.OrderSet[Order][i];603 for(int l=0;l<RowCounter[ FragmentNr ];l++) {604 int j = Indices[ FragmentNr ][l];605 if (j > RowCounter[MatrixCounter]) {606 cerr << "Current force index " << j << " is greater than " << RowCounter[MatrixCounter] << "!" << endl;607 return false;608 }609 if (j != -1) {610 //if (j == 0) cout << "Summing onto ion 0, type 0 from fragment " << FragmentNr << ", ion " << l << "." << endl;611 for(int k=2;k<ColumnCounter;k++)612 Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ FragmentNr ][l][k];613 }614 }615 }616 return true;599 int FragmentNr; 600 // sum forces 601 for(int i=0;i<KeySet.FragmentsPerOrder[Order];i++) { 602 FragmentNr = KeySet.OrderSet[Order][i]; 603 for(int l=0;l<RowCounter[ FragmentNr ];l++) { 604 int j = Indices[ FragmentNr ][l]; 605 if (j > RowCounter[MatrixCounter]) { 606 cerr << "Current force index " << j << " is greater than " << RowCounter[MatrixCounter] << "!" << endl; 607 return false; 608 } 609 if (j != -1) { 610 //if (j == 0) cout << "Summing onto ion 0, type 0 from fragment " << FragmentNr << ", ion " << l << "." << endl; 611 for(int k=2;k<ColumnCounter;k++) 612 Matrix[MatrixCounter][j][k] += sign*Fragments.Matrix[ FragmentNr ][l][k]; 613 } 614 } 615 } 616 return true; 617 617 }; 618 618 … … 625 625 * \param skiplines number of inital columns to skip 626 626 * \return parsing successful 627 */ 627 */ 628 628 bool ForceMatrix::ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns) 629 629 { 630 char filename[1023];631 ifstream input;632 stringstream file;633 int nr;634 bool status = MatrixContainer::ParseFragmentMatrix(name, prefix, suffix, skiplines, skipcolumns);635 636 if (status) {637 // count number of atoms for last plus one matrix638 file << name << FRAGMENTPREFIX << KEYSETFILE;639 input.open(file.str().c_str(), ios::in);640 if (input == NULL) {641 cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;642 return false;643 }644 RowCounter[MatrixCounter] = 0;645 while (!input.eof()) {646 input.getline(filename, 1023);647 stringstream zeile(filename);648 while (!zeile.eof()) {649 zeile >> nr;650 //cout << "Current index: " << nr << "." << endl;651 if (nr > RowCounter[MatrixCounter])652 RowCounter[MatrixCounter] = nr;653 }654 }655 RowCounter[MatrixCounter]++;// nr start at 0, count starts at 1656 input.close();657 658 // allocate last plus one matrix659 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter << " columns." << endl;660 Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]");661 for(int j=0;j<=RowCounter[MatrixCounter];j++)662 Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]");663 664 // try independently to parse global forcesuffix file if present665 strncpy(filename, name, 1023);666 strncat(filename, prefix, 1023-strlen(filename));667 strncat(filename, suffix.c_str(), 1023-strlen(filename));668 ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter);669 }670 671 672 return status;630 char filename[1023]; 631 ifstream input; 632 stringstream file; 633 int nr; 634 bool status = MatrixContainer::ParseFragmentMatrix(name, prefix, suffix, skiplines, skipcolumns); 635 636 if (status) { 637 // count number of atoms for last plus one matrix 638 file << name << FRAGMENTPREFIX << KEYSETFILE; 639 input.open(file.str().c_str(), ios::in); 640 if (input == NULL) { 641 cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl; 642 return false; 643 } 644 RowCounter[MatrixCounter] = 0; 645 while (!input.eof()) { 646 input.getline(filename, 1023); 647 stringstream zeile(filename); 648 while (!zeile.eof()) { 649 zeile >> nr; 650 //cout << "Current index: " << nr << "." << endl; 651 if (nr > RowCounter[MatrixCounter]) 652 RowCounter[MatrixCounter] = nr; 653 } 654 } 655 RowCounter[MatrixCounter]++; // nr start at 0, count starts at 1 656 input.close(); 657 658 // allocate last plus one matrix 659 cout << "Allocating last plus one matrix with " << (RowCounter[MatrixCounter]+1) << " rows and " << ColumnCounter << " columns." << endl; 660 Matrix[MatrixCounter] = (double **) Malloc(sizeof(double *)*(RowCounter[MatrixCounter]+1), "MatrixContainer::ParseFragmentMatrix: **Matrix[]"); 661 for(int j=0;j<=RowCounter[MatrixCounter];j++) 662 Matrix[MatrixCounter][j] = (double *) Malloc(sizeof(double)*ColumnCounter, "MatrixContainer::ParseFragmentMatrix: *Matrix[][]"); 663 664 // try independently to parse global forcesuffix file if present 665 strncpy(filename, name, 1023); 666 strncat(filename, prefix, 1023-strlen(filename)); 667 strncat(filename, suffix.c_str(), 1023-strlen(filename)); 668 ParseMatrix(filename, skiplines, skipcolumns, MatrixCounter); 669 } 670 671 672 return status; 673 673 }; 674 674 … … 678 678 */ 679 679 KeySetsContainer::KeySetsContainer() { 680 KeySets = NULL;681 AtomCounter = NULL;682 FragmentCounter = 0;683 Order = 0;684 FragmentsPerOrder = 0;685 OrderSet = NULL;680 KeySets = NULL; 681 AtomCounter = NULL; 682 FragmentCounter = 0; 683 Order = 0; 684 FragmentsPerOrder = 0; 685 OrderSet = NULL; 686 686 }; 687 687 … … 689 689 */ 690 690 KeySetsContainer::~KeySetsContainer() { 691 for(int i=FragmentCounter;i--;)692 Free((void **)&KeySets[i], "KeySetsContainer::~KeySetsContainer: *KeySets[]");693 for(int i=Order;i--;)694 Free((void **)&OrderSet[i], "KeySetsContainer::~KeySetsContainer: *OrderSet[]");695 Free((void **)&KeySets, "KeySetsContainer::~KeySetsContainer: **KeySets");696 Free((void **)&OrderSet, "KeySetsContainer::~KeySetsContainer: **OrderSet");697 Free((void **)&AtomCounter, "KeySetsContainer::~KeySetsContainer: *AtomCounter");698 Free((void **)&FragmentsPerOrder, "KeySetsContainer::~KeySetsContainer: *FragmentsPerOrder");691 for(int i=FragmentCounter;i--;) 692 Free((void **)&KeySets[i], "KeySetsContainer::~KeySetsContainer: *KeySets[]"); 693 for(int i=Order;i--;) 694 Free((void **)&OrderSet[i], "KeySetsContainer::~KeySetsContainer: *OrderSet[]"); 695 Free((void **)&KeySets, "KeySetsContainer::~KeySetsContainer: **KeySets"); 696 Free((void **)&OrderSet, "KeySetsContainer::~KeySetsContainer: **OrderSet"); 697 Free((void **)&AtomCounter, "KeySetsContainer::~KeySetsContainer: *AtomCounter"); 698 Free((void **)&FragmentsPerOrder, "KeySetsContainer::~KeySetsContainer: *FragmentsPerOrder"); 699 699 }; 700 700 … … 706 706 */ 707 707 bool KeySetsContainer::ParseKeySets(const char *name, const int *ACounter, const int FCounter) { 708 ifstream input;709 char *FragmentNumber = NULL;710 stringstream file;711 char filename[1023];712 713 FragmentCounter = FCounter;714 cout << "Parsing key sets." << endl;715 KeySets = (int **) Malloc(sizeof(int *)*FragmentCounter, "KeySetsContainer::ParseKeySets: **KeySets");716 for(int i=FragmentCounter;i--;)717 KeySets[i] = NULL;718 file << name << FRAGMENTPREFIX << KEYSETFILE;719 input.open(file.str().c_str(), ios::in);720 if (input == NULL) {721 cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl;722 return false;723 }724 725 AtomCounter = (int *) Malloc(sizeof(int)*FragmentCounter, "KeySetsContainer::ParseKeySets: *RowCounter");726 for(int i=0;(i<FragmentCounter) && (!input.eof());i++) {727 stringstream line;728 AtomCounter[i] = ACounter[i];729 // parse the values730 KeySets[i] = (int *) Malloc(sizeof(int)*AtomCounter[i], "KeySetsContainer::ParseKeySets: *KeySets[]");731 for(int j=AtomCounter[i];j--;)732 KeySets[i][j] = -1;733 FragmentNumber = FixedDigitNumber(FragmentCounter, i);734 //cout << FRAGMENTPREFIX << FragmentNumber << "[" << AtomCounter[i] << "]:";735 Free((void **)&FragmentNumber, "KeySetsContainer::ParseKeySets: *FragmentNumber");736 input.getline(filename, 1023);737 line.str(filename);738 for(int j=0;(j<AtomCounter[i]) && (!line.eof());j++) {739 line >> KeySets[i][j];740 //cout << " " << KeySets[i][j];741 }742 //cout << endl;743 }744 input.close();745 return true;708 ifstream input; 709 char *FragmentNumber = NULL; 710 stringstream file; 711 char filename[1023]; 712 713 FragmentCounter = FCounter; 714 cout << "Parsing key sets." << endl; 715 KeySets = (int **) Malloc(sizeof(int *)*FragmentCounter, "KeySetsContainer::ParseKeySets: **KeySets"); 716 for(int i=FragmentCounter;i--;) 717 KeySets[i] = NULL; 718 file << name << FRAGMENTPREFIX << KEYSETFILE; 719 input.open(file.str().c_str(), ios::in); 720 if (input == NULL) { 721 cout << endl << "Unable to open " << file.str() << ", is the directory correct?" << endl; 722 return false; 723 } 724 725 AtomCounter = (int *) Malloc(sizeof(int)*FragmentCounter, "KeySetsContainer::ParseKeySets: *RowCounter"); 726 for(int i=0;(i<FragmentCounter) && (!input.eof());i++) { 727 stringstream line; 728 AtomCounter[i] = ACounter[i]; 729 // parse the values 730 KeySets[i] = (int *) Malloc(sizeof(int)*AtomCounter[i], "KeySetsContainer::ParseKeySets: *KeySets[]"); 731 for(int j=AtomCounter[i];j--;) 732 KeySets[i][j] = -1; 733 FragmentNumber = FixedDigitNumber(FragmentCounter, i); 734 //cout << FRAGMENTPREFIX << FragmentNumber << "[" << AtomCounter[i] << "]:"; 735 Free((void **)&FragmentNumber, "KeySetsContainer::ParseKeySets: *FragmentNumber"); 736 input.getline(filename, 1023); 737 line.str(filename); 738 for(int j=0;(j<AtomCounter[i]) && (!line.eof());j++) { 739 line >> KeySets[i][j]; 740 //cout << " " << KeySets[i][j]; 741 } 742 //cout << endl; 743 } 744 input.close(); 745 return true; 746 746 }; 747 747 … … 751 751 bool KeySetsContainer::ParseManyBodyTerms() 752 752 { 753 int Counter;754 755 cout << "Creating Fragment terms." << endl;756 // scan through all to determine maximum order757 Order=0;758 for(int i=FragmentCounter;i--;) {759 Counter=0;760 for(int j=AtomCounter[i];j--;)761 if (KeySets[i][j] != -1)762 Counter++;763 if (Counter > Order)764 Order = Counter;765 }766 cout << "Found Order is " << Order << "." << endl;767 768 // scan through all to determine fragments per order769 FragmentsPerOrder = (int *) Malloc(sizeof(int)*Order, "KeySetsContainer::ParseManyBodyTerms: *FragmentsPerOrder");770 for(int i=Order;i--;)771 FragmentsPerOrder[i] = 0;772 for(int i=FragmentCounter;i--;) {773 Counter=0;774 for(int j=AtomCounter[i];j--;)775 if (KeySets[i][j] != -1)776 Counter++;777 FragmentsPerOrder[Counter-1]++;778 }779 for(int i=0;i<Order;i++)780 cout << "Found No. of Fragments of Order " << i+1 << " is " << FragmentsPerOrder[i] << "." << endl;781 782 // scan through all to gather indices to each order set783 OrderSet = (int **) Malloc(sizeof(int *)*Order, "KeySetsContainer::ParseManyBodyTerms: **OrderSet");784 for(int i=Order;i--;)785 OrderSet[i] = (int *) Malloc(sizeof(int)*FragmentsPerOrder[i], "KeySetsContainer::ParseManyBodyTermsKeySetsContainer::ParseManyBodyTerms: *OrderSet[]");786 for(int i=Order;i--;)787 FragmentsPerOrder[i] = 0;788 for(int i=FragmentCounter;i--;) {789 Counter=0;790 for(int j=AtomCounter[i];j--;)791 if (KeySets[i][j] != -1)792 Counter++;793 OrderSet[Counter-1][FragmentsPerOrder[Counter-1]] = i;794 FragmentsPerOrder[Counter-1]++;795 }796 cout << "Printing OrderSet." << endl;797 for(int i=0;i<Order;i++) {798 for (int j=0;j<FragmentsPerOrder[i];j++) {799 cout << " " << OrderSet[i][j];800 }801 cout << endl;802 }803 cout << endl;804 805 806 return true;753 int Counter; 754 755 cout << "Creating Fragment terms." << endl; 756 // scan through all to determine maximum order 757 Order=0; 758 for(int i=FragmentCounter;i--;) { 759 Counter=0; 760 for(int j=AtomCounter[i];j--;) 761 if (KeySets[i][j] != -1) 762 Counter++; 763 if (Counter > Order) 764 Order = Counter; 765 } 766 cout << "Found Order is " << Order << "." << endl; 767 768 // scan through all to determine fragments per order 769 FragmentsPerOrder = (int *) Malloc(sizeof(int)*Order, "KeySetsContainer::ParseManyBodyTerms: *FragmentsPerOrder"); 770 for(int i=Order;i--;) 771 FragmentsPerOrder[i] = 0; 772 for(int i=FragmentCounter;i--;) { 773 Counter=0; 774 for(int j=AtomCounter[i];j--;) 775 if (KeySets[i][j] != -1) 776 Counter++; 777 FragmentsPerOrder[Counter-1]++; 778 } 779 for(int i=0;i<Order;i++) 780 cout << "Found No. of Fragments of Order " << i+1 << " is " << FragmentsPerOrder[i] << "." << endl; 781 782 // scan through all to gather indices to each order set 783 OrderSet = (int **) Malloc(sizeof(int *)*Order, "KeySetsContainer::ParseManyBodyTerms: **OrderSet"); 784 for(int i=Order;i--;) 785 OrderSet[i] = (int *) Malloc(sizeof(int)*FragmentsPerOrder[i], "KeySetsContainer::ParseManyBodyTermsKeySetsContainer::ParseManyBodyTerms: *OrderSet[]"); 786 for(int i=Order;i--;) 787 FragmentsPerOrder[i] = 0; 788 for(int i=FragmentCounter;i--;) { 789 Counter=0; 790 for(int j=AtomCounter[i];j--;) 791 if (KeySets[i][j] != -1) 792 Counter++; 793 OrderSet[Counter-1][FragmentsPerOrder[Counter-1]] = i; 794 FragmentsPerOrder[Counter-1]++; 795 } 796 cout << "Printing OrderSet." << endl; 797 for(int i=0;i<Order;i++) { 798 for (int j=0;j<FragmentsPerOrder[i];j++) { 799 cout << " " << OrderSet[i][j]; 800 } 801 cout << endl; 802 } 803 cout << endl; 804 805 806 return true; 807 807 }; 808 808 … … 814 814 bool KeySetsContainer::Contains(const int GreaterSet, const int SmallerSet) 815 815 { 816 bool result = true;817 bool intermediate;818 if ((GreaterSet < 0) || (SmallerSet < 0) || (GreaterSet > FragmentCounter) || (SmallerSet > FragmentCounter)) // index out of bounds819 return false;820 for(int i=AtomCounter[SmallerSet];i--;) {821 intermediate = false;822 for (int j=AtomCounter[GreaterSet];j--;)823 intermediate = (intermediate || ((KeySets[SmallerSet][i] == KeySets[GreaterSet][j]) || (KeySets[SmallerSet][i] == -1)));824 result = result && intermediate;825 }826 827 return result;816 bool result = true; 817 bool intermediate; 818 if ((GreaterSet < 0) || (SmallerSet < 0) || (GreaterSet > FragmentCounter) || (SmallerSet > FragmentCounter)) // index out of bounds 819 return false; 820 for(int i=AtomCounter[SmallerSet];i--;) { 821 intermediate = false; 822 for (int j=AtomCounter[GreaterSet];j--;) 823 intermediate = (intermediate || ((KeySets[SmallerSet][i] == KeySets[GreaterSet][j]) || (KeySets[SmallerSet][i] == -1))); 824 result = result && intermediate; 825 } 826 827 return result; 828 828 }; 829 829 -
Property mode
changed from
-
src/parser.hpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 2 2 * 3 3 * Definitions of various class functions for the parsing of value files. 4 * 4 * 5 5 */ 6 6 … … 40 40 41 41 class MatrixContainer { 42 public:43 double ***Matrix;44 int **Indices;45 char *Header;46 int MatrixCounter;47 int *RowCounter;48 int ColumnCounter;49 50 MatrixContainer();51 ~MatrixContainer();52 53 bool ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr);54 virtual bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);55 bool AllocateMatrix(char *GivenHeader, int MCounter, int *RCounter, int CCounter);56 bool ResetMatrix();57 double FindMinValue();58 double FindMaxValue();59 bool SetLastMatrix(double value, int skipcolumns);60 bool SetLastMatrix(double **values, int skipcolumns);61 //bool ParseIndices();62 //bool SumSubValues();63 bool SumSubManyBodyTerms(class MatrixContainer &Matrix, class KeySetsContainer &KeySet, int Order);64 bool WriteTotalFragments(const char *name, const char *prefix);65 bool WriteLastMatrix(const char *name, const char *prefix, const char *suffix);66 }; 42 public: 43 double ***Matrix; 44 int **Indices; 45 char *Header; 46 int MatrixCounter; 47 int *RowCounter; 48 int ColumnCounter; 49 50 MatrixContainer(); 51 virtual ~MatrixContainer(); 52 53 bool ParseMatrix(const char *name, int skiplines, int skipcolumns, int MatrixNr); 54 virtual bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns); 55 bool AllocateMatrix(char *GivenHeader, int MCounter, int *RCounter, int CCounter); 56 bool ResetMatrix(); 57 double FindMinValue(); 58 double FindMaxValue(); 59 bool SetLastMatrix(double value, int skipcolumns); 60 bool SetLastMatrix(double **values, int skipcolumns); 61 //bool ParseIndices(); 62 //bool SumSubValues(); 63 bool SumSubManyBodyTerms(class MatrixContainer &Matrix, class KeySetsContainer &KeySet, int Order); 64 bool WriteTotalFragments(const char *name, const char *prefix); 65 bool WriteLastMatrix(const char *name, const char *prefix, const char *suffix); 66 }; 67 67 68 68 // ======================================= CLASS EnergyMatrix ============================= 69 69 70 70 class EnergyMatrix : public MatrixContainer { 71 public:72 bool ParseIndices();73 bool SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign);74 bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);71 public: 72 bool ParseIndices(); 73 bool SumSubEnergy(class EnergyMatrix &Fragments, class EnergyMatrix *CorrectionFragments, class KeySetsContainer &KeySet, int Order, double sign); 74 bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns); 75 75 }; 76 76 … … 78 78 79 79 class ForceMatrix : public MatrixContainer { 80 public: 81 bool ParseIndices(char *name);82 bool SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign);83 bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns);80 public: 81 bool ParseIndices(char *name); 82 bool SumSubForces(class ForceMatrix &Fragments, class KeySetsContainer &KeySet, int Order, double sign); 83 bool ParseFragmentMatrix(char *name, char *prefix, string suffix, int skiplines, int skipcolumns); 84 84 }; 85 85 … … 87 87 88 88 class KeySetsContainer { 89 public:90 int **KeySets;91 int *AtomCounter;92 int FragmentCounter;93 int Order;94 int *FragmentsPerOrder;95 int **OrderSet;96 97 KeySetsContainer();98 ~KeySetsContainer();99 100 bool ParseKeySets(const char *name, const int *ACounter, const int FCounter);101 bool ParseManyBodyTerms();102 bool Contains(const int GreaterSet, const int SmallerSet);89 public: 90 int **KeySets; 91 int *AtomCounter; 92 int FragmentCounter; 93 int Order; 94 int *FragmentsPerOrder; 95 int **OrderSet; 96 97 KeySetsContainer(); 98 ~KeySetsContainer(); 99 100 bool ParseKeySets(const char *name, const int *ACounter, const int FCounter); 101 bool ParseManyBodyTerms(); 102 bool Contains(const int GreaterSet, const int SmallerSet); 103 103 }; 104 104 -
Property mode
changed from
-
src/periodentafel.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 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; 23 end->next = NULL;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 end->next = NULL; 24 24 }; 25 25 … … 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 { 42 pointer->sort = &pointer->Z;43 if (pointer->Z < 1 && pointer->Z >= MAX_ELEMENTS)44 cout << Verbose(0) << "Invalid Z number!\n";45 return add(pointer, end); 40 bool periodentafel::AddElement(element *pointer) 41 { 42 pointer->sort = &pointer->Z; 43 if (pointer->Z < 1 && pointer->Z >= MAX_ELEMENTS) 44 cout << Verbose(0) << "Invalid Z number!\n"; 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 … … 70 70 element * periodentafel::FindElement(int Z) 71 71 { 72 element *walker = find(&Z, start,end);73 if (walker == NULL) { // not found: enter and put into db74 cout << Verbose(0) << "Element not found in database, please enter." << endl;75 walker = new element;76 cout << Verbose(0) << "Mass: " << endl;77 cin >> walker->mass;78 walker->Z = Z; 79 cout << Verbose(0) << "Atomic number: " << walker->Z << endl; 80 cout << Verbose(0) << "Name [max 64 chars]: " << endl;81 cin >> walker->name;82 cout << Verbose(0) << "Short form [max 3 chars]: " << endl;83 cin >> walker->symbol;84 periodentafel::AddElement(walker);85 }86 return(walker);72 element *walker = find(&Z, start,end); 73 if (walker == NULL) { // not found: enter and put into db 74 cout << Verbose(0) << "Element not found in database, please enter." << endl; 75 walker = new element; 76 cout << Verbose(0) << "Mass: " << endl; 77 cin >> walker->mass; 78 walker->Z = Z; 79 cout << Verbose(0) << "Atomic number: " << walker->Z << endl; 80 cout << Verbose(0) << "Name [max 64 chars]: " << endl; 81 cin >> walker->name; 82 cout << Verbose(0) << "Short form [max 3 chars]: " << endl; 83 cin >> walker->symbol; 84 periodentafel::AddElement(walker); 85 } 86 return(walker); 87 87 }; 88 88 … … 94 94 element * periodentafel::FindElement(char *shorthand) const 95 95 { 96 element *walker =periodentafel::start;97 while (walker->next != periodentafel::end) {98 walker = walker->next;99 if (strncmp(walker->symbol, shorthand, 3) == 0)100 return(walker);101 }102 return (NULL);96 element *walker = periodentafel::start; 97 while (walker->next != periodentafel::end) { 98 walker = walker->next; 99 if (strncmp(walker->symbol, shorthand, 3) == 0) 100 return(walker); 101 } 102 return (NULL); 103 103 }; 104 104 105 105 /** Asks for element number and returns pointer to element 106 106 */ 107 element * periodentafel::AskElement() 108 { 109 element *walker = NULL; 110 int Z; 111 do { 112 cout << Verbose(0) << "Atomic number Z: "; 113 cin >> Z; 114 walker = this->FindElement(Z); // give type 115 } while (walker == NULL); 116 return walker; 117 }; 118 107 element * periodentafel::AskElement() 108 { 109 element *walker = NULL; 110 int Z; 111 do { 112 cout << Verbose(0) << "Atomic number Z: "; 113 cin >> Z; 114 walker = this->FindElement(Z); // give type 115 } while (walker == NULL); 116 return walker; 117 }; 119 118 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 { 125 bool result = true;126 element *walker = start;127 if (output != NULL) {128 while (walker->next != end) {129 walker = walker->next;130 result = result && walker->Output(output);131 }132 return result;133 } else 134 return false;124 bool result = true; 125 element *walker = start; 126 if (output != NULL) { 127 while (walker->next != end) { 128 walker = walker->next; 129 result = result && walker->Output(output); 130 } 131 return result; 132 } else 133 return false; 135 134 }; 136 135 … … 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 { 143 element *walker = start; 144 bool result = true; 145 int No = 1; 146 147 if (output != NULL) { 148 *output << "# Ion type data (PP = PseudoPotential, Z = atomic number)" << endl; 149 *output << "#Ion_TypeNr.\tAmount\tZ\tRGauss\tL_Max(PP)L_Loc(PP)IonMass\t# chemical name, symbol" << endl; 150 while (walker->next != end) { 151 walker = walker->next; 152 if ((walker != NULL) && (walker->Z > 0) && (walker->Z < MAX_ELEMENTS) && (checkliste[walker->Z])) { 153 walker->No = No; 154 result = result && walker->Checkout(output, No++, checkliste[walker->Z]); 155 } 156 } 157 return result; 158 } else 159 return false; 160 }; 161 142 element *walker = start; 143 bool result = true; 144 int No = 1; 145 146 if (output != NULL) { 147 *output << "# Ion type data (PP = PseudoPotential, Z = atomic number)" << endl; 148 *output << "#Ion_TypeNr.\tAmount\tZ\tRGauss\tL_Max(PP)L_Loc(PP)IonMass\t# chemical name, symbol" << endl; 149 while (walker->next != end) { 150 walker = walker->next; 151 if ((walker != NULL) && (walker->Z > 0) && (walker->Z < MAX_ELEMENTS) && (checkliste[walker->Z])) { 152 walker->No = No; 153 result = result && walker->Checkout(output, No++, checkliste[walker->Z]); 154 } 155 } 156 return result; 157 } else 158 return false; 159 }; 162 160 163 161 /** Loads element list from file. … … 166 164 bool periodentafel::LoadPeriodentafel(char *path) 167 165 { 168 ifstream infile;169 double tmp;170 element *ptr;171 bool status = true;172 bool otherstatus = true;173 char *filename = new char[MAXSTRINGSIZE];174 175 // fill elements DB176 strncpy(filename, path, MAXSTRINGSIZE);177 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));178 strncat(filename, STANDARDELEMENTSDB, MAXSTRINGSIZE-strlen(filename));179 infile.open(filename);180 if (infile != NULL) {181 infile.getline(header1, MAXSTRINGSIZE);182 infile.getline(header2, MAXSTRINGSIZE); // skip first two header lines183 cout <<"Parsed elements:";184 while (!infile.eof()) {185 element *neues = new element;186 infile >> neues->name;187 //infile >> ws;188 infile >> neues->symbol;189 //infile >> ws;190 infile >> neues->period;191 //infile >> ws;192 infile >> neues->group;193 //infile >> ws;194 infile >> neues->block;195 //infile >> ws;196 infile >> neues->Z;197 //infile >> ws;198 infile >> neues->mass;199 //infile >> ws;200 infile >> neues->CovalentRadius;201 //infile >> ws;202 infile >> neues->VanDerWaalsRadius;203 //infile >> ws;204 infile >> ws;205 cout << " " << neues->symbol;206 //neues->Output((ofstream *)&cout);207 if ((neues->Z > 0) && (neues->Z < MAX_ELEMENTS))208 periodentafel::AddElement(neues);209 else {210 cout << "Could not parse element: ";211 neues->Output((ofstream *)&cout);212 }213 }214 cout << endl;215 infile.close();216 infile.clear();217 } else218 status = false;219 220 // fill valence DB per element221 strncpy(filename, path, MAXSTRINGSIZE);222 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));223 strncat(filename, STANDARDVALENCEDB, MAXSTRINGSIZE-strlen(filename));224 infile.open(filename);225 if (infile != NULL) {226 while (!infile.eof()) {227 infile >> tmp;228 infile >> ws;229 infile >> FindElement((int)tmp)->Valence;230 infile >> ws;231 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->Valence << " valence electrons." << endl;232 }233 infile.close();234 infile.clear();235 } else236 otherstatus = false;237 238 // fill valence DB per element239 strncpy(filename, path, MAXSTRINGSIZE);240 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));241 strncat(filename, STANDARDORBITALDB, MAXSTRINGSIZE-strlen(filename));242 infile.open(filename);243 if (infile != NULL) {244 while (!infile.eof()) {245 infile >> tmp;246 infile >> ws;247 infile >> FindElement((int)tmp)->NoValenceOrbitals;248 infile >> ws;249 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->NoValenceOrbitals << " number of singly occupied valence orbitals." << endl;250 }251 infile.close();252 infile.clear();253 } else254 otherstatus = false;255 256 // fill H-BondDistance DB per element257 strncpy(filename, path, MAXSTRINGSIZE);258 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));259 strncat(filename, STANDARDHBONDDISTANCEDB, MAXSTRINGSIZE-strlen(filename));260 infile.open(filename);261 if (infile != NULL) {262 while (!infile.eof()) {263 infile >> tmp;264 ptr = FindElement((int)tmp);265 infile >> ws;266 infile >> ptr->HBondDistance[0];267 infile >> ptr->HBondDistance[1];268 infile >> ptr->HBondDistance[2];269 infile >> ws;270 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->HBondDistance[0] << " Angstrom typical distance to hydrogen." << endl;271 }272 infile.close();273 infile.clear();274 } else275 otherstatus = false;276 277 // fill H-BondAngle DB per element278 strncpy(filename, path, MAXSTRINGSIZE);279 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));280 strncat(filename, STANDARDHBONDANGLEDB, MAXSTRINGSIZE-strlen(filename));281 infile.open(filename);282 if (infile != NULL) {283 while (!infile.eof()) {284 infile >> tmp;285 ptr = FindElement((int)tmp);286 infile >> ws;287 infile >> ptr->HBondAngle[0];288 infile >> ptr->HBondAngle[1];289 infile >> ptr->HBondAngle[2];290 infile >> ws;291 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->HBondAngle[0] << ", " << FindElement((int)tmp)->HBondAngle[1] << ", " << FindElement((int)tmp)->HBondAngle[2] << " degrees bond angle for one, two, three connected hydrogens." << endl;292 }293 infile.close();294 } else295 otherstatus = false;296 297 if (!otherstatus)298 cerr << "WARNING: Something went wrong while parsing the other databases!" << endl;299 300 return status;166 ifstream infile; 167 double tmp; 168 element *ptr; 169 bool status = true; 170 bool otherstatus = true; 171 char filename[255]; 172 173 // fill elements DB 174 strncpy(filename, path, MAXSTRINGSIZE); 175 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename)); 176 strncat(filename, STANDARDELEMENTSDB, MAXSTRINGSIZE-strlen(filename)); 177 infile.open(filename); 178 if (infile != NULL) { 179 infile.getline(header1, MAXSTRINGSIZE); 180 infile.getline(header2, MAXSTRINGSIZE); // skip first two header lines 181 cout << "Parsed elements:"; 182 while (!infile.eof()) { 183 element *neues = new element; 184 infile >> neues->name; 185 //infile >> ws; 186 infile >> neues->symbol; 187 //infile >> ws; 188 infile >> neues->period; 189 //infile >> ws; 190 infile >> neues->group; 191 //infile >> ws; 192 infile >> neues->block; 193 //infile >> ws; 194 infile >> neues->Z; 195 //infile >> ws; 196 infile >> neues->mass; 197 //infile >> ws; 198 infile >> neues->CovalentRadius; 199 //infile >> ws; 200 infile >> neues->VanDerWaalsRadius; 201 //infile >> ws; 202 infile >> ws; 203 cout << " " << neues->symbol; 204 //neues->Output((ofstream *)&cout); 205 if ((neues->Z > 0) && (neues->Z < MAX_ELEMENTS)) 206 periodentafel::AddElement(neues); 207 else { 208 cout << "Could not parse element: "; 209 neues->Output((ofstream *)&cout); 210 } 211 } 212 cout << endl; 213 infile.close(); 214 infile.clear(); 215 } else 216 status = false; 217 218 // fill valence DB per element 219 strncpy(filename, path, MAXSTRINGSIZE); 220 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename)); 221 strncat(filename, STANDARDVALENCEDB, MAXSTRINGSIZE-strlen(filename)); 222 infile.open(filename); 223 if (infile != NULL) { 224 while (!infile.eof()) { 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; 230 } 231 infile.close(); 232 infile.clear(); 233 } else 234 otherstatus = false; 235 236 // fill valence DB per element 237 strncpy(filename, path, MAXSTRINGSIZE); 238 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename)); 239 strncat(filename, STANDARDORBITALDB, MAXSTRINGSIZE-strlen(filename)); 240 infile.open(filename); 241 if (infile != NULL) { 242 while (!infile.eof()) { 243 infile >> tmp; 244 infile >> ws; 245 infile >> FindElement((int)tmp)->NoValenceOrbitals; 246 infile >> ws; 247 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->NoValenceOrbitals << " number of singly occupied valence orbitals." << endl; 248 } 249 infile.close(); 250 infile.clear(); 251 } else 252 otherstatus = false; 253 254 // fill H-BondDistance DB per element 255 strncpy(filename, path, MAXSTRINGSIZE); 256 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename)); 257 strncat(filename, STANDARDHBONDDISTANCEDB, MAXSTRINGSIZE-strlen(filename)); 258 infile.open(filename); 259 if (infile != NULL) { 260 while (!infile.eof()) { 261 infile >> tmp; 262 ptr = FindElement((int)tmp); 263 infile >> ws; 264 infile >> ptr->HBondDistance[0]; 265 infile >> ptr->HBondDistance[1]; 266 infile >> ptr->HBondDistance[2]; 267 infile >> ws; 268 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->HBondDistance[0] << " Angstrom typical distance to hydrogen." << endl; 269 } 270 infile.close(); 271 infile.clear(); 272 } else 273 otherstatus = false; 274 275 // fill H-BondAngle DB per element 276 strncpy(filename, path, MAXSTRINGSIZE); 277 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename)); 278 strncat(filename, STANDARDHBONDANGLEDB, MAXSTRINGSIZE-strlen(filename)); 279 infile.open(filename); 280 if (infile != NULL) { 281 while (!infile.eof()) { 282 infile >> tmp; 283 ptr = FindElement((int)tmp); 284 infile >> ws; 285 infile >> ptr->HBondAngle[0]; 286 infile >> ptr->HBondAngle[1]; 287 infile >> ptr->HBondAngle[2]; 288 infile >> ws; 289 //cout << Verbose(3) << "Element " << (int)tmp << " has " << FindElement((int)tmp)->HBondAngle[0] << ", " << FindElement((int)tmp)->HBondAngle[1] << ", " << FindElement((int)tmp)->HBondAngle[2] << " degrees bond angle for one, two, three connected hydrogens." << endl; 290 } 291 infile.close(); 292 } else 293 otherstatus = false; 294 295 if (!otherstatus) 296 cerr << "WARNING: Something went wrong while parsing the other databases!" << endl; 297 298 return status; 301 299 }; 302 300 … … 305 303 bool periodentafel::StorePeriodentafel(char *path) const 306 304 { 307 bool result = true;308 ofstream f;309 char filename[MAXSTRINGSIZE];310 311 strncpy(filename, path, MAXSTRINGSIZE);312 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename));313 strncat(filename, STANDARDELEMENTSDB, MAXSTRINGSIZE-strlen(filename));314 f.open(filename);315 if (f != NULL) {316 f << header1 << endl;317 f << header2 << endl;318 element *walker = periodentafel::start;319 while (walker->next != periodentafel::end) {320 walker = walker->next;321 result = result && walker->Output(&f);322 }323 f.close();324 } else325 result = false;326 return result;327 }; 305 bool result = true; 306 ofstream f; 307 char filename[MAXSTRINGSIZE]; 308 309 strncpy(filename, path, MAXSTRINGSIZE); 310 strncat(filename, "/", MAXSTRINGSIZE-strlen(filename)); 311 strncat(filename, STANDARDELEMENTSDB, MAXSTRINGSIZE-strlen(filename)); 312 f.open(filename); 313 if (f != NULL) { 314 f << header1 << endl; 315 f << header2 << endl; 316 element *walker = periodentafel::start; 317 while (walker->next != periodentafel::end) { 318 walker = walker->next; 319 result = result && walker->Output(&f); 320 } 321 f.close(); 322 } else 323 result = false; 324 return result; 325 }; -
Property mode
changed from
-
src/periodentafel.hpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 21 21 */ 22 22 class element { 23 public:24 double mass;//!< mass in g/mol25 double CovalentRadius;//!< covalent radius26 double VanDerWaalsRadius;//!< can-der-Waals radius27 int Z;//!< atomic number28 char name[64];//!< atom name, i.e. "Hydrogren"29 char symbol[3]; //!< short form of the atom, i.e. "H"30 char period[8];//!< period: n quantum number31 char group[8];//!< group: l quantum number32 char block[8];//!< block: l quantum number33 element *previous;//!< previous item in list34 element *next;//!< next element in list35 int *sort;//!< sorc criteria36 int No;//!< number of element set on periodentafel::Output()37 double Valence;//!< number of valence electrons for this element38 int NoValenceOrbitals;//!< number of valence orbitals, used for determining bond degree in molecule::CreateConnectmatrix()39 double HBondDistance[NDIM]; //!< distance in Angstrom of this element to hydrogen(for single, double and triple bonds)40 double HBondAngle[NDIM];//!< typical angle for one, two, three bonded hydrogen (in degrees)23 public: 24 double mass; //!< mass in g/mol 25 double CovalentRadius; //!< covalent radius 26 double VanDerWaalsRadius; //!< can-der-Waals radius 27 int Z; //!< atomic number 28 char name[64]; //!< atom name, i.e. "Hydrogren" 29 char symbol[3]; //!< short form of the atom, i.e. "H" 30 char period[8]; //!< period: n quantum number 31 char group[8]; //!< group: l quantum number 32 char block[8]; //!< block: l quantum number 33 element *previous; //!< previous item in list 34 element *next; //!< next element in list 35 int *sort; //!< sorc criteria 36 int No; //!< number of element set on periodentafel::Output() 37 double Valence; //!< number of valence electrons for this element 38 int NoValenceOrbitals; //!< number of valence orbitals, used for determining bond degree in molecule::CreateConnectmatrix() 39 double HBondDistance[NDIM]; //!< distance in Angstrom of this element to hydrogen (for single, double and triple bonds) 40 double HBondAngle[NDIM]; //!< typical angle for one, two, three bonded hydrogen (in degrees) 41 41 42 element();43 ~element();42 element(); 43 ~element(); 44 44 45 //> print element entries to screen46 bool Output(ofstream *out) const;47 bool Checkout(ofstream *out, const int No, const int NoOfAtoms) const;48 49 private:45 //> print element entries to screen 46 bool Output(ofstream *out) const; 47 bool Checkout(ofstream *out, const int No, const int NoOfAtoms) const; 48 49 private: 50 50 }; 51 51 … … 53 53 */ 54 54 class periodentafel { 55 public:56 element *start; //!< start of element list57 element *end;//!< end of element list58 char header1[MAXSTRINGSIZE]; //!< store first header line59 char header2[MAXSTRINGSIZE]; //!< store second header line60 61 periodentafel();62 ~periodentafel(); 63 64 bool AddElement(element *pointer);65 bool RemoveElement(element *pointer);66 bool CleanupPeriodtable();67 element * FindElement(int Z);68 element * FindElement(char *shorthand) const;69 element * AskElement(); 70 bool Output(ofstream *output) const;71 bool Checkout(ofstream *output, const int *checkliste) const;72 bool LoadPeriodentafel(char *path = NULL);73 bool StorePeriodentafel(char *path = NULL) const;74 75 private:55 public: 56 element *start; //!< start of element list 57 element *end; //!< end of element list 58 char header1[MAXSTRINGSIZE]; //!< store first header line 59 char header2[MAXSTRINGSIZE]; //!< store second header line 60 61 periodentafel(); 62 ~periodentafel(); 63 64 bool AddElement(element *pointer); 65 bool RemoveElement(element *pointer); 66 bool CleanupPeriodtable(); 67 element * FindElement(int Z); 68 element * FindElement(char *shorthand) const; 69 element * AskElement(); 70 bool Output(ofstream *output) const; 71 bool Checkout(ofstream *output, const int *checkliste) const; 72 bool LoadPeriodentafel(char *path = NULL); 73 bool StorePeriodentafel(char *path = NULL) const; 74 75 private: 76 76 }; 77 77 -
Property mode
changed from
-
src/stackclass.hpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 10 10 */ 11 11 template <typename T> class StackClass { 12 public:13 StackClass<T>(int dimension);14 ~StackClass<T>();15 16 bool Push(T object);17 T PopFirst();18 T PopLast();19 bool RemoveItem(T ptr);20 void ClearStack();21 bool IsEmpty();22 bool IsFull();23 int ItemCount();24 void Output(ofstream *out) const;25 void TestImplementation(ofstream *out, T test);26 27 private:28 T *StackList;//!< the list containing the atom pointers29 int EntryCount;//!< number of entries in the stack30 int CurrentLastEntry;//!< Current last entry (newest item on stack)31 int CurrentFirstEntry;//!< Current first entry (oldest item on stack)32 int NextFreeField;//!< Current index of next free field12 public: 13 StackClass<T>(int dimension); 14 ~StackClass<T>(); 15 16 bool Push(T object); 17 T PopFirst(); 18 T PopLast(); 19 bool RemoveItem(T ptr); 20 void ClearStack(); 21 bool IsEmpty(); 22 bool IsFull(); 23 int ItemCount(); 24 void Output(ofstream *out) const; 25 void TestImplementation(ofstream *out, T test); 26 27 private: 28 T *StackList; //!< the list containing the atom pointers 29 int EntryCount; //!< number of entries in the stack 30 int CurrentLastEntry; //!< Current last entry (newest item on stack) 31 int CurrentFirstEntry; //!< Current first entry (oldest item on stack) 32 int NextFreeField; //!< Current index of next free field 33 33 }; 34 34 … … 37 37 template <typename T> StackClass<T>::StackClass(int dimension) 38 38 { 39 CurrentLastEntry = 0;40 CurrentFirstEntry = 0;41 NextFreeField = 0;42 EntryCount = dimension;43 StackList = (T *) Malloc(sizeof(T)*EntryCount, "StackClass::StackClass: **StackList");39 CurrentLastEntry = 0; 40 CurrentFirstEntry = 0; 41 NextFreeField = 0; 42 EntryCount = dimension; 43 StackList = (T *) Malloc(sizeof(T)*EntryCount, "StackClass::StackClass: **StackList"); 44 44 }; 45 45 … … 48 48 template <typename T> StackClass<T>::~StackClass() 49 49 { 50 Free((void **)&StackList, "StackClass::StackClass: **StackList");50 Free((void **)&StackList, "StackClass::StackClass: **StackList"); 51 51 }; 52 52 … … 57 57 template <typename T> bool StackClass<T>::Push(T object) 58 58 { 59 if (!IsFull()) {// check whether free field is really not occupied60 StackList[NextFreeField] = object;61 CurrentLastEntry = NextFreeField;62 NextFreeField = (NextFreeField + 1) % EntryCount; // step on to next free field63 return true;64 } else {65 cerr << "ERROR: Stack is full, " << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tNextFreeField " << NextFreeField << "\tEntryCount " << EntryCount << "!" << endl;66 return false;67 }59 if (!IsFull()) { // check whether free field is really not occupied 60 StackList[NextFreeField] = object; 61 CurrentLastEntry = NextFreeField; 62 NextFreeField = (NextFreeField + 1) % EntryCount; // step on to next free field 63 return true; 64 } else { 65 cerr << "ERROR: Stack is full, " << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tNextFreeField " << NextFreeField << "\tEntryCount " << EntryCount << "!" << endl; 66 return false; 67 } 68 68 }; 69 69 … … 74 74 template <typename T> T StackClass<T>::PopFirst() 75 75 { 76 T Walker = NULL;77 if (!IsEmpty()) {78 Walker = StackList[CurrentFirstEntry];79 if (Walker == NULL)80 cerr << "ERROR: Stack's field is empty!" << endl;81 StackList[CurrentFirstEntry] = NULL;82 if (CurrentFirstEntry != CurrentLastEntry) { // hasn't last item been popped as well?83 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)84 } else {85 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1)86 CurrentLastEntry = CurrentFirstEntry;87 }88 } else89 cerr << "ERROR: Stack is empty!" << endl; 90 return Walker;76 T Walker = NULL; 77 if (!IsEmpty()) { 78 Walker = StackList[CurrentFirstEntry]; 79 if (Walker == NULL) 80 cerr << "ERROR: Stack's field is empty!" << endl; 81 StackList[CurrentFirstEntry] = NULL; 82 if (CurrentFirstEntry != CurrentLastEntry) { // hasn't last item been popped as well? 83 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1) 84 } else { 85 CurrentFirstEntry = (CurrentFirstEntry + 1) % EntryCount; // step back from current free field to last used (somehow modulo does not work in -1) 86 CurrentLastEntry = CurrentFirstEntry; 87 } 88 } else 89 cerr << "ERROR: Stack is empty!" << endl; 90 return Walker; 91 91 }; 92 92 … … 97 97 template <typename T> T StackClass<T>::PopLast() 98 98 { 99 T Walker = NULL;100 if (!IsEmpty()) {101 Walker = StackList[CurrentLastEntry];102 StackList[CurrentLastEntry] = NULL;103 if (Walker == NULL)104 cerr << "ERROR: Stack's field is empty!" << endl;105 NextFreeField = CurrentLastEntry;106 if (CurrentLastEntry != CurrentFirstEntry)// has there been more than one item on stack107 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; // step back from current free field to last (modulo does not work in -1, thus go EntryCount-1 instead)108 } else {109 cerr << "ERROR: Stack is empty!" << endl;110 } 111 return Walker;99 T Walker = NULL; 100 if (!IsEmpty()) { 101 Walker = StackList[CurrentLastEntry]; 102 StackList[CurrentLastEntry] = NULL; 103 if (Walker == NULL) 104 cerr << "ERROR: Stack's field is empty!" << endl; 105 NextFreeField = CurrentLastEntry; 106 if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack 107 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; // step back from current free field to last (modulo does not work in -1, thus go EntryCount-1 instead) 108 } else { 109 cerr << "ERROR: Stack is empty!" << endl; 110 } 111 return Walker; 112 112 }; 113 113 … … 120 120 template <typename T> bool StackClass<T>::RemoveItem(T ptr) 121 121 { 122 bool found = false;123 cout << Verbose(5) << "First " << CurrentFirstEntry<< "\tLast " << CurrentLastEntry<< "\tNext " << NextFreeField<< "\tCount " << EntryCount<< "." << endl;124 int i=CurrentFirstEntry;125 if (!IsEmpty())126 do {127 if (StackList[i] == ptr) {// if item found, remove128 cout << Verbose(5) << "Item " << *ptr << " was number " << i << " on stack, removing it." << endl;129 found = true;130 StackList[i] = NULL;131 }132 if ((found) && (StackList[i] != NULL)) {// means we have to shift (and not the removed item)133 if (i == 0) { // we are down to first item in stack, have to put onto last item134 cout << Verbose(5) << "Shifting item 0 to place " << EntryCount-1 << "." << endl;135 StackList[EntryCount-1] = StackList[0];136 } else {137 cout << Verbose(5) << "Shifting item " << i << " to place " << i-1 << "." << endl;138 StackList[i-1] = StackList[i];139 }140 }141 i=((i + 1) % EntryCount); // step on142 } while (i!=NextFreeField);143 else144 cerr << "ERROR: Stack is already empty!" << endl;145 if (found) {146 NextFreeField = CurrentLastEntry;147 if (CurrentLastEntry != CurrentFirstEntry)// has there been more than one item on stack148 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount;149 }150 return found;122 bool found = false; 123 cout << Verbose(5) << "First " << CurrentFirstEntry<< "\tLast " << CurrentLastEntry<< "\tNext " << NextFreeField<< "\tCount " << EntryCount<< "." << endl; 124 int i=CurrentFirstEntry; 125 if (!IsEmpty()) 126 do { 127 if (StackList[i] == ptr) { // if item found, remove 128 cout << Verbose(5) << "Item " << *ptr << " was number " << i << " on stack, removing it." << endl; 129 found = true; 130 StackList[i] = NULL; 131 } 132 if ((found) && (StackList[i] != NULL)) { // means we have to shift (and not the removed item) 133 if (i == 0) { // we are down to first item in stack, have to put onto last item 134 cout << Verbose(5) << "Shifting item 0 to place " << EntryCount-1 << "." << endl; 135 StackList[EntryCount-1] = StackList[0]; 136 } else { 137 cout << Verbose(5) << "Shifting item " << i << " to place " << i-1 << "." << endl; 138 StackList[i-1] = StackList[i]; 139 } 140 } 141 i=((i + 1) % EntryCount); // step on 142 } while (i!=NextFreeField); 143 else 144 cerr << "ERROR: Stack is already empty!" << endl; 145 if (found) { 146 NextFreeField = CurrentLastEntry; 147 if (CurrentLastEntry != CurrentFirstEntry) // has there been more than one item on stack 148 CurrentLastEntry = (CurrentLastEntry + (EntryCount-1)) % EntryCount; 149 } 150 return found; 151 151 }; 152 152 153 153 /** Test the functionality of the stack. 154 154 * \param *out ofstream for debugging 155 * \param *test one item to put on stack 155 * \param *test one item to put on stack 156 156 * \return true - all tests worked correctly 157 157 */ 158 158 template <typename T> void StackClass<T>::TestImplementation(ofstream *out, T test) 159 159 { 160 T Walker = test;161 *out << Verbose(1) << "Testing the snake stack..." << endl;162 for (int i=0;i<EntryCount;i++) {163 *out << Verbose(2) << "Filling " << i << "th element of stack." << endl; 164 Push(Walker);165 Walker=Walker->next;166 }167 *out << endl;168 Output(out);169 if (IsFull())170 *out << "Stack is full as supposed to be!" << endl;171 else172 *out << "ERROR: Stack is not as full as supposed to be!" << endl;173 //if (StackList[(EntryCount+1)/2] != NULL) {174 *out << "Removing element in the middle ..." << endl;175 RemoveItem(StackList[(EntryCount+1)/2]);176 Output(out);177 //}178 //if (StackList[CurrentFirstEntry] != NULL) {179 *out << "Removing first element..." << endl;180 RemoveItem(StackList[CurrentFirstEntry]);181 Output(out);182 //}183 //if (StackList[CurrentLastEntry] != NULL) {184 *out << "Removing last element ..." << endl;185 RemoveItem(StackList[CurrentLastEntry]);186 Output(out);187 //}188 *out << "Clearing stack ... " << endl; 189 ClearStack();190 Output(out);191 if (IsEmpty())192 *out << "Stack is empty as supposed to be!" << endl;193 else194 *out << "ERROR: Stack is not as empty as supposed to be!" << endl;195 *out << "done." << endl;160 T Walker = test; 161 *out << Verbose(1) << "Testing the snake stack..." << endl; 162 for (int i=0;i<EntryCount;i++) { 163 *out << Verbose(2) << "Filling " << i << "th element of stack." << endl; 164 Push(Walker); 165 Walker=Walker->next; 166 } 167 *out << endl; 168 Output(out); 169 if (IsFull()) 170 *out << "Stack is full as supposed to be!" << endl; 171 else 172 *out << "ERROR: Stack is not as full as supposed to be!" << endl; 173 //if (StackList[(EntryCount+1)/2] != NULL) { 174 *out << "Removing element in the middle ..." << endl; 175 RemoveItem(StackList[(EntryCount+1)/2]); 176 Output(out); 177 //} 178 //if (StackList[CurrentFirstEntry] != NULL) { 179 *out << "Removing first element ..." << endl; 180 RemoveItem(StackList[CurrentFirstEntry]); 181 Output(out); 182 //} 183 //if (StackList[CurrentLastEntry] != NULL) { 184 *out << "Removing last element ..." << endl; 185 RemoveItem(StackList[CurrentLastEntry]); 186 Output(out); 187 //} 188 *out << "Clearing stack ... " << endl; 189 ClearStack(); 190 Output(out); 191 if (IsEmpty()) 192 *out << "Stack is empty as supposed to be!" << endl; 193 else 194 *out << "ERROR: Stack is not as empty as supposed to be!" << endl; 195 *out << "done." << endl; 196 196 }; 197 197 … … 201 201 template <typename T> void StackClass<T>::Output(ofstream *out) const 202 202 { 203 *out << "Contents of Stack: ";204 for(int i=0;i<EntryCount;i++) {205 *out << "\t";206 if (i == CurrentFirstEntry)207 *out << " 1";208 if(i == CurrentLastEntry)209 *out << " "<< EntryCount;210 if (i ==NextFreeField)211 *out << " F";212 *out << ": " << StackList[i];213 }214 *out << endl;203 *out << "Contents of Stack: "; 204 for(int i=0;i<EntryCount;i++) { 205 *out << "\t"; 206 if (i == CurrentFirstEntry) 207 *out << " 1"; 208 if (i == CurrentLastEntry) 209 *out << " "<< EntryCount; 210 if (i == NextFreeField) 211 *out << " F"; 212 *out << ": " << StackList[i]; 213 } 214 *out << endl; 215 215 }; 216 216 … … 222 222 template <typename T> bool StackClass<T>::IsEmpty() 223 223 { 224 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry == CurrentFirstEntry));224 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry == CurrentFirstEntry)); 225 225 }; 226 226 … … 232 232 template <typename T> bool StackClass<T>::IsFull() 233 233 { 234 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry != CurrentFirstEntry));234 return((NextFreeField == CurrentFirstEntry) && (CurrentLastEntry != CurrentFirstEntry)); 235 235 }; 236 236 … … 242 242 template <typename T> int StackClass<T>::ItemCount() 243 243 { 244 //cout << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tEntryCount " << EntryCount << "." << endl;245 return((NextFreeField + (EntryCount - CurrentFirstEntry)) % EntryCount);244 //cout << "Stack: CurrentLastEntry " << CurrentLastEntry<< "\tCurrentFirstEntry " << CurrentFirstEntry << "\tEntryCount " << EntryCount << "." << endl; 245 return((NextFreeField + (EntryCount - CurrentFirstEntry)) % EntryCount); 246 246 }; 247 247 … … 251 251 template <typename T> void StackClass<T>::ClearStack() 252 252 { 253 for(int i=EntryCount; i--;)254 StackList[i] = NULL;255 CurrentFirstEntry = 0;256 CurrentLastEntry = 0;257 NextFreeField = 0;253 for(int i=EntryCount; i--;) 254 StackList[i] = NULL; 255 CurrentFirstEntry = 0; 256 CurrentLastEntry = 0; 257 NextFreeField = 0; 258 258 }; 259 259 -
Property mode
changed from
-
src/valence.db
-
Property mode
changed from
100644to100755
-
Property mode
changed from
-
src/vector.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 28 28 double Vector::DistanceSquared(const Vector *y) const 29 29 { 30 double res = 0.;31 for (int i=NDIM;i--;)32 res += (x[i]-y->x[i])*(x[i]-y->x[i]);33 return (res);30 double res = 0.; 31 for (int i=NDIM;i--;) 32 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 33 return (res); 34 34 }; 35 35 … … 40 40 double Vector::Distance(const Vector *y) const 41 41 { 42 double res = 0.; 43 for (int i=NDIM;i--;) 44 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 45 return (sqrt(res)); 42 double res = 0.; 43 for (int i=NDIM;i--;) 44 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 45 return (sqrt(res)); 46 }; 47 48 /** Calculates distance between this and another vector in a periodic cell. 49 * \param *y array to second vector 50 * \param *cell_size 6-dimensional array with (xx, xy, yy, xz, yz, zz) entries specifying the periodic cell 51 * \return \f$| x - y |\f$ 52 */ 53 double Vector::PeriodicDistance(const Vector *y, const double *cell_size) const 54 { 55 double res = Distance(y), tmp, matrix[NDIM*NDIM]; 56 Vector Shiftedy, TranslationVector; 57 int N[NDIM]; 58 matrix[0] = cell_size[0]; 59 matrix[1] = cell_size[1]; 60 matrix[2] = cell_size[3]; 61 matrix[3] = cell_size[1]; 62 matrix[4] = cell_size[2]; 63 matrix[5] = cell_size[4]; 64 matrix[6] = cell_size[3]; 65 matrix[7] = cell_size[4]; 66 matrix[8] = cell_size[5]; 67 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells 68 for (N[0]=-1;N[0]<=1;N[0]++) 69 for (N[1]=-1;N[1]<=1;N[1]++) 70 for (N[2]=-1;N[2]<=1;N[2]++) { 71 // create the translation vector 72 TranslationVector.Zero(); 73 for (int i=NDIM;i--;) 74 TranslationVector.x[i] = (double)N[i]; 75 TranslationVector.MatrixMultiplication(matrix); 76 // add onto the original vector to compare with 77 Shiftedy.CopyVector(y); 78 Shiftedy.AddVector(&TranslationVector); 79 // get distance and compare with minimum so far 80 tmp = Distance(&Shiftedy); 81 if (tmp < res) res = tmp; 82 } 83 return (res); 46 84 }; 47 85 … … 51 89 * \return \f$| x - y |^2\f$ 52 90 */ 53 double Vector::PeriodicDistance (const Vector *y, const double *cell_size) const54 { 55 double res = Distance(y), tmp, matrix[NDIM*NDIM];56 Vector Shiftedy, TranslationVector;57 int N[NDIM];58 matrix[0] = cell_size[0];59 matrix[1] = cell_size[1];60 matrix[2] = cell_size[3];61 matrix[3] = cell_size[1];62 matrix[4] = cell_size[2];63 matrix[5] = cell_size[4];64 matrix[6] = cell_size[3];65 matrix[7] = cell_size[4];66 matrix[8] = cell_size[5];67 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells68 for (N[0]=-1;N[0]<=1;N[0]++)69 for (N[1]=-1;N[1]<=1;N[1]++)70 for (N[2]=-1;N[2]<=1;N[2]++) {71 // create the translation vector72 TranslationVector.Zero();73 for (int i=NDIM;i--;)74 TranslationVector.x[i] = (double)N[i];75 TranslationVector.MatrixMultiplication(matrix);76 // add onto the original vector to compare with77 Shiftedy.CopyVector(y);78 Shiftedy.AddVector(&TranslationVector);79 // get distance and compare with minimum so far80 tmp = Distance(&Shiftedy);81 if (tmp < res) res = tmp;82 }83 return (res);91 double Vector::PeriodicDistanceSquared(const Vector *y, const double *cell_size) const 92 { 93 double res = DistanceSquared(y), tmp, matrix[NDIM*NDIM]; 94 Vector Shiftedy, TranslationVector; 95 int N[NDIM]; 96 matrix[0] = cell_size[0]; 97 matrix[1] = cell_size[1]; 98 matrix[2] = cell_size[3]; 99 matrix[3] = cell_size[1]; 100 matrix[4] = cell_size[2]; 101 matrix[5] = cell_size[4]; 102 matrix[6] = cell_size[3]; 103 matrix[7] = cell_size[4]; 104 matrix[8] = cell_size[5]; 105 // in order to check the periodic distance, translate one of the vectors into each of the 27 neighbouring cells 106 for (N[0]=-1;N[0]<=1;N[0]++) 107 for (N[1]=-1;N[1]<=1;N[1]++) 108 for (N[2]=-1;N[2]<=1;N[2]++) { 109 // create the translation vector 110 TranslationVector.Zero(); 111 for (int i=NDIM;i--;) 112 TranslationVector.x[i] = (double)N[i]; 113 TranslationVector.MatrixMultiplication(matrix); 114 // add onto the original vector to compare with 115 Shiftedy.CopyVector(y); 116 Shiftedy.AddVector(&TranslationVector); 117 // get distance and compare with minimum so far 118 tmp = DistanceSquared(&Shiftedy); 119 if (tmp < res) res = tmp; 120 } 121 return (res); 84 122 }; 85 123 … … 90 128 void Vector::KeepPeriodic(ofstream *out, double *matrix) 91 129 { 92 // int N[NDIM];93 // bool flag = false;94 //vector Shifted, TranslationVector;95 Vector TestVector;96 // *out << Verbose(1) << "Begin of KeepPeriodic." << endl;97 // *out << Verbose(2) << "Vector is: ";98 // Output(out);99 // *out << endl;100 TestVector.CopyVector(this);101 TestVector.InverseMatrixMultiplication(matrix);102 for(int i=NDIM;i--;) { // correct periodically103 if (TestVector.x[i] < 0) {// get every coefficient into the interval [0,1)104 TestVector.x[i] += ceil(TestVector.x[i]);105 } else {106 TestVector.x[i] -= floor(TestVector.x[i]);107 }108 }109 TestVector.MatrixMultiplication(matrix);110 CopyVector(&TestVector);111 // *out << Verbose(2) << "New corrected vector is: ";112 // Output(out);113 // *out << endl;114 // *out << Verbose(1) << "End of KeepPeriodic." << endl;130 // int N[NDIM]; 131 // bool flag = false; 132 //vector Shifted, TranslationVector; 133 Vector TestVector; 134 // *out << Verbose(1) << "Begin of KeepPeriodic." << endl; 135 // *out << Verbose(2) << "Vector is: "; 136 // Output(out); 137 // *out << endl; 138 TestVector.CopyVector(this); 139 TestVector.InverseMatrixMultiplication(matrix); 140 for(int i=NDIM;i--;) { // correct periodically 141 if (TestVector.x[i] < 0) { // get every coefficient into the interval [0,1) 142 TestVector.x[i] += ceil(TestVector.x[i]); 143 } else { 144 TestVector.x[i] -= floor(TestVector.x[i]); 145 } 146 } 147 TestVector.MatrixMultiplication(matrix); 148 CopyVector(&TestVector); 149 // *out << Verbose(2) << "New corrected vector is: "; 150 // Output(out); 151 // *out << endl; 152 // *out << Verbose(1) << "End of KeepPeriodic." << endl; 115 153 }; 116 154 … … 121 159 double Vector::ScalarProduct(const Vector *y) const 122 160 { 123 double res = 0.;124 for (int i=NDIM;i--;)125 res += x[i]*y->x[i];126 return (res);161 double res = 0.; 162 for (int i=NDIM;i--;) 163 res += x[i]*y->x[i]; 164 return (res); 127 165 }; 128 166 129 167 130 168 /** Calculates VectorProduct between this and another vector. 131 * -# returns the Product in place of vector from which it was initiated132 * -# ATTENTION: Only three dim.133 * \param *y array to vector with which to calculate crossproduct134 * \return \f$ x \times y \f&169 * -# returns the Product in place of vector from which it was initiated 170 * -# ATTENTION: Only three dim. 171 * \param *y array to vector with which to calculate crossproduct 172 * \return \f$ x \times y \f& 135 173 */ 136 174 void Vector::VectorProduct(const Vector *y) 137 175 { 138 Vector tmp;139 tmp.x[0] = x[1]* (y->x[2]) - x[2]* (y->x[1]);140 tmp.x[1] = x[2]* (y->x[0]) - x[0]* (y->x[2]);141 tmp.x[2] = x[0]* (y->x[1]) - x[1]* (y->x[0]);142 this->CopyVector(&tmp);176 Vector tmp; 177 tmp.x[0] = x[1]* (y->x[2]) - x[2]* (y->x[1]); 178 tmp.x[1] = x[2]* (y->x[0]) - x[0]* (y->x[2]); 179 tmp.x[2] = x[0]* (y->x[1]) - x[1]* (y->x[0]); 180 this->CopyVector(&tmp); 143 181 144 182 }; … … 151 189 void Vector::ProjectOntoPlane(const Vector *y) 152 190 { 153 Vector tmp;154 tmp.CopyVector(y);155 tmp.Normalize();156 tmp.Scale(ScalarProduct(&tmp));157 this->SubtractVector(&tmp);191 Vector tmp; 192 tmp.CopyVector(y); 193 tmp.Normalize(); 194 tmp.Scale(ScalarProduct(&tmp)); 195 this->SubtractVector(&tmp); 158 196 }; 159 197 … … 164 202 double Vector::Projection(const Vector *y) const 165 203 { 166 return (ScalarProduct(y));204 return (ScalarProduct(y)); 167 205 }; 168 206 … … 172 210 double Vector::Norm() const 173 211 { 174 double res = 0.;175 for (int i=NDIM;i--;)176 res += this->x[i]*this->x[i];177 return (sqrt(res));212 double res = 0.; 213 for (int i=NDIM;i--;) 214 res += this->x[i]*this->x[i]; 215 return (sqrt(res)); 178 216 }; 179 217 … … 182 220 void Vector::Normalize() 183 221 { 184 double res = 0.;185 for (int i=NDIM;i--;)186 res += this->x[i]*this->x[i];187 if (fabs(res) > MYEPSILON)188 res = 1./sqrt(res);189 Scale(&res);222 double res = 0.; 223 for (int i=NDIM;i--;) 224 res += this->x[i]*this->x[i]; 225 if (fabs(res) > MYEPSILON) 226 res = 1./sqrt(res); 227 Scale(&res); 190 228 }; 191 229 … … 194 232 void Vector::Zero() 195 233 { 196 for (int i=NDIM;i--;)197 this->x[i] = 0.;234 for (int i=NDIM;i--;) 235 this->x[i] = 0.; 198 236 }; 199 237 … … 202 240 void Vector::One(double one) 203 241 { 204 for (int i=NDIM;i--;)205 this->x[i] = one;242 for (int i=NDIM;i--;) 243 this->x[i] = one; 206 244 }; 207 245 … … 210 248 void Vector::Init(double x1, double x2, double x3) 211 249 { 212 x[0] = x1;213 x[1] = x2;214 x[2] = x3;250 x[0] = x1; 251 x[1] = x2; 252 x[2] = x3; 215 253 }; 216 254 … … 219 257 * \return \f$\acos\bigl(frac{\langle x, y \rangle}{|x||y|}\bigr)\f$ 220 258 */ 221 double Vector::Angle( Vector *y) const222 { 223 return acos(this->ScalarProduct(y)/Norm()/y->Norm());259 double Vector::Angle(const Vector *y) const 260 { 261 return acos(this->ScalarProduct(y)/Norm()/y->Norm()); 224 262 }; 225 263 … … 230 268 void Vector::RotateVector(const Vector *axis, const double alpha) 231 269 { 232 Vector a,y;233 // normalise this vector with respect to axis234 a.CopyVector(this);235 a.Scale(Projection(axis));236 SubtractVector(&a);237 // construct normal vector238 y.MakeNormalVector(axis,this);239 y.Scale(Norm());240 // scale normal vector by sine and this vector by cosine241 y.Scale(sin(alpha));242 Scale(cos(alpha));243 // add scaled normal vector onto this vector244 AddVector(&y);245 // add part in axis direction246 AddVector(&a);270 Vector a,y; 271 // normalise this vector with respect to axis 272 a.CopyVector(this); 273 a.Scale(Projection(axis)); 274 SubtractVector(&a); 275 // construct normal vector 276 y.MakeNormalVector(axis,this); 277 y.Scale(Norm()); 278 // scale normal vector by sine and this vector by cosine 279 y.Scale(sin(alpha)); 280 Scale(cos(alpha)); 281 // add scaled normal vector onto this vector 282 AddVector(&y); 283 // add part in axis direction 284 AddVector(&a); 247 285 }; 248 286 … … 254 292 Vector& operator+=(Vector& a, const Vector& b) 255 293 { 256 a.AddVector(&b);257 return a;294 a.AddVector(&b); 295 return a; 258 296 }; 259 297 /** factor each component of \a a times a double \a m. … … 264 302 Vector& operator*=(Vector& a, const double m) 265 303 { 266 a.Scale(m);267 return a;268 }; 269 270 /** Sums two vectors \a and \b component-wise.304 a.Scale(m); 305 return a; 306 }; 307 308 /** Sums two vectors \a and \b component-wise. 271 309 * \param a first vector 272 310 * \param b second vector … … 275 313 Vector& operator+(const Vector& a, const Vector& b) 276 314 { 277 Vector *x = new Vector;278 x->CopyVector(&a);279 x->AddVector(&b);280 return *x;315 Vector *x = new Vector; 316 x->CopyVector(&a); 317 x->AddVector(&b); 318 return *x; 281 319 }; 282 320 … … 288 326 Vector& operator*(const Vector& a, const double m) 289 327 { 290 Vector *x = new Vector;291 x->CopyVector(&a);292 x->Scale(m);293 return *x;328 Vector *x = new Vector; 329 x->CopyVector(&a); 330 x->Scale(m); 331 return *x; 294 332 }; 295 333 … … 300 338 bool Vector::Output(ofstream *out) const 301 339 { 302 if (out != NULL) { 303 *out << "("; 304 for (int i=0;i<NDIM;i++) { 305 *out << x[i]; 306 if (i != 2) 307 *out << ","; 308 } 309 *out << ")"; 310 return true; 311 } else 312 return false; 313 }; 314 315 ofstream& operator<<(ofstream& ost,Vector& m) 316 { 317 m.Output(&ost); 340 if (out != NULL) { 341 *out << "("; 342 for (int i=0;i<NDIM;i++) { 343 *out << x[i]; 344 if (i != 2) 345 *out << ","; 346 } 347 *out << ")"; 348 return true; 349 } else 350 return false; 351 }; 352 353 ostream& operator<<(ostream& ost,Vector& m) 354 { 355 ost << "("; 356 for (int i=0;i<NDIM;i++) { 357 ost << m.x[i]; 358 if (i != 2) 359 ost << ","; 360 } 361 ost << ")"; 318 362 return ost; 319 363 }; … … 324 368 void Vector::Scale(double **factor) 325 369 { 326 for (int i=NDIM;i--;)327 x[i] *= (*factor)[i];370 for (int i=NDIM;i--;) 371 x[i] *= (*factor)[i]; 328 372 }; 329 373 330 374 void Vector::Scale(double *factor) 331 375 { 332 for (int i=NDIM;i--;)333 x[i] *= *factor;376 for (int i=NDIM;i--;) 377 x[i] *= *factor; 334 378 }; 335 379 336 380 void Vector::Scale(double factor) 337 381 { 338 for (int i=NDIM;i--;)339 x[i] *= factor;382 for (int i=NDIM;i--;) 383 x[i] *= factor; 340 384 }; 341 385 … … 345 389 void Vector::Translate(const Vector *trans) 346 390 { 347 for (int i=NDIM;i--;)348 x[i] += trans->x[i];391 for (int i=NDIM;i--;) 392 x[i] += trans->x[i]; 349 393 }; 350 394 … … 354 398 void Vector::MatrixMultiplication(double *M) 355 399 { 356 Vector C;357 // do the matrix multiplication358 C.x[0] = M[0]*x[0]+M[3]*x[1]+M[6]*x[2];359 C.x[1] = M[1]*x[0]+M[4]*x[1]+M[7]*x[2];360 C.x[2] = M[2]*x[0]+M[5]*x[1]+M[8]*x[2];361 // transfer the result into this362 for (int i=NDIM;i--;)363 x[i] = C.x[i];400 Vector C; 401 // do the matrix multiplication 402 C.x[0] = M[0]*x[0]+M[3]*x[1]+M[6]*x[2]; 403 C.x[1] = M[1]*x[0]+M[4]*x[1]+M[7]*x[2]; 404 C.x[2] = M[2]*x[0]+M[5]*x[1]+M[8]*x[2]; 405 // transfer the result into this 406 for (int i=NDIM;i--;) 407 x[i] = C.x[i]; 364 408 }; 365 409 … … 369 413 void Vector::InverseMatrixMultiplication(double *A) 370 414 { 371 Vector C;372 double B[NDIM*NDIM];373 double detA = RDET3(A);374 double detAReci;375 376 // calculate the inverse B377 if (fabs(detA) > MYEPSILON) {;// RDET3(A) yields precisely zero if A irregular378 detAReci = 1./detA;379 B[0] = detAReci*RDET2(A[4],A[5],A[7],A[8]);// A_11380 B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]);// A_12381 B[2] = detAReci*RDET2(A[1],A[2],A[4],A[5]);// A_13382 B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]);// A_21383 B[4] = detAReci*RDET2(A[0],A[2],A[6],A[8]);// A_22384 B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]);// A_23385 B[6] = detAReci*RDET2(A[3],A[4],A[6],A[7]);// A_31386 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]);// A_32387 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]);// A_33388 389 // do the matrix multiplication390 C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2];391 C.x[1] = B[1]*x[0]+B[4]*x[1]+B[7]*x[2];392 C.x[2] = B[2]*x[0]+B[5]*x[1]+B[8]*x[2];393 // transfer the result into this394 for (int i=NDIM;i--;)395 x[i] = C.x[i];396 } else {397 cerr << "ERROR: inverse of matrix does not exists!" << endl;398 }415 Vector C; 416 double B[NDIM*NDIM]; 417 double detA = RDET3(A); 418 double detAReci; 419 420 // calculate the inverse B 421 if (fabs(detA) > MYEPSILON) {; // RDET3(A) yields precisely zero if A irregular 422 detAReci = 1./detA; 423 B[0] = detAReci*RDET2(A[4],A[5],A[7],A[8]); // A_11 424 B[1] = -detAReci*RDET2(A[1],A[2],A[7],A[8]); // A_12 425 B[2] = detAReci*RDET2(A[1],A[2],A[4],A[5]); // A_13 426 B[3] = -detAReci*RDET2(A[3],A[5],A[6],A[8]); // A_21 427 B[4] = detAReci*RDET2(A[0],A[2],A[6],A[8]); // A_22 428 B[5] = -detAReci*RDET2(A[0],A[2],A[3],A[5]); // A_23 429 B[6] = detAReci*RDET2(A[3],A[4],A[6],A[7]); // A_31 430 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]); // A_32 431 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]); // A_33 432 433 // do the matrix multiplication 434 C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2]; 435 C.x[1] = B[1]*x[0]+B[4]*x[1]+B[7]*x[2]; 436 C.x[2] = B[2]*x[0]+B[5]*x[1]+B[8]*x[2]; 437 // transfer the result into this 438 for (int i=NDIM;i--;) 439 x[i] = C.x[i]; 440 } else { 441 cerr << "ERROR: inverse of matrix does not exists!" << endl; 442 } 399 443 }; 400 444 … … 409 453 void Vector::LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors) 410 454 { 411 for(int i=NDIM;i--;)412 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i];455 for(int i=NDIM;i--;) 456 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i]; 413 457 }; 414 458 … … 418 462 void Vector::Mirror(const Vector *n) 419 463 { 420 double projection;421 projection = ScalarProduct(n)/n->ScalarProduct(n);// remove constancy from n (keep as logical one)422 // withdraw projected vector twice from original one423 cout << Verbose(1) << "Vector: ";424 Output((ofstream *)&cout);425 cout << "\t";426 for (int i=NDIM;i--;)427 x[i] -= 2.*projection*n->x[i];428 cout << "Projected vector: ";429 Output((ofstream *)&cout);430 cout << endl;464 double projection; 465 projection = ScalarProduct(n)/n->ScalarProduct(n); // remove constancy from n (keep as logical one) 466 // withdraw projected vector twice from original one 467 cout << Verbose(1) << "Vector: "; 468 Output((ofstream *)&cout); 469 cout << "\t"; 470 for (int i=NDIM;i--;) 471 x[i] -= 2.*projection*n->x[i]; 472 cout << "Projected vector: "; 473 Output((ofstream *)&cout); 474 cout << endl; 431 475 }; 432 476 … … 440 484 bool Vector::MakeNormalVector(const Vector *y1, const Vector *y2, const Vector *y3) 441 485 { 442 Vector x1, x2;443 444 x1.CopyVector(y1);445 x1.SubtractVector(y2);446 x2.CopyVector(y3);447 x2.SubtractVector(y2);448 if ((x1.Norm()==0) || (x2.Norm()==0)) {449 cout << Verbose(4) << "Given vectors are linear dependent." << endl;450 return false;451 }452 // cout << Verbose(4) << "relative, first plane coordinates:";453 // x1.Output((ofstream *)&cout);454 // cout << endl;455 // cout << Verbose(4) << "second plane coordinates:";456 // x2.Output((ofstream *)&cout);457 // cout << endl;458 459 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]);460 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]);461 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]);462 Normalize();463 464 return true;486 Vector x1, x2; 487 488 x1.CopyVector(y1); 489 x1.SubtractVector(y2); 490 x2.CopyVector(y3); 491 x2.SubtractVector(y2); 492 if ((fabs(x1.Norm()) < MYEPSILON) || (fabs(x2.Norm()) < MYEPSILON) || (fabs(x1.Angle(&x2)) < MYEPSILON)) { 493 cout << Verbose(4) << "Given vectors are linear dependent." << endl; 494 return false; 495 } 496 // cout << Verbose(4) << "relative, first plane coordinates:"; 497 // x1.Output((ofstream *)&cout); 498 // cout << endl; 499 // cout << Verbose(4) << "second plane coordinates:"; 500 // x2.Output((ofstream *)&cout); 501 // cout << endl; 502 503 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]); 504 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]); 505 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]); 506 Normalize(); 507 508 return true; 465 509 }; 466 510 … … 476 520 bool Vector::MakeNormalVector(const Vector *y1, const Vector *y2) 477 521 { 478 Vector x1,x2;479 x1.CopyVector(y1);480 x2.CopyVector(y2);481 Zero();482 if ((x1.Norm()==0) || (x2.Norm()==0)) {483 cout << Verbose(4) << "Given vectors are linear dependent." << endl;484 return false;485 }486 // cout << Verbose(4) << "relative, first plane coordinates:";487 // x1.Output((ofstream *)&cout);488 // cout << endl;489 // cout << Verbose(4) << "second plane coordinates:";490 // x2.Output((ofstream *)&cout);491 // cout << endl;492 493 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]);494 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]);495 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]);496 Normalize();497 498 return true;522 Vector x1,x2; 523 x1.CopyVector(y1); 524 x2.CopyVector(y2); 525 Zero(); 526 if ((fabs(x1.Norm()) < MYEPSILON) || (fabs(x2.Norm()) < MYEPSILON) || (fabs(x1.Angle(&x2)) < MYEPSILON)) { 527 cout << Verbose(4) << "Given vectors are linear dependent." << endl; 528 return false; 529 } 530 // cout << Verbose(4) << "relative, first plane coordinates:"; 531 // x1.Output((ofstream *)&cout); 532 // cout << endl; 533 // cout << Verbose(4) << "second plane coordinates:"; 534 // x2.Output((ofstream *)&cout); 535 // cout << endl; 536 537 this->x[0] = (x1.x[1]*x2.x[2] - x1.x[2]*x2.x[1]); 538 this->x[1] = (x1.x[2]*x2.x[0] - x1.x[0]*x2.x[2]); 539 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]); 540 Normalize(); 541 542 return true; 499 543 }; 500 544 … … 507 551 { 508 552 bool result = false; 509 Vector x1;510 x1.CopyVector(y1);511 x1.Scale(x1.Projection(this));512 SubtractVector(&x1);513 for (int i=NDIM;i--;)514 result = result || (fabs(x[i]) > MYEPSILON);515 516 return result;553 Vector x1; 554 x1.CopyVector(y1); 555 x1.Scale(x1.Projection(this)); 556 SubtractVector(&x1); 557 for (int i=NDIM;i--;) 558 result = result || (fabs(x[i]) > MYEPSILON); 559 560 return result; 517 561 }; 518 562 … … 525 569 bool Vector::GetOneNormalVector(const Vector *GivenVector) 526 570 { 527 int Components[NDIM]; // contains indices of non-zero components528 int Last = 0;// count the number of non-zero entries in vector529 int j;// loop variables530 double norm;531 532 cout << Verbose(4);533 GivenVector->Output((ofstream *)&cout);534 cout << endl;535 for (j=NDIM;j--;)536 Components[j] = -1;537 // find two components != 0538 for (j=0;j<NDIM;j++)539 if (fabs(GivenVector->x[j]) > MYEPSILON)540 Components[Last++] = j;541 cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl;542 543 switch(Last) {544 case 3:// threecomponent system545 case 2:// two component system546 norm = sqrt(1./(GivenVector->x[Components[1]]*GivenVector->x[Components[1]]) + 1./(GivenVector->x[Components[0]]*GivenVector->x[Components[0]]));547 x[Components[2]] = 0.;548 // in skp both remaining parts shall become zero but with opposite sign and third is zero549 x[Components[1]] = -1./GivenVector->x[Components[1]] / norm;550 x[Components[0]] = 1./GivenVector->x[Components[0]] / norm;551 return true;552 break;553 case 1: // one component system554 // set sole non-zero component to 0, and one of the other zero component pendants to 1555 x[(Components[0]+2)%NDIM] = 0.;556 x[(Components[0]+1)%NDIM] = 1.;557 x[Components[0]] = 0.;558 return true;559 break;560 default:561 return false;562 }571 int Components[NDIM]; // contains indices of non-zero components 572 int Last = 0; // count the number of non-zero entries in vector 573 int j; // loop variables 574 double norm; 575 576 cout << Verbose(4); 577 GivenVector->Output((ofstream *)&cout); 578 cout << endl; 579 for (j=NDIM;j--;) 580 Components[j] = -1; 581 // find two components != 0 582 for (j=0;j<NDIM;j++) 583 if (fabs(GivenVector->x[j]) > MYEPSILON) 584 Components[Last++] = j; 585 cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl; 586 587 switch(Last) { 588 case 3: // threecomponent system 589 case 2: // two component system 590 norm = sqrt(1./(GivenVector->x[Components[1]]*GivenVector->x[Components[1]]) + 1./(GivenVector->x[Components[0]]*GivenVector->x[Components[0]])); 591 x[Components[2]] = 0.; 592 // in skp both remaining parts shall become zero but with opposite sign and third is zero 593 x[Components[1]] = -1./GivenVector->x[Components[1]] / norm; 594 x[Components[0]] = 1./GivenVector->x[Components[0]] / norm; 595 return true; 596 break; 597 case 1: // one component system 598 // set sole non-zero component to 0, and one of the other zero component pendants to 1 599 x[(Components[0]+2)%NDIM] = 0.; 600 x[(Components[0]+1)%NDIM] = 1.; 601 x[Components[0]] = 0.; 602 return true; 603 break; 604 default: 605 return false; 606 } 563 607 }; 564 608 … … 571 615 double Vector::CutsPlaneAt(Vector *A, Vector *B, Vector *C) 572 616 { 573 // cout << Verbose(3) << "For comparison: ";574 // cout << "A " << A->Projection(this) << "\t";575 // cout << "B " << B->Projection(this) << "\t";576 // cout << "C " << C->Projection(this) << "\t";577 // cout << endl;578 return A->Projection(this);617 // cout << Verbose(3) << "For comparison: "; 618 // cout << "A " << A->Projection(this) << "\t"; 619 // cout << "B " << B->Projection(this) << "\t"; 620 // cout << "C " << C->Projection(this) << "\t"; 621 // cout << endl; 622 return A->Projection(this); 579 623 }; 580 624 … … 594 638 } 595 639 596 int np = 3;640 int np = 3; 597 641 struct LSQ_params par; 598 642 599 const gsl_multimin_fminimizer_type *T =600 gsl_multimin_fminimizer_nmsimplex;601 gsl_multimin_fminimizer *s = NULL;602 gsl_vector *ss, *y;603 gsl_multimin_function minex_func;604 605 size_t iter = 0, i;606 int status;607 double size;608 609 /* Initial vertex size vector */610 ss = gsl_vector_alloc (np);611 y = gsl_vector_alloc (np);612 613 /* Set all step sizes to 1 */614 gsl_vector_set_all (ss, 1.0);615 616 /* Starting point */617 par.vectors = vectors;643 const gsl_multimin_fminimizer_type *T = 644 gsl_multimin_fminimizer_nmsimplex; 645 gsl_multimin_fminimizer *s = NULL; 646 gsl_vector *ss, *y; 647 gsl_multimin_function minex_func; 648 649 size_t iter = 0, i; 650 int status; 651 double size; 652 653 /* Initial vertex size vector */ 654 ss = gsl_vector_alloc (np); 655 y = gsl_vector_alloc (np); 656 657 /* Set all step sizes to 1 */ 658 gsl_vector_set_all (ss, 1.0); 659 660 /* Starting point */ 661 par.vectors = vectors; 618 662 par.num = num; 619 663 … … 621 665 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.); 622 666 623 /* Initialize method and iterate */624 minex_func.f = &LSQ;625 minex_func.n = np;626 minex_func.params = (void *)∥627 628 s = gsl_multimin_fminimizer_alloc (T, np);629 gsl_multimin_fminimizer_set (s, &minex_func, y, ss);630 631 do632 {633 iter++;634 status = gsl_multimin_fminimizer_iterate(s);635 636 if (status)637 break;638 639 size = gsl_multimin_fminimizer_size (s);640 status = gsl_multimin_test_size (size, 1e-2);641 642 if (status == GSL_SUCCESS)643 {644 printf ("converged to minimum at\n");645 }646 647 printf ("%5d ", (int)iter);648 for (i = 0; i < (size_t)np; i++)649 {650 printf ("%10.3e ", gsl_vector_get (s->x, i));651 }652 printf ("f() = %7.3f size = %.3f\n", s->fval, size);653 }654 while (status == GSL_CONTINUE && iter < 100);655 656 for (i=(size_t)np;i--;)657 this->x[i] = gsl_vector_get(s->x, i);658 gsl_vector_free(y);659 gsl_vector_free(ss);660 gsl_multimin_fminimizer_free (s);667 /* Initialize method and iterate */ 668 minex_func.f = &LSQ; 669 minex_func.n = np; 670 minex_func.params = (void *)∥ 671 672 s = gsl_multimin_fminimizer_alloc (T, np); 673 gsl_multimin_fminimizer_set (s, &minex_func, y, ss); 674 675 do 676 { 677 iter++; 678 status = gsl_multimin_fminimizer_iterate(s); 679 680 if (status) 681 break; 682 683 size = gsl_multimin_fminimizer_size (s); 684 status = gsl_multimin_test_size (size, 1e-2); 685 686 if (status == GSL_SUCCESS) 687 { 688 printf ("converged to minimum at\n"); 689 } 690 691 printf ("%5d ", (int)iter); 692 for (i = 0; i < (size_t)np; i++) 693 { 694 printf ("%10.3e ", gsl_vector_get (s->x, i)); 695 } 696 printf ("f() = %7.3f size = %.3f\n", s->fval, size); 697 } 698 while (status == GSL_CONTINUE && iter < 100); 699 700 for (i=(size_t)np;i--;) 701 this->x[i] = gsl_vector_get(s->x, i); 702 gsl_vector_free(y); 703 gsl_vector_free(ss); 704 gsl_multimin_fminimizer_free (s); 661 705 662 706 return true; … … 668 712 void Vector::AddVector(const Vector *y) 669 713 { 670 for (int i=NDIM;i--;)671 this->x[i] += y->x[i];714 for (int i=NDIM;i--;) 715 this->x[i] += y->x[i]; 672 716 } 673 717 … … 677 721 void Vector::SubtractVector(const Vector *y) 678 722 { 679 for (int i=NDIM;i--;)680 this->x[i] -= y->x[i];723 for (int i=NDIM;i--;) 724 this->x[i] -= y->x[i]; 681 725 } 682 726 … … 686 730 void Vector::CopyVector(const Vector *y) 687 731 { 688 for (int i=NDIM;i--;)689 this->x[i] = y->x[i];732 for (int i=NDIM;i--;) 733 this->x[i] = y->x[i]; 690 734 } 691 735 … … 697 741 void Vector::AskPosition(double *cell_size, bool check) 698 742 { 699 char coords[3] = {'x','y','z'};700 int j = -1;701 for (int i=0;i<3;i++) {702 j += i+1;703 do {704 cout << Verbose(0) << coords[i] << "[0.." << cell_size[j] << "]: ";705 cin >> x[i];706 } while (((x[i] < 0) || (x[i] >= cell_size[j])) && (check));707 }743 char coords[3] = {'x','y','z'}; 744 int j = -1; 745 for (int i=0;i<3;i++) { 746 j += i+1; 747 do { 748 cout << Verbose(0) << coords[i] << "[0.." << cell_size[j] << "]: "; 749 cin >> x[i]; 750 } while (((x[i] < 0) || (x[i] >= cell_size[j])) && (check)); 751 } 708 752 }; 709 753 … … 725 769 bool Vector::SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c) 726 770 { 727 double D1,D2,D3,E1,E2,F1,F2,F3,p,q=0., A, B1, B2, C;728 double ang; // angle on testing729 double sign[3];730 int i,j,k;731 A = cos(alpha) * x1->Norm() * c;732 B1 = cos(beta + M_PI/2.) * y->Norm() * c;733 B2 = cos(beta) * x2->Norm() * c;734 C = c * c;735 cout << Verbose(2) << "A " << A << "\tB " << B1 << "\tC " << C << endl;736 int flag = 0;737 if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping738 if (fabs(x1->x[1]) > MYEPSILON) {739 flag = 1;740 } else if (fabs(x1->x[2]) > MYEPSILON) {741 flag = 2;742 } else {743 return false;744 }745 }746 switch (flag) {747 default:748 case 0:749 break;750 case 2:751 flip(&x1->x[0],&x1->x[1]);752 flip(&x2->x[0],&x2->x[1]);753 flip(&y->x[0],&y->x[1]);754 //flip(&x[0],&x[1]);755 flip(&x1->x[1],&x1->x[2]);756 flip(&x2->x[1],&x2->x[2]);757 flip(&y->x[1],&y->x[2]);758 //flip(&x[1],&x[2]);759 case 1:760 flip(&x1->x[0],&x1->x[1]);761 flip(&x2->x[0],&x2->x[1]);762 flip(&y->x[0],&y->x[1]);763 //flip(&x[0],&x[1]);764 flip(&x1->x[1],&x1->x[2]);765 flip(&x2->x[1],&x2->x[2]);766 flip(&y->x[1],&y->x[2]);767 //flip(&x[1],&x[2]);768 break;769 }770 // now comes the case system771 D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1];772 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2];773 D3 = y->x[0]/x1->x[0]*A-B1;774 cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n";775 if (fabs(D1) < MYEPSILON) {776 cout << Verbose(2) << "D1 == 0!\n";777 if (fabs(D2) > MYEPSILON) {778 cout << Verbose(3) << "D2 != 0!\n";779 x[2] = -D3/D2;780 E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2;781 E2 = -x1->x[1]/x1->x[0];782 cout << Verbose(3) << "E1 " << E1 << "\tE2 " << E2 << "\n";783 F1 = E1*E1 + 1.;784 F2 = -E1*E2;785 F3 = E1*E1 + D3*D3/(D2*D2) - C;786 cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n";787 if (fabs(F1) < MYEPSILON) {788 cout << Verbose(4) << "F1 == 0!\n";789 cout << Verbose(4) << "Gleichungssystem linear\n";790 x[1] = F3/(2.*F2);791 } else {792 p = F2/F1;793 q = p*p - F3/F1;794 cout << Verbose(4) << "p " << p << "\tq " << q << endl;795 if (q < 0) {796 cout << Verbose(4) << "q < 0" << endl;797 return false;798 }799 x[1] = p + sqrt(q);800 }801 x[0] =A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];802 } else {803 cout << Verbose(2) << "Gleichungssystem unterbestimmt\n";804 return false;805 }806 } else {807 E1 = A/x1->x[0]+x1->x[1]/x1->x[0]*D3/D1;808 E2 = x1->x[1]/x1->x[0]*D2/D1 - x1->x[2];809 cout << Verbose(2) << "E1 " << E1 << "\tE2 " << E2 << "\n";810 F1 = E2*E2 + D2*D2/(D1*D1) + 1.;811 F2 = -(E1*E2 + D2*D3/(D1*D1));812 F3 = E1*E1 + D3*D3/(D1*D1) - C;813 cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n";814 if (fabs(F1) < MYEPSILON) {815 cout << Verbose(3) << "F1 == 0!\n";816 cout << Verbose(3) << "Gleichungssystem linear\n";817 x[2] = F3/(2.*F2);818 } else {819 p = F2/F1;820 q = p*p - F3/F1;821 cout << Verbose(3) << "p " << p << "\tq " << q << endl;822 if (q < 0) {823 cout << Verbose(3) << "q < 0" << endl;824 return false;825 }826 x[2] = p + sqrt(q);827 }828 x[1] = (-D2 * x[2] - D3)/D1;829 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2];830 }831 switch (flag) { // back-flipping832 default:833 case 0:834 break;835 case 2:836 flip(&x1->x[0],&x1->x[1]);837 flip(&x2->x[0],&x2->x[1]);838 flip(&y->x[0],&y->x[1]);839 flip(&x[0],&x[1]);840 flip(&x1->x[1],&x1->x[2]);841 flip(&x2->x[1],&x2->x[2]);842 flip(&y->x[1],&y->x[2]);843 flip(&x[1],&x[2]);844 case 1:845 flip(&x1->x[0],&x1->x[1]);846 flip(&x2->x[0],&x2->x[1]);847 flip(&y->x[0],&y->x[1]);848 //flip(&x[0],&x[1]);849 flip(&x1->x[1],&x1->x[2]);850 flip(&x2->x[1],&x2->x[2]);851 flip(&y->x[1],&y->x[2]);852 flip(&x[1],&x[2]);853 break;854 }855 // one z component is only determined by its radius (without sign)856 // thus check eight possible sign flips and determine by checking angle with second vector857 for (i=0;i<8;i++) {858 // set sign vector accordingly859 for (j=2;j>=0;j--) {860 k = (i & pot(2,j)) << j;861 cout << Verbose(2) << "k " << k << "\tpot(2,j) " << pot(2,j) << endl;862 sign[j] = (k == 0) ? 1. : -1.;863 }864 cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n";865 // apply sign matrix866 for (j=NDIM;j--;)867 x[j] *= sign[j];868 // calculate angle and check869 ang = x2->Angle (this);870 cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t";871 if (fabs(ang - cos(beta)) < MYEPSILON) {872 break;873 }874 // unapply sign matrix (is its own inverse)875 for (j=NDIM;j--;)876 x[j] *= sign[j];877 }878 return true;879 }; 771 double D1,D2,D3,E1,E2,F1,F2,F3,p,q=0., A, B1, B2, C; 772 double ang; // angle on testing 773 double sign[3]; 774 int i,j,k; 775 A = cos(alpha) * x1->Norm() * c; 776 B1 = cos(beta + M_PI/2.) * y->Norm() * c; 777 B2 = cos(beta) * x2->Norm() * c; 778 C = c * c; 779 cout << Verbose(2) << "A " << A << "\tB " << B1 << "\tC " << C << endl; 780 int flag = 0; 781 if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping 782 if (fabs(x1->x[1]) > MYEPSILON) { 783 flag = 1; 784 } else if (fabs(x1->x[2]) > MYEPSILON) { 785 flag = 2; 786 } else { 787 return false; 788 } 789 } 790 switch (flag) { 791 default: 792 case 0: 793 break; 794 case 2: 795 flip(&x1->x[0],&x1->x[1]); 796 flip(&x2->x[0],&x2->x[1]); 797 flip(&y->x[0],&y->x[1]); 798 //flip(&x[0],&x[1]); 799 flip(&x1->x[1],&x1->x[2]); 800 flip(&x2->x[1],&x2->x[2]); 801 flip(&y->x[1],&y->x[2]); 802 //flip(&x[1],&x[2]); 803 case 1: 804 flip(&x1->x[0],&x1->x[1]); 805 flip(&x2->x[0],&x2->x[1]); 806 flip(&y->x[0],&y->x[1]); 807 //flip(&x[0],&x[1]); 808 flip(&x1->x[1],&x1->x[2]); 809 flip(&x2->x[1],&x2->x[2]); 810 flip(&y->x[1],&y->x[2]); 811 //flip(&x[1],&x[2]); 812 break; 813 } 814 // now comes the case system 815 D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1]; 816 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2]; 817 D3 = y->x[0]/x1->x[0]*A-B1; 818 cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n"; 819 if (fabs(D1) < MYEPSILON) { 820 cout << Verbose(2) << "D1 == 0!\n"; 821 if (fabs(D2) > MYEPSILON) { 822 cout << Verbose(3) << "D2 != 0!\n"; 823 x[2] = -D3/D2; 824 E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2; 825 E2 = -x1->x[1]/x1->x[0]; 826 cout << Verbose(3) << "E1 " << E1 << "\tE2 " << E2 << "\n"; 827 F1 = E1*E1 + 1.; 828 F2 = -E1*E2; 829 F3 = E1*E1 + D3*D3/(D2*D2) - C; 830 cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 831 if (fabs(F1) < MYEPSILON) { 832 cout << Verbose(4) << "F1 == 0!\n"; 833 cout << Verbose(4) << "Gleichungssystem linear\n"; 834 x[1] = F3/(2.*F2); 835 } else { 836 p = F2/F1; 837 q = p*p - F3/F1; 838 cout << Verbose(4) << "p " << p << "\tq " << q << endl; 839 if (q < 0) { 840 cout << Verbose(4) << "q < 0" << endl; 841 return false; 842 } 843 x[1] = p + sqrt(q); 844 } 845 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2]; 846 } else { 847 cout << Verbose(2) << "Gleichungssystem unterbestimmt\n"; 848 return false; 849 } 850 } else { 851 E1 = A/x1->x[0]+x1->x[1]/x1->x[0]*D3/D1; 852 E2 = x1->x[1]/x1->x[0]*D2/D1 - x1->x[2]; 853 cout << Verbose(2) << "E1 " << E1 << "\tE2 " << E2 << "\n"; 854 F1 = E2*E2 + D2*D2/(D1*D1) + 1.; 855 F2 = -(E1*E2 + D2*D3/(D1*D1)); 856 F3 = E1*E1 + D3*D3/(D1*D1) - C; 857 cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 858 if (fabs(F1) < MYEPSILON) { 859 cout << Verbose(3) << "F1 == 0!\n"; 860 cout << Verbose(3) << "Gleichungssystem linear\n"; 861 x[2] = F3/(2.*F2); 862 } else { 863 p = F2/F1; 864 q = p*p - F3/F1; 865 cout << Verbose(3) << "p " << p << "\tq " << q << endl; 866 if (q < 0) { 867 cout << Verbose(3) << "q < 0" << endl; 868 return false; 869 } 870 x[2] = p + sqrt(q); 871 } 872 x[1] = (-D2 * x[2] - D3)/D1; 873 x[0] = A/x1->x[0] - x1->x[1]/x1->x[0]*x[1] + x1->x[2]/x1->x[0]*x[2]; 874 } 875 switch (flag) { // back-flipping 876 default: 877 case 0: 878 break; 879 case 2: 880 flip(&x1->x[0],&x1->x[1]); 881 flip(&x2->x[0],&x2->x[1]); 882 flip(&y->x[0],&y->x[1]); 883 flip(&x[0],&x[1]); 884 flip(&x1->x[1],&x1->x[2]); 885 flip(&x2->x[1],&x2->x[2]); 886 flip(&y->x[1],&y->x[2]); 887 flip(&x[1],&x[2]); 888 case 1: 889 flip(&x1->x[0],&x1->x[1]); 890 flip(&x2->x[0],&x2->x[1]); 891 flip(&y->x[0],&y->x[1]); 892 //flip(&x[0],&x[1]); 893 flip(&x1->x[1],&x1->x[2]); 894 flip(&x2->x[1],&x2->x[2]); 895 flip(&y->x[1],&y->x[2]); 896 flip(&x[1],&x[2]); 897 break; 898 } 899 // one z component is only determined by its radius (without sign) 900 // thus check eight possible sign flips and determine by checking angle with second vector 901 for (i=0;i<8;i++) { 902 // set sign vector accordingly 903 for (j=2;j>=0;j--) { 904 k = (i & pot(2,j)) << j; 905 cout << Verbose(2) << "k " << k << "\tpot(2,j) " << pot(2,j) << endl; 906 sign[j] = (k == 0) ? 1. : -1.; 907 } 908 cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n"; 909 // apply sign matrix 910 for (j=NDIM;j--;) 911 x[j] *= sign[j]; 912 // calculate angle and check 913 ang = x2->Angle (this); 914 cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t"; 915 if (fabs(ang - cos(beta)) < MYEPSILON) { 916 break; 917 } 918 // unapply sign matrix (is its own inverse) 919 for (j=NDIM;j--;) 920 x[j] *= sign[j]; 921 } 922 return true; 923 }; -
Property mode
changed from
-
src/vector.hpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 8 8 */ 9 9 class Vector { 10 public:11 double x[NDIM];10 public: 11 double x[NDIM]; 12 12 13 Vector();14 Vector(double x1, double x2, double x3);15 ~Vector();13 Vector(); 14 Vector(double x1, double x2, double x3); 15 ~Vector(); 16 16 17 double Distance(const Vector *y) const; 18 double DistanceSquared(const Vector *y) const; 19 double PeriodicDistance(const Vector *y, const double *cell_size) const; 20 double ScalarProduct(const Vector *y) const; 21 double Projection(const Vector *y) const; 22 double Norm() const ; 23 double Angle(Vector *y) const; 17 double Distance(const Vector *y) const; 18 double DistanceSquared(const Vector *y) const; 19 double PeriodicDistance(const Vector *y, const double *cell_size) const; 20 double PeriodicDistanceSquared(const Vector *y, const double *cell_size) const; 21 double ScalarProduct(const Vector *y) const; 22 double Projection(const Vector *y) const; 23 double Norm() const ; 24 double Angle(const Vector *y) const; 24 25 25 void AddVector(const Vector *y); 26 void SubtractVector(const Vector *y); 27 void CopyVector(const Vector *y); 28 void RotateVector(const Vector *y, const double alpha); 29 void VectorProduct(const Vector *y); 30 void ProjectOntoPlane(const Vector *y); 31 void Zero(); 32 void One(double one); 33 void Init(double x1, double x2, double x3); 34 void Normalize(); 35 void Translate(const Vector *x); 36 void Mirror(const Vector *x); 37 void Scale(double **factor); 38 void Scale(double *factor); 39 void Scale(double factor); 40 void MatrixMultiplication(double *M); 41 void InverseMatrixMultiplication(double *M); 42 void KeepPeriodic(ofstream *out, double *matrix); 43 void LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors); 44 45 double CutsPlaneAt(Vector *A, Vector *B, Vector *C); 46 bool GetOneNormalVector(const Vector *x1); 47 bool MakeNormalVector(const Vector *y1); 48 bool MakeNormalVector(const Vector *y1, const Vector *y2); 49 bool MakeNormalVector(const Vector *x1, const Vector *x2, const Vector *x3); 50 bool SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c); 51 bool LSQdistance(Vector **vectors, int dim); 52 53 void AskPosition(double *cell_size, bool check); 54 bool Output(ofstream *out) const; 26 void AddVector(const Vector *y); 27 void SubtractVector(const Vector *y); 28 void CopyVector(const Vector *y); 29 void RotateVector(const Vector *y, const double alpha); 30 void VectorProduct(const Vector *y); 31 void ProjectOntoPlane(const Vector *y); 32 void Zero(); 33 void One(double one); 34 void Init(double x1, double x2, double x3); 35 void Normalize(); 36 void Translate(const Vector *x); 37 void Mirror(const Vector *x); 38 void Scale(double **factor); 39 void Scale(double *factor); 40 void Scale(double factor); 41 void MatrixMultiplication(double *M); 42 void InverseMatrixMultiplication(double *M); 43 void KeepPeriodic(ofstream *out, double *matrix); 44 void LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors); 45 double CutsPlaneAt(Vector *A, Vector *B, Vector *C); 46 bool GetOneNormalVector(const Vector *x1); 47 bool MakeNormalVector(const Vector *y1); 48 bool MakeNormalVector(const Vector *y1, const Vector *y2); 49 bool MakeNormalVector(const Vector *x1, const Vector *x2, const Vector *x3); 50 bool SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c); 51 bool LSQdistance(Vector **vectors, int dim); 52 void AskPosition(double *cell_size, bool check); 53 bool Output(ofstream *out) const; 55 54 }; 56 55 57 o fstream& operator<<(ofstream& 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);56 ostream & operator << (ostream& ost, Vector &m); 57 //Vector& operator+=(Vector& a, const Vector& b); 58 //Vector& operator*=(Vector& a, const double m); 59 //Vector& operator*(const Vector& a, const double m); 60 //Vector& operator+(const Vector& a, const Vector& b); 62 61 63 62 #endif /*VECTOR_HPP_*/ -
Property mode
changed from
-
src/verbose.cpp
-
Property mode
changed from
100644to100755
r124df1 r6ac7ee 7 7 ostream& Verbose::print (ostream &ost) const 8 8 { 9 for (int i=Verbosity;i--;)10 ost.put('\t');11 //cout << "Verbose(.) called." << endl;12 return ost;9 for (int i=Verbosity;i--;) 10 ost.put('\t'); 11 //cout << "Verbose(.) called." << endl; 12 return ost; 13 13 }; 14 14 … … 35 35 int bits = 1, counter = 1; 36 36 while ((bits = 1 << counter) < BinaryNumber) 37 counter++;38 for (int i=0;i<counter-1;i++) {39 if ((BinaryNumber & (1 << i)) == 0)40 ost.put('0');37 counter++; 38 for (int i=0;i<counter-1;i++) { 39 if ((BinaryNumber & (1 << i)) == 0) 40 ost.put('0'); 41 41 else 42 ost.put('1');43 }44 ost.put('b');45 //cout << "Binary(.) called." << endl;46 return ost;42 ost.put('1'); 43 } 44 ost.put('b'); 45 //cout << "Binary(.) called." << endl; 46 return ost; 47 47 }; 48 48 -
Property mode
changed from
Note:
See TracChangeset
for help on using the changeset viewer.
