/************************************************************ Step This is where knowledge of physical systems comes in handy. For every vertex the surface tension is computed as the cumulative sum of the difference between the vertex height and its neighbors. This data is fed into the change in velocity. The other values added are for damped oscillation (one is a proportional control and the other is differential) and so the three physical quantities accounted for are elasticity, viscosity, and surface tension. Height is just incremented by time*velocity. ************************************************************/ void WaterField::Step(float time) { int i, j, k, l, mi, ni, mj, nj; float cumulativeTension = 0; int calRadius = 1; for(i=0; i<myXdivs; i++) for(j=0; j<myYdivs; j++) { cumulativeTension = 0; myPoints[i][j].avecolor = 0; ni = i-calRadius > 0 ? i-calRadius : 0;// ni = iMax(0,i-calRadius); mi = iMin(myXdivs-1, i+calRadius); nj = iMax(0,j-calRadius); mj = iMin(myYdivs-1, j+calRadius); /*int numCount = ((mi-ni+1)*(mj-nj+1)); //numCount = 1.0f; int rcum = (numCount/2) << 16, gcum = (numCount/2) << 8, bcum = numCount/2;*/ for(k=ni; k<=mi; k++) for(l=nj; l<=mj; l++) { cumulativeTension += myPoints[k][l].height- myPoints[i][j].height; /*rcum += myPoints[k][l].color & 0xFF0000; gcum += myPoints[k][l].color & 0x00FF00; bcum += myPoints[k][l].color & 0x0000FF;*/ // myPoints[i][j].avecolor = AddColor(myPoints[i][j].avecolor, myPoints[k][l].color, numCount);//1.0f/numCount++); } /*myPoints[i][j].avecolor = (rcum/numCount) && 0xFF0000 + (gcum/numCount) && 0xFF00 + (bcum/numCount) && 0xFF; //myPoints[i][j].avecolor = *((DWORD*)&(LerpColor2(*((Color*)&(myPoints[i][j].avecolor)), black, 0.75f)));//1.0f/numCount++); //myPoints[i][j].avecolor = LerpColor(myPoints[i][j].avecolor, black, 0.75f);//1.0f/numCount++); for(k=ni; k<=mi; k++) { cumulativeTension += myPoints[k][j].height- myPoints[i][j].height; myPoints[i][j].avecolor = AddColor(myPoints[i][j].avecolor, myPoints[k][j].color, numCount +0.5f);//1.0f/numCount++); //AddColor2(*((Color*)&(myPoints[i][j].avecolor)), *((Color*)&(myPoints[k][j].color)), numCount);//1.0f/numCount++); } for(l=nj; l<=mj; l++) { cumulativeTension += myPoints[i][l].height- myPoints[i][j].height; myPoints[i][j].avecolor = AddColor(myPoints[i][j].avecolor, myPoints[i][l].color, numCount+0.5f);//1.0f/numCount++); //AddColor2(*((Color*)&(myPoints[i][j].avecolor)), *((Color*)&(myPoints[i][l].color)), numCount);//1.0f/numCount++); }*/ myPoints[i][j].velocity +=m_elasticity*(myHeight-myPoints[i][j].height) - m_viscosity * myPoints[i][j].velocity + m_tension*cumulativeTension; } for(i=0; i<myXdivs; i++) for(j=0; j<myYdivs; j++) { myPoints[i][j].height += myPoints[i][j].velocity*time; //myPoints[i][j].color = LerpColor3(myPoints[i][j].color, myPoints[i][j].color, m_blendability); SetNormalForPoint(i,j); } }
void* System::alignedMalloc(size_t bytes, size_t alignment) { alwaysAssertM(isPow2(alignment), "alignment must be a power of 2"); // We must align to at least a word boundary. alignment = iMax((int)alignment, sizeof(void *)); // Pad the allocation size with the alignment size and the // size of the redirect pointer. size_t totalBytes = bytes + alignment + sizeof(intptr_t); void* truePtr = System::malloc(totalBytes); if (!truePtr) { // malloc returned NULL return NULL; } debugAssert(isValidHeapPointer(truePtr)); #ifdef G3D_WIN32 // The blocks we return will not be valid Win32 debug heap // pointers because they are offset // debugAssert(_CrtIsValidPointer(truePtr, totalBytes, TRUE) ); #endif // The return pointer will be the next aligned location (we must at least // leave space for the redirect pointer, however). char* alignedPtr = ((char*)truePtr)+ sizeof(intptr_t); #if 0 // 2^n - 1 has the form 1111... in binary. uint32 bitMask = (alignment - 1); // Advance forward until we reach an aligned location. while ((((intptr_t)alignedPtr) & bitMask) != 0) { alignedPtr += sizeof(void*); } #else alignedPtr += alignment - (((intptr_t)alignedPtr) & (alignment - 1)); // assert((alignedPtr - truePtr) + bytes <= totalBytes); #endif debugAssert((alignedPtr - truePtr) + bytes <= totalBytes); // Immediately before the aligned location, write the true array location // so that we can free it correctly. intptr_t* redirectPtr = (intptr_t*)(alignedPtr - sizeof(intptr_t)); redirectPtr[0] = (intptr_t)truePtr; debugAssert(isValidHeapPointer(truePtr)); #ifdef G3D_WIN32 debugAssert( _CrtIsValidPointer(alignedPtr, bytes, TRUE) ); #endif return (void*)alignedPtr; }
void GuiDropDownList::render(RenderDevice* rd, const GuiSkinRef& skin) const { if (m_visible) { if (m_useStringList) { // If there are no elements in the list, display the empty string const std::string& str = (m_stringListValue->size() > 0) ? (*m_stringListValue)[iMax(0, iMin(m_stringListValue->size() - 1, *m_indexValue))] : ""; skin->renderDropDownList(m_rect, m_enabled, focused() || mouseOver(), m_selecting, str, m_caption); } else { // If there are no elements in the list, display the empty string const GuiCaption& str = (m_captionListValue->size() > 0) ? (*m_captionListValue)[iMax(0, iMin(m_captionListValue->size() - 1, *m_indexValue))] : ""; skin->renderDropDownList(m_rect, m_enabled, focused() || mouseOver(), m_selecting, str, m_caption); } } }
BumpMap::Settings::Settings(const Any& any) { *this = Settings(); any.verifyName("BumpMap::Settings"); for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) { const std::string& key = toLower(it->key); if (key == "iterations") { iterations = iMax(0, iRound(it->value.number())); } else if (key == "scale") { scale = it->value; } else if (key == "bias") { bias = it->value; } else { any.verify(false, "Illegal key: " + it->key); } } }
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 ); } } } }
GlutWindow::GlutWindow(const GWindowSettings& s) { _mouseVisible = true; _windowTitle = "G3D"; settings = s; currentGlutWindow = this; // Set window size and position glutInitWindowSize(settings.width, settings.height); glutInitWindowPosition(settings.x, settings.y); glutInitDisplayMode(computeGlutFlags(settings)); if (! glutInitialized) { glutInitDummy(); glutInitialized = true; } glutWindowHandle = glutCreateWindow("G3D"); if (settings.center) { glutPositionWindow( iMax(0,(glutGet(GLUT_SCREEN_WIDTH) - settings.width) / 2), iMax(0,(glutGet(GLUT_SCREEN_HEIGHT) - settings.height) / 2)); } if (settings.fullScreen) { glutFullScreen(); } // See what settings we actually got settings.alphaBits = glutGet(GLUT_WINDOW_ALPHA_SIZE); settings.depthBits = glutGet(GLUT_WINDOW_DEPTH_SIZE); // No gamma ramp on Glut windows settings.lightSaturation = 1.0; settings.stencilBits = glutGet(GLUT_WINDOW_STENCIL_SIZE); settings.fsaaSamples = glutGet(GLUT_WINDOW_NUM_SAMPLES); settings.stereo = (glutGet(GLUT_WINDOW_STEREO) != 0); mouseButtons = 0; #ifdef G3D_LINUX if (glXGetCurrentDisplay != NULL) { G3D::_internal::x11Display = glXGetCurrentDisplay(); } if (glXGetCurrentDrawable != NULL) { G3D::_internal::x11Window = glXGetCurrentDrawable(); } #endif glutReshapeFunc(g_reshape); glutKeyboardFunc(g_keyboard); glutKeyboardUpFunc(g_keyboardup); glutSpecialFunc(g_keyboardspecial); glutSpecialUpFunc(g_keyboardspecialup); glutMotionFunc(g_mousemotion); glutPassiveMotionFunc(g_mousemotion); glutMouseFunc(g_mousebtn); glutDisplayFunc(g_draw); }
void VideoOutput::initialize(const String& filename, const Settings& settings) { // helper for exiting VideoOutput construction (exceptions caught by static ref creator) #define throwException(exp, msg) if (!(exp)) { throw String(msg); } debugAssert(settings.width > 0); debugAssert(settings.height > 0); debugAssert(settings.fps > 0); #ifndef G3D_NO_FFMPEG // initialize list of available muxers/demuxers and codecs in ffmpeg av_register_all(); m_filename = filename; m_settings = settings; // see if ffmpeg can support this muxer and setup output format m_avOutputFormat = av_guess_format(NULL, filename.c_str(), NULL); throwException(m_avOutputFormat, ("Error initializing FFmpeg in guess_format.")); // set the codec id m_avOutputFormat->video_codec = static_cast<AVCodecID>(m_settings.codec); // create format context which controls writing the file m_avFormatContext = avformat_alloc_context(); throwException(m_avFormatContext, ("Error initializing FFmpeg in av_alloc_format_context.")); // attach format to context m_avFormatContext->oformat = m_avOutputFormat; strncpy(m_avFormatContext->filename, filename.c_str(), sizeof(m_avFormatContext->filename)); // add video stream 0 m_avStream = avformat_new_stream(m_avFormatContext, 0); throwException(m_avStream, ("Error initializing FFmpeg in av_new_stream.")); // setup video stream m_avStream->codec->codec_id = m_avOutputFormat->video_codec; m_avStream->codec->codec_type = AVMEDIA_TYPE_VIDEO; // find and open required codec AVCodec* codec = avcodec_find_encoder(m_avStream->codec->codec_id); throwException(codec, format("Could not find an %s (%d) encoder on this machine.", toString(static_cast<InternalCodecID>(m_avStream->codec->codec_id)), m_avStream->codec->codec_id)); // finish setting codec parameters m_avStream->codec->bit_rate = m_settings.bitrate * 10; m_avStream->time_base.den = 30; m_avStream->time_base.num = 1; m_avStream->codec->time_base.den = 30; m_avStream->codec->time_base.num = 1; m_avStream->codec->width = m_settings.width; m_avStream->codec->height = m_settings.height; // set codec input format if (m_settings.codec == CODEC_ID_RAWVIDEO) { m_avStream->codec->pix_fmt = ConvertImageFormatToPixelFormat(m_settings.raw.format); throwException(m_avStream->codec->pix_fmt != PIX_FMT_NONE, ("Error initializing FFmpeg setting raw video input format.")); } else { m_avStream->codec->pix_fmt = codec->pix_fmts[0]; } // set the fourcc if (m_settings.fourcc != 0) { m_avStream->codec->codec_tag = m_settings.fourcc; } // some formats want stream headers to be separate if (m_avOutputFormat->flags & AVFMT_GLOBALHEADER) { m_avStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; } //set a bunch of obscure presets that stop ffmpeg from breaking m_avStream->codec->rc_max_rate = 0; m_avStream->codec->rc_buffer_size = 0; m_avStream->codec->gop_size = 40; m_avStream->codec->max_b_frames = 3; m_avStream->codec->b_frame_strategy = 1; m_avStream->codec->coder_type = 1; m_avStream->codec->me_cmp = 1; m_avStream->codec->me_range = 16; m_avStream->codec->qmin = 10; m_avStream->codec->qmax = 51; m_avStream->codec->scenechange_threshold = 40; m_avStream->codec->flags |= CODEC_FLAG_LOOP_FILTER; m_avStream->codec->me_method = ME_HEX; m_avStream->codec->me_subpel_quality = 5; m_avStream->codec->i_quant_factor = 0.71; m_avStream->codec->qcompress = 0.6; m_avStream->codec->max_qdiff = 4; m_avStream->codec->profile = FF_PROFILE_H264_BASELINE; int avRet = avcodec_open2(m_avStream->codec, codec, NULL); throwException(avRet >= 0, ("Error initializing FFmpeg in avcodec_open")); // create encoding buffer - just allocate largest possible for now (3 channels) m_avEncodingBufferSize = iMax(m_settings.width * m_settings.height * 3, 512 * 1024); m_avEncodingBuffer = static_cast<uint8*>(av_malloc(m_avEncodingBufferSize)); // create buffer to hold converted input frame if the codec needs a conversion int inputBufferSize = avpicture_get_size(m_avStream->codec->pix_fmt, m_settings.width, m_settings.height); m_avInputBuffer = static_cast<uint8*>(av_malloc(inputBufferSize)); throwException(m_avInputBuffer, ("Error initializing FFmpeg in av_malloc")); m_avInputFrame = avcodec_alloc_frame(); throwException(m_avInputFrame, ("Error initializing FFmpeg in avcodec_alloc_frame")); avpicture_fill(reinterpret_cast<AVPicture*>(m_avInputFrame), m_avInputBuffer, m_avStream->codec->pix_fmt, m_settings.width, m_settings.height); // open output file for writing using ffmpeg avRet = avio_open(&m_avFormatContext->pb, filename.c_str(), AVIO_FLAG_WRITE); throwException(avRet >= 0, ("Error opening FFmpeg video file with url_fopen")); // start the stream avRet = avformat_write_header(m_avFormatContext, NULL); // make sure the file is closed on error if (avRet < 0) { // abort closes and removes the output file abort(); throwException(false, ("Error initializing and writing FFmpeg video file.")); } #endif m_isInitialized = true; }
bool CameraControlWindow::onEvent(const GEvent& event) { // Allow super class to process the event if (GuiWindow::onEvent(event)) { return true; } // Accelerator key for toggling camera control. Active even when the window is hidden. if ((event.type == GEventType::KEY_DOWN) && (event.key.keysym.sym == GKey::F2)) { manualOperation = ! manualOperation; sync(); return true; } if (! visible()) { return false; } // Special buttons if (event.type == GEventType::GUI_ACTION) { GuiControl* control = event.gui.control; if (control == drawerButton) { // Change the window size m_expanded = ! m_expanded; morphTo(Rect2D::xywh(rect().x0y0(), m_expanded ? bigSize : smallSize)); drawerButton->setCaption(m_expanded ? drawerCollapseCaption : drawerExpandCaption); } else if (control == trackList) { if (trackFileArray[trackFileIndex] != untitled) { // Load the new spline loadSpline(trackFileArray[trackFileIndex] + ".trk"); // When we load, we lose our temporarily recorded spline, // so remove that display from the menu. if (trackFileArray.last() == untitled) { trackFileArray.remove(trackFileArray.size() - 1); } } } else if (control == playButton) { // Take over manual operation manualOperation = true; // Restart at the beginning of the path trackManipulator->setTime(0); } else if ((control == recordButton) || (control == cameraLocationTextBox)) { // Take over manual operation and reset the recording manualOperation = true; trackManipulator->clear(); trackManipulator->setTime(0); // Select the untitled path if ((trackFileArray.size() == 0) || (trackFileArray.last() != untitled)) { trackFileArray.append(untitled); } trackFileIndex = trackFileArray.size() - 1; saveButton->setEnabled(true); } else if (control == saveButton) { // Save std::string saveName; if (_internal::SaveDialog::getFilename(saveName, this)) { saveName = filenameBaseExt(trimWhitespace(saveName)); if (saveName != "") { saveName = saveName.substr(0, saveName.length() - filenameExt(saveName).length()); BinaryOutput b(saveName + ".trk", G3D_LITTLE_ENDIAN); trackManipulator->spline().serialize(b); b.commit(); updateTrackFiles(); // Select the one we just saved trackFileIndex = iMax(0, trackFileArray.findIndex(saveName)); saveButton->setEnabled(false); } } } sync(); } else if (trackManipulator->mode() == UprightSplineManipulator::RECORD_KEY_MODE) { // Check if the user has added a point yet sync(); } return false; }
void GuiFunctionBox::drawSpline(RenderDevice* rd, const GuiThemeRef& skin) const { (void)skin; int N = iMax((int)(m_bounds.width() / 4), 30); # if 0 // Debugging code for looking at the slope of the curve // Show desired tangents in green rd->beginPrimitive(PrimitiveType::LINES); rd->setColor(Color3::green() * 0.5); for (int j = 0; j < m_spline->control.size(); ++j) { float t, v, x, y; int i; i = j - 1; m_spline->getControl(i, t, v); x = m_bounds.x0() + m_bounds.width() * (t - m_minTime) / (m_maxTime - m_minTime); y = m_bounds.y1() - (v - m_minValue) / m_scale.y; Vector2 va(x, y); i = j; m_spline->getControl(i, t, v); x = m_bounds.x0() + m_bounds.width() * (t - m_minTime) / (m_maxTime - m_minTime); y = m_bounds.y1() - (v - m_minValue) / m_scale.y; Vector2 vb(x, y); i = j + 1; m_spline->getControl(i, t, v); x = m_bounds.x0() + m_bounds.width() * (t - m_minTime) / (m_maxTime - m_minTime); y = m_bounds.y1() - (v - m_minValue) / m_scale.y; Vector2 vc(x, y); Vector2 tangent = (vc - va).direction() * m_bounds.width() / (2 * m_spline->control.size()); rd->sendVertex(vb - tangent); rd->sendVertex(vb + tangent); } rd->endPrimitive(); // Show true tangents in blue rd->beginPrimitive(PrimitiveType::LINES); rd->setColor(Color3::blue()); for (int i = 1; i < m_spline->control.size() - 1; ++i) { float t, v, x, y; float dt = (m_spline->time[i + 1] - m_spline->time[i - 1]) / 10; t = m_spline->time[i] - dt; v = m_spline->evaluate(t); x = m_bounds.x0() + m_bounds.width() * (t - m_minTime) / (m_maxTime - m_minTime); y = m_bounds.y1() - (v - m_minValue) / m_scale.y; Vector2 va(x, y); t = m_spline->time[i]; v = m_spline->control[i]; x = m_bounds.x0() + m_bounds.width() * (t - m_minTime) / (m_maxTime - m_minTime); y = m_bounds.y1() - (v - m_minValue) / m_scale.y; Vector2 vb(x, y); t = m_spline->time[i] + dt; v = m_spline->evaluate(t); x = m_bounds.x0() + m_bounds.width() * t - (m_minTime) / (m_maxTime - m_minTime); y = m_bounds.y1() - (v - m_minValue) / m_scale.y; Vector2 vc(x, y); Vector2 tangent = (vc - va).direction() * m_bounds.width() / (2 * m_spline->control.size()); rd->sendVertex(vb - tangent); rd->sendVertex(vb + tangent); } rd->endPrimitive(); # endif rd->beginPrimitive(PrimitiveType::LINE_STRIP); rd->setColor(m_splineColor); for (int i = -2; i < N + 2; ++i) { float t = (m_maxTime - m_minTime) * i / (N - 1.0f) + m_minTime; float v = m_spline->evaluate(t); float x = m_bounds.x0() + m_bounds.width() * i / (N - 1.0f); float y = m_bounds.y1() - (v - m_minValue) / m_scale.y; rd->sendVertex(Vector2(x, y)); } rd->endPrimitive(); }
// 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 ); } } }