Why does the larger of two curves have the lower integrated value using trapz from numpy?

Using trapz from numpy I get the following:

lewis_result_outer = np.trapz(lewis_few_elements_outer_y, x=lewis_few_elements_outer_x)
lewis_result_inner = np.trapz(lewis_few_elements_inner_y, x=lewis_few_elements_inner_x)
lewis_result = lewis_result_inner - lewis_result_outer
lewis_result_outer : 99.02254450000001
lewis_result_inner : 98.324206
lewis_result: -0.6983385000000055

Looking at a plot I made of the inner and outer result this is clearly wrong, figure code:

   figure(1)
    plt.plot(lewis_few_elements_outer_x,      # X-axis
             lewis_few_elements_outer_y,      # Y-axis
             's',                       # Marker type
             color = 'green',           # Marker color
             markersize=6,              # Marker size
             alpha=0.5,                 # Gennemsigtighed
             label='Lewis 40 element, outer')                 
    plt.plot(lewis_few_elements_inner_x,      # X-axis
             lewis_few_elements_inner_y,      # Y-axis
             's',                       # Marker type
             color = 'blue',            # Marker color
             markersize=6,              # Marker size
             alpha=0.5,                 # Gennemsigtighed
             label='Lewis 40 element, inner')
    plt.xlabel("r/R", size=20)          # X-label name
    plt.ylabel("Cp for int", size=20)   # Y-label name
    plt.legend()
    plt.show

Link to plot img

The inner should be larger than the outer. However it's not, why?

I did make sure that the list I use are ordered as follows:

lewis_few_elements_outer_y
Out[251]: 
[100.66,99.867,99.79,99.676,99.57,99.504,99.445,99.405,99.366,99.34,99.334,99.387,99.527,99.743,99.921,100.068,100.178,100.268,100.322]

lewis_few_elements_outer_x
Out[252]: 
[0.004,0.015,0.04,0.076,0.125,0.174,0.243,0.312,0.38,0.46,0.541,0.618,0.692, 0.762,0.828,0.883,0.925,0.959,0.998]

lewis_few_elements_inner_y
Out[253]: 
[100.707,99.939,99.887,99.82,99.762,99.734,99.706,99.697,99.684,99.671,99.657,99.672,99.755,99.902,100.012,100.121,100.212,100.296]

lewis_few_elements_inner_x
Out[254]: 
[0.003,0.015,0.039,0.074,0.118,0.177,0.239,0.309,0.38,0.458,0.543,0.617,0.691,0.762,0.826,0.884,0.927,0.988]

Solution 1:

Incidental, but you can trivially verify that trapz(y, x) is just

(0.5 * (y[1:] + y[:-1]) * (x[1:] - x[:-1])).sum()

As it turns out, the issue is one of scaling and span. Your chart shows the segments as being wildly different, but notice that the height difference is on the order of ~0.4 out of ~100. Here is a plot showing the segments you are adding up in a more representative scale:

enter image description here

Very clearly, lewis_few_elements_outer_x spans a noticeably wider domain than lewis_few_elements_inner_x. So no matter what the tiny differences at the top of the function may look like, it's the right margin that matters.

>>> np.ptp(lewis_few_elements_outer_x)
0.994
>>> np.ptp(lewis_few_elements_inner_x)
0.985

Off the cuff, you're trading a ~0.3% height decrease for a ~1% increase in width, and sure enough, the discrepancy is approximately 0.7% in favor of the wider dataset.

Plot code for reference:

l, = plt.plot(lewis_few_elements_inner_x, lewis_few_elements_inner_y, label='inner')
for x, y in zip(lewis_few_elements_inner_x, lewis_few_elements_inner_y):
    plt.plot([x, x], [y, 0], c=l.get_color())
l, = plt.plot(lewis_few_elements_outer_x, lewis_few_elements_outer_y, label='outer')
for x, y in zip(lewis_few_elements_outer_x, lewis_few_elements_outer_y):
    plt.plot([x, x], [y, 0], c=l.get_color())
plt.legend()