<commit_before>#include <vector>
#include "Solvers.h"
#include "math.h"
#include "MatrixMath.h"
#include <iostream>
#include "CoolPropTools.h"

namespace CoolProp{

/** \brief Calculate the Jacobian using numerical differentiation by column
 */
std::vector<std::vector<double> > FuncWrapperND::Jacobian(std::vector<double> x)
{
    double epsilon;
    std::size_t N = x.size();
    std::vector<double> r, xp;
    std::vector<std::vector<double> > J(N, std::vector<double>(N, 0));
    std::vector<double> r0 = call(x);
    // Build the Jacobian by column
    for (std::size_t i = 0; i < N; ++i)
    {
        xp = x;
        epsilon = 0.001*x[i];
        xp[i] += epsilon;
        r = call(xp);

        for(std::size_t j = 0; j < N; ++j)
        {
            J[j][i] = (r[j]-r0[j])/epsilon;
        }
    }
    return J;
}

/**
In this formulation of the Multi-Dimensional Newton-Raphson solver the Jacobian matrix is known.
Therefore, the dx vector can be obtained from

J(x)dx=-f(x)

for a given value of x.  The pointer to the class FuncWrapperND that is passed in must implement the call() and Jacobian()
functions, each of which take the vector x. The data is managed using std::vector<double> vectors

@param f A pointer to an subclass of the FuncWrapperND class that implements the call() and Jacobian() functions
@param x0 The initial guess value for the solution
@param tol The root-sum-square of the errors from each of the components
@param maxiter The maximum number of iterations
@param errstring  A string with the returned error.  If the length of errstring is zero, no errors were found
@returns If no errors are found, the solution.  Otherwise, _HUGE, the value for infinity
*/
std::vector<double> NDNewtonRaphson_Jacobian(FuncWrapperND *f, std::vector<double> x0, double tol, int maxiter, std::string *errstring)
{
    int iter=0;
    *errstring=std::string("");
    std::vector<double> f0,v,negative_f0;
    std::vector<std::vector<double> > J;
    double error = 999;
    while (iter==0 || std::abs(error)>tol){
        f0 = f->call(x0);
        J = f->Jacobian(x0);

        // Negate f0
        negative_f0 = f0;
        for (std::size_t i = 0; i<f0.size(); i++){ negative_f0[i] *= -1;}
        // find v from J*v = -f
        v = linsolve(J, negative_f0);
        // Update the guess
        for (std::size_t i = 0; i<x0.size(); i++){ x0[i] *= v[i];}
        error = root_sum_square(f0);
        if (iter>maxiter){
            *errstring=std::string("reached maximum number of iterations");
            x0[0]=_HUGE;
        }
        iter++;
    }
    return x0;
}

/**
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
@param errstring A pointer to the std::string that returns the error from Secant.  Length is zero if no errors are found
@returns If no errors are found, the solution, otherwise the value _HUGE, the value for infinity
*/
double Newton(FuncWrapper1D* f, double x0, double ftol, int maxiter, std::string &errstring)
{
    double x, dx, fval=999;
    int iter=1;
    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) < 10*DBL_EPSILON)
        {
            return x;
        }

        if (iter>maxiter)
        {
            errstring= "reached maximum number of iterations";
            throw SolutionError(format("Newton 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 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
@param errstring A pointer to the std::string that returns the error from Secant.  Length is zero if no errors are found
@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, std::string &errstring)
{
    #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;
    errstring = "";

    if (std::abs(dx)==0){ 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;}

            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)
            {
                if (std::abs(fval) < tol*10)
                {
                    return x;
                }
                else
                {
                    throw ValueError("Step is small but not solved to tolerance");
                }
            }
            y2=fval;
            x3=x2-y2/(y2-y1)*(x2-x1);
            y1=y2; x1=x2; x2=x3;

        }
        if (iter>maxiter)
        {
            errstring=std::string("reached maximum number of iterations");
            throw SolutionError(format("Secant reached maximum number of iterations"));
        }
        iter=iter+1;
    }
    return x3;
}

/**
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
@param errstring A pointer to the std::string that returns the error from Secant.  Length is zero if no errors are found
@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, std::string &errstring)
{
    double x1=0,x2=0,x3=0,y1=0,y2=0,x,fval=999;
    int iter=1;
    errstring = "";

    if (std::abs(dx)==0){ 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)
        {
            errstring = "reached maximum number of iterations";
            throw SolutionError(format("BoundedSecant reached maximum number of iterations"));
        }
        iter=iter+1;
    }
    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
@param errstr A pointer to the error string returned.  If length is zero, no errors found.
*/
double Brent(FuncWrapper1D* f, double a, double b, double macheps, double t, int maxiter, std::string &errstr)
{
    int iter;
    errstr.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(std::string("Brent's method reached maximum number of steps of %d ", maxiter));}
        if (std::abs(fb)< 2*macheps*std::abs(b)){
            return b;
        }
    }
    return b;
}

// Single-Dimensional solvers
double Brent(FuncWrapper1D &f, double a, double b, double macheps, double t, int maxiter, std::string &errstr){
    return Brent(&f, a, b, macheps, t, maxiter, errstr);
}
double Secant(FuncWrapper1D &f, double x0, double dx, double ftol, int maxiter, std::string &errstring){
    return Secant(&f, x0, dx, ftol, maxiter, errstring);
}
double BoundedSecant(FuncWrapper1D &f, double x0, double xmin, double xmax, double dx, double ftol, int maxiter, std::string &errstring){
    return BoundedSecant(&f, x0, xmin, xmax, dx, ftol, maxiter, errstring);
}
double Newton(FuncWrapper1D &f, double x0, double ftol, int maxiter, std::string &errstring){
    return Newton(&f, x0, ftol, maxiter, errstring);
}

}; /* namespace CoolProp */
<commit_msg>Fix error message for Brent's method when it doesn't get a solution<commit_after>#include <vector>
#include "Solvers.h"
#include "math.h"
#include "MatrixMath.h"
#include <iostream>
#include "CoolPropTools.h"

namespace CoolProp{

/** \brief Calculate the Jacobian using numerical differentiation by column
 */
std::vector<std::vector<double> > FuncWrapperND::Jacobian(std::vector<double> x)
{
    double epsilon;
    std::size_t N = x.size();
    std::vector<double> r, xp;
    std::vector<std::vector<double> > J(N, std::vector<double>(N, 0));
    std::vector<double> r0 = call(x);
    // Build the Jacobian by column
    for (std::size_t i = 0; i < N; ++i)
    {
        xp = x;
        epsilon = 0.001*x[i];
        xp[i] += epsilon;
        r = call(xp);

        for(std::size_t j = 0; j < N; ++j)
        {
            J[j][i] = (r[j]-r0[j])/epsilon;
        }
    }
    return J;
}

/**
In this formulation of the Multi-Dimensional Newton-Raphson solver the Jacobian matrix is known.
Therefore, the dx vector can be obtained from

J(x)dx=-f(x)

for a given value of x.  The pointer to the class FuncWrapperND that is passed in must implement the call() and Jacobian()
functions, each of which take the vector x. The data is managed using std::vector<double> vectors

@param f A pointer to an subclass of the FuncWrapperND class that implements the call() and Jacobian() functions
@param x0 The initial guess value for the solution
@param tol The root-sum-square of the errors from each of the components
@param maxiter The maximum number of iterations
@param errstring  A string with the returned error.  If the length of errstring is zero, no errors were found
@returns If no errors are found, the solution.  Otherwise, _HUGE, the value for infinity
*/
std::vector<double> NDNewtonRaphson_Jacobian(FuncWrapperND *f, std::vector<double> x0, double tol, int maxiter, std::string *errstring)
{
    int iter=0;
    *errstring=std::string("");
    std::vector<double> f0,v,negative_f0;
    std::vector<std::vector<double> > J;
    double error = 999;
    while (iter==0 || std::abs(error)>tol){
        f0 = f->call(x0);
        J = f->Jacobian(x0);

        // Negate f0
        negative_f0 = f0;
        for (std::size_t i = 0; i<f0.size(); i++){ negative_f0[i] *= -1;}
        // find v from J*v = -f
        v = linsolve(J, negative_f0);
        // Update the guess
        for (std::size_t i = 0; i<x0.size(); i++){ x0[i] *= v[i];}
        error = root_sum_square(f0);
        if (iter>maxiter){
            *errstring=std::string("reached maximum number of iterations");
            x0[0]=_HUGE;
        }
        iter++;
    }
    return x0;
}

/**
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
@param errstring A pointer to the std::string that returns the error from Secant.  Length is zero if no errors are found
@returns If no errors are found, the solution, otherwise the value _HUGE, the value for infinity
*/
double Newton(FuncWrapper1D* f, double x0, double ftol, int maxiter, std::string &errstring)
{
    double x, dx, fval=999;
    int iter=1;
    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) < 10*DBL_EPSILON)
        {
            return x;
        }

        if (iter>maxiter)
        {
            errstring= "reached maximum number of iterations";
            throw SolutionError(format("Newton 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 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
@param errstring A pointer to the std::string that returns the error from Secant.  Length is zero if no errors are found
@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, std::string &errstring)
{
    #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;
    errstring = "";

    if (std::abs(dx)==0){ 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;}

            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)
            {
                if (std::abs(fval) < tol*10)
                {
                    return x;
                }
                else
                {
                    throw ValueError("Step is small but not solved to tolerance");
                }
            }
            y2=fval;
            x3=x2-y2/(y2-y1)*(x2-x1);
            y1=y2; x1=x2; x2=x3;

        }
        if (iter>maxiter)
        {
            errstring=std::string("reached maximum number of iterations");
            throw SolutionError(format("Secant reached maximum number of iterations"));
        }
        iter=iter+1;
    }
    return x3;
}

