<commit_before>/**
 *       \file  calc_well_pressure.cpp
 *      \brief  Implementation of calc_well_pressure
 *     \author  Sergey Miryanov (sergey-miryanov), sergey.miryanov@gmail.com
 *       \date  26.09.2008
 *  \copyright  This source code is released under the terms of
 *              the BSD License. See LICENSE for more details.
 * */
#include "stdafx.h"
#include "calc_well_pressure.h"
#include "calc_model.h"
#include "calc_well.h"
#include "well_connection.h"
#include "calc_model_data_accessors.h"
#include "reservoir.h"
#include "facility_manager.h"

namespace blue_sky
  {

  /**
   * \brief  'default' ctor for calc_well_pressure
   * \param  param Additional params for ctor
   * */
  calc_well_pressure::calc_well_pressure (bs_type_ctor_param /*param = NULL */)
  {
  }

  /**
   * \brief  copy-ctor for calc_well_pressure
   * \param  rhs Instance of calc_well_pressure to be copied
   * */
  calc_well_pressure::calc_well_pressure (const calc_well_pressure &rhs)
  : bs_refcounter ()
  {
    *this = rhs;
  }

  bool
  calc_well_pressure::calculate (sp_well_t &well, const sp_calc_model_t &calc_model) const
    {
      BS_ASSERT (!well->is_shut ()) (well->name ());

      if (well->is_rate ())
        {
          return calculate_for_rate (well, calc_model);
        }
      else
        {
          return false;
        }
    }

  /**
   * \class calc_for_rate
   * \brief Calculates BHP for well if well controlled by rate
   * */
  template <typename calc_well_pressure_t>
  struct calc_for_rate
    {
      typedef typename calc_well_pressure_t::item_t       item_t;
      typedef typename calc_well_pressure_t::index_t      index_t;
      typedef typename calc_well_pressure_t::item_array_t item_array_t;
      typedef typename calc_well_pressure_t::calc_model_t calc_model_t;
      typedef typename calc_model_t::data_t               calc_model_data_t;
      typedef typename calc_model_t::sat_d_t              sat_d_t;
      typedef typename calc_model_t::phase_d_t            phase_d_t;

      typedef typename calc_well_pressure_t::sp_well_t    sp_well_t;

      /**
       * \brief  ctor for calc_for_rate, initializes references and flags
       * \param  well
       * \param  phase_d
       * \param  sat_d
       * \param  n_phases
       * \param  gas_oil_ratio
       * */
      calc_for_rate (const sp_well_t &well, const phase_d_t &phase_d, const sat_d_t &sat_d, index_t n_phases, const t_double *gas_oil_ratio)
          : is_prod (well->get_well_controller ()->is_production ())
          , phase_d (phase_d)
          , sat_d (sat_d)
          , n_phases (n_phases)
          , n_block (0)
          , gas_oil_ratio (gas_oil_ratio)
      {
        // TODO: BAD DESIGN
        if (is_prod)
          {
            using namespace wells;
            rate_control_type control_type = well->get_well_controller ()->get_control_type ();
            is_w = control_type == water_rate_control || control_type == liquid_rate_control;
            is_g = control_type == gas_rate_control;
            is_o = control_type == oil_rate_control || control_type == liquid_rate_control;
          }
        else
          {
            using namespace wells;
            injection_type injection = well->get_well_controller ()->injection ();

            is_w = injection == injection_water;
            is_g = injection == injection_gas;
            is_o = injection == injection_oil;
          }

        // TODO: HACK
        is_w = phase_d[FI_PHASE_WATER] != -1 && is_w;
        is_g = phase_d[FI_PHASE_GAS] != -1 && is_g;
        is_o = phase_d[FI_PHASE_OIL] != -1 && is_o;
      }

      /**
       * \brief      Calculates denom and numer for production well
       * \param[in]  data
       * \param[out] denom
       * \param[out] numer
       * */
      void
      calc_prod (const calc_model_data_t &data, item_t &denom, item_t &numer)
      {
        if (is_w)
          {
            const item_t &mw    = MOBILITY (data, phase_d, FI_PHASE_WATER);
            item_t pcwo         = n_phases == 1 ? 0 : CAP_PRESSURE (data, phase_d, FI_PHASE_WATER);
            item_t y            = gw * mw;
            item_t z            = y * (H  - po - pcwo);

            denom += y;
            numer += z;
          }
        if (is_g)
          {
            const item_t &mg    = MOBILITY (data, phase_d, FI_PHASE_GAS);
            item_t mo           = phase_d[FI_PHASE_OIL]   == -1 ? 0 : MOBILITY (data, phase_d, FI_PHASE_OIL);
            item_t gor          = phase_d[FI_PHASE_OIL]   == -1 ? 0 : gas_oil_ratio [n_block];
            item_t pcgo         = n_phases == 1 ? 0 : CAP_PRESSURE (data, phase_d, FI_PHASE_GAS);
            item_t Po           = (H - po);
            item_t Pg           = (Po - pcgo);
            item_t y            = gw * (mg + gor * mo);
            item_t z            = gw * (mg * Pg + gor * mo * Po);

            denom += y;
            numer += z;
          }
        if (is_o)
          {
            item_t mo   = MOBILITY (data, phase_d, FI_PHASE_OIL);
            item_t y    = gw * mo;
            item_t z    = y * (H - po);

            denom += y;
            numer += z;
          }
      }

      /**
       * \brief      Calculates denom and numer for injection well
       * \param[in]  data
       * \param[out] denom
       * \param[out] numer
       * */
      void
      calc_inj (const calc_model_data_t &data, item_t &denom, item_t &numer)
      {
        item_t mw   = 0;
        item_t mg   = 0;
        item_t mo   = 0;
        item_t pcwo = 0;
        item_t pcgo = 0;

        if (n_phases == 1)
          {
            mw = phase_d[FI_PHASE_WATER] == -1 ? 0 : INVERS_VISCOSITY (data, phase_d, FI_PHASE_WATER);
            mg = phase_d[FI_PHASE_GAS]   == -1 ? 0 : INVERS_VISCOSITY (data, phase_d, FI_PHASE_GAS);
            mo = phase_d[FI_PHASE_OIL]   == -1 ? 0 : INVERS_VISCOSITY (data, phase_d, FI_PHASE_OIL);
          }
        else
          {
            mw = phase_d[FI_PHASE_WATER] == -1 ? 0 : (RELATIVE_PERM (data, phase_d, FI_PHASE_WATER) * INVERS_VISCOSITY (data, phase_d, FI_PHASE_WATER));
            mg = phase_d[FI_PHASE_GAS]   == -1 ? 0 : (RELATIVE_PERM (data, phase_d, FI_PHASE_GAS)   * INVERS_VISCOSITY (data, phase_d, FI_PHASE_GAS));
            mo = phase_d[FI_PHASE_OIL]   == -1 ? 0 : (RELATIVE_PERM (data, phase_d, FI_PHASE_OIL)   * INVERS_VISCOSITY (data, phase_d, FI_PHASE_OIL));
            pcwo = phase_d[FI_PHASE_WATER] == -1 ? 0 : CAP_PRESSURE (data, phase_d, FI_PHASE_WATER);
            pcgo = phase_d[FI_PHASE_GAS]   == -1 ? 0 : CAP_PRESSURE (data, phase_d, FI_PHASE_GAS);
          }

        if (is_w)
          {
            item_t bw   = INVERS_FVF (data, phase_d, FI_PHASE_WATER);
            mw          = mw * bw;
            mg          = mg * bw;
            mo          = mo * bw;

            item_t y    = gw * (mw + mg + mo);
            item_t z    = y * (H - po - pcwo);

            denom += y;
            numer += z;
          }
        else if (is_g)
          {
            item_t bg   = INVERS_FVF (data, phase_d, FI_PHASE_GAS);
            mw          = mw * bg;
            mg          = mg * bg;
            mo          = mo * bg;

            item_t y    = gw * (mw + mg + mo);
            item_t z    = y * (H - po - pcgo);

            denom += y;
            numer += z;
          }
        else if (is_o)
          {
            item_t bo   = INVERS_FVF (data, phase_d, FI_PHASE_OIL);
            mw          = mw * bo;
            mg          = mg * bo;
            mo          = mo * bo;

            item_t y    = gw * (mw + mg + mo);
            item_t z    = y * (H - po);

            denom += y;
            numer += z;
          }
      }

public:

      bool is_prod;
      bool is_w, is_g, is_o;

      auto_value <item_t> gw;
      auto_value <item_t> po;
      auto_value <item_t> H;

      const phase_d_t &phase_d;
      const sat_d_t &sat_d;

      index_t n_phases;
      index_t n_block;

      const t_double *gas_oil_ratio;
    };

  bool
  calc_well_pressure::calculate_for_rate (sp_well_t &well, const sp_calc_model_t &calc_model) const
    {
      BS_ASSERT (!well->is_shut ()) (well->name ());

      typedef base_t::well_t::connection_t         connection_t;
      typedef base_t::well_t::sp_connection_t      sp_connection_t;

      typedef base_t::calc_model_t::sat_d_t        sat_d_t;
      typedef base_t::calc_model_t::phase_d_t      phase_d_t;

      typedef base_t::calc_model_t::data_t         calc_model_data_t;

      if (well->is_no_primary_connections ())
        {
          return false;
        }

      item_t gravity                = calc_model->internal_constants.gravity_constant;
      item_t numer                  = 0;
      item_t denom                  = 0;
      item_t prev_depth             = well->get_first_connection ()->connection_depth;

      calc_for_rate <this_t> calc (well, calc_model->phase_d, calc_model->sat_d, calc_model->n_phases, &(*calc_model->gas_oil_ratio)[0]);
      base_t::well_t::connection_iterator_t it = well->connections_begin (), e = well->connections_end ();
      for (; it != e; ++it)
        {
          const sp_connection_t &c (*it);
          if (c->is_shut ())
            {
              prev_depth                  = c->connection_depth;
              continue;
            }

          calc.n_block                    = c->n_block ();
          const calc_model_data_t &data   = calc_model->get_data (calc.n_block);
          main_var_type main_var          = calc_model->main_variable[calc.n_block];

          item_t rho                      = c->density;
          item_t diff_h                   = c->connection_depth - prev_depth;
          prev_depth                      = c->connection_depth;
          calc.gw                         = c->get_fact ();
          calc.po                         = (*calc_model->pressure)[calc.n_block];
          calc.H                          = rho * gravity * diff_h;

          BS_ASSERT (main_var != FI_NULL) (main_var);

          if (calc.is_prod)
            {
              calc.calc_prod (data, denom, numer);
            }
          else
            {
              calc.calc_inj (data, denom, numer);
            }
        }

      item_t q_rate = well->get_input_rate ();
      item_t bhp = (q_rate - numer) / denom;
      bool switched_to_bhp = false;

      BOSOUT (section::wells, level::low) << "[" << well->name () << "] calc_well_pressure: q_rate: " << q_rate << " numer: " << numer << " denom: " << denom << " bhp: " << bhp << bs_end;
      if ((fabs (denom) < 1e-10) || (bhp < 1.0 || bhp > 1000.0))
        {
          BOSOUT (section::wells, level::low) << "[" << well->name () << "] calc_well_pressure: switched to bhp" << bs_end;

          well->get_well_controller ()->switch_to_bhp (well);
          switched_to_bhp = true;
        }
      else
        {
          BOSOUT (section::wells, level::low) << "[" << well->name () << "] calc_well_pressure: none" << bs_end;

          well->set_bhp (bhp);
        }

      return switched_to_bhp;
    }

  BLUE_SKY_TYPE_STD_CREATE (calc_well_pressure);
  BLUE_SKY_TYPE_STD_COPY (calc_well_pressure);
  BLUE_SKY_TYPE_IMPL (calc_well_pressure, objbase, "calc_well_pressure", "calc_well_pressure", "calc_well_pressure");

  bool
  calc_well_pressure_register_types (const blue_sky::plugin_descriptor &pd)
  {
    bool res = true;

    res &= BS_KERNEL.register_type (pd, calc_well_pressure::bs_type ()); BS_ASSERT (res);

    return res;
  }

} // namespace blue_sky

