00001
00004 #include <stdlib.h>
00005 #include <stdio.h>
00006 #include <float.h>
00007 #include <math.h>
00008 #include <time.h>
00009
00010 #include "gridlabd.h"
00011 #include "solvers.h"
00012
00013 static unsigned long _nan[2] = {0xffffffff,0x7fffffff};
00014 static double NaN = *(double*)&_nan;
00015 #define EVAL(t,a,n,b,m,c) (a*exp(n*t) + b*exp(m*t) + c)
00016
00019 double e2solve(double a,
00020 double n,
00021 double b,
00022 double m,
00023 double c,
00024 double p,
00025 double *e)
00026 {
00027 double t=0;
00028 double f = EVAL(t,a,n,b,m,c);
00029
00030
00031
00032
00033 if (fabs(a/b)<p)
00034 return c*b<0 && fabs(c)<fabs(b) ? log(-c/b)/m : NaN;
00035 else if (fabs(b/a)<p)
00036 return c*a<0 && fabs(c)<fabs(a) ? log(-c/a)/n : NaN;
00037
00038
00039 if (a*b<0)
00040 {
00041
00042 double an_bm = -a*n/(b*m);
00043 double tm = log(an_bm)/(m-n);
00044 double fm = EVAL(tm,a,n,b,m,c);
00045 double ti = log(an_bm*n/m)/(m-n);
00046 double fi = EVAL(ti,a,n,b,m,c);
00047 if (tm>0)
00048 {
00049 if (f*fm<0)
00050 t = 0;
00051 else if (c*fm<0)
00052 t = ti;
00053 else
00054 return NaN;
00055 }
00056 else if (tm<0 && ti>0)
00057 {
00058 if (fm*c<0)
00059 t = ti;
00060 else
00061 return NaN;
00062 }
00063 else if (ti<0)
00064 {
00065 if (fi*c<0)
00066 t = ti;
00067 else
00068 return NaN;
00069 }
00070 else
00071 return NaN;
00072 }
00073 else if (f*c>0)
00074 {
00075 return NaN;
00076 }
00077
00078
00079 int iter = default_etp_iterations;
00080 if (t!=0)
00081 double f = EVAL(t,a,n,b,m,c);
00082 double dfdt = EVAL(t,a*n,n,b*m,m,0);
00083 while ( fabs(f)>p && isfinite(t) && iter-->0)
00084 {
00085 t -= f/dfdt;
00086 f = EVAL(t,a,n,b,m,c);
00087 dfdt = EVAL(t,a*n,n,b*m,m,0);
00088 }
00089 if (iter==0)
00090 {
00091 gl_error("etp::solve(a=%.4f,n=%.4f,b=%.4f,m=%.4f,c=%.4f,prec=%.g) failed to converge",a,n,b,m,c,p);
00092 return NaN;
00093 }
00094 if (e!=NULL)
00095 *e = p/dfdt;
00096 return t>0?t:NaN;
00097 }
00098