Hello,
I am having trouble with my code. I have sorption data and trying to fit it to Langmuir Isotherm. There are 5 concentrations (represented by conc in the code) and two plants (C and L). I have 3 blocks which represent the time at which I ran the sorption experiment. qt is the amount sorbed at equilibrium.
When I run the code, I keep getting the error " WARNING: Maximum number of iterations exceeded.
WARNING: PROC NLIN failed to converge.
NOTE: The above message was for the following BY group:
Plant=C block=3"
I tried changing the starting parameters and even the method but keep getting that error for that particular block. The data for that block seems fine and there appears to be no anomaly.
I will appreciate suggestions on how to fix this. Thanks.
Here is the code:
data Isotherm;
input Plant $ conc block ce qt;
Datalines;
C 5 1 0.0019435976 0.0556402439
C 10 1 0.003973607 0.1026392962
C 15 1 0.0078216918 0.2178308178
C 20 1 0.0116147443 0.338525573
C 25 1 0.0159964979 0.4003502126
C 5 2 0.0018444556 0.0655544441
C 10 2 0.0040143691 0.0985630894
C 15 2 0.0076276945 0.237230553
C 20 2 0.0115231028 0.3476897185
C 25 2 0.0158549932 0.414500684
C 5 3 0.0021044099 0.0395590143
C 10 3 0.0040763926 0.0923607392
C 15 3 0.0084038988 0.1596101231
C 20 3 0.0122161836 0.2783816425
C 25 3 0.016261635 0.3738365034
L 5 1 0.0008449972 0.1655002772
L 10 1 0.0017438207 0.3256179305
L 15 1 0.0036381186 0.6361881362
L 20 1 0.0054052714 0.9594728589
L 25 1 0.0076868098 1.2313190151
L 5 2 0.0008488139 0.1651186053
L 10 2 0.0018084868 0.3191513247
L 15 2 0.00368791 0.6312089972
L 20 2 0.0056812271 0.931877295
L 25 2 0.0080631555 1.1936844505
L 5 3 0.001515348 0.0984651967
L 10 3 0.0028983664 0.2101633637
L 15 3 0.0056429549 0.4357045144
L 20 3 0.0087318841 0.6268115942
L 25 3 0.0120204371 0.797956293
;
title 'Sorption Isotherm: Langmuir';
proc nlin data=Isotherm method=marquardt hougaard;by plant block;
parameters k=1 to 10 by 1 Smax=0.1 to 5 by 0.1;
model qt = ((K*Smax*Ce)/(1+K*Ce));
output out=mod1 predicted=pred l95m=l95mean u95m=u95mean
l95=l95ind u95=u95ind residual=res student=s sse=sse parms=k Smax
run;
Proc Sort Data=mod1;
by conc plant ;
run;
data mod1; set mod1;
proc print data=mod1;
run;
proc means noprint var std stderr uss css;
var qt pred res;
output out = mod2 n=numobs var=qt_v pred_v res_v
uss=qt_uss pred_uss res_uss css=css
pred_css res_css;
run;
data mod3; set mod1; set mod2;
rsq = 1 - sse/css; *i.e., pseudo rsq;
rmse=sqrt(res_v);
run;
proc print data=mod3;
var rsq rmse;
run;
Title 'Print of parameterestimates';
proc print data=mod1;
run;
It might be a good idea to reduce the number of estimated parameters. Looking at available estimated values, it looks like blocks for the same plant differ mostly by the K value. So it may make sense to estimate a singe Smax value per plant and a separate K value for each block. This is how you could do it:
proc nlin data=Isotherm method=marquardt hougaard noitprint best=5;
by plant;
parameters k1=1 to 10 by 1 k2=1 to 10 by 1 k3=1 to 10 by 1 Smax=0.1 to 5 by 0.1;
if block = 1 then K = k1;
else if block = 2 then K = k2;
else if block = 3 then K = k3;
model qt = ((K*Smax*Ce)/(1+K*Ce));
output out=isothermPred predicted=pred;
run;
proc sgpanel data=isothermPred;
panelby plant block / layout=lattice;
scatter y=qt x=ce;
series y=pred x=ce;
run;
------------------------------------- Plant=C -------------------------------------- The NLIN Procedure Approx Approximate 95% Parameter Estimate Std Error Confidence Limits Skewness k1 8.5985 6.8528 -6.4844 23.6815 0.3503 k2 9.0683 7.2581 -6.9067 25.0434 0.3693 k3 7.0638 5.5454 -5.1416 19.2691 0.2843 Smax 3.4478 2.4736 -1.9965 8.8921 4.4256 ------------------------------------- Plant=L -------------------------------------- The NLIN Procedure Approx Approximate 95% Parameter Estimate Std Error Confidence Limits Skewness k1 38.0343 5.9238 24.9960 51.0726 0.1305 k2 35.3447 5.4840 23.2744 47.4149 0.1273 k3 14.5648 2.1192 9.9004 19.2291 0.0782 Smax 5.4533 0.6910 3.9323 6.9742 0.7988
Note: The correlation among parameter estimates (not shown) is terrible. But the fit is quite reasonable.
The model you are fitting is essentially
y = Kx / (1+Kx)
which passes through the origin and is concave down (second derivative less than 0) for all values of x.
The model does not fit the data for that BY group very well. They look to be linear and not concave down. The optimization routine is trying to choose the parameters so that
y = S * Kx / (1+Kx)
the function is "as linear as possible," Two make the second derivative small, K -> 0. But to make the slope nonzero, S -> infinity. Thus no convergence.
The main problem is the third observation for that BY group:
C 15 3 0.0084038988 0.1596101231
If the qt value was larger, such as
C 15 3 0.0084038988 0.23
then the model would converge for that By group, too.
It might be a good idea to reduce the number of estimated parameters. Looking at available estimated values, it looks like blocks for the same plant differ mostly by the K value. So it may make sense to estimate a singe Smax value per plant and a separate K value for each block. This is how you could do it:
proc nlin data=Isotherm method=marquardt hougaard noitprint best=5;
by plant;
parameters k1=1 to 10 by 1 k2=1 to 10 by 1 k3=1 to 10 by 1 Smax=0.1 to 5 by 0.1;
if block = 1 then K = k1;
else if block = 2 then K = k2;
else if block = 3 then K = k3;
model qt = ((K*Smax*Ce)/(1+K*Ce));
output out=isothermPred predicted=pred;
run;
proc sgpanel data=isothermPred;
panelby plant block / layout=lattice;
scatter y=qt x=ce;
series y=pred x=ce;
run;
------------------------------------- Plant=C -------------------------------------- The NLIN Procedure Approx Approximate 95% Parameter Estimate Std Error Confidence Limits Skewness k1 8.5985 6.8528 -6.4844 23.6815 0.3503 k2 9.0683 7.2581 -6.9067 25.0434 0.3693 k3 7.0638 5.5454 -5.1416 19.2691 0.2843 Smax 3.4478 2.4736 -1.9965 8.8921 4.4256 ------------------------------------- Plant=L -------------------------------------- The NLIN Procedure Approx Approximate 95% Parameter Estimate Std Error Confidence Limits Skewness k1 38.0343 5.9238 24.9960 51.0726 0.1305 k2 35.3447 5.4840 23.2744 47.4149 0.1273 k3 14.5648 2.1192 9.9004 19.2291 0.0782 Smax 5.4533 0.6910 3.9323 6.9742 0.7988
Note: The correlation among parameter estimates (not shown) is terrible. But the fit is quite reasonable.
Thank you. I ran the code as suggested and found no convergence warning.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
ANOVA, or Analysis Of Variance, is used to compare the averages or means of two or more populations to better understand how they differ. Watch this tutorial for more.
Find more tutorials on the SAS Users YouTube channel.