<commit_before>// $Id$
// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library 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 2.1 of the License, or (at your option) any later version.

// This library 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 for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "elem.h"
#include "fe.h"
#include "fe_interface.h"

namespace libMesh
{

  // ------------------------------------------------------------
  // Hierarchic-specific implementations

  // Anonymous namespace for local helper functions
  namespace {

    void l2_hierarchic_nodal_soln(const Elem* elem,
				  const Order order,
				  const std::vector<Number>& elem_soln,
				  std::vector<Number>&       nodal_soln,
				  unsigned Dim)
    {
      const unsigned int n_nodes = elem->n_nodes();

      const ElemType elem_type = elem->type();

      nodal_soln.resize(n_nodes);

      const Order totalorder = static_cast<Order>(order + elem->p_level());

      // FEType object to be passed to various FEInterface functions below.
      FEType fe_type(totalorder, L2_HIERARCHIC);

      switch (totalorder)
	{
	  // Constant shape functions
	case CONSTANT:
	  {
	    libmesh_assert (elem_soln.size() == 1);

	    const Number val = elem_soln[0];

	    for (unsigned int n=0; n<n_nodes; n++)
	      nodal_soln[n] = val;

	    return;
	  }

	  // For other orders do interpolation at the nodes
	  // explicitly.
	default:
	  {

	    const unsigned int n_sf =
	      // FE<Dim,T>::n_shape_functions(elem_type, totalorder);
	      FEInterface::n_shape_functions(Dim, fe_type, elem_type);

	    for (unsigned int n=0; n<n_nodes; n++)
	      {
		const Point mapped_point =
		  // FE<Dim,T>::inverse_map(elem, elem->point(n));
		  FEInterface::inverse_map(Dim, fe_type, elem, elem->point(n));

		libmesh_assert (elem_soln.size() == n_sf);

		// Zero before summation
		nodal_soln[n] = 0;

		// u_i = Sum (alpha_i phi_i)
		for (unsigned int i=0; i<n_sf; i++)
		  nodal_soln[n] += elem_soln[i] *
		    // FE<Dim,T>::shape(elem, order, i, mapped_point);
		    FEInterface::shape(Dim, fe_type, elem, i, mapped_point);
	      }

	    return;
	  }
	}
    } // l2_hierarchic_nodal_soln()

    unsigned int l2_hierarchic_n_dofs(const ElemType t, const Order o)
    {
      libmesh_assert (o > 0);
      switch (t)
	{
	case NODEELEM:
	  return 1;
	case EDGE2:
	case EDGE3:
	  return (o+1);
	case QUAD4:
	case QUAD8:
	case QUAD9:
	  return ((o+1)*(o+1));
	case HEX8:
	case HEX20:
	case HEX27:
	  return ((o+1)*(o+1)*(o+1));
	case TRI6:
	  return ((o+1)*(o+2)/2);
	default:
	  libmesh_error();
	}

      libmesh_error();
      return 0;
    } // l2_hierarchic_n_dofs()

    unsigned int l2_hierarchic_n_dofs_per_elem(const ElemType t,
					       const Order o)
    {
      return l2_hierarchic_n_dofs(t, o);
    } // l2_hierarchic_n_dofs_per_elem()

  } // anonymous namespace

  // Do full-specialization of nodal_soln() function for every
  // dimension, instead of explicit instantiation at the end of this
  // file.
  // This could be macro-ified so that it fits on one line...
  template <>
  void FE<0,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/0); }

  template <>
  void FE<1,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/1); }

  template <>
  void FE<2,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/2); }

  template <>
  void FE<3,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/3); }

  // Full specialization of n_dofs() function for every dimension
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }

  // Full specialization of n_dofs_at_node() function for every dimension.
  // Discontinuous L2 elements only have interior nodes
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }

  // Full specialization of n_dofs_per_elem() function for every dimension.
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }

  // L2 Hierarchic FEMs are C^0 continuous
  template <> FEContinuity FE<0,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<1,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<2,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<3,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }

  // L2 Hierarchic FEMs are hierarchic (duh!)
  template <> bool FE<0,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<1,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<2,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<3,L2_HIERARCHIC>::is_hierarchic() const { return true; }

#ifdef LIBMESH_ENABLE_AMR
  // compute_constraints() specializations are only needed for 2 and 3D
  template <>
  void FE<2,L2_HIERARCHIC>::compute_constraints (DofConstraints &constraints,
						 DofMap &dof_map,
						 const unsigned int variable_number,
						 const Elem* elem)
  { compute_proj_constraints(constraints, dof_map, variable_number, elem); }

  template <>
  void FE<3,L2_HIERARCHIC>::compute_constraints (DofConstraints &constraints,
						 DofMap &dof_map,
						 const unsigned int variable_number,
						 const Elem* elem)
  { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
#endif // #ifdef LIBMESH_ENABLE_AMR

  // L2-Hierarchic FEM shapes need reinit
  template <> bool FE<0,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<1,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<2,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<3,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }

} // namespace libMesh
<commit_msg>Reverting Truman's fix; it was redundant after mine<commit_after>// $Id$
// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library 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 2.1 of the License, or (at your option) any later version.

// This library 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 for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "elem.h"
#include "fe.h"
#include "fe_interface.h"

namespace libMesh
{

  // ------------------------------------------------------------
  // Hierarchic-specific implementations

  // Anonymous namespace for local helper functions
  namespace {

    void l2_hierarchic_nodal_soln(const Elem* elem,
				  const Order order,
				  const std::vector<Number>& elem_soln,
				  std::vector<Number>&       nodal_soln,
				  unsigned Dim)
    {
      const unsigned int n_nodes = elem->n_nodes();

      const ElemType elem_type = elem->type();

      nodal_soln.resize(n_nodes);

      const Order totalorder = static_cast<Order>(order + elem->p_level());

      // FEType object to be passed to various FEInterface functions below.
      FEType fe_type(totalorder, L2_HIERARCHIC);

      switch (totalorder)
	{
	  // Constant shape functions
	case CONSTANT:
	  {
	    libmesh_assert (elem_soln.size() == 1);

	    const Number val = elem_soln[0];

	    for (unsigned int n=0; n<n_nodes; n++)
	      nodal_soln[n] = val;

	    return;
	  }

	  // For other orders do interpolation at the nodes
	  // explicitly.
	default:
	  {

	    const unsigned int n_sf =
	      // FE<Dim,T>::n_shape_functions(elem_type, totalorder);
	      FEInterface::n_shape_functions(Dim, fe_type, elem_type);

	    for (unsigned int n=0; n<n_nodes; n++)
	      {
		const Point mapped_point =
		  // FE<Dim,T>::inverse_map(elem, elem->point(n));
		  FEInterface::inverse_map(Dim, fe_type, elem, elem->point(n));

		libmesh_assert (elem_soln.size() == n_sf);

		// Zero before summation
		nodal_soln[n] = 0;

		// u_i = Sum (alpha_i phi_i)
		for (unsigned int i=0; i<n_sf; i++)
		  nodal_soln[n] += elem_soln[i] *
		    // FE<Dim,T>::shape(elem, order, i, mapped_point);
		    FEInterface::shape(Dim, fe_type, elem, i, mapped_point);
	      }

	    return;
	  }
	}
    } // l2_hierarchic_nodal_soln()

    unsigned int l2_hierarchic_n_dofs(const ElemType t, const Order o)
    {
      libmesh_assert (o > 0);
      switch (t)
	{
	case NODEELEM:
	  return 1;
	case EDGE2:
	case EDGE3:
	  return (o+1);
	case QUAD4:
	case QUAD8:
	case QUAD9:
	  return ((o+1)*(o+1));
	case HEX8:
	case HEX20:
	case HEX27:
	  return ((o+1)*(o+1)*(o+1));
	case TRI6:
	  return ((o+1)*(o+2)/2);
	default:
	  libmesh_error();
	}

      libmesh_error();
      return 0;
    } // l2_hierarchic_n_dofs()

  } // anonymous namespace

  // Do full-specialization of nodal_soln() function for every
  // dimension, instead of explicit instantiation at the end of this
  // file.
  // This could be macro-ified so that it fits on one line...
  template <>
  void FE<0,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/0); }

  template <>
  void FE<1,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/1); }

  template <>
  void FE<2,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/2); }

  template <>
  void FE<3,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/3); }

  // Full specialization of n_dofs() function for every dimension
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }

  // Full specialization of n_dofs_at_node() function for every dimension.
  // Discontinuous L2 elements only have interior nodes
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }

  // Full specialization of n_dofs_per_elem() function for every dimension.
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }

  // L2 Hierarchic FEMs are C^0 continuous
  template <> FEContinuity FE<0,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<1,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<2,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<3,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }

  // L2 Hierarchic FEMs are hierarchic (duh!)
  template <> bool FE<0,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<1,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<2,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<3,L2_HIERARCHIC>::is_hierarchic() const { return true; }

#ifdef LIBMESH_ENABLE_AMR
  // compute_constraints() specializations are only needed for 2 and 3D
  template <>
  void FE<2,L2_HIERARCHIC>::compute_constraints (DofConstraints &constraints,
						 DofMap &dof_map,
						 const unsigned int variable_number,
						 const Elem* elem)
  { compute_proj_constraints(constraints, dof_map, variable_number, elem); }

  template <>
  void FE<3,L2_HIERARCHIC>::compute_constraints (DofConstraints &constraints,
						 DofMap &dof_map,
						 const unsigned int variable_number,
						 const Elem* elem)
  { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
#endif // #ifdef LIBMESH_ENABLE_AMR

  // L2-Hierarchic FEM shapes need reinit
  template <> bool FE<0,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<1,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<2,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<3,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }

} // namespace libMesh
<|endoftext|>


<commit_before>//  Copyright 2011 Gregory Szorc
//
//  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.

#ifndef ZIPPYLOG_DEVICE_HPP_
#define ZIPPYLOG_DEVICE_HPP_

