0
$\begingroup$

I have a system of DDEs with 2 free parameters I solved with NDSolve, as you can see below

    n = 1;
system[l_?NumericQ, 
  eps_] := {m'[t] == 2/n*((1 - m[t])/2*lp[t] - (1 + m[t])/2*lm[t]),
  lp'[t] == 
   1/n *((1 + m[t])/2*((1 - m[t])/2 - lm[t])) - 
    1/n *((1 + m[t - l])/2*((1 - m[t - l])/2 - lm[t - l])),
  lm'[t] == 
   1/n *((1 - m[t])/2*((1 + m[t])/2 - lp[t])) - 
    1/n *((1 - m[t - l])/2*((1 + m[t - l])/2 - lp[t - l])),
  m[t /; t <= l] == eps*(2*E^(-t/(2 n)) - 1), 
  lp[t /; t <= l] == (1 - eps)/2*(1 - E^(-t/(2 n))), 
  lm[t /; t <= l] == (1 - eps)/2*(1 - E^(-t/(2 n)))}
sol[l_?NumericQ, eps_] := 
  NDSolve[system[l, eps], {m, lp, lm}, {t, 0, 300}];

This method works and gives me the chance of exploring the solutions of my system varying the two parameters l and eps.

Now I would like to fit a dataset I imported using the solution provided by NDSolve as a model, but I just can't define the model correctly to make it work with FindFit or similars.

I tried with

model[t_, a_, b_, c_] := m[t + a] /. sol[b, c]

and variations (tried Evaluate, adding ?NumericQ and so on) but it always gives me the error

ReplaceAll::reps: {sol[b,c]} is neither a list of replacement rules nor a valid dispatch table, and so cannot be used for replacing.

I think the problem is Mathematica attempts at evaluating m[t] with sol, which contains no numbers, just parameters, and it fails at it. How can I fix it to make it suitable for fitting?

And please excuse me if I couldn't find the answer among similar questions posted, but I find Mathematica very criptic (yet useful!).

Thanks in advance

EDIT: Here's the data I want to fit (orange) and the solution of my system I'd like to use (I have manually found it with Manipulate). Manual overlap

Dataset to fit:

t, m
    {{0, 0.007}, {1, -0.011}, {2, -0.017}, {3, -0.036}, {4, -0.044}, {5, \
-0.045}, {6, -0.043}, {7, -0.053}, {8, -0.059}, {9, -0.06}, {10, \
-0.061}, {11, -0.077}, {12, -0.084}, {13, -0.055}, {14, -0.054}, {15, \
-0.057}, {16, -0.061}, {17, -0.058}, {18, -0.041}, {19, -0.024}, {20, \
-0.018}, {21, 0.006}, {22, 0.032}, {23, 0.017}, {24, -0.002}, {25, 
  0.02}, {26, 0.042}, {27, 0.067}, {28, 0.062}, {29, 0.062}, {30, 
  0.053}, {31, 0.052}, {32, 0.06}, {33, 0.068}, {34, 0.088}, {35, 
  0.065}, {36, 0.052}, {37, 0.074}, {38, 0.072}, {39, 0.075}, {40, 
  0.087}, {41, 0.074}, {42, 0.046}, {43, 0.018}, {44, 0.014}, {45, 
  0.015}, {46, 0.005}, {47, 0.007}, {48, 0.019}, {49, 0.014}, {50, 
  0.004}, {51, -0.002}, {52, 
  0.001}, {53, -0.006}, {54, -0.021}, {55, -0.024}, {56, -0.018}, \
{57, -0.026}, {58, -0.03}, {59, -0.047}, {60, -0.047}, {61, -0.063}, \
{62, -0.081}}

UPDATE: I hope this might be useful to somebody. I've found a way of passing my model to FindFit or NonLinearModelFit:

n = 1;
model[l_?NumberQ, 
  eps_?NumberQ] := (model[a, b] = 
   Module[{m, lp, lm, t}, 
    First[m /. 
      NDSolve[{m'[t] == 2/n*((1 - m[t])/2*lp[t] - (1 + m[t])/2*lm[t]),
        lp'[t] == 
         1/n *((1 + m[t])/2*((1 - m[t])/2 - lm[t])) - 
          1/n *((1 + m[t - l])/2*((1 - m[t - l])/2 - lm[t - l])),
        lm'[t] == 
         1/n *((1 - m[t])/2*((1 + m[t])/2 - lp[t])) - 
          1/n *((1 - m[t - l])/2*((1 + m[t - l])/2 - lp[t - l])),
        m[t /; t <= l] == eps*(2*E^(-t/(2 n)) - 1), 
        lp[t /; t <= l] == (1 - eps)/2*(1 - E^(-t/(2 n))), 
        lm[t /; t <= l] == (1 - eps)/2*(1 - E^(-t/(2 n)))}, {m, lp, 
        lm}, {t, 0, 300}]]])
nlm = FindFit[
  death, {model[a, b][
    t + c], {11 < a < 12}, {0.0001 < b < 0.01}, {150 < c < 180}}, {{a,
     11.2}, {b, 0.001}, {c, 160}}, t]

If I run this, my code works, but the answer isn't quite the one I expected (although I set the initial values of the parameters with the one I found manually with Manipulate).

Does anybody know how I can improve FindFit or NonLinearModelFit? The documentation is not explanatory at all.

$\endgroup$
10
  • $\begingroup$ sol returns functions for m,lp,lm, but you model only contains m? Further, where are the data you want to fit.? $\endgroup$ Commented Feb 7, 2023 at 11:00
  • $\begingroup$ As for now I am just interested in using m to fit some data I have correctly imported from a csv. I'll add a pic to the post. Thank you @DanielHuber $\endgroup$ Commented Feb 7, 2023 at 11:07
  • $\begingroup$ @GiovanniPalermo Please provide your data too $\endgroup$ Commented Feb 7, 2023 at 12:37
  • 2
    $\begingroup$ Have you seen ParametricNDSolve? See the docs for it and look under Applications > Parameter Fitting $\endgroup$
    – Michael E2
    Commented Feb 7, 2023 at 13:19
  • $\begingroup$ @MichaelE2 tried that too, but the issue still remains, I can't properly access the solution for m. The only difference with the example in the docs is that I have a system, so the output isn't one variable but a list of 3 variables. I am trying to save the solutions with sol = ParametricNDSolveValue[ system, {m, lp, lm}, {t, 0, 300}, {l, eps}]. It returns a ParametricFunction, then I should be able to access m as m=sol[l,eps][[1]][t] and plot it, but it just plots a blank graph $\endgroup$ Commented Feb 7, 2023 at 14:20

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.