<commit_before>/*
  Transport PK

  Copyright 2010-201x held jointly by LANS/LANL, LBNL, and PNNL.
  Amanzi is released under the three-clause BSD License.
  The terms of use and "as is" disclaimer for this license are
  provided in the top-level COPYRIGHT file.

  Author: Konstantin Lipnikov (lipnikov@lanl.gov)
*/

#include <algorithm>

#include "ReconstructionCellGrad.hh"
#include "OperatorDefs.hh"
#include "transport_ats.hh"

namespace Amanzi {
namespace Transport {

/* *******************************************************************
 * Routine takes a parallel overlapping vector C and returns a parallel
 * overlapping vector F(C).
 ****************************************************************** */
void Transport_ATS::FunctionalTimeDerivative(double t,
                                                const Epetra_Vector& component,
                                                Epetra_Vector& f_component)
{
  // distribute vector
  auto component_tmp = Teuchos::rcp(new Epetra_Vector(component));
  component_tmp->Import(component, tcc->importer("cell"), Insert);

  Teuchos::ParameterList recon_list = plist_->sublist("reconstruction");
  lifting_->Init(recon_list);
  lifting_->Compute(component_tmp);

  // extract boundary conditions for the current component
  std::vector<int> bc_model(nfaces_wghost, Operators::OPERATOR_BC_NONE);
  std::vector<double> bc_value(nfaces_wghost);

  for (int m = 0; m < bcs_.size(); m++) {
    std::vector<int>& tcc_index = bcs_[m]->tcc_index();
    int ncomp = tcc_index.size();

    for (int i = 0; i < ncomp; i++) {
      if (current_component_ == tcc_index[i]) {
        for (auto it = bcs_[m]->begin(); it != bcs_[m]->end(); ++it) {
          int f = it->first;
          std::vector<double>& values = it->second;

          bc_model[f] = Operators::OPERATOR_BC_DIRICHLET;
          bc_value[f] = values[i];
        }
      }
    }
  }

  limiter_->Init(recon_list, flux_);
  limiter_->ApplyLimiter(component_tmp, 0, lifting_, bc_model, bc_value);
  lifting_->data()->ScatterMasterToGhosted("cell");

  // ADVECTIVE FLUXES
  // We assume that limiters made their job up to round-off errors.
  // Min-max condition will enforce robustness w.r.t. these errors.

  f_component.PutScalar(0.0);
  for (int f = 0; f < nfaces_wghost; f++) {  // loop over master and slave faces
    int c1 = (*upwind_cell_)[f];
    int c2 = (*downwind_cell_)[f];

    double u1, u2, umin, umax;
    if (c1 >= 0 && c2 >= 0) {
      u1 = component[c1];
      u2 = component[c2];
      umin = std::min(u1, u2);
      umax = std::max(u1, u2);
    } else if (c1 >= 0) {
      u1 = u2 = umin = umax = component[c1];
    } else if (c2 >= 0) {
      u1 = u2 = umin = umax = component[c2];
    }

    double u = fabs((*flux_)[0][f]);
    const AmanziGeometry::Point& xf = mesh_->face_centroid(f);

    double upwind_tcc, tcc_flux;
    if (c1 >= 0 && c1 < ncells_owned && c2 >= 0 && c2 < ncells_owned) {
      upwind_tcc = limiter_->getValue(c1, xf);
      upwind_tcc = std::max(upwind_tcc, umin);
      upwind_tcc = std::min(upwind_tcc, umax);

      tcc_flux = u * upwind_tcc;
      f_component[c1] -= tcc_flux;
      f_component[c2] += tcc_flux;

    } else if (c1 >= 0 && c1 < ncells_owned && (c2 >= ncells_owned || c2 < 0)) {
      upwind_tcc = limiter_->getValue(c1, xf);
      upwind_tcc = std::max(upwind_tcc, umin);
      upwind_tcc = std::min(upwind_tcc, umax);

      tcc_flux = u * upwind_tcc;
      f_component[c1] -= tcc_flux;

    } else if (c1 >= 0 && c1 < ncells_owned && (c2 < 0)) {
      upwind_tcc = component[c1];
      upwind_tcc = std::max(upwind_tcc, umin);
      upwind_tcc = std::min(upwind_tcc, umax);

      tcc_flux = u * upwind_tcc;
      f_component[c1] -= tcc_flux;

    } else if (c1 >= ncells_owned && c2 >= 0 && c2 < ncells_owned) {
      upwind_tcc = limiter_->getValue(c1, xf);
      upwind_tcc = std::max(upwind_tcc, umin);
      upwind_tcc = std::min(upwind_tcc, umax);

      tcc_flux = u * upwind_tcc;
      f_component[c2] += tcc_flux;
    }
  }

  // process external sources
  if (srcs_.size() != 0) {
    ComputeAddSourceTerms(t, 1., f_component, current_component_, current_component_);
  }

  for (int c = 0; c < ncells_owned; c++) {  // calculate conservative quantatity
    double vol_phi_ws_den = mesh_->cell_volume(c) * (*phi_)[0][c] * (*ws_current)[0][c] * (*mol_dens_current)[0][c];
    if ((*ws_current)[0][c] < 1e-12)
      vol_phi_ws_den = mesh_->cell_volume(c) * (*phi_)[0][c] * (*ws_next)[0][c] * (*mol_dens_next)[0][c];

    if (vol_phi_ws_den > water_tolerance_){
      f_component[c] /= vol_phi_ws_den;
    }
  }

  // BOUNDARY CONDITIONS for ADVECTION
  for (int m = 0; m < bcs_.size(); m++) {
    std::vector<int>& tcc_index = bcs_[m]->tcc_index();
    int ncomp = tcc_index.size();

    for (int i = 0; i < ncomp; i++) {
      if (current_component_ == tcc_index[i]) {
        for (auto it = bcs_[m]->begin(); it != bcs_[m]->end(); ++it) {
          int f = it->first;
          std::vector<double>& values = it->second;
          int c2 = (*downwind_cell_)[f];

          if (c2 >= 0 && f < nfaces_owned) {
            double u = fabs((*flux_)[0][f]);
            double vol_phi_ws_den = mesh_->cell_volume(c2) * (*phi_)[0][c2] * (*ws_current)[0][c2] * (*mol_dens_current)[0][c2];
            if ((*ws_current)[0][c2] < 1e-12)
              vol_phi_ws_den = mesh_->cell_volume(c2) * (*phi_)[0][c2] * (*ws_next)[0][c2] * (*mol_dens_next)[0][c2];

            double tcc_flux = u * values[i];
            if (vol_phi_ws_den > water_tolerance_ ){
              f_component[c2] += tcc_flux / vol_phi_ws_den;
            }
          }
        }
      }
    }
  }
}

}  // namespace Transport
}  // namespace Amanzi

<commit_msg>Fixed a parallel bug in transport.<commit_after>/*
  Transport PK

  Copyright 2010-201x held jointly by LANS/LANL, LBNL, and PNNL.
  Amanzi is released under the three-clause BSD License.
  The terms of use and "as is" disclaimer for this license are
  provided in the top-level COPYRIGHT file.

  Author: Konstantin Lipnikov (lipnikov@lanl.gov)
*/

#include <algorithm>

#include "ReconstructionCellGrad.hh"
#include "OperatorDefs.hh"
#include "transport_ats.hh"

namespace Amanzi {
namespace Transport {

/* *******************************************************************
 * Routine takes a parallel overlapping vector C and returns a parallel
 * overlapping vector F(C).
 ****************************************************************** */
void Transport_ATS::FunctionalTimeDerivative(double t,
                                                const Epetra_Vector& component,
                                                Epetra_Vector& f_component)
{
  // distribute vector
  auto component_tmp = Teuchos::rcp(new Epetra_Vector(component));
  component_tmp->Import(component, tcc->importer("cell"), Insert);

  Teuchos::ParameterList recon_list = plist_->sublist("reconstruction");
  lifting_->Init(recon_list);
  lifting_->Compute(component_tmp);

  // extract boundary conditions for the current component
  std::vector<int> bc_model(nfaces_wghost, Operators::OPERATOR_BC_NONE);
  std::vector<double> bc_value(nfaces_wghost);

  for (int m = 0; m < bcs_.size(); m++) {
    std::vector<int>& tcc_index = bcs_[m]->tcc_index();
    int ncomp = tcc_index.size();

    for (int i = 0; i < ncomp; i++) {
      if (current_component_ == tcc_index[i]) {
        for (auto it = bcs_[m]->begin(); it != bcs_[m]->end(); ++it) {
          int f = it->first;
          std::vector<double>& values = it->second;

          bc_model[f] = Operators::OPERATOR_BC_DIRICHLET;
          bc_value[f] = values[i];
        }
      }
    }
  }

  limiter_->Init(recon_list, flux_);
  limiter_->ApplyLimiter(component_tmp, 0, lifting_, bc_model, bc_value);
  lifting_->data()->ScatterMasterToGhosted("cell");

  // ADVECTIVE FLUXES
  // We assume that limiters made their job up to round-off errors.
  // Min-max condition will enforce robustness w.r.t. these errors.

  f_component.PutScalar(0.0);
  for (int f = 0; f < nfaces_wghost; f++) {  // loop over master and slave faces
    int c1 = (*upwind_cell_)[f];
    int c2 = (*downwind_cell_)[f];

    double u1, u2, umin, umax;
    if (c1 >= 0 && c2 >= 0) {
      u1 = (*component_tmp)[c1];
      u2 = (*component_tmp)[c2];
      umin = std::min(u1, u2);
      umax = std::max(u1, u2);
    } else if (c1 >= 0) {
      u1 = u2 = umin = umax = (*component_tmp)[c1];
    } else if (c2 >= 0) {
      u1 = u2 = umin = umax = (*component_tmp)[c2];
    }

    double u = fabs((*flux_)[0][f]);
    const AmanziGeometry::Point& xf = mesh_->face_centroid(f);

    double upwind_tcc, tcc_flux;
    if (c1 >= 0 && c1 < ncells_owned && c2 >= 0 && c2 < ncells_owned) {
      upwind_tcc = limiter_->getValue(c1, xf);
      upwind_tcc = std::max(upwind_tcc, umin);
      upwind_tcc = std::min(upwind_tcc, umax);

      tcc_flux = u * upwind_tcc;
      f_component[c1] -= tcc_flux;
      f_component[c2] += tcc_flux;

    } else if (c1 >= 0 && c1 < ncells_owned && (c2 >= ncells_owned || c2 < 0)) {
      upwind_tcc = limiter_->getValue(c1, xf);
      upwind_tcc = std::max(upwind_tcc, umin);
      upwind_tcc = std::min(upwind_tcc, umax);

      tcc_flux = u * upwind_tcc;
      f_component[c1] -= tcc_flux;

    } else if (c1 >= 0 && c1 < ncells_owned && (c2 < 0)) {
      upwind_tcc = component[c1];
      upwind_tcc = std::max(upwind_tcc, umin);
      upwind_tcc = std::min(upwind_tcc, umax);

      tcc_flux = u * upwind_tcc;
      f_component[c1] -= tcc_flux;

    } else if (c1 >= ncells_owned && c2 >= 0 && c2 < ncells_owned) {
      upwind_tcc = limiter_->getValue(c1, xf);
      upwind_tcc = std::max(upwind_tcc, umin);
      upwind_tcc = std::min(upwind_tcc, umax);

      tcc_flux = u * upwind_tcc;
      f_component[c2] += tcc_flux;
    }
  }

  // process external sources
  if (srcs_.size() != 0) {
    ComputeAddSourceTerms(t, 1., f_component, current_component_, current_component_);
  }

  for (int c = 0; c < ncells_owned; c++) {  // calculate conservative quantatity
    double vol_phi_ws_den = mesh_->cell_volume(c) * (*phi_)[0][c] * (*ws_current)[0][c] * (*mol_dens_current)[0][c];
    if ((*ws_current)[0][c] < 1e-12)
      vol_phi_ws_den = mesh_->cell_volume(c) * (*phi_)[0][c] * (*ws_next)[0][c] * (*mol_dens_next)[0][c];

    if (vol_phi_ws_den > water_tolerance_){
      f_component[c] /= vol_phi_ws_den;
    }
  }

  // BOUNDARY CONDITIONS for ADVECTION
  for (int m = 0; m < bcs_.size(); m++) {
    std::vector<int>& tcc_index = bcs_[m]->tcc_index();
    int ncomp = tcc_index.size();

    for (int i = 0; i < ncomp; i++) {
      if (current_component_ == tcc_index[i]) {
        for (auto it = bcs_[m]->begin(); it != bcs_[m]->end(); ++it) {
          int f = it->first;
          std::vector<double>& values = it->second;
          int c2 = (*downwind_cell_)[f];

          if (c2 >= 0 && f < nfaces_owned) {
            double u = fabs((*flux_)[0][f]);
            double vol_phi_ws_den = mesh_->cell_volume(c2) * (*phi_)[0][c2] * (*ws_current)[0][c2] * (*mol_dens_current)[0][c2];
            if ((*ws_current)[0][c2] < 1e-12)
              vol_phi_ws_den = mesh_->cell_volume(c2) * (*phi_)[0][c2] * (*ws_next)[0][c2] * (*mol_dens_next)[0][c2];

            double tcc_flux = u * values[i];
            if (vol_phi_ws_den > water_tolerance_ ){
              f_component[c2] += tcc_flux / vol_phi_ws_den;
            }
          }
        }
      }
    }
  }
}

}  // namespace Transport
}  // namespace Amanzi

