/** In the newton function, a 1-D Newton-Raphson solver is implemented using exact solutions. An initial guess for the solution is provided. @param f A pointer to an instance of the FuncWrapper1D class that implements the call() function @param x0 The inital guess for the solution @param ftol The absolute value of the tolerance accepted for the objective function @param maxiter Maximum number of iterations @returns If no errors are found, the solution, otherwise the value _HUGE, the value for infinity */ double Newton(FuncWrapper1DWithDeriv* f, double x0, double ftol, int maxiter) { double x, dx, fval=999; int iter=1; f->errstring.clear(); x = x0; while (iter < 2 || std::abs(fval) > ftol) { fval = f->call(x); dx = -fval/f->deriv(x); if (!ValidNumber(fval)){ throw ValueError("Residual function in newton returned invalid number"); }; x += dx; if (std::abs(dx/x) < 1e-11){ return x; } if (iter>maxiter) { f->errstring= "reached maximum number of iterations"; throw SolutionError(format("Newton reached maximum number of iterations")); } iter=iter+1; } return x; }
double _T_hp_secant(std::string Ref, double h, double p, double T_guess) { double x1=0,x2=0,x3=0,y1=0,y2=0,eps=1e-8,change=999,f=999,T=300; int iter=1; while ((iter<=3 || fabs(f)>eps) && iter<100) { if (iter==1){x1=T_guess; T=x1;} if (iter==2){x2=T_guess+0.1; T=x2;} if (iter>2) {T=x2;} f=Props("H",'T',T,'P',p,Ref)-h; if (iter==1){y1=f;} if (iter>1) { y2=f; x3=x2-y2/(y2-y1)*(x2-x1); change=fabs(y2/(y2-y1)*(x2-x1)); y1=y2; x1=x2; x2=x3; } iter=iter+1; if (iter>100) { throw SolutionError(format("iter %d: T_hp not converging with inputs(%s,%g,%g,%g) value: %0.12g\n",iter,(char*)Ref.c_str(),h,p,T_guess,f)); } } return T; }
/** In the secant function, a 1-D Newton-Raphson solver is implemented. An initial guess for the solution is provided. @param f A pointer to an instance of the FuncWrapper1D class that implements the call() function @param x0 The inital guess for the solutionh @param dx The initial amount that is added to x in order to build the numerical derivative @param tol The absolute value of the tolerance accepted for the objective function @param maxiter Maximum number of iterations @returns If no errors are found, the solution, otherwise the value _HUGE, the value for infinity */ double Secant(FuncWrapper1D* f, double x0, double dx, double tol, int maxiter) { #if defined(COOLPROP_DEEP_DEBUG) static std::vector<double> xlog, flog; xlog.clear(); flog.clear(); #endif double x1=0,x2=0,x3=0,y1=0,y2=0,x,fval=999; int iter=1; f->errstring.clear(); if (std::abs(dx)==0){ f->errstring="dx cannot be zero"; return _HUGE;} while (iter<=2 || std::abs(fval)>tol) { if (iter==1){x1=x0; x=x1;} if (iter==2){x2=x0+dx; x=x2;} if (iter>2) {x=x2;} if (f->input_not_in_range(x)){ throw ValueError(format("Input [%g] is out of range",x)); } fval = f->call(x); #if defined(COOLPROP_DEEP_DEBUG) xlog.push_back(x); flog.push_back(fval); #endif if (!ValidNumber(fval)){ throw ValueError("Residual function in secant returned invalid number"); }; if (iter==1){y1=fval;} if (iter>1) { double deltax = x2-x1; if (std::abs(deltax)<1e-14){ return x; } y2=fval; double deltay = y2-y1; if (iter > 2 && std::abs(deltay)<1e-14){ return x; } x3=x2-y2/(y2-y1)*(x2-x1); y1=y2; x1=x2; x2=x3; } if (iter>maxiter) { f->errstring=std::string("reached maximum number of iterations"); throw SolutionError(format("Secant reached maximum number of iterations")); } iter=iter+1; } return x3; }
/** In the Halley's method solver, two derivatives of the input variable are needed, it yields the following method: \f[ x_{n+1} = x_n - \frac {2 f(x_n) f'(x_n)} {2 {[f'(x_n)]}^2 - f(x_n) f''(x_n)} \f] http://en.wikipedia.org/wiki/Halley%27s_method @param f A pointer to an instance of the FuncWrapper1DWithTwoDerivs class that implements the call() and two derivatives @param x0 The inital guess for the solution @param ftol The absolute value of the tolerance accepted for the objective function @param maxiter Maximum number of iterations @returns If no errors are found, the solution, otherwise the value _HUGE, the value for infinity */ double Halley(FuncWrapper1DWithTwoDerivs* f, double x0, double ftol, int maxiter) { double x, dx, fval=999, dfdx, d2fdx2; int iter=1; f->errstring.clear(); x = x0; while (iter < 2 || std::abs(fval) > ftol) { fval = f->call(x); dfdx = f->deriv(x); d2fdx2 = f->second_deriv(x); if (f->input_not_in_range(x)){ throw ValueError(format("Input [%g] is out of range",x)); } if (!ValidNumber(fval)){ throw ValueError("Residual function in Halley returned invalid number"); }; if (!ValidNumber(dfdx)){ throw ValueError("Derivative function in Halley returned invalid number"); }; dx = -(2*fval*dfdx)/(2*POW2(dfdx)-fval*d2fdx2); x += dx; if (std::abs(dx/x) < 10*DBL_EPSILON){ return x; } if (iter>maxiter){ f->errstring= "reached maximum number of iterations"; throw SolutionError(format("Halley reached maximum number of iterations")); } iter=iter+1; } return x; }
/** In the secant function, a 1-D Newton-Raphson solver is implemented. An initial guess for the solution is provided. @param f A pointer to an instance of the FuncWrapper1D class that implements the call() function @param x0 The inital guess for the solution @param xmax The upper bound for the solution @param xmin The lower bound for the solution @param dx The initial amount that is added to x in order to build the numerical derivative @param tol The absolute value of the tolerance accepted for the objective function @param maxiter Maximum number of iterations @returns If no errors are found, the solution, otherwise the value _HUGE, the value for infinity */ double BoundedSecant(FuncWrapper1D* f, double x0, double xmin, double xmax, double dx, double tol, int maxiter) { double x1=0,x2=0,x3=0,y1=0,y2=0,x,fval=999; int iter=1; f->errstring.clear(); if (std::abs(dx)==0){ f->errstring = "dx cannot be zero"; return _HUGE;} while (iter<=3 || std::abs(fval)>tol) { if (iter==1){x1=x0; x=x1;} else if (iter==2){x2=x0+dx; x=x2;} else {x=x2;} fval=f->call(x); if (iter==1){y1=fval;} else { y2=fval; x3=x2-y2/(y2-y1)*(x2-x1); // Check bounds, go half the way to the limit if limit is exceeded if (x3 < xmin) { x3 = (xmin + x2)/2; } if (x3 > xmax) { x3 = (xmax + x2)/2; } y1=y2; x1=x2; x2=x3; } if (iter>maxiter){ f->errstring = "reached maximum number of iterations"; throw SolutionError(format("BoundedSecant reached maximum number of iterations")); } iter=iter+1; } f->errcode = 0; return x3; }
/** This function implements a 1-D bounded solver using the algorithm from Brent, R. P., Algorithms for Minimization Without Derivatives. Englewood Cliffs, NJ: Prentice-Hall, 1973. Ch. 3-4. a and b must bound the solution of interest and f(a) and f(b) must have opposite signs. If the function is continuous, there must be at least one solution in the interval [a,b]. @param f A pointer to an instance of the FuncWrapper1D class that must implement the class() function @param a The minimum bound for the solution of f=0 @param b The maximum bound for the solution of f=0 @param macheps The machine precision @param t Tolerance (absolute) @param maxiter Maximum numer of steps allowed. Will throw a SolutionError if the solution cannot be found */ double Brent(FuncWrapper1D* f, double a, double b, double macheps, double t, int maxiter) { int iter; f->errstring.clear(); double fa,fb,c,fc,m,tol,d,e,p,q,s,r; fa = f->call(a); fb = f->call(b); // If one of the boundaries is to within tolerance, just stop if (std::abs(fb) < t) { return b;} if (!ValidNumber(fb)){ throw ValueError(format("Brent's method f(b) is NAN for b = %g, other input was a = %g",b,a).c_str()); } if (std::abs(fa) < t) { return a;} if (!ValidNumber(fa)){ throw ValueError(format("Brent's method f(a) is NAN for a = %g, other input was b = %g",a,b).c_str()); } if (fa*fb>0){ throw ValueError(format("Inputs in Brent [%f,%f] do not bracket the root. Function values are [%f,%f]",a,b,fa,fb)); } c=a; fc=fa; iter=1; if (std::abs(fc)<std::abs(fb)){ // Goto ext: from Brent ALGOL code a=b; b=c; c=a; fa=fb; fb=fc; fc=fa; } d=b-a; e=b-a; m=0.5*(c-b); tol=2*macheps*std::abs(b)+t; while (std::abs(m)>tol && fb!=0){ // See if a bisection is forced if (std::abs(e)<tol || std::abs(fa) <= std::abs(fb)){ m=0.5*(c-b); d=e=m; } else{ s=fb/fa; if (a==c){ //Linear interpolation p=2*m*s; q=1-s; } else{ //Inverse quadratic interpolation q=fa/fc; r=fb/fc; m=0.5*(c-b); p=s*(2*m*q*(q-r)-(b-a)*(r-1)); q=(q-1)*(r-1)*(s-1); } if (p>0){ q=-q; } else{ p=-p; } s=e; e=d; m=0.5*(c-b); if (2*p<3*m*q-std::abs(tol*q) || p<std::abs(0.5*s*q)){ d=p/q; } else{ m=0.5*(c-b); d=e=m; } } a=b; fa=fb; if (std::abs(d)>tol){ b+=d; } else if (m>0){ b+=tol; } else{ b+=-tol; } fb=f->call(b); if (!ValidNumber(fb)){ throw ValueError(format("Brent's method f(t) is NAN for t = %g",b).c_str()); } if (std::abs(fb) < macheps){ return b; } if (fb*fc>0){ // Goto int: from Brent ALGOL code c=a; fc=fa; d=e=b-a; } if (std::abs(fc)<std::abs(fb)){ // Goto ext: from Brent ALGOL code a=b; b=c; c=a; fa=fb; fb=fc; fc=fa; } m=0.5*(c-b); tol=2*macheps*std::abs(b)+t; iter+=1; if (!ValidNumber(a)){ throw ValueError(format("Brent's method a is NAN").c_str());} if (!ValidNumber(b)){ throw ValueError(format("Brent's method b is NAN").c_str());} if (!ValidNumber(c)){ throw ValueError(format("Brent's method c is NAN").c_str());} if (iter>maxiter){ throw SolutionError(format("Brent's method reached maximum number of steps of %d ", maxiter));} if (std::abs(fb)< 2*macheps*std::abs(b)){ return b; } } return b; }
int main(int argc, char * argv[]) { pthread_t *tid;//number of thread args *arg; int total_processes; double *a, *b, *x; int res1, res2; long int t; int n; int N; int i; char * filename = 0; const char * name = "c.txt"; if( argc != 3 && argc != 4 ) { printf("Usage : %s <n> <total_processes> <filename>\n", argv[0]); return 0; } n = atoi(argv[1]);//from number to string total_processes = atoi (argv[2]); if(!n || !total_processes) { printf("Usage : %s <n> <total_processes> <filename>\n", argv[0]); return 0; } a = new double[n*n]; b = new double[n]; x = new double[n]; tid = new pthread_t[total_processes]; arg = new args[total_processes]; if(argc > 3) filename = argv[3]; if(filename) { res1 = read_matrix(a, n, "a.txt"); res2 = read_vector(b, n, "b.txt"); if(res1 || res2) { printf("cannot read from file\n"); delete [] tid; delete [] arg; delete [] a; delete [] b; delete [] x; return 1; } } else { init_matrix(a, n); init_vector(b, a, n); } printf("matrix A:\n"); print_matrix(a, n); printf("vector b:\n"); print_vector(b, n); for (i = 0; i < total_processes; i++) { arg[i].a = a; arg[i].b = b; arg[i].n = n; arg[i].total_processes = total_processes; arg[i].num_process = i; arg[i].error = 0; } t = get_full_time (); for (i = 0; i < total_processes; i++) { if (pthread_create (tid + i, 0, &thread_method_of_reflections, arg + i)) { printf ("Cannot create thread %d\n", i); return 2; } } for (i = 0; i < total_processes; i++) pthread_join (tid[i], 0); back_hod(a, b, x, n); t = get_full_time () - t; N = (n < MAX_N) ? n : MAX_N; printf("result : "); for(i = 0; i < N; i++) printf("%lg ", x[i]); printvectorfile(x,n,name); if(filename) { read_matrix(a, n, "a.txt"); read_vector(b, n, "b.txt"); printf("\nResidual = %le\nElapsed time = %Lg\n",SolutionError(n,a,b,x),(long double)t/(CLOCKS_PER_SEC)); } else { init_matrix(a, n); init_vector(b, a, n); printf("\nResidual = %le\nError = %le\nElapsed time = %Lg\n",SolutionError(n,a,b,x), SolutionAccuracy(n,x),(long double)t/(CLOCKS_PER_SEC)); } delete [] tid; delete [] arg; delete [] a; delete [] b; delete [] x; return 0; }