示例#1
0
    def solve_problem_nd_t(self, mesh, boundary_facets, ds, dS, V, V_exact,
                           VV_exact, H_div, u_e, f, A, invA, adjA, min_eig_A,
                           lmbd, a, eps_curr, uD, uN, C_FD, C_Ntr,
                           project_path, results_folder, test_params):

        # Define the number of refinements
        ref_num = test_params['number_of_refinements'] + 20

        # Define arrays with data collected on the refinement steps
        ref_num_array = postprocess.allocate_array(ref_num + 1)
        h_max_array = postprocess.allocate_array(ref_num + 1)
        h_min_array = postprocess.allocate_array(ref_num + 1)
        dofs_array = postprocess.allocate_array(ref_num + 1)
        numcells_array = postprocess.allocate_array(ref_num + 1)
        numverts_array = postprocess.allocate_array(ref_num + 1)
        e_array = postprocess.allocate_array(ref_num + 1)
        e_l2_array = postprocess.allocate_array(ref_num + 1)
        e_linf_array = postprocess.allocate_array(ref_num + 1)

        e_min_array = postprocess.allocate_array(ref_num + 1)
        maj_array = postprocess.allocate_array(ref_num + 1)
        min_array = postprocess.allocate_array(ref_num + 1)
        i_eff_maj_array = postprocess.allocate_array(ref_num + 1)
        i_eff_min_array = postprocess.allocate_array(ref_num + 1)

        # Initialize the variables before the loop
        maj = 10e8
        i = 0
        h_min = 10e8

        # TO DO: Calculate the reference solution on the refined mesh
        '''
        if test_params['solution_tag'] == "reference-solution":
            mesh_ref = self.construct_mesh(2 ** ref_num * test_params["nx0"],
                                           2 ** ref_num * test_params["nx1"],
                                           2 ** ref_num * test_params["nx2"],
                                           2 ** ref_num * test_params["res"], project_path)
            # Update functional spaces, BC, and stiffness/mass matrices
            V_ref, VV_ref, V_ref_exact, VV_ref_exact, H_ref_div = problem.functional_spaces(mesh_ref,
                                                                            test_params["v_approx_order"],
                                                                            test_params["flux_approx_order"],
                                                                            dim)
            boundary_facets_ref, ds = self.construct_boundary_faces(mesh_ref)
            u_e, delta = problem.solve_convection_reaction_diffusion(V_ref_exact, f, A, min_eig_A, lmbd,
                                                                     problem.interpolate_vector_function(a, dim, V_ref_exact, VV_ref_exact),
                                                                     self.boundary, uD, uN,
                                                                     mesh_ref, boundary_facets_ref,
                                                                     dim, test_num)
        '''

        while h_min > eps_curr:  # (i <= ref_num and maj > test_params['accuracy_level']) or

            print(" ")
            print(
                "%-----------------------------------------------------------------------------------------------------------%"
            )
            print " Refinement cycle # %d : DOFs = %d" % (
                i, len(V.dofmap().dofs()))
            print(
                "%-----------------------------------------------------------------------------------------------------------%"
            )
            print(" ")

            # Compute approximate solution u and stabilization parameter (in case of the convection dominated problem)

            u, delta = problem.solve_convection_reaction_diffusion(
                V, f, A, min_eig_A, lmbd,
                problem.interpolate_vector_function(a, dim, V_exact, VV_exact),
                self.boundary, uD, uN, mesh, boundary_facets, self.dim,
                self.test_num, test_params)

            # In case of explicitely unknown exact solution, calculate it with high order order polynomials
            if test_params['solution_tag'] == "reference-solution":
                # Compute reference solution with high order polynomials
                u_e, delta = problem.solve_convection_reaction_diffusion(
                    V_exact, f, A, min_eig_A, lmbd,
                    problem.interpolate_vector_function(
                        a, dim, V_exact,
                        VV_exact), self.boundary, uD, uN, mesh,
                    boundary_facets, self.dim, self.test_num, test_params)

            if test_params["PLOT"] == True:
                #plot(u, interactive=True)
                # Plot approximate solution
                postprocess.plot_function(
                    u, mesh, dim, project_path + results_folder + 'u-%d' % i)

            # Calculate error
            grad_e, e_l2, e_linf, delta_e, lambda_e, a_e, var_grad_e, var_lmbd_diva_e, var_lmbd_e, var_a_e = \
                estimates.error_norm(u, u_e, lmbd, A, invA,
                                     a,
                                     problem.interpolate_vector_function(a, dim, V_exact, VV_exact),
                                     V, V_exact, mesh, dim)
            # Define the error for the majorant
            error = grad_e + delta_e

            # Define the error for the minorant
            if test_params[
                    "pde_tag"] == "reaction-diffusion-pde" or test_params[
                        "pde_tag"] == "diffusion-pde":
                error_min = grad_e + delta_e
            elif test_params[
                    "pde_tag"] == "reaction-convection-diffusion-pde" or test_params[
                        "pde_tag"] == "convection-diffusion-pde":
                error_min = grad_e + lambda_e + a_e

            if test_params["error_estimates"] == True:

                # L2-projection of grad u to Hdiv space
                y = project(A * Grad(u, dim), H_div)

                # Test for the correctness of the code and the majorant for the y = A dot \grad u
                # y = interpolate(A * Grad(u, dim), H_div)
                #y = project(A * Grad(u_e, dim), H_div)

                # Contruct the majorant
                maj, y, beta, md, mf, var_m_d, var_m_f_w_opt, \
                majorant_reconstruction_time, majorant_minimization_time = \
                    estimates.majorant_nd(u, y, H_div, f, A, invA, min_eig_A, eps, a, lmbd, error, mesh, dim, C_FD, C_Ntr, test_params)

                # Output the results of upper bound reconstructions
                estimates.output_result_error_and_majorant(
                    sqrt(error), sqrt(maj), sqrt(maj / error))

                # Construct error and majorant distribution
                ed_distr, delta_e_distr, e_distr, md_distr, mf_distr, maj_distr, ed, md = \
                    estimates.error_majorant_distribution_nd(mesh, dim, V_exact,
                                                             var_grad_e, var_lmbd_diva_e, var_m_d, var_m_f_w_opt, beta)

                # Calculate the smoothness parameter
                #smoothness_distr = problem.smoothness_distribution(u, mesh, dim)
                #print "smoothness ", smoothness_distr

                #smooth_criterion = problem.SmoothnessCriterion(v=interpolate(u, V_exact), mesh=mesh,
                #                                               expression_degree=test_params["expression_degree"])

                #smoothness_vals = project(smooth_criterion, FunctionSpace(mesh, "DG", 0))
                #print "smoothness_vals:", smoothness_vals.vector().array()

                # Calculate minorant
                min, phi = estimates.minorant(u_e, u, mesh, ds, V_exact, uN,
                                              self.boundary, f, A, lmbd, a,
                                              dim, test_params)
                # Output the results of lower bound reconstructions
                estimates.output_result_minorant(sqrt(error_min), sqrt(min),
                                                 sqrt(min / error_min))

                maj_array[i] = sqrt(maj)
                i_eff_maj_array[i] = sqrt(maj / error)

                min_array[i] = sqrt(min)
                i_eff_min_array[i] = sqrt(min / error_min)

                if test_params["pde_tag"] == "reaction-convection-diffusion-pde" \
                            or test_params["pde_tag"] == "convection-diffusion-pde":
                    e_min_array[i] = sqrt(error_min)
                else:
                    e_min_array[i] = e_array[i]
                '''
                #tag = 'E-DWR-'
                #tag = 'eta-'
                #tag = 'error-'
                #tag = 'm-d-'
                #tag = 'm-df-'

                eta_distr, E_DWR_distr, J_e_distr, m_d_distr, m_df_distr  = \
                    compare_error_indicators(mesh, V, V_star, V_e, f, u_0, boundary, u,
                                             interpolate(u_e, V_e), interpolate(grad_u_e, VV_e),
                                             y, beta, test_num, tag)



                cells_num = mesh.num_cells()
                N_array[i] = cells_num
                e_array[i] = sum(J_e_distr)

                if tag == 'eta-':
                    distr = eta_distr
                elif tag == 'E-DWR-':
                    distr = E_DWR_distr
                elif tag == 'error-':
                    distr = J_e_distr
                elif tag == 'm-d-':
                    distr = m_d_distr
                elif tag == 'm-df-':
                    distr = m_df_distr

                '''
                '''
                md_CG0_distr, mdf_CG0_distr, e_CGO_distr = estimates.majorant_distribution_DG0(mesh, f, lmbd, A, invA, u, e_form, y, beta, C_FD, dim)

                residual_CG0_distr, e_DWR_CG0_distr, J_e_CG0_distr = estimates.get_indicators_CG0(mesh, V, V_exact, f, A, adjA, lmbd, u_0, boundary, u, u_e,
                                                                                                  e_form, sqrt(e_d), dim)

                # Plot histograms with obtained indicators
                postprocess.plot_histogram(mesh, J_e_CG0_distr, residual_CG0_distr,
                                           project_path + results_folder + 'je-residual-distr-hist' + results_info)
                postprocess.plot_histogram(mesh, J_e_CG0_distr, e_DWR_CG0_distr,
                                           project_path + results_folder + 'je-edwr-distr-hist' + results_info)
                # Plot histograms with obtained indicators from majorant
                postprocess.plot_histogram(mesh, J_e_CG0_distr, md_CG0_distr,
                                           project_path + results_folder + 'je-md-distr-hist' + results_info)
                postprocess.plot_histogram(mesh, J_e_CG0_distr, mdf_CG0_distr,
                                           project_path + results_folder + 'je-mdf-distr-hist' + results_info)
                '''

            # Update the arrays of data with respect to the refinement cycle
            ref_num_array[i] = i + 1
            e_array[i] = sqrt(error)
            e_l2_array[i] = e_l2
            e_linf_array[i] = e_linf
            h_max_array[i] = mesh.hmax()
            h_min_array[i] = mesh.hmin()

            h_min = mesh.hmin()
            print "hmax = ", mesh.hmax()
            print "hmin = ", mesh.hmin()

            num_cells = mesh.num_cells()
            num_vertices = mesh.num_vertices()
            num_dofs = len(V.dofmap().dofs())

            numcells_array[i] = num_cells
            numverts_array[i] = num_vertices
            dofs_array[i] = num_dofs

            # Construct the tag with problem information
            results_info = postprocess.construct_result_tag(
                test_num, i, test_params["nx0"], test_params["nx1"],
                test_params["nx2"], num_cells, num_vertices)

            # Plot histogram with the error and majorant distribution
            #postprocess.plot_histogram(mesh, ed_distr, md_distr,
            #                           project_path + results_folder + 'e-maj-distr-hist' + results_info)
            #postprocess.plot_histogram_smoothness(mesh, mf_distr, 'k',
            #                           project_path + results_folder + 'mf-distr-hist' + results_info)
            #postprocess.plot_histogram_smoothness(mesh, smoothness_distr, 'b',
            #                           project_path + results_folder + 'smoothness-distr-hist' + results_info)

            # For the refinement accept the last one change the mesh-dependent values like spaces and mesh functions
            if ref_num > 0 and i + 1 <= ref_num:

                # If the error estimates are constructed, then the mesh refinement can vary: uniform or adaptive
                if test_params["error_estimates"] == True:
                    # Refine mesh
                    mesh, mat_file_tag = self.execute_refinement_strategy(
                        test_params, mesh, e_distr, md_distr, project_path,
                        results_folder, results_info)
                    # Save the results in mat-file
                    postprocess.save_results_to_mat_file(
                        ed_distr, md_distr, e_array, maj_array,
                        i_eff_maj_array, e_min_array, min_array, mat_file_tag)

                    if i + 1 == ref_num:
                        postprocess.save_mesh_to_xml_file(
                            mesh, project_path + results_folder, results_info)

                    # If the refiniment strategy is adaptive, that plot the changes in the mesh, majorant, and the error
                    if test_params['refinement_tag'] == "adaptive":

                        if test_params["PLOT"] == True:
                            # Plot result mesh
                            if dim == 2:
                                postprocess.plot_mesh(
                                    mesh, project_path + results_folder +
                                    'mesh' + results_info)

                                # Plot 'carpets with colored elements' dependent on the error and the majorant
                                #postprocess.plot_carpet_2d(mesh, ed,
                                #                           project_path + results_folder + 'carpet-error' + results_info)
                                #postprocess.plot_carpet_2d(mesh, md,
                                #                           project_path + results_folder + 'carpet-majorant' + results_info)
                            elif dim == 3:
                                postprocess.plot_mesh_3d(
                                    mesh, project_path + results_folder +
                                    'initial-mesh')
                # If the error estimates aren't constructed, the mesh refinement is uniform
                else:
                    mesh = refine(mesh)

                # Update functional spaces, BC, and stiffness/mass matrices
                V, VV, V_exact, VV_exact, H_div = problem.functional_spaces(
                    mesh, test_params, dim)
                if test_params[
                        'material_tag'] == "material-changing":  # over the domain
                    # Define A if it is changing
                    A = problem.construct_from_mesh_functions(
                        dim, self.A_expr, mesh)

                boundary_facets, ds, dS = self.construct_boundary_faces(mesh)

                # Define the value of the maj for the loop criteria
                if test_params["error_estimates"] == True:
                    maj = maj_array[i]
                else:
                    maj = e_array[i]

            # Update the refinement number
            i += 1

        # Output the results
        decay_result_folder = postprocess.create_decay_tag(
            test_params, project_path, results_folder, results_info)

        postprocess.document_errors_decay(float(self.dim), test_params,
                                          decay_result_folder, dofs_array[0:i],
                                          h_min_array[0:i], e_array[0:i],
                                          e_l2_array[0:i], e_linf_array[0:i],
                                          e_min_array[0:i], maj_array[0:i],
                                          min_array[0:i])
        return mesh, V, VV, V_exact, VV_exact, H_div, boundary_facets, ds, dS
