Community Tip - Need to share some code when posting a question or reply? Make sure to use the "Insert code sample" menu option. Learn more! X
I would like some help to develop a loop in Mathcad that appends each intersection point between a piecewise linear curve and a set of straight lines, to the piecewise linear curve matrix. The attached Mathcad Prime 11 file contains the details and a fuller explanation of this request for assistance.
Solved! Go to Solution.
Here is your program fixed :
But I would rather prefer to make the program self-contained, independent from the existence of global worksheet variables ninc, Avals and Bvals. And it may also be a good idea to make it ORIGIN aware so that it does not rely on ORIGIN being set to zero:
You now can create a table similar to the one in the picture embedded in your sheet
or you may create a plot showing all the points of intersection
For the plot I had replaced two values in the C-vector to test my function in case a horizontal line is too low or too high and does not intersect the graph at all. Therefore the lines at height 24 and 36 are missing as they were replaced by lines in height -10 and 50. In this case my program returns a simple NaN instead of a row vector with x-values.
I am aware that you wrote that this case never occurs in your application, but I believe that a program should always be able to handle all possible cases whenever possible (provided that this can be achieved with reasonable programming effort).
EDIT: Added a version where multiple identical values such as the duplicate 500 in the last row are removed.
Hope that the attached Prime 11 file will help.
Hi
Like this:
Cheers
Terry
Thanks Terry. This is a neat solution and does achieve what I had requested. Grateful for the time you spent on it and help it provided me in seeing alternative approaches to solving the problem.
I am impressed by the short time between posting the request for help and the provision of your answer.
Here is your program fixed :
But I would rather prefer to make the program self-contained, independent from the existence of global worksheet variables ninc, Avals and Bvals. And it may also be a good idea to make it ORIGIN aware so that it does not rely on ORIGIN being set to zero:
You now can create a table similar to the one in the picture embedded in your sheet
or you may create a plot showing all the points of intersection
For the plot I had replaced two values in the C-vector to test my function in case a horizontal line is too low or too high and does not intersect the graph at all. Therefore the lines at height 24 and 36 are missing as they were replaced by lines in height -10 and 50. In this case my program returns a simple NaN instead of a row vector with x-values.
I am aware that you wrote that this case never occurs in your application, but I believe that a program should always be able to handle all possible cases whenever possible (provided that this can be achieved with reasonable programming effort).
EDIT: Added a version where multiple identical values such as the duplicate 500 in the last row are removed.
Hope that the attached Prime 11 file will help.
Thanks. This is awesome!! Your solution not only solved the problem as per my request, but also provided a refinement that corrected other issues I had not mentioned in my earlier post regarding the removal of duplicates. I appreciate the fact you fixed my attempt as well as providing a better version.
If you have time, would you please add a function to the end of your solution that would determine for each constant y value in Cvals matrix, the area under the discretized curve between y = 0 and y = the constant in the corresponding Cvals row? For example, when a row in Cvals = 24, then the area calculated would be as shaded in purple in the figure posted with this additional request. Obviously I will need to add units to the values. Mostly interested in how to write the loop so that it knows when to use the trapezoidal rule based on the coordinates of the discretized curve and when to use the coordinates that the earlier function interpolated based on intersecting the y = constant lines.
I tried to add units and ran into some difficulty with the NaN values, which I subsequently filtered but it is still a bit of a mess. I'd appreciate any help you can provide in correcting it.
Unfortunately its necessary to apply units to NaN's as well.
So you either may use the "SIUnitsOf()" function or, because you know the units (meter) needed apply them directly
After doing so the plot works as intended
BTW, you had overlooked that I also had changed Cval#2 from 12 to 10
The points in your second plot are all placed to the far left because you forgot to change the unit in the x-axis placeholder from m to mm.
Concerning the areas see my reply below.
I guess that calculating the area would be easier to accomplish if we DON't remove the duplicate values we get when the horizontal line runs through one of the points defining the polygon.
If we don't remove the duplicates, the algorithm could be
1) Create interpolating function f(x) using "linterp"
2) integral of f(x) from x=0 to x=first x-value in list of intersections.
3) Add area of rectangle from current x-value to next in list, height is C
4) Add Integral from current x to next in list
Repeat step 3 and 4 until x-value = last x-value in vector A.
EDIT: No need to use the duplicate values and adding multiple integrals and rectangles!
Define the interpolating function f(x) and simply integrate from first to last value in A the function min(f(x),Cval).
Pls check if the results are correct
Remark: Te values show numerical round-offs. Last area should be exactly 15000.
Precision can be increased by setting the system variable TOL from its default 10^-3 to a lower value - either in the menu or by assignment in the sheet.
EDIT2: Added an alternative way to avoid duplicate values ("Intersect4" in attached sheet)
Prime 11 sheet attached
Thank you!! This is excellent. I will go through the solution you provided and let you know if I need any additional clarification. The help you have provided is very much appreciated.
Please find some further questions towards the end of the attached file. I am hopeful that this will be the last of my questions on this topic. I would appreciate any help you can provide with any of the questions.
See my comments in the file.
Area calculation cam be quite tricky if horizontals run through a data point.
We would have somehow to distinguish between "horizontal crosses interpolation curve" and "horizontal does not cross (just touch at a peak)".
Added an Intersect6 function which returns two values in case the horizontal runs through a local maximum (peak) or minimum, but just one value if it runs through a data point but crosses.
That way it was easy to write functions to calculate the demanded areas.
Sometimes it helps to sleep on a problem overnight. 😄
And at the morning its easier than you thought!
Here are ways to calculate all desired areas without using the 'Intersect6' function introduced earlier (and thus without repeated intersection determination).
And here are alternatives to these functions for your choice
And here an attempt to explain why/how they work
The variants with the if function might be the easiest to grasp.
EDIT: Replaced the somewhat awkward "shade" function by a more generic "hatch" function which can be used to shade/hatch the area between any two curves in a given range of x-values.
Prime 11 sheet attached
Thank you once again!! Very impressive solutions and a huge help to me.
Would you please show me how to write a loop that would produce an array of results corresponding to each "Area1(dj)" result for all values in the dj array (i.e., Cvals)?
No loop necessary - use vectorization:
But of course you can create the same result with a programmed for-loop
EDIT: I just noticed that I already had shown how to create the desired array in the file I posted!!???
Thanks yet again. Much appreciated.
Please find attached a file with some more questions I would appreciate some help resolving. The questions are at the end of the previous solutions provided. The file also includes the issue mentioned recently regarding checking the vec1 function against the inbuilt vec function. It is at the very end of the file.
See the comments in the attached file.
I must confess that in the meantime I lost track of your file and this thread.
I would suggest that you create a new file from scratch, using units right from the start and including only the real necessary parts. It may make sense to open a new thread for new questions.
Thank you. Much appreciated.
I agree regarding it making sense to start a new thread for new questions.
Thus, I will follow your suggestion for any further questions.