#include <zippylog/zippylog.hpp>
#include <zippylog/platform.hpp>

namespace zippylog {
namespace device {

/// Represents the result of a Pump() operation in a Device
///
/// See Device::Pump() for more
class ZIPPYLOG_EXPORT PumpResult {
public:
    static PumpResult MakeWorkDone();
    static PumpResult MakeNoWorkDone();
    static PumpResult MakeError();

    inline bool IsError() { return this->is_error; }

private:
    PumpResult() : is_error(false) { }

    bool is_error;
};

/// An entity that performs work
///
/// Devices are entities that perform specific functionality. Devices
/// communicate with other entities and devices via 0MQ sockets. In other
/// words, devices send their output via 0MQ sockets and typically receive
/// their input via 0MQ sockets. This being said, the behavior is not
/// enforced, so devices could operate using other means, for example.
///
/// This class is an abstract base class to be used by real devices. It
/// defines a core API and a set of functions which must be defined on
/// all derived devices.
///
class ZIPPYLOG_EXPORT Device {
public:
    /// Base constructor
    ///
    /// Should be called by child classes in their constructors
    Device(::zippylog::platform::ConditionalWait *cw);

    /// Base class destructor
    virtual ~Device();

    /// Performs pending work
    ///
    /// This is the most important function in a device because it is what
    /// triggers the device to perform work. From within this function, an
    /// implementation should process pending work or wait for work to become
    /// available until the timeout specified.
    ///
    /// It is important for devices to honor the timeout threshold, otherwise
    /// the device breaks its API contract, which may have negative impact on
    /// performance, latency, etc.
    ///
    /// @param timeout_microseconds How long to wait for work to become
    /// available before giving up
    virtual PumpResult Pump(int32 timeout_microseconds) = 0;

    /// Runs the device forever
    ///
    /// The device runs until the semaphore defined by the constructor
    /// signals. If the semaphore has not been defined, an error is thrown.
    ///
    /// Calling this function is equivalent to calling Pump() inside an
    /// infinite loop.
    void Run();

    /// Runs the device asynchronously on a new thread
    ///
    /// This function will spawn a new thread and have the device execute
    /// continuously on that thread.
    ///
    /// The function does not return until after OnRunStart() finishes.
    /// This gives devices an opportunity to fully initialize on their new
    /// thread before program execution continues.
    ///
    /// To stop this thread, call StopAsync().
    void RunAsync();

    /// Stops the device from executing on a background thread
    ///
    /// This is the inverse of RunAsync(). It will signal the device to stop
    /// and terminate the spawned thread. When the function returns, the
    /// thread is guaranteed to be shut down.
    ///
    /// @param join_timeout How long to wait for the thread to join before
    /// resorting to an abort, in microseconds
    void StopAsync(int32 join_timeout = 1000000);

    /// Query to see if the device is running
    ///
    /// @return true if device is running. false if not
    inline bool IsRunning() { return this->running; }

protected:

    /// Called when the device first runs
    ///
    /// This can be used to perform one-time object setup. Execution occurs
    /// on the new thread if running asynchronously.
    virtual void OnFirstRun();

    /// Called at the start of Run() and RunAsync()
    ///
    /// Child classes should define this to perform commands every time Run()
    /// is called.
    virtual void OnRunStart();

    /// Called at the end of Run() and StopAsync()
    ///
    /// This function should perform cleanup actions
    virtual void OnRunFinish();

private:
    /// Function that gets executed when RunAsync() is called
    ///
    /// @param data this pointer to Device instance
    static void * AsyncExecStart(void *data);

    /// Background thread device executes on
    ///
    /// This will only be defined if RunAsync() is called.
    ::zippylog::platform::Thread *thread;

    ::zippylog::platform::ConditionalWait *cw;

    /// Whether the device is running
    bool running;

    /// Whether Run() has executed before
    bool has_ran;

    /// Used by RunAsync() so function blocks until after OnRunStart() is
    /// finished
    ::zippylog::platform::ConditionalWait async_wait;

    /// Disable copy constructor and assignment operator
    Device(Device const &orig);
    Device & operator=(Device const &orig);
};

}} // namespace

#endif // file include<commit_msg>document socket migration w/ 0MQ 2.0.x<commit_after>//  Copyright 2011 Gregory Szorc
//
//  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.

#ifndef ZIPPYLOG_DEVICE_HPP_
#define ZIPPYLOG_DEVICE_HPP_

#include <zippylog/zippylog.hpp>
#include <zippylog/platform.hpp>

namespace zippylog {
namespace device {

/// Represents the result of a Pump() operation in a Device
///
/// See Device::Pump() for more
class ZIPPYLOG_EXPORT PumpResult {
public:
    static PumpResult MakeWorkDone();
    static PumpResult MakeNoWorkDone();
    static PumpResult MakeError();

    inline bool IsError() { return this->is_error; }

private:
    PumpResult() : is_error(false) { }

    bool is_error;
};

/// An entity that performs work
///
/// Devices are entities that perform specific functionality. Devices
/// communicate with other entities and devices via 0MQ sockets. In other
/// words, devices send their output via 0MQ sockets and typically receive
/// their input via 0MQ sockets. This being said, the behavior is not
/// enforced, so devices could operate using other means, for example.
///
/// This class is an abstract base class to be used by real devices. It
/// defines a core API and a set of functions which must be defined on
/// all derived devices.
///
/// In 0MQ 2.0.x, 0MQ sockets cannot be migrated between threads. Since
/// devices are constructed on one thread and can run on another, it is
/// important for the constructor not to initialize 0MQ sockets. Instead,
/// it is recommended to initialize sockets inside the OnFirstRun() handler,
/// which will only be called once.
///
class ZIPPYLOG_EXPORT Device {
public:
    /// Base constructor
    ///
    /// Should be called by child classes in their constructors
    Device(::zippylog::platform::ConditionalWait *cw);

    /// Base class destructor
    virtual ~Device();

    /// Performs pending work
    ///
    /// This is the most important function in a device because it is what
    /// triggers the device to perform work. From within this function, an
    /// implementation should process pending work or wait for work to become
    /// available until the timeout specified.
    ///
    /// It is important for devices to honor the timeout threshold, otherwise
    /// the device breaks its API contract, which may have negative impact on
    /// performance, latency, etc.
    ///
    /// @param timeout_microseconds How long to wait for work to become
    /// available before giving up
    virtual PumpResult Pump(int32 timeout_microseconds) = 0;

    /// Runs the device forever
    ///
    /// The device runs until the semaphore defined by the constructor
    /// signals. If the semaphore has not been defined, an error is thrown.
    ///
    /// Calling this function is equivalent to calling Pump() inside an
    /// infinite loop.
    void Run();

    /// Runs the device asynchronously on a new thread
    ///
    /// This function will spawn a new thread and have the device execute
    /// continuously on that thread.
    ///
    /// The function does not return until after OnRunStart() finishes.
    /// This gives devices an opportunity to fully initialize on their new
    /// thread before program execution continues.
    ///
    /// To stop this thread, call StopAsync().
    void RunAsync();

    /// Stops the device from executing on a background thread
    ///
    /// This is the inverse of RunAsync(). It will signal the device to stop
    /// and terminate the spawned thread. When the function returns, the
    /// thread is guaranteed to be shut down.
    ///
    /// @param join_timeout How long to wait for the thread to join before
    /// resorting to an abort, in microseconds
    void StopAsync(int32 join_timeout = 1000000);

    /// Query to see if the device is running
    ///
    /// @return true if device is running. false if not
    inline bool IsRunning() { return this->running; }

protected:

    /// Called when the device first runs
    ///
    /// This can be used to perform one-time object setup. Execution occurs
    /// on the new thread if running asynchronously.
    virtual void OnFirstRun();

    /// Called at the start of Run() and RunAsync()
    ///
    /// Child classes should define this to perform commands every time Run()
    /// is called.
    virtual void OnRunStart();

    /// Called at the end of Run() and StopAsync()
    ///
    /// This function should perform cleanup actions
    virtual void OnRunFinish();

private:
    /// Function that gets executed when RunAsync() is called
    ///
    /// @param data this pointer to Device instance
    static void * AsyncExecStart(void *data);

    /// Background thread device executes on
    ///
    /// This will only be defined if RunAsync() is called.
    ::zippylog::platform::Thread *thread;

    ::zippylog::platform::ConditionalWait *cw;

    /// Whether the device is running
    bool running;

    /// Whether Run() has executed before
    bool has_ran;

    /// Used by RunAsync() so function blocks until after OnRunStart() is
    /// finished
    ::zippylog::platform::ConditionalWait async_wait;

    /// Disable copy constructor and assignment operator
    Device(Device const &orig);
    Device & operator=(Device const &orig);
};

}} // namespace

#endif // file include<|endoftext|>


<commit_before>// -*-Mode: C++;-*-

// * BeginRiceCopyright *****************************************************
//
// $HeadURL$
// $Id$
//
// --------------------------------------------------------------------------
// Part of HPCToolkit (hpctoolkit.org)
//
// Information about sources of support for research and development of
// HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
// --------------------------------------------------------------------------
//
// Copyright ((c)) 2002-2018, Rice University
// 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 Rice University (RICE) 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 RICE 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 RICE 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.
//
// ******************************************************* EndRiceCopyright *

//***************************************************************************
//
// File:
//   $HeadURL$
//
// Purpose:
//   [The purpose of this file]
//
// Description:
//   [The set of functions, macros, etc. defined in the file]
//
//***************************************************************************

//**************************** MPI Include Files ****************************

#include <mpi.h>

//************************* System Include Files ****************************

#include <iostream>

#include <string>
using std::string;

#include <algorithm>

#include <stdint.h>

//*************************** User Include Files ****************************

#include <include/uint.h>

#include "ParallelAnalysis.hpp"

#include <lib/analysis/CallPath.hpp>
#include <lib/analysis/Util.hpp>

#include <lib/support/diagnostics.h>
#include <lib/support/StrUtil.hpp>

