programmable filter gives wrong results

error.pvsm (954.5 KB)

I have two .vtu files (field1 and field2) which contain one scalar field each defined on a rectangular grid.
I want to compute the absolute error and the relative error between them.

Attached is a .pvsm file which contain the two input files, and a programmable filter to compute the errors between them. Also, there are three ProbeLocation objects to evaluate the two input files and the computed errors at an arbitrary point in the grid. Lets call this point P.

Interestingly, the absolute error (field1(P) - field2(P)) is correct, which I can verify by the ProbeLocation on the two input files, however, the relative error (field1(P)-field2(P))/field1(P) is clearly wrong. In particular, I have field1(P) = 0.312567, field2(P) = 0.310265, (field1(P) - field2(P) = 0.00230214, (field1(P)-field2(P))/field1(P) = 0.0116339. I double-checked in matlab that the absolute error is correct, only the relative error is wrong.

This looks like a bug to me, or is there something I make wrong?

The vtu files are not contained in the pvsm state file. Could you share them?

energy_opt.vtu (4.6 KB)
energy_ref.vtu (4.5 KB)

Please find attached the .vtu files.

I took a look at your data. The filter is computing the correct values at every point. The problem is happening with the interpolation. Your Probe Location requires ParaView to interpolate a value inside a cell, and ParaView’s interpolation is not accurate (and there is no reasonable way it could ever be).

ParaView is using linear interpolation within your cells. (More specifically, it is using bi-linear interpolation in your quad cells.) That’s fine for expressions like ref-opt for the absolute error because that expression is linear. But your expression for relative error, (ref-opt)/ref is nonlinear. Your probe location is near where ref is close to zero, where the equation goes pretty crazy. That is why you are getting values that are so off.

You might want to consider using a different equation for relative error. The problem with dividing by each value is that the relative errors are fairly incomparable with each other. When the reference value is near zero, your error is going to shoot up even if you’re within the same range. And note that you are getting a NaN when the reference value is 0. Consider instead using the range of values (max(ref) - min(ref)) or the largest absolute value (max(abs(ref))). This will solve the problem of your relative error going wonky as the reference values approach 0 and will make your expressing linear, which will solve the interpolation error.

Thank you for taking your time! Let me please ask some follow-up questions:

Your probe location is near where ref is close to zero, where the equation goes pretty crazy. That is why you are getting values that are so off.

I also probed at different locations where ref is far from being zero and observed similar inaccuracies. I think the problem comes. But as you said, the relative error at the vertices is correct.

But your expression for relative error, (ref-opt)/ref is nonlinear.

What I did in matlab is (Interp(ref) - Interp(opt)) / Interp(ref), where Interp(…) denotes bilinear interpolation. But when I write (ref-opt)/ref in the programmable filter, this translates into
Interp( (ref-opt)/ref ). Is this the reason why the relative is not what I expected?

Consider instead using the range of values (max(ref) - min(ref)) or the largest absolute value (max(abs(ref)))

You mean defining the relative error as (ref - opt)/ max(abs(ref)) , for instance?

Correct. Matlab is interpolating the operands first whereas ParaView is interpolating the result. If you were to first probe the location and then apply your filter, you should get the expected result.

Yes, this is what I mean.

What do you mean by probe in this context? If I say probe, I refer to the “Probe Location” filter. But I do not know how this filter effects the programmable filter.
Or let me reformulate my question:
Currently, I write (ref-opt)/ref in the programmable filter. What would I have to write instead to get the “expected” results?

I mean the same thing. What I mean is to run Probe Location on the two input files and then run your Programmable Filter on the outputs of the probes. So, this is basically reversing the order of operations (probe location first then filter instead of filter then probe).

I see. But my understanding of Probe Location is to probe the fields of interest at a small number of points. So going your way, I would evaluate the relative error only at the points that I defined in Probe Location but I would not get a new field containing all points, right?

Correct. I’m not necessarily saying this should be the way you should go. That all depends on what you are doing this for. I was mostly just trying to demonstrate the problem and the differences between ParaView and Matlab.

More commonly, you might resample your data (say with Resample To Image) to a fine enough level where the difference from linear interpolation is tolerable.

Last question:

Is there a solution to have the relative error as a new field (just right now with the programmable filter), but with the formulae (Interp(ref) - Interp(opt) ) / Interp(ref) instead of Interp( (ref - opt)/ref ) ?

Short answer: no. That would require defining a field as a function, and that is just not supported in VTK.

The closest thing I can think of is to define an expression for the Calculator filter that could be applied wherever you need it. I would start by combining the ref and opt arrays into one dataset (which you can do with the Rename Arrays and Append Attributes filters. From there, you can use the simple Calculator filter to find the relative error whenever you need it. The Calculator filter now allows you to save expressions, which makes it easier to apply the same thing over and over again.