/*  DESCRIPTOR Boltzmann sample, written in C++, using the OpenLB
 *  library
 *
 *  Copyright (C) 2006-2016 Thomas Henn, Fabian Klemens, Robn Trunk, Davide Dapelo
 *  E-mail contact: info@openlb.net
 *  The most recent release of OpenLB can be downloaded at
 *  
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public
 *  License along with this program; if not, write to the Free
 *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA  02110-1301, USA.
 */
#ifndef PARTICLEDYNAMICS_3D_H
#define PARTICLEDYNAMICS_3D_H
#include "core/superLattice3D.h"
#include "functors/analytical/indicator/smoothIndicatorBaseF3D.h"
namespace olb {
template
class ParticleDynamics3D {
private:
  SuperLattice3D& _sLattice;
  UnitConverter const& _converter;
  SuperGeometry3D& _superGeometry;
  std::shared_ptr > _indicatorF;
  std::vector* > _vectorOfIndicator;
  T _lengthX;
  T _lengthY;
  T _lengthZ;
  Vector _accExt;
  bool _escapeFromDomain=false;
  bool _oldWallCollision=true;
public:
  ParticleDynamics3D(SuperLattice3D& sLattice, 
                    UnitConverter const& converter,
                    SuperGeometry3D& superGeometry, 
                    T lengthX, T lengthY, T lengthZ, 
                    Vector accExt = Vector (0.,0.,0.))
    : _sLattice(sLattice), 
      _converter(converter),
      _superGeometry(superGeometry), 
      _lengthX(lengthX), 
      _lengthY(lengthY), 
      _lengthZ(lengthZ),
      _accExt(accExt) 
  {}
  ParticleDynamics3D(SuperLattice3D& sLattice,
		    UnitConverter const& converter,
                    SuperGeometry3D& superGeometry, 
                    std::shared_ptr > indicatorF,
		    bool escapeFromDomain, bool oldWallCollision=false,
                    Vector accExt = Vector (0.,0.,0.))
      : _sLattice(sLattice),
	_converter(converter),
        _superGeometry(superGeometry),
	_indicatorF(indicatorF),
        _accExt(accExt),
	_escapeFromDomain(escapeFromDomain),
        _oldWallCollision(oldWallCollision)
  {}
  void addCuboid(Vector< T, 3> center, T xLength, T yLength, T zLength, T mass, T epsilon, Vector< T, 3 > theta, Vector vel = Vector (0.,0.,0.));
  void addSphere(Vector< T, 3> center, T radius, T epsilon, T density, Vector vel = Vector (0.,0.,0.));
  void addParticle(SmoothIndicatorF3D& indicator);
  void computeBoundaryForce(std::vector* >& indicator);
  void addWallColl(SmoothIndicatorF3D& indicator, T delta);
  void verletIntegration(SmoothIndicatorF3D& indicator);
  void updateParticleDynamics(std::string name, SmoothIndicatorF3D& indicator);
  void checkAndRemoveEscaped();
  void addParticleField(SmoothIndicatorF3D& indicator);
  void simulateTimestep(std::string name);
  void print();
  void load(std::string filename, T epsilon);
  void save(std::string filename);
  void eulerIntegration(SmoothIndicatorF3D& indicator);
};
}
#endif