int main(int argc, const char * argv[]) { // cout << "Setting program parameters..."<<endl; // // int order = 4; // int nx[4] = {51, 101, 201, 401}; // double err1[4]; // int ny = 1; // int nz = 1; // for (int n = 0; n < 4; n++) { // double h = 2*M_PI/(nx[n]-1); // myData u(nx[n],ny,nz),ux(nx[n],ny,nz),uxx(nx[n],ny,nz); // // for (int i = 0; i < u.Nx(); i++) { // double a = sin(i*h); // double b = cos(i*h); // for (int j = 0; j < u.Ny(); j++) { // for (int k = 0; k < u.Nz(); k++) { // u(i,j,k) = a; // ux(i,j,k) = b; // uxx(i,j,k) = -a; // } // } // } // // // // myData vx = u.D1(h, order, X_DIR); //// myData vxx = u.D2(h, order, X_DIR); // // myData w = vx - ux; //// w = vxx - uxx; // err1[n] = w.Norm()*sqrt(h); //// err1[n] = w.Norm()*h; // // for (int i = 0; i < u.Nx(); i++) // for (int j = 0; j < u.Ny(); j++) // for (int k = 0; k < u.Nz(); k++) // cout<<w(i,j,k)<<endl; // } // // for (int i = 0; i < 4; i++) // cout<<"Error :"<<err1[i]<<endl; // // for (int i = 0; i < 4; i++) // cout<<"Value :"<<log2(err1[i])<<endl; // // for (int i = 0; i < 3; i++) // cout<<"D1 :"<<log2(err1[i]) - log2(err1[i+1])<<endl; double h = 0.04; int order = 2; double tEnd = 2; double dt_coef = 0.1; for (int i = 0; i < argc; i++) { if (strcmp(argv[i],"-o") == 0) order = atoi(argv[i+1]); if (strcmp(argv[i],"-h") == 0) h = atof(argv[i+1]); if (strcmp(argv[i],"-dt") == 0) dt_coef = atof(argv[i+1]); if (strcmp(argv[i],"-t") == 0) tEnd = atof(argv[i+1]); if (strcmp(argv[i],"--help") == 0){ cout<<"Useage : ./fdm [options]"<<endl; cout<<"\t -o : order of accuracy (Default is 2)"<<endl; cout<<"\t -h : spatial step size (Default is 0.04)"<<endl; cout<<"\t -dt : time step size coefficient(Default is c = 0.1 in dt = c*h)"<<endl; cout<<"\t -t : Final calculation time (Default is 2)"<<endl; return 0; } } double dt = dt_coef*h; cout<<"Initialising..."<<endl; cout<<"Order of accuracy: "<<order<<endl; cout<<"Spatial step size: "<<h<<endl; cout<<"Time step: "<<dt<<endl; cout<<"Final time: "<<tEnd<<endl; FDM::pmlSolver pmlSol(h,dt,order); FDM::solver refSol(h,dt,order); pmlSol.Set_EndTime(tEnd); refSol.Set_EndTime(tEnd); int LN_X = 2; int LN_Y = 1; int LN_Z = 1; int ref_LN_Y = 2; vector<double> x_layers(LN_X + 1); x_layers[0] = 0; x_layers[1] = 0.5; x_layers[2] = 1; vector<double> y_layers(ref_LN_Y + 1); y_layers[0] = 0; y_layers[1] = 1; y_layers[2] = 6; vector<double> z_layers(LN_Z + 1); z_layers[0] = 0; z_layers[1] = 1; vector<double> pml_y_layers(LN_Y + 1); pml_y_layers[0] = 0; pml_y_layers[1] = 1; vector<double> ref_spd(LN_X*ref_LN_Y*LN_Z); ref_spd[0] = 1; ref_spd[1] = 1; ref_spd[2] = 1; ref_spd[3] = 1; vector<double> spd(LN_X*LN_Y*LN_Z); spd[0] = 1; spd[1] = 1; refSol.Set_Domain(x_layers, y_layers, z_layers, ref_spd); pmlSol.Set_Domain(x_layers, pml_y_layers, z_layers, spd); refSol.Set_FourceFunction(RikerWavelet, NULL); pmlSol.Set_FourceFunction(RikerWavelet, NULL); pmlSol.Set_Plotter(plot, NULL); ////////// // pmlSol.Set_Initializer(start, NULL); // pmlSol.Set_Finilizer(finale, NULL); // pmlSol.Set_FourceFunction(MMS, NULL); // pmlSol.Set_DampingCoeff(false,0); // // refSol.Set_Initializer(start, NULL); // refSol.Set_Finilizer(finale, NULL); // refSol.Set_FourceFunction(MMS, NULL); Vdata pml = pmlSol.run(); Vdata ref = refSol.run(); double err = 0; double val = 0; for (int i = 0; i < LN_X; i++) { for (int j = 0; j < ref_LN_Y - 1; j++) { for (int k = 0; k < LN_Z; k++) { int ind = idx(i, j, k); val = (pml[ind]-ref[ind]).NormSquare(); err+=val; } } } err = sqrt(err)*sqrt(h*h*h); cout << "-----------------------"<<endl; cout<<"Error:"<<err<<endl; cout<<"log2(error):"<<log2(err)<<endl; cout << "-----------------------"<<endl; return 0; }
/** Solve a mixed boundary value problem based on Poisson's equation * * New features are * - application of Neumann boundary conditions and body forces * - use classes to describe the reference solution and the boundary * value problem * - convergence analysis (if executed for many meshes) * * The picture shows the convergence behaviour of the method * for various mesh sizes, a linear finite element basis * \code{.cpp} * const unsigned fieldDeg = 1; * \endcode * and a quadratic finite element basis * \code{.cpp} * const unsigned fieldDeg = 2; * \endcode * in the \f$ L_2 \f$-norm * \f[ * \| u - u^h \|_{L_2(\Omega)}^2 * = \int_\Omega (u - u^h)^2 d x * \f] * and the \f$ H^1 \f$-semi-norm * \f[ * | u - u^h |_{H^1(\Omega)}^2 * = \int_\Omega (\nabla u - \nabla u^h)^2 d x * \f] * * \image html convergence.png "Convergence diagram" * */ int ref05::mixedPoisson( int argc, char * argv[] ) { if ( argc != 2 ) { std::cout << "Usage: " << argv[0] << " file.smf \n\n"; return -1; } const std::string smfFile = boost::lexical_cast<std::string>( argv[1] ); const std::string baseName = base::io::baseName( smfFile, ".smf" ); //-------------------------------------------------------------------------- const unsigned geomDeg = 1; const unsigned fieldDeg = 2; const base::Shape shape = base::QUAD; const unsigned doFSize = 1; //-------------------------------------------------------------------------- typedef base::Unstructured<shape,geomDeg> Mesh; const unsigned dim = Mesh::Node::dim; Mesh mesh; { std::ifstream smf( smfFile.c_str() ); base::io::smf::readMesh( smf, mesh ); smf.close(); } // Quadrature and surface quadrature const unsigned kernelDegEstimate = 3; typedef base::Quadrature<kernelDegEstimate,shape> Quadrature; Quadrature quadrature; typedef base::SurfaceQuadrature<kernelDegEstimate,shape> SurfaceQuadrature; SurfaceQuadrature surfaceQuadrature; // DOF handling typedef base::fe::Basis<shape,fieldDeg> FEBasis; typedef base::Field<FEBasis,doFSize> Field; typedef Field::DegreeOfFreedom DoF; Field field; // generate DoFs from mesh base::dof::generate<FEBasis>( mesh, field ); // Object of reference solution and the Poisson problem typedef ReferenceSolution<dim> RefSol; typedef GivenData<RefSol> GivenData; RefSol refSol( 3., 5., 4. ); GivenData givenData( refSol ); // Creates a list of <Element,faceNo> pairs base::mesh::MeshBoundary meshBoundary; meshBoundary.create( mesh.elementsBegin(), mesh.elementsEnd() ); // Object to constrain the boundary base::dof::constrainBoundary<FEBasis>( meshBoundary.begin(), meshBoundary.end(), mesh, field, boost::bind( &GivenData::dirichletBC<DoF>, &givenData, _1, _2 ) ); // Number of DoFs after constraint application! const std::size_t numDofs = base::dof::numberDoFsConsecutively( field.doFsBegin(), field.doFsEnd() ); std::cout << "Number of dofs " << numDofs << std::endl; // Create a solver object typedef base::solver::Eigen3 Solver; Solver solver( numDofs ); // Bind the fields together typedef base::asmb::FieldBinder<Mesh,Field> FieldBinder; FieldBinder fieldBinder( mesh, field ); typedef FieldBinder::TupleBinder<1,1>::Type FTB; // Body force base::asmb::bodyForceComputation<FTB>( quadrature, solver, fieldBinder, boost::bind( &GivenData::forceFun, &givenData, _1 ) ); #if 0 base::asmb::bodyForceComputation2<FTB>( quadrature, solver, fieldBinder, boost::bind( &GivenData::forceFun2<Mesh::Element>, &givenData, _1, _2 ) ); #endif // Create a connectivity out of this list typedef base::mesh::BoundaryMeshBinder<Mesh::Element>::Type BoundaryMesh; BoundaryMesh boundaryMesh; { // Create a real mesh object from this list base::mesh::generateBoundaryMesh( meshBoundary.begin(), meshBoundary.end(), mesh, boundaryMesh ); } typedef base::asmb::SurfaceFieldBinder<BoundaryMesh,Field> SurfaceFieldBinder; SurfaceFieldBinder surfaceFieldBinder( boundaryMesh, field ); typedef SurfaceFieldBinder::TupleBinder<1>::Type SFTB; // Neumann boundary condition base::asmb::neumannForceComputation<SFTB>( surfaceQuadrature, solver, surfaceFieldBinder, boost::bind( &GivenData::neumannBC, &givenData, _1, _2 ) ); // compute stiffness matrix typedef heat::Laplace<FTB::Tuple> Laplace; Laplace laplace( 1. ); base::asmb::stiffnessMatrixComputation<FTB>( quadrature, solver, fieldBinder, laplace ); // Finalise assembly solver.finishAssembly(); // Solve solver.choleskySolve(); // distribute results back to dofs base::dof::setDoFsFromSolver( solver, field ); //-------------------------------------------------------------------------- // output to a VTK file { // VTK Legacy const std::string vtkFile = baseName + ".vtk"; std::ofstream vtk( vtkFile.c_str() ); base::io::vtk::LegacyWriter vtkWriter( vtk ); vtkWriter.writeUnstructuredGrid( mesh ); base::io::vtk::writePointData( vtkWriter, mesh, field, "temperature" ); const base::Vector<dim>::Type xi = base::ShapeCentroid<Mesh::Element::shape>::apply(); base::io::vtk::writeCellData( vtkWriter, mesh, field, boost::bind( base::post::evaluateFieldGradient< Mesh::Element, Field::Element>, _1, _2, xi ), "flux" ); vtk.close(); } //-------------------------------------------------------------------------- // compute L2-error std::cout << "L2-error = " << base::post::errorComputation<0>( quadrature, mesh, field, boost::bind( &ReferenceSolution<dim>::evaluate, &refSol, _1 ) ) << '\n'; //-------------------------------------------------------------------------- // compute H1-error std::cout << "H1-error = " << base::post::errorComputation<1>( quadrature, mesh, field, boost::bind( &ReferenceSolution<dim>::evaluateGradient, &refSol, _1 ) ) << '\n'; //-------------------------------------------------------------------------- // Compute mesh volume double volume = 0.; base::asmb::simplyIntegrate<FTB>( quadrature, volume, fieldBinder, base::kernel::Measure<FTB::Tuple>() ); std::cout << "Volume of mesh: " << volume << '\n'; return 0; }