/**
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
@param errstring A pointer to the std::string that returns the error from Secant.  Length is zero if no errors are found
@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, std::string &errstring)
{
    double x1=0,x2=0,x3=0,y1=0,y2=0,x,fval=999;
    int iter=1;
    errstring = "";

    if (std::abs(dx)==0){ 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)
        {
            errstring = "reached maximum number of iterations";
            throw SolutionError(format("BoundedSecant reached maximum number of iterations"));
        }
        iter=iter+1;
    }
    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
@param errstr A pointer to the error string returned.  If length is zero, no errors found.
*/
double Brent(FuncWrapper1D* f, double a, double b, double macheps, double t, int maxiter, std::string &errstr)
{
    int iter;
    errstr.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;
}

// Single-Dimensional solvers
double Brent(FuncWrapper1D &f, double a, double b, double macheps, double t, int maxiter, std::string &errstr){
    return Brent(&f, a, b, macheps, t, maxiter, errstr);
}
double Secant(FuncWrapper1D &f, double x0, double dx, double ftol, int maxiter, std::string &errstring){
    return Secant(&f, x0, dx, ftol, maxiter, errstring);
}
double BoundedSecant(FuncWrapper1D &f, double x0, double xmin, double xmax, double dx, double ftol, int maxiter, std::string &errstring){
    return BoundedSecant(&f, x0, xmin, xmax, dx, ftol, maxiter, errstring);
}
double Newton(FuncWrapper1D &f, double x0, double ftol, int maxiter, std::string &errstring){
    return Newton(&f, x0, ftol, maxiter, errstring);
}

}; /* namespace CoolProp */
<|endoftext|>


<commit_before>// Copyright (c) 2020 The Orbit Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ProcessListManager.h"

#include <chrono>
#include <memory>
#include <string>

#include "OrbitBase/Logging.h"
#include "grpcpp/grpcpp.h"
#include "services.grpc.pb.h"

namespace {

constexpr uint64_t kGrpcCallTimeoutMilliseconds = 200;

class ProcessListManagerImpl final : public ProcessListManager {
 public:
  explicit ProcessListManagerImpl(std::shared_ptr<grpc::Channel> channel,
                                  absl::Duration refresh_timeout);

  void SetCallback(
      const std::function<void(std::vector<ProcessInfo>&&)>& listener) override;
  void Start() override;
  void Shutdown() override;

 private:
  void WorkerFunction();

  std::unique_ptr<ProcessService::Stub> process_service_;

  absl::Duration refresh_timeout_;
  absl::Mutex shutdown_mutex_;
  bool shutdown_initiated_;

  absl::Mutex callback_mutex_;
  std::function<void(std::vector<ProcessInfo>&&)> callback_;
  std::thread worker_thread_;
};

ProcessListManagerImpl::ProcessListManagerImpl(
    std::shared_ptr<grpc::Channel> channel, absl::Duration refresh_timeout)
    : process_service_(ProcessService::NewStub(channel)),
      refresh_timeout_(refresh_timeout),
      shutdown_initiated_(false) {}

void ProcessListManagerImpl::SetCallback(
    const std::function<void(std::vector<ProcessInfo>&&)>& callback) {
  absl::MutexLock lock(&callback_mutex_);
  callback_ = callback;
}

void ProcessListManagerImpl::Start() {
  CHECK(!worker_thread_.joinable());
  worker_thread_ = std::thread([this] { WorkerFunction(); });
}

void ProcessListManagerImpl::Shutdown() {
  shutdown_mutex_.Lock();
  shutdown_initiated_ = true;
  shutdown_mutex_.Unlock();
  if (worker_thread_.joinable()) {
    worker_thread_.join();
  }
}

bool IsTrue(bool* var) { return *var; }

void ProcessListManagerImpl::WorkerFunction() {
  while (true) {
    if (shutdown_mutex_.LockWhenWithTimeout(
            absl::Condition(IsTrue, &shutdown_initiated_), refresh_timeout_)) {
      // Shutdown was initiated we need to exit
      shutdown_mutex_.Unlock();
      return;
    }
    shutdown_mutex_.Unlock();
    // Timeout expired - refresh the list

    GetProcessListRequest request;
    GetProcessListResponse response;
    grpc::ClientContext context;

    std::chrono::time_point deadline =
        std::chrono::system_clock::now() +
        std::chrono::milliseconds(kGrpcCallTimeoutMilliseconds);
    context.set_deadline(deadline);

    grpc::Status status =
        process_service_->GetProcessList(&context, request, &response);
    if (!status.ok()) {
      ERROR("Grpc call failed: %s", status.error_message());
      continue;
    }

    std::vector<ProcessInfo> processes(response.processes().begin(),
                                       response.processes().end());

    absl::MutexLock callback_lock(&callback_mutex_);
    callback_(std::move(processes));
  }
}

}  // namespace

std::unique_ptr<ProcessListManager> ProcessListManager::Create(
    std::shared_ptr<grpc::Channel> channel, absl::Duration refresh_timeout) {
  return std::make_unique<ProcessListManagerImpl>(channel, refresh_timeout);
}
<commit_msg>Increase GetProcessList call timout to one second.<commit_after>// Copyright (c) 2020 The Orbit Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ProcessListManager.h"

#include <chrono>
#include <memory>
#include <string>

#include "OrbitBase/Logging.h"
#include "grpcpp/grpcpp.h"
#include "services.grpc.pb.h"

namespace {

constexpr uint64_t kGrpcCallTimeoutMilliseconds = 1000;

class ProcessListManagerImpl final : public ProcessListManager {
 public:
  explicit ProcessListManagerImpl(std::shared_ptr<grpc::Channel> channel,
                                  absl::Duration refresh_timeout);

  void SetCallback(
      const std::function<void(std::vector<ProcessInfo>&&)>& listener) override;
  void Start() override;
  void Shutdown() override;

 private:
  void WorkerFunction();

  std::unique_ptr<ProcessService::Stub> process_service_;

  absl::Duration refresh_timeout_;
  absl::Mutex shutdown_mutex_;
  bool shutdown_initiated_;

  absl::Mutex callback_mutex_;
  std::function<void(std::vector<ProcessInfo>&&)> callback_;
  std::thread worker_thread_;
};

ProcessListManagerImpl::ProcessListManagerImpl(
    std::shared_ptr<grpc::Channel> channel, absl::Duration refresh_timeout)
    : process_service_(ProcessService::NewStub(channel)),
      refresh_timeout_(refresh_timeout),
      shutdown_initiated_(false) {}

void ProcessListManagerImpl::SetCallback(
    const std::function<void(std::vector<ProcessInfo>&&)>& callback) {
  absl::MutexLock lock(&callback_mutex_);
  callback_ = callback;
}

void ProcessListManagerImpl::Start() {
  CHECK(!worker_thread_.joinable());
  worker_thread_ = std::thread([this] { WorkerFunction(); });
}

void ProcessListManagerImpl::Shutdown() {
  shutdown_mutex_.Lock();
  shutdown_initiated_ = true;
  shutdown_mutex_.Unlock();
  if (worker_thread_.joinable()) {
    worker_thread_.join();
  }
}

bool IsTrue(bool* var) { return *var; }

void ProcessListManagerImpl::WorkerFunction() {
  while (true) {
    if (shutdown_mutex_.LockWhenWithTimeout(
            absl::Condition(IsTrue, &shutdown_initiated_), refresh_timeout_)) {
      // Shutdown was initiated we need to exit
      shutdown_mutex_.Unlock();
      return;
    }
    shutdown_mutex_.Unlock();
    // Timeout expired - refresh the list

    GetProcessListRequest request;
    GetProcessListResponse response;
    grpc::ClientContext context;

    std::chrono::time_point deadline =
        std::chrono::system_clock::now() +
        std::chrono::milliseconds(kGrpcCallTimeoutMilliseconds);
    context.set_deadline(deadline);

    grpc::Status status =
        process_service_->GetProcessList(&context, request, &response);
    if (!status.ok()) {
      ERROR("Grpc call failed: %s", status.error_message());
      continue;
    }

    std::vector<ProcessInfo> processes(response.processes().begin(),
                                       response.processes().end());

    absl::MutexLock callback_lock(&callback_mutex_);
    callback_(std::move(processes));
  }
}

}  // namespace

