/*

Copyright (c) 2005-2016, University of Oxford.
All rights reserved.

University of Oxford means the Chancellor, Masters and Scholars of the
University of Oxford, having an administrative office at Wellington
Square, Oxford OX1 2JD, UK.

This file is part of Chaste.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
 * Neither the name of the University of Oxford nor the names of its
   contributors may be used to endorse or promote products derived from this
   software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TESTGOLDBETER1991ODESYSTEM_HPP_
#define TESTGOLDBETER1991ODESYSTEM_HPP_

#include <cxxtest/TestSuite.h>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <ctime>
#include <vector>
#include <iostream>

#include "OutputFileHandler.hpp"
#include "Goldbeter1991OdeSystem.hpp"
#include "RungeKutta4IvpOdeSolver.hpp"
#include "EulerIvpOdeSolver.hpp"

//#include "RungeKutta4IvpOdeSolver.hpp"
//#include "RungeKuttaFehlbergIvpOdeSolver.hpp"
//#include "BackwardEulerIvpOdeSolver.hpp"
#include "CvodeAdaptor.hpp"

//This test is always run sequentially (never in parallel)
#include "FakePetscSetup.hpp"

/*
 * Basic tests only - no archiving test
 *
 */

class TestGoldbeter1991OdeSystem : public CxxTest::TestSuite
{
public:

    void TestGoldbeter1991Equation()
    {
        Goldbeter1991OdeSystem ode_system;

        double time = 0.0;
        std::vector<double> initial_conditions;
        initial_conditions.push_back(0.01);
        initial_conditions.push_back(0.01);
        initial_conditions.push_back(0.01);

        std::vector<double> derivs(initial_conditions.size());
        ode_system.EvaluateYDerivatives(time, initial_conditions, derivs);

        // Test derivatives are correct
        TS_ASSERT_DELTA(derivs[0], 0.0240, 1e-4);
        TS_ASSERT_DELTA(derivs[1], -0.9414, 1e-4);
        TS_ASSERT_DELTA(derivs[2], -0.3233, 1e-4);
    }

    void TestGoldbeter1991OSolver() throw(Exception)
    {
        Goldbeter1991OdeSystem ode_system;

        RungeKutta4IvpOdeSolver ode_solver;

        OdeSolution solutions;

        std::vector<double> initial_conditions = ode_system.GetInitialConditions();
        double start_time = 0.0;
        double end_time = 100.0;
        double h_value = 0.01; // 1.0 // maximum tolerance

        //Test the hard coded ics
        TS_ASSERT_DELTA(initial_conditions[0], 0.01, 1e-6);
        TS_ASSERT_DELTA(initial_conditions[1], 0.01, 1e-6);
        TS_ASSERT_DELTA(initial_conditions[2], 0.01, 1e-6);

        double cpu_start_time = (double) std::clock();
        solutions = ode_solver.Solve(&ode_system, initial_conditions, start_time, end_time, h_value, h_value);
        double cpu_end_time = (double) std::clock();
        double cpu_elapsed_time = (cpu_end_time - cpu_start_time)/(CLOCKS_PER_SEC);
        std::cout <<  "1. Solver Elapsed time = " << cpu_elapsed_time << "\n";

        // Test solutions are OK for a small time increase...
        int end = solutions.rGetSolutions().size() - 1;
        // Tests the simulation is ending at the right time...(going into S phase at 7.8 hours)
        TS_ASSERT_DELTA(solutions.rGetTimes()[end], end_time, 1e-2);
        //std::cout <<  "End time = " << solutions.rGetTimes()[end] << "\n";
        // Decent results - checked with numpy # [ 0.54706214  0.29369527  0.00678837]
        TS_ASSERT_DELTA(solutions.rGetSolutions()[end][0], 0.5470, 1e-4);
        TS_ASSERT_DELTA(solutions.rGetSolutions()[end][1], 0.2936, 1e-4);
        TS_ASSERT_DELTA(solutions.rGetSolutions()[end][2], 0.0067, 1e-4);
    }

    void TestArchiving()
    {
        OutputFileHandler handler("archive", false);
        std::string archive_filename = handler.GetOutputDirectoryFullPath() + "gb1991_ode.arch";

        {

            std::vector<double> state_variables;
            state_variables.push_back(3.0);
            state_variables.push_back(4.0);
            state_variables.push_back(5.0);

            Goldbeter1991OdeSystem ode_system(state_variables);

            ode_system.SetDefaultInitialCondition(2, 3.25);

            std::vector<double> initial_conditions = ode_system.GetInitialConditions();
            TS_ASSERT_EQUALS(initial_conditions.size(), 3u);
            TS_ASSERT_DELTA(initial_conditions[0], 0.01, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[1], 0.01, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[2], 3.2500, 1e-4);

            double var1 = ode_system.GetStateVariable(0);
            double var2 = ode_system.GetStateVariable(1);
            double var3 = ode_system.GetStateVariable(2);

            TS_ASSERT_DELTA(var1, 3.0, 1e-3);
            TS_ASSERT_DELTA(var2, 4.0, 1e-3);
            TS_ASSERT_DELTA(var3, 5.0, 1e-3);

            // Create an output archive
            std::ofstream ofs(archive_filename.c_str());
            boost::archive::text_oarchive output_arch(ofs);

            // Archive ODE system
            AbstractOdeSystem* const p_const_ode_system = &ode_system;
            output_arch << p_const_ode_system;
        }

        {
            AbstractOdeSystem* p_ode_system;

            // Create an input archive
            std::ifstream ifs(archive_filename.c_str(), std::ios::binary);
            boost::archive::text_iarchive input_arch(ifs);

            // Restore from the archive
            input_arch >> p_ode_system;

            // Check that archiving worked correctly
            std::vector<double> initial_conditions = p_ode_system->GetInitialConditions();
            TS_ASSERT_EQUALS(initial_conditions.size(), 3u);
            TS_ASSERT_DELTA(initial_conditions[0], 0.01, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[1], 0.01, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[2], 0.01, 1e-4);

            double var1 = p_ode_system->GetStateVariable(0);
            double var2 = p_ode_system->GetStateVariable(1);
            double var3 = p_ode_system->GetStateVariable(2);

            TS_ASSERT_DELTA(var1, 3.0, 1e-3);
            TS_ASSERT_DELTA(var2, 4.0, 1e-3);
            TS_ASSERT_DELTA(var3, 5.0, 1e-3);

            // Tidy up
            delete p_ode_system;
        }
    }
};

#endif /* TESTGOLDBETER1991ODESYSTEM_HPP_ */


/*

Copyright (c) 2005-2016, University of Oxford.
All rights reserved.

University of Oxford means the Chancellor, Masters and Scholars of the
University of Oxford, having an administrative office at Wellington
Square, Oxford OX1 2JD, UK.

This file is part of Chaste.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
 * Neither the name of the University of Oxford nor the names of its
   contributors may be used to endorse or promote products derived from this
   software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TESTTYSONNOVAK2001ODESYSTEM_HPP_
#define TESTTYSONNOVAK2001ODESYSTEM_HPP_

#include <cxxtest/TestSuite.h>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <vector>
#include <iostream>

#include "TysonNovak2001OdeSystem.hpp"
#include "BackwardEulerIvpOdeSolver.hpp"
#include "EulerIvpOdeSolver.hpp"
#include "RungeKutta4IvpOdeSolver.hpp"
#include "ColumnDataWriter.hpp"
#include "Timer.hpp"

#include "PetscTools.hpp"
#include "PetscSetupAndFinalize.hpp"

class TestTysonNovak2001OdeSystem : public CxxTest::TestSuite
{
public:

    void TestTysonNovakEquation()
    {
        TysonNovak2001OdeSystem tyson_novak_system;

        double time = 0.0;
        std::vector<double> initial_conditions;
        initial_conditions.push_back(0.6);
        initial_conditions.push_back(0.1);
        initial_conditions.push_back(1.5);
        initial_conditions.push_back(0.6);
        initial_conditions.push_back(0.6);
        initial_conditions.push_back(0.85);

        std::vector<double> derivs(initial_conditions.size());
        tyson_novak_system.EvaluateYDerivatives(time, initial_conditions, derivs);

        // Test derivatives are correct
        // Divided by 60 to change to hours
        TS_ASSERT_DELTA(derivs[0], -4.400000000000000e-02*60.0, 1e-5);
        TS_ASSERT_DELTA(derivs[1], -6.047872340425530e+00*60.0, 1e-5);
        TS_ASSERT_DELTA(derivs[2], 3.361442884485838e-02*60.0, 1e-5);
        TS_ASSERT_DELTA(derivs[3], 4.016602000735009e-02*60.0, 1e-5);
        TS_ASSERT_DELTA(derivs[4], 8.400000000000001e-03*60.0, 1e-5);
        TS_ASSERT_DELTA(derivs[5], 7.777500000000001e-03*60.0, 1e-5);
    }

    void TestTysonNovakSolver() throw(Exception)
    {
        TysonNovak2001OdeSystem tyson_novak_system;

        // Solve system using backward Euler solver

        // Matlab's strictest bit uses 0.01 below and relaxes it on flatter bits

        double dt = 0.1/60.0;

        //Euler solver solution worked out
        BackwardEulerIvpOdeSolver backward_euler_solver(6);

        std::vector<double> state_variables = tyson_novak_system.GetInitialConditions();

        Timer::Reset();
        OdeSolution solutions = backward_euler_solver.Solve(&tyson_novak_system, state_variables, 0.0, 75.8350/60.0, dt, dt);
        Timer::Print("1. Tyson Novak Backward Euler");

        // If you run it up to about 75min the ODE will stop, anything less and it will not and this test will fail
        TS_ASSERT_EQUALS(backward_euler_solver.StoppingEventOccurred(), true);

        unsigned end = solutions.rGetSolutions().size() - 1;

        // The following code provides nice output for gnuplot
        // use the command
        // plot "tyson_novak.dat" u 1:2
        // or
        // plot "tyson_novak.dat" u 1:3 etc. for the various proteins...

//        OutputFileHandler handler("");
//        out_stream file=handler.OpenOutputFile("tyson_novak.dat");
//        for (unsigned i=0; i<=end; i++)
//        {
//            (*file) << solutions.rGetTimes()[i]<< "\t" << solutions.rGetSolutions()[i][0] << "\t" << solutions.rGetSolutions()[i][1] << "\t" << solutions.rGetSolutions()[i][2] << "\t" << solutions.rGetSolutions()[i][3] << "\t" << solutions.rGetSolutions()[i][4] << "\t" << solutions.rGetSolutions()[i][5] << "\n" << std::flush;
//        }
//        file->close();

        ColumnDataWriter writer("TysonNovak", "TysonNovak");
        if (PetscTools::AmMaster()) // if master process
        {
            int step_per_row = 1;
            int time_var_id = writer.DefineUnlimitedDimension("Time", "s");

            std::vector<int> var_ids;
            for (unsigned i=0; i<tyson_novak_system.rGetStateVariableNames().size(); i++)
            {
                var_ids.push_back(writer.DefineVariable(tyson_novak_system.rGetStateVariableNames()[i],
                                                        tyson_novak_system.rGetStateVariableUnits()[i]));
            }
            writer.EndDefineMode();

            for (unsigned i = 0; i < solutions.rGetSolutions().size(); i+=step_per_row)
            {
                writer.PutVariable(time_var_id, solutions.rGetTimes()[i]);
                for (unsigned j=0; j<var_ids.size(); j++)
                {
                    writer.PutVariable(var_ids[j], solutions.rGetSolutions()[i][j]);
                }
                writer.AdvanceAlongUnlimitedDimension();
            }
            writer.Close();
        }
        PetscTools::Barrier();

        // Proper values calculated using the Matlab stiff ODE solver ode15s. Note that
        // large tolerances are required for the tests to pass with both chaste solvers
        // and CVODE.
        TS_ASSERT_DELTA(solutions.rGetSolutions()[end][0],0.10000000000000, 1e-2);
        TS_ASSERT_DELTA(solutions.rGetSolutions()[end][1],0.98913684535843, 1e-2);
        TS_ASSERT_DELTA(solutions.rGetSolutions()[end][2],1.54216806705641, 1e-1);
        TS_ASSERT_DELTA(solutions.rGetSolutions()[end][3],1.40562614481544, 1e-1);
        TS_ASSERT_DELTA(solutions.rGetSolutions()[end][4],0.67083371879876, 1e-2);
        TS_ASSERT_DELTA(solutions.rGetSolutions()[end][5],0.95328206604519, 2e-2);
    }

    void TestArchiving()
    {
        OutputFileHandler handler("archive", false);
        std::string archive_filename = handler.GetOutputDirectoryFullPath() + "tn_ode.arch";

        {
            TysonNovak2001OdeSystem ode_system;

            ode_system.SetDefaultInitialCondition(2, 3.25);

            std::vector<double> initial_conditions = ode_system.GetInitialConditions();
            TS_ASSERT_EQUALS(initial_conditions.size(), 6u);
            TS_ASSERT_DELTA(initial_conditions[0], 0.0999, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[1], 0.9890, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[2], 3.2500, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[3], 1.4211, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[4], 0.6728, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[5], 0.4854, 1e-4);

            // Create an output archive
            std::ofstream ofs(archive_filename.c_str());
            boost::archive::text_oarchive output_arch(ofs);

            // Archive ODE system
            AbstractOdeSystem* const p_const_ode_system = &ode_system;
            output_arch << p_const_ode_system;
        }

        {
            AbstractOdeSystem* p_ode_system;

            // Create an input archive
            std::ifstream ifs(archive_filename.c_str(), std::ios::binary);
            boost::archive::text_iarchive input_arch(ifs);

            // Restore from the archive
            input_arch >> p_ode_system;

            // Check that archiving worked correctly
            std::vector<double> initial_conditions = p_ode_system->GetInitialConditions();
            TS_ASSERT_EQUALS(initial_conditions.size(), 6u);
            TS_ASSERT_DELTA(initial_conditions[0], 0.0999, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[1], 0.9890, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[2], 3.2500, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[3], 1.4211, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[4], 0.6728, 1e-4);
            TS_ASSERT_DELTA(initial_conditions[5], 0.4854, 1e-4);

            // Tidy up
            delete p_ode_system;
        }
    }
};

#endif /*TESTTYSONNOVAK2001ODESYSTEM_HPP_*/


