Page 1 of 1

Generate multiple systems with a for loop

Posted: Thu Mar 03, 2016 1:33 am
by thanasis
Hello everyone,

I want to generate n spin systems, all of which are variants of a basic system according to a predefined trigonometric function. The fit is carried out on two external parameters that generate the actual parameters of each individual spin system.

My code is:

Code: Select all

cm=100*clight/1e6; % Conversion constant from cm-1 to MHz

J=-30; % Isotropic exchange in cm-1 according to the -2JSiSj formalism (external parameter)
r=0.01; % Coefficient (external parameter)
gxy=2; gz=2;
n=12; %Number of variations of the phi angle <--This is the number of the individual spin systems that will be generated

% Angles to be used as constants
theta1=0;
theta2=-2*pi/3;
theta3=2*pi/3;

%Experimental for curry
[T,chiSI] = textread('data_easyspin_chiSI.dat','%f %f');
Exp.Field = 1000; Exp.Temperature = T; chiSI = n*chiSI; <-- The calculated curves are added up. The experimental curve needs to be multiplied by [i]n[/i] to be brought up to the calculated curve.

%Define a dummy system containing the J and r parameters as variables
SysA.r = r;
SysA.J = J;

% Create n systems Sys(1), Sys(2),...Sys(n)
for i=1:n 
phi(i)=((i-1)/n)*2*pi;

%The trigonometric function:
a12(i)=r*(cos(phi(i)-theta1));
a13(i)=r*(cos(phi(i)-theta2));
a23(i)=r*(cos(phi(i)-theta3));

J12(i)=-2*cm*J*(1+a12(i));
J13(i)=-2*cm*J*(1+a13(i));
J23(i)=-2*cm*J*(1+a23(i));

Sys(i).S=[5/2 5/2 5/2];
Sys(i).g=[gxy gz; gxy gz; gxy gz];
Sys(i).weight=1/n;
Sys(i).ee = [J12(i) J13(i) J23(i)];
end

VaryA.r = [0.01];
VaryA.J = [5];
for i=1:n
    Vary(i).ee = [0 0 0];
    Vary(i).g = [0 0; 0 0; 0 0];
end

FitOpt.OutArg = [2 2];   % to fit the magnetic susceptibility chizz (second output)
FitOpt.Method = 'simplex fcn';
FitOpt.Scaling = 'none';

esfit('curry',chiSI,{SysA,Sys(1),Sys(2),Sys(3),Sys(4),Sys(5),Sys(6),Sys(7),Sys(8),Sys(9),Sys(10),Sys(11),Sys(12)},{VaryA,Vary(1),Vary(2),Vary(3),Vary(4),Vary(5),Vary(6),Vary(7),Vary(8),Vary(9),Vary(10),Vary(11),Vary(12)},Exp,[],FitOpt);
The code works up to a certain point. The fitting window comes up, the calculated curve is displayed for the initial values of the parameters, but the RMSD stays invariable despite the variation of J and r. In essence, there is no fit taking place.

What am I missing?

Thanks in advance!

Re: Generate multiple systems with a for loop

Posted: Wed Mar 09, 2016 10:10 am
by joscha_nehrkorn
You vary r and J, which do not affect the calculations done in curry. That's why no fitting take place.

You have to define a function which do the assignment of r and J to the subsystems and then call curry. Then you can call this function with esfit (read the manual on how to use esfit with self-written fit function).

Re: Generate multiple systems with a for loop

Posted: Thu Mar 10, 2016 1:12 am
by thanasis
Thanks for the pointer Joscha, I will look into it!

Re: Generate multiple systems with a for loop

Posted: Fri Mar 11, 2016 2:20 am
by thanasis
OK, so I took another look at the examples on the use of esfit with external functions.

One thing that I don't understand is how to deal with several Sys structures, like in my case. I have defined SysA which holds the two "dummy" variables and Sys(i) (i = 1,2,....n) which are the actual spin systems.

I tried building a function like:

Code: Select all

function y = myfun(SysA,Exp,Opt)
r=0;
J=0;
gz=2; gxy=2;
n=0;
theta1=0;
theta2=-2*pi/3;
theta3=2*pi/3;
cm=100*clight/1e6; % Conversion constant from cm-1 to MHz
SysA.r = r;
SysA.J = J;

for i=1:n 
phi(i)=((i-1)/n)*2*pi;

a12(i)=... etc
J12(i)=...etc

Sys(i).S=[5/2 5/2 5/2];
Sys(i).g=[gxy gz; gxy gz; gxy gz];
Sys(i).weight=1/n;
Sys(i).ee = [J12(i) J13(i) J23(i)];

Vary(i).ee = [0 0 0];
Vary(i).g = [0 0; 0 0; 0 0];
end
[x,y] = curry(SysA,Exp,Opt);
return
,
where I invoke only the "dummy" system SysA. Is that a valid approach?

I then found that I still need to define the Sys(i) systems with the for loop in my main code, otherwise I get an error for undefined variables. Then, when I invoke my function like so:

Code: Select all

esfit('myfun',chiSI,{SysA,Sys(1),Sys(2),Sys(3),...},VaryA,Vary(1),Vary(2),Vary(3),...},Exp,[],FitOpt);
When the fitting window comes up and I hit "Start", I get the error:

Code: Select all

Error using myfun
Too many output arguments.
What am I missing?

Re: Generate multiple systems with a for loop

Posted: Fri Mar 11, 2016 11:29 am
by joscha_nehrkorn
I doubt that there is any physical sense in what you want to try.

Anyhow, reread the manual to writing your own fit function and start with a way simpler example which you might be able to make it work. For example take the following: as you want to use curry, write a fit function which return chi *T in cgs units. After this you can go to more advanced things.
A few hints:
-when you define a fit function you should be able to call it without esfit and it should return reasonable results. Think about a case where you believe to know what the output should be
- think about where variables should be defined and how should they look like
- debug your code and watch values of variables

Re: Generate multiple systems with a for loop

Posted: Fri Jan 06, 2017 6:05 am
by thanasis
I am resurrecting this thread to post an update of this work. The system we needed to treat (and the model we used) is described in http://pubs.acs.org/doi/abs/10.1021/acs ... em.6b01912. I particularly want to thank Stefan and Joscha for their helpful comments.

I had to make some custom fitting code to work around the fact that curry doesn't accept multiple systems. If this could be built into its functionality at some later stage, that would be really great!

Re: Generate multiple systems with a for loop

Posted: Mon Jan 09, 2017 12:56 pm
by Stefan Stoll
I see. We will add multi-system support for curry to our feature request list.

Re: Generate multiple systems with a for loop

Posted: Thu Jan 12, 2017 10:15 am
by Stefan Stoll
The new version 5.1.9 has this implemented.Check it out.