<commit_before>/**
 * @file
 * @author Alexander Sherikov
 * @date 19.07.2011 22:30:13 MSD
 */

/****************************************
 * INCLUDES
 ****************************************/
#include "qp_as.h"
#include "state_handling.h"

#include <string.h> // in order to use memcpy and memmove
#include <cmath> // cos, sin

/****************************************
 * FUNCTIONS
 ****************************************/

//==============================================
// bound
/**
 * @brief Set parameters of the bound
 *
 * @param[in] var_num_ index of variable in the vector of states
 * @param[in] lb_ lower bound
 * @param[in] ub_ upper bound
 * @param[in] active activity of the bound
 */
void bound::set(int var_num_, double lb_, double ub_, int active)
{
    var_num = var_num_;
    lb = lb_;
    ub = ub_;
    isActive = active;
}

//==============================================
// qp_as

/** @brief Constructor: initialization of the constant parameters

    @param[in] N_ Number of sampling times in a preview window
    @param[in] Alpha Velocity gain
    @param[in] Beta Position gain
    @param[in] Gamma Jerk gain
    @param[in] regularization regularization
    @param[in] tol_ tolerance
*/
qp_as::qp_as(int N_, double Alpha, double Beta, double Gamma, double regularization, double tol_) : chol (N_)
{
    N = N_;
    tol = tol_;

    gain_alpha = Alpha;
    gain_beta  = Beta;
    gain_gamma = Gamma;

    chol_param.i2Q[0] = 1/(2*(Beta/2));
    chol_param.i2Q[1] = 1/(2*(Alpha/2));
    chol_param.i2Q[2] = 1/(2*regularization);

    chol_param.i2P = 1/(2 * (Gamma/2));

    chol_param.iHg = new double[NUM_VAR*N]();

    chol_param.T = NULL;
    chol_param.h = NULL;
#ifdef QPAS_VARIABLE_T_h
    chol_param.dh = NULL;
#endif

    chol_param.angle_cos = NULL;
    chol_param.angle_sin = NULL;

    // there are no inequality constraints in the initial working set (no hot-starting for the moment)
    W = new int[2*N];
#ifdef QPAS_DOWNDATE
    W_sign = new int[2*N];
#endif
    alpha = 1;

    dX = new double[NUM_VAR*N]();

    Bounds.resize(2*N);
}

/** Destructor */
qp_as::~qp_as()
{
    if (W  != NULL)
        delete [] W;

    if (dX  != NULL)
        delete [] dX;

    if (chol_param.angle_cos != NULL)
        delete chol_param.angle_cos;

    if (chol_param.angle_sin != NULL)
        delete chol_param.angle_sin;

    if (chol_param.iHg != NULL)
        delete chol_param.iHg;

#ifdef QPAS_VARIABLE_T_h
    if (chol_param.dh != NULL)
        delete chol_param.dh;
#endif
#ifdef QPAS_DOWNDATE
    if (W_sign != NULL)
        delete W_sign;
#endif
}

/** @brief Initializes quadratic problem.

    @param[in] T_ Sampling time (for the moment it is assumed to be constant) [sec.]
    @param[in] h_ Height of the Center of Mass divided by gravity
    @param[in] angle Rotation angle for each state in the preview window
    @param[in] zref_x reference values of z_x
    @param[in] zref_y reference values of z_y
    @param[in] lb array of lower bounds for z_x and z_y
    @param[in] ub array of upper bounds for z_x and z_y
    @param[in] X_tilde current state
    @param[in,out] X_ initial guess / solution of optimization problem
*/
void qp_as::init(
        double* T_,
        double* h_,
        double* angle,
        double* zref_x,
        double* zref_y,
        double* lb,
        double* ub,
        double* X_tilde,
        double* X_)
{
    nW = 0;

    chol_param.T = T_;
    chol_param.h = h_;
#ifdef QPAS_VARIABLE_T_h
    chol_param.dh = new double[N-1]();
    for (int i = 0; i < N-1; i++)
    {
        chol_param.dh[i] = chol_param.h[i+1] - chol_param.h[i];
    }
#endif

    X = X_;

    form_bounds(lb, ub);

    chol_param.angle_cos = new double[N];
    chol_param.angle_sin = new double[N];

    for (int i = 0; i < N; i++)
    {
        chol_param.angle_cos[i] = cos(angle[i]);
        chol_param.angle_sin[i] = sin(angle[i]);
    }

    form_init_fp (zref_x, zref_y, X_tilde);
    form_iHg (zref_x, zref_y);
}

/**
 * @brief Generates an initial feasible point.
 * First we perform a change of variable to @ref pX_tilde "X_tilde"
 * generate a feasible point, and then we go back to @ref pX_bar "X_bar".
 */
void qp_as::form_init_fp(double *zref_x, double *zref_y, double *X_tilde)
{
    double *control = &X[NUM_STATE_VAR*N];
    double *cur_state = X;
    double *prev_state = X_tilde;

#ifndef QPAS_VARIABLE_T_h
    //------------------------------------
    double T = chol_param.T[0];
    double T2 = T*T/2;
    double h = chol_param.h[0];

    /* Control matrix. */
    double B[3] = {T2*T/3 - h*T, T2, T};

    /* inv(Cp*B). This is a [2 x 2] diagonal matrix (which is invertible if T^3/6-h*T is
     * not equal to zero). The two elements one the main diagonal are equal, and only one of them
     * is stored, which is equal to
        1/(T^3/6 - h*T)
     */
    double iCpB = 1/(B[0]);

    /* inv(Cp*B)*Cp*A. This is a [2 x 6] matrix with the following structure
        iCpB_CpA = [a b c 0 0 0;
                    0 0 0 a b c];

        a = iCpB
        b = iCpB*T
        c = iCpB*T^2/2
     * Only a,b and c are stored.
     */
    double iCpB_CpA[3] = {iCpB, iCpB*T, iCpB*T2};
    //------------------------------------
#endif /*QPAS_VARIABLE_T_h*/

    for (int i=0; i<N; i++)
    {
#ifdef QPAS_VARIABLE_T_h
        //------------------------------------
        double T = chol_param.T[i];
        double T2 = T*T/2;
        double h = chol_param.h[i];

        /* Control matrix. */
        double B[3] = {T2*T/3 - h*T, T2, T};

        /* inv(Cp*B). This is a [2 x 2] diagonal matrix (which is invertible if T^3/6-h*T is
         * not equal to zero). The two elements one the main diagonal are equal, and only one of them
         * is stored, which is equal to
            1/(T^3/6 - h*T)
         */
        double iCpB = 1/(B[0]);

        /* inv(Cp*B)*Cp*A. This is a [2 x 6] matrix with the following structure
            iCpB_CpA = [a b c 0 0 0;
                        0 0 0 a b c];

            a = iCpB
            b = iCpB*T
            c = iCpB*T^2/2
         * Only a,b and c are stored.
         */
        double iCpB_CpA[3] = {iCpB, iCpB*T, iCpB*T2};
        //------------------------------------
#endif /*QPAS_VARIABLE_T_h*/

        control[0] = -iCpB_CpA[0]*prev_state[0] - iCpB_CpA[1]*prev_state[1] - iCpB_CpA[2]*prev_state[2] + iCpB*zref_x[i];
        control[1] = -iCpB_CpA[0]*prev_state[3] - iCpB_CpA[1]*prev_state[4] - iCpB_CpA[2]*prev_state[5] + iCpB*zref_y[i];

        cur_state[0] = prev_state[0] + T*prev_state[1] + T2*prev_state[2] + B[0]*control[0];
        cur_state[1] =                   prev_state[1] +  T*prev_state[2] + B[1]*control[0];
        cur_state[2] =                                      prev_state[2] + B[2]*control[0];
        cur_state[3] = prev_state[3] + T*prev_state[4] + T2*prev_state[5] + B[0]*control[1];
        cur_state[4] =                   prev_state[4] +  T*prev_state[5] + B[1]*control[1];
        cur_state[5] =                                      prev_state[5] + B[2]*control[1];

        prev_state = &X[NUM_STATE_VAR*i];
        cur_state = &X[NUM_STATE_VAR*(i+1)];
        control = &control[NUM_CONTROL_VAR];
    }

    // go back to bar states
    cur_state = X;
    for (int i=0; i<N; i++)
    {
        state_handling::tilde_to_bar (cur_state, chol_param.angle_sin[i], chol_param.angle_cos[i]);
        cur_state = &cur_state[NUM_STATE_VAR];
    }
}

/**
 * @brief Forms inv(2*H) * g.
 *
 * @param[in] zref_x reference values of z_x
 * @param[in] zref_y reference values of z_y
 */
void qp_as::form_iHg(double *zref_x, double *zref_y)
{
    double p0, p1;
    double cosA, sinA;

    for (int i = 0; i < N; i++)
    {
        cosA = chol_param.angle_cos[i];
        sinA = chol_param.angle_sin[i];

        // zref
        p0 = zref_x[i];
        p1 = zref_y[i];

        // inv (2*H) * R' * Cp' * zref
        chol_param.iHg[i*NUM_STATE_VAR + 0] =
            -chol_param.i2Q[0] * (cosA*p0 + sinA*p1)*gain_beta;
        chol_param.iHg[i*NUM_STATE_VAR + 3] =
            -chol_param.i2Q[0] * (-sinA*p0 + cosA*p1)*gain_beta;
    }
}

/**
 * @brief Forms the upper and lower bounds.
 *
 * @param[in] lb array of lower bounds for z
 * @param[in] ub array of upper bounds for z
 */
void qp_as::form_bounds(double *lb, double *ub)
{
    for (int i=0; i < N; i++)
    {
        Bounds[i*2].set(NUM_STATE_VAR*i, lb[i*2], ub[i*2], 0);
        Bounds[i*2+1].set(NUM_STATE_VAR*i+3, lb[i*2+1], ub[i*2+1], 0);
    }
}

/**
 * @brief Checks for blocking bounds.
 *
 * @return sequential number of constraint to be added, -1 if no constraints.
 */
int qp_as::check_blocking_bounds()
{
    alpha = 1;

    /* Index to include in the working set, -1 if no constraint have to be included. */
    int activated_var_num = -1;

    for (int i = 0; i < 2*N; i++)
    {
        // Check only inactive constraints for violation.
        // The constraints in the working set will not be violated regardless of
        // the depth of descent
        if (Bounds[i].isActive == 0)
        {
            int ind = Bounds[i].var_num;
#ifdef QPAS_DOWNDATE
            int sign = 1;
#endif
            double t = 1;

            if ( dX[ind] < -tol )
            {
                t = (Bounds[i].lb - X[ind])/dX[ind];
#ifdef QPAS_DOWNDATE
                sign = -1;
#endif
            }
            else if ( dX[ind] > tol )
            {
                t = (Bounds[i].ub - X[ind])/dX[ind];
            }
            else
            {
                // do nothing because dX[Bounds[i].var_num] = 0 (numerically speaking)
                t = 1;
            }

            if (t < alpha)
            {
                alpha = t;
                activated_var_num = i;
#ifdef QPAS_DOWNDATE
                W_sign[nW] = sign;
#endif
            }
        }
    }
    if (activated_var_num != -1)
    {
        W[nW] = activated_var_num;
        nW++;
        Bounds[activated_var_num].isActive = 1;
    }

    return (activated_var_num);
}

#ifdef QPAS_DOWNDATE
/**
 * @brief Selects a constraint for removal from active set.
 *
 * @param[in] lambda vector of Lagrange multipliers corresponding
 *  to inequality constraints.
 *
 * @return index of constraint in the active set, -1 if no constraint
 *  can be removed.
 *
 * @attention If a constraint for removal is selected, then it is
 * removed from the active set (#W) and the number of constraints
 * in active set (#nW) is decremented.
 */