<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <mutex>

// struct once_flag;

// constexpr once_flag();

#include <mutex>

int main()
{
    std::once_flag f;
}
<commit_msg>noexcept and constexpr applied to <mutex>.<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <mutex>

// struct once_flag;

// constexpr once_flag() noexcept;

#include <mutex>

int main()
{
    {
    std::once_flag f;
    }
#ifndef _LIBCPP_HAS_NO_CONSTEXPR
    {
    constexpr std::once_flag f;
    }
#endif
}
<|endoftext|>


<commit_before>#ifndef MJOLNIR_UNDERDAMPED_LANGEVIN_INTEGRATOR
#define MJOLNIR_UNDERDAMPED_LANGEVIN_INTEGRATOR
#include <mjolnir/core/RandomNumberGenerator.hpp>
#include <mjolnir/core/System.hpp>
#include <mjolnir/core/ForceField.hpp>
#include <mjolnir/core/constants.hpp>

namespace mjolnir
{

// Simple underdamped Langevin integrator.
// The implementation is based on the article written by J. D. Honeycutt and
// D. Thirumalai (1992) Biopolymers and also the article written by Z. Guo and
// D. Thirumalai (1995) Biopolymers. Same algorithm used as default Langevin
// integrator in CafeMol that is developed by H. Kenzaki et al., (2011) JCTC.
template<typename traitsT>
class UnderdampedLangevinStepper
{
  public:
    typedef traitsT traits_type;
    typedef System<traits_type>     system_type;
    typedef ForceField<traits_type> forcefield_type;
    typedef RandomNumberGenerator<traits_type>    rng_type;
    typedef typename traits_type::boundary_type   boundary_type;
    typedef typename traits_type::real_type       real_type;
    typedef typename traits_type::coordinate_type coordinate_type;

    struct parameter_set
    {
        real_type       gamma;
        real_type       sqrt_gamma_over_mass;
        coordinate_type accel;
    };

  public:

    UnderdampedLangevinStepper(const real_type dt,
            std::vector<real_type> gamma, rng_type&& rng)
        : dt_(dt), halfdt_(dt / 2), halfdt2_(dt * dt / 2),
          rng_(std::move(rng)),
          sqrt_gamma_over_mass_(gamma.size()),
          acceleration_(gamma.size())
    {
        gammas_ = std::move(gamma);
    }
    ~UnderdampedLangevinStepper() = default;

    void initialize(system_type& sys, forcefield_type& ff);
    real_type step(const real_type time, system_type& sys, forcefield_type& ff);

    real_type delta_t() const noexcept {return dt_;}
    void  set_delta_t(const real_type dt) noexcept
    {
        dt_ = dt; halfdt_ = dt / 2; halfdt2_ = dt * dt / 2;
    }

    void update(const system_type& sys)
    {
        if(!sys.has_attribute("temperature"))
        {
            throw std::out_of_range("mjolnir::UnderdampedLangevinStepper: "
                "Langevin Integrator requires reference temperature, but "
                "`temperature` is not found in `system.attribute`.");
        }

        this->temperature_ = sys.attribute("temperature");
        this->noise_coef_  = std::sqrt(2 * physics::constants<real_type>::kB() *
                                       this->temperature_ / dt_);
    }

  private:

    coordinate_type gen_gaussian_vec(const real_type coef)
    {
        return coordinate_type(this->rng_.gaussian(0.0, coef),
                               this->rng_.gaussian(0.0, coef),
                               this->rng_.gaussian(0.0, coef));
    }

  private:
    real_type dt_;
    real_type halfdt_;
    real_type halfdt2_;
    real_type temperature_;
    real_type noise_coef_;
    rng_type  rng_;

    std::vector<real_type>       gammas_;
    std::vector<real_type>       sqrt_gamma_over_mass_;
    std::vector<coordinate_type> acceleration_;
};

template<typename traitsT>
void UnderdampedLangevinStepper<traitsT>::initialize(
        system_type& system, forcefield_type& ff)
{
    // initialize temperature and noise intensity
    this->update(system);

    for(std::size_t i=0; i<system.size(); ++i)
    {
        system.force(i) = coordinate_type(0, 0, 0);
    }
    system.largest_displacement() = real_type(0.0);
    ff.calc_force(system);

    for(std::size_t i=0; i<system.size(); ++i)
    {
        const auto  rmass = system.rmass(i);
        const auto& force = system.force(i);

        sqrt_gamma_over_mass_[i] = std::sqrt(gammas_[i] * rmass);
        acceleration_[i] = force * rmass +
            this->gen_gaussian_vec(this->noise_coef_ * sqrt_gamma_over_mass_[i]);
    }
    return;
}

template<typename traitsT>
typename UnderdampedLangevinStepper<traitsT>::real_type
UnderdampedLangevinStepper<traitsT>::step(
        const real_type time, system_type& sys, forcefield_type& ff)
{
    real_type largest_disp2 = real_type(0.0);
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        auto&       p = sys.position(i); // position of i-th particle
        auto&       v = sys.velocity(i); // ditto
        auto&       f = sys.force(i);    // ditto
        const auto& a = this->acceleration_[i];
        auto    gamma = this->gammas_[i];

        const real_type gamma_dt_over_2           = gamma * halfdt_;
        const real_type one_minus_gamma_dt_over_2 = 1 - gamma_dt_over_2;

        const auto displacement =
            (dt_ * one_minus_gamma_dt_over_2) * v + halfdt2_ * a;

        p = sys.adjust_position(p + displacement);

        v *= one_minus_gamma_dt_over_2 * (one_minus_gamma_dt_over_2 *
             one_minus_gamma_dt_over_2 + gamma_dt_over_2);
        v += (halfdt_ * one_minus_gamma_dt_over_2) * a;

        f = coordinate_type(0, 0, 0);

        largest_disp2 = std::max(largest_disp2, length_sq(displacement));
    }
    sys.largest_displacement() = std::sqrt(largest_disp2); // use in neighbor list

    // calc f(t+dt)
    ff.calc_force(sys);

    // calc a(t+dt) and v(t+dt), generate noise
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        const auto  rm = sys.rmass(i);
        auto&       v  = sys.velocity(i);
        const auto& f  = sys.force(i);
        auto&       a  = this->acceleration_[i];

        a  = f * rm + gen_gaussian_vec(noise_coef_ * sqrt_gamma_over_mass_[i]);
        v += halfdt_ * (1 - gammas_[i] * halfdt_) * a;
    }

    return time + dt_;
}

} // mjolnir
#endif /* MJOLNIR_UNDERDAMPED_LANGEVIN_INTEGRATOR */
<commit_msg>add an accessor to UnderdampedLangevin<commit_after>#ifndef MJOLNIR_UNDERDAMPED_LANGEVIN_INTEGRATOR
#define MJOLNIR_UNDERDAMPED_LANGEVIN_INTEGRATOR
#include <mjolnir/core/RandomNumberGenerator.hpp>
#include <mjolnir/core/System.hpp>
#include <mjolnir/core/ForceField.hpp>
#include <mjolnir/core/constants.hpp>

namespace mjolnir
{

// Simple underdamped Langevin integrator.
// The implementation is based on the article written by J. D. Honeycutt and
// D. Thirumalai (1992) Biopolymers and also the article written by Z. Guo and
// D. Thirumalai (1995) Biopolymers. Same algorithm used as default Langevin
// integrator in CafeMol that is developed by H. Kenzaki et al., (2011) JCTC.
template<typename traitsT>
class UnderdampedLangevinStepper
{
  public:
    typedef traitsT traits_type;
    typedef System<traits_type>     system_type;
    typedef ForceField<traits_type> forcefield_type;
    typedef RandomNumberGenerator<traits_type>    rng_type;
    typedef typename traits_type::boundary_type   boundary_type;
    typedef typename traits_type::real_type       real_type;
    typedef typename traits_type::coordinate_type coordinate_type;

    struct parameter_set
    {
        real_type       gamma;
        real_type       sqrt_gamma_over_mass;
        coordinate_type accel;
    };

  public:

    UnderdampedLangevinStepper(const real_type dt,
            std::vector<real_type> gamma, rng_type&& rng)
        : dt_(dt), halfdt_(dt / 2), halfdt2_(dt * dt / 2),
          rng_(std::move(rng)),
          sqrt_gamma_over_mass_(gamma.size()),
          acceleration_(gamma.size())
    {
        gammas_ = std::move(gamma);
    }
    ~UnderdampedLangevinStepper() = default;

    void initialize(system_type& sys, forcefield_type& ff);
    real_type step(const real_type time, system_type& sys, forcefield_type& ff);

    real_type delta_t() const noexcept {return dt_;}
    void  set_delta_t(const real_type dt) noexcept
    {
        dt_ = dt; halfdt_ = dt / 2; halfdt2_ = dt * dt / 2;
    }

    void update(const system_type& sys)
    {
        if(!sys.has_attribute("temperature"))
        {
            throw std::out_of_range("mjolnir::UnderdampedLangevinStepper: "
                "Langevin Integrator requires reference temperature, but "
                "`temperature` is not found in `system.attribute`.");
        }

        this->temperature_ = sys.attribute("temperature");
        this->noise_coef_  = std::sqrt(2 * physics::constants<real_type>::kB() *
                                       this->temperature_ / dt_);
    }

    std::vector<real_type> const& parameters() const noexcept {return gammas_;}

  private:

    coordinate_type gen_gaussian_vec(const real_type coef)
    {
        return coordinate_type(this->rng_.gaussian(0.0, coef),
                               this->rng_.gaussian(0.0, coef),
                               this->rng_.gaussian(0.0, coef));
    }

  private:
    real_type dt_;
    real_type halfdt_;
    real_type halfdt2_;
    real_type temperature_;
    real_type noise_coef_;
    rng_type  rng_;

