<commit_before>// Ignore unused parameter warnings coming from cppuint headers
#include <libmesh/ignore_warnings.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <libmesh/restore_warnings.h>

#include <libmesh/equation_systems.h>
#include <libmesh/mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/edge_edge2.h>
#include <libmesh/face_quad4.h>
#include <libmesh/cell_hex8.h>
#include <libmesh/dof_map.h>
#include <libmesh/linear_implicit_system.h>
#include <libmesh/mesh_refinement.h>

#include "test_comm.h"

using namespace libMesh;

class SlitFunc : public FEMFunctionBase<Number>
{
public:

  SlitFunc() {}

  ~SlitFunc () {}

  virtual void init_context (const FEMContext &) libmesh_override {}

  virtual UniquePtr<FEMFunctionBase<Number> >
  clone () const libmesh_override
  {
    return UniquePtr<FEMFunctionBase<Number> > (new SlitFunc());
  }

  virtual Number operator() (const FEMContext & c,
                             const Point & p,
                             const Real /*time*/ = 0.)
  libmesh_override
  {
    const Real & x = p(0);
    const Real & y = p(1);
    const Point centroid = c.get_elem().centroid();
    const Real sign = centroid(1)/std::abs(centroid(1));

    return (1 - std::abs(1-x)) * (1-std::abs(y)) * sign;
  }

  virtual void operator() (const FEMContext & c,
                           const Point & p,
                           const Real time,
                           DenseVector<Number> & output)
  libmesh_override
  {
    for (unsigned int i=0; i != output.size(); ++i)
      output(i) = (*this)(c, p, time);
  }
};

class SlitMeshTest : public CppUnit::TestCase {
  /**
   * The goal of this test is to ensure that a 2D mesh with nodes overlapping
   * on opposite sides of an internal, "slit" edge is useable.
   */
public:
  CPPUNIT_TEST_SUITE( SlitMeshTest );

  CPPUNIT_TEST( testMesh );

  CPPUNIT_TEST_SUITE_END();

protected:

  Mesh* _mesh;

  void build_mesh()
  {
    _mesh = new Mesh(*TestCommWorld);

    /*
      (0,1)           (1,1)           (2,1)
        x---------------x---------------x
        |               |               |
        |               |               |
        |               |               |
        |               |               |
        |               |               |
        x---------------x---------------x
       (0,0)           (1,0)          (2,0)
        |               |               |
        |               |               |
        |               |               |
        |               |               |
        x---------------x---------------x
       (0,-1)          (1,-1)         (2,-1)
     */

    _mesh->set_mesh_dimension(2);

    _mesh->add_point( Point(0.0, 0.0), 0 );
    _mesh->add_point( Point(1.0, 0.0), 1 );
    _mesh->add_point( Point(1.0, 1.0), 2 );
    _mesh->add_point( Point(0.0, 1.0), 3 );
    _mesh->add_point( Point(0.0,-1.0), 4 );
    _mesh->add_point( Point(1.0,-1.0), 5 );
    _mesh->add_point( Point(1.0, 0.0), 6 );
    _mesh->add_point( Point(2.0, 0.0), 7 );
    _mesh->add_point( Point(2.0, 1.0), 8 );
    _mesh->add_point( Point(2.0,-1.0), 9 );

    {
      Elem* elem_top_left = new Quad4;
      elem_top_left->set_node(0) = _mesh->node_ptr(0);
      elem_top_left->set_node(1) = _mesh->node_ptr(1);
      elem_top_left->set_node(2) = _mesh->node_ptr(2);
      elem_top_left->set_node(3) = _mesh->node_ptr(3);
      elem_top_left->set_id() = 0;
      _mesh->add_elem(elem_top_left);

      Elem* elem_bottom_left = new Quad4;
      elem_bottom_left->set_node(0) = _mesh->node_ptr(4);
      elem_bottom_left->set_node(1) = _mesh->node_ptr(5);
      elem_bottom_left->set_node(2) = _mesh->node_ptr(6);
      elem_bottom_left->set_node(3) = _mesh->node_ptr(0);
      elem_bottom_left->set_id() = 1;
      _mesh->add_elem(elem_bottom_left);

      Elem* elem_top_right = new Quad4;
      elem_top_right->set_node(0) = _mesh->node_ptr(1);
      elem_top_right->set_node(1) = _mesh->node_ptr(7);
      elem_top_right->set_node(2) = _mesh->node_ptr(8);
      elem_top_right->set_node(3) = _mesh->node_ptr(2);
      elem_top_right->set_id() = 2;
      _mesh->add_elem(elem_top_right);

      Elem* elem_bottom_right = new Quad4;
      elem_bottom_right->set_node(0) = _mesh->node_ptr(5);
      elem_bottom_right->set_node(1) = _mesh->node_ptr(9);
      elem_bottom_right->set_node(2) = _mesh->node_ptr(7);
      elem_bottom_right->set_node(3) = _mesh->node_ptr(6);
      elem_bottom_right->set_id() = 3;
      _mesh->add_elem(elem_bottom_right);
    }

    // libMesh shouldn't renumber, or our based-on-initial-id
    // assertions later may fail.
    _mesh->allow_renumbering(false);

    _mesh->prepare_for_use();
  }

public:
  void setUp()
  {
    this->build_mesh();
  }

  void tearDown()
  {
    delete _mesh;
  }

  void testMesh()
  {
    // There'd better be 4 elements
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)4, _mesh->n_elem() );

    // There'd better still be a full 10 nodes
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)10, _mesh->n_nodes() );

    /* The middle nodes should still be distinct between the top and
     * bottom elements */
    if (_mesh->query_elem_ptr(0) && _mesh->query_elem_ptr(1))
      CPPUNIT_ASSERT( _mesh->elem_ref(0).node_id(1) != _mesh->elem_ref(1).node_id(2) );
    if (_mesh->query_elem_ptr(2) && _mesh->query_elem_ptr(3))
      CPPUNIT_ASSERT( _mesh->elem_ref(2).node_id(0) != _mesh->elem_ref(3).node_id(3) );

    /* The middle nodes should still be shared between left and right
     * elements on top and bottom */
    if (_mesh->query_elem_ptr(0) && _mesh->query_elem_ptr(2))
      CPPUNIT_ASSERT_EQUAL( _mesh->elem_ref(0).node_id(1),
                            _mesh->elem_ref(2).node_id(0) );
    if (_mesh->query_elem_ptr(1) && _mesh->query_elem_ptr(3))
      CPPUNIT_ASSERT_EQUAL( _mesh->elem_ref(1).node_id(2),
                            _mesh->elem_ref(3).node_id(3) );
  }

};

class SlitMeshRefinedMeshTest : public SlitMeshTest {
  /**
   * The goal of this test is the same as the previous, but now we do a
   * uniform refinement and make sure the result mesh is consistent. i.e.
   * the new node shared between the 1D elements is the same as the node
   * shared on the underlying quads, and so on.
   */
public:
  CPPUNIT_TEST_SUITE( SlitMeshRefinedMeshTest );

  CPPUNIT_TEST( testMesh );

  CPPUNIT_TEST_SUITE_END();

  // Yes, this is necessary. Somewhere in those macros is a protected/private
public:

  void setUp()
  {
    this->build_mesh();

#ifdef LIBMESH_ENABLE_AMR
    MeshRefinement(*_mesh).uniformly_refine(1);
#endif
  }

  void testMesh()
  {
#ifdef LIBMESH_ENABLE_AMR
    // We should have 20 total and 16 active elements.
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)20, _mesh->n_elem() );
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)16, _mesh->n_active_elem() );

    // We should have 28 nodes, not 25 or 26
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)28, _mesh->n_nodes() );
#endif
  }
};

class SlitMeshRefinedSystemTest : public SlitMeshTest {
  /**
   * The goal of this test is the same as the previous, but now we
   * create a system and set dof values to make sure they are properly
   * interpolated after refinement.
   */
public:
  CPPUNIT_TEST_SUITE( SlitMeshRefinedSystemTest );

  CPPUNIT_TEST( testMesh );

  CPPUNIT_TEST( testSystem );

#ifdef LIBMESH_ENABLE_UNIQUE_ID
  CPPUNIT_TEST( testRestart );
#endif

  CPPUNIT_TEST_SUITE_END();

protected:

  System* _sys;
  EquationSystems* _es;

public:

  void setUp()
  {
    this->build_mesh();

    // libMesh *should* renumber now, or a ParallelMesh might not have
    // contiguous ids, which is a requirement to write xda files.
    _mesh->allow_renumbering(true);

    _es = new EquationSystems(*_mesh);
    _sys = &_es->add_system<System> ("SimpleSystem");
    _sys->add_variable("u", FIRST);

    _es->init();
    SlitFunc slitfunc;
    _sys->project_solution(&slitfunc);

#ifdef LIBMESH_ENABLE_AMR
    MeshRefinement(*_mesh).uniformly_refine(1);
    _es->reinit();
    MeshRefinement(*_mesh).uniformly_refine(1);
    _es->reinit();
#endif
  }

  void tearDown()
  {
    delete _es;
    // _sys is owned by _es
    delete _mesh;
  }

  void testMesh()
  {
#ifdef LIBMESH_ENABLE_AMR
    // We should have 84 total and 64 active elements.
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)(4+16+64), _mesh->n_elem() );
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)64, _mesh->n_active_elem() );

    // We should have 88 nodes
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)88, _mesh->n_nodes() );
#endif
  }

  void testSystem()
  {
    SlitFunc slitfunc;

    unsigned int dim = 2;

    CPPUNIT_ASSERT_EQUAL( _sys->n_vars(), 1u );

    FEMContext context(*_sys);
    FEBase * fe = NULL;
    context.get_element_fe( 0, fe, dim );
    const std::vector<Point> & xyz = fe->get_xyz();
    fe->get_phi();

    MeshBase::const_element_iterator       el     =
      _mesh->active_local_elements_begin();
    const MeshBase::const_element_iterator end_el =
      _mesh->active_local_elements_end();

    for (; el != end_el; ++el)
      {
        const Elem * elem = *el;
        context.pre_fe_reinit(*_sys, elem);
        context.elem_fe_reinit();

        const unsigned int n_qp = xyz.size();

        for (unsigned int qp=0; qp != n_qp; ++qp)
          {
            const Number exact_val = slitfunc(context, xyz[qp]);

            const Number discrete_val = context.interior_value(0, qp);

            CPPUNIT_ASSERT_DOUBLES_EQUAL(libmesh_real(exact_val),
                                         libmesh_real(discrete_val),
                                         TOLERANCE*TOLERANCE);
          }
      }
  }

  void testRestart()
  {
    SlitFunc slitfunc;

    _mesh->write("slit_mesh.xda");
    _es->write("slit_solution.xda",
               EquationSystems::WRITE_DATA |
               EquationSystems::WRITE_SERIAL_FILES);

    Mesh mesh2(*TestCommWorld);
    mesh2.read("slit_mesh.xda");
    EquationSystems es2(mesh2);
    es2.read("slit_solution.xda");

    System & sys2 = es2.get_system<System> ("SimpleSystem");

    unsigned int dim = 2;

    CPPUNIT_ASSERT_EQUAL( sys2.n_vars(), 1u );

    FEMContext context(sys2);
    FEBase * fe = NULL;
    context.get_element_fe( 0, fe, dim );
    const std::vector<Point> & xyz = fe->get_xyz();
    fe->get_phi();

    MeshBase::const_element_iterator       el     =
      mesh2.active_local_elements_begin();
    const MeshBase::const_element_iterator end_el =
      mesh2.active_local_elements_end();

    for (; el != end_el; ++el)
      {
        const Elem * elem = *el;
        context.pre_fe_reinit(sys2, elem);
        context.elem_fe_reinit();

        const unsigned int n_qp = xyz.size();

        for (unsigned int qp=0; qp != n_qp; ++qp)
          {
            const Number exact_val = slitfunc(context, xyz[qp]);

            const Number discrete_val = context.interior_value(0, qp);

            CPPUNIT_ASSERT_DOUBLES_EQUAL(libmesh_real(exact_val),
                                         libmesh_real(discrete_val),
                                         TOLERANCE*TOLERANCE);
          }
      }
  }
};