int qp_as::choose_excl_constr (double *lambda)
{
    double min_lambda = -tol;
    int ind_exclude = -1;

    // find the constraint with the smallest lambda
    for (int i = 0; i < nW; i++)
    {
        if (lambda[i] * W_sign[i] < min_lambda)
        {
            min_lambda = lambda[i] * W_sign[i];
            ind_exclude = i;
        }
    }

    if (ind_exclude != -1)
    {
        Bounds[W[ind_exclude]].isActive = 0;
        for (int i = ind_exclude; i < nW-1; i++)
        {
            W[i] = W[i + 1];
            W_sign[i] = W_sign[i + 1];
        }
        nW--;
    }

    return (ind_exclude);
}
#endif /* QPAS_DOWNDATE */

/**
 * @brief Solve QP problem.
 *
 * @return number of activated constraints
 */
int qp_as::solve ()
{
    // obtain dX
    chol.solve(chol_param, X, dX);

    for (;;)
    {
        int activated_var_num = check_blocking_bounds();

        // Move in the feasible descent direction
        for (int i = 0; i < N*NUM_VAR ; i++)
        {
            X[i] += alpha * dX[i];
        }

        // no new inequality constraints
        if (activated_var_num == -1)
        {
#ifdef QPAS_DOWNDATE
            int ind_exclude = choose_excl_constr (chol.get_lambda());
            if (ind_exclude != -1)
            {
                chol.down_resolve (chol_param, nW, W, ind_exclude, X, dX);
            }
            else
            {
                break;
            }
#else
            break;
#endif /*QPAS_DOWNDATE*/
        }
        else
        {
            // add row to the L matrix and find new dX
            chol.up_resolve (chol_param, nW, W, X, dX);
        }
    }

    return (nW);
}
<commit_msg>There is no need to set dh to 0 on initialization.<commit_after>/**
 * @file
 * @author Alexander Sherikov
 * @date 19.07.2011 22:30:13 MSD
 */

/****************************************
 * INCLUDES
 ****************************************/
#include "qp_as.h"
#include "state_handling.h"

#include <string.h> // in order to use memcpy and memmove
#include <cmath> // cos, sin

/****************************************
 * FUNCTIONS
 ****************************************/

//==============================================
// bound
/**
 * @brief Set parameters of the bound
 *
 * @param[in] var_num_ index of variable in the vector of states
 * @param[in] lb_ lower bound
 * @param[in] ub_ upper bound
 * @param[in] active activity of the bound
 */
void bound::set(int var_num_, double lb_, double ub_, int active)
{
    var_num = var_num_;
    lb = lb_;
    ub = ub_;
    isActive = active;
}

//==============================================
// qp_as

/** @brief Constructor: initialization of the constant parameters

    @param[in] N_ Number of sampling times in a preview window
    @param[in] Alpha Velocity gain
    @param[in] Beta Position gain
    @param[in] Gamma Jerk gain
    @param[in] regularization regularization
    @param[in] tol_ tolerance
*/
qp_as::qp_as(int N_, double Alpha, double Beta, double Gamma, double regularization, double tol_) : chol (N_)
{
    N = N_;
    tol = tol_;

    gain_alpha = Alpha;
    gain_beta  = Beta;
    gain_gamma = Gamma;

    chol_param.i2Q[0] = 1/(2*(Beta/2));
    chol_param.i2Q[1] = 1/(2*(Alpha/2));
    chol_param.i2Q[2] = 1/(2*regularization);

    chol_param.i2P = 1/(2 * (Gamma/2));

    chol_param.iHg = new double[NUM_VAR*N]();

    chol_param.T = NULL;
    chol_param.h = NULL;
#ifdef QPAS_VARIABLE_T_h
    chol_param.dh = NULL;
#endif

    chol_param.angle_cos = NULL;
    chol_param.angle_sin = NULL;

    // there are no inequality constraints in the initial working set (no hot-starting for the moment)
    W = new int[2*N];
#ifdef QPAS_DOWNDATE
    W_sign = new int[2*N];
#endif
    alpha = 1;

    dX = new double[NUM_VAR*N]();

    Bounds.resize(2*N);
}

/** Destructor */
qp_as::~qp_as()
{
    if (W  != NULL)
        delete [] W;

    if (dX  != NULL)
        delete [] dX;

    if (chol_param.angle_cos != NULL)
        delete chol_param.angle_cos;

    if (chol_param.angle_sin != NULL)
        delete chol_param.angle_sin;

    if (chol_param.iHg != NULL)
        delete chol_param.iHg;

#ifdef QPAS_VARIABLE_T_h
    if (chol_param.dh != NULL)
        delete chol_param.dh;
#endif
#ifdef QPAS_DOWNDATE
    if (W_sign != NULL)
        delete W_sign;
#endif
}

/** @brief Initializes quadratic problem.

    @param[in] T_ Sampling time (for the moment it is assumed to be constant) [sec.]
    @param[in] h_ Height of the Center of Mass divided by gravity
    @param[in] angle Rotation angle for each state in the preview window
    @param[in] zref_x reference values of z_x
    @param[in] zref_y reference values of z_y
    @param[in] lb array of lower bounds for z_x and z_y
    @param[in] ub array of upper bounds for z_x and z_y
    @param[in] X_tilde current state
    @param[in,out] X_ initial guess / solution of optimization problem
*/
void qp_as::init(
        double* T_,
        double* h_,
        double* angle,
        double* zref_x,
        double* zref_y,
        double* lb,
        double* ub,
        double* X_tilde,
        double* X_)
{
    nW = 0;

    chol_param.T = T_;
    chol_param.h = h_;
#ifdef QPAS_VARIABLE_T_h
    chol_param.dh = new double[N-1];
    for (int i = 0; i < N-1; i++)
    {
        chol_param.dh[i] = chol_param.h[i+1] - chol_param.h[i];
    }
#endif

    X = X_;

    form_bounds(lb, ub);

    chol_param.angle_cos = new double[N];
    chol_param.angle_sin = new double[N];

    for (int i = 0; i < N; i++)
    {
        chol_param.angle_cos[i] = cos(angle[i]);
        chol_param.angle_sin[i] = sin(angle[i]);
    }

    form_init_fp (zref_x, zref_y, X_tilde);
    form_iHg (zref_x, zref_y);
}

/**
 * @brief Generates an initial feasible point.
 * First we perform a change of variable to @ref pX_tilde "X_tilde"
 * generate a feasible point, and then we go back to @ref pX_bar "X_bar".
 */
void qp_as::form_init_fp(double *zref_x, double *zref_y, double *X_tilde)
{
    double *control = &X[NUM_STATE_VAR*N];
    double *cur_state = X;
    double *prev_state = X_tilde;

#ifndef QPAS_VARIABLE_T_h
    //------------------------------------
    double T = chol_param.T[0];
    double T2 = T*T/2;
    double h = chol_param.h[0];

    /* Control matrix. */
    double B[3] = {T2*T/3 - h*T, T2, T};

    /* inv(Cp*B). This is a [2 x 2] diagonal matrix (which is invertible if T^3/6-h*T is
     * not equal to zero). The two elements one the main diagonal are equal, and only one of them
     * is stored, which is equal to
        1/(T^3/6 - h*T)
     */
    double iCpB = 1/(B[0]);

    /* inv(Cp*B)*Cp*A. This is a [2 x 6] matrix with the following structure
        iCpB_CpA = [a b c 0 0 0;
                    0 0 0 a b c];

        a = iCpB
        b = iCpB*T
        c = iCpB*T^2/2
     * Only a,b and c are stored.
     */
    double iCpB_CpA[3] = {iCpB, iCpB*T, iCpB*T2};
    //------------------------------------
#endif /*QPAS_VARIABLE_T_h*/

    for (int i=0; i<N; i++)
    {
#ifdef QPAS_VARIABLE_T_h
        //------------------------------------
        double T = chol_param.T[i];
        double T2 = T*T/2;
        double h = chol_param.h[i];

        /* Control matrix. */
        double B[3] = {T2*T/3 - h*T, T2, T};

        /* inv(Cp*B). This is a [2 x 2] diagonal matrix (which is invertible if T^3/6-h*T is
         * not equal to zero). The two elements one the main diagonal are equal, and only one of them
         * is stored, which is equal to
            1/(T^3/6 - h*T)
         */
        double iCpB = 1/(B[0]);

        /* inv(Cp*B)*Cp*A. This is a [2 x 6] matrix with the following structure
            iCpB_CpA = [a b c 0 0 0;
                        0 0 0 a b c];

            a = iCpB
            b = iCpB*T
            c = iCpB*T^2/2
         * Only a,b and c are stored.
         */
        double iCpB_CpA[3] = {iCpB, iCpB*T, iCpB*T2};
        //------------------------------------
#endif /*QPAS_VARIABLE_T_h*/

        control[0] = -iCpB_CpA[0]*prev_state[0] - iCpB_CpA[1]*prev_state[1] - iCpB_CpA[2]*prev_state[2] + iCpB*zref_x[i];
        control[1] = -iCpB_CpA[0]*prev_state[3] - iCpB_CpA[1]*prev_state[4] - iCpB_CpA[2]*prev_state[5] + iCpB*zref_y[i];

        cur_state[0] = prev_state[0] + T*prev_state[1] + T2*prev_state[2] + B[0]*control[0];
        cur_state[1] =                   prev_state[1] +  T*prev_state[2] + B[1]*control[0];
        cur_state[2] =                                      prev_state[2] + B[2]*control[0];
        cur_state[3] = prev_state[3] + T*prev_state[4] + T2*prev_state[5] + B[0]*control[1];
        cur_state[4] =                   prev_state[4] +  T*prev_state[5] + B[1]*control[1];
        cur_state[5] =                                      prev_state[5] + B[2]*control[1];

        prev_state = &X[NUM_STATE_VAR*i];
        cur_state = &X[NUM_STATE_VAR*(i+1)];
        control = &control[NUM_CONTROL_VAR];
    }

    // go back to bar states
    cur_state = X;
    for (int i=0; i<N; i++)
    {
        state_handling::tilde_to_bar (cur_state, chol_param.angle_sin[i], chol_param.angle_cos[i]);
        cur_state = &cur_state[NUM_STATE_VAR];
    }
}

/**
 * @brief Forms inv(2*H) * g.
 *
 * @param[in] zref_x reference values of z_x
 * @param[in] zref_y reference values of z_y
 */
void qp_as::form_iHg(double *zref_x, double *zref_y)
{
    double p0, p1;
    double cosA, sinA;

    for (int i = 0; i < N; i++)
    {
        cosA = chol_param.angle_cos[i];
        sinA = chol_param.angle_sin[i];

        // zref
        p0 = zref_x[i];
        p1 = zref_y[i];

        // inv (2*H) * R' * Cp' * zref
        chol_param.iHg[i*NUM_STATE_VAR + 0] =
            -chol_param.i2Q[0] * (cosA*p0 + sinA*p1)*gain_beta;
        chol_param.iHg[i*NUM_STATE_VAR + 3] =
            -chol_param.i2Q[0] * (-sinA*p0 + cosA*p1)*gain_beta;
    }
}

/**
 * @brief Forms the upper and lower bounds.
 *
 * @param[in] lb array of lower bounds for z
 * @param[in] ub array of upper bounds for z
 */
void qp_as::form_bounds(double *lb, double *ub)
{
    for (int i=0; i < N; i++)
    {
        Bounds[i*2].set(NUM_STATE_VAR*i, lb[i*2], ub[i*2], 0);
        Bounds[i*2+1].set(NUM_STATE_VAR*i+3, lb[i*2+1], ub[i*2+1], 0);
    }
}

/**
 * @brief Checks for blocking bounds.
 *
 * @return sequential number of constraint to be added, -1 if no constraints.
 */
