コード例 #1
0
ファイル: CS_Solve.cpp プロジェクト: aghakhani/aero-shock
//---------------------------------------------------------
void CSN::show_alloc() const
//---------------------------------------------------------
{
  umMSG(1, "\nAllocations in Numeric object:\n");
  umMSG(1, "   L     : %8d (csc) \n", L.size());
  umMSG(1, "   U     : %8d (csc) \n", U.size());
  umMSG(1, "   pinv  : %8d (int) \n", pinv.size());
  umMSG(1, "   B     : %8d (dbl) \n\n", B.size());
}
コード例 #2
0
//---------------------------------------------------------
void VertexAngles
(
  const DVec& x1, const DVec& x2, const DVec& x3,
  const DVec& y1, const DVec& y2, const DVec& y3,
        DVec& a1,       DVec& a2,       DVec& a3
)
//---------------------------------------------------------
{

  //------------------------------------------
  // Expand definitions from ElmTools
  //------------------------------------------
  // a1 = acos ( -a23() / sqrt(a22()*a33()) );
  // a2 = acos ( -a13() / sqrt(a11()*a33()) );
  // a3 = acos ( -a12() / sqrt(a11()*a22()) );

  DVec g2x=(y3-y1), g2y=(x1-x3), g3x=(y1-y2), g3y=(x2-x1);
  
  DVec det = g3y*g2x - g3x*g2y;  
  DVec d   = 1.0/det;
  
  g2x *= d;  g2y *= d;  g3x *= d;  g3y *= d;

  DVec g1x =  - g2x - g3x;
  DVec g1y =  - g2y - g3y;

  a1 = acos( -(g2x*g3x + g2y*g3y) / sqrt((sqr(g2x)+sqr(g2y)) * (sqr(g3x)+sqr(g3y)) ));
  a2 = acos( -(g1x*g3x + g1y*g3y) / sqrt((sqr(g1x)+sqr(g1y)) * (sqr(g3x)+sqr(g3y)) ));
  a3 = acos( -(g1x*g2x + g1y*g2y) / sqrt((sqr(g1x)+sqr(g1y)) * (sqr(g2x)+sqr(g2y)) ));

#if (0)
  // check that the angles in each element sum to 180
  int Ni = x1.size(); double sum=0.0;
  umMSG(1, "\nChecking sum of angles in %d element\n", Ni);
  for (int i=1; i<=Ni; ++i) {
    sum = fabs(a1(i)) + fabs(a2(i)) + fabs(a3(i));
    if ( fabs(sum-M_PI) > 1e-15) {
      umMSG(1, "element %4d: %12.5e\n", i, fabs(sum-M_PI)); 
    }
  }
#endif
}
コード例 #3
0
ファイル: CS_Solve.cpp プロジェクト: aghakhani/aero-shock
//---------------------------------------------------------
void CSS::show_alloc() const
//---------------------------------------------------------
{
  umMSG(1, "\nAllocations in Symbolic object:\n");
  umMSG(1, "   pinv  : %8d (int) \n", pinv.size());
  umMSG(1, "   Q     : %8d (int) \n", Q.size());
  umMSG(1, "   parent: %8d (int) \n", parent.size());
  umMSG(1, "   cp    : %8d (int) \n", cp.size());
  umMSG(1, " leftmost: %8d (int) \n", leftmost.size());
  umMSG(1, " m2: %d  lnz: %g  unz: %g \n\n", m2, lnz, unz);
}
コード例 #4
0
//---------------------------------------------------------
void MaxwellNonCon2D::AdjustMesh_P()
//---------------------------------------------------------
{
  umMSG(1, "Adjusting mesh for non-conforming (P) elements\n");

  Nfaces = 3;
  tiConnect2D(EToV, EToE,EToF);

  // make boundary conditions all "Wall" type
  BCType = int(BC_Wall) * EToE.eq(outer(Range(1,K),Ones(Nfaces)));

  IVec Norder(K);

  if (1) {
    // generate a random order for each element
    Norder = ceil(10.0*rand(K));
  } else if (0) {
    Norder = 5;
  } else {
    Norder(1) = 1;
    Norder(2) = 1;
    Norder(3) = 2;
    Norder(4) = 2;
    Norder(5) = 3;
    Norder(6) = 3;
    Norder(Range(7,K)) = 4;
  }

  // Build mesh, each element having arbitrary order
  BuildPNonCon2D(Norder, K, VX, VY, EToV, BCType,  m_PInfo);

  xx.resize(max_pinf_id);
  yy.resize(max_pinf_id);
  for (int N1=1; N1<=Nmax; ++N1) {
    const PInfo& pinf = (*m_PInfo[N1]);
    if (pinf.K > 0) {
      const IVec& pids = dynamic_cast<const IVec&>(pinf.ids);
      xx(pids) = pinf.x;
      yy(pids) = pinf.y;
    }
  }
}
コード例 #5
0
//---------------------------------------------------------
void CurvedINS2D::Run()
//---------------------------------------------------------
{
  ti0=timer.read();

  // function [Ux, Uy, PR, time] = CurvedINS2D(...
  //           Ux, Uy, PR, FinalTime, nu, simtype, ExactSolution, BCfunction);
  // Purpose: integrate the incompressible Navier-Stokes equations to FinalTime

  InitRun();            // initialize timers & counters

  // choose order to integrate exactly
  int Nint = (int)ceil(3.0*N/2.0);

  // build cubature nodes for all elements
  CubatureOrder = 2*(Nint+1); CubatureVolumeMesh2D(CubatureOrder);

  // build Gauss node data for all element faces
  NGauss = (Nint+1); GaussFaceMesh2D(NGauss);

#if (1)
  //-------------------------------------
  // check all node sets
  //-------------------------------------
  Output_Mesh();
//OutputNodes(false);   // volume nodes
//OutputNodes(true);    // face nodes
//OutputNodes_cub();    // cubature
//OutputNodes_gauss();  // quadrature
//umLOG(1, "\n*** Exiting after CUb, Gauss\n\n");
//return;
#endif

  // recover memory from registry
  NDG_garbage_collect();

  // prepare data...
  PreCalcBdryData();

  // dual splitting scheme coefficients
  g0 = 1.0; a0 = 1.0; a1 = 0.0; b0 = 1.0; b1 = 0.0; 

  CurvedINSPressureSetUp2D(); // Build pressure matrix and boundary forcing (IPDG)
  NDG_garbage_collect();      // recover memory from registry

  CurvedINSViscousSetUp2D();  // Build viscous matrix and boundary forcing (IPDG)
  NDG_garbage_collect();      // recover memory from registry

  (this->*ExactSolutionBC)    // Form inhomogeneous boundary term for rhs data 
          (Fx, Fy, nx,ny, mapI, mapO, mapW, mapC, 0.0, nu, 
           refbcUx, refbcUy, refbcPR, refbcdUndt);


  // storage for history of fields and nonlinear terms
  Uxold=Ux; NUx=0.0;  Uyold=Uy; NUy=0.0; dpdn=0.0; 

  time_work += timer.read() - ti0;  // add cost of NDG setup

  // start time stepping
  time = 0.0;
  for (tstep=1; tstep<=Nsteps; ++tstep)
  {
    tw1=timer.read();   // time NDG work

    // update dual splitting scheme coefficients after 
    // first time step, then recalculate operators
    if (2 == tstep) 
    {
      // release and recreate Cholesky solvers
      reset_solvers();

      g0 = 1.5; a0 = 2.0; a1 = -0.5; b0 = 2.0; b1 = -1.0; 

      // Rebuild pressure and viscous matrixes for new g0
      CurvedINSPressureSetUp2D();
      CurvedINSViscousSetUp2D();

      NDG_garbage_collect();
      umMSG(1, "2nd sparse setup completed\n");
    //umERROR("Testing", "Exiting early");
    }

    TimeScaleBCData();      // apply temporal scaling factors to bc data

    INSAdvection2D();       // compute nonlinear terms NUx, NUy
  //CurvedINSAdvection2D;   // curved version

    INSPressure2D();        // compute pressure PR and intermediate UxTT, UyTT
  //CurvedINSPressure2D;    // curved version

    CurvedINSViscous2D();   // compute viscous solves and update velocity

    time_work += timer.read() - tw1;  // accumulate cost of NDG work
    time = tstep*dt;        // increment time 
    Report();               // report results

    // if (tstep>100) break;
  }

  time_total = timer.read()-ti0;  // stop timing
  FinalReport();                  // final report
}
コード例 #6
0
//---------------------------------------------------------
DMat& NDG2D::ConformingHrefine2D(IMat& edgerefineflag, const DMat& Qin)
//---------------------------------------------------------
{
#if (0)
  OutputNodes(false); // volume nodes
//OutputNodes(true);  // face nodes
#endif


  // function newQ = ConformingHrefine2D(edgerefineflag, Q)
  // Purpose: apply edge splits as requested by edgerefineflag

  IVec v1("v1"), v2("v2"), v3("v3"), tvi;
  DVec x1("x1"), x2("x2"), x3("x3"), y1("y1"), y2("y2"), y3("y3");
  DVec a1("a1"), a2("a2"), a3("a3");

  // count vertices
  assert (VX.size() == Nv);

  // find vertex triplets for elements to be refined
  v1 = EToV(All,1);  v2 = EToV(All,2);  v3 = EToV(All,3);
  x1 = VX(v1);       x2 = VX(v2);       x3 = VX(v3);
  y1 = VY(v1);       y2 = VY(v2);       y3 = VY(v3);

  // find angles at each element vertex (in radians)
  VertexAngles(x1,x2,x3,y1,y2,y3, a1,a2,a3);

  // absolute value of angle size
  a1.set_abs(); a2.set_abs(); a3.set_abs();

  int k=0,k1=0,f1=0,k2=0,f2=0, e1=0,e2=0,e3=0, b1=0,b2=0,b3=0, ref=0;
  IVec m1,m2,m3; DVec mx1, my1, mx2, my2, mx3, my3;

  // create new vertices at edge centers of marked elements 
  // (use unique numbering derived from unique edge number))
  m1 = max(IVec(Nv*(v1-1)+v2+1), IVec(Nv*(v2-1)+v1+1)); mx1=0.5*(x1+x2); my1=0.5*(y1+y2);
  m2 = max(IVec(Nv*(v2-1)+v3+1), IVec(Nv*(v3-1)+v2+1)); mx2=0.5*(x2+x3); my2=0.5*(y2+y3);
  m3 = max(IVec(Nv*(v1-1)+v3+1), IVec(Nv*(v3-1)+v1+1)); mx3=0.5*(x3+x1); my3=0.5*(y3+y1);

  // ensure that both elements sharing an edge are split
  for (k1=1; k1<=K; ++k1) {
    for (f1=1; f1<=Nfaces; ++f1) {
      if (edgerefineflag(k1,f1)) {
        k2 = EToE(k1,f1); 
        f2 = EToF(k1,f1);
        edgerefineflag(k2,f2) = 1;
      }
    }
  }

  // store old data
  IMat oldEToV = EToV;  DVec oldVX = VX, oldVY = VY; 

  // count the number of elements in the refined mesh
  int newK = countrefinefaces(edgerefineflag);
  EToV.resize(newK, Nfaces, true, 0);
  IMat newBCType(newK,3, "newBCType");
  
  //   kold = [];
  IVec kold(newK, "kold");  Index1D KI,KIo;

  int sk=1, skstart=0, skend=0;

  for (k=1; k<=K; ++k)
  {
    skstart = sk;

    e1 = edgerefineflag(k,1); b1 = BCType(k,1);
    e2 = edgerefineflag(k,2); b2 = BCType(k,2);
    e3 = edgerefineflag(k,3); b3 = BCType(k,3);
    ref = e1 + 2*e2 + 4*e3;
    
    switch (ref) {

    case 0: 
      EToV(sk, All) = IVec(v1(k),v2(k),v3(k));    newBCType(sk,All) = IVec(b1, b2, b3); ++sk;
      break;

    case 1:
      EToV(sk, All) = IVec(v1(k),m1(k),v3(k));    newBCType(sk,All) = IVec(b1,  0, b3); ++sk;
      EToV(sk, All) = IVec(m1(k),v2(k),v3(k));    newBCType(sk,All) = IVec(b1, b2,  0); ++sk;
      break;

    case 2:
      EToV(sk, All) = IVec(v2(k),m2(k),v1(k));    newBCType(sk,All) = IVec(b2,  0, b1); ++sk;
      EToV(sk, All) = IVec(m2(k),v3(k),v1(k));    newBCType(sk,All) = IVec(b2, b3,  0); ++sk;
      break;

    case 4:
      EToV(sk, All) = IVec(v3(k),m3(k),v2(k));    newBCType(sk,All) = IVec(b3,  0, b2); ++sk;
      EToV(sk, All) = IVec(m3(k),v1(k),v2(k));    newBCType(sk,All) = IVec(b3, b1,  0); ++sk;
      break;

    case 3:
      EToV(sk, All) = IVec(m1(k),v2(k),m2(k));    newBCType(sk,All) = IVec(b1, b2,  0); ++sk;
      if (a1(k) > a3(k)) { // split largest angle
        EToV(sk, All) = IVec(v1(k),m1(k),m2(k));  newBCType(sk,All) = IVec(b1,  0,  0); ++sk;
        EToV(sk, All) = IVec(v1(k),m2(k),v3(k));  newBCType(sk,All) = IVec( 0, b2, b3); ++sk;
      } else {
        EToV(sk, All) = IVec(v3(k),m1(k),m2(k));  newBCType(sk,All) = IVec( 0,  0, b2); ++sk;
        EToV(sk, All) = IVec(v3(k),v1(k),m1(k));  newBCType(sk,All) = IVec(b3, b1,  0); ++sk;
      }
      break;

    case 5:
      EToV(sk, All) = IVec(v1(k),m1(k),m3(k));    newBCType(sk,All) = IVec(b1,  0, b3); ++sk;
      if (a2(k) > a3(k)) { 
        // split largest angle
        EToV(sk, All) = IVec(v2(k),m3(k),m1(k));  newBCType(sk,All) = IVec( 0,  0, b1); ++sk;
        EToV(sk, All) = IVec(v2(k),v3(k),m3(k));  newBCType(sk,All) = IVec(b2, b3,  0); ++sk;
      } else {
        EToV(sk, All) = IVec(v3(k),m3(k),m1(k));  newBCType(sk,All) = IVec(b3,  0,  0); ++sk;
        EToV(sk, All) = IVec(v3(k),m1(k),v2(k));  newBCType(sk,All) = IVec( 0, b1, b2); ++sk;
      }
      break;

    case 6:
      EToV(sk, All) = IVec(v3(k),m3(k),m2(k));    newBCType(sk,All) = IVec(b3,  0, b2); ++sk;
      if (a1(k) > a2(k)) { 
        // split largest angle
        EToV(sk, All) = IVec(v1(k),m2(k),m3(k));  newBCType(sk,All) = IVec( 0, 0, b3); ++sk;
        EToV(sk, All) = IVec(v1(k),v2(k),m2(k));  newBCType(sk,All) = IVec(b1, b2,  0); ++sk;
      } else {
        EToV(sk, All) = IVec(v2(k),m2(k),m3(k));  newBCType(sk,All) = IVec(b2,  0,  0); ++sk;
        EToV(sk, All) = IVec(v2(k),m3(k),v1(k));  newBCType(sk,All) = IVec( 0 , b3, b1); ++sk;
      }
      break;

    default:
      // split all 
      EToV(sk, All) = IVec(m1(k),m2(k),m3(k)); newBCType(sk, All) = IVec( 0, 0,  0); ++sk;
      EToV(sk, All) = IVec(v1(k),m1(k),m3(k)); newBCType(sk, All) = IVec(b1, 0, b3); ++sk;
      EToV(sk, All) = IVec(v2(k),m2(k),m1(k)); newBCType(sk, All) = IVec(b2, 0, b1); ++sk;
      EToV(sk, All) = IVec(v3(k),m3(k),m2(k)); newBCType(sk, All) = IVec(b3, 0, b2); ++sk;
      break;
    }
    
    skend = sk;

    // kold = [kold; k*ones(skend-skstart, 1)];

    // element k is to be refined into (1:4) child elements.
    // store parent element numbers in array "kold" to help 
    // with accessing parent vertex data during refinement.

    KI.reset(skstart, skend-1); // ids of child elements
    kold(KI) = k;               // mark as children of element k
  }

  // Finished with edgerefineflag.  Delete if OBJ_temp
  if (edgerefineflag.get_mode() == OBJ_temp) { 
    delete (&edgerefineflag); 
  }


  // renumber new nodes contiguously
  // ids = unique([v1;v2;v3;m1;m2;m3]);
  bool unique=true; IVec IDS, ids;
  IDS = concat( concat(v1,v2,v3), concat(m1,m2,m3) );
  ids = sort(IDS, unique);
  Nv = ids.size();

  int max_id = EToV.max_val();
  umMSG(1, "max id in EToV is %d\n", max_id);

  //         M     N   nnz vals triplet
  CSi newids(max_id,1, Nv,  1,    1  );
  //  newids = sparse(max(max(EToV)),1);

  int i=0, j=1;
  for (i=1; i<=Nv; ++i) {
  //     newids(ids)= (1:Nv);
    newids.set1(ids(i),j, i);   // load 1-based triplets
  }          // row   col x
  newids.compress();            // convert to csc form


  // Matlab -----------------------------------------------
  // v1 = newids(v1); v2 = newids(v2); v3 = newids(v3);
  // m1 = newids(m1); m2 = newids(m2); m3 = newids(m3);
  //-------------------------------------------------------

  int KVi=v1.size(), KMi=m1.size();
  // read from copies, overwrite originals 
  
  // 1. reload ids for new vertices
  tvi = v1;  for (i=1;i<=KVi;++i) {v1(i) = newids(tvi(i), 1);}
  tvi = v2;  for (i=1;i<=KVi;++i) {v2(i) = newids(tvi(i), 1);}
  tvi = v3;  for (i=1;i<=KVi;++i) {v3(i) = newids(tvi(i), 1);}

  // 2. load ids for new (midpoint) vertices
  tvi = m1;  for (i=1;i<=KMi;++i) {m1(i) = newids(tvi(i), 1);}
  tvi = m2;  for (i=1;i<=KMi;++i) {m2(i) = newids(tvi(i), 1);}
  tvi = m3;  for (i=1;i<=KMi;++i) {m3(i) = newids(tvi(i), 1);}

  VX.resize(Nv); VY.resize(Nv);
  VX(v1) =  x1; VX(v2) =  x2; VX(v3) =  x3;
  VY(v1) =  y1; VY(v2) =  y2; VY(v3) =  y3;
  VX(m1) = mx1; VX(m2) = mx2; VX(m3) = mx3;
  VY(m1) = my1; VY(m2) = my2; VY(m3) = my3;


  if (newK != (sk-1)) {
    umERROR("NDG2D::ConformingHrefine2D", "Inconsistent element count: expect %d, but sk = %d", newK, (sk-1));
  } else {
    K = newK; // sk-1;
  }

  // dumpIMat(EToV, "EToV (before)");

  // EToV = newids(EToV);
  for (j=1; j<=3; ++j) {
    for (k=1; k<=K; ++k) {
      EToV(k,j) = newids(EToV(k,j), 1);
    }
  }

#if (0)
  dumpIMat(EToV, "EToV (after)");
  // umERROR("Checking ids", "Nigel, check EToV");
#endif


  BCType = newBCType;

  Nv = VX.size();
  // xold = x; yold = y;

  StartUp2D();


#if (1)
  OutputNodes(false); // volume nodes
//OutputNodes(true);  // face nodes
//umERROR("Exiting early", "Check adapted {volume,face} nodes");
#endif


  // allocate return object
  int Nfields = Qin.num_cols();
  DMat* tmpQ = new DMat(Np*K, Nfields, "newQ", OBJ_temp);
  DMat& newQ = *tmpQ;  // use a reference for syntax

  // quick return, if no interpolation is required
  if (Qin.size()<1) {
    return newQ;
  }

  
  DVec rOUT(Np),sOUT(Np),xout,yout,xy1(2),xy2(2),xy3(2),tmp(2),rhs;
  int ko=0,kv1=0,kv2=0,kv3=0,n=0;  DMat A(2,2), interp;
  DMat oldQ = const_cast<DMat&>(Qin);

  for (k=1; k<=K; ++k)
  {
    ko = kold(k); xout = x(All,k); yout = y(All,k);
    kv1=oldEToV(ko,1); kv2=oldEToV(ko,2); kv3=oldEToV(ko,3);
    xy1.set(oldVX(kv1), oldVY(kv1));
    xy2.set(oldVX(kv2), oldVY(kv2));
    xy3.set(oldVX(kv3), oldVY(kv3));
    A.set_col(1, xy2-xy1); A.set_col(2, xy3-xy1);
    
    for (i=1; i<=Np; ++i) {
      tmp.set(xout(i), yout(i));
      rhs = 2.0*tmp - xy2 - xy3;
      tmp = A|rhs;
      rOUT(i) = tmp(1);
      sOUT(i) = tmp(2);
    }

    KI.reset (Np*(k -1)+1, Np*k );  // nodes in new element k
    KIo.reset(Np*(ko-1)+1, Np*ko);  // nodes in old element ko

    interp = Vandermonde2D(N, rOUT, sOUT)*invV;

    for (n=1; n<=Nfields; ++n) 
    {
    //newQ(:,k,n)= interp*  Q(:,ko,n);
      //DVec tm1 = interp*oldQ(KIo,n);
      //dumpDVec(tm1, "tm1");
      newQ(KI,n) = interp*oldQ(KIo,n);
    }
  }
    
  return newQ;
}
コード例 #7
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;
}
コード例 #8
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
}