18 #define TOL_CONV 1.0E-5
21 static void print_funcEval(FILE* fp,
double xval,
double fval,
int its)
24 fprintf(fp,
"...............................................................\n");
25 fprintf(fp,
".................. vcs_root1d Function Evaluation .............\n");
26 fprintf(fp,
".................. iteration = %5d ........................\n", its);
27 fprintf(fp,
".................. value = %12.5g ......................\n", xval);
28 fprintf(fp,
".................. funct = %12.5g ......................\n", fval);
29 fprintf(fp,
"...............................................................\n");
36 double FuncTargVal,
int varID,
37 double* xbest,
int printLvl)
39 static int callNum = 0;
40 const char* stre =
"vcs_root1d ERROR: ";
41 const char* strw =
"vcs_root1d WARNING: ";
42 bool converged =
false;
48 double x1, x2, xnew, f1, f2, fnew, slope;
52 bool foundPosF =
false;
53 bool foundNegF =
false;
54 bool foundStraddle =
false;
59 double c[9], f[3], xn1, xn2, x0 = 0.0, f0 = 0.0, root, theta, xquad;
64 sprintf(fileName,
"rootfd_%d.log", callNum);
65 fp = fopen(fileName,
"w");
66 fprintf(fp,
" Iter TP_its xval Func_val | Reasoning\n");
67 fprintf(fp,
"-----------------------------------------------------"
68 "-------------------------------\n");
72 plogf(
"WARNING: vcsUtil_root1d: printlvl >= 3, but debug mode not turned on\n");
76 plogf(
"%sxmin and xmax are bad: %g %g\n", stre, xmin, xmax);
80 if (x1 < xmin || x1 > xmax) {
81 x1 = (xmin + xmax) / 2.0;
83 f1 = func(x1, FuncTargVal, varID, fptrPassthrough, &err);
86 print_funcEval(fp, x1, f1, its);
87 fprintf(fp,
"%-5d %-5d %-15.5E %-15.5E\n", -2, 0, x1, f1);
93 }
else if (f1 > 0.0) {
102 x2 = x1 - (xmax - xmin) / 100.;
104 f2 = func(x2, FuncTargVal, varID, fptrPassthrough, &err);
107 print_funcEval(fp, x2, f2, its);
108 fprintf(fp,
"%-5d %-5d %-15.5E %-15.5E", -1, 0, x2, f2);
112 if (FuncTargVal != 0.0) {
113 fnorm = fabs(FuncTargVal) + 1.0E-13;
115 fnorm = 0.5*(fabs(f1) + fabs(f2)) + fabs(FuncTargVal);
120 }
else if (f2 > 0.0) {
131 foundStraddle = foundPosF && foundNegF;
145 slope = (f2 - f1) / (x2 - x1);
147 plogf(
"%s functions evals produced the same result, %g, at %g and %g\n",
149 xnew = 2*x2 - x1 + 1.0E-3;
151 xnew = x2 - f2 / slope;
155 fprintf(fp,
" | xlin = %-9.4g", xnew);
181 root = f[1]* f[1] - 4.0 * f[0] * f[2];
183 xn1 = (- f[1] + sqrt(root)) / (2.0 * f[2]);
184 xn2 = (- f[1] - sqrt(root)) / (2.0 * f[2]);
185 if (fabs(xn2 - x2) < fabs(xn1 - x2) && xn2 > 0.0) {
190 theta = fabs(xquad - xnew) / fabs(xnew - x2);
191 theta = std::min(1.0, theta);
192 xnew = theta * xnew + (1.0 - theta) * xquad;
196 fprintf(fp,
" | xquad = %-9.4g", xnew);
205 if ((DSIGN(xnew - x2) == DSIGN(x2 - x1)) &&
206 (DSIGN(x2 - x1) == DSIGN(x1 - x0))) {
210 fprintf(fp,
" | xquada = %-9.4g", xnew);
224 if ((xnew > x1 && xnew < x2) || (xnew < x1 && xnew > x2)) {
231 slope = fabs(x2 - x1) / 10.;
232 if (fabs(xnew - x1) < slope) {
233 xnew = x1 + DSIGN(xnew-x1) * slope;
236 fprintf(fp,
" | x10%% = %-9.4g", xnew);
240 if (fabs(xnew - x2) < slope) {
241 xnew = x2 + DSIGN(xnew-x2) * slope;
244 fprintf(fp,
" | x10%% = %-9.4g", xnew);
253 slope = 2.0 * fabs(x2 - x1);
254 if (fabs(slope) < fabs(xnew - x2)) {
255 xnew = x2 + DSIGN(xnew-x2) * slope;
258 fprintf(fp,
" | xlimitsize = %-9.4g", xnew);
266 xnew = x2 + (xmax - x2) / 2.0;
269 fprintf(fp,
" | xlimitmax = %-9.4g", xnew);
274 xnew = x2 + (x2 - xmin) / 2.0;
277 fprintf(fp,
" | xlimitmin = %-9.4g", xnew);
288 xnew = (xNegF + x2)/2;
291 xnew = (xNegF + x2)/2;
295 xnew = (xPosF + x2)/2;
298 xnew = (xPosF + x2)/2;
304 xnew = (xNegF + x2)/2;
307 xnew = (xNegF + x2)/2;
311 xnew = (xPosF + x2)/2;
314 xnew = (xPosF + x2)/2;
321 fprintf(fp,
" | xstraddle = %-9.4g", xnew);
327 fnew = func(xnew, FuncTargVal, varID, fptrPassthrough, &err);
331 print_funcEval(fp, xnew, fnew, its);
332 fprintf(fp,
"%-5d %-5d %-15.5E %-15.5E", its, 0, xnew, fnew);
360 if (! foundStraddle) {
365 foundStraddle =
true;
366 posStraddle = (xPosF > xNegF);
372 foundStraddle =
true;
373 posStraddle = (xPosF > xNegF);
384 if (fabs(fnew / fnorm) < 1.0E-5) {
388 }
while (! converged && its < itmax);
391 plogf(
"vcs_root1d success: convergence achieved\n");
395 fprintf(fp,
" | vcs_root1d success in %d its, fnorm = %g\n", its, fnorm);
399 retn = VCS_FAILED_CONVERGENCE;
401 plogf(
"vcs_root1d ERROR: maximum iterations exceeded without convergence\n");
405 fprintf(fp,
"\nvcs_root1d failure in %lu its\n", its);
double(* VCS_FUNC_PTR)(double xval, double Vtarget, int varID, void *fptrPassthrough, int *err)
Definition of the function pointer for the root finder.
int vcsUtil_root1d(double xmin, double xmax, size_t itmax, VCS_FUNC_PTR func, void *fptrPassthrough, double FuncTargVal, int varID, double *xbest, int printLvl)
One dimensional root finder.
Internal declarations for the VCSnonideal package.
int vcsUtil_mlequ(double *c, size_t idem, size_t n, double *b, size_t m)
Invert an n x n matrix and solve m rhs's.
#define plogf
define this Cantera function to replace printf