int qp_as::check_blocking_bounds()
{
    alpha = 1;

    /* Index to include in the working set, -1 if no constraint have to be included. */
    int activated_var_num = -1;

    for (int i = 0; i < 2*N; i++)
    {
        // Check only inactive constraints for violation.
        // The constraints in the working set will not be violated regardless of
        // the depth of descent
        if (Bounds[i].isActive == 0)
        {
            int ind = Bounds[i].var_num;
#ifdef QPAS_DOWNDATE
            int sign = 1;
#endif
            double t = 1;

            if ( dX[ind] < -tol )
            {
                t = (Bounds[i].lb - X[ind])/dX[ind];
#ifdef QPAS_DOWNDATE
                sign = -1;
#endif
            }
            else if ( dX[ind] > tol )
            {
                t = (Bounds[i].ub - X[ind])/dX[ind];
            }
            else
            {
                // do nothing because dX[Bounds[i].var_num] = 0 (numerically speaking)
                t = 1;
            }

            if (t < alpha)
            {
                alpha = t;
                activated_var_num = i;
#ifdef QPAS_DOWNDATE
                W_sign[nW] = sign;
#endif
            }
        }
    }
    if (activated_var_num != -1)
    {
        W[nW] = activated_var_num;
        nW++;
        Bounds[activated_var_num].isActive = 1;
    }

    return (activated_var_num);
}

#ifdef QPAS_DOWNDATE
/**
 * @brief Selects a constraint for removal from active set.
 *
 * @param[in] lambda vector of Lagrange multipliers corresponding
 *  to inequality constraints.
 *
 * @return index of constraint in the active set, -1 if no constraint
 *  can be removed.
 *
 * @attention If a constraint for removal is selected, then it is
 * removed from the active set (#W) and the number of constraints
 * in active set (#nW) is decremented.
 */
int qp_as::choose_excl_constr (double *lambda)
{
    double min_lambda = -tol;
    int ind_exclude = -1;

    // find the constraint with the smallest lambda
    for (int i = 0; i < nW; i++)
    {
        if (lambda[i] * W_sign[i] < min_lambda)
        {
            min_lambda = lambda[i] * W_sign[i];
            ind_exclude = i;
        }
    }

    if (ind_exclude != -1)
    {
        Bounds[W[ind_exclude]].isActive = 0;
        for (int i = ind_exclude; i < nW-1; i++)
        {
            W[i] = W[i + 1];
            W_sign[i] = W_sign[i + 1];
        }
        nW--;
    }

    return (ind_exclude);
}
#endif /* QPAS_DOWNDATE */

/**
 * @brief Solve QP problem.
 *
 * @return number of activated constraints
 */
int qp_as::solve ()
{
    // obtain dX
    chol.solve(chol_param, X, dX);

    for (;;)
    {
        int activated_var_num = check_blocking_bounds();

        // Move in the feasible descent direction
        for (int i = 0; i < N*NUM_VAR ; i++)
        {
            X[i] += alpha * dX[i];
        }

        // no new inequality constraints
        if (activated_var_num == -1)
        {
#ifdef QPAS_DOWNDATE
            int ind_exclude = choose_excl_constr (chol.get_lambda());
            if (ind_exclude != -1)
            {
                chol.down_resolve (chol_param, nW, W, ind_exclude, X, dX);
            }
            else
            {
                break;
            }
#else
            break;
#endif /*QPAS_DOWNDATE*/
        }
        else
        {
            // add row to the L matrix and find new dX
            chol.up_resolve (chol_param, nW, W, X, dX);
        }
    }

    return (nW);
}
<|endoftext|>


<commit_before>//----------------------------------*-C++-*----------------------------------//
/*!
 * \file   spn_tpetra/Eigenvalue_Solver.cc
 * \author Thomas M. Evans, Steven Hamilton
 * \date   Mon Mar 10 14:20:33 2014
 * \brief  Eigenvalue_Solver member definitions.
 * \note   Copyright (C) 2014 Oak Ridge National Laboratory, UT-Battelle, LLC.
 */
//---------------------------------------------------------------------------//

#include <cmath>
#include <string>

#include "Teuchos_XMLParameterListHelpers.hpp"

#include "harness/DBC.hh"
#include "comm/P_Stream.hh"
#include "comm/global.hh"
#include "utils/String_Functions.hh"
#include "solvers/EigenvalueSolverBuilder.hh"
#include "solvers/PreconditionerBuilder.hh"
#include "solvers/InverseOperator.hh"
#include "Linear_System_FV.hh"
#include "Energy_Multigrid.hh"
#include "Eigenvalue_Solver.hh"

namespace profugus
{
namespace tpetra
{

//---------------------------------------------------------------------------//
// CONSTRUCTOR
//---------------------------------------------------------------------------//
/*!
 * \brief Constructor.
 */
Eigenvalue_Solver::Eigenvalue_Solver(RCP_ParameterList db)
    : Base(db)
    , d_keff(2.0)
{
    Require (!b_db.is_null());

    set_default_parameters();
}

//---------------------------------------------------------------------------//
// PUBLIC INTERFACE
//---------------------------------------------------------------------------//
/*!
 * \brief Setup the solver.
 *
 * Calls to this function builds the linear SPN system.
 */
void Eigenvalue_Solver::setup(RCP_Dimensions  dim,
                              RCP_Mat_DB      mat,
                              RCP_Mesh        mesh,
                              RCP_Indexer     indexer,
                              RCP_Global_Data data)
{
    Require (!b_db.is_null());
    Require (!dim.is_null());
    Require (!mat.is_null());
    Require (!mesh.is_null());
    Require (!indexer.is_null());
    Require (!data.is_null());
    Require (b_db->isSublist("eigenvalue_db"));

    // build the linear system (we only provide finite volume for now)
    std::string &eqn_type = b_db->get("eqn_type", std::string("fv"));

    if (profugus::to_lower(eqn_type) == "fv")
    {
        b_system = Teuchos::rcp(
            new Linear_System_FV(b_db, dim, mat, mesh, indexer, data));
    }
    else
    {
        std::string msg = "Undefined equation type: " + eqn_type;
        throw profugus::assertion(msg);
    }
    Check (!b_system.is_null());

    // build the SPN matrix and build the fission matrix
    b_system->build_Matrix();
    b_system->build_fission_matrix();

    // If we haven't built an eigenvector yet, build one and initialize it
    // If we already have one, copy its data into new vector
    if( d_u.is_null() )
    {
        // make the eigenvector
        d_u = Teuchos::rcp(new Vector_t(Base::b_system->get_Map()));

        // initialize it to 1.0
        d_u->putScalar(1.0);
    }
    else
    {
        // If we already have a vector, we need to temporarily store it
        //  get the new vector, then copy the data from the old vector
        //  into the new one.  We can't just use the old vector because
        //  its internal map was destroyed when the new matrices were built,
        //  which leads to problems when something downstream of here needs
        //  access to the map.
        RCP_Vector tmp_vec = d_u;

        // make the eigenvector
        d_u = Teuchos::rcp(new Vector_t(Base::b_system->get_Map()));

        // Assign data from old vector to new one
        d_u->update(1.0, *tmp_vec, 0.0);
    }

    // the map is a block map where the block size is the number of groups
    //  OR a point map
    Check (b_system->get_Map()->getNodeNumElements() * mat->xs().num_groups()
           == d_u->getLocalLength() ||
           b_system->get_Map()->getNodeNumElements()
           == d_u->getLocalLength() );
    Check (!d_u.is_null());

    // get the eigenvalue solver settings
    RCP_ParameterList edb = Teuchos::sublist(b_db, "eigenvalue_db");

    // The default energy multigrid preconditioner for the Davidson solver
    // fails on one group.  Switch to a different preconditioner
    if ( mat->xs().num_groups() == 1 )
    {
        edb->set("Preconditioner", std::string("Ifpack2"));
    }

    // Build a preconditioenr
    RCP_Tpetra_Op prec = build_preconditioner(dim, mat, mesh, indexer, data);

    // Build the eigensolver
    d_eigensolver = EigenvalueSolverBuilder<MV,OP>::build_solver(
        edb, b_system->get_Operator(), b_system->get_fission_matrix(), prec);

    Ensure (!d_eigensolver.is_null());
}

//---------------------------------------------------------------------------//
/*!
 * \brief Solve the SPN eigenvalue equations.
 */
void Eigenvalue_Solver::solve()
{
    Require (!b_system.is_null());
    Require (!d_u.is_null());
    Require (!d_eigensolver.is_null());

    // solve the problem
    d_eigensolver->solve(d_keff, d_u);

    profugus::pout << profugus::setprecision(10) << profugus::fixed;
    profugus::pout << "k-eff = " << d_keff << profugus::endl;
    profugus::pout << profugus::setprecision(6);
}

//---------------------------------------------------------------------------//
/*!
 * \brief Write scalar flux (eigenvector) into the state.
 */
void Eigenvalue_Solver::write_state(State_t &state)
{
    Require (state.mesh().num_cells() *
             b_system->get_dims()->num_equations() * state.num_groups()
             <= d_u->getLocalLength());

    Base::write_u_into_state(*d_u, state);

    // normalize the eigenvector (over all groups/space)
    double norm[2] = {0.0, 0.0};

    // flux in state at each moment/unknown/cell/energy
    double flux = 0.0;

    // number of groups
    int Ng = state.num_groups();

    // number of cells in this domain
    int Nc = state.mesh().num_cells();

    // loop over groups
    for (int g = 0; g < Ng; ++g)
    {
        // get moments for this group
        View_Field moments = state.flux(g, g);

        // loop over cells on this domain
        for (int cell = 0; cell < Nc; ++cell)
        {
            // get the scalar flux at this point
            flux = moments[cell];

            // add to the normalization factor
            norm[0] += flux * flux;

            // sum the vector to determine the sign of the eigenvector
            norm[1] += flux;
        }
    }

    // do a global reduction on the normalization
    profugus::global_sum(norm, 2);
    Check (norm[0] > 0.0);

    // apply the normalization
    double norm_f = (1.0 / std::sqrt(norm[0])) * (std::fabs(norm[1]) / norm[1]);

    // loop over groups
    for (int g = 0; g < Ng; ++g)
    {
        // get moments for this group
        View_Field moments = state.flux(g, g);

        // loop over cells on this domain
        for (int cell = 0; cell < Nc; ++cell)
        {
            // get the scalar flux at this point
            moments[cell] *= norm_f;
        }
    }
}

//---------------------------------------------------------------------------//
// PRIVATE FUNCTIONS
//---------------------------------------------------------------------------//
/*!
 * \brief Set default db entries for Davidson solver
 */
void Eigenvalue_Solver::set_default_parameters()
{
    // Get eigenvalue db
    RCP_ParameterList eig_db = Teuchos::sublist(
        b_db, std::string("eigenvalue_db"));
    Check (!eig_db.is_null());

    // Look for user specified tolerance in a few places, set a default if we
    // can't find one
    double tol = b_db->get("tolerance", 1.0e-6);
    tol        = eig_db->get("tolerance", tol);
    eig_db->get("Convergence Tolerance", tol);

    // look for user specified iteration limit in a few places, set a default
    // if we can't find one
    int max_itr = b_db->get("max_itr", 500);
    max_itr     = eig_db->get("max_itr", max_itr);
    eig_db->get("Maximum Restarts", max_itr);

    // Forgive the formatting, column limits are a bit of an issue
    // If no parameters are provided, the default solver is a
    //  Davidson solver with a multigrid-in-energy preconditioner which
    //  internally uses an ilu-preconditioned BiCGStab as a smoother
    // The goal here is to support "good" default parameters for a variety
    //  of different solvers and preconditioners so that the user can toggle
    //  between a small number of options without having to set many
    //  parameters.  Advanced users can still specify as much detail
    //  as they want.
    const std::string plrefstr(
        "<ParameterList name='eigenvalue_db'>                               \n\
  <Parameter name='eigensolver' type='string' value='Davidson'/>            \n\
  <Parameter name='Output Level' type='string' value='low'/>                \n\
  <Parameter name='verbosity' type='string' value='Low'/>                   \n\
  <Parameter name='Preconditioner' type='string' value='Ifpack2'/>          \n\
  <ParameterList name='Multigrid Preconditioner'>                           \n\
   <ParameterList name='Smoother'>                                          \n\
    <Parameter name='Preconditioner' type='string' value='Ifpack'/>         \n\
    <Parameter name='verbosity' type='string' value='None'/>                \n\
    <Parameter name='max_itr' type='int' value='3'/>                        \n\
    <Parameter name='solver_type' type='string' value='stratimikos'/>       \n\
   </ParameterList>                                                         \n\
  </ParameterList>                                                          \n\
  <ParameterList name='Anasazi'>                                            \n\
    <Parameter name='Maximum Subspace Dimension' type='int' value='25'/>    \n\
    <Parameter name='Restart Dimension' type='int' value='5'/>              \n\
  </ParameterList>                                                          \n\
  <Parameter name='Ifpack2 Type' type='string' value='ILUT'/>               \n\
  <Parameter name='Ifpack2 Overlap' type='int' value='0'/>                  \n\
  <ParameterList name='Ifpack2 Params'>                                     \n\
    <Parameter name='fact: drop tolerance' type='double' value='1e-2'/>     \n\
    <Parameter name='fact: ilut level-of-fill' type='double' value='1.2'/>  \n\
  </ParameterList>                                                          \n\
  <ParameterList name='operator_db'>                                        \n\
   <Parameter name='verbosity' type='string' value='Low'/>                  \n\
   <Parameter name='solver_type' type='string' value='stratimikos'/>        \n\
  </ParameterList>                                                          \n\
 </ParameterList>                                                           \n"
        );

    // Convert string to a Teuchos PL
    RCP_ParameterList default_pl =
        Teuchos::getParametersFromXmlString(plrefstr);

    // Insert defaults into pl, leaving existing values in tact
    eig_db->setParametersNotAlreadySet(*default_pl);

    // propagate stopping criteria for Arnoldi
    eig_db->sublist("Anasazi").get("Convergence Tolerance", tol);
    eig_db->sublist("Anasazi").get("Maximum Restarts", max_itr);

    // propagate stopping criteria for operators
    eig_db->sublist("operator_db").get("tolerance", 0.1 * tol);
    eig_db->sublist("operator_db").get("max_itr", max_itr);
}

//---------------------------------------------------------------------------//
/*!
 * \brief Build preconditioner
 */
Eigenvalue_Solver::RCP_Tpetra_Op
Eigenvalue_Solver::build_preconditioner(RCP_Dimensions  dim,
                                        RCP_Mat_DB      mat,
                                        RCP_Mesh        mesh,
                                        RCP_Indexer     indexer,
                                        RCP_Global_Data data)
{
    Require (b_db->isSublist("eigenvalue_db"));

    // preconditioner operator
    RCP_Tpetra_Op prec;

    // get the eigenvalue database
    RCP_ParameterList edb = Teuchos::sublist(b_db, "eigenvalue_db");

    // get the preconditioner type
    std::string prec_type = profugus::to_lower(
        edb->get("Preconditioner", std::string("Multigrid")));

    // build the appropriate preconditioners
    if (prec_type=="multigrid" || prec_type=="multilevel")
    {
        RCP_ParameterList prec_db = Teuchos::sublist(
            edb, "Multigrid Preconditioner");

        prec = Teuchos::rcp(
            new Energy_Multigrid(b_db, prec_db, dim, mat, mesh,
                                 indexer, data, b_system));
        Check(prec != Teuchos::null);
    }
    else
    {
        prec = PreconditionerBuilder<OP>::build_preconditioner(
                b_system->get_Operator(),edb );
    }

    return prec;
}

} // end namespace profugus
} // end namespace tpetra

