Exemplo n.º 1
0
// prepares the file catalogue and searches for given text
void Executive::PrepareCatalogue()
{
	bool IsRecursive = false;
	DataStore ds;
	FileManager Fm(path_, ds);
	Fm.addAllPatterns(Patterns_);
	Arguments::iterator argIter = std::find(Options_.begin(), Options_.end(), "/s");
	if (argIter != Options_.end())
	{
		IsRecursive = true;
	}
	Fm.search(IsRecursive);

	Display dp;
	dp.DisplayCatalogue(ds);

	argIter = std::find(Options_.begin(), Options_.end(), "/d");
	if (argIter != Options_.end())
	{
		dp.DisplayDuplicates(ds);
	}

	argIter = std::find(Options_.begin(), Options_.end(), "/f");
	if (argIter != Options_.end())
	{
		Fm.TextSearch(ds, searchText);
		dp.DisplaySearchFiles(ds, searchText);
	}

	DoSearch(Fm, ds, dp);
}
Exemplo n.º 2
0
// Right-hand side of the Lax-Wendroff discretization:
//
//      ( q(t+dt) - q(t) )/dt = -F_{x} - G_{y}.
//
// This routine constructs the 'time-integrated' flux functions F and G using the
// Cauchy-Kowalewski procedure.
//
// First, consider time derivatives of q
//
//    q^{n+1} = q^n + dt * (q^n_t + dt/2 * q^n_tt + dt^3/6 q^n_ttt ).
//
// Formally, these are given by
//
//   q_{t}    = ( -f(q) )_x + ( -g(q) )_y, 
//   q_{tt}   = ( f'(q) * ( f_x + g_y )_x + ( g'(q) * ( f_x + g_y )_y
//   q_{ttt}  = ...
//
// Now, considering Taylor expansions of f and g, centered about t = t^n
//
//  F = f^n + (t-t^n) \dot{f^n} + \cdots
//  G = g^n + (t-t^n) \dot{g^n} + \cdots
//
// We have the following form, after integrating in time
//
//  F: = ( f - dt/2 * ( f'(q)*( f_x+g_y ) 
//           + dt^2/6 ( \pd2{f}{q} \cdot (f_x+g_y,f_x+g_y) +
//                        \pd{f}{q} (  f_x + g_y )_t  ) + \cdots
//
//  G: = ( g - dt/2 * ( g'(q)*( f_x+g_y )
//           + dt^2/6 ( \pd2{g}{q} \cdot (f_x+g_y,f_x+g_y) +
//                        \pd{g}{q} (  f_x + g_y )_t ) + \cdots
//
// where the final ingredient is
//
//  (f_x+g_y)_t = \pd2{f}{q} \cdot (q_x, f_x+g_y ) + \pd{f}{q} ( f_xx + g_xy ) +
//                \pd2{g}{q} \cdot (q_y, f_x+g_y ) + \pd{g}{q} ( f_xy + g_yy ).
//
// At the end of the day, we set
//
//    L(q) := -F_x - G_y.
//
// See also: ConstructL.
void LaxWendroff(double dt, 
    const dTensorBC4& aux, const dTensorBC4& q,    // set bndy values modifies these
    dTensorBC4& Lstar, dTensorBC3& smax)
{

printf("This call hasn't been tested \n");

    if ( !dogParams.get_flux_term() )
    {  return;  }

    const edge_data& edgeData = Legendre2d::get_edgeData();
    const int space_order = dogParams.get_space_order();
    const int mx   = q.getsize(1);
    const int my   = q.getsize(2);
    const int meqn = q.getsize(3);
    const int kmax = q.getsize(4);
    const int mbc  = q.getmbc();
    const int maux = aux.getsize(3);

    // Flux values
    //
    // Space-order = number of quadrature points needed for 1D integration
    // along cell edges.
    //
    dTensorBC4 Fm(mx, my, meqn, space_order, mbc);
    dTensorBC4 Fp(mx, my, meqn, space_order, mbc);
    dTensorBC4 Gm(mx, my, meqn, space_order, mbc);
    dTensorBC4 Gp(mx, my, meqn, space_order, mbc);

    // Flux function
    void FluxFunc(const dTensor2& xpts,
                  const dTensor2& Q,
                  const dTensor2& Aux,
                  dTensor3& flux);

    // Jacobian of the flux function:
    void DFluxFunc(const dTensor2& xpts, 
                   const dTensor2& Q,
                   const dTensor2& Aux, 
                   dTensor4& Dflux );

    // Hessian of the flux function:
    void D2FluxFunc(const dTensor2& xpts, 
                   const dTensor2& Q,
                   const dTensor2& Aux, 
                   dTensor5& D2flux );


    // Riemann solver that relies on the fact that we already have 
    // f(ql) and f(qr) already computed:
    double RiemannSolveLxW(const dTensor1& nvec,
        const dTensor1& xedge,
        const dTensor1& Ql,   const dTensor1& Qr,
        const dTensor1& Auxl, const dTensor1& Auxr,
        const dTensor1& ffl,  const dTensor1& ffr,
        dTensor1& Fl, dTensor1& Fr);

    void LstarExtra(const dTensorBC4*,
            const dTensorBC4*,
            dTensorBC4*);
    void ArtificialViscosity(const dTensorBC4* aux, 
            const dTensorBC4* q, 
            dTensorBC4* Lstar);

    // Grid information
    const double xlower = dogParamsCart2.get_xlow();
    const double ylower = dogParamsCart2.get_ylow();
    const double dx = dogParamsCart2.get_dx();
    const double dy = dogParamsCart2.get_dy();

    // --------------------------------------------------------------------- //
    // Boundary data:
    // --------------------------------------------------------------------- //
    // TODO - call this routine before calling this function.
//  void SetBndValues(dTensorBC4& q, dTensorBC4& aux);
//  SetBndValues(q, aux);
    // ---------------------------------------------------------

    // --------------------------------------------------------------------- //
    // Part 0: Compute the Lax-Wendroff "flux" function:
    //
    // Here, we include the extra information about time derivatives.
    // --------------------------------------------------------------------- //
    dTensorBC4 F(mx, my, meqn, kmax, mbc);  F.setall(0.);
    dTensorBC4 G(mx, my, meqn, kmax, mbc);  G.setall(0.);
    void L2ProjectLxW( const int mterms, 
        const double alpha, const double beta_dt, const double charlie_dt,
        const int istart, const int iend, 
        const int jstart, const int jend,
        const int QuadOrder,
        const int BasisOrder_auxin,
        const int BasisOrder_fout,    
        const dTensorBC4* qin,
        const dTensorBC4* auxin,
        dTensorBC4* F,
        dTensorBC4* G,
        void FluxFunc (const dTensor2& xpts, 
            const dTensor2& Q, const dTensor2& Aux, dTensor3& flux),
        void DFluxFunc (const dTensor2& xpts, 
            const dTensor2& Q, const dTensor2& aux, dTensor4& Dflux),
        void D2FluxFunc (const dTensor2& xpts, 
            const dTensor2& Q, const dTensor2& aux, dTensor5& D2flux) );
printf("hello\n");
    L2ProjectLxW( 3, 1.0, 0.5*dt, dt*dt/6.0,
        1-mbc, mx+mbc, 1-mbc, my+mbc,
        space_order, space_order, space_order,
        &q, &aux, &F, &G, &FluxFunc, &DFluxFunc, D2FluxFunc );

    // ---------------------------------------------------------
    // Part I: compute source term
    // --------------------------------------------------------- 
    if( dogParams.get_source_term() > 0 )
    {
        // eprintf("error: have not implemented source term for LxW solver.");
        printf("Source term has not been implemented for LxW solver.  Terminating program.");
        exit(1);
    }
    Lstar.setall( 0. );

    // ---------------------------------------------------------
    // Part II: compute inter-element interaction fluxes
    //
    //   N = int( F(q,x,t) * phi_x, x ) / dA
    //
    // ---------------------------------------------------------

    // 1-direction: loop over interior edges and solve Riemann problems
    dTensor1 nvec(2);
    nvec.set(1, 1.0e0 );
    nvec.set(2, 0.0e0 );

#pragma omp parallel for
    for (int i=(2-mbc); i<=(mx+mbc); i++)
    {

        dTensor1 Ql(meqn),   Qr(meqn);
        dTensor1 ffl(meqn),  ffr(meqn);
        dTensor1 Fl(meqn),   Fr(meqn);
        dTensor1 DFl(meqn),  DFr(meqn);
        dTensor1 Auxl(maux), Auxr(maux);

        dTensor1 xedge(2);

        for (int j=(2-mbc); j<=(my+mbc-1); j++)
        {
            // ell indexes Riemann point along the edge
            for (int ell=1; ell<=space_order; ell++)
            {
                // Riemann data - q and f (from basis functions/q)
                for (int m=1; m<=meqn; m++)
                {
                    Ql.set (m, 0.0 );
                    Qr.set (m, 0.0 );
                    ffl.set(m, 0.0 );
                    ffr.set(m, 0.0 );

                    for (int k=1; k<=kmax; k++)
                    {
                        // phi_xl( xi=1.0, eta ), phi_xr( xi=-1.0, eta )
                        Ql.fetch(m)  += edgeData.phi_xl->get(ell,k)*q.get(i-1, j, m, k );
                        Qr.fetch(m)  += edgeData.phi_xr->get(ell,k)*q.get(i,   j, m, k );
                        ffl.fetch(m) += edgeData.phi_xl->get(ell,k)*F.get(i-1, j, m, k );
                        ffr.fetch(m) += edgeData.phi_xr->get(ell,k)*F.get(i,   j, m, k );
                    }

                }

                // Riemann data - aux
                for (int m=1; m<=maux; m++)
                {
                    Auxl.set(m, 0.0 );
                    Auxr.set(m, 0.0 );

                    for (int k=1; k<=kmax; k++)
                    {
                        Auxl.fetch(m) += edgeData.phi_xl->get(ell,k)*aux.get(i-1, j, m, k);
                        Auxr.fetch(m) += edgeData.phi_xr->get(ell,k)*aux.get(i,   j, m, k);
                    }
                }

                // Solve Riemann problem
                xedge.set(1, xlower + (double(i)-1.0)*dx );
                xedge.set(2, ylower + (double(j)-0.5)*dy );

                const double smax_edge = RiemannSolveLxW(
                    nvec, xedge, Ql, Qr, Auxl, Auxr, ffl, ffr, Fl, Fr);

                smax.set(i-1, j, 1, Max(dy*smax_edge,smax.get(i-1, j, 1)) );
                smax.set(i,   j, 1, Max(dy*smax_edge,smax.get(i,   j, 1)) );

                // Construct fluxes
                for (int m=1; m<=meqn; m++)
                {
                    Fm.set(i  , j, m, ell,  Fr.get(m) );
                    Fp.set(i-1, j, m, ell,  Fl.get(m) );
                }
            }
        }
    }


    // 2-direction: loop over interior edges and solve Riemann problems
    nvec.set(1, 0.0e0 );
    nvec.set(2, 1.0e0 );

#pragma omp parallel for
    for (int i=(2-mbc); i<=(mx+mbc-1); i++)
    {
        dTensor1  Ql(meqn),   Qr(meqn);
        dTensor1  Fl(meqn),   Fr(meqn);
        dTensor1 ffl(meqn),  ffr(meqn);
        dTensor1 Auxl(maux),Auxr(maux);
        dTensor1 xedge(2);

        for (int j=(2-mbc); j<=(my+mbc); j++)
        for (int ell=1; ell<=space_order; ell++)
        {
            // Riemann data - q
            for (int m=1; m<=meqn; m++)
            {

                Ql.set  (m, 0.0 );
                Qr.set  (m, 0.0 );
                ffl.set (m, 0.0 );
                ffr.set (m, 0.0 );

                for (int k=1; k<=kmax; k++)
                {
                    Ql.fetch(m)  += edgeData.phi_yl->get(ell, k)*q.get(i, j-1, m, k );
                    Qr.fetch(m)  += edgeData.phi_yr->get(ell, k)*q.get(i, j,   m, k );
                    ffl.fetch(m) += edgeData.phi_yl->get(ell, k)*G.get(i, j-1, m, k );
                    ffr.fetch(m) += edgeData.phi_yr->get(ell, k)*G.get(i,   j, m, k );
                }
            }

            // Riemann data - aux
            for (int m=1; m<=maux; m++)
            {
                Auxl.set(m, 0.0 );
                Auxr.set(m, 0.0 );

                for (int k=1; k<=kmax; k++)
                {
                    Auxl.fetch(m) += edgeData.phi_yl->get(ell,k)*aux.get(i,j-1,m,k);
                    Auxr.fetch(m) += edgeData.phi_yr->get(ell,k)*aux.get(i,j,m,k);
                }
            }

            // Solve Riemann problem
            xedge.set(1, xlower + (double(i)-0.5)*dx );
            xedge.set(2, ylower + (double(j)-1.0)*dy );

            const double smax_edge = RiemannSolveLxW(
                nvec, xedge, Ql, Qr, Auxl, Auxr, ffl, ffr, Fl, Fr);

            smax.set(i, j-1, 2,  Max(dx*smax_edge, smax.get(i, j-1, 2)) );
            smax.set(i, j,   2,  Max(dx*smax_edge, smax.get(i, j,   2)) );

            // Construct fluxes
            for (int m=1; m<=meqn; m++)
            {
                Gm.set(i, j,   m, ell, Fr.get(m) );
                Gp.set(i, j-1, m, ell, Fl.get(m) );
            }
        }
    }

    // Compute ``flux differences'' dF and dG    
    const double half_dx_inv = 0.5/dx;
    const double half_dy_inv = 0.5/dy;
    const int mlength = Lstar.getsize(3);   assert_eq( meqn, mlength );

    // Use the four values, Gm, Gp, Fm, Fp to construct the boundary integral:
#pragma omp parallel for
    for (int i=(2-mbc); i<=(mx+mbc-1); i++)    
    for (int j=(2-mbc); j<=(my+mbc-1); j++)
    for (int m=1; m<=mlength; m++)
    for (int k=1; k<=kmax; k++)
    {
        // 1-direction: dF
        double F1 = 0.0;
        double F2 = 0.0;
        for (int ell=1; ell<=space_order; ell++)
        {
            F1 = F1 + edgeData.wght_phi_xr->get(ell,k)*Fm.get(i,j,m,ell);
            F2 = F2 + edgeData.wght_phi_xl->get(ell,k)*Fp.get(i,j,m,ell);
        }

        // 2-direction: dG
        double G1 = 0.0;
        double G2 = 0.0;
        for (int ell=1; ell<=space_order; ell++)
        {
            G1 = G1 + edgeData.wght_phi_yr->get(ell,k)*Gm.get(i,j,m,ell);
            G2 = G2 + edgeData.wght_phi_yl->get(ell,k)*Gp.get(i,j,m,ell);
        }

        Lstar.fetch(i,j,m,k) -= (half_dx_inv*(F2-F1) + half_dy_inv*(G2-G1));

    }
    // ---------------------------------------------------------


    // ---------------------------------------------------------
    // Part III: compute intra-element contributions
    // ---------------------------------------------------------
    // No need to call this if first-order in space
    if(dogParams.get_space_order()>1)
    {

        dTensorBC4 Ltmp( mx, my, meqn, kmax, mbc );
        void L2ProjectGradAddLegendre(const int istart, 
                const int iend, 
                const int jstart, 
                const int jend,
                const int QuadOrder, 
                const dTensorBC4* F, 
                const dTensorBC4* G, 
                dTensorBC4* fout );
        L2ProjectGradAddLegendre( 1-mbc, mx+mbc, 1-mbc, my+mbc,
            space_order, &F, &G, &Lstar );

    }
    // ---------------------------------------------------------  

    // ---------------------------------------------------------
    // Part IV: add extra contributions to Lstar
    // ---------------------------------------------------------
    // Call LstarExtra
    LstarExtra(&q,&aux,&Lstar);
    // ---------------------------------------------------------


    // ---------------------------------------------------------
    // Part V: artificial viscosity limiter
    // ---------------------------------------------------------  
    if (dogParams.get_space_order()>1  &&
            dogParams.using_viscosity_limiter())
    {  ArtificialViscosity(&aux,&q,&Lstar);  }
    // ---------------------------------------------------------

}
Exemplo n.º 3
0
//---------------------------------------------------------
DVec& NDG2D::PoissonIPDGbc2D
(DVec& ubc, //[in]
 DVec& qbc  //[in]
)
//---------------------------------------------------------
{
  // function [OP] = PoissonIPDGbc2D()
  // Purpose: Set up the discrete Poisson matrix directly
  //          using LDG. The operator is set up in the weak form

  // build DG derivative matrices
  int max_OP = (K*Np*Np*(1+Nfaces));

  // initialize parameters
  DVec faceR("faceR"), faceS("faceS");
  DMat V1D("V1D"), Dx("Dx"),Dy("Dy"), Dn1("Dn1"), mmE_Fm1("mmE(:,Fm1)");
  IVec Fm("Fm"), Fm1("Fm1"), fidM("fidM");
  double lnx=0.0,lny=0.0,lsJ=0.0,hinv=0.0,gtau=0.0;
  int i=0,k1=0,f1=0,id=0;
  IVec i1_Nfp = Range(1,Nfp);
  double N1N1 = double((N+1)*(N+1));

  // build local face matrices
  DMat massEdge[4]; // = zeros(Np,Np,Nfaces);
  for (i=1; i<=Nfaces; ++i) {
    massEdge[i].resize(Np,Np);
  }

  // face mass matrix 1
  Fm = Fmask(All,1); faceR = r(Fm); 
  V1D = Vandermonde1D(N, faceR);
  massEdge[1](Fm,Fm) = inv(V1D*trans(V1D));

  // face mass matrix 2
  Fm = Fmask(All,2); faceR = r(Fm); 
  V1D = Vandermonde1D(N, faceR);
  massEdge[2](Fm,Fm) = inv(V1D*trans(V1D));

  // face mass matrix 3
  Fm = Fmask(All,3); faceS = s(Fm); 
  V1D = Vandermonde1D(N, faceS); 
  massEdge[3](Fm,Fm) = inv(V1D*trans(V1D));
 
  // build DG right hand side
  DVec* pBC = new DVec(Np*K, "bc", OBJ_temp); 
  DVec& bc = (*pBC);  // reference, for syntax
  ////////////////////////////////////////////////////////////////

  umMSG(1, "\n ==> {OP} assembly [bc]: ");
  for (k1=1; k1<=K; ++k1)
  {
    if (! (k1%100)) { umMSG(1, "%d, ",k1); }

    // rows1 = outer(Range((k1-1)*Np+1,k1*Np), Ones(NGauss));

    // Build element-to-element parts of operator
    for (f1=1; f1<=Nfaces; ++f1)
    {
      if (BCType(k1,f1))
      {
        ////////////////////////added by Kevin ///////////////////////////////
        Fm1 = Fmask(All,f1); 
        fidM  = (k1-1)*Nfp*Nfaces + (f1-1)*Nfp + i1_Nfp;
        id = 1+(f1-1)*Nfp + (k1-1)*Nfp*Nfaces;

        lnx = nx(id); lny = ny(id); 
        lsJ = sJ(id); hinv = Fscale(id);

        Dx = rx(1,k1)*Dr + sx(1,k1)*Ds;  
        Dy = ry(1,k1)*Dr + sy(1,k1)*Ds;
        Dn1 = lnx*Dx + lny*Dy;

      //mmE = lsJ*massEdge(:,:,f1);
      //bc(All,k1) += (gtau*mmE(All,Fm1) - Dn1'*mmE(All,Fm1))*ubc(fidM);

        mmE_Fm1 = massEdge[f1](All,Fm1);  mmE_Fm1 *= lsJ;

        gtau = 10*N1N1*hinv; // set penalty scaling
        //bc(All,k1) += (gtau*mmE_Fm1 - trans(Dn1)*mmE_Fm1) * ubc(fidM);

        switch(BCType(k1,f1)){
	  case BC_Dirichlet: 
            bc(Np*(k1-1)+Range(1,Np)) += (gtau*mmE_Fm1 - trans(Dn1)*mmE_Fm1)*ubc(fidM);  
            break;
          case BC_Neuman:
            bc(Np*(k1-1)+Range(1,Np)) += mmE_Fm1*qbc(fidM);
            break;
	default:
	  std::cout<<"warning: boundary condition is incorrect"<<std::endl;
	}
      }
    }
  }
  return bc;
}
Exemplo n.º 4
0
//---------------------------------------------------------
void NDG3D::PoissonIPDG3D(CSd& spOP, CSd& spMM)
//---------------------------------------------------------
{
  // function [OP,MM] = PoissonIPDG3D()
  //
  // Purpose: Set up the discrete Poisson matrix directly
  //          using LDG. The operator is set up in the weak form


  DVec faceR("faceR"), faceS("faceS"), faceT("faceT");
  DMat V2D;  IVec Fm("Fm");  IVec i1_Nfp = Range(1,Nfp);
  double opti1=0.0, opti2=0.0; int i=0; 

  umLOG(1, "\n ==> {OP,MM} assembly: ");
  opti1 = timer.read(); // time assembly

  // build local face matrices
  DMat massEdge[5]; // = zeros(Np,Np,Nfaces);
  for (i=1; i<=Nfaces; ++i) {
    massEdge[i].resize(Np,Np);
  }

  // face mass matrix 1
  Fm = Fmask(All,1); faceR=r(Fm); faceS=s(Fm); 
  V2D = Vandermonde2D(N, faceR, faceS);
  massEdge[1](Fm,Fm) = inv(V2D*trans(V2D));

  // face mass matrix 2
  Fm = Fmask(All,2); faceR = r(Fm); faceT = t(Fm);
  V2D = Vandermonde2D(N, faceR, faceT);
  massEdge[2](Fm,Fm) = inv(V2D*trans(V2D));

  // face mass matrix 3
  Fm = Fmask(All,3); faceS = s(Fm); faceT = t(Fm);
  V2D = Vandermonde2D(N, faceS, faceT); 
  massEdge[3](Fm,Fm) = inv(V2D*trans(V2D));

  // face mass matrix 4
  Fm = Fmask(All,4); faceS = s(Fm); faceT = t(Fm);
  V2D = Vandermonde2D(N, faceS, faceT); 
  massEdge[4](Fm,Fm) = inv(V2D*trans(V2D));

  // build local volume mass matrix
  MassMatrix = trans(invV)*invV;

  DMat Dx("Dx"),Dy("Dy"),Dz("Dz"), Dx2("Dx2"),Dy2("Dy2"),Dz2("Dz2");
  DMat Dn1("Dn1"),Dn2("Dn2"), mmE("mmE"), OP11("OP11"), OP12("OP12");
  DMat mmE_All_Fm1, mmE_Fm1_Fm1, Dn2_Fm2_All;
  IMat rows1,cols1,rows2,cols2;  int k1=0,f1=0,k2=0,f2=0,id=0;
  Index1D entries, entriesMM, idsM;  IVec fidM,vidM,Fm1,vidP,Fm2;
  double lnx=0.0,lny=0.0,lnz=0.0,lsJ=0.0,hinv=0.0,gtau=0.0;
  double N1N1 = double((N+1)*(N+1)); int NpNp = Np*Np;

  // build DG derivative matrices
  int max_OP = (K*Np*Np*(1+Nfaces));
  int max_MM = (K*Np*Np);

  // "OP" triplets (i,j,x), extracted to {Ai,Aj,Ax}
  IVec OPi(max_OP), OPj(max_OP), Ai,Aj; DVec OPx(max_OP), Ax;
  // "MM" triplets (i,j,x)
  IVec MMi(max_MM), MMj(max_MM); DVec MMx(max_MM);
  IVec OnesNp = Ones(Np);

  // global node numbering
  entries.reset(1,NpNp); entriesMM.reset(1,NpNp);

  OP12.resize(Np,Np);

  for (k1=1; k1<=K; ++k1)
  {
    if (! (k1%250)) { umLOG(1, "%d, ",k1); }

    rows1 = outer( Range((k1-1)*Np+1,k1*Np), OnesNp );
    cols1 = trans(rows1);

    // Build local operators  
    Dx = rx(1,k1)*Dr + sx(1,k1)*Ds + tx(1,k1)*Dt;   
    Dy = ry(1,k1)*Dr + sy(1,k1)*Ds + ty(1,k1)*Dt;
    Dz = rz(1,k1)*Dr + sz(1,k1)*Ds + tz(1,k1)*Dt;

    OP11 = J(1,k1)*(trans(Dx)*MassMatrix*Dx + 
                    trans(Dy)*MassMatrix*Dy + 
                    trans(Dz)*MassMatrix*Dz);

    // Build element-to-element parts of operator
    for (f1=1; f1<=Nfaces; ++f1) {
      k2 = EToE(k1,f1); f2 = EToF(k1,f1); 

      rows2 = outer( Range((k2-1)*Np+1, k2*Np), OnesNp );
      cols2 = trans(rows2);

      fidM  = (k1-1)*Nfp*Nfaces + (f1-1)*Nfp + i1_Nfp;
      vidM = vmapM(fidM); Fm1 = mod(vidM-1,Np)+1;
      vidP = vmapP(fidM); Fm2 = mod(vidP-1,Np)+1;

      id = 1+(f1-1)*Nfp + (k1-1)*Nfp*Nfaces;
      lnx = nx(id);  lny = ny(id);  lnz = nz(id); lsJ = sJ(id); 
      hinv = std::max(Fscale(id), Fscale(1+(f2-1)*Nfp, k2));    

      Dx2 = rx(1,k2)*Dr + sx(1,k2)*Ds + tx(1,k2)*Dt;   
      Dy2 = ry(1,k2)*Dr + sy(1,k2)*Ds + ty(1,k2)*Dt;
      Dz2 = rz(1,k2)*Dr + sz(1,k2)*Ds + tz(1,k2)*Dt;
      
      Dn1 = lnx*Dx  + lny*Dy  + lnz*Dz;
      Dn2 = lnx*Dx2 + lny*Dy2 + lnz*Dz2;

      mmE = lsJ*massEdge[f1];

      gtau = 2.0 * N1N1 * hinv; // set penalty scaling

      if (EToE(k1,f1)==k1) {
        OP11 += ( gtau*mmE - mmE*Dn1 - trans(Dn1)*mmE ); // ok
      }
      else 
      {
        // interior face variational terms
        OP11 += 0.5*( gtau*mmE - mmE*Dn1 - trans(Dn1)*mmE );

        // extract mapped regions:
        mmE_All_Fm1 = mmE(All,Fm1);
        mmE_Fm1_Fm1 = mmE(Fm1,Fm1);
        Dn2_Fm2_All = Dn2(Fm2,All);

        OP12 = 0.0;   // reset to zero
        OP12(All,Fm2)  = -0.5*(       gtau*mmE_All_Fm1 );
        OP12(Fm1,All) -=  0.5*(            mmE_Fm1_Fm1*Dn2_Fm2_All );
      //OP12(All,Fm2) -=  0.5*(-trans(Dn1)*mmE_All_Fm1 );
        OP12(All,Fm2) +=  0.5*( trans(Dn1)*mmE_All_Fm1 );

        // load this set of triplets
#if (1)
        OPi(entries)=rows1; OPj(entries)=cols2, OPx(entries)=OP12;
        entries += (NpNp);
#else
        //###########################################################
        // load only the lower triangle (after droptol test?)
        sk=0; start=entries(1);
        for (int i=1; i<=NpNp; ++i) {
          eid = start+i;
          id=entries(eid); rid=rows1(i); cid=cols2(i);
          if (rows1(rid) >= cid) {          // take lower triangle
            if ( fabs(OP12(id)) > 1e-15) {  // drop small entries
              ++sk; OPi(id)=rid; OPj(id)=cid, OPx(id)=OP12(id);
            }
          }
        }
        entries += sk;
        //###########################################################
#endif
      }
    }

    OPi(entries  )=rows1; OPj(entries  )=cols1, OPx(entries  )=OP11;
    MMi(entriesMM)=rows1; MMj(entriesMM)=cols1; MMx(entriesMM)=J(1,k1)*MassMatrix;
    entries += (NpNp); entriesMM += (NpNp);
  }
  umLOG(1, "\n ==> {OP,MM} to sparse\n");

  entries.reset(1, entries.hi()-Np*Np);

  // Extract triplets from the large buffers. Note: this 
  // requires copying each array, and since these arrays 
  // can be HUGE(!), we force immediate deallocation:

  Ai=OPi(entries);  OPi.Free();
  Aj=OPj(entries);  OPj.Free();
  Ax=OPx(entries);  OPx.Free();
  umLOG(1, " ==> triplets ready (OP) nnz = %10d\n", entries.hi());

  // adjust triplet indices for 0-based sparse operators
  Ai -= 1; Aj -= 1; MMi -= 1; MMj -= 1;  int npk=Np*K;

#if defined(NDG_USE_CHOLMOD) || defined(NDG_New_CHOLINC)
  // load only the lower triangle tril(OP)        free args?
  spOP.load(npk,npk, Ai,Aj,Ax, sp_LT, false,1e-15, true);  // {LT, false} -> TriL
#else
  // select {upper,lower,both} triangles
//spOP.load(npk,npk, Ai,Aj,Ax, sp_LT, true,1e-15,true);   // LT -> enforce symmetry
//spOP.load(npk,npk, Ai,Aj,Ax, sp_All,true,1e-15,true);   // All-> includes "noise"
//spOP.load(npk,npk, Ai,Aj,Ax, sp_UT, false,1e-15,true);  // UT -> triu(OP) only
#endif

  Ai.Free();  Aj.Free();  Ax.Free();

  umLOG(1, " ==> triplets ready (MM) nnz = %10d\n", entriesMM.hi());

  //-------------------------------------------------------
  // The mass matrix operator will NOT be factorised, 
  // Load ALL elements (both upper and lower triangles):
  //-------------------------------------------------------
  spMM.load(npk,npk, MMi,MMj,MMx, sp_All,false,1.00e-15,true);
  MMi.Free(); MMj.Free(); MMx.Free();

  opti2 = timer.read(); // time assembly
  umLOG(1, " ==> {OP,MM} converted to csc.  (%g secs)\n", opti2-opti1);
}
Exemplo n.º 5
0
void NDG2D::PoissonIPDGbc2D(
  CSd& spOP //[out] sparse operator 
  )
{
  // function [OP] = PoissonIPDGbc2D()
  // Purpose: Set up the discrete Poisson matrix directly
  //          using LDG. The operator is set up in the weak form

  // build DG derivative matrices
  int max_OP = (K*Np*Np*(1+Nfaces));

  //initialize parameters
  DVec faceR("faceR"), faceS("faceS");
  IVec Fm("Fm"), Fm1("Fm1"), fidM("fidM");
  DMat V1D("V1D"); int i=0;

  // build local face matrices
  DMat massEdge[4]; // = zeros(Np,Np,Nfaces);
  for (i=1; i<=Nfaces; ++i) {
    massEdge[i].resize(Np,Np);
  }

  // face mass matrix 1
  Fm = Fmask(All,1); faceR = r(Fm); 
  V1D = Vandermonde1D(N, faceR);
  massEdge[1](Fm,Fm) = inv(V1D*trans(V1D));

  // face mass matrix 2
  Fm = Fmask(All,2); faceR = r(Fm); 
  V1D = Vandermonde1D(N, faceR);
  massEdge[2](Fm,Fm) = inv(V1D*trans(V1D));

  // face mass matrix 3
  Fm = Fmask(All,3); faceS = s(Fm); 
  V1D = Vandermonde1D(N, faceS); 
  massEdge[3](Fm,Fm) = inv(V1D*trans(V1D));

  //continue initialize parameters
  DMat Dx("Dx"),Dy("Dy"), Dn1("Dn1"), mmE_Fm1("mmE(:,Fm1)");
  double lnx=0.0,lny=0.0,lsJ=0.0,hinv=0.0,gtau=0.0;
  int k1=0,f1=0,id=0;
  IVec i1_Nfp = Range(1,Nfp);
  double N1N1 = double((N+1)*(N+1));
  
  // "OP" triplets (i,j,x), extracted to {Ai,Aj,Ax}
  IVec OPi(max_OP),OPj(max_OP), Ai,Aj; DVec OPx(max_OP), Ax;
  IMat rows1, cols1;  Index1D entries; DMat OP11(Np,Nfp, 0.0);

  // global node numbering
  entries.reset(1,Np*Nfp); 
  cols1 = outer(Ones(Np), Range(1,Nfp));

  umMSG(1, "\n ==> {OP} assembly [bc]: ");
  for (k1=1; k1<=K; ++k1)
  {
    if (! (k1%100)) { umMSG(1, "%d, ",k1); }
    rows1 = outer(Range((k1-1)*Np+1,k1*Np), Ones(Nfp));

    // Build element-to-element parts of operator
    for (f1=1; f1<=Nfaces; ++f1)
    {
      if (BCType(k1,f1))
      {   
        ////////////////////////added by Kevin ///////////////////////////////
        Fm1 = Fmask(All,f1); 
        fidM  = (k1-1)*Nfp*Nfaces + (f1-1)*Nfp + i1_Nfp;
        id = 1+(f1-1)*Nfp + (k1-1)*Nfp*Nfaces;

        lnx = nx(id); lny = ny(id); 
        lsJ = sJ(id); hinv = Fscale(id);

        Dx = rx(1,k1)*Dr + sx(1,k1)*Ds;  
        Dy = ry(1,k1)*Dr + sy(1,k1)*Ds;
        Dn1 = lnx*Dx + lny*Dy;

      //mmE = lsJ*massEdge(:,:,f1);
      //bc(All,k1) += (gtau*mmE(All,Fm1) - Dn1'*mmE(All,Fm1))*ubc(fidM);

        mmE_Fm1 = massEdge[f1](All,Fm1);  mmE_Fm1 *= lsJ;

        gtau = 10*N1N1*hinv; // set penalty scaling
        //bc(All,k1) += (gtau*mmE_Fm1 - trans(Dn1)*mmE_Fm1) * ubc(fidM);

        switch(BCType(k1,f1)){
	  case BC_Dirichlet: 
            OP11 = gtau*mmE_Fm1 - trans(Dn1)*mmE_Fm1;  
            break;
          case BC_Neuman:
            OP11 = mmE_Fm1;
            break;
	default:
	  std::cout<<"warning: boundary condition is incorrect"<<std::endl;
	}

        OPi(entries)=rows1; OPj(entries)=cols1; OPx(entries)=OP11; 
        entries += (Np*Nfp);
      }
      cols1 += Nfp;
    }
  }

  umMSG(1, "\n ==> {OPbc} to sparse\n");
  entries.reset(1, entries.hi()-(Np*Nfp));

  // extract triplets from large buffers
  Ai=OPi(entries); Aj=OPj(entries); Ax=OPx(entries);

  // These arrays can be HUGE, so force deallocation
  OPi.Free(); OPj.Free(); OPx.Free();

  // return 0-based sparse result
  Ai -= 1; Aj -= 1;

  //-------------------------------------------------------
  // This operator is not symmetric, and will NOT be 
  // factorised, only used to create reference RHS's:
  //
  //    refrhsbcPR = spOP1 * bcPR;
  //    refrhsbcUx = spOP2 * bcUx;
  //    refrhsbcUy = spOP2 * bcUy;
  //
  // Load ALL elements (both upper and lower triangles):
  //-------------------------------------------------------
  spOP.load(Np*K, Nfp*Nfaces*K, Ai,Aj,Ax, sp_All,false, 1e-15,true);

  Ai.Free();  Aj.Free();  Ax.Free();
  umMSG(1, " ==> {OPbc} ready.\n");

#if (1)
  // check on original estimates for nnx
  umMSG(1, " ==> max_OP: %12d\n", max_OP);
  umMSG(1, " ==> nnz_OP: %12d\n", entries.hi());
#endif
}