/*
#@HEADER
# ************************************************************************
#
#                          Moertel FE Package
#                 Copyright (2006) Sandia Corporation
#
# Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
# license for use of this work by or on behalf of the U.S. Government.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the Corporation nor the names of the
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
# 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.
#
# Questions? Contact Glen Hansen (gahanse@sandia.gov)
#
# ************************************************************************
#@HEADER
*/
/* ******************************************************************** */
/* See the file COPYRIGHT for a complete copyright notice, contact      */
/* person and disclaimer.                                               */
/* ******************************************************************** */
/*!
 * \file mrtr_segment.H
 *
 * \class MOERTEL::Segment
 *
 * \brief A virtual class to serve as base class for different types of interface segmentsconstruct a single interface
 *
 * \date Last update to Doxygen: 15-Dec-05
 *
 */
#ifndef MOERTEL_SEGMENT_H
#define MOERTEL_SEGMENT_H

#include <ctime>
#include <iostream>
#include <map>
#include <vector>

#include "Teuchos_RefCountPtr.hpp"
#include "mrtr_function.H"

/*!
\brief MOERTEL: namespace of the Moertel package

The Moertel package depends on \ref Epetra, \ref EpetraExt, \ref Teuchos,
\ref Amesos, \ref ML and \ref AztecOO:<br>
Use at least the following lines in the configure of Trilinos:<br>
\code
--enable-moertel 
--enable-epetra 
--enable-epetraext
--enable-teuchos 
--enable-ml
--enable-aztecoo --enable-aztecoo-teuchos 
--enable-amesos
\endcode

*/
namespace MOERTEL
{

class Interface;
class Node;

/*!
\class Segment

\brief <b> A virtual class as a basis for different types of interface segments</b>

This class serves as a (not pure) virtual base class to several types of interface segments.

The \ref MOERTEL::Segment class supports the ostream& operator <<

\author Glen Hansen (gahanse@sandia.gov)

*/
class Segment 
{
public:
  
  /*!
  \brief Type of segment
         
   \param seg_none : default value
   \param seg_Linear1D : linear 1D segment with 2 nodes
   \param seg_BiLinearQuad : linear 2D triangle with 3 nodes
   \param seg_BiLinearTri : linear 2D quadrilateral with 4 nodes
  */
  enum SegmentType 
  {
    seg_none,
    seg_Linear1D,
    seg_BiLinearQuad,
    seg_BiLinearTri
  };


  // @{ \name Constructors and destructors

  /*!
  \brief Standard Constructor
  
  \param Id : A unique positive Segment id. Does not need to be continous among segments
  \param nnode : Number of nodes this segment is attached to
  \param nodeId : Pointer to vector length nnode holding unique positive 
                  node ids of nodes this segment is attached to
  \param outlevel : Level of output to stdout to be generated by this class (0-10)
  */
  Segment(int id, int nnode, int* nodeId, int outlevel);
  
  /*!
  \brief Empty Constructor

  This constructor is used together with \ref Pack and \ref UnPack for
  communicating segments
  
  \param outlevel : Level of output to stdout to be generated by this class (0-10)
  */
  Segment(int outlevel);
  
  /*!
  \brief Copy Constructor

  Makes a deep copy of a Segment
  
  */
  Segment(MOERTEL::Segment& old);
  
  /*!
  \brief Destructor

  */
  virtual ~Segment();
  
  //@}

  // @{ \name Methods implemented by this class

  /*!
  \brief Return level of output to be generated by this class (0-10)

  */
  int OutLevel() { return outputlevel_; }
  
  /*!
  \brief Return unique id of this Segment

  */
  int Id() const { return Id_; }
  
  /*!
  \brief Return number of nodes attached to this Segment

  */
  int Nnode() const { return nodeId_.size(); }
  
  /*!
  \brief Return type of Segment

  */
  MOERTEL::Segment::SegmentType Type() const { return stype_; }
  