<commit_msg>Fix access to gas_oil_ratio in calc_well_pressure on gas-less models<commit_after>/**
 *       \file  calc_well_pressure.cpp
 *      \brief  Implementation of calc_well_pressure
 *     \author  Sergey Miryanov (sergey-miryanov), sergey.miryanov@gmail.com
 *       \date  26.09.2008
 *  \copyright  This source code is released under the terms of
 *              the BSD License. See LICENSE for more details.
 * */
#include "stdafx.h"
#include "calc_well_pressure.h"
#include "calc_model.h"
#include "calc_well.h"
#include "well_connection.h"
#include "calc_model_data_accessors.h"
#include "reservoir.h"
#include "facility_manager.h"

namespace blue_sky
  {

  /**
   * \brief  'default' ctor for calc_well_pressure
   * \param  param Additional params for ctor
   * */
  calc_well_pressure::calc_well_pressure (bs_type_ctor_param /*param = NULL */)
  {
  }

  /**
   * \brief  copy-ctor for calc_well_pressure
   * \param  rhs Instance of calc_well_pressure to be copied
   * */
  calc_well_pressure::calc_well_pressure (const calc_well_pressure &rhs)
  : bs_refcounter ()
  {
    *this = rhs;
  }

  bool
  calc_well_pressure::calculate (sp_well_t &well, const sp_calc_model_t &calc_model) const
    {
      BS_ASSERT (!well->is_shut ()) (well->name ());

      if (well->is_rate ())
        {
          return calculate_for_rate (well, calc_model);
        }
      else
        {
          return false;
        }
    }

  /**
   * \class calc_for_rate
   * \brief Calculates BHP for well if well controlled by rate
   * */
  struct calc_for_rate
    {
      typedef calc_well_pressure::item_t       item_t;
      typedef calc_well_pressure::index_t      index_t;
      typedef calc_well_pressure::item_array_t item_array_t;
      typedef calc_model::data_t               calc_model_data_t;
      typedef calc_model::sat_d_t              sat_d_t;
      typedef calc_model::phase_d_t            phase_d_t;

      typedef calc_well_pressure::sp_well_t    sp_well_t;

      /**
       * \brief  ctor for calc_for_rate, initializes references and flags
       * \param  well
       * \param  phase_d
       * \param  sat_d
       * \param  n_phases
       * \param  gas_oil_ratio
       * */
      calc_for_rate (const sp_well_t &well, const phase_d_t &phase_d, const sat_d_t &sat_d, index_t n_phases, const t_double *gas_oil_ratio)
          : is_prod (well->get_well_controller ()->is_production ())
          , phase_d (phase_d)
          , sat_d (sat_d)
          , n_phases (n_phases)
          , n_block (0)
          , gas_oil_ratio (gas_oil_ratio)
      {
        // TODO: BAD DESIGN
        if (is_prod)
          {
            using namespace wells;
            rate_control_type control_type = well->get_well_controller ()->get_control_type ();
            is_w = control_type == water_rate_control || control_type == liquid_rate_control;
            is_g = control_type == gas_rate_control;
            is_o = control_type == oil_rate_control || control_type == liquid_rate_control;
          }
        else
          {
            using namespace wells;
            injection_type injection = well->get_well_controller ()->injection ();

            is_w = injection == injection_water;
            is_g = injection == injection_gas;
            is_o = injection == injection_oil;
          }

        // TODO: HACK
        is_w = phase_d[FI_PHASE_WATER] != -1 && is_w;
        is_g = phase_d[FI_PHASE_GAS] != -1 && is_g;
        is_o = phase_d[FI_PHASE_OIL] != -1 && is_o;
      }

      /**
       * \brief      Calculates denom and numer for production well
       * \param[in]  data
       * \param[out] denom
       * \param[out] numer
       * */
      void
      calc_prod (const calc_model_data_t &data, item_t &denom, item_t &numer)
      {
        if (is_w)
          {
            const item_t &mw    = MOBILITY (data, phase_d, FI_PHASE_WATER);
            item_t pcwo         = n_phases == 1 ? 0 : CAP_PRESSURE (data, phase_d, FI_PHASE_WATER);
            item_t y            = gw * mw;
            item_t z            = y * (H  - po - pcwo);

            denom += y;
            numer += z;
          }
        if (is_g)
          {
            const item_t &mg    = MOBILITY (data, phase_d, FI_PHASE_GAS);
            item_t mo           = phase_d[FI_PHASE_OIL]   == -1 ? 0 : MOBILITY (data, phase_d, FI_PHASE_OIL);
            item_t gor          = phase_d[FI_PHASE_OIL]   == -1 ? 0 : gas_oil_ratio [n_block];
            item_t pcgo         = n_phases == 1 ? 0 : CAP_PRESSURE (data, phase_d, FI_PHASE_GAS);
            item_t Po           = (H - po);
            item_t Pg           = (Po - pcgo);
            item_t y            = gw * (mg + gor * mo);
            item_t z            = gw * (mg * Pg + gor * mo * Po);

            denom += y;
            numer += z;
          }
        if (is_o)
          {
            item_t mo   = MOBILITY (data, phase_d, FI_PHASE_OIL);
            item_t y    = gw * mo;
            item_t z    = y * (H - po);

            denom += y;
            numer += z;
          }
      }

      /**
       * \brief      Calculates denom and numer for injection well
       * \param[in]  data
       * \param[out] denom
       * \param[out] numer
       * */
      void
      calc_inj (const calc_model_data_t &data, item_t &denom, item_t &numer)
      {
        item_t mw   = 0;
        item_t mg   = 0;
        item_t mo   = 0;
        item_t pcwo = 0;
        item_t pcgo = 0;

        if (n_phases == 1)
          {
            mw = phase_d[FI_PHASE_WATER] == -1 ? 0 : INVERS_VISCOSITY (data, phase_d, FI_PHASE_WATER);
            mg = phase_d[FI_PHASE_GAS]   == -1 ? 0 : INVERS_VISCOSITY (data, phase_d, FI_PHASE_GAS);
            mo = phase_d[FI_PHASE_OIL]   == -1 ? 0 : INVERS_VISCOSITY (data, phase_d, FI_PHASE_OIL);
          }
        else
          {
            mw = phase_d[FI_PHASE_WATER] == -1 ? 0 : (RELATIVE_PERM (data, phase_d, FI_PHASE_WATER) * INVERS_VISCOSITY (data, phase_d, FI_PHASE_WATER));
            mg = phase_d[FI_PHASE_GAS]   == -1 ? 0 : (RELATIVE_PERM (data, phase_d, FI_PHASE_GAS)   * INVERS_VISCOSITY (data, phase_d, FI_PHASE_GAS));
            mo = phase_d[FI_PHASE_OIL]   == -1 ? 0 : (RELATIVE_PERM (data, phase_d, FI_PHASE_OIL)   * INVERS_VISCOSITY (data, phase_d, FI_PHASE_OIL));
            pcwo = phase_d[FI_PHASE_WATER] == -1 ? 0 : CAP_PRESSURE (data, phase_d, FI_PHASE_WATER);
            pcgo = phase_d[FI_PHASE_GAS]   == -1 ? 0 : CAP_PRESSURE (data, phase_d, FI_PHASE_GAS);
          }

        if (is_w)
          {
            item_t bw   = INVERS_FVF (data, phase_d, FI_PHASE_WATER);
            mw          = mw * bw;
            mg          = mg * bw;
            mo          = mo * bw;

            item_t y    = gw * (mw + mg + mo);
            item_t z    = y * (H - po - pcwo);

            denom += y;
            numer += z;
          }
        else if (is_g)
          {
            item_t bg   = INVERS_FVF (data, phase_d, FI_PHASE_GAS);
            mw          = mw * bg;
            mg          = mg * bg;
            mo          = mo * bg;

            item_t y    = gw * (mw + mg + mo);
            item_t z    = y * (H - po - pcgo);

            denom += y;
            numer += z;
          }
        else if (is_o)
          {
            item_t bo   = INVERS_FVF (data, phase_d, FI_PHASE_OIL);
            mw          = mw * bo;
            mg          = mg * bo;
            mo          = mo * bo;

            item_t y    = gw * (mw + mg + mo);
            item_t z    = y * (H - po);

            denom += y;
            numer += z;
          }
      }

public:

      bool is_prod;
      bool is_w, is_g, is_o;

      auto_value <item_t> gw;
      auto_value <item_t> po;
      auto_value <item_t> H;

      const phase_d_t &phase_d;
      const sat_d_t &sat_d;

      index_t n_phases;
      index_t n_block;

      const t_double *gas_oil_ratio;
    };

  bool
  calc_well_pressure::calculate_for_rate (sp_well_t &well, const sp_calc_model_t &calc_model) const
    {
      BS_ASSERT (!well->is_shut ()) (well->name ());

      typedef base_t::well_t::connection_t         connection_t;
      typedef base_t::well_t::sp_connection_t      sp_connection_t;

      typedef base_t::calc_model_t::sat_d_t        sat_d_t;
      typedef base_t::calc_model_t::phase_d_t      phase_d_t;

      typedef base_t::calc_model_t::data_t         calc_model_data_t;

      if (well->is_no_primary_connections ())
        {
          return false;
        }

      item_t gravity                = calc_model->internal_constants.gravity_constant;
      item_t numer                  = 0;
      item_t denom                  = 0;
      item_t prev_depth             = well->get_first_connection ()->connection_depth;

      calc_for_rate calc (well,
                          calc_model->phase_d,
                          calc_model->sat_d,
                          calc_model->n_phases,
                          calc_model->is_gas () ? calc_model->gas_oil_ratio->data () : 0);

      well_t::connection_iterator_t it = well->connections_begin (), e = well->connections_end ();
      for (; it != e; ++it)
        {
          const sp_connection_t &c (*it);
          if (c->is_shut ())
            {
              prev_depth                  = c->connection_depth;
              continue;
            }

          calc.n_block                    = c->n_block ();
          const calc_model_data_t &data   = calc_model->get_data (calc.n_block);
          main_var_type main_var          = calc_model->main_variable[calc.n_block];

          item_t rho                      = c->density;
          item_t diff_h                   = c->connection_depth - prev_depth;
          prev_depth                      = c->connection_depth;
          calc.gw                         = c->get_fact ();
          calc.po                         = (*calc_model->pressure)[calc.n_block]; // FIXME: access to pressure
          calc.H                          = rho * gravity * diff_h;

          BS_ASSERT (main_var != FI_NULL) (main_var);

          if (calc.is_prod)
            {
              calc.calc_prod (data, denom, numer);
            }
          else
            {
              calc.calc_inj (data, denom, numer);
            }
        }

      item_t q_rate = well->get_input_rate ();
      item_t bhp = (q_rate - numer) / denom;
      bool switched_to_bhp = false;

      BOSOUT (section::wells, level::low) << "[" << well->name () << "] calc_well_pressure: q_rate: " << q_rate << " numer: " << numer << " denom: " << denom << " bhp: " << bhp << bs_end;
      if ((fabs (denom) < 1e-10) || (bhp < 1.0 || bhp > 1000.0))
        {
          BOSOUT (section::wells, level::low) << "[" << well->name () << "] calc_well_pressure: switched to bhp" << bs_end;

          well->get_well_controller ()->switch_to_bhp (well);
          switched_to_bhp = true;
        }
      else
        {
          BOSOUT (section::wells, level::low) << "[" << well->name () << "] calc_well_pressure: none" << bs_end;

          well->set_bhp (bhp);
        }

      return switched_to_bhp;
    }

  BLUE_SKY_TYPE_STD_CREATE (calc_well_pressure);
  BLUE_SKY_TYPE_STD_COPY (calc_well_pressure);
  BLUE_SKY_TYPE_IMPL (calc_well_pressure, objbase, "calc_well_pressure", "calc_well_pressure", "calc_well_pressure");

  bool
  calc_well_pressure_register_types (const blue_sky::plugin_descriptor &pd)
  {
    bool res = true;

    res &= BS_KERNEL.register_type (pd, calc_well_pressure::bs_type ()); BS_ASSERT (res);

    return res;
  }

} // namespace blue_sky

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2007 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * 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.
 *
 * Authors: Gabe Black
 */