//---------------------------------------------------------------------------//
//                 end of Eigenvalue_Solver.cc
//---------------------------------------------------------------------------//
<commit_msg>Changing invalid default parameter.<commit_after>//----------------------------------*-C++-*----------------------------------//
/*!
 * \file   spn_tpetra/Eigenvalue_Solver.cc
 * \author Thomas M. Evans, Steven Hamilton
 * \date   Mon Mar 10 14:20:33 2014
 * \brief  Eigenvalue_Solver member definitions.
 * \note   Copyright (C) 2014 Oak Ridge National Laboratory, UT-Battelle, LLC.
 */
//---------------------------------------------------------------------------//

#include <cmath>
#include <string>

#include "Teuchos_XMLParameterListHelpers.hpp"

#include "harness/DBC.hh"
#include "comm/P_Stream.hh"
#include "comm/global.hh"
#include "utils/String_Functions.hh"
#include "solvers/EigenvalueSolverBuilder.hh"
#include "solvers/PreconditionerBuilder.hh"
#include "solvers/InverseOperator.hh"
#include "Linear_System_FV.hh"
#include "Energy_Multigrid.hh"
#include "Eigenvalue_Solver.hh"

namespace profugus
{
namespace tpetra
{

//---------------------------------------------------------------------------//
// CONSTRUCTOR
//---------------------------------------------------------------------------//
/*!
 * \brief Constructor.
 */
Eigenvalue_Solver::Eigenvalue_Solver(RCP_ParameterList db)
    : Base(db)
    , d_keff(2.0)
{
    Require (!b_db.is_null());

    set_default_parameters();
}

//---------------------------------------------------------------------------//
// PUBLIC INTERFACE
//---------------------------------------------------------------------------//
/*!
 * \brief Setup the solver.
 *
 * Calls to this function builds the linear SPN system.
 */
void Eigenvalue_Solver::setup(RCP_Dimensions  dim,
                              RCP_Mat_DB      mat,
                              RCP_Mesh        mesh,
                              RCP_Indexer     indexer,
                              RCP_Global_Data data)
{
    Require (!b_db.is_null());
    Require (!dim.is_null());
    Require (!mat.is_null());
    Require (!mesh.is_null());
    Require (!indexer.is_null());
    Require (!data.is_null());
    Require (b_db->isSublist("eigenvalue_db"));

    // build the linear system (we only provide finite volume for now)
    std::string &eqn_type = b_db->get("eqn_type", std::string("fv"));

    if (profugus::to_lower(eqn_type) == "fv")
    {
        b_system = Teuchos::rcp(
            new Linear_System_FV(b_db, dim, mat, mesh, indexer, data));
    }
    else
    {
        std::string msg = "Undefined equation type: " + eqn_type;
        throw profugus::assertion(msg);
    }
    Check (!b_system.is_null());

    // build the SPN matrix and build the fission matrix
    b_system->build_Matrix();
    b_system->build_fission_matrix();

    // If we haven't built an eigenvector yet, build one and initialize it
    // If we already have one, copy its data into new vector
    if( d_u.is_null() )
    {
        // make the eigenvector
        d_u = Teuchos::rcp(new Vector_t(Base::b_system->get_Map()));

        // initialize it to 1.0
        d_u->putScalar(1.0);
    }
    else
    {
        // If we already have a vector, we need to temporarily store it
        //  get the new vector, then copy the data from the old vector
        //  into the new one.  We can't just use the old vector because
        //  its internal map was destroyed when the new matrices were built,
        //  which leads to problems when something downstream of here needs
        //  access to the map.
        RCP_Vector tmp_vec = d_u;

        // make the eigenvector
        d_u = Teuchos::rcp(new Vector_t(Base::b_system->get_Map()));

        // Assign data from old vector to new one
        d_u->update(1.0, *tmp_vec, 0.0);
    }

    // the map is a block map where the block size is the number of groups
    //  OR a point map
    Check (b_system->get_Map()->getNodeNumElements() * mat->xs().num_groups()
           == d_u->getLocalLength() ||
           b_system->get_Map()->getNodeNumElements()
           == d_u->getLocalLength() );
    Check (!d_u.is_null());

    // get the eigenvalue solver settings
    RCP_ParameterList edb = Teuchos::sublist(b_db, "eigenvalue_db");

    // The default energy multigrid preconditioner for the Davidson solver
    // fails on one group.  Switch to a different preconditioner
    if ( mat->xs().num_groups() == 1 )
    {
        edb->set("Preconditioner", std::string("Ifpack2"));
    }

    // Build a preconditioenr
    RCP_Tpetra_Op prec = build_preconditioner(dim, mat, mesh, indexer, data);

    // Build the eigensolver
    d_eigensolver = EigenvalueSolverBuilder<MV,OP>::build_solver(
        edb, b_system->get_Operator(), b_system->get_fission_matrix(), prec);

    Ensure (!d_eigensolver.is_null());
}

//---------------------------------------------------------------------------//
/*!
 * \brief Solve the SPN eigenvalue equations.
 */
void Eigenvalue_Solver::solve()
{
    Require (!b_system.is_null());
    Require (!d_u.is_null());
    Require (!d_eigensolver.is_null());

    // solve the problem
    d_eigensolver->solve(d_keff, d_u);

    profugus::pout << profugus::setprecision(10) << profugus::fixed;
    profugus::pout << "k-eff = " << d_keff << profugus::endl;
    profugus::pout << profugus::setprecision(6);
}

//---------------------------------------------------------------------------//
/*!
 * \brief Write scalar flux (eigenvector) into the state.
 */
void Eigenvalue_Solver::write_state(State_t &state)
{
    Require (state.mesh().num_cells() *
             b_system->get_dims()->num_equations() * state.num_groups()
             <= d_u->getLocalLength());

    Base::write_u_into_state(*d_u, state);

    // normalize the eigenvector (over all groups/space)
    double norm[2] = {0.0, 0.0};

    // flux in state at each moment/unknown/cell/energy
    double flux = 0.0;

    // number of groups
    int Ng = state.num_groups();

    // number of cells in this domain
    int Nc = state.mesh().num_cells();

    // loop over groups
    for (int g = 0; g < Ng; ++g)
    {
        // get moments for this group
        View_Field moments = state.flux(g, g);

        // loop over cells on this domain
        for (int cell = 0; cell < Nc; ++cell)
        {
            // get the scalar flux at this point
            flux = moments[cell];

            // add to the normalization factor
            norm[0] += flux * flux;

            // sum the vector to determine the sign of the eigenvector
            norm[1] += flux;
        }
    }

    // do a global reduction on the normalization
    profugus::global_sum(norm, 2);
    Check (norm[0] > 0.0);

    // apply the normalization
    double norm_f = (1.0 / std::sqrt(norm[0])) * (std::fabs(norm[1]) / norm[1]);

    // loop over groups
    for (int g = 0; g < Ng; ++g)
    {
        // get moments for this group
        View_Field moments = state.flux(g, g);

        // loop over cells on this domain
        for (int cell = 0; cell < Nc; ++cell)
        {
            // get the scalar flux at this point
            moments[cell] *= norm_f;
        }
    }
}

//---------------------------------------------------------------------------//
// PRIVATE FUNCTIONS
//---------------------------------------------------------------------------//
/*!
 * \brief Set default db entries for Davidson solver
 */
void Eigenvalue_Solver::set_default_parameters()
{
    // Get eigenvalue db
    RCP_ParameterList eig_db = Teuchos::sublist(
        b_db, std::string("eigenvalue_db"));
    Check (!eig_db.is_null());

    // Look for user specified tolerance in a few places, set a default if we
    // can't find one
    double tol = b_db->get("tolerance", 1.0e-6);
    tol        = eig_db->get("tolerance", tol);
    eig_db->get("Convergence Tolerance", tol);

    // look for user specified iteration limit in a few places, set a default
    // if we can't find one
    int max_itr = b_db->get("max_itr", 500);
    max_itr     = eig_db->get("max_itr", max_itr);
    eig_db->get("Maximum Restarts", max_itr);

    // Forgive the formatting, column limits are a bit of an issue
    // If no parameters are provided, the default solver is a
    //  Davidson solver with a multigrid-in-energy preconditioner which
    //  internally uses an ilu-preconditioned BiCGStab as a smoother
    // The goal here is to support "good" default parameters for a variety
    //  of different solvers and preconditioners so that the user can toggle
    //  between a small number of options without having to set many
    //  parameters.  Advanced users can still specify as much detail
    //  as they want.
    const std::string plrefstr(
        "<ParameterList name='eigenvalue_db'>                               \n\
  <Parameter name='eigensolver' type='string' value='Davidson'/>            \n\
  <Parameter name='Output Level' type='string' value='low'/>                \n\
  <Parameter name='verbosity' type='string' value='Low'/>                   \n\
  <Parameter name='Preconditioner' type='string' value='Ifpack2'/>          \n\
  <ParameterList name='Multigrid Preconditioner'>                           \n\
   <ParameterList name='Smoother'>                                          \n\
    <Parameter name='Preconditioner' type='string' value='Ifpack2'/>        \n\
    <Parameter name='verbosity' type='string' value='None'/>                \n\
    <Parameter name='max_itr' type='int' value='3'/>                        \n\
    <Parameter name='solver_type' type='string' value='stratimikos'/>       \n\
   </ParameterList>                                                         \n\
  </ParameterList>                                                          \n\
  <ParameterList name='Anasazi'>                                            \n\
    <Parameter name='Maximum Subspace Dimension' type='int' value='25'/>    \n\
    <Parameter name='Restart Dimension' type='int' value='5'/>              \n\
  </ParameterList>                                                          \n\
  <Parameter name='Ifpack2 Type' type='string' value='ILUT'/>               \n\
  <Parameter name='Ifpack2 Overlap' type='int' value='0'/>                  \n\
  <ParameterList name='Ifpack2 Params'>                                     \n\
    <Parameter name='fact: drop tolerance' type='double' value='1e-2'/>     \n\
    <Parameter name='fact: ilut level-of-fill' type='double' value='1.2'/>  \n\
  </ParameterList>                                                          \n\
  <ParameterList name='operator_db'>                                        \n\
   <Parameter name='verbosity' type='string' value='Low'/>                  \n\
   <Parameter name='solver_type' type='string' value='stratimikos'/>        \n\
  </ParameterList>                                                          \n\
 </ParameterList>                                                           \n"
        );

    // Convert string to a Teuchos PL
    RCP_ParameterList default_pl =
        Teuchos::getParametersFromXmlString(plrefstr);

    // Insert defaults into pl, leaving existing values in tact
    eig_db->setParametersNotAlreadySet(*default_pl);

    // propagate stopping criteria for Arnoldi
    eig_db->sublist("Anasazi").get("Convergence Tolerance", tol);
    eig_db->sublist("Anasazi").get("Maximum Restarts", max_itr);

    // propagate stopping criteria for operators
    eig_db->sublist("operator_db").get("tolerance", 0.1 * tol);
    eig_db->sublist("operator_db").get("max_itr", max_itr);
}

//---------------------------------------------------------------------------//
/*!
 * \brief Build preconditioner
 */
Eigenvalue_Solver::RCP_Tpetra_Op
Eigenvalue_Solver::build_preconditioner(RCP_Dimensions  dim,
                                        RCP_Mat_DB      mat,
                                        RCP_Mesh        mesh,
                                        RCP_Indexer     indexer,
                                        RCP_Global_Data data)
{
    Require (b_db->isSublist("eigenvalue_db"));

    // preconditioner operator
    RCP_Tpetra_Op prec;

    // get the eigenvalue database
    RCP_ParameterList edb = Teuchos::sublist(b_db, "eigenvalue_db");

    // get the preconditioner type
    std::string prec_type = profugus::to_lower(
        edb->get("Preconditioner", std::string("Multigrid")));

    // build the appropriate preconditioners
    if (prec_type=="multigrid" || prec_type=="multilevel")
    {
        RCP_ParameterList prec_db = Teuchos::sublist(
            edb, "Multigrid Preconditioner");

        prec = Teuchos::rcp(
            new Energy_Multigrid(b_db, prec_db, dim, mat, mesh,
                                 indexer, data, b_system));
        Check(prec != Teuchos::null);
    }
    else
    {
        prec = PreconditionerBuilder<OP>::build_preconditioner(
                b_system->get_Operator(),edb );
    }

    return prec;
}

} // end namespace profugus
} // end namespace tpetra

