// JL20170612: TO BE FINISHED/REVISED
// WG3d_Tetra.h
// This file will be expanded as we develop more weak Galerkin finite elements 
// James Liu, Graham Harper, ColoState; 2014/07--2017/07

#include "matrix.h"
#include "vector.h"

#include "cell3d.h"
#include "GaussQuad.h"
#include "mat3.h"
#include "PtVec3d.h"
#include "TetraMesh.h"


////////////////////////////////////////////////////////////////////////////////
// For WG3d: Tetra(P0,P0;RT0):
////////////////////////////////////////////////////////////////////////////////

// WG3d: Tetra(P0,P0;RT0): Coeffs. of disc.wk.grad. in RT0 nmlz.bas. (5-by-4)

int WG3d_TetraP0P0RT0_CofDiscWkGrad_NmlzBas(FullMatrix &CDWG, const Tetra &tetra,
                                            Tri3d STF[4], int sign[4],
                                            const GaussQuad &GQTe);


// WG3d: Tetra(P0,P0;RT0): Element grad-grad matrix (5-by-5)
// with diffusion/permeability (3x3) matrix MatK

int WG3d_TetraP0P0RT0_EltGradGradMatK(FullMatrix &EGGMK, const Tetra &tetra,
                                      Tri3d STF[4], int sign[4],
                                      Mat3 &MatK, const GaussQuad &GQTe);


// WG3d: Tetra(P0,P0;RT0): Mixed product of disc.wk.grad. & bas.fxn.val.
// with another vector-valued function, e.g., velocity

int WG3d_TetraP0P0RT0_EltMatGradVal(FullMatrix &EGV,
                                    PtVec3d (*fxnVec)(const PtVec3d &),
                                    const Tetra &tetra, Tri3d STF[4], int sign[4],
                                    const GaussQuad &GQTe);

// WG3d: Tetra(P0,P0;RT0):
// Projecting a spatial scalar function to WG(P0,P0) on a tetrahedral mesh

int WG3d_TetraP0P0RT0_ProjScaFxn0(Vector &ProjScaEm, Vector &ProjScaFc,
                                  double (*fxnSca)(const PtVec3d&),
                                  const TetraMesh &mesh,
                                  const GaussQuad &GQTe, const GaussQuad &GQT);

////////////////////////////////////////////////////////////////////////////////
// JL20160826: TO BE FINISHED/REVISED
// For WG3d: Tetra(P1,P0;P0^3) with stabilizer
////////////////////////////////////////////////////////////////////////////////

// WG3d: Tetra(P1,P0;P03): Coeffs. of disc.wk.grad. in P_0^3 nat.bas. (8-by-3)

FullMatrix WG3d_TetraP1P0P03_CofDiscWkGrad_NatBas(const Tetra &tetra,
                                                  Tri3d STF[4], int sign[4],
                                                  const GaussQuad &GQTe,
                                                  const GaussQuad &GQT);


// WG3d: Tetra(P1,P0;P0^3): Element grad-grad matrix (8-by-8)

FullMatrix WG3d_TetraP1P0P03_EltGradGradMatK(const Tetra &tetra, Mat3 &MatK,
                                             Tri3d STF[4], int sign[4],
                                             const GaussQuad &GQTe,
                                             const GaussQuad &GQT);


// WG3d: Tetra(P1,P0;P0^3): Elementwise stabilizer matrix (8-by-8)

FullMatrix WG3d_TetraP1P0P03_EltStabMat(const Tetra &tetra,
                                        Tri3d STF[4], int sign[4],
                                        const GaussQuad &GQTe,
                                        const GaussQuad &GQT);


////////////////////////////////////////////////////////////////////////////////
// For WG(P0^3,P0^3;RT0^3,P0) for elasticity
////////////////////////////////////////////////////////////////////////////////

// WG3d: Tetra(P0^3,P0^3;RT0^3,P0):
// Coeff. of disc.wk.grad. in RT0^3 nmlz.bas. for 15 WG bas.fxns
// 15-by-12 matrix

FullMatrix WG3d_TetraP03P03RT03P0_CofNmlzBas_DiscWkGradBasFxn(
  const Tetra &tetra, Tri3d STF[4], int sign[4],
  const GaussQuad &GQTe, const GaussQuad &GQT);


// WG3d: Tetra(P0^3,P0^3;RT0^3,P0):
// Coeff. of disc.wk.div. in P0 nmlz.bas. for 15 WG bas.fxns
// 15-dim vector

Vector WG3d_TetraP03P03RT03P0_CofNmlzBas_DiscWkDivBasFxn(
  const Tetra &tetra, Tri3d STF[4], int sign[4],
  const GaussQuad &GQTe, const GaussQuad &GQT);


// WG3d: Tetra(P0^3,P0^3;RT0^3,P0):
// Elementwise discrete weak div-div matrix

FullMatrix WG3d_TetraP03P03RT03P0_NmlBas_EltDivDivMat(
  const Tetra &tetra, Tri3d STF[4], int sign[4],
  const GaussQuad &GQTe, const GaussQuad &GQT);


// WG3d: Tetra(P0^3,P0^3;RT0^3,P0):
// Elementwise discrete weak grad-grad matrix

FullMatrix WG3d_TetraP03P03RT03P0_NmlBas_EltGradGradMat(
  const Tetra &tetra, Tri3d STF[4], int sign[4],
  const GaussQuad &GQTe, const GaussQuad &GQT);


// WG3d: Tetra(P0^3,P0^3;RT0^3,P0):
// Elementwise discrete weak strain-strain matrix

FullMatrix WG3d_TetraP03P03RT03P0_NmlBas_EltStrnStrnMat(
  const Tetra &tetra, Tri3d STF[4], int sign[4],
  const GaussQuad &GQTe, const GaussQuad &GQT);

// WG3d_Tetra.h