/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * 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.
 *
 * Authors: Gabe Black
 */

#include "arch/x86/faults.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
#include "cpu/thread_context.hh"
#if !FULL_SYSTEM
#include "arch/x86/isa_traits.hh"
#include "mem/page_table.hh"
#include "sim/process.hh"
#endif

namespace X86ISA
{
#if FULL_SYSTEM
    void X86Trap::invoke(TheeadContext * tc)
    {
        panic("X86 faults are not implemented!");
    }

    void X86Abort::invoke(TheeadContext * tc)
    {
        panic("X86 faults are not implemented!");
    }

    void X86Interrupt::invoke(TheeadContext * tc)
    {
        panic("X86 faults are not implemented!");
    }
#else // !FULL_SYSTEM
    void FakeITLBFault::invoke(ThreadContext * tc)
    {
        DPRINTF(TLB, "Invoking an ITLB fault for address %#x at pc %#x.\n",
                vaddr, tc->readPC());
        Process *p = tc->getProcessPtr();
        Addr paddr;
        bool success = p->pTable->translate(vaddr, paddr);
        if(!success) {
            panic("Tried to execute unmapped address %#x.\n", vaddr);
        } else {
            TlbEntry entry;
            entry.pageStart = p->pTable->pageAlign(paddr);
            entry.writeable = false;
            entry.user = true;
            entry.uncacheable = false;
            entry.global = false;
            entry.patBit = 0;
            entry.noExec = false;
            entry.size = PageBytes;
            Addr alignedVaddr = p->pTable->pageAlign(vaddr);
            DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr, entry.pageStart);
            tc->getITBPtr()->insert(alignedVaddr, entry);
        }
    }

    void FakeDTLBFault::invoke(ThreadContext * tc)
    {
        DPRINTF(TLB, "Invoking an DTLB fault for address %#x at pc %#x.\n",
                vaddr, tc->readPC());
        Process *p = tc->getProcessPtr();
        Addr paddr;
        bool success = p->pTable->translate(vaddr, paddr);
        if(!success) {
            p->checkAndAllocNextPage(vaddr);
            success = p->pTable->translate(vaddr, paddr);
        }
        if(!success) {
            panic("Tried to access unmapped address %#x.\n", vaddr);
        } else {
            TlbEntry entry;
            entry.pageStart = p->pTable->pageAlign(paddr);
            entry.writeable = true;
            entry.user = true;
            entry.uncacheable = false;
            entry.global = false;
            entry.patBit = 0;
            entry.noExec = true;
            entry.size = PageBytes;
            Addr alignedVaddr = p->pTable->pageAlign(vaddr);
            DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr, entry.pageStart);
            tc->getDTBPtr()->insert(alignedVaddr, entry);
        }
    }
#endif
} // namespace X86ISA

<commit_msg>X86: X86 FS compile fix.<commit_after>/*
 * Copyright (c) 2003-2007 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * 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.
 *
 * Authors: Gabe Black
 */

/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * 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.
 *
 * Authors: Gabe Black
 */

#include "arch/x86/faults.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
#include "cpu/thread_context.hh"
#if !FULL_SYSTEM
#include "arch/x86/isa_traits.hh"
#include "mem/page_table.hh"
#include "sim/process.hh"
#endif

namespace X86ISA
{
#if FULL_SYSTEM
    void X86Trap::invoke(ThreadContext * tc)
    {
        panic("X86 faults are not implemented!");
    }

    void X86Abort::invoke(ThreadContext * tc)
    {
        panic("X86 faults are not implemented!");
    }

    void X86Interrupt::invoke(ThreadContext * tc)
    {
        panic("X86 faults are not implemented!");
    }
#else // !FULL_SYSTEM
    void FakeITLBFault::invoke(ThreadContext * tc)
    {
        DPRINTF(TLB, "Invoking an ITLB fault for address %#x at pc %#x.\n",
                vaddr, tc->readPC());
        Process *p = tc->getProcessPtr();
        Addr paddr;
        bool success = p->pTable->translate(vaddr, paddr);
        if(!success) {
            panic("Tried to execute unmapped address %#x.\n", vaddr);
        } else {
            TlbEntry entry;
            entry.pageStart = p->pTable->pageAlign(paddr);
            entry.writeable = false;
            entry.user = true;
            entry.uncacheable = false;
            entry.global = false;
            entry.patBit = 0;
            entry.noExec = false;
            entry.size = PageBytes;
            Addr alignedVaddr = p->pTable->pageAlign(vaddr);
            DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr, entry.pageStart);
            tc->getITBPtr()->insert(alignedVaddr, entry);
        }
    }

    void FakeDTLBFault::invoke(ThreadContext * tc)
    {
        DPRINTF(TLB, "Invoking an DTLB fault for address %#x at pc %#x.\n",
                vaddr, tc->readPC());
        Process *p = tc->getProcessPtr();
        Addr paddr;
        bool success = p->pTable->translate(vaddr, paddr);
        if(!success) {
            p->checkAndAllocNextPage(vaddr);
            success = p->pTable->translate(vaddr, paddr);
        }
        if(!success) {
            panic("Tried to access unmapped address %#x.\n", vaddr);
        } else {
            TlbEntry entry;
            entry.pageStart = p->pTable->pageAlign(paddr);
            entry.writeable = true;
            entry.user = true;
            entry.uncacheable = false;
            entry.global = false;
            entry.patBit = 0;
            entry.noExec = true;
            entry.size = PageBytes;
            Addr alignedVaddr = p->pTable->pageAlign(vaddr);
            DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr, entry.pageStart);
            tc->getDTBPtr()->insert(alignedVaddr, entry);
        }
    }
#endif
} // namespace X86ISA

<|endoftext|>


<commit_before>#include "game/ui/base/basescreen.h"
#include "forms/ui.h"
#include "framework/event.h"
#include "framework/framework.h"
#include "framework/image.h"
#include "game/state/base/base.h"
#include "game/state/base/facility.h"
#include "game/ui/base/basegraphics.h"
#include "game/ui/base/researchscreen.h"
#include "game/ui/base/vequipscreen.h"
#include "game/ui/general/messagebox.h"
#include "game/ui/ufopaedia/ufopaediacategoryview.h"