//---------------------------------------------------------------------------//
//                 end of Eigenvalue_Solver.cc
//---------------------------------------------------------------------------//
<|endoftext|>


<commit_before>#include "../log.h"
#include "../common.h"
#include "../p6vxcommon.h"
#include "../p6vxapp.h"

#include <QVector>
#include <QImage>
#include <QRgb>
#include <QDir>
#include <QFile>
#include <QDateTime>
#ifdef Q_OS_ANDROID
#include "ekkesShare/shareutils.hpp"
#endif

extern QVector<QRgb> PaletteTable;              // パレットテーブル

////////////////////////////////////////////////////////////////
// Img SAVE from Data
//   情報参照「PNG利用術」 http://gmoon.jp/png/
//			 「プログラミング・ライブラリ」 http://dencha.ojaru.jp/
//
// 引数:	filename		保存ファイル名
//			pixels			保存するデータ領域へのポインタ
//			bpp				色深度
//			ww				幅
//			hh				高さ
//			pos				保存する領域情報へのポインタ
// 返値:	bool	true:成功 false:失敗
////////////////////////////////////////////////////////////////
bool SaveImgData( const P6VPATH& filename, BYTE *pixels, const int bpp, const int ww, const int hh, VRect *pos )
{
	PRINTD( GRP_LOG, "[COMMON][SaveImg] -> %s\n", filename );
	P6VXApp* app = qobject_cast<P6VXApp*>(qApp);

	VRect rec;
	// 領域設定
	if( pos ){
		rec.x = pos->x;	rec.y = pos->y;
		rec.w = pos->w;	rec.h = pos->h;
	}else{
		rec.x =     rec.y = 0;
		rec.w = ww; rec.h = hh;
	}

	QImage image(rec.w, rec.h, QImage::Format_RGB888);
	if(bpp == 8){
		image.setColorTable(app->getPaletteTable());
	}

	memcpy( image.bits(), pixels, image.sizeInBytes());

	auto saveFilePath = QDir::cleanPath(P6VPATH2QSTR(filename));
	auto saveDir = QFileInfo(saveFilePath).absoluteDir();
	// P6VXでは独自にファイル名をつける(filenameは無視する)
	auto dt = QDateTime::currentDateTime();
	auto d = dt.date();
	auto t = dt.time();
	auto saveFileName = QString("P6VX%1%2%3%4%5%6.png")
			.arg(d.year(), 4)
			.arg(d.month(), 2, 10, QLatin1Char('0'))
			.arg(d.day(), 2, 10, QLatin1Char('0'))
			.arg(t.hour(), 2, 10, QLatin1Char('0'))
			.arg(t.minute(), 2, 10, QLatin1Char('0'))
			.arg(t.second(), 2, 10, QLatin1Char('0'));

	auto saveFileFullPath = QDir(saveDir).filePath(saveFileName);
	image.save(saveFileFullPath);

#ifdef Q_OS_ANDROID
	// Androidの場合はインテントで他のアプリに送る
	ShareUtils util;
	int req = 0;
	bool altImpl = false;
	util.sendFile(saveFileFullPath, "Snapshot", "image/png", req, altImpl);
#endif

	return true;
}

////////////////////////////////////////////////////////////////
// Img SAVE
//			 「プログラミング・ライブラリ」 http://dencha.ojaru.jp/
//
// 引数:	filename		保存ファイル名
//			sur				保存するサーフェスへのポインタ
//			pos				保存する領域情報へのポインタ
// 返値:	bool	true:成功 false:失敗
////////////////////////////////////////////////////////////////
bool SaveImg( const P6VPATH& filename, VSurface *sur, VRect *pos )
{
	return SaveImgData( filename, (BYTE *)sur->GetPixels().data(), INBPP, sur->Width(), sur->Height(), pos );
}

////////////////////////////////////////////////////////////////
// Img LOAD
//			 「プログラミング・ライブラリ」 http://dencha.ojaru.jp/
//
// 引数:	filename		読込むファイル名
// 返値:	VSurface *		読込まれたサーフェスへのポインタ
////////////////////////////////////////////////////////////////
VSurface *LoadImg( const P6VPATH& filepath )
{
	PRINTD( GRP_LOG, "[COMMON][LoadImg] <- %s\n", filename );

	// 画像を読み込む
	QImage loadImage(P6VPATH2QSTR(filepath));
	QImage image = loadImage.convertToFormat(QImage::Format_Indexed8);

	// サーフェスを作成
	VSurface* sur = new VSurface;
	sur->InitSurface( image.width(), image.height() );

	// 画像データを取得
	BYTE *doff = (BYTE *)sur->GetPixels().data();
	for( int i=0; i<(int)sur->Height(); i++ ){
		memcpy( doff, image.scanLine(i), sur->Width() * image.depth() / 8 );
		doff += sur->Pitch();
	}

	return sur;
}

////////////////////////////////////////////////////////////////
// 矩形領域合成
//
// 引数:	rr		合成結果を出力する矩形領域へのポインタ
//			r1,r2	合成する矩形領域へのポインタ
// 返値:	なし
////////////////////////////////////////////////////////////////
void RectAdd( VRect *rr, VRect *r1, VRect *r2 )
{
	if( !rr || !r1 || !r2 ) return;

	int x1 = qMax( r1->x, r2->x );
	int y1 = qMax( r1->y, r2->y );
	int x2 = qMin( r1->x + r1->w - 1, r2->x + r2->w - 1);
	int y2 = qMin( r1->y + r1->h - 1, r2->y + r2->h - 1);

	rr->w = x1 > x2 ? 0 : x2 - x1 + 1;
	rr->h = y1 > y2 ? 0 : y2 - y1 + 1;

	rr->x = rr->w ? x1 : 0;
	rr->y = rr->h ? y1 : 0;
}

#include <QString>
#include <QByteArray>
#include <QMutex>
#include <QTemporaryFile>
#include <QFileInfo>
#include <QDateTime>
#include <QDateTime>

void TiltScreen(TiltDirection dir)
{
	P6VXApp* app = qobject_cast<P6VXApp*>(qApp);
	app->setTiltDirection(dir);
}

void UpdateTilt()
{
	P6VXApp* app = qobject_cast<P6VXApp*>(qApp);
	if(!app->isTiltEnabled()) return;

	const int maxStep = 30;
	const int t = app->getTiltStep();
	switch (app->getTiltDirection()){
	case LEFT: // 左
		app->setTiltStep(qMax(-maxStep, t - 1));
		break;
	case RIGHT: // 右
		app->setTiltStep(qMin(maxStep, t + 1));
		break;
	case NEWTRAL:
		app->setTiltStep(t == 0 ? 0 : t > 0 ? t - 1 : t + 1);
	default:;
	}
}
<commit_msg>typoを修正<commit_after>#include "../log.h"
#include "../common.h"
#include "../p6vxcommon.h"
#include "../p6vxapp.h"

#include <QVector>
#include <QImage>
#include <QRgb>
#include <QDir>
#include <QFile>
#include <QDateTime>
#ifdef Q_OS_ANDROID
#include "ekkesShare/shareutils.hpp"
#endif

extern QVector<QRgb> PaletteTable;              // パレットテーブル