std::unique_ptr<ProcessListManager> ProcessListManager::Create(
    std::shared_ptr<grpc::Channel> channel, absl::Duration refresh_timeout) {
  return std::make_unique<ProcessListManagerImpl>(channel, refresh_timeout);
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <algorithm>
// If <iostream> is included, put it after <stdio.h>, because it includes
// <stdio.h>, and therefore would ignore the _WITH_GETLINE.
#ifdef FREEBSD
#define _WITH_GETLINE
#endif
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <Context.h>
#include <Hooks.h>
#include <text.h>
#include <util.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
Hooks::Hooks ()
{
}

////////////////////////////////////////////////////////////////////////////////
Hooks::~Hooks ()
{
}

////////////////////////////////////////////////////////////////////////////////
void Hooks::initialize ()
{
  // Scan <rc.data.location>/hooks
  Directory d (context.config.get ("data.location"));
  d += "hooks";
  if (d.is_directory () &&
      d.readable ())
  {
    _scripts = d.list ();
    std::sort (_scripts.begin (), _scripts.end ());
  }
}

////////////////////////////////////////////////////////////////////////////////
// The on-launch event is triggered once, after initialization, before an
// processing occurs
//
// No input
//
// Output:
// - all emitted JSON lines must be fully-formed tasks
// - all emitted non-JSON lines are considered feedback messages
//
// Exit:
//   0 Means:     - all emitted JSON lines are added/modified
//                - all emitted non-JSON lines become footnote entries
//   non-0 Means: - all emitted JSON lines are ignored
//                - all emitted non-JSON lines become error entries
//
void Hooks::onLaunch ()
{
  context.timer_hooks.start ();

  std::vector <std::string> matchingScripts = scripts ("on-launch");
  std::vector <std::string>::iterator i;
  for (i = matchingScripts.begin (); i != matchingScripts.end (); ++i)
  {
    std::string output;
    std::vector <std::string> args;
    int status = execute (*i, args, "", output);

    std::vector <std::string> lines;
    split (lines, output, '\n');
    std::vector <std::string>::iterator line;

    if (status == 0)
    {
      for (line = lines.begin (); line != lines.end (); ++line)
      {
        if (line->length () && (*line)[0] == '{')
        {
          Task newTask (*line);
          context.tdb2.add (newTask);
        }
        else
          context.header (*line);
      }
    }
    else
    {
      for (line = lines.begin (); line != lines.end (); ++line)
        if (line->length () && (*line)[0] != '{')
          context.error (*line);

      throw 0;  // This is how hooks silently terminate processing.
    }
  }

  context.timer_hooks.stop ();
}

////////////////////////////////////////////////////////////////////////////////
// Input:
// - A read-only line of JSON for each task added/modified
//
// Output:
// - all emitted non-JSON lines are considered feedback messages
// - The onExit event occurs too late to allow any changes, so the input is not
//   to be modified
//
// Exit:
//   0 Means:     - all emitted non-JSON lines become footnote entries
//   non-0 Means: - all emitted non-JSON lines become error entries
void Hooks::onExit ()
{
  context.timer_hooks.start ();

  std::vector <std::string> matchingScripts = scripts ("on-exit");
  std::vector <std::string>::iterator i;
  for (i = matchingScripts.begin (); i != matchingScripts.end (); ++i)
  {
    std::string input;
    std::string output;
    std::vector <std::string> args;
    int status = execute (*i, args, input, output);

    std::vector <std::string> lines;
    split (lines, output, '\n');
    std::vector <std::string>::iterator line;

    for (line = lines.begin (); line != lines.end (); ++line)
    {
      if (line->length () && (*line)[0] != '{')
      {
        if (status == 0)
          context.footnote (*line);
        else
          context.error (*line);
      }
    }
  }

  context.timer_hooks.stop ();
}

////////////////////////////////////////////////////////////////////////////////
// The on-add event is triggered separately for each task added
//
// Input:
// - A line of JSON for the task added
//
// Output:
// - all emitted JSON lines must be fully-formed tasks
// - all emitted non-JSON lines are considered feedback messages
//
// Exit:
//   0 Means:     - all emitted JSON lines are added/modified
//                - all emitted non-JSON lines become footnote entries
//   non-0 Means: - all emitted JSON lines are ignored
//                - all emitted non-JSON lines become error entries
//
void Hooks::onAdd (Task& after)
{
  context.timer_hooks.start ();

  std::vector <std::string> matchingScripts = scripts ("on-add");
  std::vector <std::string>::iterator i;
  for (i = matchingScripts.begin (); i != matchingScripts.end (); ++i)
  {
    std::string input = after.composeJSON () + "\n";
    std::string output;
    std::vector <std::string> args;
    int status = execute (*i, args, input, output);

    std::vector <std::string> lines;
    split (lines, output, '\n');
    std::vector <std::string>::iterator line;

    if (status == 0)
    {
      bool first = true;
      for (line = lines.begin (); line != lines.end (); ++line)
      {
        if (line->length () && (*line)[0] == '{')
        {
          Task newTask (*line);

          if (first)
          {
            after = newTask;
            first = false;
          }
          else
            context.tdb2.add (newTask);
        }
        else
          context.footnote (*line);
      }
    }
    else
    {
      for (line = lines.begin (); line != lines.end (); ++line)
        if (line->length () && (*line)[0] != '{')
          context.error (*line);

      throw 0;  // This is how hooks silently terminate processing.
    }
  }

  context.timer_hooks.stop ();
}

////////////////////////////////////////////////////////////////////////////////
// The on-modify event is triggered separately for each task added or modified
//
// Input:
// - A line of JSON for the original task
// - A line of JSON for the modified task
//
// Output:
// - all emitted JSON lines must be fully-formed tasks
// - all emitted non-JSON lines are considered feedback messages
//
// Exit:
//   0 Means:     - all emitted JSON lines are added/modified
//                - all emitted non-JSON lines become footnote entries
//   non-0 Means: - all emitted JSON lines are ignored
//                - all emitted non-JSON lines become error entries
void Hooks::onModify (const Task& before, Task& after)
{
  context.timer_hooks.start ();

  std::vector <std::string> matchingScripts = scripts ("on-modify");
  std::vector <std::string>::iterator i;
  for (i = matchingScripts.begin (); i != matchingScripts.end (); ++i)
  {
    std::string afterJSON = after.composeJSON ();
    std::string input = before.composeJSON ()
                      + "\n"
                      + afterJSON
                      + "\n";
    std::string output;
    std::vector <std::string> args;
    int status = execute (*i, args, input, output);

    std::vector <std::string> lines;
    split (lines, output, '\n');
    std::vector <std::string>::iterator line;

    if (status == 0)
    {
      bool first = true;
      for (line = lines.begin (); line != lines.end (); ++line)
      {
        if (line->length () && (*line)[0] == '{')
        {
          Task newTask (*line);

          if (first)
          {
            after = newTask;
            first = false;
          }
          else
            context.tdb2.add (newTask);
        }
        else
          context.footnote (*line);
      }
    }
    else
    {
      for (line = lines.begin (); line != lines.end (); ++line)
        if (line->length () && (*line)[0] != '{')
          context.error (*line);

      throw 0;  // This is how hooks silently terminate processing.
    }
  }

  context.timer_hooks.stop ();
}

////////////////////////////////////////////////////////////////////////////////
std::vector <std::string> Hooks::list ()
{
  return _scripts;
}

////////////////////////////////////////////////////////////////////////////////
std::vector <std::string> Hooks::scripts (const std::string& event)
{
  std::vector <std::string> matching;
  std::vector <std::string>::iterator i;
  for (i = _scripts.begin (); i != _scripts.end (); ++i)
  {
    if (i->find ("/" + event) != std::string::npos)
    {
      File script (*i);
      if (script.executable ())
        matching.push_back (*i);
    }
  }

  return matching;
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>Hooks<commit_after>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <algorithm>
// If <iostream> is included, put it after <stdio.h>, because it includes
// <stdio.h>, and therefore would ignore the _WITH_GETLINE.
#ifdef FREEBSD
#define _WITH_GETLINE
#endif
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <Context.h>
#include <Hooks.h>
#include <text.h>
#include <util.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
Hooks::Hooks ()
{
}

////////////////////////////////////////////////////////////////////////////////
Hooks::~Hooks ()
{
}

////////////////////////////////////////////////////////////////////////////////
void Hooks::initialize ()
{
  // Scan <rc.data.location>/hooks
  Directory d (context.config.get ("data.location"));
  d += "hooks";
  if (d.is_directory () &&
      d.readable ())
  {
    _scripts = d.list ();
    std::sort (_scripts.begin (), _scripts.end ());
  }
}

////////////////////////////////////////////////////////////////////////////////
// The on-launch event is triggered once, after initialization, before an
// processing occurs
//
// No input
//
// Output:
// - all emitted JSON lines must be fully-formed tasks
// - all emitted non-JSON lines are considered feedback messages
//
// Exit:
//   0 Means:     - all emitted JSON lines are added/modified
//                - all emitted non-JSON lines become footnote entries
//   non-0 Means: - all emitted JSON lines are ignored
//                - all emitted non-JSON lines become error entries
//
void Hooks::onLaunch ()
{
  context.timer_hooks.start ();

  std::vector <std::string> matchingScripts = scripts ("on-launch");
  std::vector <std::string>::iterator i;
  for (i = matchingScripts.begin (); i != matchingScripts.end (); ++i)
  {
    std::string output;
    std::vector <std::string> args;
    int status = execute (*i, args, "", output);

    std::vector <std::string> lines;
    split (lines, output, '\n');
    std::vector <std::string>::iterator line;

    if (status == 0)
    {
      for (line = lines.begin (); line != lines.end (); ++line)
      {
        if (line->length () && (*line)[0] == '{')
        {
          // Only 'add' is possible.
          Task newTask (*line);
          context.tdb2.add (newTask);
        }
        else
          context.header (*line);
      }
    }
    else
    {
      for (line = lines.begin (); line != lines.end (); ++line)
        if (line->length () && (*line)[0] != '{')
          context.error (*line);

      throw 0;  // This is how hooks silently terminate processing.
    }
  }

  context.timer_hooks.stop ();
}

////////////////////////////////////////////////////////////////////////////////
// Input:
// - A read-only line of JSON for each task added/modified
//
// Output:
// - all emitted non-JSON lines are considered feedback messages
// - The onExit event occurs too late to allow any changes, so the input is not
//   to be modified
//
// Exit:
//   0 Means:     - all emitted non-JSON lines become footnote entries
//   non-0 Means: - all emitted non-JSON lines become error entries
void Hooks::onExit ()
{
  context.timer_hooks.start ();

  std::vector <std::string> matchingScripts = scripts ("on-exit");
  std::vector <std::string>::iterator i;
  for (i = matchingScripts.begin (); i != matchingScripts.end (); ++i)
  {
    std::string input;
    std::string output;
    std::vector <std::string> args;
    int status = execute (*i, args, input, output);

    std::vector <std::string> lines;
    split (lines, output, '\n');
    std::vector <std::string>::iterator line;

    for (line = lines.begin (); line != lines.end (); ++line)
    {
      if (line->length () && (*line)[0] != '{')
      {
        if (status == 0)
          context.footnote (*line);
        else
          context.error (*line);
      }
    }
  }

  context.timer_hooks.stop ();
}

////////////////////////////////////////////////////////////////////////////////
// The on-add event is triggered separately for each task added
//
// Input:
// - A line of JSON for the task added
//
// Output:
// - all emitted JSON lines must be fully-formed tasks
// - all emitted non-JSON lines are considered feedback messages
//
// Exit:
//   0 Means:     - all emitted JSON lines are added/modified
//                - all emitted non-JSON lines become footnote entries
//   non-0 Means: - all emitted JSON lines are ignored
//                - all emitted non-JSON lines become error entries
//
void Hooks::onAdd (Task& after)
{
  context.timer_hooks.start ();

  std::vector <std::string> matchingScripts = scripts ("on-add");
  std::vector <std::string>::iterator i;
  for (i = matchingScripts.begin (); i != matchingScripts.end (); ++i)
  {
    std::string input = after.composeJSON () + "\n";
    std::string output;
    std::vector <std::string> args;
    int status = execute (*i, args, input, output);

    std::vector <std::string> lines;
    split (lines, output, '\n');
    std::vector <std::string>::iterator line;

    if (status == 0)
    {
      bool first = true;
      for (line = lines.begin (); line != lines.end (); ++line)
      {
        if (line->length () && (*line)[0] == '{')
        {
          Task newTask (*line);

          // TODO Not sure if this first/!first thing is good.
          if (first)
          {
            after = newTask;
            first = false;
          }
          else
            context.tdb2.add (newTask);
        }
        else
          context.footnote (*line);
      }
    }
    else
    {
      for (line = lines.begin (); line != lines.end (); ++line)
        if (line->length () && (*line)[0] != '{')
          context.error (*line);

      throw 0;  // This is how hooks silently terminate processing.
    }
  }

  context.timer_hooks.stop ();
}

////////////////////////////////////////////////////////////////////////////////
// The on-modify event is triggered separately for each task added or modified
//
// Input:
// - A line of JSON for the original task
// - A line of JSON for the modified task
//
// Output:
// - all emitted JSON lines must be fully-formed tasks
// - all emitted non-JSON lines are considered feedback messages
//
// Exit:
//   0 Means:     - all emitted JSON lines are added/modified
//                - all emitted non-JSON lines become footnote entries
//   non-0 Means: - all emitted JSON lines are ignored
//                - all emitted non-JSON lines become error entries
void Hooks::onModify (const Task& before, Task& after)
{
  context.timer_hooks.start ();

  std::vector <std::string> matchingScripts = scripts ("on-modify");
  std::vector <std::string>::iterator i;
  for (i = matchingScripts.begin (); i != matchingScripts.end (); ++i)
  {
    std::string afterJSON = after.composeJSON ();
    std::string input = before.composeJSON ()
                      + "\n"
                      + afterJSON
                      + "\n";
    std::string output;
    std::vector <std::string> args;
    int status = execute (*i, args, input, output);

    std::vector <std::string> lines;
    split (lines, output, '\n');
    std::vector <std::string>::iterator line;

    if (status == 0)
    {
      bool first = true;
      for (line = lines.begin (); line != lines.end (); ++line)
      {
        if (line->length () && (*line)[0] == '{')
        {
          Task newTask (*line);

          // TODO Not sure if this first/!first thing is good.
          if (first)
          {
            after = newTask;
            first = false;
          }
          else
            context.tdb2.add (newTask);
        }
        else
          context.footnote (*line);
      }
    }
    else
    {
      for (line = lines.begin (); line != lines.end (); ++line)
        if (line->length () && (*line)[0] != '{')
          context.error (*line);

      throw 0;  // This is how hooks silently terminate processing.
    }
  }

  context.timer_hooks.stop ();
}

////////////////////////////////////////////////////////////////////////////////
std::vector <std::string> Hooks::list ()
{
  return _scripts;
}

////////////////////////////////////////////////////////////////////////////////
std::vector <std::string> Hooks::scripts (const std::string& event)
{
  std::vector <std::string> matching;
  std::vector <std::string>::iterator i;
  for (i = _scripts.begin (); i != _scripts.end (); ++i)
  {
    if (i->find ("/" + event) != std::string::npos)
    {
      File script (*i);
      if (script.executable ())
        matching.push_back (*i);
    }
  }

  return matching;
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before><commit_msg>removed empty file<commit_after><|endoftext|>


<commit_before>#include "includes.h"

using namespace std::chrono;
using std::chrono::system_clock;
using std::chrono::milliseconds;

system_clock::time_point now_millis()
{
    return time_point_cast<milliseconds>(system_clock::now());
}
TEST_CASE("dequeue-empty-nowait", "[mpmc_blocking_q]")
{
    size_t q_size = 100;
    milliseconds tolerance_wait(10);
    spdlog::details::mpmc_blocking_queue<int> q(q_size);
    int popped_item;

    auto millis_0 = now_millis();
    auto rv = q.dequeue_for(popped_item, milliseconds::zero());
    auto millis_1 = now_millis();

    REQUIRE(rv == false);
    REQUIRE((millis_1-millis_0) <= tolerance_wait);

}

TEST_CASE("dequeue-empty-wait", "[mpmc_blocking_q]")
{

    size_t q_size = 100;
    milliseconds wait_ms(250);
    milliseconds tolerance_wait(10);

    spdlog::details::mpmc_blocking_queue<int> q(q_size);
    int popped_item;
    auto millis_0 = now_millis();
    auto rv = q.dequeue_for(popped_item, wait_ms);
    auto millis_1 = now_millis();
    auto delta_ms = millis_1 - millis_0;

    REQUIRE(rv == false);
    REQUIRE(delta_ms >= wait_ms);
    REQUIRE(delta_ms <= wait_ms + tolerance_wait);
}

TEST_CASE("enqueue_nowait", "[mpmc_blocking_q]")
{

    size_t q_size = 1;
    spdlog::details::mpmc_blocking_queue<int> q(q_size);
    milliseconds tolerance_wait(10);

    q.enqueue(1);
    REQUIRE(q.overrun_counter() == 0);

    auto millis_0 = now_millis();
    q.enqueue_nowait(2);
    auto millis_1 = now_millis();
    REQUIRE((millis_1-millis_0) <= tolerance_wait);
    REQUIRE(q.overrun_counter() == 1);
}

TEST_CASE("bad_queue", "[mpmc_blocking_q]")
{
    size_t q_size = 0;
    spdlog::details::mpmc_blocking_queue<int> q(q_size);
    q.enqueue_nowait(1);
    REQUIRE(q.overrun_counter() == 1);
    int i;
    REQUIRE(q.dequeue_for(i, milliseconds(0)) == false);
}

TEST_CASE("empty_queue", "[mpmc_blocking_q]")
{
    size_t q_size = 10;
    spdlog::details::mpmc_blocking_queue<int> q(q_size);
    int i;
    REQUIRE(q.dequeue_for(i, milliseconds(10)) == false);
}

TEST_CASE("full_queue", "[mpmc_blocking_q]")
{
    size_t q_size = 100;
    spdlog::details::mpmc_blocking_queue<int> q(q_size);
    for(int i = 0; i < static_cast<int>(q_size); i++)
    {
        q.enqueue(std::move(i));
    }

    q.enqueue_nowait(123456);
    REQUIRE(q.overrun_counter() == 1);

    for(int i = 1; i < static_cast<int>(q_size); i++)
    {
        int item=-1;
        q.dequeue_for(item, milliseconds(0));
        REQUIRE(item == i);
    }

    // last item pushed has overridden the oldest.
    int item=-1;
    q.dequeue_for(item, milliseconds(0));
    REQUIRE(item == 123456);
}<commit_msg>code formatting<commit_after>#include "includes.h"

using namespace std::chrono;
using std::chrono::milliseconds;
using std::chrono::system_clock;

system_clock::time_point now_millis()
{
    return time_point_cast<milliseconds>(system_clock::now());
}
TEST_CASE("dequeue-empty-nowait", "[mpmc_blocking_q]")
{
    size_t q_size = 100;
    milliseconds tolerance_wait(10);
    spdlog::details::mpmc_blocking_queue<int> q(q_size);
    int popped_item;

    auto millis_0 = now_millis();
    auto rv = q.dequeue_for(popped_item, milliseconds::zero());
    auto millis_1 = now_millis();

    REQUIRE(rv == false);
    REQUIRE((millis_1 - millis_0) <= tolerance_wait);
}

TEST_CASE("dequeue-empty-wait", "[mpmc_blocking_q]")
{

    size_t q_size = 100;
    milliseconds wait_ms(250);
    milliseconds tolerance_wait(10);

    spdlog::details::mpmc_blocking_queue<int> q(q_size);
    int popped_item;
    auto millis_0 = now_millis();
    auto rv = q.dequeue_for(popped_item, wait_ms);
    auto millis_1 = now_millis();
    auto delta_ms = millis_1 - millis_0;

    REQUIRE(rv == false);
    REQUIRE(delta_ms >= wait_ms);
    REQUIRE(delta_ms <= wait_ms + tolerance_wait);
}

TEST_CASE("enqueue_nowait", "[mpmc_blocking_q]")
{

    size_t q_size = 1;
    spdlog::details::mpmc_blocking_queue<int> q(q_size);
    milliseconds tolerance_wait(10);

    q.enqueue(1);
    REQUIRE(q.overrun_counter() == 0);

    auto millis_0 = now_millis();
    q.enqueue_nowait(2);
    auto millis_1 = now_millis();
    REQUIRE((millis_1 - millis_0) <= tolerance_wait);
    REQUIRE(q.overrun_counter() == 1);
}

TEST_CASE("bad_queue", "[mpmc_blocking_q]")
{
    size_t q_size = 0;
    spdlog::details::mpmc_blocking_queue<int> q(q_size);
    q.enqueue_nowait(1);
    REQUIRE(q.overrun_counter() == 1);
    int i;
    REQUIRE(q.dequeue_for(i, milliseconds(0)) == false);
}

TEST_CASE("empty_queue", "[mpmc_blocking_q]")
{
    size_t q_size = 10;
    spdlog::details::mpmc_blocking_queue<int> q(q_size);
    int i;
    REQUIRE(q.dequeue_for(i, milliseconds(10)) == false);
}

TEST_CASE("full_queue", "[mpmc_blocking_q]")
{
    size_t q_size = 100;
    spdlog::details::mpmc_blocking_queue<int> q(q_size);
    for (int i = 0; i < static_cast<int>(q_size); i++)
    {
        q.enqueue(std::move(i));
    }

    q.enqueue_nowait(123456);
    REQUIRE(q.overrun_counter() == 1);

    for (int i = 1; i < static_cast<int>(q_size); i++)
    {
        int item = -1;
        q.dequeue_for(item, milliseconds(0));
        REQUIRE(item == i);
    }

    // last item pushed has overridden the oldest.
    int item = -1;
    q.dequeue_for(item, milliseconds(0));
    REQUIRE(item == 123456);
}<|endoftext|>


<commit_before>#include "Ising.h"
#include "Utilities.h"

#include <math.h>
#include <assert.h>
#include <stack>

#define SQUARED(x) x*x

namespace ising {
    inline int s(char x,char y,char z) {
        return (x<<2) + (y<<1) + (z);
    }

    inline int boundsCheck(int x, const int max) {
        if (x < 0) {
            return max + x;
        }
        if (x >= max) {
            return x-max;
        }
        return x;
    }
}

using namespace ising;

Reservoir::InteractionResult IsingReservoir::interactWithBit(int bit) {
    InteractionResult result;
    if (currentState->bit != bit) {
        currentState=currentState->bitFlipState;
    }

    assert(ceil(constants.tau)>0 &&
           "Figure out how tau converts to discrete time.");
    int iterations = ceil(constants.tau);

    for (int k = 0; k<iterations; k++) {
        parity = 0;
        this->isingStep(result);
        this->wheelStep(result);
    }

    result.bit = currentState->bit;

    return result;
}

inline void IsingReservoir::isingStep(InteractionResult &result) {
    int row = 0;
    int column = (currentStepType == odd ? row + 1 : row) % 2;
    while (row<isingSide) {
        while (column<isingSide) {
            Coordinate coord(row,column);
            //Evolve each cell.
            char &cell = getCell(coord);
            if (countHighNeighbors(coord) == 2) {
                cell = (cell + 1) % 2;
            }
            parity += cell;

            column+=2;
        }
        row++;
        column = (currentStepType == odd ? row + 1 : row) % 2;
    }
    currentStepType = (currentStepType == odd) ? even : odd;
}

void IsingReservoir::reset() {
    currentState = randomState();
    for (int k = 0; k<clusters; k++) {
        clusterMethod();
    }
}

void IsingReservoir::clusterMethod() {

//  http://link.springer.com/chapter/10.1007%2F3-540-35273-2_1?LI=true#page-1

    std::stack<Coordinate> workStack;
    Coordinate currentCoord(rand()%isingSide,rand()%isingSide);
    workStack.push(currentCoord);
    char &currentCell = getCell(currentCoord);
    unsigned char clusterBit = currentCell;
    currentCell^=1;

    double inclusionProbability = 1 - exp(-2*constants.beta());
    assert(inclusionProbability<=1 && inclusionProbability>=0);

    //Basic BFT
    while (!workStack.empty()) {
        currentCoord = workStack.top();
        char &currentCell = getCell(currentCoord);
        workStack.pop();
        Neighbors neighbors = getNeighbors(currentCoord);
        for (int k=0; k<4; k++) {
            Coordinate neighborCoord = neighbors.coordinates[k];
            char &neighborCell = getCell(neighborCoord);

            if (neighborCell == clusterBit &&
                    gsl_rng_uniform(RNG)<inclusionProbability) {
                workStack.push(neighborCoord);
                neighborCell^=1;
            }
        }
        assert(workStack.size()<SQUARED(isingSide));
    }

}

inline void IsingReservoir::wheelStep(InteractionResult &result) {
    char &s1 = getCell(interactionCells.first);
    char &s2 = getCell(interactionCells.second);

    int inputState = s(s1,s2,parity % 2);

    SystemState *lastState = currentState;
    TransitionTable currentTable = transitions[currentState];
    SystemState *nextState = currentTable[inputState];

    assert(inputState<8 && inputState>=0 && "Invalid input state.");
    assert(currentTable.size() == 8 && "Transition table size should be 8");
    assert(nextState && "nextState must not be null.");

    const int &oldBit = nextState->bit;
    const int &newBit = currentState->bit;

    //The abstraction is leaking, but this saves a very complicated table.
    if (oldBit != newBit) {
        int initialEnergy = getEnergy(interactionCells.first) \
                                + getEnergy(interactionCells.second) - s1 ^ s2;

        if (newBit>oldBit) {
            s1 = 0;
            s2 = 0;
        } else if (newBit < oldBit) {
            s1 = 0;
            s2 = 1;
        }

        int finalEnergy = getEnergy(interactionCells.first) \
                                + getEnergy(interactionCells.second) - s1 ^ s2;

        result.work += initialEnergy - finalEnergy;
    }

    currentState = nextState;
}

inline int IsingReservoir::getEnergy(Coordinate c) {
    int highNeighbors = countHighNeighbors(c);

    if (getCell(c) == 1) {
        return 4 - highNeighbors;
    } else {
        return highNeighbors;
    }
}

inline int IsingReservoir::countHighNeighbors(Coordinate c) {
    Neighbors neighbors = getNeighbors(c);
    return countHigh(neighbors);
}

void IsingReservoir::initializeCellsWithRNG(gsl_rng *RNG, int N) {
    reset();
}

inline char &IsingReservoir::getCell(const Coordinate c) {
    //FIXME: Bounds check?
    return cells[c.y][c.x];
}

inline int IsingReservoir::countHigh(Neighbors list) {
    int highCount = 0;
    for (int k=0; k<4; k++) {
        highCount+=getCell(list.coordinates[k]);
    }
    return highCount;
}

IsingReservoir::Neighbors IsingReservoir::getNeighbors(const Coordinate c){
    Neighbors neighbors;
    for (int k = 0; k<4; k++) {
        Coordinate neighbor;
        switch (k) {
            case 0: // North
                neighbor.x = c.x;
                neighbor.y = c.y - 1;
                break;

            case 1: // South
                neighbor.x = c.x;
                neighbor.y = c.y + 1;
                break;

            case 2: // East
                neighbor.x = c.x - 1;
                neighbor.y = c.y;
                break;

            case 3: // West
                neighbor.x = c.x + 1;
                neighbor.y = c.y;
                break;

            default: // We should never be here.
                assert(0 && "Unreachable.");
                break;
        }
        neighbor.x = boundsCheck(neighbor.x, isingSide);
        neighbor.y = boundsCheck(neighbor.y, isingSide);
        neighbors.coordinates[k] = neighbor;
    }
    return neighbors;
}

IsingReservoir::~IsingReservoir() {
    for (int k=0; k<this->isingSide; k++) {
        delete [] cells[k];
    }
    delete [] cells;
}

IsingReservoir::IsingReservoir(gsl_rng *RNG_, Constants constants, int IS, int cls) :
        Reservoir(constants), isingSide(IS), RNG(RNG_), clusters(cls) {
    setupStateTable();
    cells = new char *[IS];
    for (int k=0; k<IS; k++) {
        cells[k]=new char[IS];

        std::fill(cells[k], cells[k]+IS, 0);
    }
    this->initializeCellsWithRNG(RNG);
}

inline void IsingReservoir::setupStateTable() {
    //TODO: Custom states. This is goofy.
    //Source: http://imgur.com/FF5TBQh

    #define init(XX) \
                TransitionTable XX;\
                for (char k=0; k<8; k++) \
                    XX[k]=&State##XX;
    init(A1);
    A1[s(0,0,1)] = &StateB1;
    A1[s(1,0,1)] = &StateB1;
    transitions[&StateA1]=A1;

    init(B1);
    B1[s(0,0,1)] = &StateA1;
    B1[s(1,0,1)] = &StateA1;
    B1[s(1,1,1)] = &StateC1;
    B1[s(0,1,1)] = &StateC1;
    transitions[&StateB1]=B1;

    init(C1);
    C1[s(0,1,1)] = &StateB1;
    C1[s(1,1,1)] = &StateB1;
    C1[s(0,0,1)] = &StateA0;
    C1[s(0,0,0)] = &StateA0;
    transitions[&StateC1]=C1;

    init(A0);
    A0[s(0,1,0)] = &StateC1;
    A0[s(0,1,1)] = &StateC1;
    A0[s(1,0,1)] = &StateB0;
    A0[s(0,0,1)] = &StateB0;
    transitions[&StateA0]=A0;

    init(B0);
    B0[s(0,0,1)] = &StateB0;
    B0[s(1,0,1)] = &StateB0;
    B0[s(1,1,1)] = &StateA0;
    B0[s(0,1,1)] = &StateA0;
    transitions[&StateB0] = B0;

    init(C0);
    C0[s(1,1,1)] = &StateB0;
    C0[s(0,1,1)] = &StateB0;
    transitions[&StateC0] = C0;
    //TODO: TEST ME.
}

Reservoir *IsingReservoir::IsingFactory::create(gsl_rng *RNG, Constants constants) {
    return new IsingReservoir(RNG,constants,dimension,clusters);
}

void isingEnergyDistribution(int d, int clusters) {
    Constants constants;
    constants.tau = 1;
    constants.delta = .5;
    constants.epsilon = 0;
    gsl_rng *RNG = GSLRandomNumberGenerator();
    for (int energy = 0; energy!=4; energy++) {
        constants.epsilon = .24*energy;
        printf("Beta: %lf\n",constants.beta());
        IsingReservoir *reservoir = new IsingReservoir(RNG,constants,d);
        reservoir->reset();
        for (int k=0; k<20000; k++) {
            printf("%d\n",reservoir->totalEnergy());
            reservoir->reset();
        }
        delete reservoir;
        printf("\n");
    }
}

int IsingReservoir::totalEnergy() {
    int N = SQUARED(isingSide);
    int energy = 0;
    for (int k = 0; k<N; k++) {
        int row = (int)(k % this->isingSide);
        int column = (int)(k / this->isingSide);
        energy += getEnergy(Coordinate(row, column));
    }
    // This method overcounts by two, considering both the forward and
    // backword bonds.
    return energy/2;
}
<commit_msg>Use more reasonable distribution length.<commit_after>#include "Ising.h"
#include "Utilities.h"

#include <math.h>
#include <assert.h>
#include <stack>

#define SQUARED(x) x*x

namespace ising {
    inline int s(char x,char y,char z) {
        return (x<<2) + (y<<1) + (z);
    }

    inline int boundsCheck(int x, const int max) {
        if (x < 0) {
            return max + x;
        }
        if (x >= max) {
            return x-max;
        }
        return x;
    }
}

using namespace ising;

Reservoir::InteractionResult IsingReservoir::interactWithBit(int bit) {
    InteractionResult result;
    if (currentState->bit != bit) {
        currentState=currentState->bitFlipState;
    }

    assert(ceil(constants.tau)>0 &&
           "Figure out how tau converts to discrete time.");
    int iterations = ceil(constants.tau);

    for (int k = 0; k<iterations; k++) {
        parity = 0;
        this->isingStep(result);
        this->wheelStep(result);
    }

    result.bit = currentState->bit;

    return result;
}

inline void IsingReservoir::isingStep(InteractionResult &result) {
    int row = 0;
    int column = (currentStepType == odd ? row + 1 : row) % 2;
    while (row<isingSide) {
        while (column<isingSide) {
            Coordinate coord(row,column);
            //Evolve each cell.
            char &cell = getCell(coord);
            if (countHighNeighbors(coord) == 2) {
                cell = (cell + 1) % 2;
            }
            parity += cell;

            column+=2;
        }
        row++;
        column = (currentStepType == odd ? row + 1 : row) % 2;
    }
    currentStepType = (currentStepType == odd) ? even : odd;
}

void IsingReservoir::reset() {
    currentState = randomState();
    for (int k = 0; k<clusters; k++) {
        clusterMethod();
    }
}

void IsingReservoir::clusterMethod() {

//  http://link.springer.com/chapter/10.1007%2F3-540-35273-2_1?LI=true#page-1

    std::stack<Coordinate> workStack;
    Coordinate currentCoord(rand()%isingSide,rand()%isingSide);
    workStack.push(currentCoord);
    char &currentCell = getCell(currentCoord);
    unsigned char clusterBit = currentCell;
    currentCell^=1;

    double inclusionProbability = 1 - exp(-2*constants.beta());
    assert(inclusionProbability<=1 && inclusionProbability>=0);

    //Basic BFT
    while (!workStack.empty()) {
        currentCoord = workStack.top();
        char &currentCell = getCell(currentCoord);
        workStack.pop();
        Neighbors neighbors = getNeighbors(currentCoord);
        for (int k=0; k<4; k++) {
            Coordinate neighborCoord = neighbors.coordinates[k];
            char &neighborCell = getCell(neighborCoord);

            if (neighborCell == clusterBit &&
                    gsl_rng_uniform(RNG)<inclusionProbability) {
                workStack.push(neighborCoord);
                neighborCell^=1;
            }
        }
        assert(workStack.size()<SQUARED(isingSide));
    }

}

inline void IsingReservoir::wheelStep(InteractionResult &result) {
    char &s1 = getCell(interactionCells.first);
    char &s2 = getCell(interactionCells.second);

    int inputState = s(s1,s2,parity % 2);

    SystemState *lastState = currentState;
    TransitionTable currentTable = transitions[currentState];
    SystemState *nextState = currentTable[inputState];

    assert(inputState<8 && inputState>=0 && "Invalid input state.");
    assert(currentTable.size() == 8 && "Transition table size should be 8");
    assert(nextState && "nextState must not be null.");

    const int &oldBit = nextState->bit;
    const int &newBit = currentState->bit;

    //The abstraction is leaking, but this saves a very complicated table.
    if (oldBit != newBit) {
        int initialEnergy = getEnergy(interactionCells.first) \
                                + getEnergy(interactionCells.second) - s1 ^ s2;

        if (newBit>oldBit) {
            s1 = 0;
            s2 = 0;
        } else if (newBit < oldBit) {
            s1 = 0;
            s2 = 1;
        }

        int finalEnergy = getEnergy(interactionCells.first) \
                                + getEnergy(interactionCells.second) - s1 ^ s2;

        result.work += initialEnergy - finalEnergy;
    }

    currentState = nextState;
}

inline int IsingReservoir::getEnergy(Coordinate c) {
    int highNeighbors = countHighNeighbors(c);

    if (getCell(c) == 1) {
        return 4 - highNeighbors;
    } else {
        return highNeighbors;
    }
}

inline int IsingReservoir::countHighNeighbors(Coordinate c) {
    Neighbors neighbors = getNeighbors(c);
    return countHigh(neighbors);
}

void IsingReservoir::initializeCellsWithRNG(gsl_rng *RNG, int N) {
    reset();
}

inline char &IsingReservoir::getCell(const Coordinate c) {
    //FIXME: Bounds check?
    return cells[c.y][c.x];
}

inline int IsingReservoir::countHigh(Neighbors list) {
    int highCount = 0;
    for (int k=0; k<4; k++) {
        highCount+=getCell(list.coordinates[k]);
    }
    return highCount;
}

IsingReservoir::Neighbors IsingReservoir::getNeighbors(const Coordinate c){
    Neighbors neighbors;
    for (int k = 0; k<4; k++) {
        Coordinate neighbor;
        switch (k) {
            case 0: // North
                neighbor.x = c.x;
                neighbor.y = c.y - 1;
                break;

            case 1: // South
                neighbor.x = c.x;
                neighbor.y = c.y + 1;
                break;

            case 2: // East
                neighbor.x = c.x - 1;
                neighbor.y = c.y;
                break;

            case 3: // West
                neighbor.x = c.x + 1;
                neighbor.y = c.y;
                break;

            default: // We should never be here.
                assert(0 && "Unreachable.");
                break;
        }
        neighbor.x = boundsCheck(neighbor.x, isingSide);
        neighbor.y = boundsCheck(neighbor.y, isingSide);
        neighbors.coordinates[k] = neighbor;
    }
    return neighbors;
}

IsingReservoir::~IsingReservoir() {
    for (int k=0; k<this->isingSide; k++) {
        delete [] cells[k];
    }
    delete [] cells;
}

IsingReservoir::IsingReservoir(gsl_rng *RNG_, Constants constants, int IS, int cls) :
        Reservoir(constants), isingSide(IS), RNG(RNG_), clusters(cls) {
    setupStateTable();
    cells = new char *[IS];
    for (int k=0; k<IS; k++) {
        cells[k]=new char[IS];

        std::fill(cells[k], cells[k]+IS, 0);
    }
    this->initializeCellsWithRNG(RNG);
}

inline void IsingReservoir::setupStateTable() {
    //TODO: Custom states. This is goofy.
    //Source: http://imgur.com/FF5TBQh

    #define init(XX) \
                TransitionTable XX;\
                for (char k=0; k<8; k++) \
                    XX[k]=&State##XX;
    init(A1);
    A1[s(0,0,1)] = &StateB1;
    A1[s(1,0,1)] = &StateB1;
    transitions[&StateA1]=A1;

    init(B1);
    B1[s(0,0,1)] = &StateA1;
    B1[s(1,0,1)] = &StateA1;
    B1[s(1,1,1)] = &StateC1;
    B1[s(0,1,1)] = &StateC1;
    transitions[&StateB1]=B1;

    init(C1);
    C1[s(0,1,1)] = &StateB1;
    C1[s(1,1,1)] = &StateB1;
    C1[s(0,0,1)] = &StateA0;
    C1[s(0,0,0)] = &StateA0;
    transitions[&StateC1]=C1;

    init(A0);
    A0[s(0,1,0)] = &StateC1;
    A0[s(0,1,1)] = &StateC1;
    A0[s(1,0,1)] = &StateB0;
    A0[s(0,0,1)] = &StateB0;
    transitions[&StateA0]=A0;

    init(B0);
    B0[s(0,0,1)] = &StateB0;
    B0[s(1,0,1)] = &StateB0;
    B0[s(1,1,1)] = &StateA0;
    B0[s(0,1,1)] = &StateA0;
    transitions[&StateB0] = B0;

    init(C0);
    C0[s(1,1,1)] = &StateB0;
    C0[s(0,1,1)] = &StateB0;
    transitions[&StateC0] = C0;
    //TODO: TEST ME.
}

Reservoir *IsingReservoir::IsingFactory::create(gsl_rng *RNG, Constants constants) {
    return new IsingReservoir(RNG,constants,dimension,clusters);
}

void isingEnergyDistribution(int d, int clusters) {
    Constants constants;
    constants.tau = 1;
    constants.delta = .5;
    constants.epsilon = 0;
    gsl_rng *RNG = GSLRandomNumberGenerator();
    for (int energy = 0; energy!=4; energy++) {
        constants.epsilon = .24*energy;
        printf("Beta: %lf\n",constants.beta());
        IsingReservoir *reservoir = new IsingReservoir(RNG,constants,d);
        reservoir->reset();
        for (int k=0; k<100; k++) {
            printf("%d\n",reservoir->totalEnergy());
            reservoir->reset();
        }
        delete reservoir;
        printf("\n");
    }
}

int IsingReservoir::totalEnergy() {
    int N = SQUARED(isingSide);
    int energy = 0;
    for (int k = 0; k<N; k++) {
        int row = (int)(k % this->isingSide);
        int column = (int)(k / this->isingSide);
        energy += getEnergy(Coordinate(row, column));
    }
    // This method overcounts by two, considering both the forward and
    // backword bonds.
    return energy/2;
}
<|endoftext|>


<commit_before>#include "dualnumberarray.h"
#include <iostream>
#include <masa.h>

typedef double RawScalar;

template <std::size_t NDIM, typename Scalar>
void evaluate_q (const NumberArray<NDIM, Scalar>& xyz);

using namespace MASA;

int main(void)
{
  int err = 0;

  const unsigned int NDIM = 2;

  const RawScalar xvecinit[] = {1., 0.};
  const RawScalar yvecinit[] = {0., 1.};

  const NumberArray<NDIM, RawScalar> xvec(xvecinit);
  const NumberArray<NDIM, RawScalar> yvec(yvecinit);

  typedef DualNumber<RawScalar, NumberArray<NDIM, RawScalar> > FirstDerivType;
  typedef DualNumber<FirstDerivType, NumberArray<NDIM, FirstDerivType> > SecondDerivType;

  typedef SecondDerivType ADType;
  // typedef FirstDerivType ADType;

  // initialize the problem in MASA
  err += masa_init("euler-example","euler_2d");

  // call the sanity check routine
  // (tests that all variables have been initialized)
  err += masa_sanity_check();

  err += masa_printid<double>();

  NumberArray<NDIM, ADType> xy;
  xy[0] = ADType(1., xvec);
  xy[1] = ADType(1., yvec);

  evaluate_q(xy);
}

// Note: ADScalar needs to be a FirstDerivType or better since we have
// first derivatives here.  Adding diffusion will require a
// SecondDerivType or better

template <std::size_t NDIM, typename ADScalar>
void evaluate_q (const NumberArray<NDIM, ADScalar>& xyz)
{
  typedef typename RawType<ADScalar>::value_type Scalar;

  const Scalar PI = std::acos(Scalar(-1));

  const Scalar k = 1.38;
  const Scalar u_0 = 200.23;
  const Scalar u_x = 1.1;
  const Scalar u_y = 1.08;
  const Scalar v_0 = 1.2;
  const Scalar v_x = 1.6;
  const Scalar v_y = .47;
  const Scalar rho_0 = 100.02;
  const Scalar rho_x = 2.22;
  const Scalar rho_y = 0.8;
  const Scalar p_0 = 150.2;
  const Scalar p_x = .91;
  const Scalar p_y = .623;
  const Scalar a_px = .165;
  const Scalar a_py = .612;
  const Scalar a_rhox = 1.0;
  const Scalar a_rhoy = 1.0;
  const Scalar a_ux = .1987;
  const Scalar a_uy = 1.189;
  const Scalar a_vx = 1.91;
  const Scalar a_vy = 1.0;
  const Scalar Gamma = 1.01;
  const Scalar mu = .918;
  const Scalar L = 3.02;

  const ADScalar& x = xyz[0];
  const ADScalar& y = xyz[1];

  // Treat velocity as a vector
  NumberArray<NDIM, ADScalar> U;

  // Arbitrary manufactured solution
  U[0] = u_0 + u_x * std::sin(a_ux * PI * x / L) + u_y * std::cos(a_uy * PI * y / L);
  U[1] = v_0 + v_x * std::cos(a_vx * PI * x / L) + v_y * std::sin(a_vy * PI * y / L);
  ADScalar RHO = rho_0 + rho_x * std::sin(a_rhox * PI * x / L) + rho_y * std::cos(a_rhoy * PI * y / L);
  ADScalar P = p_0 + p_x * std::cos(a_px * PI * x / L) + p_y * std::sin(a_py * PI * y / L);

  // Perfect gas energies
  ADScalar E = 1./(Gamma-1.)*P/RHO;
  ADScalar ET = E + .5 * U.dot(U);

  // Euler equation residuals
  Scalar Q_rho = raw_value(divergence(U));
  NumberArray<NDIM, Scalar> Q_rho_u = raw_value(divergence(RHO*U.outerproduct(U)) + P.derivatives());
  Scalar Q_rho_e = raw_value(divergence((RHO*ET+P)*U));

//  std::cout << f;
}
<commit_msg>[masa]: stuck, moving into holding pattern for #2117<commit_after>#include "dualnumberarray.h"
#include <iostream>
#include <masa.h>

typedef double RawScalar;

template <std::size_t NDIM, typename Scalar>
void evaluate_q (const NumberArray<NDIM, Scalar>& xyz);

using namespace MASA;

int main(void)
{
  int err = 0;

  const unsigned int NDIM = 2;

  const RawScalar xvecinit[] = {1., 0.};
  const RawScalar yvecinit[] = {0., 1.};

  const NumberArray<NDIM, RawScalar> xvec(xvecinit);
  const NumberArray<NDIM, RawScalar> yvec(yvecinit);

  typedef DualNumber<RawScalar, NumberArray<NDIM, RawScalar> > FirstDerivType;
  typedef DualNumber<FirstDerivType, NumberArray<NDIM, FirstDerivType> > SecondDerivType;

  typedef SecondDerivType ADType;
  // typedef FirstDerivType ADType;

  // initialize the problem in MASA
  err += masa_init("euler-maple","euler_2d");

  // call the sanity check routine
  // (tests that all variables have been initialized)
  err += masa_sanity_check();
  err += masa_printid<double>();

  // set up array
  NumberArray<NDIM, ADType> xy;
  xy[0] = ADType(1., xvec);
  xy[1] = ADType(1., yvec);

  // evaluate source terms
  evaluate_q(xy);

}

// Note: ADScalar needs to be a FirstDerivType or better since we have
// first derivatives here.  Adding diffusion will require a
// SecondDerivType or better

template <std::size_t NDIM, typename ADScalar>
void evaluate_q (const NumberArray<NDIM, ADScalar>& xyz)
{
  typedef typename RawType<ADScalar>::value_type Scalar;

  const Scalar PI = std::acos(Scalar(-1));

  const Scalar k = 1.38;
  const Scalar u_0 = 200.23;
  const Scalar u_x = 1.1;
  const Scalar u_y = 1.08;
  const Scalar v_0 = 1.2;
  const Scalar v_x = 1.6;
  const Scalar v_y = .47;
  const Scalar rho_0 = 100.02;
  const Scalar rho_x = 2.22;
  const Scalar rho_y = 0.8;
  const Scalar p_0 = 150.2;
  const Scalar p_x = .91;
  const Scalar p_y = .623;
  const Scalar a_px = .165;
  const Scalar a_py = .612;
  const Scalar a_rhox = 1.0;
  const Scalar a_rhoy = 1.0;
  const Scalar a_ux = .1987;
  const Scalar a_uy = 1.189;
  const Scalar a_vx = 1.91;
  const Scalar a_vy = 1.0;
  const Scalar Gamma = 1.01;
  const Scalar mu = .918;
  const Scalar L = 3.02;

  const ADScalar& x = xyz[0];
  const ADScalar& y = xyz[1];

  // Treat velocity as a vector
  NumberArray<NDIM, ADScalar> U;

  // Arbitrary manufactured solution
  U[0] = u_0 + u_x * std::sin(a_ux * PI * x / L) + u_y * std::cos(a_uy * PI * y / L);
  U[1] = v_0 + v_x * std::cos(a_vx * PI * x / L) + v_y * std::sin(a_vy * PI * y / L);
  ADScalar RHO = rho_0 + rho_x * std::sin(a_rhox * PI * x / L) + rho_y * std::cos(a_rhoy * PI * y / L);
  ADScalar P = p_0 + p_x * std::cos(a_px * PI * x / L) + p_y * std::sin(a_py * PI * y / L);

  // Perfect gas energies
  ADScalar E = 1./(Gamma-1.)*P/RHO;
  ADScalar ET = E + .5 * U.dot(U);

  // Euler equation residuals
  Scalar Q_rho = raw_value(divergence(U));
  NumberArray<NDIM, Scalar> Q_rho_u = raw_value(divergence(RHO*U.outerproduct(U)) + P.derivatives());
  Scalar Q_rho_e = raw_value(divergence((RHO*ET+P)*U));

//  std::cout << f;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "Utilities/utilities.hpp"
#include "Display/display.h"

using Utilities::SafeDelete;

Display::Display()
{
    m_inputModule = nullptr;
    m_isClosed = false;
    m_projMatrix = glm::mat4(1.0f);
}

Display::Display(int width, int height, std::string title, int argc, char** args)
{
    m_isClosed = false;
    m_projMatrix = glm::mat4(1.0f);

    if(!InitDisplay(width, height, title, argc, args))
    {
        std::cout << "Couldn't init display" << std::endl;
        throw;
    }
}

Display::~Display()
{
    Destroy();
}

glm::mat4 Display::GetProjectionMatrix()
{
    return m_projMatrix;
}

void callback()
{

}

bool Display::InitDisplay(int width, int height, std::string title, int argc, char** args)
{
    glutInit(&argc, args);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize(width, height);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(title.c_str());
    glutDisplayFunc(callback);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    std::cout << "Entering main loop" << std::endl;
    glutMainLoop();
    std::cout << "Exiting main loop" << std::endl;

    glewExperimental = GL_TRUE;
    GLenum status = glewInit();
    if(status != GLEW_OK)
    {
        std::cout << "Glew failed to initialize: " << status << std::endl;
        return false;
    }

    m_projMatrix = glm::perspective(glm::radians(75.0f), (float) width / (float) height, 0.1f, 100.0f);
    m_inputModule = std::make_shared<InputModule>();
    m_cameraModule = std::make_shared<CameraModule>();

    return true;
}

void Display::Destroy()
{

}

void Display::Update()
{

}

std::shared_ptr<Display::InputModule> Display::GetInputModule()
{
    return m_inputModule;
}

std::shared_ptr<Display::CameraModule> Display::GetCameraModule()
{
    return m_cameraModule;
}

bool Display::IsClosed()
{
    return m_isClosed;
}

<commit_msg>Added TODO<commit_after>#include <iostream>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "Utilities/utilities.hpp"
#include "Display/display.h"

using Utilities::SafeDelete;

Display::Display()
{
    m_inputModule = nullptr;
    m_isClosed = false;
    m_projMatrix = glm::mat4(1.0f);
}

Display::Display(int width, int height, std::string title, int argc, char** args)
{
    m_isClosed = false;
    m_projMatrix = glm::mat4(1.0f);

    if(!InitDisplay(width, height, title, argc, args))
    {
        std::cout << "Couldn't init display" << std::endl;
        throw;
    }
}

Display::~Display()
{
    Destroy();
}

glm::mat4 Display::GetProjectionMatrix()
{
    return m_projMatrix;
}

void callback()
{

}

bool Display::InitDisplay(int width, int height, std::string title, int argc, char** args)
{
    glutInit(&argc, args);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize(width, height);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(title.c_str());
    glutDisplayFunc(callback);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    // TODO fill callback with render information
    glutMainLoop();
    std::cout << "Exiting main loop" << std::endl;

    glewExperimental = GL_TRUE;
    GLenum status = glewInit();
    if(status != GLEW_OK)
    {
        std::cout << "Glew failed to initialize: " << status << std::endl;
        return false;
    }

    m_projMatrix = glm::perspective(glm::radians(75.0f), (float) width / (float) height, 0.1f, 100.0f);
    m_inputModule = std::make_shared<InputModule>();
    m_cameraModule = std::make_shared<CameraModule>();

    return true;
}

void Display::Destroy()
{

}

void Display::Update()
{

}

std::shared_ptr<Display::InputModule> Display::GetInputModule()
{
    return m_inputModule;
}

std::shared_ptr<Display::CameraModule> Display::GetCameraModule()
{
    return m_cameraModule;
}

bool Display::IsClosed()
{
    return m_isClosed;
}

<|endoftext|>


<commit_before>#include "Esp8266.h"

void Esp8266::begin() {

  LOG.verbose(F("Setup ESP8266 ..."));
  // setup hardware components
  motorA.begin(MOTOR_A_PWM, MOTOR_A_DIR),
  motorB.begin(MOTOR_B_PWM, MOTOR_B_DIR),
  MotorDriver::setPWMRange(PWM_RANGE);
  // setup WiFi client
  WIFI_CLIENT.getWiFiMulti().addAP(WIFI_SSID_1, WIFI_PASSWD_1);
  WIFI_CLIENT.getWiFiMulti().addAP(WIFI_SSID_2, WIFI_PASSWD_2);
  WIFI_CLIENT.begin();
  // setup WiFi access point
  WIFI_STATION.begin(WIFI_AP_SSID, WIFI_AP_PASSWD);
  // setup MDNS
  MDNS_SERVICE.begin("esp8266");
  MDNS_SERVICE.getMDNSResponder().addService("http", "tcp", PORT);
  //MDNS_SERVICE.getMDNSResponder().addService("https", "tcp", 443);
  // setup web server
  SERVER.begin(PORT);
  // rewrite root context˘˘
  SERVER.getWebServer().rewrite("/", "/index.build.html");
  // handle static web resources
  SERVER.getWebServer().serveStatic("/", SPIFFS, "/www/", "max-age:15"); // cache-control 15 seconds
  // add dynamic http resources
  SERVER.on("/esp", HTTP_GET, [this](AsyncWebServerRequest * request) {
    SERVER.send(request, SYSTEM.getDetails());
  });
  SERVER.on("/fs/details", HTTP_GET, [this](AsyncWebServerRequest * request) {
    SERVER.send(request, FILESYSTEM.getStorageDetails());
  });
  SERVER.on("/fs/listing", HTTP_GET, [this](AsyncWebServerRequest * request) {
    SERVER.send(request, FILESYSTEM.getFileListing());
  });
  SERVER.on("/wifi/client", HTTP_GET, [this](AsyncWebServerRequest * request) {
    SERVER.send(request, WIFI_CLIENT.getDetails());
  });
  SERVER.on("/wifi/station", HTTP_GET, [this](AsyncWebServerRequest * request) {
    SERVER.send(request, WIFI_STATION.getDetails());
  });
  SERVER.on("/mdns", HTTP_GET, [this](AsyncWebServerRequest * request) {
    SERVER.send(request, MDNS_SERVICE.getDetails());
  });
  SERVER.on("/motor/a", HTTP_GET, [this](AsyncWebServerRequest *request) {
    SERVER.send(request, motorA.getDetails());
  });
  SERVER.on("/motor/b", HTTP_GET, [this](AsyncWebServerRequest *request) {
    SERVER.send(request, motorB.getDetails());
  });
  // add web socket support
  wsl.onTextMessage([this](AsyncWebSocket *ws, AsyncWebSocketClient *client, AwsEventType type, AwsFrameInfo *info, uint8_t *data, size_t len) {

    DynamicJsonBuffer buffer;
    JsonObject &json = buffer.parse((char*)data);
    if (json.success() && json["motorA"].success() && json["motorB"].success() && json["mode"].success()) {

      int speedA = json["motorA"];
      int speedB = json["motorB"];

      //int speedA = atoi(json["motorA"]);
      //int speedB = atoi(json["motorB"]);
      const char* mode = json["mode"];

      LOG.verbose(F("Set motor A = %d and motor B = %d, PWM range = %d"), speedA, speedB, motorA.getPWMRange());

      // decide which mode to use
      if (strcmp("absolute", mode) == 0) {
        motorA.setSpeed(speedA);
        motorB.setSpeed(speedB);
      } else {
        motorA.applySpeed(speedA);
        motorB.applySpeed(speedB);
      }

      // create JSON reply message
      DynamicJsonBuffer buffer;
      JsonObject& message = buffer.createObject();
      message["clientId"] = client->id();
      message["motorA"] = motorA.getSpeed();
      message["motorB"] = motorB.getSpeed();

      // send reply message
      uint16_t length = message.measureLength() + 1;
      char payload[length];
      message.printTo(payload, length);
      client->text(payload);
    } else {
      client->text(F("Received an unexpected message."));
    }
  });
  // add web socket
  AsyncWebSocket* webSocket = new AsyncWebSocket("/racer");
  webSocket->onEvent([this](AsyncWebSocket *ws, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
    wsl.onEvent(ws, client, type, arg, data, len);
  });
  SERVER.getWebServer().addHandler(webSocket);

  LOG.verbose(F("========================="));
  LOG.verbose(F("Setup finished. Have fun."));
  LOG.verbose(F("========================="));
}

void Esp8266::run() {

  if (SYSTEM.nextLoopInterval()) {

    MDNS_SERVICE.getMDNSResponder().update();
  }
}<commit_msg>fixed missing SPIFFS initialization<commit_after>#include "Esp8266.h"

void Esp8266::begin() {

  LOG.verbose(F("Setup ESP8266 ..."));
  // setup hardware components
  motorA.begin(MOTOR_A_PWM, MOTOR_A_DIR),
  motorB.begin(MOTOR_B_PWM, MOTOR_B_DIR),
  MotorDriver::setPWMRange(PWM_RANGE);
  // setup WiFi client
  WIFI_CLIENT.getWiFiMulti().addAP(WIFI_SSID_1, WIFI_PASSWD_1);
  WIFI_CLIENT.getWiFiMulti().addAP(WIFI_SSID_2, WIFI_PASSWD_2);
  WIFI_CLIENT.begin();
  // setup WiFi access point
  WIFI_STATION.begin(WIFI_AP_SSID, WIFI_AP_PASSWD);
  // setup MDNS
  MDNS_SERVICE.begin("esp8266");
  MDNS_SERVICE.getMDNSResponder().addService("http", "tcp", PORT);
  //MDNS_SERVICE.getMDNSResponder().addService("https", "tcp", 443);
  FILESYSTEM.getFileSystem();
  // setup web server
  SERVER.begin(PORT);
  // rewrite root context˘˘
  SERVER.getWebServer().rewrite("/", "/index.build.html");
  // handle static web resources
  SERVER.getWebServer().serveStatic("/", SPIFFS, "/www/", "max-age:15"); // cache-control 15 seconds
  // add dynamic http resources
  SERVER.on("/esp", HTTP_GET, [this](AsyncWebServerRequest * request) {
    SERVER.send(request, SYSTEM.getDetails());
  });
  SERVER.on("/fs/details", HTTP_GET, [this](AsyncWebServerRequest * request) {
    SERVER.send(request, FILESYSTEM.getStorageDetails());
  });
  SERVER.on("/fs/listing", HTTP_GET, [this](AsyncWebServerRequest * request) {
    SERVER.send(request, FILESYSTEM.getFileListing());
  });
  SERVER.on("/wifi/client", HTTP_GET, [this](AsyncWebServerRequest * request) {
    SERVER.send(request, WIFI_CLIENT.getDetails());
  });
  SERVER.on("/wifi/station", HTTP_GET, [this](AsyncWebServerRequest * request) {
    SERVER.send(request, WIFI_STATION.getDetails());
  });
  SERVER.on("/mdns", HTTP_GET, [this](AsyncWebServerRequest * request) {
    SERVER.send(request, MDNS_SERVICE.getDetails());
  });
  SERVER.on("/motor/a", HTTP_GET, [this](AsyncWebServerRequest *request) {
    SERVER.send(request, motorA.getDetails());
  });
  SERVER.on("/motor/b", HTTP_GET, [this](AsyncWebServerRequest *request) {
    SERVER.send(request, motorB.getDetails());
  });
  // add web socket support
  wsl.onTextMessage([this](AsyncWebSocket *ws, AsyncWebSocketClient *client, AwsEventType type, AwsFrameInfo *info, uint8_t *data, size_t len) {

    DynamicJsonBuffer buffer;
    JsonObject &json = buffer.parse((char*)data);
    if (json.success() && json["motorA"].success() && json["motorB"].success() && json["mode"].success()) {

      int speedA = json["motorA"];
      int speedB = json["motorB"];

      //int speedA = atoi(json["motorA"]);
      //int speedB = atoi(json["motorB"]);
      const char* mode = json["mode"];

      LOG.verbose(F("Set motor A = %d and motor B = %d, PWM range = %d"), speedA, speedB, motorA.getPWMRange());

      // decide which mode to use
      if (strcmp("absolute", mode) == 0) {
        motorA.setSpeed(speedA);
        motorB.setSpeed(speedB);
      } else {
        motorA.applySpeed(speedA);
        motorB.applySpeed(speedB);
      }

      // create JSON reply message
      DynamicJsonBuffer buffer;
      JsonObject& message = buffer.createObject();
      message["clientId"] = client->id();
      message["motorA"] = motorA.getSpeed();
      message["motorB"] = motorB.getSpeed();

      // send reply message
      uint16_t length = message.measureLength() + 1;
      char payload[length];
      message.printTo(payload, length);
      client->text(payload);
    } else {
      client->text(F("Received an unexpected message."));
    }
  });
  // add web socket
  AsyncWebSocket* webSocket = new AsyncWebSocket("/racer");
  webSocket->onEvent([this](AsyncWebSocket *ws, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
    wsl.onEvent(ws, client, type, arg, data, len);
  });
  SERVER.getWebServer().addHandler(webSocket);

  LOG.verbose(F("========================="));
  LOG.verbose(F("Setup finished. Have fun."));
  LOG.verbose(F("========================="));
}

void Esp8266::run() {

  if (SYSTEM.nextLoopInterval()) {

    MDNS_SERVICE.getMDNSResponder().update();
  }
}<|endoftext|>