namespace OpenApoc
{

const Vec2<int> BaseScreen::NO_SELECTION = {-1, -1};

BaseScreen::BaseScreen(sp<GameState> state) : BaseStage(state), selection(NO_SELECTION), drag(false)
{
	form = ui().getForm("FORM_BASESCREEN");
	viewHighlight = BaseGraphics::FacilityHighlight::Construction;
}

BaseScreen::~BaseScreen() = default;

void BaseScreen::changeBase(sp<Base> newBase)
{
	BaseStage::changeBase(newBase);
	form->findControlTyped<TextEdit>("TEXT_BASE_NAME")->setText(state->current_base->name);
	form->findControlTyped<Graphic>("GRAPHIC_MINIMAP")
	    ->setImage(BaseGraphics::drawMinimap(state, state->current_base->building));
}

void BaseScreen::begin()
{
	BaseStage::begin();

	baseView = form->findControlTyped<Graphic>("GRAPHIC_BASE_VIEW");
	selText = form->findControlTyped<Label>("TEXT_SELECTED_FACILITY");
	selGraphic = form->findControlTyped<Graphic>("GRAPHIC_SELECTED_FACILITY");
	for (int i = 0; i < 3; i++)
	{
		auto labelName = UString::format("LABEL_%d", i + 1);
		auto label = form->findControlTyped<Label>(labelName);
		if (!label)
		{
			LogError("Failed to find UI control matching \"%s\"", labelName.cStr());
		}
		statsLabels.push_back(label);

		auto valueName = UString::format("VALUE_%d", i + 1);
		auto value = form->findControlTyped<Label>(valueName);
		if (!value)
		{
			LogError("Failed to find UI control matching \"%s\"", valueName.cStr());
		}
		statsValues.push_back(value);
	}

	auto facilities = form->findControlTyped<ListBox>("LISTBOX_FACILITIES");
	for (auto &i : state->facility_types)
	{
		auto &facility = i.second;
		if (!facility->isVisible())
			continue;

		auto graphic = mksp<Graphic>(facility->sprite);
		graphic->AutoSize = true;
		graphic->setData(mksp<UString>(i.first));
		graphic->Name = "FACILITY_BUILD_TILE";
		facilities->addItem(graphic);
	}

	form->findControlTyped<GraphicButton>("BUTTON_OK")
	    ->addCallback(FormEventType::ButtonClick,
	                  [](Event *) { fw().stageQueueCommand({StageCmd::Command::POP}); });
	form->findControlTyped<GraphicButton>("BUTTON_BASE_EQUIPVEHICLE")
	    ->addCallback(FormEventType::ButtonClick, [this](Event *) {
		    // FIXME: If you don't have any vehicles this button should do nothing
		    fw().stageQueueCommand({StageCmd::Command::PUSH, mksp<VEquipScreen>(state)});
		});
	form->findControlTyped<GraphicButton>("BUTTON_BASE_RES_AND_MANUF")
	    ->addCallback(FormEventType::ButtonClick, [this](Event *) {
		    // FIXME: If you don't have any facilities this button should do nothing
		    fw().stageQueueCommand({StageCmd::Command::PUSH, mksp<ResearchScreen>(state)});
		});
	form->findControlTyped<TextEdit>("TEXT_BASE_NAME")
	    ->addCallback(FormEventType::TextEditFinish, [this](Event *e) {
		    this->state->current_base->name =
		        std::dynamic_pointer_cast<TextEdit>(e->forms().RaisedBy)->getText();
		});
}

void BaseScreen::pause() {}

void BaseScreen::resume() { textFunds->setText(state->getPlayerBalance()); }

void BaseScreen::finish() {}

void BaseScreen::eventOccurred(Event *e)
{
	form->eventOccured(e);

	if (e->type() == EVENT_KEY_DOWN)
	{
		if (e->keyboard().KeyCode == SDLK_ESCAPE)
		{
			fw().stageQueueCommand({StageCmd::Command::POP});
			return;
		}
	}

	if (e->type() == EVENT_MOUSE_MOVE)
	{
		mousePos = {e->mouse().X, e->mouse().Y};
	}

	if (e->type() == EVENT_FORM_INTERACTION)
	{
		if (e->forms().RaisedBy == baseView)
		{
			if (e->forms().EventFlag == FormEventType::MouseMove)
			{
				selection = {e->forms().MouseInfo.X, e->forms().MouseInfo.Y};
				selection /= BaseGraphics::TILE_SIZE;
				if (!drag)
				{
					selFacility = state->current_base->getFacility(selection);
				}
				return;
			}
			else if (e->forms().EventFlag == FormEventType::MouseLeave)
			{
				selection = NO_SELECTION;
				selFacility = nullptr;
				return;
			}
		}
		if (e->forms().RaisedBy->Name == "LISTBOX_FACILITIES")
		{
			if (!drag && e->forms().EventFlag == FormEventType::ListBoxChangeHover)
			{
				auto list = form->findControlTyped<ListBox>("LISTBOX_FACILITIES");
				auto dragFacilityName = list->getHoveredData<UString>();
				if (dragFacilityName)
				{
					dragFacility = StateRef<FacilityType>{state.get(), *dragFacilityName};
					return;
				}
			}
		}
		if (e->forms().RaisedBy->Name == "FACILITY_BUILD_TILE")
		{
			if (!drag && e->forms().EventFlag == FormEventType::MouseLeave)
			{
				selection = NO_SELECTION;
				selFacility = nullptr;
				dragFacility = "";
			}
		}

		if (e->forms().EventFlag == FormEventType::MouseDown)
		{
			if (e->forms().MouseInfo.Button == 1)
			{
				if (!drag && dragFacility)
				{
					if (e->forms().RaisedBy->Name == "LISTBOX_FACILITIES")
					{
						drag = true;
					}
				}
			}
			else if (e->forms().MouseInfo.Button == 4 &&
			         e->forms().RaisedBy->Name == "LISTBOX_FACILITIES")
			{
				auto list = std::dynamic_pointer_cast<ListBox>(e->forms().RaisedBy);
				auto clickedFacilityName = list->getHoveredData<UString>();
				StateRef<FacilityType> clickedFacility;
				if (clickedFacilityName)
					clickedFacility = StateRef<FacilityType>{state.get(), *clickedFacilityName};
				if (!clickedFacility)
					return;

				auto ufopaedia_entry = clickedFacility->ufopaedia_entry;
				sp<UfopaediaCategory> ufopaedia_category;
				if (ufopaedia_entry)
				{
					for (auto &cat : this->state->ufopaedia)
					{
						for (auto &entry : cat.second->entries)
						{
							if (ufopaedia_entry == entry.second)
							{
								ufopaedia_category = cat.second;
								break;
							}
						}
						if (ufopaedia_category)
							break;
					}
					if (!ufopaedia_category)
					{
						LogError("No UFOPaedia category found for entry %s",
						         ufopaedia_entry->title.cStr());
					}
					fw().stageQueueCommand(
					    {StageCmd::Command::PUSH,
					     mksp<UfopaediaCategoryView>(state, ufopaedia_category, ufopaedia_entry)});
				}
			}
		}

		if (e->forms().EventFlag == FormEventType::MouseUp)
		{
			// Facility construction
			if (drag && dragFacility)
			{
				if (selection != NO_SELECTION)
				{
					Base::BuildError error =
					    state->current_base->canBuildFacility(dragFacility, selection);
					switch (error)
					{
						case Base::BuildError::NoError:
							state->current_base->buildFacility(*state, dragFacility, selection);
							textFunds->setText(state->getPlayerBalance());
							refreshView();
							break;
						case Base::BuildError::Occupied:
							fw().stageQueueCommand(
							    {StageCmd::Command::PUSH,
							     mksp<MessageBox>(tr("Area Occupied By Existing Facility"),
							                      tr("Existing facilities in this area of the base "
							                         "must be destroyed "
							                         "before construction work can begin."),
							                      MessageBox::ButtonOptions::Ok)});
							break;
						case Base::BuildError::OutOfBounds:
							fw().stageQueueCommand(
							    {StageCmd::Command::PUSH,
							     mksp<MessageBox>(
							         tr("Planning Permission Denied"),
							         tr("Planning permission is denied for this proposed extension "
							            "to "
							            "the base, on the grounds that the additional excavations "
							            "required would seriously weaken the foundations of the "
							            "building."),
							         MessageBox::ButtonOptions::Ok)});
							break;
						case Base::BuildError::NoMoney:
							fw().stageQueueCommand(
							    {StageCmd::Command::PUSH,
							     mksp<MessageBox>(tr("Funds exceeded"),
							                      tr("The proposed construction work is not "
							                         "possible with your available funds."),
							                      MessageBox::ButtonOptions::Ok)});
							break;
						case Base::BuildError::Indestructible:
							// Indestrictible facilities (IE the access lift) are just silently
							// ignored
							break;
					}
				}
				drag = false;
				dragFacility = "";
			}
			// Facility removal
			else if (selFacility)
			{
				if (selection != NO_SELECTION)
				{
					Base::BuildError error = state->current_base->canDestroyFacility(selection);
					switch (error)
					{
						case Base::BuildError::NoError:
							fw().stageQueueCommand(
							    {StageCmd::Command::PUSH,
							     mksp<MessageBox>(tr("Destroy facility"), tr("Are you sure?"),
							                      MessageBox::ButtonOptions::YesNo, [this] {
								                      this->state->current_base->destroyFacility(
								                          *this->state, this->selection);
								                      this->refreshView();
								                  })});
							break;
						case Base::BuildError::Occupied:
							fw().stageQueueCommand(
							    {StageCmd::Command::PUSH,
							     mksp<MessageBox>(tr("Facility in use"), tr(""),
							                      MessageBox::ButtonOptions::Ok)});
						default:
							break;
					}
					selFacility = nullptr;
				}
			}
		}
	}

	selText->setText("");
	selGraphic->setImage(nullptr);
	for (auto label : statsLabels)
	{
		label->setText("");
	}
	for (auto value : statsValues)
	{
		value->setText("");
	}
	if (dragFacility)
	{
		selText->setText(tr(dragFacility->name));
		selGraphic->setImage(dragFacility->sprite);
		statsLabels[0]->setText(tr("Cost to build"));
		statsValues[0]->setText(UString::format("$%d", dragFacility->buildCost));
		statsLabels[1]->setText(tr("Days to build"));
		statsValues[1]->setText(UString::format("%d", dragFacility->buildTime));
		statsLabels[2]->setText(tr("Maintenance cost"));
		statsValues[2]->setText(UString::format("$%d", dragFacility->weeklyCost));
	}
	else if (selFacility != nullptr)
	{
		selText->setText(tr(selFacility->type->name));
		selGraphic->setImage(selFacility->type->sprite);
		if (selFacility->type->capacityAmount > 0)
		{
			statsLabels[0]->setText(tr("Capacity"));
			statsValues[0]->setText(UString::format("%d", selFacility->type->capacityAmount));
			statsLabels[1]->setText(tr("Usage"));
			statsValues[1]->setText(
			    UString::format("%d%%", state->current_base->getUsage(selFacility)));
		}
	}
	else if (selection != NO_SELECTION)
	{
		int sprite = BaseGraphics::getCorridorSprite(state->current_base, selection);
		auto image = UString::format(
		    "PCK:xcom3/ufodata/base.pck:xcom3/ufodata/base.tab:%d:xcom3/ufodata/base.pcx", sprite);
		if (sprite != 0)
		{
			selText->setText(tr("Corridor"));
		}
		else
		{
			selText->setText(tr("Earth"));
		}
		selGraphic->setImage(fw().data->loadImage(image));
	}
}

void BaseScreen::update() { form->update(); }

void BaseScreen::render()
{
	fw().stageGetPrevious(this->shared_from_this())->render();
	form->render();
	renderBase();
	BaseStage::render();
}

bool BaseScreen::isTransition() { return false; }

void BaseScreen::renderBase()
{
	const Vec2<int> BASE_POS = form->Location + baseView->Location;

	BaseGraphics::renderBase(BASE_POS, state->current_base);

	// Draw selection
	if (selection != NO_SELECTION)
	{
		Vec2<int> pos = selection;
		Vec2<int> size = {BaseGraphics::TILE_SIZE, BaseGraphics::TILE_SIZE};
		if (drag && dragFacility)
		{
			size *= dragFacility->size;
		}
		else if (selFacility != nullptr)
		{
			pos = selFacility->pos;
			size *= selFacility->type->size;
		}
		pos = BASE_POS + pos * BaseGraphics::TILE_SIZE;
		fw().renderer->drawRect(pos, size, Colour{255, 255, 255});
	}

	// Draw dragged facility
	if (drag && dragFacility)
	{
		sp<Image> facility = dragFacility->sprite;
		Vec2<int> pos;
		if (selection == NO_SELECTION)
		{
			pos = mousePos -
			      Vec2<int>{BaseGraphics::TILE_SIZE, BaseGraphics::TILE_SIZE} / 2 *
			          dragFacility->size;
		}
		else
		{
			pos = BASE_POS + selection * BaseGraphics::TILE_SIZE;
		}
		fw().renderer->draw(facility, pos);
	}
}

}; // namespace OpenApoc
<commit_msg>Fix right-click Ufopaedia in base screen<commit_after>#include "game/ui/base/basescreen.h"
#include "forms/ui.h"
#include "framework/event.h"
#include "framework/framework.h"
#include "framework/image.h"
#include "game/state/base/base.h"
#include "game/state/base/facility.h"
#include "game/ui/base/basegraphics.h"
#include "game/ui/base/researchscreen.h"
#include "game/ui/base/vequipscreen.h"
#include "game/ui/general/messagebox.h"
#include "game/ui/ufopaedia/ufopaediacategoryview.h"