/* ----------------------------------------------------------------------------

 * GTSAM Copyright 2010, Georgia Tech Research Corporation,
 * Atlanta, Georgia 30332-0415
 * All Rights Reserved
 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)

 * See LICENSE for the license information

 * -------------------------------------------------------------------------- */

/**
 * @file    testVectorValues.cpp
 * @author  Richard Roberts
 * @date    Sep 16, 2010
 */

#include <boost/assign/std/vector.hpp>

#include <gtsam/base/Testable.h>
#include <gtsam/linear/VectorValues.h>
#include <gtsam/inference/Permutation.h>

#include <CppUnitLite/TestHarness.h>

using namespace std;
using namespace boost::assign;
using namespace gtsam;

/* ************************************************************************* */
TEST(VectorValues, insert) {

  // insert, with out-of-order indices
  VectorValues actual;
  actual.insert(0, Vector_(1, 1.0));
  actual.insert(1, Vector_(2, 2.0, 3.0));
  actual.insert(5, Vector_(2, 6.0, 7.0));
  actual.insert(2, Vector_(2, 4.0, 5.0));

  // Check dimensions
  LONGS_EQUAL(6, actual.size());
  LONGS_EQUAL(7, actual.dim());
  LONGS_EQUAL(1, actual.dim(0));
  LONGS_EQUAL(2, actual.dim(1));
  LONGS_EQUAL(2, actual.dim(2));
  LONGS_EQUAL(2, actual.dim(5));

  // Logic
  EXPECT(actual.exists(0));
  EXPECT(actual.exists(1));
  EXPECT(actual.exists(2));
  EXPECT(!actual.exists(3));
  EXPECT(!actual.exists(4));
  EXPECT(actual.exists(5));
  EXPECT(!actual.exists(6));

  // Check values
  EXPECT(assert_equal(Vector_(1, 1.0), actual[0]));
  EXPECT(assert_equal(Vector_(2, 2.0, 3.0), actual[1]));
  EXPECT(assert_equal(Vector_(2, 4.0, 5.0), actual[2]));
  EXPECT(assert_equal(Vector_(2, 6.0, 7.0), actual[5]));
  EXPECT(assert_equal(Vector_(7, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0), actual.vector()));

  // Check exceptions
  CHECK_EXCEPTION(actual.insert(1, Vector()), invalid_argument);
  CHECK_EXCEPTION(actual.dim(3), out_of_range);
}

/* ************************************************************************* */
TEST(VectorValues, dimsConstructor) {
	vector<size_t> dims;
	dims.push_back(1);
	dims.push_back(2);
	dims.push_back(2);

	VectorValues actual(dims);
	actual[0] = Vector_(1, 1.0);
	actual[1] = Vector_(2, 2.0, 3.0);
	actual[2] = Vector_(2, 4.0, 5.0);

	// Check dimensions
	LONGS_EQUAL(3, actual.size());
	LONGS_EQUAL(5, actual.dim());
	LONGS_EQUAL(1, actual.dim(0));
	LONGS_EQUAL(2, actual.dim(1));
	LONGS_EQUAL(2, actual.dim(2));

	// Check values
	EXPECT(assert_equal(Vector_(1, 1.0), actual[0]));
  EXPECT(assert_equal(Vector_(2, 2.0, 3.0), actual[1]));
  EXPECT(assert_equal(Vector_(2, 4.0, 5.0), actual[2]));
  EXPECT(assert_equal(Vector_(5, 1.0, 2.0, 3.0, 4.0, 5.0), actual.vector()));
}

/* ************************************************************************* */
TEST(VectorValues, copyConstructor) {

  // insert, with out-of-order indices
  VectorValues original;
  original.insert(0, Vector_(1, 1.0));
  original.insert(1, Vector_(2, 2.0, 3.0));
  original.insert(5, Vector_(2, 6.0, 7.0));
  original.insert(2, Vector_(2, 4.0, 5.0));

  VectorValues actual(original);

  // Check dimensions
  LONGS_EQUAL(6, actual.size());
  LONGS_EQUAL(7, actual.dim());
  LONGS_EQUAL(1, actual.dim(0));
  LONGS_EQUAL(2, actual.dim(1));
  LONGS_EQUAL(2, actual.dim(2));
  LONGS_EQUAL(2, actual.dim(5));

  // Logic
  EXPECT(actual.exists(0));
  EXPECT(actual.exists(1));
  EXPECT(actual.exists(2));
  EXPECT(!actual.exists(3));
  EXPECT(!actual.exists(4));
  EXPECT(actual.exists(5));
  EXPECT(!actual.exists(6));

  // Check values
  EXPECT(assert_equal(Vector_(1, 1.0), actual[0]));
  EXPECT(assert_equal(Vector_(2, 2.0, 3.0), actual[1]));
  EXPECT(assert_equal(Vector_(2, 4.0, 5.0), actual[2]));
  EXPECT(assert_equal(Vector_(2, 6.0, 7.0), actual[5]));
  EXPECT(assert_equal(Vector_(7, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0), actual.vector()));

  // Check exceptions
  CHECK_EXCEPTION(actual.insert(1, Vector()), invalid_argument);
}

/* ************************************************************************* */
TEST(VectorValues, assignment) {

  VectorValues actual;

  {
    // insert, with out-of-order indices
    VectorValues original;
    original.insert(0, Vector_(1, 1.0));
    original.insert(1, Vector_(2, 2.0, 3.0));
    original.insert(5, Vector_(2, 6.0, 7.0));
    original.insert(2, Vector_(2, 4.0, 5.0));
    actual = original;
  }

  // Check dimensions
  LONGS_EQUAL(6, actual.size());
  LONGS_EQUAL(7, actual.dim());
  LONGS_EQUAL(1, actual.dim(0));
  LONGS_EQUAL(2, actual.dim(1));
  LONGS_EQUAL(2, actual.dim(2));
  LONGS_EQUAL(2, actual.dim(5));

  // Logic
  EXPECT(actual.exists(0));
  EXPECT(actual.exists(1));
  EXPECT(actual.exists(2));
  EXPECT(!actual.exists(3));
  EXPECT(!actual.exists(4));
  EXPECT(actual.exists(5));
  EXPECT(!actual.exists(6));

  // Check values
  EXPECT(assert_equal(Vector_(1, 1.0), actual[0]));
  EXPECT(assert_equal(Vector_(2, 2.0, 3.0), actual[1]));
  EXPECT(assert_equal(Vector_(2, 4.0, 5.0), actual[2]));
  EXPECT(assert_equal(Vector_(2, 6.0, 7.0), actual[5]));
  EXPECT(assert_equal(Vector_(7, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0), actual.vector()));

  // Check exceptions
  CHECK_EXCEPTION(actual.insert(1, Vector()), invalid_argument);
}

