ATSuite C++  v1.0
Scientific C++ routines originally developed by Alexis Tantet
transferOperator.hpp
Go to the documentation of this file.
1 #ifndef TRANSFEROPERATOR_HPP
2 #define TRANSFEROPERATOR_HPP
3 
4 #include <iostream>
5 #include <vector>
6 #include <gsl/gsl_vector.h>
7 #include <gsl/gsl_vector_uint.h>
8 #include <gsl/gsl_matrix.h>
9 #include <gsl/gsl_matrix_uint.h>
10 #include <Eigen/Dense>
11 #include <Eigen/Sparse>
12 #include <ATSuite/atmatrix.hpp>
13 #include <ATSuite/atmarkov.hpp>
14 #include <ATSuite/atio.hpp>
15 #if defined (WITH_OMP) && WITH_OMP == 1
16 #include <omp.h>
17 #endif
18 
27 /*
28  * Typedef declaration
29  */
30 
32 typedef Eigen::Triplet<double> triplet;
34 typedef std::vector<triplet> tripletVector;
36 typedef Eigen::Triplet<size_t> tripletUInt;
38 typedef std::vector<tripletUInt> tripletUIntVector;
40 typedef Eigen::SparseMatrix<double, Eigen::ColMajor> SpMatCSC;
42 typedef Eigen::SparseMatrix<double, Eigen::RowMajor> SpMatCSR;
43 
44 
45 /*
46  * Class declarations
47  */
48 
54 class Grid {
56  void allocate(gsl_vector_uint *);
58  void getRectGrid(gsl_vector_uint *, const gsl_vector *, const gsl_vector *);
59 
60 public:
62  size_t dim;
64  size_t N;
66  gsl_vector_uint *nx;
68  std::vector<gsl_vector *> *gridBounds;
69 
71  Grid(){}
73  Grid(gsl_vector_uint *nx_){ allocate(nx_); }
75  Grid(gsl_vector_uint *, const gsl_vector *, const gsl_vector *);
77  Grid(size_t, size_t, double, double);
79  ~Grid();
80 
82  int printGrid(const char *, const char *, bool);
83 };
84 
104  void allocate(size_t);
106  void buildFromMembership(const gsl_matrix_uint *);
107 
108 public:
109  size_t N;
110  SpMatCSR *P;
111  SpMatCSR *Q;
112  gsl_vector *initDist;
113  gsl_vector *finalDist;
114 
118  transferOperator(size_t gridSize){ allocate(gridSize); }
120  transferOperator(const gsl_matrix_uint *, size_t);
122  transferOperator(const gsl_vector_uint *, size_t);
124  transferOperator(const gsl_matrix *, const gsl_matrix *, const Grid *);
126  transferOperator(const gsl_matrix *, const Grid *, size_t);
128  ~transferOperator();
129 
130  // Output methods
132  int printForwardTransition(const char *, const char *);
134  int printBackwardTransition(const char *, const char *);
136  int printInitDist(const char *, const char *);
138  int printFinalDist(const char *, const char *);
139 };
140 
141 
142 /*
143  * Functions declarations
144  */
145 
147 gsl_matrix_uint *getGridMemMatrix(const gsl_matrix *, const gsl_matrix *, const Grid *);
149 gsl_matrix_uint *getGridMemMatrix(const gsl_matrix *, const Grid *, const size_t);
151 gsl_vector_uint *getGridMemVector(const gsl_matrix *, const Grid *);
153 gsl_matrix_uint *memVector2memMatrix(const gsl_vector_uint *, size_t);
155 gsl_matrix_uint * memVectorList2memMatrix(const std::vector<gsl_vector_uint *> *, size_t);
157 int getBoxMembership(const gsl_vector *, const Grid *);
159 tripletUIntVector *getTransitionCountTriplet(const gsl_matrix_uint *, size_t);
160 
161 
162 /*
163  * Constructors and destructors definitions
164  */
165 
173 transferOperator::transferOperator(const gsl_matrix_uint *gridMem, size_t gridSize)
174 {
175  // Allocate
176  allocate(gridSize);
177 
178  // Get transition matrices and distributions from grid membership matrix
179  buildFromMembership(gridMem);
180 
181  return;
182 }
183 
192 transferOperator::transferOperator(const gsl_matrix *initStates,
193  const gsl_matrix *finalStates,
194  const Grid *grid)
195 {
196  gsl_matrix_uint *gridMem;
197 
198  // Allocate
199  N = grid->N;
200  allocate(N);
201 
202  // Get grid membership matrix
203  gridMem = getGridMemMatrix(initStates, finalStates, grid);
204 
205  // Get transition matrices and distributions from grid membership matrix
206  buildFromMembership(gridMem);
207 
208  // Free
209  gsl_matrix_uint_free(gridMem);
210 
211  return;
212 }
213 
221 transferOperator::transferOperator(const gsl_matrix *states, const Grid *grid,
222  const size_t tauStep)
223 {
224  gsl_matrix_uint *gridMem;
225 
226  // Allocate
227  N = grid->N;
228  allocate(N);
229 
230  // Get grid membership matrix from a single long trajectory
231  gridMem = getGridMemMatrix(states, grid, tauStep);
232 
233  // Get transition matrices and distributions from grid membership matrix
234  buildFromMembership(gridMem);
235 
236  // Free
237  gsl_matrix_uint_free(gridMem);
238 
239  return;
240 }
241 
244 {
245  delete P;
246  delete Q;
247  gsl_vector_free(initDist);
248  gsl_vector_free(finalDist);
249 }
250 
257 Grid::Grid(gsl_vector_uint *nx_, const gsl_vector *xmin, const gsl_vector *xmax)
258 {
259  // Allocate and build uniform rectangular grid
260  getRectGrid(nx_, xmin, xmax);
261 }
262 
270 Grid::Grid(size_t dim_, size_t inx, double dxmin, double dxmax)
271 {
272  // Convert to uniform vectors to call getRectGrid.
273  gsl_vector_uint *nx_ = gsl_vector_uint_alloc(dim_);
274  gsl_vector *xmin_ = gsl_vector_alloc(dim_);
275  gsl_vector *xmax_ = gsl_vector_alloc(dim_);
276  gsl_vector_uint_set_all(nx_, inx);
277  gsl_vector_set_all(xmin_, dxmin);
278  gsl_vector_set_all(xmax_, dxmax);
279 
280  // Allocate and build uniform rectangular grid
281  getRectGrid(nx_, xmin_, xmax_);
282 
283  // Free
284  gsl_vector_uint_free(nx_);
285  gsl_vector_free(xmin_);
286  gsl_vector_free(xmax_);
287 }
288 
291 {
292  gsl_vector_uint_free(nx);
293  for (size_t d = 0; d < dim; d++)
294  gsl_vector_free((*gridBounds)[d]);
295  delete gridBounds;
296 }
297 
298 
299 /*
300  * Methods definitions
301  */
302 
307 void
308 transferOperator::allocate(size_t gridSize)
309 {
310  N = gridSize;
311  P = new SpMatCSR(N, N);
312  Q = new SpMatCSR(N, N);
313  initDist = gsl_vector_alloc(N);
314  finalDist = gsl_vector_alloc(N);
315 
316  return;
317 }
318 
324 void
325 transferOperator::buildFromMembership(const gsl_matrix_uint *gridMem)
326 {
327  // Get transition count triplets
329 
330  // Convert to CSR matrix
331  P->setFromTriplets(T->begin(), T->end());
332 
333  // Get initial and final distribution
334  getRowSum(P, initDist);
335  getColSum(P, finalDist);
336 
337  // Get forward and backward transition matrices
338  *Q = SpMatCSR(P->transpose());
339  toLeftStochastic(P);
340  toLeftStochastic(Q);
341  normalizeVector(initDist);
342  normalizeVector(finalDist);
343 
344  // Free
345  delete T;
346 
347  return;
348 }
349 
356 int
357 transferOperator::printForwardTransition(const char *path, const char *dataFormat="%lf")
358 {
359  FILE *fp;
360 
361  // Open file
362  if ((fp = fopen(path, "w")) == NULL){
363  fprintf(stderr, "Can't open %s for printing the forward transition matrix!\n", path);
364  return(EXIT_FAILURE);
365  }
366 
367  // Print
368  Eigen2Compressed(fp, P, dataFormat);
369 
370  // Close
371  fclose(fp);
372 
373  return 0;
374 }
375 
382 int
383 transferOperator::printBackwardTransition(const char *path, const char *dataFormat="%lf")
384 {
385  FILE *fp;
386 
387  // Open file
388  if ((fp = fopen(path, "w")) == NULL){
389  fprintf(stderr, "Can't open %s for printing the backward transition matrix!\n", path);
390  return(EXIT_FAILURE);
391  }
392 
393  // Print
394  Eigen2Compressed(fp, Q, dataFormat);
395 
396  // Close
397  fclose(fp);
398 
399  return 0;
400 }
401 
408 int
409 transferOperator::printInitDist(const char *path, const char *dataFormat="%lf")
410 {
411  FILE *fp;
412 
413  // Open file
414  if ((fp = fopen(path, "w")) == NULL){
415  fprintf(stderr, "Can't open %s for printing the initial distribution!\n", path);
416  return(EXIT_FAILURE);
417  }
418 
419  // Print
420  gsl_vector_fprintf(fp, initDist, dataFormat);
421 
422  // Close
423  fclose(fp);
424 
425  return 0;
426 }
427 
434 int
435 transferOperator::printFinalDist(const char *path, const char *dataFormat="%lf")
436 {
437  FILE *fp;
438 
439  // Open file
440  if ((fp = fopen(path, "w")) == NULL){
441  fprintf(stderr, "Can't open %s for printing the final distribution!\n", path);
442  return(EXIT_FAILURE);
443  }
444 
445  // Print
446  gsl_vector_fprintf(fp, finalDist, dataFormat);
447 
448  // Close
449  fclose(fp);
450 
451  return 0;
452 }
453 
458 void
459 Grid::allocate(gsl_vector_uint *nx_)
460 {
461  dim = nx_->size;
462 
463  nx = gsl_vector_uint_alloc(dim);
464  gsl_vector_uint_memcpy(nx, nx_);
465 
466  N = 1;
467  gridBounds = new std::vector<gsl_vector *>(dim);
468  for (size_t d = 0; d < dim; d++){
469  N *= gsl_vector_uint_get(nx, d);
470  (*gridBounds)[d] = gsl_vector_alloc(gsl_vector_uint_get(nx, d) + 1);
471  }
472 
473  return;
474 }
475 
482 void
483 Grid::getRectGrid(gsl_vector_uint *nx_, const gsl_vector *xmin, const gsl_vector *xmax)
484 {
485  double delta;
486 
487  // Allocate
488  allocate(nx_);
489 
490  // Build uniform grid bounds
491  for (size_t d = 0; d < dim; d++) {
492  // Get spatial step
493  delta = (gsl_vector_get(xmax, d) - gsl_vector_get(xmin, d))
494  / gsl_vector_uint_get(nx, d);
495  // Set grid bounds
496  gsl_vector_set((*gridBounds)[d], 0, gsl_vector_get(xmin, d));
497  for (size_t i = 1; i < gsl_vector_uint_get(nx, d) + 1; i++)
498  gsl_vector_set((*gridBounds)[d], i,
499  gsl_vector_get((*gridBounds)[d], i-1) + delta);
500  }
501 
502  return;
503 }
504 
512 int
513 Grid::printGrid(const char *path, const char *dataFormat="%lf", bool verbose=false)
514 {
515  gsl_vector *bounds;
516  FILE *fp;
517 
518  // Open file
519  if ((fp = fopen(path, "w")) == NULL){
520  fprintf(stderr, "Can't open %s for printing the grid!\n", path);
521  return(EXIT_FAILURE);
522  }
523 
524  if (verbose)
525  std::cout << "Domain grid (min, max, n):" << std::endl;
526 
527  // Print grid
528  for (size_t d = 0; d < dim; d++) {
529  bounds = (*gridBounds)[d];
530  if (verbose) {
531  std::cout << "dim " << d+1 << ": ("
532  << gsl_vector_get(bounds, 0) << ", "
533  << gsl_vector_get(bounds, bounds->size - 1) << ", "
534  << (bounds->size - 1) << ")" << std::endl;
535  }
536 
537  for (size_t i = 0; i < bounds->size; i++){
538  fprintf(fp, dataFormat, gsl_vector_get((*gridBounds)[d], i));
539  fprintf(fp, " ");
540  }
541  fprintf(fp, "\n");
542  }
543 
544  // Close
545  fclose(fp);
546 
547  return 0;
548 }
549 
550 
551 /*
552  * Function definitions
553  */
554 
562 gsl_matrix_uint *
563 getGridMemMatrix(const gsl_matrix *initStates, const gsl_matrix *finalStates,
564  const Grid *grid)
565 {
566  const size_t nTraj = initStates->size1;
567  const size_t dim = initStates->size2;
568  gsl_matrix_uint *gridMem;
569 
570  // Allocate
571  gridMem = gsl_matrix_uint_alloc(grid->N, 2);
572 
573  // Assign a pair of source and destination boxes to each trajectory
574 #pragma omp parallel
575  {
576  gsl_vector *X = gsl_vector_alloc(dim);
577 
578 #pragma omp for
579  for (size_t traj = 0; traj < nTraj; traj++) {
580  // Find initial box
581  gsl_matrix_get_row(X, initStates, traj);
582  gsl_matrix_uint_set(gridMem, traj, 0, getBoxMembership(X, grid));
583 
584  // Find final box
585  gsl_matrix_get_row(X, finalStates, traj);
586  gsl_matrix_uint_set(gridMem, traj, 1, getBoxMembership(X, grid));
587  }
588  gsl_vector_free(X);
589  }
590 
591  return gridMem;
592 }
593 
600 gsl_vector_uint *
601 getGridMemVector(const gsl_matrix *states, const Grid *grid)
602 {
603  const size_t nStates = states->size1;
604  const size_t dim = states->size2;
605  gsl_vector_uint *gridMem = gsl_vector_uint_alloc(nStates);
606 
607  // Assign a pair of source and destination boxes to each trajectory
608 #pragma omp parallel
609  {
610  gsl_vector *X = gsl_vector_alloc(dim);
611 
612 #pragma omp for
613  for (size_t traj = 0; traj < nStates; traj++) {
614  // Find initial box
615  gsl_matrix_get_row(X, states, traj);
616 #pragma omp critical
617  {
618  gsl_vector_uint_set(gridMem, traj, getBoxMembership(X, grid));
619  }
620  }
621  gsl_vector_free(X);
622  }
623 
624  return gridMem;
625 }
626 
633 gsl_matrix_uint *
634 memVector2memMatrix(gsl_vector_uint *gridMemVect, size_t tauStep)
635 {
636  const size_t nStates = gridMemVect->size;
637  gsl_matrix_uint *gridMem = gsl_matrix_uint_alloc(nStates - tauStep, 2);
638 
639  // Get membership matrix from vector
640  for (size_t traj = 0; traj < (nStates - tauStep); traj++) {
641  gsl_matrix_uint_set(gridMem, traj, 0,
642  gsl_vector_uint_get(gridMemVect, traj));
643  gsl_matrix_uint_set(gridMem, traj, 1,
644  gsl_vector_uint_get(gridMemVect, traj + tauStep));
645  }
646 
647  return gridMem;
648 }
649 
657 gsl_matrix_uint *
658 getGridMemMatrix(const gsl_matrix *states, const Grid *grid, const size_t tauStep)
659 {
660  // Get membership vector
661  gsl_vector_uint *gridMemVect = getGridMemVector(states, grid);
662 
663  // Get membership matrix from vector
664  gsl_matrix_uint *gridMem = memVector2memMatrix(gridMemVect, tauStep);
665 
666  // Free
667  gsl_vector_uint_free(gridMemVect);
668 
669  return gridMem;
670 }
671 
679 gsl_matrix_uint *
680 memVectorList2memMatrix(const std::vector<gsl_vector_uint *> *memList, size_t tauStep)
681 {
682  size_t nStatesTot = 0;
683  size_t count;
684  const size_t listSize = memList->size();
685  gsl_matrix_uint *gridMem, *gridMemMatrixL;
686 
687  // Get total number of states and allocate grid membership matrix
688  for (size_t l = 0; l < listSize; l++)
689  nStatesTot += (memList->at(l))->size;
690  gridMem = gsl_matrix_uint_alloc(nStatesTot - tauStep * listSize, 2);
691 
692  // Get membership matrix from list of membership vectors
693  count = 0;
694  for (size_t l = 0; l < listSize; l++) {
695  gridMemMatrixL = memVector2memMatrix(memList->at(l), tauStep);
696  for (size_t t = 0; t < gridMemMatrixL->size1; t++) {
697  gsl_matrix_uint_set(gridMem, count, 0,
698  gsl_matrix_uint_get(gridMemMatrixL, t, 0));
699  gsl_matrix_uint_set(gridMem, count, 1,
700  gsl_matrix_uint_get(gridMemMatrixL, t, 1));
701  count++;
702  }
703  gsl_matrix_uint_free(gridMemMatrixL);
704  }
705 
706  return gridMem;
707 }
708 
715 int
716 getBoxMembership(const gsl_vector *state, const Grid *grid)
717 {
718  const size_t dim = state->size;
719  size_t inBox, nBoxDir;
720  size_t foundBox;
721  size_t subbp, subbn, ids;
722  gsl_vector *bounds;
723 
724  // Get box
725  foundBox = grid->N;
726  for (size_t box = 0; box < grid->N; box++){
727  inBox = 0;
728  subbp = box;
729  for (size_t d = 0; d < dim; d++){
730  bounds = grid->gridBounds->at(d);
731  nBoxDir = bounds->size - 1;
732  subbn = (size_t) (subbp / nBoxDir);
733  ids = subbp - subbn * nBoxDir;
734  inBox += (size_t) ((gsl_vector_get(state, d)
735  >= gsl_vector_get(bounds, ids))
736  & (gsl_vector_get(state, d)
737  < gsl_vector_get(bounds, ids+1)));
738  subbp = subbn;
739  }
740  if (inBox == dim){
741  foundBox = box;
742  break;
743  }
744  }
745 
746  return foundBox;
747 }
748 
757 getTransitionCountTriplet(const gsl_matrix_uint *gridMem, size_t N)
758 {
759  const size_t nTraj = gridMem->size1;
760  size_t box0, boxf;
761  size_t nOut = 0;
763  T->reserve(nTraj);
764 
765  for (size_t traj = 0; traj < nTraj; traj++) {
766  box0 = gsl_matrix_uint_get(gridMem, traj, 0);
767  boxf = gsl_matrix_uint_get(gridMem, traj, 1);
768 
769  // Add transition triplet
770  if ((box0 < N) && (boxf < N))
771  T->push_back(tripletUInt(box0, boxf, 1));
772  else
773  nOut++;
774  }
775  std::cout << nOut * 100. / nTraj
776  << "% of the trajectories ended up out of the domain." << std::endl;
777 
778  return T;
779 }
780 
781 #endif
int printFinalDist(const char *, const char *)
Print final distribution to file.
size_t N
Eigen::SparseMatrix< double, Eigen::ColMajor > SpMatCSC
Eigen CSC matrix of double type.
gsl_vector_uint * getGridMemVector(const gsl_matrix *, const Grid *)
Get the grid membership matrix from a single long trajectory.
~Grid()
Destructor.
std::vector< gsl_vector * > * gridBounds
void toLeftStochastic(SpMatCSR *)
Make an Eigen CSR matrix left stochastic.
Definition: atmarkov.hpp:101
Eigen::SparseMatrix< double, Eigen::RowMajor > SpMatCSR
Eigen CSR matrix of double type.
int printForwardTransition(const char *, const char *)
Print forward transition matrix to file in compressed matrix format.
transferOperator(size_t gridSize)
Empty constructor allocating for grid size.
gsl_vector * finalDist
Final distribution.
Eigen::Triplet< double > triplet
Eigen triplet of double.
Eigen::Triplet< size_t > tripletUInt
Eigen triplet of integer.
~transferOperator()
Destructor.
Transfer operator class.
transferOperator()
Default constructor.
tripletUIntVector * getTransitionCountTriplet(const gsl_matrix_uint *, size_t)
Get triplet vector from membership matrix.
SpMatCSR * Q
Backward transition matrix.
gsl_vector * getColSum(SpMatCSR *)
Get the sum of each column of an Eigen CSR matrix.
Definition: atmatrix.hpp:119
gsl_vector * initDist
Initial distribution.
gsl_vector * getRowSum(SpMatCSR *)
Get the sum of each row of an Eigen CSR matrix.
Definition: atmatrix.hpp:56
size_t dim
int printBackwardTransition(const char *, const char *)
Print backward transition matrix to file in compressed matrix format.
Grid()
Default constructor.
gsl_matrix_uint * memVectorList2memMatrix(const std::vector< gsl_vector_uint * > *, size_t)
Concatenate a list of membership vectors into one membership matrix.
std::vector< triplet > tripletVector
STD vector of Eigen triplet of double.
SpMatCSR * P
Forward transition matrix.
gsl_matrix_uint * getGridMemMatrix(const gsl_matrix *, const gsl_matrix *, const Grid *)
Get membership matrix from initial and final states for a grid.
gsl_matrix_uint * memVector2memMatrix(const gsl_vector_uint *, size_t)
Get the grid membership matrix from the membership vector for a given lag.
int printInitDist(const char *, const char *)
Print initial distribution to file.
std::vector< tripletUInt > tripletUIntVector
STD vector of Eigen triplet of integer.
int getBoxMembership(const gsl_vector *, const Grid *)
Get membership to a grid box of a single realization.
Grid(gsl_vector_uint *nx_)
Constructor allocating an empty grid.
void Eigen2Compressed(FILE *, const SpMatCSC *, const char *)
Print an Eigen CSC matrix to file in compressed format.
Definition: atio.hpp:137
size_t N
Size of the grid.
Grid class.
gsl_vector_uint * nx
void normalizeVector(gsl_vector *)
Normalize a GSL vector by the sum of its elements.
Definition: atmatrix.hpp:222
int printGrid(const char *, const char *, bool)
Print the grid to file.