|
Code /
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; } |