////////////////////////////////////////////////////////////////
// Img SAVE from Data
//   情報参照「PNG利用術」 http://gmoon.jp/png/
//			 「プログラミング・ライブラリ」 http://dencha.ojaru.jp/
//
// 引数:	filename		保存ファイル名
//			pixels			保存するデータ領域へのポインタ
//			bpp				色深度
//			ww				幅
//			hh				高さ
//			pos				保存する領域情報へのポインタ
// 返値:	bool	true:成功 false:失敗
////////////////////////////////////////////////////////////////
bool SaveImgData( const P6VPATH& filename, BYTE *pixels, const int bpp, const int ww, const int hh, VRect *pos )
{
	PRINTD( GRP_LOG, "[COMMON][SaveImg] -> %s\n", filename );
	P6VXApp* app = qobject_cast<P6VXApp*>(qApp);

	VRect rec;
	// 領域設定
	if( pos ){
		rec.x = pos->x;	rec.y = pos->y;
		rec.w = pos->w;	rec.h = pos->h;
	}else{
		rec.x =     rec.y = 0;
		rec.w = ww; rec.h = hh;
	}

	QImage image(rec.w, rec.h, QImage::Format_RGB888);
	if(bpp == 8){
		image.setColorTable(app->getPaletteTable());
	}

	memcpy( image.bits(), pixels, image.sizeInBytes());

	auto saveFilePath = QDir::cleanPath(P6VPATH2QSTR(filename));
	auto saveDir = QFileInfo(saveFilePath).absoluteDir();
	// P6VXでは独自にファイル名をつける(filenameは無視する)
	auto dt = QDateTime::currentDateTime();
	auto d = dt.date();
	auto t = dt.time();
	auto saveFileName = QString("P6VX%1%2%3%4%5%6.png")
			.arg(d.year(), 4)
			.arg(d.month(), 2, 10, QLatin1Char('0'))
			.arg(d.day(), 2, 10, QLatin1Char('0'))
			.arg(t.hour(), 2, 10, QLatin1Char('0'))
			.arg(t.minute(), 2, 10, QLatin1Char('0'))
			.arg(t.second(), 2, 10, QLatin1Char('0'));

	auto saveFileFullPath = QDir(saveDir).filePath(saveFileName);
	image.save(saveFileFullPath);

#ifdef Q_OS_ANDROID
	// Androidの場合はインテントで他のアプリに送る
	ShareUtils util;
	int req = 0;
	bool altImpl = false;
	util.sendFile(saveFileFullPath, "Snapshot", "image/png", req, altImpl);
#endif

	return true;
}

////////////////////////////////////////////////////////////////
// Img SAVE
//			 「プログラミング・ライブラリ」 http://dencha.ojaru.jp/
//
// 引数:	filename		保存ファイル名
//			sur				保存するサーフェスへのポインタ
//			pos				保存する領域情報へのポインタ
// 返値:	bool	true:成功 false:失敗
////////////////////////////////////////////////////////////////
bool SaveImg( const P6VPATH& filename, VSurface *sur, VRect *pos )
{
	return SaveImgData( filename, (BYTE *)sur->GetPixels().data(), INBPP, sur->Width(), sur->Height(), pos );
}

////////////////////////////////////////////////////////////////
// Img LOAD
//			 「プログラミング・ライブラリ」 http://dencha.ojaru.jp/
//
// 引数:	filename		読込むファイル名
// 返値:	VSurface *		読込まれたサーフェスへのポインタ
////////////////////////////////////////////////////////////////
VSurface *LoadImg( const P6VPATH& filepath )
{
	PRINTD( GRP_LOG, "[COMMON][LoadImg] <- %s\n", filepath );

	// 画像を読み込む
	QImage loadImage(P6VPATH2QSTR(filepath));
	QImage image = loadImage.convertToFormat(QImage::Format_Indexed8);

	// サーフェスを作成
	VSurface* sur = new VSurface;
	sur->InitSurface( image.width(), image.height() );

	// 画像データを取得
	BYTE *doff = (BYTE *)sur->GetPixels().data();
	for( int i=0; i<(int)sur->Height(); i++ ){
		memcpy( doff, image.scanLine(i), sur->Width() * image.depth() / 8 );
		doff += sur->Pitch();
	}

	return sur;
}

////////////////////////////////////////////////////////////////
// 矩形領域合成
//
// 引数:	rr		合成結果を出力する矩形領域へのポインタ
//			r1,r2	合成する矩形領域へのポインタ
// 返値:	なし
////////////////////////////////////////////////////////////////
void RectAdd( VRect *rr, VRect *r1, VRect *r2 )
{
	if( !rr || !r1 || !r2 ) return;

	int x1 = qMax( r1->x, r2->x );
	int y1 = qMax( r1->y, r2->y );
	int x2 = qMin( r1->x + r1->w - 1, r2->x + r2->w - 1);
	int y2 = qMin( r1->y + r1->h - 1, r2->y + r2->h - 1);

	rr->w = x1 > x2 ? 0 : x2 - x1 + 1;
	rr->h = y1 > y2 ? 0 : y2 - y1 + 1;

	rr->x = rr->w ? x1 : 0;
	rr->y = rr->h ? y1 : 0;
}

#include <QString>
#include <QByteArray>
#include <QMutex>
#include <QTemporaryFile>
#include <QFileInfo>
#include <QDateTime>
#include <QDateTime>

void TiltScreen(TiltDirection dir)
{
	P6VXApp* app = qobject_cast<P6VXApp*>(qApp);
	app->setTiltDirection(dir);
}

void UpdateTilt()
{
	P6VXApp* app = qobject_cast<P6VXApp*>(qApp);
	if(!app->isTiltEnabled()) return;

	const int maxStep = 30;
	const int t = app->getTiltStep();
	switch (app->getTiltDirection()){
	case LEFT: // 左
		app->setTiltStep(qMax(-maxStep, t - 1));
		break;
	case RIGHT: // 右
		app->setTiltStep(qMin(maxStep, t + 1));
		break;
	case NEWTRAL:
		app->setTiltStep(t == 0 ? 0 : t > 0 ? t - 1 : t + 1);
	default:;
	}
}
<|endoftext|>


<commit_before>// An example how to display PS, EPS, PDF files in canvas
//Author: Valeriy Onoutchin

#include "TROOT.h"
#include "TCanvas.h"
#include "TImage.h"

void psview()
{
   // set to batch  mode -> do not display graphics
   gROOT->SetBatch(1);

   // create PostScript file psexam.ps
   gROOT->Macro("psexam.C");

   // back to graphics mode
   gROOT->SetBatch(0);

   // create an image from PS file
   TImage *ps = TImage::Open("psexam.ps");

   if (!ps) {
      printf("GhostScript (gs) program must be installed\n");
      return;
   }

   new TCanvas("psexam", "Example how to display PS file in canvas", 500, 650);
   ps->Draw("xxx");
}
<commit_msg>- This macro generates a PS file and then visualize it in a Canvas. It used    psexam.C to create the PS file. The macro psexam.C is not available anymore.    The PS file is now generated from feynman.C.<commit_after>// An example how to display PS, EPS, PDF files in canvas
//Author: Valeriy Onoutchin

#include "TROOT.h"
#include "TCanvas.h"
#include "TImage.h"

void psview()
{
   // set to batch mode -> do not display graphics
   gROOT->SetBatch(1);

   // create a PostScript file
   gROOT->Macro("feynman.C");
   gPad->Print("feynman.ps");

   // back to graphics mode
   gROOT->SetBatch(0);

   // create an image from PS file
   TImage *ps = TImage::Open("feynman.ps");

   if (!ps) {
      printf("GhostScript (gs) program must be installed\n");
      return;
   }

   new TCanvas("psexam", "Example how to display PS file in canvas", 500, 650);
   ps->Draw("xxx");
}
<|endoftext|>


<commit_before>// formatxx - C++ string formatting library.
//
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non - commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// 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 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.
//
// For more information, please refer to <http://unlicense.org/>
//
// Authors:
//   Sean Middleditch <sean@middleditch.us>

#include "formatxx/format.h"

#include "write_integer.inl"

#include <cstdio>
#include <limits>
#include <climits>

namespace formatxx {

namespace {

// string_view over string literals is safe on all platforms for which I'm aware
constexpr string_view sErrBadFormat{"#BADF", 5};
constexpr string_view sErrIncomplete{"#INCL", 5};
constexpr string_view sErrOutOfRange{"#RNGE", 5};

char const* parse_unsigned(char const* start, char const* end, unsigned& result);
char const* parse_spec(char const* start, char const* end, format_spec& result);

} // anonymous namespace

format_writer& format(format_writer& writer, string_view format)
{
	_detail::format_impl(writer, format, 0, nullptr, nullptr);
	return writer;
}

void format_value(format_writer& out, char ch, format_spec const&)
{
	out.write(string_view(&ch, 1));
}

void format_value(format_writer& out, bool value, format_spec const&)
{
	out.write(value ? "true" : "false");
}

void format_value(format_writer& out, char* ptr, string_view spec)
{
	if (ptr != nullptr)
		format_value(out, static_cast<char const*>(ptr), spec);
	else
		format_value(out, static_cast<void const*>(nullptr), spec);
}

void format_value(format_writer& out, char const* zstr, string_view spec)
{
	if (zstr != nullptr)
		out.write(string_view(zstr));
	else
		format_value(out, static_cast<void const*>(nullptr), spec);
}

void format_value(format_writer& out, string_view str, format_spec const&)
{
	out.write(str);
}

void format_value(format_writer& out, signed int value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, signed char value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, signed long value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, signed short value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, signed long long value, string_view spec) { write_integer(out, value, spec); }

void format_value(format_writer& out, unsigned int value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, unsigned char value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, unsigned long value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, unsigned short value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, unsigned long long value, string_view spec) { write_integer(out, value, spec); }

void format_value(format_writer& out, float value, string_view spec)
{
	format_value(out, static_cast<double>(value), spec);
}

void format_value(format_writer& out, double value, string_view spec_string)
{
	char fmt[3] = "%f";

	format_spec const spec = parse_format_spec(spec_string);

	switch (spec.code)
	{
	case 'a':
	case 'A':
	case 'e':
	case 'E':
	case 'f':
	case 'F':
	case 'g':
	case 'G':
		fmt[1] = spec.code;
		break;
	default:
		// leave default
		break;
	}

	char buf[1048]; // not actually enough for every float, but...
	int len = std::snprintf(buf, sizeof(buf), fmt, value);
	if (len > 0)
		out.write(string_view(buf, len));
}

void format_value(format_writer& out, void* ptr, string_view spec)
{
	write_integer(out, reinterpret_cast<std::uintptr_t>(ptr), spec);
}

void format_value(format_writer& out, void const* ptr, string_view spec)
{
	write_integer(out, reinterpret_cast<std::uintptr_t>(ptr), spec);
}

format_spec parse_format_spec(string_view spec)
{
	format_spec result;
	parse_spec(spec.data(), spec.data() + spec.size(), result);
	return result;
}

namespace _detail {

void format_impl(format_writer& out, string_view format, std::size_t count, FormatterThunk const* funcs, void const** values)
{
	unsigned next_index = 0;

	char const* begin = format.data();
	char const* const end = begin + format.size();
	char const* iter = begin;

	while (iter < end)
	{
		if (*iter == '{')
		{
			// write out the string so far, since we don't write characters immediately
			if (iter > begin)
				out.write(string_view(begin, iter - begin));

			++iter; // swallow the {

			// if we hit the end of the input, we have an incomplete format, and nothing else we can do
			if (iter == end)
			{
				out.write(sErrIncomplete);
				break;
			}

			// if we just have another { then take it as a literal character by starting our next begin here,
			// so it'll get written next time we write out the begin; nothing else to do for formatting here
			if (*iter == '{')
			{
				begin = iter++;
				continue;
			}

			// determine which argument we're going to format
			unsigned index = 0;
			char const* const start = iter;
			char const* iter = parse_unsigned(start, end, index);

			// if we read nothing, we have a "next index" situation (or an error)
			if (iter == start)
				index = next_index;

			// if we hit the end of the string, we have an incomplete format
			if (iter == end)
			{
				out.write(sErrIncomplete);
				break;
			}

			string_view spec;

			// if a : follows the number, we have some formatting controls
			if (*iter == ':')
			{
				++iter; // eat separator
				char const* const spec_begin = iter;

				while (iter < end && *iter != '}')
				{
					++iter;
				}

				if (iter == end)
				{
					// invalid spec
					out.write(sErrBadFormat);
					break;
				}

				spec = string_view(spec_begin, iter);
			}

			// after the index/spec, we expect an end to the format marker
			if (*iter != '}')
			{
				// we have something besides a number, no bueno
				out.write(sErrIncomplete);
				begin = iter; // make sure we're set up for the next begin, which starts at this unknown character
				continue;
			}

			// the iterrent text begin begins with the next character following the format directive's end
			begin = iter = iter + 1;

			// if the index is out of range, we have nothing to format
			if (index >= count)
			{
				out.write(sErrOutOfRange);
				continue;
			}

			// magic!
			funcs[index](out, values[index], spec);

			// if we continue to receive {} then the next index will be the next one after the last one used
			next_index = index + 1;
		}
		else
		{
			++iter;
		}
	}

	// write out tail end of format string
	if (iter > begin)
		out.write(string_view(begin, iter - begin));
}

} // namespace _detail

namespace {

char const* parse_unsigned(char const* start, char const* end, unsigned& result)
{
	result = 0;
	while (start != end && *start >= '0' && *start <= '9')
	{
		result *= 10;
		result += *start - '0';
		++start;
	}
	return start;
}

char const* parse_spec(char const* start, char const* end, formatxx::format_spec& result)
{
	// sign
	if (start != end && *start == '+')
	{
		result.sign = format_spec::sign_always;
		++start;
	}
	else if (start != end && *start == ' ')
	{
		result.sign = format_spec::sign_space;
		++start;
	}
	else if (start != end && *start == '-')
	{
		result.sign = format_spec::sign_default;
		++start;
	}

	// print numeric prefix
	if (start != end && *start == '#')
	{
		result.type_prefix = true;
		++start;
	}

	// generic mode option allowed
	if (start != end && *start != ':' && *start != '}')
	{
		result.code = *start;
		++start;
	}

	// type-specific format allowed
	if (start != end && *start == ':')
	{
		char const* const extra = ++start;
		while (start != end && *start != '}' && *start != '{')
			++start;
		result.extra = formatxx::string_view(extra, start);
	}

	return start;
}

} // anonymous namespace
} // namespace formatxx<commit_msg>Remove parse_spec in favor of just parse_format_spec.<commit_after>// formatxx - C++ string formatting library.
//
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non - commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// 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 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.
//
// For more information, please refer to <http://unlicense.org/>
//
// Authors:
//   Sean Middleditch <sean@middleditch.us>