namespace OpenApoc
{

const Vec2<int> BaseScreen::NO_SELECTION = {-1, -1};

BaseScreen::BaseScreen(sp<GameState> state) : BaseStage(state), selection(NO_SELECTION), drag(false)
{
	form = ui().getForm("FORM_BASESCREEN");
	viewHighlight = BaseGraphics::FacilityHighlight::Construction;
}

BaseScreen::~BaseScreen() = default;

void BaseScreen::changeBase(sp<Base> newBase)
{
	BaseStage::changeBase(newBase);
	form->findControlTyped<TextEdit>("TEXT_BASE_NAME")->setText(state->current_base->name);
	form->findControlTyped<Graphic>("GRAPHIC_MINIMAP")
	    ->setImage(BaseGraphics::drawMinimap(state, state->current_base->building));
}

void BaseScreen::begin()
{
	BaseStage::begin();

	baseView = form->findControlTyped<Graphic>("GRAPHIC_BASE_VIEW");
	selText = form->findControlTyped<Label>("TEXT_SELECTED_FACILITY");
	selGraphic = form->findControlTyped<Graphic>("GRAPHIC_SELECTED_FACILITY");
	for (int i = 0; i < 3; i++)
	{
		auto labelName = UString::format("LABEL_%d", i + 1);
		auto label = form->findControlTyped<Label>(labelName);
		if (!label)
		{
			LogError("Failed to find UI control matching \"%s\"", labelName.cStr());
		}
		statsLabels.push_back(label);

		auto valueName = UString::format("VALUE_%d", i + 1);
		auto value = form->findControlTyped<Label>(valueName);
		if (!value)
		{
			LogError("Failed to find UI control matching \"%s\"", valueName.cStr());
		}
		statsValues.push_back(value);
	}

	auto facilities = form->findControlTyped<ListBox>("LISTBOX_FACILITIES");
	for (auto &i : state->facility_types)
	{
		auto &facility = i.second;
		if (!facility->isVisible())
			continue;

		auto graphic = mksp<Graphic>(facility->sprite);
		graphic->AutoSize = true;
		graphic->setData(mksp<UString>(i.first));
		graphic->Name = "FACILITY_BUILD_TILE";
		facilities->addItem(graphic);
	}

	form->findControlTyped<GraphicButton>("BUTTON_OK")
	    ->addCallback(FormEventType::ButtonClick,
	                  [](Event *) { fw().stageQueueCommand({StageCmd::Command::POP}); });
	form->findControlTyped<GraphicButton>("BUTTON_BASE_EQUIPVEHICLE")
	    ->addCallback(FormEventType::ButtonClick, [this](Event *) {
		    // FIXME: If you don't have any vehicles this button should do nothing
		    fw().stageQueueCommand({StageCmd::Command::PUSH, mksp<VEquipScreen>(state)});
		});
	form->findControlTyped<GraphicButton>("BUTTON_BASE_RES_AND_MANUF")
	    ->addCallback(FormEventType::ButtonClick, [this](Event *) {
		    // FIXME: If you don't have any facilities this button should do nothing
		    fw().stageQueueCommand({StageCmd::Command::PUSH, mksp<ResearchScreen>(state)});
		});
	form->findControlTyped<TextEdit>("TEXT_BASE_NAME")
	    ->addCallback(FormEventType::TextEditFinish, [this](Event *e) {
		    this->state->current_base->name =
		        std::dynamic_pointer_cast<TextEdit>(e->forms().RaisedBy)->getText();
		});
}

void BaseScreen::pause() {}

void BaseScreen::resume() { textFunds->setText(state->getPlayerBalance()); }

void BaseScreen::finish() {}

void BaseScreen::eventOccurred(Event *e)
{
	form->eventOccured(e);

	if (e->type() == EVENT_KEY_DOWN)
	{
		if (e->keyboard().KeyCode == SDLK_ESCAPE)
		{
			fw().stageQueueCommand({StageCmd::Command::POP});
			return;
		}
	}

	if (e->type() == EVENT_MOUSE_MOVE)
	{
		mousePos = {e->mouse().X, e->mouse().Y};
	}

	if (e->type() == EVENT_FORM_INTERACTION)
	{
		if (e->forms().RaisedBy == baseView)
		{
			if (e->forms().EventFlag == FormEventType::MouseMove)
			{
				selection = {e->forms().MouseInfo.X, e->forms().MouseInfo.Y};
				selection /= BaseGraphics::TILE_SIZE;
				if (!drag)
				{
					selFacility = state->current_base->getFacility(selection);
				}
				return;
			}
			else if (e->forms().EventFlag == FormEventType::MouseLeave)
			{
				selection = NO_SELECTION;
				selFacility = nullptr;
				return;
			}
		}
		if (e->forms().RaisedBy->Name == "LISTBOX_FACILITIES")
		{
			if (!drag && e->forms().EventFlag == FormEventType::ListBoxChangeHover)
			{
				auto list = form->findControlTyped<ListBox>("LISTBOX_FACILITIES");
				auto dragFacilityName = list->getHoveredData<UString>();
				if (dragFacilityName)
				{
					dragFacility = StateRef<FacilityType>{state.get(), *dragFacilityName};
					return;
				}
			}
		}
		if (e->forms().RaisedBy->Name == "FACILITY_BUILD_TILE")
		{
			if (!drag && e->forms().EventFlag == FormEventType::MouseLeave)
			{
				selection = NO_SELECTION;
				selFacility = nullptr;
				dragFacility = "";
			}
		}

		if (e->forms().EventFlag == FormEventType::MouseDown)
		{
			if (e->forms().MouseInfo.Button == 1)
			{
				if (!drag && dragFacility)
				{
					if (e->forms().RaisedBy->Name == "LISTBOX_FACILITIES")
					{
						drag = true;
					}
				}
			}
			else if (e->forms().MouseInfo.Button == 4)
			{
				sp<UString> clickedFacilityName;
				if (e->forms().RaisedBy->Name == "LISTBOX_FACILITIES")
				{
					auto list = std::dynamic_pointer_cast<ListBox>(e->forms().RaisedBy);
					clickedFacilityName = list->getHoveredData<UString>();
				}
				else if (e->forms().RaisedBy->Name == "GRAPHIC_BASE_VIEW")
				{
					if (selFacility)
						clickedFacilityName = mksp<UString>(selFacility->type.id);
				}

				StateRef<FacilityType> clickedFacility;
				if (clickedFacilityName)
					clickedFacility = StateRef<FacilityType>{state.get(), *clickedFacilityName};
				if (!clickedFacility)
					return;

				auto ufopaedia_entry = clickedFacility->ufopaedia_entry;
				sp<UfopaediaCategory> ufopaedia_category;
				if (ufopaedia_entry)
				{
					for (auto &cat : this->state->ufopaedia)
					{
						for (auto &entry : cat.second->entries)
						{
							if (ufopaedia_entry == entry.second)
							{
								ufopaedia_category = cat.second;
								break;
							}
						}
						if (ufopaedia_category)
							break;
					}
					if (!ufopaedia_category)
					{
						LogError("No UFOPaedia category found for entry %s",
						         ufopaedia_entry->title.cStr());
					}
					fw().stageQueueCommand(
					    {StageCmd::Command::PUSH,
					     mksp<UfopaediaCategoryView>(state, ufopaedia_category, ufopaedia_entry)});
				}
			}
		}

		if (e->forms().EventFlag == FormEventType::MouseUp)
		{
			// Facility construction
			if (drag && dragFacility)
			{
				if (selection != NO_SELECTION)
				{
					Base::BuildError error =
					    state->current_base->canBuildFacility(dragFacility, selection);
					switch (error)
					{
						case Base::BuildError::NoError:
							state->current_base->buildFacility(*state, dragFacility, selection);
							textFunds->setText(state->getPlayerBalance());
							refreshView();
							break;
						case Base::BuildError::Occupied:
							fw().stageQueueCommand(
							    {StageCmd::Command::PUSH,
							     mksp<MessageBox>(tr("Area Occupied By Existing Facility"),
							                      tr("Existing facilities in this area of the base "
							                         "must be destroyed "
							                         "before construction work can begin."),
							                      MessageBox::ButtonOptions::Ok)});
							break;
						case Base::BuildError::OutOfBounds:
							fw().stageQueueCommand(
							    {StageCmd::Command::PUSH,
							     mksp<MessageBox>(
							         tr("Planning Permission Denied"),
							         tr("Planning permission is denied for this proposed extension "
							            "to "
							            "the base, on the grounds that the additional excavations "
							            "required would seriously weaken the foundations of the "
							            "building."),
							         MessageBox::ButtonOptions::Ok)});
							break;
						case Base::BuildError::NoMoney:
							fw().stageQueueCommand(
							    {StageCmd::Command::PUSH,
							     mksp<MessageBox>(tr("Funds exceeded"),
							                      tr("The proposed construction work is not "
							                         "possible with your available funds."),
							                      MessageBox::ButtonOptions::Ok)});
							break;
						case Base::BuildError::Indestructible:
							// Indestrictible facilities (IE the access lift) are just silently
							// ignored
							break;
					}
				}
				drag = false;
				dragFacility = "";
			}
			// Facility removal
			else if (selFacility)
			{
				if (selection != NO_SELECTION)
				{
					Base::BuildError error = state->current_base->canDestroyFacility(selection);
					switch (error)
					{
						case Base::BuildError::NoError:
							fw().stageQueueCommand(
							    {StageCmd::Command::PUSH,
							     mksp<MessageBox>(tr("Destroy facility"), tr("Are you sure?"),
							                      MessageBox::ButtonOptions::YesNo, [this] {
								                      this->state->current_base->destroyFacility(
								                          *this->state, this->selection);
								                      this->refreshView();
								                  })});
							break;
						case Base::BuildError::Occupied:
							fw().stageQueueCommand(
							    {StageCmd::Command::PUSH,
							     mksp<MessageBox>(tr("Facility in use"), tr(""),
							                      MessageBox::ButtonOptions::Ok)});
						default:
							break;
					}
					selFacility = nullptr;
				}
			}
		}
	}

	selText->setText("");
	selGraphic->setImage(nullptr);
	for (auto label : statsLabels)
	{
		label->setText("");
	}
	for (auto value : statsValues)
	{
		value->setText("");
	}
	if (dragFacility)
	{
		selText->setText(tr(dragFacility->name));
		selGraphic->setImage(dragFacility->sprite);
		statsLabels[0]->setText(tr("Cost to build"));
		statsValues[0]->setText(UString::format("$%d", dragFacility->buildCost));
		statsLabels[1]->setText(tr("Days to build"));
		statsValues[1]->setText(UString::format("%d", dragFacility->buildTime));
		statsLabels[2]->setText(tr("Maintenance cost"));
		statsValues[2]->setText(UString::format("$%d", dragFacility->weeklyCost));
	}
	else if (selFacility != nullptr)
	{
		selText->setText(tr(selFacility->type->name));
		selGraphic->setImage(selFacility->type->sprite);
		if (selFacility->type->capacityAmount > 0)
		{
			statsLabels[0]->setText(tr("Capacity"));
			statsValues[0]->setText(UString::format("%d", selFacility->type->capacityAmount));
			statsLabels[1]->setText(tr("Usage"));
			statsValues[1]->setText(
			    UString::format("%d%%", state->current_base->getUsage(selFacility)));
		}
	}
	else if (selection != NO_SELECTION)
	{
		int sprite = BaseGraphics::getCorridorSprite(state->current_base, selection);
		auto image = UString::format(
		    "PCK:xcom3/ufodata/base.pck:xcom3/ufodata/base.tab:%d:xcom3/ufodata/base.pcx", sprite);
		if (sprite != 0)
		{
			selText->setText(tr("Corridor"));
		}
		else
		{
			selText->setText(tr("Earth"));
		}
		selGraphic->setImage(fw().data->loadImage(image));
	}
}

void BaseScreen::update() { form->update(); }

void BaseScreen::render()
{
	fw().stageGetPrevious(this->shared_from_this())->render();
	form->render();
	renderBase();
	BaseStage::render();
}

bool BaseScreen::isTransition() { return false; }

void BaseScreen::renderBase()
{
	const Vec2<int> BASE_POS = form->Location + baseView->Location;

	BaseGraphics::renderBase(BASE_POS, state->current_base);

	// Draw selection
	if (selection != NO_SELECTION)
	{
		Vec2<int> pos = selection;
		Vec2<int> size = {BaseGraphics::TILE_SIZE, BaseGraphics::TILE_SIZE};
		if (drag && dragFacility)
		{
			size *= dragFacility->size;
		}
		else if (selFacility != nullptr)
		{
			pos = selFacility->pos;
			size *= selFacility->type->size;
		}
		pos = BASE_POS + pos * BaseGraphics::TILE_SIZE;
		fw().renderer->drawRect(pos, size, Colour{255, 255, 255});
	}

	// Draw dragged facility
	if (drag && dragFacility)
	{
		sp<Image> facility = dragFacility->sprite;
		Vec2<int> pos;
		if (selection == NO_SELECTION)
		{
			pos = mousePos -
			      Vec2<int>{BaseGraphics::TILE_SIZE, BaseGraphics::TILE_SIZE} / 2 *
			          dragFacility->size;
		}
		else
		{
			pos = BASE_POS + selection * BaseGraphics::TILE_SIZE;
		}
		fw().renderer->draw(facility, pos);
	}
}

}; // namespace OpenApoc
<|endoftext|>


