OutputText.c

 /* output module for text based output of a few nodes */

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



 #include "CardioWave.h"

 /* local function prototypes */
 void ExitOutput?_Text( void );

 static char* RCSID = "$Id: OutputText.c,v 1.8 2004/08/24 19:28:40 jpormann Exp $";

 static int*  NodeList? = NULL;
 static int   NumNodes? = 0;
 static int   LocalNumNodes? = 0;
 static int*  VdataPerPE? = NULL;
 static int*  VdataOffset? = NULL;
 static int   LocalQdataSize? = 0;
 static int   NumQdata? = 0;
 static int*  QdataPerPE? = NULL;
 static int*  QdataOffset? = NULL;
 static int   LocalAuxdataSize? = 0;
 static int   NumAuxdata? = 0;
 static int*  AuxdataPerPE? = NULL;
 static int*  AuxdataOffset? = NULL;
 static logical print_vm   = true;
 static logical print_ve   = false;
 static logical print_vi   = false;
 static logical print_q    = false;
 static logical print_aux  = false;
 static logical print_bath = false;
 static logical print_hdr  = true;
 static FILE* fp = NULL;
 static real  Tspacing = 0.1;
 static real  Tnext    = 0.0;
 static int   OutTag?;
 static real  print_flush = 9.9e9;
 static real  last_flush  = 0.0;
 static real* real_buffer = NULL;

 static rword resources[] = {
 	{ "appendout",	6030 },
 	{ "appendoutput",6030 },
 	{ "outfile",	6003 },
 	{ "outfilename",6003 },
 	{ "outputfile",	6003 },
 	{ "outputfilename",6003 },
 	{ "print_a",	6011 },
 	{ "print_aux",	6011 },
 	{ "print_b",	6012 },
 	{ "print_bath",	6012 },
 	{ "print_flush",6031 },
 	{ "print_list",	6002 },
 	{ "print_node",	6002 },
 	{ "print_nodes",6002 },
 	{ "print_q",	6010 },
 	{ "print_spacing",6001 },
 	{ "print_tnext",6099 },
 	{ "print_ve",	6022 },
 	{ "print_vi",	6023 },
 	{ "print_vm",	6021 },
 	{ "printa",	6011 },
 	{ "printaux",	6011 },
 	{ "printb",	6012 },
 	{ "printbath",	6012 },
 	{ "printflush",	6031 },
 	{ "printlist",	6002 },
 	{ "printnode",	6002 },
 	{ "printnodes",	6002 },
 	{ "printq",	6010 },
 	{ "printspacing",6001 },
 	{ "printtnext",	6099 },
 	{ "printve",	6022 },
 	{ "printvi",	6023 },
 	{ "printvm",	6021 },
 	{ "print_hdr",	6040 },
 	{ "printhdr",	6040 },
 	{ "print_header",6040 },
 	{ "printheader",6040 },
 	{ NULL, 0 }
 };

 int InitOutput?_Text( char** res ) {
 	int i,j,k,c,n,q,a;
 	int cmd,offset;
 	char* filename = NULL;
 	char  fn[MAX_FILENAME];
 	FILE* fp_hdr;
 	logical appendOutput = false;
 	MPI_Status mpistat;
 	byte* nt = NodeType.data;
 	int*  intptr;

 	i = 0;
 	while( res[i] != NULL ) {
 		cmd = FindCommand( resources, res[i] );
 		switch( cmd ) {
 			case 6001:
 				Tspacing = GetRealValue( res[i] );
 				break;
 			case 6002:
 				c = GetNumValues( res[i] );
 				if( c != NumNodes? ) {
 					NumNodes? = c;
 					free( NodeList? );
 				}
 				NodeList? = GetIntArray( res[i] );
 				break;
 			case 6003:
 				filename = GetStringValue( res[i] );
 				break;
 			case 6010:
 				print_q = GetTFValue( res[i] );
 				break;
 			case 6011:
 				print_aux = GetTFValue( res[i] );
 				break;
 			case 6012:
 				print_bath = GetTFValue( res[i] );
 				break;
 			case 6021:
 				print_vm = GetTFValue( res[i] );
 				break;
 			case 6022:
 				print_ve = GetTFValue( res[i] );
 				break;
 			case 6023:
 				print_vi = GetTFValue( res[i] );
 				break;
 			case 6030:
 				appendOutput = GetTFValue( res[i] );
 				break;
 			case 6031:
 				print_flush = GetRealValue( res[i] );
 				break;
 			case 6040:
 				print_hdr = GetTFValue( res[i] );
 				break;
 			case 6099:
 				Tnext = GetRealValue( res[i] );
 				break;
 		}
 		i++;
 	}

 	/* grab some message tags - Vm,Vi,Ve,Vb,Q,Aux */
 	/* : also one for the header exchange */
 	OutTag? = NextMsgTag();
 	NextMsgTag();
 	NextMsgTag();
 	NextMsgTag();
 	NextMsgTag();
 	NextMsgTag();
 	NextMsgTag();

 	strncpy( fn, filename, MAX_FILENAME );
 	strcat( fn, ".txt" );

 	/* make sure we don't try to print out non-existant values */
 	if( SimType == Monodomain ) {
 		print_ve = false;
 		print_vi = false;
 	} else if( SimType == ReducedBidomain? ) {
 		print_vi = false;
 	}
 	if( (SimType!=ReducedBidomainBath?) and (SimType!=FullBidomainBath?) ) {
 		print_bath = false;
 	}
 	if( print_bath == true ) {
 		/* *** Can't handle bath output yet!! */
 		print_bath = false;
 	}
 	if( not UseAuxvars ) {
 		print_aux = false;
 	}

 	/* make sure we have some room to work with State & Aux vars */
 	if( Workspace.size < 1024 ) {
 		real_buffer = (real*)malloc( 1024*sizeof(real) );
 	}

 	/* should we clear the old file? */
 	if( SelfPE == 0 ) {
 		if( filename == NULL ) {
 			/* if no file given, use stdout */
 			fp = stdout;
 		} else {
 			if( appendOutput == true ) {
 				fp = fopen( fn, "a" );
 			} else {
 				fp = fopen( fn, "w" );
 			}
 			if( fp == NULL ) {
 				return( -2 );
 			}
 		}
 	}

 	/* remove global node numbers that fall outside this PE's local area */
 	c = 0;
 	q = 0;
 	a = 0;
 	for(j=0;j<NumNodes?;j++) {
 		n = Global2Local( Tissue, NodeList?[j] );
 		if( (n>=0) and (n<TissueLocalSize) ) {
 			/* keep this node */
 			c++;
 			/* and accumulate the amount of Q/Aux data we'll send */
 			q += PatchSize[ nt[n] ];
 			a += AuxiliarySize[ nt[n] ];
 		}
 	}
 	LocalNumNodes?  = c;
 	LocalQdataSize? = q;
 	LocalAuxdataSize? = a;
 	k = 0;
 	for(j=0;j<c;j++) {
 		while( true ) {
 			n = Global2Local( Tissue, NodeList?[k] );
 			if( (n>=0) and (n<TissueLocalSize) ) {
 				NodeList?[j] = n;
 				break;
 			}
 			k++;
 		}
 		k++;
 	}

 	/* now sort the list so we can optimize the search process */
 	/* (for Q and Aux) later on in the Output fcn */
 	/* : just do a bucket sort for now */
 	for(i=0;i<LocalNumNodes?;i++) {
 	   for(j=(i+1);j<LocalNumNodes?;j++) {
 		if( NodeList?[i] > NodeList?[j] ) {
 			k = NodeList?[i];
 			NodeList?[i] = NodeList?[j];
 			NodeList?[j] = k;
 		}
 	   }
 	}

 	/* accumulate the number of printable pieces from each PE */
 	if( SelfPE == 0 ) {
 		VdataPerPE? = (int*)malloc( NumPEs*sizeof(int) );
 		if( VdataPerPE? == NULL ) {
 			return( -10 );
 		}
 		VdataOffset? = (int*)malloc( NumPEs*sizeof(int) );
 		if( VdataOffset? == NULL ) {
 			return( -11 );
 		}
 		if( print_q ) {
 			QdataPerPE? = (int*)malloc( NumPEs*sizeof(int) );
 			if( QdataPerPE? == NULL ) {
 				return( -12 );
 			}
 			QdataOffset? = (int*)malloc( NumPEs*sizeof(int) );
 			if( QdataOffset? == NULL ) {
 				return( -13 );
 			}
 		}
 		if( print_aux ) {
 			AuxdataPerPE? = (int*)malloc( NumPEs*sizeof(int) );
 			if( AuxdataPerPE? == NULL ) {
 				return( -12 );
 			}
 			AuxdataOffset? = (int*)malloc( NumPEs*sizeof(int) );
 			if( AuxdataOffset? == NULL ) {
 				return( -13 );
 			}
 		}
 	}
 	MPI_Gather( &LocalNumNodes?, 1, MPI_INT, VdataPerPE?, 1, MPI_INT,
 		0, MPI_COMM_WORLD );
 	if( print_q ) {
 		MPI_Gather( &LocalQdataSize?, 1, MPI_INT, QdataPerPE?, 1, MPI_INT,
 			0, MPI_COMM_WORLD );
 	}
 	if( print_aux ){
 		MPI_Gather( &LocalAuxdataSize?, 1, MPI_INT, AuxdataPerPE?, 1, 
 			MPI_INT, 0, MPI_COMM_WORLD );
 	}

 	if( SelfPE == 0 ) {
 		VdataOffset?[0] = 0;
 		for(i=1;i<NumPEs;i++) {
 			VdataOffset?[i] = VdataOffset?[i-1] + VdataPerPE?[i-1];
 		}
 		if( print_q ) {
 			QdataOffset?[0] = 0;
 			for(i=1;i<NumPEs;i++) {
 				QdataOffset?[i] = QdataOffset?[i-1] 
 					+ QdataPerPE?[i-1];
 			}
 			NumQdata? = QdataOffset?[NumPEs-1] + QdataPerPE?[NumPEs-1];
 		}
 		if( print_aux ) {
 			AuxdataOffset?[0] = 0;
 			for(i=1;i<NumPEs;i++) {
 				AuxdataOffset?[i] = AuxdataOffset?[i-1] 
 							+ AuxdataPerPE?[i-1];
 			}
 			NumAuxdata? = AuxdataOffset?[NumPEs-1] 
 				+ AuxdataPerPE?[NumPEs-1];
 		}
 	}

 	if( print_hdr ) {
 		/* print a header file with the output-node ordering */
 		strncpy( fn, filename, MAX_FILENAME );
 		strcat( fn, ".hdr" );
 		intptr = (int*)Workspace.data;

 		if( SelfPE == 0 ) {
 			fp_hdr = fopen( fn, "w" );
 			if( fp_hdr == NULL ) {
 				return( -3 );
 			}
 			fprintf( fp_hdr, "Node ordering in output file\n" ); 
 			for(i=0;i<LocalNumNodes?;i++) {
 				fprintf( fp_hdr, "%i ", NodeList?[i] );
 			}

 			for(q=1;q<NumPEs;q++) {
 				MPI_Send( &q, 1, MPI_INT, q, OutTag?+6,
 					MPI_COMM_WORLD );
 				MPI_Recv( intptr, VdataPerPE?[q], MPI_INT, q,
 					OutTag?+6, MPI_COMM_WORLD, &mpistat );

 				for(i=0;i<VdataPerPE?[q];i++) {
 					fprintf( fp_hdr, "%i ", intptr[i] );
 				}
 			}

 			fprintf( fp_hdr, "\n" );
 			fclose( fp_hdr );

 		} else {
 			for(i=0;i<LocalNumNodes?;i++) {
 				intptr[i] = Local2Global( Tissue, NodeList?[i] );
 			}

 			MPI_Recv( &q, 1, MPI_INT, 0, OutTag?+6, MPI_COMM_WORLD,
 				&mpistat );
 			MPI_Send( intptr, LocalNumNodes?, MPI_INT, 0, OutTag?+6,
 				MPI_COMM_WORLD );
 		}
 	}

 	if( (DebugLevel>0) and (SelfPE==0) ) {
 		printf("OutputText?: spacing = %le, print = [c,c,c,%c]\n",
 			Tspacing, (print_vm?'Y':'N'), (print_ve?'Y':'N'),
 			(print_vi?'Y':'N'), (print_bath?'Y':'N'),
 			(print_q?'Y':'N'), (print_aux?'Y':'N'),
 			(print_hdr?'Y':'N') );
 		if( DebugLevel > 1 ) {
 			printf("OutputText?: RCSID: %s\n",RCSID);
 		}
 	}

 	return( 0 );
 }

 void ExitOutput?_Text( void ) {
 	if( SaveState and (SelfPE==0) ) {
 		fprintf( FpResources, "print_tnext=%le\n", Tnext );
 	}

 	if( (fp!=NULL) and (fp!=stdout) ) {
 		fclose( fp );
 	}

 	return;
 }

 void Output_Text( real t, vector Vm, vector Vx, vector Q, vector Av ) {
 	int i,j,k,n,c,p;
 	real* wksp;
 	real* rp = NULL;
 	vector vtmp;
 	byte* nt = NodeType.data;
 	MPI_Status mpistat;
 	MPI_Request mpireq;

 	if( real_buffer == NULL ) {
 		wksp = Workspace.data;
 	} else {
 		wksp = real_buffer;
 	}

 	if( t >= Tnext ) {
 		if( SelfPE == 0 ) {
 			fprintf(fp,"%le ",t);
 		}

 		if( print_vm ) {
 			/* accumulate Vm data into Workspace */
 			rp = Vm.data;
 			for(i=0;i<LocalNumNodes?;i++) {
 				wksp[i] = rp[ NodeList?[i] ];
 			}

 			if( SelfPE == 0 ) {
 				fprintf(fp,"\t");
 				for(i=0;i<LocalNumNodes?;i++) {
 					fprintf(fp,"%le ",wksp[i]);
 				}
 				for(p=1;p<NumPEs;p++) {
 					MPI_Recv( wksp, VdataPerPE?[p],
 						MPI_SSREAL, p, OutTag?,
 						MPI_COMM_WORLD, &mpistat );
 					for(i=0;i<VdataPerPE?[p];i++) {
 						fprintf(fp,"%le ",wksp[i]);
 					}
 				}
 			} else {
 				MPI_Isend( wksp, LocalNumNodes?, MPI_SSREAL,
 					0, OutTag?, MPI_COMM_WORLD, &mpireq );
 				MPI_Request_free( &mpireq );
 			}
 		}

 		if( print_vi ) {
 			/* accumulate Vi data into Workspace */
 			AliasVxVi( Vx, &vtmp );
 			rp = vtmp.data;
 			for(i=0;i<LocalNumNodes?;i++) {
 				wksp[i] = rp[ NodeList?[i] ];
 			}

 			if( SelfPE == 0 ) {
 				fprintf(fp,"\t");
 				for(i=0;i<LocalNumNodes?;i++) {
 					fprintf(fp,"%le ",wksp[i]);
 				}
 				for(p=1;p<NumPEs;p++) {
 					MPI_Recv( wksp, VdataPerPE?[p],
 						MPI_SSREAL, p, OutTag?+1,
 						MPI_COMM_WORLD, &mpistat );
 					for(i=0;i<VdataPerPE?[p];i++) {
 						fprintf(fp,"%le ",wksp[i]);
 					}
 				}
 			} else {
 				MPI_Isend( wksp, LocalNumNodes?, MPI_SSREAL,
 					0, OutTag?+1, MPI_COMM_WORLD, &mpireq );
 				MPI_Request_free( &mpireq );
 			}
 		}

 		if( print_ve ) {
 			/* accumulate Vi data into Workspace */
 			AliasVxVe( Vx, &vtmp );
 			rp = vtmp.data;
 			for(i=0;i<LocalNumNodes?;i++) {
 				wksp[i] = rp[ NodeList?[i] ];
 			}

 			if( SelfPE == 0 ) {
 				fprintf(fp,"\t");
 				for(i=0;i<LocalNumNodes?;i++) {
 					fprintf(fp,"%le ",wksp[i]);
 				}
 				for(p=1;p<NumPEs;p++) {
 					MPI_Recv( wksp, VdataPerPE?[p],
 						MPI_SSREAL, p, OutTag?+2,
 						MPI_COMM_WORLD, &mpistat );
 					for(i=0;i<VdataPerPE?[p];i++) {
 						fprintf(fp,"%le ",wksp[i]);
 					}
 				}
 			} else {
 				MPI_Isend( wksp, LocalNumNodes?, MPI_SSREAL,
 					0, OutTag?+2, MPI_COMM_WORLD, &mpireq );
 				MPI_Request_free( &mpireq );
 			}
 		}

 		if( print_q ) {
 			/* accumulate Q data into Workspace */
 			rp = Q.data;
 			j  = 0;
 			c  = 0;
 			for(i=0;i<LocalNumNodes?;i++) {
 				/* skip to NodeList?[i-1] */
 				n = NodeList?[i];
 				for(;j<n;j++) {
 					rp += PatchSize[ nt[j] ];
 				}
 				for(k=0;k<PatchSize[nt[n]];k++) {
 					wksp[c] = rp[k];
 					c++;
 				}
 				rp += PatchSize[ nt[n] ];
 				j++;
 			}

 			if( SelfPE == 0 ) {
 				fprintf(fp,"\t");
 				for(i=0;i<LocalQdataSize?;i++) {
 					fprintf(fp,"%le ",wksp[i]);
 				}
 				for(p=1;p<NumPEs;p++) {
 					MPI_Recv( wksp, QdataPerPE?[p],
 						MPI_SSREAL, p, OutTag?+3,
 						MPI_COMM_WORLD, &mpistat );
 					for(i=0;i<QdataPerPE?[p];i++) {
 						fprintf(fp,"%le ",wksp[i]);
 					}
 				}
 			} else {
 				MPI_Isend( wksp, LocalQdataSize?, MPI_SSREAL,
 					0, OutTag?+3, MPI_COMM_WORLD, &mpireq );
 				MPI_Request_free( &mpireq );
 			}
 		}

 		if( print_aux ) {
 			/* accumulate Aux data into Workspace */
 			rp = Av.data;
 			j  = 0;
 			c  = 0;
 			for(i=0;i<LocalNumNodes?;i++) {
 				/* skip to NodeList?[i-1] */
 				n = NodeList?[i];
 				for(;j<n;j++) {
 					rp += AuxiliarySize[ nt[j] ];
 				}
 				for(k=0;k<AuxiliarySize[nt[n]];k++) {
 					wksp[c] = rp[k];
 					c++;
 				}
 				rp += AuxiliarySize[ nt[n] ];
 				j++;
 			}

 			if( SelfPE == 0 ) {
 				fprintf(fp,"\t");
 				for(i=0;i<LocalAuxdataSize?;i++) {
 					fprintf(fp,"%le ",wksp[i]);
 				}
 				for(p=1;p<NumPEs;p++) {
 					MPI_Recv( wksp, AuxdataPerPE?[p],
 						MPI_SSREAL, p, OutTag?+4,
 						MPI_COMM_WORLD, &mpistat );
 					for(i=0;i<AuxdataPerPE?[p];i++) {
 						fprintf(fp,"%le ",wksp[i]);
 					}
 				}
 			} else {
 				MPI_Isend( wksp, LocalAuxdataSize?, MPI_SSREAL,
 					0, OutTag?+4, MPI_COMM_WORLD, &mpireq );
 				MPI_Request_free( &mpireq );
 			}
 		}

 		if( SelfPE == 0 ) {
 			fprintf(fp,"\n");
 			if( t >= last_flush ) {
 				fflush( fp );
 				last_flush += print_flush;
 			}
 		}

 		Tnext += Tspacing;
 	}

 	return;
 }
Edit - History - Print - Recent Changes - Search
Page last modified on November 23, 2009, at 09:48 AM