//*************************** Forward Declarations **************************

#define DBG_CCT_MERGE 0

//***************************************************************************

namespace ParallelAnalysis {

//***************************************************************************
// forward declarations
//***************************************************************************

static void
packStringSet(const StringSet& profile,
		 uint8_t** buffer, size_t* bufferSz);

static StringSet*
unpackStringSet(uint8_t* buffer, size_t bufferSz);

//***************************************************************************
// private functions
//***************************************************************************

static void
broadcast_sizet
(
  size_t &size,
  int root,
  MPI_Comm comm
)
{
  long size_l = size;
  MPI_Bcast(&size_l, 1, MPI_LONG, root, comm);
  size = size_l;
}

//***************************************************************************
// interface functions
//***************************************************************************

void
broadcast
(
  Prof::CallPath::Profile*& profile,
  int myRank,
  MPI_Comm comm
)
{
  size_t size = 0;
  uint8_t* buf = NULL;

  if (myRank == 0) {
    packProfile(*profile, &buf, &size);
  }

  broadcast_sizet(size, comm);

  if (myRank != 0) {
    buf = new uint8_t[size];
  }

  MPI_Bcast(buf, size, MPI_BYTE, 0, comm);

  if (myRank != 0) {
    profile = unpackProfile(buf, size);
  }

  delete [] buf;
}

void
broadcast
(
  StringSet &stringSet,
  int myRank,
  MPI_Comm comm
)
{
  size_t size = 0;
  uint8_t* buf = NULL;

  if (myRank == 0) {
    packStringSet(stringSet, &buf, &size);
  }

  broadcast_sizet(size, comm);

  if (myRank != 0) {
    buf = new uint8_t[size];
  }

  MPI_Bcast(buf, size, MPI_BYTE, 0, comm);

  if (myRank != 0) {
    StringSet *rhs = unpackStringSet(buf, size);
    stringSet += *rhs;
    delete rhs;
  }

  delete [] buf;
}

void
packSend(Prof::CallPath::Profile* profile,
	 int dest, int myRank, MPI_Comm comm)
{
  uint8_t* profileBuf = NULL;
  size_t profileBufSz = 0;
  packProfile(*profile, &profileBuf, &profileBufSz);
  MPI_Send(profileBuf, (int)profileBufSz, MPI_BYTE, dest, myRank, comm);
  free(profileBuf);
}

void
recvMerge(Prof::CallPath::Profile* profile,
	  int src, int myRank, MPI_Comm comm)
{
  // rank_x probes src
  MPI_Status mpistat;
  MPI_Probe(src, src, comm, &mpistat);
  int profileBufSz;
  MPI_Get_count(&mpistat, MPI_BYTE, &profileBufSz);

  // receive profile from src
  uint8_t *profileBuf = new uint8_t[profileBufSz];
  MPI_Recv(profileBuf, profileBufSz, MPI_BYTE, src, src, comm, &mpistat);
  Prof::CallPath::Profile* new_profile =
    unpackProfile(profileBuf, (size_t)profileBufSz);
  delete[] profileBuf;

  if (DBG_CCT_MERGE) {
    string pfx0 = "[" + StrUtil::toStr(myRank) + "]";
    string pfx1 = "[" + StrUtil::toStr(src) + "]";
    DIAG_DevMsgIf(1, profile->metricMgr()->toString(pfx0.c_str()));
    DIAG_DevMsgIf(1, new_profile->metricMgr()->toString(pfx1.c_str()));
  }

  int mergeTy = Prof::CallPath::Profile::Merge_MergeMetricByName;
  profile->merge(*new_profile, mergeTy);

  // merging the perf event statistics
  profile->metricMgr()->mergePerfEventStatistics(new_profile->metricMgr());

  if (DBG_CCT_MERGE) {
    string pfx = ("[" + StrUtil::toStr(src)
		  + " => " + StrUtil::toStr(myRank) + "]");
    DIAG_DevMsgIf(1, profile->metricMgr()->toString(pfx.c_str()));
  }

  delete new_profile;
}

void
packSend(std::pair<Prof::CallPath::Profile*,
	                ParallelAnalysis::PackedMetrics*> data,
	 int dest, int myRank, MPI_Comm comm)
{
  Prof::CallPath::Profile* profile = data.first;
  ParallelAnalysis::PackedMetrics* packedMetrics = data.second;
  packMetrics(*profile, *packedMetrics);
  MPI_Send(packedMetrics->data(), packedMetrics->dataSize(),
	   MPI_DOUBLE, dest, myRank, comm);
}

void
recvMerge(std::pair<Prof::CallPath::Profile*,
	  ParallelAnalysis::PackedMetrics*> data,
	  int src, int myRank, MPI_Comm comm)
{
  Prof::CallPath::Profile* profile = data.first;
  ParallelAnalysis::PackedMetrics* packedMetrics = data.second;

  // receive new metric data from src
  MPI_Status mpistat;
  MPI_Recv(packedMetrics->data(), packedMetrics->dataSize(),
	   MPI_DOUBLE, src, src, comm, &mpistat);
  DIAG_Assert(packedMetrics->verify(), DIAG_UnexpectedInput);
  unpackMetrics(*profile, *packedMetrics);
}

void
packSend(StringSet *stringSet,
	 int dest, int myRank, MPI_Comm comm)
{
  uint8_t* stringSetBuf = NULL;
  size_t stringSetBufSz = 0;
  packStringSet(*stringSet, &stringSetBuf, &stringSetBufSz);
  MPI_Send(stringSetBuf, (int)stringSetBufSz, MPI_BYTE,
	   dest, myRank, comm);
  free(stringSetBuf);
}

void
recvMerge(StringSet *stringSet,
	  int src, int myRank, MPI_Comm comm)
{
  // determine size of incoming packed directory set from src
  MPI_Status mpistat;
  MPI_Probe(src, src, comm, &mpistat);
  int stringSetBufSz = 0;
  MPI_Get_count(&mpistat, MPI_BYTE, &stringSetBufSz);

  // receive new stringSet from src
  uint8_t *stringSetBuf = new uint8_t[stringSetBufSz];
  MPI_Recv(stringSetBuf, stringSetBufSz, MPI_BYTE,
	   src, src, comm, &mpistat);
  StringSet *new_stringSet =
    unpackStringSet(stringSetBuf, (size_t) stringSetBufSz);
  delete[] stringSetBuf;
  *stringSet += *new_stringSet;
  delete new_stringSet;
}

//***************************************************************************

void
packProfile(const Prof::CallPath::Profile& profile,
	    uint8_t** buffer, size_t* bufferSz)
{
  // open_memstream: mallocs buffer and sets bufferSz
  FILE* fs = open_memstream((char**)buffer, bufferSz);

  uint wFlags = Prof::CallPath::Profile::WFlg_VirtualMetrics;
  Prof::CallPath::Profile::fmt_fwrite(profile, fs, wFlags);

  fclose(fs);
}

Prof::CallPath::Profile*
unpackProfile(uint8_t* buffer, size_t bufferSz)
{
  FILE* fs = fmemopen(buffer, bufferSz, "r");

  Prof::CallPath::Profile* prof = NULL;
  uint rFlags = Prof::CallPath::Profile::RFlg_VirtualMetrics;
  Prof::CallPath::Profile::fmt_fread(prof, fs, rFlags,
				     "(ParallelAnalysis::unpackProfile)",
				     NULL, NULL);

  fclose(fs);
  return prof;
}

//***************************************************************************

static void
packStringSet(const StringSet& stringSet,
	      uint8_t** buffer, size_t* bufferSz)
{
  // open_memstream: malloc buffer and sets bufferSz
  FILE* fs = open_memstream((char**)buffer, bufferSz);

  StringSet::fmt_fwrite(stringSet, fs);

  fclose(fs);
}

static StringSet*
unpackStringSet(uint8_t* buffer, size_t bufferSz)
{
  FILE* fs = fmemopen(buffer, bufferSz, "r");

  StringSet* stringSet = NULL;

  StringSet::fmt_fread(stringSet, fs);

  fclose(fs);

  return stringSet;
}

//***************************************************************************

void
packMetrics(const Prof::CallPath::Profile& profile,
	    ParallelAnalysis::PackedMetrics& packedMetrics)
{
  Prof::CCT::Tree& cct = *profile.cct();

  // pack derived metrics [mDrvdBeg, mDrvdEnd) from 'profile' into
  // 'packedMetrics'
  uint mDrvdBeg = packedMetrics.mDrvdBegId();
  uint mDrvdEnd = packedMetrics.mDrvdEndId();

  DIAG_Assert(packedMetrics.numNodes() == cct.maxDenseId() + 1, "");
  DIAG_Assert(packedMetrics.numMetrics() == mDrvdEnd - mDrvdBeg, "");

  for (Prof::CCT::ANodeIterator it(cct.root()); it.Current(); ++it) {
    Prof::CCT::ANode* n = it.current();
    for (uint mId1 = 0, mId2 = mDrvdBeg; mId2 < mDrvdEnd; ++mId1, ++mId2) {
      packedMetrics.idx(n->id(), mId1) = n->metric(mId2);
    }
  }
}

void
unpackMetrics(Prof::CallPath::Profile& profile,
	      const ParallelAnalysis::PackedMetrics& packedMetrics)
{
  Prof::CCT::Tree& cct = *profile.cct();

  // 1. unpack 'packedMetrics' into temporary derived metrics [mBegId,
  //    mEndId) in 'profile'
  uint mBegId = packedMetrics.mBegId(), mEndId = packedMetrics.mEndId();

  DIAG_Assert(packedMetrics.numNodes() == cct.maxDenseId() + 1, "");
  DIAG_Assert(packedMetrics.numMetrics() == mEndId - mBegId, "");

  for (uint nodeId = 1; nodeId < packedMetrics.numNodes(); ++nodeId) {
    for (uint mId1 = 0, mId2 = mBegId; mId2 < mEndId; ++mId1, ++mId2) {
      Prof::CCT::ANode* n = cct.findNode(nodeId);
      n->demandMetric(mId2) = packedMetrics.idx(nodeId, mId1);
    }
  }

  // 2. update derived metrics [mDrvdBeg, mDrvdEnd) based on new
  //    values in [mBegId, mEndId)
  uint mDrvdBeg = packedMetrics.mDrvdBegId();
  uint mDrvdEnd = packedMetrics.mDrvdEndId();
  cct.root()->computeMetricsIncr(*profile.metricMgr(), mDrvdBeg, mDrvdEnd,
				 Prof::Metric::AExprIncr::FnCombine);
}

//***************************************************************************

} // namespace ParallelAnalysis
<commit_msg>Fix comment.<commit_after>// -*-Mode: C++;-*-