<commit_before>// -------------------------------------------------------------------
/// \file   GHepReader.cxx
/// \brief
///
/// \author  <justo.martin-albo@physics.ox.ac.uk>
/// \date    Creation: 7 June 2016
// -------------------------------------------------------------------

#include "GHepReader.h"

#include <G4Event.hh>

#include <TChain.h>
#include <TCollection.h>

#include <Ntuple/NtpMCEventRecord.h>
#include <EVGCore/EventRecord.h>
#include <GHEP/GHepParticle.h>

GHepReader::GHepReader(const G4String& path, G4double mean):
  BeamSpillSource(), ifiles_(0), mcrec_(0), max_entries_(0), current_entry_(-1)
{
  this->Initialize(path);
}

GHepReader::~GHepReader()
{}

void GHepReader::Initialize(const G4String& path)
{
  ifiles_ = new TChain("gtree");
  ifiles_->Add(path);
  ifiles_->SetBranchAddress("gmcrec", &mcrec_);

  max_entries_ = ifiles_->GetEntries();
}

void GHepReader::FillG4Event(G4Event* event)
{
   // A G4Event organizes its particles in terms of "vertices" and
    // "particles", like HepMC.  Unfortunately, ROOT doesn't use
    // HepMC, so the MCTruth objects aren't organized that way.
    // For most of the work that we'll ever do, there'll be only one
    // vertex in the event.  However, just in case there are multiple
    // vertices (e.g., overlays, double vertex studies) I want the
    // code to function properly.

    // So create a map of particle positions and associated
    // G4PrimaryVertex*.  Note that the map must use CLHEP's
    // LorentzVector, and not ROOT's, since ROOT does not define an
    // operator< for its physics vectors.
    std::map<G4LorentVector, G4PrimaryVertex*> vertex_map;
    std::map<G4LorentVector, G4PrimaryVertex*>::const_iterator vm_iter;

  G4cout << "GHepReader::FillG4Event()" << G4endl;

  current_entry_++;
  ifiles_->GetEntry(current_entry_);

  genie::EventRecord* record = mcrec_->event;

  //genie::Interaction* inter = gevtrec.Summary();
  //const genie::Target& target = inter->InitState().Tgt();

  //G4cout << "Target Z = " << target.Z() << G4endl;

  TLorentzVector* vtx_position = record->Vertex();

  TIter gpart_iter(record);
  genie::GHepParticle* gpart = 0;

  while ((gpart = dynamic_cast<genie::GHepParticle*>(gpart_iter.Next()))) {

    if (gpart->Status() != 1) continue;

    G4LorentVector xyzt;

    xyzt.setX( gpart->Vx()*fermi + vtx_position->X()*meter );
    xyzt.setY( gpart->Vy()*fermi + vtx_position->Y()*meter );
    xyzt.setZ( gpart->Vz()*fermi + vtx_position->Z()*meter );

    // Check whether a vertex corresponding to that position and time
    // exists already in the event
    G4PrimaryVertex* vertex = 0;
    auto result = vertex_map.find(xyzt);

    if (result == vertex_map.end()) {
      // The vertex does not exits. Therefore, create a new one and
      // add it to both the map and the event.
      vertex = new G4PrimaryVertex(xyzt.X(), xyzt.Y(), xyzt.Z(), xyzt.T());
      event->AddPrimaryVertex(vertex);
      vertex_map[xyzt] = vertex;
    }
    else {
      // The vertex exists already. No need to create a new one.
      vertex = (*result).second;
    }

    G4ParticleDefinition* particle_def =
      G4ParticleDefinition::GetParticleTable()->FindParticle(gpart->Pdg());

    if (!particle_def) {
      G4cerr << "PDG code " << gpart->Pdg() << " not found." << G4endl;
      continue;
    }

    // Create a new primary particle and add it to the vertex
    G4PrimaryParticle* particle = new G4PrimaryParticle(particle_def,
                                                        gpart->Px() * GeV,
                                                        gpart->Py() * GeV,
                                                        gpart->Pz() * GeV);

    vertex->SetPrimary(particle);

  }

  /*
  // Decide how many interactions we are supposed to read from the file

  G4int num_interactions;

  genie::EventRecord* record;

  for (G4int i=0; i<num_interactions; i++) {

    TLorentzVector* vertex = record->Vertex();

    double spill_time =
      fGlobalTimeOffset + fHelperRandom->Uniform()*fRandomTimeOffset;

    // add the particles from the interaction
    TIter partitr(record);
    genie::GHepParticle *part = 0;

    // GHepParticles return units of GeV/c for p.  the V_i are all in fermis
    // and are relative to the center of the struck nucleus.
    // add the vertex X/Y/Z to the V_i for status codes 0 and 1
    int trackid = 0;

    while ((part = dynamic_cast<genie::GHepParticle *>(partitr.Next()))) {

      // Check particle status

      // Get PDG code for the particle

      double vtx[4] = {part->Vx(), part->Vy(), part->Vz(), part->Vt()};
      vtx[0] = 100.*(part->Vx()*1.e-15 + vertex->X());
      vtx[1] = 100.*(part->Vy()*1.e-15 + vertex->Y());
      vtx[2] = 100.*(part->Vz()*1.e-15 + vertex->Z());
      vtx[3] = part->Vt() + spillTime;
    TLorentzVector pos(vtx[0], vtx[1], vtx[2], vtx[3]);
    TLorentzVector mom(part->Px(), part->Py(), part->Pz(), part->E());
    if(part->PolzIsSet()) {
        TVector3 polz;
        part->GetPolarization(polz);
        tpart.SetPolarization(polz);
      }
    }

     // Is this vertex already in our map?
    G4PrimaryVertex* vertex = 0;
    std::map< CLHEP::HepLorentzVector, G4PrimaryVertex* >::const_iterator result = vertexMap.find( fourpos );
    if ( result == vertexMap.end() ){
141
          // No, it's not, so create a new vertex and add it to the
142
          // map.
143
          vertex = new G4PrimaryVertex(x, y, z, t);
144
          vertexMap[ fourpos ] = vertex;
145
146
          // Add the vertex to the G4Event.
147
          event->AddPrimaryVertex( vertex );
148
        }
149
        else{
150
          // Yes, it is, so use the existing vertex.
151
          vertex = (*result).second;
152
        }
                // Get additional particle information.
155
        TLorentzVector momentum = particle.Momentum(); // (px,py,pz,E)
156
        TVector3 polarization = particle.Polarization();
157

158
        // Get the particle table if necessary.  (Note: we're
159
        // doing this "late" because I'm not sure at what point
160
        // the G4 particle table is initialized in the loading process.
161
        if ( fParticleTable == 0 ){
162
          fParticleTable = G4ParticleTable::GetParticleTable();
163
        }
164
165
        if ( pdgCode > 1000000000 )
166
          LOG_DEBUG("ConvertPrimaryToGeant4") << ": %%% Nuclear PDG code = " << pdgCode
167
                                              << " (x,y,z,t)=(" << x
168
                                              << "," << y
169
                                              << "," << z
170
                                              << "," << t << ")"
171
                                              << " P=" << momentum.P()
172
                                              << ", E=" << momentum.E();
173
174
        // Get Geant4's definition of the particle.
175
        G4ParticleDefinition* particleDefinition;
176

177
        if(pdgCode==0){
178
          particleDefinition = fParticleTable->FindParticle("opticalphoton");
179
        }
180
        else
181
          particleDefinition = fParticleTable->FindParticle(pdgCode);
182
183
        // What if the PDG code is unknown?  This has been a known
184
        // issue with GENIE.
185
        if ( particleDefinition == 0 ){
186
          LOG_DEBUG("ConvertPrimaryToGeant4") << ": %%% Code not found = " << pdgCode;
187
          fUnknownPDG[ pdgCode ] += 1;
188
          continue;
189
        }
190

191
        // Create a Geant4 particle to add to the vertex.
192
        G4PrimaryParticle* g4particle = new G4PrimaryParticle( particleDefinition,
193
                                                               momentum.Px() * CLHEP::GeV,
194
                                                               momentum.Py() * CLHEP::GeV,
195
                                                               momentum.Pz() * CLHEP::GeV);
196
197

        // Add more particle information the Geant4 particle.
198
        G4double charge = particleDefinition->GetPDGCharge();
199
        g4particle->SetCharge( charge );
200
        g4particle->SetPolarization( polarization.x(),
201
                                     polarization.y(),
202
                                     polarization.z() );
203

204
        // Add the particle to the vertex.
205
        vertex->SetPrimary( g4particle );
206
207
        // Create a PrimaryParticleInformation object, and save
208
        // the MCTruth pointer in it.  This will allow the
209
        // ParticleActionList class to access MCTruth
210
        // information during Geant4's tracking.
211
        PrimaryParticleInformation* primaryParticleInfo = new PrimaryParticleInformation;
212
        primaryParticleInfo->SetMCTruth( mct, index );
213

214
        // Save the PrimaryParticleInformation in the
215
        // G4PrimaryParticle for access during tracking.
216
        g4particle->SetUserInformation( primaryParticleInfo );
217
218

  }*/
}<commit_msg>Added cmake module.<commit_after>// -------------------------------------------------------------------
/// \file   GHepReader.cxx
/// \brief
///
/// \author  <justo.martin-albo@physics.ox.ac.uk>
/// \date    Creation: 7 June 2016
// -------------------------------------------------------------------