    std::vector<real_type>       gammas_;
    std::vector<real_type>       sqrt_gamma_over_mass_;
    std::vector<coordinate_type> acceleration_;
};

template<typename traitsT>
void UnderdampedLangevinStepper<traitsT>::initialize(
        system_type& system, forcefield_type& ff)
{
    // initialize temperature and noise intensity
    this->update(system);

    for(std::size_t i=0; i<system.size(); ++i)
    {
        system.force(i) = coordinate_type(0, 0, 0);
    }
    system.largest_displacement() = real_type(0.0);
    ff.calc_force(system);

    for(std::size_t i=0; i<system.size(); ++i)
    {
        const auto  rmass = system.rmass(i);
        const auto& force = system.force(i);

        sqrt_gamma_over_mass_[i] = std::sqrt(gammas_[i] * rmass);
        acceleration_[i] = force * rmass +
            this->gen_gaussian_vec(this->noise_coef_ * sqrt_gamma_over_mass_[i]);
    }
    return;
}

template<typename traitsT>
typename UnderdampedLangevinStepper<traitsT>::real_type
UnderdampedLangevinStepper<traitsT>::step(
        const real_type time, system_type& sys, forcefield_type& ff)
{
    real_type largest_disp2 = real_type(0.0);
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        auto&       p = sys.position(i); // position of i-th particle
        auto&       v = sys.velocity(i); // ditto
        auto&       f = sys.force(i);    // ditto
        const auto& a = this->acceleration_[i];
        auto    gamma = this->gammas_[i];

        const real_type gamma_dt_over_2           = gamma * halfdt_;
        const real_type one_minus_gamma_dt_over_2 = 1 - gamma_dt_over_2;

        const auto displacement =
            (dt_ * one_minus_gamma_dt_over_2) * v + halfdt2_ * a;

        p = sys.adjust_position(p + displacement);

        v *= one_minus_gamma_dt_over_2 * (one_minus_gamma_dt_over_2 *
             one_minus_gamma_dt_over_2 + gamma_dt_over_2);
        v += (halfdt_ * one_minus_gamma_dt_over_2) * a;

        f = coordinate_type(0, 0, 0);

        largest_disp2 = std::max(largest_disp2, length_sq(displacement));
    }
    sys.largest_displacement() = std::sqrt(largest_disp2); // use in neighbor list

    // calc f(t+dt)
    ff.calc_force(sys);

    // calc a(t+dt) and v(t+dt), generate noise
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        const auto  rm = sys.rmass(i);
        auto&       v  = sys.velocity(i);
        const auto& f  = sys.force(i);
        auto&       a  = this->acceleration_[i];

        a  = f * rm + gen_gaussian_vec(noise_coef_ * sqrt_gamma_over_mass_[i]);
        v += halfdt_ * (1 - gammas_[i] * halfdt_) * a;
    }

    return time + dt_;
}

} // mjolnir
#endif /* MJOLNIR_UNDERDAMPED_LANGEVIN_INTEGRATOR */
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// packet_manager_test.cpp
//
// Identification: test/wire/packet_manager_test.cpp
//
// Copyright (c) 2016-17, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "common/harness.h"
#include "gtest/gtest.h"
#include "common/logger.h"
#include "wire/libevent_server.h"
#include <pqxx/pqxx> /* libpqxx is used to instantiate C++ client */

#define NUM_THREADS 1

namespace peloton {
namespace test {

//===--------------------------------------------------------------------===//
// Packet Manager Tests
//===--------------------------------------------------------------------===//

class PacketManagerTests : public PelotonTest {};

static void *LaunchServer(peloton::wire::LibeventServer libeventserver) {
  try {
    libeventserver.StartServer();
  } catch (peloton::ConnectionException exception) {
    LOG_INFO("[LaunchServer] exception in thread");
  }
  return NULL;
}

/**
 * Simple select query test
 */
static void *SimpleQueryTest(void *) {
  try {
    pqxx::connection C(
        "host=127.0.0.1 port=15721 user=postgres sslmode=disable");
    LOG_INFO("[SimpleQueryTest] Connected to %s", C.dbname());
    pqxx::work W(C);

    peloton::wire::LibeventSocket *conn =
        peloton::wire::LibeventServer::GetConn(
            peloton::wire::LibeventServer::recent_connfd);

    EXPECT_EQ(conn->pkt_manager.is_started, true);
    EXPECT_EQ(conn->state, peloton::wire::CONN_READ);
    // create table and insert some data
    W.exec("DROP TABLE IF EXISTS employee;");
    W.exec("CREATE TABLE employee(id INT, name VARCHAR(100));");
    W.exec("INSERT INTO employee VALUES (1, 'Han LI');");
    W.exec("INSERT INTO employee VALUES (2, 'Shaokun ZOU');");
    W.exec("INSERT INTO employee VALUES (3, 'Yilei CHU');");

    pqxx::result R = W.exec("SELECT name FROM employee where id=1;");

    EXPECT_EQ(R.size(), 1);
    LOG_INFO("[SimpleQueryTest] Found %lu employees", R.size());
    W.commit();
  } catch (const std::exception &e) {
    LOG_INFO("[SimpleQueryTest] Exception occurred");
  }

  LOG_INFO("[SimpleQueryTest] Client has closed");
  return NULL;
}

/**
 * named prepare statement without parameters
 * TODO: add prepare's parameters when parser team fix the bug
 */

static void *PrepareStatementTest(void *) {
  try {
    pqxx::connection C(
        "host=127.0.0.1 port=15721 user=postgres sslmode=disable");
    LOG_INFO("[PrepareStatementTest] Connected to %s", C.dbname());
    pqxx::work W(C);

    peloton::wire::LibeventSocket *conn =
        peloton::wire::LibeventServer::GetConn(
            peloton::wire::LibeventServer::recent_connfd);

    // create table and insert some data
    W.exec("DROP TABLE IF EXISTS employee;");
    W.exec("CREATE TABLE employee(id INT, name VARCHAR(100));");
    W.exec("INSERT INTO employee VALUES (1, 'Han LI');");
    W.exec("INSERT INTO employee VALUES (2, 'Shaokun ZOU');");
    W.exec("INSERT INTO employee VALUES (3, 'Yilei CHU');");

    // test prepare statement
    C.prepare("searchstmt","SELECT name FROM employee WHERE id=1;");
    // invocation as in variable binding
    pqxx::result R = W.prepared("searchstmt").exec();
    W.commit();

    // test prepared statement already in statement cache
//    LOG_INFO("[Prepare statement cache] %d",conn->pkt_manager.ExistCachedStatement("searchstmt"));
    EXPECT_TRUE(conn->pkt_manager.ExistCachedStatement("searchstmt"));

    LOG_INFO("Prepare statement search result:%lu",R.size());
  } catch (const std::exception &e) {
    LOG_INFO("[PrepareStatementTest] Exception occurred");
  }

  LOG_INFO("[PrepareStatementTest] Client has closed");
  return NULL;
}

/**
 * Use std::thread to initiate peloton server and pqxx client in separate
 * threads
 * Simple query test to guarantee both sides run correctly
 * Callback method to close server after client finishes
 */
TEST_F(PacketManagerTests, SimpleQueryTest) {
  peloton::PelotonInit::Initialize();
  LOG_INFO("Server initialized");
  peloton::wire::LibeventServer libeventserver;
  std::thread serverThread(LaunchServer, libeventserver);
  while (!libeventserver.is_started) {
    sleep(1);
  }

  /* server & client running correctly */
  SimpleQueryTest(NULL);

  /* TODO: monitor packet_manager's status when receiving prepare statement from
   * client */
  // PrepareStatementTest(NULL);

  libeventserver.CloseServer();
  serverThread.join();
  LOG_INFO("Thread has joined");
  peloton::PelotonInit::Shutdown();
  LOG_INFO("Peloton has shut down\n");
}

TEST_F(PacketManagerTests, PrepareStatementTest) {
  peloton::PelotonInit::Initialize();
  LOG_INFO("Server initialized");
  peloton::wire::LibeventServer libeventserver;
  std::thread serverThread(LaunchServer, libeventserver);
  while (!libeventserver.is_started) {
    sleep(1);
  }

  PrepareStatementTest(NULL);

  libeventserver.CloseServer();
  serverThread.join();
  LOG_INFO("Thread has joined");
  peloton::PelotonInit::Shutdown();
  LOG_INFO("Peloton has shut down\n");
}

}  // End test namespace
}  // End peloton namespace
<commit_msg>add rollback test<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// packet_manager_test.cpp
//
// Identification: test/wire/packet_manager_test.cpp
//
// Copyright (c) 2016-17, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "common/harness.h"
#include "gtest/gtest.h"
#include "common/logger.h"
#include "wire/libevent_server.h"
#include <pqxx/pqxx> /* libpqxx is used to instantiate C++ client */

#define NUM_THREADS 1

