1

I have two data sets in the form dat1={{x,y,z}, f1[x,y,z]} and dat2={{x,y,z}, f2[x,y,z]} I want to fit a model with common parameters. A minimum example: first these two functions to synthesize some data

f1[{x_, y_, z_}] = 
  G0 - Sqrt[G^2 + c24^2 x^2 + c24^2 y^2 + c23^2 z^2];
f2[{x_, y_, z_}] = 
  G0 + Sqrt[G^2 + c24^2 x^2 + c24^2 y^2 + c23^2 z^2];
G = c01 - c11 z^2 - c12 (x^2 + y^2);
G0 = c02 + c21 z^2 + c22 (x^2 + y^2);   

the points xyzdata={x,y,z} are known

xyzdata={{1.28228, 0., 1.28228}, {1.21817, 0., 1.21817}, {1.15405, 0., 
  1.15405}, {1.08994, 0., 1.08994}, {1.02583, 0., 1.02583}, {0.961712,
   0., 0.961712}, {0.897598, 0., 0.897598}, {0.833484, 0., 
  0.833484}, {0.76937, 0., 0.76937}, {0.705256, 0., 
  0.705256}, {0.641141, 0., 0.641141}, {0.577027, 0., 
  0.577027}, {0.512913, 0., 0.512913}, {0.448799, 0., 
  0.448799}, {0.384685, 0., 0.384685}, {0.320571, 0., 
  0.320571}, {0.256457, 0., 0.256457}, {0.192342, 0., 
  0.192342}, {0.128228, 0., 0.128228}, {0.0641141, 0., 
  0.0641141}, {2.50691*10^-16, 0., 2.50691*10^-16}, {0., 0., 
  0.}, {0.0641141, 0., 0.}, {0.128228, 0., 0.}, {0.192342, 0., 
  0.}, {0.256457, 0., 0.}, {0.320571, 0., 0.}, {0.384685, 0., 
  0.}, {0.448799, 0., 0.}, {0.512913, 0., 0.}, {0.577027, 0., 
  0.}, {0.641141, 0., 0.}, {0.705256, 0., 0.}, {0.76937, 0., 
  0.}, {0.833484, 0., 0.}, {0.897598, 0., 0.}, {0.961712, 0., 
  0.}, {1.02583, 0., 0.}, {1.08994, 0., 0.}, {1.15405, 0., 
  0.}, {1.21817, 0., 0.}};       

Now we get the two data as

Block[{c01 = 0.108, c02 = 0.052, c11 = -0.15, c12 = 1.42, 
  c21 = 0.075, , c22 = 0.425, c23 = -0.34, c24 = 0.51, kx, ky, kz}, 
 data1 = Table[{xyzdata[[i]], f1[xyzdata[[i]]]}, {i, Length@xyzdata}];
  data2 = 
  Table[{xyzdata[[i]], f2[xyzdata[[i]]]}, {i, 1, Length@xyzdata}]]     

Finally, we can plot these data as

ListPlot[{data1[[All, 2]], data2[[All, 2]]}, PlotRange -> {-1, 1}, 
 PlotLegends -> {"dat1", "dat2"}]       

enter image description here

my question is assuming that we don't know the constants {c01,c02,c11,c12,c21,c22,c23,c24} that are used to generate data1 and data1 how can we fit the data to get the constants?

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
MMA13
  • 4,664
  • 3
  • 15
  • 21

2 Answers2

5

Fitting functions with shared parameters is what I wrote ResourceFunction["MultiNonlinearModelFit"] for. You just need to punch the data into the right format:

fit = ResourceFunction["MultiNonlinearModelFit"][
  {
   Flatten /@ data1,
   Flatten /@ data2
   },
  {f1[{x, y, z}], f2[{x, y, z}]},
  {c01, c02, c11, c12, c21, c22, c23, c24},
  {x, y, z}
 ]
fit["BestFitParameters"]
Sjoerd Smit
  • 23,370
  • 46
  • 75
2

To get a fit, we must first bring the data in a suitable form: {x,y,z,f[xy,z]} (note, define G and G0= before f1 and f2):

dat1 = Map[Flatten, data1, {1}];
dat2 = Map[Flatten, data2, {1}];

With the data adapted we can do the fit:

fun1 = NonlinearModelFit[dat1, 
   f1[{x, y, z}], {c01, c11, c12, c02, c21, c22, c23, c24}, {x, y, z}];
fun2 = NonlinearModelFit[dat2, 
   f2[{x, y, z}], {c01, c11, c12, c02, c21, c22, c23, c24}, {x, y, 
    z}];

To get the fitted parameters:

fun1["BestFitParameters"]

{c01 -> 0.108, c11 -> -0.15, c12 -> 1.42, c02 -> 0.052, c21 -> 0.075, c22 -> 0.425, c23 -> -0.34, c24 -> 0.51}

fun2["BestFitParameters"]

{c01 -> 0.108, c11 -> -0.15, c12 -> 1.42, c02 -> 0.052, c21 -> 0.075, c22 -> 0.425, c23 -> -0.34, c24 -> 0.51}

Daniel Huber
  • 51,463
  • 1
  • 23
  • 57