// * BeginRiceCopyright *****************************************************
//
// $HeadURL$
// $Id$
//
// --------------------------------------------------------------------------
// Part of HPCToolkit (hpctoolkit.org)
//
// Information about sources of support for research and development of
// HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
// --------------------------------------------------------------------------
//
// Copyright ((c)) 2002-2018, Rice University
// 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 Rice University (RICE) 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 RICE 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 RICE 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.
//
// ******************************************************* EndRiceCopyright *

//***************************************************************************
//
// File:
//   $HeadURL$
//
// Purpose:
//   [The purpose of this file]
//
// Description:
//   [The set of functions, macros, etc. defined in the file]
//
//***************************************************************************

//**************************** MPI Include Files ****************************

#include <mpi.h>

//************************* System Include Files ****************************

#include <iostream>

#include <string>
using std::string;

#include <algorithm>

#include <stdint.h>

//*************************** User Include Files ****************************

#include <include/uint.h>

#include "ParallelAnalysis.hpp"

#include <lib/analysis/CallPath.hpp>
#include <lib/analysis/Util.hpp>

#include <lib/support/diagnostics.h>
#include <lib/support/StrUtil.hpp>

//*************************** Forward Declarations **************************

#define DBG_CCT_MERGE 0

//***************************************************************************

namespace ParallelAnalysis {

//***************************************************************************
// forward declarations
//***************************************************************************

static void
packStringSet(const StringSet& profile,
		 uint8_t** buffer, size_t* bufferSz);

static StringSet*
unpackStringSet(uint8_t* buffer, size_t bufferSz);

//***************************************************************************
// private functions
//***************************************************************************

static void
broadcast_sizet
(
  size_t &size,
  int root,
  MPI_Comm comm
)
{
  long size_l = size;
  MPI_Bcast(&size_l, 1, MPI_LONG, root, comm);
  size = size_l;
}

//***************************************************************************
// interface functions
//***************************************************************************

void
broadcast
(
  Prof::CallPath::Profile*& profile,
  int myRank,
  MPI_Comm comm
)
{
  size_t size = 0;
  uint8_t* buf = NULL;

  if (myRank == 0) {
    packProfile(*profile, &buf, &size);
  }

  broadcast_sizet(size, comm);

  if (myRank != 0) {
    buf = new uint8_t[size];
  }

  MPI_Bcast(buf, size, MPI_BYTE, 0, comm);

  if (myRank != 0) {
    profile = unpackProfile(buf, size);
  }

  delete [] buf;
}

void
broadcast
(
  StringSet &stringSet,
  int myRank,
  MPI_Comm comm
)
{
  size_t size = 0;
  uint8_t* buf = NULL;

  if (myRank == 0) {
    packStringSet(stringSet, &buf, &size);
  }

  broadcast_sizet(size, comm);

  if (myRank != 0) {
    buf = new uint8_t[size];
  }

  MPI_Bcast(buf, size, MPI_BYTE, 0, comm);

  if (myRank != 0) {
    StringSet *rhs = unpackStringSet(buf, size);
    stringSet += *rhs;
    delete rhs;
  }

  delete [] buf;
}

void
packSend(Prof::CallPath::Profile* profile,
	 int dest, int myRank, MPI_Comm comm)
{
  uint8_t* profileBuf = NULL;
  size_t profileBufSz = 0;
  packProfile(*profile, &profileBuf, &profileBufSz);
  MPI_Send(profileBuf, (int)profileBufSz, MPI_BYTE, dest, myRank, comm);
  free(profileBuf);
}

void
recvMerge(Prof::CallPath::Profile* profile,
	  int src, int myRank, MPI_Comm comm)
{
  // probe src
  MPI_Status mpistat;
  MPI_Probe(src, src, comm, &mpistat);
  int profileBufSz;
  MPI_Get_count(&mpistat, MPI_BYTE, &profileBufSz);

  // receive profile from src
  uint8_t *profileBuf = new uint8_t[profileBufSz];
  MPI_Recv(profileBuf, profileBufSz, MPI_BYTE, src, src, comm, &mpistat);
  Prof::CallPath::Profile* new_profile =
    unpackProfile(profileBuf, (size_t)profileBufSz);
  delete[] profileBuf;

  if (DBG_CCT_MERGE) {
    string pfx0 = "[" + StrUtil::toStr(myRank) + "]";
    string pfx1 = "[" + StrUtil::toStr(src) + "]";
    DIAG_DevMsgIf(1, profile->metricMgr()->toString(pfx0.c_str()));
    DIAG_DevMsgIf(1, new_profile->metricMgr()->toString(pfx1.c_str()));
  }

  int mergeTy = Prof::CallPath::Profile::Merge_MergeMetricByName;
  profile->merge(*new_profile, mergeTy);

  // merging the perf event statistics
  profile->metricMgr()->mergePerfEventStatistics(new_profile->metricMgr());

  if (DBG_CCT_MERGE) {
    string pfx = ("[" + StrUtil::toStr(src)
		  + " => " + StrUtil::toStr(myRank) + "]");
    DIAG_DevMsgIf(1, profile->metricMgr()->toString(pfx.c_str()));
  }

  delete new_profile;
}

void
packSend(std::pair<Prof::CallPath::Profile*,
	                ParallelAnalysis::PackedMetrics*> data,
	 int dest, int myRank, MPI_Comm comm)
{
  Prof::CallPath::Profile* profile = data.first;
  ParallelAnalysis::PackedMetrics* packedMetrics = data.second;
  packMetrics(*profile, *packedMetrics);
  MPI_Send(packedMetrics->data(), packedMetrics->dataSize(),
	   MPI_DOUBLE, dest, myRank, comm);
}

void
recvMerge(std::pair<Prof::CallPath::Profile*,
	  ParallelAnalysis::PackedMetrics*> data,
	  int src, int myRank, MPI_Comm comm)
{
  Prof::CallPath::Profile* profile = data.first;
  ParallelAnalysis::PackedMetrics* packedMetrics = data.second;

  // receive new metric data from src
  MPI_Status mpistat;
  MPI_Recv(packedMetrics->data(), packedMetrics->dataSize(),
	   MPI_DOUBLE, src, src, comm, &mpistat);
  DIAG_Assert(packedMetrics->verify(), DIAG_UnexpectedInput);
  unpackMetrics(*profile, *packedMetrics);
}

void
packSend(StringSet *stringSet,
	 int dest, int myRank, MPI_Comm comm)
{
  uint8_t* stringSetBuf = NULL;
  size_t stringSetBufSz = 0;
  packStringSet(*stringSet, &stringSetBuf, &stringSetBufSz);
  MPI_Send(stringSetBuf, (int)stringSetBufSz, MPI_BYTE,
	   dest, myRank, comm);
  free(stringSetBuf);
}

void
recvMerge(StringSet *stringSet,
	  int src, int myRank, MPI_Comm comm)
{
  // determine size of incoming packed directory set from src
  MPI_Status mpistat;
  MPI_Probe(src, src, comm, &mpistat);
  int stringSetBufSz = 0;
  MPI_Get_count(&mpistat, MPI_BYTE, &stringSetBufSz);

  // receive new stringSet from src
  uint8_t *stringSetBuf = new uint8_t[stringSetBufSz];
  MPI_Recv(stringSetBuf, stringSetBufSz, MPI_BYTE,
	   src, src, comm, &mpistat);
  StringSet *new_stringSet =
    unpackStringSet(stringSetBuf, (size_t) stringSetBufSz);
  delete[] stringSetBuf;
  *stringSet += *new_stringSet;
  delete new_stringSet;
}

//***************************************************************************

void
packProfile(const Prof::CallPath::Profile& profile,
	    uint8_t** buffer, size_t* bufferSz)
{
  // open_memstream: mallocs buffer and sets bufferSz
  FILE* fs = open_memstream((char**)buffer, bufferSz);

  uint wFlags = Prof::CallPath::Profile::WFlg_VirtualMetrics;
  Prof::CallPath::Profile::fmt_fwrite(profile, fs, wFlags);

  fclose(fs);
}

Prof::CallPath::Profile*
unpackProfile(uint8_t* buffer, size_t bufferSz)
{
  FILE* fs = fmemopen(buffer, bufferSz, "r");

  Prof::CallPath::Profile* prof = NULL;
  uint rFlags = Prof::CallPath::Profile::RFlg_VirtualMetrics;
  Prof::CallPath::Profile::fmt_fread(prof, fs, rFlags,
				     "(ParallelAnalysis::unpackProfile)",
				     NULL, NULL);

  fclose(fs);
  return prof;
}

//***************************************************************************

static void
packStringSet(const StringSet& stringSet,
	      uint8_t** buffer, size_t* bufferSz)
{
  // open_memstream: malloc buffer and sets bufferSz
  FILE* fs = open_memstream((char**)buffer, bufferSz);

  StringSet::fmt_fwrite(stringSet, fs);

  fclose(fs);
}

static StringSet*
unpackStringSet(uint8_t* buffer, size_t bufferSz)
{
  FILE* fs = fmemopen(buffer, bufferSz, "r");

  StringSet* stringSet = NULL;

  StringSet::fmt_fread(stringSet, fs);

  fclose(fs);

  return stringSet;
}

//***************************************************************************

void
packMetrics(const Prof::CallPath::Profile& profile,
	    ParallelAnalysis::PackedMetrics& packedMetrics)
{
  Prof::CCT::Tree& cct = *profile.cct();

  // pack derived metrics [mDrvdBeg, mDrvdEnd) from 'profile' into
  // 'packedMetrics'
  uint mDrvdBeg = packedMetrics.mDrvdBegId();
  uint mDrvdEnd = packedMetrics.mDrvdEndId();

  DIAG_Assert(packedMetrics.numNodes() == cct.maxDenseId() + 1, "");
  DIAG_Assert(packedMetrics.numMetrics() == mDrvdEnd - mDrvdBeg, "");

  for (Prof::CCT::ANodeIterator it(cct.root()); it.Current(); ++it) {
    Prof::CCT::ANode* n = it.current();
    for (uint mId1 = 0, mId2 = mDrvdBeg; mId2 < mDrvdEnd; ++mId1, ++mId2) {
      packedMetrics.idx(n->id(), mId1) = n->metric(mId2);
    }
  }
}

void
unpackMetrics(Prof::CallPath::Profile& profile,
	      const ParallelAnalysis::PackedMetrics& packedMetrics)
{
  Prof::CCT::Tree& cct = *profile.cct();

  // 1. unpack 'packedMetrics' into temporary derived metrics [mBegId,
  //    mEndId) in 'profile'
  uint mBegId = packedMetrics.mBegId(), mEndId = packedMetrics.mEndId();

  DIAG_Assert(packedMetrics.numNodes() == cct.maxDenseId() + 1, "");
  DIAG_Assert(packedMetrics.numMetrics() == mEndId - mBegId, "");

  for (uint nodeId = 1; nodeId < packedMetrics.numNodes(); ++nodeId) {
    for (uint mId1 = 0, mId2 = mBegId; mId2 < mEndId; ++mId1, ++mId2) {
      Prof::CCT::ANode* n = cct.findNode(nodeId);
      n->demandMetric(mId2) = packedMetrics.idx(nodeId, mId1);
    }
  }

  // 2. update derived metrics [mDrvdBeg, mDrvdEnd) based on new
  //    values in [mBegId, mEndId)
  uint mDrvdBeg = packedMetrics.mDrvdBegId();
  uint mDrvdEnd = packedMetrics.mDrvdEndId();
  cct.root()->computeMetricsIncr(*profile.metricMgr(), mDrvdBeg, mDrvdEnd,
				 Prof::Metric::AExprIncr::FnCombine);
}

//***************************************************************************

} // namespace ParallelAnalysis
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * 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 "modules/perception/common/perception_gflags.h"