namespace peloton {
namespace test {

//===--------------------------------------------------------------------===//
// Packet Manager Tests
//===--------------------------------------------------------------------===//

class PacketManagerTests : public PelotonTest {};

static void *LaunchServer(peloton::wire::LibeventServer libeventserver) {
  try {
    libeventserver.StartServer();
  } catch (peloton::ConnectionException exception) {
    LOG_INFO("[LaunchServer] exception in thread");
  }
  return NULL;
}

/**
 * Simple select query test
 */
static void *SimpleQueryTest(void *) {
  try {
    pqxx::connection C(
        "host=127.0.0.1 port=15721 user=postgres sslmode=disable");
    LOG_INFO("[SimpleQueryTest] Connected to %s", C.dbname());
    pqxx::work W(C);

    peloton::wire::LibeventSocket *conn =
        peloton::wire::LibeventServer::GetConn(
            peloton::wire::LibeventServer::recent_connfd);

    EXPECT_EQ(conn->pkt_manager.is_started, true);
    EXPECT_EQ(conn->state, peloton::wire::CONN_READ);
    // create table and insert some data
    W.exec("DROP TABLE IF EXISTS employee;");
    W.exec("CREATE TABLE employee(id INT, name VARCHAR(100));");
    W.exec("INSERT INTO employee VALUES (1, 'Han LI');");
    W.exec("INSERT INTO employee VALUES (2, 'Shaokun ZOU');");
    W.exec("INSERT INTO employee VALUES (3, 'Yilei CHU');");

    pqxx::result R = W.exec("SELECT name FROM employee where id=1;");

    EXPECT_EQ(R.size(), 1);
    LOG_INFO("[SimpleQueryTest] Found %lu employees", R.size());
    W.commit();
  } catch (const std::exception &e) {
    LOG_INFO("[SimpleQueryTest] Exception occurred");
  }

  LOG_INFO("[SimpleQueryTest] Client has closed");
  return NULL;
}

/**
 * named prepare statement without parameters
 * TODO: add prepare's parameters when parser team fix the bug
 */

static void *PrepareStatementTest(void *) {
  try {
    pqxx::connection C(
        "host=127.0.0.1 port=15721 user=postgres sslmode=disable");
    LOG_INFO("[PrepareStatementTest] Connected to %s", C.dbname());
    pqxx::work W(C);

    peloton::wire::LibeventSocket *conn =
        peloton::wire::LibeventServer::GetConn(
            peloton::wire::LibeventServer::recent_connfd);

    // create table and insert some data
    W.exec("DROP TABLE IF EXISTS employee;");
    W.exec("CREATE TABLE employee(id INT, name VARCHAR(100));");
    W.exec("INSERT INTO employee VALUES (1, 'Han LI');");
    W.exec("INSERT INTO employee VALUES (2, 'Shaokun ZOU');");
    W.exec("INSERT INTO employee VALUES (3, 'Yilei CHU');");

    // test prepare statement
    C.prepare("searchstmt","SELECT name FROM employee WHERE id=1;");
    // invocation as in variable binding
    pqxx::result R = W.prepared("searchstmt").exec();
    W.commit();

    // test prepared statement already in statement cache
//    LOG_INFO("[Prepare statement cache] %d",conn->pkt_manager.ExistCachedStatement("searchstmt"));
    EXPECT_TRUE(conn->pkt_manager.ExistCachedStatement("searchstmt"));

    LOG_INFO("Prepare statement search result:%lu",R.size());
  } catch (const std::exception &e) {
    LOG_INFO("[PrepareStatementTest] Exception occurred");
  }

  LOG_INFO("[PrepareStatementTest] Client has closed");
  return NULL;
}

/**
 * rollback test
 */
static void *RollbackTest(void *) {
  try {
    pqxx::connection C(
        "host=127.0.0.1 port=15721 user=postgres sslmode=disable");
    LOG_INFO("[RollbackTest] Connected to %s", C.dbname());
    pqxx::work W(C);

    peloton::wire::LibeventSocket *conn =
        peloton::wire::LibeventServer::GetConn(
            peloton::wire::LibeventServer::recent_connfd);

    EXPECT_EQ(conn->pkt_manager.is_started, true);
    EXPECT_EQ(conn->state, peloton::wire::CONN_READ);
    // create table and insert some data
    W.exec("DROP TABLE IF EXISTS employee;");
    W.exec("CREATE TABLE employee(id INT, name VARCHAR(100));");
    w.abort();

    // W.exec("INSERT INTO employee VALUES (1, 'Han LI');");
    // W.exec("INSERT INTO employee VALUES (2, 'Shaokun ZOU');");
    // W.exec("INSERT INTO employee VALUES (3, 'Yilei CHU');");

    pqxx::result R = W.exec("SELECT name FROM employee where id=1;");

    EXPECT_EQ(R.size(), 1);
    LOG_INFO("[RollbackTest] Found %lu employees", R.size());
    W.commit();
  } catch (const std::exception &e) {
    LOG_INFO("[RollbackTest] Exception occurred");
  }

  LOG_INFO("[RollbackTest] Client has closed");
  return NULL;
}

/**
 * Use std::thread to initiate peloton server and pqxx client in separate
 * threads
 * Simple query test to guarantee both sides run correctly
 * Callback method to close server after client finishes
 */
TEST_F(PacketManagerTests, SimpleQueryTest) {
  peloton::PelotonInit::Initialize();
  LOG_INFO("Server initialized");
  peloton::wire::LibeventServer libeventserver;
  std::thread serverThread(LaunchServer, libeventserver);
  while (!libeventserver.is_started) {
    sleep(1);
  }

  /* server & client running correctly */
  SimpleQueryTest(NULL);

  /* TODO: monitor packet_manager's status when receiving prepare statement from
   * client */
  // PrepareStatementTest(NULL);

  libeventserver.CloseServer();
  serverThread.join();
  LOG_INFO("Thread has joined");
  peloton::PelotonInit::Shutdown();
  LOG_INFO("Peloton has shut down\n");
}

TEST_F(PacketManagerTests, PrepareStatementTest) {
  peloton::PelotonInit::Initialize();
  LOG_INFO("Server initialized");
  peloton::wire::LibeventServer libeventserver;
  std::thread serverThread(LaunchServer, libeventserver);
  while (!libeventserver.is_started) {
    sleep(1);
  }

  PrepareStatementTest(NULL);

  libeventserver.CloseServer();
  serverThread.join();
  LOG_INFO("Thread has joined");
  peloton::PelotonInit::Shutdown();
  LOG_INFO("Peloton has shut down\n");
}

TEST_F(PacketManagerTests, RollbackTest) {
  peloton::PelotonInit::Initialize();
  LOG_INFO("Server initialized");
  peloton::wire::LibeventServer libeventserver;
  std::thread serverThread(LaunchServer, libeventserver);
  while (!libeventserver.is_started) {
    sleep(1);
  }

  RollbackTest(NULL);

  libeventserver.CloseServer();
  serverThread.join();
  LOG_INFO("Thread has joined");
  peloton::PelotonInit::Shutdown();
  LOG_INFO("Peloton has shut down\n");
}

}  // End test namespace
}  // End peloton namespace
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: 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 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file VM.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "VM.h"

using namespace std;
using namespace dev;
using namespace dev::eth;

void VM::reset(u256 _gas)
{
	m_gas = _gas;
	m_curPC = 0;
	m_jumpDests.reset();
}
<commit_msg>Build fix.<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: 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 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file VM.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "VM.h"

using namespace std;
using namespace dev;
using namespace dev::eth;

void VM::reset(u256 _gas)
{
	m_gas = _gas;
	m_curPC = 0;
	m_jumpDests.clear();
}
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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 OWNER 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 <modules/base/io/ivfsequencevolumereader.h>
#include <modules/base/io/ivfvolumewriter.h>
#include <inviwo/core/util/filesystem.h>

namespace inviwo {
IvfSequenceVolumeReader::IvfSequenceVolumeReader() {
    addExtension({"ivfs", "Sequence of Inviwo ivf volumes"});
}

std::shared_ptr<VolumeSequence> IvfSequenceVolumeReader::readData(const std::string &filePath) {
    std::string fileName = filePath;
    if (!filesystem::fileExists(fileName)) {
        std::string newPath = filesystem::addBasePath(fileName);

        if (filesystem::fileExists(newPath)) {
            fileName = newPath;
        } else {
            throw DataReaderException("Error could not find input file: " + fileName, IvwContext);
        }
    }

    auto volumes = std::make_shared<VolumeSequence>();

    auto dir = filesystem::getFileDirectory(fileName);

    std::vector<std::string> filenames;
    Deserializer d(fileName);
    d.deserialize("volumes", filenames , "volume");
    for (auto filename : filenames) {
        auto abs = filesystem::cleanupPath( dir + "/" + filename);
        volumes->push_back(reader_.readData(abs));
    }

    return volumes;
}

}  // namespace inviwo
<commit_msg>Base: Added missing include<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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 OWNER 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 <modules/base/io/ivfsequencevolumereader.h>
#include <modules/base/io/ivfvolumewriter.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/core/io/datareaderexception.h>

namespace inviwo {
IvfSequenceVolumeReader::IvfSequenceVolumeReader() {
    addExtension({"ivfs", "Sequence of Inviwo ivf volumes"});
}

std::shared_ptr<VolumeSequence> IvfSequenceVolumeReader::readData(const std::string &filePath) {
    std::string fileName = filePath;
    if (!filesystem::fileExists(fileName)) {
        std::string newPath = filesystem::addBasePath(fileName);

        if (filesystem::fileExists(newPath)) {
            fileName = newPath;
        } else {
            throw DataReaderException("Error could not find input file: " + fileName, IvwContext);
        }
    }

    auto volumes = std::make_shared<VolumeSequence>();

    auto dir = filesystem::getFileDirectory(fileName);

    std::vector<std::string> filenames;
    Deserializer d(fileName);
    d.deserialize("volumes", filenames , "volume");
    for (auto filename : filenames) {
        auto abs = filesystem::cleanupPath( dir + "/" + filename);
        volumes->push_back(reader_.readData(abs));
    }

    return volumes;
}

}  // namespace inviwo
<|endoftext|>


<commit_before>// Copyright 2011 The Avalon Project Authors. All rights reserved.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the LICENSE file.
//
// Main loop for helmsman: open client sockets to wind and imu, server
// socket for helsman clients (e.g. the skipper and sysmon) and shovel
// data between all open file descriptors and the main controller.
//

#include <errno.h>
#include <math.h>
#include <signal.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>

#include "proto/rudder.h"
#include "proto/wind.h"
#include "proto/imu.h"
#include "proto/helmsman.h"
#include "proto/remote.h"
#include "proto/skipper_input.h"

#include "common/convert.h"
#include "common/unknown.h"
#include "sampling_period.h"
#include "ship_control.h"

extern int debug;

// -----------------------------------------------------------------------------
namespace {

// -----------------------------------------------------------------------------
//   Together with getopt in main, this is our minimalistic UI
// -----------------------------------------------------------------------------

//const char* version = "$Id: $";
const char* argv0;
int verbose = 0;

void crash(const char* fmt, ...) {
  va_list ap;
  char buf[1000];
  va_start(ap, fmt);
  vsnprintf(buf, sizeof(buf), fmt, ap);
  if (debug)
    fprintf(stderr, "%s:%s%s%s\n", argv0, buf,
      (errno) ? ": " : "",
      (errno) ? strerror(errno):"" );
  else
    syslog(LOG_CRIT, "%s%s%s\n", buf,
           (errno) ? ": " : "",
           (errno) ? strerror(errno):"" );
  exit(1);
  va_end(ap);
  return;
}

static void fault(int i) { crash("fault"); }

void usage(void) {
  fprintf(stderr,
    "usage: [plug /path/to/bus] %s [options]\n"
    "options:\n"
    "\t-d debug (don't go daemon, don't syslog)\n"
    , argv0);
  exit(2);
}

static void set_fd(fd_set* s, int* maxfd, FILE* f) {
        int fd = fileno(f);
        FD_SET(fd, s);
        if (*maxfd < fd) *maxfd = fd;
}

uint64_t now_ms() {
  timeval tv;
  if (gettimeofday(&tv, NULL) < 0) crash("gettimeofday");
  uint64_t ms1 = tv.tv_sec;  ms1 *= 1000;
  uint64_t ms2 = tv.tv_usec; ms2 /= 1000;
  return ms1 + ms2;
}

uint64_t now_micros() {
  timeval tv;
  if (gettimeofday(&tv, NULL) < 0) crash("gettimeofday");
  return tv.tv_sec * 1000000LL + tv.tv_usec;
}

uint64_t nanos_to_wait(uint64_t last_controller_call_micros) {
  uint64_t now = now_micros();
  const uint64_t period = 100000LL;
  uint64_t timeout = last_controller_call_micros + period > now ?
     last_controller_call_micros + period - now :
     0;
  return 1000 * timeout;
}

void HandleRemoteControl(RemoteProto remote, int* control_mode) {
  if (remote.command != *control_mode)
    fprintf(stderr, "Helmsman switched to control mode %d\n", remote.command);
  switch (remote.command) {
    case kNormalControlMode:
      *control_mode = remote.command;
      ShipControl::Normal();
      break;
    case kDockingControlMode:
      *control_mode = remote.command;
       ShipControl::Docking();
      break;
    case kBrakeControlMode:
    case kPowerShutdownMode:
      *control_mode = remote.command;
      ShipControl::Brake();
      break;
    case kOverrideSkipperMode:
      *control_mode = remote.command;
      ShipControl::Normal();
      break;
  default:
    fprintf(stderr, "Illegal remote control");
  }
}

} // namespace

