source: src/datacreator.cpp@ b6dbff

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since b6dbff was 112b09, checked in by Tillmann Crueger <crueger@…>, 15 years ago

Added #include "Helpers/MemDebug.hpp" to all .cpp files

  • Property mode set to 100755
File size: 35.8 KB
RevLine 
[14de469]1/** \file datacreator.cpp
2 *
[6ac7ee]3 * Declarations of assisting functions in creating data and plot files.
4 *
[14de469]5 */
6
7//============================ INCLUDES ===========================
8
[112b09]9#include "Helpers/MemDebug.hpp"
10
[14de469]11#include "datacreator.hpp"
[f66195]12#include "helpers.hpp"
13#include "parser.hpp"
[14de469]14
15//=========================== FUNCTIONS============================
16
17/** Opens a file with \a *filename in \a *dir.
18 * \param output file handle on return
19 * \param *dir directory
20 * \param *filename name of file
21 * \return true if file has been opened
22 */
23bool OpenOutputFile(ofstream &output, const char *dir, const char *filename)
24{
[042f82]25 stringstream name;
26 name << dir << "/" << filename;
27 output.open(name.str().c_str(), ios::out);
28 if (output == NULL) {
[a67d19]29 DoLog(0) && (Log() << Verbose(0) << "Unable to open " << name.str() << " for writing, is directory correct?" << endl);
[042f82]30 return false;
31 }
32 return true;
[6ac7ee]33};
[14de469]34
[19f3d6]35/** Opens a file for appending with \a *filename in \a *dir.
36 * \param output file handle on return
37 * \param *dir directory
38 * \param *filename name of file
39 * \return true if file has been opened
40 */
41bool AppendOutputFile(ofstream &output, const char *dir, const char *filename)
42{
[042f82]43 stringstream name;
44 name << dir << "/" << filename;
45 output.open(name.str().c_str(), ios::app);
46 if (output == NULL) {
[a67d19]47 DoLog(0) && (Log() << Verbose(0) << "Unable to open " << name.str() << " for writing, is directory correct?" << endl);
[042f82]48 return false;
49 }
50 return true;
[6ac7ee]51};
[19f3d6]52
[14de469]53/** Plots an energy vs. order.
[390248]54 * \param &Fragments EnergyMatrix class containing matrix values
[f66195]55 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
[14de469]56 * \param *prefix prefix in filename (without ending)
57 * \param *msg message to be place in first line as a comment
58 * \return true if file was written successfully
59 */
[f66195]60bool CreateDataEnergyOrder(class EnergyMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
[14de469]61{
[042f82]62 stringstream filename;
63 ofstream output;
64
65 filename << prefix << ".dat";
66 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
[a67d19]67 DoLog(0) && (Log() << Verbose(0) << msg << endl);
[042f82]68 output << "# " << msg << ", created on " << datum;
[b12a35]69 output << "#Order\tFrag.No.\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
[f66195]70 for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
71 for(int i=KeySets.FragmentsPerOrder[BondOrder];i--;) {
72 for(int j=Fragments.RowCounter[ KeySets.OrderSet[BondOrder][i] ];j--;)
73 for(int k=Fragments.ColumnCounter[ KeySets.OrderSet[BondOrder][i] ];k--;)
74 Fragments.Matrix[Fragments.MatrixCounter][j][k] += Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][k];
[042f82]75 }
[f66195]76 output << BondOrder+1 << "\t" << KeySets.FragmentsPerOrder[BondOrder];
[f731ae]77 for (int l=0;l<Fragments.ColumnCounter[Fragments.MatrixCounter];l++)
[042f82]78 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l];
79 output << endl;
80 }
81 output.close();
82 return true;
[390248]83};
84
85/** Plots an energy error vs. order.
86 * \param &Energy EnergyMatrix class containing reference values (in MatrixCounter matrix)
87 * \param &Fragments EnergyMatrix class containing matrix values
[f66195]88 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
[390248]89 * \param *prefix prefix in filename (without ending)
90 * \param *msg message to be place in first line as a comment
91 * \return true if file was written successfully
92 */
[f66195]93bool CreateDataDeltaEnergyOrder(class EnergyMatrix &Energy, class EnergyMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
[390248]94{
[042f82]95 stringstream filename;
96 ofstream output;
97
98 filename << prefix << ".dat";
99 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
[a67d19]100 DoLog(0) && (Log() << Verbose(0) << msg << endl);
[042f82]101 output << "# " << msg << ", created on " << datum;
[b12a35]102 output << "#Order\tFrag.No.\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
[042f82]103 Fragments.SetLastMatrix(Energy.Matrix[Energy.MatrixCounter],0);
[f66195]104 for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
105 for(int i=KeySets.FragmentsPerOrder[BondOrder];i--;) {
106 for(int j=Fragments.RowCounter[ KeySets.OrderSet[BondOrder][i] ];j--;)
107 for(int k=Fragments.ColumnCounter[ KeySets.OrderSet[BondOrder][i] ];k--;)
108 Fragments.Matrix[Fragments.MatrixCounter][j][k] -= Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][k];
[042f82]109 }
[f66195]110 output << BondOrder+1 << "\t" << KeySets.FragmentsPerOrder[BondOrder];
[f731ae]111 for (int l=0;l<Fragments.ColumnCounter[Energy.MatrixCounter];l++)
[042f82]112 if (fabs(Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]) < MYEPSILON)
113 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l];
114 else
115 output << scientific << "\t" << (Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter]-1 ][l] / Energy.Matrix[Energy.MatrixCounter][ Energy.RowCounter[Energy.MatrixCounter]-1 ][l]);
116 output << endl;
117 }
118 output.close();
119 return true;
[14de469]120};
121
122/** Plot forces vs. order.
[390248]123 * \param &Fragments ForceMatrix class containing matrix values
[f66195]124 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
[390248]125 * \param *prefix prefix in filename (without ending)
126 * \param *msg message to be place in first line as a comment
127 * \param *datum current date and time
128 * \return true if file was written successfully
[14de469]129 */
[f66195]130bool CreateDataForcesOrder(class ForceMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix,const char *msg, const char *datum, void (*CreateForce)(class MatrixContainer &, int))
[14de469]131{
[042f82]132 stringstream filename;
133 ofstream output;
134
135 filename << prefix << ".dat";
136 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
[a67d19]137 DoLog(0) && (Log() << Verbose(0) << msg << endl);
[042f82]138 output << "# " << msg << ", created on " << datum;
[b12a35]139 output << "# Order\tFrag.No.\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
[042f82]140 Fragments.SetLastMatrix(0.,0);
[f66195]141 for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
142 Fragments.SumSubForces(Fragments, KeySets, BondOrder, 1.);
143 output << BondOrder+1 << "\t" << KeySets.FragmentsPerOrder[BondOrder];
[042f82]144 CreateForce(Fragments, Fragments.MatrixCounter);
[f731ae]145 for (int l=0;l<Fragments.ColumnCounter[Fragments.MatrixCounter];l++)
[042f82]146 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l];
147 output << endl;
148 }
149 output.close();
150 return true;
[390248]151};
152
153/** Plot forces error vs. order.
154 * \param &Force ForceMatrix containing reference values (in MatrixCounter matrix)
155 * \param &Fragments ForceMatrix class containing matrix values
[f66195]156 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
[390248]157 * \param *prefix prefix in filename (without ending)
158 * \param *msg message to be place in first line as a comment
159 * \param *datum current date and time
160 * \return true if file was written successfully
161 */
[f66195]162bool CreateDataDeltaForcesOrder(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum, void (*CreateForce)(class MatrixContainer &, int))
[390248]163{
[042f82]164 stringstream filename;
165 ofstream output;
166
167 filename << prefix << ".dat";
168 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
[a67d19]169 DoLog(0) && (Log() << Verbose(0) << msg << endl);
[042f82]170 output << "# " << msg << ", created on " << datum;
[b12a35]171 output << "# Order\tFrag.No.\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
[042f82]172 Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter],0);
[f66195]173 for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
174 Fragments.SumSubForces(Fragments, KeySets, BondOrder, -1.);
175 output << BondOrder+1 << "\t" << KeySets.FragmentsPerOrder[BondOrder];
[042f82]176 CreateForce(Fragments, Fragments.MatrixCounter);
[f731ae]177 for (int l=0;l<Fragments.ColumnCounter[Fragments.MatrixCounter];l++)
[042f82]178 output << scientific << "\t" << Fragments.Matrix[Fragments.MatrixCounter][ Fragments.RowCounter[Fragments.MatrixCounter] ][l];
179 output << endl;
180 }
181 output.close();
182 return true;
[390248]183};
184
185/** Plot forces error vs. vs atom vs. order.
186 * \param &Force ForceMatrix containing reference values (in MatrixCounter matrix)
187 * \param &Fragments ForceMatrix class containing matrix values
[f66195]188 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
[390248]189 * \param *prefix prefix in filename (without ending)
190 * \param *msg message to be place in first line as a comment
191 * \param *datum current date and time
192 * \return true if file was written successfully
193 */
[f66195]194bool CreateDataDeltaForcesOrderPerAtom(class ForceMatrix &Force, class ForceMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
[390248]195{
[042f82]196 stringstream filename;
197 ofstream output;
198 double norm = 0.;
199
200 filename << prefix << ".dat";
201 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
[a67d19]202 DoLog(0) && (Log() << Verbose(0) << msg << endl);
[042f82]203 output << "# " << msg << ", created on " << datum;
[b12a35]204 output << "# AtomNo\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
[042f82]205 Fragments.SetLastMatrix(Force.Matrix[Force.MatrixCounter], 0);
[f66195]206 for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
[e138de]207 //Log() << Verbose(0) << "Current order is " << BondOrder << "." << endl;
[f66195]208 Fragments.SumSubForces(Fragments, KeySets, BondOrder, -1.);
[042f82]209 // errors per atom
210 output << endl << "#Order\t" << BondOrder+1 << endl;
211 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
212 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";
[f731ae]213 for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++) {
[042f82]214 if (((l+1) % 3) == 0) {
215 norm = 0.;
216 for (int m=0;m<NDIM;m++)
217 norm += Force.Matrix[Force.MatrixCounter][ j ][l+m]*Force.Matrix[Force.MatrixCounter][ j ][l+m];
218 norm = sqrt(norm);
[437922]219 }
[042f82]220// if (norm < MYEPSILON)
221 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";
222// else
223// output << scientific << (Fragments.Matrix[Fragments.MatrixCounter][ j ][l] / norm) << "\t";
224 }
225 output << endl;
226 }
227 output << endl;
228 }
229 output.close();
230 return true;
[390248]231};
232
233/** Plot forces error vs. vs atom vs. order.
234 * \param &Fragments ForceMatrix class containing matrix values
[f66195]235 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
[390248]236 * \param *prefix prefix in filename (without ending)
237 * \param *msg message to be place in first line as a comment
238 * \param *datum current date and time
239 * \return true if file was written successfully
240 */
[f66195]241bool CreateDataForcesOrderPerAtom(class ForceMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
[390248]242{
[042f82]243 stringstream filename;
244 ofstream output;
245
246 filename << prefix << ".dat";
247 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
[a67d19]248 DoLog(0) && (Log() << Verbose(0) << msg << endl);
[042f82]249 output << "# " << msg << ", created on " << datum;
[b12a35]250 output << "# AtomNo\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
[f66195]251 for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
[e138de]252 //Log() << Verbose(0) << "Current order is " << BondOrder << "." << endl;
[f66195]253 Fragments.SumSubForces(Fragments, KeySets, BondOrder, 1.);
[042f82]254 // errors per atom
255 output << endl << "#Order\t" << BondOrder+1 << endl;
256 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
257 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";
[f731ae]258 for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++)
[390248]259 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";
260 output << endl;
[14de469]261 }
262 output << endl;
263 }
264 output.close();
265 return true;
266};
267
[b12a35]268
269/** Plot hessian error vs. vs atom vs. order.
270 * \param &Hessian HessianMatrix containing reference values (in MatrixCounter matrix)
271 * \param &Fragments HessianMatrix class containing matrix values
[f66195]272 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
[b12a35]273 * \param *prefix prefix in filename (without ending)
274 * \param *msg message to be place in first line as a comment
275 * \param *datum current date and time
276 * \return true if file was written successfully
277 */
[f66195]278bool CreateDataDeltaHessianOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
[b12a35]279{
280 stringstream filename;
281 ofstream output;
282
283 filename << prefix << ".dat";
284 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
[a67d19]285 DoLog(0) && (Log() << Verbose(0) << msg << endl);
[b12a35]286 output << "# " << msg << ", created on " << datum;
287 output << "# AtomNo\t" << Fragments.Header[Fragments.MatrixCounter] << endl;
288 Fragments.SetLastMatrix(Hessian.Matrix[Hessian.MatrixCounter], 0);
[f66195]289 for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
[e138de]290 //Log() << Verbose(0) << "Current order is " << BondOrder << "." << endl;
[f66195]291 Fragments.SumSubHessians(Fragments, KeySets, BondOrder, -1.);
[b12a35]292 // errors per atom
293 output << endl << "#Order\t" << BondOrder+1 << endl;
294 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
295 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";
296 for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++) {
297 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";
298 }
299 output << endl;
300 }
301 output << endl;
302 }
303 output.close();
304 return true;
305};
[05d2b2]306
307/** Plot hessian error vs. vs atom vs. order in the frobenius norm.
308 * \param &Hessian HessianMatrix containing reference values (in MatrixCounter matrix)
309 * \param &Fragments HessianMatrix class containing matrix values
[f66195]310 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
[05d2b2]311 * \param *prefix prefix in filename (without ending)
312 * \param *msg message to be place in first line as a comment
313 * \param *datum current date and time
314 * \return true if file was written successfully
315 */
[f66195]316bool CreateDataDeltaFrobeniusOrderPerAtom(class HessianMatrix &Hessian, class HessianMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
[05d2b2]317{
318 stringstream filename;
319 ofstream output;
320 double norm = 0;
321 double tmp;
322
323 filename << prefix << ".dat";
324 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
[a67d19]325 DoLog(0) && (Log() << Verbose(0) << msg << endl);
[05d2b2]326 output << "# " << msg << ", created on " << datum;
327 output << "# AtomNo\t";
328 Fragments.SetLastMatrix(Hessian.Matrix[Hessian.MatrixCounter], 0);
[f66195]329 for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
[05d2b2]330 output << "Order" << BondOrder+1 << "\t";
331 }
332 output << endl;
333 output << Fragments.RowCounter[ Fragments.MatrixCounter ] << "\t";
[f66195]334 for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
[e138de]335 //Log() << Verbose(0) << "Current order is " << BondOrder << "." << endl;
[f66195]336 Fragments.SumSubHessians(Fragments, KeySets, BondOrder, -1.);
[05d2b2]337 // frobenius norm of errors per atom
338 norm = 0.;
339 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
340 for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++) {
[ce5ac3]341 tmp = Fragments.Matrix[Fragments.MatrixCounter][ j ][l];
342 norm += tmp*tmp;
[05d2b2]343 }
344 }
345 output << scientific << sqrt(norm)/(Fragments.RowCounter[ Fragments.MatrixCounter ]*Fragments.ColumnCounter[ Fragments.MatrixCounter] ) << "\t";
346 }
347 output << endl;
348 output.close();
349 return true;
350};
[b12a35]351
352/** Plot hessian error vs. vs atom vs. order.
353 * \param &Fragments HessianMatrix class containing matrix values
[f66195]354 * \param KeySets KeySetContainer class holding bond KeySetContainer::Order
[b12a35]355 * \param *prefix prefix in filename (without ending)
356 * \param *msg message to be place in first line as a comment
357 * \param *datum current date and time
358 * \return true if file was written successfully
359 */
[f66195]360bool CreateDataHessianOrderPerAtom(class HessianMatrix &Fragments, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum)
[b12a35]361{
362 stringstream filename;
363 ofstream output;
364
365 filename << prefix << ".dat";
366 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
[a67d19]367 DoLog(0) && (Log() << Verbose(0) << msg << endl);
[b12a35]368 output << "# " << msg << ", created on " << datum;
369 output << "# AtomNo\t" << Fragments.Header[ Fragments.MatrixCounter ] << endl;
370 Fragments.SetLastMatrix(0., 0);
[f66195]371 for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
[e138de]372 //Log() << Verbose(0) << "Current order is " << BondOrder << "." << endl;
[f66195]373 Fragments.SumSubHessians(Fragments, KeySets, BondOrder, 1.);
[b12a35]374 // errors per atom
375 output << endl << "#Order\t" << BondOrder+1 << endl;
376 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
377 output << Fragments.Indices[Fragments.MatrixCounter][j] << "\t";
378 for (int l=0;l<Fragments.ColumnCounter[ Fragments.MatrixCounter ];l++)
[042f82]379 output << scientific << Fragments.Matrix[Fragments.MatrixCounter][ j ][l] << "\t";
380 output << endl;
381 }
382 output << endl;
383 }
384 output.close();
385 return true;
[14de469]386};
387
388/** Plot matrix vs. fragment.
389 */
[f66195]390bool CreateDataFragment(class MatrixContainer &Fragment, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum, void (*CreateFragment)(class MatrixContainer &, int))
[14de469]391{
[042f82]392 stringstream filename;
393 ofstream output;
394
395 filename << prefix << ".dat";
396 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
[a67d19]397 DoLog(0) && (Log() << Verbose(0) << msg << endl);
[042f82]398 output << "# " << msg << ", created on " << datum << endl;
[b12a35]399 output << "#Order\tFrag.No.\t" << Fragment.Header[ Fragment.MatrixCounter ] << endl;
[f66195]400 for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
401 for(int i=0;i<KeySets.FragmentsPerOrder[BondOrder];i++) {
402 output << BondOrder+1 << "\t" << KeySets.OrderSet[BondOrder][i]+1;
403 CreateFragment(Fragment, KeySets.OrderSet[BondOrder][i]);
404 for (int l=0;l<Fragment.ColumnCounter[ KeySets.OrderSet[BondOrder][i] ];l++)
405 output << scientific << "\t" << Fragment.Matrix[ KeySets.OrderSet[BondOrder][i] ][ Fragment.RowCounter[ KeySets.OrderSet[BondOrder][i] ] ][l];
[042f82]406 output << endl;
407 }
408 }
409 output.close();
410 return true;
[14de469]411};
412
413/** Copies fragment energy values into last matrix of \a Matrix with greatest total energy.
414 * \param &Matrix MatrixContainer with all fragment energy values
[f66195]415 * \param &KeySets KeySetsContainer with associations of each fragment to a bond order
[14de469]416 * \param BondOrder current bond order
[6ac7ee]417 */
[f66195]418void CreateMaxFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySets, int BondOrder)
[14de469]419{
[042f82]420 for(int j=Fragments.RowCounter[ Fragments.MatrixCounter ];j--;) {
[f66195]421 for(int i=KeySets.FragmentsPerOrder[BondOrder];i--;) {
422 if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < fabs(Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][1])) {
[f731ae]423 for (int k=Fragments.ColumnCounter[ Fragments.MatrixCounter ];k--;)
[f66195]424 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][k];
[042f82]425 }
426 }
427 }
[14de469]428};
429
430/** Copies fragment energy values into last matrix of \a Matrix with smallest total energy.
431 * \param &Matrix MatrixContainer with all fragment energy values
[f66195]432 * \param &KeySets KeySetsContainer with associations of each fragment to a bond order
[14de469]433 * \param BondOrder current bond order
[6ac7ee]434 */
[f66195]435void CreateMinFragmentOrder(class MatrixContainer &Fragments, class KeySetsContainer &KeySets, int BondOrder)
[14de469]436{
[042f82]437 for(int j=0;j<Fragments.RowCounter[ Fragments.MatrixCounter ];j++) {
438 int i=0;
439 do { // first get a minimum value unequal to 0
[f731ae]440 for (int k=Fragments.ColumnCounter[ Fragments.MatrixCounter ];k--;)
[f66195]441 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][k];
[042f82]442 i++;
[f66195]443 } while ((fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) < MYEPSILON) && (i<KeySets.FragmentsPerOrder[BondOrder]));
444 for(;i<KeySets.FragmentsPerOrder[BondOrder];i++) { // then find lowest
445 if (fabs(Fragments.Matrix[ Fragments.MatrixCounter ][j][1]) > fabs(Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][1])) {
[f731ae]446 for (int k=Fragments.ColumnCounter[ Fragments.MatrixCounter ];k--;)
[f66195]447 Fragments.Matrix[ Fragments.MatrixCounter ][j][k] = Fragments.Matrix[ KeySets.OrderSet[BondOrder][i] ][j][k];
[042f82]448 }
449 }
450 }
[14de469]451};
452
453/** Plot matrix vs. fragment.
454 */
[f66195]455bool CreateDataFragmentOrder(class MatrixContainer &Fragment, class KeySetsContainer &KeySets, const char *dir, const char *prefix, const char *msg, const char *datum, void (*CreateFragmentOrder)(class MatrixContainer &, class KeySetsContainer &, int))
[14de469]456{
[042f82]457 stringstream filename;
458 ofstream output;
459
460 filename << prefix << ".dat";
461 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
[a67d19]462 DoLog(0) && (Log() << Verbose(0) << msg << endl);
[042f82]463 output << "# " << msg << ", created on " << datum;
[b12a35]464 output << "#Order\tFrag.No.\t" << Fragment.Header[ Fragment.MatrixCounter ] << endl;
[042f82]465 // max
[f66195]466 for (int BondOrder=0;BondOrder<KeySets.Order;BondOrder++) {
[042f82]467 Fragment.SetLastMatrix(0.,0);
[f66195]468 CreateFragmentOrder(Fragment, KeySets, BondOrder);
469 output << BondOrder+1 << "\t" << KeySets.FragmentsPerOrder[BondOrder];
[f731ae]470 for (int l=0;l<Fragment.ColumnCounter[ Fragment.MatrixCounter ];l++)
[042f82]471 output << scientific << "\t" << Fragment.Matrix[ Fragment.MatrixCounter ][ Fragment.RowCounter[ Fragment.MatrixCounter ]-1 ][l];
472 output << endl;
473 }
474 output.close();
475 return true;
[14de469]476};
477
478/** Takes last but one row and copies into final row.
479 * \param Energy MatrixContainer with matrix values
480 * \param MatrixNumber the index for the ForceMatrix::matrix array
481 */
482void CreateEnergy(class MatrixContainer &Energy, int MatrixNumber)
483{
[f731ae]484 for(int k=0;k<Energy.ColumnCounter[MatrixNumber];k++)
[042f82]485 Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber] ] [k] = Energy.Matrix[MatrixNumber][ Energy.RowCounter[MatrixNumber]-1 ] [k];
[14de469]486};
487
488/** Scans forces for the minimum in magnitude.
489 * Results are stored in the matrix ForceMatrix::MatrixCounter of \a Force.
490 * \param Force ForceMatrix class containing matrix values
491 * \param MatrixNumber the index for the ForceMatrix::matrix array
492 */
493void CreateMinimumForce(class MatrixContainer &Force, int MatrixNumber)
494{
[f731ae]495 for (int l=Force.ColumnCounter[MatrixNumber];l--;)
[042f82]496 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;
[f731ae]497 for (int l=5;l<Force.ColumnCounter[MatrixNumber];l+=3) {
[042f82]498 double stored = 0;
499 int k=0;
500 do {
501 for (int m=NDIM;m--;) {
502 stored += Force.Matrix[MatrixNumber][ k ][l+m]
503 * Force.Matrix[MatrixNumber][ k ][l+m];
504 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m];
505 }
506 k++;
507 } while ((fabs(stored) < MYEPSILON) && (k<Force.RowCounter[MatrixNumber]));
508 for (;k<Force.RowCounter[MatrixNumber];k++) {
509 double tmp = 0;
510 for (int m=NDIM;m--;)
511 tmp += Force.Matrix[MatrixNumber][ k ][l+m]
512 * Force.Matrix[MatrixNumber][ k ][l+m];
513 if ((fabs(tmp) > MYEPSILON) && (tmp < stored)) { // current force is greater than stored
514 for (int m=NDIM;m--;)
515 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m];
516 stored = tmp;
517 }
518 }
519 }
[14de469]520};
521
522/** Scans forces for the mean in magnitude.
523 * Results are stored in the matrix ForceMatrix::MatrixCounter of \a Force.
524 * \param Force ForceMatrix class containing matrix values
[042f82]525 * \param MatrixNumber the index for the ForceMatrix::matrix array
[14de469]526 */
527void CreateMeanForce(class MatrixContainer &Force, int MatrixNumber)
528{
[042f82]529 int divisor = 0;
[f731ae]530 for (int l=Force.ColumnCounter[MatrixNumber];l--;)
[042f82]531 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;
[f731ae]532 for (int l=5;l<Force.ColumnCounter[MatrixNumber];l+=3) {
[042f82]533 double tmp = 0;
534 for (int k=Force.RowCounter[MatrixNumber];k--;) {
535 double norm = 0.;
536 for (int m=NDIM;m--;)
537 norm += Force.Matrix[MatrixNumber][ k ][l+m]
538 * Force.Matrix[MatrixNumber][ k ][l+m];
539 tmp += sqrt(norm);
540 if (fabs(norm) > MYEPSILON) divisor++;
541 }
542 tmp /= (double)divisor;
543 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = tmp;
544 }
[14de469]545};
546
547/** Scans forces for the maximum in magnitude.
548 * Results are stored in the matrix ForceMatrix::MatrixCounter of \a Force.
549 * \param Force ForceMatrix class containing matrix values
550 * \param MatrixNumber the index for the ForceMatrix::matrix array
551 */
552void CreateMaximumForce(class MatrixContainer &Force, int MatrixNumber)
553{
[f731ae]554 for (int l=5;l<Force.ColumnCounter[MatrixNumber];l+=3) {
[042f82]555 double stored = 0;
556 for (int k=Force.RowCounter[MatrixNumber];k--;) {
557 double tmp = 0;
558 for (int m=NDIM;m--;)
559 tmp += Force.Matrix[MatrixNumber][ k ][l+m]
560 * Force.Matrix[MatrixNumber][ k ][l+m];
561 if (tmp > stored) { // current force is greater than stored
562 for (int m=NDIM;m--;)
563 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l+m] = Force.Matrix[MatrixNumber][ k ][l+m];
564 stored = tmp;
565 }
566 }
567 }
[14de469]568};
569
[390248]570/** Leaves the Force.Matrix as it is.
571 * \param Force ForceMatrix class containing matrix values
572 * \param MatrixNumber the index for the ForceMatrix::matrix array
573*/
574void CreateSameForce(class MatrixContainer &Force, int MatrixNumber)
575{
[042f82]576 // does nothing
[390248]577};
578
[14de469]579/** Adds vectorwise all forces.
580 * Results are stored in the matrix ForceMatrix::MatrixCounter of \a Force.
581 * \param Force ForceMatrix class containing matrix values
582 * \param MatrixNumber the index for the ForceMatrix::matrix array
583 */
584void CreateVectorSumForce(class MatrixContainer &Force, int MatrixNumber)
585{
[f731ae]586 for (int l=Force.ColumnCounter[MatrixNumber];l--;)
[042f82]587 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] = 0.;
[f731ae]588 for (int l=0;l<Force.ColumnCounter[MatrixNumber];l++) {
[042f82]589 for (int k=Force.RowCounter[MatrixNumber];k--;)
590 Force.Matrix[MatrixNumber][ Force.RowCounter[MatrixNumber] ][l] += Force.Matrix[MatrixNumber][k][l];
591 }
[14de469]592};
593
594/** Writes the standard pyxplot header info.
595 * \param keycolumns number of columns of the key
596 * \param *key position of key
597 * \param *logscale axis for logscale
[6ac7ee]598 * \param *extraline extra set lines if desired
[14de469]599 * \param mxtics small tics at ...
600 * \param xtics large tics at ...
[6ac7ee]601 * \param *xlabel label for x axis
[14de469]602 * \param *ylabel label for y axis
[6ac7ee]603 */
[14de469]604void 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)
605{
[042f82]606 //output << "#!/home/heber/build/pyxplot/pyxplot" << endl << endl;
607 output << "reset" << endl;
608 output << "set keycolumns "<< keycolumns << endl;
609 output << "set key " << key << endl;
610 output << "set mxtics "<< mxtics << endl;
611 output << "set xtics "<< xtics << endl;
612 if (logscale != NULL)
613 output << "set logscale " << logscale << endl;
614 if (extraline != NULL)
615 output << extraline << endl;
616 output << "set xlabel '" << xlabel << "'" << endl;
617 output << "set ylabel '" << ylabel << "'" << endl;
618 output << "set terminal eps color" << endl;
619 output << "set output '"<< prefix << ".eps'" << endl;
[14de469]620};
621
622/** Creates the pyxplotfile for energy data.
623 * \param Matrix MatrixContainer with matrix values
[f66195]624 * \param KeySets contains bond order
[14de469]625 * \param *dir directory
626 * \param *prefix prefix for all filenames (without ending)
627 * \param keycolumns number of columns of the key
628 * \param *key position of key
629 * \param logscale axis for logscale
630 * \param mxtics small tics at ...
631 * \param xtics large tics at ...
[6ac7ee]632 * \param xlabel label for x axis
[14de469]633 * \param xlabel label for x axis
634 * \param *xrange xrange
635 * \param *yrange yrange
636 * \param *xargument number of column to plot against (x axis)
637 * \param uses using string for plot command
638 * \param (*CreatePlotLines) function reference that writes a single plot line
639 * \return true if file was written successfully
[6ac7ee]640 */
[f66195]641bool CreatePlotOrder(class MatrixContainer &Matrix, const class KeySetsContainer &KeySets, const char *dir, const char *prefix, const int keycolumns, const char *key, const char *logscale, const char *extraline, const int mxtics, const int xtics, const char *xlabel, const char *ylabel, const char *xrange, const char *yrange, const char *xargument, const char *uses, void (*CreatePlotLines)(ofstream &, class MatrixContainer &, const char *, const char *, const char *))
[14de469]642{
[042f82]643 stringstream filename;
644 ofstream output;
645
646 filename << prefix << ".pyx";
647 if (!OpenOutputFile(output, dir, filename.str().c_str())) return false;
648 CreatePlotHeader(output, prefix, keycolumns, key, logscale, extraline, mxtics, xtics, xlabel, ylabel);
649 output << "plot " << xrange << " " << yrange << " \\" << endl;
650 CreatePlotLines(output, Matrix, prefix, xargument, uses);
651 output.close();
652 return true;
[14de469]653};
654
655/** Writes plot lines for absolute energies.
656 * \param output file handler
657 * \param Energy MatrixContainer with matrix values
658 * \param *prefix prefix of data file
659 * \param *xargument number of column to plot against (x axis)
660 * \param *uses uses command
661 */
662void AbsEnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses)
663{
[b12a35]664 stringstream line(Energy.Header[ Energy.MatrixCounter ]);
[042f82]665 string token;
666
667 getline(line, token, '\t');
[f731ae]668 for (int i=2; i<= Energy.ColumnCounter[Energy.MatrixCounter];i++) {
[042f82]669 getline(line, token, '\t');
670 while (token[0] == ' ') // remove leading white spaces
671 token.erase(0,1);
672 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+2 << ")) " << uses;
[f731ae]673 if (i != (Energy.ColumnCounter[Energy.MatrixCounter]))
[042f82]674 output << ", \\";
675 output << endl;
676 }
[14de469]677};
678
679/** Writes plot lines for energies.
680 * \param output file handler
681 * \param Energy MatrixContainer with matrix values
682 * \param *prefix prefix of data file
683 * \param *xargument number of column to plot against (x axis)
684 * \param *uses uses command
685 */
686void EnergyPlotLine(ofstream &output, class MatrixContainer &Energy, const char *prefix, const char *xargument, const char *uses)
687{
[b12a35]688 stringstream line(Energy.Header[Energy.MatrixCounter]);
[042f82]689 string token;
690
691 getline(line, token, '\t');
[f731ae]692 for (int i=1; i<= Energy.ColumnCounter[Energy.MatrixCounter];i++) {
[042f82]693 getline(line, token, '\t');
694 while (token[0] == ' ') // remove leading white spaces
695 token.erase(0,1);
696 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":" << i+2 << " " << uses;
[f731ae]697 if (i != (Energy.ColumnCounter[Energy.MatrixCounter]))
[042f82]698 output << ", \\";
699 output << endl;
700 }
[14de469]701};
702
703/** Writes plot lines for absolute force magnitudes.
704 * \param output file handler
705 * \param Force MatrixContainer with matrix values
706 * \param *prefix prefix of data file
707 * \param *xargument number of column to plot against (x axis)
708 * \param *uses uses command
709 */
710void ForceMagnitudePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses)
711{
[b12a35]712 stringstream line(Force.Header[Force.MatrixCounter]);
[042f82]713 string token;
714
715 getline(line, token, '\t');
716 getline(line, token, '\t');
717 getline(line, token, '\t');
718 getline(line, token, '\t');
719 getline(line, token, '\t');
[f731ae]720 for (int i=7; i< Force.ColumnCounter[Force.MatrixCounter];i+=NDIM) {
[042f82]721 getline(line, token, '\t');
722 while (token[0] == ' ') // remove leading white spaces
723 token.erase(0,1);
724 token.erase(token.length(), 1); // kill residual index char (the '0')
725 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(sqrt($" << i+1 << "*$" << i+1 << "+$" << i+2 << "*$" << i+2 << "+$" << i+3 << "*$" << i+3 << ")) " << uses;
[f731ae]726 if (i != (Force.ColumnCounter[Force.MatrixCounter]-1))
[042f82]727 output << ", \\";
728 output << endl;
729 getline(line, token, '\t');
730 getline(line, token, '\t');
731 }
[14de469]732};
733
734/** Writes plot lines for first component of force vector.
735 * \param output file handler
736 * \param Force MatrixContainer with matrix values
737 * \param *prefix prefix of data file
738 * \param *xargument number of column to plot against (x axis)
739 * \param *uses uses command
740 */
741void AbsFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses)
742{
[b12a35]743 stringstream line(Force.Header[Force.MatrixCounter]);
[042f82]744 string token;
745
746 getline(line, token, '\t');
747 getline(line, token, '\t');
748 getline(line, token, '\t');
749 getline(line, token, '\t');
750 getline(line, token, '\t');
[f731ae]751 for (int i=7; i< Force.ColumnCounter[Force.MatrixCounter];i+=NDIM) {
[042f82]752 getline(line, token, '\t');
753 while (token[0] == ' ') // remove leading white spaces
754 token.erase(0,1);
755 token.erase(token.length(), 1); // kill residual index char (the '0')
756 output << "'" << prefix << ".dat' title '" << token << "' using " << xargument << ":(abs($" << i+1 << ")) " << uses;
[f731ae]757 if (i != (Force.ColumnCounter[Force.MatrixCounter]-1))
[042f82]758 output << ", \\";
759 output << endl;
760 getline(line, token, '\t');
761 getline(line, token, '\t');
762 }
[14de469]763};
764
765/** Writes plot lines for force vector as boxes with a fillcolor.
766 * \param output file handler
767 * \param Force MatrixContainer with matrix values
768 * \param *prefix prefix of data file
769 * \param *xargument number of column to plot against (x axis)
770 * \param *uses uses command
771 */
772void BoxesForcePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses)
773{
[b12a35]774 stringstream line(Force.Header[Force.MatrixCounter]);
[1f2217]775 const char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"};
[042f82]776 string token;
777
778 getline(line, token, '\t');
779 getline(line, token, '\t');
780 getline(line, token, '\t');
781 getline(line, token, '\t');
782 getline(line, token, '\t');
[f731ae]783 for (int i=7; i< Force.ColumnCounter[Force.MatrixCounter];i+=NDIM) {
[042f82]784 getline(line, token, '\t');
785 while (token[0] == ' ') // remove leading white spaces
786 token.erase(0,1);
787 token.erase(token.length(), 1); // kill residual index char (the '0')
788 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];
[f731ae]789 if (i != (Force.ColumnCounter[Force.MatrixCounter]-1))
[042f82]790 output << ", \\";
791 output << endl;
792 getline(line, token, '\t');
793 getline(line, token, '\t');
794 }
[14de469]795};
796
797/** Writes plot lines for first force vector component as boxes with a fillcolor.
798 * \param output file handler
799 * \param Force MatrixContainer with matrix values
800 * \param *prefix prefix of data file
801 * \param *xargument number of column to plot against (x axis)
802 * \param *uses uses command
803 */
804void BoxesFirstForceValuePlotLine(ofstream &output, class MatrixContainer &Force, const char *prefix, const char *xargument, const char *uses)
805{
[b12a35]806 stringstream line(Force.Header[Force.MatrixCounter]);
[1f2217]807 const char *fillcolor[5] = {"black", "red", "blue", "green", "cyan"};
[042f82]808 string token;
809
810 getline(line, token, '\t');
811 getline(line, token, '\t');
812 getline(line, token, '\t');
813 getline(line, token, '\t');
814 getline(line, token, '\t');
[f731ae]815 for (int i=7; i< Force.ColumnCounter[Force.MatrixCounter];i+=NDIM) {
[042f82]816 getline(line, token, '\t');
817 while (token[0] == ' ') // remove leading white spaces
818 token.erase(0,1);
819 token.erase(token.length(), 1); // kill residual index char (the '0')
820 output << "'" << prefix << ".dat' title '" << token << "' using ($" << xargument << "+" << fixed << setprecision(1) << (double)((i-7)/3)*0.2 << "):" << i+1 << " " << uses << " " << fillcolor[(i-7)/3];
[f731ae]821 if (i != (Force.ColumnCounter[Force.MatrixCounter]-1))
[042f82]822 output << ", \\";
823 output << endl;
824 getline(line, token, '\t');
825 getline(line, token, '\t');
826 }
[14de469]827};
Note: See TracBrowser for help on using the repository browser.