// This is a user-supplied routine that sets the the boundary conditions // void SetBndValues_Unst(const mesh& Mesh, dTensor3* q, dTensor3* aux) { int meqn = q->getsize(2); int kmax = q->getsize(3); int maux = aux->getsize(2); int NumElems = Mesh.get_NumElems(); int NumPhysElems = Mesh.get_NumPhysElems(); int NumGhostElems = Mesh.get_NumGhostElems(); int NumNodes = Mesh.get_NumNodes(); int NumPhysNodes = Mesh.get_NumPhysNodes(); int NumEdges = Mesh.get_NumEdges(); // ---------------------------------------- // Loop over each ghost cell element and // place the correct information into // these elements // ---------------------------------------- for (int i=1; i<=NumGhostElems; i++) { int j = Mesh.get_ghost_link(i); for (int m=1; m<=meqn; m++) for (int k=1; k<=kmax; k++) { q->set(i+NumPhysElems,m,k, 0.0 ); } } }
// This is a user-supplied routine that sets the the boundary conditions // // The default routine for the 4D Vlasov code is to apply zero boundary // conditions in configuration space. This routine is identical to the one // found in the unst branch of the 2D DoGPack code, and *should* be setting // periodic boundary conditions. // void SetBndValues_Unst(const mesh& Mesh, dTensor3* q, dTensor3* aux) { // problem information (If this were to be pulled from DogParams, these // numbers would NOT be correct! The reason is that each quadrature point // was actually saved as a separate "equation") const int meqn = q->getsize(2); const int kmax = q->getsize(3); const int maux = aux->getsize(2); // Mesh information const int NumElems = Mesh.get_NumElems(); const int NumPhysElems = Mesh.get_NumPhysElems(); const int NumGhostElems = Mesh.get_NumGhostElems(); const int NumNodes = Mesh.get_NumNodes(); const int NumPhysNodes = Mesh.get_NumPhysNodes(); const int NumEdges = Mesh.get_NumEdges(); // ---------------------------------------- // Loop over each ghost cell element and // place the correct information into // these elements // ---------------------------------------- for (int i=1; i<=NumGhostElems; i++) { int j = Mesh.get_ghost_link(i); for (int m=1; m<=meqn; m++) for (int k=1; k<=kmax; k++) { q->set(i+NumPhysElems, m, k, q->get(j, m, k) ); } } }
// // Output basic mesh information to screen // void ScreenOutput(const mesh& Mesh) { // Compute mesh quality parameters double totalarea = Mesh.get_area_prim(1); double maxarea = Mesh.get_area_prim(1); double minarea = Mesh.get_area_prim(1); for (int i=2; i<=Mesh.get_NumPhysElems(); i++) { double tmp = Mesh.get_area_prim(i); totalarea = totalarea + tmp; if (tmp < minarea) { minarea = tmp; } if (tmp > maxarea) { maxarea = tmp; } } double minAngle = 180.0; for (int i=1; i<=Mesh.get_NumPhysElems(); i++) { const int i1 = Mesh.get_tnode(i,1); const int i2 = Mesh.get_tnode(i,2); const int i3 = Mesh.get_tnode(i,3); point v12, v23, v31; v12.x = Mesh.get_node(i2,1) - Mesh.get_node(i1,1); v12.y = Mesh.get_node(i2,2) - Mesh.get_node(i1,2); v23.x = Mesh.get_node(i3,1) - Mesh.get_node(i2,1); v23.y = Mesh.get_node(i3,2) - Mesh.get_node(i2,2); v31.x = Mesh.get_node(i1,1) - Mesh.get_node(i3,1); v31.y = Mesh.get_node(i1,2) - Mesh.get_node(i3,2); double angle1 = acos((v12.x*-v31.x+v12.y*-v31.y) /(sqrt(v12.x*v12.x+v12.y*v12.y)*sqrt(v31.x*v31.x+v31.y*v31.y))); double angle2 = acos((v23.x*-v12.x+v23.y*-v12.y) /(sqrt(v23.x*v23.x+v23.y*v23.y)*sqrt(v12.x*v12.x+v12.y*v12.y))); double angle3 = acos((v31.x*-v23.x+v31.y*-v23.y) /(sqrt(v31.x*v31.x+v31.y*v31.y)*sqrt(v23.x*v23.x+v23.y*v23.y))); if ((angle1*180/pi) < minAngle) { minAngle = angle1*180/pi; } if ((angle2*180/pi) < minAngle) { minAngle = angle2*180/pi; } if ((angle3*180/pi) < minAngle) { minAngle = angle3*180/pi; } } // Output summary of results to screen printf("\n"); printf(" SUMMARY OF RESULTS:\n"); printf(" -------------------\n"); printf(" Number of Elements: %8i\n",Mesh.get_NumElems()); printf(" Number of Physical Elements: %8i\n",Mesh.get_NumPhysElems()); printf(" Number of Ghost Elements: %8i\n",Mesh.get_NumGhostElems()); printf(" Number of Nodes: %8i\n",Mesh.get_NumNodes()); printf(" Number of Physical Nodes: %8i\n",Mesh.get_NumPhysNodes()); printf(" Number of Boundary Nodes: %8i\n",Mesh.get_NumBndNodes()); printf(" Number of Edges: %8i\n",Mesh.get_NumEdges()); printf(" Number of Boundary Edges: %8i\n",Mesh.get_NumBndEdges()); printf("\n"); printf(" Total Area Covered: %24.16e\n",totalarea); printf(" Area Ratio: small/large: %24.16e\n",minarea/maxarea); printf(" Angle Ratio: minAngle/60: %24.16e\n",minAngle/60.0); printf("\n"); }
// This routine simply glues together many of the routines that are already // written in the Poisson solver library // // phi( 1:SubNumPhysNodes ) is a scalar quantity. // // E1 ( 1:NumElems, 1:kmax2d ) is a vector quantity. // E2 ( 1:NumElems, 1:kmax2d ) is a vector quantity. // // See also: ConvertEfieldOntoDGbasis void ComputeElectricField( const double t, const mesh& Mesh, const dTensorBC5& q, dTensor2& E1, dTensor2& E2) { // const int mx = q.getsize(1); assert_eq(mx,dogParamsCart2.get_mx()); const int my = q.getsize(2); assert_eq(my,dogParamsCart2.get_my()); const int NumElems = q.getsize(3); const int meqn = q.getsize(4); const int kmax = q.getsize(5); const int space_order = dogParams.get_space_order(); // unstructured parameters: const int kmax2d = E2.getsize(2); const int NumBndNodes = Mesh.get_NumBndNodes(); const int NumPhysNodes = Mesh.get_NumPhysNodes(); // Quick error check if( !Mesh.get_is_submesh() ) { printf("ERROR: mesh needs to have subfactor set to %d\n", space_order); printf("Go to Unstructured mesh and remesh the problem\n"); exit(-1); } const int SubFactor = Mesh.get_SubFactor(); assert_eq( NumElems, Mesh.get_NumElems() ); // -- Step 1: Compute rho -- // dTensor3 rho(NumElems, 1, kmax2d ); void ComputeDensity( const mesh& Mesh, const dTensorBC5& q, dTensor3& rho ); ComputeDensity( Mesh, q, rho ); // -- Step 2: Figure out how large phi needs to be int SubNumPhysNodes = 0; int SubNumBndNodes = 0; switch( dogParams.get_space_order() ) { case 1: SubNumPhysNodes = NumPhysNodes; SubNumBndNodes = NumBndNodes; break; case 2: SubNumPhysNodes = Mesh.get_SubNumPhysNodes(); SubNumBndNodes = Mesh.get_SubNumBndNodes(); if(SubFactor!=2) { printf("\n"); printf(" Error: for space_order = %i, need SubFactor = %i\n",space_order,2); printf(" SubFactor = %i\n",SubFactor); printf("\n"); exit(1); } break; case 3: SubNumPhysNodes = Mesh.get_SubNumPhysNodes(); SubNumBndNodes = Mesh.get_SubNumBndNodes(); if(SubFactor!=3) { printf("\n"); printf(" Error: for space_order = %i, need SubFactor = %i\n",space_order,3); printf(" SubFactor = %i\n",SubFactor); printf("\n"); exit(1); } break; default: printf("\n"); printf(" ERROR in RunDogpack_unst.cpp: space_order value not supported.\n"); printf(" space_order = %i\n",space_order); printf("\n"); exit(1); } // local storage: dTensor1 rhs(SubNumPhysNodes); dTensor1 phi(SubNumPhysNodes); // Get Cholesky factorization matrix R // // TODO - this should be saved earlier in the code rather than reading // from file every time we with to run a Poisson solve! // SparseCholesky R(SubNumPhysNodes); string outputdir = dogParams.get_outputdir(); R.init(outputdir); R.read(outputdir); // Create right-hand side vector void Rhs2D_unst(const int space_order, const mesh& Mesh, const dTensor3& rhs_dg, dTensor1& rhs); Rhs2D_unst(space_order, Mesh, rho, rhs); // Call Poisson solver void PoissonSolver2D_unst(const int space_order, const mesh& Mesh, const SparseCholesky& R, const dTensor1& rhs, dTensor1& phi, dTensor2& E1, dTensor2& E2); PoissonSolver2D_unst(space_order, Mesh, R, rhs, phi, E1, E2); // Compare errors with the exact Electric field: // void L2Project_Unst( const double time, 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 double t, const dTensor2* vel_vec, const dTensor2&,const dTensor2&, const dTensor2&,dTensor2&)); const int sorder = dogParams.get_space_order(); dTensor3 qtmp (NumElems, 2, kmax2d ); qtmp.setall(0.); dTensor3 auxtmp (NumElems, 0, kmax2d ); dTensor3 ExactE (NumElems, 2, kmax2d ); L2Project_Unst( t, NULL, 1, NumElems, sorder, sorder, sorder, sorder, Mesh, &qtmp, &auxtmp, &ExactE, &ExactElectricField ); // Compute errors on these two: // double err = 0.; for( int n=1; n <= NumElems; n++ ) for( int k=1; k <= kmax2d; k++ ) { err += Mesh.get_area_prim(n)*pow( ExactE.get(n,1,k) - E1.get(n,k), 2 ); err += Mesh.get_area_prim(n)*pow( ExactE.get(n,2,k) - E2.get(n,k), 2 ); } printf("error = %2.15e\n", err ); }