// -----------------------------------------------------------------------------
//   Main.
// -----------------------------------------------------------------------------
int main(int argc, char* argv[]) {

  int ch;
  argv0 = strrchr(argv[0], '/');
  if (argv0) ++argv0; else argv0 = argv[0];

  while ((ch = getopt(argc, argv, "dhv")) != -1){
    switch (ch) {
    case 'd': ++debug; break;
    case 'v': ++verbose; break;
    case 'h':
    default:
      usage();
    }
  }

  argv += optind;
  argc -= optind;

  if (argc != 0) usage();

  setlinebuf(stdout);

  if (!debug) openlog(argv0, LOG_PERROR, LOG_LOCAL0);

  if (signal(SIGBUS, fault) == SIG_ERR)  crash("signal(SIGBUS)");
  if (signal(SIGSEGV, fault) == SIG_ERR)  crash("signal(SIGSEGV)");
  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) crash("signal");

  if (debug) {
    fprintf(stderr, "Helmsman started\n");
  } else {
    daemon(0,0);
    char* path_to_pidfile = NULL;
    asprintf(&path_to_pidfile, "/var/run/%s.pid", argv0);
    FILE* pidfile = fopen(path_to_pidfile, "w");
    if(!pidfile) crash("writing pidfile (%s)", path_to_pidfile);
    fprintf(pidfile, "%d\n", getpid());
    fclose(pidfile);
    free(path_to_pidfile);

    syslog(LOG_INFO, "Helmsman started");
  }

  ControllerInput ctrl_in;

  int nn = 0;

  struct WindProto wind  = INIT_WINDPROTO;
  struct RudderProto sts = INIT_RUDDERPROTO;
  struct IMUProto imu    = INIT_IMUPROTO;
  struct HelmsmanCtlProto ctl = INIT_HELMSMANCTLPROTO;
  struct RemoteProto remote = INIT_REMOTEPROTO;
  ctrl_in.alpha_star_rad = Deg2Rad(225);  // Going SouthWest is a good guess (and breaks up a deadlock)
  int control_mode = kNormalControlMode;
  int loops = 0;
  uint64_t last_run_micros = 0;

  while (!feof(stdin)) {

    if (ferror(stdin)) clearerr(stdin);

    struct timespec timeout = { 0, nanos_to_wait(last_run_micros) }; // Run ship cotroller exactly once every 100ms
    fd_set rfds;
    int max_fd = -1;
    FD_ZERO(&rfds);
    set_fd(&rfds, &max_fd, stdin);

    sigset_t empty_mask;
    sigemptyset(&empty_mask);
    int r = pselect(max_fd + 1, &rfds,  NULL, NULL, &timeout, &empty_mask);
    if (r == -1 && errno != EINTR) crash("pselect");

    if (debug>2) fprintf(stderr, "Woke up %d\n", r);

    if (FD_ISSET(fileno(stdin), &rfds)) {
      char line[1024];
      if (!fgets(line, sizeof line, stdin))
        crash("Error reading stdin");

      if (sscanf(line, IFMT_WINDPROTO(&wind, &nn)) > 0) {
        ctrl_in.wind.Reset();
        ctrl_in.wind.alpha_deg = SymmetricDeg(NormalizeDeg(wind.angle_deg));
        ctrl_in.wind.mag_kn = MeterPerSecondToKnots(wind.speed_m_s);

      } else if (sscanf(line, IFMT_IMUPROTO(&imu, &nn)) > 0) {
        ctrl_in.imu.Reset();
        ctrl_in.imu.temperature_c = imu.temp_c;

        ctrl_in.imu.acceleration.x_m_s2 = imu.acc_x_m_s2;
        ctrl_in.imu.acceleration.y_m_s2 = imu.acc_y_m_s2;
        ctrl_in.imu.acceleration.z_m_s2 = imu.acc_z_m_s2;

        ctrl_in.imu.gyro.omega_x_rad_s  = imu.gyr_x_rad_s;
        ctrl_in.imu.gyro.omega_y_rad_s  = imu.gyr_y_rad_s;
        ctrl_in.imu.gyro.omega_z_rad_s  = imu.gyr_z_rad_s;

        ctrl_in.imu.attitude.phi_x_rad = Deg2Rad(imu.roll_deg);
        ctrl_in.imu.attitude.phi_y_rad = Deg2Rad(imu.pitch_deg);
        ctrl_in.imu.attitude.phi_z_rad = SymmetricRad(NormalizeRad(Deg2Rad(imu.yaw_deg)));

        ctrl_in.imu.position.latitude_deg = imu.lat_deg;
        ctrl_in.imu.position.longitude_deg = imu.lng_deg;
        ctrl_in.imu.position.altitude_m = imu.alt_m;

        ctrl_in.imu.velocity.x_m_s = imu.vel_x_m_s;
        ctrl_in.imu.velocity.y_m_s = imu.vel_y_m_s;
        ctrl_in.imu.velocity.z_m_s = imu.vel_z_m_s;

        ctrl_in.imu.speed_m_s = sqrt(imu.vel_x_m_s * imu.vel_x_m_s +
                                     imu.vel_y_m_s * imu.vel_y_m_s);

      } else if (sscanf(line, IFMT_RUDDERPROTO_STS(&sts, &nn)) > 0) {
        ctrl_in.drives.gamma_rudder_left_rad  = Deg2Rad(sts.rudder_l_deg);
        ctrl_in.drives.gamma_rudder_right_rad = Deg2Rad(sts.rudder_r_deg);
        ctrl_in.drives.gamma_sail_rad         = Deg2Rad(sts.sail_deg);
        ctrl_in.drives.homed_rudder_left = !isnan(sts.rudder_l_deg);
        ctrl_in.drives.homed_rudder_right = !isnan(sts.rudder_r_deg);
        ctrl_in.drives.homed_sail = !isnan(sts.sail_deg);

      } else if (sscanf(line, IFMT_HELMSMANCTLPROTO(&ctl, &nn)) > 0) {
          if (control_mode != kOverrideSkipperMode &&
              !isnan(ctl.alpha_star_deg))
            ctrl_in.alpha_star_rad = Deg2Rad(ctl.alpha_star_deg);
      } else if (sscanf(line, IFMT_REMOTEPROTO(&remote, &nn)) > 0) {
        HandleRemoteControl(remote, &control_mode);
        if (control_mode == kOverrideSkipperMode)
          ctrl_in.alpha_star_rad = Deg2Rad(remote.alpha_star_deg);
      }
    }

    if (nanos_to_wait(last_run_micros) > 100)
      continue;
    ControllerOutput ctrl_out;
    last_run_micros = now_micros();
    ShipControl::Run(ctrl_in, &ctrl_out);
    struct RudderProto ctl = {
      now_ms(),
      Rad2Deg(ctrl_out.drives_reference.gamma_rudder_star_left_rad),
      Rad2Deg(ctrl_out.drives_reference.gamma_rudder_star_right_rad),
      Rad2Deg(ctrl_out.drives_reference.gamma_sail_star_rad) };
    printf(OFMT_RUDDERPROTO_CTL(ctl, &nn));

    if (loops == 0) {
      struct SkipperInputProto to_skipper = {
        now_ms(),
        ctrl_out.skipper_input.longitude_deg,
        ctrl_out.skipper_input.latitude_deg,
        ctrl_out.skipper_input.angle_true_deg,
        ctrl_out.skipper_input.mag_true_kn
      };
      printf(OFMT_SKIPPER_INPUTPROTO(to_skipper, &nn));
    }
      /*
      if (loops == 5) {
        struct HelmsmanStatus = {
          Rad2Deg(ctrl_in.alpha_star_rad)
        };
        printf(OFMT_HELMSMAN_STATUSPROTO);
      */
    loops = loops == 9 ? 0 : loops+1;

  }  // for ever

  crash("Main loop exit");

  return 0;
}

<commit_msg>component: Speed is x-component of the ships speed vector.<commit_after>// Copyright 2011 The Avalon Project Authors. All rights reserved.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the LICENSE file.
//
// Main loop for helmsman: open client sockets to wind and imu, server
// socket for helsman clients (e.g. the skipper and sysmon) and shovel
// data between all open file descriptors and the main controller.
//

#include <errno.h>
#include <math.h>
#include <signal.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>

#include "proto/rudder.h"
#include "proto/wind.h"
#include "proto/imu.h"
#include "proto/helmsman.h"
#include "proto/remote.h"
#include "proto/skipper_input.h"

#include "common/convert.h"
#include "common/unknown.h"
#include "sampling_period.h"
#include "ship_control.h"

extern int debug;

// -----------------------------------------------------------------------------
namespace {

// -----------------------------------------------------------------------------
//   Together with getopt in main, this is our minimalistic UI
// -----------------------------------------------------------------------------

//const char* version = "$Id: $";
const char* argv0;
int verbose = 0;

void crash(const char* fmt, ...) {
  va_list ap;
  char buf[1000];
  va_start(ap, fmt);
  vsnprintf(buf, sizeof(buf), fmt, ap);
  if (debug)
    fprintf(stderr, "%s:%s%s%s\n", argv0, buf,
      (errno) ? ": " : "",
      (errno) ? strerror(errno):"" );
  else
    syslog(LOG_CRIT, "%s%s%s\n", buf,
           (errno) ? ": " : "",
           (errno) ? strerror(errno):"" );
  exit(1);
  va_end(ap);
  return;
}

static void fault(int i) { crash("fault"); }

void usage(void) {
  fprintf(stderr,
    "usage: [plug /path/to/bus] %s [options]\n"
    "options:\n"
    "\t-d debug (don't go daemon, don't syslog)\n"
    , argv0);
  exit(2);
}

static void set_fd(fd_set* s, int* maxfd, FILE* f) {
        int fd = fileno(f);
        FD_SET(fd, s);
        if (*maxfd < fd) *maxfd = fd;
}

uint64_t now_ms() {
  timeval tv;
  if (gettimeofday(&tv, NULL) < 0) crash("gettimeofday");
  uint64_t ms1 = tv.tv_sec;  ms1 *= 1000;
  uint64_t ms2 = tv.tv_usec; ms2 /= 1000;
  return ms1 + ms2;
}

uint64_t now_micros() {
  timeval tv;
  if (gettimeofday(&tv, NULL) < 0) crash("gettimeofday");
  return tv.tv_sec * 1000000LL + tv.tv_usec;
}

uint64_t nanos_to_wait(uint64_t last_controller_call_micros) {
  uint64_t now = now_micros();
  const uint64_t period = 100000LL;
  uint64_t timeout = last_controller_call_micros + period > now ?
     last_controller_call_micros + period - now :
     0;
  return 1000 * timeout;
}

void HandleRemoteControl(RemoteProto remote, int* control_mode) {
  if (remote.command != *control_mode)
    fprintf(stderr, "Helmsman switched to control mode %d\n", remote.command);
  switch (remote.command) {
    case kNormalControlMode:
      *control_mode = remote.command;
      ShipControl::Normal();
      break;
    case kDockingControlMode:
      *control_mode = remote.command;
       ShipControl::Docking();
      break;
    case kBrakeControlMode:
    case kPowerShutdownMode:
      *control_mode = remote.command;
      ShipControl::Brake();
      break;
    case kOverrideSkipperMode:
      *control_mode = remote.command;
      ShipControl::Normal();
      break;
  default:
    fprintf(stderr, "Illegal remote control");
  }
}

} // namespace