示例#2
0
    def test_estimates(self, test_params):

        # Define the project path
        # --------------------------------------------------------------------------------------------------------------#
        project_path = postprocess.get_project_path()

        # Check if it does exist and create folder for the results
        # --------------------------------------------------------------------------------------------------------------#
        results_folder_name = postprocess.construct_result_folder_name(
            self.dim, test_num, test_params)
        postprocess.create_results_folder(results_folder_name, test_params)

        # --------------------------------------------------------------------------------------------------------------#
        # Define problem data
        # --------------------------------------------------------------------------------------------------------------#

        # Define the mesh based on the domain geometry
        # --------------------------------------------------------------------------------------------------------------#
        mesh = self.construct_mesh(test_params["nx0"], test_params["nx1"],
                                   test_params["nx2"], test_params["nt"],
                                   test_params["res"], project_path)

        if test_params["PLOT"] == True:
            # Plot and save the initial mesh
            file_name = project_path + results_folder_name + 'initial-mesh'
            if self.dim == 2: postprocess.plot_mesh(mesh, file_name)
            elif self.dim == 3: postprocess.plot_mesh_3d(mesh, file_name)

        boundary_facets, ds, dS = self.construct_boundary_faces(mesh)

        # Calculate the estimate for Freidrichs constant based on the domain
        C_FD = problem.calculate_CF_of_domain(domain, self.dim - 1)
        C_Ntr = problem.calculate_trace_constant(self.test_num)

        # Define functional spaces based on the mesh
        #--------------------------------------------------------------------------------------------------------------#
        V, VV, V_exact, VV_exact, H_div = \
            problem.functional_spaces(mesh, test_params, self.dim)

        # Define problem data functions
        #--------------------------------------------------------------------------------------------------------------#
        f, A, invA, adjA, lmbd, a, uD, uN, u0, u_e, grad_u_e = self.convert_problem_data_to_expressions(
            mesh, test_params)

        # Majorant parameters
        delta = 1
        # gamma = 1.5
        # gamma = 2
        gamma = 1

        # Output to console the problem data
        problem.output_problem_characteristics(self.test_num, self.u_expr,
                                               self.grad_u_expr, self.f_expr,
                                               self.domain, self.dim,
                                               mesh.num_cells(),
                                               mesh.num_vertices(),
                                               test_params["v_approx_order"])

        t0_problem = time.clock()
        self.solve_problem_nd_t(mesh, boundary_facets, ds, dS, V, VV, V_exact,
                                VV_exact, H_div, u_e, grad_u_e, f, A, invA,
                                adjA, self.min_eig_A, lmbd, a, u0, uD, uN,
                                C_FD, C_Ntr, delta, gamma, project_path,
                                results_folder_name, test_params)
        t1_problem = time.clock()

        print("time = %d s" % (t1_problem - t0_problem))
