0

I am working on a library in F# that calculates rheological parameters for a fluid using MathNet.Numerics. However, I'm encountering an issue when implementing the BinghamModel and GetBinghamModelFit functions.

Here's the code I'm using:

open MathNet.Numerics
open MathNet.Numerics.Optimization
open MathNet.Numerics.LinearAlgebra

let BinghamModel (tau0: float) (mu: float) (shearRate: float) =
    tau0 + mu * shearRate

let GetBinghamModelFit (shearRate: float[]) (shearStress: float[]) =
    let results = Fit.Line(shearRate, shearStress)
    let Tau0, Mu = results
    let shearStressCalculated = Array.map (BinghamModel Tau0 Mu) shearRate
    let RSquared = GoodnessOfFit.RSquared(shearStressCalculated, shearStress)
    (Tau0, Mu, RSquared)

However, I'm encountering the following error during compilation: "One tuple type is a struct tuple, the other is a reference tuple"

It seems that the Fit.Line function returns a struct tuple (float * float) whereas I'm using reference tuples (float, float) in my code.

How can I resolve this issue and make my code work with the Fit.Line function provided by MathNet.Numerics? I have followed the example provided by the library creators, but it's not working as expected.

remark: I added the MathNet.Numerics and MathNet.Numerics.FSharp nugets to my project. Any insights or suggestions would be greatly appreciated!

I attempted different approaches to resolve the issue with the Fit.Line function in MathNet.Numerics returning a struct tuple (float * float) while I was using reference tuples (float, float) in my code.

Attempt 1:

let Tau0, Mu = ref(results)

Expected: I expected that using ref would allow me to capture the values from the struct tuple and store them in reference tuples. Outcome: Unfortunately, this approach did not work as expected, and I still encountered the error.

Attempt 2:

let Tau0, Mu = struct(results)

Expected: I hoped that using struct would somehow convert the struct tuple to reference tuples. Outcome: This approach also did not work as intended, and I still faced the same error.

Attempt 3:

let Tau0, Mu = box results :?> float * float

Expected: I thought that explicitly casting results to the expected tuple type might resolve the issue. Outcome: While the compiler did not raise any complaints, when I used the function in an F# script, it resulted in an error. In summary, despite trying these different approaches, I haven't been able to successfully convert the struct tuple (float * float) returned by Fit.Line into the reference tuple (float, float) that my code requires.

I appreciate any guidance or insights on how to properly handle this type conversion issue and make my code work seamlessly with the Fit.Line function.

2 Answers2

2

You should be able to use the struct keyword in the pattern part of let to deconstruct a struct tuple:

let struct(Tau, Mu) = Fit.Line(shearRate, shearStress)
Tarmil
  • 11,177
  • 30
  • 35
1

It looks like you are encountering a type mismatch issue between struct tuples and reference tuples. The Fit.Line function from MathNet.Numerics returns a struct tuple (float * float), but your code is expecting reference tuples (float, float).

To resolve this issue, you can use pattern matching to extract the values from the struct tuple returned by Fit.Line and assign them to reference tuples. Here's how you can modify your GetBinghamModelFit function to do that:

open MathNet.Numerics
open MathNet.Numerics.Optimization
open MathNet.Numerics.LinearAlgebra

let BinghamModel (tau0: float) (mu: float) (shearRate: float) =
    tau0 + mu * shearRate

let GetBinghamModelFit (shearRate: float[]) (shearStress: float[]) =
    let (|StructTuple|) (x, y) = x, y
    let results = Fit.Line(shearRate, shearStress)
    let StructTuple(Tau0, Mu) = results
    let shearStressCalculated = Array.map (BinghamModel Tau0 Mu) shearRate
    let RSquared = GoodnessOfFit.RSquared(shearStressCalculated, shearStress)
    (Tau0, Mu, RSquared)

In this modified version, we define a custom active pattern called "StructTuple" that allows us to pattern match against the struct tuple (float * float). Then, we use this active pattern to extract the values from the struct tuple and assign them to the reference tuples Tau0 and Mu.

T D Nguyen
  • 7,054
  • 4
  • 51
  • 71