OR Units of Measure
#11
Posted 14 May 2013 - 03:33 PM
It was said the steamer code was to be rewriten, I certainly think the multiple units standards have created problems and these __should__ be corrected first. When doing any development work one __MUST__ take only one step at a time, one should only abandon a line of research once it has become completely clear its leading nowhere. The one has learned something from the abandoned line.
Wether the current way or a new way to do the steam physics is the best I do not know, but I believe one cannot make a decent judgment on the issue from a source file with possible bugs in it.
Lindsay
#12
Posted 22 May 2013 - 02:37 PM
The EvaporationLBpS = boilerKW / (1.055f * steamHeat); equation is correct. steamHeat is in BTU/LB and is from the steam table in SteamTable.cs. Dividing boilerKW by 1.055 converts it into BTU/S and dividing that by BTU/LB gives LB/S.
The EvaporationAreaSqM value is something used in Anthony's model that is not in a normal MSTS eng file. It is calculated by setting the EvaporationLBpS value to the maximum boiler output and then solving the boilerKW equation for EvaporationAreaSqM with the boiler pressure at the maximum and FlueTempK set to 1400. I don't know the significance of the 1400 but it is from Anthony's model.
Doug
#13
Posted 23 May 2013 - 01:26 AM
dajones, on 22 May 2013 - 02:37 PM, said:
The EvaporationLBpS = boilerKW / (1.055f * steamHeat); equation is correct. steamHeat is in BTU/LB and is from the steam table in SteamTable.cs. Dividing boilerKW by 1.055 converts it into BTU/S and dividing that by BTU/LB gives LB/S.
The EvaporationAreaSqM value is something used in Anthony's model that is not in a normal MSTS eng file. It is calculated by setting the EvaporationLBpS value to the maximum boiler output and then solving the boilerKW equation for EvaporationAreaSqM with the boiler pressure at the maximum and FlueTempK set to 1400. I don't know the significance of the 1400 but it is from Anthony's model.
Doug
Thanks for the clarification.
Cheers
Peter
#14
Posted 23 May 2013 - 01:39 AM
dajones, on 22 May 2013 - 02:37 PM, said:
The EvaporationLBpS = boilerKW / (1.055f * steamHeat); equation is correct. steamHeat is in BTU/LB and is from the steam table in SteamTable.cs. Dividing boilerKW by 1.055 converts it into BTU/S and dividing that by BTU/LB gives LB/S.
The EvaporationAreaSqM value is something used in Anthony's model that is not in a normal MSTS eng file. It is calculated by setting the EvaporationLBpS value to the maximum boiler output and then solving the boilerKW equation for EvaporationAreaSqM with the boiler pressure at the maximum and FlueTempK set to 1400. I don't know the significance of the 1400 but it is from Anthony's model.
Doug
Much thanks for this info, I certainly believe that for subjects such as this these sort of comments should be in the source. The equation for the evaparation area does actually produce an aproximately correct result. I am still though getting odd behavior out of the steam loco simulation.
There appears to be a good number of assumptions made in the code (such as the 1400) where absolutely no clue is given for the origin so one has a major problem judging how good the simulation actually is. It currently though performs well below a good steamer and so far I have only been able to correct it by "cooking" the numbers.
Not good,
Hmmmmmmmmmmmmmm,I may have to go and look at some my old steamer design books I would not die of shock to find that is the origin of the maths.
Lindsay
#15
Posted 23 May 2013 - 02:12 PM
dajones, on 22 May 2013 - 02:37 PM, said:
The EvaporationLBpS = boilerKW / (1.055f * steamHeat); equation is correct. steamHeat is in BTU/LB and is from the steam table in SteamTable.cs. Dividing boilerKW by 1.055 converts it into BTU/S and dividing that by BTU/LB gives LB/S.
The EvaporationAreaSqM value is something used in Anthony's model that is not in a normal MSTS eng file. It is calculated by setting the EvaporationLBpS value to the maximum boiler output and then solving the boilerKW equation for EvaporationAreaSqM with the boiler pressure at the maximum and FlueTempK set to 1400. I don't know the significance of the 1400 but it is from Anthony's model.
Doug
Do you know the origin of the Data in the Forcefactor1 and 2 interpolaters. These tables look to be the cylinders BMEP ratio given the cuttoff, but the data does not match what I think should happen in real life.
Take for example at a cuttoff of 85 percent the pressure in the cylinder for 85 percent of the stroke is close to the cylinders input pressure and only falls off a small amount before the exhaust port opens. In the table this s given as 0.607703f this appears to be way to low given the previous sentence. the calculated result using values calculated every 10 degrees of crank rotation is around 0.97f. I have checked this with some indicator diagrams and this value is aprox correct.
If required I have calculated these values between the cuttoff ranges of 0.15 and 0.75 and checked them when I can with some inductor diagrams and I am reasonably confident of there accuracy.
Note, Two methods have been used to do these calculations, the first being the traditional method of working out a cylinders mean effective pressure. The second working this pressure out using the 10 degree intervals and working out the RMS value of the pressure, the results from both methods were close to each other.
Lindsay
#16
Posted 24 May 2013 - 01:34 PM
The simulation I mentioned above computed tractive force based on crank angle for low speeds and it used these tables for high speeds. I didn't port that code so instead I copied the tables calculated by that sim. into the OR code. Here is the fragment of code that computes those values:
release.add(.2,.7); release.add(.37,.8); release.add(.5,.85); release.add(.75,.93); release.add(.85,.96); release.compute(); for (int i=0; i<=10; i++) { float cutoff= release.getMinX() + .1*i*(release.getMaxX()-release.getMinX()); float rel= release(cutoff); float cutoffAngle= crankAngle(cutoff); float releaseAngle= crankAngle(rel); float s0= (cos(releaseAngle)-1)/3.14159; float s1= (1-cos(cutoffAngle))/3.14159; int n= 30; float dx= (rel-cutoff)/n; for (int j=0; j<=n; j++) { float x= cutoff + j*dx; float y= sin(crankAngle(x))* (cutoff+clearanceVolume)/(x+clearanceVolume); if (j==0 || j==n) s1+= dx*y/3; else if (j%2==0) s1+= dx*4*y/3; else s1+= dx*2*y/3; } forceFactor1.add(cutoff,s0); forceFactor2.add(cutoff,s1); fprintf(stderr,"%.3f %.3f %3.0f %3.0f", cutoff,rel,180*cutoffAngle/3.14159,180*releaseAngle/3.14159); fprintf(stderr," %f %f %f\n",s0,s1, .85*cutoff*(1-(1-cutoff)*log(cutoff))); } // returns the crank angle given piston position float SteamEngine::crankAngle(float x) { float a= mainRodLength; float b= .5*cylStroke; float c= b+a-x*cylStroke; return acos(.5*(b*b+c*c-a*a)/(b*c)); }
The s0 and s1 variables are initialized to the calculated result for the part of the integration that was easy to solve. The part between the cutoff and release points is integrated numerically using Simpson's rule. The values used in OR were calculated using mainRodLength set to 4*cylStroke and clearanceVolume set to .07. Here is the output from that program that was used to populate the values in OR:
0.200 0.700 50 110 -0.428043 0.371714 0.388884 0.265 0.738 59 115 -0.453624 0.429217 0.445116 0.330 0.776 67 120 -0.479480 0.476195 0.488856 0.395 0.810 74 125 -0.502123 0.512149 0.524430 0.460 0.835 82 129 -0.519346 0.536852 0.554956 0.525 0.858 89 133 -0.535572 0.554344 0.582834 0.590 0.879 97 137 -0.550099 0.565618 0.609989 0.655 0.900 105 141 -0.564719 0.573383 0.638022 0.720 0.920 113 145 -0.579431 0.579257 0.668293 0.785 0.940 122 150 -0.593737 0.584714 0.701977 0.850 0.960 132 155 -0.607703 0.591967 0.740113
The release object in the code above is a table used to map the cutoff position to the release position. This was calculated using another program using some assumed valve gear settings. I don't remember where these value gear settings came from, but I think they are all in inches. Here is that code:
// test program for calculating steam engine value events float maxTravel= 5.; float steamLap= 1.; float exhaustLap= 0; float lead= .0625; float portWidth= 1.25; float stroke= 24.; float rodLen= 108.; float rad2deg= 180./3.14159; for (int i=20; i>=0; i--) { float travel= .05*i*(.5*maxTravel-lead-steamLap)+lead+steamLap; float deadCenter= asin((lead+steamLap)/travel); float cutoff= 3.14159 - asin(steamLap/travel) - deadCenter; float release= 3.14159 - deadCenter + asin(exhaustLap/travel); float cutoffFrac= (rodLen+.5*stroke-.5*stroke*cos(cutoff)- cos(asin(.5*stroke*sin(cutoff)/rodLen))*rodLen)/stroke; float releaseFrac= (rodLen+.5*stroke-.5*stroke*cos(release)- cos(asin(.5*stroke*sin(release)/rodLen))*rodLen)/stroke; fprintf(stderr,"%.2f %.2f %f %f %f %f\n", cutoffFrac,releaseFrac, travel,rad2deg*deadCenter, rad2deg*cutoff,rad2deg*release); }
And here is the output it produced:
0.85 0.96 2.500000 25.150686 131.271118 154.849319 0.84 0.95 2.428125 25.949629 129.729858 154.050385 0.83 0.95 2.356250 26.803286 128.083801 153.196716 0.81 0.95 2.284375 27.717772 126.321388 152.282227 0.80 0.94 2.212500 28.700186 124.429176 151.299820 0.79 0.94 2.140625 29.758860 122.391457 150.241150 0.77 0.94 2.068750 30.903627 120.189713 149.096390 0.75 0.93 1.996875 32.146221 117.801971 147.853775 0.74 0.93 1.925000 33.500793 115.201775 146.499222 0.71 0.92 1.853125 34.984604 112.356987 145.015396 0.69 0.91 1.781250 36.619041 109.228020 143.380966 0.66 0.90 1.709375 38.431068 105.765266 141.568939 0.63 0.89 1.637500 40.455360 101.905411 139.544647 0.59 0.88 1.565625 42.737709 97.565628 137.262299 0.55 0.87 1.493750 45.340588 92.634285 134.659409 0.50 0.85 1.421875 48.353004 86.954857 131.647003 0.44 0.83 1.350000 51.909519 80.295898 128.090485 0.37 0.80 1.278125 56.232124 72.287354 123.767876 0.29 0.76 1.206250 61.742588 62.259624 118.257423 0.19 0.70 1.134375 69.494652 48.676270 110.505348 0.03 0.53 1.062500 90.000084 19.749784 89.999924
Doug
#17
Posted 24 May 2013 - 02:43 PM
The problem for me is I find even now the origin of these tables difficult to understand and hence almost impossible to correct. Another factor is in the simulation I am currently writing on the Linux OS I have done the steam loco in a completely different way, believeing a full mathematical simulation would not produce the result I required. What I have done is the loco operating controls (regulator, reverser etc.) directly control the performance, the actual performacne figures comming from real life tests. Internel conditions (effective cylinder pressure, steam consumption etc) calculated by working backwards, ie these calculated figures do not actaully effect the loco's performance in the sim, they do though reflect the loco's performance.
Essentaily what I have done is an enhancement of the way MSTS steam simulation works.
Lindsay
#18
Posted 24 May 2013 - 10:44 PM
Are you able to shed any light on the following formula?
SteamUsageLBpS = .6f * SteamUsageLBpS + .4f * speed * SteamUsageFactor * (cutoff + .07f) * (CylinderSteamDensity[cylinderPressure] - CylinderSteamDensity[backPressure]);
Are you able to "quote" the original from the Steam Locomotive Book, as I don't have access to a copy?
In particular, I am interested in the "speed * SteamUsageFactor" portion, I assume that this is trying to determine the cylinder volume, and the number of cylinder strokes at the current locomotive speed, and then combining it with the steam density at the working pressure and cutoff to determine the steam usage.
Is this correct?
Thanks
Peter
#19
Posted 25 May 2013 - 02:32 AM
steamer_ctn, on 24 May 2013 - 10:44 PM, said:
Are you able to shed any light on the following formula?
SteamUsageLBpS = .6f * SteamUsageLBpS + .4f * speed * SteamUsageFactor * (cutoff + .07f) * (CylinderSteamDensity[cylinderPressure] - CylinderSteamDensity[backPressure]);
Are you able to "quote" the original from the Steam Locomotive Book, as I don't have access to a copy?
In particular, I am interested in the "speed * SteamUsageFactor" portion, I assume that this is trying to determine the cylinder volume, and the number of cylinder strokes at the current locomotive speed, and then combining it with the steam density at the working pressure and cutoff to determine the steam usage.
Is this correct?
Thanks
Peter
Thats how I would read it, the SteamUsageFactor appears basicly to be a number that represents the amount of cylinder volume swept when the loco moves. So if you multiply this number by the distance moved gives one the total cylinder volume used. Quite what all those constant numbers are doing in the calculation I am not sure (.6f, .4f, .07f).
Lindsay
#20
Posted 15 August 2013 - 08:01 AM
James Ross, on 14 May 2013 - 10:06 AM, said:
Sadly, leaving out the units does seem to be a "really common practice", at least for ENG files. It looks as though just logging the first occurrence only would result in every log file having dozens of information messages.
I'm thinking of putting this idea on hold and focus, with steamer_ctn (Peter Newark) on the other issues for now,