示例#3
0
    def test_estimates(self, test_params):

        # Define the project path
        # --------------------------------------------------------------------------------------------------------------#
        project_path = postprocess.get_project_path()

        # Check if it does exist and create folder for the results
        # --------------------------------------------------------------------------------------------------------------#
        results_folder_name = postprocess.construct_result_folder_name(
            self.dim, test_num, test_params)
        postprocess.create_results_folder(results_folder_name, test_params)

        # --------------------------------------------------------------------------------------------------------------#
        # Define problem data
        # --------------------------------------------------------------------------------------------------------------#

        # Define the mesh based on the domain geometry
        # --------------------------------------------------------------------------------------------------------------#
        mesh = self.construct_mesh(test_params["nx0"], test_params["nx1"],
                                   test_params["nx2"], test_params["res"],
                                   project_path)

        if test_params["PLOT"] == True:
            # Plot and save the initial mesh
            if self.dim == 2:
                postprocess.plot_mesh(
                    mesh, project_path + results_folder_name + 'initial-mesh')
            elif self.dim == 3:
                postprocess.plot_mesh_3d(
                    mesh, project_path + results_folder_name + 'initial-mesh')

        boundary_facets, ds, dS = self.construct_boundary_faces(mesh)

        # Calculate the estimate for Freidrichs constant based on the domain
        C_FD = problem.calculate_CF_of_domain(domain, self.dim)
        C_Ntr = self.calculate_trace_constant()

        # Define functional spaces based on the mesh
        #--------------------------------------------------------------------------------------------------------------#
        V, VV, V_exact, VV_exact, H_div = \
            problem.functional_spaces(mesh, test_params, self.dim)

        # Define problem data functions
        eps = 1e0  # initialize the eps
        #--------------------------------------------------------------------------------------------------------------#
        f, A, invA, adjA, min_eig_A, lmbd, a, uD, uN, u_e, grad_u_e = self.convert_problem_data_to_expressions(
            mesh, test_params, eps)

        # Output to console the problem data
        problem.output_problem_characteristics(
            self.test_num, self.u_expr, self.grad_u_expr, self.f_expr,
            self.A_expr, self.lambda_expr, self.a_expr,
            self.uD_expr, self.domain, self.dim, mesh.num_cells(),
            mesh.num_vertices(), test_params["v_approx_order"],
            test_params["flux_approx_order"])

        # Run the solver with a posteriori error control
        # --------------------------------------------------------------------------------------------------------------#
        t0_problem = time.clock()

        while eps > self.eps:

            mesh, V, VV, V_exact, VV_exact, H_div, boundary_facets, ds, dS \
                = self.solve_problem_nd_t(mesh, boundary_facets, ds, dS,
                                    V, V_exact, VV_exact, H_div,
                                    u_e, f, A, invA, adjA, min_eig_A, lmbd, a, eps,
                                    uD, uN,
                                    C_FD, C_Ntr,
                                    project_path, results_folder_name, test_params)

            test_params['number_of_refinements'] = test_params[
                'number_of_refinements'] + 2
            #test_params['percentage_value'] = test_params['percentage_value'] + 0.1
            eps = 1e-1 * eps
            f, A, invA, adjA, min_eig_A, lmbd, a, uD, uN, u_e, grad_u_e = self.convert_problem_data_to_expressions(
                mesh, test_params, eps)
            print "\n\nmin_eig_A = ", min_eig_A
            print "\n\nupdated eps = ", eps
            print "\n\n"

        t1_problem = time.clock()
        print("time = %d" % (t1_problem - t0_problem))