CWaveKernel.c

 /* CardioWave - main kernel routines */

 /* Copyright John B. Pormann, 21 July 2000, all rights reserved */



 #include "CardioWave.h"
 #include <signal.h>

 #if defined(CWAVEARCH_Linux)
 #  include <unistd.h>
 #  include <sys/types.h>
 #  define _use_procstat
 #elif defined(CWAVEARCH_AIX) || defined(CWAVEARCH_SunOS)
 #  include <sys/resource.h>
 #  define _use_getrusage
 #elif defined(CWAVEARCH_Darwin)
 #  include <malloc.h>
 #  define _use_mallocstat
 #else
 #  include <unistd.h>
 #  define _use_sbrk
 #endif

 void CatchSignal( int i );

 int  NumPEs = 1, SelfPE = 0;
 int  DebugLevel = 0;
 logical LoadState  = false;
 logical SaveState  = false;
 logical CheckpointState = false;
 logical UseAuxvars = false;
 FILE*   FpResources  = NULL;
 real Beta = 2000.0;
 real Cm   = 1.0;
 char* LoadStateFilename = NULL;
 char* SaveStateFilename = NULL;
 char* CheckpointFilename = NULL;

 int   NumMem = 1;
 int   (*FunctionTable[MAX_MEMBRANE])();
 void  (*SetpatchTable[MAX_MEMBRANE])();
 int   PatchSize[MAX_MEMBRANE];
 int   AuxiliarySize[MAX_MEMBRANE];
 int   MemParamSize[MAX_MEMBRANE];

 logical NeedVolume    = false;
 logical NeedInvVolume = false;

 bvector NodeType   = _INIT_VECTOR;
 vector  Volume     = _INIT_VECTOR;
 vector  InvVolume  = _INIT_VECTOR;
 vector  Workspace  = _INIT_VECTOR;
 vector  MemParams  = _INIT_VECTOR;
 sparse  MatrixINT  = _INIT_SPARSE;
 sparse  MatrixEXT  = _INIT_SPARSE;
 sparse  MatrixBATH = _INIT_SPARSE;
 sparse  MatrixE2B  = _INIT_SPARSE;
 sparse  MatrixB2E  = _INIT_SPARSE;

 int    TissueGlobalSize = 0, TissueLocalSize = 0;
 int    BathGlobalSize = 0, BathLocalSize = 0;
 int    SolverGlobalSize = 0, SolverLocalSize = 0;
 int    StateGlobalSize = 0, StateLocalSize = 0;
 int    AuxiliaryGlobalSize = 0, AuxiliaryLocalSize = 0;
 int    MemparamGlobalSize = 0, MemparamLocalSize = 0;
 int*   TissueSplit;
 int*   BathSplit;
 int*   SolverSplit;
 int*   StateSplit;
 int*   AuxiliarySplit;
 int*   MemparamSplit;

 static char* RCSID = "$Id: CWaveKernel.c,v 1.18 2005/05/18 21:29:22 john Exp $";

 static char  CkptVmFile?[MAX_FILENAME],CkptVmTemp?[MAX_FILENAME];
 static char  CkptViFile?[MAX_FILENAME],CkptViTemp?[MAX_FILENAME];
 static char  CkptVeFile?[MAX_FILENAME],CkptVeTemp?[MAX_FILENAME];
 static char  CkptVbFile?[MAX_FILENAME],CkptVbTemp?[MAX_FILENAME];
 static char  CkptQFile?[MAX_FILENAME],CkptQTemp?[MAX_FILENAME];
 static int   CheckpointInterval? = -1;
 static int   CkptMsgTag?;

 static char* InitCondFileVm? = NULL;
 static char* InitCondFile?[MAX_PATCHSIZE];

 static int   CW_SignalRecvd = 0;
 static int   CW_NumTsteps = 0;
 static int   CW_SignalTime = 999999;
 static MPI_Comm SignalComm?;

 static char* MemparamFile? = NULL;

 static int NextTagNum? = 1;

 static rword resources[] = {
 	{ "auxvar",	9044 },
 	{ "auxvars",	9044 },
 	{ "beta",	9010 },
 	{ "catchsig",	9099 },
 	{ "catchsignal",9099 },
 	{ "checkpoint",	9100 },
 	{ "checkpointfile", 9101 },
 	{ "checkpointinterval", 9102 },
 	{ "ckpt",	9100 },
 	{ "ckptfile",	9101 },
 	{ "ckptint",	9102 },
 	{ "ckptinterval", 9102 },
 	{ "cm",		9011 },
 	{ "debug",	9002 },
 	{ "debuglevel",	9002 },
 	{ "loadfile",   9040 },
 	{ "loadstate",	9030 },
 	{ "memfile",	9033 },
 	{ "memparam",	9033 },
 	{ "memparamfile", 9033 },
 	{ "savefile",	9041 },
 	{ "savestate",  9031 },
 	{ "statefile",	9021 },
 	{ "statfile",	9021 },
 	{ "statusfile",	9021 },
 	{ "useauxvar",	9044 },
 	{ "useauxvars",	9044 },
 	{ "initvm",	9201 },
 	{ "initialvm",	9201 },
 	{ "initcondvm",	9201 },
 	{ "initcondfilevm", 9201 },
 	{ "initcondvmfile", 9201 },
 	{ "initialconditionvm", 9201 },
 	{ "initcond",	9200 },
 	{ "initcondfile", 9200 },
 	{ "initialcondition", 9200 },
 	{ NULL, 0 }
 };

 int InitSimulation( char** res ) {
 	int i;
 	int max_npes = -1;
 	int cmd,num;
 	char fname[MAX_FILENAME];
 	char* av[2] = { NULL, NULL };
 	char* statefilename = NULL;
 	logical catchsig = false;

 	InitCondFileVm? = NULL;
 	for(i=0;i<MAX_PATCHSIZE;i++) {
 		InitCondFile?[i] = NULL;
 	}

 	/* go through resource list and look for word/val pairs */
 	i = 0;
 	while( res[i] != NULL ) {
 		cmd = FindCommand( resources, res[i] );
 		switch( cmd ) {
 			case 9002:
 				DebugLevel = GetIntValue( res[i] );
 				break;
 			case 9010:
 				Beta = GetRealValue( res[i] );
 				break;
 			case 9011:
 				Cm = GetRealValue( res[i] );
 				break;
 			case 9021:
 				statefilename = GetStringValue( res[i] );
 				break;
 			case 9030:
 				LoadState = GetTFValue( res[i] );
 				break;
 			case 9031:
 				SaveState = GetTFValue( res[i] );
 				break;
 			case 9033:
 				MemparamFile? = GetStringValue( res[i] );
 				break;
 			case 9040:
 				LoadStateFilename = GetStringValue( res[i] );
 				break;
 			case 9041:
 				SaveStateFilename = GetStringValue( res[i] );
 				break;
 			case 9044:
 				UseAuxvars = GetTFValue( res[i] );
 				break;
 			case 9099:
 				catchsig = GetTFValue( res[i] );
 				break;
 			case 9100:
 				CheckpointState = GetTFValue( res[i] );
 				break;
 			case 9101:
 				CheckpointFilename = GetStringValue( res[i] );
 				break;
 			case 9102:
 				CheckpointInterval? = GetIntValue( res[i] );
 				break;
 			case 9200:
 				num = FindNum( res[i] );
 				InitCondFile?[num] = GetStringValue( res[i] );
 				break;
 			case 9201:
 				InitCondFileVm? = GetStringValue( res[i] );
 				break;
 		}
 		i++;
 	}

 	/* see who we are */
 	MPI_Comm_size( MPI_COMM_WORLD, &NumPEs );
 	MPI_Comm_rank( MPI_COMM_WORLD, &SelfPE );

 	/* create a duplicate communicator so that signal processing */
 	/* does not interfere with normal processing */
 	/* : only create this if needed ... to allow use if MP_Lite */
 	if( CheckpointState ) {
 		MPI_Comm_dup( MPI_COMM_WORLD, &SignalComm? );
 	}

 	if( (LoadStateFilename==NULL) and (statefilename!=NULL) ) {
 		LoadStateFilename = statefilename;
 	}
 	if( (SaveStateFilename==NULL) and (statefilename!=NULL) ) {
 		SaveStateFilename = statefilename;
 	}
 	if( (CheckpointFilename==NULL) and (statefilename!=NULL) ) {
 		CheckpointFilename = statefilename;
 	}

 	if( SaveState or CheckpointState or catchsig ) {
 		/* attach to the CPU Time Limit signal(s) */
 		#if defined(SIGCPULIM)
 			signal( SIGCPULIM, CatchSignal );
 		#endif
 		#if defined(SIGXCPU)
 			signal( SIGXCPU, CatchSignal );
 		#endif
 		/* also catch the terminate/quit/interrupt signals */
 		signal( SIGTERM, CatchSignal );
 		signal( SIGINT, CatchSignal );
 		signal( SIGQUIT, CatchSignal );
 		/* NOTE: MPICH uses SIGUSR1?, so we can't touch it */
 		signal( SIGUSR2?, CatchSignal );
 	}

 	if( SaveState or CheckpointState ) {
 		/* reopen file for possible restart of this run */
 		if( SelfPE == 0 ) {
 			FpResources = fopen( "restart.in", "a" );
 		} else {
 			FpResources = NULL;
 		}
 	}

 	CkptMsgTag? = NextMsgTag();
 	if( CheckpointState ) {
 		/* : Vm first */
 		strncpy( CkptVmFile?, CheckpointFilename, MAX_FILENAME );
 		strcat(  CkptVmFile?, ".vm.vec" );
 		strncpy( CkptVmTemp?, CheckpointFilename, MAX_FILENAME );
 		strcat(  CkptVmTemp?, ".vm_tmp.vec" );

 		/* : Ve/Vi/Vb next */
 		strncpy( CkptViFile?, CheckpointFilename, MAX_FILENAME );
 		strcat(  CkptViFile?, ".vi.vec" );
 		strncpy( CkptViTemp?, CheckpointFilename, MAX_FILENAME );
 		strcat(  CkptViTemp?, ".vi_tmp.vec" );
 		strncpy( CkptVeFile?, CheckpointFilename, MAX_FILENAME );
 		strcat(  CkptVeFile?, ".ve.vec" );
 		strncpy( CkptVeTemp?, CheckpointFilename, MAX_FILENAME );
 		strcat(  CkptVeTemp?, ".ve_tmp.vec" );
 		strncpy( CkptVbFile?, CheckpointFilename, MAX_FILENAME );
 		strcat(  CkptVbFile?, ".vb.vec" );
 		strncpy( CkptVbTemp?, CheckpointFilename, MAX_FILENAME );
 		strcat(  CkptVbTemp?, ".vb_tmp.vec" );

 		/* : Q last */
 		strncpy( CkptQFile?, CheckpointFilename, MAX_FILENAME );
 		strcat(  CkptQFile?, ".q.vec" );
 		strncpy( CkptQTemp?, CheckpointFilename, MAX_FILENAME );
 		strcat(  CkptQTemp?, ".q_tmp.vec" );
 	}

 	if( (DebugLevel>0) and (SelfPE==0) ) {
 		printf("CardioWave: debug=c, save=c/c\n",
 			DebugLevel,
 			(LoadState?'Y':'N'),(SaveState?'Y':'N'),
 			(CheckpointState?'Y':'N'),CheckpointInterval?,
 			(UseAuxvars?'Y':'N') );
 		if( DebugLevel > 1 ) {
 			printf("CWaveKernel?: RCSID: %s\n",RCSID);
 		}
 	}

 	return( 0 );
 }

 void ExitSimulation( vector Vm, vector Vx, vector Q, vector Av ) {
 	char  fname[MAX_FILENAME];
 	vector vtmp;

 	if( SaveState ) {
 		/* dump state information */

 		/* : Vm first */
 		strncpy( fname, SaveStateFilename, MAX_FILENAME );
 		strcat(  fname, ".vm.vec" );
 		vecwrite( fname, Vm );

 		/* : Ve/Vi/Vb next */
 		if( (SimType==FullBidomain?) or (SimType==FullBidomainBath?) ) {
 			strncpy( fname, SaveStateFilename, MAX_FILENAME );
 			strcat(  fname, ".vi.vec" );
 			AliasVxVi( Vx, &vtmp );
 			vecwrite( fname, vtmp );
 		}
 		if( SimType != Monodomain ) {
 			strncpy( fname, SaveStateFilename, MAX_FILENAME );
 			strcat(  fname, ".ve.vec" );
 			AliasVxVe( Vx, &vtmp );
 			vecwrite( fname, vtmp );
 		}
 		if( (SimType==ReducedBidomainBath?) 
 		    or (SimType==FullBidomainBath?) ) {
 			strncpy( fname, SaveStateFilename, MAX_FILENAME );
 			strcat(  fname, ".vb.vec" );
 			AliasVxVb( Vx, &vtmp );
 			vecwrite( fname, vtmp );
 		}

 		/* : Q last */
 		if( StateGlobalSize != 0 ) {
 			strncpy( fname, SaveStateFilename, MAX_FILENAME );
 			strcat(  fname, ".q.vec" );
 			vecwrite( fname, Q );
 		}

 		/* : MemParams too ? */
 		if( MemparamGlobalSize != 0 ) {
 			strncpy( fname, SaveStateFilename, MAX_FILENAME );
 			strcat(  fname, ".mp.vec" );
 			vecwrite( fname, MemParams );
 		}

 		/* note that this will be the LAST function called */
 		if( SelfPE == 0 ) {
 			fclose( FpResources );
 		}
 	}

 	return;
 }

 int Checkpoint( real t, vector Vm, vector Vx, vector Q, vector Av ) {
 	static int count = 1;
 	vector Vi,Ve,Vb;
 	int e;

 	/* was a signal caught? */
 	if( CW_SignalRecvd == SIGUSR2? ) {
 		/* force an early checkpoint */
 		if( CW_NumTsteps >= CW_SignalTime ) {
 			count = CheckpointInterval?;
 			CW_SignalRecvd = 0;
 		}
 	} else if( CW_SignalRecvd != 0 ) {
 		/* force an early exit */
 		if( CW_NumTsteps >= CW_SignalTime ) {
 			return( -1 );
 		}
 	}
 	CW_NumTsteps++;

 	if( CheckpointState ) {
 		if( count >= CheckpointInterval? ) {
 			/* first, we'll hit a barrier to make */
 			/* sure everyone is still alive       */
 			e = MPI_Barrier( SignalComm? );
 			if( e < 0 ) {
 				return( -100 );
 			}

 			/* initially, we write to temp files */
 			vecwrite( CkptVmTemp?, Vm );

 			if( (SimType==FullBidomain?) 
 			    or (SimType==FullBidomainBath?) ) {
 				AliasVxVi( Vx, &Vi );
 				vecwrite( CkptViTemp?, Vi );
 			}
 			if( SimType != Monodomain ) {
 				AliasVxVe( Vx, &Ve );
 				vecwrite( CkptVeTemp?, Ve );
 			}
 			if( (SimType==ReducedBidomainBath?)
 			    or (SimType==FullBidomainBath?) ) {
 				AliasVxVb( Vx, &Vb );
 				vecwrite( CkptVbTemp?, Vb );
 			}

 			if( StateGlobalSize > 0 ) {
 				vecwrite( CkptQTemp?, Q );
 			}

 			/* now, we can rename the files */
 			if( SelfPE == 0 ) {
 				rename( CkptVmTemp?, CkptVmFile? );
 				if( (SimType==FullBidomain?)
 				    or (SimType==FullBidomainBath?) ) {
 					rename( CkptViTemp?, CkptViFile? );
 				}
 				if( SimType != Monodomain ) {
 					rename( CkptVeTemp?, CkptVeFile? );
 				}
 				if( (SimType==ReducedBidomainBath?)
 				    or (SimType==FullBidomainBath?) ) {
 					rename( CkptVbTemp?, CkptVbFile? );
 				}
 				if( StateGlobalSize > 0 ) {
 					rename( CkptQTemp?, CkptQFile? );
 				}
 			}

 			/* finally, we write out the time-step that */
 			/* we just completed */
 			if( SelfPE == 0 ) {
 				rewind( FpResources );
 				fprintf( FpResources, "t0=%le\n", t );
 				fflush( FpResources );
 			}

 			count = 1;
 		} else {
 			count++;
 		}
 	}

 	return( 0 );
 }

 int ComputeSizes( char** res ) {
 	int i;
 	byte* nt = NodeType.data;
 	int* itmp;

 	/* allocate space for a work or temporary vector */
 	if( BathLocalSize > TissueLocalSize ) {
 		if( vecalloc(&Workspace,Bath) < 0 ) {
 			return( -8 );
 		}
 	} else {
 		if( vecalloc(&Workspace,Tissue) < 0 ) {
 			return( -9 );
 		}
 	}

 	itmp = (int*)Workspace.data;

 	/* add up the state sizes */
 	StateSplit = (int*)malloc( (NumPEs+1)*sizeof(int) );
 	if( StateSplit == NULL ) {
 		return( -1 );
 	}
 	StateLocalSize = 0;
 	for(i=0;i<TissueLocalSize;i++) {
 		StateLocalSize += PatchSize[ nt[i] ];
 	}
 	MPI_Allgather( &StateLocalSize, 1, MPI_INT, itmp, 
 		1, MPI_INT, MPI_COMM_WORLD );
 	StateGlobalSize = 0;
 	for(i=0;i<NumPEs;i++) {
 		StateSplit[i] = StateGlobalSize;
 		StateGlobalSize += itmp[i];
 	}
 	StateSplit[i] = StateGlobalSize;

 	/* add up the auxiliary sizes */
 	AuxiliarySplit = (int*)malloc( (NumPEs+1)*sizeof(int) );
 	if( AuxiliarySplit == NULL ) {
 		return( -2 );
 	}
 	AuxiliaryLocalSize = 0;
 	for(i=0;i<TissueLocalSize;i++) {
 		AuxiliaryLocalSize += AuxiliarySize[ nt[i] ];
 	}
 	MPI_Allgather( &AuxiliaryLocalSize, 1, MPI_INT, itmp, 
 		1, MPI_INT, MPI_COMM_WORLD );
 	AuxiliaryGlobalSize = 0;
 	for(i=0;i<NumPEs;i++) {
 		AuxiliarySplit[i] = AuxiliaryGlobalSize;
 		AuxiliaryGlobalSize += itmp[i];
 	}
 	AuxiliarySplit[i] = AuxiliaryGlobalSize;

 	/* add up the mem param sizes */
 	MemparamSplit = (int*)malloc( (NumPEs+1)*sizeof(int) );
 	if( MemparamSplit == NULL ) {
 		return( -3 );
 	}
 	MemparamLocalSize = 0;
 	for(i=0;i<TissueLocalSize;i++) {
 		MemparamLocalSize += MemParamSize[ nt[i] ];
 	}
 	MPI_Allgather( &MemparamLocalSize, 1, MPI_INT, itmp, 
 		1, MPI_INT, MPI_COMM_WORLD );
 	MemparamGlobalSize = 0;
 	for(i=0;i<NumPEs;i++) {
 		MemparamSplit[i] = MemparamGlobalSize;
 		MemparamGlobalSize += itmp[i];
 	}
 	MemparamSplit[i] = MemparamGlobalSize;

 	SolverSplit = (int*)malloc( (NumPEs+1)*sizeof(int) );
 	if( SolverSplit == NULL ) {
 		return( -4 );
 	}
 	switch( SimType ) {
 		case Monodomain:
 		case ReducedBidomain?:
 			SolverGlobalSize = TissueGlobalSize;
 			SolverLocalSize = TissueLocalSize;
 			for(i=0;i<(NumPEs+1);i++) {
 				SolverSplit[i] = TissueSplit[i];
 			}
 			break;
 		case FullBidomain?:
 			SolverGlobalSize = 2*TissueGlobalSize;
 			SolverLocalSize = 2*TissueLocalSize;
 			for(i=0;i<(NumPEs+1);i++) {
 				SolverSplit[i] = 2*TissueSplit[i];
 			}
 			break;
 		case ReducedBidomainBath?:
 			SolverGlobalSize = TissueGlobalSize + BathGlobalSize;
 			SolverLocalSize = TissueLocalSize + BathLocalSize;
 			for(i=0;i<(NumPEs+1);i++) {
 				SolverSplit[i] = TissueSplit[i] + BathSplit[i];
 			}
 			break;
 		case FullBidomainBath?:
 			SolverGlobalSize = 2*TissueGlobalSize + BathGlobalSize;
 			SolverLocalSize = 2*TissueLocalSize + BathLocalSize;
 			for(i=0;i<(NumPEs+1);i++) {
 				SolverSplit[i] = 2*TissueSplit[i]
 						+ BathSplit[i];
 			}
 			break;
 	}

 	return( 0 );
 }

 int DomainLocalSize( domain_t dt ) {
         switch( dt ) {
                 case Tissue:
                 case Intra:
                 case Extra:
                         return( TissueLocalSize );
                         break;
                 case Bath:
                         return( BathLocalSize );
                         break;
                 case Solver:
                         return( SolverLocalSize );
                         break;
                 case State:
                         return( StateLocalSize );
                         break;
                 case Aux:
                         return( AuxiliaryLocalSize );
                         break;
 		case Param:
 			return( MemparamLocalSize );
 			break;
         }
         return( -1 );
 }

 int DomainGlobalSize( domain_t dt ) {
         switch( dt ) {
                 case Tissue:
                 case Intra:
                 case Extra:
                         return( TissueGlobalSize );
                         break;
                 case Bath:
                         return( BathGlobalSize );
                         break;
                 case Solver:
                         return( SolverGlobalSize );
                         break;
                 case State:
                         return( StateGlobalSize );
                         break;
                 case Aux:
                         return( AuxiliaryGlobalSize );
                         break;
 		case Param:
 			return( MemparamGlobalSize );
 			break;
         }
         return( -1 );
 }

 int AliasVxVi( vector Vx, vector* Vi ) {
 	switch( SimType ) {
 		case ReducedBidomain?:
 		case ReducedBidomainBath?:
 			Vi->size = 0;
 			Vi->data = NULL;
 			Vi->dtype = Tissue;
 			break;
 		case Monodomain:
 			/* fudge it so that Vi looks like Vm */
 		case FullBidomain?:
 		case FullBidomainBath?:
 			Vi->size = TissueLocalSize;
 			Vi->data = Vx.data;
 			Vi->dtype = Tissue;
 			break;
 	}

 	return( 0 );
 }

 int AliasVxVe( vector Vx, vector* Ve ) {
 	switch( SimType ) {
 		case Monodomain:
 			Ve->size = 0;
 			Ve->data = NULL;
 			Ve->dtype = -1;
 			break;
 		case ReducedBidomain?:
 		case ReducedBidomainBath?:
 			Ve->size = TissueLocalSize;
 			Ve->data = Vx.data;
 			Ve->dtype = Tissue;
 			break;
 		case FullBidomain?:
 		case FullBidomainBath?:
 			Ve->size = TissueLocalSize;
 			Ve->data = Vx.data + TissueLocalSize;
 			Ve->dtype = Tissue;
 			break;
 	}

 	return( 0 );
 }

 int AliasVxVb( vector Vx, vector* Vb ) {
 	switch( SimType ) {
 		case Monodomain:
 		case FullBidomain?:
 		case ReducedBidomain?:
 			Vb->size = 0;
 			Vb->data = NULL;
 			Vb->dtype = -1;
 			break;
 		case FullBidomainBath?:
 			Vb->size = TissueLocalSize;
 			Vb->data = Vx.data + 2*TissueLocalSize;
 			Vb->dtype = Bath;
 			break;
 		case ReducedBidomainBath?:
 			Vb->size = TissueLocalSize;
 			Vb->data = Vx.data + TissueLocalSize;
 			Vb->dtype = Bath;
 			break;
 	}

 	return( 0 );
 }

 /* allocate the vectors and load the initial values */
 int GetInitialValues( vector* Vm, vector* Vx, vector* Q, vector* Av ) {
 	int   i,j,k,r,n;
 	int   status = 0;
 	int   initflag = 0;
 	real* rp;
 	char  fnamevm[MAX_FILENAME];
 	char  fnamevi[MAX_FILENAME];
 	char  fnameve[MAX_FILENAME];
 	char  fnamevb[MAX_FILENAME];
 	char  fnameq[MAX_FILENAME];
 	vector Vi,Ve,Vb;
 	real* wksp;
 	real* qp;
 	byte* nt = NodeType.data;

 	/* allocate or load in the state vectors */
 	if( LoadState ) {
 		/* attempt to load in the state file vectors */
 		/* : load vectors will return a negative indicator on error */
 		/* first, check files to make sure they are correct size */
 		strncpy( fnamevm, LoadStateFilename, MAX_FILENAME );
 		strcat(  fnamevm, ".vm.vec" );
 		r = vecreadinfo( fnamevm, &i );
 		if( (r<0) or (i!=TissueGlobalSize) ) {
 			if( SelfPE == 0 ) {
 				printf("Problems loading vm restart file [%s]\n",
 					fnamevm );
 			}
 			status = -1;
 		}

 		if( SimType != Monodomain ) {
 			strncpy( fnameve, LoadStateFilename, MAX_FILENAME );
 			strcat(  fnameve, ".ve.vec" );
 			r = vecreadinfo( fnameve, &i );
 			if( (r<0) or (i!=TissueGlobalSize) ) {
 			  if( SelfPE == 0 ) {
 				printf("Problems loading ve restart file [%s]\n",
 					fnameve );
 			  }
 			  status = -1;
 			}
 		}
 		if( (SimType==FullBidomain?) or (SimType==FullBidomainBath?) ) {
 			strncpy( fnamevi, LoadStateFilename, MAX_FILENAME );
 			strcat(  fnamevi, ".vi.vec" );
 			r = vecreadinfo( fnamevi, &i );
 			if( (r<0) or (i!=TissueGlobalSize) ) {
 			  if( SelfPE == 0 ) {
 				printf("Problems loading vi restart file [%s]\n",
 					fnamevi );
 			  }
 			  status = -1;
 			}
 		}
 		if( (SimType==ReducedBidomainBath?) 
 		    or (SimType==FullBidomainBath?) ) {
 			strncpy( fnamevb, LoadStateFilename, MAX_FILENAME );
 			strcat(  fnamevb, ".vb.vec" );
 			r = vecreadinfo( fnamevb, &i );
 			if( (r<0) or (i!=BathGlobalSize) ) {
 			  if( SelfPE == 0 ) {
 				printf("Problems loading vb restart file [%s]\n",
 					fnamevb );
 			  }
 			  status = -1;
 			}
 		}
 		if( StateGlobalSize > 0 ) {
 			strncpy( fnameq, LoadStateFilename, MAX_FILENAME );
 			strcat(  fnameq, ".q.vec" );
 			r = vecreadinfo( fnameq, &i );
 			if( (r<0) or (i!=StateGlobalSize) ) {
 			  if( SelfPE == 0 ) {
 				printf("Problems loading q restart file [%s]\n",
 					fnameq );
 			  }
 			  status = -1;
 			}
 		}
 	}

 	/* allocate the vectors */
 	if( vecalloc(Vm,Tissue) < 0 ) {
 		return( -1 );
 	}
 	if( vecalloc(Vx,Solver) < 0 ) {
 		return( -2 );
 	}
 	if( StateGlobalSize > 0 ) {
 		if( vecalloc(Q,State) < 0 ) {
 			return( -3 );
 		}
 	}
 	/* allocate space for the AuxVars? */
 	if( (AuxiliaryGlobalSize>0) and UseAuxvars ) {
 		if( vecalloc(Av,Aux) < 0 ) {
 			return( -4 );
 		}
 	}

 	if( MemparamGlobalSize > 0 ) {
 		if( vecalloc(&MemParams,Memparam) < 0 ) {
 			return( -5 );
 		}
 		r = vecreadinfo( MemparamFile?, &i );
 		if( (r<0) or (i!=MemparamGlobalSize) ) {
 		  for(i=0;i<MAX_MEMBRANE;i++) {
 			if( SetpatchTable[i] != NULL ) {
 				SetpatchTable[i]( Memparam, *Vm, *Q );
 			}
 		  }
 		  if( SelfPE == 0 ) {
 		    if( MemparamFile? != NULL ) {
 		      printf("Problems loading membrane parameter file [%s]\n",
 				MemparamFile? );
 		    } else {
 		      printf("No membrane parameter file given\n");
 		    }
 		    printf("Using modules' Setpatch functions\n");
 		  }
 		} else {
 		  vecread( MemparamFile?, MemParams );
 		  if( SelfPE == 0 ) {
 			printf("Loaded membrane parameters from file\n");
 		  }
 		}
 	}

 	if( LoadState and (status>=0) ) {
 		/* get Vm */
 		vecread( fnamevm, *Vm );

 		/* get Ve & Vi */
 		if( (SimType==FullBidomain?) 
 		    or (SimType==FullBidomainBath?) ) {
 			AliasVxVi( *Vx, &Vi );
 			vecread( fnamevi, Vi );
 		}
 		if( SimType != Monodomain ) {
 			AliasVxVe( *Vx, &Ve );
 			vecread( fnameve, Ve );
 		}
 		if( (SimType==ReducedBidomainBath?)
 		    or (SimType==FullBidomainBath?) ) {
 			AliasVxVb( *Vx, &Vb );
 			vecread( fnamevb, Vb );
 		}

 		/* get Q */
 		if( StateGlobalSize > 0 ) {
 			vecread( fnameq, *Q );
 		}

 		if( (SelfPE==0) and (DebugLevel>0) ) {
 			printf("Loaded initial values from file\n");
 		}
 	} else {
 		/* now call InitPatches?() */
 		for(i=0;i<MAX_MEMBRANE;i++) {
 			if( SetpatchTable[i] != NULL ) {
 				SetpatchTable[i]( Tissue, *Vm, *Q );
 			}
 		}

 		if( (SimType==FullBidomain?) 
 		    or (SimType==FullBidomainBath?) ) {
 			AliasVxVi( *Vx, &Vi );
 			vcopy( *Vm, Vi );
 		}

 		if( (SelfPE==0) and (DebugLevel>0) ) {
 			printf("Computed initial values as resting conditions\n");
 		}
 	}

 	/* now overwrite with any 'initcond[]=file' settings */
 	n = -1;
 	for(i=0;i<MAX_MEMBRANE;i++) {
 		if( PatchSize[i] > n ) {
 			n = PatchSize[i];
 		}
 	}
 	if( InitCondFileVm? ) {
 		if( (SelfPE==0) and (DebugLevel>0) ) {
 		   printf("Overwriting initial voltage with file [%s]\n",
 				InitCondFileVm? );
 		}
 		r = vecreadinfo( InitCondFileVm?, &j );
 		if( (r==0) and (j==TissueGlobalSize) ) {
 			vecread( InitCondFileVm?, Workspace );
 			wksp = Workspace.data;
 			qp = Vm->data;
 			for(k=0;k<TissueLocalSize;k++) {
 				qp[i] = wksp[i];
 				qp++;
 				wksp++;
 			}
 		}
 	}
 	initflag = 0;
 	for(i=0;i<n;i++) {
 		if( InitCondFile?[i] ) {
 			initflag = 1;
 			if( (SelfPE==0) and (DebugLevel>0) ) {
 			   printf("Overwriting state var %d with file [%s]\n",
 					i, InitCondFile?[i] );
 			}
 			r = vecreadinfo( InitCondFile?[i], &j );
 			if( (r==0) and (j==TissueGlobalSize) ) {
 				vecread( InitCondFile?[i], Workspace );
 				wksp = Workspace.data;
 				qp = Q->data;
 				for(k=0;k<TissueLocalSize;k++) {
 					qp[i] = wksp[i];
 					qp += PatchSize[ nt[k] ];
 					wksp += PatchSize[ nt[k] ];
 				}
 			}
 		}
 	} 
 	if( initflag and (SelfPE==0) and (DebugLevel>0) ) {
 		printf("Found %i state vars max\n",n);
 		if( NumMem > 1 ) {
 			printf("Warning: multiple membrane models found [%d]\n",
 				NumMem );
 		}
 	}

 	return( 0 );
 }

 /* GetF is just a loop over the MEM*_GetF functions */
 #ifndef _NEURO
 int GetF( vector Vm, vector Q, vector Fv, vector Fq, vector Av ) {
 	int i,r;

 	r = 0;

 	for(i=0;i<MAX_MEMBRANE;i++) {
 		if( FunctionTable[i] != NULL ) {
 			r |= FunctionTable[i]( Vm, Q, Fv, Fq, Av );
 		}
 	}

 	return( r );
 }
 #endif

 void CatchSignal( int i ) {
 	int max_time;

 	/* since signals are asynchronous, the tasks may be working */
 	/* on different t-steps, so we'll stop at the farthest one  */
 	MPI_Allreduce( &CW_NumTsteps, &max_time, 1, MPI_INT,
 		MPI_MAX, SignalComm? );

 	CW_SignalRecvd = i;
 	CW_SignalTime  = max_time;

 	return;
 }

 int NextMsgTag( void ) {
 	int r = NextTagNum?;
 	NextTagNum?++;
 	return( r );
 }

 int AppendResources( char** res, int ac, char** av ) {
 	FILE* fp;
 	int   i,k,c;
 	long  l;
 	char* buffer;
 	char* ptr;

 	c = NumResources( res );
 	for(i=1;i<ac;i++) {
 		if( (av[i][0]=='-') or (av[i][0]=='+') ) {
 			/* input file */
 			fp = fopen( av[i]+1, "r" );
 			if( fp != NULL ) {
 				/* get file size */
 				l = 0;
 				fseek( fp, l, SEEK_END );
 				l = ftell( fp );
 				/* allocate memory to hold the file */
 				buffer = (char*)malloc( l+1 );
 				/* load file into malloc'd memory */
 				rewind( fp );
 				fread( buffer, 1, l, fp );
 				fclose( fp );
 				buffer[l] = 0;
 				/* parse each line */
 				k = 0;
 				ptr = buffer;
 				while( k < l ) {
 					if( buffer[k] == '\n' ) {
 						buffer[k] = 0;
 						if( (ptr[0]!='#') 
 						  and (ptr[0]!='%') 
 						  and (ptr[0]!='!')
 						  and (ptr[0]!='/')
 						  and (ptr[0]!=0) ) {
 							res[c] = ptr;
 							c++;
 						}
 						/* set up for next one */
 						ptr = buffer+k+1;
 					} else if( (buffer[k]=='\\') 
 						   and (buffer[k+1]=='\n') ) {
 						/* catenate with */
 						/* previous line */
 						buffer[k] = ' ';
 						buffer[k+1] = ' ';
 					}
 					k++;
 				}
 				/* check to see if we forgot to put a return */
 				/* after the last line of the input file     */
 				if( ptr[0] != 0 ) {
 					res[c] = ptr;
 					c++;
 				}
 			} else {
 				printf("Error opening file %s\n",av[i]+1);
 			}
 		} else {
 			/* resource spec:  stuff=value */
 			res[c] = av[i];
 			c++;
 		}
 	}
 	res[c] = NULL;

 	return( 0 );
 }

 int NumResources( char** res ) {
 	int i;

 	i = 0;
 	while( res[i] != NULL ) {
 		i++;
 	}

 	return( i );
 }

 int NumWords( rword* list ) {
 	int i;

 	i = 0;
 	while( list[i].txt != NULL ) {
 		i++;
 	}

 	return( i );
 }

 real GetRealValue( char* txt ) {
 	int i;

 	/* move to the equals sign */
 	i = 0;
 	while( txt[i] != '=' ) {
 		i++;
 	}

 	if( txt[i] == 0 ) {
 		return( -9.9e9 );
 	}
 	/* note that spaces will be ignored by atof */
 	return( atof(txt+i+1) );
 }

 int GetIntValue( char* txt ) {
 	int i;

 	/* move to the equals sign */
 	i = 0;
 	while( txt[i] != '=' ) {
 		i++;
 	}
 	/* note that spaces will be ignored by atoi */
 	if( txt[i] == 0 ) {
 		return( -1 );
 	}

 	return( atoi(txt+i+1) );
 }

 byte GetByteValue( char* txt ) {
 	int i;
 	byte b;

 	/* move to the equals sign */
 	i = 0;
 	while( txt[i] != '=' ) {
 		i++;
 	}

 	if( txt[i] == 0 ) {
 		return( -1 );
 	}
 	/* note that spaces will be ignored by atoi */
 	b = (byte)(atoi(txt+i+1));
 	return( b );
 }

 logical GetTFValue( char* txt ) {
 	int i;

 	/* move to the equals sign */
 	i = 0;
 	while( txt[i] != '=' ) {
 		i++;
 	}
 	i++;
 	/* skip any spaces */
 	while( (txt[i]==' ') or (txt[i]=='\t') ) {
 		i++;
 	}

 	if( txt[i] == 0 ) {
 		/* this is really an error condition, but no real way */
 		/* to indicate that with only 'true' or 'false'       */
 		return( false );
 	}

 	/* look for the 't' in 'true' or the 'y' in 'yes' */
 	if( (txt[i]=='t') or (txt[i]=='T') or (txt[i]=='1') 
 		or (txt[i]=='y') or (txt[i]=='Y') ) {
 		return( true );
 	}	
 	/* look for the word 'on' */
 	if( (txt[i]=='o') or (txt[i]=='O') ) {
 		if( (txt[i+1]=='n') or (txt[i+1]=='N') ) {
 			return( true );
 		}
 	}

 	return( false );
 }

 int GetNumValues( char* txt ) {
 	int i,j,k,s,nc;
 	char* p;
 	char* cpy;
 	int count;
 	static char* lasttxt   = NULL;
 	static int   lastcount = -1;

 	if( txt == lasttxt ) {
 		return( lastcount );
 	}

 	/* go to the equals sign */
 	i = 0;
 	while( txt[i] != '=' ) {
 		i++;
 	}
 	i++;

 	/* go thru each token in the text */
 	count = 0;
 	cpy = strdup( txt+i );
 	p   = strtok( cpy, "," );
 	while( p != NULL ) {
 		/* look for commas and colons */
 		i = 0;
 		nc = 0;
 		while( p[i] != 0 ) {
 			if( p[i] == ':' ) {
 				if( nc == 0 ) {
 					j = i;
 				} else if( nc == 1 ) {
 					k = i;
 				}
 				nc++;
 			}
 			i++;
 		}
 		switch( nc ) {
 			case 0: /* no colons, just a single number */
 				count++;
 				break;
 			case 1: /* 1 colon, assume unit stride */
 				k = atoi( p+j+1 );
 				j = atoi( p );
 				count += (k-j)+1;
 				break;
 			case 2: /* 2 colon, non-unit stride */
 				k = atoi( p+k+1 );
 				s = atoi( p+j+1 );
 				j = atoi( p );
 				count += ((k-j)/s) + 1;
 				break;
 		}
 		p = strtok( NULL, "," );
 	}

 	lasttxt = txt;
 	lastcount = count;

 	return( count );
 }

 int* GetIntArray( char* txt ) {
 	int  i,j,k,s,nc,l;
 	int* list = NULL;
 	char* p   = NULL;
 	char* cpy = NULL;
 	int count;

 	count = GetNumValues( txt );
 	list = (int*)malloc( count*sizeof(int) );

 	/* go to the equals sign */
 	i = 0;
 	while( txt[i] != '=' ) {
 		i++;
 	}
 	i++;

 	/* go thru each token in the text */
 	count = 0;
 	cpy = strdup( txt+i );
 	p   = strtok( cpy, "," );
 	while( p != NULL ) {
 		/* look for commas and colons */
 		i = 0;
 		nc = 0;
 		while( p[i] != 0 ) {
 			if( p[i] == ':' ) {
 				if( nc == 0 ) {
 					j = i;
 				} else if( nc == 1 ) {
 					k = i;
 				}
 				nc++;
 			}
 			i++;
 		}
 		switch( nc ) {
 			case 0: /* no colons, just a single number */
 				list[count] = atoi( p );
 				count++;
 				break;
 			case 1: /* 1 colon, assume unit stride */
 				k = atoi( p+j+1 );
 				j = atoi( p );
 				for(l=j;l<=k;l++) {
 					list[count] = l;
 					count++;
 				}
 				break;
 			case 2: /* 2 colons, non-unit stride */
 				k = atoi( p+k+1 );
 				s = atoi( p+j+1 );
 				j = atoi( p );
 				for(l=j;l<=k;l+=s) {
 					list[count] = l;
 					count++;
 				}
 				break;
 		}
 		p = strtok( NULL, "," );
 	}

 	return( list );
 }

 real* GetRealArray( char* txt ) {
 	int  i,j,k,s,nc;
 	char* p   = NULL;
 	char* cpy = NULL;
 	int count;
 	real  l;
 	real* list = NULL;

 	count = GetNumValues( txt );
 	list = (real*)malloc( count*sizeof(real) );

 	/* go to the equals sign */
 	i = 0;
 	while( txt[i] != '=' ) {
 		i++;
 	}
 	i++;

 	/* go thru each token in the text */
 	count = 0;
 	cpy = strdup( txt+i );
 	p   = strtok( cpy, "," );
 	while( p != NULL ) {
 		/* look for commas and colons */
 		i = 0;
 		nc = 0;
 		while( p[i] != 0 ) {
 			if( p[i] == ':' ) {
 				if( nc == 0 ) {
 					j = i;
 				} else if( nc == 1 ) {
 					k = i;
 				}
 				nc++;
 			}
 			i++;
 		}
 		switch( nc ) {
 			case 0: /* no colons, just a single number */
 				list[count] = atof( p );
 				count++;
 				break;
 			case 1: /* 1 colon, assume unit stride */
 				k = atof( p+j+1 );
 				j = atof( p );
 				for(l=j;l<=k;l+=1.0) {
 					list[count] = l;
 					count++;
 				}
 				break;
 			case 2: /* 2 colons, non-unit stride */
 				k = atof( p+k+1 );
 				s = atof( p+j+1 );
 				j = atof( p );
 				for(l=j;l<=k;l+=s) {
 					list[count] = l;
 					count++;
 				}
 				break;
 		}
 		p = strtok( NULL, "," );
 	}

 	return( list );
 }

 char* GetStringValue( char* txt ) {
 	int i;

 	i = 0;
 	while( txt[i] != '=' ) {
 		i++;
 	}
 	i++;
 	/* skip any spaces */
 	while( (txt[i]==' ') or (txt[i]=='\t') ) {
 		i++;
 	}

 	if( txt[i] == 0 ) {
 		return( 0 );
 	}

 	return( txt+i );
 }

 int wordcompare( const void* v1, const void* v2 ) {
 	const rword* w1 = (rword*)v1;
 	const rword* w2 = (rword*)v2;

 	return( strcasecmp(w1->txt,w2->txt) );
 }

 int FindCommand( rword* list, char* txt ) {
 	int    i;
 	int    cmd = -1;
 	rword* wf;
 	static char keytxt[128];
 	rword v1,v2;

 	i = 0;
 	while( (txt[i]!='(') and (txt[i]!='[') 
 		and (txt[i]!=':') and (txt[i]!='=') 
 		and (txt[i]!=' ') and (txt[i]!='\t') ) {
 		keytxt[i] = txt[i];
 		i++;
 	}
 	keytxt[i] = 0;

 	wf = list;
 	while( (wf->txt) != NULL ) {
 		i = strcasecmp( wf->txt, keytxt );
 		if( i == 0 ) {
 			/* match found */
 			cmd = wf->cmd;
 			break;
 		} else {
 			wf++;
 		}
 	}

 	return( cmd );
 }

 int FindNum( char* txt ) {
 	int i;

 	/* move forward to a bracket/paren/colon */
 	i = 0;
 	while( (txt[i]!='(') and (txt[i]!='[') 
 		and (txt[i]!=':') and (txt[i]!=0) ) {
 		i++;
 	}
 	if( txt[i] == 0 ) {
 		return( -1 );
 	}
 	i++;

 	if( (txt[i]<'0') or (txt[i]>'9') ) {
 		if( txt[i] < 'a' ) {
 			return( (int)txt[i]+32 );
 		} else {
 			return( (int)txt[i] );
 		}
 	}
 	return( atoi(txt+i) );
 }

 int FindNum2( char* txt ) {
 	int i;

 	/* move forward to a bracket/paren/colon */
 	i = 0;
 	while( (txt[i]!='(') and (txt[i]!='[') 
 		and (txt[i]!=':') and (txt[i]!=0) ) {
 		i++;
 	}
 	if( txt[i] == 0 ) {
 		return( -1 );
 	}
 	i++;
 	/* move forward to the second bracket/paren */
 	i = 0;
 	while( (txt[i]!='(') and (txt[i]!='[') 
 		and (txt[i]!=':') and (txt[i]!=0) ) {
 		i++;
 	}
 	if( txt[i] == 0 ) {
 		return( -1 );
 	}
 	i++;

 	if( (txt[i]<'0') or (txt[i]>'9') ) {
 		if( txt[i] < 'a' ) {
 			return( (int)txt[i]+32 );
 		} else {
 			return( (int)txt[i] );
 		}
 	}
 	return( atoi(txt+i) );
 }

 /* amount of memory used by the program in KB */
 #if defined(_use_sbrk )
 real GetMemUsed( void ) {
 	char* ptr;
 	long  imem;
 	real  mem;

 	ptr = (char*)sbrk(0);
 	imem = (long)(ptr);
 	mem = (real)(imem)/1024.0;

 	return( mem );
 }
 #elif defined(_use_getrusage)
 real GetMemUsed( void ) {
 	struct rusage ru;
 	getrusage( RUSAGE_SELF, &ru );
 	return( (real)(ru.ru_maxrss) );
 }
 #elif defined(_use_procstat)
 real GetMemUsed( void ) {
 	FILE* fp;
 	char buffer[512];
 	int i,c,l;
 	long long npgs;
 	size_t pgsz;

 	pgsz = getpagesize();

 	sprintf( buffer, "/proc/%i/stat", getpid() );
 	fp = fopen( buffer, "r" );
 	fgets( buffer, 512, fp );
 	fclose( fp );

 	npgs = -1;
 	c = 0;
 	for(i=0;i<512;i++) {
 		if( buffer[i] == ' ' ) {
 			l = i;
 			c++;
 			if( c == 23 ) {
 				npgs = atoll( buffer+l+1 );
 			}
 		}
 	}

 	return( (real)(npgs*pgsz)/1024.0 );
 }
 #elif defined(_use_mallocstat)
 real GetMemUsed( void ) {
 	malloc_statistics_t mstat = {0,0,0,0};

 	malloc_zone_statistics( NULL, &mstat );
 	/* convert to KB */
 	mstat.size_allocated >>= 10;

 	return( (real)(mstat.size_allocated) );
 }
 #else
 real GetMemUsed( void ) {
 	return( 0.0 );
 }
 #endif
Edit - History - Print - Recent Changes - Search
Page last modified on November 23, 2009, at 10:06 AM