#include "GHepReader.h"

#include <G4Event.hh>
#include <G4LorentzVector.hh>
#include <G4SystemOfUnits.hh>
#include <G4ParticleDefinition.hh>
#include <G4ParticleTable.hh>

#include <TChain.h>
#include <TCollection.h>

#include <Ntuple/NtpMCEventRecord.h>
#include <EVGCore/EventRecord.h>
#include <GHEP/GHepParticle.h>

#include <map>

GHepReader::GHepReader(const G4String& path, G4double mean):
  BeamSpillSource(), ifiles_(0), mcrec_(0), max_entries_(0), current_entry_(-1)
{
  this->Initialize(path);
}

GHepReader::~GHepReader()
{}

void GHepReader::Initialize(const G4String& path)
{
  ifiles_ = new TChain("gtree");
  ifiles_->Add(path);
  ifiles_->SetBranchAddress("gmcrec", &mcrec_);

  max_entries_ = ifiles_->GetEntries();
}

void GHepReader::FillG4Event(G4Event* event)
{
   // A G4Event organizes its particles in terms of "vertices" and
    // "particles", like HepMC.  Unfortunately, ROOT doesn't use
    // HepMC, so the MCTruth objects aren't organized that way.
    // For most of the work that we'll ever do, there'll be only one
    // vertex in the event.  However, just in case there are multiple
    // vertices (e.g., overlays, double vertex studies) I want the
    // code to function properly.

    // So create a map of particle positions and associated
    // G4PrimaryVertex*.  Note that the map must use CLHEP's
    // LorentzVector, and not ROOT's, since ROOT does not define an
    // operator< for its physics vectors.
    std::map<G4LorentzVector, G4PrimaryVertex*> vertex_map;
    std::map<G4LorentzVector, G4PrimaryVertex*>::const_iterator vm_iter;

  G4cout << "GHepReader::FillG4Event()" << G4endl;

  current_entry_++;
  ifiles_->GetEntry(current_entry_);

  genie::EventRecord* record = mcrec_->event;

  //genie::Interaction* inter = gevtrec.Summary();
  //const genie::Target& target = inter->InitState().Tgt();

  //G4cout << "Target Z = " << target.Z() << G4endl;

  TLorentzVector* vtx_position = record->Vertex();

  TIter gpart_iter(record);
  genie::GHepParticle* gpart = 0;

  while ((gpart = dynamic_cast<genie::GHepParticle*>(gpart_iter.Next()))) {

    if (gpart->Status() != 1) continue;

    G4LorentzVector xyzt;

    xyzt.setX( gpart->Vx()*fermi + vtx_position->X()*meter );
    xyzt.setY( gpart->Vy()*fermi + vtx_position->Y()*meter );
    xyzt.setZ( gpart->Vz()*fermi + vtx_position->Z()*meter );

    // Check whether a vertex corresponding to that position and time
    // exists already in the event
    G4PrimaryVertex* vertex = 0;
    auto result = vertex_map.find(xyzt);

    if (result == vertex_map.end()) {
      // The vertex does not exits. Therefore, create a new one and
      // add it to both the map and the event.
      vertex = new G4PrimaryVertex(xyzt.x(), xyzt.y(), xyzt.z(), xyzt.t());
      event->AddPrimaryVertex(vertex);
      vertex_map[xyzt] = vertex;
    }
    else {
      // The vertex exists already. No need to create a new one.
      vertex = (*result).second;
    }

    G4ParticleDefinition* particle_def =
      G4ParticleTable::GetParticleTable()->FindParticle(gpart->Pdg());

    if (!particle_def) {
      G4cerr << "PDG code " << gpart->Pdg() << " not found." << G4endl;
      continue;
    }

    // Create a new primary particle and add it to the vertex
    G4PrimaryParticle* particle = new G4PrimaryParticle(particle_def,
                                                        gpart->Px() * GeV,
                                                        gpart->Py() * GeV,
                                                        gpart->Pz() * GeV);

    vertex->SetPrimary(particle);

  }

  /*
  // Decide how many interactions we are supposed to read from the file

  G4int num_interactions;

  genie::EventRecord* record;

  for (G4int i=0; i<num_interactions; i++) {

    TLorentzVector* vertex = record->Vertex();

    double spill_time =
      fGlobalTimeOffset + fHelperRandom->Uniform()*fRandomTimeOffset;

    // add the particles from the interaction
    TIter partitr(record);
    genie::GHepParticle *part = 0;

    // GHepParticles return units of GeV/c for p.  the V_i are all in fermis
    // and are relative to the center of the struck nucleus.
    // add the vertex X/Y/Z to the V_i for status codes 0 and 1
    int trackid = 0;

    while ((part = dynamic_cast<genie::GHepParticle *>(partitr.Next()))) {

      // Check particle status

      // Get PDG code for the particle

      double vtx[4] = {part->Vx(), part->Vy(), part->Vz(), part->Vt()};
      vtx[0] = 100.*(part->Vx()*1.e-15 + vertex->X());
      vtx[1] = 100.*(part->Vy()*1.e-15 + vertex->Y());
      vtx[2] = 100.*(part->Vz()*1.e-15 + vertex->Z());
      vtx[3] = part->Vt() + spillTime;
    TLorentzVector pos(vtx[0], vtx[1], vtx[2], vtx[3]);
    TLorentzVector mom(part->Px(), part->Py(), part->Pz(), part->E());
    if(part->PolzIsSet()) {
        TVector3 polz;
        part->GetPolarization(polz);
        tpart.SetPolarization(polz);
      }
    }

     // Is this vertex already in our map?
    G4PrimaryVertex* vertex = 0;
    std::map< CLHEP::HepLorentzVector, G4PrimaryVertex* >::const_iterator result = vertexMap.find( fourpos );
    if ( result == vertexMap.end() ){
141
          // No, it's not, so create a new vertex and add it to the
142
          // map.
143
          vertex = new G4PrimaryVertex(x, y, z, t);
144
          vertexMap[ fourpos ] = vertex;
145
146
          // Add the vertex to the G4Event.
147
          event->AddPrimaryVertex( vertex );
148
        }
149
        else{
150
          // Yes, it is, so use the existing vertex.
151
          vertex = (*result).second;
152
        }
                // Get additional particle information.
155
        TLorentzVector momentum = particle.Momentum(); // (px,py,pz,E)
156
        TVector3 polarization = particle.Polarization();
157

158
        // Get the particle table if necessary.  (Note: we're
159
        // doing this "late" because I'm not sure at what point
160
        // the G4 particle table is initialized in the loading process.
161
        if ( fParticleTable == 0 ){
162
          fParticleTable = G4ParticleTable::GetParticleTable();
163
        }
164
165
        if ( pdgCode > 1000000000 )
166
          LOG_DEBUG("ConvertPrimaryToGeant4") << ": %%% Nuclear PDG code = " << pdgCode
167
                                              << " (x,y,z,t)=(" << x
168
                                              << "," << y
169
                                              << "," << z
170
                                              << "," << t << ")"
171
                                              << " P=" << momentum.P()
172
                                              << ", E=" << momentum.E();
173
174
        // Get Geant4's definition of the particle.
175
        G4ParticleDefinition* particleDefinition;
176

177
        if(pdgCode==0){
178
          particleDefinition = fParticleTable->FindParticle("opticalphoton");
179
        }
180
        else
181
          particleDefinition = fParticleTable->FindParticle(pdgCode);
182
183
        // What if the PDG code is unknown?  This has been a known
184
        // issue with GENIE.
185
        if ( particleDefinition == 0 ){
186
          LOG_DEBUG("ConvertPrimaryToGeant4") << ": %%% Code not found = " << pdgCode;
187
          fUnknownPDG[ pdgCode ] += 1;
188
          continue;
189
        }
190

191
        // Create a Geant4 particle to add to the vertex.
192
        G4PrimaryParticle* g4particle = new G4PrimaryParticle( particleDefinition,
193
                                                               momentum.Px() * CLHEP::GeV,
194
                                                               momentum.Py() * CLHEP::GeV,
195
                                                               momentum.Pz() * CLHEP::GeV);
196
197

        // Add more particle information the Geant4 particle.
198
        G4double charge = particleDefinition->GetPDGCharge();
199
        g4particle->SetCharge( charge );
200
        g4particle->SetPolarization( polarization.x(),
201
                                     polarization.y(),
202
                                     polarization.z() );
203

204
        // Add the particle to the vertex.
205
        vertex->SetPrimary( g4particle );
206
207
        // Create a PrimaryParticleInformation object, and save
208
        // the MCTruth pointer in it.  This will allow the
209
        // ParticleActionList class to access MCTruth
210
        // information during Geant4's tracking.
211
        PrimaryParticleInformation* primaryParticleInfo = new PrimaryParticleInformation;
212
        primaryParticleInfo->SetMCTruth( mct, index );
213

214
        // Save the PrimaryParticleInformation in the
215
        // G4PrimaryParticle for access during tracking.
216
        g4particle->SetUserInformation( primaryParticleInfo );
217
218

  }*/
}<|endoftext|>