DEFINE_string(perception_adapter_config_filename,
              "modules/perception/conf/adapter.conf",
              "The adapter config filename");

/// lib/config_manager/config_manager.cc
DEFINE_string(config_manager_path, "./conf/config_manager.config",
              "The ModelConfig config paths file.");
DEFINE_string(work_root, "/apollo/modules/perception/",
              "perception work root direcotry.");

/// obstacle/base/object.cc
DEFINE_bool(is_serialize_point_cloud, false,
            "serialize and output object cloud");

/// obstacle/onboard/hdmap_input.cc
DEFINE_double(map_radius, 60.0, "get map radius of car center");
DEFINE_int32(map_sample_step, 1, "step for sample road boundary points");

/// obstacle/onboard/lidar_process.cc
DEFINE_bool(enable_hdmap_input, false, "enable hdmap input for roi filter");
DEFINE_string(onboard_roi_filter, "DummyROIFilter", "onboard roi filter");
DEFINE_string(onboard_segmentor, "DummySegmentation", "onboard segmentation");
DEFINE_string(onboard_object_builder, "DummyObjectBuilder",
              "onboard object builder");
DEFINE_string(onboard_tracker, "DummyTracker", "onboard tracker");
DEFINE_string(onboard_type_fuser, "DummyTypeFuser", "onboard type fuser");

DEFINE_int32(tf2_buff_in_ms, 10, "the tf2 buff size in ms");
DEFINE_int32(localization_buffer_size, 40, "localization buffer size");
DEFINE_string(lidar_tf2_frame_id, "novatel", "the tf2 transform frame id");
DEFINE_string(lidar_tf2_child_frame_id, "velodyne64",
              "the tf2 transform child frame id");
DEFINE_string(obstacle_module_name, "perception_obstacle",
              "perception obstacle module name");
DEFINE_bool(enable_visualization, false, "enable visualization for debug");

/// obstacle/perception.cc
/* dag streaming config for Apollo 2.0 */
DEFINE_string(dag_config_path, "./conf/dag_streaming.config",
              "Onboard DAG Streaming config.");

/// obstacle/onboard/radar_process_subnode.cc
DEFINE_string(onboard_radar_detector, "DummyRadarDetector",
              "onboard radar detector");
DEFINE_string(radar_tf2_frame_id, "novatel", "the tf2 transform frame id");
DEFINE_string(radar_tf2_child_frame_id, "radar",
              "the tf2 transform child frame id");
DEFINE_double(front_radar_forward_distance, 120.0,
              "get front radar forward distancer");
DEFINE_string(radar_extrinsic_file,
              "modules/perception/data/params/radar_extrinsics.yaml",
              "radar extrinsic file");
DEFINE_string(short_camera_extrinsic_file,
              "modules/perception/data/params/short_camera_extrinsics.yaml",
              "short_camera extrinsic file");

/// obstacle/onboard/camera_process_subnode.cc
// Ex: /apollo/modules/perception/data/yolo_camera_detector_test/test.jpg
DEFINE_string(image_file_path, "", "Debug image file");
DEFINE_bool(image_file_debug, false, "Debug ROS to CV image");

/// modules/perception/lib/config_manager/calibration_config_manager.cc
DEFINE_string(front_camera_extrinsics_file,
              "modules/perception/data/params/front_camera_extrinsics.yaml",
              "front_camera extrinsic file");
DEFINE_string(front_camera_intrinsics_file,
              "modules/perception/data/params/front_camera_intrinsics.yaml",
              "front_camera intrinsic file");

/// obstacle/onboard/fusion_subnode.cc
DEFINE_string(onboard_fusion, "ProbabilisticFusion",
              "fusion name which enabled onboard");

DEFINE_double(query_signal_range, 100.0, "max distance to front signals");
DEFINE_bool(output_raw_img, false, "write raw image to disk");
DEFINE_bool(output_debug_img, false, "write debug image to disk");

/// Temporarily change Kalman motion fusion to config here.
DEFINE_double(q_matrix_coefficient_amplifier, 0.5,
              "Kalman fitler matrix Q coeffcients");
DEFINE_double(r_matrix_amplifier, 1, "Kalman fitler matrix r coeffcients");
DEFINE_double(p_matrix_amplifier, 1, "Kalman fitler matrix p coeffcients");

DEFINE_double(a_matrix_covariance_coeffcient_1, 0.05,
              "Kalman fitler matrix a coeffcients, a_matrix_(0, 2)");
DEFINE_double(a_matrix_covariance_coeffcient_2, 0.05,
              "Kalman fitler matrix a coeffcients, a_matrix_(1, 3)");

/// calibration_config_manager.cc
DEFINE_int32(obs_camera_detector_gpu, 0, "device id for camera detector");

// obstacle/onboard/lane_post_processing_subnode.cc
DEFINE_string(onboard_lane_post_processor, "CCLanePostProcessor",
              "onboard lane post-processing algorithm name");

/// visualization

DEFINE_bool(show_radar_objects, false, "");

DEFINE_bool(show_camera_objects2d, false, "");
DEFINE_bool(show_camera_objects, false, "");
DEFINE_bool(show_camera_parsing, false, "");

DEFINE_bool(show_fused_objects, false, "");

DEFINE_bool(show_fusion_association, false, "");

DEFINE_bool(capture_screen, false, "");

DEFINE_string(screen_output_dir, "./", "");

DEFINE_string(frame_visualizer, "GLFusionVisualizer", "");

DEFINE_bool(async_fusion, false, "use distance angle ");
DEFINE_bool(use_distance_angle_fusion, true,
            "use distance angle prob distance in fusion");
DEFINE_bool(publish_fusion_event, false, "publish fusion event");
DEFINE_bool(bag_mode, false, "run perception in bag mode");

DEFINE_bool(show_motion, false, "visualize motion and object trajectories");
DEFINE_bool(skip_camera_frame, false, "skip camera frame");
DEFINE_int32(camera_hz, 30, "camera hz");
DEFINE_string(fusion_publish_sensor_id, "velodyne_64", "fusion publish id");

DEFINE_int32(pbf_fusion_assoc_distance_percent, 20, "fusion distance percent");
DEFINE_double(pbf_distance_speed_cos_diff, 0.5, "fusion velocity cosine diff");

DEFINE_string(cc_lane_post_processor_config_file,
              "modules/perception/model/camera/lane_post_process_config.pb.txt",
              "The config file of cc_lane_post_processor.");
DEFINE_string(probabilistic_fusion_config_file,
              "modules/perception/model/probabilistic_fusion_config.pb.txt",
              "The config file of probabilistic_fusion.");
DEFINE_string(yolo_config_filename, "config.pt", "Yolo config filename.");
DEFINE_string(
    yolo_camera_detector_config,
    "modules/perception/model/camera/yolo_camera_detector_config.pb.txt",
    "Yolo camera detector config filename.");
DEFINE_string(modest_radar_detector_config,
              "modules/perception/model/modest_radar_detector_config.pb.txt",
              "modest radar detector config filename.");
DEFINE_string(tracker_config, "modules/perception/model/tracker_config.pb.txt",
              "tracker config filename.");
DEFINE_string(sequence_type_fuser_config,
              "modules/perception/model/sequence_type_fuser_config.pb.txt",
              "sequence_type_fuser config filename.");
DEFINE_string(async_fusion_config,
              "modules/perception/model/async_fusion_config.pb.txt",
              "async_fuser config filename.");
