Skip to content

Commit

Permalink
initial commit -- first working version
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomas Stary authored and Tomas Stary committed Apr 14, 2016
0 parents commit a4dc8bb
Show file tree
Hide file tree
Showing 6 changed files with 271 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
all: inaEigenLAPACK
CC=gcc -g
INC=/usr/include/
LIB=-llapacke -llapack -lm

%LAPACK: %LAPACK.c inaEigen.h clancy_rates.h clancy_markov.h
$(CC) -Wall -I$(INC)/lapacke/ $(LIB) $< -o $@
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# mc-eigen-lapack

## Description

This program computes eigenvalues of a transition rates matrix
corresponding to a Markov chain model and saves them into the files.

* `vm_INa_LAPACK.dat` : grid of membrane voltage
* `evals_INa_LAPACK.dat` : eigenvalues
* `left_evecs_INa_LAPACK.dat` : left eigenvector matrix
* `right_evecs_INa_LAPACK.dat` : right eigenvector matrix

Those
files can be then used for the exponential integration from a cellular
model of the Markov Chain matrix using Matrix Rush-Larsen method.

## Dependencies

This program requires [C compiler](http://www.gnu.org/software/gcc/)
and [LAPACK](http://www.netlib.org/lapack/) with the LAPACKe API for
C.

Optionally [Make](https://www.gnu.org/software/make/) for a simple
compilation by `make`.


## Compilation

The program is compiled by a command

```
gcc -Wall -I/usr/include/lapacke/ -llapacke -llapack -lm inaEigenLAPACK -o inaEigenLAPACK
```

## Running

Run the program by a command: ` ./inaEigenLAPACK ` which creates files
in the same directory where it is run. You can refer to those files
from the cellular model.

## License

Free software under [GNU GPLv3](http://www.gnu.org/licenses/gpl.txt).
96 changes: 96 additions & 0 deletions inaEigen.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
* Copyright 2015 Vadim Biktashev, Tomas Stary
*
* Free software under GNU GPLv3.
* See <http://www.gnu.org/licenses/>.
*/

/* voltage range */
#define VMIN -100.0
#define DV 0.01
#define VMAX 70.0

/* file with values of voltage */
#define FVM "vm_INa_%s.dat"
/* file with eigen values */
#define FEVINA "evals_INa_%s.dat"
/* file with left eigenvectors */
#define FLEVINA "left_evecs_INa_%s.dat"
/* file with right eigenvectors */
#define FREVINA "right_evecs_INa_%s.dat"

#define ERROR(msg){fprintf(stderr,msg);exit(1);}
#define CALLOC(p,a,b) if(0==(p=calloc(a,b)))ERROR("not enough memory\n")
#define MAKE_ARRAY(type, name, length) type * name; CALLOC(name, length, sizeof(type));
#define OPEN_FILE(fileid, name,suffix) \
FILE * fileid; \
sprintf(filename,name,suffix); \
if ( ( fileid = fopen(filename,"w")) == NULL){ \
fprintf(stderr,"Error while openning the file: %s.\n",filename); \
exit(1);}
#define WRITE_EVAL(fileid, dimension, eval_Re, eval_Im) { \
int ii; \
for( ii = 0; ii < dimension; ii++ ) { \
if( eval_Im[ii] == (double)0.0 ) { \
fprintf(fileid, " %.10e", eval_Re[ii] ); \
} else { \
ERROR("The imaginary part is not zero.\n"); \
/* fprintf(fileid, "(%.10e,%10e)", eval_Re[ii], eval_Im[ii] ); */ \
} \
/* separators */ \
(ii < (dimension-1))? fprintf(fileid, "\t"): fprintf(fileid,"\n"); \
} \
}
#define WRITE_EVEC(fileid, dimension, eval_Im, evec) { \
int ii, jj; \
for( jj = 0; jj < dimension; jj++ ) { \
ii = 0; \
while( ii < dimension ) { \
if( eval_Im[ii] == (double)0.0 ) { \
fprintf(fileid, "%.10e", evec[jj*dimension+ii] ); \
ii++; \
} else { \
ERROR("The imaginary part is not zero.\n"); \
/* fprintf(fileid, "(%.10e,%.10e)", evec[jj*dimension+ii], evec[jj*dimension+(ii+1)] ); */ \
/* fprintf(fileid, "(%.10e,%.10e)", evec[jj*dimension+ii], -evec[jj*dimension+(ii+1)] ); */ \
/* ii += 2; */ \
} \
/* separators */ \
((jj*dimension+ii) < (dimension*dimension) )? fprintf(fileid, "\t"): fprintf(fileid,"\n"); \
} \
} \
}

/* Enumerate the markov chain states */
enum
{
#define _(n,i) markov_##n,
#include "ina_markov.h"
#undef _
DIM /* total number of Markov variables */
};

void
ina_trans_rates_matrix(double V, double *tr)
{
/* Updates the transition rates matrix of INa Markov chain model
published by Clancy, Rudy (2002) */
/* input variables: V -- membrane voltage; tr -- pointer to the
matrix */
int i;
for (i=0; i<DIM*DIM; i++)
{
/* reset entries */
tr[i]=0;
}
/* recompute the tr matrix for new value of V */
#define _VFUN(name,expression) double name=expression;
#define _RATE(from,to,direct,reverse) \
tr[markov_##to*DIM+markov_##from]=direct; \
tr[markov_##from*DIM+markov_##from]-=direct; \
tr[markov_##from*DIM+markov_##to]=reverse; \
tr[markov_##to*DIM+markov_##to]-=reverse;
#include "ina_rates.h"
#undef _VFUN
#undef _RATE
}
86 changes: 86 additions & 0 deletions inaEigenLAPACK.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* Copyright 2015 Vadim Biktashev, Tomas Stary
*
* Free software under GNU GPLv3.
* See <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <lapacke.h>
#include <math.h>
#include "inaEigen.h"

/* dimension of the system */
#define LDA DIM
#define LDVL DIM
#define LDVR DIM

int
main (int argc, const char * argv[] )
{
/* initialize lapack variables */
/* ld stands for leading dimension of an array -- for example it
would be 20 for an array (20, 10) */
const int n = DIM, lda = LDA, ldvl = LDVL, ldvr = LDVR;
int lapack_exit_status;

/****************************************/
/* create array and allocate the memory */
/* transition rates matrix of INa */
MAKE_ARRAY(double, trans_rates_matrix, DIM*DIM);
/* real part of eigenvalues */
MAKE_ARRAY(double, eval_real, DIM);
/* imaginary part of eigenvalues */
MAKE_ARRAY(double, eval_imag, DIM);
/* left eigenvectors */
MAKE_ARRAY(double, evec_left, LDVL*DIM);
/* right eigenvectors */
MAKE_ARRAY(double, evec_right, LDVR*DIM);

/**********************************************/
/* create pointers and open the output files */
MAKE_ARRAY(char, filename, 64); /* name of output file */
OPEN_FILE(fvolt, FVM, "LAPACK"); /* file for voltage */
OPEN_FILE(feval, FEVINA, "LAPACK"); /* file for eigenvalues */
OPEN_FILE(fevec_left, FLEVINA, "LAPACK"); /* file for left eigenvectors */
OPEN_FILE(fevec_right, FREVINA, "LAPACK"); /* file for right eigenvectors */
free(filename);

/* membrane potential in mV */
double volt;
/* number of voltage steps */
const int volt_steps_N = (( VMAX - VMIN )/DV);

int i;
for (i = 0;i <= volt_steps_N;i++ )
{/* Membrane potential loop */
/* get membrane potential */
volt = VMIN+i*DV;
/* get transition rates matrix */
ina_trans_rates_matrix(volt, trans_rates_matrix);
/* calculate the eigenvalues and right and left eigenvectors */
lapack_exit_status =
LAPACKE_dgeev(LAPACK_ROW_MAJOR, 'V', 'V', n, trans_rates_matrix,
lda, eval_real, eval_imag, evec_left, ldvl, evec_right, ldvr);
/* Check for convergence */
if( lapack_exit_status != 0 ) ERROR( "The algorithm failed to compute eigenvalues.\n" );
/* write results */
fprintf(fvolt, "%.2f\n", volt);
WRITE_EVAL(feval, n, eval_real, eval_imag);
WRITE_EVEC(fevec_left, n, eval_imag, evec_left);
WRITE_EVEC(fevec_right, n, eval_imag, evec_right);
} /* end of membrane potential loop */
/* free memory */
free(trans_rates_matrix);
free(eval_imag);
free(evec_left);
free(evec_right);

/* close files */
fclose(fvolt);
fclose(feval);
fclose(fevec_left);
fclose(fevec_right);

return 0;
}
12 changes: 12 additions & 0 deletions ina_markov.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* ina mc states */
_(O,4.38587098159465e-08)
_(C1,5.32914708198526e-05)
_(C2,0.010642045025986)
_(C3,0.801808970977337)
_(IC3,0.143555231208206)
_(IC2,0.00190739109198479)
_(IC1,1.11107023501962e-05)
_(IM1,0.000841692031966022)
_(IM2,0.041180223632675)
/* impose state conservation law */
/* _(IM1,1-(O+C1+C2+C3+IC3+IC2+IC1+IM2)) */
27 changes: 27 additions & 0 deletions ina_rates.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* Transition rates from Clancy, Rudy (2002) */
_VFUN(alpha11,3.802/(0.1027*exp(-V/17.0)+0.20*exp(-V/150.))) /* C3->C2 (R->Q); IC3->IC2 (S->T) */
_VFUN(alpha12,3.802/(0.1027*exp(-V/15.0)+0.23*exp(-V/150.))) /* C2->C1 (Q->P); IC2->IF (T->U) */
_VFUN(alpha13,3.802/(0.1027*exp(-V/12.0)+0.25*exp(-V/150.))) /* C1->O (P->O) */
_VFUN(beta11,0.1917*exp(-V/20.3)) /* C2->C3 (Q->R); C2->C3 (T->S) */
_VFUN(beta12,0.20*exp(-(V-5)/20.3)) /* C1->C2 (P->Q); C1->C2 (U->T) */
_VFUN(beta13,0.22*exp(-(V-10)/20.3)) /* O->C1 (O->P) */
_VFUN(alpha3,3.7933e-7*exp(-V/7.7)) /* IF->C1 (U->P); IC2->C2 (T->Q); IC3->C3 (S->R) */
_VFUN(beta3,8.4e-3+2e-5*V) /* C1->IF (P->U); C2->IC2 (Q->T); C3->IC3 (R->S) */
_VFUN(alpha2,9.178*exp(V/29.68)) /* O->IF (O->U) */
_VFUN(beta2,(alpha13*alpha2*alpha3)/(beta13*beta3)) /* IF->O (U->O) */
_VFUN(alpha4,alpha2/100.) /* IF->IM1 (U->V) */
_VFUN(beta4,alpha3) /* IM1->IF (V->U) */
_VFUN(alpha5,alpha2/(9.5e4)) /* IM1->IM2 (V->W) */
_VFUN(beta5,alpha3/50.) /* IM2->IM1 (W->V) */

_RATE(O,C1,beta13,alpha13)
_RATE(C1,C2,beta12,alpha12)
_RATE(C2,C3,beta11,alpha11)
_RATE(C3,IC3,beta3,alpha3)
_RATE(IC3,IC2,alpha11,beta11)
_RATE(IC2,IC1,alpha12,beta12)
_RATE(IC1,IM1,alpha4,beta4)
_RATE(IM1,IM2,alpha5,beta5)
_RATE(IC2,C2,alpha3,beta3)
_RATE(IC1,C1,alpha3,beta3)
_RATE(IC1,O,beta2,alpha2)

0 comments on commit a4dc8bb

Please sign in to comment.