MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
KinSparseMatrix.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 ** This program is part of 'MOOSE', the
3 ** Messaging Object Oriented Simulation Environment,
4 ** also known as GENESIS 3 base code.
5 ** copyright (C) 2003-2006 Upinder S. Bhalla. and NCBS
6 ** It is made available under the terms of the
7 ** GNU Lesser General Public License version 2.1
8 ** See the file COPYING.LIB for the full notice.
9 **********************************************************************/
10 
11 #include <functional>
12 #include <algorithm>
13 #include <vector>
14 #include <iostream>
15 #include <cassert>
16 #include <cmath>
17 #include "SparseMatrix.h"
18 #include "utility/numutil.h"
19 #include "KinSparseMatrix.h"
20 
21 using namespace std;
22 
29  unsigned int row, const vector< double >& v
30  ) const
31 {
32  assert( nColumns() == 0 || row < nRows() );
33  assert( v.size() == nColumns() );
34  const int* entry = 0;
35  const unsigned int* colIndex = 0;
36  unsigned int numEntries = getRow( row, &entry, &colIndex );
37  const int* end = entry + numEntries;
38 
39  double ret = 0.0;
40  for ( const int* i = entry; i != end; ++i ) {
41  ret += *i * v[ *colIndex++ ];
42  }
43 
44 /*
45  for ( unsigned int i = 0; i < numEntries; ++i ) {
46  ret += entry[i] * v[ colIndex[i] ];
47 
48  }
49 
50  vector< int >::const_iterator i;
51  unsigned int rs = rowStart_[ row ];
52  vector< unsigned int >::const_iterator j = colIndex_.begin() + rs;
53  vector< int >::const_iterator end = N_.begin() + rowStart_[ row + 1 ];
54 
55  double ret = 0.0;
56  for ( i = N_.begin() + rs; i != end; i++ )
57  ret += *i * v[ *j++ ];
58 
59  // assert ( !( ret !<>= 0.0 ) );
60  */
61 
62  assert ( !( std::isnan( ret ) ) );
63  return ret;
64 }
65 
66 
74  unsigned int row, vector< unsigned int >& deps
75 ) const
76 {
77  deps.resize( 0 );
78  // vector< unsigned int > deps;
79  for ( unsigned int i = 0; i < nrows_; ++i ) {
80  // i is index for reac # here. Note that matrix is transposed.
81  unsigned int j = rowStart_[ row ];
82  unsigned int jend = rowStart_[ row + 1 ];
83  unsigned int k = rowStart_[ i ];
84  unsigned int kend = rowStart_[ i + 1 ];
85 
86  while ( j < jend && k < kend ) {
87  if ( colIndex_[ j ] == colIndex_[ k ] ) {
88  /* Pre 28 Nov 2015. Why below zero? Shouldn't it be any?
89  if ( N_[ k ] < 0 ) {
90  deps.push_back( i );
91  }
92  */
93  assert( round( N_[k] ) != 0 );
94  deps.push_back( i );
95  ++j;
96  ++k;
97  } else if ( colIndex_[ j ] < colIndex_[ k ] ) {
98  ++j;
99  } else if ( colIndex_[ j ] > colIndex_[ k ] ) {
100  ++k;
101  } else {
102  assert( 0 );
103  }
104  }
105  }
106 }
107 
113 void KinSparseMatrix::fireReac( unsigned int reacIndex, vector< double >& S, double direction )
114  const
115 {
116  assert( ncolumns_ == S.size() && reacIndex < nrows_ );
117  unsigned int rowBeginIndex = rowStart_[ reacIndex ];
118  // vector< int >::const_iterator rowEnd = N_.begin() + rowStart_[ reacIndex + 1];
119  vector< int >::const_iterator rowBegin =
120  N_.begin() + rowBeginIndex;
121  vector< int >::const_iterator rowEnd =
122  N_.begin() + rowTruncated_[ reacIndex ];
123  vector< unsigned int >::const_iterator molIndex =
124  colIndex_.begin() + rowBeginIndex;
125 
126  for ( vector< int >::const_iterator i = rowBegin; i != rowEnd; ++i ) {
127  double& x = S[ *molIndex++ ];
128  x += *i * direction;
129  x *= (x > 0 );
130  // assert( S[ *molIndex ] + *i * direction >= 0.0 );
131  // S[ *molIndex++ ] += *i * direction;
132  }
133 }
134 
141 void KinSparseMatrix::truncateRow( unsigned int maxColumnIndex )
142 {
143  rowTruncated_.resize( nrows_, 0 );
144  if ( colIndex_.size() == 0 )
145  return;
146  for ( unsigned int i = 0; i < nrows_; ++i ) {
147  unsigned int endCol = rowStart_[ i ];
148  for ( unsigned int j = rowStart_[ i ];
149  j < rowStart_[ i + 1 ]; ++j ) {
150  if ( colIndex_[ j ] < maxColumnIndex ) {
151  endCol = j + 1;
152  } else {
153  break;
154  }
155  }
156  rowTruncated_[ i ] = endCol;
157  }
158 }
159 
160 
161 void makeVecUnique( vector< unsigned int >& v )
162 {
163  vector< unsigned int >::iterator pos = unique( v.begin(), v.end() );
164  v.resize( pos - v.begin() );
165 }
166 
167 
168 #ifdef DO_UNIT_TESTS
169 #include "header.h"
170 
171 void testKinSparseMatrix()
172 {
173  const double EPSILON = 1e-7;
174  // This is the stoichiometry matrix for the unidirectional reacns
175  // coming out of the following system:
176  // a + b <===> c
177  // c + d <===> e
178  // a + f <===> g
179  // a + e <===> 2g
180  //
181  // When halfreac 0 fires, it affects 0, 1, 2, 4, 6.
182  // and so on.
183  static int transposon[][ 8 ] = {
184  { -1, 1, 0, 0, -1, 1, -1, 1 },
185  { -1, 1, 0, 0, 0, 0, 0, 0 },
186  { 1, -1, -1, 1, 0, 0, 0, 0 },
187  { 0, 0, -1, 1, 0, 0, 0, 0 },
188  { 0, 0, 1, -1, 0, 0, -1, 1 },
189  { 0, 0, 0, 0, -1, 1, 0, 0 },
190  { 0, 0, 0, 0, 1, -1, 2, -2 }
191  };
192 
193  cout << "\nTesting KinSparseMatrix" << flush;
194  const unsigned int NR = 4;
195  const unsigned int NC = 5;
196 
197  const unsigned int NTR = 7; // for transposon
198  const unsigned int NTC = 8;
199 
200  KinSparseMatrix sm;
201  sm.setSize( NR, NC );
202 
203  for ( unsigned int i = 0; i < NR; i++ ) {
204  for ( unsigned int j = 0; j < NC; j++ ) {
205  sm.set( i, j, 10 * i + j );
206  // cout << i << ", " << j << ", " << sm.nColumns() << endl;
207  int ret = sm.get( i, j );
208  assert( ret == static_cast< int >( 10 * i + j ) );
209  }
210  }
211  // cout << sm;
212 
213  vector< double > v( 5, 1.0 );
214  double dret = sm.computeRowRate( 0, v );
215  assert( fabs( dret - 10.0 ) < EPSILON );
216  dret = sm.computeRowRate( 1, v );
217  assert( fabs( dret - 60.0 ) < EPSILON );
218  dret = sm.computeRowRate( 2, v );
219  assert( fabs( dret - 110.0 ) < EPSILON );
220  dret = sm.computeRowRate( 3, v );
221  assert( fabs( dret - 160.0 ) < EPSILON );
222 
224  // Checking transposition operation
226  KinSparseMatrix orig;
227  orig.setSize( NTR, NTC );
228  for ( unsigned int i = 0; i < NTR; i++ )
229  for ( unsigned int j = 0; j < NTC; j++ )
230  orig.set( i, j, transposon[ i ][ j ] );
231 
232  for ( unsigned int i = 0; i < NTR; i++ )
233  for ( unsigned int j = 0; j < NTC; j++ )
234  assert( orig.get( i, j ) == transposon[ i ][ j ] );
235 
236  orig.transpose();
237  for ( unsigned int i = 0; i < NTR; i++ )
238  for ( unsigned int j = 0; j < NTC; j++ )
239  assert( orig.get( j, i ) == transposon[ i ][ j ] );
240 
241 
243  // Checking generation of dependency graphs.
245 
246  KinSparseMatrix trans;
247  vector< unsigned int > deps;
248  trans.getGillespieDependence( 0, deps );
249  /*
250  makeVecUnique( deps );
251  ASSERT( deps.size() == 5, "Gillespie dependence" );
252  ASSERT( deps[0] == 0, "Gillespie dependence" );
253  ASSERT( deps[1] == 1, "Gillespie dependence" );
254  ASSERT( deps[2] == 2, "Gillespie dependence" );
255  ASSERT( deps[3] == 4, "Gillespie dependence" );
256  ASSERT( deps[4] == 6, "Gillespie dependence" );
257 
258  trans.getGillespieDependence( 1, deps );
259  makeVecUnique( deps );
260  ASSERT( deps.size() == 5, "Gillespie dependence" );
261  ASSERT( deps[0] == 0, "Gillespie dependence" );
262  ASSERT( deps[1] == 1, "Gillespie dependence" );
263  ASSERT( deps[2] == 2, "Gillespie dependence" );
264  ASSERT( deps[3] == 4, "Gillespie dependence" );
265  ASSERT( deps[4] == 6, "Gillespie dependence" );
266 
267  trans.getGillespieDependence( 2, deps );
268  makeVecUnique( deps );
269  ASSERT( deps.size() == 4, "Gillespie dependence" );
270  ASSERT( deps[0] == 1, "Gillespie dependence" );
271  ASSERT( deps[1] == 2, "Gillespie dependence" );
272  ASSERT( deps[2] == 3, "Gillespie dependence" );
273  ASSERT( deps[3] == 6, "Gillespie dependence" );
274 
275  trans.getGillespieDependence( 4, deps );
276  makeVecUnique( deps );
277  ASSERT( deps.size() == 5, "Gillespie dependence" );
278  ASSERT( deps[0] == 0, "Gillespie dependence" );
279  ASSERT( deps[1] == 4, "Gillespie dependence" );
280  ASSERT( deps[2] == 5, "Gillespie dependence" );
281  ASSERT( deps[3] == 6, "Gillespie dependence" );
282  ASSERT( deps[4] == 7, "Gillespie dependence" );
283 
284  trans.getGillespieDependence( 6, deps );
285  makeVecUnique( deps );
286  ASSERT( deps.size() == 6, "Gillespie dependence" );
287  ASSERT( deps[0] == 0, "Gillespie dependence" );
288  ASSERT( deps[1] == 3, "Gillespie dependence" );
289  ASSERT( deps[2] == 4, "Gillespie dependence" );
290  ASSERT( deps[3] == 5, "Gillespie dependence" );
291  ASSERT( deps[4] == 6, "Gillespie dependence" );
292  ASSERT( deps[5] == 7, "Gillespie dependence" );
293  */
294 }
295 
296 #endif
T get(unsigned int row, unsigned int column) const
Definition: SparseMatrix.h:253
void set(unsigned int row, unsigned int column, T value)
Definition: SparseMatrix.h:161
void makeVecUnique(vector< unsigned int > &v)
const int numEntries
Definition: proc.cpp:60
void transpose()
Definition: SparseMatrix.h:456
void fireReac(unsigned int reacIndex, vector< double > &S, double direction) const
void getGillespieDependence(unsigned int row, vector< unsigned int > &cols) const
double computeRowRate(unsigned int row, const vector< double > &v) const
void setSize(unsigned int nrows, unsigned int ncolumns)
Definition: SparseMatrix.h:126
void truncateRow(unsigned int maxColumnIndex)
#define EPSILON
Definition: MatrixOps.h:28