  /*!
  \brief Return view of node ids of nodes attached to this Segment

  */
  const int* NodeIds() const { return &(nodeId_[0]); }
  
  /*!
  \brief Return pointer to vector of length \ref Nnode() of 
   pointers to Nodes attached to this Segment

  */
  MOERTEL::Node** Nodes() { return &(nodeptr_[0]); }
  
  /*!
  \brief Return number of functions defined on this Segment

  */
  int Nfunctions() { return functions_.size(); }
  
  /*!
  \brief Return FunctionType of a function with the Id id

  \param id : function id to lookup the type for
  */
  MOERTEL::Function::FunctionType FunctionType(int id);
  
  /*!
  \brief Attach a function to this Segment
  
  Will attach a function to this Segment under the function Id id.
  Segment will not take ownership of func but will store a deep copy

  \param id : unique function id to store function
  \param func : Function to store in this Segment
  */
  bool SetFunction(int id, MOERTEL::Function* func);

  /*!
  \brief Evaluate a function with a certain id
  
  Will evaluate the function with Id id at a given local coordinate

  \param id (in): unique function id 
  \param xi (in): Segment local coordinates where to evaluate the function
  \param val (out): Vector holding function values at xi on output. If NULL on input, 
                    function will not evaluate values.
  \param valdim (in): length of val
  \param deriv (out): Vector holding function derivatives at xi on output, 
                      should be of length 2*valdim in most cases. If NULL on input, 
                      function will not evaluate derivatives.
  */
  bool EvaluateFunction(int id, const double* xi, double* val, int valdim, double* deriv);
  
  /*!
  \brief Build normal at a node adjacent to this Segment
  
  \param nid : global unique node id
  */
  double* BuildNormalAtNode(int nid);
  
  /*!
  \brief Get pointers to Nodes attached to this Segment from the Interface this Segment resides on
  
  */
  bool GetPtrstoNodes(MOERTEL::Interface& interface);

  /*!
  \brief Get pointers to Nodes attached to this Segment from a vector of Node pointers
  
  */
  bool GetPtrstoNodes(std::vector<MOERTEL::Node*>& nodes);

  /*!
  \brief Print this Segment
  
  */
  virtual bool Print() const;
  
  /*!
  \brief Get segment-local node id from global node id nid
  
  */
  int GetLocalNodeId(int nid);

  //@}
  // @{ \name Pure virtual methods of this class

  /*!
  \brief Deep copy the derived class and return pointer to it
  
  */
  virtual MOERTEL::Segment* Clone() = 0;

  /*!
  \brief Pack some data from this class to an int vector of length size so
         it can be communicated using MPI
  
  */
  virtual int* Pack(int* size) = 0;
  
  /*!
  \brief Unpack some data an int vector and store data in this class
  
  */
  virtual bool UnPack(int* pack) = 0;
  
  /*!
  \brief Build an outward normal at segment coordinates xi
  
  */
  virtual double* BuildNormal(double* xi) = 0;
  
  /*!
  \brief Compute and return the area of this Segment
  
  */
  virtual double Area() = 0;

  /*!
  \brief Build the basis vectors and metric tensor at a given local coord in this segment
  
  */
  virtual double Metric(double* xi, double g[], double G[][3]) = 0;

  /*!
  \brief Get local coords of a node attached to this segment with \b local node Id lid 
  
  */
  virtual bool LocalCoordinatesOfNode(int lid, double* xi) = 0;

  //@}

protected:

  int                                       Id_;         // this segments unique id
  int                                       outputlevel_;
  std::vector<int>                               nodeId_;     // vector of unique node ids 
  std::vector<MOERTEL::Node*>                    nodeptr_;    // vector with ptrs to nodes adj to me

  SegmentType                               stype_;      // segment type
  std::map< int,Teuchos::RCP<MOERTEL::Function> > functions_;  // functions that live on this segment

};

} // namespace MOERTEL

// << operator
std::ostream& operator << (std::ostream& os, const MOERTEL::Segment& seg);

#endif // MOERTEL_SEGMENT_H
