-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathdemo4.m
More file actions
182 lines (159 loc) · 5.09 KB
/
demo4.m
File metadata and controls
182 lines (159 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
function demo4
% Function that demonstrates use of getFitme
% EXAMPLE 1 Hydrogen
f1 = getFitme(1,1,1,1,'h2',2:7);
[lowLimits,highLimits] = getLimits(f1);
start = f1.getPars;
options = optimset('DiffMinChange',1.0e-5,'TolFun',1.0e-3,'TolX',3.0e-3);
[pt,resnorm,residual,exitflag,output,lambda,jacobian] = ...
lsqnonlin(@f1.err, start,lowLimits,highLimits,options);
display('Hydrogen results');
display(['pt = ',num2str(pt)]);
display(['resnorm = ',num2str(resnorm)]);
%pt = 0.62343 1.9482 0.67907 1.2712 0.48982 1.4852
%resnorm = 0.076006 (7.706 kcal/mol)
%
% EXAMPLE 2 methane fit: KE only for 7 geometries (geoms can go up to 1:17)
f1 = getFitme(1,0,0,1,'ch4',1:7);
[lowLimits,highLimits] = getLimits(f1);
start = f1.getPars;
options = optimset('DiffMinChange',1.0e-5,'TolFun',1.0e-3,'TolX',3.0e-3);
[pt,resnorm,residual,exitflag,output,lambda,jacobian] = ...
lsqnonlin(@f1.err, start,lowLimits,highLimits,options);
display('Methane results');
display(['pt = ',num2str(pt)]);
display(['resnorm = ',num2str(resnorm)]);
%Methane results
%pt = 1.0211 0.85864 1.3767
%resnorm = 0.2444 (25.5857 kcal/mol)
% EXAMPLE 3: methane fit: all energies, for 7 geometries (geoms can go up to 1:17)
f1 = getFitme(1,1,1,1,'ch4',1:7);
[lowLimits,highLimits] = getLimits(f1);
start = f1.getPars;
options = optimset('DiffMinChange',1.0e-5,'TolFun',1.0e-3,'TolX',3.0e-3);
[pt,resnorm,residual,exitflag,output,lambda,jacobian] = ...
lsqnonlin(@f1.err, start,lowLimits,highLimits,options);
display('Methane results');
display(['pt = ',num2str(pt)]);
display(['resnorm = ',num2str(resnorm)]);
%Methane results
%pt = 1.1305 0.77577 1.9704 0.79484 0.92042 1.1347 0.20348 0.95222 0.95053 0.93869
%resnorm = 0.32642 (11.1763 kcal/mol)
end
function f1 = getFitme(KE,EN,E2,scale,varargin)
% input
% KE,EN,E2: int that specifies how to handle these energy terms
% 0 = ignore 1 = regular 2 = hybrid
% E2 does not yet support hybrid
% scale : bool using scaling (with constant) if true
% varargin : other argument to pass to makeFitme, especially
% for h2 use 'h2',2:7 for methane: 'ch4',1:17
args = varargin;
if (scale)
ftype = 2;
else
ftype = 4;
end
if (KE==0)
args = {args{:},'kemods',0};
elseif (KE==1)
ke = createStruct('ke',ftype,0);
args = {args{:},'kestruct',ke};
elseif (KE==2)
ke = createStruct('ke',ftype,1);
args = {args{:},'kestructh',ke};
end
if (EN==0)
args = {args{:},'enmods',0};
elseif (EN==1)
en = createStruct('en',ftype,0);
args = {args{:},'enstruct',en};
elseif (EN==2)
en = createStruct('en',ftype,1);
args = {args{:},'enstructh',en};
end
if (E2 == 1)
if (scale == 1)
iP = 1;
else
iP = 0;
end
e2.H = Mixer(iP,1,'e2.H',ftype);
e2.C = Mixer(iP,1,'e2.C',ftype);
e2.HH = Mixer(iP,1,'e2.HH',ftype);
e2.CC = Mixer(iP,1,'e2.CC',ftype);
e2.CH = Mixer(iP,1,'e2.CH',ftype);
args = {args{:},'e2struct',e2};
elseif (E2 == 2)
error('getFitme: E2 == 2, but hybrid not supported for E2');
end
f1 = makeFitme(args{:});
end
function res = createStruct(label,ftype,hybrid)
% creates a structure with all relevant mixers for makeFitme
% Input:
% label: string, desc field of Mixer will start with this label
% ftype: ftype for Mixer (see Mixer.m)
% hybrid: bool, creates Mixers for hybrid orbitals
% Output:
% res: structure with fields shown below, each of which holds a handle to
% a Mixer. fields in parens have handles to same Mixer, e.g.
% (Cs Cp) means res.Cs and res.Cp point to same Mixer
% hybrid = 0 : H (Cs Cp) HH (CsH CpH) (CsCs CsCp CpCp)
% hybrid = 1 : H (Cs Cp) HH CH CCs CCp
% use 1 for initial parameter if ftype is scaling, 0 for interpolation
if ((ftype == 2) || (ftype == 3))
iP = 1;
else
iP = 0;
end
if (~hybrid)
res.H = Mixer(iP,1,[label,'.H'],ftype);
res.Cs = Mixer(iP,1,[label,'.C'],ftype);
res.Cp = res.Cs;
res.HH = Mixer(iP,1,[label,'.HH'],ftype);
res.CsH = Mixer(iP,1,[label,'.CH'],ftype);
res.CpH = res.CsH;
res.CsCs = Mixer(iP,1,[label,'.CC'],ftype);
res.CsCp = res.CsCs;
res.CpCp = res.CsCs;
else
res.H = Mixer(iP,1,[label,'.H'],ftype);
res.Cs = Mixer(iP,1,[label,'.C'],ftype);
res.Cp = res.Cs;
res.HH = Mixer(iP,1,[label,'.HH'],ftype);
res.CH = Mixer(iP,1,[label,'.CH'],ftype);
res.CH.hybrid = 1;
res.CCs = Mixer(iP,1,[label,'.CCs'],ftype);
res.CC.hybrid = 1;
res.CCp = Mixer(iP,1,[label,'.CCp'],ftype);
res.CCp.hybrid = 2;
end
end
function [lowLimits, highLimits] = getLimits(f1)
% For scale parameters, sets limits from 0 to 5
% all other parameters have limits -infinity to infinity
maxScale = 5;
lowLimits = zeros(f1.npar,1);
highLimits = lowLimits;
i1 = 1;
for imix = 1:length(f1.mixers)
mix = f1.mixers{imix};
if ((mix.funcType == 2)||(mix.funcType == 3))
lowLimits(i1) = 0.0;
highLimits(i1) = maxScale;
i1 = i1+1;
for i2 = 2:mix.npar
lowLimits(i1) = -inf;
highLimits(i1) = inf;
i1 = i1+1;
end
else
for i2 = 1:mix.npar
lowLimits(i1) = -inf;
highLimits(i1) = inf;
i1 = i1+1;
end
end
end
end