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
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
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)
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)
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
# 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