unit Minimisation;
{ ============================================================================= }
{ les procédures de minimisation                                                }
{ ============================================================================= }
{ 14.08.03:FO: première version de cette unité                                  }
{ ============================================================================= }
{ 04.02.03:FO: nouvelle procédure de la calcul de la différence RMS entre 2 vecteurs }
{ ============================================================================= }
{ A FAIRE                                                                       }
{ * simplifier l'écriture des "minimisationCrawling"                            }
{   pour alléger un peu les procedures                                          }
{ NOTA                                                                          }
{ * dans les minimisations, c'est la valeur zYN qui est prioritaire             }
{   si zYN repasse à -1, il est possible que les zCorr restent a leurs valeurs précédentes  }
{   2 possiblités : rendre zYN prioritaire ou bien réinitialiser zCorr quand nécesaire }

interface

uses math387,MtxVec,DataReflec;

function RMS(var R1,R2:Tvec):double;
function Difference2(var R1,R1s,R2:Tvec;ponderationType:string):double;
function Difference(var MyDataExp,MyDataCalc:TDataReflectivity;var MyExpCond:TExperimentalParameters):double;
Procedure MinimisationCrawling(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMultiLayer:TMultiLayer;var MyProfiles:TProfiles;var MyDataExp,MyDataCalc:TDataReflectivity);
Procedure MinimisationCrawling_P(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMultiLayer:TMultiLayer;var MyProfiles:TProfiles;var MyDataExp,MyDataCalc:TDataReflectivity);
Procedure MinimisationCrawling_SF(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMultiLayer:TMultiLayer;var MyProfiles:TProfiles;var MyDataExp,MyDataCalc:TDataReflectivity);
Procedure MinimisationCrawling_SF_HF(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMultiLayer:TMultiLayer;var MyProfiles:TProfiles;var MyDataExp,MyDataCalc:TDataReflectivity);

Procedure MinimisationCrawling_PD(randomness:integer;var MyEP:TExperimentalParameters;var MyML1,MyML2:TMultiLayer;var MyProfiles:TProfiles;var MyDataExp,MyDC1,MyDC2:TDataReflectivity);
Procedure MinimisationCrawling_SF_PD(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMultiLayer,MyMultiLayer2:TMultiLayer;var MyProfiles:TProfiles;var MyDataExp,MyDataCalc,MyDataCalc2:TDataReflectivity);

Procedure MinimisationCrawlingMDS(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMDS_ML:array of TMultiLayer;var MyProfiles:TProfiles;var MyMDSfit,MyMDS_dataCalc:array of TDataReflectivity);
Procedure MinimisationCrawlingMDS_P(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMDS_ML:array of TMultiLayer;var MyProfiles:TProfiles;var MyMDSfit,MyMDS_dataCalc:array of TDataReflectivity);

implementation

uses forms,sysUtils,calculReflec, constants, SimulReflecForm;

{ procédure de calcul de la différence aux moindres carrés entre deux vecteurs  }
{ pas de pondération                                                            }
{ INPUT: R1 vecteurs de points expérimentaux                               }
{        R1s l'erreur statistique sur ces points expérimenatux             }
{        R1s correspond a la fluctuation statistique                       }
{        R2, les vaelurs théoriques calculées                              }
{        m, la méthode de pondération; 0 aucune, 1 statistique, 2 autre    }
{        -1 a des fins de test uniquement                                  }
{ OUTPUT: la différence aux moindres carrés                                }
function RMS(var R1,R2:Tvec):double;
var diff:double;
    i:integer;
    nbrPoints:integer;
begin
     nbrPoints:=R1.length;
     diff:=0;
     for i:=0 to nbrPoints-1 do diff:=diff+sqr(R1.values[i]-R2.values[i]);
     result:=diff;
end;


{ procédure de calcul de la différence entre deux courbes avec pondération }
{ INPUT: R1 vecteurs de points expérimentaux                               }
{        R1s l'erreur statistique sur ces points expérimenatux             }
{        R1s correspond a la fluctuation statistique                       }
{        R2, les vaelurs théoriques calculées                              }
{        m, la méthode de pondération; 0 aucune, 1 statistique, 2 autre    }
{        -1 a des fins de test uniquement                                  }
{ OUTPUT: la différence aux moindres carrés                                }
function Difference2(var R1,R1s,R2:Tvec;ponderationType:string):double;
var diff:double;
    i:integer;
    nbrPoints:integer;
begin
     nbrPoints:=R1.length;
     diff:=0;
     if ponderationType = 'linear' then { linear version OTT }
     begin
          for i:=0 to nbrPoints-1 do
          begin { version maison FO }
            if R1.values[i]<>0 then diff:=diff+sqr((R1.values[i]-R2.values[i])/(R1.values[i]+R2.values[i]));
          end;
     end;
     if ponderationType = 'log' then { abs(log) }
     begin
          for i:=0 to nbrPoints-1 do
          begin
            if R1.values[i]<>0 then diff:=diff+abs(log10(R1.values[i])-log10(R2.values[i]));
          end;
     end;
     if ponderationType = 'log²' then { log² type Julich}
     begin
          for i:=0 to nbrPoints-1 do
          begin
            if R1.values[i]<>0 then diff:=diff+sqr(log10(R1.values[i])-log10(R2.values[i]));
          end;
     end;
{ les pondérations suivantes sont très inefficaces }
{     if ponderationType = 'least square (linear)' then
     begin
          for i:=0 to nbrPoints-1 do
          begin
            if R1.values[i]<>0 then diff:=diff+sqr((R1.values[i]-R2.values[i])/R1s.values[i]);
          end;
     end;
     if ponderationType = 'least square (log)' then
     begin
          for i:=0 to nbrPoints-1 do
          begin
            if R1.values[i]<>0 then diff:=diff+sqr(R2.values[i]*(log10(R1.values[i])-log10(R2.values[i]))/(R1s.values[i]));
          end;
     end;
     if ponderationType = 'test' then
     begin
          for i:=0 to nbrPoints-1 do
          begin
            if R1.values[i]<>0 then diff:=diff+sqr(R1.values[i]-R2.values[i]);
          end;
     end;       }
     result:=diff;
end;

{ fonction de calcul de la difference pondérées entre deux courbes de réflectivité }
{ fonction "haut niveau" % Difference2                                          }
function Difference(var MyDataExp,MyDataCalc:TDataReflectivity;var MyExpCond:TExperimentalParameters):double;
var diff:double;
begin
   if MyDataExp.PolarisationType='non polarised'
   then begin
        diff:=difference2(MyDataExp.R,MyDataExp.Rs,MyDataCalc.R,MyExpCond.PonderationType);
        end;
   if MyDataExp.PolarisationType='polarised'
   then begin
        diff:=difference2(MyDataExp.Rup,MyDataExp.RupS,MyDataCalc.Rup,MyExpCond.PonderationType)
                +difference2(MyDataExp.Rdo,MyDataExp.RdoS,MyDataCalc.Rdo,MyExpCond.PonderationType);
        end;
   if MyDataExp.PolarisationType='with spin-flip'
   then begin
        diff:=difference2(MyDataExp.Ruu,MyDataExp.RuuS,MyDataCalc.Ruu,MyExpCond.PonderationType)
                +difference2(MyDataExp.Rdd,MyDataExp.RddS,MyDataCalc.Rdd,MyExpCond.PonderationType)
                +difference2(MyDataExp.Rud,MyDataExp.RudS,MyDataCalc.Rud,MyExpCond.PonderationType);
        end;
   if MyDataExp.PolarisationType='with SF high field'
   then begin
        diff:=difference2(MyDataExp.Ruu,MyDataExp.RuuS,MyDataCalc.Ruu,MyExpCond.PonderationType)
                +difference2(MyDataExp.Rdd,MyDataExp.RddS,MyDataCalc.Rdd,MyExpCond.PonderationType)
                +difference2(MyDataExp.Rud,MyDataExp.RudS,MyDataCalc.Rud,MyExpCond.PonderationType)
                +difference2(MyDataExp.Rdu,MyDataExp.RduS,MyDataCalc.Rdu,MyExpCond.PonderationType);
        end;
   result:=diff;
end;


{ ============================================================================= }
{ PROCEDURES DE MINIMISATION                                                    }
{ ============================================================================= }

{ =======================================================================}
{ MINIMISATION AVEC NOUVEAUX TYPES DE DATA                               }
{ procédure de minimisation utilisant le crawling                        }
{ on déplace chaque parametre d'une quantité step en + ou en - et        }
{ on garde la meilleure valeur                                           }
{ NOTA : Il faut que les paramètres de DataCalc et DateExp soient compatible }
Procedure MinimisationCrawling(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMultiLayer:TMultiLayer;var MyProfiles:TProfiles;var MyDataExp,MyDataCalc:TDataReflectivity);
var i,nIter,nbrIter: integer;
    chi,chimoins,chiplus,aux:double; { valeurs du paramètre , point de départ, dpart + step, depart - step }

function CalculDifference:double;
var diff,diffSmooth:double;
begin
   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   { application du facteur de normalisation }
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
   { Calcul de la différence aux moindres carrés }
   diff:=difference2(MyDataExp.R,MyDataExp.Rs,MyDataCalc.R,MyExperimentalParameters.PonderationType);
   { CE N'EST PAS LA MEILLEURE PLACE; ON DEVRAIT CALCULER CA SEULEMENT SI UN PARA DU PROFIL CHANGE }
   { ajout de la ponderation liée au profil de type smooth }
   if MyMultiLayer.profiled
   then diffSmooth:=MyMultiLayer.SmoothProfile(MyProfiles) else diffSmooth:=0;
   result:=diff+diffSmooth;
end;

begin
     StopFittingFlag:=false;
     with SimulReflecWindow do
        begin FittingStatus.caption:='Fitting...';FittingStatus.update;
              nbrIter:=spinEditNbrIter.value end;
     { calcul de l'ecart au point de depart }
     chi:=CalculDifference;
     { on boucle sur les différents paramètres }
     for niter:=1 to round(NbrIter/(100-randomness)*100) do
     begin
        with SimulReflecWindow do begin IterCrt.caption:=IntToStr(nIter);IterCrt.update; end;
        { fit sur la normalisation }
        with MyExperimentalParameters do
        begin
        if (FitNormalisation=true) and (random(100)>=randomness) then begin
                                 aux:=normalisationFactor;
                                 normalisationFactor:=aux-normalisationFactorStep;
                                 chiMoins:=CalculDifference;
                                 normalisationFactor:=aux+normalisationFactorStep;
                                 chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin normalisationfactor:=aux-normalisationFactorStep;chi:=chiMoins end
                                 else if chiPlus<chi then begin normalisationfactor:=aux+normalisationFactorStep;chi:=chiMoins;chi:=chiPlus end
                                                     else begin normalisationfactor:=aux;  end
                                 end;
        end;
        { on boucle sur toutes les couches du système }
        with MyMultilayer do
        for i:=0 to nbrLayers-1 do
        begin
             if (zYN[i]=0) and (random(100)>=randomness)
             then if (Ord(zCorr[i])>=65) and (Ord(zCorr[i])<=70)
                  then begin     aux:=z[i];z[i]:=aux-zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chiMoins:=CalculDifference;
                                 z[i]:=aux+zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin z[i]:=aux-zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin z[i]:=aux+zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chi:=chiPlus end
                                                     else begin z[i]:=aux;MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);  end
                                 end
                  else begin     aux:=z[i];z[i]:=aux-zStep[i];chiMoins:=CalculDifference;
                                 z[i]:=aux+zStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin z[i]:=aux-zStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin z[i]:=aux+zStep[i];chi:=chiPlus end
                                                     else begin z[i]:=aux;  end
                                 end;

            if MyExperimentalParameters.Particles='neutrons' then
            begin
             if (dYN[i]=0) and (random(100)>=randomness)
             then if (Ord(dCorr[i])>=65) and (Ord(dCorr[i])<=70)
                  then begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]); end;
                                 end
                  else begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i] end;
                                 end;
             if (bYN[i]=0) and (random(100)>=randomness)
             then if (Ord(bCorr[i])>=65) and (Ord(bCorr[i])<=70)
                  then begin     aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chiMoins:=CalculDifference;
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i];MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]); end
                                 end
                  else begin     aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];chiMoins:=CalculDifference;
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i] end
                                 end;
             if (biYN[i]=0) and (random(100)>=randomness)
             then if (Ord(biCorr[i])>=65) and (Ord(biCorr[i])<=70)
                  then begin     aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chiMoins:=CalculDifference;
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]); end
                                 end
                  else begin     aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiMoins:=CalculDifference;
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i]; end
                                 end;
            end;
            if MyExperimentalParameters.Particles='xrays' then
            begin
             if (dYN[i]=0) and (random(100)>=randomness)
             then if (Ord(dCorr[i])>=65) and (Ord(dCorr[i])<=70)
                  then begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];MyMultiLayer.SetCorrParams(dCorr[i],'rho_x',d[i]);chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];MyMultiLayer.SetCorrParams(dCorr[i],'rho_x',d[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];MyMultiLayer.SetCorrParams(dCorr[i],'rho_x',d[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];MyMultiLayer.SetCorrParams(dCorr[i],'rho_x',d[i]);chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];MyMultiLayer.SetCorrParams(dCorr[i],'rho_x',d[i]); end;
                                 end
                  else begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i]; end;
                                 end;
             if (fYN[i]=0) and (random(100)>=randomness)
             then if (Ord(fCorr[i])>=65) and (Ord(fCorr[i])<=70)
                  then begin     aux:=f[i];f[i]:=aux-fStep[i];V[i]:=Cte*d[i]*f[i];MyMultiLayer.SetCorrParams(fCorr[i],'f',f[i]);chiMoins:=CalculDifference;
                                 f[i]:=aux+fStep[i];V[i]:=Cte*d[i]*f[i];MyMultiLayer.SetCorrParams(fCorr[i],'f',f[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin f[i]:=aux-fStep[i];V[i]:=Cte*d[i]*f[i];MyMultiLayer.SetCorrParams(fCorr[i],'f',f[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin f[i]:=aux+fStep[i];V[i]:=Cte*d[i]*f[i];MyMultiLayer.SetCorrParams(fCorr[i],'f',f[i]);chi:=chiPlus end
                                                     else begin f[i]:=aux;V[i]:=Cte*d[i]*f[i];MyMultiLayer.SetCorrParams(fCorr[i],'f',f[i]); end
                                 end
                  else begin     aux:=f[i];f[i]:=aux-fStep[i];V[i]:=Cte*d[i]*f[i];chiMoins:=CalculDifference;
                                 f[i]:=aux+fStep[i];V[i]:=Cte*d[i]*f[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin f[i]:=aux-fStep[i];V[i]:=Cte*d[i]*f[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin f[i]:=aux+fStep[i];V[i]:=Cte*d[i]*f[i];chi:=chiPlus end
                                                     else begin f[i]:=aux;V[i]:=Cte*d[i]*f[i]; end
                                 end;
             if (fiYN[i]=0) and (random(100)>=randomness)
             then if (Ord(fiCorr[i])>=65) and (Ord(fiCorr[i])<=70)
                  then begin     aux:=fi[i];fi[i]:=aux-fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];MyMultiLayer.SetCorrParams(fiCorr[i],'fi',fi[i]);chiMoins:=CalculDifference;
                                 fi[i]:=aux+fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];MyMultiLayer.SetCorrParams(fiCorr[i],'fi',fi[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin fi[i]:=aux-fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];MyMultiLayer.SetCorrParams(fiCorr[i],'fi',fi[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin fi[i]:=aux+fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];MyMultiLayer.SetCorrParams(fiCorr[i],'fi',fi[i]);chi:=chiPlus end
                                                     else begin fi[i]:=aux;Vi[i]:=-Cte*d[i]*fi[i];MyMultiLayer.SetCorrParams(fiCorr[i],'fi',fi[i]); end
                                 end
                  else begin     aux:=fi[i];fi[i]:=aux-fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];chiMoins:=CalculDifference;
                                 fi[i]:=aux+fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin fi[i]:=aux-fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin fi[i]:=aux+fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];chi:=chiPlus end
                                                     else begin fi[i]:=aux;Vi[i]:=-Cte*d[i]*fi[i]; end
                                 end;
            end;

             if (sigYN[i]=0) and (random(100)>=randomness)
             then if (Ord(sigmaCorr[i])>=65) and (Ord(sigmaCorr[i])<=70)
                  then begin     aux:=sigma[i];sigma[i]:=aux-sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chiMoins:=CalculDifference;
                                 sigma[i]:=aux+sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin sigma[i]:=aux-sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin sigma[i]:=aux+sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chi:=chiPlus end
                                                     else begin sigma[i]:=aux;MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]); end
                                 end
                  else begin     aux:=sigma[i];sigma[i]:=aux-sigmaStep[i];chiMoins:=CalculDifference;
                                 sigma[i]:=aux+sigmaStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin sigma[i]:=aux-sigmaStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin sigma[i]:=aux+sigmaStep[i];chi:=chiPlus end
                                                     else begin sigma[i]:=aux; end
                                 end;
             if sigma[i]<0 then sigma[i]:=-sigma[i]; { on passe systématiquement les sigam à des valeurs positives } 
        end;
{ après une première boucle, on met a jour les paramètres du tableau }
        SimulReflecWindow.updateDisplayWhileFitting(SimulReflecWindow.MultiLayerGrid,MyMultiLayer,MyExperimentalParameters,chi);

        Application.processMessages; { l'utilisateur a-t-il appuyé sur le boutton ? }
        if StopFittingFlag=true then break; { on sort du fit }
        if ReplotFlag=true then begin CalculateReflectivity(MyExperimentalParameters,MyMultilayer,MyDataCalc);SimulReflecWindow.PlotReflectivity(MyExperimentalParameters,MyDataCalc);replotFlag:=false end;
      end;
   { le fit est fini }
end;

{ =======================================================================}
{ MINIMISATION AVEC NOUVEAUX TYPES DE DATA                               }
{ procédure de minimisation utilisant le crawling                        }
{ on déplace chaque parametre d'une quantité step en + ou en - et        }
{ on garde la meilleure valeur                                           }
{ NOTA : Il faut que les paramètres de DataCalc et DateExp soient compatible }
Procedure MinimisationCrawling_P(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMultiLayer:TMultiLayer;var MyProfiles:TProfiles;var MyDataExp,MyDataCalc:TDataReflectivity);
var i,niter,nbrIter: integer;
    chi,chimoins,chiplus,aux:double; { valeurs du paramètre , point de départ, dpart + step, depart - step }
    dataFittingOption:integer; { fitting all the data curves (0); the NSF only (1); the SF only (2); up+do only }

function CalculDifference:double;
var i:integer;
    diff,diffSmooth:double;
begin
   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   { application du facteur de normalisation }
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
   { Calcul de la différence aux moindres carrés }
   case dataFittingOption of
       0:diff:=difference2(MyDataExp.Rup,MyDataExp.Rups,MyDataCalc.Rup,MyExperimentalParameters.PonderationType)
             +difference2(MyDataExp.Rdo,MyDataExp.Rdos,MyDataCalc.Rdo,MyExperimentalParameters.PonderationType);
       3:begin { cas ou on fitte seulement UP+DO } { il faut que Rup et Rdo contiennent les mêmes data }
        { il faut sommer MyDataCalc.Rup et Rdo }
         MyDataCalc.R.length:=MyDataCalc.Rup.length;
         for i:=0 to MyDataCalc.R.length-1 do MyDataCalc.R[i]:=(MyDataCalc.Rup[i]+MyDataCalc.Rdo[i])/2;
         diff:=difference2(MyDataExp.Rup,MyDataExp.Rups,MyDataCalc.R,MyExperimentalParameters.PonderationType)
         end;
       4:begin { fit sur la spin-asymmety uniquement }
         MyDataCalc.R.length:=MyDataCalc.Rup.length;
         MyDataExp.R.length:=MyDataExp.Rup.length;
         for i:=0 to MyDataCalc.R.length-1 do
         begin MyDataCalc.R[i]:=(MyDataCalc.Rup[i]-MyDataCalc.Rdo[i])/(MyDataCalc.Rup[i]+MyDataCalc.Rdo[i]);
               MyDataExp.R[i]:=(MyDataExp.Rup[i]-MyDataExp.Rdo[i])/(MyDataExp.Rup[i]+MyDataExp.Rdo[i]);
         end;
         diff:=RMS(MyDataExp.R,MyDataCalc.R);
         end;

   end;
   { ajout de la ponderation liée au profil de type smooth }
   if MyMultiLayer.profiled
   then diffSmooth:=MyMultiLayer.SmoothProfile(MyProfiles) else diffSmooth:=0;
   result:=diff+diffSmooth;
end;

begin
     StopFittingFlag:=false;
     with SimulReflecWindow do
     begin
         dataFittingOption:=dataFittingOptionsBox.itemIndex;
         FittingStatus.caption:='Fitting...';FittingStatus.update;
         nbrIter:=spinEditNbrIter.value
     end;
     { calcul de l'ecart au point de depart }
     chi:=CalculDifference;
     { on boucle sur les différents paramètres }
     for niter:=1 to round(NbrIter/(100-randomness)*100) do
     begin
        with SimulReflecWindow do
          begin IterCrt.caption:=IntToStr(nIter);IterCrt.update end;
        { fit sur la normalisation }
        with MyExperimentalParameters do
        begin
        if (FitNormalisation=true) and (random(100)>=randomness) then begin
                                 aux:=normalisationFactor;
                                 normalisationFactor:=aux-normalisationFactorStep;
                                 chiMoins:=CalculDifference;
                                 normalisationFactor:=aux+normalisationFactorStep;
                                 chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin normalisationfactor:=aux-normalisationFactorStep;chi:=chiMoins end
                                 else if chiPlus<chi then begin normalisationfactor:=aux+normalisationFactorStep;chi:=chiMoins;chi:=chiPlus end
                                                     else begin normalisationfactor:=aux;  end
                                 end;
        end;
        { on boucle sur toutes les couches du système }
        with MyMultilayer do
        for i:=0 to nbrLayers-1 do
        begin
             if (zYN[i]=0) and (random(100)>=randomness)
             then if (Ord(zCorr[i])>=65) and (Ord(zCorr[i])<=70)
                  then begin     aux:=z[i];z[i]:=aux-zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chiMoins:=CalculDifference;
                                 z[i]:=aux+zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin z[i]:=aux-zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin z[i]:=aux+zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chi:=chiPlus end
                                                     else begin z[i]:=aux;MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);  end
                                 end
                  else begin     aux:=z[i];z[i]:=aux-zStep[i];chiMoins:=CalculDifference;
                                 z[i]:=aux+zStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin z[i]:=aux-zStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin z[i]:=aux+zStep[i];chi:=chiPlus end
                                                     else begin z[i]:=aux;  end
                                 end;
             if (dYN[i]=0) and (random(100)>=randomness)
             then if (Ord(dCorr[i])>=65) and (Ord(dCorr[i])<=70)
                  then begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]); end;
                                 end
                  else begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end;
                                 end;
             if (sigYN[i]=0) and (random(100)>=randomness)
             then if (Ord(sigmaCorr[i])>=65) and (Ord(sigmaCorr[i])<=70)
                  then begin     aux:=sigma[i];sigma[i]:=aux-sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chiMoins:=CalculDifference;
                                 sigma[i]:=aux+sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin sigma[i]:=aux-sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin sigma[i]:=aux+sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chi:=chiPlus end
                                                     else begin sigma[i]:=aux;MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]); end
                                 end
                  else begin     aux:=sigma[i];sigma[i]:=aux-sigmaStep[i];chiMoins:=CalculDifference;
                                 sigma[i]:=aux+sigmaStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin sigma[i]:=aux-sigmaStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin sigma[i]:=aux+sigmaStep[i];chi:=chiPlus end
                                                     else begin sigma[i]:=aux; end
                                 end;
             if sigma[i]<0 then sigma[i]:=-sigma[i]; { on passe systématiquement les sigam à des valeurs positives }
             if (bYN[i]=0) and (random(100)>=randomness)
             then if (Ord(bCorr[i])>=65) and (Ord(bCorr[i])<=70)
                  then begin     aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chiMoins:=CalculDifference;
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]); end
                                 end
                  else begin     aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference;
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end
                                 end;
             if (biYN[i]=0) and (random(100)>=randomness)
             then if (Ord(biCorr[i])>=65) and (Ord(biCorr[i])<=70)
                  then begin     aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chiMoins:=CalculDifference;
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]); end
                                 end
                  else begin     aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiMoins:=CalculDifference;
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i]; end
                                 end;
             if (MYN[i]=0) and (random(100)>=randomness)
             then if (Ord(MCorr[i])>=65) and (Ord(MCorr[i])<=70)
                  then begin     aux:=Aim[i];Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chiMoins:=CalculDifference;
                                 Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chi:=chiPlus end
                                                     else begin Aim[i]:=aux;Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]); end
                                 end
                  else begin     aux:=Aim[i];Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference;
                                 Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin Aim[i]:=aux;Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end
                                 end;
        end;
   { après une première boucle, on met a jour les paramètres du tableau }
        SimulReflecWindow.updateDisplayWhileFitting(SimulReflecWindow.MultiLayerGrid,MyMultiLayer,MyExperimentalParameters,chi);
        Application.processMessages; { l'utilisateur a-t-il appuyé sur le boutton ? }
        if StopFittingFlag=true then break; { on sort du fit }
        if ReplotFlag=true then begin CalculateReflectivity(MyExperimentalParameters,MyMultilayer,MyDataCalc);SimulReflecWindow.PlotReflectivity(MyExperimentalParameters,MyDataCalc);replotFlag:=false end;
        end;
{ le fit est fini }

end;

{ =======================================================================}
{ MINIMISATION AVEC NOUVEAUX TYPES DE DATA pour mesures de SPIN-FLIP     }
{ procédure de minimisation utilisant le crawling                        }
{ on déplace chaque parametre d'une quantité step en + ou en - et        }
{ on garde la meilleure valeur                                           }
{ NOTA : Il faut que les paramètres de DataCalc et DateExp soient compatible }
Procedure MinimisationCrawling_SF(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMultiLayer:TMultiLayer;var MyProfiles:TProfiles;var MyDataExp,MyDataCalc:TDataReflectivity);
var i,niter,nbrIter: integer;
    chi,chimoins,chiplus,aux:double; { valeurs du paramètre , point de départ, dpart + step, depart - step }
    dataFittingOption:integer; { fitting all the data curves (0); the NSF only (1); the SF only (2) }
    MyMultiLayer2:TmultiLayer;
    MyDataCalc2:TDataReflectivity;

function CalculDifference:double;
var diff,diffSmooth:double;
    i:integer;
begin
   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   { application du facteur de normalisation }
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
   { Calcul de la différence aux moindres carrés }
   case dataFittingOption of
      0:diff:=difference2(MyDataExp.Ruu,MyDataExp.Ruus,MyDataCalc.Ruu,MyExperimentalParameters.PonderationType)
        +difference2(MyDataExp.Rdd,MyDataExp.Rdds,MyDataCalc.Rdd,MyExperimentalParameters.PonderationType)
        +difference2(MyDataExp.Rud,MyDataExp.Ruds,MyDataCalc.Rud,MyExperimentalParameters.PonderationType);
      1:diff:=difference2(MyDataExp.Ruu,MyDataExp.Ruus,MyDataCalc.Ruu,MyExperimentalParameters.PonderationType)
        +difference2(MyDataExp.Rdd,MyDataExp.Rdds,MyDataCalc.Rdd,MyExperimentalParameters.PonderationType);
      2:diff:=difference2(MyDataExp.Rud,MyDataExp.Ruds,MyDataCalc.Rud,MyExperimentalParameters.PonderationType);
      4:begin { fit sur la spin-asymmety uniquement }
         MyDataCalc.R.length:=MyDataCalc.Ruu.length;
         MyDataExp.R.length:=MyDataExp.Ruu.length;
         for i:=0 to MyDataCalc.R.length-1 do
         begin MyDataCalc.R[i]:=(MyDataCalc.Ruu[i]-MyDataCalc.Rdd[i])/(MyDataCalc.Ruu[i]+MyDataCalc.Rdd[i]);
               MyDataExp.R[i]:=(MyDataExp.Ruu[i]-MyDataExp.Rdd[i])/(MyDataExp.Ruu[i]+MyDataExp.Rdd[i]);
         end;
         diff:=RMS(MyDataExp.R,MyDataCalc.R);
        end;
      5:begin { fit sur le cos PHI }
        { calcul de la reflectivity avec PHI = 0° }
        MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
        for i:=0 to MyMultiLayer2.nbrLayers-1 do MyMultiLayer2.phi[i]:=0;             { on remplace les angles phi par la valeur 0 }
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2); { on fait le calcul de reflectivité }
        MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
        { fin du calcul avec PHI = 0° }
        MyDataCalc.R.length:=MyDataCalc.Ruu.length;
        MyDataExp.R.length:=MyDataExp.Ruu.length;
        for i:=0 to MyDataCalc.R.length-1 do
        begin MyDataCalc.R[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc2.Ruu.values[i]-MyDataCalc2.Rdd.values[i]); { calculated cos PHI }
              MyDataExp.R[i]:=(MyDataExp.Ruu.values[i]-MyDataExp.Rdd.values[i])/(MyDataCalc2.Ruu.values[i]-MyDataCalc2.Rdd.values[i]); { experimental COS PHI }
        end;
        diff:=RMS(MyDataExp.R,MyDataCalc.R);
        end;
      6:begin { fit sur le sin² PHI }
        { calcul de la reflectivity avec PHI = 90° }
        MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
        for i:=0 to MyMultiLayer2.nbrLayers-2 do MyMultiLayer2.phi[i]:=pi/2;       { on remplace les angles phi par la valeur pi/2 suaf le vide !! }
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2); { on fait le calcul de reflectivité }
        MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
        { fin du calcul avec PHI = 90° }
        MyDataCalc.R.length:=MyDataCalc.Ruu.length;
        MyDataExp.R.length:=MyDataExp.Ruu.length;
        for i:=0 to MyDataCalc.R.length-1 do
        begin MyDataCalc.R[i]:=MyDataCalc.Rud.values[i]/MyDataCalc2.Rud.values[i];
              MyDataExp.R[i]:=MyDataExp.Rud.values[i]/MyDataCalc2.Rud.values[i];
        end;
        diff:=RMS(MyDataExp.R,MyDataCalc.R);
        end;

   end;
   { CE N'EST PAS LA MEILLEURE PLACE; ON DEVRAIT CALCULER CA SEULEMENT SI UN PARA DU PROFIL CHANGE }
   { ajout de la ponderation liée au profil de type smooth }
   if MyMultiLayer.profiled
   then diffSmooth:=MyMultiLayer.SmoothProfile(MyProfiles) else diffSmooth:=0;
   result:=diff+diffSmooth;
end;

begin
   MyDataCalc2:=TDataReflectivity.create;
   MyMultiLayer2:=TMultiLayer.Create;
   { stockage intermédiare pour les calculs eventuels en COS PHI ou SIN² PHI}
   MyDataCalc2.abscisses.copy(MyDataExp.abscisses);MyDataCalc2.updateWithAbscisses(MyExperimentalParameters);

     StopFittingFlag:=false;
     with SimulReflecWindow do
     begin
         dataFittingOption:=dataFittingOptionsBox.itemIndex;
         FittingStatus.caption:='Fitting...';FittingStatus.update;
         nbrIter:=spinEditNbrIter.value
     end;

     { calcul de l'ecart au point de depart }
     chi:=CalculDifference;
     { on boucle sur les différents paramètres }
     for niter:=1 to round(NbrIter/(100-randomness)*100) do
     begin
        with SimulReflecWindow do begin IterCrt.caption:=IntToStr(nIter);IterCrt.update; end;
        { fit sur la normalisation }
        with MyExperimentalParameters do
        begin
        if (FitNormalisation=true) and (random(100)>=randomness) then begin
                                 aux:=normalisationFactor;
                                 normalisationFactor:=aux-normalisationFactorStep;
                                 chiMoins:=CalculDifference;
                                 normalisationFactor:=aux+normalisationFactorStep;
                                 chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin normalisationfactor:=aux-normalisationFactorStep;chi:=chiMoins end
                                 else if chiPlus<chi then begin normalisationfactor:=aux+normalisationFactorStep;chi:=chiMoins;chi:=chiPlus end
                                                     else begin normalisationfactor:=aux;  end
                                 end;
        end;
        { on boucle sur toutes les couches du système }
        with MyMultilayer do
        for i:=0 to nbrLayers-1 do
        begin
             if (zYN[i]=0) and (random(100)>=randomness)
             then if (Ord(zCorr[i])>=65) and (Ord(zCorr[i])<=70)
                  then begin     aux:=z[i];z[i]:=aux-zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chiMoins:=CalculDifference;
                                 z[i]:=aux+zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin z[i]:=aux-zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin z[i]:=aux+zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chi:=chiPlus end
                                                     else begin z[i]:=aux;MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);  end
                                 end
                  else begin     aux:=z[i];z[i]:=aux-zStep[i];chiMoins:=CalculDifference;
                                 z[i]:=aux+zStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin z[i]:=aux-zStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin z[i]:=aux+zStep[i];chi:=chiPlus end
                                                     else begin z[i]:=aux;  end
                                 end;
             if (dYN[i]=0) and (random(100)>=randomness)
             then if (Ord(dCorr[i])>=65) and (Ord(dCorr[i])<=70)
                  then begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;SetCorrParams(dCorr[i],'rho_n',d[i]); end;
                                 end
                  else begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end;
                                 end;
             if (sigYN[i]=0) and (random(100)>=randomness)
             then if (Ord(sigmaCorr[i])>=65) and (Ord(sigmaCorr[i])<=70)
                  then begin     aux:=sigma[i];sigma[i]:=aux-sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chiMoins:=CalculDifference;
                                 sigma[i]:=aux+sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin sigma[i]:=aux-sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin sigma[i]:=aux+sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chi:=chiPlus end
                                                     else begin sigma[i]:=aux;MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]); end
                                 end
                  else begin     aux:=sigma[i];sigma[i]:=aux-sigmaStep[i];chiMoins:=CalculDifference;
                                 sigma[i]:=aux+sigmaStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin sigma[i]:=aux-sigmaStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin sigma[i]:=aux+sigmaStep[i];chi:=chiPlus end
                                                     else begin sigma[i]:=aux; end
                                 end;
             if sigma[i]<0 then sigma[i]:=-sigma[i]; { on passe systématiquement les sigam à des valeurs positives }
             if (bYN[i]=0) and (random(100)>=randomness)
             then if (Ord(bCorr[i])>=65) and (Ord(bCorr[i])<=70)
                  then begin     aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chiMoins:=CalculDifference;
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]); end
                                 end
                  else begin     aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference;
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end
                                 end;
             if (biYN[i]=0) and (random(100)>=randomness)
             then if (Ord(biCorr[i])>=65) and (Ord(biCorr[i])<=70)
                  then begin     aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chiMoins:=CalculDifference;
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]); end
                                 end
                  else begin     aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiMoins:=CalculDifference;
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i]; end
                                 end;
             if (MYN[i]=0) and (random(100)>=randomness)
             then if (Ord(MCorr[i])>=65) and (Ord(MCorr[i])<=70)
                  then begin     aux:=Aim[i];Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chiMoins:=CalculDifference;
                                 Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chi:=chiPlus end
                                                     else begin Aim[i]:=aux;Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]); end
                                 end
                  else begin     aux:=Aim[i];Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference;
                                 Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin Aim[i]:=aux;Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end
                                 end;
             if (PhiYN[i]=0) and (random(100)>=randomness)
             then if (Ord(PhiCorr[i])>=65) and (Ord(PhiCorr[i])<=70)
                  then begin    { aux:=Phi[i];Phi[i]:=aux-PhiStep[i];MyMultiLayer.MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chiMoins:=CalculDifference;
                                 Phi[i]:=aux+PhiStep[i];MyMultiLayer.MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Phi[i]:=aux-PhiStep[i];MyMultiLayer.MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin Phi[i]:=aux+PhiStep[i];MyMultiLayer.MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chi:=chiPlus end
                                                     else begin Phi[i]:=aux;MyMultiLayer.MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]); end }
                                 end
                  else begin     aux:=Phi[i];Phi[i]:=aux-MyMultiLayer.PhiStep[i];chiMoins:=CalculDifference;
                                 Phi[i]:=aux+PhiStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Phi[i]:=aux-PhiStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin Phi[i]:=aux+PhiStep[i];chi:=chiPlus end
                                                     else begin Phi[i]:=aux; end
                                 end;
        end;
   { après une première boucle, on met a jour les paramètres du tableau }
        SimulReflecWindow.updateDisplayWhileFitting(SimulReflecWindow.MultiLayerGrid,MyMultiLayer,MyExperimentalParameters,chi);

          Application.processMessages; { l'utilisateur a-t-il appuyé sur le boutton ? }
          if StopFittingFlag=true then break; { on sort du fit }
          if ReplotFlag=true then begin CalculateReflectivity(MyExperimentalParameters,MyMultilayer,MyDataCalc);SimulReflecWindow.PlotReflectivity(MyExperimentalParameters,MyDataCalc);replotFlag:=false end;          
        end;
{ le fit est fini }
end;

{ =======================================================================}
{ MINIMISATION AVEC NOUVEAUX TYPES DE DATA pour mesures de SPIN-FLIP     }
{ procédure de minimisation utilisant le crawling                        }
{ on déplace chaque parametre d'une quantité step en + ou en - et        }
{ on garde la meilleure valeur                                           }
{ NOTA : Il faut que les paramètres de DataCalc et DateExp soient compatible }
Procedure MinimisationCrawling_SF_HF(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMultiLayer:TMultiLayer;var MyProfiles:TProfiles;var MyDataExp,MyDataCalc:TDataReflectivity);
var i,niter,nbrIter: integer;
    chi,chimoins,chiplus,aux:double; { valeurs du paramètre , point de départ, dpart + step, depart - step }
    dataFittingOption:integer; { fitting all the data curves (0); the NSF only (1); the SF only (2) }
    MyMultiLayer2:TmultiLayer;
    MyDataCalc2:TDataReflectivity;

{ repercussion des changements de phi et theta sur le champ effectif }
{ INPUT : indice de la couche }
procedure UpdateBeff(idx:integer);
var BeffX,BeffY,BeffZ:double;
begin
     With MyMultiLayer do
     begin
        { calcul du champ effectif dans chaque couche }
        BeffX:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Cos(MyExperimentalParameters.fieldPhi)
           +Aim[idx]*Sin(theta[idx])*Cos(phi[idx]);
        BeffY:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Sin(MyExperimentalParameters.fieldPhi)
           +Aim[idx]*Sin(theta[idx])*Sin(phi[idx]);
        BeffZ:=MyExperimentalParameters.FieldMag*Cos(MyExperimentalParameters.fieldTheta);
        BeffMag[idx]:= sqrt(sqr(BeffX)+sqr(BeffY)+sqr(BeffZ));
        {definition des angles théta et phi du champ efficace}
        if BeffMag[idx]<>0 then BeffTheta[idx]:=ArcCos(BeffZ/BeffMag[idx]) else BeffTheta[idx]:=0; {en radians}
        if (BeffX<>0) and (BeffY<>0) then BeffPhi[idx]:=arg(Cplx(BeffX,BeffY)) else BeffPhi[idx]:=0;{en radians}
     end;
end;

function CalculDifference:double;
var diff,diffSmooth:double;
    i:integer;
    BeffX,BeffY,BeffZ:double;
begin
   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   { application du facteur de normalisation }
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
   { Calcul de la différence aux moindres carrés }
   case dataFittingOption of
      0:diff:=difference2(MyDataExp.Ruu,MyDataExp.Ruus,MyDataCalc.Ruu,MyExperimentalParameters.PonderationType)
        +difference2(MyDataExp.Rdd,MyDataExp.Rdds,MyDataCalc.Rdd,MyExperimentalParameters.PonderationType)
        +difference2(MyDataExp.Rud,MyDataExp.Ruds,MyDataCalc.Rud,MyExperimentalParameters.PonderationType)
        +difference2(MyDataExp.Rdu,MyDataExp.Rdus,MyDataCalc.Rdu,MyExperimentalParameters.PonderationType);
      1:diff:=difference2(MyDataExp.Ruu,MyDataExp.Ruus,MyDataCalc.Ruu,MyExperimentalParameters.PonderationType)
        +difference2(MyDataExp.Rdd,MyDataExp.Rdds,MyDataCalc.Rdd,MyExperimentalParameters.PonderationType);
      2:diff:=difference2(MyDataExp.Rud,MyDataExp.Ruds,MyDataCalc.Rud,MyExperimentalParameters.PonderationType)
        +difference2(MyDataExp.Rdu,MyDataExp.Rdus,MyDataCalc.Rdu,MyExperimentalParameters.PonderationType);
      4:begin { fit sur la spin-asymmety uniquement }
         MyDataCalc.R.length:=MyDataCalc.Ruu.length;
         MyDataExp.R.length:=MyDataExp.Ruu.length;
         for i:=0 to MyDataCalc.R.length-1 do
         begin MyDataCalc.R[i]:=(MyDataCalc.Ruu[i]-MyDataCalc.Rdd[i])/(MyDataCalc.Ruu[i]+MyDataCalc.Rdd[i]);
               MyDataExp.R[i]:=(MyDataExp.Ruu[i]-MyDataExp.Rdd[i])/(MyDataExp.Ruu[i]+MyDataExp.Rdd[i]);
         end;
         diff:=RMS(MyDataExp.R,MyDataCalc.R);
        end;
      5:begin { fit sur le cos PHI }
        { calcul de la reflectivity avec PHI = 0° }
        MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
        for i:=0 to MyMultiLayer2.nbrLayers-1 do
             begin
                with MyMultiLayer2 do
                begin  { calcul du champ effectif dans chaque couche } { avec PHI = 0; on suppose que le champ est suivant PHI=0 }
                       BeffX:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Cos(MyExperimentalParameters.fieldPhi)+Aim[i];
                       BeffY:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Sin(MyExperimentalParameters.fieldPhi); { zero en principe }
                       BeffZ:=MyExperimentalParameters.FieldMag*Cos(MyExperimentalParameters.fieldTheta); { zero en principe }
                       BeffMag[i]:= sqrt(sqr(BeffX)+sqr(BeffY)+sqr(BeffZ));
                       {definition des angles théta et phi du champ efficace}
                       if BeffMag[i]<>0 then BeffTheta[i]:=ArcCos(BeffZ/BeffMag[i]) else BeffTheta[i]:=0; {en radians}
                       if (BeffX<>0) and (BeffY<>0) then BeffPhi[i]:=arg(Cplx(BeffX,BeffY)) else BeffPhi[i]:=0;{en radians}
                end;
             end;
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2); { on fait le calcul de reflectivité }
        MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
        { fin du calcul avec PHI = 0° }
        MyDataCalc.R.length:=MyDataCalc.Ruu.length;
        MyDataExp.R.length:=MyDataExp.Ruu.length;
        for i:=0 to MyDataCalc.R.length-1 do
        begin MyDataCalc.R[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc2.Ruu.values[i]-MyDataCalc2.Rdd.values[i]); { calculated cos PHI }
              MyDataExp.R[i]:=(MyDataExp.Ruu.values[i]-MyDataExp.Rdd.values[i])/(MyDataCalc2.Ruu.values[i]-MyDataCalc2.Rdd.values[i]); { experimental COS PHI }
        end;
        diff:=RMS(MyDataExp.R,MyDataCalc.R);
        end;
      6:begin { fit sur le sin² PHI }
        MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
        for i:=0 to MyMultiLayer2.nbrLayers-2 do       { on remplace les angles phi par la valeur pi/2 suaf le vide !! }
             begin
                with MyMultiLayer2 do
                begin  { calcul du champ effectif dans chaque couche } { avec PHI = 90°; on suppose que le champ est suivant PHI=0 }
                       BeffX:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Cos(MyExperimentalParameters.fieldPhi);
                       BeffY:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Sin(MyExperimentalParameters.fieldPhi)+Aim[i];
                       BeffZ:=MyExperimentalParameters.FieldMag*Cos(MyExperimentalParameters.fieldTheta); { zero en principe }
                       BeffMag[i]:= sqrt(sqr(BeffX)+sqr(BeffY)+sqr(BeffZ));
                       {definition des angles théta et phi du champ efficace}
                       if BeffMag[i]<>0 then BeffTheta[i]:=ArcCos(BeffZ/BeffMag[i]) else BeffTheta[i]:=0; {en radians}
                       if (BeffX<>0) and (BeffY<>0) then BeffPhi[i]:=arg(Cplx(BeffX,BeffY)) else BeffPhi[i]:=0;{en radians}
                end;
             end;
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2); { on fait le calcul de reflectivité }
        MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
        { fin du calcul avec PHI = 90° }
        MyDataCalc.R.length:=MyDataCalc.Ruu.length;
        MyDataExp.R.length:=MyDataExp.Ruu.length;
        for i:=0 to MyDataCalc.R.length-1 do
        begin MyDataCalc.R[i]:=MyDataCalc.Rud.values[i]/MyDataCalc2.Rud.values[i];
              MyDataExp.R[i]:=MyDataExp.Rud.values[i]/MyDataCalc2.Rud.values[i];
        end;
        diff:=RMS(MyDataExp.R,MyDataCalc.R);
        end;
   end;
   { CE N'EST PAS LA MEILLEURE PLACE; ON DEVRAIT CALCULER CA SEULEMENT SI UN PARA DU PROFIL CHANGE }
   { ajout de la ponderation liée au profil de type smooth }
   if MyMultiLayer.profiled
   then diffSmooth:=MyMultiLayer.SmoothProfile(MyProfiles) else diffSmooth:=0;
   result:=diff+diffSmooth;
end;

begin
   MyDataCalc2:=TDataReflectivity.create;
   MyMultiLayer2:=TMultiLayer.Create;
   { stockage intermédiare pour les calculs eventuels en COS PHI ou SIN² PHI}
   MyDataCalc2.abscisses.copy(MyDataExp.abscisses);MyDataCalc2.updateWithAbscisses(MyExperimentalParameters);

     StopFittingFlag:=false;
     with SimulReflecWindow do
     begin
         dataFittingOption:=dataFittingOptionsBox.itemIndex;
         FittingStatus.caption:='Fitting...';FittingStatus.update;
         nbrIter:=spinEditNbrIter.value
     end;

     { calcul de l'ecart au point de depart }
     chi:=CalculDifference;
     { on boucle sur les différents paramètres }
     for niter:=1 to round(NbrIter/(100-randomness)*100) do
     begin
        with SimulReflecWindow do begin IterCrt.caption:=IntToStr(nIter);IterCrt.update; end;
        { fit sur la normalisation }
        with MyExperimentalParameters do
        begin
        if (FitNormalisation=true) and (random(100)>=randomness) then begin
                                 aux:=normalisationFactor;
                                 normalisationFactor:=aux-normalisationFactorStep;
                                 chiMoins:=CalculDifference;
                                 normalisationFactor:=aux+normalisationFactorStep;
                                 chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin normalisationfactor:=aux-normalisationFactorStep;chi:=chiMoins end
                                 else if chiPlus<chi then begin normalisationfactor:=aux+normalisationFactorStep;chi:=chiMoins;chi:=chiPlus end
                                                     else begin normalisationfactor:=aux;  end
                                 end;
        end;
        { on boucle sur toutes les couches du système }
        with MyMultilayer do
        for i:=0 to nbrLayers-1 do
        begin
             if (zYN[i]=0) and (random(100)>=randomness)
             then if (Ord(zCorr[i])>=65) and (Ord(zCorr[i])<=70)
                  then begin     aux:=z[i];z[i]:=aux-zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chiMoins:=CalculDifference;
                                 z[i]:=aux+zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin z[i]:=aux-zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin z[i]:=aux+zStep[i];MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);chi:=chiPlus end
                                                     else begin z[i]:=aux;MyMultiLayer.SetCorrParams(zCorr[i],'z',z[i]);  end
                                 end
                  else begin     aux:=z[i];z[i]:=aux-zStep[i];chiMoins:=CalculDifference;
                                 z[i]:=aux+zStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin z[i]:=aux-zStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin z[i]:=aux+zStep[i];chi:=chiPlus end
                                                     else begin z[i]:=aux;  end
                                 end;
             if (dYN[i]=0) and (random(100)>=randomness)
             then if (Ord(dCorr[i])>=65) and (Ord(dCorr[i])<=70)
                  then begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]);chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(dCorr[i],'rho_n',d[i]); end;
                                 end
                  else begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end;
                                 end;
             if (sigYN[i]=0) and (random(100)>=randomness)
             then if (Ord(sigmaCorr[i])>=65) and (Ord(sigmaCorr[i])<=70)
                  then begin     aux:=sigma[i];sigma[i]:=aux-sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chiMoins:=CalculDifference;
                                 sigma[i]:=aux+sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin sigma[i]:=aux-sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin sigma[i]:=aux+sigmaStep[i];MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]);chi:=chiPlus end
                                                     else begin sigma[i]:=aux;MyMultiLayer.SetCorrParams(sigmaCorr[i],'sigma',sigma[i]); end
                                 end
                  else begin     aux:=sigma[i];sigma[i]:=aux-sigmaStep[i];chiMoins:=CalculDifference;
                                 sigma[i]:=aux+sigmaStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin sigma[i]:=aux-sigmaStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin sigma[i]:=aux+sigmaStep[i];chi:=chiPlus end
                                                     else begin sigma[i]:=aux; end
                                 end;
             if sigma[i]<0 then sigma[i]:=-sigma[i]; { on passe systématiquement les sigam à des valeurs positives }
             if (bYN[i]=0) and (random(100)>=randomness)
             then if (Ord(bCorr[i])>=65) and (Ord(bCorr[i])<=70)
                  then begin     aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chiMoins:=CalculDifference;
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]);chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(bCorr[i],'b',bn[i]); end
                                 end
                  else begin     aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference;
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end
                                 end;
             if (biYN[i]=0) and (random(100)>=randomness)
             then if (Ord(biCorr[i])>=65) and (Ord(biCorr[i])<=70)
                  then begin     aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chiMoins:=CalculDifference;
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]);chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i];MyMultiLayer.SetCorrParams(biCorr[i],'bi',bni[i]); end
                                 end
                  else begin     aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiMoins:=CalculDifference;
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i]; end
                                 end;
             if (MYN[i]=0) and (random(100)>=randomness)
             then if (Ord(MCorr[i])>=65) and (Ord(MCorr[i])<=70)
                  then begin     aux:=Aim[i];Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chiMoins:=CalculDifference;
                                 Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chi:=chiPlus end
                                                     else begin Aim[i]:=aux;Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]); end
                                 end
                  else begin     aux:=Aim[i];Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference;
                                 Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin Aim[i]:=aux;Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end
                                 end;
             if (PhiYN[i]=0) and (random(100)>=randomness)
             then if (Ord(PhiCorr[i])>=65) and (Ord(PhiCorr[i])<=70)
                  then begin    { aux:=Phi[i];Phi[i]:=aux-PhiStep[i];MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chiMoins:=CalculDifference;
                                 Phi[i]:=aux+PhiStep[i];MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Phi[i]:=aux-PhiStep[i];MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin Phi[i]:=aux+PhiStep[i];MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chi:=chiPlus end
                                                     else begin Phi[i]:=aux;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]); end }
                                 end
                  else begin     aux:=Phi[i];Phi[i]:=aux-PhiStep[i];UpdateBeff(i);chiMoins:=CalculDifference;
                                 Phi[i]:=aux+PhiStep[i];UpdateBeff(i);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Phi[i]:=aux-PhiStep[i];UpdateBeff(i);chi:=chiMoins end
                                 else if chiPlus<chi then begin Phi[i]:=aux+PhiStep[i];UpdateBeff(i);chi:=chiPlus end
                                                     else begin Phi[i]:=aux;UpdateBeff(i); end
                                 end;
             if (ThetaYN[i]=0) and (random(100)>=randomness)
             then if (Ord(ThetaCorr[i])>=65) and (Ord(ThetaCorr[i])<=70)
                  then begin    { aux:=Phi[i];Phi[i]:=aux-PhiStep[i];MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chiMoins:=CalculDifference;
                                 Phi[i]:=aux+PhiStep[i];MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Phi[i]:=aux-PhiStep[i];MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin Phi[i]:=aux+PhiStep[i];MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]);chi:=chiPlus end
                                                     else begin Phi[i]:=aux;MyMultiLayer.SetCorrParams(MCorr[i],'M',Aim[i]); end }
                                 end
                  else begin     aux:=Theta[i];Theta[i]:=aux-ThetaStep[i];UpdateBeff(i);chiMoins:=CalculDifference;
                                 Theta[i]:=aux+ThetaStep[i];UpdateBeff(i);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Theta[i]:=aux-ThetaStep[i];UpdateBeff(i);chi:=chiMoins end
                                 else if chiPlus<chi then begin Theta[i]:=aux+ThetaStep[i];UpdateBeff(i);chi:=chiPlus end
                                                     else begin Theta[i]:=aux;UpdateBeff(i); end
                                 end;
        end;
   { après une première boucle, on met a jour les paramètres du tableau }
        SimulReflecWindow.updateDisplayWhileFitting(SimulReflecWindow.MultiLayerGrid,MyMultiLayer,MyExperimentalParameters,chi);

          Application.processMessages; { l'utilisateur a-t-il appuyé sur le boutton ? }
          if StopFittingFlag=true then break; { on sort du fit }
          if ReplotFlag=true then begin CalculateReflectivity(MyExperimentalParameters,MyMultilayer,MyDataCalc);SimulReflecWindow.PlotReflectivity(MyExperimentalParameters,MyDataCalc);replotFlag:=false end;          
        end;
{ le fit est fini }
end;

{ =======================================================================}
{ ================ CAS POLYDOMAINES   ===================================}
{ =======================================================================}

{ procédure de minimisation utilisant le crawling                        }
{ on déplace chaque parametre d'une quantité step en + ou en - et        }
{ on garde la meilleure valeur                                           }
{ NOTA : Il faut que les paramètres de DataCalc et DateExp soient compatible }
{ NOTA2 : il y a une bidouille moche avec MLNr pour gagner en vitesse de calcul }
Procedure MinimisationCrawling_PD(randomness:integer;var MyEP:TExperimentalParameters;var MyML1,MyML2:TMultiLayer;var MyProfiles:TProfiles;var MyDataExp,MyDC1,MyDC2:TDataReflectivity);
var niter,NbrIter: integer;
    chi,chimoins,chiplus,aux:double; { valeurs du paramètre , point de départ, dpart + step, depart - step }
    dataFittingOption:integer; { fitting all the data curves (0); the NSF only (1); the SF only (2) }
    fraction1,fraction2:double;
    R:Tvec;

    function CalculDifference(MLnr:integer):double;
    var diff,diffSmooth:double;
    begin
       if MLnr=1 then begin CalculateReflectivity(MyEP,MyML1,MyDC1);MyDC1.Normalise(MyEP.NormalisationFactor*fraction1); end;
       if MLnr=2 then begin CalculateReflectivity(MyEP,MyML2,MyDC2);MyDC2.Normalise(MyEP.NormalisationFactor*fraction2); end;
       { on conserve de manière implicite les data calculées pour l'autre ML }
       { Calcul de la différence aux moindres carrés }
       R.copy(MyDC1.R);R.add(MyDC2.R);
       diff:=difference2(MyDataExp.R,MyDataExp.Rs,R,MyEP.PonderationType);
       result:=diff;
    end;

    procedure Crawl(var MyML:TMultiLayer;MLNr:integer);
    var i:integer;
    begin
        with MyML do
        for i:=0 to nbrLayers-1 do
        begin
            if (zYN[i]=0) and (random(100)>=randomness) then begin
                                 aux:=z[i];z[i]:=aux-zStep[i];chiMoins:=CalculDifference(MLNr);
                                 z[i]:=aux+zStep[i];chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin z[i]:=aux-zStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin z[i]:=aux+zStep[i];chi:=chiPlus end
                                                     else begin z[i]:=aux;  end
                                 end;

            if MyEP.Particles='neutrons' then
            begin
             if (dYN[i]=0) and (random(100)>=randomness)
             then if (Ord(dCorr[i])>=65) and (Ord(dCorr[i])<=70)
                  then begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];MyML.SetCorrParams(dCorr[i],'rho_n',d[i]);chiMoins:=CalculDifference(MLNr);
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];MyML.SetCorrParams(dCorr[i],'rho_n',d[i]);chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];MyML.SetCorrParams(dCorr[i],'rho_n',d[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];MyML.SetCorrParams(dCorr[i],'rho_n',d[i]);chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];MyML.SetCorrParams(dCorr[i],'rho_n',d[i]); end;
                                 end
                  else begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];chiMoins:=CalculDifference(MLNr);
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i] end;
                                 end;
             if (bYN[i]=0) and (random(100)>=randomness)
             then if (Ord(bCorr[i])>=65) and (Ord(bCorr[i])<=70)
                  then begin     aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];MyML.SetCorrParams(bCorr[i],'b',bn[i]);chiMoins:=CalculDifference(MLNr);
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];MyML.SetCorrParams(bCorr[i],'b',bn[i]);chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];MyML.SetCorrParams(bCorr[i],'b',bn[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];MyML.SetCorrParams(bCorr[i],'b',bn[i]);chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i];MyML.SetCorrParams(bCorr[i],'b',bn[i]); end
                                 end
                  else begin     aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];chiMoins:=CalculDifference(MLNr);
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i] end
                                 end;
             if (biYN[i]=0) and (random(100)>=randomness)
             then if (Ord(biCorr[i])>=65) and (Ord(biCorr[i])<=70)
                  then begin     aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyML.SetCorrParams(biCorr[i],'bi',bni[i]);chiMoins:=CalculDifference(MLNr);
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyML.SetCorrParams(biCorr[i],'bi',bni[i]);chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyML.SetCorrParams(biCorr[i],'bi',bni[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];MyML.SetCorrParams(biCorr[i],'bi',bni[i]);chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i];MyML.SetCorrParams(biCorr[i],'bi',bni[i]); end
                                 end
                  else begin     aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiMoins:=CalculDifference(MLNr);
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i]; end
                                 end;
            end;
            if MyEP.Particles='xrays' then
            begin
             if (dYN[i]=0) and (random(100)>=randomness)
             then if (Ord(dCorr[i])>=65) and (Ord(dCorr[i])<=70)
                  then begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];MyML.SetCorrParams(dCorr[i],'rho_x',d[i]);chiMoins:=CalculDifference(MLNr);
                                 d[i]:=aux+dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];MyML.SetCorrParams(dCorr[i],'rho_x',d[i]);chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];MyML.SetCorrParams(dCorr[i],'rho_x',d[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];MyML.SetCorrParams(dCorr[i],'rho_x',d[i]);chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];MyML.SetCorrParams(dCorr[i],'rho_x',d[i]); end;
                                 end
                  else begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];chiMoins:=CalculDifference(MLNr);
                                 d[i]:=aux+dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i]; end;
                                 end;
             if (fYN[i]=0) and (random(100)>=randomness)
             then if (Ord(fCorr[i])>=65) and (Ord(fCorr[i])<=70)
                  then begin     aux:=f[i];f[i]:=aux-fStep[i];V[i]:=Cte*d[i]*f[i];MyML.SetCorrParams(fCorr[i],'f',f[i]);chiMoins:=CalculDifference(MLNr);
                                 f[i]:=aux+fStep[i];V[i]:=Cte*d[i]*f[i];MyML.SetCorrParams(fCorr[i],'f',f[i]);chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin f[i]:=aux-fStep[i];V[i]:=Cte*d[i]*f[i];MyML.SetCorrParams(fCorr[i],'f',f[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin f[i]:=aux+fStep[i];V[i]:=Cte*d[i]*f[i];MyML.SetCorrParams(fCorr[i],'f',f[i]);chi:=chiPlus end
                                                     else begin f[i]:=aux;V[i]:=Cte*d[i]*f[i];MyML.SetCorrParams(fCorr[i],'f',f[i]); end
                                 end
                  else begin     aux:=f[i];f[i]:=aux-fStep[i];V[i]:=Cte*d[i]*f[i];chiMoins:=CalculDifference(MLNr);
                                 f[i]:=aux+fStep[i];V[i]:=Cte*d[i]*f[i];chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin f[i]:=aux-fStep[i];V[i]:=Cte*d[i]*f[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin f[i]:=aux+fStep[i];V[i]:=Cte*d[i]*f[i];chi:=chiPlus end
                                                     else begin f[i]:=aux;V[i]:=Cte*d[i]*f[i]; end
                                 end;
             if (fiYN[i]=0) and (random(100)>=randomness)
             then if (Ord(fiCorr[i])>=65) and (Ord(fiCorr[i])<=70)
                  then begin     aux:=fi[i];fi[i]:=aux-fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];MyML.SetCorrParams(fiCorr[i],'fi',fi[i]);chiMoins:=CalculDifference(MLNr);
                                 fi[i]:=aux+fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];MyML.SetCorrParams(fiCorr[i],'fi',fi[i]);chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin fi[i]:=aux-fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];MyML.SetCorrParams(fiCorr[i],'fi',fi[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin fi[i]:=aux+fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];MyML.SetCorrParams(fiCorr[i],'fi',fi[i]);chi:=chiPlus end
                                                     else begin fi[i]:=aux;Vi[i]:=-Cte*d[i]*fi[i];MyML.SetCorrParams(fiCorr[i],'fi',fi[i]); end
                                 end
                  else begin     aux:=fi[i];fi[i]:=aux-fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];chiMoins:=CalculDifference(MLNr);
                                 fi[i]:=aux+fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin fi[i]:=aux-fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin fi[i]:=aux+fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];chi:=chiPlus end
                                                     else begin fi[i]:=aux;Vi[i]:=-Cte*d[i]*fi[i]; end
                                 end;
            end;

             if (sigYN[i]=0) and (random(100)>=randomness) then begin
                                 aux:=sigma[i];sigma[i]:=aux-sigmaStep[i];chiMoins:=CalculDifference(MLNr);
                                 sigma[i]:=aux+sigmaStep[i];chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin sigma[i]:=aux-sigmaStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin sigma[i]:=aux+sigmaStep[i];chi:=chiPlus end
                                                     else begin sigma[i]:=aux; end
                                 end;
             if sigma[i]<0 then sigma[i]:=-sigma[i]; { on passe systématiquement les sigam à des valeurs positives }

        end;
    end;