// -----------------------------------------------------------------------------
//   Main.
// -----------------------------------------------------------------------------
int main(int argc, char* argv[]) {

  int ch;
  argv0 = strrchr(argv[0], '/');
  if (argv0) ++argv0; else argv0 = argv[0];

  while ((ch = getopt(argc, argv, "dhv")) != -1){
    switch (ch) {
    case 'd': ++debug; break;
    case 'v': ++verbose; break;
    case 'h':
    default:
      usage();
    }
  }

  argv += optind;
  argc -= optind;

  if (argc != 0) usage();

  setlinebuf(stdout);

  if (!debug) openlog(argv0, LOG_PERROR, LOG_LOCAL0);

  if (signal(SIGBUS, fault) == SIG_ERR)  crash("signal(SIGBUS)");
  if (signal(SIGSEGV, fault) == SIG_ERR)  crash("signal(SIGSEGV)");
  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) crash("signal");

  if (debug) {
    fprintf(stderr, "Helmsman started\n");
  } else {
    daemon(0,0);
    char* path_to_pidfile = NULL;
    asprintf(&path_to_pidfile, "/var/run/%s.pid", argv0);
    FILE* pidfile = fopen(path_to_pidfile, "w");
    if(!pidfile) crash("writing pidfile (%s)", path_to_pidfile);
    fprintf(pidfile, "%d\n", getpid());
    fclose(pidfile);
    free(path_to_pidfile);

    syslog(LOG_INFO, "Helmsman started");
  }

  ControllerInput ctrl_in;

  int nn = 0;

  struct WindProto wind  = INIT_WINDPROTO;
  struct RudderProto sts = INIT_RUDDERPROTO;
  struct IMUProto imu    = INIT_IMUPROTO;
  struct HelmsmanCtlProto ctl = INIT_HELMSMANCTLPROTO;
  struct RemoteProto remote = INIT_REMOTEPROTO;
  ctrl_in.alpha_star_rad = Deg2Rad(225);  // Going SouthWest is a good guess (and breaks up a deadlock)
  int control_mode = kNormalControlMode;
  int loops = 0;
  uint64_t last_run_micros = 0;

  while (!feof(stdin)) {

    if (ferror(stdin)) clearerr(stdin);

    struct timespec timeout = { 0, nanos_to_wait(last_run_micros) }; // Run ship cotroller exactly once every 100ms
    fd_set rfds;
    int max_fd = -1;
    FD_ZERO(&rfds);
    set_fd(&rfds, &max_fd, stdin);

    sigset_t empty_mask;
    sigemptyset(&empty_mask);
    int r = pselect(max_fd + 1, &rfds,  NULL, NULL, &timeout, &empty_mask);
    if (r == -1 && errno != EINTR) crash("pselect");

    if (debug>2) fprintf(stderr, "Woke up %d\n", r);

    if (FD_ISSET(fileno(stdin), &rfds)) {
      char line[1024];
      if (!fgets(line, sizeof line, stdin))
        crash("Error reading stdin");

      if (sscanf(line, IFMT_WINDPROTO(&wind, &nn)) > 0) {
        ctrl_in.wind.Reset();
        ctrl_in.wind.alpha_deg = SymmetricDeg(NormalizeDeg(wind.angle_deg));
        ctrl_in.wind.mag_kn = MeterPerSecondToKnots(wind.speed_m_s);

      } else if (sscanf(line, IFMT_IMUPROTO(&imu, &nn)) > 0) {
        ctrl_in.imu.Reset();
        ctrl_in.imu.temperature_c = imu.temp_c;

        ctrl_in.imu.acceleration.x_m_s2 = imu.acc_x_m_s2;
        ctrl_in.imu.acceleration.y_m_s2 = imu.acc_y_m_s2;
        ctrl_in.imu.acceleration.z_m_s2 = imu.acc_z_m_s2;

        ctrl_in.imu.gyro.omega_x_rad_s  = imu.gyr_x_rad_s;
        ctrl_in.imu.gyro.omega_y_rad_s  = imu.gyr_y_rad_s;
        ctrl_in.imu.gyro.omega_z_rad_s  = imu.gyr_z_rad_s;

        ctrl_in.imu.attitude.phi_x_rad = Deg2Rad(imu.roll_deg);
        ctrl_in.imu.attitude.phi_y_rad = Deg2Rad(imu.pitch_deg);
        ctrl_in.imu.attitude.phi_z_rad = SymmetricRad(NormalizeRad(Deg2Rad(imu.yaw_deg)));

        ctrl_in.imu.position.latitude_deg = imu.lat_deg;
        ctrl_in.imu.position.longitude_deg = imu.lng_deg;
        ctrl_in.imu.position.altitude_m = imu.alt_m;

        ctrl_in.imu.velocity.x_m_s = imu.vel_x_m_s;
        ctrl_in.imu.velocity.y_m_s = imu.vel_y_m_s;
        ctrl_in.imu.velocity.z_m_s = imu.vel_z_m_s;

        ctrl_in.imu.speed_m_s = imu.vel_x_m_s;

      } else if (sscanf(line, IFMT_RUDDERPROTO_STS(&sts, &nn)) > 0) {
        ctrl_in.drives.gamma_rudder_left_rad  = Deg2Rad(sts.rudder_l_deg);
        ctrl_in.drives.gamma_rudder_right_rad = Deg2Rad(sts.rudder_r_deg);
        ctrl_in.drives.gamma_sail_rad         = Deg2Rad(sts.sail_deg);
        ctrl_in.drives.homed_rudder_left = !isnan(sts.rudder_l_deg);
        ctrl_in.drives.homed_rudder_right = !isnan(sts.rudder_r_deg);
        ctrl_in.drives.homed_sail = !isnan(sts.sail_deg);

      } else if (sscanf(line, IFMT_HELMSMANCTLPROTO(&ctl, &nn)) > 0) {
          if (control_mode != kOverrideSkipperMode &&
              !isnan(ctl.alpha_star_deg))
            ctrl_in.alpha_star_rad = Deg2Rad(ctl.alpha_star_deg);
      } else if (sscanf(line, IFMT_REMOTEPROTO(&remote, &nn)) > 0) {
        HandleRemoteControl(remote, &control_mode);
        if (control_mode == kOverrideSkipperMode)
          ctrl_in.alpha_star_rad = Deg2Rad(remote.alpha_star_deg);
      }
    }

    if (nanos_to_wait(last_run_micros) > 100)
      continue;
    ControllerOutput ctrl_out;
    last_run_micros = now_micros();
    ShipControl::Run(ctrl_in, &ctrl_out);
    struct RudderProto ctl = {
      now_ms(),
      Rad2Deg(ctrl_out.drives_reference.gamma_rudder_star_left_rad),
      Rad2Deg(ctrl_out.drives_reference.gamma_rudder_star_right_rad),
      Rad2Deg(ctrl_out.drives_reference.gamma_sail_star_rad) };
    printf(OFMT_RUDDERPROTO_CTL(ctl, &nn));

    if (loops == 0) {
      struct SkipperInputProto to_skipper = {
        now_ms(),
        ctrl_out.skipper_input.longitude_deg,
        ctrl_out.skipper_input.latitude_deg,
        ctrl_out.skipper_input.angle_true_deg,
        ctrl_out.skipper_input.mag_true_kn
      };
      printf(OFMT_SKIPPER_INPUTPROTO(to_skipper, &nn));
    }
      /*
      if (loops == 5) {
        struct HelmsmanStatus = {
          Rad2Deg(ctrl_in.alpha_star_rad)
        };
        printf(OFMT_HELMSMAN_STATUSPROTO);
      */
    loops = loops == 9 ? 0 : loops+1;

  }  // for ever

  crash("Main loop exit");

  return 0;
}

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "hex_map.h"

#include <array>

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "asdf_multiplat/data/gl_resources.h"
#include "asdf_multiplat/data/content_manager.h"

using namespace std;
using namespace glm;

namespace asdf
{
    using namespace util;
    using namespace data;

namespace hexmap
{
namespace ui
{
    //const glm::vec4 grid_color(0.0f, 0.0f, 0.0f, 1.0f);
    const glm::vec4 grid_color(1.0f, 1.0f, 1.0f, 1.0f);
    constexpr float grid_overlay_thickness = 2.0f;

    constexpr char terrain_types_json_filename[] = "terrain_types.json";

    constexpr int apply_hexagon_textures = 1;

    gl_vertex_spec_<vertex_attrib::position3_t/*, vertex_attrib::color_t*/> hexagon_vertex_t::vertex_spec;

    hex_map_t::hex_map_t(data::hex_map_t& _map_data)
    : map_data(_map_data)
    {
        shader = Content.create_shader("hexmap", 330);
        spritebatch.spritebatch_shader = Content.shaders["spritebatch"];

        std::vector<hexagon_vertex_t> verts(6);

        for(size_t i = 0; i < 6; ++i)
        {
            verts[i].position.x = hexagon_points[i*3 + 0];
            verts[i].position.y = hexagon_points[i*3 + 1];
            verts[i].position.z = hexagon_points[i*3 + 2];

            //verts[i].color = grid_color;
        }

        hexagon.initialize(shader);
        hexagon.set_data(verts);
        hexagon.draw_mode = GL_LINE_LOOP;

        ASSERT(!CheckGLError(), "");
        GL_State->bind(hexagons_vao);

            GL_State->bind(hexagon.vbo);
            hexagon_vertex_t::vertex_spec.set_vertex_attribs(shader);
            ASSERT(!CheckGLError(), "Error setting vertex attributes");

            GL_State->bind(hex_gl_data);
            GLint attrib_loc = glGetAttribLocation(shader->shader_program_id, "TileID");
            glEnableVertexAttribArray(attrib_loc); //tell the location
            glVertexAttribIPointer(attrib_loc, 1, GL_UNSIGNED_INT, sizeof(data::hex_tile_id_t), 0);  // must use Atrib ** I ** for unsigned int to be used as a uint in glsl
            glVertexAttribDivisor(attrib_loc, 1); //second arg is 1, which means the vertex buffer for hexagon tile ID is incremented every instance, instead of every vertex

        GL_State->unbind_vao();

        ASSERT(!CheckGLError(), "");

        std::array<glm::vec4, num_tile_colors> colors =
        {
              COLOR_RED
            , COLOR_GREEN
            , COLOR_BLUE
            , COLOR_CYAN
            , COLOR_YELLOW
            , COLOR_MAGENTA
            , COLOR_TEAL
            , COLOR_ORANGE
            , COLOR_LIGHTGREY
            , COLOR_GREY
        };

        set_tile_colors(colors);
        ASSERT(!CheckGLError(), "");

        auto dir = find_folder("data");
        ASSERT(dir.length() > 0, "Could not find data folder");

        auto terrain_types_json_filepath = dir + "/" + string(terrain_types_json_filename);
        terrain_bank.load_from_file(terrain_types_json_filepath);

        objects_atlas = make_unique<texture_atlas_t>(string(dir + "/../assets/Objects/objects_atlas_data.json"));

        spline_renderer.init(Content.create_shader("spline", "spline", 330));
        spline_renderer.spline_list = &map_data.splines;
    }

    void hex_map_t::set_tile_colors(std::array<glm::vec4, num_tile_colors> const& colors)
    {
        GL_State->bind(shader);
        glUniform4fv(shader->uniform("TileColors[0]"), num_tile_colors, reinterpret_cast<const GLfloat*>(colors.data()));
        ASSERT(!CheckGLError(), "");
    }

    void hex_map_t::update(float dt)
    {
        camera_controller.update(dt);
        camera.position = camera_controller.position;
    }

    void hex_map_t::render()
    {
        ASSERT(map_data.hex_grid.chunks.size(), "");
        ASSERT(map_data.hex_grid.chunks[0].size(), "");

        shader->world_matrix = glm::mat4();
        shader->view_matrix       = camera.view_matrix();
        shader->projection_matrix = camera.projection_ortho();

        GL_State->bind(shader);
        glUniform1i(shader->uniform("ApplyTexture"), apply_hexagon_textures);

        map_data.hex_grid.for_each_chunk( [this](data::hex_grid_chunk_t& chunk) -> void
        {
            render_chunk(chunk);
        });

        glUniform1i(shader->uniform("ApplyTexture"), 0);  //turn of textures for the grid
        render_grid_overlay(map_data.hex_grid.size);

        render_map_objects();

        render_splines();

        //TEST
        // re-importing every frame so I can capture it with nvidia's gfx debugger
        // GL_State->bind(texture_bank.atlas_fbo);
        // glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // auto dir = find_folder("data");
        // auto imported_textures_json_filepath = dir + "/" + string(imported_textures_json_filename);
        // texture_bank.saved_textures.clear(); //reset so I'm not infinitely piling stuff on
        // texture_bank.load_from_list_file(imported_textures_json_filepath);
        // glBindTexture(GL_TEXTURE_2D, texture_bank.atlas_texture.texture_id);
        //---
    }

    void hex_map_t::on_event(SDL_Event* event)
    {
        camera_controller.on_event(event);
        camera.position = camera_controller.position;
    }

    void hex_map_t::render_chunk(data::hex_grid_chunk_t const& chunk)
    {
        GL_State->bind(hexagons_vao);

        hex_gl_data.set_data(chunk);

        float chunk_width_cells = hex_width_d4 * 3 * chunk.allocated_size.x;
        float chunk_height_cells = hex_height * chunk.allocated_size.y;

        shader->world_matrix[3][0] = chunk.position.x * chunk_width_cells;
        shader->world_matrix[3][1] = chunk.position.y * chunk_height_cells;
        shader->update_wvp_uniform();

        glUniform4f(shader->uniform("Color"), 1.0f, 1.0f, 1.0f, 1.0f);

        glBindTexture(GL_TEXTURE_2D, terrain_bank.atlas_texture.texture_id);

        render_hexagons(chunk.size, GL_TRIANGLE_FAN);
        GL_State->unbind_vao();
    }

