Example #1
0
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;
}
Example #2
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;
}