begin
     createIt(R);
     StopFittingFlag:=false;
     with SimulReflecWindow do
     begin
         dataFittingOption:=dataFittingOptionsBox.itemIndex;
         fraction1:=fraction1Box.value/(fraction1Box.value+fraction2Box.value);
         fraction2:=fraction2Box.value/(fraction1Box.value+fraction2Box.value);
         FittingStatus.caption:='Fitting...';FittingStatus.update;
         nbrIter:=spinEditNbrIter.value
     end;

     { calcul de l'ecart au point de depart }
     CalculateReflectivity(MyEP,MyML2,MyDC2);MyDC2.Normalise(MyEP.NormalisationFactor*fraction2);
     CalculateReflectivity(MyEP,MyML1,MyDC1);MyDC1.Normalise(MyEP.NormalisationFactor*fraction1);
     chi:=CalculDifference(0); { avec indice 0 onne recalcule pas les réflectivités }
     { on boucle sur les différents paramètres }
     for niter:=1 to round(NbrIter/(100-randomness)*100) do
     begin
        with SimulReflecWindow do begin IterCrt.caption:=IntToStr(nIter);IterCrt.update;end;
        { fit sur la normalisation }
        with MyEP do
        begin
        if (FitNormalisation=true) and (random(100)>=randomness)
        then begin
             { on initialise les data calculées }
             CalculateReflectivity(MyEP,MyML2,MyDC2);MyDC2.Normalise(MyEP.NormalisationFactor*fraction2);
             CalculateReflectivity(MyEP,MyML1,MyDC1);MyDC1.Normalise(MyEP.NormalisationFactor*fraction1);
             aux:=normalisationFactor;
             normalisationFactor:=aux-normalisationFactorStep;
             CalculateReflectivity(MyEP,MyML2,MyDC2);MyDC2.Normalise(MyEP.NormalisationFactor*fraction2);
             CalculateReflectivity(MyEP,MyML1,MyDC1);MyDC1.Normalise(MyEP.NormalisationFactor*fraction1);
             chiMoins:=CalculDifference(0); { l'indice 1 n'est pas important puisqu'on ne fait bouger que la normalisation }
             normalisationFactor:=aux+normalisationFactorStep;
             CalculateReflectivity(MyEP,MyML2,MyDC2);MyDC2.Normalise(MyEP.NormalisationFactor*fraction2);
             CalculateReflectivity(MyEP,MyML1,MyDC1);MyDC1.Normalise(MyEP.NormalisationFactor*fraction1);
             chiPlus:=CalculDifference(0);
             if chiMoins<chi
             then begin normalisationfactor:=aux-normalisationFactorStep;chi:=chiMoins end
             else if chiPlus<chi then begin normalisationfactor:=aux+normalisationFactorStep;chi:=chiMoins;chi:=chiPlus end
                                 else begin normalisationfactor:=aux;  end
             end;
        end;
        { on boucle sur toutes les couches du système }
        { on initialise les data calculées }
        CalculateReflectivity(MyEP,MyML2,MyDC2);MyDC2.Normalise(MyEP.NormalisationFactor*fraction2);
        Crawl(MyML1,1);
        CalculateReflectivity(MyEP,MyML1,MyDC1);MyDC1.Normalise(MyEP.NormalisationFactor*fraction1);
        Crawl(MyML2,2);
   { après une première boucle, on met a jour les paramètres du tableau }
        SimulReflecWindow.updateDisplayWhileFitting(SimulReflecWindow.MultiLayerGrid,MyML1,MyEP,chi);
        SimulReflecWindow.updateDisplayWhileFitting(SimulReflecWindow.MultiLayerGrid2,MyML2,MyEP,chi);
        Application.processMessages; { l'utilisateur a-t-il appuyé sur le boutton ? }
        if StopFittingFlag=true then break; { on sort du fit }
{        if ReplotFlag=true then begin CalculateReflectivity(MyExperimentalParameters,MyMultilayer,MyDataCalc);SimulReflecWindow.PlotReflectivity(MyExperimentalParameters,MyDataCalc);replotFlag:=false end; }
   end;
{ le fit est fini }
   freeIt(R);
end;


{ MINIMISATION AVEC NOUVEAUX TYPES DE DATA pour mesures de SPIN-FLIP     }
{ procédure de minimisation utilisant le crawling                        }
{ on déplace chaque parametre d'une quantité step en + ou en - et        }
{ on garde la meilleure valeur                                           }
{ NOTA : Il faut que les paramètres de DataCalc et DateExp soient compatible }
{ NOTA2 : il y a une bidouille moche avec MLNr pour gagner en vitesse de calcul }
Procedure MinimisationCrawling_SF_PD(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMultiLayer,MyMultiLayer2:TMultiLayer;var MyProfiles:TProfiles;var MyDataExp,MyDataCalc,MyDataCalc2:TDataReflectivity);
var niter,NbrIter: integer;
    chi,chimoins,chiplus,aux:double; { valeurs du paramètre , point de départ, dpart + step, depart - step }
    dataFittingOption:integer; { fitting all the data curves (0); the NSF only (1); the SF only (2) }
    fraction1,fraction2:double;

    function CalculDifference(MLnr:integer):double; { peu subtil, on calcul deux fois trop les courbes }
    var diff,diffSmooth:double;
    begin
       if MLnr=1
       then begin CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor) end
       else begin CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor) end;
       { application du facteur de normalisation }
       { Calcul de la différence aux moindres carrés }
       { N'IMPORTE QUOI !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! }
       case dataFittingOption of
         0:diff:=fraction1*(difference2(MyDataExp.Ruu,MyDataExp.Ruus,MyDataCalc.Ruu,MyExperimentalParameters.PonderationType)
                           +difference2(MyDataExp.Rdd,MyDataExp.Rdds,MyDataCalc.Rdd,MyExperimentalParameters.PonderationType)
                           +difference2(MyDataExp.Rud,MyDataExp.Ruds,MyDataCalc.Rud,MyExperimentalParameters.PonderationType))
                +fraction2*(difference2(MyDataExp.Ruu,MyDataExp.Ruus,MyDataCalc2.Ruu,MyExperimentalParameters.PonderationType)
                           +difference2(MyDataExp.Rdd,MyDataExp.Rdds,MyDataCalc2.Rdd,MyExperimentalParameters.PonderationType)
                           +difference2(MyDataExp.Rud,MyDataExp.Ruds,MyDataCalc2.Rud,MyExperimentalParameters.PonderationType));
         1:diff:=fraction1*(difference2(MyDataExp.Ruu,MyDataExp.Ruus,MyDataCalc.Ruu,MyExperimentalParameters.PonderationType)
                           +difference2(MyDataExp.Rdd,MyDataExp.Rdds,MyDataCalc.Rdd,MyExperimentalParameters.PonderationType))
                +fraction2*(difference2(MyDataExp.Ruu,MyDataExp.Ruus,MyDataCalc2.Ruu,MyExperimentalParameters.PonderationType)
                           +difference2(MyDataExp.Rdd,MyDataExp.Rdds,MyDataCalc2.Rdd,MyExperimentalParameters.PonderationType));
         2:diff:=fraction1*difference2(MyDataExp.Rud,MyDataExp.Ruds,MyDataCalc.Rud,MyExperimentalParameters.PonderationType)
                +fraction2*difference2(MyDataExp.Rud,MyDataExp.Ruds,MyDataCalc2.Rud,MyExperimentalParameters.PonderationType);
     end;
     { CE N'EST PAS LA MEILLEURE PLACE; ON DEVRAIT CALCULER CA SEULEMENT SI UN PARA DU PROFIL CHANGE }
     { ajout de la ponderation liée au profil de type smooth }
     diffSmooth:=0;
     if MyMultiLayer.profiled then diffSmooth:=diffSmooth+MyMultiLayer.SmoothProfile(MyProfiles);
     if MyMultiLayer2.profiled then diffSmooth:=diffSmooth+MyMultiLayer2.SmoothProfile(MyProfiles);
     result:=diff+diffSmooth;
    end;

    procedure Crawl(var MyML:TMultiLayer;MLNr:integer);
    var i:integer;
    begin
        with MyML do
        for i:=0 to nbrLayers-1 do
        begin
             if (zYN[i]=0) and (random(100)>=randomness) then begin
                                 aux:=z[i];z[i]:=aux-zStep[i];chiMoins:=CalculDifference(MLNr);
                                 z[i]:=aux+zStep[i];chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin z[i]:=aux-zStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin z[i]:=aux+zStep[i];chi:=chiPlus end
                                                     else begin z[i]:=aux;  end
                                 end;
             if (dYN[i]=0) and (random(100)>=randomness) then begin
                                 aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference(MLNr);
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end;
                                 end;
             if (sigYN[i]=0) and (random(100)>=randomness) then begin
                                 aux:=sigma[i];sigma[i]:=aux-sigmaStep[i];chiMoins:=CalculDifference(MLNr);
                                 sigma[i]:=aux+sigmaStep[i];chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin sigma[i]:=aux-sigmaStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin sigma[i]:=aux+sigmaStep[i];chi:=chiPlus end
                                                     else begin sigma[i]:=aux; end
                                 end;
             if sigma[i]<0 then sigma[i]:=-sigma[i]; { on passe systématiquement les sigam à des valeurs positives }
             if (bYN[i]=0) and (random(100)>=randomness) then begin
                                 aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference(MLNr);
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end
                                 end;
             if (biYN[i]=0) and (random(100)>=randomness) then begin
                                 aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiMoins:=CalculDifference(MLNr);
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i]; end
                                 end;
             if (MYN[i]=0) and (random(100)>=randomness) then begin
                                 aux:=Aim[i];Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference(MLNr);
                                 Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin Aim[i]:=aux;Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end
                                 end;
             if (PhiYN[i]=0) and (random(100)>=randomness) then begin
                                 aux:=Phi[i];Phi[i]:=aux-PhiStep[i];chiMoins:=CalculDifference(MLNr);
                                 Phi[i]:=aux+PhiStep[i];chiPlus:=CalculDifference(MLNr);
                                 if chiMoins<chi
                                 then begin Phi[i]:=aux-PhiStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin Phi[i]:=aux+PhiStep[i];chi:=chiPlus end
                                                     else begin Phi[i]:=aux; end
                                 end;
        end;
    end;

begin
     StopFittingFlag:=false;
     with SimulReflecWindow do
     begin
         dataFittingOption:=dataFittingOptionsBox.itemIndex;
         fraction1:=fraction1Box.value/(fraction1Box.value+fraction2Box.value);
         fraction2:=fraction2Box.value/(fraction1Box.value+fraction2Box.value);
         FittingStatus.caption:='Fitting...';FittingStatus.update;
         nbrIter:=spinEditNbrIter.value
     end;

     { calcul de l'ecart au point de depart }
     chi:=CalculDifference(1);
     chi:=CalculDifference(2); { ca fait un peu bricolage ! }
     { on boucle sur les différents paramètres }
     for niter:=1 to round(NbrIter/(100-randomness)*100) do
     begin
        with SimulReflecWindow do begin IterCrt.caption:=IntToStr(nIter);IterCrt.update;end;
        { fit sur la normalisation }
        with MyExperimentalParameters do
        begin
        if (FitNormalisation=true) and (random(100)>=randomness) then begin
                                 aux:=normalisationFactor;
                                 normalisationFactor:=aux-normalisationFactorStep;
                                 chiMoins:=CalculDifference(1);chiMoins:=CalculDifference(2); { ca fait un peu bricolage ! }
                                 normalisationFactor:=aux+normalisationFactorStep;
                                 chiPlus:=CalculDifference(1);chiPlus:=CalculDifference(2);
                                 if chiMoins<chi
                                 then begin normalisationfactor:=aux-normalisationFactorStep;chi:=chiMoins end
                                 else if chiPlus<chi then begin normalisationfactor:=aux+normalisationFactorStep;chi:=chiMoins;chi:=chiPlus end
                                                     else begin normalisationfactor:=aux;  end
                                 end;
        end;
        { on boucle sur toutes les couches du système }
        Crawl(MyMultiLayer,1);
        Crawl(MyMultiLayer2,2);
   { après une première boucle, on met a jour les paramètres du tableau }

        SimulReflecWindow.updateDisplayWhileFitting(SimulReflecWindow.MultiLayerGrid,MyMultiLayer,MyExperimentalParameters,chi);
        SimulReflecWindow.updateDisplayWhileFitting(SimulReflecWindow.MultiLayerGrid2,MyMultiLayer,MyExperimentalParameters,chi);
        Application.processMessages; { l'utilisateur a-t-il appuyé sur le boutton ? }
        if StopFittingFlag=true then break; { on sort du fit }
        if ReplotFlag=true then begin CalculateReflectivity(MyExperimentalParameters,MyMultilayer,MyDataCalc);SimulReflecWindow.PlotReflectivity(MyExperimentalParameters,MyDataCalc);replotFlag:=false end;        
   end;
{ le fit est fini }

end;

{ =======================================================================}
{ MINIMISATION DES MDS                                                   }
{ procédure de minimisation utilisant le crawling                        }
{ on déplace chaque parametre d'une quantité step en + ou en - et        }
{ on garde la meilleure valeur                                           }
{ NOTA : Il faut que les paramètres de DataCalc et DateExp soient compatible }
Procedure MinimisationCrawlingMDS(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMDS_ML:array of TMultiLayer;var MyProfiles:TProfiles;var MyMDSfit,MyMDS_dataCalc:array of TDataReflectivity);
var MDSidx,i,niter,nbrIter: integer;
    chi,chimoins,chiplus,aux:double; { valeurs du paramètre , point de départ, dpart + step, depart - step }

function CalculDifference:double;
var i:integer;
    diff,diffSmooth:double;
begin
   diff:=0;
   for i:=0 to high(MyMDSfit) do
   begin
        CalculateReflectivity(MyExperimentalParameters,MyMDS_ML[i],MyMDS_DataCalc[i]);
        { application du facteur de normalisation }
        { Calcul de la différence aux moindres carrés }
        diff:=diff+difference2(MyMDSfit[i].R,MyMDSfit[i].Rs,MyMDS_DataCalc[i].R,MyExperimentalParameters.PonderationType);
        if MyMDS_ML[i].profiled
        then diffSmooth:=MyMDS_ML[i].SmoothProfile(MyProfiles) else diffSmooth:=0;
        diff:=diff+diffSmooth;
   end;
   result:=diff;
end;

procedure UpdateMDS_ML(para:string;idx:integer;value:double);
var i:integer;
begin
    for i:=0 to high(MyMDS_ML) do
    begin
      with MyMDS_ML[i] do
      begin
        if para='z' then z[idx]:=value;
        if para='rho'
        then begin
             if MyExperimentalParameters.Particles='neutrons' then begin d[idx]:=value;V[idx]:=Pihm*d[idx]*bn[idx];Vi[idx]:=-Pihm*d[idx]*bni[idx] end;
             if MyExperimentalParameters.Particles='xrays' then begin d[idx]:=value;V[idx]:=Cte*d[idx]*f[idx];Vi[idx]:=-Cte*d[idx]*fi[idx] end;
             end;
        if para='b' then begin bn[idx]:=value;V[idx]:=Pihm*d[idx]*bn[idx] end;
        if para='bi' then begin bni[idx]:=value;Vi[idx]:=-Pihm*d[idx]*bni[idx] end;
        if para='f' then begin f[idx]:=value;V[idx]:=Cte*d[idx]*f[idx] end;
        if para='fi' then begin fi[idx]:=value;Vi[idx]:=-Cte*d[idx]*fi[idx] end;
        if para='sigma' then sigma[idx]:=value;
      end
    end;
end;

begin
     StopFittingFlag:=false;
     with SimulReflecWindow do
     begin
         FittingStatus.caption:='Fitting...';FittingStatus.update;
         nbrIter:=spinEditNbrIter.value
     end;
     { calcul de l'ecart au point de depart }
     chi:=CalculDifference;
     { on boucle sur les différents paramètres }
     for niter:=1 to round(NbrIter/(100-randomness)*100) do
     begin
        with SimulReflecWindow do begin IterCrt.caption:=IntToStr(nIter);IterCrt.update; end;
        { fit sur la normalisation }
        { désactivé pour les MDS puisque ca n'a pas de sens }
        { on boucle sur toutes les couches du système }
        { pour chaque parametre, 2 cas :                }
        { 1°/c'est un paramètre fixe et donc on propage sa modification a toutes les couches }
        { 2°/ c'est un paramètre libre et donc on le fitte indépendamment pour chaque dataSet }
        for MDSidx:=0 to high(MyMDSfit) do
        begin

        with MyMDS_ML[MDSidx] do
        for i:=0 to nbrLayers-1 do
        begin
             if (zYN[i]=0) and (random(100)>=randomness)
             then if (zCorr[i]='L') { we are dealing with a free parameter between the MDS }
                  then begin     aux:=z[i];z[i]:=aux-zStep[i];chiMoins:=CalculDifference;
                                 z[i]:=aux+zStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin z[i]:=aux-zStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin z[i]:=aux+zStep[i];chi:=chiPlus end
                                                     else begin z[i]:=aux;  end
                                 end
{ linked para }   else begin     aux:=z[i];UpdateMDS_ML('z',i,aux-zStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('z',i,aux+zStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('z',i,aux-zStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('z',i,aux+zStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('z',i,aux) end
                                 end;

            if MyExperimentalParameters.Particles='neutrons' then
            begin
             if (dYN[i]=0) and (random(100)>=randomness)
             then if (dCorr[i]='L')
                  then begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i] end;
                                 end
                  else begin     aux:=d[i];UpdateMDS_ML('rho',i,aux-dStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('rho',i,aux+dStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('rho',i,aux-dStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('rho',i,aux+dStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('rho',i,aux); end;
                                 end;
             if (bYN[i]=0) and (random(100)>=randomness)
             then if (bCorr[i]='L')
                  then begin     aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];chiMoins:=CalculDifference;
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i] end
                                 end
                  else begin     aux:=bn[i];UpdateMDS_ML('b',i,aux-bStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('b',i,aux+bStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('b',i,aux-bStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('b',i,aux+bStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('b',i,aux) end
                                 end;
             if (biYN[i]=0) and (random(100)>=randomness)
             then if (biCorr[i]='L')
                  then begin     aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiMoins:=CalculDifference;
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i]; end
                                 end
                  else begin     aux:=bni[i];UpdateMDS_ML('bi',i,aux-biStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('bi',i,aux+biStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('bi',i,aux-biStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('bi',i,aux+biStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('bi',i,aux) end
                                 end;
            end;
            if MyExperimentalParameters.Particles='xrays' then
            begin
             if (dYN[i]=0) and (random(100)>=randomness)
             then if (dCorr[i]='L')
                  then begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i];chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i]; end;
                                 end
                  else begin     aux:=d[i];UpdateMDS_ML('d',i,aux-dStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('d',i,aux+dStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('d',i,aux-dStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('d',i,aux+dStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('d',i,aux) end;
                                 end;
             if (fYN[i]=0) and (random(100)>=randomness)
             then if (fCorr[i]='L')
                  then begin     aux:=f[i];f[i]:=aux-fStep[i];V[i]:=Cte*d[i]*f[i];chiMoins:=CalculDifference;
                                 f[i]:=aux+fStep[i];V[i]:=Cte*d[i]*f[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin f[i]:=aux-fStep[i];V[i]:=Cte*d[i]*f[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin f[i]:=aux+fStep[i];V[i]:=Cte*d[i]*f[i];chi:=chiPlus end
                                                     else begin f[i]:=aux;V[i]:=Cte*d[i]*f[i]; end
                                 end
                  else begin     aux:=f[i];UpdateMDS_ML('f',i,aux-fStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('f',i,aux+fStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('f',i,aux-fStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('f',i,aux+fStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('f',i,aux) end
                                 end;
             if (fiYN[i]=0) and (random(100)>=randomness)
             then if (fiCorr[i]='L')
                  then begin     aux:=fi[i];fi[i]:=aux-fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];chiMoins:=CalculDifference;
                                 fi[i]:=aux+fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin fi[i]:=aux-fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin fi[i]:=aux+fiStep[i];Vi[i]:=-Cte*d[i]*fi[i];chi:=chiPlus end
                                                     else begin fi[i]:=aux;Vi[i]:=-Cte*d[i]*fi[i]; end
                                 end
                  else begin     aux:=fi[i];UpdateMDS_ML('fi',i,aux-fiStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('fi',i,aux+fiStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('fi',i,aux-fiStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('fi',i,aux+fiStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('fi',i,aux) end
                                 end;
            end;

             if (sigYN[i]=0) and (random(100)>=randomness)
             then if (sigmaCorr[i]='L')
                  then begin     aux:=sigma[i];sigma[i]:=aux-sigmaStep[i];chiMoins:=CalculDifference;
                                 sigma[i]:=aux+sigmaStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin sigma[i]:=aux-sigmaStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin sigma[i]:=aux+sigmaStep[i];chi:=chiPlus end
                                                     else begin sigma[i]:=aux; end
                                 end
                  else begin     aux:=sigma[i];UpdateMDS_ML('sigma',i,aux-sigmaStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('sigma',i,aux+sigmaStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('sigma',i,aux-sigmaStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('sigma',i,aux+sigmaStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('sigma',i,aux) end
                                 end;
             if sigma[i]<0 then sigma[i]:=-sigma[i]; { on passe systématiquement les sigam à des valeurs positives }

        end; { fin de la boucle sur les différentes couches en i }
        end; { fin de la boucle sur les MDS en MDSidx }

   { après une première boucle, on met a jour les paramètres du tableau }
   { on affiche les paramètres de la couche indiqués par MDSIndexBox }
          SimulReflecWindow.updateDisplayWhileFitting(SimulReflecWindow.MultiLayerGrid,MyMDS_ML[SimulReflecWindow.MDSIndexBox.value-1],MyExperimentalParameters,chi);
          SimulReflecWindow.UpdateMDSfreeParams(MyMDS_ML,MyExperimentalParameters);

          Application.processMessages; { l'utilisateur a-t-il appuyé sur le boutton ? }
          if StopFittingFlag=true then break; { on sort du fit }
        end;
{ le fit est fini }

end;

{ =======================================================================}
{ MINIMISATION DES MDS                                                   }
{ procédure de minimisation utilisant le crawling                        }
{ on déplace chaque parametre d'une quantité step en + ou en - et        }
{ on garde la meilleure valeur                                           }
{ NOTA : Il faut que les paramètres de DataCalc et DateExp soient compatible }
Procedure MinimisationCrawlingMDS_P(randomness:integer;var MyExperimentalParameters:TExperimentalParameters;var MyMDS_ML:array of TMultiLayer;var MyProfiles:TProfiles;var MyMDSfit,MyMDS_dataCalc:array of TDataReflectivity);
var MDSidx,i,niter,nbrIter:integer;
    toto,chi,chimoins,chiplus,aux:double; { valeurs du paramètre , point de départ, dpart + step, depart - step }

function CalculDifference:double;
var i:integer;
    diff,diffSmooth:double;
begin
   diff:=0;
   for i:=0 to high(MyMDSfit) do
   begin
        CalculateReflectivity(MyExperimentalParameters,MyMDS_ML[i],MyMDS_DataCalc[i]);
        { application du facteur de normalisation }
        { Calcul de la différence aux moindres carrés }
        diff:=diff+difference2(MyMDSfit[i].Rup,MyMDSfit[i].Rups,MyMDS_DataCalc[i].Rup,MyExperimentalParameters.PonderationType)
                  +difference2(MyMDSfit[i].Rdo,MyMDSfit[i].Rdos,MyMDS_DataCalc[i].Rdo,MyExperimentalParameters.PonderationType);
        { CE N'EST PAS LA MEILLEURE PLACE; ON DEVRAIT CALCULER CA SEULEMENT SI UN PARA DU PROFIL CHANGE }
        { ajout de la ponderation liée au profil de type smooth }
        if MyMDS_ML[i].profiled
        then diffSmooth:=MyMDS_ML[i].SmoothProfile(MyProfiles) else diffSmooth:=0;
        diff:=diff+diffSmooth;
   end;
   result:=diff;
end;

procedure UpdateMDS_ML(para:string;idx:integer;value:double);
var i:integer;
begin
    for i:=0 to high(MyMDS_ML) do
    begin
      with MyMDS_ML[i] do
      begin
        if para='z' then z[idx]:=value;
        if para='rho'
        then begin
             if MyExperimentalParameters.Particles='neutrons'
             then begin d[idx]:=value;
                        V[idx]:=Pihm*d[idx]*bn[idx];Vi[idx]:=-Pihm*d[idx]*bni[idx];
                        Vup[idx]:=V[idx]-Aim[idx]*mun;Vdo[idx]:=V[idx]+Aim[idx]*mun;
                        end;
             if MyExperimentalParameters.Particles='xrays'
             then begin d[idx]:=value;V[idx]:=Cte*d[idx]*f[idx];Vi[idx]:=-Cte*d[idx]*fi[idx] end;
             end;
        if para='b' then begin bn[idx]:=value;V[idx]:=Pihm*d[idx]*bn[idx];Vup[idx]:=V[idx]-Aim[idx]*mun;Vdo[idx]:=V[idx]+Aim[idx]*mun end;
        if para='bi' then begin bni[idx]:=value;Vi[idx]:=-Pihm*d[idx]*bni[idx];Vup[idx]:=V[idx]-Aim[idx]*mun;Vdo[idx]:=V[idx]+Aim[idx]*mun end;
        if para='f' then begin f[idx]:=value;V[idx]:=Cte*d[idx]*f[idx] end;
        if para='fi' then begin fi[idx]:=value;Vi[idx]:=-Cte*d[idx]*fi[idx] end;
        if para='M' then begin Aim[idx]:=value;Vup[idx]:=V[idx]-Aim[idx]*mun;Vdo[idx]:=V[idx]+Aim[idx]*mun end;
        if para='sigma' then sigma[idx]:=value;
      end
    end;
end;

begin
     StopFittingFlag:=false;
     with SimulReflecWindow do
     begin
         FittingStatus.caption:='Fitting...';FittingStatus.update;
         nbrIter:=spinEditNbrIter.value
     end;
     { calcul de l'ecart au point de depart }
     chi:=CalculDifference;
     { on boucle sur les différents paramètres }
     for niter:=1 to round(NbrIter/(100-randomness)*100) do
     begin
        with SimulReflecWindow do begin IterCrt.caption:=IntToStr(nIter);IterCrt.update; end;
        { fit sur la normalisation }
        { désactivé pour les MDS puisque ca n'a pas de sens }
        { on boucle sur toutes les couches du système }
        { pour chaque parametre, 2 cas :                }
        { 1°/c'est un paramètre fixe et donc on propage sa modification a toutes les couches }
        { 2°/ c'est un paramètre libre et donc on le fitte indépendamment pour chaque dataSet }
        for MDSidx:=0 to high(MyMDSfit) do
        begin

        with MyMDS_ML[MDSidx] do
        for i:=0 to nbrLayers-1 do
        begin
             if (zYN[i]=0) and (random(100)>=randomness)
             then if (zCorr[i]='L') { we are dealing with a free parameter between the MDS }
                  then begin     aux:=z[i];z[i]:=aux-zStep[i];chiMoins:=CalculDifference;
                                 z[i]:=aux+zStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin z[i]:=aux-zStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin z[i]:=aux+zStep[i];chi:=chiPlus end
                                                     else begin z[i]:=aux;  end
                                 end
{ linked para }   else begin     aux:=z[i];UpdateMDS_ML('z',i,aux-zStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('z',i,aux+zStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('z',i,aux-zStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('z',i,aux+zStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('z',i,aux) end
                                 end;

             if (dYN[i]=0) and (random(100)>=randomness)
             then if (dCorr[i]='L')
                  then begin     aux:=d[i];d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference;
                                 d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin d[i]:=aux-dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin d[i]:=aux+dStep[i];V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin d[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end;
                                 end
                  else begin     aux:=d[i];UpdateMDS_ML('rho',i,aux-dStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('rho',i,aux+dStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('rho',i,aux-dStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('rho',i,aux+dStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('rho',i,aux); end;
                                 end;
             if (bYN[i]=0) and (random(100)>=randomness)
             then if (bCorr[i]='L')
                  then begin     aux:=bn[i];bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference;
                                 bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bn[i]:=aux-bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin bn[i]:=aux+bStep[i];V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin bn[i]:=aux;V[i]:=Pihm*d[i]*bn[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end
                                 end
                  else begin     aux:=bn[i];UpdateMDS_ML('b',i,aux-bStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('b',i,aux+bStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('b',i,aux-bStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('b',i,aux+bStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('b',i,aux) end
                                 end;
             if (biYN[i]=0) and (random(100)>=randomness)
             then if (biCorr[i]='L')
                  then begin     aux:=bni[i];bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiMoins:=CalculDifference;
                                 bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin bni[i]:=aux-biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin bni[i]:=aux+biStep[i];Vi[i]:=-Pihm*d[i]*bni[i];chi:=chiPlus end
                                                     else begin bni[i]:=aux;Vi[i]:=-Pihm*d[i]*bni[i]; end
                                 end
                  else begin     aux:=bni[i];UpdateMDS_ML('bi',i,aux-biStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('bi',i,aux+biStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('bi',i,aux-biStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('bi',i,aux+biStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('bi',i,aux) end
                                 end;
             if (MYN[i]=0) and (random(100)>=randomness)
             then if (MCorr[i]='L')
                  then begin     aux:=Aim[i];Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiMoins:=CalculDifference;
                                 Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin Aim[i]:=aux-AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiMoins end
                                 else if chiPlus<chi then begin Aim[i]:=aux+AimStep[i];Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun;chi:=chiPlus end
                                                     else begin Aim[i]:=aux;Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun end
                                 end
                  else begin     aux:=Aim[i];UpdateMDS_ML('M',i,aux-AimStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('M',i,aux+AimStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('M',i,aux-AimStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('M',i,aux+AimStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('M',i,aux); end
                                 end;

             if (sigYN[i]=0) and (random(100)>=randomness)
             then if (sigmaCorr[i]='L')
                  then begin     aux:=sigma[i];sigma[i]:=aux-sigmaStep[i];chiMoins:=CalculDifference;
                                 sigma[i]:=aux+sigmaStep[i];chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin sigma[i]:=aux-sigmaStep[i];chi:=chiMoins end
                                 else if chiPlus<chi then begin sigma[i]:=aux+sigmaStep[i];chi:=chiPlus end
                                                     else begin sigma[i]:=aux; end
                                 end
                  else begin     aux:=sigma[i];UpdateMDS_ML('sigma',i,aux-sigmaStep[i]);chiMoins:=CalculDifference;
                                 UpdateMDS_ML('sigma',i,aux+sigmaStep[i]);chiPlus:=CalculDifference;
                                 if chiMoins<chi
                                 then begin UpdateMDS_ML('sigma',i,aux-sigmaStep[i]);chi:=chiMoins end
                                 else if chiPlus<chi then begin UpdateMDS_ML('sigma',i,aux+sigmaStep[i]);chi:=chiPlus end
                                                     else begin UpdateMDS_ML('sigma',i,aux) end
                                 end;
             if sigma[i]<0 then sigma[i]:=-sigma[i]; { on passe systématiquement les sigam à des valeurs positives }

        end; { fin de la boucle sur les différentes couches en i }
        end; { fin de la boucle sur les MDS en MDSidx }

   { après une première boucle, on met a jour les paramètres du tableau }
   { on affiche les paramètres de la couche indiqués par MDSInexBox }
          SimulReflecWindow.updateDisplayWhileFitting(SimulReflecWindow.MultiLayerGrid,MyMDS_ML[SimulReflecWindow.MDSIndexBox.value-1],MyExperimentalParameters,chi);
          SimulReflecWindow.UpdateMDSfreeParams(MyMDS_ML,MyExperimentalParameters);
                    
          Application.processMessages; { l'utilisateur a-t-il appuyé sur le boutton ? }
          if StopFittingFlag=true then break; { on sort du fit }
        end;
{ le fit est fini }
end;

{ ============================================================================= }
{ fin des procédures de minimisation CRAWLING                                   }
{ ============================================================================= }

end.