    void hex_map_t::render_grid_overlay(glm::uvec2 grid_size)
    {
        GL_State->bind(shader);
        GL_State->bind(hexagon.vao);

        glLineWidth(grid_overlay_thickness);

        shader->world_matrix[3][0] = 0.0f;
        shader->world_matrix[3][1] = 0.0f;
        shader->update_wvp_uniform();

        glUniform4fv( shader->uniform("Color"), 1, glm::value_ptr(grid_color) );

        render_hexagons(grid_size, hexagon.draw_mode);
        GL_State->unbind_vao();
    }

    void hex_map_t::render_hexagons(glm::uvec2 grid_size, GLuint draw_mode)
    {
        auto loc = shader->uniform("CHUNK_HEIGHT");
        glUniform1i(loc, grid_size.y);

        size_t n = grid_size.x * grid_size.y;
        glDrawArraysInstanced(draw_mode, 0, 6, n); //start at 0th, draw 6 points per shape, draw (width/2)
    }

    void hex_map_t::render_map_objects()
    {
        spritebatch.begin(shader->view_matrix, shader->projection_matrix);

        for(auto& obj : map_data.objects)
        {
            ASSERT(obj.id < objects_atlas->atlas_entries.size(), "object ID does not exist in atlas");
            auto const& atlas_entry = objects_atlas->atlas_entries[obj.id];

            rect_t src_rect(atlas_entry.top_left_px.x, atlas_entry.top_left_px.y, atlas_entry.size_px.x, atlas_entry.size_px.y);
            auto sprite_scale = obj.scale * glm::vec2(units_per_px);

            spritebatch.draw(objects_atlas->atlas_texture, obj.position, src_rect, obj.color, sprite_scale, obj.rotation);
        }

        spritebatch.end();
    }

    void hex_map_t::render_splines()
    {
        ASSERT(spline_renderer.shader, "spline shader required to render splines");

        auto& sr_s = spline_renderer.shader;
        sr_s->view_matrix       = shader->view_matrix;
        sr_s->projection_matrix = shader->projection_matrix;

        spline_renderer.rebuild_if_dirty();
        spline_renderer.render();
    }

    void hex_buffer_data_t::set_data(data::hex_grid_chunk_t const& chunk)
    {
        //std::array<data::hex_tile_id_t, data::max_chunk_width * data::max_chunk_height> cell_data;
        std::vector<data::hex_tile_id_t> cell_data(chunk.size.x * chunk.size.y);

        for(size_t x = 0; x < chunk.size.x; ++x)
        {
            for(size_t y = 0; y < chunk.size.y; ++y)
            {
                //cell_data[x*chunk.size.y + y] = rand() % 10;
                //cell_data[x*chunk.size.y + y] = chunk.position.x + abs(chunk.position.y);  //set id to chunk pos for debugging chunks

                cell_data[x*chunk.size.y + y] = chunk.cells[x][y].tile_id;
            }
        }

        GL_State->bind(*this);
        GL_State->buffer_data(*this, (cell_data.size() * sizeof(data::hex_tile_id_t)), reinterpret_cast<GLvoid*>(cell_data.data()) );

        ASSERT(!CheckGLError(), "Error setting hexagon buffer data");
    }
}
}
}<commit_msg>WIP opengl 3.0 compatability<commit_after>#include "stdafx.h"
#include "hex_map.h"

#include <array>

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "asdf_multiplat/data/gl_resources.h"
#include "asdf_multiplat/data/content_manager.h"

using namespace std;
using namespace glm;

namespace asdf
{
    using namespace util;
    using namespace data;

namespace hexmap
{
namespace ui
{
    //const glm::vec4 grid_color(0.0f, 0.0f, 0.0f, 1.0f);
    const glm::vec4 grid_color(1.0f, 1.0f, 1.0f, 1.0f);
    constexpr float grid_overlay_thickness = 2.0f;

    constexpr char terrain_types_json_filename[] = "terrain_types.json";

    constexpr int apply_hexagon_textures = 1;

    gl_vertex_spec_<vertex_attrib::position3_t/*, vertex_attrib::color_t*/> hexagon_vertex_t::vertex_spec;

    hex_map_t::hex_map_t(data::hex_map_t& _map_data)
    : map_data(_map_data)
    {
        /// FIXME opengl shader compatability
        //shader = Content.create_shader("hexmap", 330);
        shader = Content.create_shader("hexmap", 130);
        spritebatch.spritebatch_shader = Content.shaders["spritebatch"];

        std::vector<hexagon_vertex_t> verts(6);

        for(size_t i = 0; i < 6; ++i)
        {
            verts[i].position.x = hexagon_points[i*3 + 0];
            verts[i].position.y = hexagon_points[i*3 + 1];
            verts[i].position.z = hexagon_points[i*3 + 2];

            //verts[i].color = grid_color;
        }

        hexagon.initialize(shader);
        hexagon.set_data(verts);
        hexagon.draw_mode = GL_LINE_LOOP;

        ASSERT(!CheckGLError(), "");
        GL_State->bind(hexagons_vao);

            GL_State->bind(hexagon.vbo);
            hexagon_vertex_t::vertex_spec.set_vertex_attribs(shader);
            ASSERT(!CheckGLError(), "Error setting vertex attributes");

            GL_State->bind(hex_gl_data);
            GLint attrib_loc = glGetAttribLocation(shader->shader_program_id, "TileID");
            glEnableVertexAttribArray(attrib_loc); //tell the location

            //FIXME OpenGL Compatability
            glVertexAttribIPointer(attrib_loc, 1, GL_UNSIGNED_INT, sizeof(data::hex_tile_id_t), 0);  // must use Atrib ** I ** for unsigned int to be used as a uint in glsl
            //glVertexAttribDivisor(attrib_loc, 1); //second arg is 1, which means the vertex buffer for hexagon tile ID is incremented every instance, instead of every vertex
            glVertexAttribDivisorARB(attrib_loc, 1);

        GL_State->unbind_vao();

        ASSERT(!CheckGLError(), "");

        std::array<glm::vec4, num_tile_colors> colors =
        {
              COLOR_RED
            , COLOR_GREEN
            , COLOR_BLUE
            , COLOR_CYAN
            , COLOR_YELLOW
            , COLOR_MAGENTA
            , COLOR_TEAL
            , COLOR_ORANGE
            , COLOR_LIGHTGREY
            , COLOR_GREY
        };

        set_tile_colors(colors);
        ASSERT(!CheckGLError(), "");

        auto dir = find_folder("data");
        ASSERT(dir.length() > 0, "Could not find data folder");

        auto terrain_types_json_filepath = dir + "/" + string(terrain_types_json_filename);
        terrain_bank.load_from_file(terrain_types_json_filepath);

        objects_atlas = make_unique<texture_atlas_t>(string(dir + "/../assets/Objects/objects_atlas_data.json"));

        /// FIXME OpenGL Compatability
        //spline_renderer.init(Content.create_shader("spline", "spline", 330));
        spline_renderer.init(Content.create_shader("spline", "spline", 130));
        spline_renderer.spline_list = &map_data.splines;
    }

    void hex_map_t::set_tile_colors(std::array<glm::vec4, num_tile_colors> const& colors)
    {
        GL_State->bind(shader);
        glUniform4fv(shader->uniform("TileColors[0]"), num_tile_colors, reinterpret_cast<const GLfloat*>(colors.data()));
        ASSERT(!CheckGLError(), "");
    }

    void hex_map_t::update(float dt)
    {
        camera_controller.update(dt);
        camera.position = camera_controller.position;
    }

    void hex_map_t::render()
    {
        ASSERT(map_data.hex_grid.chunks.size(), "");
        ASSERT(map_data.hex_grid.chunks[0].size(), "");

        shader->world_matrix = glm::mat4();
        shader->view_matrix       = camera.view_matrix();
        shader->projection_matrix = camera.projection_ortho();

        GL_State->bind(shader);
        glUniform1i(shader->uniform("ApplyTexture"), apply_hexagon_textures);

        map_data.hex_grid.for_each_chunk( [this](data::hex_grid_chunk_t& chunk) -> void
        {
            render_chunk(chunk);
        });

        glUniform1i(shader->uniform("ApplyTexture"), 0);  //turn of textures for the grid
        render_grid_overlay(map_data.hex_grid.size);

        render_map_objects();

        render_splines();

        //TEST
        // re-importing every frame so I can capture it with nvidia's gfx debugger
        // GL_State->bind(texture_bank.atlas_fbo);
        // glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // auto dir = find_folder("data");
        // auto imported_textures_json_filepath = dir + "/" + string(imported_textures_json_filename);
        // texture_bank.saved_textures.clear(); //reset so I'm not infinitely piling stuff on
        // texture_bank.load_from_list_file(imported_textures_json_filepath);
        // glBindTexture(GL_TEXTURE_2D, texture_bank.atlas_texture.texture_id);
        //---
    }

    void hex_map_t::on_event(SDL_Event* event)
    {
        camera_controller.on_event(event);
        camera.position = camera_controller.position;
    }

    void hex_map_t::render_chunk(data::hex_grid_chunk_t const& chunk)
    {
        GL_State->bind(hexagons_vao);

        hex_gl_data.set_data(chunk);

        float chunk_width_cells = hex_width_d4 * 3 * chunk.allocated_size.x;
        float chunk_height_cells = hex_height * chunk.allocated_size.y;

        shader->world_matrix[3][0] = chunk.position.x * chunk_width_cells;
        shader->world_matrix[3][1] = chunk.position.y * chunk_height_cells;
        shader->update_wvp_uniform();

        glUniform4f(shader->uniform("Color"), 1.0f, 1.0f, 1.0f, 1.0f);

        glBindTexture(GL_TEXTURE_2D, terrain_bank.atlas_texture.texture_id);

        render_hexagons(chunk.size, GL_TRIANGLE_FAN);
        GL_State->unbind_vao();
    }

    void hex_map_t::render_grid_overlay(glm::uvec2 grid_size)
    {
        GL_State->bind(shader);
        GL_State->bind(hexagon.vao);

        glLineWidth(grid_overlay_thickness);

        shader->world_matrix[3][0] = 0.0f;
        shader->world_matrix[3][1] = 0.0f;
        shader->update_wvp_uniform();

        glUniform4fv( shader->uniform("Color"), 1, glm::value_ptr(grid_color) );

        render_hexagons(grid_size, hexagon.draw_mode);
        GL_State->unbind_vao();
    }

    void hex_map_t::render_hexagons(glm::uvec2 grid_size, GLuint draw_mode)
    {
        auto loc = shader->uniform("CHUNK_HEIGHT");
        glUniform1i(loc, grid_size.y);

        size_t n = grid_size.x * grid_size.y;

        ///FIXME OpenGL Compatability
        if(GLEW_VERSION_3_1)
        {
            glDrawArraysInstanced(draw_mode, 0, 6, n); //start at 0th, draw 6 points per shape, draw (width/2)
        }
        else
        {
            glDrawArrays(draw_mode, 0, 6);
        }

    }

    void hex_map_t::render_map_objects()
    {
        spritebatch.begin(shader->view_matrix, shader->projection_matrix);

        for(auto& obj : map_data.objects)
        {
            ASSERT(obj.id < objects_atlas->atlas_entries.size(), "object ID does not exist in atlas");
            auto const& atlas_entry = objects_atlas->atlas_entries[obj.id];

            rect_t src_rect(atlas_entry.top_left_px.x, atlas_entry.top_left_px.y, atlas_entry.size_px.x, atlas_entry.size_px.y);
            auto sprite_scale = obj.scale * glm::vec2(units_per_px);

            spritebatch.draw(objects_atlas->atlas_texture, obj.position, src_rect, obj.color, sprite_scale, obj.rotation);
        }

        spritebatch.end();
    }