/* ************************************************************************* */
TEST(VectorValues, SameStructure) {
  // insert, with out-of-order indices
  VectorValues original;
  original.insert(0, Vector_(1, 1.0));
  original.insert(1, Vector_(2, 2.0, 3.0));
  original.insert(5, Vector_(2, 6.0, 7.0));
  original.insert(2, Vector_(2, 4.0, 5.0));

  VectorValues actual(VectorValues::SameStructure(original));

  // Check dimensions
  LONGS_EQUAL(6, actual.size());
  LONGS_EQUAL(7, actual.dim());
  LONGS_EQUAL(1, actual.dim(0));
  LONGS_EQUAL(2, actual.dim(1));
  LONGS_EQUAL(2, actual.dim(2));
  LONGS_EQUAL(2, actual.dim(5));

  // Logic
  EXPECT(actual.exists(0));
  EXPECT(actual.exists(1));
  EXPECT(actual.exists(2));
  EXPECT(!actual.exists(3));
  EXPECT(!actual.exists(4));
  EXPECT(actual.exists(5));
  EXPECT(!actual.exists(6));

  // Check exceptions
  CHECK_EXCEPTION(actual.insert(1, Vector()), invalid_argument);
}

/* ************************************************************************* */
TEST(VectorValues, Zero_fromModel) {
  // insert, with out-of-order indices
  VectorValues original;
  original.insert(0, Vector_(1, 1.0));
  original.insert(1, Vector_(2, 2.0, 3.0));
  original.insert(5, Vector_(2, 6.0, 7.0));
  original.insert(2, Vector_(2, 4.0, 5.0));

  VectorValues actual(VectorValues::Zero(original));

  // Check dimensions
  LONGS_EQUAL(6, actual.size());
  LONGS_EQUAL(7, actual.dim());
  LONGS_EQUAL(1, actual.dim(0));
  LONGS_EQUAL(2, actual.dim(1));
  LONGS_EQUAL(2, actual.dim(2));
  LONGS_EQUAL(2, actual.dim(5));

  // Values
  EXPECT(assert_equal(Vector::Zero(1), actual[0]));
  EXPECT(assert_equal(Vector::Zero(2), actual[1]));
  EXPECT(assert_equal(Vector::Zero(2), actual[5]));
  EXPECT(assert_equal(Vector::Zero(2), actual[2]));

  // Logic
  EXPECT(actual.exists(0));
  EXPECT(actual.exists(1));
  EXPECT(actual.exists(2));
  EXPECT(!actual.exists(3));
  EXPECT(!actual.exists(4));
  EXPECT(actual.exists(5));
  EXPECT(!actual.exists(6));

  // Check exceptions
  CHECK_EXCEPTION(actual.insert(1, Vector()), invalid_argument);
}

/* ************************************************************************* */
TEST(VectorValues, Zero_fromDims) {
  vector<size_t> dims;
  dims.push_back(1);
  dims.push_back(2);
  dims.push_back(2);

  VectorValues actual(VectorValues::Zero(dims));

  // Check dimensions
  LONGS_EQUAL(3, actual.size());
  LONGS_EQUAL(5, actual.dim());
  LONGS_EQUAL(1, actual.dim(0));
  LONGS_EQUAL(2, actual.dim(1));
  LONGS_EQUAL(2, actual.dim(2));

  // Values
  EXPECT(assert_equal(Vector::Zero(1), actual[0]));
  EXPECT(assert_equal(Vector::Zero(2), actual[1]));
  EXPECT(assert_equal(Vector::Zero(2), actual[2]));
}

/* ************************************************************************* */
TEST(VectorValues, Zero_fromUniform) {
  VectorValues actual(VectorValues::Zero(3, 2));

  // Check dimensions
  LONGS_EQUAL(3, actual.size());
  LONGS_EQUAL(6, actual.dim());
  LONGS_EQUAL(2, actual.dim(0));
  LONGS_EQUAL(2, actual.dim(1));
  LONGS_EQUAL(2, actual.dim(2));

  // Values
  EXPECT(assert_equal(Vector::Zero(2), actual[0]));
  EXPECT(assert_equal(Vector::Zero(2), actual[1]));
  EXPECT(assert_equal(Vector::Zero(2), actual[2]));
}

/* ************************************************************************* */
TEST(VectorValues, resizeLike) {
  // insert, with out-of-order indices
  VectorValues original;
  original.insert(0, Vector_(1, 1.0));
  original.insert(1, Vector_(2, 2.0, 3.0));
  original.insert(5, Vector_(2, 6.0, 7.0));
  original.insert(2, Vector_(2, 4.0, 5.0));

  VectorValues actual(10, 3);
  actual.resizeLike(original);

  // Check dimensions
  LONGS_EQUAL(6, actual.size());
  LONGS_EQUAL(7, actual.dim());
  LONGS_EQUAL(1, actual.dim(0));
  LONGS_EQUAL(2, actual.dim(1));
  LONGS_EQUAL(2, actual.dim(2));
  LONGS_EQUAL(2, actual.dim(5));

  // Logic
  EXPECT(actual.exists(0));
  EXPECT(actual.exists(1));
  EXPECT(actual.exists(2));
  EXPECT(!actual.exists(3));
  EXPECT(!actual.exists(4));
  EXPECT(actual.exists(5));
  EXPECT(!actual.exists(6));

  // Check exceptions
  CHECK_EXCEPTION(actual.insert(1, Vector()), invalid_argument);
}

/* ************************************************************************* */
TEST(VectorValues, resize_fromUniform) {
  VectorValues actual(4, 10);
  actual.resize(3, 2);

  actual[0] = Vector_(2, 1.0, 2.0);
  actual[1] = Vector_(2, 2.0, 3.0);
  actual[2] = Vector_(2, 4.0, 5.0);

  // Check dimensions
  LONGS_EQUAL(3, actual.size());
  LONGS_EQUAL(6, actual.dim());
  LONGS_EQUAL(2, actual.dim(0));
  LONGS_EQUAL(2, actual.dim(1));
  LONGS_EQUAL(2, actual.dim(2));

  // Check values
  EXPECT(assert_equal(Vector_(2, 1.0, 2.0), actual[0]));
  EXPECT(assert_equal(Vector_(2, 2.0, 3.0), actual[1]));
  EXPECT(assert_equal(Vector_(2, 4.0, 5.0), actual[2]));
  EXPECT(assert_equal(Vector_(6, 1.0, 2.0, 2.0, 3.0, 4.0, 5.0), actual.vector()));
}

/* ************************************************************************* */
TEST(VectorValues, resize_fromDims) {
  vector<size_t> dims;
  dims.push_back(1);
  dims.push_back(2);
  dims.push_back(2);

  VectorValues actual(4, 10);
  actual.resize(dims);
  actual[0] = Vector_(1, 1.0);
  actual[1] = Vector_(2, 2.0, 3.0);
  actual[2] = Vector_(2, 4.0, 5.0);

  // Check dimensions
  LONGS_EQUAL(3, actual.size());
  LONGS_EQUAL(5, actual.dim());
  LONGS_EQUAL(1, actual.dim(0));
  LONGS_EQUAL(2, actual.dim(1));
  LONGS_EQUAL(2, actual.dim(2));

  // Check values
  EXPECT(assert_equal(Vector_(1, 1.0), actual[0]));
  EXPECT(assert_equal(Vector_(2, 2.0, 3.0), actual[1]));
  EXPECT(assert_equal(Vector_(2, 4.0, 5.0), actual[2]));
  EXPECT(assert_equal(Vector_(5, 1.0, 2.0, 3.0, 4.0, 5.0), actual.vector()));
}

/* ************************************************************************* */
TEST(VectorValues, append) {
  // insert
  VectorValues actual;
  actual.insert(0, Vector_(1, 1.0));
  actual.insert(1, Vector_(2, 2.0, 3.0));
  actual.insert(2, Vector_(2, 4.0, 5.0));

  // append
  vector<size_t> dims(2);
  dims[0] = 3;
  dims[1] = 5;
  actual.append(dims);

  // Check dimensions
  LONGS_EQUAL(5, actual.size());
  LONGS_EQUAL(13, actual.dim());
  LONGS_EQUAL(1, actual.dim(0));
  LONGS_EQUAL(2, actual.dim(1));
  LONGS_EQUAL(2, actual.dim(2));
  LONGS_EQUAL(3, actual.dim(3));
  LONGS_EQUAL(5, actual.dim(4));

  // Logic
  EXPECT(actual.exists(0));
  EXPECT(actual.exists(1));
  EXPECT(actual.exists(2));
  EXPECT(actual.exists(3));
  EXPECT(actual.exists(4));
  EXPECT(!actual.exists(5));

  // Check values
  EXPECT(assert_equal(Vector_(1, 1.0), actual[0]));
  EXPECT(assert_equal(Vector_(2, 2.0, 3.0), actual[1]));
  EXPECT(assert_equal(Vector_(2, 4.0, 5.0), actual[2]));

  // Check exceptions
  CHECK_EXCEPTION(actual.insert(3, Vector()), invalid_argument);
}

/* ************************************************************************* */
TEST(VectorValues, hasSameStructure) {
  VectorValues v1(2, 3);
  VectorValues v2(3, 2);
  VectorValues v3(4, 2);
  VectorValues v4(4, 2);

  EXPECT(!v1.hasSameStructure(v2));
  EXPECT(!v2.hasSameStructure(v3));
  EXPECT(v3.hasSameStructure(v4));
  EXPECT(VectorValues().hasSameStructure(VectorValues()));
  EXPECT(!v1.hasSameStructure(VectorValues()));
}

/* ************************************************************************* */
TEST(VectorValues, permute) {

	VectorValues original;
	original.insert(0, Vector_(1, 1.0));
	original.insert(1, Vector_(2, 2.0, 3.0));
	original.insert(2, Vector_(2, 4.0, 5.0));
	original.insert(3, Vector_(2, 6.0, 7.0));

	VectorValues expected;
	expected.insert(0, Vector_(2, 4.0, 5.0)); // from 2
	expected.insert(1, Vector_(1, 1.0)); // from 0
	expected.insert(2, Vector_(2, 6.0, 7.0)); // from 3
	expected.insert(3, Vector_(2, 2.0, 3.0)); // from 1

	Permutation permutation(4);
	permutation[0] = 2;
	permutation[1] = 0;
	permutation[2] = 3;
	permutation[3] = 1;

	VectorValues actual = original.permute(permutation);

	EXPECT(assert_equal(expected, actual));
}