CPPUNIT_TEST_SUITE_REGISTRATION( SlitMeshTest );
CPPUNIT_TEST_SUITE_REGISTRATION( SlitMeshRefinedMeshTest );
CPPUNIT_TEST_SUITE_REGISTRATION( SlitMeshRefinedSystemTest );
<commit_msg>Heavier test coverage of unique_id() reads<commit_after>// Ignore unused parameter warnings coming from cppuint headers
#include <libmesh/ignore_warnings.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <libmesh/restore_warnings.h>

#include <libmesh/equation_systems.h>
#include <libmesh/mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/edge_edge2.h>
#include <libmesh/face_quad4.h>
#include <libmesh/cell_hex8.h>
#include <libmesh/dof_map.h>
#include <libmesh/linear_implicit_system.h>
#include <libmesh/mesh_refinement.h>

#include "test_comm.h"

using namespace libMesh;

class SlitFunc : public FEMFunctionBase<Number>
{
public:

  SlitFunc() {}

  ~SlitFunc () {}

  virtual void init_context (const FEMContext &) libmesh_override {}

  virtual UniquePtr<FEMFunctionBase<Number> >
  clone () const libmesh_override
  {
    return UniquePtr<FEMFunctionBase<Number> > (new SlitFunc());
  }

  virtual Number operator() (const FEMContext & c,
                             const Point & p,
                             const Real /*time*/ = 0.)
  libmesh_override
  {
    const Real & x = p(0);
    const Real & y = p(1);
    const Point centroid = c.get_elem().centroid();
    const Real sign = centroid(1)/std::abs(centroid(1));

    return (1 - std::abs(1-x)) * (1-std::abs(y)) * sign;
  }

  virtual void operator() (const FEMContext & c,
                           const Point & p,
                           const Real time,
                           DenseVector<Number> & output)
  libmesh_override
  {
    for (unsigned int i=0; i != output.size(); ++i)
      output(i) = (*this)(c, p, time);
  }
};

class SlitMeshTest : public CppUnit::TestCase {
  /**
   * The goal of this test is to ensure that a 2D mesh with nodes overlapping
   * on opposite sides of an internal, "slit" edge is useable.
   */
public:
  CPPUNIT_TEST_SUITE( SlitMeshTest );

  CPPUNIT_TEST( testMesh );

  CPPUNIT_TEST_SUITE_END();

protected:

  Mesh* _mesh;

  void build_mesh()
  {
    _mesh = new Mesh(*TestCommWorld);

    /*
      (0,1)           (1,1)           (2,1)
        x---------------x---------------x
        |               |               |
        |               |               |
        |               |               |
        |               |               |
        |               |               |
        x---------------x---------------x
       (0,0)           (1,0)          (2,0)
        |               |               |
        |               |               |
        |               |               |
        |               |               |
        x---------------x---------------x
       (0,-1)          (1,-1)         (2,-1)
     */

    _mesh->set_mesh_dimension(2);

    _mesh->add_point( Point(0.0, 0.0), 0 );
    _mesh->add_point( Point(1.0, 0.0), 1 );
    _mesh->add_point( Point(1.0, 1.0), 2 );
    _mesh->add_point( Point(0.0, 1.0), 3 );
    _mesh->add_point( Point(0.0,-1.0), 4 );
    _mesh->add_point( Point(1.0,-1.0), 5 );
    _mesh->add_point( Point(1.0, 0.0), 6 );
    _mesh->add_point( Point(2.0, 0.0), 7 );
    _mesh->add_point( Point(2.0, 1.0), 8 );
    _mesh->add_point( Point(2.0,-1.0), 9 );

    {
      Elem* elem_top_left = new Quad4;
      elem_top_left->set_node(0) = _mesh->node_ptr(0);
      elem_top_left->set_node(1) = _mesh->node_ptr(1);
      elem_top_left->set_node(2) = _mesh->node_ptr(2);
      elem_top_left->set_node(3) = _mesh->node_ptr(3);
      elem_top_left->set_id() = 0;
      _mesh->add_elem(elem_top_left);

      Elem* elem_bottom_left = new Quad4;
      elem_bottom_left->set_node(0) = _mesh->node_ptr(4);
      elem_bottom_left->set_node(1) = _mesh->node_ptr(5);
      elem_bottom_left->set_node(2) = _mesh->node_ptr(6);
      elem_bottom_left->set_node(3) = _mesh->node_ptr(0);
      elem_bottom_left->set_id() = 1;
      _mesh->add_elem(elem_bottom_left);

      Elem* elem_top_right = new Quad4;
      elem_top_right->set_node(0) = _mesh->node_ptr(1);
      elem_top_right->set_node(1) = _mesh->node_ptr(7);
      elem_top_right->set_node(2) = _mesh->node_ptr(8);
      elem_top_right->set_node(3) = _mesh->node_ptr(2);
      elem_top_right->set_id() = 2;
      _mesh->add_elem(elem_top_right);

      Elem* elem_bottom_right = new Quad4;
      elem_bottom_right->set_node(0) = _mesh->node_ptr(5);
      elem_bottom_right->set_node(1) = _mesh->node_ptr(9);
      elem_bottom_right->set_node(2) = _mesh->node_ptr(7);
      elem_bottom_right->set_node(3) = _mesh->node_ptr(6);
      elem_bottom_right->set_id() = 3;
      _mesh->add_elem(elem_bottom_right);
    }

    // libMesh shouldn't renumber, or our based-on-initial-id
    // assertions later may fail.
    _mesh->allow_renumbering(false);

    _mesh->prepare_for_use();
  }

public:
  void setUp()
  {
    this->build_mesh();
  }

  void tearDown()
  {
    delete _mesh;
  }

  void testMesh()
  {
    // There'd better be 4 elements
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)4, _mesh->n_elem() );

    // There'd better still be a full 10 nodes
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)10, _mesh->n_nodes() );

    /* The middle nodes should still be distinct between the top and
     * bottom elements */
    if (_mesh->query_elem_ptr(0) && _mesh->query_elem_ptr(1))
      CPPUNIT_ASSERT( _mesh->elem_ref(0).node_id(1) != _mesh->elem_ref(1).node_id(2) );
    if (_mesh->query_elem_ptr(2) && _mesh->query_elem_ptr(3))
      CPPUNIT_ASSERT( _mesh->elem_ref(2).node_id(0) != _mesh->elem_ref(3).node_id(3) );

    /* The middle nodes should still be shared between left and right
     * elements on top and bottom */
    if (_mesh->query_elem_ptr(0) && _mesh->query_elem_ptr(2))
      CPPUNIT_ASSERT_EQUAL( _mesh->elem_ref(0).node_id(1),
                            _mesh->elem_ref(2).node_id(0) );
    if (_mesh->query_elem_ptr(1) && _mesh->query_elem_ptr(3))
      CPPUNIT_ASSERT_EQUAL( _mesh->elem_ref(1).node_id(2),
                            _mesh->elem_ref(3).node_id(3) );
  }

};

class SlitMeshRefinedMeshTest : public SlitMeshTest {
  /**
   * The goal of this test is the same as the previous, but now we do a
   * uniform refinement and make sure the result mesh is consistent. i.e.
   * the new node shared between the 1D elements is the same as the node
   * shared on the underlying quads, and so on.
   */
public:
  CPPUNIT_TEST_SUITE( SlitMeshRefinedMeshTest );

  CPPUNIT_TEST( testMesh );

  CPPUNIT_TEST_SUITE_END();

  // Yes, this is necessary. Somewhere in those macros is a protected/private
public:

  void setUp()
  {
    this->build_mesh();

#ifdef LIBMESH_ENABLE_AMR
    MeshRefinement(*_mesh).uniformly_refine(1);
#endif
  }

  void testMesh()
  {
#ifdef LIBMESH_ENABLE_AMR
    // We should have 20 total and 16 active elements.
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)20, _mesh->n_elem() );
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)16, _mesh->n_active_elem() );

    // We should have 28 nodes, not 25 or 26
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)28, _mesh->n_nodes() );
#endif
  }
};

class SlitMeshRefinedSystemTest : public SlitMeshTest {
  /**
   * The goal of this test is the same as the previous, but now we
   * create a system and set dof values to make sure they are properly
   * interpolated after refinement.
   */
public:
  CPPUNIT_TEST_SUITE( SlitMeshRefinedSystemTest );

  CPPUNIT_TEST( testMesh );

  CPPUNIT_TEST( testSystem );

#ifdef LIBMESH_ENABLE_UNIQUE_ID
  CPPUNIT_TEST( testRestart );
#endif

  CPPUNIT_TEST_SUITE_END();

protected:

  System* _sys;
  EquationSystems* _es;

public:

  void setUp()
  {
    this->build_mesh();

    // libMesh *should* renumber now, or a ParallelMesh might not have
    // contiguous ids, which is a requirement to write xda files.
    _mesh->allow_renumbering(true);

    _es = new EquationSystems(*_mesh);
    _sys = &_es->add_system<System> ("SimpleSystem");
    _sys->add_variable("u", FIRST);

    _es->init();
    SlitFunc slitfunc;
    _sys->project_solution(&slitfunc);

#ifdef LIBMESH_ENABLE_AMR
    MeshRefinement(*_mesh).uniformly_refine(1);
    _es->reinit();
    MeshRefinement(*_mesh).uniformly_refine(1);
    _es->reinit();
#endif
  }

  void tearDown()
  {
    delete _es;
    // _sys is owned by _es
    delete _mesh;
  }