DEFINE_string(
    geometry_camera_converter_config,
    "modules/perception/model/geometry_camera_converter_config.pb.txt",
    "geometry_camera_converter config filename.");
<commit_msg>Bugfix for #4061<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * 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 "modules/perception/common/perception_gflags.h"

DEFINE_string(perception_adapter_config_filename,
              "modules/perception/conf/adapter.conf",
              "The adapter config filename");

/// lib/config_manager/config_manager.cc
DEFINE_string(config_manager_path, "./conf/config_manager.config",
              "The ModelConfig config paths file.");
DEFINE_string(work_root, "/apollo/modules/perception/",
              "perception work root direcotry.");

/// obstacle/base/object.cc
DEFINE_bool(is_serialize_point_cloud, false,
            "serialize and output object cloud");

/// obstacle/onboard/hdmap_input.cc
DEFINE_double(map_radius, 60.0, "get map radius of car center");
DEFINE_int32(map_sample_step, 1, "step for sample road boundary points");

/// obstacle/onboard/lidar_process.cc
DEFINE_bool(enable_hdmap_input, false, "enable hdmap input for roi filter");
DEFINE_string(onboard_roi_filter, "DummyROIFilter", "onboard roi filter");
DEFINE_string(onboard_segmentor, "DummySegmentation", "onboard segmentation");
DEFINE_string(onboard_object_builder, "DummyObjectBuilder",
              "onboard object builder");
DEFINE_string(onboard_tracker, "DummyTracker", "onboard tracker");
DEFINE_string(onboard_type_fuser, "DummyTypeFuser", "onboard type fuser");

DEFINE_int32(tf2_buff_in_ms, 10, "the tf2 buff size in ms");
DEFINE_int32(localization_buffer_size, 40, "localization buffer size");
DEFINE_string(lidar_tf2_frame_id, "novatel", "the tf2 transform frame id");
DEFINE_string(lidar_tf2_child_frame_id, "velodyne64",
              "the tf2 transform child frame id");
DEFINE_string(obstacle_module_name, "perception_obstacle",
              "perception obstacle module name");
DEFINE_bool(enable_visualization, false, "enable visualization for debug");

/// obstacle/perception.cc
/* dag streaming config for Apollo 2.0 */
DEFINE_string(dag_config_path, "./conf/dag_streaming.config",
              "Onboard DAG Streaming config.");

/// obstacle/onboard/radar_process_subnode.cc
DEFINE_string(onboard_radar_detector, "DummyRadarDetector",
              "onboard radar detector");
DEFINE_string(radar_tf2_frame_id, "novatel", "the tf2 transform frame id");
DEFINE_string(radar_tf2_child_frame_id, "radar",
              "the tf2 transform child frame id");
DEFINE_double(front_radar_forward_distance, 120.0,
              "get front radar forward distancer");
DEFINE_string(radar_extrinsic_file,
              "modules/perception/data/params/radar_extrinsics.yaml",
              "radar extrinsic file");
DEFINE_string(short_camera_extrinsic_file,
              "modules/perception/data/params/short_camera_extrinsics.yaml",
              "short_camera extrinsic file");

/// obstacle/onboard/camera_process_subnode.cc
// Ex: /apollo/modules/perception/data/yolo_camera_detector_test/test.jpg
DEFINE_string(image_file_path, "", "Debug image file");
DEFINE_bool(image_file_debug, false, "Debug ROS to CV image");

/// modules/perception/lib/config_manager/calibration_config_manager.cc
DEFINE_string(front_camera_extrinsics_file,
              "modules/perception/data/params/front_camera_extrinsics.yaml",
              "front_camera extrinsic file");
DEFINE_string(front_camera_intrinsics_file,
              "modules/perception/data/params/front_camera_intrinsics.yaml",
              "front_camera intrinsic file");

/// obstacle/onboard/fusion_subnode.cc
DEFINE_string(onboard_fusion, "ProbabilisticFusion",
              "fusion name which enabled onboard");

DEFINE_double(query_signal_range, 100.0, "max distance to front signals");
DEFINE_bool(output_raw_img, false, "write raw image to disk");
DEFINE_bool(output_debug_img, false, "write debug image to disk");

/// Temporarily change Kalman motion fusion to config here.
DEFINE_double(q_matrix_coefficient_amplifier, 0.5,
              "Kalman fitler matrix Q coeffcients");
DEFINE_double(r_matrix_amplifier, 1, "Kalman fitler matrix r coeffcients");
DEFINE_double(p_matrix_amplifier, 1, "Kalman fitler matrix p coeffcients");

DEFINE_double(a_matrix_covariance_coeffcient_1, 0.05,
              "Kalman fitler matrix a coeffcients, a_matrix_(0, 2)");
DEFINE_double(a_matrix_covariance_coeffcient_2, 0.05,
              "Kalman fitler matrix a coeffcients, a_matrix_(1, 3)");

/// calibration_config_manager.cc
DEFINE_int32(obs_camera_detector_gpu, 0, "device id for camera detector");

// obstacle/onboard/lane_post_processing_subnode.cc
DEFINE_string(onboard_lane_post_processor, "CCLanePostProcessor",
              "onboard lane post-processing algorithm name");

/// visualization

DEFINE_bool(show_radar_objects, false, "");

DEFINE_bool(show_camera_objects2d, false, "");
DEFINE_bool(show_camera_objects, false, "");
DEFINE_bool(show_camera_parsing, false, "");

DEFINE_bool(show_fused_objects, false, "");

DEFINE_bool(show_fusion_association, false, "");

DEFINE_bool(capture_screen, false, "");

DEFINE_string(screen_output_dir, "./", "");

DEFINE_string(frame_visualizer, "GLFusionVisualizer", "");

DEFINE_bool(async_fusion, false, "use distance angle ");
DEFINE_bool(use_distance_angle_fusion, true,
            "use distance angle prob distance in fusion");
DEFINE_bool(publish_fusion_event, false, "publish fusion event");
DEFINE_bool(bag_mode, false, "run perception in bag mode");

DEFINE_bool(show_motion, false, "visualize motion and object trajectories");
DEFINE_bool(skip_camera_frame, false, "skip camera frame");
DEFINE_int32(camera_hz, 30, "camera hz");
DEFINE_string(fusion_publish_sensor_id, "velodyne_64", "fusion publish id");

DEFINE_int32(pbf_fusion_assoc_distance_percent, 20, "fusion distance percent");
DEFINE_double(pbf_distance_speed_cos_diff, 0.5, "fusion velocity cosine diff");

DEFINE_string(cc_lane_post_processor_config_file,
              "modules/perception/model/camera/lane_post_process_config.pb.txt",
              "The config file of cc_lane_post_processor.");
DEFINE_string(probabilistic_fusion_config_file,
              "modules/perception/model/probabilistic_fusion_config.pb.txt",
              "The config file of probabilistic_fusion.");
DEFINE_string(yolo_config_filename, "config.pt", "Yolo config filename.");
DEFINE_string(
    yolo_camera_detector_config,
    "modules/perception/model/camera/yolo_camera_detector_config.pb.txt",
    "Yolo camera detector config filename.");
DEFINE_string(modest_radar_detector_config,
              "modules/perception/model/modest_radar_detector_config.pb.txt",
              "modest radar detector config filename.");
DEFINE_string(tracker_config, "modules/perception/model/tracker_config.pb.txt",
              "tracker config filename.");
DEFINE_string(sequence_type_fuser_config,
              "modules/perception/model/sequence_type_fuser_config.pb.txt",
              "sequence_type_fuser config filename.");
DEFINE_string(async_fusion_config,
              "modules/perception/model/async_fusion_config.pb.txt",
              "async_fuser config filename.");
DEFINE_string(
    geometry_camera_converter_config,
    "modules/perception/model/camera/geometry_camera_converter_config.pb.txt",
    "geometry_camera_converter config filename.");
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2020 The Apollo Authors. All Rights Reserved.
 *
 * 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 "modules/planning/pipeline/feature_generator.h"

#include <cmath>
#include <string>

#include "absl/strings/str_cat.h"
#include "cyber/common/file.h"
#include "cyber/record/record_reader.h"
#include "modules/common/adapters/adapter_gflags.h"
#include "modules/planning/common/planning_gflags.h"

DEFINE_string(planning_data_dir, "/apollo/modules/planning/data/",
              "Prefix of files to store learning_data_frame data");
DEFINE_int32(localization_freq, 100, "frequence of localization message");
DEFINE_int32(planning_freq, 10, "frequence of planning message");
DEFINE_int32(learning_data_frame_num_per_file, 100,
             "number of learning_data_frame to write out in one data file.");
DEFINE_bool(enable_binary_learning_data, true,
            "True to generate protobuf binary data file.");

