text: //    |  /           |
  //    ' /   __| _` | __|  _ \   __|
  //    . \  |   (   | |   (   |\__ `
  //   _|\_\_|  \__,_|\__|\___/ ____/
  //                   Multi-Physics
  //
  //  License:		 BSD License
  //					 Kratos default license: kratos/license.txt
  //
  //  Main authors:    Inigo Lopez and Riccardo Rossi
  //
  
  #ifndef KRATOS_POTENTIAL_WALL_CONDITION_H
  #define KRATOS_POTENTIAL_WALL_CONDITION_H
  
  // System includes
  #include <string>
  #include <iostream>
  
  #include "includes/kratos_flags.h"
  #include "includes/deprecated_variables.h"
  
  // External includes
  
  // Project includes
  #include "includes/define.h"
  #include "includes/serializer.h"
  #include "includes/condition.h"
  #include "includes/process_info.h"
  #include "includes/cfd_variables.h"
  
  // Application includes
  #include "compressible_potential_flow_application_variables.h"
  
  namespace Kratos
  {
  ///@addtogroup FluidDynamicsApplication
  ///@{
  
  ///@name Kratos Globals
  ///@{
  
  ///@}
  ///@name Type Definitions
  ///@{
  
  ///@}
  ///@name  Enum's
  ///@{
  
  ///@}
  ///@name  Functions
  ///@{
  
  ///@}
  ///@name Kratos Classes
  ///@{
  
  /// Implements a wall condition for the potential flow formulation
  template <unsigned int TDim, unsigned int TNumNodes = TDim>
  class KRATOS_API(COMPRESSIBLE_POTENTIAL_FLOW_APPLICATION) PotentialWallCondition : public Condition
  {
  public:
      ///@name Type Definitions
      ///@{
  
      /// Pointer definition of PotentialWallCondition
      KRATOS_CLASS_INTRUSIVE_POINTER_DEFINITION(PotentialWallCondition);
  
      static constexpr int NumNodes = TNumNodes;
      static constexpr int Dim = TDim;
  
      typedef Node<3> NodeType;
  
      typedef Properties PropertiesType;
  
      typedef Geometry<NodeType> GeometryType;
  
      typedef Geometry<NodeType>::PointsArrayType NodesArrayType;
  
      typedef Vector VectorType;
  
      typedef Matrix MatrixType;
  
      typedef std::size_t IndexType;
  
      typedef std::size_t SizeType;
  
      typedef std::vector<std::size_t> EquationIdVectorType;
  
      typedef std::vector<Dof<double>::Pointer> DofsVectorType;
  
      typedef PointerVectorSet<Dof<double>, IndexedObject> DofsArrayType;
  
      typedef Element::WeakPointer ElementWeakPointerType;
  
      typedef Element::Pointer ElementPointerType;
  
      ///@}
      ///@name Life Cycle
      ///@{
  
      /// Default constructor.
      /** Admits an Id as a parameter.
        @param NewId Index for the new condition
        */
      explicit PotentialWallCondition(IndexType NewId = 0) : Condition(NewId)
      {
      }
  
      /// Constructor using an array of nodes
      /**
       @param NewId Index of the new condition
       @param ThisNodes An array containing the nodes of the new condition
       */
      PotentialWallCondition(IndexType NewId, const NodesArrayType& ThisNodes)
          : Condition(NewId, ThisNodes)
      {
      }
  
      /// Constructor using Geometry
      /**
       @param NewId Index of the new condition
       @param pGeometry Pointer to a geometry object
       */
      PotentialWallCondition(IndexType NewId, GeometryType::Pointer pGeometry)
          : Condition(NewId, pGeometry)
      {
      }
  
      /// Constructor using Properties
      /**
       @param NewId Index of the new element
       @param pGeometry Pointer to a geometry object
       @param pProperties Pointer to the element's properties
       */
      PotentialWallCondition(IndexType NewId,
                             GeometryType::Pointer pGeometry,
                             PropertiesType::Pointer pProperties)
          : Condition(NewId, pGeometry, pProperties)
      {
      }
  
      /// Copy constructor
      PotentialWallCondition(PotentialWallCondition const& rOther) = delete;
  
      /// Move constructor
      PotentialWallCondition(PotentialWallCondition&& rOther) = delete;
  
      /// Destructor.
      ~PotentialWallCondition() override
      {
      }
  
      ///@}
      ///@name Operators
      ///@{
  
      /// Assignment operator.
      PotentialWallCondition& operator=(PotentialWallCondition const& rOther)
      {
          Condition::operator=(rOther);
          return *this;
      }
  
      /// Move operator.
      PotentialWallCondition& operator=(PotentialWallCondition&& rOther)
      {
          Condition::operator=(rOther);
          return *this;
      }
  
      ///@}
      ///@name Operations
      ///@{
  
      Condition::Pointer Create(IndexType NewId,
                                NodesArrayType const& ThisNodes,
                                PropertiesType::Pointer pProperties) const override;
  
      Condition::Pointer Create(IndexType NewId,
                                Condition::GeometryType::Pointer pGeom,
                                PropertiesType::Pointer pProperties) const override;
  
      Condition::Pointer Clone(IndexType NewId, NodesArrayType const& rThisNodes) const override;
  
      // Find the condition's parent element.
      void Initialize(const ProcessInfo& rCurrentProcessInfo) override;
  
      void CalculateLeftHandSide(MatrixType& rLeftHandSideMatrix,
                                 const ProcessInfo& rCurrentProcessInfo) override;
  
      void CalculateRightHandSide(VectorType& rRightHandSideVector,
                                 const ProcessInfo& rCurrentProcessInfo) override;
  
      void CalculateLocalSystem(MatrixType& rLeftHandSideMatrix,
                                VectorType& rRightHandSideVector,
                                const ProcessInfo& rCurrentProcessInfo) override;
  
      void EquationIdVector(EquationIdVectorType& rResult,
                            const ProcessInfo& rCurrentProcessInfo) const override;
  
      void GetDofList(DofsVectorType& ConditionDofList, const ProcessInfo& CurrentProcessInfo) const override;
  
      void FinalizeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) override;
  
      ///@}
      ///@name Access
      ///@{
  
      ///@}
      ///@name Inquiry
      ///@{
  
      int Check(const ProcessInfo& rCurrentProcessInfo) override;
  
      ///@}
      ///@name Input and output
      ///@{
  
      /// Turn back information as a string.
      std::string Info() const override;
  
      /// Print information about this object.
      void PrintInfo(std::ostream& rOStream) const override;
  
      /// Print object's data.
      void PrintData(std::ostream& rOStream) const override;
  
      ///@}
      ///@name Friends
      ///@{
  
      ///@}
  
  protected:
      ///@name Protected static Member Variables
      ///@{
  
      ///@}
      ///@name Protected member Variables
      ///@{
  
      ///@}
      ///@name Protected Operators
      ///@{
  
      ///@}
      ///@name Protected Operations
      ///@{
  
      ///@}
      ///@name Protected  Access
      ///@{
  
      ///@}
      ///@name Protected Inquiry
      ///@{
  
      ///@}
      ///@name Protected LifeCycle
      ///@{
  
      ///@}
  
  private:
      ///@name Static Member Variables
      ///@{
  
      ///@}
      ///@name Member Variables
      ///@{
  
      bool mInitializeWasPerformed = false;
  
      GlobalPointer<Element> mpElement;
  
      void CalculateNormal2D(array_1d<double, 3>& An) const;
  
      void CalculateNormal3D(array_1d<double, 3>& An) const;
  
      ///@}
      ///@name Serialization
      ///@{
  
      friend class Serializer;
  
      void save(Serializer& rSerializer) const override;
  
      void load(Serializer& rSerializer) override;
  
      ///@}
      ///@name Private Operators
      ///@{
  
      inline GlobalPointer<Element> pGetElement() const;
  
      void GetElementCandidates(GlobalPointersVector<Element>& ElementCandidates,
                                const GeometryType& rGeom) const;
  
      void GetSortedIds(std::vector<IndexType>& Ids, const GeometryType& rGeom) const;
  
      void FindParentElement(std::vector<IndexType>& NodeIds,
                             std::vector<IndexType>& ElementNodeIds,
                             GlobalPointersVector<Element> ElementCandidates);
  
      ///@}
      ///@name Private Operations
      ///@{
  
      ///@}
      ///@name Private  Access
      ///@{
  
      ///@}
      ///@name Private Inquiry
      ///@{
  
      ///@}
      ///@name Un accessible methods
      ///@{
  
      ///@}
  
  }; // Class PotentialWallCondition
  
  ///@}
  
  ///@name Type Definitions
  ///@{
  
  ///@}
  ///@name Input and output
  ///@{
  
  /// input stream function
  template <unsigned int TDim, unsigned int TNumNodes>
  inline std::istream& operator>>(std::istream& rIStream,
                                  PotentialWallCondition<TDim, TNumNodes>& rThis)
  {
      return rIStream;
  }
  
  /// output stream function
  template <unsigned int TDim, unsigned int TNumNodes>
  inline std::ostream& operator<<(std::ostream& rOStream,
                                  const PotentialWallCondition<TDim, TNumNodes>& rThis)
  {
      rThis.PrintInfo(rOStream);
      rOStream << std::endl;
      rThis.PrintData(rOStream);
  
      return rOStream;
  }
  
  ///@}
  
  ///@} addtogroup block
  
  } // namespace Kratos.
  
  #endif // KRATOS_POTENTIAL_WALL_CONDITION_H
  