def close_fun(self, master, main):
        # Check that inputs are correct.
        if self.user_choice.get() == self.options_list[0] and self.z_of_r.get(
        ) == '':
            messagebox.showwarning(
                title='Error',
                message=
                'No function was introduced, and it cannot be left blank.\n'
                'Introduce a valid function.')
            return
        elif self.user_choice.get() == self.options_list[1]:
            if self.r_fun.get() == '' or self.z_fun.get() == '':
                messagebox.showwarning(
                    title='Error',
                    message='One of the functions was not introduced.\n'
                    'Introduce a valid function.')
                return
        elif self.user_choice.get() == self.default_choice:
            messagebox.showwarning(
                title='Error',
                message='Please, select an option before proceeding.')
            return

        self.master2.destroy()
        label = tk.Label(
            master,
            text='File was properly loaded. You can now close this window.',
            justify='center')
        label.grid(row=2, column=1)
        master.destroy()

        # Generate the .geo file from the given data.
        self.geo_gen = GMSHInterface()
        num_points = int(self.number_points.get())
        initial_ind_coord = str_2_num(self.initial_ind_coord.get())
        final_ind_coord = str_2_num(self.final_ind_coord.get())
        self.base_data = np.linspace(initial_ind_coord, final_ind_coord,
                                     num_points)
        if self.z_of_r.get() != '':
            self.geo_gen.geometry_generator(interface_fun=self.z_of_r.get(),
                                            r=self.base_data)
        elif self.z_fun.get() is not None and self.r_fun.get() is not None:
            self.geo_gen.geometry_generator(interface_fun_r=self.r_fun.get(),
                                            interface_fun_z=self.z_fun.get(),
                                            independent_param=self.base_data,
                                            angle_unit=self.angle_unit)
        self.msh_filename = self.geo_gen.mesh_generation_GUI()
        main.msh_filename = self.msh_filename
Beispiel #2
0
    def get_boundaries(self):
        """
        Define the boundaries of the problem from the facet_region generated
        by dolfin.
        Parameters
        ----------
        mesh: cpp.mesh.Mesh
            Mesh object.
        name: string
            Name of the .xml file (with or without extension).
        mesh_folder_path: string
            Name of the path of the folder where the mesh is stored.
        Returns
        -------
        boundaries: cpp.mesh.MeshFunctionSizet
            Object containing all the defined boundaries.
        """

        bound_name = self.filename.split('.')[0] + '_facet_region.xml'
        file = self.mesh_folder_path + '/' + bound_name
        self.boundaries = df.MeshFunction('size_t', self.mesh, file)

        # Obtain the boundaries ids from the .geo file.
        """
        For this part, we do not need to take into account if curves or
        physical surfaces are defined first. This is already taken into
        account in the gmsh_handle.get_physical_curves_and_tags. Since we
        only accept two subdomains, if these are defined first, we know that
        the first curve id will be 3, the next one 4 and so on.
        """
        self.boundaries_ids, _ = GMSHInterface.get_boundaries_ids(
            self.geo_filepath)
        return self.boundaries, self.boundaries_ids
Beispiel #3
0
    def get_subdomains(self):
        """
        Load the subdomains data for a given mesh. More specifically, this method loads the physical_region.xml file
        generated by the dolfin-converter.
        Returns:

        """
        if self.subdomains is None:
            sub_name = self.filename.split('.')[0] + '_physical_region.xml'
            file = self.mesh_folder_path + '/' + sub_name
            self.subdomains = df.MeshFunction('size_t', self.mesh, file)

        # Obtain the ids of the subdomains.
        self.subdomains_ids = GMSHInterface.get_subdomains_ids(self.geo_file)
Beispiel #4
0
    def get_boundaries(self):
        """
        Load the boundaries data of the mesh. More specifically, this method loads the facet_region.xml file generated
        by the dolfin-converter.
        Returns:

        """
        if self.boundaries is None:
            bound_name = self.filename.split('.')[0] + '_facet_region.xml'
            file = self.mesh_folder_path + '/' + bound_name
            self.boundaries = fn.MeshFunction('size_t', self.mesh, file)

        if self.boundaries_ids is None:
            self.boundaries_ids, _ = GMSHInterface.get_boundaries_ids(
                self.geo_file)
Beispiel #5
0
    def get_subdomains(self):
        """
        Obtain the subdomains of the problem from the physical_region file
        generated by the dolfin converter.
        Raises
        ------
        AttributeError
            If boundaries are defined first in the .geo file and boundaries
            were not defined previously, this error will warn the user about
            that, and give the proper advice.
        Returns
        -------
        dolfin.cpp.mesh.MeshFunctionSizet
            Object containing the subdomains info.
        """

        sub_name = self.filename.split('.')[0] + '_physical_region.xml'
        filepath = self.mesh_folder_path + '/' + sub_name
        self.subdomains = df.MeshFunction('size_t', self.mesh, filepath)
        self.subdomains_ids = GMSHInterface.get_subdomains_ids(
            self.geo_filepath)

        return self.subdomains, self.subdomains_ids