  void testMesh()
  {
#ifdef LIBMESH_ENABLE_AMR
    // We should have 84 total and 64 active elements.
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)(4+16+64), _mesh->n_elem() );
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)64, _mesh->n_active_elem() );

    // We should have 88 nodes
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)88, _mesh->n_nodes() );
#endif
  }

  void testSystem()
  {
    SlitFunc slitfunc;

    unsigned int dim = 2;

    CPPUNIT_ASSERT_EQUAL( _sys->n_vars(), 1u );

    FEMContext context(*_sys);
    FEBase * fe = NULL;
    context.get_element_fe( 0, fe, dim );
    const std::vector<Point> & xyz = fe->get_xyz();
    fe->get_phi();

    MeshBase::const_element_iterator       el     =
      _mesh->active_local_elements_begin();
    const MeshBase::const_element_iterator end_el =
      _mesh->active_local_elements_end();

    for (; el != end_el; ++el)
      {
        const Elem * elem = *el;
        context.pre_fe_reinit(*_sys, elem);
        context.elem_fe_reinit();

        const unsigned int n_qp = xyz.size();

        for (unsigned int qp=0; qp != n_qp; ++qp)
          {
            const Number exact_val = slitfunc(context, xyz[qp]);

            const Number discrete_val = context.interior_value(0, qp);

            CPPUNIT_ASSERT_DOUBLES_EQUAL(libmesh_real(exact_val),
                                         libmesh_real(discrete_val),
                                         TOLERANCE*TOLERANCE);
          }
      }
  }

  void testRestart()
  {
    SlitFunc slitfunc;

    _mesh->write("slit_mesh.xda");
    _es->write("slit_solution.xda",
               EquationSystems::WRITE_DATA |
               EquationSystems::WRITE_SERIAL_FILES);

    Mesh mesh2(*TestCommWorld);
    mesh2.read("slit_mesh.xda");
    EquationSystems es2(mesh2);
    es2.read("slit_solution.xda");

    System & sys2 = es2.get_system<System> ("SimpleSystem");

    unsigned int dim = 2;

    CPPUNIT_ASSERT_EQUAL( sys2.n_vars(), 1u );

    FEMContext context(sys2);
    FEBase * fe = NULL;
    context.get_element_fe( 0, fe, dim );
    const std::vector<Point> & xyz = fe->get_xyz();
    fe->get_phi();

    // While we're in the middle of a unique id based test case, let's
    // make sure our unique ids were all read in correctly too.
    UniquePtr<PointLocatorBase> locator = _mesh->sub_point_locator();

    MeshBase::const_element_iterator       el     =
      mesh2.active_local_elements_begin();
    const MeshBase::const_element_iterator end_el =
      mesh2.active_local_elements_end();

    for (; el != end_el; ++el)
      {
        const Elem * elem = *el;

        const Elem * mesh1_elem = (*locator)(elem->centroid());
        if (mesh1_elem)
          {
            CPPUNIT_ASSERT_EQUAL( elem->unique_id(),
                                  mesh1_elem->unique_id() );

            for (unsigned int n=0; n != elem->n_nodes(); ++n)
              {
                Node & node       = elem->node_ref(n);
                Node & mesh1_node = mesh1_elem->node_ref(n);
                CPPUNIT_ASSERT_EQUAL( node.unique_id(),
                                      mesh1_node.unique_id() );
              }
          }

        context.pre_fe_reinit(sys2, elem);
        context.elem_fe_reinit();

        const unsigned int n_qp = xyz.size();

        for (unsigned int qp=0; qp != n_qp; ++qp)
          {
            const Number exact_val = slitfunc(context, xyz[qp]);

            const Number discrete_val = context.interior_value(0, qp);

            CPPUNIT_ASSERT_DOUBLES_EQUAL(libmesh_real(exact_val),
                                         libmesh_real(discrete_val),
                                         TOLERANCE*TOLERANCE);
          }
      }
  }
};

CPPUNIT_TEST_SUITE_REGISTRATION( SlitMeshTest );
CPPUNIT_TEST_SUITE_REGISTRATION( SlitMeshRefinedMeshTest );
CPPUNIT_TEST_SUITE_REGISTRATION( SlitMeshRefinedSystemTest );
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "sparse_solver.h"
#include <Eigen/SparseLU>
#include <unsupported/Eigen/SparseExtra>

template<typename T> void test_metis_T()
{
  SparseLU<SparseMatrix<T, ColMajor>, COLAMDOrdering<int> > sparselu_metis;

  check_sparse_square_solving(sparselu_metis);
}

void test_metis_support()
{
  CALL_SUBTEST_1(test_metis_T<double>());
}
<commit_msg>Fix test for Metis<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "sparse_solver.h"
#include <Eigen/SparseLU>
#include <Eigen/MetisSupport>
#include <unsupported/Eigen/SparseExtra>

template<typename T> void test_metis_T()
{
  SparseLU<SparseMatrix<T, ColMajor>, MetisOrdering<int> > sparselu_metis;

  check_sparse_square_solving(sparselu_metis);
}

void test_metis_support()
{
  CALL_SUBTEST_1(test_metis_T<double>());
}
<|endoftext|>


<commit_before>/* Copyright (c) 2015-present Advanced Micro Devices, Inc.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE. */

#include <hip/hip_runtime.h>
#include "hip_internal.hpp"
#include "hip_platform.hpp"
#include "platform/runtime.hpp"
#include "utils/flags.hpp"
#include "utils/versions.hpp"

std::vector<hip::Device*> g_devices;

namespace hip {

thread_local Device* g_device = nullptr;
thread_local std::stack<Device*> g_ctxtStack;
thread_local hipError_t g_lastError = hipSuccess;
std::once_flag g_ihipInitialized;
Device* host_device = nullptr;

void init() {
  if (!amd::Runtime::initialized()) {
    amd::IS_HIP = true;
    GPU_NUM_MEM_DEPENDENCY = 0;
    AMD_DIRECT_DISPATCH = flagIsDefault(AMD_DIRECT_DISPATCH) ? 1 : AMD_DIRECT_DISPATCH;
    amd::Runtime::init();
  }

  const std::vector<amd::Device*>& devices = amd::Device::getDevices(CL_DEVICE_TYPE_GPU, false);

  for (unsigned int i=0; i<devices.size(); i++) {
    const std::vector<amd::Device*> device(1, devices[i]);
    amd::Context* context = new amd::Context(device, amd::Context::Info());
    if (!context) return;

    // Enable active wait on the device by default
    devices[i]->SetActiveWait(true);

    if (context && CL_SUCCESS != context->create(nullptr)) {
      context->release();
    } else {
      g_devices.push_back(new Device(context, i));
    }
  }

  amd::Context* hContext = new amd::Context(devices, amd::Context::Info());
  if (!hContext) return;

  if (CL_SUCCESS != hContext->create(nullptr)) {
    hContext->release();
  }
  host_device = new Device(hContext, -1);

  PlatformState::instance().init();
}

Device* getCurrentDevice() {
  return g_device;
}

void setCurrentDevice(unsigned int index) {
  assert(index<g_devices.size());
  g_device = g_devices[index];
}

amd::HostQueue* getQueue(hipStream_t stream) {
 if (stream == nullptr) {
    return getNullStream();
  } else {
    constexpr bool WaitNullStreamOnly = true;
    amd::HostQueue* queue = reinterpret_cast<hip::Stream*>(stream)->asHostQueue();
    if (!(reinterpret_cast<hip::Stream*>(stream)->Flags() & hipStreamNonBlocking)) {
      iHipWaitActiveStreams(queue, WaitNullStreamOnly);
    }
    return queue;
  }
}

// ================================================================================================
amd::HostQueue* getNullStream(amd::Context& ctx) {
  for (auto& it : g_devices) {
    if (it->asContext() == &ctx) {
      return it->NullStream();
    }
  }
  // If it's a pure SVM allocation with system memory access, then it shouldn't matter which device
  // runtime selects by default
  if (hip::host_device->asContext() == &ctx) {
    // Return current...
    return getNullStream();
  }
  return nullptr;
}

// ================================================================================================
amd::HostQueue* getNullStream() {
  Device* device = getCurrentDevice();
  return device ? device->NullStream() : nullptr;
}

};

using namespace hip;

