Domain123.c

 /*	Grid123? Module					*/
 /*							*/
 /*	used for 1,2,3-D domains, especially for	*/
 /*	implicit codes which need storage of the main	*/
 /*	diagonal					*/
 /*							*/
 /*		sigma is in mS/cm			*/
 /*		dx & dy are in cm			*/
 /*		dz or thickness is in cm		*/
 /*		volume is in cm^3 (if used)		*/
 /*							*/
 /*	uses the sparse banded matrix format		*/

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



 #include "CardioWave.h"

 void MakeMatrix( sparse M, domain_t dt, int lsz, int Nd,
         int xd, int yd, int zd,
         real sx, real sy, real sz, real th, real ph,
         real dx, real dy, real dz );

 static real __volume = 1.0;
 static real __invvolume = 1.0;
 static char* RCSID = "$Id: Domain123.c,v 1.5 2004/08/24 18:51:34 jpormann Exp $";

 static rword resources[] = {
 	{ "bathdx",	4111 },
 	{ "bathdy",	4112 },
 	{ "bathdz",	4113 },
 	{ "bathxd",	4101 },
 	{ "bathxdim",	4101 },
 	{ "bathyd",	4102 },
 	{ "bathydim",	4102 },
 	{ "bathzd",	4103 },
 	{ "bathzdim",	4103 },
 	{ "bdx",	4111 },
 	{ "bdy",	4112 },
 	{ "bdz",	4113 },
 	{ "defaultnodetype",	4201 },
 	{ "default_nodetype",	4201 },
 	{ "nodefile",	4200 },
 	{ "dx",		4001 },
 	{ "dy",		4002 },
 	{ "dz",		4003 },
 	{ "scale",	4040 },
 	{ "scalefactor",4040 },
 	{ "scaling",	4040 },
 	{ "sig",	4999 },
 	{ "sigma",	4999 },
 	{ "sigma_0",	4030 },
 	{ "sigma_1",	4031 },
 	{ "sigma_2",	4032 },
 	{ "sigma_x",	4030 },
 	{ "sigma_y",	4031 },
 	{ "sigma_z",	4032 },
 	{ "sigma_th",	4036 },
 	{ "sigma_theta",4036 },
 	{ "sigma_angle",4036 },
 	{ "sigma_ph",	4037 },
 	{ "sigma_phi",	4037 },
 	{ "sigma_int_0",4030 },
 	{ "sigma_int_1",4031 },
 	{ "sigma_int_2",4032 },
 	{ "sigma_int_x",4030 },
 	{ "sigma_int_y",4031 },
 	{ "sigma_int_z",4032 },
 	{ "sigma_int_th",4036 },
 	{ "sigma_int_theta",4036 },
 	{ "sigma_int_angle",4036 },
 	{ "sigma_int_ph",4037 },
 	{ "sigma_int_phi",4037 },
 	{ "sigma_ext_0",4033 },
 	{ "sigma_ext_1",4034 },
 	{ "sigma_ext_2",4035 },
 	{ "sigma_ext_x",4033 },
 	{ "sigma_ext_y",4034 },
 	{ "sigma_ext_z",4035 },
 	{ "sigma_ext_th",4036 },
 	{ "sigma_ext_theta",4038 },
 	{ "sigma_ext_angle",4038 },
 	{ "sigma_ext_ph",4039 },
 	{ "sigma_ext_phi",4039 },
 	{ "sigma_b",	4131 },
 	{ "sigma_bath",	4131 },
 	{ "vol",	4051 },
 	{ "volume",	4051 },
 	{ "xd",		4004 },
 	{ "xdim",	4004 },
 	{ "yd",		4005 },
 	{ "ydim",	4005 },
 	{ "zd",		4006 },
 	{ "zdim",	4006 },
 	{ NULL, 0 }
 };

 int InitDomain( char** res ) {
 	int  i,j;
 	int  cmd;
 	real sex = 1.0, sey = 1.0, sez = 1.0;
 	real six = 1.0, siy = 1.0, siz = 1.0, sss;
 	real theta_int = 0.0, phi_int = 0.0;
 	real theta_ext = 0.0, phi_ext = 0.0;
 	real scale = 1.0;
 	real dx = 1.0, dy = 1.0, dz = 1.0;
 	real volume = 1.0;
 	int  Ndim = 0, Xdim = 1, Ydim = 1, Zdim = 1;
 	int  Flags;
 	int  BathXdim? = 1, BathYdim? = 1, BathZdim? = 1;
 	int  BathBW?;
 	real sb = 1.0, sbx, sby, sbz, sb2;
 	real bdx = 1.0, bdy = 1.0, bdz = 1.0;
 	byte defaultnodetype = ByteError?;
 	char* nodefile = NULL;

 	i = 0;
 	while( res[i] != NULL ) {
 		cmd = FindCommand( resources, res[i] );
 		if( cmd == 4999 ) {
 			/* assume a resource like:	*/
 			/*   sigma[e][y]=1.0		*/
 			/*   sigma(i)=1.0		*/
 			/*   sigma:bath=1.0		*/
 			j = FindNum( res[i] );
 			switch( j ) {
 				case 'E':
 				case 'e':
 					cmd = 4033;
 					break;
 				case 'I':
 				case 'i':
 					cmd = 4030;
 					break;
 				case 'B':
 				case 'b':
 					cmd = 4111;
 					break;
 			}
 			/* FindNum2() will return -1 if no second paren is found */
 			j = FindNum2( res[i] );
 			if( j == 'Y' ) {
 				/* they specified the y-dir conductivity */
 				cmd++;
 			}
 			if( j == 'A' ) {
 				/* they specified the angle for the fiber */
 				cmd += 2;
 			}
 		}
 		switch( cmd ) {
 			case 4001:
 				dx = GetRealValue( res[i] );
 				break;
 			case 4002:
 				dy = GetRealValue( res[i] );
 				break;
 			case 4003:
 				dz = GetRealValue( res[i] );
 				break;
 			case 4004:
 				Xdim = GetIntValue( res[i] );
 				break;
 			case 4005:
 				Ydim = GetIntValue( res[i] );
 				break;
 			case 4006:
 				Zdim = GetIntValue( res[i] );
 				break;
 			case 4030:
 				six = GetRealValue( res[i] );
 				break;
 			case 4031:
 				siy = GetRealValue( res[i] );
 				break;
 			case 4032:
 				siz = GetRealValue( res[i] );
 				break;
 			case 4033:
 				sex = GetRealValue( res[i] );
 				break;
 			case 4034:
 				sey = GetRealValue( res[i] );
 				break;
 			case 4035:
 				sez = GetRealValue( res[i] );
 				break;
 			case 4036:
 				theta_int = GetRealValue( res[i] );
 				break;
 			case 4037:
 				phi_int = GetRealValue( res[i] );
 				break;
 			case 4038:
 				theta_ext = GetRealValue( res[i] );
 				break;
 			case 4039:
 				phi_ext = GetRealValue( res[i] );
 				break;
 			case 4040:
 				scale = GetRealValue( res[i] );
 				break;
 			case 4051:
 				volume = GetRealValue( res[i] );
 				break;
 			/* bath properties */
 			case 4101:
 				BathXdim? = GetIntValue( res[i] );
 				break;
 			case 4102:
 				BathYdim? = GetIntValue( res[i] );
 				break;
 			case 4103:
 				BathZdim? = GetIntValue( res[i] );
 				break;
 			case 4111:
 				bdx = GetRealValue( res[i] );
 				break;
 			case 4112:
 				bdy = GetRealValue( res[i] );
 				break;
 			case 4113:
 				bdz = GetRealValue( res[i] );
 				break;
 			case 4131:
 				sb = GetRealValue( res[i] );
 				break;
 			case 4200:
 				nodefile = GetStringValue( res[i] );
 				break;
 			case 4201:
 				defaultnodetype = GetByteValue( res[i] );
 				break;
 		}
 		i++;
 	}

 	/* set up the system size */
 	Ndim  = (Xdim!=1)+(Ydim!=1)+(Zdim!=1);
 	CreateRegularSplitting( Tissue, Xdim, Ydim, Zdim );

 	/* now create the matrices */
 	i = spralloc( &MatrixINT, Intra, _STENCIL, TissueLocalSize, 
 		TissueLocalSize, 1024 );
 	if( i < 0 ) {
 		return( -1 );
 	}
 	/* create the matrix */
 	MatrixINT.jcoef[0] = Ndim;
 	switch( Ndim ) {
 		case 3: MatrixINT.jcoef[3] = Zdim;
 		case 2: MatrixINT.jcoef[2] = Ydim;
 		case 1: MatrixINT.jcoef[1] = Xdim;
 	}
 	MakeMatrix( MatrixINT, Intra, TissueLocalSize, Ndim, Xdim, Ydim, Zdim,
 		scale*six, scale*siy, scale*siz, theta_int, phi_int,
 		dx, dy, dz );

 	if( SimType != Monodomain ) {
 		i = spralloc( &MatrixEXT, Extra, _STENCIL, 
 			TissueLocalSize, TissueLocalSize, 1024 );
 		if( i < 0 ) {
 			return( -3 );
 		}
 		MatrixEXT.jcoef[0] = Ndim;
 		switch( Ndim ) {
 			case 3: MatrixEXT.jcoef[3] = Zdim;
 			case 2: MatrixEXT.jcoef[2] = Ydim;
 			case 1: MatrixEXT.jcoef[1] = Xdim;
 		}
 		MakeMatrix( MatrixEXT, Extra, TissueLocalSize, Ndim, Xdim,
 			Ydim, Zdim, scale*sex, scale*sey, scale*sez,
 			theta_ext, phi_ext, dx, dy, dz );
 	}

 	if( (SimType==ReducedBidomainBath?) or (SimType==FullBidomainBath?) ) {
 		if( SelfPE == 0 ) {
 			printf("Stencil matrix cannot be used with Bath!\n");
 		}
 		return( -100 );
 	}

 	/* fudge the volume vector */
 	/* : we usually set volume=1 */
 	if( volume < 0.0 ) {
 		volume = 1.0;
 		switch( Ndim ) {
 			case 3:
 				volume *= dz;
 			case 2:
 				volume *= dy;
 			case 1:
 				volume *= dx;
 		}
 	}
 	/* fudge the volume vector */
 	__volume = volume;
 	__invvolume = 1.0/volume;
 	Volume.size  = 1;
 	Volume.dtype = Tissue;
 	Volume.data  = &__volume;
 	InvVolume.size  = 1;
 	InvVolume.dtype = Tissue;
 	InvVolume.data  = &__invvolume;

 	/* now load in the node info */
 	if( nodefile != NULL ) {
 		i = bvecreadinfo( nodefile, &j );
 		if( i < 0 ) {
 			return( -15 );
 		}
 		if( j != TissueGlobalSize ) {
 			return( -16 );
 		}
 	}
 	bvecalloc( &NodeType, Tissue );
 	if( nodefile != NULL ) {
 		bvecread( nodefile, NodeType );
 	} else if( defaultnodetype == ByteError? ) {
 		bvfill( 0, NodeType );
 	} else {
 		bvfill( defaultnodetype, NodeType );
 	}

 	if( (DebugLevel>0) and (SelfPE==0) ) {
 		printf("Domain123?: i x i = %i\n",
 			Ndim, Xdim, Ydim, Zdim, TissueGlobalSize );
 		if( DebugLevel > 1 ) {
 			printf("Domain123?: RCSID: %s\n",RCSID);
 		}
 	}

 	return( 0 );
 }

 void ExitDomain( void ) {
 	return;
 }

 void MakeMatrix( sparse MM, domain_t tp, int localsz, int Ndim, int Xdim, 
 		int Ydim, int Zdim, real sx, real sy, real sz,
 		real th, real ph, real dx, real dy, real dz ) {
 	int  m,g,f,x,y,z;
 	real ssdd,ssd;
 	real mx,my,mz;
 	real RX,RY,RZ,RXY,RXZ,RYZ,sn,cs,sn2,cs2;
 	int  XYdim? = Xdim*Ydim;
 	int  Xd1?   = Xdim-1;
 	int  Yd1?   = Ydim-1;
 	int  Zd1?   = Zdim-1;

 	/* compute the main diagonal term */
 	ssd = 0.0;
 	switch( Ndim ) {
 		case 3: ssd = 0.0;
 			cs  = cos( th );
 			sn  = sin( th );
 			cs2 = cos( ph );
 			sn2 = sin( ph );
 			RX  = ( sx*cs*cs + sy*sn*sn )/dx/dx;
 			RY  = ( sx*cs2*cs2*sn*sn + sy*cs2*cs2*cs*cs
 				+ sz*sn2*sn2 )/dy/dy;
 			RZ  = ( sx*sn2*sn2*sn*sn + sy*sn2*sn2*cs*cs
 				+ sz*cs2*cs2 )/dz/dz;
 			RXY = ( (sy - sx)*cs2*cs*sn )/2.0/dx/dy;
 			RXZ = ( (sx - sy)*sn2*cs*sn )/2.0/dx/dz;
 			RYZ = ( -1.0*sn2*cs2*( sx*sn*sn - sy*cs*cs )
 				+ sz*sn2*cs2 )/2.0/dy/dz;
 			m = XYdim? + Xdim + 1;
 			break;
 		case 2: ssd = 0.0;
 			cs = cos( th );
 			sn = sin( th );
 			RX  = ( sx*cs*cs + sy*sn*sn )/dx/dx;
 			RXY = cs*sn*( sy - sx )/2.0/dx/dy;
 			RY  = ( sx*sn*sn + sy*cs*cs )/dy/dy;
 			m = Xdim + 1;
 			break;
 		case 1: ssd = 0.0;
 			RX = sx/dx/dx;
 			m = 1;
 			break;
 		case 0: ssd = 0.0;
 			m = 0;
 			break;
 	}

 	/* m is the local node number */
 	/* : for Stencil matrices, we fudged it above */
 	/* decompose node number to (x,y,z) */
 	z = 1;
 	y = 1;
 	x = 1;

 		/* in case of 0D domain, we'll set ssdd to 0.0 */
 		ssdd = ssd;

 		/* first dimension */
 		if( Ndim > 0 ) {
 			if( x < Xd1? ) {
 				sprput(MM,m,m+1,RX);
 				ssdd += RX;
 			}
 			if( x > 0 ) {
 				sprput(MM,m,m-1,RX);
 				ssdd += RX;
 			}
 		}

 		/* second dimension */
 		if( Ndim > 1 ) {
 			if( y < Yd1? ) {
 				sprput(MM,m,m+Xdim,RY);
 				ssdd += RY;
 				if( x < Xd1? ) {
 					sprput(MM,m,m+Xdim+1,RXY);
 					ssdd += RXY;
 				}
 				if( x > 0 ) {
 					sprput(MM,m,m+Xdim-1,-RXY);
 					ssdd -= RXY;
 				}
 			}
 			if( y > 0 ) {
 				sprput(MM,m,m-Xdim,RY);
 				ssdd += RY;
 				if( x < Xd1? ) {
 					sprput(MM,m,m-Xdim+1,-RXY);
 					ssdd -= RXY;
 				}
 				if( x > 0 ) {
 					sprput(MM,m,m-Xdim-1,RXY);
 					ssdd += RXY;
 				}
 			}
 		}

 		/* third dimension */
 		if( Ndim > 2 ) {
 			if( z < Zd1? ) {
 				sprput(MM,m,m+XYdim?,RZ);
 				ssdd += RZ;
 				if( y < Yd1? ) {
 					sprput(MM,m,m+XYdim?+Xdim,RYZ);
 					ssdd += RYZ;
 				}
 				if( y > 0 ) {
 					sprput(MM,m,m+XYdim?-Xdim,-RYZ);
 					ssdd -= RYZ;
 				}
 				if( x < Xd1? ) {
 					sprput(MM,m,m+XYdim?+1,RXZ);
 					ssdd += RXZ;
 				}
 				if( x > 0 ) {
 					sprput(MM,m,m+XYdim?-1,-RXZ);
 					ssdd -= RXZ;
 				}
 			}
 			if( z > 0 ) {
 				sprput(MM,m,m-XYdim?,RZ);
 				ssdd += RZ;
 				if( y < Yd1? ) {
 					sprput(MM,m,m-XYdim?+Xdim,-RYZ);
 					ssdd -= RYZ;
 				}
 				if( y > 0 ) {
 					sprput(MM,m,m-XYdim?-Xdim,RYZ);
 					ssdd += RYZ;
 				}
 				if( x < Xd1? ) {
 					sprput(MM,m,m-XYdim?+1,-RXZ);
 					ssdd -= RXZ;
 				}
 				if( x > 0 ) {
 					sprput(MM,m,m-XYdim?-1,RXZ);
 					ssdd += RXZ;
 				}
 			}
 		}

 		/* now correct the main diagonal term */
 		sprput(MM,m,m,-ssdd);

 	return;
 }
Edit - History - Print - Recent Changes - Search
Page last modified on November 07, 2009, at 10:24 AM