00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <stdlib.h>
00013 #include <stdio.h>
00014 #include <float.h>
00015 #include <math.h>
00016 #include <time.h>
00017 #include "gridlabd.h"
00018
00019 #include "solvers.h"
00020
00021 #ifndef WIN32
00022 #define _finite isfinite
00023 #endif
00024 static unsigned long _nan[2] = {0xffffffff,0x7fffffff};
00025 static double NaN = *(double*)&_nan;
00026 #define EVAL(t,a,n,b,m,c) (a*exp(n*t) + b*exp(m*t) + c)
00027
00030 double e2solve( double a,
00031 double n,
00032 double b,
00033 double m,
00034 double c,
00035 double p,
00036 double *e)
00037 {
00038 double t=0;
00039 double f = EVAL(t,a,n,b,m,c);
00040
00041
00042 if (a*b<0)
00043 {
00044
00045 double an_bm = -a*n/(b*m);
00046 double tm = log(an_bm)/(m-n);
00047 double fm = EVAL(tm,a,n,b,m,c);
00048 double ti = log(an_bm*n/m)/(m-n);
00049 double fi = EVAL(ti,a,n,b,m,c);
00050 if (tm>0)
00051 {
00052 if (f*fm<0)
00053 t = 0;
00054 else if (c*fm<0)
00055 t = ti;
00056 else
00057 return NaN;
00058 }
00059 else if (tm<0 && ti>0)
00060 {
00061 if (fm*c<0)
00062 t = ti;
00063 else
00064 return NaN;
00065 }
00066 else if (ti<0)
00067 {
00068 if (fi*c<0)
00069 t = ti;
00070 else
00071 return NaN;
00072 }
00073 else
00074 return NaN;
00075 }
00076
00077
00078 int iter = 100;
00079 if (t!=0)
00080 double f = EVAL(t,a,n,b,m,c);
00081 double dfdt = EVAL(t,a*n,n,b*m,m,0);
00082 while ( fabs(f)>p && isfinite(t) && iter-->0 )
00083 {
00084 t -= f/dfdt;
00085 f = EVAL(t,a,n,b,m,c);
00086 dfdt = EVAL(t,a*n,n,b*m,m,0);
00087 }
00088 if (iter==0)
00089 {
00090 gl_warning("etp::solve(a=%.4f,n=%.4f,b=%.4f,m=%.4f,c=%.4f,prec=%.g) failed to converge",a,n,b,m,c,p);
00091 return NaN;
00092 }
00093 if (e!=NULL)
00094 *e = p/dfdt;
00095 return t>0?t:NaN;
00096 }
00097
00098 #ifdef OLD_SOLVER
00099 #define SGNP(X,P) ((X)<-(P)?-1:((X)>(P)?+1:0))
00100
00101 int dual_decay_solve(double *ans, double prec, double start, double end, int f, double a, double n, double b, double m, double c)
00102 {
00103 #define EVAL(f,t,a,n,b,m,c) (a*pow(n,f)*exp(n*t) + b*pow(m,f)*exp(m*t) + c)
00104
00105
00106 double df_start = EVAL(f+1,start,a,n,b,m,c);
00107 double df_end = EVAL(f+1,end,a,n,b,m,c);
00108
00109 if(!_finite(df_start) || !_finite(df_end))
00110 return -1;
00111
00112 int sa = SGNP(df_start,prec);
00113 int sb = SGNP(df_end,prec);
00114
00115
00116 if (sa*sb==-1)
00117 {
00118
00119 double t;
00120 if (!dual_decay_solve(&t, prec, start, end, a*pow(n,f+1),n,b*pow(m,f+1),m,0))
00121
00122
00123 return -1;
00124
00125
00126 int n_right = dual_decay_solve(ans, prec, t, end, f, a,n,b,m,c);
00127 if (n_right<0)
00128 return -1;
00129
00130 int n_left = dual_decay_solve(ans, prec, start, t, f, a,n,b,m,c);
00131 if (n_left<0)
00132 return -1;
00133
00134 return n_left+n_right;
00135 }
00136 return dual_decay_solve(ans, prec, start, end, a,n,b,m,c);
00137 #undef EVAL
00138 }
00139
00140 int dual_decay_solve(double *ans, double prec, double start, double end, double a, double n, double b, double m, double c)
00141 {
00142 #define EVAL(t,a,n,b,m,c) (a*exp(n*t) + b*exp(m*t) + c)
00143
00144 double f_start = EVAL(start,a,n,b,m,c);
00145 double f_end = EVAL(end,a,n,b,m,c);
00146
00147 if (!_finite(f_start) ||!_finite(f_end))
00148 return -1;
00149
00150 int sa = SGNP(f_start,prec);
00151 int sb = SGNP(f_end,prec);
00152
00153
00154 if (sa*sb==1)
00155
00156
00157 return 0;
00158
00159
00160 else if (sa==0)
00161 *ans = start;
00162 else if (sb==0)
00163 *ans = end;
00164 else
00165 {
00166
00167 double t=(start+end)/2;
00168 int result = dual_decay_solve(ans,prec,start,t,a,n,b,m,c);
00169 if (result==0)
00170 result = dual_decay_solve(ans,prec,t,end,a,n,b,m,c);
00171 return result;
00172 }
00173
00174 return 1;
00175 }
00176 #endif
00177
00178 #undef SGNP