#include "formatxx/format.h"

#include "write_integer.inl"

#include <cstdio>
#include <limits>
#include <climits>

namespace formatxx {

namespace {

// string_view over string literals is safe on all platforms for which I'm aware
constexpr string_view sErrBadFormat{"#BADF", 5};
constexpr string_view sErrIncomplete{"#INCL", 5};
constexpr string_view sErrOutOfRange{"#RNGE", 5};

char const* parse_unsigned(char const* start, char const* end, unsigned& result);

} // anonymous namespace

format_writer& format(format_writer& writer, string_view format)
{
	_detail::format_impl(writer, format, 0, nullptr, nullptr);
	return writer;
}

void format_value(format_writer& out, char ch, format_spec const&)
{
	out.write(string_view(&ch, 1));
}

void format_value(format_writer& out, bool value, format_spec const&)
{
	out.write(value ? "true" : "false");
}

void format_value(format_writer& out, char* ptr, string_view spec)
{
	if (ptr != nullptr)
		format_value(out, static_cast<char const*>(ptr), spec);
	else
		format_value(out, static_cast<void const*>(nullptr), spec);
}

void format_value(format_writer& out, char const* zstr, string_view spec)
{
	if (zstr != nullptr)
		out.write(string_view(zstr));
	else
		format_value(out, static_cast<void const*>(nullptr), spec);
}

void format_value(format_writer& out, string_view str, format_spec const&)
{
	out.write(str);
}

void format_value(format_writer& out, signed int value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, signed char value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, signed long value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, signed short value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, signed long long value, string_view spec) { write_integer(out, value, spec); }

void format_value(format_writer& out, unsigned int value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, unsigned char value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, unsigned long value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, unsigned short value, string_view spec) { write_integer(out, value, spec); }
void format_value(format_writer& out, unsigned long long value, string_view spec) { write_integer(out, value, spec); }

void format_value(format_writer& out, float value, string_view spec)
{
	format_value(out, static_cast<double>(value), spec);
}

void format_value(format_writer& out, double value, string_view spec_string)
{
	char fmt[3] = "%f";

	format_spec const spec = parse_format_spec(spec_string);

	switch (spec.code)
	{
	case 'a':
	case 'A':
	case 'e':
	case 'E':
	case 'f':
	case 'F':
	case 'g':
	case 'G':
		fmt[1] = spec.code;
		break;
	default:
		// leave default
		break;
	}

	char buf[1048]; // not actually enough for every float, but...
	int len = std::snprintf(buf, sizeof(buf), fmt, value);
	if (len > 0)
		out.write(string_view(buf, len));
}

void format_value(format_writer& out, void* ptr, string_view spec)
{
	write_integer(out, reinterpret_cast<std::uintptr_t>(ptr), spec);
}

void format_value(format_writer& out, void const* ptr, string_view spec)
{
	write_integer(out, reinterpret_cast<std::uintptr_t>(ptr), spec);
}

format_spec parse_format_spec(string_view spec)
{
	format_spec result;

	if (spec.empty())
		return result;

	char const* start = spec.data();
	char const* const end = spec.data() + spec.size();

	// sign
	if (*start == '+')
	{
		result.sign = format_spec::sign_always;
		++start;
	}
	else if (*start == ' ')
	{
		result.sign = format_spec::sign_space;
		++start;
	}
	else if (*start == '-')
	{
		result.sign = format_spec::sign_default;
		++start;
	}

	if (start == end)
		return result;

	// print numeric prefix
	if (*start == '#')
	{
		result.type_prefix = true;

		if (++start == end)
			return result;
	}

	// generic mode option allowed
	if (*start != ':' && *start != '}')
	{
		result.code = *start;

		if (++start == end)
			return result;
	}

	// type-specific format allowed
	if (*start == ':')
	{
		result.extra = string_view(++start, end);
	}

	return result;
}

namespace _detail {

void format_impl(format_writer& out, string_view format, std::size_t count, FormatterThunk const* funcs, void const** values)
{
	unsigned next_index = 0;

	char const* begin = format.data();
	char const* const end = begin + format.size();
	char const* iter = begin;

	while (iter < end)
	{
		if (*iter == '{')
		{
			// write out the string so far, since we don't write characters immediately
			if (iter > begin)
				out.write(string_view(begin, iter - begin));

			++iter; // swallow the {

			// if we hit the end of the input, we have an incomplete format, and nothing else we can do
			if (iter == end)
			{
				out.write(sErrIncomplete);
				break;
			}

			// if we just have another { then take it as a literal character by starting our next begin here,
			// so it'll get written next time we write out the begin; nothing else to do for formatting here
			if (*iter == '{')
			{
				begin = iter++;
				continue;
			}

			// determine which argument we're going to format
			unsigned index = 0;
			char const* const start = iter;
			char const* iter = parse_unsigned(start, end, index);

			// if we read nothing, we have a "next index" situation (or an error)
			if (iter == start)
				index = next_index;

			// if we hit the end of the string, we have an incomplete format
			if (iter == end)
			{
				out.write(sErrIncomplete);
				break;
			}

			string_view spec;

			// if a : follows the number, we have some formatting controls
			if (*iter == ':')
			{
				++iter; // eat separator
				char const* const spec_begin = iter;

				while (iter < end && *iter != '}')
				{
					++iter;
				}

				if (iter == end)
				{
					// invalid spec
					out.write(sErrBadFormat);
					break;
				}

				spec = string_view(spec_begin, iter);
			}

			// after the index/spec, we expect an end to the format marker
			if (*iter != '}')
			{
				// we have something besides a number, no bueno
				out.write(sErrIncomplete);
				begin = iter; // make sure we're set up for the next begin, which starts at this unknown character
				continue;
			}

			// the iterrent text begin begins with the next character following the format directive's end
			begin = iter = iter + 1;

			// if the index is out of range, we have nothing to format
			if (index >= count)
			{
				out.write(sErrOutOfRange);
				continue;
			}

			// magic!
			funcs[index](out, values[index], spec);

			// if we continue to receive {} then the next index will be the next one after the last one used
			next_index = index + 1;
		}
		else
		{
			++iter;
		}
	}

	// write out tail end of format string
	if (iter > begin)
		out.write(string_view(begin, iter - begin));
}

} // namespace _detail

namespace {

char const* parse_unsigned(char const* start, char const* end, unsigned& result)
{
	result = 0;
	while (start != end && *start >= '0' && *start <= '9')
	{
		result *= 10;
		result += *start - '0';
		++start;
	}
	return start;
}

} // anonymous namespace
} // namespace formatxx<|endoftext|>


<commit_before><commit_msg>apply consistent colorspace to cubemaps<commit_after><|endoftext|>


<commit_before>/*****************************************************************************/
/**
 *  @file   main.cpp
 *  @brief  Hydrogen volume data generator.
 *  @author Naohisa Sakamoto
 *
 *  Compile:\
 *  \code
 *  % kvsmake -G
 *  % kvsmake
 *  \endcode
 *
 *  Usage:\n
 *  \code
 *  % ./Hydrogen [-h|--help] <Output filename>
 *  \endcode
 */
/*----------------------------------------------------------------------------
 *
 *  Copyright (c) Visualization Laboratory, Kyoto University.
 *  All rights reserved.
 *  See http://www.viz.media.kyoto-u.ac.jp/kvs/copyright/ for details.
 *
 *  $Id: main.cpp 1403 2012-12-07 07:35:18Z naohisa.sakamoto@gmail.com $
 */
/*****************************************************************************/
#include "Argument.h"
#include "Hydrogen.h"
#include <string>
#include <iostream>
#include <kvs/Type>
#include <kvs/File>
#include <kvs/Vector3>
#include <kvs/Message>
#include <kvs/StructuredVolumeObject>
#include <kvs/StructuredVolumeExporter>
#include <kvs/AVSField>
#include <kvs/KVSMLObjectStructuredVolume>

/*===========================================================================*/
/**
 *  @brief  Main function
 *  @param  argc [in] argument count
 *  @param  argv [in] argument values
 */
/*===========================================================================*/
int main( int argc, char** argv )
{
    Argument arg( argc, argv );
    if ( !arg.parse() ) exit( EXIT_FAILURE );

    // Volume resolution.
    kvs::Vector3ui resolution( 64, 64, 64 );
    if ( arg.hasOption("r") )
    {
        const kvs::UInt32 rx = arg.optionValue<kvs::UInt32>("r",0);
        const kvs::UInt32 ry = arg.optionValue<kvs::UInt32>("r",1);
        const kvs::UInt32 rz = arg.optionValue<kvs::UInt32>("r",2);
        resolution = kvs::Vector3ui( rx, ry, rz );
    }

    // Output filename.
    std::string filename("hydrogen.kvsml");
    if ( arg.hasValues() )
    {
        filename = arg.value<std::string>();
    }

    // Generate hydrogen volume.
    kvs::StructuredVolumeObject* volume = new Hydrogen( resolution );
    if ( !volume )
    {
        kvsMessageError( "Cannot create a hydrogen volume." );
        return( false );
    }

    if ( arg.hasOption("verbose") )
    {
        std::cout << "> Structured volume object" << std::endl;
        volume->print( std::cout );
    }

    // Output the hydrogen volume to the file.
    const kvs::File file( filename );
    const std::string extension( file.extension() );
    if ( extension == "fld" )
    {
        kvs::AVSField* field = new kvs::StructuredVolumeExporter<kvs::AVSField>( volume );
        if ( !field )
        {
            kvsMessageError( "Cannot export hydrogen volume." );
            delete volume;
            return( false );
        }

        if ( !field->write( filename ) )
        {
            kvsMessageError( "Cannot write to the file as AVS field format." );
            delete volume;
            return( false );
        }

        if ( arg.hasOption("verbose") )
        {
            std::cout << "AVS field data format" << std::endl;
            field->print( std::cout );
        }

        delete field;
    }
    else if ( extension == "kvsml" )
    {
        kvs::KVSMLObjectStructuredVolume* kvsml =
            new kvs::StructuredVolumeExporter<kvs::KVSMLObjectStructuredVolume>( volume );
        if ( !kvsml )
        {
            kvsMessageError( "Cannot export hydrogen volume." );
            delete volume;
            return( false );
        }

        if ( arg.hasOption("a") )
        {
            kvsml->setWritingDataType( kvs::KVSMLObjectStructuredVolume::ExternalAscii );
        }

        if ( arg.hasOption("b") )
        {
            kvsml->setWritingDataType( kvs::KVSMLObjectStructuredVolume::ExternalBinary );
        }

        if ( !kvsml->write( filename ) )
        {
            kvsMessageError( "Cannot write to the file as KVSML format." );
            delete volume;
            return( false );
        }

        if ( arg.hasOption("verbose") )
        {
            std::cout << "KVS XML data format" << std::endl;
            kvsml->print( std::cout );
        }

        delete kvsml;
    }

    std::cout << "Output >> " << filename << std::endl;

    delete volume;

    return( 0 );
}
<commit_msg>Modified.<commit_after>/*****************************************************************************/
/**
 *  @file   main.cpp
 *  @brief  Hydrogen volume data generator.
 *  @author Naohisa Sakamoto
 *
 *  Compile:\
 *  \code
 *  % kvsmake -G
 *  % kvsmake
 *  \endcode
 *
 *  Usage:\n
 *  \code
 *  % ./Hydrogen [-h|--help] <Output filename>
 *  \endcode
 */