<commit_before>//===- lib/ReaderWriter/MachO/ExecutableAtoms.hpp -------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
#define LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H

#include "Atoms.h"

#include "llvm/Support/MachO.h"

#include "lld/Core/ArchiveLibraryFile.h"
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/File.h"
#include "lld/Core/LinkingContext.h"
#include "lld/Core/Reference.h"
#include "lld/Core/Simple.h"
#include "lld/Core/UndefinedAtom.h"
#include "lld/ReaderWriter/MachOLinkingContext.h"

namespace lld {
namespace mach_o {

//
// CEntryFile adds an UndefinedAtom for "_main" so that the Resolving
// phase will fail if "_main" is undefined.
//
class CEntryFile : public SimpleFile {
public:
  CEntryFile(const MachOLinkingContext &context)
      : SimpleFile("C entry"),
       _undefMain(*this, context.entrySymbolName()) {
    this->addAtom(_undefMain);
  }

private:
  SimpleUndefinedAtom   _undefMain;
};

//
// StubHelperFile adds an UndefinedAtom for "dyld_stub_binder" so that
// the Resolveing phase will fail if "dyld_stub_binder" is undefined.
//
class StubHelperFile : public SimpleFile {
public:
  StubHelperFile(const MachOLinkingContext &context)
      : SimpleFile("stub runtime"),
        _undefBinder(*this, context.binderSymbolName()) {
    this->addAtom(_undefBinder);
  }

private:
  SimpleUndefinedAtom   _undefBinder;
};

//
// MachHeaderAliasFile lazily instantiates the magic symbols that mark the start
// of the mach_header for final linked images.
//
class MachHeaderAliasFile : public ArchiveLibraryFile {
public:
  MachHeaderAliasFile(const MachOLinkingContext &context)
      : ArchiveLibraryFile("mach_header symbols") {
      switch (context.outputMachOType()) {
      case llvm::MachO::MH_EXECUTE:
        _machHeaderSymbolName = "__mh_execute_header";
        break;
      case llvm::MachO::MH_DYLIB:
        _machHeaderSymbolName = "__mh_dylib_header";
        break;
      case llvm::MachO::MH_BUNDLE:
        _machHeaderSymbolName = "__mh_bundle_header";
        break;
      case llvm::MachO::MH_DYLINKER:
        _machHeaderSymbolName = "__mh_dylinker_header";
        break;
      case llvm::MachO::MH_PRELOAD:
        _machHeaderSymbolName = "__mh_preload_header";
        break;
      default:
        llvm_unreachable("no mach_header symbol for file type");
      }
  }

  std::error_code
  parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
    return std::error_code();
  }

  const File *find(StringRef sym, bool dataSymbolOnly) const override {
    if (sym.equals("___dso_handle") || sym.equals(_machHeaderSymbolName)) {
      _definedAtoms._atoms.push_back(new (_alloc) MachODefinedAtom(
          *this, sym, DefinedAtom::scopeLinkageUnit,
          DefinedAtom::typeMachHeader, DefinedAtom::mergeNo, false, false,
          ArrayRef<uint8_t>(), DefinedAtom::Alignment(12,0)));
      return this;
    }
    return nullptr;
  }

  const atom_collection<DefinedAtom> &defined() const override {
    return _definedAtoms;
  }
  const atom_collection<UndefinedAtom> &undefined() const override {
    return _undefinedAtoms;
  }

  const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
    return _sharedLibraryAtoms;
  }

  const atom_collection<AbsoluteAtom> &absolute() const override {
    return _absoluteAtoms;
  }

private:
  mutable atom_collection_vector<DefinedAtom> _definedAtoms;
  atom_collection_vector<UndefinedAtom> _undefinedAtoms;
  atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
  atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
  StringRef _machHeaderSymbolName;
  mutable llvm::BumpPtrAllocator _alloc;
};

} // namespace mach_o
} // namespace lld

#endif // LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
<commit_msg>[Mach-O] Remove redundant allocator<commit_after>//===- lib/ReaderWriter/MachO/ExecutableAtoms.hpp -------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
#define LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H

#include "Atoms.h"

#include "llvm/Support/MachO.h"

#include "lld/Core/ArchiveLibraryFile.h"
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/File.h"
#include "lld/Core/LinkingContext.h"
#include "lld/Core/Reference.h"
#include "lld/Core/Simple.h"
#include "lld/Core/UndefinedAtom.h"
#include "lld/ReaderWriter/MachOLinkingContext.h"

namespace lld {
namespace mach_o {

//
// CEntryFile adds an UndefinedAtom for "_main" so that the Resolving
// phase will fail if "_main" is undefined.
//
class CEntryFile : public SimpleFile {
public:
  CEntryFile(const MachOLinkingContext &context)
      : SimpleFile("C entry"),
       _undefMain(*this, context.entrySymbolName()) {
    this->addAtom(_undefMain);
  }

private:
  SimpleUndefinedAtom   _undefMain;
};

//
// StubHelperFile adds an UndefinedAtom for "dyld_stub_binder" so that
// the Resolveing phase will fail if "dyld_stub_binder" is undefined.
//
class StubHelperFile : public SimpleFile {
public:
  StubHelperFile(const MachOLinkingContext &context)
      : SimpleFile("stub runtime"),
        _undefBinder(*this, context.binderSymbolName()) {
    this->addAtom(_undefBinder);
  }

private:
  SimpleUndefinedAtom   _undefBinder;
};

//
// MachHeaderAliasFile lazily instantiates the magic symbols that mark the start
// of the mach_header for final linked images.
//
class MachHeaderAliasFile : public ArchiveLibraryFile {
public:
  MachHeaderAliasFile(const MachOLinkingContext &context)
      : ArchiveLibraryFile("mach_header symbols") {
      switch (context.outputMachOType()) {
      case llvm::MachO::MH_EXECUTE:
        _machHeaderSymbolName = "__mh_execute_header";
        break;
      case llvm::MachO::MH_DYLIB:
        _machHeaderSymbolName = "__mh_dylib_header";
        break;
      case llvm::MachO::MH_BUNDLE:
        _machHeaderSymbolName = "__mh_bundle_header";
        break;
      case llvm::MachO::MH_DYLINKER:
        _machHeaderSymbolName = "__mh_dylinker_header";
        break;
      case llvm::MachO::MH_PRELOAD:
        _machHeaderSymbolName = "__mh_preload_header";
        break;
      default:
        llvm_unreachable("no mach_header symbol for file type");
      }
  }

  std::error_code
  parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
    return std::error_code();
  }

  const File *find(StringRef sym, bool dataSymbolOnly) const override {
    if (sym.equals("___dso_handle") || sym.equals(_machHeaderSymbolName)) {
      _definedAtoms._atoms.push_back(new (allocator()) MachODefinedAtom(
          *this, sym, DefinedAtom::scopeLinkageUnit,
          DefinedAtom::typeMachHeader, DefinedAtom::mergeNo, false, false,
          ArrayRef<uint8_t>(), DefinedAtom::Alignment(12,0)));
      return this;
    }
    return nullptr;
  }

  const atom_collection<DefinedAtom> &defined() const override {
    return _definedAtoms;
  }
  const atom_collection<UndefinedAtom> &undefined() const override {
    return _undefinedAtoms;
  }

  const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
    return _sharedLibraryAtoms;
  }

  const atom_collection<AbsoluteAtom> &absolute() const override {
    return _absoluteAtoms;
  }

private:
  mutable atom_collection_vector<DefinedAtom> _definedAtoms;
  atom_collection_vector<UndefinedAtom> _undefinedAtoms;
  atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
  atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
  StringRef _machHeaderSymbolName;
};

} // namespace mach_o
} // namespace lld

#endif // LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
<|endoftext|>