    void hex_map_t::render_splines()
    {
        ASSERT(spline_renderer.shader, "spline shader required to render splines");

        auto& sr_s = spline_renderer.shader;
        sr_s->view_matrix       = shader->view_matrix;
        sr_s->projection_matrix = shader->projection_matrix;

        spline_renderer.rebuild_if_dirty();
        spline_renderer.render();
    }

    void hex_buffer_data_t::set_data(data::hex_grid_chunk_t const& chunk)
    {
        //std::array<data::hex_tile_id_t, data::max_chunk_width * data::max_chunk_height> cell_data;
        std::vector<data::hex_tile_id_t> cell_data(chunk.size.x * chunk.size.y);

        for(size_t x = 0; x < chunk.size.x; ++x)
        {
            for(size_t y = 0; y < chunk.size.y; ++y)
            {
                //cell_data[x*chunk.size.y + y] = rand() % 10;
                //cell_data[x*chunk.size.y + y] = chunk.position.x + abs(chunk.position.y);  //set id to chunk pos for debugging chunks

                cell_data[x*chunk.size.y + y] = chunk.cells[x][y].tile_id;
            }
        }

        GL_State->bind(*this);
        GL_State->buffer_data(*this, (cell_data.size() * sizeof(data::hex_tile_id_t)), reinterpret_cast<GLvoid*>(cell_data.data()) );

        ASSERT(!CheckGLError(), "Error setting hexagon buffer data");
    }
}
}
}<|endoftext|>


<commit_before>/*
 * Copyright (c) 2000 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form 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.
 *
 *    This program 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 General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: link_const.cc,v 1.11 2001/08/25 23:50:03 steve Exp $"
#endif

# include "config.h"

# include  "netlist.h"
# include  "netmisc.h"

/*
 * Scan the link for drivers. If there are only constant drivers, then
 * the nexus has a known constant value. If there is a supply net,
 * then the nexus again has a known constant value.
 */
bool link_drivers_constant(const Link&lnk)
{
      const Nexus*nex = lnk.nexus();
      bool flag = true;

      for (const Link*cur = nex->first_nlink()
		 ; cur  ;  cur = cur->next_nlink()) {
	    const NetNet*sig;

	    if (cur == &lnk)
		  continue;
	    if (cur->get_dir() == Link::INPUT)
		  continue;

	      /* If this is an input or inout port of a root module,
		 then the is probably not a constant value. I
		 certainly don't know what the value is, anyhow. This
		 can happen in cases like this:

		 module main(sig);
		     input sig;
		 endmodule

		 If main is a root module (it has no parent) then sig
		 is not constant because it connects to an unspecified
		 outside world. */

	    if (sig = dynamic_cast<const NetNet*>(cur->get_obj())) do {
		  if (sig->port_type() == NetNet::NOT_A_PORT)
			break;

		  if (sig->port_type() == NetNet::POUTPUT)
			break;

		  if (sig->scope()->parent())
			break;

		  flag = false;
	    } while(0);

	      /* If the link is PASSIVE then it doesn't count as a
		 driver if its initial value is Vz. PASSIVE nodes
		 include wires and tri nets. */
	    if (cur->get_dir() == Link::PASSIVE)
		  continue;

	    if (! dynamic_cast<const NetConst*>(cur->get_obj()))
		  flag = false;

	      /* If there is a supply net, then this nexus will have a
		 constant value independent of any drivers. */
	    if (const NetNet*sig = dynamic_cast<const NetNet*>(cur->get_obj()))
		  switch (sig->type()) {
		      case NetNet::SUPPLY0:
		      case NetNet::SUPPLY1:
			return true;
		      default:
			break;
		  }
      }

      return flag;
}

verinum::V driven_value(const Link&lnk)
{
      verinum::V val = lnk.get_init();

      const Nexus*nex = lnk.nexus();
      for (const Link*cur = nex->first_nlink()
		 ; cur  ;  cur = cur->next_nlink()) {

	    const NetConst*obj;
	    const NetNet*sig;
	    if (obj = dynamic_cast<const NetConst*>(cur->get_obj())) {
		  val = obj->value(cur->get_pin());

	    } else if (sig = dynamic_cast<const NetNet*>(cur->get_obj())) {

		  if (sig->type() == NetNet::SUPPLY0)
			return verinum::V0;

		  if (sig->type() == NetNet::SUPPLY1)
			return verinum::V1;
	    }
      }

      return val;
}

/*
 * $Log: link_const.cc,v $
 * Revision 1.11  2001/08/25 23:50:03  steve
 *  Change the NetAssign_ class to refer to the signal
 *  instead of link into the netlist. This is faster
 *  and uses less space. Make the NetAssignNB carry
 *  the delays instead of the NetAssign_ lval objects.
 *
 *  Change the vvp code generator to support multiple
 *  l-values, i.e. concatenations of part selects.
 *
 * Revision 1.10  2001/07/25 03:10:49  steve
 *  Create a config.h.in file to hold all the config
 *  junk, and support gcc 3.0. (Stephan Boettcher)
 *
 * Revision 1.9  2001/07/07 03:01:37  steve
 *  Detect and make available to t-dll the right shift.
 *
 * Revision 1.8  2001/02/16 03:27:07  steve
 *  links to root inputs are not constant.
 *
 * Revision 1.7  2000/11/20 01:41:12  steve
 *  Whoops, return the calculated constant value rom driven_value.
 *
 * Revision 1.6  2000/11/20 00:58:40  steve
 *  Add support for supply nets (PR#17)
 *
 * Revision 1.5  2000/07/14 06:12:57  steve
 *  Move inital value handling from NetNet to Nexus
 *  objects. This allows better propogation of inital
 *  values.
 *
 *  Clean up constant propagation  a bit to account
 *  for regs that are not really values.
 *
 * Revision 1.4  2000/06/25 19:59:42  steve
 *  Redesign Links to include the Nexus class that
 *  carries properties of the connected set of links.
 *
 * Revision 1.3  2000/05/14 17:55:04  steve
 *  Support initialization of FF Q value.
 *
 * Revision 1.2  2000/05/07 04:37:56  steve
 *  Carry strength values from Verilog source to the
 *  pform and netlist for gates.
 *
 *  Change vvm constants to use the driver_t to drive
 *  a constant value. This works better if there are
 *  multiple drivers on a signal.
 *
 * Revision 1.1  2000/04/20 00:28:03  steve
 *  Catch some simple identity compareoptimizations.
 *
 */

<commit_msg> Shuffle link_drivers_constant for speed.<commit_after>/*
 * Copyright (c) 2000 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form 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.
 *
 *    This program 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 General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: link_const.cc,v 1.12 2002/06/19 04:18:46 steve Exp $"
#endif

# include "config.h"

# include  "netlist.h"
# include  "netmisc.h"

/*
 * Scan the link for drivers. If there are only constant drivers, then
 * the nexus has a known constant value. If there is a supply net,
 * then the nexus again has a known constant value.
 */
bool link_drivers_constant(const Link&lnk)
{
      const Nexus*nex = lnk.nexus();

      for (const Link*cur = nex->first_nlink()
		 ; cur  ;  cur = cur->next_nlink()) {
	    const NetNet*sig;
	    Link::DIR cur_dir;

	    if (cur == &lnk)
		  continue;

	    cur_dir = cur->get_dir();
	    if (cur_dir == Link::INPUT)
		  continue;

	      /* If this is an input or inout port of a root module,
		 then the is probably not a constant value. I
		 certainly don't know what the value is, anyhow. This
		 can happen in cases like this:

		 module main(sig);
		     input sig;
		 endmodule

		 If main is a root module (it has no parent) then sig
		 is not constant because it connects to an unspecified
		 outside world. */

	    if (cur_dir == Link::PASSIVE) {

		  const NetObj*obj = cur->get_obj();
		  if (obj->scope()->parent() != 0)
			continue;

		  sig = dynamic_cast<const NetNet*>(cur->get_obj());
		  assert(sig);

		  if (sig->port_type() == NetNet::NOT_A_PORT)
			continue;

		  if (sig->port_type() == NetNet::POUTPUT)
			continue;

		  return false;

	    }

	    if (! dynamic_cast<const NetConst*>(cur->get_obj()))
		  return false;

	      /* If there is a supply net, then this nexus will have a
		 constant value independent of any drivers. */
	    if (const NetNet*sig = dynamic_cast<const NetNet*>(cur->get_obj()))
		  switch (sig->type()) {
		      case NetNet::SUPPLY0:
		      case NetNet::SUPPLY1:
			return true;
		      default:
			break;
		  }
      }

      return true;
}

verinum::V driven_value(const Link&lnk)
{
      verinum::V val = lnk.get_init();

      const Nexus*nex = lnk.nexus();
      for (const Link*cur = nex->first_nlink()
		 ; cur  ;  cur = cur->next_nlink()) {

	    const NetConst*obj;
	    const NetNet*sig;
	    if (obj = dynamic_cast<const NetConst*>(cur->get_obj())) {
		  val = obj->value(cur->get_pin());

	    } else if (sig = dynamic_cast<const NetNet*>(cur->get_obj())) {

		  if (sig->type() == NetNet::SUPPLY0)
			return verinum::V0;

		  if (sig->type() == NetNet::SUPPLY1)
			return verinum::V1;
	    }
      }

      return val;
}

/*
 * $Log: link_const.cc,v $
 * Revision 1.12  2002/06/19 04:18:46  steve
 *  Shuffle link_drivers_constant for speed.
 *
 * Revision 1.11  2001/08/25 23:50:03  steve
 *  Change the NetAssign_ class to refer to the signal
 *  instead of link into the netlist. This is faster
 *  and uses less space. Make the NetAssignNB carry
 *  the delays instead of the NetAssign_ lval objects.
 *
 *  Change the vvp code generator to support multiple
 *  l-values, i.e. concatenations of part selects.
 *
 * Revision 1.10  2001/07/25 03:10:49  steve
 *  Create a config.h.in file to hold all the config
 *  junk, and support gcc 3.0. (Stephan Boettcher)
 *
 * Revision 1.9  2001/07/07 03:01:37  steve
 *  Detect and make available to t-dll the right shift.
 *
 * Revision 1.8  2001/02/16 03:27:07  steve
 *  links to root inputs are not constant.
 *
 * Revision 1.7  2000/11/20 01:41:12  steve
 *  Whoops, return the calculated constant value rom driven_value.
 *
 * Revision 1.6  2000/11/20 00:58:40  steve
 *  Add support for supply nets (PR#17)
 *
 * Revision 1.5  2000/07/14 06:12:57  steve
 *  Move inital value handling from NetNet to Nexus
 *  objects. This allows better propogation of inital
 *  values.
 *
 *  Clean up constant propagation  a bit to account
 *  for regs that are not really values.
 *
 * Revision 1.4  2000/06/25 19:59:42  steve
 *  Redesign Links to include the Nexus class that
 *  carries properties of the connected set of links.
 *
 * Revision 1.3  2000/05/14 17:55:04  steve
 *  Support initialization of FF Q value.
 *
 * Revision 1.2  2000/05/07 04:37:56  steve
 *  Carry strength values from Verilog source to the
 *  pform and netlist for gates.
 *
 *  Change vvm constants to use the driver_t to drive
 *  a constant value. This works better if there are
 *  multiple drivers on a signal.
 *
 * Revision 1.1  2000/04/20 00:28:03  steve
 *  Catch some simple identity compareoptimizations.
 *
 */

<|endoftext|>