Esempio n. 1
0
pxcStatus UtilCapture::ReadStreamAsync(PXCImage *images[], PXCScheduler::SyncPoint **sp) {
    UtilTrace trace(L"UtilCapture::ReadStreamAsync(video)", m_session_service);
	int nvstreams=(int)m_vstreams.size();
    if (m_maps.size()==1) {   // for a single I/O, we use the m_maps order.
        if (nvstreams==1)
            return m_vstreams.front()->ReadStreamAsync(images,sp);

        PXCSmartSPArray spts(PXCCapture::VideoStream::STREAM_LIMIT);
        for (int s=0;s<nvstreams;s++) {
            pxcStatus sts=m_vstreams[m_maps[0][s]]->ReadStreamAsync(&images[s],&spts[s]);
            if (sts<PXC_STATUS_NO_ERROR) return sts;
        }
        return PXCSmartAsyncImplIxOy<UtilCapture,PXCImage,PXCCapture::VideoStream::STREAM_LIMIT,PXCScheduler::SyncPoint,PXCCapture::VideoStream::STREAM_LIMIT>::
                SubmitTask(images,nvstreams,spts.ReleasePtrs(),nvstreams,sp,this,m_scheduler,&UtilCapture::ReadStreamSync,&UtilCapture::PassOnStatus,L"UtilCapture::ReadStreamSync");
    } else {    // for multiple I/O, we use the m_vstreams order. Each I/O is supposed to use MapStreams to get the right view.
        PXCSmartSPArray spts(PXCCapture::VideoStream::STREAM_LIMIT);
        for (int s1=0;s1<nvstreams;s1++) {
            pxcStatus sts=m_vstreams[s1]->ReadStreamAsync(&images[s1],&spts[s1]);
            if (sts<PXC_STATUS_NO_ERROR) return sts;
        }
        return PXCSmartAsyncImplIxOy<UtilCapture,PXCImage,PXCCapture::VideoStream::STREAM_LIMIT,PXCScheduler::SyncPoint,PXCCapture::VideoStream::STREAM_LIMIT>::
                SubmitTask(images,nvstreams,spts.ReleasePtrs(),nvstreams,sp,this,m_scheduler,&UtilCapture::ReadStreamSync,&UtilCapture::PassOnStatus,L"UtilCapture::ReadStreamSync");
    }
}
void L2Project_interface(int mopt, int run,int istart, int iend,
	       const dTensor2& node,
	       const dTensorBC3& qin, 
	       const dTensorBC3& auxin,
               const dTensor4 qI,
               const dTensor4 auxI,dTensor4& Implicit,double dt,  
               const dTensor1 interf2global,
               const dTensorBC1 global2interf,
               const dTensor2 dxi,
	       dTensorBC3& Fout,
               dTensor4& FI,
	       void (*Func)(const dTensor1&, const dTensor2&, const dTensor2&, dTensor2&))
{    
  const int kmax = dogParams.get_space_order();
  const int meqn = qin.getsize(2);
  const int maux = auxin.getsize(2);
  const int mlength = Fout.getsize(2);
  const int mpoints = Fout.getsize(3);  

  int mtmp = iMax(1,6-mopt);//iMax(1,mpoints-mopt);
  dTensor1 wgt(mtmp), spts(mtmp),rspts(mtmp),lspts(mtmp);
  dTensor2 phi(mtmp,kmax), phi_x(mtmp,kmax), rIphi_x(mtmp,kmax), lIphi_x(mtmp,kmax);

  // -----------------
  // Quick error check
  // -----------------
  if (meqn<1 || maux <0 || mpoints<1 || mpoints>6 || mlength<1 
      || mopt < 0 || mopt > 1)
    {
      printf(" Error in L2project.cpp ... \n");
      printf("         meqn = %i\n",meqn);
      printf("         maux = %i\n",maux);
      printf("      mpoints = %i\n",mpoints);
      printf("      mlength = %i\n",mlength);
      printf("       istart = %i\n",istart);
      printf("         iend = %i\n",iend);
      printf("        mopts = %i\n",mopt);
      printf("\n");
      exit(1);
    }

  // ---------------------------------------------
  // Check for trivial case in the case of mopt==1
  // ---------------------------------------------
  if ( mpoints == mopt )
    { Fout.setall(0.); }
  else
    {
      // Set quadrature weights and points
      void SetQuadPts(dTensor1&,dTensor1&);
      SetQuadPts(wgt,spts);

      // Sample basis function at quadrature points
      void SampleBasis(const dTensor1&,dTensor2&);
      SampleBasis(spts,phi);

      // Sample gradient of basis function at quadrature points
      void SampleBasisGrad(const dTensor1&,dTensor2&);
      void SampleBasisGrad_variable(const dTensor1&,dTensor2&,double);
      SampleBasisGrad(spts,phi_x);

      // ----------------------------------
      // Loop over all elements of interest
      // ----------------------------------    
      const double xlow = dogParamsCart1.get_xlow();
      const double dx = dogParamsCart1.get_dx();

#pragma omp parallel for
      for (int i=istart; i<=iend; i++)
        {
          if(abs(global2interf.get(i))<1.0e-1)
          {
	  double xc = xlow + (double(i)-0.5)*dx;

	  // Each of these three items needs to be private to each thread ..
	  dTensor1 xpts(mtmp);
	  dTensor2 qvals(mtmp,meqn);
	  dTensor2 auxvals(mtmp,maux);
	  dTensor2 fvals(mtmp,mlength);

	  // Loop over each quadrature point
	  for (int m=1; m<=mtmp; m++)
            {
	      // grid point x
	      xpts.set( m, xc + 0.5*dx*spts.get(m) );

	      // Solution values (q) at each grid point
	      for (int me=1; me<=meqn; me++)
                {
		  qvals.set(m,me, 0.0 );

		  for (int k=1; k<=mpoints; k++)
                    {
		      qvals.set(m,me, qvals.get(m,me) 
                                + phi.get(m,k) * qin.get(i,me,k) );
                    }
                }

	      // Auxiliary values (aux) at each grid point
	      for (int ma=1; ma<=maux; ma++)
                {
		  auxvals.set(m,ma, 0.0 );

		  for (int k=1; k<=mpoints; k++)
                    {
		      auxvals.set(m,ma, auxvals.get(m,ma) 
				  + phi.get(m,k) * auxin.get(i,ma,k) );
                    }
                }
            }


	  // Call user-supplied function to set fvals
	  Func(xpts,qvals,auxvals,fvals);

	  // Evaluate integrals
	  if (mopt==0) // project onto Legendre basis
            {
	      for (int m1=1; m1<=mlength; m1++)
		for (int m2=1; m2<=mpoints; m2++)
		  {
		    double tmp = 0.0;
		    for (int k=1; k<=mtmp; k++)
		      {
			tmp += wgt.get(k)*fvals.get(k,m1)*phi.get(k,m2);
		      }
		    Fout.set(i,m1,m2, 0.5*tmp );
		  }

            }
	  else // project onto derivatives of Legendre basis
            {
	      for (int m1=1; m1<=mlength; m1++)             
		for (int m2=1; m2<=mpoints; m2++)
		  {
		    double tmp = 0.0;
		    for (int k=1; k<=mtmp; k++)
		      {
			tmp += wgt.get(k)*fvals.get(k,m1)*phi_x.get(k,m2);
		      }
		    Fout.set(i,m1,m2, 0.5*tmp );
		  }
            }
        }
          else if(run==1)
          {


          int iint=int(global2interf.get(i));

	  double xc1 = xlow + (double(i)-1.0)*dx+0.5*dxi.get(iint,1);
          double xc2 = xlow + (double(i)-1.0)*dx+dxi.get(iint,1)+0.5*dxi.get(iint,2);

          double dxl=dxi.get(iint,1);
          double dxr=dxi.get(iint,2);

        
	  // Each of these three items needs to be private to each thread ..
	  dTensor1 xptsl(mtmp);
	  dTensor2 qvalsl(mtmp,meqn);
	  dTensor2 auxvalsl(mtmp,maux);
	  dTensor2 fvalsl(mtmp,mlength);


	  dTensor1 xptsr(mtmp);
	  dTensor2 qvalsr(mtmp,meqn);
	  dTensor2 auxvalsr(mtmp,maux);
	  dTensor2 fvalsr(mtmp,mlength);

          //SampleBasisGrad_variable(lspts,lIphi_x,dxl);
          //SampleBasisGrad_variable(rspts,rIphi_x,dxr);           
          //SampleBasisGrad_variable(lspts,lIphi_x,1.0);
          //SampleBasisGrad_variable(rspts,rIphi_x,1.0);           

          SampleBasisGrad_variable(spts,lIphi_x,1.0);
          SampleBasisGrad_variable(spts,rIphi_x,1.0);



	  // Loop over each quadrature point
	  for (int m=1; m<=mtmp; m++)
            {
	      // grid point x
	      xptsl.set( m, xc1 + 0.5*dxl*spts.get(m) );
              xptsr.set( m, xc2 + 0.5*dxr*spts.get(m) );

              
	      // Solution values (q) at each grid point
	      for (int me=1; me<=meqn; me++)
                {
		  qvalsl.set(m,me, 0.0 );
                  qvalsr.set(m,me, 0.0 );

		  for (int k=1; k<=mpoints; k++)
                    {
		      qvalsl.set(m,me, qvalsl.get(m,me) 
                                + phi.get(m,k) * qI.get(1,iint,me,k) );
                      qvalsr.set(m,me, qvalsr.get(m,me) 
                                + phi.get(m,k) * qI.get(2,iint,me,k) );
                    }
                }

	      // Auxiliary values (aux) at each grid point
	      for (int ma=1; ma<=maux; ma++)
                {
		  auxvalsl.set(m,ma, 0.0 );

		  auxvalsr.set(m,ma, 0.0 );

		  for (int k=1; k<=mpoints; k++)
                    {
		      auxvalsl.set(m,ma, auxvalsl.get(m,ma) 
				  + phi.get(m,k) * auxI.get(1,iint,ma,k) );

		      auxvalsr.set(m,ma, auxvalsr.get(m,ma) 
				  + phi.get(m,k) * auxI.get(2,iint,ma,k) );
                    }
                }
            //printf("xcl=%e xtryl= %e \n",xc1,dxl);
            //printf("xcr=%e xtryr= %e \n",xc2,dxr);
            }

	  // Call user-supplied function to set fvals
          
	  Func(xptsl,qvalsl,auxvalsl,fvalsl);
          Func(xptsr,qvalsr,auxvalsr,fvalsr);
          /*
          for (int m=1; m<=mtmp; m++)
            {
               printf("xtryl= %e \n",xptsl.get(m));
               printf("xtryr= %e \n",xptsr.get(m));
               printf("qtryl= %e \n",qvalsl.get(m,1));
               printf("qtryr= %e \n",qvalsr.get(m,1));
            }*/


          //printf("i=%d iint=%d q= %e %e \n",i,iint,qI.get(1,iint,1,1),qI.get(1,iint,1,2)); 
          //printf("2i=%d iint=%d q= %e %e \n",i,iint,Iq.qget(2,iint,1,1),qI.get(2,iint,1,2)); 

          /*
	  for (inti m=1; m<=mtmp; m++)
            {
                printf("Points HERE! %d %e %e %e %e \n",m,xptsl.get(m),fvalsl.get(m,1),xptsr.get(m),fvalsl.get(m,1));
              
             }*/
 

	  // Evaluate integrals
	  if (mopt==0) // project onto Legendre basis
            {
	      for (int m1=1; m1<=mlength; m1++)
		for (int m2=1; m2<=mpoints; m2++)
		  {
		    double tmpl = 0.0;
                    double tmpr = 0.0;
		    for (int k=1; k<=mtmp; k++)
		      {
			tmpl += wgt.get(k)*fvalsl.get(k,m1)*phi.get(k,m2);
			tmpr += wgt.get(k)*fvalsr.get(k,m1)*phi.get(k,m2);
		      }
		    FI.set(1,iint,m1,m2, 0.5*tmpl );
                    FI.set(2,iint,m1,m2, 0.5*tmpr );
		  }
            }
	  else // project onto derivatives of Legendre basis
            {

              double Ul=auxI.get(1,iint,1,1);
              double Ur=auxI.get(2,iint,1,1);
              /*
	      for (int m1=1; m1<=mlength; m1++)             
		for (int m2=1; m2<=mpoints; m2++)
		  {
		    double tmpl = 0.0;
		    double tmpr = 0.0;
		    for (int k=1; k<=mtmp; k++)
		      {
			tmpl += wgt.get(k)*fvalsl.get(k,m1)*lIphi_x.get(k,m2);
			tmpr += wgt.get(k)*fvalsr.get(k,m1)*rIphi_x.get(k,m2);
		      }
		    FI.set(1,iint,m1,m2, 0.5*tmpl );
		    FI.set(2,iint,m1,m2, 0.5*tmpr );  
		  }*/

                for (int m2=1; m2<=mpoints; m2++)
                  for (int m3=1; m3<=mpoints; m3++)
                  {

                    double tmponl = 0.0;
                    double tmponr = 0.0;

                    double tmpIl = 0.0;
                    double tmpIr = 0.0;
                    for (int k=1; k<=mtmp; k++)
                      {
                        tmpIl += wgt.get(k)*Ul*phi.get(k,m3)*lIphi_x.get(k,m2);
                        tmpIr += wgt.get(k)*Ur*phi.get(k,m3)*rIphi_x.get(k,m2);
                        tmponl += wgt.get(k)*Ul*phi.get(k,m3)*phi_x.get(k,m2);
                        tmponr += wgt.get(k)*Ur*phi.get(k,m3)*phi_x.get(k,m2);
                      }
                    // Implicit.set(iint,m1,m2,m3, Implicit.get(iint,m1,m2,m3)-0.5*tmpIl );
                    //Implicit.set(iint,m1,kmax+m2,kmax+m3, Implicit.get(iint,m1,kmax+m2,kmax+m3)-0.5*tmpIr );
                    //Implicit.set(iint,m1,m2,m3, Implicit.get(iint,m1,m2,m3)+0.5*tmpIl );
                    //Implicit.set(iint,m1,kmax+m2,kmax+m3, Implicit.get(iint,m1,kmax+m2,kmax+m3)+0.5*tmpIr );
                    Implicit.set(iint,1,m2,m3, Implicit.get(iint,1,m2,m3)-0.5*tmpIl );
                    Implicit.set(iint,1,kmax+m2,kmax+m3, Implicit.get(iint,1,kmax+m2,kmax+m3)-0.5*tmpIl );
                    Implicit.set(iint,1,2*kmax+m2,2*kmax+m3, Implicit.get(iint,1,2*kmax+m2,2*kmax+m3)-0.5*tmpIl );
                    Implicit.set(iint,1,3*kmax+m2,3*kmax+m3, Implicit.get(iint,1,3*kmax+m2,3*kmax+m3)-0.5*tmpIr );
                    Implicit.set(iint,1,4*kmax+m2,4*kmax+m3, Implicit.get(iint,1,4*kmax+m2,4*kmax+m3)-0.5*tmpIr );
                    Implicit.set(iint,1,5*kmax+m2,5*kmax+m3, Implicit.get(iint,1,5*kmax+m2,5*kmax+m3)-0.5*tmpIr );
                    //if(abs(tmpIl)>1.0e-12 || abs(tmpIr)>1.0e-12)
                    //{printf("HERE2!!!! %e %e \n",0.5*tmpIl,0.5*tmpIr);}
                  }
                 /*
                 for(int m2=1;m2<=mpoints;m2++)
                 {
                  double tmp1=0.0;
                  double tmp2=0.0;
                  for (int m3=1;m3<=mpoints;m3++)
                  {
                    double tmpIl = 0.0;
                    double tmpIr = 0.0;
                    for (int k=1; k<=mtmp; k++)
                    {
                        tmpIl += wgt.get(k)*Ul*phi.get(k,m3)*lIphi_x.get(k,m2);
                        tmpIr += wgt.get(k)*Ur*phi.get(k,m3)*rIphi_x.get(k,m2);
                    }
                   tmp1=tmp1+0.5*tmpIl*qI.get(1,iint,1,m3);
                   tmp2=tmp2+0.5*tmpIr*qI.get(2,iint,1,m3);
                  }
                  //printf("HERE left! %e \n",tmp1-FI.get(1,1,1,m2));
                  //printf("HERE right! %e \n",tmp2-FI.get(2,1,1,m2));
                  }*/ 
            }
        }

      }
    }

}
// All-purpose routine for computing the L2-projection
// of various functions onto the gradient of the Legendre basis
//     (Unstructured grid version)
//
void L2ProjectGrad_Unst(
    const dTensor2* vel_vec,
    const int istart, 
    const int iend, 
    const int QuadOrder, 
    const int BasisOrder_qin,
    const int BasisOrder_auxin,
    const int BasisOrder_fout,
    const mesh& Mesh, 
    const dTensor3* qin, 
    const dTensor3* auxin, 
    dTensor3* fout, 
    void (*Func)(const dTensor2* vel_vec,
        const dTensor2&,const dTensor2&,
        const dTensor2&,dTensor3&))
{
    // starting and ending indeces
    const int   NumElems = Mesh.get_NumElems();
    assert_ge(istart,1);
    assert_le(iend,NumElems);

    // qin variable
    assert_eq(NumElems,qin->getsize(1));
    const int     meqn = qin->getsize(2);
    const int kmax_qin = qin->getsize(3);
    assert_eq(kmax_qin,(BasisOrder_qin*(BasisOrder_qin+1))/2);

    // auxin variable
    assert_eq(NumElems,auxin->getsize(1));
    const int       maux = auxin->getsize(2);
    const int kmax_auxin = auxin->getsize(3);
    assert_eq(kmax_auxin,(BasisOrder_auxin*(BasisOrder_auxin+1))/2);

    // fout variables
    assert_eq(NumElems,fout->getsize(1));
    const int mcomps_out = fout->getsize(2);
    const int  kmax_fout = fout->getsize(3);
    assert_eq(kmax_fout,(BasisOrder_fout*(BasisOrder_fout+1))/2);

    // number of quadrature points
    assert_ge(QuadOrder,1);
    assert_le(QuadOrder,5);
    int mpoints;
    switch ( QuadOrder )
    {
        case 1:
            mpoints = 0;
            break;

        case 2:
            mpoints = 1;
            break;

        case 3:
            mpoints = 6;
            break;

        case 4:
            mpoints = 7;
            break;

        case 5:	     
            mpoints = 16;
            break;
    }

    // trivial case
    if ( QuadOrder==1 )
    {
        for (int i=istart; i<=iend; i++)
        for (int m=1; m<=mcomps_out; m++) 
        for (int k=1; k<=kmax_fout; k++) 
        {  fout->set(i,m,k, 0.0 );  }
    }
    else
    {
        const int kmax = iMax(iMax(kmax_qin,kmax_auxin),kmax_fout);
        dTensor2    spts(mpoints,2);
        dTensor1    wgts(mpoints);
        dTensor2    xpts(mpoints,2);
        dTensor2   qvals(mpoints,meqn);
        dTensor2 auxvals(mpoints,maux);
        dTensor3   fvals(mpoints,mcomps_out,2);
        dTensor2      mu(mpoints,kmax); // monomial basis (non-orthogonal)
        dTensor2     phi(mpoints,kmax); // Legendre basis (orthogonal)
        dTensor2   mu_xi(mpoints,kmax_fout);   //  xi-derivative of monomial basis (non-orthogonal)
        dTensor2  mu_eta(mpoints,kmax_fout);   // eta-derivative of monomial basis (non-orthogonal)
        dTensor2  phi_xi(mpoints,kmax_fout);   //  xi-derivative of Legendre basis (orthogonal)
        dTensor2 phi_eta(mpoints,kmax_fout);   // eta-derivative of Legendre basis (orthogonal)
        dTensor2   phi_x(mpoints,kmax_fout);   //   x-derivative of Legendre basis (orthogonal)
        dTensor2   phi_y(mpoints,kmax_fout);   //   y-derivative of Legendre basis (orthogonal)

        switch ( QuadOrder )
        {
            case 2:
                spts.set(1,1, 0.0 );
                spts.set(1,2, 0.0 );

                wgts.set(1, 0.5 );
                break;

            case 3:
                spts.set(1,1,  0.112615157582632 );
                spts.set(1,2,  0.112615157582632 );

                spts.set(2,1, -0.225230315165263 );
                spts.set(2,2,  0.112615157582632 );

                spts.set(3,1,  0.112615157582632 );
                spts.set(3,2, -0.225230315165263 );

                spts.set(4,1, -0.241757119823562 );
                spts.set(4,2, -0.241757119823562 );

                spts.set(5,1,  0.483514239647126 );
                spts.set(5,2, -0.241757119823562 );

                spts.set(6,1, -0.241757119823562 );
                spts.set(6,2,  0.483514239647126 );

                wgts.set(1, 0.1116907948390055 );
                wgts.set(2, 0.1116907948390055 );
                wgts.set(3, 0.1116907948390055 );
                wgts.set(4, 0.0549758718276610 );
                wgts.set(5, 0.0549758718276610 );
                wgts.set(6, 0.0549758718276610 );
                break;

            case 4:
                spts.set(1,1,   0.000000000000000 );
                spts.set(1,2,   0.000000000000000 );

                spts.set(2,1,   0.136808730771782 );
                spts.set(2,2,   0.136808730771782 );

                spts.set(3,1,  -0.273617461543563 );
                spts.set(3,2,   0.136808730771782 );

                spts.set(4,1,   0.136808730771782 );
                spts.set(4,2,  -0.273617461543563 );

                spts.set(5,1,  -0.232046826009877 );
                spts.set(5,2,  -0.232046826009877 );

                spts.set(6,1,   0.464093652019754 );
                spts.set(6,2,  -0.232046826009877 );

                spts.set(7,1,  -0.232046826009877 );
                spts.set(7,2,   0.464093652019754 );	 

                wgts.set(1,  0.1125000000000000 );
                wgts.set(2,  0.0661970763942530 );
                wgts.set(3,  0.0661970763942530 );
                wgts.set(4,  0.0661970763942530 );
                wgts.set(5,  0.0629695902724135 );
                wgts.set(6,  0.0629695902724135 );
                wgts.set(7,  0.0629695902724135 );
                break;

            case 5:
                spts.set(1,1,   0.000000000000000 );
                spts.set(1,2,   0.000000000000000 );

                spts.set(2,1,   0.125959254959390 );
                spts.set(2,2,   0.125959254959390 );

                spts.set(3,1,  -0.251918509918779 );
                spts.set(3,2,   0.125959254959390 );

                spts.set(4,1,   0.125959254959390 );
                spts.set(4,2,  -0.251918509918779 );

                spts.set(5,1,  -0.162764025581573 );
                spts.set(5,2,  -0.162764025581573 );

                spts.set(6,1,   0.325528051163147 );
                spts.set(6,2,  -0.162764025581573 );

                spts.set(7,1,  -0.162764025581573 );
                spts.set(7,2,   0.325528051163147 );

                spts.set(8,1,  -0.282786105016302 );
                spts.set(8,2,  -0.282786105016302 );

                spts.set(9,1,   0.565572210032605 );
                spts.set(9,2,  -0.282786105016302 );

                spts.set(10,1, -0.282786105016302 );
                spts.set(10,2,  0.565572210032605 );

                spts.set(11,1, -0.324938555923375 );
                spts.set(11,2, -0.070220503698695 );

                spts.set(12,1, -0.324938555923375 );
                spts.set(12,2,  0.395159059622071 );

                spts.set(13,1, -0.070220503698695 );
                spts.set(13,2, -0.324938555923375 );

                spts.set(14,1, -0.070220503698695 );
                spts.set(14,2,  0.395159059622071 );

                spts.set(15,1,  0.395159059622071 );
                spts.set(15,2, -0.324938555923375 );

                spts.set(16,1,  0.395159059622071 );
                spts.set(16,2, -0.070220503698695 );

                wgts.set(1,  0.0721578038388935 );
                wgts.set(2,  0.0475458171336425 );
                wgts.set(3,  0.0475458171336425 );
                wgts.set(4,  0.0475458171336425 );
                wgts.set(5,  0.0516086852673590 );
                wgts.set(6,  0.0516086852673590 );
                wgts.set(7,  0.0516086852673590 );
                wgts.set(8,  0.0162292488115990 );
                wgts.set(9,  0.0162292488115990 );
                wgts.set(10, 0.0162292488115990 );
                wgts.set(11, 0.0136151570872175 );
                wgts.set(12, 0.0136151570872175 );
                wgts.set(13, 0.0136151570872175 );
                wgts.set(14, 0.0136151570872175 );
                wgts.set(15, 0.0136151570872175 );
                wgts.set(16, 0.0136151570872175 );
                break;
        }

        // Loop over each quadrature point and construct monomial polys
        for (int m=1; m<=mpoints; m++)
        {
            // coordinates
            const double xi   = spts.get(m,1);      
            const double xi2  = xi*xi;
            const double xi3  = xi2*xi;
            const double xi4  = xi3*xi;
            const double eta  = spts.get(m,2);
            const double eta2 = eta*eta;
            const double eta3 = eta2*eta;
            const double eta4 = eta3*eta;      

            // monomial basis functions at each gaussian quadrature point
            switch( kmax )
            {
                case 15:  // fifth order		    		    
                    mu.set(m, 15, eta4     );
                    mu.set(m, 14, xi4      );
                    mu.set(m, 13, xi2*eta2 );
                    mu.set(m, 12, eta3*xi  );
                    mu.set(m, 11, xi3*eta  );

                case 10:  // fourth order
                    mu.set(m, 10, eta3     );
                    mu.set(m, 9,  xi3      );
                    mu.set(m, 8,  xi*eta2  );
                    mu.set(m, 7,  eta*xi2  );

                case 6:  // third order
                    mu.set(m, 6,  eta2     );
                    mu.set(m, 5,  xi2      );
                    mu.set(m, 4,  xi*eta   );		    

                case 3:  // second order		    
                    mu.set(m, 3, eta       );
                    mu.set(m, 2, xi        );

                case 1:  // first order
                    mu.set(m, 1, 1.0       );

                    break;		    
            }

            // Loop over each quadrature point and construct Legendre polys
            for (int i=1; i<=kmax; i++)
            {
                double tmp = 0.0;
                for (int j=1; j<=i; j++)
                {  tmp = tmp + Mmat[i-1][j-1]*mu.get(m,j);  }

                phi.set(m,i, tmp );
            }	

            // Gradient of monomial basis functions at each gaussian quadrature point
            switch( kmax_fout )
            {
                case 15:  // fifth order
                    mu_xi.set( m,15,  0.0         );
                    mu_xi.set( m,14,  4.0*xi3     );
                    mu_xi.set( m,13,  2.0*xi*eta2 );
                    mu_xi.set( m,12,  eta3        );
                    mu_xi.set( m,11,  3.0*xi2*eta );

                    mu_eta.set( m,15, 4.0*eta3    );
                    mu_eta.set( m,14, 0.0         );
                    mu_eta.set( m,13, 2.0*xi2*eta );
                    mu_eta.set( m,12, 3.0*eta2*xi );
                    mu_eta.set( m,11, xi3 );

                case 10:  // fourth order
                    mu_xi.set( m,10,  0.0        );
                    mu_xi.set( m,9,   3.0*xi2    );			
                    mu_xi.set( m,8,   eta2       );
                    mu_xi.set( m,7,   2.0*eta*xi );

                    mu_eta.set( m,10, 3.0*eta2   );
                    mu_eta.set( m,9,  0.0        );
                    mu_eta.set( m,8,  2.0*eta*xi );
                    mu_eta.set( m,7,  xi2        );

                case 6:  // third order
                    mu_xi.set( m,6,  0.0      );
                    mu_xi.set( m,5,  2.0*xi   );			
                    mu_xi.set( m,4,  eta      );

                    mu_eta.set( m,6,  2.0*eta );			
                    mu_eta.set( m,5,  0.0     );
                    mu_eta.set( m,4,  xi      );

                case 3:  // second order
                    mu_xi.set( m,3,  0.0 );
                    mu_xi.set( m,2,  1.0 );

                    mu_eta.set( m,3, 1.0 );
                    mu_eta.set( m,2, 0.0 );

                case 1:  // first order
                    mu_xi.set( m,1,  0.0 );

                    mu_eta.set( m,1, 0.0 );
                    break;
            }

            // Loop over each quadrature point and construct Legendre polys
            for (int i=1; i<=kmax_fout; i++)
            {
                double tmp1 = 0.0;
                double tmp2 = 0.0;
                for (int j=1; j<=i; j++)
                {  
                    tmp1 = tmp1 + Mmat[i-1][j-1]*mu_xi.get(m,j);  
                    tmp2 = tmp2 + Mmat[i-1][j-1]*mu_eta.get(m,j);
                }

                phi_xi.set(m,i,  tmp1 );
                phi_eta.set(m,i, tmp2 );
            }
        }

        // -------------------------------------------------------------
        // Loop over every grid cell indexed by user supplied parameters
        // described by istart...iend
        // -------------------------------------------------------------
#pragma omp parallel for
        for (int i=istart; i<=iend; i++)
        {	  
            // Find center of current cell
            const int i1 = Mesh.get_tnode(i,1);
            const int i2 = Mesh.get_tnode(i,2);
            const int i3 = Mesh.get_tnode(i,3);
            const double x1 = Mesh.get_node(i1,1);
            const double y1 = Mesh.get_node(i1,2);
            const double x2 = Mesh.get_node(i2,1);
            const double y2 = Mesh.get_node(i2,2);
            const double x3 = Mesh.get_node(i3,1);
            const double y3 = Mesh.get_node(i3,2);

            const double xc = (x1+x2+x3)/3.0;
            const double yc = (y1+y2+y3)/3.0;

            // Compute q, aux and fvals at each Gaussian Quadrature point
            // for this current cell indexed by (i,j)
            // Save results into dTensor2 qvals, auxvals and fvals.
            for (int m=1; m<=mpoints; m++)
            {
                // convert phi_xi and phi_eta derivatives
                // to phi_x and phi_y derivatives through Jacobian
                for (int k=1; k<=kmax_fout; k++)
                {
                    phi_x.set(m,k, Mesh.get_jmat(i,1,1)*phi_xi.get(m,k)
                            + Mesh.get_jmat(i,1,2)*phi_eta.get(m,k) );
                    phi_y.set(m,k, Mesh.get_jmat(i,2,1)*phi_xi.get(m,k)
                            + Mesh.get_jmat(i,2,2)*phi_eta.get(m,k) );
                }

                // point on the unit triangle
                const double s = spts.get(m,1);
                const double t = spts.get(m,2);

                // point on the physical triangle
                xpts.set(m,1, xc + (x2-x1)*s + (x3-x1)*t );
                xpts.set(m,2, yc + (y2-y1)*s + (y3-y1)*t );

                // Solution values (q) at each grid point
                for (int me=1; me<=meqn; me++)
                {
                    qvals.set(m,me, 0.0 );

                    for (int k=1; k<=kmax_qin; k++)
                    {
                        qvals.set(m,me, qvals.get(m,me) 
                                + phi.get(m,k) * qin->get(i,me,k) );
                    }
                }

                // Auxiliary values (aux) at each grid point
                for (int ma=1; ma<=maux; ma++)
                {
                    auxvals.set(m,ma, 0.0 );

                    for (int k=1; k<=kmax_auxin; k++)
                    {
                        auxvals.set(m,ma, auxvals.get(m,ma) 
                                + phi.get(m,k) * auxin->get(i,ma,k) );
                    }
                } 
            }

            // Call user-supplied function to set fvals
            Func(vel_vec, xpts, qvals, auxvals, fvals);

            // Evaluate integral on current cell (project onto Legendre basis) 
            // using Gaussian Quadrature for the integration
            for (int m1=1; m1<=mcomps_out; m1++)		
            for (int m2=1; m2<=kmax_fout; m2++)
            {
                double tmp = 0.0;
                for (int k=1; k<=mpoints; k++)
                {
                    tmp = tmp + wgts.get(k)*
                        ( fvals.get(k,m1,1)*phi_x.get(k,m2) +
                          fvals.get(k,m1,2)*phi_y.get(k,m2) );
                }
                fout->set(i, m1, m2,  2.0*tmp );
            }

        }
    }
}
Esempio n. 4
0
void ConstructA_CG2(const mesh& Mesh, FullMatrix& A)
{
  const int NumPhysElems = Mesh.get_NumPhysElems();
  const int NumBndNodes  = Mesh.get_SubNumBndNodes();
  const int Asize = Mesh.get_SubNumPhysNodes();

  assert_eq(Asize,A.get_NumRows());
  assert_eq(Asize,A.get_NumCols());
  
  dTensor1 A1(6);
  dTensor1 A2(6);
  dTensor1 A3(6);
  dTensor1 A4(6);
  dTensor1 A5(6);
  dTensor1 A6(6);

  A1.set(1, -oneninth     );
  A1.set(2,  4.0*oneninth );
  A1.set(3, -oneninth     );
  A1.set(4,  4.0*oneninth );
  A1.set(5,  4.0*oneninth );
  A1.set(6, -oneninth     );
  
  A2.set(1, -onethird     );
  A2.set(2,  0.0          );
  A2.set(3,  onethird     );
  A2.set(4, -4.0*onethird );
  A2.set(5,  4.0*onethird );
  A2.set(6,  0.0          );
  
  A3.set(1, -onethird     );
  A3.set(2, -4.0*onethird );
  A3.set(3,  0.0          );
  A3.set(4,  0.0          );
  A3.set(5,  4.0*onethird );
  A3.set(6,  onethird     );
  
  A4.set(1,  4.0          );
  A4.set(2, -4.0          );
  A4.set(3,  0.0          );
  A4.set(4, -4.0          );
  A4.set(5,  4.0          );
  A4.set(6,  0.0          );

  A5.set(1,  2.0          );
  A5.set(2, -4.0          );
  A5.set(3,  2.0          );
  A5.set(4,  0.0          );
  A5.set(5,  0.0          );
  A5.set(6,  0.0          );
  
  A6.set(1,  2.0          );
  A6.set(2,  0.0          );
  A6.set(3,  0.0          );
  A6.set(4, -4.0          );
  A6.set(5,  0.0          );
  A6.set(6,  2.0          );

  dTensor2 spts(3,2);
  spts.set(1,1,  1.0/3.0 );
  spts.set(1,2, -1.0/6.0 );
  
  spts.set(2,1, -1.0/6.0 );
  spts.set(2,2, -1.0/6.0 );
  
  spts.set(3,1, -1.0/6.0 );
  spts.set(3,2,  1.0/3.0 );
  
  dTensor1 wgts(3);
  wgts.set(1, 1.0/6.0 );
  wgts.set(2, 1.0/6.0 );
  wgts.set(3, 1.0/6.0 );
  
  // Loop over all elements in the mesh
  for (int i=1; i<=NumPhysElems; i++)
    {
      // Information for element i
      iTensor1 tt(6);
      for (int k=1; k<=6; k++)
	{  tt.set(k, Mesh.get_node_subs(i,k) );  }
      
      // Evaluate gradients of the Lagrange polynomials on Gauss quadrature points      
      dTensor2 gpx(6,3);
      dTensor2 gpy(6,3);
      
      for (int m=1; m<=3; m++)
	{
	  double  xi = spts.get(m,1);
	  double eta = spts.get(m,2);
	  
	  for (int k=1; k<=6; k++)
	    {
	      double gp_xi  = A2.get(k) + 2.0*A5.get(k)*xi + A4.get(k)*eta;
	      double gp_eta = A3.get(k) + A4.get(k)*xi + 2.0*A6.get(k)*eta;

	      gpx.set(k,m, Mesh.get_jmat(i,1,1)*gp_xi
		         + Mesh.get_jmat(i,1,2)*gp_eta );
	      gpy.set(k,m, Mesh.get_jmat(i,2,1)*gp_xi
		         + Mesh.get_jmat(i,2,2)*gp_eta );
	    }
	}

      // Entries of the stiffness matrix A
      double Area = Mesh.get_area_prim(i);
      for (int j=1; j<=6; j++)
	for (int k=1; k<=6; k++)
	  {
	    double tmp = A.get(tt.get(j),tt.get(k));
	    for (int m=1; m<=3; m++)
	      {
		tmp = tmp + 2.0*Area*wgts.get(m)*(gpx.get(j,m)*gpx.get(k,m)+gpy.get(j,m)*gpy.get(k,m));
	      }
	    A.set(tt.get(j),tt.get(k), tmp );
	  }
    }

  // Replace boundary node equations by Dirichlet boundary condition enforcement
  for (int i=1; i<=NumBndNodes; i++)
    {
      const int j=Mesh.get_sub_bnd_node(i);
      
      for (int k=1; k<=A.get_NumCols(); k++)
	{
	  A.set(j,k, 0.0 );	  
	}
      for (int k=1; k<=A.get_NumRows(); k++)
	{
	  A.set(k,j, 0.0 );
	}
      A.set(j,j, 1.0 );
    }

  // Get sparse structure representation
  A.Sparsify();
  
}
// This is the positivity preserving limiter proposed in 
// "Maximum-Principle-Satisfying and Positivity-Preserving
// High Order Discontinuous Galerkin Schemes
// for Conservation Laws on Triangular Meshes", Zhang, Xia and Shu
// J. Sci. Comput. (2012).
//
// THIS METHOD ASSUMES THAT EVERY COMPONENT OF CONSERVED VARIABLES SHOULD STAY
// POSITIVE.
//
// In order to implement this for a different scheme, one should rewrite, or
// redefine what components should remain positiive.  This will require
// reworking the control flow logic for how time step lengths are chosen.
void ApplyPosLimiter_Unst(const mesh& Mesh, const dTensor3& aux, dTensor3& q)
{

    const int NumElems      = Mesh.get_NumElems();
    const int NumPhysElems  = Mesh.get_NumPhysElems();
    const int NumEdges      = Mesh.get_NumEdges();
    const int meqn          = q.getsize(2);
    const int kmax          = q.getsize(3);
    const int maux          = aux.getsize(2);
    const int space_order   = dogParams.get_space_order();

    // Do nothing in the case of piecewise constants
    if( space_order == 1 )
    { return; }

    // ------------------------------------------------ //
    // number of points where we want to check solution //
    // ------------------------------------------------ //
    const int space_order_sq = space_order*space_order;
    const int mpts_vec[] = {0, 3*space_order_sq, 18, 3*space_order_sq, 3*space_order_sq };  // TODO - FILL IN 2ND-ORDER CASE
    const int mpoints    = mpts_vec[space_order-1];

    // ---------------------------------------------------------- //
    // sample basis at all points where we want to check solution //
    // ---------------------------------------------------------- //
    dTensor2 spts(mpoints, 2);
    void SetPositivePoints_Unst(const int& space_order, dTensor2& spts);
    SetPositivePoints_Unst(space_order, spts);

    void SamplePhiAtPositivePoints_Unst(const int& space_order, 
            const dTensor2& spts, dTensor2& phi);
    dTensor2 phi(mpoints, kmax);
    SamplePhiAtPositivePoints_Unst(space_order, spts, phi);

    // -------------------------------------------------------------- //
    // q_limited = Q1 + \theta ( q(xi,eta) - Q1 )                     //
    // where theta = min(1, |Q1| / |Q1-m|; m = min_{i} q(xi_i, eta_i) //
    // -------------------------------------------------------------- //
#pragma omp parallel for
    for(int  i=1;  i <= NumPhysElems; i++)
    for(int me=1; me <= meqn; me++)
    {

        double m = 0.0;
        for(int mp=1; mp <= mpoints; mp++)
        {
            // evaluate q at spts(mp) //
            double qnow = 0.0;
            for( int k=1; k <= kmax; k++ )
            {
                qnow += q.get(i,me,k) * phi.get(mp,k);
            }
            m = Min(m, qnow);
        }

        double theta = 0.0;
        double Q1 = q.get(i,me,1);  assert_ge( Q1, -1e-13 );
        if( fabs( Q1 - m ) < 1.0e-14 ){ theta = 1.0; }
        else{ theta = Min( 1.0, fabs( Q1 / (Q1 - m) ) ); }

        // limit q //
        for( int k=2; k <= kmax; k++ )
        {
            q.set(i,me,k, q.get(i,me,k) * theta );
        }

    }

}
// Modified version of the all purpose routine L2Project specifically written
// for projecting the "time-averaged" flux function onto the basis function.
//
// This routine also returns the coefficients of the Lax Wendroff Flux
// Function when expanded with legendre basis functions, and therefore the
// basis expansions produced by this routine can be used for all of the
// Riemann solves.
//
// ---------------------------------------------------------------------
// Inputs should have the following sizes:   
//           TODO - document the inputs here
// ---------------------------------------------------------------------
void L2ProjectLxW_Unst( const int mterms,
        const double alpha, const double beta_dt, const double charlie_dt,
        const int istart, const int iend,               // Start-stop indices
        const int QuadOrder,
        const int BasisOrder_qin,
        const int BasisOrder_auxin,
        const int BasisOrder_fout,
        const mesh& Mesh, 
        const dTensor3* qin, const dTensor3* auxin,     // state vector
        dTensor3* F, dTensor3* G,                       // time-averaged Flux function
        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) )
{    

    if( fabs( alpha ) < 1e-14 && fabs( beta_dt ) < 1e-14 && fabs( charlie_dt ) < 1e-14 )
    {
        F->setall(0.);
        G->setall(0.);
        return;
    }

    // starting and ending indices 
    const int   NumElems = Mesh.get_NumElems();
    assert_ge(istart,1);
    assert_le(iend,NumElems);

    // qin variable
    assert_eq(NumElems,qin->getsize(1));
    const int     meqn = qin->getsize(2);
    const int kmax_qin = qin->getsize(3);
    assert_eq(kmax_qin,(BasisOrder_qin*(BasisOrder_qin+1))/2);

    // auxin variable
    assert_eq(NumElems,auxin->getsize(1));
    const int       maux = auxin->getsize(2);
    const int kmax_auxin = auxin->getsize(3);
    assert_eq(kmax_auxin,(BasisOrder_auxin*(BasisOrder_auxin+1))/2);

    // fout variables
    assert_eq(NumElems,    F->getsize(1));
    const int mcomps_out = F->getsize(2);
    const int  kmax_fout = F->getsize(3);
    assert_eq(kmax_fout, (BasisOrder_fout*(BasisOrder_fout+1))/2 );

    // number of quadrature points
    assert_ge(QuadOrder, 1);
    assert_le(QuadOrder, 5);

    // Number of quadrature points
    int mpoints;
    switch( QuadOrder )
    {
        case 1:
            mpoints = 1;
            break;

        case 2:
            mpoints = 3;
            break;

        case 3:
            mpoints = 6;
            break;

        case 4:
            mpoints = 12;
            break;

        case 5:	     
            mpoints = 16;
            break;
    }

    const int kmax = iMax(iMax(kmax_qin, kmax_auxin), kmax_fout);
    dTensor2  phi(mpoints, kmax); // Legendre basis (orthogonal)
    dTensor2 spts(mpoints, 2);    // List of quadrature points
    dTensor1 wgts(mpoints);       // List of quadrature weights

    setQuadPoints_Unst( QuadOrder, wgts, spts );

    // ---------------------------------------------------------------------- //
    // Evaluate the basis functions at each point
    SetLegendreAtPoints_Unst(spts, phi);
    // ---------------------------------------------------------------------- //

    // ---------------------------------------------------------------------- //
    // First-order derivatives
    dTensor2 phi_xi (mpoints, kmax );
    dTensor2 phi_eta(mpoints, kmax );
    SetLegendreGrad_Unst( spts, phi_xi, phi_eta );
    // ---------------------------------------------------------------------- //

    // ---------------------------------------------------------------------- //
    // Second-order derivatives
    dTensor2 phi_xi2  (mpoints, kmax );
    dTensor2 phi_xieta(mpoints, kmax );
    dTensor2 phi_eta2 (mpoints, kmax );
    LegendreDiff2_Unst(spts, &phi_xi2, &phi_xieta, &phi_eta2 );
    // ---------------------------------------------------------------------- //

    // ------------------------------------------------------------- //
    // Loop over every grid cell indexed by user supplied parameters //
    // described by istart...iend, jstart...jend                     // 
    // ------------------------------------------------------------- //
#pragma omp parallel for
    for (int i=istart; i<=iend; i++)
    {

        // These need to be defined locally.  Each mesh element carries its
        // own change of basis matrix, so these need to be recomputed for
        // each element.  The canonical derivatives, phi_xi, and phi_eta can
        // be computed and shared for each element.

        // First-order derivatives
        dTensor2   phi_x(mpoints, kmax_fout);   //   x-derivative of Legendre basis (orthogonal)
        dTensor2   phi_y(mpoints, kmax_fout);   //   y-derivative of Legendre basis (orthogonal)

        // Second-order derivatives
        dTensor2   phi_xx(mpoints, kmax_fout);   //   xx-derivative of Legendre basis (orthogonal)
        dTensor2   phi_xy(mpoints, kmax_fout);   //   xy-derivative of Legendre basis (orthogonal)
        dTensor2   phi_yy(mpoints, kmax_fout);   //   yy-derivative of Legendre basis (orthogonal)

        //find center of current cell
        const int    i1 = Mesh.get_tnode(i,1);
        const int    i2 = Mesh.get_tnode(i,2);
        const int    i3 = Mesh.get_tnode(i,3);

        // Corners:
        const double x1 = Mesh.get_node(i1,1);
        const double y1 = Mesh.get_node(i1,2);
        const double x2 = Mesh.get_node(i2,1);
        const double y2 = Mesh.get_node(i2,2);
        const double x3 = Mesh.get_node(i3,1);
        const double y3 = Mesh.get_node(i3,2);

        // Center of current cell:
        const double xc = (x1+x2+x3)/3.0;
        const double yc = (y1+y2+y3)/3.0;

        // Variables that need to be written to, and therefore are 
        // created for each thread
        dTensor2 xpts   (mpoints, 2);
        dTensor2 qvals  (mpoints, meqn);
        dTensor2 auxvals(mpoints, maux);

        // local storage for Flux function its Jacobian, and the Hessian:
        dTensor3    fvals(mpoints,             meqn, 2);  // flux function (vector)
        dTensor4        A(mpoints,       meqn, meqn, 2);  // Jacobian of flux
        dTensor5        H(mpoints, meqn, meqn, meqn, 2);  // Hessian of flux

        // Compute q, aux and fvals at each Gaussian Quadrature point
        // for this current cell indexed by (i,j)
        // Save results into dTensor2 qvals, auxvals and fvals.
        for (int m=1; m<= mpoints; m++)
        {

            // convert phi_xi and phi_eta derivatives
            // to phi_x and phi_y derivatives through Jacobian
            //
            // Note that: 
            //
            //     pd_x = J11 pd_xi + J12 pd_eta and
            //     pd_y = J21 pd_xi + J22 pd_eta.
            //
            // Squaring these operators yields the second derivatives.
            for (int k=1; k<=kmax_fout; k++)
            {
                phi_x.set(m,k, Mesh.get_jmat(i,1,1)*phi_xi.get(m,k)
                             + Mesh.get_jmat(i,1,2)*phi_eta.get(m,k) );
                phi_y.set(m,k, Mesh.get_jmat(i,2,1)*phi_xi.get(m,k)
                             + Mesh.get_jmat(i,2,2)*phi_eta.get(m,k) );

                phi_xx.set(m,k, Mesh.get_jmat(i,1,1)*Mesh.get_jmat(i,1,1)*phi_xi2.get(m,k)
                              + Mesh.get_jmat(i,1,1)*Mesh.get_jmat(i,1,2)*phi_xieta.get(m,k)
                              + Mesh.get_jmat(i,1,2)*Mesh.get_jmat(i,1,2)*phi_eta2.get(m,k)
                           );

                phi_xy.set(m,k, Mesh.get_jmat(i,1,1)*Mesh.get_jmat(i,2,1)*phi_xi2.get(m,k)
                             +(Mesh.get_jmat(i,1,2)*Mesh.get_jmat(i,2,1)
                             + Mesh.get_jmat(i,1,1)*Mesh.get_jmat(i,2,2))*phi_xieta.get(m,k)
                             + Mesh.get_jmat(i,1,2)*Mesh.get_jmat(i,2,2)*phi_eta2.get(m,k)
                           );

                phi_yy.set(m,k, Mesh.get_jmat(i,2,1)*Mesh.get_jmat(i,2,1)*phi_xi2.get(m,k)
                              + Mesh.get_jmat(i,2,1)*Mesh.get_jmat(i,2,2)*phi_xieta.get(m,k)
                              + Mesh.get_jmat(i,2,2)*Mesh.get_jmat(i,2,2)*phi_eta2.get(m,k)
                           );
            }

            // point on the unit triangle
            const double s = spts.get(m,1);
            const double t = spts.get(m,2);

            // point on the physical triangle
            xpts.set(m,1, xc + (x2-x1)*s + (x3-x1)*t );
            xpts.set(m,2, yc + (y2-y1)*s + (y3-y1)*t );

            // Solution values (q) at each grid point
            for (int me=1; me<=meqn; me++)
            {
                qvals.set(m,me, 0.0 );
                for (int k=1; k<=kmax_qin; k++)
                {
                    qvals.set(m,me, qvals.get(m,me) 
                            + phi.get(m,k) * qin->get(i,me,k) );
                }
            }

            // Auxiliary values (aux) at each grid point
            for (int ma=1; ma<=maux; ma++)
            {
                auxvals.set(m,ma, 0.0 );
                for (int k=1; k<=kmax_auxin; k++)
                {
                    auxvals.set(m,ma, auxvals.get(m,ma) 
                            + phi.get(m,k) * auxin->get(i,ma,k) );
                }
            } 
        }

        // ----------------------------------------------------------------- //
        //
        // Part I:
        //
        // Project the flux function onto the basis 
        // functions.  This is the term of order O( 1 ) in the
        // "time-averaged" Taylor expansion of f and g.
        //
        // ----------------------------------------------------------------- //

        // Call user-supplied function to set fvals
        FluxFunc(xpts, qvals, auxvals, fvals);

        // Evaluate integral on current cell (project onto Legendre basis) 
        // using Gaussian Quadrature for the integration
        //
        // TODO - do we want to optimize this by looking into using transposes,
        // as has been done in the 2d/cart code? (5/14/2014) -DS
        for (int me=1; me<=mcomps_out; me++)		
        for (int k=1; k<=kmax; k++)
        {
            double tmp1 = 0.0;
            double tmp2 = 0.0;
            for (int mp=1; mp <= mpoints; mp++)
            {
                tmp1 += wgts.get(mp)*fvals.get(mp, me, 1)*phi.get(mp, k);
                tmp2 += wgts.get(mp)*fvals.get(mp, me, 2)*phi.get(mp, k);
            }
            F->set(i, me, k,  2.0*tmp1 );
            G->set(i, me, k,  2.0*tmp2 );
        }

        // ----------------------------------------------------------------- //
        //
        // Part II:
        //
        // Project the derivative of the flux function onto the basis 
        // functions.  This is the term of order O( \dt ) in the
        // "time-averaged" Taylor expansion of f and g.
        //
        // ----------------------------------------------------------------- //

        // ----------------------------------------------------------------- //
        // Compute pointwise values for fx+gy:
        //
        // We can't multiply fvals of f, and g,
        // by alpha, otherwise we compute the wrong derivative here!
        //
        dTensor2 fx_plus_gy( mpoints, meqn ); fx_plus_gy.setall(0.);
        for( int mp=1; mp <= mpoints; mp++ )
        for( int me=1; me <= meqn; me++ )
        {
            double tmp = 0.;
            for( int k=2; k <= kmax; k++ )                
            {
                tmp += F->get( i, me, k ) * phi_x.get( mp, k );
                tmp += G->get( i, me, k ) * phi_y.get( mp, k );
            }
            fx_plus_gy.set( mp, me, tmp );
        }

        // Call user-supplied Jacobian to set f'(q) and g'(q):
        DFluxFunc( xpts, qvals, auxvals, A );

        // place-holders for point values of
        // f'(q)( fx + gy ) and g'(q)( fx + gy ):
        dTensor2 dt_times_fdot( mpoints, meqn );
        dTensor2 dt_times_gdot( mpoints, meqn );

        // Compute point values for f'(q) * (fx+gy) and g'(q) * (fx+gy):
        for( int mp=1; mp <= mpoints; mp++ )
        for( int m1=1; m1 <= meqn; m1++ )
        {
            double tmp1 = 0.;
            double tmp2 = 0.;
            for( int m2=1; m2 <= meqn; m2++ )
            {
                tmp1 += A.get(mp, m1, m2, 1 ) * fx_plus_gy.get(mp, m2);
                tmp2 += A.get(mp, m1, m2, 2 ) * fx_plus_gy.get(mp, m2);
            }
            dt_times_fdot.set( mp, m1, -beta_dt*tmp1 );
            dt_times_gdot.set( mp, m1, -beta_dt*tmp2 );
        }

        // ---  Third-order terms --- //
        //
        // These are the terms that are O( \dt^2 ) in the "time-averaged"
        // flux function.
        dTensor2 f_tt( mpoints, meqn );   f_tt.setall(0.);
        dTensor2 g_tt( mpoints, meqn );   g_tt.setall(0.);
        if( mterms > 2 )
        {

            // Construct the Hessian at each (quadrature) point
            D2FluxFunc( xpts, qvals, auxvals, H );

            // Second-order derivative terms
            dTensor2 qx_vals (mpoints, meqn);   qx_vals.setall(0.);
            dTensor2 qy_vals (mpoints, meqn);   qy_vals.setall(0.);

            dTensor2 fxx_vals(mpoints, meqn);   fxx_vals.setall(0.);
            dTensor2 gxx_vals(mpoints, meqn);   gxx_vals.setall(0.);

            dTensor2 fxy_vals(mpoints, meqn);   fxy_vals.setall(0.);
            dTensor2 gxy_vals(mpoints, meqn);   gxy_vals.setall(0.);

            dTensor2 fyy_vals(mpoints, meqn);   fyy_vals.setall(0.);
            dTensor2 gyy_vals(mpoints, meqn);   gyy_vals.setall(0.);

            for( int m=1; m <= mpoints; m++ )
            for( int me=1; me <= meqn; me++ )
            {
                // Can start at k=1, because derivative of a constant is
                // zero.
                double tmp_qx = 0.;
                double tmp_qy = 0.;
                for( int  k=2; k <= kmax; k++   )
                {
                    tmp_qx += phi_x.get(m,k) * qin->get(i,me,k);
                    tmp_qy += phi_y.get(m,k) * qin->get(i,me,k);
                }
                qx_vals.set(m,me, tmp_qx );
                qy_vals.set(m,me, tmp_qy );

                // First non-zero terms start at third-order.
                for( int  k=4; k <= kmax; k++   )
                {
                    fxx_vals.set(m,me, fxx_vals.get(m,me) + phi_xx.get(m,k)*F->get(i,me,k) );
                    gxx_vals.set(m,me, gxx_vals.get(m,me) + phi_xx.get(m,k)*G->get(i,me,k) );

                    fxy_vals.set(m,me, fxy_vals.get(m,me) + phi_xy.get(m,k)*F->get(i,me,k) );
                    gxy_vals.set(m,me, gxy_vals.get(m,me) + phi_xy.get(m,k)*G->get(i,me,k) );

                    fyy_vals.set(m,me, fyy_vals.get(m,me) + phi_yy.get(m,k)*F->get(i,me,k) );
                    gyy_vals.set(m,me, gyy_vals.get(m,me) + phi_yy.get(m,k)*G->get(i,me,k) );
                }

            }

            // ----------------------------------- //
            // Part I: Compute (f_x + g_y)_{,t}
            // ----------------------------------- //

            // Compute terms that get multiplied by \pd2{ f }{ q } and \pd2{ g }{ q }.
            dTensor2 fx_plus_gy_t( mpoints, meqn );
            for( int  m = 1;  m <= mpoints; m++ )
            for( int me = 1; me <= meqn; me++   )
            {

                double tmp = 0.;

                // Terms that get multiplied by the Hessian:
                for( int m1=1; m1 <= meqn; m1++ )
                for( int m2=1; m2 <= meqn; m2++ )
                {

                    tmp += H.get(m,me,m1,m2,1)*qx_vals.get(m,m1)*fx_plus_gy.get(m,m2);
                    tmp += H.get(m,me,m1,m2,2)*qy_vals.get(m,m1)*fx_plus_gy.get(m,m2);
                }

                // Terms that get multiplied by f'(q) and g'(q):
                for( int m1=1; m1 <= meqn; m1++ )
                {

                    tmp += A.get(m,me,m1,1)*( fxx_vals.get(m,m1)+gxy_vals.get(m,m1) );
                    tmp += A.get(m,me,m1,2)*( fxy_vals.get(m,m1)+gyy_vals.get(m,m1) );
                }

                fx_plus_gy_t.set( m, me, tmp );
            }

            // ----------------------------------- //
            // Part II: Compute 
            //      f'(q) * fx_plus_gy_t and 
            //      g'(q) * fx_plus_gy_t
            // ----------------------------------- //

            // Add in the third term that gets multiplied by A:
            for( int m=1; m <= mpoints; m++ )
            for( int m1=1; m1 <= meqn; m1++ )
            {
                double tmp1 = 0.;
                double tmp2 = 0.;
                for( int m2=1; m2 <= meqn; m2++ )
                {
                    tmp1 += A.get(m,m1,m2,1)*fx_plus_gy_t.get(m,m2);
                    tmp2 += A.get(m,m1,m2,2)*fx_plus_gy_t.get(m,m2);
                }
                f_tt.set( m, m1, tmp1 );
                g_tt.set( m, m1, tmp2 );
            }

            // ----------------------------------------------- //
            // Part III: Add in contributions from
            //      f''(q) * (fx_plus_gy, fx_plus_gy ) and 
            //      g''(q) * (fx_plus_gy, fx_plus_gy ).
            // ----------------------------------------------- //
            for( int m =1; m <= mpoints; m++ )
            for( int me =1; me <= meqn; me++ )
            {
                double tmp1 = 0.;
                double tmp2 = 0.;

                // Terms that get multiplied by the Hessian:
                for( int m1=1; m1 <= meqn; m1++ )
                for( int m2=1; m2 <= meqn; m2++ )
                {
                    tmp1 += H.get(m,me,m1,m2,1)*fx_plus_gy.get(m,m1)*fx_plus_gy.get(m,m2);
                    tmp2 += H.get(m,me,m1,m2,2)*fx_plus_gy.get(m,m1)*fx_plus_gy.get(m,m2);
                }

                f_tt.set( m, me, f_tt.get(m,me) + tmp1 );
                g_tt.set( m, me, g_tt.get(m,me) + tmp2 );
            }

        } // End of computing "third"-order terms

        // ---------------------------------------------------------- //
        // 
        // Construct basis coefficients (integrate_on_current_cell)
        //
        // ---------------------------------------------------------- //
        for (int me=1; me<=mcomps_out; me++)		
        for (int k=1; k<=kmax; k++)
        {

            double tmp1 = 0.0;
            double tmp2 = 0.0;
            for (int mp=1; mp<=mpoints; mp++)
            {
                tmp1 += wgts.get(mp)*phi.get(mp,k)*(
                    dt_times_fdot.get(mp, me) + charlie_dt*f_tt.get(mp, me) );
                tmp2 += wgts.get(mp)*phi.get(mp,k)*(
                    dt_times_gdot.get(mp, me) + charlie_dt*g_tt.get(mp, me) );
            }
            F->set(i,me,k,  F->get(i,me,k) + 2.0*tmp1 );
            G->set(i,me,k,  G->get(i,me,k) + 2.0*tmp2 );

        }

    }

}
//////////////////////////////////////////////////////////////////////////////
// Function for stepping advection equation forward in time.
//
// The advection equation: q_t + u q_x = 0.  
//
// It is assumed that aux(1,1,1) = u is constant.
//
//////////////////////////////////////////////////////////////////////////////
void StepAdvecFluxForm(const double& dt, const dTensor2& node,
  dTensorBC3& auxvals, dTensorBC1& smax,
  const dTensorBC3& qold, dTensorBC3& qnew)
{

    void SetBndValues(const dTensor2& node, dTensorBC3& aux, dTensorBC3& q);
    SetBndValues(node, auxvals, qnew);

    //-local parameters -----------------------------------------------------//
    const int melems  = qnew.getsize(1);     //number of elements in grid
    const int meqn    = qnew.getsize(2);     //number of equations
    const int kmax    = qnew.getsize(3);     //number of polynomials
    const int mbc     = qnew.getmbc();       //number of ghost cells
    //-----------------------------------------------------------------------//

    //save the center of each grid cell
    const double dx = node.get(2,1)-node.get(1,1);
    const double speed = auxvals.get(1,1,1);

    for(int j=1-mbc; j<=melems+mbc; j++)
    { smax.set(j, Max(smax.get(j), fabs(speed) ) ); }

    // compute quadrature points for where Q needs to be sampled
    const double s_area = 2.0;
    const double large_eta = speed*dt/dx;

    // integration points and weights (for interior)
    const int mpts = 5;

    dTensor1 wgt( mpts ), spts( mpts );
    dTensor2 phi( mpts, 5), phi_x(mpts, 5);
    if( kmax > 1 )
    {
        void setGaussPoints1d(dTensor1& x1d, dTensor1& w1d);
        void evaluateLegendrePolys( 
                const double dx, const dTensor1& spts, dTensor2& phi, dTensor2& phi_x);

        setGaussPoints1d( spts, wgt );
        evaluateLegendrePolys(dx, spts, phi, phi_x);
    }

#pragma omp parallel for
    for(int i=1; i<=melems; i++)
    {

        //loop over each equation
        for(int me=1; me<= meqn; me++)
        {

            dg_cell* dgc = new dg_cell();

            for( int k=1; k <= kmax; k++)
            {

                double qnp1 = qold.get(i,me,k);

                if( k > 1 )
                {
                    // interior integral
                    for( int m=1; m <= mpts; m++ )
                    {

                        double a   = spts.get(m) - 2.0 * large_eta;
                        double b   = spts.get(m);

                        int ishift = get_shift_index( a );

                        double integral = 0.0;
                        if( ishift == 0 )
                        {
                            // no shift takes place, can simply integrate from a to b
                            for( int kq = 1; kq <= kmax; kq++ )
                            {
                                integral += qold.get(i, me, kq) * 
                                    dgc->integratePhi( a, b, kq );
                            }

                        }
                        else if( ishift < 0 )
                        {

                            // integral at the shifted value
                            for( int kq = 1; kq <= kmax; kq++ )
                            {
                                integral += qold.get(i+ishift, me, kq) * 
                                    dgc->integratePhi( shift_xi(a), 1.0, kq );
                            }

                            // integrals between i and ishift
                            for( int n=-1; n > ishift; n-- )
                            { integral += qold.get(i + n, meqn, 1) * dgc->integratePhi(-1.0, 1.0, 1); }

                            // integral inside current cell
                            for( int kq = 1; kq <= kmax; kq++ )
                            {
                                integral += qold.get(i, me, kq) * 
                                    dgc->integratePhi( -1.0, spts.get(m), kq );
                            }

                        }
                        else
                        {
                            printf("   StepAdvecFluxForm.cpp problem can't handle negative velocities yet\n");
                            exit(1);
                        }

                        qnp1 += 0.25 * dx * wgt.get(m) * phi_x.get(m,k) * integral;

                    }
                }

                // left flux
                double a = -1.0 - 2.0 * large_eta;
                int ishift = get_shift_index( a );

                double Fm = 0.0;
                if( ishift < 0 )
                {
                    for( int kq = 1; kq <= kmax; kq++ )
                    {
                        Fm += qold.get(i+ishift, me, kq) * 
                            dgc->integratePhi( shift_xi(a), 1.0, kq ) / 2.0;
                    }
                    for( int n=-1; n > ishift; n-- )
                    {
                        Fm += qold.get(i+n, me, 1);
                    }
                }
                Fm *= sqrt(2*k-1) * pow(-1, k+1 );

                // right flux
                double Fp = 0.0;
                a += 2.0;
                ishift = get_shift_index( a );
                if( ishift < 1 )
                {
                    for( int kq = 1; kq <= kmax; kq++ )
                    {
                        Fp += qold.get(i+ishift, me, kq) * 
                            dgc->integratePhi( shift_xi(a), 1.0, kq ) / 2.0;
                    }
                }
                for( int n=0; n > ishift; n-- )
                { Fp += qold.get(i+n, me, 1); }
                Fp *= sqrt(2*k-1);

                qnew.set(i, me, k, qnp1 - ( Fp - Fm ) );

            }

            delete dgc;

        }//end of loop over each cell
    }//end of loop over each eqn  

    void SetBndValues(const dTensor2& node, dTensorBC3& aux, dTensorBC3& q);
    SetBndValues(node, auxvals, qnew);

}