Damper manual is used by AI, not manual

Bug #1989236 reported by Wesley Johnson
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Open Rails
New
Undecided
Unassigned

Bug Description

In every comment, the DamperFactorManual is said to be for manual damper control.
At the point of use, it is used by the AI, and not the manual damper control.
The test is reversed, or something more complicated,

File: MSTSSteamLocomotive.cs

float DamperFactorManual = 1.0f; // factor to control draft through fire when locomotive is running in Manual mode

DamperFactorManual = TheoreticalMaxSteamOutputLBpS / SpeedEquivMpS; // Calculate a factor for damper control that will vary with speed.

// ORTS ERROR: or at least this is terribly confusing given the previous comments.

// Damper - to determine smoke color
  float SmokeColorDamper = 0.0f;
  if (FiringIsManual)
  {
                SmokeColorDamper = DamperBurnEffect; // set to the damper burn effect as set for manual firing
  }
  else
  {
                SmokeColorDamper = absSpeedMpS * DamperFactorManual; // Damper value for manual firing - related to increased speed, and airflow through fire
  }

Note: my code is replacing the ORTS damper controls with something entirely new, with more control,
and more refined simulation. Not entirely ready yet, as I have these details to figure out.

My code:
// ---- Damper Model
// factor to control draft through fire when locomotive is running in Manual mode
float damper_factor_manual = 1.0f; // kg/meter/sec
      // DamperFactorManual lb/meter/sec
float fire_draft_multiplier; // kg / kg/sec // multiply by fuel_burn_rate
float exhaust_draft_multiplier; // kg / kg/sec // multiply by cylinder_steam_usage

// ---- Damper in engine unit
// Damper
byte damper_control; // 0..255
float draft_air; // 1.0 = air to burn 1kg
float DamperBurnEffect; // Effect of the Damper control

// Draft caused by fire. Do not ever let it be 0.
   draft_air = model->fire_draft_multiplier * fuel_burn_rate_eff;
// Draft caused by exhaust steam.
   draft_air += model->exhaust_draft_multiplier * cylinder_steam_usage;

// Damper - need to be calculated in AI fireman case too, to determine smoke color
if (absSpeedMpS < 1.0f) // locomotive is stationary then damper will have no effect
{
    // This is not necessary.
    DamperBurnEffect = 0.0f;
}
else
{
    // Damper value for manual firing - related to damper setting and increased speed
    DamperBurnEffect = damper_control * (1.0/255) * absSpeedMpS * model->damper_factor_manual;
}
draft_air *= damper_control * (1.0/255);

// Manual fireman
// Test to see if blower has been manually activated.
if( blower_control > 0 )
{
  fire_control_status |= SF_blower; // turn blower on if being used
  blower_steam_usage = model->blower_steam_usage_factor * boiler_pressure * blower_control;
  BlowerBurnEffect = model->blower_multiplier * blower_steam_usage;
  draft_air += model->blower_draft_multiplier * blower_steam_usage;
}

// AI fireman
draft_air = fire_mass; // perfect damper control ?? FIXME

// The draft_air is measured as the amount of fire that can be supported, so it is measured the same as fire mass.
float fire_supported = fire_mass;
float fire_mass_unburned = 0;
float excess_air = 0;
draft_air += (fire_mass * 0.01f) + 0.1; // damper leakage, and so draft_air is never 0.
if( draft_air > fire_mass ) {
  // Excess air
  excess_air = draft_air - fire_mass;
  // Excess air cools the fire, the boiler, and the superheater.
  // The amount of air that would be ideal for the fire is same value as fire_mass.
  // All the draft_air going through the firebox has to be heated too.
  float excess_air_frac = fire_mass / draft_air;
  float source_temp = C_to_K(environment_temperature);
  superheater_temperature = ((superheater_temperature - source_temp) * excess_air_frac) + source_temp;
  // specific heat of air = 1.006 kj/kg K
  // specific heat of water = 4.22 kj/kg K at 300 K
  float draft_heat_loss = excess_air * (boiler_water_temp_K - source_temp) * (1.006 / 4.22) / boiler_water_mass;
  boiler_output_heat_rate += draft_heat_loss;
  boiler_heat -= draft_heat_loss * tick_secs; // Reduce boiler Heat to reflect heat lost by excess air.
}else{
  // Insufficient air
  // Can only support draft_air amount of fire.
  fire_supported = draft_air;
  fire_mass_unburned = fire_mass - draft_air; // creates smoke
}
fire_burn_rate_inst *= fire_supported / model->fire_mass_ideal;

I have not yet tied the draft_air and fire_mass_unburned to the smoke, as that requires
rewriting the smoke generation for my graphics files and environment.

Revision history for this message
Wesley Johnson (trackcreworts) wrote :

I missed putting this in the bug report.
From my code:

// verify_and_correct model

// max steam vrs max speed
damper_factor_manual = boiler_steam_output_max / MPH60; // a factor for damper control that will vary with speed.

blower_steam_usage_factor = (0.04f * 2.20462f / 255) * boiler_steam_output_max / boiler_pressure_max; // kg/sec/psi/control_step

// draft_air multipliers, guess work for now
// natural draft can support 20% of full burn
fire_draft_multiplier = (fire_mass_ideal * 0.2f) / grate_burn_rate_max; // background burn rate
// exhaust, by itself, supplies air for 85% of full burn
exhaust_draft_multiplier = (fire_mass_ideal * 0.85f) / boiler_steam_output_max;
// blower can support 40% of full burn
blower_draft_multiplier = (fire_mass_ideal * 0.4f / 255) / (blower_steam_usage_factor * boiler_pressure_max); // control 0..255

note:
I expect at full steam, the firebox will suffer from excess air.
I expect that because the stack and flues will be designed for efficient operation at a
nomimal steam usage less than the maximum.
The fireman will be expected to close the dampers somewhat.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.