/* ----------------------------------------------------------------------
   LIGGGHTS - LAMMPS Improved for General Granular and Granular Heat
   Transfer Simulations

   LIGGGHTS is part of the CFDEMproject
   www.liggghts.com | www.cfdem.com

   This file was modified with respect to the release in LAMMPS
   Modifications are Copyright 2009-2012 JKU Linz
                     Copyright 2012-     DCS Computing GmbH, Linz

   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
   http://lammps.sandia.gov, Sandia National Laboratories
   Steve Plimpton, sjplimp@sandia.gov

   Copyright (2003) Sandia Corporation.  Under the terms of Contract
   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
   certain rights in this software.  This software is distributed under
   the GNU General Public License.

   See the README file in the top-level directory.
------------------------------------------------------------------------- */

#ifndef LMP_FORCE_H
#define LMP_FORCE_H

#include "pointers.h"
#include "property_registry.h"
#include <map>
#include <string>

namespace LAMMPS_NS {

class Force : protected Pointers {
 friend class Coarsegraining;

 public:
  double boltz;                      // Boltzmann constant (eng/degree-K)
  double hplanck;                    // Planck's constant (energy-time)
  double mvv2e;                      // conversion of mv^2 to energy
  double ftm2v;                      // conversion of ft/m to velocity
  double mv2d;                       // conversion of mass/volume to density
  double nktv2p;                     // conversion of NkT/V to pressure
  double qqr2e;                      // conversion of q^2/r to energy
  double qe2f;                       // conversion of qE to force
  double vxmu2f;                     // conversion of vx dynamic-visc to force
  double xxt2kmu;                    // conversion of xx/t to kinematic-visc
  double dielectric;                 // dielectric constant
  double qqrd2e;                     // q^2/r to energy w/ dielectric constant
  double e_mass;                     // electron mass
  double hhmrr2e;                    // conversion of (hbar)^2/(mr^2) to energy
  double mvh2r;                      // conversion of mv/hbar to distance
                                     // hbar = h/(2*pi)
  double angstrom;                   // 1 angstrom in native units
  double femtosecond;                // 1 femtosecond in native units
  double qelectron;                  // 1 electron charge abs() in native units

  int newton,newton_pair,newton_bond;   // Newton's 3rd law settings

  class Pair *pair;
  char *pair_style;

  typedef Pair *(*PairCreator)(LAMMPS *);
  std::map<std::string,PairCreator> *pair_map;

  class Bond *bond;
  char *bond_style;

  class Angle *angle;
  char *angle_style;

  class Dihedral *dihedral;
  char *dihedral_style;

  class Improper *improper;
  char *improper_style;

  class KSpace *kspace;
  char *kspace_style;
                             // index [0] is not used in these arrays
  double special_lj[4];      // 1-2, 1-3, 1-4 prefactors for LJ
  double special_coul[4];    // 1-2, 1-3, 1-4 prefactors for Coulombics
  int special_angle;         // 0 if defined angles are ignored
                             // 1 if only weight 1,3 atoms if in an angle
  int special_dihedral;      // 0 if defined dihedrals are ignored
                             // 1 if only weight 1,4 atoms if in a dihedral
  int special_extra;         // extra space for added bonds

  Force(class LAMMPS *);
  ~Force();
  void init();

  void create_pair(const char *, int & narg, char** & args, const char *suffix = NULL);
  void create_pair_from_restart(FILE* fp,const char *, const char *suffix = NULL);
  class Pair *new_pair(const char *, int & narg, char** & args, const char *, int &);
  class Pair *new_pair_from_restart(FILE* fp, const char *, const char *, int &);
  class Pair *new_granular_pair(int & narg, char ** & args);
  class Pair *new_granular_pair_from_restart(FILE * fp);

  class Fix* new_granular_wall_fix(int narg, char ** args);

  class Pair *pair_match(const char *, int);

  void create_bond(const char *, const char *suffix = NULL);
  class Bond *new_bond(const char *, const char *, int &);
  class Bond *bond_match(const char *);

  void create_angle(const char *, const char *suffix = NULL);
  class Angle *new_angle(const char *, const char *, int &);

  void create_dihedral(const char *, const char *suffix = NULL);
  class Dihedral *new_dihedral(const char *, const char *, int &);

  void create_improper(const char *, const char *suffix = NULL);
  class Improper *new_improper(const char *, const char *, int &);

  void create_kspace(int, char **, const char *suffix = NULL);
  class KSpace *new_kspace(int, char **, const char *, int &);
  class KSpace *kspace_match(const char *, int);

  void set_special(int, char **);
  void bounds(char *, int, int &, int &, int nmin=1);
  double numeric(const char *, int, char *);
  int inumeric(const char *, int, char *);
  bigint memory_usage();

  inline double cg() 
  { return coarsegraining; }

  inline bool cg_active() 
  { return (cg() > 1.); }

  inline bool error_cg() 
  { return error_coarsegraining; }

  PropertyRegistry registry;

 private:
  template <typename T> static Pair *pair_creator(LAMMPS *);

  double coarsegraining; 
  bool error_coarsegraining; 

  typedef class Pair*(*GranularPairCreator)(LAMMPS*);
  typedef class Fix*(*GranularWallFixCreator)(LAMMPS*,int,char**);
  std::map<int64_t, GranularPairCreator> granular_pair_style_creators;
  std::map<int64_t, GranularWallFixCreator> granular_wall_fix_creators;
  std::map<std::string, int> surface_model_map;
  std::map<std::string, int> normal_model_map;
  std::map<std::string, int> tangential_model_map;
  std::map<std::string, int> cohesion_model_map;
  std::map<std::string, int> rolling_model_map;

  int64_t select_contact_model(int & narg, char ** & args);

  template<int MODEL, int TANGENTIAL, int COHESION, int ROLLING, int SURFACE>
  void register_granular_pair_style();

  template<int MODEL, int TANGENTIAL, int COHESION, int ROLLING, int SURFACE>
  void register_granular_wall_fix();
};

class Pair;
class Fix;

template<typename T>
Pair * create_pair_style_instance(LAMMPS* lmp) {
  return new T(lmp);
}

template<typename T>
Fix * create_fix_instance(LAMMPS* lmp, int narg, char ** args) {
  return new T(lmp, narg, args);
}

}

#endif

/* ERROR/WARNING messages:

E: Invalid pair style

The choice of pair style is unknown.

E: Invalid bond style

The choice of bond style is unknown.

E: Invalid angle style

The choice of angle style is unknown.

E: Invalid dihedral style

The choice of dihedral style is unknown.

E: Invalid improper style

The choice of improper style is unknown.

E: Invalid kspace style

The choice of kspace style is unknown.

E: Illegal ... command

Self-explanatory.  Check the input script syntax and compare to the
documentation for the command.  You can use -echo screen as a
command-line option when running LAMMPS to see the offending line.

E: Numeric index is out of bounds

A command with an argument that specifies an integer or range of
integers is using a value that is less than 1 or greater than the
maximum allowed limit.

U: Expected floating point parameter in input script or data file

The quantity being read is an integer on non-numeric value.

U: Expected integer parameter in input script or data file

The quantity being read is a floating point or non-numeric value.

*/