Beispiel #6
0
    # Substitute possible conflicts between used numerical parser and sympy symbology.
    fprime = fprime.subs({'PI': sp.pi})
    fprime2 = fprime2.subs({'PI': sp.pi})

    # Transform the derivatives into evaluable functions.
    fprimeLambdified = sp.lambdify(sym_ind_param, fprime, 'numpy')
    fprime2Lambdified = sp.lambdify(sym_ind_param, fprime2, 'numpy')

    return fprimeLambdified, fprime2Lambdified


# Introduce the surface parametrization.
if app.geom_data.angle_unit == 'degrees':  # Need to transform degrees into radians.
    if app.geom_data.z_of_r.get() == '':
        fun_surf = GMSHInterface.angle_handler(app.geom_data.z_fun.get())
        r_param = app.geom_data.r_fun.get()
        r_param = sp.sympify(r_param)
        ind_data = app.geom_data.base_data
    else:
        fun_surf = GMSHInterface.angle_handler(app.geom_data.z_of_r.get())
        r_data = app.geom_data.base_data
else:
    if app.geom_data.z_of_r.get() == '':
        fun_surf = app.geom_data.z_fun.get()
        r_param = app.geom_data.r_fun.get()
        r_param = sp.sympify(r_param)
        ind_data = app.geom_data.base_data
    else:
        fun_surf = app.geom_data.z_of_r.get()
        r_data = app.geom_data.base_data
