Пример #1
0
/***********************************************************************************
 * main program                                                                    *
************************************************************************************/
int main(int argc, char **args)
{

#ifdef WITH_PETSC
    PetscInitialize(NULL, NULL, PETSC_NULL, PETSC_NULL);
    PetscPushErrorHandler(PetscIgnoreErrorHandler, PETSC_NULL);		// Disable PETSc error handler.
#endif

    // Load the inital mesh.
    Mesh mesh;
    Mesh3DReader mesh_loader;
    mesh_loader.load("hexahedron.mesh3d", &mesh);

    // Initial uniform  mesh refinements.
    printf("Performing %d initial mesh refinements.\n", INIT_REF_NUM);
    for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(H3D_H3D_H3D_REFT_HEX_XYZ);
    Word_t (nelem) = mesh.get_num_elements();
    printf("New number of elements is %d.\n", nelem);

    //Initialize the shapeset and the cache.
    H1ShapesetLobattoHex shapeset;

    //Matrix solver.
#if defined WITH_UMFPACK
    UMFPackMatrix mat;
    UMFPackVector rhs;
    UMFPackLinearSolver solver(&mat, &rhs);
#elif defined WITH_PETSC
    PetscMatrix mat;
    PetscVector rhs;
    PetscLinearSolver solver(&mat, &rhs);
#elif defined WITH_MUMPS
    MumpsMatrix mat;
    MumpsVector rhs;
    MumpsSolver solver(&mat, &rhs);
#endif

    // Graphs of DOF convergence.
    GnuplotGraph graph;
    graph.set_captions("", "Degrees of Freedom", "Error [%]");
    graph.set_log_y();
    graph.add_row("Total error", "k", "-", "O");

    // Create H1 space to setup the problem.
    H1Space space(&mesh, &shapeset);
    space.set_bc_types(bc_types);
    space.set_essential_bc_values(essential_bc_values);
    space.set_uniform_order(order3_t(P_INIT, P_INIT, P_INIT));

    // Initialize the weak formulation.
    WeakForm wf;
    wf.add_matrix_form(biform<double, double>, biform<ord_t, ord_t>, SYM, ANY);
    wf.add_vector_form(liform<double, double>, liform<ord_t, ord_t>, ANY);

    // Initialize the coarse mesh problem.
    LinProblem lp(&wf);
    lp.set_space(&space);

    // Adaptivity loop.
    int as = 0;
    bool done = false;
    do {
        printf("\n---- Adaptivity step %d:\n", as);

        printf("\nSolving on coarse mesh:\n");

        // Procedures for coarse mesh problem.
        // Assign DOF.
        int ndof = space.assign_dofs();
        printf("  - Number of DOF: %d\n", ndof);

        // Assemble stiffness matrix and rhs.
        printf("  - Assembling... ");
        fflush(stdout);
        if (lp.assemble(&mat, &rhs))
            printf("done in %lf secs.\n", lp.get_time());
        else
            error("failed!");

        // Solve the system.
        printf("  - Solving... ");
        fflush(stdout);
        bool solved = solver.solve();
        if (solved)
            printf("done in %lf secs.\n", solver.get_time());
        else
        {
            printf("Failed.\n");
            break;
        }

        // Construct a solution.
        Solution sln(&mesh);
        sln.set_fe_solution(&space, solver.get_solution());

        // Output the orders and the solution.
        if (do_output)
        {
            out_orders(&space, "order", as);
            out_fn(&sln, "sln", as);
        }

        // Solving fine mesh problem.
        printf("Solving on fine mesh:\n");

        // Matrix solver.
#if defined WITH_UMFPACK
        UMFPackLinearSolver rsolver(&mat, &rhs);
#elif defined WITH_PETSC
        PetscLinearSolver rsolver(&mat, &rhs);
#elif defined WITH_MUMPS
        MumpsSolver rsolver(&mat, &rhs);
#endif

        // Construct the refined mesh for reference(refined) solution.
        Mesh rmesh;
        rmesh.copy(mesh);
        rmesh.refine_all_elements(H3D_H3D_H3D_REFT_HEX_XYZ);

        // Setup space for the reference (globally refined) solution.
        Space *rspace = space.dup(&rmesh);
        rspace->copy_orders(space, 1);

        // Initialize the mesh problem for reference solution.
        LinProblem rlp(&wf);
        rlp.set_space(rspace);

        // Assign DOF.
        int rndof = rspace->assign_dofs();
        printf("  - Number of DOF: %d\n", rndof);

        // Assemble stiffness matric and rhs.
        printf("  - Assembling... ");
        fflush(stdout);
        if (rlp.assemble(&mat, &rhs))
            printf("done in %lf secs.\n", rlp.get_time());
        else
            error("failed!");

        // Solve the system.
        printf("  - Solving... ");
        fflush(stdout);
        bool rsolved = rsolver.solve();
        if (rsolved)
            printf("done in %lf secs.\n", rsolver.get_time());
        else
        {
            printf("failed.\n");
            break;
        }

        // Construct the reference(refined) solution.
        Solution rsln(&rmesh);
        rsln.set_fe_solution(rspace, rsolver.get_solution());

        // Compare coarse and fine mesh.
        // Calculate the error estimate wrt. refined mesh solution.
        double err = h1_error(&sln, &rsln);
        printf("  - H1 error: % lf\n", err * 100);

        // Save it to the graph.
        graph.add_value(0, ndof, err * 100);
        if (do_output)
            graph.save("conv.gp");

        // Calculate error estimates for adaptivity.
        printf("Adaptivity\n");
        printf("  - calculating error: ");
        fflush(stdout);
        H1Adapt hp(&space);
        double err_est = hp.calc_error(&sln, &rsln) * 100;
        printf("% lf %%\n", err_est);

        // If error is too large, adapt the mesh.
        if (err_est < ERR_STOP)
        {
            printf("\nDone\n");
            break;
        }
        printf("  - adapting... ");
        fflush(stdout);
        hp.adapt(THRESHOLD);
        printf("done in %lf secs (refined %d element(s)).\n", hp.get_adapt_time(), hp.get_num_refined_elements());

        if (rndof >= NDOF_STOP)
        {
            printf("\nDone.\n");
            break;
        }

        // Clean up.
        delete rspace;

        // Next adaptivity step.
        as++;

        mat.free();
        rhs.free();
    } while (!done);

#ifdef WITH_PETSC
    PetscFinalize();
#endif

    return 1;
}