def perform_mesh_convergence_study(a_usr_input: dict):
    study_result = dict()
    print('Performing mesh convergence study --- START.')


    for rho_gamma in a_usr_input['rho']:
        print('rho_gamma = ' + str(rho_gamma))
        i = 0
        for mesh in a_usr_input['cv_y']:
            i = i+1
            print('mesh = ' + str(i))

            # Prepare.
            current_study = {'mesh': None, 'fields': None, 'coeffs': None, 'solver': None}
            current_study_name = 'rho_gamma' + str(rho_gamma) + '_' + 'mesh' + str(i)
            current_study_user_input = a_usr_input.copy()
            current_study_user_input['rho'] = rho_gamma
            current_study_user_input['cv_y'] = mesh
            current_study_user_input['cv_x'] = 2*mesh  # For Smith-Hutton problem, to keep the mesh constant, as the domain is twice as long as high.
            current_study_user_input['number_of_nodes'] = mesh * (2 * mesh)

            # Perform.
            current_study['mesh'] = Mesher(current_study_user_input)
            current_study['mesh'].build_mesh()

            current_study['fields'] = Fields(current_study_user_input,
                                             current_study['mesh'])
            current_study['fields'].build_velocity()
            current_study['fields'].build_phi()
            current_study['fields'].build_convection_strength()
            current_study['fields'].build_diffusion_strength()
            current_study['fields'].build_peclet_number()

            current_study['coeffs'] = DiscretCoeffs(current_study_user_input,
                                                    current_study['mesh'],
                                                    current_study['fields'])
            current_study['coeffs'].build_coeffs()

            current_study['solver'] = SolverGaussSeidelPhi(current_study_user_input,
                                                           current_study['mesh'],
                                                           current_study['fields'],
                                                           current_study['coeffs'])
            tic('Solving')
            current_study['solver'].solve_phi(p_verbose_level=0)
            toc('Solving')
            current_study['solver'].timer = timer.copy()

            if (current_study['solver'].solution_divergence):
                print(current_study_name + ' - Solution has diverged.')

            # Save the current study.
            study_result[current_study_name] = current_study

    print('Performing mesh convergence study ---   END.')
    return study_result
def perform_numerical_scheme_study(a_usr_input):
    study_result = dict()
    print('Performing numerical scheme study --- START.')

    for scheme in a_usr_input['numerical_scheme']:
        print('Numerical scheme = ' + scheme)
        for rho_gamma in a_usr_input['rho']:
            print('rho_gamma = ' + str(rho_gamma))
            # Prepare.
            current_study = {'mesh': None, 'fields': None, 'coeffs': None, 'solver': None}
            current_study_name = 'rho_gamma_' + str(rho_gamma) + '_scheme_' + scheme
            current_study_user_input = a_usr_input.copy()
            current_study_user_input['numerical_scheme'] = scheme
            current_study_user_input['rho'] = rho_gamma

            # Perform.
            current_study['mesh'] = Mesher(current_study_user_input)
            current_study['mesh'].build_mesh()

            current_study['fields'] = Fields(current_study_user_input,
                                             current_study['mesh'])
            current_study['fields'].build_velocity()
            current_study['fields'].build_phi()
            current_study['fields'].build_convection_strength()
            current_study['fields'].build_diffusion_strength()
            current_study['fields'].build_peclet_number()

            current_study['coeffs'] = DiscretCoeffs(current_study_user_input,
                                                    current_study['mesh'],
                                                    current_study['fields'])
            current_study['coeffs'].build_coeffs()

            current_study['solver'] = SolverGaussSeidelPhi(current_study_user_input,
                                                           current_study['mesh'],
                                                           current_study['fields'],
                                                           current_study['coeffs'])
            tic('Solving')
            current_study['solver'].solve_phi(p_verbose_level=0)
            toc('Solving')
            current_study['solver'].timer = timer.copy()

            if (current_study['solver'].solution_divergence):
                print(current_study_name + ' - Solution has diverged.')

            # Save the current study.
            study_result[current_study_name] = current_study

    print('Performing numerical scheme study --- END.')
    return study_result
                     a_n_Radius_north=5 * n_lengths,
                     a_n_Radius_south=-5 * n_lengths)
mesh.build_mesh()

# Initialize velocity, pressure, temperature, density, and stream function fields.
fields = Fields(mesh, phys_prop)
fields.build_v()
fields.build_P()
fields.build_T()
fields.build_rho()
fields.build_Psi()

# Initialize stream function coefficients: aP, aE, aW, aN, aS.
coeffs = DiscretCoeffs(mesh, phys_prop, fields)
coeffs.build_coeffs()
toc('Preprocessing')

# Solve for the stream function.
tic('Solving')
solver = SolverGaussSeidelPsi(epsilon, mesh, fields, coeffs)
solver.solve_psi()
toc('Solving')

# Postprocess by solving the interesting flow physical variables.
tic('Postprocessing')
postprocessor = SolverPhysicalQuantities(mesh, fields, coeffs, phys_prop)
postprocessor.solve_velocity()
postprocessor.solve_temperature()
postprocessor.solve_pressure()
postprocessor.solve_rho()