The Problem
Air resistance should be proportional to velocity squared, but it is currently only proportional to velocity.Symptoms
In vanilla, trains accelerate more than they should at high speeds and don't accelerate as much as they should at low speeds. With the max_speed cap of ~300km/h this is less noticeable than it otherwise would be; but removing the hard cap and relying on air resistance to cap the speed (using a mod that changes properties of RollingStockPrototypes, see https://mods.factorio.com/mod/ConfigTra ... icationsMU) makes the problem much worse: a train with N locomotives goes N times faster than a single locomotive!As it is now, since we're trying to approximate a quadratic function with a linear one, we can either 1. underestimate the air resistance and have trains be able to continue accelerating and reach much higher top speeds, or 2. overestimate the air resistance and have trains accelerate from a stop extremely slowly.
Corroborating quotes
These are some quotes indicating this is a real issue. Koub and Optera even seem to assume air resistance is correctly calculated proportional to velocity squared, when it actually isn't!BlueTemplar wrote: ↑Fri Jul 12, 2019 1:16 pmmass has no (direct) effect on top speed, only drag has (aerodynamic and wheel friction*). And drag depends solely on the shape of the object and the density of the fluid it's moving through. An extreme case is vacuum, with no top speed in newtonian mechanics.
Dimensional analysis
Factorio clearly strives to get fundamental relations between units correct (energy vs power vs heat vs efficiency, velocity vs acceleration vs force vs weight, etc). However, looking at the air resistance component to the train speed equation we can see that it immediately fails under simple dimensional analysis! This means that the application of air resistance to the train speed each tick does not make physical or in-game sense.Reference code from the wiki:
Code: Select all
train_speed = max(0, abs(train_speed) - train_friction_force ÷ train_weight)
train_speed = train_speed + (10 × number_of_locomotives_in_moving_direction × fuel_acceleration_bonus ÷ train_weight)
train_speed = train_speed × (1 - air_resistance_of_front_rolling_stock ÷ (train_weight ÷ 1000))
- train_speed :: distance / time (speed)
- train_weight :: mass
- train_friction_force :: mass * distance / time^2 (force)
The more ambiguous units:
- number_of_locomotives_in_moving_direction :: mass * distance / time^2 (force)
- fuel_acceleration_bonus :: unitless
- air_resistance_of_front_rolling_stock :: ???
For last, most important line in question, how can we algebraically manipulate this to match the previous lines (of the form speed = speed + acceleration * dt)? Distributing the multiplication by train_speed, we get:
Code: Select all
train_speed = train_speed - train_speed × air_resistance_of_front_rolling_stock ÷ (train_weight ÷ 1000)
I hope by this point you can agree that something is definitely wrong. Specifically, the real equation for the drag force is proportional to the velocity squared (along with air density, cross-sectional area, and drag coefficient which can be baked into the air_resistance_of_front_rolling_stock constant with new dimensions mass / distance).
Suggested (backwards-compatible) fix
The last line of the code should instead look like this:Code: Select all
train_speed = train_speed - 500 × train_speed × train_speed × air_resistance_of_front_rolling_stock ÷ train_weight