namespace apollo {
namespace planning {

using apollo::canbus::Chassis;
using apollo::cyber::record::RecordMessage;
using apollo::cyber::record::RecordReader;
using apollo::localization::LocalizationEstimate;
using apollo::perception::TrafficLightDetection;
using apollo::routing::RoutingResponse;

void FeatureGenerator::Init() {}

void FeatureGenerator::WriteOutLearningData(const LearningData& learning_data,
                                            const std::string& file_name) {
  if (FLAGS_enable_binary_learning_data) {
    cyber::common::SetProtoToBinaryFile(learning_data, file_name);
    cyber::common::SetProtoToASCIIFile(learning_data, file_name + ".txt");
  } else {
    cyber::common::SetProtoToASCIIFile(learning_data, file_name);
  }
  learning_data_.Clear();
  ++learning_data_file_index_;
}

void FeatureGenerator::Close() {
  const std::string file_name = absl::StrCat(
      FLAGS_planning_data_dir, "/learning_data.",
      learning_data_file_index_, ".bin");
  WriteOutLearningData(learning_data_, file_name);
  AINFO << "Total learning_data_frame number:"
        << total_learning_data_frame_num_;
}

void FeatureGenerator::OnLocalization(
    const apollo::localization::LocalizationEstimate& le) {
  // auto features = learning_data_frame_->mutable_localization();
  // const auto& pose = le.pose();
  // features->mutable_position()->CopyFrom(pose.position());
  // features->set_heading(pose.heading());
  // features->mutable_linear_velocity()->CopyFrom(pose.linear_velocity());
  // features->mutable_linear_acceleration()->CopyFrom(pose.linear_acceleration());
  // features->mutable_angular_velocity()->CopyFrom(pose.angular_velocity());
  localization_for_label_.push_back(le);

  const int localization_msg_start_cnt =
      FLAGS_localization_freq * FLAGS_trajectory_time_length;
  if (static_cast<int>(localization_for_label_.size()) <
      localization_msg_start_cnt) {
    return;
  }

  // generate one frame data
  GenerateLearningDataFrame();

  const int localization_move_window_step =
      FLAGS_localization_freq / FLAGS_planning_freq;
  for (int i = 0; i < localization_move_window_step; ++i) {
    localization_for_label_.pop_front();
  }

  // write frames into a file
  if (learning_data_.learning_data_size() >=
      FLAGS_learning_data_frame_num_per_file) {
    const std::string file_name = absl::StrCat(
        FLAGS_planning_data_dir, "/learning_data.",
        learning_data_file_index_, ".bin");
    WriteOutLearningData(learning_data_, file_name);
  }
}

void FeatureGenerator::OnChassis(const apollo::canbus::Chassis& chassis) {
  /* To be fixed
  if (learning_data_frame_ == nullptr) {
    AERROR << "learning_data_frame_ pointer is nullptr";
    return;
  }
  auto features = learning_data_frame_->mutable_chassis();
  features->set_speed_mps(chassis.speed_mps());
  features->set_throttle_percentage(chassis.throttle_percentage());
  features->set_brake_percentage(chassis.brake_percentage());
  features->set_steering_percentage(chassis.steering_percentage());
  features->set_gear_location(chassis.gear_location());
  */
}

void FeatureGenerator::OnTafficLightDetection(
    const TrafficLightDetection& traffic_light_detection) {
  // AINFO << "traffic_light_detection received at frame["
  //      << total_learning_data_frame_num_ << "]";

  traffic_lights_.clear();
  for (int i = 0; i < traffic_light_detection.traffic_light_size(); ++i) {
    const auto& traffic_light_id =
        traffic_light_detection.traffic_light(i).id();
    if (traffic_light_id.empty()) continue;

    // AINFO << "  traffic_light_id[" << traffic_light_id << "] color["
    //       << traffic_light_detection.traffic_light(i).color() << "]";
    traffic_lights_[traffic_light_id] =
        traffic_light_detection.traffic_light(i).color();
  }
}

void FeatureGenerator::OnRoutingResponse(
  const apollo::routing::RoutingResponse& routing_response) {
  AINFO << "routing_response received at frame["
        << total_learning_data_frame_num_ << "]";
  routing_lane_ids_.clear();
  for (int i = 0; i < routing_response.road_size(); ++i) {
    for (int j = 0; j < routing_response.road(i).passage_size(); ++j) {
      for (int k = 0; k < routing_response.road(i).passage(j).segment_size();
          ++k) {
        routing_lane_ids_.push_back(
            routing_response.road(i).passage(j).segment(k).id());
      }
    }
  }
}

void FeatureGenerator::GenerateTrajectoryPoints(
    const std::list<apollo::localization::LocalizationEstimate>&
        localization_for_label,
    LearningDataFrame* learning_data_frame) {
  int i = -1;
  int cnt = 0;

  const int localization_sample_interval_for_trajectory_point =
      FLAGS_localization_freq / FLAGS_planning_freq;
  for (const auto& le : localization_for_label) {
    ++i;
    if ((i % localization_sample_interval_for_trajectory_point) != 0) {
      continue;
    }
    auto trajectory_point = learning_data_frame->add_trajectory_point();
    auto& pose = le.pose();
    trajectory_point->mutable_path_point()->set_x(pose.position().x());
    trajectory_point->mutable_path_point()->set_y(pose.position().y());
    trajectory_point->mutable_path_point()->set_z(pose.position().z());
    trajectory_point->mutable_path_point()->set_theta(pose.heading());
    auto v = std::sqrt(pose.linear_velocity().x() * pose.linear_velocity().x() +
                       pose.linear_velocity().y() * pose.linear_velocity().y());
    trajectory_point->set_v(v);
    auto a = std::sqrt(
        pose.linear_acceleration().x() * pose.linear_acceleration().x() +
        pose.linear_acceleration().y() * pose.linear_acceleration().y());
    trajectory_point->set_a(a);

    cnt++;
  }
  // AINFO << "number of trajectory points in one frame: " << cnt;
}

void FeatureGenerator::GenerateLearningDataFrame() {
  auto learning_data_frame = learning_data_.add_learning_data();
  // add timestamp_sec & frame_num
  learning_data_frame->set_timestamp_sec(
      localization_for_label_.back().header().timestamp_sec());
  learning_data_frame->set_frame_num(total_learning_data_frame_num_++);

  // add traffic_light
  learning_data_frame->clear_traffic_light();
  for (const auto& tl : traffic_lights_) {
    auto traffic_light = learning_data_frame->add_traffic_light();
    traffic_light->set_id(tl.first);
    traffic_light->set_color(tl.second);
  }

  // add routing
  auto features = learning_data_frame->mutable_routing_response();
  features->Clear();
  for (const auto& lane_id : routing_lane_ids_) {
    features->add_lane_id(lane_id);
  }

  // add trajectory_points
  GenerateTrajectoryPoints(localization_for_label_, learning_data_frame);
}

void FeatureGenerator::ProcessOfflineData(const std::string& record_filename) {
  RecordReader reader(record_filename);
  if (!reader.IsValid()) {
    AERROR << "Fail to open " << record_filename;
    return;
  }

  RecordMessage message;
  while (reader.ReadMessage(&message)) {
    if (message.channel_name == FLAGS_chassis_topic) {
      Chassis chassis;
      if (chassis.ParseFromString(message.content)) {
        OnChassis(chassis);
      }
    } else if (message.channel_name == FLAGS_localization_topic) {
      LocalizationEstimate localization;
      if (localization.ParseFromString(message.content)) {
        OnLocalization(localization);
      }
    } else if (message.channel_name == FLAGS_routing_response_topic) {
      RoutingResponse routing_response;
      if (routing_response.ParseFromString(message.content)) {
        OnRoutingResponse(routing_response);
      }
    } else if (message.channel_name == FLAGS_traffic_light_detection_topic) {
      TrafficLightDetection traffic_light_detection;
      if (traffic_light_detection.ParseFromString(message.content)) {
        OnTafficLightDetection(traffic_light_detection);
      }
    }
  }
}

}  // namespace planning
}  // namespace apollo
<commit_msg>planning: fixed localization feature data in learning data<commit_after>/******************************************************************************
 * Copyright 2020 The Apollo Authors. All Rights Reserved.
 *
 * 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 "modules/planning/pipeline/feature_generator.h"

#include <cmath>
#include <string>

#include "absl/strings/str_cat.h"
#include "cyber/common/file.h"
#include "cyber/record/record_reader.h"
#include "modules/common/adapters/adapter_gflags.h"
#include "modules/planning/common/planning_gflags.h"

DEFINE_string(planning_data_dir, "/apollo/modules/planning/data/",
              "Prefix of files to store learning_data_frame data");
DEFINE_int32(localization_freq, 100, "frequence of localization message");
DEFINE_int32(planning_freq, 10, "frequence of planning message");
DEFINE_int32(learning_data_frame_num_per_file, 100,
             "number of learning_data_frame to write out in one data file.");
DEFINE_bool(enable_binary_learning_data, true,
            "True to generate protobuf binary data file.");

namespace apollo {
namespace planning {

using apollo::canbus::Chassis;
using apollo::cyber::record::RecordMessage;
using apollo::cyber::record::RecordReader;
using apollo::localization::LocalizationEstimate;
using apollo::perception::TrafficLightDetection;
using apollo::routing::RoutingResponse;

void FeatureGenerator::Init() {}

void FeatureGenerator::WriteOutLearningData(const LearningData& learning_data,
                                            const std::string& file_name) {
  if (FLAGS_enable_binary_learning_data) {
    cyber::common::SetProtoToBinaryFile(learning_data, file_name);
    cyber::common::SetProtoToASCIIFile(learning_data, file_name + ".txt");
  } else {
    cyber::common::SetProtoToASCIIFile(learning_data, file_name);
  }
  learning_data_.Clear();
  ++learning_data_file_index_;
}

void FeatureGenerator::Close() {
  const std::string file_name = absl::StrCat(
      FLAGS_planning_data_dir, "/learning_data.",
      learning_data_file_index_, ".bin");
  WriteOutLearningData(learning_data_, file_name);
  AINFO << "Total learning_data_frame number:"
        << total_learning_data_frame_num_;
}

void FeatureGenerator::OnLocalization(
    const apollo::localization::LocalizationEstimate& le) {
  localization_for_label_.push_back(le);

  const int localization_msg_start_cnt =
      FLAGS_localization_freq * FLAGS_trajectory_time_length;
  if (static_cast<int>(localization_for_label_.size()) <
      localization_msg_start_cnt) {
    return;
  }

  // generate one frame data
  GenerateLearningDataFrame();

  const int localization_move_window_step =
      FLAGS_localization_freq / FLAGS_planning_freq;
  for (int i = 0; i < localization_move_window_step; ++i) {
    localization_for_label_.pop_front();
  }

  // write frames into a file
  if (learning_data_.learning_data_size() >=
      FLAGS_learning_data_frame_num_per_file) {
    const std::string file_name = absl::StrCat(
        FLAGS_planning_data_dir, "/learning_data.",
        learning_data_file_index_, ".bin");
    WriteOutLearningData(learning_data_, file_name);
  }
}

void FeatureGenerator::OnChassis(const apollo::canbus::Chassis& chassis) {
  /* To be fixed
  if (learning_data_frame_ == nullptr) {
    AERROR << "learning_data_frame_ pointer is nullptr";
    return;
  }
  auto features = learning_data_frame_->mutable_chassis();
  features->set_speed_mps(chassis.speed_mps());
  features->set_throttle_percentage(chassis.throttle_percentage());
  features->set_brake_percentage(chassis.brake_percentage());
  features->set_steering_percentage(chassis.steering_percentage());
  features->set_gear_location(chassis.gear_location());
  */
}