/*----------------------------------------------------------------------------
 *
 *  Copyright (c) Visualization Laboratory, Kyoto University.
 *  All rights reserved.
 *  See http://www.viz.media.kyoto-u.ac.jp/kvs/copyright/ for details.
 *
 *  $Id: main.cpp 1403 2012-12-07 07:35:18Z naohisa.sakamoto@gmail.com $
 */
/*****************************************************************************/
#include "Argument.h"
#include "Hydrogen.h"
#include <string>
#include <iostream>
#include <kvs/Type>
#include <kvs/File>
#include <kvs/Vector3>
#include <kvs/Message>
#include <kvs/StructuredVolumeObject>
#include <kvs/StructuredVolumeExporter>
#include <kvs/AVSField>
#include <kvs/KVSMLStructuredVolumeObject>

/*===========================================================================*/
/**
 *  @brief  Main function
 *  @param  argc [in] argument count
 *  @param  argv [in] argument values
 */
/*===========================================================================*/
int main( int argc, char** argv )
{
    Argument arg( argc, argv );
    if ( !arg.parse() ) exit( EXIT_FAILURE );

    // Volume resolution.
    kvs::Vector3ui resolution( 64, 64, 64 );
    if ( arg.hasOption("r") )
    {
        const kvs::UInt32 rx = arg.optionValue<kvs::UInt32>("r",0);
        const kvs::UInt32 ry = arg.optionValue<kvs::UInt32>("r",1);
        const kvs::UInt32 rz = arg.optionValue<kvs::UInt32>("r",2);
        resolution = kvs::Vector3ui( rx, ry, rz );
    }

    // Output filename.
    std::string filename("hydrogen.kvsml");
    if ( arg.hasValues() )
    {
        filename = arg.value<std::string>();
    }

    // Generate hydrogen volume.
    kvs::StructuredVolumeObject* volume = new Hydrogen( resolution );
    if ( !volume )
    {
        kvsMessageError( "Cannot create a hydrogen volume." );
        return( false );
    }

    if ( arg.hasOption("verbose") )
    {
        std::cout << "> Structured volume object" << std::endl;
        volume->print( std::cout );
    }

    // Output the hydrogen volume to the file.
    const kvs::File file( filename );
    const std::string extension( file.extension() );
    if ( extension == "fld" )
    {
        kvs::AVSField* field = new kvs::StructuredVolumeExporter<kvs::AVSField>( volume );
        if ( !field )
        {
            kvsMessageError( "Cannot export hydrogen volume." );
            delete volume;
            return( false );
        }

        if ( !field->write( filename ) )
        {
            kvsMessageError( "Cannot write to the file as AVS field format." );
            delete volume;
            return( false );
        }

        if ( arg.hasOption("verbose") )
        {
            std::cout << "AVS field data format" << std::endl;
            field->print( std::cout );
        }

        delete field;
    }
    else if ( extension == "kvsml" )
    {
        kvs::KVSMLStructuredVolumeObject* kvsml =
            new kvs::StructuredVolumeExporter<kvs::KVSMLStructuredVolumeObject>( volume );
        if ( !kvsml )
        {
            kvsMessageError( "Cannot export hydrogen volume." );
            delete volume;
            return( false );
        }

        if ( arg.hasOption("a") )
        {
            kvsml->setWritingDataType( kvs::KVSMLStructuredVolumeObject::ExternalAscii );
        }

        if ( arg.hasOption("b") )
        {
            kvsml->setWritingDataType( kvs::KVSMLStructuredVolumeObject::ExternalBinary );
        }

        if ( !kvsml->write( filename ) )
        {
            kvsMessageError( "Cannot write to the file as KVSML format." );
            delete volume;
            return( false );
        }

        if ( arg.hasOption("verbose") )
        {
            std::cout << "KVS XML data format" << std::endl;
            kvsml->print( std::cout );
        }

        delete kvsml;
    }

    std::cout << "Output >> " << filename << std::endl;

    delete volume;

    return( 0 );
}
<|endoftext|>


<commit_before>
#include <QApplication>
#include <QPainter>
#include <QGraphicsView>
#include <QResizeEvent>
#include <QCheckBox>
#include <QStyle>
#include <QGraphicsPixmapItem>
#include <QGraphicsProxyWidget>
#include <QDialog>
#include <QVBoxLayout>

#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkConeSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"

#include "QVTKWidget.h"

class MyQGraphicsView : public QGraphicsView
{
public:
  MyQGraphicsView()
  {
  mWidget = new QVTKWidget();
  this->setViewport(mWidget);
  this->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
  this->setCacheMode(CacheNone);

  vtkRenderWindow* renWin = vtkRenderWindow::New();
  mWidget->SetRenderWindow(renWin);
  renWin->Delete();
  }

  QVTKWidget* qvtkWidget() { return mWidget; }

protected:
  void resizeEvent(QResizeEvent* e)
    {
    if(this->scene())
      {
      this->scene()->setSceneRect(QRect(QPoint(0,0), e->size()));
      }
    QGraphicsView::resizeEvent(e);
    }

  void paintEvent(QPaintEvent* e)
    {
    this->mWidget->GetRenderWindow()->SetSwapBuffers(0);
    QGraphicsView::paintEvent(e);
    this->mWidget->GetRenderWindow()->SetSwapBuffers(1);
    this->mWidget->GetRenderWindow()->Frame();
    }

  void drawBackground(QPainter*, const QRectF& r)
    {
    mWidget->GetRenderWindow()->Render();
    }
  QVTKWidget* mWidget;

};

class MyScene : public QGraphicsScene
{
public:
  MyScene(QObject* p = NULL) : QGraphicsScene(p)
  {
  QPixmap pix = qApp->style()->standardPixmap(QStyle::SP_ComputerIcon);
  QGraphicsItem* item = this->addPixmap(pix);
  item->setFlag(QGraphicsItem::ItemIsMovable, true);
  item->setPos(10,10);

  QDialog* d = new QDialog(0, Qt::CustomizeWindowHint | Qt::WindowTitleHint);
  d->setWindowOpacity(0.8);
  d->setWindowTitle("My Title");
  d->setLayout(new QVBoxLayout);
  d->layout()->addWidget(new QCheckBox("check me"));

  item = this->addWidget(d);
  item->setFlag(QGraphicsItem::ItemIsMovable, true);
  item->setPos(100,100);
  }
protected:
};

int main(int argc, char** argv)
{
  QApplication app(argc, argv);

  MyQGraphicsView view;
  view.resize(256,256);
  MyScene scene;
  view.setScene(&scene);

  QVTKWidget* qvtkwidget = view.qvtkWidget();
  vtkRenderWindow* renWin = qvtkwidget->GetRenderWindow();
  vtkRenderer *ren = vtkRenderer::New();
  renWin->AddRenderer(ren);
  ren->SetBackground( 0, 1, 1 );

  vtkConeSource *cone = vtkConeSource::New();
  cone->SetHeight( 0.5 );
  cone->SetRadius( 0.2 );
  cone->SetResolution( 20 );

  vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New();
  coneMapper->SetInputConnection( cone->GetOutputPort() );

  vtkActor *coneActor = vtkActor::New();
  coneActor->SetMapper( coneMapper );
  ren->AddActor( coneActor );

  view.show();

  app.exec();

  ren->Delete();
  cone->Delete();
  coneMapper->Delete();
  coneActor->Delete();

  return 0;
}

<commit_msg>COMP:Fixed warning.<commit_after>
#include <QApplication>
#include <QPainter>
#include <QGraphicsView>
#include <QResizeEvent>
#include <QCheckBox>
#include <QStyle>
#include <QGraphicsPixmapItem>
#include <QGraphicsProxyWidget>
#include <QDialog>
#include <QVBoxLayout>

#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkConeSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"

#include "QVTKWidget.h"

class MyQGraphicsView : public QGraphicsView
{
public:
  MyQGraphicsView()
  {
  mWidget = new QVTKWidget();
  this->setViewport(mWidget);
  this->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
  this->setCacheMode(CacheNone);

  vtkRenderWindow* renWin = vtkRenderWindow::New();
  mWidget->SetRenderWindow(renWin);
  renWin->Delete();
  }

  QVTKWidget* qvtkWidget() { return mWidget; }

protected:
  void resizeEvent(QResizeEvent* e)
    {
    if(this->scene())
      {
      this->scene()->setSceneRect(QRect(QPoint(0,0), e->size()));
      }
    QGraphicsView::resizeEvent(e);
    }

  void paintEvent(QPaintEvent* e)
    {
    this->mWidget->GetRenderWindow()->SetSwapBuffers(0);
    QGraphicsView::paintEvent(e);
    this->mWidget->GetRenderWindow()->SetSwapBuffers(1);
    this->mWidget->GetRenderWindow()->Frame();
    }

  void drawBackground(QPainter*, const QRectF& vtkNotUsed(r))
    {
    mWidget->GetRenderWindow()->Render();
    }
  QVTKWidget* mWidget;

};

class MyScene : public QGraphicsScene
{
public:
  MyScene(QObject* p = NULL) : QGraphicsScene(p)
  {
  QPixmap pix = qApp->style()->standardPixmap(QStyle::SP_ComputerIcon);
  QGraphicsItem* item = this->addPixmap(pix);
  item->setFlag(QGraphicsItem::ItemIsMovable, true);
  item->setPos(10,10);

  QDialog* d = new QDialog(0, Qt::CustomizeWindowHint | Qt::WindowTitleHint);
  d->setWindowOpacity(0.8);
  d->setWindowTitle("My Title");
  d->setLayout(new QVBoxLayout);
  d->layout()->addWidget(new QCheckBox("check me"));

  item = this->addWidget(d);
  item->setFlag(QGraphicsItem::ItemIsMovable, true);
  item->setPos(100,100);
  }
protected:
};

int main(int argc, char** argv)
{
  QApplication app(argc, argv);

  MyQGraphicsView view;
  view.resize(256,256);
  MyScene scene;
  view.setScene(&scene);

  QVTKWidget* qvtkwidget = view.qvtkWidget();
  vtkRenderWindow* renWin = qvtkwidget->GetRenderWindow();
  vtkRenderer *ren = vtkRenderer::New();
  renWin->AddRenderer(ren);
  ren->SetBackground( 0, 1, 1 );

  vtkConeSource *cone = vtkConeSource::New();
  cone->SetHeight( 0.5 );
  cone->SetRadius( 0.2 );
  cone->SetResolution( 20 );

  vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New();
  coneMapper->SetInputConnection( cone->GetOutputPort() );

  vtkActor *coneActor = vtkActor::New();
  coneActor->SetMapper( coneMapper );
  ren->AddActor( coneActor );

  view.show();

  app.exec();

  ren->Delete();
  cone->Delete();
  coneMapper->Delete();
  coneActor->Delete();

  return 0;
}

<|endoftext|>