hipError_t hipInit(unsigned int flags) {
  HIP_INIT_API(hipInit, flags);

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxCreate(hipCtx_t *ctx, unsigned int flags,  hipDevice_t device) {
  HIP_INIT_API(hipCtxCreate, ctx, flags, device);

  if (static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  *ctx = reinterpret_cast<hipCtx_t>(g_devices[device]);

  // Increment ref count for device primary context
  g_devices[device]->retain();
  g_ctxtStack.push(g_devices[device]);

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxSetCurrent(hipCtx_t ctx) {
  HIP_INIT_API(hipCtxSetCurrent, ctx);

  if (ctx == nullptr) {
    if(!g_ctxtStack.empty()) {
      g_ctxtStack.pop();
    }
  } else {
    hip::g_device = reinterpret_cast<hip::Device*>(ctx);
    if(!g_ctxtStack.empty()) {
      g_ctxtStack.pop();
    }
    g_ctxtStack.push(hip::getCurrentDevice());
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxGetCurrent(hipCtx_t* ctx) {
  HIP_INIT_API(hipCtxGetCurrent, ctx);

  *ctx = reinterpret_cast<hipCtx_t>(hip::getCurrentDevice());

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxGetSharedMemConfig(hipSharedMemConfig* pConfig) {
  HIP_INIT_API(hipCtxGetSharedMemConfig, pConfig);

  *pConfig = hipSharedMemBankSizeFourByte;

  HIP_RETURN(hipSuccess);
}

hipError_t hipRuntimeGetVersion(int *runtimeVersion) {
  HIP_INIT_API(hipRuntimeGetVersion, runtimeVersion);

  if (!runtimeVersion) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  // HIP_VERSION = HIP_VERSION_MAJOR*100 + HIP_MINOR_VERSION
  *runtimeVersion = HIP_VERSION;

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxDestroy(hipCtx_t ctx) {
  HIP_INIT_API(hipCtxDestroy, ctx);

  hip::Device* dev = reinterpret_cast<hip::Device*>(ctx);
  if (dev == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  // Need to remove the ctx of calling thread if its the top one
  if (!g_ctxtStack.empty() && g_ctxtStack.top() == dev) {
    g_ctxtStack.pop();
  }

  // Remove context from global context list
  for (unsigned int i = 0; i < g_devices.size(); i++) {
    if (g_devices[i] == dev) {
      // Decrement ref count for device primary context
      dev->release();
    }
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxPopCurrent(hipCtx_t* ctx) {
  HIP_INIT_API(hipCtxPopCurrent, ctx);

  hip::Device** dev = reinterpret_cast<hip::Device**>(ctx);
  if (!g_ctxtStack.empty()) {
    if (dev != nullptr) {
      *dev = g_ctxtStack.top();
    }
    g_ctxtStack.pop();
  } else {
    DevLogError("Context Stack empty \n");
    HIP_RETURN(hipErrorInvalidContext);
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxPushCurrent(hipCtx_t ctx) {
  HIP_INIT_API(hipCtxPushCurrent, ctx);

  hip::Device* dev = reinterpret_cast<hip::Device*>(ctx);
  if (dev == nullptr) {
    HIP_RETURN(hipErrorInvalidContext);
  }

  hip::g_device = dev;
  g_ctxtStack.push(hip::getCurrentDevice());

  HIP_RETURN(hipSuccess);
}

hipError_t hipDriverGetVersion(int* driverVersion) {
  HIP_INIT_API(hipDriverGetVersion, driverVersion);

  auto* deviceHandle = g_devices[0]->devices()[0];
  const auto& info = deviceHandle->info();

  if (driverVersion) {
    *driverVersion = AMD_PLATFORM_BUILD_NUMBER * 100 +
                     AMD_PLATFORM_REVISION_NUMBER;
  } else {
    HIP_RETURN(hipErrorInvalidValue);
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxGetDevice(hipDevice_t* device) {
  HIP_INIT_API(hipCtxGetDevice, device);

  if (device != nullptr) {
    *device = hip::getCurrentDevice()->deviceId();
    HIP_RETURN(hipSuccess);
  } else {
    HIP_RETURN(hipErrorInvalidValue);
  }

  HIP_RETURN(hipErrorInvalidContext);
}

hipError_t hipCtxGetApiVersion(hipCtx_t ctx, int* apiVersion) {
  HIP_INIT_API(hipCtxGetApiVersion, apiVersion);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorNotSupported);
}

hipError_t hipCtxGetCacheConfig(hipFuncCache_t* cacheConfig) {
  HIP_INIT_API(hipCtxGetCacheConfig, cacheConfig);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorNotSupported);
}

hipError_t hipCtxSetCacheConfig(hipFuncCache_t cacheConfig) {
  HIP_INIT_API(hipCtxSetCacheConfig, cacheConfig);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorNotSupported);
}

hipError_t hipCtxSetSharedMemConfig(hipSharedMemConfig config) {
  HIP_INIT_API(hipCtxSetSharedMemConfig, config);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorNotSupported);
}

hipError_t hipCtxSynchronize(void) {
  HIP_INIT_API(hipCtxSynchronize, 1);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorNotSupported);
}

hipError_t hipCtxGetFlags(unsigned int* flags) {
  HIP_INIT_API(hipCtxGetFlags, flags);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorNotSupported);
}

hipError_t hipDevicePrimaryCtxGetState(hipDevice_t dev, unsigned int* flags, int* active) {
  HIP_INIT_API(hipDevicePrimaryCtxGetState, dev, flags, active);

  if (static_cast<unsigned int>(dev) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (flags != nullptr) {
    *flags = 0;
  }

  if (active != nullptr) {
    *active = (g_devices[dev] == hip::getCurrentDevice())? 1 : 0;
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipDevicePrimaryCtxRelease(hipDevice_t dev) {
  HIP_INIT_API(hipDevicePrimaryCtxRelease, dev);

  if (static_cast<unsigned int>(dev) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipDevicePrimaryCtxRetain(hipCtx_t* pctx, hipDevice_t dev) {
  HIP_INIT_API(hipDevicePrimaryCtxRetain, pctx, dev);

  if (static_cast<unsigned int>(dev) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }
  if (pctx == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  *pctx = reinterpret_cast<hipCtx_t>(g_devices[dev]);

  HIP_RETURN(hipSuccess);
}

hipError_t hipDevicePrimaryCtxReset(hipDevice_t dev) {
  HIP_INIT_API(hipDevicePrimaryCtxReset, dev);

  HIP_RETURN(hipSuccess);
}

hipError_t hipDevicePrimaryCtxSetFlags(hipDevice_t dev, unsigned int flags) {
  HIP_INIT_API(hipDevicePrimaryCtxSetFlags, dev, flags);

  if (static_cast<unsigned int>(dev) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  } else {
    HIP_RETURN(hipErrorContextAlreadyInUse);
  }
}
<commit_msg>SWDEV-244287 - Keep direct dispatch for Linux only<commit_after>/* Copyright (c) 2015-present Advanced Micro Devices, Inc.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE. */

#include <hip/hip_runtime.h>
#include "hip_internal.hpp"
#include "hip_platform.hpp"
#include "platform/runtime.hpp"
#include "utils/flags.hpp"
#include "utils/versions.hpp"

std::vector<hip::Device*> g_devices;

namespace hip {

thread_local Device* g_device = nullptr;
thread_local std::stack<Device*> g_ctxtStack;
thread_local hipError_t g_lastError = hipSuccess;
std::once_flag g_ihipInitialized;
Device* host_device = nullptr;

void init() {
  if (!amd::Runtime::initialized()) {
    amd::IS_HIP = true;
    GPU_NUM_MEM_DEPENDENCY = 0;
    AMD_DIRECT_DISPATCH = flagIsDefault(AMD_DIRECT_DISPATCH) ? IS_LINUX : AMD_DIRECT_DISPATCH;
    amd::Runtime::init();
  }

  const std::vector<amd::Device*>& devices = amd::Device::getDevices(CL_DEVICE_TYPE_GPU, false);

  for (unsigned int i=0; i<devices.size(); i++) {
    const std::vector<amd::Device*> device(1, devices[i]);
    amd::Context* context = new amd::Context(device, amd::Context::Info());
    if (!context) return;

    // Enable active wait on the device by default
    devices[i]->SetActiveWait(true);

    if (context && CL_SUCCESS != context->create(nullptr)) {
      context->release();
    } else {
      g_devices.push_back(new Device(context, i));
    }
  }

  amd::Context* hContext = new amd::Context(devices, amd::Context::Info());
  if (!hContext) return;

  if (CL_SUCCESS != hContext->create(nullptr)) {
    hContext->release();
  }
  host_device = new Device(hContext, -1);

  PlatformState::instance().init();
}

Device* getCurrentDevice() {
  return g_device;
}

void setCurrentDevice(unsigned int index) {
  assert(index<g_devices.size());
  g_device = g_devices[index];
}

amd::HostQueue* getQueue(hipStream_t stream) {
 if (stream == nullptr) {
    return getNullStream();
  } else {
    constexpr bool WaitNullStreamOnly = true;
    amd::HostQueue* queue = reinterpret_cast<hip::Stream*>(stream)->asHostQueue();
    if (!(reinterpret_cast<hip::Stream*>(stream)->Flags() & hipStreamNonBlocking)) {
      iHipWaitActiveStreams(queue, WaitNullStreamOnly);
    }
    return queue;
  }
}

// ================================================================================================
amd::HostQueue* getNullStream(amd::Context& ctx) {
  for (auto& it : g_devices) {
    if (it->asContext() == &ctx) {
      return it->NullStream();
    }
  }
  // If it's a pure SVM allocation with system memory access, then it shouldn't matter which device
  // runtime selects by default
  if (hip::host_device->asContext() == &ctx) {
    // Return current...
    return getNullStream();
  }
  return nullptr;
}

// ================================================================================================
amd::HostQueue* getNullStream() {
  Device* device = getCurrentDevice();
  return device ? device->NullStream() : nullptr;
}

};

using namespace hip;

hipError_t hipInit(unsigned int flags) {
  HIP_INIT_API(hipInit, flags);

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxCreate(hipCtx_t *ctx, unsigned int flags,  hipDevice_t device) {
  HIP_INIT_API(hipCtxCreate, ctx, flags, device);

  if (static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  *ctx = reinterpret_cast<hipCtx_t>(g_devices[device]);

  // Increment ref count for device primary context
  g_devices[device]->retain();
  g_ctxtStack.push(g_devices[device]);

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxSetCurrent(hipCtx_t ctx) {
  HIP_INIT_API(hipCtxSetCurrent, ctx);

  if (ctx == nullptr) {
    if(!g_ctxtStack.empty()) {
      g_ctxtStack.pop();
    }
  } else {
    hip::g_device = reinterpret_cast<hip::Device*>(ctx);
    if(!g_ctxtStack.empty()) {
      g_ctxtStack.pop();
    }
    g_ctxtStack.push(hip::getCurrentDevice());
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxGetCurrent(hipCtx_t* ctx) {
  HIP_INIT_API(hipCtxGetCurrent, ctx);

  *ctx = reinterpret_cast<hipCtx_t>(hip::getCurrentDevice());

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxGetSharedMemConfig(hipSharedMemConfig* pConfig) {
  HIP_INIT_API(hipCtxGetSharedMemConfig, pConfig);

  *pConfig = hipSharedMemBankSizeFourByte;

  HIP_RETURN(hipSuccess);
}

hipError_t hipRuntimeGetVersion(int *runtimeVersion) {
  HIP_INIT_API(hipRuntimeGetVersion, runtimeVersion);

  if (!runtimeVersion) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  // HIP_VERSION = HIP_VERSION_MAJOR*100 + HIP_MINOR_VERSION
  *runtimeVersion = HIP_VERSION;

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxDestroy(hipCtx_t ctx) {
  HIP_INIT_API(hipCtxDestroy, ctx);

  hip::Device* dev = reinterpret_cast<hip::Device*>(ctx);
  if (dev == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  // Need to remove the ctx of calling thread if its the top one
  if (!g_ctxtStack.empty() && g_ctxtStack.top() == dev) {
    g_ctxtStack.pop();
  }

  // Remove context from global context list
  for (unsigned int i = 0; i < g_devices.size(); i++) {
    if (g_devices[i] == dev) {
      // Decrement ref count for device primary context
      dev->release();
    }
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxPopCurrent(hipCtx_t* ctx) {
  HIP_INIT_API(hipCtxPopCurrent, ctx);

  hip::Device** dev = reinterpret_cast<hip::Device**>(ctx);
  if (!g_ctxtStack.empty()) {
    if (dev != nullptr) {
      *dev = g_ctxtStack.top();
    }
    g_ctxtStack.pop();
  } else {
    DevLogError("Context Stack empty \n");
    HIP_RETURN(hipErrorInvalidContext);
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxPushCurrent(hipCtx_t ctx) {
  HIP_INIT_API(hipCtxPushCurrent, ctx);

  hip::Device* dev = reinterpret_cast<hip::Device*>(ctx);
  if (dev == nullptr) {
    HIP_RETURN(hipErrorInvalidContext);
  }

  hip::g_device = dev;
  g_ctxtStack.push(hip::getCurrentDevice());

  HIP_RETURN(hipSuccess);
}

hipError_t hipDriverGetVersion(int* driverVersion) {
  HIP_INIT_API(hipDriverGetVersion, driverVersion);

  auto* deviceHandle = g_devices[0]->devices()[0];
  const auto& info = deviceHandle->info();

  if (driverVersion) {
    *driverVersion = AMD_PLATFORM_BUILD_NUMBER * 100 +
                     AMD_PLATFORM_REVISION_NUMBER;
  } else {
    HIP_RETURN(hipErrorInvalidValue);
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxGetDevice(hipDevice_t* device) {
  HIP_INIT_API(hipCtxGetDevice, device);

  if (device != nullptr) {
    *device = hip::getCurrentDevice()->deviceId();
    HIP_RETURN(hipSuccess);
  } else {
    HIP_RETURN(hipErrorInvalidValue);
  }

  HIP_RETURN(hipErrorInvalidContext);
}

hipError_t hipCtxGetApiVersion(hipCtx_t ctx, int* apiVersion) {
  HIP_INIT_API(hipCtxGetApiVersion, apiVersion);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorNotSupported);
}

hipError_t hipCtxGetCacheConfig(hipFuncCache_t* cacheConfig) {
  HIP_INIT_API(hipCtxGetCacheConfig, cacheConfig);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorNotSupported);
}

hipError_t hipCtxSetCacheConfig(hipFuncCache_t cacheConfig) {
  HIP_INIT_API(hipCtxSetCacheConfig, cacheConfig);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorNotSupported);
}

hipError_t hipCtxSetSharedMemConfig(hipSharedMemConfig config) {
  HIP_INIT_API(hipCtxSetSharedMemConfig, config);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorNotSupported);
}

hipError_t hipCtxSynchronize(void) {
  HIP_INIT_API(hipCtxSynchronize, 1);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorNotSupported);
}

hipError_t hipCtxGetFlags(unsigned int* flags) {
  HIP_INIT_API(hipCtxGetFlags, flags);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorNotSupported);
}

hipError_t hipDevicePrimaryCtxGetState(hipDevice_t dev, unsigned int* flags, int* active) {
  HIP_INIT_API(hipDevicePrimaryCtxGetState, dev, flags, active);

  if (static_cast<unsigned int>(dev) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (flags != nullptr) {
    *flags = 0;
  }

  if (active != nullptr) {
    *active = (g_devices[dev] == hip::getCurrentDevice())? 1 : 0;
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipDevicePrimaryCtxRelease(hipDevice_t dev) {
  HIP_INIT_API(hipDevicePrimaryCtxRelease, dev);

  if (static_cast<unsigned int>(dev) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipDevicePrimaryCtxRetain(hipCtx_t* pctx, hipDevice_t dev) {
  HIP_INIT_API(hipDevicePrimaryCtxRetain, pctx, dev);

  if (static_cast<unsigned int>(dev) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }
  if (pctx == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  *pctx = reinterpret_cast<hipCtx_t>(g_devices[dev]);

  HIP_RETURN(hipSuccess);
}

hipError_t hipDevicePrimaryCtxReset(hipDevice_t dev) {
  HIP_INIT_API(hipDevicePrimaryCtxReset, dev);

  HIP_RETURN(hipSuccess);
}

hipError_t hipDevicePrimaryCtxSetFlags(hipDevice_t dev, unsigned int flags) {
  HIP_INIT_API(hipDevicePrimaryCtxSetFlags, dev, flags);

  if (static_cast<unsigned int>(dev) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  } else {
    HIP_RETURN(hipErrorContextAlreadyInUse);
  }
}
<|endoftext|>


<commit_before>// $Id$
//
//  Copyright (C) 2003-2011 Greg Landrum and Rational Discovery LLC
//
//   @@ All Rights Reserved @@
//  This file is part of the RDKit.
//  The contents are covered by the terms of the BSD license
//  which is included in the file license.txt, found at the root
//  of the RDKit source tree.
//

#define NO_IMPORT_ARRAY
#include <boost/python.hpp>
#include <string>

//ours
#include <GraphMol/FileParsers/MolWriters.h>
#include <GraphMol/RDKitBase.h>
#include "rdchem.h"
#include <RDBoost/PySequenceHolder.h>
#include <RDBoost/python_streambuf.h>

namespace python = boost::python;
using boost_adaptbx::python::streambuf;

namespace RDKit {
  SDWriter *getSDWriter(python::object &fileobj){
    // FIX: minor leak here
    streambuf *sb=new streambuf(fileobj);
    streambuf::ostream *ost=new streambuf::ostream(*sb);
    return new SDWriter(ost,true);
  }

  void SetSDWriterProps(SDWriter &writer, python::object props) {
    // convert the python list to a STR_VECT
    STR_VECT propNames;
    PySequenceHolder<std::string> seq(props);
    for (unsigned int i = 0; i < seq.size(); i++) {
      propNames.push_back(seq[i]);
    }
    writer.setProps(propNames);
  }
  void WriteMolToSD(SDWriter &writer, ROMol &mol, int confId) {
    writer.write(mol, confId);
  }

  struct sdwriter_wrap {
    static void wrap() {
      std::string docStr="A class for writing molecules to SD files.\n\
\n\
  Usage examples:\n\
\n\
    1) writing to a named file:\n\
       >>> writer = SDWriter('out.sdf')\n\
       >>> for mol in list_of_mols:\n\
       ...    writer.write(mol)\n\
\n\
    2) writing to a file-like object: \n\
       >>> import gzip\n\
       >>> outf=gzip.open('out.sdf.gz','w+')\n\
       >>> writer = ForwardSDMolSupplier(outf)\n\
       >>> for mol in list_of_mols:\n \
       ...   writer.write(mol)\n\
\n\
  By default all non-private molecular properties are written to the SD file.\n\
  This can be changed using the SetProps method:\n\
       >>> writer = SDWriter('out.sdf')\n\
       >>> writer.SetProps(['prop1','prop2'])\n\
\n";
      python::class_<SDWriter,
		     boost::noncopyable>("SDWriter",
					 docStr.c_str(),
					 python::no_init)
        .def("__init__", python::make_constructor(&getSDWriter))
	.def(python::init<std::string>(python::args("fileName"),
				       "Constructor.\n\n"
				       "   If a string argument is provided, it will be treated as the name of the output file.\n"
				       "   If a file-like object is provided, output will be sent there.\n\n"))
	.def("SetProps", SetSDWriterProps,
	     "Sets the properties to be written to the output file\n\n"
	     "  ARGUMENTS:\n\n"
	     "    - props: a list or tuple of property names\n\n")
	.def("write", WriteMolToSD,
             (python::arg("self"), python::arg("mol"), python::arg("confId")=-1),
	     "Writes a molecule to the output file.\n\n"
	     "  ARGUMENTS:\n\n"
	     "    - mol: the Mol to be written\n"
             "    - confId: (optional) ID of the conformation to write\n\n")
	.def("flush", &SDWriter::flush,
	     "Flushes the output file (forces the disk file to be updated).\n\n"
	     )
	.def("close", &SDWriter::close,
	     "Flushes the output file and closes it. The Writer cannot be used after this.\n\n"
	     )
	.def("NumMols", &SDWriter::numMols,
	     "Returns the number of molecules written so far.\n\n"
	     )
	;
    };
  };
}

void wrap_sdwriter() {
  RDKit::sdwriter_wrap::wrap();
}
<commit_msg>docs fix<commit_after>// $Id$
//
//  Copyright (C) 2003-2011 Greg Landrum and Rational Discovery LLC
//
//   @@ All Rights Reserved @@
//  This file is part of the RDKit.
//  The contents are covered by the terms of the BSD license
//  which is included in the file license.txt, found at the root
//  of the RDKit source tree.
//

#define NO_IMPORT_ARRAY
#include <boost/python.hpp>
#include <string>

//ours
#include <GraphMol/FileParsers/MolWriters.h>
#include <GraphMol/RDKitBase.h>
#include "rdchem.h"
#include <RDBoost/PySequenceHolder.h>
#include <RDBoost/python_streambuf.h>

namespace python = boost::python;
using boost_adaptbx::python::streambuf;

namespace RDKit {
  SDWriter *getSDWriter(python::object &fileobj){
    // FIX: minor leak here
    streambuf *sb=new streambuf(fileobj);
    streambuf::ostream *ost=new streambuf::ostream(*sb);
    return new SDWriter(ost,true);
  }

  void SetSDWriterProps(SDWriter &writer, python::object props) {
    // convert the python list to a STR_VECT
    STR_VECT propNames;
    PySequenceHolder<std::string> seq(props);
    for (unsigned int i = 0; i < seq.size(); i++) {
      propNames.push_back(seq[i]);
    }
    writer.setProps(propNames);
  }
  void WriteMolToSD(SDWriter &writer, ROMol &mol, int confId) {
    writer.write(mol, confId);
  }

  struct sdwriter_wrap {
    static void wrap() {
      std::string docStr="A class for writing molecules to SD files.\n\
\n\
  Usage examples:\n\
\n\
    1) writing to a named file:\n\
       >>> writer = SDWriter('out.sdf')\n\
       >>> for mol in list_of_mols:\n\
       ...    writer.write(mol)\n\
\n\
    2) writing to a file-like object: \n\
       >>> import gzip\n\
       >>> outf=gzip.open('out.sdf.gz','w+')\n\
       >>> writer = SDWriter(outf)\n\
       >>> for mol in list_of_mols:\n \
       ...   writer.write(mol)\n\
       >>> writer.close()\n\
       >>> outf.close()\n\
\n\
  By default all non-private molecular properties are written to the SD file.\n\
  This can be changed using the SetProps method:\n\
       >>> writer = SDWriter('out.sdf')\n\
       >>> writer.SetProps(['prop1','prop2'])\n\
\n";
      python::class_<SDWriter,
		     boost::noncopyable>("SDWriter",
					 docStr.c_str(),
					 python::no_init)
        .def("__init__", python::make_constructor(&getSDWriter))
	.def(python::init<std::string>(python::args("fileName"),
				       "Constructor.\n\n"
				       "   If a string argument is provided, it will be treated as the name of the output file.\n"
				       "   If a file-like object is provided, output will be sent there.\n\n"))
	.def("SetProps", SetSDWriterProps,
	     "Sets the properties to be written to the output file\n\n"
	     "  ARGUMENTS:\n\n"
	     "    - props: a list or tuple of property names\n\n")
	.def("write", WriteMolToSD,
             (python::arg("self"), python::arg("mol"), python::arg("confId")=-1),
	     "Writes a molecule to the output file.\n\n"
	     "  ARGUMENTS:\n\n"
	     "    - mol: the Mol to be written\n"
             "    - confId: (optional) ID of the conformation to write\n\n")
	.def("flush", &SDWriter::flush,
	     "Flushes the output file (forces the disk file to be updated).\n\n"
	     )
	.def("close", &SDWriter::close,
	     "Flushes the output file and closes it. The Writer cannot be used after this.\n\n"
	     )
	.def("NumMols", &SDWriter::numMols,
	     "Returns the number of molecules written so far.\n\n"
	     )
	;
    };
  };
}

void wrap_sdwriter() {
  RDKit::sdwriter_wrap::wrap();
}
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                            OpenSenseUtilities.cpp                          *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2019 Stanford University and the Authors                *
 * Author(s): OpenSim Team                                                    *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */
#include <OpenSim/Common/STOFileAdapter.h>
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Simulation/MarkersReference.h>
#include <OpenSim/Simulation/InverseKinematicsSolver.h>
#include "OpenSenseUtilities.h"

using namespace OpenSim;
using namespace SimTK;
using namespace std;

TimeSeriesTable_<SimTK::Rotation> OpenSenseUtilities::
    convertQuaternionsToRotations(
        const TimeSeriesTableQuaternion& qauternionsTable,
        std::tuple<size_t, size_t> startEnd)
{
    // Fixed transform to rotate sensor orientations in world with Z up into the
    // OpenSim ground reference frame with Y up and X forward.
    SimTK::Rotation R_XG = SimTK::Rotation(
        SimTK::BodyOrSpaceType::BodyRotationSequence,
        -SimTK_PI / 2, SimTK::XAxis,
        0, SimTK::YAxis,
        0, SimTK::ZAxis);

    // OpenSim to the local reference frame of the pelvis (back)
    //SimTK::Rotation R_XG(SimTK::BodyOrSpaceType::BodyRotationSequence,
    //    SimTK::Pi / 2, SimTK::ZAxis,
    //    SimTK::Pi / 2, SimTK::XAxis,
    //    0., SimTK::ZAxis);

    //SimTK::Vec3 grav(9.807, 0., 0.);
    //double theta = acos(avg_accel.transpose() * grav / (avg_accel.norm() * grav.norm()));
    //SimTK::Vec3 C = SimTK::cross(avg_accel, grav);
    //C = C / C.norm();

    //SimTK::Rotation tilt_correction = SimTK::Rotation(axisAngleToRotation(C, theta));
    //R_XG = R_XG * tilt_correction;

    int nc = int(qauternionsTable.getNumColumns());

    const auto& times = qauternionsTable.getIndependentColumn();

    size_t nt = std::get<1>(startEnd) - std::get<0>(startEnd) + 1;

    std::vector<double> newTimes(nt, SimTK::NaN);
    SimTK::Matrix_<SimTK::Rotation> matrix(int(nt), nc, Rotation());

    int cnt = 0;
    for (size_t i = std::get<0>(startEnd); i <= std::get<1>(startEnd); ++i) {
        newTimes[cnt] = times[i];
        const auto& quatRow = qauternionsTable.getRowAtIndex(i);
        for (int j = 0; j < nc; ++j) {
            const Quaternion& quatO = quatRow[j];
            matrix.updElt(cnt, j) = R_XG*Rotation(quatO);
        }
        cnt++;
    }

    TimeSeriesTable_<SimTK::Rotation> orientationTable(newTimes,
        matrix,
        qauternionsTable.getColumnLabels());
    orientationTable.updTableMetaData() = qauternionsTable.getTableMetaData();
    orientationTable.setDependentsMetaData(qauternionsTable.getDependentsMetaData());

    // Base will rotate to match <base>_imu, so we must first remove the base
    // rotation from the other IMUs to get their orientation with respect to
    // individual model bodies and thereby compute correct offsets unbiased by the
    // initial base orientation.
    auto imuLabels = orientationTable.getColumnLabels();
    auto pix = distance(imuLabels.begin(), std::find(imuLabels.begin(), imuLabels.end(), "pelvis_imu")); //torso_imu
    auto startRow = orientationTable.getRowAtIndex(0);
    const Rotation& base_R = startRow.getElt(0, int(pix));

    //// Heading direction of the base IMU in this case the pelvis_imu heading is its ZAxis
    UnitVec3 pelvisHeading = base_R(SimTK::ZAxis);
    UnitVec3 groundX = UnitVec3(1, 0, 0);
    SimTK::Real angularDifference = acos(~pelvisHeading*groundX);

    // If the forward axis actually is the backward axis, change direction by 180 degrees
    if (angularDifference >= SimTK_PI / 2) {
        if (angularDifference >= 0) {
            angularDifference -= SimTK_PI;
        }
        else if (angularDifference <= -SimTK_PI / 2) {
            angularDifference += SimTK_PI;
        }
    }

    std::cout << "Heading correction computed to be "
        << angularDifference * SimTK_RADIAN_TO_DEGREE
        << "degs about ground Y" << std::endl;

    SimTK::Rotation R_HG = SimTK::Rotation(
        SimTK::BodyOrSpaceType::SpaceRotationSequence,
        0, SimTK::XAxis,
        angularDifference, SimTK::YAxis,
        0, SimTK::ZAxis
    );

    for (size_t i = 0; i < orientationTable.getNumRows(); ++i) {
        auto& rotationsRow = orientationTable.updRowAtIndex(i);
        for (int j = 0; j < nc; ++j) {
            rotationsRow[j] = R_HG*rotationsRow[j];
        }
    }

    return orientationTable;
}
<commit_msg>Fix compilatopn error in gcc<commit_after>/* -------------------------------------------------------------------------- *
 *                            OpenSenseUtilities.cpp                          *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2019 Stanford University and the Authors                *
 * Author(s): OpenSim Team                                                    *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */
#include <OpenSim/Common/STOFileAdapter.h>
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Simulation/MarkersReference.h>
#include <OpenSim/Simulation/InverseKinematicsSolver.h>
#include "OpenSenseUtilities.h"

using namespace OpenSim;
using namespace SimTK;
using namespace std;

TimeSeriesTable_<SimTK::Rotation> OpenSenseUtilities::
    convertQuaternionsToRotations(
        const TimeSeriesTableQuaternion& qauternionsTable,
        std::tuple<size_t, size_t> startEnd)
{
    // Fixed transform to rotate sensor orientations in world with Z up into the
    // OpenSim ground reference frame with Y up and X forward.
    SimTK::Rotation R_XG = SimTK::Rotation(
        SimTK::BodyOrSpaceType::BodyRotationSequence,
        -SimTK_PI / 2, SimTK::XAxis,
        0, SimTK::YAxis,
        0, SimTK::ZAxis);

    // OpenSim to the local reference frame of the pelvis (back)
    //SimTK::Rotation R_XG(SimTK::BodyOrSpaceType::BodyRotationSequence,
    //    SimTK::Pi / 2, SimTK::ZAxis,
    //    SimTK::Pi / 2, SimTK::XAxis,
    //    0., SimTK::ZAxis);

    //SimTK::Vec3 grav(9.807, 0., 0.);
    //double theta = acos(avg_accel.transpose() * grav / (avg_accel.norm() * grav.norm()));
    //SimTK::Vec3 C = SimTK::cross(avg_accel, grav);
    //C = C / C.norm();

    //SimTK::Rotation tilt_correction = SimTK::Rotation(axisAngleToRotation(C, theta));
    //R_XG = R_XG * tilt_correction;

    int nc = int(qauternionsTable.getNumColumns());

    const auto& times = qauternionsTable.getIndependentColumn();

    size_t nt = std::get<1>(startEnd) - std::get<0>(startEnd) + 1;

    std::vector<double> newTimes(nt, SimTK::NaN);
    SimTK::Matrix_<SimTK::Rotation> matrix(int(nt), nc, Rotation());

    int cnt = 0;
    for (size_t i = std::get<0>(startEnd); i <= std::get<1>(startEnd); ++i) {
        newTimes[cnt] = times[i];
        const auto& quatRow = qauternionsTable.getRowAtIndex(i);
        for (int j = 0; j < nc; ++j) {
            const Quaternion& quatO = quatRow[j];
            matrix.updElt(cnt, j) = R_XG*Rotation(quatO);
        }
        cnt++;
    }

    TimeSeriesTable_<SimTK::Rotation> orientationTable(newTimes,
        matrix,
        qauternionsTable.getColumnLabels());
    orientationTable.updTableMetaData() = qauternionsTable.getTableMetaData();
    orientationTable.setDependentsMetaData(qauternionsTable.getDependentsMetaData());

    // Base will rotate to match <base>_imu, so we must first remove the base
    // rotation from the other IMUs to get their orientation with respect to
    // individual model bodies and thereby compute correct offsets unbiased by the
    // initial base orientation.
    auto imuLabels = orientationTable.getColumnLabels();
    auto pix = distance(imuLabels.begin(), std::find(imuLabels.begin(), imuLabels.end(), "pelvis_imu")); //torso_imu
    auto startRow = orientationTable.getRowAtIndex(0);
    const Rotation& base_R = startRow.getElt(0, int(pix));

    //// Heading direction of the base IMU in this case the pelvis_imu heading is its ZAxis
    UnitVec3 pelvisHeading = base_R(SimTK::ZAxis);
    UnitVec3 groundX = UnitVec3(1, 0, 0);
    SimTK::Real angularDifference = acos(~pelvisHeading*groundX);

    // If the forward axis actually is the backward axis, change direction by 180 degrees
    if (angularDifference >= SimTK_PI / 2) {
        if (angularDifference >= 0) {
            angularDifference -= SimTK_PI;
        }
        else if (angularDifference <= -SimTK_PI / 2) {
            angularDifference += SimTK_PI;
        }
    }

    std::cout << "Heading correction computed to be "
        << angularDifference * SimTK_RADIAN_TO_DEGREE
        << "degs about ground Y" << std::endl;

    SimTK::Rotation R_HG = SimTK::Rotation(
        SimTK::BodyOrSpaceType::SpaceRotationSequence,
        0, SimTK::XAxis,
        angularDifference, SimTK::YAxis,
        0, SimTK::ZAxis
    );

    for (size_t i = 0; i < orientationTable.getNumRows(); ++i) {
        RowVectorView_<SimTK::Rotation>& rotationsRow = orientationTable.updRowAtIndex(i);
        for (int j = 0; j < nc; ++j) {
            rotationsRow[j] = R_HG*rotationsRow[j];
        }
    }

    return orientationTable;
}
<|endoftext|>


<commit_before>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2013 ETH Zurich
 ** All rights reserved.
 **
 ** 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 ETH Zurich 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.
 **
 **********************************************************************************************************************/

#include "VComment.h"
#include "VCommentBrowser.h"
#include "VCommentImage.h"
#include "VisualizationBase/src/items/Line.h"
#include "VisualizationBase/src/items/ItemStyle.h"
#include "VisualizationBase/src/items/Text.h"
#include "VisualizationBase/src/declarative/DeclarativeItemDef.h"

using namespace Visualization;

namespace Comments {

ITEM_COMMON_DEFINITIONS(VComment, "item")

VComment::VComment(Item* parent, NodeType* node) : Super(parent, node, itemStyles().get())
{
	// import existing diagrams
	for(auto diagram : *node->diagrams())
	{
		diagrams_[diagram->name()] = diagram;
	}

	editing_ = node->lines()->size() == 0 || (node->lines()->size() == 1 && node->lines()->at(0)->get().isEmpty());
	parseLines();
}

// split up user-provided text into single elements
void VComment::parseLines()
{
	clearChildren();
	bool isHTML = false;

	QSet<QString> diagramNames{};
	int listCount = -1;

	for(auto nodeLine : *node()->lines())
	{
		QRegExp rx("^={3,}|-{3,}|\\.{3,}$");
		QString line = nodeLine->get();

		// is this a new enumeration item?
		if(line.left(3) == " * ")
		{
			listCount++;
			// does this create a new list?
			if(listCount == 0)
			{
				pushTextLine("

");
				line = line.mid(3);
			}
			// otherwise, just add another list item
			else
			{
				pushTextLine("

");
				line = line.mid(3);
			}
		}
		// or is this extending an existing list?
		else if(line.left(3) == "   " && listCount > -1)
		{
			line = line.mid(3);
		}
		// if this is not an enumeration item, reset listCount
		else if(listCount > -1 && line.left(3) != " * " && line.left(3) != "   ")
		{
			pushTextLine("

");
			listCount = -1;
		}

		// is this HTML?
		if(line == "")
		{
			popLineBuffer();
			isHTML = true;
			continue;
		}
		else if(isHTML)
		{
			if(line == "")
			{
				isHTML = false;
				popLineBuffer(true);
			}
			else
			{
				pushTextLine(line);
			}
			// don't process further
			continue;
		}

		if(rx.exactMatch(line))
		{
			// A line consists of one of . - = that is repeated three times or more
			// The used character defines the strength of the header, i.e. one of three levels
			QString style;
			switch(line[0].toAscii())
			{
				default:
				case '.': style = "single"; break;
				case '-': style = "double"; break;
				case '=': style = "triple"; break;
			}

			addChildItem(new Line(this, Line::itemStyles().get(style)));
			continue;
		}

		// is this a header? replace it right away with the appropriate tag
		rx.setPattern("^(#+)([^#].*)");
		// allow headers h1 to h6
		if(rx.exactMatch(line) && rx.cap(1).length() <= 6)
		{
			QString len = QString::number(rx.cap(1).length());
			pushTextLine("<h" + len + ">" + rx.cap(2).simplified() + "</h" + len + ">");
		}
		// is this a diagram? format: [diagram#diagramName]
		else if(line.left(9) == "[diagram#" && line.right(1) == "]" && line.size() > 9+1)
		{
			QString diagramName = line.mid(9,line.size()-9-1);
			diagramNames << diagramName;

			CommentDiagram* diagram = diagrams_.value(diagramName, nullptr);

			if(diagram == nullptr)
			{
				diagram = new CommentDiagram(nullptr, diagramName);
				diagrams_[diagramName] = diagram;
			}

			auto item = renderer()->render(this, diagram);
			addChildItem(item);
		}
		// urls are specified as [browser#http://www.google.com]
		else if(line.left(9) == "[browser#" && line.right(1) == "]" && line.size() > 9+1)
		{
			QString mid = line.mid(9, line.size()-9-1);
			// read width and height, if specified
			auto items = parseMarkdownArguments(mid);
			QString url = items->at(0).second;
			auto browser = new VCommentBrowser(this, QUrl(url));

			if(items->size() > 1)
			{
				QSize size = parseSize(items->at(1).second);
				browser->updateSize(size);
			}

			addChildItem(browser);
			delete items;
		}
		// images are specified as
		//   [image#/home/user/image.png]
		//   [image#image.png|300x300] to specify a size
		else if(line.left(7) == "[image#" && line.right(1) == "]" && line.size() > 7+1)
		{
			QString mid = line.mid(7, line.size()-7-1);
			// read width and height, if specified
			auto items = parseMarkdownArguments(mid);
			QString path = items->at(0).second;
			QSize size(0,0);
			if(items->size() > 1)
				size = parseSize(items->at(1).second);

			addChildItem(new VCommentImage(this, items->at(0).second, size));
			delete items;
		}
		else
		{
			pushTextLine(line);
		}
	}

	popLineBuffer();
	synchroniseDiagrams(diagramNames);
}

void VComment::synchroniseDiagrams(QSet<QString> itemDiagramNames)
{
	// get all diagrams from the node
	auto nodeDiagrams = node()->diagrams();
	// gather all names from the node diagrams for easier comparison
	QSet<QString> nodeDiagramNames{};
	for(auto diagram : *nodeDiagrams)
		nodeDiagramNames << diagram->name();

	// get intersection of two sets
	QSet<QString> intersection(itemDiagramNames);
	intersection.intersect(nodeDiagramNames);

	// new diagrams were already constructed inside of parseLines(),
	// they also need to be added to the model now
	auto newDiagramNames = itemDiagramNames - intersection;

	if(newDiagramNames.size() > 0)
	{
		node()->model()->beginModification(node(), "Adding new diagrams");
		for(auto diagramName : newDiagramNames)
		{
			auto diagram = diagrams_.value(diagramName);
			node()->diagrams()->append(diagram);
		}
		node()->model()->endModification();
	}

	// diagrams that are no longer referenced need to be removed from the model
	auto oldDiagramNames = nodeDiagramNames - intersection;

	if(oldDiagramNames.size() > 0)
	{
		node()->model()->beginModification(node(), "Removing unreferenced diagrams");
		for(auto diagramName : oldDiagramNames)
		{
			auto diagram = diagrams_.value(diagramName);
			node()->diagrams()->remove(diagram);
			diagrams_.remove(diagramName);
		}
		node()->model()->endModification();
	}
}

QMap<QString, CommentDiagram*> VComment::diagrams() const
{
	return diagrams_;
}

QSize VComment::parseSize(const QString& str)
{
	int index = str.indexOf('x');
	bool ok{};

	int width = str.left(index).toInt(&ok);
	if(index > 0 && !ok)
		qDebug() << "Invalid width specified in size string:" << str;

	int height = str.mid(index+1).toInt(&ok);
	if(index+1 < str.size()-1 && !ok)
		qDebug() << "Invalid height specified in size string:" << str;

	return QSize(width, height);
}

QVector<QPair<QString,QString>>* VComment::parseMarkdownArguments(const QString& argString)
{
	// split string on all pipes
	auto lines = argString.split('|');
	// TODO: get rid of escaped pipes \| e.g. in case an url contains one

	auto pairs = new QVector<QPair<QString,QString>>();
	// read key/value pairs
	QRegExp rx("^[a-zA-Z]{,15}=");
	for(auto line : lines)
	{
		int index = rx.indexIn(line);
		if(index == -1)
			pairs->push_back(qMakePair(QString(), line));
		else
			pairs->push_back(qMakePair(line.left(index), line.mid(index+1)));
	}

	return pairs;
}

QString VComment::replaceMarkdown(QString str)
{
	QRegExp rx;

	rx.setPattern("\\*\\*([^\\*]+)\\*\\*");
	str.replace(rx, "\\1");

	rx.setPattern("\\*([^\\*]+)\\*");
	str.replace(rx, "\\1");

	return str;
}

void VComment::pushTextLine(QString text)
{
	lineBuffer_.push_back(text);
}

void VComment::popLineBuffer(bool asHtml)
{
	if(lineBuffer_.size() > 0)
	{
		auto joined = lineBuffer_.join("\n");

		if(asHtml)
		{
			auto browser = new VCommentBrowser(this, joined);
			children_.push_back(browser);
		}
		else
		{
			auto text = new Text(this, Text::itemStyles().get("comment"), replaceMarkdown(joined));
			text->setTextFormat(Qt::RichText);
			children_.push_back(text);
		}

		lineBuffer_.clear();
	}
}

void VComment::addChildItem(Visualization::Item* item)
{
	popLineBuffer();
	children_.push_back(item);
}

void VComment::toggleEditing()
{
	if(node()->lines()->size() == 0)
		editing_ = true;
	else
		editing_ = !editing_;

	if(!editing_)
		parseLines();

	setUpdateNeeded(StandardUpdate);
}

bool VComment::editing() const
{
	return editing_;
}

void VComment::initializeForms()
{
	addForm((new SequentialLayoutFormElement())
				->setVertical()
				->setListOfItems([](Item* i) {
					auto vc = static_cast<VComment*>(i);
					return vc->children_;
				}
	));

	addForm(item(&I::editLabel_, [](I* v){
		return v->node()->lines();
	}));
}

int VComment::determineForm()
{
	return editing_ ? 1 : 0;
}

} /* namespace Comments */
<commit_msg>Follow Markdown guidelines for italic and bold text.<commit_after>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2013 ETH Zurich
 ** All rights reserved.
 **
 ** 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 ETH Zurich 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.
 **
 **********************************************************************************************************************/

#include "VComment.h"
#include "VCommentBrowser.h"
#include "VCommentImage.h"
#include "VisualizationBase/src/items/Line.h"
#include "VisualizationBase/src/items/ItemStyle.h"
#include "VisualizationBase/src/items/Text.h"
#include "VisualizationBase/src/declarative/DeclarativeItemDef.h"

using namespace Visualization;

namespace Comments {

ITEM_COMMON_DEFINITIONS(VComment, "item")

VComment::VComment(Item* parent, NodeType* node) : Super(parent, node, itemStyles().get())
{
	// import existing diagrams
	for(auto diagram : *node->diagrams())
	{
		diagrams_[diagram->name()] = diagram;
	}

	editing_ = node->lines()->size() == 0 || (node->lines()->size() == 1 && node->lines()->at(0)->get().isEmpty());
	parseLines();
}

// split up user-provided text into single elements
void VComment::parseLines()
{
	clearChildren();
	bool isHTML = false;

	QSet<QString> diagramNames{};
	int listCount = -1;

	for(auto nodeLine : *node()->lines())
	{
		QRegExp rx("^={3,}|-{3,}|\\.{3,}$");
		QString line = nodeLine->get();

		// is this a new enumeration item?
		if(line.left(3) == " * ")
		{
			listCount++;
			// does this create a new list?
			if(listCount == 0)
			{
				pushTextLine("

");
				line = line.mid(3);
			}
			// otherwise, just add another list item
			else
			{
				pushTextLine("

");
				line = line.mid(3);
			}
		}
		// or is this extending an existing list?
		else if(line.left(3) == "   " && listCount > -1)
		{
			line = line.mid(3);
		}
		// if this is not an enumeration item, reset listCount
		else if(listCount > -1 && line.left(3) != " * " && line.left(3) != "   ")
		{
			pushTextLine("

");
			listCount = -1;
		}

		// is this HTML?
		if(line == "")
		{
			popLineBuffer();
			isHTML = true;
			continue;
		}
		else if(isHTML)
		{
			if(line == "")
			{
				isHTML = false;
				popLineBuffer(true);
			}
			else
			{
				pushTextLine(line);
			}
			// don't process further
			continue;
		}

		if(rx.exactMatch(line))
		{
			// A line consists of one of . - = that is repeated three times or more
			// The used character defines the strength of the header, i.e. one of three levels
			QString style;
			switch(line[0].toAscii())
			{
				default:
				case '.': style = "single"; break;
				case '-': style = "double"; break;
				case '=': style = "triple"; break;
			}

			addChildItem(new Line(this, Line::itemStyles().get(style)));
			continue;
		}

		// is this a header? replace it right away with the appropriate tag
		rx.setPattern("^(#+)([^#].*)");
		// allow headers h1 to h6
		if(rx.exactMatch(line) && rx.cap(1).length() <= 6)
		{
			QString len = QString::number(rx.cap(1).length());
			pushTextLine("<h" + len + ">" + rx.cap(2).simplified() + "</h" + len + ">");
		}
		// is this a diagram? format: [diagram#diagramName]
		else if(line.left(9) == "[diagram#" && line.right(1) == "]" && line.size() > 9+1)
		{
			QString diagramName = line.mid(9,line.size()-9-1);
			diagramNames << diagramName;

			CommentDiagram* diagram = diagrams_.value(diagramName, nullptr);

			if(diagram == nullptr)
			{
				diagram = new CommentDiagram(nullptr, diagramName);
				diagrams_[diagramName] = diagram;
			}

			auto item = renderer()->render(this, diagram);
			addChildItem(item);
		}
		// urls are specified as [browser#http://www.google.com]
		else if(line.left(9) == "[browser#" && line.right(1) == "]" && line.size() > 9+1)
		{
			QString mid = line.mid(9, line.size()-9-1);
			// read width and height, if specified
			auto items = parseMarkdownArguments(mid);
			QString url = items->at(0).second;
			auto browser = new VCommentBrowser(this, QUrl(url));

			if(items->size() > 1)
			{
				QSize size = parseSize(items->at(1).second);
				browser->updateSize(size);
			}

			addChildItem(browser);
			delete items;
		}
		// images are specified as
		//   [image#/home/user/image.png]
		//   [image#image.png|300x300] to specify a size
		else if(line.left(7) == "[image#" && line.right(1) == "]" && line.size() > 7+1)
		{
			QString mid = line.mid(7, line.size()-7-1);
			// read width and height, if specified
			auto items = parseMarkdownArguments(mid);
			QString path = items->at(0).second;
			QSize size(0,0);
			if(items->size() > 1)
				size = parseSize(items->at(1).second);

			addChildItem(new VCommentImage(this, items->at(0).second, size));
			delete items;
		}
		else
		{
			pushTextLine(line);
		}
	}

	popLineBuffer();
	synchroniseDiagrams(diagramNames);
}

void VComment::synchroniseDiagrams(QSet<QString> itemDiagramNames)
{
	// get all diagrams from the node
	auto nodeDiagrams = node()->diagrams();
	// gather all names from the node diagrams for easier comparison
	QSet<QString> nodeDiagramNames{};
	for(auto diagram : *nodeDiagrams)
		nodeDiagramNames << diagram->name();

	// get intersection of two sets
	QSet<QString> intersection(itemDiagramNames);
	intersection.intersect(nodeDiagramNames);

	// new diagrams were already constructed inside of parseLines(),
	// they also need to be added to the model now
	auto newDiagramNames = itemDiagramNames - intersection;

	if(newDiagramNames.size() > 0)
	{
		node()->model()->beginModification(node(), "Adding new diagrams");
		for(auto diagramName : newDiagramNames)
		{
			auto diagram = diagrams_.value(diagramName);
			node()->diagrams()->append(diagram);
		}
		node()->model()->endModification();
	}

	// diagrams that are no longer referenced need to be removed from the model
	auto oldDiagramNames = nodeDiagramNames - intersection;

	if(oldDiagramNames.size() > 0)
	{
		node()->model()->beginModification(node(), "Removing unreferenced diagrams");
		for(auto diagramName : oldDiagramNames)
		{
			auto diagram = diagrams_.value(diagramName);
			node()->diagrams()->remove(diagram);
			diagrams_.remove(diagramName);
		}
		node()->model()->endModification();
	}
}

QMap<QString, CommentDiagram*> VComment::diagrams() const
{
	return diagrams_;
}

QSize VComment::parseSize(const QString& str)
{
	int index = str.indexOf('x');
	bool ok{};

	int width = str.left(index).toInt(&ok);
	if(index > 0 && !ok)
		qDebug() << "Invalid width specified in size string:" << str;

	int height = str.mid(index+1).toInt(&ok);
	if(index+1 < str.size()-1 && !ok)
		qDebug() << "Invalid height specified in size string:" << str;

	return QSize(width, height);
}

QVector<QPair<QString,QString>>* VComment::parseMarkdownArguments(const QString& argString)
{
	// split string on all pipes
	auto lines = argString.split('|');
	// TODO: get rid of escaped pipes \| e.g. in case an url contains one

	auto pairs = new QVector<QPair<QString,QString>>();
	// read key/value pairs
	QRegExp rx("^[a-zA-Z]{,15}=");
	for(auto line : lines)
	{
		int index = rx.indexIn(line);
		if(index == -1)
			pairs->push_back(qMakePair(QString(), line));
		else
			pairs->push_back(qMakePair(line.left(index), line.mid(index+1)));
	}

	return pairs;
}

QString VComment::replaceMarkdown(QString str)
{
	QRegExp rx;

	rx.setPattern("\\*\\*([^\\*]+)\\*\\*");
	str.replace(rx, "\\1");

	rx.setPattern("\\*([^\\*]+)\\*");
	str.replace(rx, "\\1");

	return str;
}

void VComment::pushTextLine(QString text)
{
	lineBuffer_.push_back(text);
}

void VComment::popLineBuffer(bool asHtml)
{
	if(lineBuffer_.size() > 0)
	{
		auto joined = lineBuffer_.join("\n");

		if(asHtml)
		{
			auto browser = new VCommentBrowser(this, joined);
			children_.push_back(browser);
		}
		else
		{
			auto text = new Text(this, Text::itemStyles().get("comment"), replaceMarkdown(joined));
			text->setTextFormat(Qt::RichText);
			children_.push_back(text);
		}

		lineBuffer_.clear();
	}
}

void VComment::addChildItem(Visualization::Item* item)
{
	popLineBuffer();
	children_.push_back(item);
}

void VComment::toggleEditing()
{
	if(node()->lines()->size() == 0)
		editing_ = true;
	else
		editing_ = !editing_;

	if(!editing_)
		parseLines();

	setUpdateNeeded(StandardUpdate);
}

bool VComment::editing() const
{
	return editing_;
}

void VComment::initializeForms()
{
	addForm((new SequentialLayoutFormElement())
				->setVertical()
				->setListOfItems([](Item* i) {
					auto vc = static_cast<VComment*>(i);
					return vc->children_;
				}
	));

	addForm(item(&I::editLabel_, [](I* v){
		return v->node()->lines();
	}));
}

int VComment::determineForm()
{
	return editing_ ? 1 : 0;
}

} /* namespace Comments */
<|endoftext|>


<commit_before>/*
 * AddTask macro for class
 * Redmer Alexander Bertens, rbertens@cern.ch
 * Utrecht University, Utrecht, Netherlands
 *
 * Note: this macro is pretty much a copy of AddTaskEmcalJetSample.C
 *
 */

AliAnalysisTaskRhoVnModulation* AddTaskRhoVnModulation(
  const char *ntracks            = "Tracks",
  const char *nclusters          = "",
  const char *njets              = "Jets",
  const char *nrho               = "Rho",
  Double_t   jetradius          = 0.2,
  Double_t   jetptcut           = 1,
  Double_t   jetareacut         = 0.557,
  const char* type              = "TPC",
  Int_t      leadhadtype        = 0,
  const char *taskname           = "AliAnalysisTaskRhoVnModulation",
  UInt_t     runMode            = AliAnalysisTaskRhoVnModulation::kGrid,
  Bool_t     fillQA             = kTRUE,
  TString    fitOpts            = "WLQI",
  UInt_t     fitType            = AliAnalysisTaskRhoVnModulation::kFourierSeries,
  TArrayI    *centralities      = 0x0,
  TRandom3   *randomizer        = 0x0,
  Double_t   trackptcut         = .15
  )
{
  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr)
  {
    ::Error("AddTaskEmcalJetSample", "No analysis manager to connect to.");
    return NULL;
  }

  // Check the analysis type using the event handlers connected to the analysis manager.
  //==============================================================================
  if (!mgr->GetInputEventHandler())
  {
    ::Error("AddTaskEmcalJetSample", "This task requires an input event handler");
    return NULL;
  }

  //-------------------------------------------------------
  // Init the task and do settings
  //-------------------------------------------------------

  TString name(taskname);
  if (strcmp(njets,"")) {
    name += "_";
    name += njets;
  }
  if (strcmp(nrho,"")) {
    name += "_";
    name += nrho;
  }
  if (!strcmp(type, "TPC"))
    name += "_TPC";
  else if (!strcmp(type, "EMCAL"))
    name += "_EMCAL";
  else if (!strcmp(type, "USER"))
    name += "_USER";

  AliAnalysisTaskRhoVnModulation* jetTask = new AliAnalysisTaskRhoVnModulation(name, runMode);
  // inherited setters
  AliParticleContainer* partCont = jetTask->AddParticleContainer(ntracks);
  if(partCont) {
      partCont->SetName("Tracks");
      partCont->SetParticlePtCut(trackptcut);
  }
  AliJetContainer* jetCont = jetTask->AddJetContainer(njets, type, jetradius);
  if(jetCont) {
      jetCont->SetName("Jets");
      jetCont->SetPercAreaCut(jetareacut);
      jetCont->SetRhoName(nrho);
      jetCont->ConnectParticleContainer(partCont);
  }
  // task specific setters
  jetTask->SetFillQAHistograms(fillQA);
  jetTask->SetDebugMode(-1);
  jetTask->SetModulationFitType(fitType);
  jetTask->SetModulationFitOptions(fitOpts);
  jetTask->SetModulationFitMinMaxP(.001, 1);
  jetTask->SetRandomConeRadius(jetradius);
  // if centralities haven't been specified use defaults
  if(!centralities) {
     Int_t c[] = {0, 10, 30, 50, 70, 90};
     jetTask->SetCentralityClasses(new TArrayI(sizeof(c)/sizeof(c[0]), c));
  }
  // if a randomized hasn't specified use a safe default
  if(!randomizer) jetTask->SetRandomSeed(new TRandom3(0));

  //-------------------------------------------------------
  // Final settings, pass to manager and set the containers
  //-------------------------------------------------------

  mgr->AddTask(jetTask);

  // Create containers for input/output
  AliAnalysisDataContainer *cinput1  = mgr->GetCommonInputContainer()  ;
  TString contname(name);
  contname+="_PWGJE";
  AliAnalysisDataContainer *coutput1 = mgr->CreateContainer(contname.Data(),
							    TList::Class(),AliAnalysisManager::kOutputContainer,
							    Form("%s", AliAnalysisManager::GetCommonFileName()));
  mgr->ConnectInput  (jetTask, 0,  cinput1 );
  mgr->ConnectOutput (jetTask, 1, coutput1 );

  switch (runMode) {
      case AliAnalysisTaskRhoVnModulation::kLocal : {
          gStyle->SetOptFit(1);
          AliAnalysisDataContainer *coutput2 = mgr->CreateContainer(Form("good_fits_%s", name.Data()),
							    TList::Class(),AliAnalysisManager::kOutputContainer,
							    Form("%s", AliAnalysisManager::GetCommonFileName()));
          AliAnalysisDataContainer *coutput3 = mgr->CreateContainer(Form("bad_fits_%s", name.Data()),
							    TList::Class(),AliAnalysisManager::kOutputContainer,
							     Form("%s", AliAnalysisManager::GetCommonFileName()));
          mgr->ConnectOutput (jetTask, 2, coutput2);
          mgr->ConnectOutput (jetTask, 3, coutput3);
      } break;
      default: break;
  }
  return jetTask;
}
<commit_msg> bugfix add task (changed int into double in task but forgot to update addtask)<commit_after>/*
 * AddTask macro for class
 * Redmer Alexander Bertens, rbertens@cern.ch
 * Utrecht University, Utrecht, Netherlands
 *
 * Note: this macro is pretty much a copy of AddTaskEmcalJetSample.C
 *
 */

AliAnalysisTaskRhoVnModulation* AddTaskRhoVnModulation(
  const char *ntracks            = "Tracks",
  const char *nclusters          = "",
  const char *njets              = "Jets",
  const char *nrho               = "Rho",
  Double_t   jetradius          = 0.2,
  Double_t   jetptcut           = 1,
  Double_t   jetareacut         = 0.557,
  const char* type              = "TPC",
  Int_t      leadhadtype        = 0,
  const char *taskname           = "AliAnalysisTaskRhoVnModulation",
  UInt_t     runMode            = AliAnalysisTaskRhoVnModulation::kGrid,
  Bool_t     fillQA             = kTRUE,
  TString    fitOpts            = "WLQI",
  UInt_t     fitType            = AliAnalysisTaskRhoVnModulation::kFourierSeries,
  TArrayD    *centralities      = 0x0,
  TRandom3   *randomizer        = 0x0,
  Double_t   trackptcut         = .15
  )
{
  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr)
  {
    ::Error("AddTaskEmcalJetSample", "No analysis manager to connect to.");
    return NULL;
  }

  // Check the analysis type using the event handlers connected to the analysis manager.
  //==============================================================================
  if (!mgr->GetInputEventHandler())
  {
    ::Error("AddTaskEmcalJetSample", "This task requires an input event handler");
    return NULL;
  }

  //-------------------------------------------------------
  // Init the task and do settings
  //-------------------------------------------------------

  TString name(taskname);
  if (strcmp(njets,"")) {
    name += "_";
    name += njets;
  }
  if (strcmp(nrho,"")) {
    name += "_";
    name += nrho;
  }
  if (!strcmp(type, "TPC"))
    name += "_TPC";
  else if (!strcmp(type, "EMCAL"))
    name += "_EMCAL";
  else if (!strcmp(type, "USER"))
    name += "_USER";

  AliAnalysisTaskRhoVnModulation* jetTask = new AliAnalysisTaskRhoVnModulation(name, runMode);
  // inherited setters
  AliParticleContainer* partCont = jetTask->AddParticleContainer(ntracks);
  if(partCont) {
      partCont->SetName("Tracks");
      partCont->SetParticlePtCut(trackptcut);
  }
  AliJetContainer* jetCont = jetTask->AddJetContainer(njets, type, jetradius);
  if(jetCont) {
      jetCont->SetName("Jets");
      jetCont->SetPercAreaCut(jetareacut);
      jetCont->SetRhoName(nrho);
      jetCont->ConnectParticleContainer(partCont);
  }
  // task specific setters
  jetTask->SetFillQAHistograms(fillQA);
  jetTask->SetDebugMode(-1);
  jetTask->SetModulationFitType(fitType);
  jetTask->SetModulationFitOptions(fitOpts);
  jetTask->SetModulationFitMinMaxP(.001, 1);
  jetTask->SetRandomConeRadius(jetradius);
  // if centralities haven't been specified use defaults
  if(!centralities) {
     Double_t c[] = {0., 10., 30., 50., 70., 90.};
     jetTask->SetCentralityClasses(new TArrayD(sizeof(c)/sizeof(c[0]), c));
  }
  // if a randomized hasn't specified use a safe default
  if(!randomizer) jetTask->SetRandomSeed(new TRandom3(0));

  //-------------------------------------------------------
  // Final settings, pass to manager and set the containers
  //-------------------------------------------------------

  mgr->AddTask(jetTask);

  // Create containers for input/output
  AliAnalysisDataContainer *cinput1  = mgr->GetCommonInputContainer()  ;
  TString contname(name);
  contname+="_PWGJE";
  AliAnalysisDataContainer *coutput1 = mgr->CreateContainer(contname.Data(),
							    TList::Class(),AliAnalysisManager::kOutputContainer,
							    Form("%s", AliAnalysisManager::GetCommonFileName()));
  mgr->ConnectInput  (jetTask, 0,  cinput1 );
  mgr->ConnectOutput (jetTask, 1, coutput1 );

  switch (runMode) {
      case AliAnalysisTaskRhoVnModulation::kLocal : {
          gStyle->SetOptFit(1);
          AliAnalysisDataContainer *coutput2 = mgr->CreateContainer(Form("good_fits_%s", name.Data()),
							    TList::Class(),AliAnalysisManager::kOutputContainer,
							    Form("%s", AliAnalysisManager::GetCommonFileName()));
          AliAnalysisDataContainer *coutput3 = mgr->CreateContainer(Form("bad_fits_%s", name.Data()),
							    TList::Class(),AliAnalysisManager::kOutputContainer,
							     Form("%s", AliAnalysisManager::GetCommonFileName()));
          mgr->ConnectOutput (jetTask, 2, coutput2);
          mgr->ConnectOutput (jetTask, 3, coutput3);
      } break;
      default: break;
  }
  return jetTask;
}
<|endoftext|>