void FeatureGenerator::OnTafficLightDetection(
    const TrafficLightDetection& traffic_light_detection) {
  // AINFO << "traffic_light_detection received at frame["
  //      << total_learning_data_frame_num_ << "]";

  traffic_lights_.clear();
  for (int i = 0; i < traffic_light_detection.traffic_light_size(); ++i) {
    const auto& traffic_light_id =
        traffic_light_detection.traffic_light(i).id();
    if (traffic_light_id.empty()) continue;

    // AINFO << "  traffic_light_id[" << traffic_light_id << "] color["
    //       << traffic_light_detection.traffic_light(i).color() << "]";
    traffic_lights_[traffic_light_id] =
        traffic_light_detection.traffic_light(i).color();
  }
}

void FeatureGenerator::OnRoutingResponse(
  const apollo::routing::RoutingResponse& routing_response) {
  AINFO << "routing_response received at frame["
        << total_learning_data_frame_num_ << "]";
  routing_lane_ids_.clear();
  for (int i = 0; i < routing_response.road_size(); ++i) {
    for (int j = 0; j < routing_response.road(i).passage_size(); ++j) {
      for (int k = 0; k < routing_response.road(i).passage(j).segment_size();
          ++k) {
        routing_lane_ids_.push_back(
            routing_response.road(i).passage(j).segment(k).id());
      }
    }
  }
}

void FeatureGenerator::GenerateTrajectoryPoints(
    const std::list<apollo::localization::LocalizationEstimate>&
        localization_for_label,
    LearningDataFrame* learning_data_frame) {
  int i = -1;
  int cnt = 0;

  const int localization_sample_interval_for_trajectory_point =
      FLAGS_localization_freq / FLAGS_planning_freq;
  for (const auto& le : localization_for_label) {
    ++i;
    if ((i % localization_sample_interval_for_trajectory_point) != 0) {
      continue;
    }
    auto trajectory_point = learning_data_frame->add_trajectory_point();
    auto& pose = le.pose();
    trajectory_point->mutable_path_point()->set_x(pose.position().x());
    trajectory_point->mutable_path_point()->set_y(pose.position().y());
    trajectory_point->mutable_path_point()->set_z(pose.position().z());
    trajectory_point->mutable_path_point()->set_theta(pose.heading());
    auto v = std::sqrt(pose.linear_velocity().x() * pose.linear_velocity().x() +
                       pose.linear_velocity().y() * pose.linear_velocity().y());
    trajectory_point->set_v(v);
    auto a = std::sqrt(
        pose.linear_acceleration().x() * pose.linear_acceleration().x() +
        pose.linear_acceleration().y() * pose.linear_acceleration().y());
    trajectory_point->set_a(a);

    cnt++;
  }
  // AINFO << "number of trajectory points in one frame: " << cnt;
}

void FeatureGenerator::GenerateLearningDataFrame() {
  auto learning_data_frame = learning_data_.add_learning_data();
  // add timestamp_sec & frame_num
  learning_data_frame->set_timestamp_sec(
      localization_for_label_.back().header().timestamp_sec());
  learning_data_frame->set_frame_num(total_learning_data_frame_num_++);

  // add localization
  auto localization = learning_data_frame->mutable_localization();
  const auto& pose = localization_for_label_.back().pose();
  localization->mutable_position()->CopyFrom(pose.position());
  localization->set_heading(pose.heading());
  localization->mutable_linear_velocity()->CopyFrom(pose.linear_velocity());
  localization->mutable_linear_acceleration()->CopyFrom(
      pose.linear_acceleration());
  localization->mutable_angular_velocity()->CopyFrom(pose.angular_velocity());

  // add traffic_light
  learning_data_frame->clear_traffic_light();
  for (const auto& tl : traffic_lights_) {
    auto traffic_light = learning_data_frame->add_traffic_light();
    traffic_light->set_id(tl.first);
    traffic_light->set_color(tl.second);
  }

  // add routing
  auto routing_response = learning_data_frame->mutable_routing_response();
  routing_response->Clear();
  for (const auto& lane_id : routing_lane_ids_) {
    routing_response->add_lane_id(lane_id);
  }

  // add trajectory_points
  GenerateTrajectoryPoints(localization_for_label_, learning_data_frame);
}

void FeatureGenerator::ProcessOfflineData(const std::string& record_filename) {
  RecordReader reader(record_filename);
  if (!reader.IsValid()) {
    AERROR << "Fail to open " << record_filename;
    return;
  }

  RecordMessage message;
  while (reader.ReadMessage(&message)) {
    if (message.channel_name == FLAGS_chassis_topic) {
      Chassis chassis;
      if (chassis.ParseFromString(message.content)) {
        OnChassis(chassis);
      }
    } else if (message.channel_name == FLAGS_localization_topic) {
      LocalizationEstimate localization;
      if (localization.ParseFromString(message.content)) {
        OnLocalization(localization);
      }
    } else if (message.channel_name == FLAGS_routing_response_topic) {
      RoutingResponse routing_response;
      if (routing_response.ParseFromString(message.content)) {
        OnRoutingResponse(routing_response);
      }
    } else if (message.channel_name == FLAGS_traffic_light_detection_topic) {
      TrafficLightDetection traffic_light_detection;
      if (traffic_light_detection.ParseFromString(message.content)) {
        OnTafficLightDetection(traffic_light_detection);
      }
    }
  }
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2013 Preferred Networks and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library 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 for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef JUBATUS_CLIENT_COMMON_CLIENT_HPP_
#define JUBATUS_CLIENT_COMMON_CLIENT_HPP_

#include <stdint.h>
#include <map>
#include <string>
#include <jubatus/msgpack/rpc/client.h>

namespace jubatus {
namespace client {
namespace common {

class client {
 public:
  client(const std::string& host,
         uint64_t port,
         const std::string& name,
         unsigned int timeout_sec)
      : c_(host, port), name_(name) {
    c_.set_timeout(timeout_sec);
  }

  msgpack::rpc::client& get_client() {
    return c_;
  }

  std::string get_config() {
    msgpack::rpc::future f = c_.call("get_config", name_);
    return f.get<std::string>();
  }

  bool save(const std::string& id) {
    msgpack::rpc::future f = c_.call("save", name_, id);
    return f.get<bool>();
  }

  bool load(const std::string& id) {
    msgpack::rpc::future f = c_.call("load", name_, id);
    return f.get<bool>();
  }

  std::map<std::string, std::map<std::string, std::string> > get_status() {
    msgpack::rpc::future f = c_.call("get_status", name_);
    return f.get<std::map<std::string, std::map<std::string, std::string> > >();
  }

  bool do_mix() {
    msgpack::rpc::future f = c_.call("do_mix", name_);
    return f.get<bool>();
  }

  std::map<std::string, std::map<std::string, std::string> >
      get_proxy_status() {
    msgpack::rpc::future f = c_.call("get_proxy_status", name_);
    return f.get<std::map<std::string, std::map<std::string, std::string> > >();
  }

  std::string get_name() const {
    return name_;
  }

  void set_name(const std::string& name) {
    name_ = name;
  }

 protected:
  msgpack::rpc::client c_;
  std::string name_;
};

}  // namespace common
}  // namespace client
}  // namespace jubatus

#endif  // JUBATUS_CLIENT_COMMON_CLIENT_HPP_
<commit_msg>Fix return type of save in client<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2013 Preferred Networks and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library 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 for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef JUBATUS_CLIENT_COMMON_CLIENT_HPP_
#define JUBATUS_CLIENT_COMMON_CLIENT_HPP_

#include <stdint.h>
#include <map>
#include <string>
#include <jubatus/msgpack/rpc/client.h>

namespace jubatus {
namespace client {
namespace common {

class client {
 public:
  client(const std::string& host,
         uint64_t port,
         const std::string& name,
         unsigned int timeout_sec)
      : c_(host, port), name_(name) {
    c_.set_timeout(timeout_sec);
  }

  msgpack::rpc::client& get_client() {
    return c_;
  }

  std::string get_config() {
    msgpack::rpc::future f = c_.call("get_config", name_);
    return f.get<std::string>();
  }

  std::map<std::string, std::string> save(const std::string& id) {
    msgpack::rpc::future f = c_.call("save", name_, id);
    return f.get<std::map<std::string, std::string> >();
  }

  bool load(const std::string& id) {
    msgpack::rpc::future f = c_.call("load", name_, id);
    return f.get<bool>();
  }

  std::map<std::string, std::map<std::string, std::string> > get_status() {
    msgpack::rpc::future f = c_.call("get_status", name_);
    return f.get<std::map<std::string, std::map<std::string, std::string> > >();
  }

  bool do_mix() {
    msgpack::rpc::future f = c_.call("do_mix", name_);
    return f.get<bool>();
  }

  std::map<std::string, std::map<std::string, std::string> >
      get_proxy_status() {
    msgpack::rpc::future f = c_.call("get_proxy_status", name_);
    return f.get<std::map<std::string, std::map<std::string, std::string> > >();
  }

  std::string get_name() const {
    return name_;
  }

  void set_name(const std::string& name) {
    name_ = name;
  }

 protected:
  msgpack::rpc::client c_;
  std::string name_;
};

}  // namespace common
}  // namespace client
}  // namespace jubatus

#endif  // JUBATUS_CLIENT_COMMON_CLIENT_HPP_
<|endoftext|>