Now that the 1.4 Beta is live with the standard 90% outfitting discount, I took the opportunity to test actual shield strengths for various modules on various ships, in order to confirm the formula that was provided/confirmed by [FD] Mike Evans earlier in this thread.
And as it happens, that formula is not quite correct.
To explain the problem, let me first re-state the formula that was developed in this thread (and subsequently built in to tools such as
edshipyard.com and
coriolis.io). At each step, I'll work through a few examples to illustrate how it (supposedly) works.
- Each ship has baseline hull mass and shield strength values.
The Asp's base mass is 280 and its base shield strength is 140.
The mass is shown directly in the in-game shipyard, so we can be sure those figures are correct. The base shield strength is no longer shown directly, but back in EDv1.0 it was also shown in the in-game shipyard, and so far as I know (except for the Python) those values have never changed since. What has changed is the in-game shipyard, which no longer shows the base shield strength, but instead now shows the effective shield strength for a ship with its current outfitting (or, for ships you don't own yet, its original/default outfitting). This feature is what allowed me to test and audit the formula: change the generator, switch to a different ship, and check the new shield strength under "Stored Ships".
- Each shield generator class has three values which form an "optimal mass curve".
Class 3 shields use the curve 83 - 165 - 413.
Class 5 shields use the curve 203 - 405 - 1013.
The last two figures are shown in the in-game outfitter as the shield generator's "optimal mass" and "maximum mass", and [FD] Mike Evans was kind enough to provide us with the "minimum mass" figures for all shield classes earlier in this thread. So far the maximum is always 2.5x the optimal, and the minimum is always 0.5x optimal, but in theory there could someday be special (perhaps Power-specific) generators with differently shaped mass curves.
- Each shield generator rating has three values which form a "strength multiplier curve".
Rating E shields use the curve 0.3 - 0.8 - 1.3.
Rating C shields use the curve 0.5 - 1.0 - 1.5.
Rating A shields use the curve 0.7 - 1.2 - 1.7.
All of these values are hidden, but [FD] Mike Evans offered some generous hints, and later confirmed the values that were guessed. Originally this curve also always had the same shape with just a flat +0.1 per rating above E, but the special "Prismatic" generators effectively have all values multiplied by 1.2 by achieve the 20% strength bonus. There may also someday be other generators with differently shaped multiplier curves.
- Given a ship's hull mass and its generator's optimal mass curve, we can compute an "optimality" value ranging from -1 to 1; if the hull mass is greater than the generator's optimal mass, the "optimality" will be negative, and vice versa.
Asp,3E => (optimalMass - hullMass) / (maximumMass - optimalMass) == (165 - 280) / (413 - 165) ~= -0.4637
Asp,5E => (optimalMass - hullMass) / (optimalMass - minimumMass) == (405 - 280) / (405 - 203) ~= 0.6188
The "optimality" can never be less than -1, because that would mean the hull mass exceeds the generator's maximum mass, and in that case you can't even install the generator. The "optimality" can be greater than 1, however, if the hull mass is less than the generator's minimum mass; in this case we simply cap it at exactly 1.
- Using the optimality value, we perform a linear interpolation of two of the shield generator's multiplier curve values to find the effective multiplier; negative optimality is interpolated over the bottom half of the multiplier curve, and vice versa.
Asp,3E => (-1 * optimality * lowMultiplier) + ((1 + optimality) * midMultiplier) == ((-1) * (-0.4637) * 0.3) + ((1 + -0.4637) * 0.8) ~= 0.5682
Asp,5E => (optimality * highMultiplier) + ((1 - optimality) * midMultiplier) == (0.6188 * 1.3) + ((1 - 0.6188) * 0.8) ~= 1.1094
If you find it easier, you can also split the optimality into separate "bonus" and "penalty" values which each range from 0 to 1; avoiding the negatives makes the equations look a little neater, but it involves multiple values to indicate basically the same thing, so I prefer this style.
- Finally, we apply this effective multiplier to the ship's baseline shield strength to find its effective shield strength with that generator installed.
Asp,3E => (effMultiplier * baseShields) == (0.5682 * 140) ~= 79.548
Asp,5E => (effMultiplier * baseShields) == (1.1094 * 140) ~= 155.316
This graph illustrates the concept for rating E, C and A shields:

So far so good -- and yet the game disagrees. To see this for yourself, install a 5E shield on an Asp and then switch to another ship in the same station (buy a cheap Sidewinder if you have to). From the other ship, open up the shipyard again and find your Asp under "Stored Ships" to see what its actual shield strength is:
Asp,5E in-game: 152
Asp,3E in-game: 57
The class 5 is only off by a few points, but the 3E is really in trouble -- it has only 72% of the shield strength that our formula says it should!
To get a better handle on what's going on, I went through every single ship and tried installing an E-rating shield of every class that would fit, recording the actual in-game shield strength for each combination. Then just to be sure the pattern held, I did the same for C- and A-rating shields on a few select ships. This graph shows all of those results as square points, compared to the diamonds which represent the predicted values based on the formula:

Clearly there has been some kind of misunderstanding. [FD] Mike Evans indicated that the formula involved linear interpolation based on the hull mass and generator curves, and while there certainly is a direct relationship there, it is most definitely not linear. The effect is most pronounced at low optimality (hull mass ~1.5-2x optimal mass), but even on the top half, the actual data values have a slight downward bend compared to the straight line of the predicted values.
To correct for this I experimented with a few types of curves (sine, sigmoid, etc) but in the end, what seemed to work best was just a couple of hand-tuned magic number exponents. I make no claim that what follows is the "actual" algorithm that exists in the game code, because as [FD] Mike Evans pointed out, magic numbers are "a sure sign that it isn't what we're using." But in this instance they seem to achieve the correct results to within 1 shield point in almost all cases, so until Mike or someone else at [FD] chooses to clarify, it'll have to do.
My solution is this:
- If the optimality is negative, then add it to 1, raise it to the 2.425 power, and then subtract 1 again:
(optimality < 0) ? (-1 + ((1 + optimality) ^ 2.425))
- If the optimality is positive, then subtract it from 1, raise it to the 0.87 power, and then subtract it from 1 again:
(optimality >= 0) ? (1 - ((1 - optimality) ^ 0.87))
With these adjustments, the graph looks like this:

It's not quite perfect, but it's a lot better than it was.
edshipyard.com has been updated with this new algorithm, and
coriolis.io is of course more than welcome to lift the function for their use as well.
EDIT 1: Collected a bit more data for rating C shields and added them to the graphs, in response to folks who thought C might still be linear even when E and A are not.