SpatialDomains::HexGeomSharedPtr CreateHexGeom(int argc, char *argv[]) { if (argc != 35) { cout << "Insufficient points for a hex!" << endl; } // ///////////////////////////////////////////////////////////////////// // Set up Hexahedron vertex coordinates // PointGeom (const int coordim, const int vid, double x, double y, // double z) const int nVerts = 8; const double point[][3] = { {atof(argv[11]),atof(argv[12]),atof(argv[13])}, {atof(argv[14]),atof(argv[15]),atof(argv[16])}, {atof(argv[17]),atof(argv[18]),atof(argv[19])}, {atof(argv[20]),atof(argv[21]),atof(argv[22])}, {atof(argv[23]),atof(argv[24]),atof(argv[25])}, {atof(argv[26]),atof(argv[27]),atof(argv[28])}, {atof(argv[29]),atof(argv[30]),atof(argv[31])}, {atof(argv[32]),atof(argv[33]),atof(argv[34])} }; // Populate the list of verts PointGeomSharedPtr verts[8]; const int three = 3; for( int i = 0; i < nVerts; ++i ) { verts[i] = MemoryManager<PointGeom> ::AllocateSharedPtr( three, i, point[i][0], point[i][1], point[i][2] ); } // ///////////////////////////////////////////////////////////////////// // Set up Hexahedron Edges // SegGeom (int id, const int coordim), EdgeComponent(id, coordim) const int nEdges = 12; const int vertexConnectivity[][2] = { {0,1}, {1,2}, {2,3}, {0,3}, {0,4}, {1,5}, {2,6}, {3,7}, {4,5}, {5,6}, {6,7}, {4,7} }; // Populate the list of edges SegGeomSharedPtr edges[nEdges]; for( int i = 0; i < nEdges; ++i ) { PointGeomSharedPtr vertsArray[2]; for( int j = 0; j < 2; ++j ) { vertsArray[j] = verts[vertexConnectivity[i][j]]; } edges[i] = MemoryManager<SegGeom>:: AllocateSharedPtr( i, three, vertsArray); } // ////////////////////////////////////////////////////////////////////// // Set up Hexahedron faces const int nFaces = 6; const int edgeConnectivity[][4] = { {0,1,2,3}, {0,5,8,4}, {1,6,9,5}, {2,7,10,6}, {3,7,11,4}, {8,9,10,11} }; const bool isEdgeFlipped[][4] = { {0,0,0,1}, {0,0,1,1}, {0,0,1,1}, {0,0,1,1}, {0,0,1,1}, {0,0,0,1} }; // Populate the list of faces QuadGeomSharedPtr faces[nFaces]; for( int i = 0; i < nFaces; ++i ) { SegGeomSharedPtr edgeArray[4]; Orientation eorientArray[4]; for( int j = 0; j < 4; ++j ) { edgeArray[j] = edges[edgeConnectivity[i][j]]; eorientArray[j] = isEdgeFlipped[i][j] ? eBackwards : eForwards; } faces[i] = MemoryManager<QuadGeom> ::AllocateSharedPtr( i, edgeArray, eorientArray); } SpatialDomains::HexGeomSharedPtr geom = MemoryManager<SpatialDomains::HexGeom>::AllocateSharedPtr(faces); geom->SetOwnData(); return geom; }
int main(int argc, char *argv[]) { if( argc != 10 ) { cerr << "Usage: HexDemo Type_x Type_y Type_z numModes_x numModes_y " "numModes_z Qx Qy Qz" << endl; cerr << "Where type is an interger value which dictates the basis as:" << endl; cerr << "\t Ortho_A = 1\n"; cerr << "\t Modified_A = 4\n"; cerr << "\t Fourier = 7\n"; cerr << "\t Lagrange = 8\n"; cerr << "\t Legendre = 9\n"; cerr << "\t Chebyshev = 10\n"; cerr << "\n\n" << "Example: " << argv[0] << " 4 4 4 3 3 3 5 5 5" << endl; cerr << endl; exit(1); } // Set up the region shape and expansion types int bType_x_val = atoi(argv[1]); int bType_y_val = atoi(argv[2]); int bType_z_val = atoi(argv[3]); BasisType bType_x = static_cast<BasisType>( bType_x_val ); BasisType bType_y = static_cast<BasisType>( bType_y_val ); BasisType bType_z = static_cast<BasisType>( bType_z_val ); if( (bType_x_val == 13) || (bType_y_val == 13) || (bType_z_val == 13) ) { bType_x = LibUtilities::eOrtho_A; bType_y = LibUtilities::eOrtho_B; bType_z = LibUtilities::eOrtho_C; } if( (bType_x == eOrtho_B) || (bType_x == eModified_B) ) { NEKERROR(ErrorUtil::efatal, "Basis 1 cannot be of type Ortho_B or Modified_B"); } if( (bType_x == eOrtho_C) || (bType_x == eModified_C) ) { NEKERROR(ErrorUtil::efatal, "Basis 1 cannot be of type Ortho_C or Modified_C"); } if( (bType_y == eOrtho_C) || (bType_y == eModified_C) ) { NEKERROR(ErrorUtil::efatal, "Basis 2 cannot be of type Ortho_C or Modified_C"); } // Set up the number of quadrature points, order of bases, etc int xModes = atoi(argv[4]); int yModes = atoi(argv[5]); int zModes = atoi(argv[6]); int Qx = atoi(argv[7]); int Qy = atoi(argv[8]); int Qz = atoi(argv[9]); int P = xModes - 1; int Q = yModes - 1; int R = zModes - 1; const int three = 3; Array<OneD, NekDouble> solution( Qx * Qy * Qz ); LibUtilities::PointsType Qtype_x, Qtype_y, Qtype_z; Array<OneD,NekDouble> x = Array<OneD,NekDouble>( Qx * Qy * Qz ); Array<OneD,NekDouble> y = Array<OneD,NekDouble>( Qx * Qy * Qz ); Array<OneD,NekDouble> z = Array<OneD,NekDouble>( Qx * Qy * Qz ); if(bType_x != LibUtilities::eFourier) { Qtype_x = LibUtilities::eGaussLobattoLegendre; } else { Qtype_x = LibUtilities::eFourierEvenlySpaced; } if(bType_y != LibUtilities::eFourier) { Qtype_y = LibUtilities::eGaussLobattoLegendre; } else { Qtype_y = LibUtilities::eFourierEvenlySpaced; } if(bType_z != LibUtilities::eFourier) { Qtype_z = LibUtilities::eGaussLobattoLegendre; } else { Qtype_z = LibUtilities::eFourierEvenlySpaced; } //----------------------------------------------- // Define a 3D expansion based on basis definition StdRegions::StdExpansion3D *lhe = 0; // //////////////////////////////////////////////////////////////// // Set up Hexahedron vertex coordinates // PointGeom (const int coordim, const int vid, double x, // double y, double z) const int nVerts = 8; const double point[][3] = { {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0}, {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1} }; // Populate the list of verts PointGeomSharedPtr verts[8]; for( int i = 0; i < nVerts; ++i ) { verts[i] = MemoryManager<PointGeom> ::AllocateSharedPtr(three, i, point[i][0], point[i][1], point[i][2]); } // //////////////////////////////////////////////////////////////// // Set up Hexahedron Edges // SegGeom (int id, const int coordim), EdgeComponent(id, coordim) const int nEdges = 12; const int vertexConnectivity[][2] = { {0,1}, {1,2}, {2,3}, {0,3}, {0,4}, {1,5}, {2,6}, {3,7}, {4,5}, {5,6}, {6,7}, {4,7} }; // Populate the list of edges SegGeomSharedPtr edges[nEdges]; for( int i = 0; i < nEdges; ++i ) { PointGeomSharedPtr vertsArray[2]; for( int j = 0; j < 2; ++j ) { vertsArray[j] = verts[vertexConnectivity[i][j]]; } edges[i] = MemoryManager<SegGeom>:: AllocateSharedPtr( i, three, vertsArray); } // //////////////////////////////////////////////////////////////// // Set up Hexahedron faces const int nFaces = 6; const int edgeConnectivity[][4] = { {0,1,2,3}, {0,5,8,4}, {1,6,9,5}, {2,7,10,6}, {3,7,11,4}, {8,9,10,11} }; const bool isEdgeFlipped[][4] = { {0,0,0,1}, {0,0,1,1}, {0,0,1,1}, {0,0,1,1}, {0,0,1,1}, {0,0,0,1} }; // Populate the list of faces QuadGeomSharedPtr faces[nFaces]; for( int i = 0; i < nFaces; ++i ) { SegGeomSharedPtr edgeArray[4]; Orientation eorientArray[4]; for( int j = 0; j < 4; ++j ) { edgeArray[j] = edges[edgeConnectivity[i][j]]; eorientArray[j] = isEdgeFlipped[i][j] ? eBackwards : eForwards; } faces[i] = MemoryManager<QuadGeom>::AllocateSharedPtr(i, edgeArray, eorientArray); } const LibUtilities::PointsKey pkey1( Qx, Qtype_x ); const LibUtilities::PointsKey pkey2( Qy, Qtype_y ); const LibUtilities::PointsKey pkey3( Qz, Qtype_z ); const LibUtilities::BasisKey bkey1( bType_x, xModes, pkey1 ); const LibUtilities::BasisKey bkey2( bType_y, yModes, pkey2 ); const LibUtilities::BasisKey bkey3( bType_z, zModes, pkey3 ); Array<OneD, StdRegions::StdExpansion3DSharedPtr> xMap(3); for(int i = 0; i < 3; ++i) { xMap[i] = MemoryManager<StdRegions::StdHexExp> ::AllocateSharedPtr(bkey1, bkey2, bkey3); } SpatialDomains::HexGeomSharedPtr geom = MemoryManager<SpatialDomains::HexGeom>::AllocateSharedPtr(faces); geom->SetOwnData(); if( bType_x_val < 10 ) { lhe = new LocalRegions::HexExp( bkey1, bkey2, bkey3, geom ); } lhe->GetCoords(x,y,z); //---------------------------------------------- // Define solution to be projected for(int n = 0; n < Qx * Qy * Qz; ++n) { solution[n] = Hex_sol( x[n], y[n], z[n], P, Q, R, bType_x, bType_y, bType_z ); } //---------------------------------------------- //--------------------------------------------- // Project onto Expansion Array<OneD, NekDouble> phys (Qx * Qy * Qz); Array<OneD, NekDouble> coeffs(lhe->GetNcoeffs()); lhe->FwdTrans( solution, coeffs ); //--------------------------------------------- //------------------------------------------- // Backward Transform Solution to get projected values lhe->BwdTrans( coeffs, phys ); //------------------------------------------- //-------------------------------------------- // Calculate L_p error cout << "L infinity error: " << lhe->Linf(phys, solution) << endl; cout << "L 2 error: " << lhe->L2 (phys, solution) << endl; //-------------------------------------------- //------------------------------------------- // Evaulate solution at x = y = z = 0 and print error Array<OneD, NekDouble> t = Array<OneD, NekDouble>(3); t[0] = 0.5; t[1] = 0.5; t[2] = 0.5; NekDouble numericSolution = lhe->PhysEvaluate(t, phys); solution[0] = Hex_sol( t[0], t[1], t[2], P, Q, R, bType_x, bType_y, bType_z ); cout << "Solution = " << solution[0] << endl; cout << "Numeric = " << numericSolution << endl; cout << "Interpolation difference from actual solution at x = ( " << t[0] << ", " << t[1] << ", " << t[2] << " ): " << numericSolution - solution[0] << endl; //------------------------------------------- return 0; }