class GeometryGeneration(tk.Frame):
    def __init__(self, master1, main):
        """
		Initialize the GeometryGeneration class, which will contain all the methods and attributes required to generate
		a geometry. When initialized, a GUI will pop up, where the user will be able to personalize all the geometry
		options to generate the desired .geo file.
		Args:
			master1: master window.
			main: main menu object
		"""
        master2 = tk.Tk()
        master2.title('Create a new Geometry')
        tk.Frame.__init__(self, master2)
        self.master2 = master2
        self.finish = False
        self.msh_filename = ''

        # Create the Labels of the inputs.
        tk.Label(master2,
                 text='Select an option for the interface expression').grid(
                     row=0, column=0)
        tk.Label(master2, text='Expression z=f(r)').grid(row=1, column=0)
        tk.Label(master2, text='Expression for r').grid(row=2, column=0)
        tk.Label(master2, text='Expression for z').grid(row=3, column=0)
        tk.Label(master2, text='Number of points:').grid(row=4, column=0)
        tk.Label(master2,
                 text='Initial independent parameter coordinate:').grid(
                     row=5, column=0)
        tk.Label(master2,
                 text='Final independent parameter coordinate:').grid(row=6,
                                                                      column=0)

        # Create the string variables that will store the inputs of the user.
        self.user_choice = tk.StringVar(master2)
        self.user_choice.set('Select an option...')
        self.default_choice = self.user_choice.get()
        self.z_of_r = tk.StringVar(master2)
        self.r_fun = tk.StringVar(master2)
        self.z_fun = tk.StringVar(master2)
        self.number_points = tk.StringVar(master2)
        self.number_points.set('200')
        self.initial_ind_coord = tk.StringVar(master2)
        self.initial_ind_coord.set('0')
        self.final_ind_coord = tk.StringVar(master2)
        self.final_ind_coord.set('1')
        self.degrees_var = tk.BooleanVar(master2)
        self.degrees = False
        self.angle_unit = 'radians'
        self.base_data = None

        # Create the option menu.
        self.options_dict = {
            'z = f(r)': 'z = f(r)',
            'Expressions for r and z': 'Expressions for r and z',
            'Predefined function': 'Predefined function'
        }
        self.options_list = list(self.options_dict.values())
        option_menu = tk.OptionMenu(master2,
                                    self.user_choice,
                                    *self.options_dict,
                                    command=self.option_fun)
        option_menu.grid(row=0, column=1, padx=10, pady=10)
        option_menu.configure(foreground='BLACK', activeforeground='BLACK')

        # Create an option to introduce the number of points.
        tk.Entry(master=self.master2,
                 textvariable=self.number_points,
                 justify='center').grid(row=4, column=1, padx=10, pady=10)

        # Create a button to close the create geometry menu.
        close_but = tk.Button(self.master,
                              text='Save and close.',
                              command=lambda: self.close_fun(master1, main))
        close_but.grid(row=7, column=2, padx=10, pady=10)
        close_but.configure(foreground='BLACK', activeforeground='BLACK')

    def option_fun(self, value):
        self.user_choice.set(value)

        # Call the function controlling the input boxes.
        self.control_boxes()

    def control_boxes(self):
        tk.Entry(master=self.master2,
                 textvariable=self.initial_ind_coord,
                 state=tk.DISABLED,
                 justify='center').grid(row=5, column=1, padx=10, pady=10)
        tk.Entry(master=self.master2,
                 textvariable=self.final_ind_coord,
                 justify='center').grid(row=6, column=1, padx=10, pady=10)
        degrees_check = tk.Checkbutton(master=self.master2,
                                       variable=self.degrees_var,
                                       text='Degrees?',
                                       command=self.check_angle_units)
        degrees_check.grid(row=7, column=1, padx=10, pady=10)
        CreateToolTip(
            degrees_check,
            'If any angle is introduced, check this option to set\n'
            'degrees as the unit to be used. Otherwise, radians\n'
            'will be used.\n'
            'Note: Ignore this option if no angles are introduced.')
        if self.user_choice.get() == self.options_list[
                0]:  # This means that the user want a f(z) option.
            self.z_fun.set('')
            self.r_fun.set('')
            tk.Entry(master=self.master2,
                     textvariable=self.z_of_r,
                     justify='center').grid(row=1, column=1, padx=10, pady=10)
            tk.Entry(master=self.master2,
                     textvariable=self.r_fun,
                     state=tk.DISABLED,
                     justify='center').grid(row=2, column=1, padx=10, pady=10)
            tk.Entry(master=self.master2,
                     textvariable=self.z_fun,
                     state=tk.DISABLED,
                     justify='center').grid(row=3, column=1, padx=10, pady=10)
        elif self.user_choice.get() == self.options_list[-1]:
            fun_data = PredefinedFunctions(self)
            if fun_data.user_fun.get() == 'Half Taylor Cone':
                tk.Entry(master=self.master2,
                         textvariable=self.z_of_r,
                         state=tk.DISABLED,
                         justify='center').grid(row=1,
                                                column=1,
                                                padx=10,
                                                pady=10)
                self.r_fun.set('((1-2*s)*1)/(1-2*s*(1-s)*(1-20))')
                self.z_fun.set(
                    '(2*(1-s)*s*20*(1/tan(49.3))*1)/(1-2*s*(1-s)*(1-20))')
                tk.Entry(master=self.master2,
                         textvariable=self.r_fun,
                         justify='center').grid(row=2,
                                                column=1,
                                                padx=10,
                                                pady=10)
                tk.Entry(master=self.master2,
                         textvariable=self.z_fun,
                         justify='center').grid(row=3,
                                                column=1,
                                                padx=10,
                                                pady=10)
                self.degrees_var.set(True)
        else:
            tk.Entry(master=self.master2,
                     textvariable=self.z_of_r,
                     state=tk.DISABLED,
                     justify='center').grid(row=1, column=1, padx=10, pady=10)
            tk.Entry(master=self.master2,
                     textvariable=self.r_fun,
                     justify='center').grid(row=2, column=1, padx=10, pady=10)
            tk.Entry(master=self.master2,
                     textvariable=self.z_fun,
                     justify='center').grid(row=3, column=1, padx=10, pady=10)

    def check_angle_units(self):
        """
		This function checks the option chosen by the user on the Degrees? checkbox from the GUI.
		Returns:

		"""
        if self.degrees_var.get():
            self.degrees = True
            self.angle_unit = 'degrees'
        else:
            self.degrees = False
            self.angle_unit = 'radians'

    def close_fun(self, master, main):
        # Check that inputs are correct.
        if self.user_choice.get() == self.options_list[0] and self.z_of_r.get(
        ) == '':
            messagebox.showwarning(
                title='Error',
                message=
                'No function was introduced, and it cannot be left blank.\n'
                'Introduce a valid function.')
            return
        elif self.user_choice.get() == self.options_list[1]:
            if self.r_fun.get() == '' or self.z_fun.get() == '':
                messagebox.showwarning(
                    title='Error',
                    message='One of the functions was not introduced.\n'
                    'Introduce a valid function.')
                return
        elif self.user_choice.get() == self.default_choice:
            messagebox.showwarning(
                title='Error',
                message='Please, select an option before proceeding.')
            return

        self.master2.destroy()
        label = tk.Label(
            master,
            text='File was properly loaded. You can now close this window.',
            justify='center')
        label.grid(row=2, column=1)
        master.destroy()

        # Generate the .geo file from the given data.
        self.geo_gen = GMSHInterface()
        num_points = int(self.number_points.get())
        initial_ind_coord = str_2_num(self.initial_ind_coord.get())
        final_ind_coord = str_2_num(self.final_ind_coord.get())
        self.base_data = np.linspace(initial_ind_coord, final_ind_coord,
                                     num_points)
        if self.z_of_r.get() != '':
            self.geo_gen.geometry_generator(interface_fun=self.z_of_r.get(),
                                            r=self.base_data)
        elif self.z_fun.get() is not None and self.r_fun.get() is not None:
            self.geo_gen.geometry_generator(interface_fun_r=self.r_fun.get(),
                                            interface_fun_z=self.z_fun.get(),
                                            independent_param=self.base_data,
                                            angle_unit=self.angle_unit)
        self.msh_filename = self.geo_gen.mesh_generation_GUI()
        main.msh_filename = self.msh_filename