/* ************************************************************************* */
int main() {
  TestResult tr; return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */


/* ----------------------------------------------------------------------------

 * GTSAM Copyright 2010, Georgia Tech Research Corporation,
 * Atlanta, Georgia 30332-0415
 * All Rights Reserved
 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)

 * See LICENSE for the license information

 * -------------------------------------------------------------------------- */

/*
 * testDecisionTreeFactor.cpp
 *
 *  @date Feb 5, 2012
 *  @author Frank Dellaert
 *  @author Duy-Nguyen Ta
 */

#include <CppUnitLite/TestHarness.h>
#include <gtsam/base/Testable.h>
#include <gtsam/discrete/DecisionTreeFactor.h>
#include <gtsam/discrete/DiscreteDistribution.h>
#include <gtsam/discrete/Signature.h>

#include <boost/assign/std/map.hpp>
using namespace boost::assign;

using namespace std;
using namespace gtsam;

/* ************************************************************************* */
TEST( DecisionTreeFactor, constructors)
{
  // Declare a bunch of keys
  DiscreteKey X(0,2), Y(1,3), Z(2,2);

  // Create factors
  DecisionTreeFactor f1(X, {2, 8});
  DecisionTreeFactor f2(X & Y, "2 5 3 6 4 7");
  DecisionTreeFactor f3(X & Y & Z, "2 5 3 6 4 7 25 55 35 65 45 75");
  EXPECT_LONGS_EQUAL(1,f1.size());
  EXPECT_LONGS_EQUAL(2,f2.size());
  EXPECT_LONGS_EQUAL(3,f3.size());

  DiscreteValues values;
  values[0] = 1; // x
  values[1] = 2; // y
  values[2] = 1; // z
  EXPECT_DOUBLES_EQUAL(8, f1(values), 1e-9);
  EXPECT_DOUBLES_EQUAL(7, f2(values), 1e-9);
  EXPECT_DOUBLES_EQUAL(75, f3(values), 1e-9);
}

/* ************************************************************************* */
TEST(DecisionTreeFactor, multiplication) {
  DiscreteKey v0(0, 2), v1(1, 2), v2(2, 2);

  // Multiply with a DiscreteDistribution, i.e., Bayes Law!
  DiscreteDistribution prior(v1 % "1/3");
  DecisionTreeFactor f1(v0 & v1, "1 2 3 4");
  DecisionTreeFactor expected(v0 & v1, "0.25 1.5 0.75 3");
  CHECK(assert_equal(expected, static_cast<DecisionTreeFactor>(prior) * f1));
  CHECK(assert_equal(expected, f1 * prior));

  // Multiply two factors
  DecisionTreeFactor f2(v1 & v2, "5 6 7 8");
  DecisionTreeFactor actual = f1 * f2;
  DecisionTreeFactor expected2(v0 & v1 & v2, "5 6 14 16 15 18 28 32");
  CHECK(assert_equal(expected2, actual));
}

/* ************************************************************************* */
TEST( DecisionTreeFactor, sum_max)
{
  DiscreteKey v0(0,3), v1(1,2);
  DecisionTreeFactor f1(v0 & v1, "1 2  3 4  5 6");

  DecisionTreeFactor expected(v1, "9 12");
  DecisionTreeFactor::shared_ptr actual = f1.sum(1);
  CHECK(assert_equal(expected, *actual, 1e-5));

  DecisionTreeFactor expected2(v1, "5 6");
  DecisionTreeFactor::shared_ptr actual2 = f1.max(1);
  CHECK(assert_equal(expected2, *actual2));

  DecisionTreeFactor f2(v1 & v0, "1 2  3 4  5 6");
  DecisionTreeFactor::shared_ptr actual22 = f2.sum(1);
}

/* ************************************************************************* */
// Check enumerate yields the correct list of assignment/value pairs.
TEST(DecisionTreeFactor, enumerate) {
  DiscreteKey A(12, 3), B(5, 2);
  DecisionTreeFactor f(A & B, "1 2  3 4  5 6");
  auto actual = f.enumerate();
  std::vector<std::pair<DiscreteValues, double>> expected;
  DiscreteValues values;
  for (size_t a : {0, 1, 2}) {
    for (size_t b : {0, 1}) {
      values[12] = a;
      values[5] = b;
      expected.emplace_back(values, f(values));
    }
  }
  EXPECT(actual == expected);
}

/* ************************************************************************* */
TEST(DecisionTreeFactor, DotWithNames) {
  DiscreteKey A(12, 3), B(5, 2);
  DecisionTreeFactor f(A & B, "1 2  3 4  5 6");
  auto formatter = [](Key key) { return key == 12 ? "A" : "B"; };

  for (bool showZero:{true, false}) {
    string actual = f.dot(formatter, showZero);
    // pretty weak test, as ids are pointers and not stable across platforms.
    string expected = "digraph G {";
    EXPECT(actual.substr(0, 11) == expected);
  }
}

/* ************************************************************************* */
// Check markdown representation looks as expected.
TEST(DecisionTreeFactor, markdown) {
  DiscreteKey A(12, 3), B(5, 2);
  DecisionTreeFactor f(A & B, "1 2  3 4  5 6");
  string expected =
      "|A|B|value|\n"
      "|:-:|:-:|:-:|\n"
      "|0|0|1|\n"
      "|0|1|2|\n"
      "|1|0|3|\n"
      "|1|1|4|\n"
      "|2|0|5|\n"
      "|2|1|6|\n";
  auto formatter = [](Key key) { return key == 12 ? "A" : "B"; };
  string actual = f.markdown(formatter);
  EXPECT(actual == expected);
}

/* ************************************************************************* */
// Check markdown representation with a value formatter.
TEST(DecisionTreeFactor, markdownWithValueFormatter) {
  DiscreteKey A(12, 3), B(5, 2);
  DecisionTreeFactor f(A & B, "1 2  3 4  5 6");
  string expected =
      "|A|B|value|\n"
      "|:-:|:-:|:-:|\n"
      "|Zero|-|1|\n"
      "|Zero|+|2|\n"
      "|One|-|3|\n"
      "|One|+|4|\n"
      "|Two|-|5|\n"
      "|Two|+|6|\n";
  auto keyFormatter = [](Key key) { return key == 12 ? "A" : "B"; };
  DecisionTreeFactor::Names names{{12, {"Zero", "One", "Two"}},
                                  {5, {"-", "+"}}};
  string actual = f.markdown(keyFormatter, names);
  EXPECT(actual == expected);
}

/* ************************************************************************* */
// Check html representation with a value formatter.
TEST(DecisionTreeFactor, htmlWithValueFormatter) {
  DiscreteKey A(12, 3), B(5, 2);
  DecisionTreeFactor f(A & B, "1 2  3 4  5 6");
  string expected =
      "
\n"
      "
\n"
      "
\n"
      "
A	B	value
\n"
      "
\n"
      "
\n"
      "
Zero	-	1
\n"
      "
Zero	+	2
\n"
      "
One	-	3
\n"
      "
One	+	4
\n"
      "
Two	-	5
\n"
      "
Two	+	6
\n"
      "
\n"
      "
\n"
      "
";
  auto keyFormatter = [](Key key) { return key == 12 ? "A" : "B"; };
  DecisionTreeFactor::Names names{{12, {"Zero", "One", "Two"}},
                                  {5, {"-", "+"}}};
  string actual = f.html(keyFormatter, names);
  EXPECT(actual == expected);
}

/* ************************************************************************* */
int main() {
  TestResult tr;
  return TestRegistry::runAllTests(tr);
}
/* ************************************************************************* */


/*! \file
    \brief Demonstration of showing the 1D data point values rotated at various angles.
    \details  Showing the 1D values of items from the data set.

    Some of the many possible formatting options are demonstrated,
    including controlling the precision and iosflags,
    and prefix and suffix also useful for giving units.

    Quickbook markup to include in documentation.
*/

// 1d_value_label_rotation.cpp
//
// Copyright Paul A Bristow 2021

// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
//   or copy at http://www.boost.org/LICENSE_1_0.txt)

// An example to demonstrate labelling data-points with their values and rotation.

// This file is written to be included from a Quickbook .qbk document.
// It can be compiled by the C++ compiler, and run. Any output can
// also be added here as comment or included or pasted in elsewhere.

// Caution: this file contains Quickbook markup as well as code
// and comments: don't change any of the special comment markups!

//[1d_value_label_rotation

/*` Showing the 1-D values of items from the data set.
    Some of the many possible formatting options are demonstrated.

    As ever, we need a few includes to use Boost.Plot
*/

#include <boost/svg_plot/svg_1d_plot.hpp>
using namespace boost::svg;
using boost::svg::svg_1d_plot;

#include <boost/svg_plot/show_1d_settings.hpp>
// using boost::svg::show_1d_plot_settings - Only needed for showing which settings in use.

#include <iostream>
using std::cout;
using std::endl;
using std::hex;

#include <vector>
using std::vector;
//] [1d_value_label_rotation]

int main()
{
  //[demo_1d_values_2
  /*`Some fictional data is pushed into an STL container, here `vector<double>`:*/
  vector<double> my_data;
  //my_data.push_back(+1.1);
  my_data.push_back(2.2);
//  my_data.push_back(3.3);
  //my_data.push_back(4.4);
 // my_data.push_back(5.5);

  try
  { // try'n'catch blocks are needed to ensure error messages from any exceptions are shown.
    svg_1d_plot my_1d_plot; // Construct a plot with all the default constructor values.

    my_1d_plot
      .title("Rotating 1D value-labelling") // Add a string title of the plot.
      .title_on(false) // Avoid showing title for this test as an issue in handling of title causes second plot to not have a title.
      .x_range(-0, 4) // Add a range for the X-axis.
      .x_major_interval(1.)
      .x_num_minor_ticks(4)
      .x_label("length (m)"); // Add a label for the X-axis.

/*`Add the one data series, `my_data` and a description, and how the data points are to marked,
here a circle with a diameter of 5 pixels.
*/
    my_1d_plot.plot(my_data, "1D Values").shape(circlet).size(10).stroke_color(red).fill_color(blue);

    /*`To put a value-label against each data point, switch on the option:
    */
    my_1d_plot.x_values_on(true); // Add a label for the X-axis.

/*`If the default size and color are not to your taste, set more options, like:
*/
    my_1d_plot.size(500, 250) // Change from default size.
      .x_values_font_size(10) // Change font size for the X-axis value-labels.
      .x_values_font_family("Times New Roman") // Change font for the X-axis value-labels.
      .x_values_color(red); // Change color of value-label text from default black to red.

/*`The format of the values may also not be ideal,
so we can use the normal `iostream precision` and `ioflags` to change,
here to reduce the number of digits used from default precision 6 down to a more readable 2,
reducing the risk of collisions between adjacent values.
(Obviously the most suitable precision depends on the range of the data points.
If values are very close to each other, a higher precision wil be needed to differentiate them).
*/
    my_1d_plot.x_values_precision(2); // precision label for the X-axis value-label.

/*`We can also prescribe the use of scientific format and force a positive sign:
*/
    //my_1d_plot.x_values_ioflags(std::ios::scientific | std::ios::showpos);

    /*`By default, any unnecessary spacing-wasting zeros in the exponent field are removed.
    (If, perversely, the full 1.123456e+012 format is required, the stripping can be switched off with:
      `my_1d_plot.x_labels_strip_e0s(false);` )

    In general, sticking to the defaults usually produces the neatest presentation of the values.
    */
     my_1d_plot.x_decor("[ x=", "", " s]");
   // my_1d_plot.x_decor("  [x=", "", " s]");
    // Note Leading Normal spaces are ignored!
    // To get a real space you may need one or more of the several Unicode spaces, for example: A0 as   .

     /*`[note Code is shared between 1D and 2D variants, so arrangement is never perfect. [br]
     1D data-point markers are usually above the X-axis line, so many will overwrite the line.
     Prefix Unicode space(s) can avoid this, but the marker and value-label are then further apart.
     */

    /*`The default value-label is horizontal, centered above the data point marker,
    but, depending on the type and density of data points, and the length of the values
    (controlled in turn by the `precision` and `ioflags` in use),
    it is often clearer to use a different orientation.
    This can be controlled in steps of 45 degrees, using an 'enum rotate_style` whose possible values are:
   ``
    enum rotate_style
    {
      // Also need a no_rotate, = -1; ??
      horizontal = 0, //!< normal horizontal left to right, centered.
      slopeup = -30, //!< slope up.
      uphill = -45, //!< 45 steep up.
      steepup = -60, //!< up near vertical.
      upward = -90, //!< vertical writing up.
      backup = -135, //!< slope up backwards - upside down!
      leftward= -180, //!< horizontal to left.
      rightward = 360, //!< horizontal to right.
      slopedownhill = 30, //!< 30 gentle slope down.
      downhill = 45, //!< 45 down.
      steepdown = 60, //!<  60 steeply down.
      downward = 90,  //!< vertical writing down.
      backdown = 135, //!< slope down backwards.
      upsidedown = 180 //!< upside down!  (== -180)
    };
``
    * `uphill` - writing up at 45 degree slope is often a good choice,
    * `upward` - writing vertically up and
    * `backup` are also useful.

    (For 1-D plots other directions are less attractive,
    placing the values below the horizontal Y-axis line,
    but for 2-D plots all writing orientations can be useful).
    */

    // Orientation for the X-axis value-labels,
   //  my_1d_plot.x_values_rotation(steepup);  //  Nearly vertically upwards. OK Best compromise?
    // my_1d_plot.x_values_rotation(slopeup); // OK but is a bit high.
    // my_1d_plot.x_values_rotation(uphill); // OK but is a bit high.
    // my_1d_plot.x_values_rotation(upward); //  Vertically upwards. OK, but may need height for long labels.
    // my_1d_plot.x_values_rotation(horizontal);  // Default Centered above, OK, but nearby values can collide, especially long labels.
    // my_1d_plot.x_values_rotation(backup); // OK
    // my_1d_plot.x_values_rotation(steepdown); // For 1D, Clashes with the y = 0 axis line, so need a few leading spaces, for example
    // my_1d_plot.x_decor("  [x=", "", " s]");
    // Or put the X-axis tick value-labels above the y= 0 axis line, and the markers below the axis line.
    // my_1d_plot.x_values_rotation(slopedown); //  Clashes with X axis line.
    //  my_1d_plot.x_values_rotation(downhill); //  Clashes with X axis line.
    //   my_1d_plot.x_values_rotation(downward); // Straight down - Clashes with X axis line.
    // my_1d_plot.x_values_rotation(backdown); // Clashes with X axis line.
    // my_1d_plot.x_values_rotation(upsidedown); // Upside down and Clashes with X axis line.

  //  my_1d_plot.x_values_rotation(leftward); // OK, but can clash with nearby points.
  //  my_1d_plot.x_values_rotation(rightward); // OK, but can clash with nearby points.
     // default orientation write value-labels horizontally above the markers.

 /*`To use all these settings, finally write the plot to file.
 */
    my_1d_plot.write("1d_value_label_rotation.svg");

    // Repeat for testing labelling rotation.
    my_1d_plot.x_values_rotation(leftward); //
    my_1d_plot.write("1d_value_label_rotation_all.svg");
    my_1d_plot.x_values_rotation(upward); //
    my_1d_plot.write("1d_value_label_rotation_all.svg");
    // See note above about issue in title means that second (and subsequent?) plots have not title and so are offset down.
    my_1d_plot.x_values_rotation(rightward); // OK, but can clash with nearby points.
    my_1d_plot.write("1d_value_label_rotation_all.svg");
    my_1d_plot.x_values_rotation(uphill); //
    my_1d_plot.write("1d_value_label_rotation_all.svg");
    my_1d_plot.x_values_rotation(backup); //
    my_1d_plot.write("1d_value_label_rotation_all.svg");
    // Vertical below axis line, but collides.
    my_1d_plot.x_values_rotation(upward); //
    my_1d_plot.write("1d_value_label_rotation_all.svg");
    my_1d_plot.x_values_rotation(downward); //
    my_1d_plot.write("1d_value_label_rotation_all.svg");

    my_1d_plot.x_values_rotation(backdown); // Below with X axis line.
    my_1d_plot.write("1d_value_label_rotation_all.svg");

    my_1d_plot.x_values_rotation(upsidedown); // Upside down - clashes a bitwith X axis line.
    my_1d_plot.write("1d_value_label_rotation_all.svg");

    my_1d_plot.x_values_rotation(downhill); // downhill - clashes a with X axis line.
    my_1d_plot.write("1d_value_label_rotation_all.svg");
    my_1d_plot.x_values_rotation(slopedownhill); // downsteep - clashes a with X axis line (and downhill).
    my_1d_plot.write("1d_value_label_rotation_all.svg");
    my_1d_plot.x_values_rotation(steepdown); //steepdown - clashes a with X axis line (and downhill).
    my_1d_plot.write("1d_value_label_rotation_all.svg");
    // Displays all layouts around the point above the line.
    // Probably also will work OK if ticks and tick-value-labels are above the y=0 X-axis horizontal line and the marker is below.

    /*`If chosen settings do not have the effect that you expect, it may be helpful to display some of them!
    (All the myriad settings can be displayed with `show_1d_plot_settings(my_1d_plot)`.)
    */
    //show_1d_plot_settings(my_1d_plot);
    using boost::svg::detail::operator<<;
    //] [demo_1d_values_2]
  }
  catch (const std::exception& e)
  {
    std::cout <<
      "\n""Message from thrown exception was:\n   " << e.what() << std::endl;
  }
  return 0;
} // int main()

/*

//[demo_1d_values_output

Output:

demo_1d_values.cpp
Plot written to file demo_1d_values.svg.
my_1d_plot.image_size() 500, 350
my_1d_plot.image x_size() 500
my_1d_plot.image y_size() 350
my_1d_plot.x_values_font_size() 14
my_1d_plot.x_values_font_family() Times New Roman
my_1d_plot.x_values_color() RGB(255,0,0)
my_1d_plot.x_values_precision() 2
my_1d_plot.x_values_ioflags() 1020

//] [demo_1d_values_output]
*/


/* Author: Wolfgang Bangerth, University of Texas at Austin, 2000, 2004 */

/*    $Id: step-17.cc 28351 2013-02-12 23:23:18Z heister $       */
/*                                                                */
/*    Copyright (C) 2000, 2004-2009, 2011-2012 by the deal.II authors */
/*                                                                */
/*    This file is subject to QPL and may not be  distributed     */
/*    without copyright and license information. Please refer     */
/*    to the file deal.II/doc/license.html for the  text  and     */
/*    further information on this license.                        */

// First the usual assortment of header files we have already used in previous
// example programs:
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/function.h>
#include <deal.II/base/logstream.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/constraint_matrix.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/grid_refinement.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/tria_boundary_lib.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/fe/fe_system.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/numerics/data_out.h>
#include <deal.II/numerics/error_estimator.h>

// And here come the things that we need particularly for this example program
// and that weren't in step-8. First, we replace the standard output
// std::cout by a new stream pcout which is used in
// %parallel computations for generating output only on one of the MPI
// processes.
#include <deal.II/base/conditional_ostream.h>
// We are going to query the number of processes and the number of the present
// process by calling the respective functions in the Utilities::MPI
// namespace.
#include <deal.II/base/utilities.h>
// Then, we are going to replace all linear algebra components that involve
// the (global) linear system by classes that wrap interfaces similar to our
// own linear algebra classes around what PETSc offers (PETSc is a library
// written in C, and deal.II comes with wrapper classes that provide the PETSc
// functionality with an interface that is similar to the interface we already
// had for our own linear algebra classes). In particular, we need vectors and
// matrices that are distributed across several processes in MPI programs (and
// simply map to sequential, local vectors and matrices if there is only a
// single process, i.e. if you are running on only one machine, and without
// MPI support):
#include <deal.II/lac/petsc_vector.h>
#include <deal.II/lac/petsc_parallel_vector.h>
#include <deal.II/lac/petsc_parallel_sparse_matrix.h>
// Then we also need interfaces for solvers and preconditioners that PETSc
// provides:
#include <deal.II/lac/petsc_solver.h>
#include <deal.II/lac/petsc_precondition.h>
// And in addition, we need some algorithms for partitioning our meshes so
// that they can be efficiently distributed across an MPI network. The
// partitioning algorithm is implemented in the GridTools class,
// and we need an additional include file for a function in
// DoFRenumbering that allows to sort the indices associated with
// degrees of freedom so that they are numbered according to the subdomain
// they are associated with:
#include <deal.II/grid/grid_tools.h>
#include <deal.II/dofs/dof_renumbering.h>

// And this is simply C++ again:
#include <fstream>
#include <iostream>
#include <sstream>

// The last step is as in all previous programs:
namespace Step17
{
  using namespace dealii;

  // Now, here comes the declaration of the main class and of various other
  // things below it. As mentioned in the introduction, almost all of this has
  // been copied verbatim from step-8, so we only comment on the few things
  // that are different. There is one (cosmetic) change in that we let
  // solve return a value, namely the number of iterations it
  // took to converge, so that we can output this to the screen at the
  // appropriate place. In addition, we introduce a stream-like variable
  // pcout, explained below:
  template <int dim>
  class ElasticProblem
  {
  public:
    ElasticProblem ();
    ~ElasticProblem ();
    void run ();

  private:
    void setup_system ();
    void assemble_system ();
    unsigned int solve ();
    void refine_grid ();
    void output_results (const unsigned int cycle) const;

    // The first variable is basically only for convenience: in %parallel
    // program, if each process outputs status information, then there quickly
    // is a lot of clutter. Rather, we would want to only have one process
    // output everything once, for example the one with process number
    // zero. ConditionalOStream does exactly this: it acts as if
    // it were a stream, but only forwards to a real, underlying stream if a
    // flag is set. By setting this condition to
    // this_mpi_process==0, we make sure that output is only
    // generated from the first process and that we don't get the same lines
    // of output over and over again, once per process.
    //
    // With this simple trick, we make sure that we don't have to guard each
    // and every write to std::cout by a prefixed
    // if(this_mpi_process==0).
    ConditionalOStream pcout;

    // The next few variables are taken verbatim from step-8:
    Triangulation<dim>   triangulation;
    DoFHandler<dim>      dof_handler;

    FESystem<dim>        fe;

    ConstraintMatrix     hanging_node_constraints;

    // In step-8, this would have been the place where we would have declared
    // the member variables for the sparsity pattern, the system matrix, right
    // hand, and solution vector. We change these declarations to use
    // %parallel PETSc objects instead (note that the fact that we use the
    // %parallel versions is denoted the fact that we use the classes from the
    // PETScWrappers::MPI namespace; sequential versions of these
    // classes are in the PETScWrappers namespace, i.e. without
    // the MPI part). Note also that we do not use a separate
    // sparsity pattern, since PETSc manages that as part of its matrix data
    // structures.
    PETScWrappers::MPI::SparseMatrix system_matrix;

    PETScWrappers::MPI::Vector       solution;
    PETScWrappers::MPI::Vector       system_rhs;

    // The next change is that we have to declare a variable that indicates
    // the MPI communicator over which we are supposed to distribute our
    // computations. Note that if this is a sequential job without support by
    // MPI, then PETSc provides some dummy type for MPI_Comm, so
    // we do not have to care here whether the job is really a %parallel one:
    MPI_Comm mpi_communicator;

    // Then we have two variables that tell us where in the %parallel world we
    // are. The first of the following variables, n_mpi_processes
    // tells us how many MPI processes there exist in total, while the second
    // one, this_mpi_process, indicates which is the number of
    // the present process within this space of processes. The latter variable
    // will have a unique value for each process between zero and (less than)
    // n_mpi_processes. If this program is run on a single
    // machine without MPI support, then their values are 1 and
    // 0, respectively.
    const unsigned int n_mpi_processes;
    const unsigned int this_mpi_process;
  };

  // The following is again taken from step-8 without change:
  template <int dim>
  class RightHandSide :  public Function<dim>
  {
  public:
    RightHandSide ();

    virtual void vector_value (const Point<dim> &p,
                               Vector<double>   &values) const;

    virtual void vector_value_list (const std::vector<Point<dim> > &points,
                                    std::vector<Vector<double> >   &value_list) const;
  };

  template <int dim>
  RightHandSide<dim>::RightHandSide () :
    Function<dim> (dim)
  {}

  template <int dim>
  inline
  void RightHandSide<dim>::vector_value (const Point<dim> &p,
                                         Vector<double>   &values) const
  {
    Assert (values.size() == dim,
            ExcDimensionMismatch (values.size(), dim));
    Assert (dim >= 2, ExcInternalError());

    Point<dim> point_1, point_2;
    point_1(0) = 0.5;
    point_2(0) = -0.5;

    if (((p-point_1).square() < 0.2*0.2) ||
        ((p-point_2).square() < 0.2*0.2))
      values(0) = 1;
    else
      values(0) = 0;

    if (p.square() < 0.2*0.2)
      values(1) = 1;
    else
      values(1) = 0;
  }

  template <int dim>
  void RightHandSide<dim>::vector_value_list (const std::vector<Point<dim> > &points,
                                              std::vector<Vector<double> >   &value_list) const
  {
    const unsigned int n_points = points.size();

    Assert (value_list.size() == n_points,
            ExcDimensionMismatch (value_list.size(), n_points));

    for (unsigned int p=0; p<n_points; ++p)
      RightHandSide<dim>::vector_value (points[p],
                                        value_list[p]);
  }

  // The first step in the actual implementation of things is the constructor
  // of the main class. Apart from initializing the same member variables that
  // we already had in step-8, we here initialize the MPI communicator
  // variable we shall use with the global MPI communicator linking all
  // processes together (in more complex applications, one could here use a
  // communicator object that only links a subset of all processes), and call
  // the Utilities helper functions to determine the number of processes and
  // where the present one fits into this picture. In addition, we make sure
  // that output is only generated by the (globally) first process. As,
  // this_mpi_process is determined after creation of pcout, we cannot set the
  // condition through the constructor, i.e. by pcout(std::cout,
  // this_mpi_process==0), but set the condition separately.
  template <int dim>
  ElasticProblem<dim>::ElasticProblem ()
    :
    pcout (std::cout),
    dof_handler (triangulation),
    fe (FE_Q<dim>(1), dim),
    mpi_communicator (MPI_COMM_WORLD),
    n_mpi_processes (Utilities::MPI::n_mpi_processes(mpi_communicator)),
    this_mpi_process (Utilities::MPI::this_mpi_process(mpi_communicator))
  {
    pcout.set_condition(this_mpi_process == 0);
  }

  template <int dim>
  ElasticProblem<dim>::~ElasticProblem ()
  {
    dof_handler.clear ();
  }

  // The second step is the function in which we set up the various variables
  // for the global linear system to be solved.
  template <int dim>
  void ElasticProblem<dim>::setup_system ()
  {
    // Before we even start out setting up the system, there is one thing to
    // do for a %parallel program: we need to assign cells to each of the
    // processes. We do this by splitting (partitioning) the mesh
    // cells into as many chunks (subdomains) as there are
    // processes in this MPI job (if this is a sequential job, then there is
    // only one job and all cells will get a zero as subdomain
    // indicator). This is done using an interface to the METIS library that
    // does this in a very efficient way, trying to minimize the number of
    // nodes on the interfaces between subdomains. All this is hidden behind
    // the following call to a deal.II library function:
    GridTools::partition_triangulation (n_mpi_processes, triangulation);

    // As for the linear system: First, we need to generate an enumeration for
    // the degrees of freedom in our problem. Further below, we will show how
    // we assign each cell to one of the MPI processes before we even get
    // here. What we then need to do is to enumerate the degrees of freedom in
    // a way so that all degrees of freedom associated with cells in subdomain
    // zero (which resides on process zero) come before all DoFs associated
    // with cells on subdomain one, before those on cells on process two, and
    // so on. We need this since we have to split the global vectors for right
    // hand side and solution, as well as the matrix into contiguous chunks of
    // rows that live on each of the processors, and we will want to do this
    // in a way that requires minimal communication. This is done using the
    // following two functions, which first generates an initial ordering of
    // all degrees of freedom, and then re-sort them according to above
    // criterion:
    dof_handler.distribute_dofs (fe);
    DoFRenumbering::subdomain_wise (dof_handler);

    // While we're at it, let us also count how many degrees of freedom there
    // exist on the present process:
    const unsigned int n_local_dofs
      = DoFTools::count_dofs_with_subdomain_association (dof_handler,
                                                         this_mpi_process);

    // Then we initialize the system matrix, solution, and right hand side
    // vectors. Since they all need to work in %parallel, we have to pass them
    // an MPI communication object, as well as their global sizes (both
    // dimensions are equal to the number of degrees of freedom), and also how
    // many rows out of this global size are to be stored locally
    // (n_local_dofs). In addition, PETSc needs to know how to
    // partition the columns in the chunk of the matrix that is stored
    // locally; for square matrices, the columns should be partitioned in the
    // same way as the rows (indicated by the second n_local_dofs
    // in the call) but in the case of rectangular matrices one has to
    // partition the columns in the same way as vectors are partitioned with
    // which the matrix is multiplied, while rows have to partitioned in the
    // same way as destination vectors of matrix-vector multiplications:
    system_matrix.reinit (mpi_communicator,
                          dof_handler.n_dofs(),
                          dof_handler.n_dofs(),
                          n_local_dofs,
                          n_local_dofs,
                          dof_handler.max_couplings_between_dofs());

    solution.reinit (mpi_communicator, dof_handler.n_dofs(), n_local_dofs);
    system_rhs.reinit (mpi_communicator, dof_handler.n_dofs(), n_local_dofs);

    // Finally, we need to initialize the objects denoting hanging node
    // constraints for the present grid. Note that since PETSc handles the
    // sparsity pattern internally to the matrix, there is no need to set up
    // an independent sparsity pattern here, and to condense it for
    // constraints, as we have done in all other example programs.
    hanging_node_constraints.clear ();
    DoFTools::make_hanging_node_constraints (dof_handler,
                                             hanging_node_constraints);
    hanging_node_constraints.close ();
  }

  // The third step is to actually assemble the matrix and right hand side of
  // the problem. There are some things worth mentioning before we go into
  // detail. First, we will be assembling the system in %parallel, i.e. each
  // process will be responsible for assembling on cells that belong to this
  // particular processor. Note that the degrees of freedom are split in a way
  // such that all DoFs in the interior of cells and between cells belonging
  // to the same subdomain belong to the process that owns the
  // cell. However, even then we sometimes need to assemble on a cell with a
  // neighbor that belongs to a different process, and in these cases when we
  // write the local contributions into the global matrix or right hand side
  // vector, we actually have to transfer these entries to the other
  // process. Fortunately, we don't have to do this by hand, PETSc does all
  // this for us by caching these elements locally, and sending them to the
  // other processes as necessary when we call the compress()
  // functions on the matrix and vector at the end of this function.
  //
  // The second point is that once we have handed over matrix and vector
  // contributions to PETSc, it is a) hard, and b) very inefficient to get
  // them back for modifications. This is not only the fault of PETSc, it is
  // also a consequence of the distributed nature of this program: if an entry
  // resides on another processor, then it is necessarily expensive to get
  // it. The consequence of this is that where we previously first assembled
  // the matrix and right hand side as if there were no hanging node
  // constraints and boundary values, and then eliminated these in a second
  // step, we should now try to do that while still assembling the local
  // systems, and before handing these entries over to PETSc. At least as far
  // as eliminating hanging nodes is concerned, this is actually possible,
  // though removing boundary nodes isn't that simple. deal.II provides
  // functions to do this first part: instead of copying elements by hand into
  // the global matrix, we use the distribute_local_to_global
  // functions below to take care of hanging nodes at the same time. The
  // second step, elimination of boundary nodes, is then done in exactly the
  // same way as in all previous example programs.
  //
  // So, here is the actual implementation:
  template <int dim>
  void ElasticProblem<dim>::assemble_system ()
  {
    // The infrastructure to assemble linear systems is the same as in all the
    // other programs, and in particular unchanged from step-8. Note that we
    // still use the deal.II full matrix and vector types for the local
    // systems.
    QGauss<dim>  quadrature_formula(2);
    FEValues<dim> fe_values (fe, quadrature_formula,
                             update_values   | update_gradients |
                             update_quadrature_points | update_JxW_values);

    const unsigned int   dofs_per_cell = fe.dofs_per_cell;
    const unsigned int   n_q_points    = quadrature_formula.size();

    FullMatrix<double>   cell_matrix (dofs_per_cell, dofs_per_cell);
    Vector<double>       cell_rhs (dofs_per_cell);

    std::vector<unsigned int> local_dof_indices (dofs_per_cell);

    std::vector<double>     lambda_values (n_q_points);
    std::vector<double>     mu_values (n_q_points);

    ConstantFunction<dim> lambda(1.), mu(1.);

    RightHandSide<dim>      right_hand_side;
    std::vector<Vector<double> > rhs_values (n_q_points,
                                             Vector<double>(dim));

    // The next thing is the loop over all elements. Note that we do not have
    // to do all the work: our job here is only to assemble the system on
    // cells that actually belong to this MPI process, all other cells will be
    // taken care of by other processes. This is what the if-clause
    // immediately after the for-loop takes care of: it queries the subdomain
    // identifier of each cell, which is a number associated with each cell
    // that tells which process handles it. In more generality, the subdomain
    // id is used to split a domain into several parts (we do this above, at
    // the beginning of setup_system), and which allows to
    // identify which subdomain a cell is living on. In this application, we
    // have each process handle exactly one subdomain, so we identify the
    // terms subdomain and MPI process with each
    // other.
    //
    // Apart from this, assembling the local system is relatively uneventful
    // if you have understood how this is done in step-8, and only becomes
    // interesting again once we start distributing it into the global matrix
    // and right hand sides.
    typename DoFHandler<dim>::active_cell_iterator
    cell = dof_handler.begin_active(),
    endc = dof_handler.end();
    for (; cell!=endc; ++cell)
      if (cell->subdomain_id() == this_mpi_process)
        {
          cell_matrix = 0;
          cell_rhs = 0;

          fe_values.reinit (cell);

          lambda.value_list (fe_values.get_quadrature_points(), lambda_values);
          mu.value_list     (fe_values.get_quadrature_points(), mu_values);

          for (unsigned int i=0; i<dofs_per_cell; ++i)
            {
              const unsigned int
              component_i = fe.system_to_component_index(i).first;

              for (unsigned int j=0; j<dofs_per_cell; ++j)
                {
                  const unsigned int
                  component_j = fe.system_to_component_index(j).first;

                  for (unsigned int q_point=0; q_point<n_q_points;
                       ++q_point)
                    {
//TODO investigate really small values here
                      cell_matrix(i,j)
                      +=
                        (
                          (fe_values.shape_grad(i,q_point)[component_i] *
                           fe_values.shape_grad(j,q_point)[component_j] *
                           lambda_values[q_point])
                          +
                          (fe_values.shape_grad(i,q_point)[component_j] *
                           fe_values.shape_grad(j,q_point)[component_i] *
                           mu_values[q_point])
                          +
                          ((component_i == component_j) ?
                           (fe_values.shape_grad(i,q_point) *
                            fe_values.shape_grad(j,q_point) *
                            mu_values[q_point])  :
                           0)
                        )
                        *
                        fe_values.JxW(q_point);
                    }
                }
            }

          right_hand_side.vector_value_list (fe_values.get_quadrature_points(),
                                             rhs_values);
          for (unsigned int i=0; i<dofs_per_cell; ++i)
            {
              const unsigned int
              component_i = fe.system_to_component_index(i).first;

              for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
                cell_rhs(i) += fe_values.shape_value(i,q_point) *
                               rhs_values[q_point](component_i) *
                               fe_values.JxW(q_point);
            }

          // Now we have the local system, and need to transfer it into the
          // global objects. However, as described in the introduction to this
          // function, we want to avoid any operations to matrix and vector
          // entries after handing them off to PETSc (i.e. after distributing
          // to the global objects). Therefore, we will take care of hanging
          // node constraints already here. This is not quite trivial since
          // the rows and columns of constrained nodes have to be distributed
          // to the rows and columns of those nodes to which they are
          // constrained. This can't be done on a purely local basis (because
          // the degrees of freedom to which hanging nodes are constrained may
          // not be associated with the cell we are presently treating, and
          // are therefore not represented in the local matrix and vector),
          // but it can be done while distributing the local system to the
          // global one. This is what the following call does, i.e. we
          // distribute to the global objects and at the same time make sure
          // that hanging node constraints are taken care of:
          cell->get_dof_indices (local_dof_indices);
          hanging_node_constraints
          .distribute_local_to_global(cell_matrix, cell_rhs,
                                       local_dof_indices,
                                       system_matrix, system_rhs);
        }

    // Now compress the vector and the system matrix:
    system_matrix.compress();
    system_rhs.compress(VectorOperation::add);

    // The global matrix and right hand side vectors have now been
    // formed. Note that since we took care of this already above, we do not
    // have to condense away hanging node constraints any more.
    //
    // However, we still have to apply boundary values, in the same way as we
    // always do:
    std::map<unsigned int,double> boundary_values;
    VectorTools::interpolate_boundary_values (dof_handler,
                                              0,
                                              ZeroFunction<dim>(dim),
                                              boundary_values);
    MatrixTools::apply_boundary_values (boundary_values,
                                        system_matrix, solution,
                                        system_rhs, false);
    // The last argument to the call just performed allows for some
    // optimizations. It controls whether we should also delete the column
    // corresponding to a boundary node, or keep it (and passing
    // true as above means: yes, do eliminate the column). If we
    // do, then the resulting matrix will be symmetric again if it was before;
    // if we don't, then it won't. The solution of the resulting system should
    // be the same, though. The only reason why we may want to make the system
    // symmetric again is that we would like to use the CG method, which only
    // works with symmetric matrices.  Experience tells that CG also works
    // (and works almost as well) if we don't remove the columns associated
    // with boundary nodes, which can be easily explained by the special
    // structure of the non-symmetry. Since eliminating columns from dense
    // matrices is not expensive, though, we let the function do it; not doing
    // so is more important if the linear system is either non-symmetric
    // anyway, or we are using the non-local version of this function (as in
    // all the other example programs before) and want to save a few cycles
    // during this operation.
  }

  // The fourth step is to solve the linear system, with its distributed
  // matrix and vector objects. Fortunately, PETSc offers a variety of
  // sequential and %parallel solvers, for which we have written wrappers that
  // have almost the same interface as is used for the deal.II solvers used in
  // all previous example programs.
  template <int dim>
  unsigned int ElasticProblem<dim>::solve ()
  {
    // First, we have to set up a convergence monitor, and assign it the
    // accuracy to which we would like to solve the linear system. Next, an
    // actual solver object using PETSc's CG solver which also works with
    // %parallel (distributed) vectors and matrices. And finally a
    // preconditioner; we choose to use a block Jacobi preconditioner which
    // works by computing an incomplete LU decomposition on each block
    // (i.e. the chunk of matrix that is stored on each MPI process). That
    // means that if you run the program with only one process, then you will
    // use an ILU(0) as a preconditioner, while if it is run on many
    // processes, then we will have a number of blocks on the diagonal and the
    // preconditioner is the ILU(0) of each of these blocks.
    SolverControl           solver_control (solution.size(),
                                            1e-8*system_rhs.l2_norm());
    PETScWrappers::SolverCG cg (solver_control,
                                mpi_communicator);

    PETScWrappers::PreconditionBlockJacobi preconditioner(system_matrix);

    // Then solve the system:
    cg.solve (system_matrix, solution, system_rhs,
              preconditioner);

    // The next step is to distribute hanging node constraints. This is a
    // little tricky, since to fill in the value of a constrained node you
    // need access to the values of the nodes to which it is constrained (for
    // example, for a Q1 element in 2d, we need access to the two nodes on the
    // big side of a hanging node face, to compute the value of the
    // constrained node in the middle). Since PETSc (and, for that matter, the
    // MPI model on which it is built) does not allow to query the value of
    // another node in a simple way if we should need it, what we do here is
    // to get a copy of the distributed vector where we keep all elements
    // locally. This is simple, since the deal.II wrappers have a conversion
    // constructor for the non-MPI vector class:
    PETScWrappers::Vector localized_solution (solution);

    // Then we distribute hanging node constraints on this local copy, i.e. we
    // compute the values of all constrained nodes:
    hanging_node_constraints.distribute (localized_solution);

    // Then transfer everything back into the global vector. The following
    // operation copies those elements of the localized solution that we store
    // locally in the distributed solution, and does not touch the other
    // ones. Since we do the same operation on all processors, we end up with
    // a distributed vector that has all the constrained nodes fixed.
    solution = localized_solution;

    // Finally return the number of iterations it took to converge, to allow
    // for some output:
    return solver_control.last_step();
  }

  // Step five is to output the results we computed in this iteration. This is
  // actually the same as done in step-8 before, with two small
  // differences. First, all processes call this function, but not all of them
  // need to do the work associated with generating output. In fact, they
  // shouldn't, since we would try to write to the same file multiple times at
  // once. So we let only the first job do this, and all the other ones idle
  // around during this time (or start their work for the next iteration, or
  // simply yield their CPUs to other jobs that happen to run at the same
  // time). The second thing is that we not only output the solution vector,
  // but also a vector that indicates which subdomain each cell belongs
  // to. This will make for some nice pictures of partitioned domains.
  //
  // In practice, the present implementation of the output function is a major
  // bottleneck of this program, since generating graphical output is
  // expensive and doing so only on one process does, of course, not scale if
  // we significantly increase the number of processes. In effect, this
  // function will consume most of the run-time if you go to very large
  // numbers of unknowns and processes, and real applications should limit the
  // number of times they generate output through this function.
  //
  // The solution to this is to have each process generate output data only
  // for it's own local cells, and write them to separate files, one file per
  // process. This would distribute the work of generating the output to all
  // processes equally. In a second step, separate from running this program,
  // we would then take all the output files for a given cycle and merge these
  // parts into one single output file. This has to be done sequentially, but
  // can be done on a different machine, and should be relatively
  // cheap. However, the necessary functionality for this is not yet
  // implemented in the library, and since we are too close to the next
  // release, we do not want to do such major destabilizing changes any
  // more. This has been fixed in the meantime, though, and a better way to do
  // things is explained in the step-18 example program.
  template <int dim>
  void ElasticProblem<dim>::output_results (const unsigned int cycle) const
  {
    // One point to realize is that when we want to generate output on process
    // zero only, we need to have access to all elements of the solution
    // vector. So we need to get a local copy of the distributed vector, which
    // is in fact simple:
    const PETScWrappers::Vector localized_solution (solution);
    // The thing to notice, however, is that we do this localization operation
    // on all processes, not only the one that actually needs the data. This
    // can't be avoided, however, with the communication model of MPI: MPI
    // does not have a way to query data on another process, both sides have
    // to initiate a communication at the same time. So even though most of
    // the processes do not need the localized solution, we have to place the
    // call here so that all processes execute it.
    //
    // (In reality, part of this work can in fact be avoided. What we do is
    // send the local parts of all processes to all other processes. What we
    // would really need to do is to initiate an operation on all processes
    // where each process simply sends its local chunk of data to process
    // zero, since this is the only one that actually needs it, i.e. we need
    // something like a gather operation. PETSc can do this, but for
    // simplicity's sake we don't attempt to make use of this here. We don't,
    // since what we do is not very expensive in the grand scheme of things:
    // it is one vector communication among all processes , which has to be
    // compared to the number of communications we have to do when solving the
    // linear system, setting up the block-ILU for the preconditioner, and
    // other operations.)

    // This being done, process zero goes ahead with setting up the output
    // file as in step-8, and attaching the (localized) solution vector to the
    // output object:. (The code to generate the output file name is stolen
    // and slightly modified from step-5, since we expect that we can do a
    // number of cycles greater than 10, which is the maximum of what the code
    // in step-8 could handle.)
    if (this_mpi_process == 0)
      {
        std::ostringstream filename;
        filename << "solution-" << cycle << ".gmv";

        std::ofstream output (filename.str().c_str());

        DataOut<dim> data_out;
        data_out.attach_dof_handler (dof_handler);

        std::vector<std::string> solution_names;
        switch (dim)
          {
          case 1:
            solution_names.push_back ("displacement");
            break;
          case 2:
            solution_names.push_back ("x_displacement");
            solution_names.push_back ("y_displacement");
            break;
          case 3:
            solution_names.push_back ("x_displacement");
            solution_names.push_back ("y_displacement");
            solution_names.push_back ("z_displacement");
            break;
          default:
            Assert (false, ExcInternalError());
          }

        data_out.add_data_vector (localized_solution, solution_names);

        // The only thing we do here additionally is that we also output one
        // value per cell indicating which subdomain (i.e. MPI process) it
        // belongs to. This requires some conversion work, since the data the
        // library provides us with is not the one the output class expects,
        // but this is not difficult. First, set up a vector of integers, one
        // per cell, that is then filled by the number of subdomain each cell
        // is in:
        std::vector<unsigned int> partition_int (triangulation.n_active_cells());
        GridTools::get_subdomain_association (triangulation, partition_int);

        // Then convert this integer vector into a floating point vector just
        // as the output functions want to see:
        const Vector<double> partitioning(partition_int.begin(),
                                          partition_int.end());

        // And finally add this vector as well:
        data_out.add_data_vector (partitioning, "partitioning");

        // This all being done, generate the intermediate format and write it
        // out in GMV output format:
        data_out.build_patches ();
        data_out.write_gmv (output);
      }
  }

  // The sixth step is to take the solution just computed, and evaluate some
  // kind of refinement indicator to refine the mesh. The problem is basically
  // the same as with distributing hanging node constraints: in order to
  // compute the error indicator, we need access to all elements of the
  // solution vector. We then compute the indicators for the cells that belong
  // to the present process, but then we need to distribute the refinement
  // indicators into a distributed vector so that all processes have the
  // values of the refinement indicator for all cells. But then, in order for
  // each process to refine its copy of the mesh, they need to have acces to
  // all refinement indicators locally, so they have to copy the global vector
  // back into a local one. That's a little convoluted, but thinking about it
  // quite straightforward nevertheless. So here's how we do it:
  template <int dim>
  void ElasticProblem<dim>::refine_grid ()
  {
    // So, first part: get a local copy of the distributed solution
    // vector. This is necessary since the error estimator needs to get at the
    // value of neighboring cells even if they do not belong to the subdomain
    // associated with the present MPI process:
    const PETScWrappers::Vector localized_solution (solution);

    // Second part: set up a vector of error indicators for all cells and let
    // the Kelly class compute refinement indicators for all cells belonging
    // to the present subdomain/process. Note that the last argument of the
    // call indicates which subdomain we are interested in. The three
    // arguments before it are various other default arguments that one
    // usually doesn't need (and doesn't state values for, but rather uses the
    // defaults), but which we have to state here explicitly since we want to
    // modify the value of a following argument (i.e. the one indicating the
    // subdomain):
    Vector<float> local_error_per_cell (triangulation.n_active_cells());
    KellyErrorEstimator<dim>::estimate (dof_handler,
                                        QGauss<dim-1>(2),
                                        typename FunctionMap<dim>::type(),
                                        localized_solution,
                                        local_error_per_cell,
                                        ComponentMask(),
                                        0,
                                        multithread_info.n_default_threads,
                                        this_mpi_process);

    // Now all processes have computed error indicators for their own cells
    // and stored them in the respective elements of the
    // local_error_per_cell vector. The elements of this vector
    // for cells not on the present process are zero. However, since all
    // processes have a copy of a copy of the entire triangulation and need to
    // keep these copies in synch, they need the values of refinement
    // indicators for all cells of the triangulation. Thus, we need to
    // distribute our results. We do this by creating a distributed vector
    // where each process has its share, and sets the elements it has
    // computed. We will then later generate a local sequential copy of this
    // distributed vector to allow each process to access all elements of this
    // vector.
    //
    // So in the first step, we need to set up a %parallel vector. For
    // simplicity, every process will own a chunk with as many elements as
    // this process owns cells, so that the first chunk of elements is stored
    // with process zero, the next chunk with process one, and so on. It is
    // important to remark, however, that these elements are not necessarily
    // the ones we will write to. This is so, since the order in which cells
    // are arranged, i.e. the order in which the elements of the vector
    // correspond to cells, is not ordered according to the subdomain these
    // cells belong to. In other words, if on this process we compute
    // indicators for cells of a certain subdomain, we may write the results
    // to more or less random elements if the distributed vector, that do not
    // necessarily lie within the chunk of vector we own on the present
    // process. They will subsequently have to be copied into another
    // process's memory space then, an operation that PETSc does for us when
    // we call the compress function. This inefficiency could be
    // avoided with some more code, but we refrain from it since it is not a
    // major factor in the program's total runtime.
    //
    // So here's how we do it: count how many cells belong to this process,
    // set up a distributed vector with that many elements to be stored
    // locally, and copy over the elements we computed locally, then compress
    // the result. In fact, we really only copy the elements that are nonzero,
    // so we may miss a few that we computed to zero, but this won't hurt
    // since the original values of the vector is zero anyway.
    const unsigned int n_local_cells
      = GridTools::count_cells_with_subdomain_association (triangulation,
                                                           this_mpi_process);
    PETScWrappers::MPI::Vector
    distributed_all_errors (mpi_communicator,
                            triangulation.n_active_cells(),
                            n_local_cells);

    for (unsigned int i=0; i<local_error_per_cell.size(); ++i)
      if (local_error_per_cell(i) != 0)
        distributed_all_errors(i) = local_error_per_cell(i);
    distributed_all_errors.compress (VectorOperation::insert);

    // So now we have this distributed vector out there that contains the
    // refinement indicators for all cells. To use it, we need to obtain a
    // local copy...
    const Vector<float> localized_all_errors (distributed_all_errors);

    // ...which we can the subsequently use to finally refine the grid:
    GridRefinement::refine_and_coarsen_fixed_number (triangulation,
                                                     localized_all_errors,
                                                     0.3, 0.03);
    triangulation.execute_coarsening_and_refinement ();
  }

  // Lastly, here is the driver function. It is almost unchanged from step-8,
  // with the exception that we replace std::cout by the
  // pcout stream. Apart from this, the only other cosmetic
  // change is that we output how many degrees of freedom there are per
  // process, and how many iterations it took for the linear solver to
  // converge:
  template <int dim>
  void ElasticProblem<dim>::run ()
  {
    for (unsigned int cycle=0; cycle<10; ++cycle)
      {
        pcout << "Cycle " << cycle << ':' << std::endl;

        if (cycle == 0)
          {
            GridGenerator::hyper_cube (triangulation, -1, 1);
            triangulation.refine_global (3);
          }
        else
          refine_grid ();

        pcout << "   Number of active cells:       "
              << triangulation.n_active_cells()
              << std::endl;

        setup_system ();

        pcout << "   Number of degrees of freedom: "
              << dof_handler.n_dofs()
              << " (by partition:";
        for (unsigned int p=0; p<n_mpi_processes; ++p)
          pcout << (p==0 ? ' ' : '+')
                << (DoFTools::
                    count_dofs_with_subdomain_association (dof_handler,
                                                           p));
        pcout << ")" << std::endl;

        assemble_system ();
        const unsigned int n_iterations = solve ();

        pcout << "   Solver converged in " << n_iterations
              << " iterations." << std::endl;

        output_results (cycle);
      }
  }
}

// So that's it, almost. main() works the same way as most of the
// main functions in the other example programs, i.e. it delegates work to the
// run function of a master object, and only wraps everything
// into some code to catch exceptions:
int main (int argc, char **argv)
{
  try
    {
      using namespace dealii;
      using namespace Step17;

      // Here is the only real difference: PETSc requires that we initialize
      // it at the beginning of the program, and un-initialize it at the
      // end. The class MPI_InitFinalize takes care of that. The original code
      // sits in between, enclosed in braces to make sure that the
      // elastic_problem variable goes out of scope (and is
      // destroyed) before PETSc is closed with
      // PetscFinalize. (If we wouldn't use braces, the
      // destructor of elastic_problem would run after
      // PetscFinalize; since the destructor involves calls to
      // PETSc functions, we would get strange error messages from PETSc.)
      Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv);

      {
        deallog.depth_console (0);

        ElasticProblem<2> elastic_problem;
        elastic_problem.run ();
      }
    }
  catch (std::exception &exc)
    {
      std::cerr << std::endl << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Exception on processing: " << std::endl
                << exc.what() << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;

      return 1;
    }
  catch (...)
    {
      std::cerr << std::endl << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Unknown exception!" << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;
      return 1;
    }

  return 0;
}