The One Formula To Rule Them All: The Mechanics of Shield and Thruster Mass Curves

Much prior research has been done to understand how thruster and shield generator performance scales with ship mass; here are just a few such discussions that I'm aware of:

These threads (and probably many others) contain various iterations of formulas that achieved better and better approximations of the shield strength and thruster speed values observed in-game, but none were ever perfectly exact. After a lot of experimentation, however, I believe I have finally found that perfect formula, and it turns out to be the same single formula that governs the mass curves of both thrusters and shield generators.

The key insight was in finding the correct normalization for the input mass. Previous formulas operated on the literal mass value, or the ratio of mass to optimal (as in the FSD fuel formula), or "optimality" from -1 to 1, or various other abstractions. But in all of those parameter spaces the math becomes very ugly and requires lots of magic numbers to get a close fit to the data, which (as developer Mike Evans famously quipped) was "a sure sign that it isn't what [they were] using."

I believe now that the correct normlization for the input mass (the X axis of the mass curve) is to treat it as a measure of "underweight-ness" ranging from 0 (mass == maxMass) to 1 (mass <= minMass):

Code:
xnorm(mass) => min(1, (maxMass - mass) / (maxMass - minMass))

This scheme then suggests the correct normalization for the output value (the Y axis of the curve) as a "bonus allotment" also ranging from 0 (for minMul) to 1 (for maxMul):

Code:
ynorm(mul) => (mul - minMul) / (maxMul - minMul)
mul = minMul + (ynorm(mul) * (maxMul - minMul))

Once we're working in this coordinate space, the mass curve turns out to be a simple power function:

Code:
ynorm(xnorm(mass)) => pow(xnorm(mass), exponent)

Because pow(0,anything) == 0 and pow(1,anything) == 1, this will automatically give the correct result at the endpoints (maxMass,minMul) and (minMass,maxMul), so all we have to do is calibrate the exponent in order to hit (optMass,optMul). We can do this with substitutions and some algebra:

Code:
pow(xnorm(optMass), exponent) == ynorm(optMul)
pow(min(1, (maxMass - optMass) / (maxMass - minMass)), exponent) == (optMul - minMul) / (maxMul - minMul)
exponent == log((optMul - minMul) / (maxMul - minMul)) / log(min(1, (maxMass - optMass) / (maxMass - minMass)))

It's important to note that we cannot treat the exponent as a constant because the relative position of optMass between minMass and maxMass is not universal. Even when there seems to be a consistent pattern (such as minMass=0.5*optMass and maxMass=2.5*optMass for shield generators) it's not always exact because Frontier has rounded all of the mass limit values to whole tons; this introduces very slight differences in the ratios between min/opt/maxMass for each module, which very slightly changes the shape of the curve. This was a major source of the imprecision in many earlier iterations of these formulas: the derived "magic numbers" were attempting to serve the purpose of the curve exponent, but because that exponent works out to be very slightly different for each thruster or each class of shield generator, a single magic number could never yield correct results in all cases. They were also entirely unable to handle Enhanced Performance Thrusters with their non-standard mass curves, nor could they account for engineer modifications; both of these cases are also modeled accurately by the new mass curve formula.

As a demonstration, let's see how this new formula compares to the old estimate of a 7E shield on a Corvette, which had one of the largest discrepancies under the old formula (estimated 518.5 vs actual 516.1):

Code:
xnorm(900) = min(1, (2650 - 900) / (2650 - 530))
xnorm(900) = 0.82547169811320754716981132075472
exponent = log((0.8 - 0.3) / (1.3 - 0.3)) / log((2650 - 1060) / (2650 - 530))
exponent = log(0.5) / log(0.75)
exponent = 2.4094208396532090045824043308125
ynorm(xnorm(900)) = pow(0.82547169811320754716981132075472, 2.4094208396532090045824043308125)
ynorm(xnorm(900)) = 0.62994192796710687734470818200228
mul = 0.3 + (0.62994192796710687734470818200228 * (1.3 - 0.3))
mul = 0.92994192796710687734470818200228
shield = 555 * 0.92994192796710687734470818200228
shield ~= 516.1

This is an exact match to what is displayed in-game for this shield on this ship. I have also compared the results of this formula against hundreds and hundreds of additional shield strength and thruster speed measurements that I've made over the course of my research, and every single one is now an exact match.

This mass curve formula is included in the latest version 2.2.1 of E:D Shipyard, which has also added support for engineer modifications (among many, many other new features), so you can now model your exact shield strength and thruster performance for any module with any modifications on any loadout. If you see any discrepancies, please let me know!
 
"And the 2016 Nobel Prize in ED Mathematics goes to..." :D

This is excellent work!! Kudos!!

So if I'm following it correctly, there are no "magic numbers" at all anymore. All the values are the simple input values for mass, multipliers, etc., and all the operations are basic math functions with no arbitrary constants required. I like it :)

Wonder if FD might give it the unofficially approving nod?
 
Bookmarked. How did this thread disappear into oblivion 2 months ago without a single reply?

Right? I spent days searching the forum for this exact stuff and could only find the earlier threads with outdated info (which still get ref'ed in recent threads). It was only when taleden pointed me to it in the ED Shipyard thread that I saw it. :S
 
Back
Top Bottom