1 /*=================================================================*/
2 /*= calc.h =*/
3 /*= header file for calculation routines for treekin =*/
4 /*= =*/
5 /*= (c) Michael Thomas Wolfinger, W. Andreas Svrcek-Seiler =*/
6 /*= {mtw,svrci}@tbi.univie.ac.at =*/
7 /*= treekin =*/
8 /*=================================================================*/
9
10 #ifndef _CALC_H_
11 #define _CALC_H_
12
13 /* If we use autoconf. */
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17
18 #include <cstdlib>
19 #include <cmath>
20 #include <algorithm> /* fill_n */
21 #include <set>
22 #include <queue>
23 #include <vector>
24 #include <errno.h>
25 #include <assert.h>
26
27 #include "mxccm.h" /* functions for eigen-problems stolen from ccmath */
28 #include "globals.h"
29 #include "barparser.h"
30 #include "calcpp.h"
31 #include "bardata.h"
32 #include "exp_matrix.h"
33
34 template<typename T>
35 class Calc {
36 int dim;
37 double _kT;
38 T *evals;
39 T *evecs;
40 T *_sqrPI; /* left constant array */
41 T *sqrPI_; /* right constant array */
42 T *D; /* matrix with degree of degeneracy */
43 char Aname[30];
44
45 Globals *_globalParameters;
46 treekin_options *_opt;
47 int _lmins;
48 SubInfo *_E;
49 Mxccm mxccm;
50 std::vector<int> reorganize; /* reorganize array (so if LM 0 1 3 were reachable and 2 not, reorganize will contain r[0]=0 r[1]=1 r[2]=3), so r[x] = old position of x */
51
52 Calccpp *solver;
53
54 private:
55 T *MxMethodeA(BarData *Data);
56
57
58 /*T *MxMethodeFULL(T *); */
59 T *MxMethodeINPUT(BarData *Data,
60 T *);
61
62
63 T max_saddle(int i,
64 int j,
65 BarData *Data);
66
67
68 void print_settings(void);
69
70
71 char *time_stamp(void);
72
73
74 void MxDoDegeneracyStuff(void);
75
76
77 void MxBinWrite(T *Mx,
78 const char what[],
79 char c);
80
81
82 int MxBinRead(T **Mx,
83 const char what[],
84 char c);
85
86
87 void MxASCIIWrite(T *Mx,
88 const char *asciifile);
89
90
91 void MxASCIIWriteV(T *Mx,
92 const char *asciifile);
93
94
95 void MxKotzOutMathematica(T *Mx);
96
97
98 void MxSortEig(T *evals,
99 T *evecs);
100
101
102 void MxEVLapackSym(T *U);
103
104
105 void MxEVLapackNonSym(T *U);
106
107
108 void MxFixevecs(T *,
109 T *);
110
111
112 void MxFixevecsAbsorb(T *,
113 T *);
114
115
116 void MxDiagHelper(T *P8);
117
118
119 void norm2(T *mx);
120
121
122 int *MxErgoEigen(T *U,
123 int dim);
124
125
126 public:
127 Calc(Globals *globalParameters,
128 SubInfo *E,
129 int dim);
130 ~Calc();
131
132 /**
133 * check for ergodicity
134 */
135 int MxEgro(T **U,
136 T **p0,
137 int dim);
138
139
140 void PrintDummy(T *line);
141
142
143 /**
144 * print probabilities (adds zero (non-ergodic) columns)
145 * returns sum of these probabilities
146 */
147 T PrintProb(T *line,
148 int dim,
149 double time);
150
151
152 T PrintProbFull(T *line,
153 int dim,
154 double time,
155 int lmins);
156
157
158 T PrintProbNR(T *line,
159 int dim,
160 double time);
161
162
163 void *MxNew(size_t size);
164
165
166 void MxGetSpace(T **p8);
167
168
169 T *MxBar2Matrix(BarData *Data,
170 T *);
171
172
173 void MxEqDistr(BarData *Data,
174 T **p8);
175
176
177 void MxEqDistrFULL(SubInfo *E,
178 T *p8);
179
180
181 void MxDiagonalize(T *U,
182 T **_S,
183 T *PI);
184
185
186 void MxRecover(T **_S,
187 T *P8);
188
189
190 void MxStartVec(T **p0);
191
192
193 int ConvergenceReached(T *p8,
194 T *pt,
195 int dim,
196 int full);
197
198
199 void MxIterate(T *p0,
200 T *p8,
201 T *S);
202
203
204 void MxMemoryCleanUp(void);
205
206
207 int MxExponent(T *p0,
208 T *p8,
209 T *U);
210
211
212 void MxFPT(T *U,
213 T *p8,
214 FILE *out);
215
216
217 void MxEqDistrFromLinSys(T *U,
218 T **p8);
219
220
221 void MxEqDistrFromDetailedBalance(T *U,
222 T **p8);
223
224
225 void MxFPTSimple(T *U);
226
227
228 T *MxFPTOneState(T *U,
229 int state);
230
231
232 /* not used! (just for past testing) */
233 T MxFPTRandom(T *P,
234 T *U,
235 int src,
236 int dst,
237 int packets);
238
239
240 void MxFPTRnd(T *U,
241 int packets);
242
243
244 void MxFPrint(T *mx,
245 const char *name,
246 char c,
247 FILE *out,
248 int pure);
249
250
251 void MxPrint(T *mx,
252 const char *name,
253 char c);
254 };
255
256 template<typename T>
Calc(Globals * globalParameters,SubInfo * E,int d)257 Calc<T>::Calc(Globals *globalParameters,
258 SubInfo *E,
259 int d)
260 {
261 _globalParameters = globalParameters;
262 _opt = &globalParameters->opt;
263 _lmins = globalParameters->lmins;
264 _E = E;
265 _kT = 0.00198717 * (273.15 + _opt->T);
266
267 evals = NULL;
268 evecs = NULL;
269 _sqrPI = NULL; /* left constant array */
270 sqrPI_ = NULL; /* right constant array */
271 D = NULL;
272 dim = d;
273 solver = new Calccpp(_opt, _E);
274 }
275
276
277 template<typename T>
~Calc()278 Calc<T>::~Calc()
279 {
280 delete solver;
281 }
282
283
284 template<typename T>
285 int
MxEgro(T ** Up,T ** p0p,int dim)286 Calc<T>::MxEgro(T **Up,
287 T **p0p,
288 int dim)
289 {
290 /* aliases */
291 T *U = *Up;
292 T *p0 = *p0p;
293
294 /* lokalize first non-empty state */
295 int first = 0;
296
297 while (p0[first] == (T)0.0)
298 first++;
299
300 /* make set of all non-empty states */
301 std::set<int> set_ergo;
302 std::queue<int> que_ergo;
303
304 set_ergo.insert(first);
305 que_ergo.push(first);
306
307 /* fill the sets of non-empty states */
308 while (!que_ergo.empty() && (int)set_ergo.size() < dim) {
309 int to_do = que_ergo.front();
310 que_ergo.pop();
311
312 /* collect contingency */
313 for (int i = 0; i < dim; i++) {
314 if (i == to_do)
315 continue;
316
317 if (U[i * dim + to_do] > (T)0.0 && (int)set_ergo.count(i) == 0) {
318 set_ergo.insert(i);
319 que_ergo.push(i);
320 }
321 }
322 }
323
324 /* check ergodicity */
325 if ((int)set_ergo.size() == dim) {
326 return dim; /* all ok */
327 } else {
328 int i = first + 1;
329 while (i < dim) {
330 if (p0[i] > (T)0.0 && set_ergo.count(i) == 0) {
331 /* disconnected :( */
332 fprintf(stderr,
333 "ERROR: Matrix is non-ergodic and initial populations are disconected!! Exiting...\n");
334 exit(-1);
335 }
336
337 i++;
338 }
339
340 /* fill helper reorganize array */
341 reorganize.resize(set_ergo.size());
342 i = 0;
343 for (std::set<int>::iterator it = set_ergo.begin(); it != set_ergo.end(); it++)
344 reorganize[i++] = *it;
345
346 /* reorganize matrix */
347 for (int i = 0; i < (int)set_ergo.size(); i++)
348 for (int j = 0; j < (int)set_ergo.size(); j++)
349 U[i * set_ergo.size() + j] = U[reorganize[i] * dim + reorganize[j]];
350
351 dim = set_ergo.size();
352 /**Up = (T*)realloc(U, dim*dim*sizeof(T)); */
353 *Up = new T[dim * dim];
354 std::copy_n(U, dim * dim, *Up);
355 delete[] U;
356 U = *Up;
357
358 /* reorganize p0 */
359 for (int i = 0; i < (int)set_ergo.size(); i++)
360 p0[i] = p0[reorganize[i]];
361 /**p0p = (T*)realloc(p0, dim*sizeof(T)); */
362 *p0p = new T[dim];
363 std::copy_n(p0, dim, *p0p);
364 delete[] p0;
365 p0 = *p0p;
366
367 if (!_opt->quiet)
368 fprintf(stderr, "WARNING: Matrix is non-ergodic! Decreasing dimension to %d.\n", dim);
369
370 /*MxPrint(U, "Ergodic U", 'm'); */
371
372 if (dim == 1) {
373 PrintDummy(p0);
374 return dim;
375 }
376 }
377
378 /* return new reduced dimension of the inputmatrix. */
379 return dim;
380 }
381
382
383 template<typename T>
384 void
PrintDummy(T * line)385 Calc<T>::PrintDummy(T *line)
386 {
387 print_settings();
388 PrintProb(line, 1, _opt->t0);
389 PrintProb(line, 1, _opt->t8);
390 }
391
392
393 template<typename T>
394 T
PrintProbFull(T * line,int dim,double time,int lmins)395 Calc<T>::PrintProbFull(T *line,
396 int dim,
397 double time,
398 int lmins)
399 {
400 /* for full process: */
401 std::vector<T> ptFULL(lmins, 0.0);
402
403 if (reorganize.size() == 0)
404 for (int i = 0; i < dim; i++)
405 ptFULL[_E[i].ag] += line[i];
406 else
407 for (int i = 0; i < dim; i++)
408 ptFULL[_E[reorganize[i]].ag] += line[i];
409
410 /* sum first */
411 T check = 0.0;
412 for (int i = 0; i < lmins; i++) {
413 if (ptFULL[i] < -0.01) {
414 fprintf(stderr,
415 "prob of lmin %i at time %e has become negative: %e \n",
416 i + 1,
417 time,
418 (double)ptFULL[i]);
419 if (_opt->num_err == 'H')
420 exit(EXIT_FAILURE);
421 else if (_opt->num_err == 'R')
422 ptFULL[i] = 0.0;
423 }
424
425 /* map individual structure -> gradient basins */
426 check += abs(ptFULL[i]);
427 }
428
429 /* check for overall propability */
430 if (((check - 1.) < -0.05) || ((check - 1.) > 0.05)) {
431 fprintf(stderr, "overall probability at time %e is %e != 1.0 %s!\n", time, (double)check,
432 (_opt->num_err == 'R' ? "rescaling" : "exiting"));
433 if (_opt->num_err == 'H' || check == 0.0)
434 exit(EXIT_FAILURE);
435 }
436
437 /* print: */
438 printf("%22.20e ", time);
439 for (int i = 0; i < lmins; i++) {
440 if (_opt->num_err == 'R')
441 printf("%e ", (double)(T)(abs(ptFULL[i]) / check));
442 else
443 printf("%e ", (double)(T)abs(ptFULL[i]));
444 }
445 printf("\n");
446
447 return check;
448 }
449
450
451 template<typename T>
452 T
PrintProbNR(T * line,int dim,double time)453 Calc<T>::PrintProbNR(T *line,
454 int dim,
455 double time)
456 {
457 T check = 0.0;
458
459 /* summ first */
460 for (int i = 0; i < dim; i++) {
461 if (line[i] < -0.01) {
462 fprintf(stderr, "prob of lmin %i at time %e has become negative: %e \n", i + 1, time,
463 line[i]);
464 if (_opt->num_err == 'H')
465 exit(EXIT_FAILURE);
466 else if (_opt->num_err == 'R')
467 line[i] = 0.0;
468 }
469
470 /* map individual structure -> gradient basins */
471 check += abs(line[i]);
472 }
473
474 /* check for overall propability */
475 if (((check - 1.) < -0.05) || ((check - 1.) > 0.05)) {
476 fprintf(stderr, "overall probability at time %e is %e != 1.0 %s!\n", time, check,
477 (_opt->num_err == 'R' ? "rescaling" : "exiting"));
478 if (_opt->num_err == 'H' || check == 0.0)
479 exit(EXIT_FAILURE);
480 }
481
482 /* print */
483 printf("%22.20e ", time);
484 for (int i = 0; i < dim; i++) {
485 if (_opt->num_err == 'R')
486 printf("%e ", abs(line[i]) / check);
487 else
488 printf("%e ", abs(line[i]));
489 }
490
491 printf("\n");
492
493 return check;
494 }
495
496
497 template<typename T>
498 T
PrintProb(T * line,int dim,double time)499 Calc<T>::PrintProb(T *line,
500 int dim,
501 double time)
502 {
503 T check = (T)0.0;
504
505 /* sum it up */
506 for (int i = 0; i < dim; i++) {
507 if (line[i] < -0.01) {
508 fprintf(stderr,
509 "prob of lmin %i at time %e has become negative: %e \n",
510 i + 1,
511 time,
512 (double)line[i]);
513 if (_opt->num_err == 'H')
514 exit(EXIT_FAILURE);
515 else if (_opt->num_err == 'R')
516 line[i] = 0.0;
517 }
518
519 check += abs(line[i]);
520 }
521
522 /* check for overall probability */
523 if (((check - 1.) < -0.05) || ((check - 1.) > 0.05)) {
524 fprintf(stderr, "overall probability at time %e is %e != 1.0 %s!\n", time, (double)check,
525 (_opt->num_err == 'R' && (double)check != 0.0 ? "rescaling" : "exiting"));
526 if (_opt->num_err == 'H' || check == 0.0)
527 exit(EXIT_FAILURE);
528 }
529
530 /* print finally: */
531 printf("%22.20e ", time);
532 if (reorganize.size() == 0) {
533 for (int i = 0; i < dim; i++) {
534 /* map individual structure -> gradient basins */
535 if (_opt->num_err == 'R')
536 printf("%e ", (double)(T)(abs(line[i]) / check));
537 else
538 printf("%e ", (double)(T)abs(line[i]));
539 }
540 } else {
541 int j = 0;
542 for (int i = 0; i < dim; i++) {
543 if (j > (int)reorganize.size() || reorganize[j] != i) {
544 printf("%e ", 0.0);
545 } else {
546 if (_opt->num_err == 'R')
547 printf("%e ", (double)(T)(abs(line[j]) / check));
548 else
549 printf("%e ", (double)(T)abs(line[j]));
550
551 j++;
552 }
553 }
554 }
555
556 printf("\n");
557
558 return check;
559 }
560
561
562 template<typename T>
563 int *
MxErgoEigen(T * U,int dim)564 Calc<T>::MxErgoEigen(T *U,
565 int dim)
566 {
567 int count = 1;
568 std::vector<bool> reached(dim, false);
569
570 reached[0] = true;
571
572 std::queue<int> que_ergo;
573 que_ergo.push(0);
574
575 /* fill the sets of non-empty states */
576 while (!que_ergo.empty() && count < dim) {
577 int to_do = que_ergo.front();
578 que_ergo.pop();
579
580 /* collect contingency */
581 for (int i = 0; i < dim; i++) {
582 if (i == to_do)
583 continue;
584
585 if ((double)U[i * dim + to_do] != 0.0 && (double)U[to_do * dim + i] != 0.0 && !reached[i]) {
586 reached[i] = true;
587 que_ergo.push(i);
588 count++;
589 }
590 }
591 }
592
593 /* return the array of unreached states: */
594 if (dim == count)
595 return NULL;
596
597 int *result = (int *)malloc(dim * sizeof(int));
598 for (int i = 0; i < dim; i++)
599 result[i] = (reached[i] ? 1 : 0);
600 return result;
601 }
602
603
604 /*==*/
605 template<typename T>
606 T *
MxBar2Matrix(BarData * Data,T * R)607 Calc<T>::MxBar2Matrix(BarData *Data,
608 T *R)
609 {
610 T *U = NULL;
611
612 if (_opt->want_degenerate)
613 MxDoDegeneracyStuff();
614
615 switch (_opt->method) {
616 case 'A':
617 U = MxMethodeA(Data);
618 break;
619 /*
620 * case 'F':
621 * U = MxMethodeFULL(R);
622 * break;
623 */
624 case 'I':
625 U = MxMethodeINPUT(Data, R);
626 break;
627 default:
628 fprintf(stderr,
629 "ERROR in MxBar2Matrix(): No handler 4 method %c\n", _opt->method);
630 exit(EXIT_FAILURE);
631 }
632 if (_opt->dumpU) {
633 MxASCIIWrite(U, "U.txt");
634 MxBinWrite(U, "U", 'm');
635 }
636
637 return U;
638 }
639
640
641 /*==*/
642 template<typename T>
643 void
MxGetSpace(T ** p8)644 Calc<T>::MxGetSpace(T **p8)
645 {
646 *p8 = new T[dim];
647 std::fill_n(*p8, dim, 0.);
648 evals = new T[dim];
649 std::fill_n(evals, dim, 0.);
650 evecs = new T[dim * dim];
651 std::fill_n(evecs, dim, 0.);
652 assert(evals != NULL);
653 assert(evecs != NULL);
654 assert(p8 != NULL);
655
656 if (!_opt->absrb) {
657 _sqrPI = new T[dim * dim];
658 std::fill_n(_sqrPI, dim * dim, 0.);
659 sqrPI_ = new T[dim * dim];
660 std::fill_n(sqrPI_, dim * dim, 0.);
661 }
662 }
663
664
665 /*==*/
666 template<typename T>
667 void
MxStartVec(T ** p0)668 Calc<T>::MxStartVec(T **p0)
669 {
670 int i;
671 T *pzero = new T[dim];
672
673 std::fill_n(pzero, dim, 0.0);
674 if (_opt->pini) {
675 for (i = 1; i < (int)*_opt->pini; i += 2)
676 pzero[(int)_opt->pini[i] - 1] = (T)_opt->pini[i + 1];
677 /* -1 because our lmins start with 1, not with 0 (as Data does ) */
678 } else {
679 /* all into first state... */
680 pzero[0] = 1.0;
681 }
682
683 if (_opt->want_verbose)
684 MxPrint(pzero, "p0", 'v');
685
686 *p0 = pzero;
687 }
688
689
690 /*==*/
691 /* calculate equilibrium distribution */
692 template<typename T>
693 void
MxEqDistr(BarData * Data,T ** p8)694 Calc<T>::MxEqDistr(BarData *Data,
695 T **p8)
696 {
697 int i;
698 T Z = 0.;
699
700 if (_opt->absrb) {
701 for (i = 0; i < dim; i++)
702 (*p8)[i] = 0.;
703 (*p8)[dim - 1] = 1.0; /* last entry is the 'new' absorbing state */
704 } else {
705 double mfe = Data[0].energy;
706 for (i = 0; i < dim; i++)
707 Z += exp(-((Data[i].energy - mfe) / _kT));
708 for (i = 0; i < dim; i++)
709 (*p8)[i] = exp(-((Data[i].energy - mfe) / _kT));
710 }
711
712 /* now normalize the new p8 */
713 for (i = 0; i < dim; i++)
714 *(*p8 + i) *= 1.0 / Z; /*sumsq; */
715
716 if (_opt->want_verbose)
717 MxPrint(*p8, "p8", 'v');
718
719 return;
720 }
721
722
723 /*==*/
724 template<typename T>
725 void
MxEqDistrFULL(SubInfo * E,T * p8)726 Calc<T>::MxEqDistrFULL(SubInfo *E,
727 T *p8)
728 {
729 int i;
730 T Z = 0.;
731
732 if (_opt->absrb) {
733 for (i = 0; i < dim; i++)
734 p8[i] = 0.;
735 p8[_opt->absrb - 1] = 1.;
736 } else {
737 for (i = 0; i < dim; i++)
738 Z += exp(-E[i].energy / _kT);
739 for (i = 0; i < dim; i++)
740 p8[i] = (T)(exp(-E[i].energy / _kT) / Z);
741 }
742
743 if (_opt->want_verbose)
744 MxPrint(p8, "p8", 'v');
745
746 return;
747 }
748
749
750 template<typename T>
751 void
MxEqDistrFromLinSys(T * U,T ** p8)752 Calc<T>::MxEqDistrFromLinSys(T *U,
753 T **p8)
754 {
755 int i, j, n, nrhs, nfo, *ipiv = NULL;
756 T *A = NULL, *B = NULL;
757
758 if (_opt->absrb) {
759 for (i = 0; i < dim; i++)
760 *(*p8 + i) = 0.;
761 *(*p8 + (dim - 1)) = 1.0; /* last entry is the 'new' absorbing state */
762 } else {
763 n = dim - 1;
764 A = new T[n * n];
765 B = new T[n];
766 ipiv = (int *)malloc(n * sizeof(int));
767 nrhs = 1;
768
769 if (_opt->want_verbose)
770 MxPrint(U, "U", 'm');
771
772 for (i = 1; i <= n; i++) /* all except first row */
773 for (j = 1; j <= n; j++)
774 A[n * (i - 1) + (j - 1)] = U[dim * i + j] - (i == j && _opt->useplusI ? 1.0 : 0.0); /*U-I=Q */
775 for (n = 0, i = 1; i < dim; i++, n++)
776 B[n] = -U[dim * i];
777 dim = n;
778 mxccm.trnm(A, n);
779
780 if (_opt->want_verbose)
781 MxPrint(A, "A in MxEqDistrFromLinSys", 'm');
782
783 if (_opt->want_verbose)
784 MxPrint(B, "B in MxEqDistrFromLinSys", 'v');
785
786 /*DGESV computes the solution to a real system of linear equations A * X = B */
787 solver->Mx_Dgesv(&n, &nrhs, A, &n, ipiv, B, &n, &nfo);
788
789 if (nfo != 0) {
790 fprintf(stderr,
791 "dgesv exited with value %d (Cannot compute the equilibrium distribution) - check if the rates have good dimension(you have probably reached the numerical precision of treekin)\n",
792 nfo);
793 /*/ TODO switch to compute from detailed balance */
794 exit(EXIT_FAILURE);
795 }
796
797 if (_opt->want_verbose)
798 MxPrint(B, "X in MxEqDistrFromLinSys", 'v');
799
800 dim = n + 1;
801 *p8[0] = 1.;
802 for (i = 1; i < dim; i++)
803 *(*p8 + i) = B[i - 1];
804
805 if (_opt->want_verbose)
806 MxPrint(*p8, "p8 in MxEqDistrFromLinSys before norm", 'v');
807
808 /* now check if all are > 0.0 */
809 for (i = dim - 1; i != 0; i--) {
810 if ((*p8)[i] < 0.0) {
811 if (i == 0)
812 exit(EXIT_FAILURE);
813
814 fprintf(stderr,
815 "Warning: p8[%5d] is negative (%e), setting it to a nearby value (%e)\n",
816 i + 1,
817 (*p8)[i],
818 (i == dim - 1 ? (*p8)[i - 1] : (*p8)[i + 1]));
819 (*p8)[i] = abs((i == dim - 1 ? (*p8)[i - 1] : (*p8)[i + 1]));
820 }
821
822 if ((*p8)[i] == 0.0) {
823 fprintf(stderr,
824 "Warning: p8[%5d] is zero (%e), setting it to a minimum value (%e)\n",
825 i + 1,
826 (*p8)[i],
827 1e-20);
828 (*p8)[i] = 1e-20;
829 }
830 }
831
832 /* now make the vector stochastic (sum = 1.0) */
833 T sum = 0.0;
834 for (i = 0; i < dim; i++)
835 sum += (*p8)[i];
836 for (i = 0; i < dim; i++)
837 (*p8)[i] /= sum;
838
839 delete[] A;
840 delete[] B;
841 free(ipiv);
842 }
843
844 if (_opt->want_verbose)
845 MxPrint(*p8, "p8", 'v');
846 }
847
848
849 /*==*/
850 template<typename T>
851 void
MxDiagonalize(T * U,T ** _S,T * P8)852 Calc<T>::MxDiagonalize(T *U,
853 T **_S,
854 T *P8)
855 {
856 int i, j;
857 T *tmpMx = NULL;
858
859 if (_opt->dumpMathematica == 1)
860 MxKotzOutMathematica(U);
861
862 if (!_opt->absrb) {
863 if (_opt->want_verbose)
864 MxPrint(U, "input U", 'm');
865
866 tmpMx = new T[dim * dim];
867 /*if (_opt->want_verbose) MxPrint (P8, "P8", 'v'); */
868 MxDiagHelper(P8);
869 mxccm.mmul(tmpMx, _sqrPI, U, dim);
870 if (_opt->want_verbose)
871 MxPrint(_sqrPI, "_sqrPI", 'm');
872
873 if (_opt->want_verbose)
874 MxPrint(tmpMx, "tmpMx = _sqrPI*U", 'm');
875
876 if (_opt->want_verbose)
877 MxPrint(sqrPI_, "sqrPI_", 'm');
878
879 /*memset(U,0,dim*dim*sizeof(T)); */
880 fill_n(U, dim * dim, 0);
881 mxccm.mmul(U, tmpMx, sqrPI_, dim);
882 if (_opt->want_verbose)
883 MxPrint(U, "U = _sqrPI*U*sqrPI_ (this should be symmetric, but still uncorrected)", 'm');
884
885 delete[] tmpMx;
886
887 /* correct for numerical errors -- ensure U is symmetric */
888 T err = 0.0; /* accumulated error */
889 for (i = 0; i < dim; i++) {
890 for (j = i; j < dim; j++) {
891 T err_inc = (T)(abs((U[dim * i + j] + U[dim * j + i]) / 2 - U[dim * i + j]));
892 /*if (std::isnan(err_inc)) {
893 * fprintf(stderr, "%d %d\n", i,j);
894 * }*/
895 err += err_inc;
896 if (std::isnan((double)err_inc))
897 fprintf(stderr, "Weird rates! r(%5d,%5d)=(%e, %e)\n", i, j, (double)U[dim * i + j],
898 (double)U[dim * j + i]);
899
900 /*exit(-1); */
901
902 U[dim * i + j] = (T)((U[dim * i + j] + U[dim * j + i]) / 2.);
903 /*U[dim*i+j] = std::sqrt(U[dim*i+j]*U[dim*j+i]); */
904 U[dim * j + i] = U[dim * i + j];
905 }
906 }
907 if (std::isnan((double)err)
908 ) {
909 fprintf(stderr,
910 "Rates are not good -- check your rates (maybe the equilibrium was not computed correctly? rerun with --equil-file or -v set)!!!... (%Lf)\n",
911 (long double)err);
912 exit(-1);
913 }
914
915 if (!_opt->quiet)
916 fprintf(stderr, "Corrected numerical error: %e (%e per number)\n", (double)err,
917 (double)(T)(err / (T)(dim * dim)));
918
919 if (_opt->want_verbose)
920 MxPrint(U, "force symmetrized U", 'm');
921 }
922
923 /* get eigenv* */
924 if (_opt->absrb) {
925 MxEVLapackNonSym(U);
926 } else {
927 switch (_opt->mlapackMethod) {
928 #if defined(WITH_MLAPACK_GMP)
929 case MLAPACK_GMP:
930 solver->MxEV_Mlapack_Sym_gmp((const mpf_class *)U,
931 dim,
932 (mpf_class *)evals,
933 (mpf_class *)evecs,
934 _opt->mlapackMethod_Bits);
935 break;
936 #endif
937 #if defined(WITH_MLAPACK_QD)
938 case MLAPACK_QD:
939 solver->MxEV_Mlapack_Sym_qd((const qd_real *)U, dim, (qd_real *)evals, (qd_real *)evecs);
940 break;
941 #endif
942 #if defined(WITH_MLAPACK_MPFR)
943 case MLAPACK_MPFR:
944 solver->MxEV_Mlapack_Sym_mpfr((const mpfr::mpreal *)U, dim, (mpfr::mpreal *)evals,
945 (mpfr::mpreal *)evecs, _opt->mlapackMethod_Bits);
946 break;
947 #endif
948 #if defined(WITH_MLAPACK___FLOAT128)
949 case MLAPACK_FLOAT128:
950 solver->MxEV_Mlapack_Sym_float128((const __float128 *)U, dim, (__float128 *)evals,
951 (__float128 *)evecs);
952 break;
953 #endif
954 #if defined(WITH_MLAPACK_LD)
955 case MLAPACK_LD:
956 solver->MxEV_Mlapack_Sym_longdouble((const long double *)U, dim, (long double *)evals,
957 (long double *)evecs);
958 break;
959 #endif
960 #if defined(WITH_MLAPACK_DD)
961 case MLAPACK_DD:
962 solver->MxEV_Mlapack_Sym_dd((const dd_real *)U, dim, (dd_real *)evals, (dd_real *)evecs);
963 break;
964 #endif
965 #if defined(WITH_MLAPACK_DOUBLE)
966 case MLAPACK_DOUBLE:
967 solver->MxEV_Mlapack_Sym_double((const double *)U, dim, (double *)evals, (double *)evecs);
968 break;
969 #endif
970 default:
971 /*default standard lapack */
972 MxEVLapackSym(U);
973 break;
974 }
975 }
976
977 MxSortEig(evals, evecs);
978
979 if (_opt->want_verbose) {
980 MxPrint(evecs, "Eigenvectors of U (LAPACK)", 'm');
981 MxPrint(evals, "Eigenvalues of U (LAPACK)", 'v');
982 }
983
984 /* check for ergodicity of eigenvectors (if not ergodic, then not all the space can be reached) */
985 int *reachable = MxErgoEigen(evecs, dim);
986 if (reachable) {
987 fprintf(stderr,
988 "WARNING: Eigenvector matrix is non-ergodic (unreachable states from 1st state):");
989 for (i = 0; i < dim; i++)
990 if (!reachable[i])
991 fprintf(stderr, " %4d", i + 1);
992
993 fprintf(stderr,
994 "\n the overall probability can start to decrease if this state(s) is(are) populated!!!");
995
996 free(reachable);
997 /*exit(EXIT_FAILURE); */
998 }
999
1000 if (!_opt->quiet) {
1001 if ((T)abs(evals[0] - ((_opt->useplusI) ? 1. : 0.)) > (T)10 * _opt->FEPS) {
1002 fprintf(stderr,
1003 "WARNING largest eigenvalue is %g, see evals.txt and evecs.txt\n",
1004 (double)evals[0]);
1005 MxASCIIWriteV(evals, "evals.txt");
1006 MxASCIIWrite(evecs, "evecs.txt");
1007 }
1008 }
1009
1010 /* fix evals[0] to be 0 (or 1.0) */
1011 if (_opt->useplusI)
1012 evals[0] = 1.0;
1013 else
1014 evals[0] = 0.0;
1015
1016 /* check if we have only one eval = 0 / eval = 1 */
1017 i = 0;
1018 if (_opt->useplusI)
1019 while (evals[i] >= 1.0)
1020 evals[i++] = 1.0;
1021 else
1022 while (evals[i] >= 0.0)
1023 evals[i++] = 0.0;
1024
1025 if (i > 1)
1026 fprintf(stderr,
1027 "WARNING: There are multiple evals=%d.0 (%4d) (multiple population traps -- maybe we compute crap)\n",
1028 _opt->useplusI ? 1 : 0,
1029 i);
1030
1031 if (_opt->absrb)
1032 MxFixevecsAbsorb(evecs, evals);
1033
1034 /* else */
1035 /* MxFixevecs(evecs,evals); / * so far it's not helping ... * / */
1036
1037 *_S = evecs;
1038 if (_opt->dumpX) {
1039 MxASCIIWriteV(evals, "evals.txt");
1040 exit(EXIT_SUCCESS);
1041 }
1042
1043 if (_opt->wrecover) {
1044 MxBinWrite(evals, "evals", 'v');
1045 MxBinWrite(evecs, "evecs", 'm');
1046 MxASCIIWriteV(evals, "evals.txt");
1047 MxASCIIWrite(evecs, "evecs.txt");
1048 if (_opt->want_verbose) {
1049 T *CL; /*, *tmpMx; ? */
1050 int i, j;
1051 CL = new T[dim * dim];
1052 mxccm.mmul(CL, sqrPI_, evecs, dim);
1053 MxASCIIWrite(CL, "evecR.txt");
1054 fprintf(stderr, "Sums of EVs of rate matrix R\n");
1055 for (i = 0; i < dim; i++) {
1056 T sum, sum2, sum3;
1057 sum = sum2 = sum3 = 0.;
1058 for (j = 0; j < dim; j++)
1059 sum += CL[dim * j + i];
1060 fprintf(stderr, "%d %15.8g ", i, (double)sum);
1061 }
1062 fprintf(stderr, "\n");
1063 delete[] CL;/*free(CL); */
1064 }
1065 }
1066
1067 /* compensate for the +I matrix */
1068 if (_opt->useplusI)
1069 for (i = 0; i < dim; i++)
1070 evals[i] -= 1.0; /* compensate 4 translation of matrix U */
1071 }
1072
1073
1074 /*==*/
1075 template<typename T>
1076 void
MxDiagHelper(T * P8)1077 Calc<T>::MxDiagHelper(T *P8)
1078 {
1079 int i, j;
1080
1081 for (i = 0; i < dim; i++) {
1082 j = i;
1083 sqrPI_[dim * i + j] = (T)std::sqrt(P8[i]); /* pos right */
1084 _sqrPI[dim * i + j] = (T)(1.0 / (sqrPI_[dim * i + j])); /* neg left */
1085 }
1086 }
1087
1088
1089 /*==*/
1090 template<typename T>
1091 void
MxRecover(T ** _S,T * P8)1092 Calc<T>::MxRecover(T **_S,
1093 T *P8)
1094 {
1095 MxDiagHelper(P8);
1096 delete[] evecs;
1097 delete[] evals;
1098
1099 if (MxBinRead(&evecs, "evecs", 'm') != dim) {
1100 fprintf(stderr, "ERROR: MxBinRead() returns wrong dimension for evecs\n");
1101 exit(EXIT_FAILURE);
1102 }
1103
1104 if (MxBinRead(&evals, "evals", 'v') != dim) {
1105 fprintf(stderr, "ERROR: MxBinRead() returns wrong dimension for evals\n");
1106 exit(EXIT_FAILURE);
1107 }
1108
1109 *_S = evecs;
1110 if (_opt->want_verbose) {
1111 MxPrint(evals, "MxRecover: Eigenvalues", 'v');
1112 MxPrint(evecs, "MxRecover: Eigenvectors", 'm');
1113 }
1114
1115 return;
1116 }
1117
1118
1119 template<class T>
1120 int
ConvergenceReached(T * p8,T * pt,int dim,int full)1121 Calc<T>::ConvergenceReached(T *p8,
1122 T *pt,
1123 int dim,
1124 int full)
1125 {
1126 int pdiff_counter = 0;
1127
1128 full = (full ? 1 : 0);
1129 /* now check if we have converged yet */
1130 for (int i = 0; i < dim; i++) {
1131 if (abs(p8[i] - pt[i]) >= 0.000001) {
1132 pdiff_counter++;
1133 break;
1134 }
1135 }
1136
1137 if (pdiff_counter < 1) /* all mins' pdiff lies within threshold */
1138 return 1;
1139
1140 pdiff_counter = 0;
1141 /* end check of convergence */
1142 return false;
1143 }
1144
1145
1146 /**
1147 * @param S which comes into this function contains the (right)
1148 * eigenvectors calculated by LAPACK
1149 */
1150 template<typename T>
1151 void
MxIterate(T * p0,T * p8,T * S)1152 Calc<T>::MxIterate(T *p0,
1153 T *p8,
1154 T *S)
1155 {
1156 /* solve following equation 4 various times
1157 ***** NON-ABSORBING CASE: ******
1158 *****p(t) = sqrPI_ * S * exp(time * EV) * St * _sqrPI * p(0)
1159 *****CL = sqrPI_ * S
1160 *****CR = St * _sqrPI
1161 *****tmpVec = CR * p(0)
1162 *****tmpVec2 = exp(time * EV) * tmpVec
1163 *****p(t) = CL * tmpVec2
1164 ******* ABSORBING CASE: *******
1165 *******p(t) = S * exp(time * EV) * S_inv * p(0)
1166 *******tmpVec = S_inv * p(0)
1167 *******tmpVec2 = exp(time * EV) *tmpVec
1168 *******p(t) = S * tmpVec2
1169 */
1170 int i, count = 0;
1171 T time, check = 0.;
1172 T *CL = NULL, *CR, *exptL, *tmpVec, *tmpVec2, *pt, *St, *pdiff;
1173 T *ptFULL = NULL; /* prob dist 4 of the effective lmins of the tree at time t */
1174 T *p8FULL = NULL; /* equ dist 4 gradient basins, full process */
1175
1176 tmpVec = new T[dim];
1177 std::fill_n(tmpVec, dim, 0.);
1178 tmpVec2 = new T[dim];
1179 std::fill_n(tmpVec2, dim, 0.);
1180 pt = new T[dim];
1181 std::fill_n(pt, dim, 0.);
1182 size_t dimSquared = dim * dim;
1183 exptL = new T[dimSquared];
1184 std::fill_n(exptL, dimSquared, 0.);
1185 if (_opt->method == 'F') {
1186 size_t fullSize = _lmins + 1;
1187 ptFULL = new T[fullSize];
1188 std::fill_n(ptFULL, fullSize, 0.);
1189 p8FULL = new T[fullSize];
1190 std::fill_n(p8FULL, fullSize, 0.);
1191 pdiff = new T[fullSize];
1192 std::fill_n(pdiff, fullSize, 0.);
1193 } else {
1194 pdiff = new T[dim];
1195 }
1196
1197 if (!_opt->absrb) {
1198 /* NON-absorbing case */
1199 CL = new T[dim * dim];
1200 CR = new T[dim * dim];
1201 St = new T[dim * dim];
1202 mxccm.mcopy(St, S, dim * dim);
1203 mxccm.trnm(St, dim); /* transpose S (same as invert(S) ('cause of symmetry) minv(St, dim); )*/
1204 mxccm.mmul(CL, sqrPI_, S, dim);
1205 mxccm.mmul(CR, St, _sqrPI, dim);
1206 mxccm.vmul(tmpVec, CR, p0, dim);
1207
1208 /* test CL*CR = I */
1209 if (_opt->want_verbose) {
1210 T *testMx, *tvec;
1211 testMx = new T[dim * dim];
1212 tvec = new T[dim];
1213 mxccm.mmul(testMx, CL, CR, dim);
1214 MxPrint(testMx, "CL*CR should be I", 'm');
1215 delete[] testMx;
1216 MxPrint(tmpVec, "CR*p0 should start with 1", 'v');
1217 mxccm.vmul(tvec, _sqrPI, p0, dim);
1218 mxccm.vmul(tmpVec2, St, tvec, dim);
1219 MxPrint(tmpVec2, "CR*p0 should start with 1", 'v');
1220 MxPrint(CL, "CL", 'm');
1221 MxPrint(CR, "CR", 'm');
1222 delete[] tvec;
1223 }
1224
1225 delete[] St;
1226 delete[] CR;
1227 } else {
1228 /* absorbing case */
1229 T *S_inv = new T[dim * dim];
1230 mxccm.mcopy(S_inv, S, dim * dim);
1231 mxccm.minv(S_inv, dim, _opt->FEPS);
1232 if (_opt->want_verbose)
1233 MxPrint(evals, "evals in MxIterate", 'v');
1234
1235 mxccm.vmul(tmpVec, S_inv, p0, dim);
1236 delete[] S_inv;
1237 }
1238
1239 if (_opt->method == 'F') {
1240 /* calculate equilibrium distribution once */
1241 for (i = 0; i < dim; i++)
1242 p8FULL[_E[i].ag] += p8[i];
1243 for (i = 0; i < _lmins; i++)
1244 check += abs(p8FULL[i]);
1245 if (((check - 1.) < -0.1) || ((check - 1.) > 0.1)) {
1246 fprintf(stderr, "overall equilibrium probability is %e != 1. !\n", (double)check);
1247 if (_opt->num_err == 'H' || check == 0.0) {
1248 exit(EXIT_FAILURE);
1249 } else if (_opt->num_err == 'R') {
1250 for (i = 0; i < dim; i++)
1251 p8[i] /= check;
1252 check = 1.0;
1253 }
1254 }
1255 }
1256
1257 check = 0.;
1258
1259 /* solve fundamental equation */
1260 print_settings();
1261 if (_opt->t0 == 0.0) {
1262 if (_opt->method == 'F')
1263 PrintProbFull(p0, dim, 0.0, _lmins);
1264 else
1265 PrintProb(p0, dim, 0.0);
1266
1267 _opt->t0 = _globalParameters->TZERO;
1268 }
1269
1270 T underflow[dim], tt;
1271 for (i = 0; i < dim; i++)
1272 underflow[i] = 0.0;
1273
1274 /* iterate */
1275 T inc = _opt->t0;
1276 T t8 = _opt->t8;
1277 for (tt = inc; tt < _opt->t8 + inc; inc *= _opt->tinc, tt += inc) {
1278 if (tt > _opt->t8) {
1279 tt = _opt->t8;
1280 t8 = 0;
1281 }
1282
1283 time = tt;
1284 for (i = 0; i < dim; i++) {
1285 errno = 0;
1286 exptL[dim * i + i] = (T)exp(time / _opt->times * evals[i]);
1287 if ((errno == ERANGE || std::isnan((double)exptL[dim * i + i])
1288 ) && underflow[i] == 0.0) {
1289 /*if (_opt->warnings) fprintf(stderr, "WARNING: underflow occured on %dth state at time %g -- exp(%g * %g) = %g\n", i+1, time/_opt->times, time/_opt->times, evals[i], exptL[dim*i+i]); */
1290 /* the overall probability can start to decrease if this state is still populated!!!\n p_%d(%g) = %g, so it seems this %s\n", i+1, time/_opt->times, time/_opt->times, evals[i], exptL[dim*i+i], i+1, time/_opt->times, pt[i], pt[i]>0.1?"is DEFINITELLY BAD":(pt[i]>0.001?"is POTENTIALLY BAD":"SHOULD BE OK")); */
1291 underflow[i] = (T)(time / _opt->times);
1292 /*exit(EXIT_FAILURE); */
1293 }
1294 }
1295 mxccm.vmul(tmpVec2, exptL, tmpVec, dim);
1296 if (!_opt->absrb)
1297 mxccm.vmul(pt, CL, tmpVec2, dim);
1298 else
1299 mxccm.vmul(pt, S, tmpVec2, dim);
1300
1301 /*if (count%100 == 0) {
1302 * fprintf(stderr, "Time: %g\n", time/_opt->times);
1303 * MxPrint(tmpVec2, "tmpVec2", 'v');
1304 * MxPrint(pt, "pt", 'v');
1305 * }*/
1306
1307 count++; /* # of iterations */
1308
1309 if (_opt->method == 'F') {
1310 /*memset(ptFULL, 0, (_lmins+1)*sizeof(T)); //replaced by c++ style. */
1311 fill_n(ptFULL, _lmins + 1, 0);
1312 for (i = 0; i < dim; i++)
1313 ptFULL[_E[i].ag] += pt[i];
1314 }
1315
1316 /* print probabilities with respect to corrected ergodicity */
1317 if (_opt->method == 'F')
1318 check = PrintProbFull(pt, dim, time, _lmins);
1319 else
1320 check = PrintProb(pt, dim, time);
1321
1322 /*PrintProbNR(p8FULL, lmins, -1); */
1323 int reached;
1324 if (_opt->method == 'F')
1325 reached = ConvergenceReached(p8FULL, ptFULL, _lmins, 1);
1326 else
1327 reached = ConvergenceReached(p8, pt, dim, 0);
1328
1329 fflush(stdout);
1330 if (reached)
1331 break;
1332 }
1333
1334 /* print underflow: */
1335 if (_opt->warnings) {
1336 for (i = 0; i < dim; i++)
1337 if (underflow[i] > 0.0)
1338 fprintf(stderr, "underflow %5d at time %12g", i + 1, (double)underflow[i]);
1339 }
1340
1341 if (time < _opt->t8) {
1342 if (_opt->method == 'F')
1343 PrintProbFull(pt, dim, _opt->t8, _lmins);
1344 else
1345 PrintProb(pt, dim, _opt->t8);
1346 }
1347
1348 printf("# of iterations: %d\n", count);
1349
1350 /*** end solve fundamental equation ***/
1351
1352 if (_opt->method == 'F') {
1353 delete[] ptFULL;
1354 delete[] p8FULL;
1355 delete[] _E;
1356 }
1357
1358 /*free(evals); */
1359 delete[] exptL;
1360 delete[] CL;
1361 delete[] tmpVec;
1362 delete[] tmpVec2;
1363 delete[] pdiff;
1364 delete[] pt;
1365 }
1366
1367
1368 /*==*/
1369 template<typename T>
1370 T *
MxMethodeA(BarData * Data)1371 Calc<T>::MxMethodeA(BarData *Data)
1372 {
1373 /***************************************/
1374 /* | E_s | */
1375 /* \ ____________ / */
1376 /* \ | /\ | / */
1377 /* \ | / \ | / */
1378 /* \| / \ | / */
1379 /* \/ \ | / */
1380 /* i \ | / */
1381 /* \/ */
1382 /* j */
1383 /* -beta(E_s-E_j) */
1384 /* rate: j->i: prop e */
1385 /* -beta(E_s-E_i) */
1386 /* i->j prop e */
1387 /****************************************/
1388
1389 int i, j, real_abs = 0;
1390 T m_saddle, Zabs, abs_rate;
1391
1392 T *U = new T[dim * dim];
1393
1394 for (i = 0; i < dim; i++) {
1395 for (j = i + 1; j < dim; j++) {
1396 m_saddle = max_saddle(i, j, Data);
1397
1398 T tmp_ji = (T)(1.0 * exp(-(m_saddle - Data[j].energy) / _kT));
1399 T tmp_ij = (T)(1.0 * exp(-(m_saddle - Data[i].energy) / _kT));
1400 /* rate j -> i */
1401 U[dim * i + j] = tmp_ji;
1402 /* rate i -> j */
1403 U[dim * j + i] = tmp_ij;
1404 }
1405 }
1406
1407 if (_opt->absrb) {
1408 /*==== absorbing states ====*/
1409 dim++;
1410 fprintf(stderr, "dim increased to %i\n", dim);
1411 T *tmpU = new T[dim * dim];
1412 real_abs = _opt->absrb; /* the original absorbing lmin */
1413 real_abs--;
1414 _opt->absrb = dim; /* the 'new' abs state = last row/column of rate matrix */
1415 fprintf(stderr, "new absorbing lmin is: %i\n", _opt->absrb);
1416 Zabs = (T)(exp((-Data[real_abs].energy) / _kT));
1417 abs_rate = (T)(exp((-Data[real_abs].energy) / _kT) / Zabs);
1418
1419 for (i = 0; i < (dim - 1); i++) {
1420 /* all except the last row */
1421 for (j = 0; j < (dim - 1); j++)
1422 tmpU[dim * i + j] = U[(dim - 1) * i + j];
1423 tmpU[(dim - 1) * j + (dim - 1)] = 0.;
1424 }
1425 for (j = 0; j < dim; j++) /* last row */
1426 tmpU[dim * (dim - 1) + j] = 0.;
1427 tmpU[dim * (dim - 1) + real_abs] = abs_rate;
1428 delete[] U; /*free(U); */
1429 U = tmpU;
1430 if (_opt->want_verbose)
1431 MxPrint(U, "aufgeblasene Matrix", 'm');
1432 } /*== end absorbing states ==*/
1433
1434 /* set diagonal elements to 0 */
1435 for (i = 0; i < dim; i++)
1436 U[dim * i + i] = 0.;
1437 for (j = 0; j < dim; j++) {
1438 T tmp = 0.00;
1439 /* calculate column sum */
1440 for (i = 0; i < dim; i++)
1441 tmp += U[dim * i + j];
1442 U[dim * j + j] = (T)(-tmp); /* make U a stochastic matrix */
1443 if (_opt->useplusI)
1444 U[dim * j + j] += 1.0;
1445 }
1446 if (_opt->want_verbose)
1447 MxPrint(U, "U with Methode A", 'm');
1448
1449 return U;
1450 }
1451
1452
1453 /*==*/
1454 #if 0
1455 template<typename T>
1456 T *
1457 Calc<T>::MxMethodeFULL(T *R)
1458 {
1459 int i, j;
1460
1461 delete[] D; /*free(D); */
1462
1463 if (_opt->absrb) /*==== absorbing states ====*/
1464 for (i = 0; i < dim; i++)
1465 R[dim * i + (_opt->absrb - 1)] = 0.;
1466
1467 /*== end absorbing states ==*/
1468
1469 /* set diagonal elements to 0 */
1470 for (i = 0; i < dim; i++)
1471 R[dim * i + i] = 0.;
1472 for (j = 0; j < dim; j++) {
1473 T tmp = 0.00;
1474 /* calculate column sum */
1475 for (i = 0; i < dim; i++)
1476 tmp += R[dim * i + j];
1477 R[dim * j + j] = (T)(-tmp); /* make U a stochastic matrix */
1478 if (_opt->useplusI)
1479 R[dim * j + j] += 1.0;
1480 }
1481
1482 if (_opt->want_verbose)
1483 MxPrint(R, "R with Methode F", 'm');
1484
1485 return R;
1486 }
1487
1488
1489 #endif
1490
1491 /*==*/
1492 template<typename T>
1493 T *
MxMethodeINPUT(BarData * Data,T * Input)1494 Calc<T>::MxMethodeINPUT(BarData *Data,
1495 T *Input)
1496 {
1497 int i, j;
1498 T *U = NULL, Zabs, abs_rate;
1499
1500 if (_opt->want_verbose)
1501 MxPrint(Input, "Input Matrix", 'm');
1502
1503 if (_opt->absrb) {
1504 /*==== absorbing states ====*/
1505 dim++;
1506 fprintf(stderr, "dim increased to %i\n", dim);
1507 U = new T[dim * dim]; /*(T *) MxNew(dim*dim*sizeof(T)); */
1508 _opt->real_abs = _opt->absrb; /* the original absorbing lmin */
1509 _opt->real_abs--;
1510 _opt->absrb = dim; /* the 'new' abs state = last row/column of rate matrix */
1511 fprintf(stderr, "new absorbing lmin is: %i\n", _opt->absrb);
1512 Zabs = exp((-Data[_opt->real_abs].FGr) / _kT);
1513 abs_rate = (T)(exp((-Data[_opt->real_abs].energy) / _kT) / Zabs);
1514
1515 for (i = 0; i < (dim - 1); i++) {
1516 /* all except the last row */
1517 for (j = 0; j < (dim - 1); j++)
1518 U[dim * i + j] = Input[(dim - 1) * i + j];
1519 U[(dim - 1) * j + (dim - 1)] = 0.;
1520 }
1521 for (j = 0; j < dim; j++) /* last row */
1522 U[dim * (dim - 1) + j] = 0.;
1523 U[dim * (dim - 1) + _opt->real_abs] = abs_rate;
1524 /* if(_opt->want_verbose) MxPrint(U, "aufgeblasene Matrix", 'm'); */
1525 } /*== end absorbing states ==*/
1526 else {
1527 /*== non-absorbing states ==*/
1528 U = new T[dim * dim]; /*(T *) MxNew(dim*dim*sizeof(T)); */
1529 /*memcpy(U, Input, dim*dim*sizeof(T)); */
1530 std::copy(Input, Input + dim * dim, U);
1531 } /*== end non-absorbing states ==*/
1532
1533 /* diagonal elements */
1534 for (i = 0; i < dim; i++)
1535 U[dim * i + i] = 0.0;
1536 /*fprintf(stderr, "dim is %i\n", dim); */
1537 for (i = 0; i < dim; i++) {
1538 T tmp = 0.00;
1539 /* calculate column sum */
1540 for (j = 0; j < dim; j++)
1541 tmp += U[dim * j + i];
1542 U[dim * i + i] = (T)(-tmp); /* make U a stochastic matrix U = Q+I ?? */
1543 if (_opt->useplusI)
1544 U[dim * i + i] += 1.0;
1545 }
1546
1547 /* // normalize each column to sum=1
1548 * for (i = 0; i < dim; i++) {
1549 * double tmp = 0.00;
1550 * for(j = 0; j < dim; j++) tmp += U[dim*j+i];
1551 * for(j = 0; j < dim; j++) U[dim*j+i] /= tmp;
1552 * }*/
1553
1554
1555 if (_opt->want_verbose)
1556 MxPrint(U, "U with Methode I", 'm');
1557
1558 delete[] Input;
1559 return U;
1560 }
1561
1562
1563 /*==*/
1564 template<typename T>
1565 T
max_saddle(int i,int j,BarData * Data)1566 Calc<T>::max_saddle(int i,
1567 int j,
1568 BarData *Data)
1569 {
1570 int tmp;
1571
1572 if (Data[i].number > Data[j].father) {
1573 /* exchange i & j */
1574 tmp = i;
1575 i = j;
1576 j = tmp;
1577 }
1578
1579 if (Data[i].number == Data[j].father) {
1580 return (T)(Data[j].energy + Data[j].ediff);
1581 } else {
1582 if ((Data[j].energy + Data[j].ediff) >
1583 max_saddle((Data[j].father - 1), (Data[i].number - 1), Data))
1584 return Data[j].energy + Data[j].ediff;
1585 else
1586 return max_saddle((Data[j].father - 1), (Data[i].number - 1), Data);
1587 }
1588 }
1589
1590
1591 template<typename T>
1592 void
MxFPrint(T * mx,const char * name,char c,FILE * out,int pure)1593 Calc<T>::MxFPrint(T *mx,
1594 const char *name,
1595 char c,
1596 FILE *out,
1597 int pure)
1598 {
1599 int k, l;
1600
1601 switch (c) {
1602 case 'm': /* square matrix */
1603 if (!pure)
1604 fprintf(out, "%s:\n", name);
1605
1606 for (k = 0; k < dim; k++) {
1607 for (l = 0; l < dim; l++)
1608 fprintf(out, "%15.7g ", (double)mx[dim * k + l]);
1609 fprintf(out, "\n");
1610 }
1611 if (!pure)
1612 fprintf(out, "---\n");
1613
1614 break;
1615 case 'v':
1616 if (!pure)
1617 fprintf(out, "%s:\n", name);
1618
1619 for (k = 0; k < dim; k++)
1620 fprintf(out, "%15.7g ", (double)mx[k]);
1621 if (!pure)
1622 fprintf(out, "\n---\n");
1623 else
1624 fprintf(out, "\n");
1625
1626 break;
1627 default:
1628 fprintf(out, "ERROR MxPrint(): no handler 4 type %c\n", c);
1629 }
1630 }
1631
1632
1633 /**
1634 * print matrix stored in ccmath-format
1635 */
1636 template<typename T>
1637 void
MxPrint(T * mx,const char * name,char c)1638 Calc<T>::MxPrint(T *mx,
1639 const char *name,
1640 char c)
1641 {
1642 MxFPrint(mx, name, c, stderr, 0);
1643 }
1644
1645
1646 /*==*/
1647 template<typename T>
1648 void
norm2(T * mx)1649 Calc<T>::norm2(T *mx)
1650 {
1651 /* normalize columns of matrix mx */
1652 /* (to euclidean norm 1)*/
1653 int i, j;
1654 T sumsq;
1655 T mxValue;
1656
1657 for (j = 0; j < dim; j++) {
1658 sumsq = 0.0;
1659 for (i = 0; i < dim; i++) {
1660 mxValue = mx[dim * i + j];
1661 sumsq += mxValue * mxValue;
1662 }
1663 if (sumsq > 0.0)
1664 sumsq = (T)(1. / std::sqrt(sumsq));
1665
1666 for (i = 0; i < dim; i++)
1667 mx[dim * i + j] *= sumsq;
1668 }
1669 return;
1670 }
1671
1672
1673 /*#define abs(x) ((x)>0.0?(x):(-x)) */
1674
1675 /*==*/
1676 template<typename T>
1677 void
MxFixevecsAbsorb(T * evecs,T * evals)1678 Calc<T>::MxFixevecsAbsorb(T *evecs,
1679 T *evals)
1680 /* evecs: eigenvectors columns, dimension N */
1681 /* since the sum over each non-absorbing */
1682 /* column must vanish, replace the */
1683 /* problematic evecs with linear combinations */
1684 /* satisfying that criterion */
1685 /* rationale: with 1^T a row vector of 1s */
1686 /* Q=S*exp(L)*inv(S) */
1687 /* 1^T*Q = 1^T (probabilities sum up to 1) */
1688 /* 1^T*S*exp(L) = 1^T*S */
1689 {
1690 int i, j, maxind, abscount;
1691 T maxent, csum;
1692
1693 /* assume sorted evals */
1694 /* and an absorbing state */
1695 /* im the 1st evec=1st column */
1696
1697 /* take care of possibly more than one abs. state*/
1698 /* all abs. states have been *assigned* eigenvalue one */
1699 /* for each of them, set the largest component of the */
1700 /* eigenvectors to one, all others to zero */
1701 abscount = 0;
1702 for (i = 0; i < dim; i++) {
1703 if (evals[i] == 1.0) {
1704 abscount++;
1705 maxent = 0.;
1706 maxind = 0;
1707 for (j = 0; j < dim; j++) {
1708 if ((T)(abs(evecs[dim * j + i])) > maxent) {
1709 maxent = (T)(abs(evecs[dim * j + i]));
1710 maxind = j;
1711 }
1712 }
1713 evecs[dim * maxind + i] = 1.0;
1714 for (j = 0; j < dim; j++) {
1715 if (j == maxind)
1716 continue;
1717
1718 evecs[dim * j + i] = 0.0;
1719 }
1720 }
1721 }
1722
1723 /* repair messed non abs. eigenvectors */
1724 /* using all abs. states equally */
1725 /* using all abs. states equally */
1726 for (j = abscount; j < dim; j++) {
1727 T mu = 0.;
1728 for (i = 0; i < dim; i++)
1729 mu += evecs[dim * i + j];
1730 for (i = 0; i < abscount; i++)
1731 evecs[dim * i + j] -= mu / (T)abscount;
1732 }
1733
1734 if (_opt->want_verbose) {
1735 MxPrint(evals, "evals_complete", 'v');
1736 MxPrint(evecs, "evecs_complete", 'm');
1737 fflush(stdout);
1738 fflush(stderr);
1739 }
1740
1741 norm2(evecs);
1742
1743 if (_opt->want_verbose) {
1744 MxPrint(evals, "evals_complete", 'v');
1745 MxPrint(evecs, "evecs_complete", 'm');
1746 fflush(stdout);
1747 fflush(stderr);
1748 }
1749
1750 if (_opt->want_verbose) {
1751 fprintf(stderr, "colsums: ");
1752 for (i = 0; i < dim; i++) {
1753 csum = 0.0;
1754 for (j = 0; j < dim; j++)
1755 csum += evecs[dim * j + i];
1756 fprintf(stderr, "%g ", (double)csum);
1757 }
1758 fprintf(stderr, "\n");
1759 }
1760
1761 if (_opt->absrb && (abscount > 1)) {
1762 int i, j;
1763 if (!_opt->quiet)
1764 fprintf(stderr, "\nWARNING: found %d additional absorbing state(s): ", abscount - 1);
1765
1766 for (i = 1; i < dim; i++) {
1767 if (evals[i] == 1.) {
1768 for (j = 0; j < dim; j++)
1769 if (evecs[dim * j + i] == 1.)
1770 fprintf(stderr, " %5d", j + 1);
1771 }
1772 }
1773 fprintf(stderr, "\n");
1774 }
1775
1776 fflush(stderr);
1777 }
1778
1779
1780 template<typename T>
1781 void
MxFixevecs(T * evecs,T * evals)1782 Calc<T>::MxFixevecs(T *evecs,
1783 T *evals)
1784 /* Component sum of eigenvectors of M has to be zero, except for largest eigenvalue
1785 * Strategy to enforce this property:
1786 * transform evecs (eigenvectors of the symmertic Matrix U)
1787 * back into space of the Rate Matrix M. With S the Matrix of eigenvectors,
1788 * we compute
1789 *
1790 * V = sqrPI_ * S
1791 *
1792 * V_0 should be the equilibrium vector, i.e.
1793 * V[0,j]>0 and Sum_j V[0,j] =1
1794 *
1795 * foreach V_i, i>0, compute d = Sum_j V[i,j]
1796 * and V_i = V_i - d*V_0
1797 *
1798 * Now transform the vectors back into the space of the symmetric matrix U
1799 *
1800 * S = _sqrPI * V
1801 */
1802 {
1803 int i, j;
1804 T *V, sum, sum0;
1805
1806 V = new T[dim * dim]; /*(T *) MxNew (dim*dim*sizeof(T)); */
1807 mxccm.mmul(V, sqrPI_, evecs, dim);
1808
1809 if (_opt->want_verbose)
1810 MxPrint(V, "Eigenvectors of rate matrix M, before Fixevecs", 'm');
1811
1812 fprintf(stderr, "Sums of EVs of rate matrix R before fixing\n");
1813 for (i = 0; i < dim; i++) {
1814 T sum;
1815 sum = 0.;
1816 for (j = 0; j < dim; j++)
1817 sum += V[dim * j + i];
1818 fprintf(stderr, "%15.8g ", i, sum);
1819 }
1820 fprintf(stderr, "\n");
1821
1822 sum0 = 0.;
1823 i = 0;
1824 for (j = 0; j < dim; j++) {
1825 /* if (V[dim*j+i]<0) { */
1826 /* if (!_opt->quiet) */
1827 /* fprintf(stderr, "correcting negative equilib probability for state p[%d]=%g\n",j,V[dim*j+i]); */
1828 /* V[dim*j+i]=0; */
1829 /*} */
1830 sum0 += V[dim * j + i];
1831 }
1832 /* for (j=0; j<dim; j++) */
1833 /* V[dim*j+i] /= sum; */
1834
1835 for (i = 1; i < dim; i++) {
1836 sum = 0.;
1837 for (j = 0; j < dim; j++)
1838 sum += V[dim * j + i];
1839 for (j = 0; j < dim; j++)
1840 V[dim * j + i] -= sum / sum0 * V[dim * j + 0];
1841 }
1842
1843 fprintf(stderr, "Sums of EVs of rate matrix R after fixing\n");
1844 for (i = 0; i < dim; i++) {
1845 T sum;
1846 sum = 0.;
1847 for (j = 0; j < dim; j++)
1848 sum += V[dim * j + i];
1849 fprintf(stderr, "%15.8g ", i, (double)sum);
1850 }
1851 fprintf(stderr, "\n");
1852
1853 mxccm.mmul(evecs, _sqrPI, V, dim);
1854
1855 norm2(evecs);
1856
1857 if (_opt->want_verbose)
1858 MxPrint(evecs, "Eigenvectors of symmetric matrix U, after Fixevecs", 'm');
1859
1860 delete[] V; /*free(V); */
1861 }
1862
1863
1864 /**
1865 * sort evecs,eval
1866 */
1867 template<typename T>
1868 void
MxSortEig(T * evals,T * evecs)1869 Calc<T>::MxSortEig(T *evals,
1870 T *evecs)
1871 {
1872 int i, j, k;
1873 T p;
1874
1875 for (i = 0; i < dim; i++) {
1876 p = evals[k = i];
1877 for (j = i + 1; j < dim; j++)
1878 if (evals[j] >= p)
1879 p = evals[k = j];
1880
1881 if (k != i) {
1882 evals[k] = evals[i];
1883 evals[i] = p;
1884 for (j = 0; j < dim; j++) {
1885 p = evecs[dim * j + i];
1886 evecs[dim * j + i] = evecs[dim * j + k];
1887 evecs[dim * j + k] = p;
1888 }
1889 }
1890 }
1891 }
1892
1893
1894 /*==*/
1895 template<typename T>
1896 void
MxBinWrite(T * Mx,const char what[],char c)1897 Calc<T>::MxBinWrite(T *Mx,
1898 const char what[],
1899 char c)
1900 {
1901 int i, j, len = -1;
1902 FILE *BINOUT = NULL;
1903 char *wosis = NULL, *binfile = NULL;
1904 const char *suffix = "bin";
1905
1906 /*size_t info; */
1907
1908 wosis = (char *)what;
1909 if (_opt->basename == NULL)
1910 len = strlen(suffix) + strlen(wosis) + 4;
1911 else
1912 len = strlen(_opt->basename) + strlen(wosis) + strlen(suffix) + 4;
1913
1914 binfile = (char *)calloc(len, sizeof(char));
1915 assert(binfile != NULL);
1916 if (_opt->basename != NULL) {
1917 strcpy(binfile, _opt->basename);
1918 strcat(binfile, ".");
1919 strcat(binfile, wosis);
1920 strcat(binfile, ".");
1921 strcat(binfile, suffix);
1922 } else {
1923 /* this should not happen */
1924 strcpy(binfile, wosis);
1925 strcat(binfile, ".");
1926 strcat(binfile, suffix);
1927 }
1928
1929 if (!_opt->quiet)
1930 fprintf(stderr, "MxBinWrite: writing %s to %s\n", wosis, binfile);
1931
1932 BINOUT = fopen(binfile, "w");
1933 if (!BINOUT) {
1934 fprintf(stderr, "ERROR: could not open file pointer for binary outfile %s\n", binfile);
1935 exit(EXIT_FAILURE);
1936 }
1937
1938 /* first write dim to file */
1939 fwrite(&dim, sizeof(int), 1, BINOUT);
1940 switch (c) {
1941 case 'm': /* write matrix entries */
1942 for (i = 0; i < dim; i++)
1943 for (j = 0; j < dim; j++) {
1944 double val = (double)Mx[dim * i + j];
1945 fwrite(&val, sizeof(double), 1, BINOUT);
1946 /*if (!_opt->quiet) fprintf(stderr, "\n"); */
1947 }
1948 break;
1949 case 'v': /* write vector entries */
1950 for (i = 0; i < dim; i++) {
1951 double val = (double)Mx[i];
1952 fwrite(&val, sizeof(double), 1, BINOUT);
1953 /*fprintf(stderr, "\n"); */
1954 }
1955 break;
1956 default:
1957 fprintf(stderr, "ERROR MxBinWrite(): no handler for type %c\n", c);
1958 exit(EXIT_FAILURE);
1959 }
1960 fclose(BINOUT);
1961 /* if(binfile) free(binfile); */
1962 }
1963
1964
1965 /*==*/
1966 template<typename T>
1967 int
MxBinRead(T ** Mx,const char what[],char c)1968 Calc<T>::MxBinRead(T **Mx,
1969 const char what[],
1970 char c)
1971 {
1972 int dimension = 0, len = -1;
1973 FILE *BININ = NULL;
1974 char *wosis = NULL, *binfile = NULL;
1975 const char *suffix = "bin";
1976 double *data = NULL;
1977 int ref;
1978
1979 /*size_t info; */
1980
1981 wosis = (char *)what;
1982 if (_opt->basename == NULL)
1983 len = strlen(suffix) + strlen(wosis) + 4;
1984 else
1985 len = strlen(_opt->basename) + strlen(wosis) + strlen(suffix) + 4;
1986
1987 binfile = (char *)calloc(len, sizeof(char));
1988 assert(binfile != NULL);
1989 if (_opt->basename != NULL) {
1990 strcpy(binfile, _opt->basename);
1991 strcat(binfile, ".");
1992 strcat(binfile, wosis);
1993 strcat(binfile, ".");
1994 strcat(binfile, suffix);
1995 } else {
1996 /* this should not happen */
1997 strcpy(binfile, wosis);
1998 strcat(binfile, ".");
1999 strcat(binfile, suffix);
2000 }
2001
2002 fprintf(stderr, "MxBinRead: reading %s from %s\n", wosis, binfile);
2003 BININ = fopen(binfile, "r+");
2004 if (!BININ) {
2005 fprintf(stderr, "ERROR: could not open file pointer for\
2006 binary infile %s\n", binfile);
2007 exit(EXIT_FAILURE);
2008 }
2009
2010 /* read dimension from file */
2011 ref = fread(&dimension, sizeof(int), 1, BININ);
2012 size_t numberOfValues;
2013 switch (c) {
2014 /* read data */
2015 case 'm':
2016 numberOfValues = dimension * dimension;
2017 data = (double *)calloc(numberOfValues, sizeof(double));
2018 ref = fread((void *)data, sizeof(double), numberOfValues, BININ);
2019 break;
2020 case 'v':
2021 numberOfValues = dimension;
2022 data = (double *)calloc(numberOfValues, sizeof(double));
2023 ref = fread(data, sizeof(double), numberOfValues, BININ);
2024 break;
2025 default:
2026 fprintf(stderr, "ERROR MxBinRead(): no handler for type %c\n", c);
2027 exit(EXIT_FAILURE);
2028 }
2029
2030 T *convertedValues = new T[numberOfValues]; /*(T *)calloc(numberOfValues, sizeof(T)); */
2031 for (size_t i = 0; i < numberOfValues; i++)
2032 convertedValues[i] = (T)data[i];
2033
2034 *Mx = convertedValues;
2035 fclose(BININ);
2036 free(binfile);
2037 return dimension;
2038 }
2039
2040
2041 /*==*/
2042
2043 template<typename T>
2044 inline
2045 void
MxASCIIWrite(T * Mx,const char * asciifile)2046 Calc<T>::MxASCIIWrite(T *Mx,
2047 const char *asciifile)
2048 {
2049 int i, j;
2050 FILE *ASCIIOUT;
2051
2052 ASCIIOUT = fopen(asciifile, "w");
2053 if (!ASCIIOUT) {
2054 fprintf(stderr, "could not open file pointer 4 ASCII outfile\n");
2055 exit(EXIT_FAILURE);
2056 }
2057
2058 for (i = 0; i < dim; i++) {
2059 for (j = 0; j < dim; j++)
2060 fprintf(ASCIIOUT, "%15.10g ", (double)Mx[dim * j + i]);
2061 fprintf(ASCIIOUT, "\n");
2062 }
2063 if (!_opt->quiet)
2064 fprintf(stderr, "matrix written to ASCII file\n");
2065
2066 fclose(ASCIIOUT);
2067 }
2068
2069
2070 template<typename T>
2071 inline
2072 void
MxASCIIWriteV(T * Mx,const char * asciifile)2073 Calc<T>::MxASCIIWriteV(T *Mx,
2074 const char *asciifile)
2075 {
2076 int i;
2077 FILE *ASCIIOUT;
2078
2079 ASCIIOUT = fopen(asciifile, "w");
2080 if (!ASCIIOUT) {
2081 fprintf(stderr, "could not open file pointer 4 ASCII outfile\n");
2082 exit(EXIT_FAILURE);
2083 }
2084
2085 for (i = 0; i < dim; i++)
2086 fprintf(ASCIIOUT, "%15.10g ", (double)Mx[i]);
2087 if (!_opt->quiet)
2088 fprintf(stderr, "vector written to ASCII file\n");
2089
2090 fclose(ASCIIOUT);
2091 }
2092
2093
2094 /*==*/
2095
2096 template<typename T>
2097 int
MxExponent(T * p0,T * p8,T * U)2098 Calc<T>::MxExponent(T *p0,
2099 T *p8,
2100 T *U)
2101 {
2102 ExpMatrix em;
2103
2104 int i, j, pdiff_counter = 0, count = 0;
2105 T x, tt, time, *Uexp, *Umerk, *pt, *pdiff, check = 0.;
2106
2107 Umerk = new T[dim * dim]; /*(T *) MxNew (dim*dim*sizeof(T)); */
2108 Uexp = new T[dim * dim]; /*(T *) MxNew (dim*dim*sizeof(T)); */
2109 pt = new T[dim]; /*(T *) MxNew (dim*sizeof(T)); */
2110 pdiff = new T[dim]; /*(T *) MxNew (dim*sizeof(T)); */
2111
2112 /*memcpy(Umerk, U, dim*dim*sizeof(T)); */
2113 std::copy(U, U + dim * dim, Umerk);/*U to Umerk */
2114
2115 /* solve fundamental equation */
2116 if (_opt->t0 == 0.0) {
2117 if (_opt->method == 'F')
2118 PrintProbFull(p0, dim, 0.0, _lmins);
2119 else
2120 PrintProb(p0, dim, 0.0);
2121
2122 _opt->t0 = _globalParameters->TZERO;
2123 }
2124
2125 for (i = 0; i < dim; i++)
2126 U[(dim + 1) * i] -= 1;
2127 print_settings();
2128 for (tt = _opt->t0; tt < _opt->t8 * _opt->tinc; tt *= _opt->tinc) {
2129 time = (tt < _opt->t8) ? tt : (T)_opt->t8;
2130 /*memcpy(U, Umerk, dim*dim*sizeof(T)); */
2131 std::copy(Umerk, Umerk + dim * dim, U);/* Umerk to U; */
2132 for (i = 0; i < dim * dim; i++)
2133 U[i] *= time;
2134 em.padexp(U, Uexp, dim, 30, _opt->FEPS);
2135 x = 0.;
2136 for (j = 0; j < dim * dim; j++)
2137 x += Uexp[j];
2138 for (j = 0; j < dim * dim; j++)
2139 Uexp[j] *= (T)dim / x;
2140 mxccm.vmul(pt, Uexp, p0, dim);
2141 /* check convergence */
2142 for (i = 0; i < dim; i++) {
2143 pdiff[i] = (T)(p8[i] - pt[i]);
2144 if (abs(pdiff[i]) >= 0.0001)
2145 pdiff_counter++;
2146 }
2147 if (pdiff_counter < 1)
2148 break;
2149
2150 pdiff_counter = 0.;
2151 /* end check convergence */
2152 check = 0.;
2153 printf("%e ", (double)time); /* print p(t) to stdout */
2154 for (i = 0; i < dim; i++) {
2155 if (pt[i] < -0.00001) {
2156 fprintf(stderr, "prob of lmin %i has become negative!\n", i + 1);
2157 exit(EXIT_FAILURE);
2158 }
2159
2160 printf("%e ", (double)(T)abs(pt[i])); /*abs for mlapack */
2161 check += abs(pt[i]);
2162 }
2163 printf("\n");
2164
2165 count++; /* # of iterations */
2166
2167 if (((check - 1.) < -0.01) || ((check - 1.) > 0.01)) {
2168 fprintf(stderr,
2169 "overall probability at time %e is %e != 1.0 %s!\n",
2170 (double)time,
2171 (double)check,
2172 (_opt->num_err == 'R' ? "rescaling" : "exiting"));
2173 if (_opt->num_err == 'H') {
2174 /*clean up before writing error. */
2175 delete[] Uexp;
2176 delete[] pt;
2177 delete[] pdiff;
2178 delete[] Umerk;
2179 return 1;
2180 /*exit(EXIT_FAILURE); //Exit in main. */
2181 }
2182 }
2183
2184 fill_n(pt, dim, 0);
2185 fill_n(pdiff, dim, 0);
2186 fill_n(Uexp, dim * dim, 0);
2187 /*fill_n(U, dim*dim, 0); */
2188 }
2189 printf("# of iterations: %d\n", count);
2190 delete[] Uexp;
2191 delete[] pt;
2192 delete[] pdiff;
2193 delete[] Umerk;
2194
2195 return 0;
2196 }
2197
2198
2199 /*==*/
2200 template<typename T>
2201 void
MxFPT(T * U,T * p8,FILE * out)2202 Calc<T>::MxFPT(T *U,
2203 T *p8,
2204 FILE *out)
2205 {
2206 int i, j;
2207
2208 /*fprintf(stderr, "in MxFPT\n"); */
2209 /*if(_opt->want_verbose) MxPrint (U,"U" , 'm'); */
2210 T *Z = NULL, *M = NULL;
2211
2212 /*MxPrint(U, "U mxfpt", 'm'); */
2213
2214 if (_opt->absrb) {
2215 Z = new T[(dim - 1) * (dim - 1)];
2216
2217 int i, j, nrhs, nfo, *ipiv = NULL;
2218 T *B = new T[(dim - 1)];
2219
2220 for (i = 0; i < dim - 1; i++)
2221 B[i] = 1.0;
2222
2223 for (i = 0; i < dim - 1; i++)
2224 for (j = 0; j < dim - 1; j++)
2225 Z[(dim - 1) * i + j] = (T)((i == j && _opt->useplusI ? 1.0 : 0.0) - U[dim * i + j]); /* I-U = -Q (U is transposed) without absorbing state*/
2226
2227
2228 ipiv = (int *)malloc((dim - 1) * sizeof(int));
2229 nrhs = 1;
2230
2231 int n = dim - 1;
2232 /*DGESV computes the solution to a real system of linear equations A * X = B (I think A must be transposed) */
2233 solver->Mx_Dgesv(&n, &nrhs, Z, &n, ipiv, B, &n, &nfo);
2234
2235 /* fix non-zero in real absorbing state */
2236 for (i = 0; i < dim - 1; i++)
2237 B[i] -= B[_opt->real_abs];
2238 dim--;
2239 MxFPrint(B, "Absorbing times: ", 'v', out, out != stderr);
2240 dim++;
2241
2242 delete[] B;
2243 delete[] Z;
2244 free(ipiv);
2245 } else {
2246 /* non-absorbing case */
2247 Z = new T[dim * dim];
2248
2249 for (i = 0; i < dim; i++)
2250 for (j = 0; j < dim; j++)
2251 Z[dim * i + j] = (T)((i == j && _opt->useplusI ? 1.0 : 0.0) - U[dim * j + i] + p8[j]); /* I-U+W = W-Q (U is transposed)*/
2252
2253
2254 /*if(_opt->want_verbose) MxPrint (Z,"I-U+W" , 'm'); */
2255 mxccm.minv(Z, dim, _opt->FEPS);
2256 /*if(_opt->want_verbose)MxPrint (Z,"Fundamental matrix Z=inv(I-U+W)" , 'm'); */
2257
2258 M = new T[dim * dim];
2259 for (i = 0; i < dim; i++)
2260 for (j = 0; j < dim; j++)
2261 M[dim * i + j] = (T)((Z[dim * j + j] - Z[dim * i + j]) / p8[j]);
2262
2263 MxFPrint(M,
2264 "First passage times (i-th row, j-th column represents fpt from i-th to j-th state)",
2265 'm',
2266 out,
2267 out != stderr);
2268 delete[] M;
2269 delete[] Z;
2270 }
2271 }
2272
2273
2274 /*==*/
2275
2276 template<typename T>
2277 void
MxKotzOutMathematica(T * Mx)2278 Calc<T>::MxKotzOutMathematica(T *Mx)
2279 {
2280 int i, j;
2281 FILE *MATHEMATICA_OUT = NULL;
2282 const char *mathematica_file = "mxMat.txt";
2283
2284 MATHEMATICA_OUT = fopen(mathematica_file, "w");
2285 if (!MATHEMATICA_OUT) {
2286 fprintf(stderr, "could not open file pointer 4 Matematica outfile\n");
2287 exit(EXIT_FAILURE);
2288 }
2289
2290 fprintf(MATHEMATICA_OUT, "{");
2291 for (i = 0; i < dim; i++) {
2292 fprintf(MATHEMATICA_OUT, "{");
2293 for (j = 0; j < dim; j++) {
2294 if (j != (dim - 1))
2295 fprintf(MATHEMATICA_OUT, "%25.22f, ", (double)Mx[dim * j + i]);
2296 else
2297 fprintf(MATHEMATICA_OUT, "%25.22f}", (double)Mx[dim * j + i]);
2298 }
2299 if (i != (dim - 1))
2300 fprintf(MATHEMATICA_OUT, ",\n");
2301 else
2302 fprintf(MATHEMATICA_OUT, "}\n");
2303 }
2304 fclose(MATHEMATICA_OUT);
2305 }
2306
2307
2308 template<typename T>
2309 T *
MxFPTOneState(T * U,int state)2310 Calc<T>::MxFPTOneState(T *U,
2311 int state)
2312 {
2313 if (state >= dim) {
2314 fprintf(stderr, "State %d does not exist (--fpt %d)", state + 1, state + 1);
2315 return NULL;
2316 }
2317
2318 int i, j, nrhs, nfo;
2319 int *ipiv = NULL;
2320 int n = dim - 1;
2321 T *A = NULL, *B = NULL;
2322 A = new T[n * n];
2323 B = new T[dim];
2324
2325 /* A = Q(infinetisimal generator) = U^T-I with state-th column and row deleted (U is transposed!) */
2326 for (i = 0; i < n; i++) {
2327 for (j = 0; j < n; j++) {
2328 int ui = (i >= state ? i + 1 : i);
2329 int uj = (j >= state ? j + 1 : j);
2330 A[n * i + j] = (T)(U[dim * ui + uj] - (i == j && _opt->useplusI ? 1.0 : 0.0));
2331 }
2332 }
2333
2334 for (i = 0; i < n; i++)
2335 B[i] = -1.0;
2336
2337 /*
2338 * dim--;
2339 * MxPrint(A, "A", 'm');
2340 * MxPrint(B, "B", 'v');
2341 * dim++;
2342 */
2343
2344 ipiv = (int *)malloc(n * sizeof(int));
2345 nrhs = 1;
2346
2347 /*DGESV computes the solution to a real system of linear equations A * X = B (I think A must be transposed), solution goes to B */
2348 solver->Mx_Dgesv(&n, &nrhs, A, &n, ipiv, B, &n, &nfo);
2349
2350 for (i = dim - 1; i > state; i--)
2351 B[i] = B[i - 1];
2352 B[state] = 0.0;
2353
2354 delete[] A;
2355 free(ipiv);
2356 return B;
2357 }
2358
2359
2360 template<typename T>
2361 inline
2362 void
MxFPTSimple(T * U)2363 Calc<T>::MxFPTSimple(T *U)
2364 {
2365 int i, j;
2366
2367 fprintf(stderr, "in MxFTPSimple\n");
2368 T *M = new T[dim * dim];
2369 T *B;
2370 int p_done = 0;
2371
2372 for (i = 0; i < dim; i++) {
2373 /* calculate to one state and add it to global matrix */
2374 B = MxFPTOneState(U, i);
2375 for (j = 0; j < dim - 1; j++)
2376 M[dim * j + i] = B[j];
2377 delete[] B; /*free(B); */
2378 /* print progress */
2379 if (i * 100 / dim >= p_done) {
2380 p_done = i * 100 / dim;
2381 fprintf(stderr, "%d%%\n", p_done);
2382 }
2383 }
2384
2385 MxPrint(M, "FPT", 'm');
2386
2387 delete[] M;
2388 }
2389
2390
2391 template<typename T>
2392 inline
2393 void
MxFPTRnd(T * U,int packets)2394 Calc<T>::MxFPTRnd(T *U,
2395 int packets)
2396 {
2397 srand(time(NULL));
2398 T *P = NULL, *M = NULL;
2399
2400 P = (T *)malloc(dim * dim * sizeof(T));
2401
2402 int i, j;
2403
2404 for (i = 0; i < dim; i++) {
2405 for (j = 0; j < dim; j++)
2406 /*if (i==j) P[dim*i+j] */
2407 P[dim * i + j] = U[dim * j + i] / (1.0 - U[dim * i + i]);
2408 P[dim * i + i] = 0.0;
2409 }
2410
2411 /*MxPrint(U, "U", 'm'); */
2412 /*#MxPrint(P, "P", 'm'); */
2413
2414 if (!_opt->absrb) {
2415 /* ergodic option */
2416 M = (T *)malloc(dim * dim * sizeof(T));
2417 for (i = 0; i < dim; i++) {
2418 for (j = 0; j < dim; j++) {
2419 M[dim * i + j] = MxFPTRandom(P, U, i, j, packets);
2420 fprintf(stderr, "x");
2421 }
2422 fprintf(stderr, "\n");
2423 }
2424
2425 MxPrint(M, "M (random)", 'm');
2426 } else {
2427 /* absorbing option */
2428 M = (T *)malloc(dim * sizeof(T));
2429 for (i = 0; i < dim; i++)
2430 M[i] = MxFPTRandom(P, U, i, dim - 1, packets);
2431
2432 MxPrint(M, "M (random)", 'v');
2433 }
2434
2435 free(M);
2436 free(P);
2437 }
2438
2439
2440 template<typename T>
2441 T
MxFPTRandom(T * P,T * U,int src,int dst,int packets)2442 Calc<T>::MxFPTRandom(T *P,
2443 T *U,
2444 int src,
2445 int dst,
2446 int packets)
2447 {
2448 if (src == dst)
2449 return 0.0;
2450
2451 T wtime = 0.0;
2452 int i, j;
2453 for (i = 0; i < packets; i++) {
2454 int curr = src;
2455 T time = 0.0;
2456 while (curr != dst) {
2457 time += 1 / (1.0 - U[dim * curr + curr]);
2458 T next = random() / (T)RAND_MAX;
2459 j = 0;
2460 while (next > 0.0 && j < dim) {
2461 next -= P[dim * curr + j];
2462 j++;
2463 }
2464 j--;
2465 curr = j;
2466 }
2467 /*fprintf(stderr, "time to consume %f\n", time); */
2468 wtime += time;
2469 }
2470 return wtime / (T)packets;
2471 }
2472
2473
2474 template<typename T>
2475 void
MxEVLapackSym(T * U)2476 Calc<T>::MxEVLapackSym(T *U)
2477 {
2478 /* extern void dsyev_(char *jobz, char *uplo, int *n, double *A,int *lda, */
2479 /* double *w, double *work, int *lwork, int *info); */
2480 T abstol;
2481
2482 abstol = _opt->FEPS;
2483
2484 if (_opt->want_verbose)
2485 fprintf(stderr, "FEPS precision %20.10g\n", (double)abstol);
2486
2487 T *work = NULL, vl, vu; /* unused or inputs */
2488 int il, iu, m, lwork, liwork, *iwork = NULL, *ifail = NULL, *isuppz = NULL, nfo; /* unused or inputs */
2489 lwork = dim * (dim + 26);
2490 liwork = 10 * dim;
2491 work = (T *)malloc(lwork * sizeof(T));
2492 iwork = (int *)malloc(liwork * sizeof(int));
2493 ifail = (int *)malloc(dim * sizeof(int));
2494 isuppz = (int *)malloc(2 * dim * sizeof(int));
2495
2496 /*if (!_opt->useplusI) for (il=0; il<dim; il++) U[il*dim+il]-=1.0; */
2497
2498 /* works only with: dim, U, evals, evecs */
2499 solver->Mx_Dsyevx("V", "A", "U", &dim, U, &dim, &vl, &vu, &il, &iu,
2500 &abstol, &m, evals, evecs, &dim, work, &lwork, iwork,
2501 ifail, &nfo);
2502 /*
2503 #if 1
2504 * dsyevx_("V", "A", "U",&dim, U, &dim, &vl, &vu, &il, &iu,
2505 * &abstol, &m, evals, evecs, &dim, work, &lwork, iwork,
2506 * ifail, &nfo);
2507 #else
2508 * dsyevr_("V", "A", "U",&dim, U, &dim, &vl, &vu, &il, &iu,
2509 * &abstol, &m, evals, evecs, &dim, isuppz, work, &lwork, iwork,
2510 * &liwork, &nfo);
2511 #endif
2512 */
2513
2514 /*dsyev_("V","U",&dim, S, &dim, evals, work, &lwork, &nfo); */
2515 /*MxPrint(evecs, "Eigenvectors (bad)", 'm'); */
2516 /*MxPrint(evals, "Eigenvalues (bad)", 'v'); */
2517 if (nfo != 0) {
2518 fprintf(stderr,
2519 "dsyevx exited with value %d (val=%20.10g) (Cannot compute eigenvalues) Try to:\n - lower --feps value (try --feps=-1.0)\n - try using --useplusI option (sometimes the eigenvalues are better computed like that)\n",
2520 nfo,
2521 (double)evals[nfo - 1]);
2522 for (il = 0; il < dim; il++)
2523 fprintf(stderr, "%20.10g ", (double)evecs[nfo * dim + il]);
2524 fprintf(stderr, "\n");
2525
2526 fprintf(stderr, "\n");
2527 exit(EXIT_FAILURE);
2528 }
2529
2530 /*if (!_opt->useplusI) for (il=0; il<dim; il++) U[il*dim+il]+=1.0; */
2531
2532 free(work);
2533 free(iwork);
2534 free(ifail);
2535 free(isuppz);
2536
2537 /* transpose output */
2538 mxccm.trnm(evecs, dim);
2539 }
2540
2541
2542 template<typename T>
2543 void
MxEVLapackNonSym(T * origU)2544 Calc<T>::MxEVLapackNonSym(T *origU)
2545 /* input: matrix origU, space for (right)evec-matrix S, */
2546 /* since fortran sucks, we transpose the input matrix */
2547 /* and still want the right eigenvectors */
2548 /* matrix of right eigenvecs is transposed to have */
2549 /* the j-th evec in column c */
2550 {
2551 T *evals_re = NULL, *evals_im = NULL, *scale = NULL;
2552 T *rconde = NULL, *rcondv = NULL, *work = NULL, abnrm;
2553 int one, ilo, ihi, lwork, *iwork, nfo;
2554 /*int dimx2; */
2555 /* for sorting */
2556 int i;
2557
2558 dim = dim + 500;
2559 one = 1;
2560 /*dimx2 = 2*dim; */
2561 lwork = dim * (dim + 6);
2562
2563 evals_re = new T[dim];
2564 evals_im = new T[dim];
2565 scale = new T[dim];
2566 rconde = new T[dim];
2567 rcondv = new T[dim];
2568 work = new T[lwork];
2569 iwork = new int[2 * (dim - 2)];
2570 dim = dim - 500;
2571 if ((evals_re && evals_im && scale && rconde &&
2572 rcondv && work && iwork) == 0) {
2573 fprintf(stderr, "no space for temporary lapack arrays!\n");
2574 exit(EXIT_FAILURE);
2575 }
2576
2577 /* instead of more fiddling, we transpose the input */
2578 mxccm.trnm(origU, dim);
2579
2580 T *tmpNull = NULL;
2581 solver->Mx_Dgeevx("B", "N", "V", "V", &dim, origU, &dim, evals_re, evals_im, tmpNull, &one,
2582 evecs, &dim, &ilo, &ihi, scale, &abnrm, rconde, rcondv, work,
2583 &lwork, iwork, &nfo);
2584
2585 for (i = 0; i < dim; i++)
2586 evals[i] = evals_re[i];
2587 for (i = 0; i < dim; i++)
2588 if ((evals_re[i] != 0.0) && abs(evals_im[i] / evals_re[i]) > _opt->FEPS)
2589 fprintf(stderr, "eigenvalue %d is %g + i*%g, which is somewhat complex\n",
2590 i, (double)evals_re[i], (double)evals_im[i]);
2591
2592 /*transpose output*/
2593 mxccm.trnm(evecs, dim);
2594
2595 delete[] evals_re;
2596 delete[] evals_im;
2597 delete[] scale;
2598 delete[] rconde;
2599 delete[] rcondv;
2600 delete[] work;
2601 delete[] iwork;
2602 }
2603
2604
2605 template<typename T>
2606 inline
2607 void
MxEqDistrFromDetailedBalance(T * U,T ** p8)2608 Calc<T>::MxEqDistrFromDetailedBalance(T *U,
2609 T **p8)
2610 {
2611 T *res = *p8;
2612 int *done;
2613 int count = 1; /* num of solved states */
2614 int i = 0;
2615 int j = 1;
2616 int k;
2617
2618 done = new int[dim];
2619 std::fill_n(done, dim, 0);
2620
2621 for (k = 1; k < dim; k++)
2622 res[k] = 0.0;
2623 res[0] = 1.0;
2624
2625 /* while there are unsolved states */
2626 while (count != dim) {
2627 for (j = 1; j < dim; j++) {
2628 if (res[j] > (T)0.)
2629 continue;
2630
2631 if (U[dim * i + j] > (T)0.0) {
2632 if (U[dim * j + i] == (T)0.0) {
2633 fprintf(stderr, "Local balance is unsatisfiable at U[%d][%d]=%f\n", i, j,
2634 (double)U[dim * i + j]);
2635 exit(EXIT_FAILURE);
2636 }
2637
2638 /* local balance */
2639 T tmp = U[dim * j + i];
2640 tmp *= res[i];
2641 tmp /= U[dim * i + j];
2642 res[j] = tmp;
2643 count++;
2644 if (res[j] > (T)1. || res[j] <= (T)0.) {
2645 fprintf(stderr, "Weird eqilibrium pop for state %d", j);
2646 MxPrint(res, "p8 (local balance)", 'v');
2647 }
2648 }
2649 }
2650 done[i] = 1;
2651 for (i = 1; i < dim; i++)
2652 if ((!done[i]) && (res[i] > (T)0.))
2653 break;
2654
2655 if (i == dim && count < dim) {
2656 fprintf(stderr, "non-ergodic chain\n");
2657 MxPrint(res, "p8 (local balance)", 'v');
2658 exit(EXIT_FAILURE);
2659 }
2660 }
2661
2662 delete[] done;
2663
2664 /* now make the vector stochastic (sum = 1.0) */
2665 T sum = 0.0;
2666 for (i = 0; i < dim; i++)
2667 sum += res[i];
2668 for (i = 0; i < dim; i++)
2669 res[i] /= sum;
2670
2671 MxPrint(res, "p8 (detailed balance)", 'v');
2672 }
2673
2674
2675 /*==*/
2676 template<typename T>
2677 void *
MxNew(size_t size)2678 Calc<T>::MxNew(size_t size)
2679 {
2680 void *mx = NULL;
2681
2682 if ((mx = (void *)calloc(1, size)) == NULL)
2683 fprintf(stderr, "ERROR: new_martix() allocation failed\n");
2684
2685 return mx;
2686 }
2687
2688
2689 /*==*/
2690 template<typename T>
2691 void
MxMemoryCleanUp(void)2692 Calc<T>::MxMemoryCleanUp(void)
2693 {
2694 if (_opt->sequence)
2695 free(_opt->sequence);
2696
2697 if (_opt->basename)
2698 free(_opt->basename);
2699
2700 if (_opt->fpt_file)
2701 free(_opt->fpt_file);
2702
2703 delete[] _sqrPI;
2704 delete[] sqrPI_;
2705 delete[]evecs;
2706 delete[]evals;
2707 }
2708
2709
2710 /*==*/
2711 template<typename T>
2712 void
print_settings(void)2713 Calc<T>::print_settings(void)
2714 {
2715 printf(
2716 "# Date: %s"
2717 "# Sequence: %s\n"
2718 "# Method: %c\n"
2719 "# Start time: %.2f\n"
2720 "# Stop time: %.2f\n"
2721 "# Temperature: %.2f\n",
2722 time_stamp(),
2723 _opt->sequence,
2724 _opt->method,
2725 _opt->t0,
2726 _opt->t8,
2727 _opt->T
2728 );
2729 if (_opt->basename != NULL)
2730 printf("# Basename: %s\n", _opt->basename);
2731 else
2732 printf("# Basename: <stdin>\n");
2733
2734 if (_opt->tinc)
2735 printf("# Time increment: %.2f\n", _opt->tinc);
2736 else
2737 printf("# Time increment: %.2f \n", _opt->tinc);
2738
2739 if (_opt->want_degenerate == 1)
2740 printf("# Degeneracy: on\n");
2741 else
2742 printf("# Degeneracy: off\n");
2743
2744 if (_opt->absrb < 1)
2745 printf("# Absorbing state: none\n");
2746 else
2747 printf("# Absorbing state: %d\n", _opt->absrb);
2748
2749 if (_opt->n > 0)
2750 printf("# States limit: %d\n", _opt->n);
2751 else
2752 printf("# States limit: till EOF\n");
2753 }
2754
2755
2756 /*==*/
2757 template<typename T>
2758 char *
time_stamp(void)2759 Calc<T>::time_stamp(void)
2760 {
2761 time_t cal_time;
2762
2763 cal_time = time(NULL);
2764 return ctime(&cal_time);
2765 }
2766
2767
2768 /*==*/
2769 template<typename T>
2770 void
MxDoDegeneracyStuff(void)2771 Calc<T>::MxDoDegeneracyStuff(void)
2772 {
2773 int i, j, b, nr, current, numsad = 1, count = 0;
2774 TypeDegSaddle *saddle = NULL;
2775
2776 numsad = Barparser::ParseSaddleFile(&saddle);
2777 /* loop over all elements of structure-array saddle: */
2778 /* first we fill the upper triangle */
2779 for (count = 0; count < numsad; count++) {
2780 current = 1;
2781 nr = saddle[count].list[0];
2782 /* only for saddles with a cc >= 1 AND those which connect at least 2 lmins */
2783 if (saddle[count].cc >= 1 && nr >= 2 && !(saddle[count].cc == 1 && nr == 2)) {
2784 while (current < nr) {
2785 for (b = current + 1; b <= nr; b++) {
2786 /* skip in case a lmin which we don't see is connected by */
2787 /* the saddle (because we can only see --max x lmins) */
2788 if (saddle[count].list[current] > dim || saddle[count].list[b] > dim) {
2789 current++;
2790 continue;
2791 }
2792
2793 /* FIRST: we consider the size of the cc the saddle belongs to */
2794 if (saddle[count].cc > 1) {
2795 D[dim * (saddle[count].list[current] - 1) +
2796 (saddle[count].list[b] - 1)] += (saddle[count].cc - 1);
2797 fprintf(stderr, "transition between %3d - %3d: adding %2d cc\n",
2798 saddle[count].list[current], saddle[count].list[b], saddle[count].cc - 1);
2799 /* -1 because if the size of cc == 1 there's nothing special */
2800 /* about it, i.e. there is just one saddle */
2801 }
2802
2803 /* SECOND: we consider that the saddle connects several lmins */
2804 if (nr > 2) {
2805 D[dim * (saddle[count].list[current] - 1) + (saddle[count].list[b] - 1)] += 1;
2806 fprintf(stderr, "transition betweed %3d - %3d: adding 1 deg_saddle\n",
2807 saddle[count].list[current], saddle[count].list[b]);
2808 /* -1 because matrix starts with0, NOT with 1 */
2809 }
2810 }
2811 current++;
2812 }
2813 }
2814 }
2815
2816 for (i = 0; i < dim; i++) {
2817 /* make matrix symmetric */
2818 for (j = 0; j < dim; j++)
2819 if (i != j)
2820 D[dim * j + i] = D[dim * i + j];
2821 }
2822 if (_opt->want_verbose) {
2823 sprintf(Aname, "%s", "D (degeneracies)");
2824 MxPrint(D, Aname, 'm');
2825 }
2826
2827 free(saddle);
2828 }
2829
2830
2831 #endif
2832
2833 /* End of file */
2834