/**************************************************************************** AIRSTART.C Version 1.0 6 July 1995 AUTHOR: Larry Curcio (Currently: Curcio@Telerama.lm.com) PURPOSE: Produces a single interpolated thrust curve from 1 or more piecewise - linear, coarse thrust curves. If more than 1 curve is specified, then the interpolated curve is the sum of the input curves. Input curves may be assigned time offsets (ignition delays), to represent airstart configurations. Each input curve may also be assigned a multiplier, to represent simultaneous ignition of several thrust curves. The multiplier need not be integral. This feature may be used to mimic thrust curves from motors with impulses varying from the mean - perhaps by one or two standard deviations. Resulting thrust curves are compatible with DIGITRAK or SIMLABV5. Suitable curves for RASP.C may be obtained by transcribing, in compatible format, points at the time values in the component curves. These can also serve as piecewise linear (uninterpolated) DIGITRAK curves. Future versions of this program will generate such curves automatically upon request. ****************************************************************************/ #include #include #include #include #define _DEBUG #ifdef _DEBUG #define Scaffold(a) printf(a) #define Scaffold1(a, b) printf(a, b) #define Scaffold2(a, b, c) printf(a, b, c) #else #define Scaffold(a) #define Scaffold1(a, b) #define Scaffold2(a, b, c) #endif #define CURVE_SIZE 500 #define OUTPUT_SIZE 500 #define MAX_CURVES 50 #define STRLEN 150 #ifndef FALSE #define FALSE 0 #define TRUE 1 #endif #ifndef MISSING #define MISSING -32767 #endif #define _TURBODOS #ifdef _TURBODOS #define CLS clrscr() #endif #ifdef _UNIX #define CLS system("clear") #endif #ifdef _TURBOWIN #define CLS clrscr() #endif static double TotalTb, TotalMp, TotalImpulse; /*****************************************************************************/ void GetLine(int UpCase, char * cp) { int c; for (;;) { c = getchar(); if(UpCase) { if ((c >= 'a') && (c <= 'z')) c = c + 'A' - 'a'; } if (c == EOF || c == '\n') { *cp = 0; return; } *cp++ = c; } } /****************************************************************************/ int editnum(char * instring) /* *** EDIT FOR VALID NUMERIC *** */ { int numpt=0, numblank=0, numneg=0, notblank=0; while((*instring !='\0') &&(*instring != '\r')) { if((*instring < '0') || (*instring >'9')) { if(*instring == ' ') { if(notblank) ++numblank; else numblank=1; } else /* (*instring == ' ') */ if(*instring == '-') { ++numneg; if(notblank)return(FALSE); } else if(*instring == '.')++numpt; else return(FALSE); /* non-numeric character found */ notblank=1; } else notblank=1; ++instring; } if(numblank > 2)return(FALSE); if(numpt > 1) return(FALSE); if(numneg > 1) return(FALSE); return(TRUE); } /***************************************************************************/ float get_val(char * cp) /* *** ACCEPT NUMERIC FROM KEYBOARD, EDIT FOR VALIDITY, AND CONVERT *** */ { float res; if(!editnum(cp))return(MISSING); sscanf(cp, "%f", &res); return(res); } /***************************************************************************/ float Prompt(char * instring, float x) /* *** PROMPT USER FOR NUMERIC VALUE AND ACCEPT *** */ /* *** NUMERIC VALUE IS FLOATING POINT, BUT MORE VERSATILE WITH CASTS *** */ { int go_on; float y; char response[STRLEN]; go_on=TRUE; while (go_on) { y=x; printf("%s (%9.4f) ",instring, x); GetLine((int) FALSE, response); if( response[0] != '\0') y = get_val(response); if (y > MISSING) #ifndef _TURBODOS { go_on=FALSE; } #else { go_on=FALSE; gotoxy(1,wherey()-1); clreol(); printf("%s (%9.4f) \n\r",instring, y); } else { gotoxy(1,wherey()-1); clreol(); } #endif } return(y); } /***************************************************************************/ char get_reply(legend) /* *** ACCEPT SINGLE CHARACTER REPLY AND PUT INTO UPPER CASE *** */ char legend[]; { char reply; char linein[10]; printf("%s ", legend); do{ GetLine((int) TRUE, linein); reply = linein[0]; }while (strlen(linein) != 1); #ifdef _TURBODOS gotoxy(1,wherey()-1); printf("%s %c \r", legend, reply); #endif return(reply); } /***************************************************************************/ int ReadIn(char infilename[], double tin[], double fin[]) { int i, inlen, NumInt, nin; char linein[STRLEN], outfilename[STRLEN]; FILE *ifp, *fopen(); double Impulse, Tb, Mp; CLS; ifp=fopen(infilename, "r"); fgets(linein, STRLEN, ifp); Scaffold1("<%s>\n", linein); fscanf(ifp,"%lf %lf %lf %d", &Impulse, &Mp, &Tb, &NumInt); Scaffold2("Impulse = %lf, NumInt = %i\n", Impulse, NumInt); for(nin=0; nin<=NumInt; nin++) { fscanf(ifp,"%lf %lf ", &tin[nin], &fin[nin]); } fclose(ifp); return(NumInt + 1); } /****************************************************************************/ void WriteOut(char outfilename[], double Fout[], int nout, double Tout[], double TotalMp ) { int i, inlen, numint; char linein[STRLEN]; FILE *ofp, *fopen(); double Impulse, Tb; CLS; ofp=fopen(outfilename, "w"); Impulse = (double) 0.0; Tb = Tout[nout -1]; /* Impulse is known from component curves, but this is best evidence */ for(i=1; i < nout; i++) { Impulse += (Tout[i] - Tout[i-1]) * (double) 0.5 * (Fout[i] + Fout[i-1]); } nout --; /* Title Line */ fprintf(ofp,"Airstart Configuration\n"); /* Summary Line */ fprintf(ofp,"%lf %lf %lf %i \n",Impulse, TotalMp, Tb, nout); /* Interpolated Data - F, T Reversed, Extra (nonsense) Column Added */ for(i=0; i < nout; i++) { fprintf(ofp,"%lf %lf 1\n", Fout[i], Tout[i]); } fprintf(ofp,"%lf %lf 1\n", (double)0.0, (double) Tb); fclose(ofp); return; } /****************************************************************************/ double Interpolate0(double X[], double Y[], double MidX, int N) { int i; /* Find One Interpolated Point */ for(i = 0; (i < N) && (X[i + 1] < MidX); i++); /*printf("i = %i, F = %lf, T = %lf\n", i, Y[i], X[i]);*/ if(X[i + 1] == MidX) return(Y[i + 1]); return((MidX - X[i]) * (Y[i+1] - Y[i]) / (X[i+1] - X[i]) + Y[i]); } /*****************************************************************************/ int Interpolate(double T[], double F[], double OutF[], double IgnitionDelay, double Factor, int N, double DeltaT, double TimeMultiplier) { int j; double Time, MaxTime; /* Interpolate Entire Curve and Add to Output Curve */ for(j = 0; j < N; j++) T[j] *= TimeMultiplier; MaxTime = T[N-1] + IgnitionDelay; for(Time = IgnitionDelay, j =(int) ((IgnitionDelay / DeltaT) + (double) 0.5) ; Time <= MaxTime; j++, Time += DeltaT) { OutF[j] += Factor * Interpolate0(T, F, (Time - IgnitionDelay), N); } return(j); } /*****************************************************************************/ double GetBurningTime(char FileName[]) { double Impulse, Mp, Tb; int NumInt; FILE * Fp, * fopen(); char Buffer[STRLEN]; Scaffold1("File Name in GBT = <%s>\n", FileName); Fp=fopen(FileName, "r"); if(Fp != (FILE *) NULL) { fgets(Buffer, STRLEN, Fp); fscanf(Fp,"%lf %lf %lf %i", &Impulse, &Mp, &Tb, &NumInt); TotalImpulse += Impulse; TotalMp += Mp; Scaffold1("Burning Time in GBT = %lf\n",Tb); fclose(Fp); } else { printf("File <%s> not found \n", FileName); exit(-1); } return((double) Tb); } /*****************************************************************************/ double GetClusterBurningTime( char * FileName[], double IgnitionDelay[], double TimeMultiplier[] ) { double TotalTb = 0.0, CutoffTime; int i; /* Determine Burning time from component curve summary lines */ /* TotalTb = MAX(IgnitionDelay + Tb) */ TotalTb = TotalMp = TotalImpulse = (double) 0.0; for (i=0; FileName[i] != (char *) NULL; i++) { if((CutoffTime = TimeMultiplier[i] * GetBurningTime(FileName[i]) + IgnitionDelay[i]) > TotalTb) { TotalTb = CutoffTime; } } return(TotalTb); } /*****************************************************************************/ main() { int i, ClusterNumber = 1; double * Curves; double OutPutCurve[OUTPUT_SIZE]; char * FileName[MAX_CURVES]; char OutFileName[STRLEN]; double Offset[MAX_CURVES], TimeDelay[MAX_CURVES], TimeMultiplier[MAX_CURVES]; double N[MAX_CURVES]; int Nin; double InBufF[CURVE_SIZE], OutBufF[CURVE_SIZE]; double InBufT[CURVE_SIZE], OutBufT[CURVE_SIZE]; double IgnitionDelay, DeltaT, Time; CLS; for(i=0; i < MAX_CURVES; i++) { N[i] = TimeMultiplier[i] = 1.0; Offset[i] = TimeDelay[i] = (double) 0.0; } TotalTb = TotalMp = TotalImpulse = (double) 0.0; printf("\nEnter Output File Name "); GetLine((int) FALSE, OutFileName); printf("\nA Homogeneous Cluster is a collection of like motors"); printf(" ignited simultaneously\n"); ClusterNumber = (int) Prompt("\n\nHow many motor clusters? ", (float) ClusterNumber); /*printf("\n"); */ for(i=0; i < ClusterNumber; i++) { if((FileName[i]=malloc(STRLEN))== (char *) NULL) { printf("SEVERE ERROR!!! CANNOT ALLOCATE FILENAME SPACE. TERMINATING!!\n"); exit(-5); } printf("\nEnter Motor (Input) File Name <%i> ", i+1); GetLine((int) FALSE, FileName[i]); N[i] = (double) Prompt("Number of Motors in Cluster ", (float) N[i]); TimeDelay[i] = (double) Prompt("Ignition Delay for Cluster ", (float) TimeDelay[i]); TimeMultiplier[i] = (double) Prompt("Time Multiplier for Cluster ", (float) TimeMultiplier[i]); } FileName[ClusterNumber] = (char *) NULL; TotalTb = GetClusterBurningTime(FileName, TimeDelay, TimeMultiplier); DeltaT = TotalTb / ((double) CURVE_SIZE - (double) 1.0); Scaffold1("TotalTb = %lf\n", TotalTb); for(i=0, Time = (double) 0.0; i < CURVE_SIZE; Time += DeltaT, i++) { OutBufF[i] = (double) 0.0; OutBufT[i] = Time; } for(i = 0; i < ClusterNumber; i++) { Nin = ReadIn(FileName[i], InBufT, InBufF); (void) Interpolate(InBufT, InBufF, OutBufF, TimeDelay[i], N[i], Nin, DeltaT, TimeMultiplier[i]); } WriteOut( OutFileName, OutBufF, (int) CURVE_SIZE, OutBufT, TotalMp ); } /*****************************************************************************/