def mesh_it(self, rod_length = 0.5 , driver = [],mesher = [], bbox = [], density = "", visual = False, angles = False, save = []): """mesh_it(rod_length:float, driver, mesher, \ bbox:[float list,float list]), density, visual:bool, save:string list). Function to mesh the present object(s). The rod_length is the desired length of the connections between the mesh nodes, a value which is weighted with the C function density. The bbox defines the outer boundary box of the mesh. The flag visual consents to visualise the mesh during its relaxation process, and it can be saved specifying the file (with format) in the save list. Possible formats are postscript file(s) ("ps" extension) (2D only), vtk file(s) ("vtk" extension) (included the ones created at every visualization step) and "pyfem" format ("dat" extension). The function returns the mesh data in a python list of lists (the content is clear once they are inspected). """ self.rod = rod_length self.density = density if mesher == []: self.mesher = ocaml.mesher_defaults else: self.mesher = mesher.my_mesher self.__file_vtk = "" self.__file_ps = "" self.__file_dat = "" self.__file_png = "" globals()['fig_number']=0 globals()['angles_time']=[] globals()['default_iterations'] = 200 def check_save(): """Function to check if the mesh has to be saved in any format. """ # print "check_save" if len(save)>0: for filename in save: if filename[-3:]=="dat": self.__file_dat = filename elif filename[-3:]=="vtk": self.__file_vtk = filename elif filename[-3:]==".ps": self.__file_ps = filename elif filename[-3:]=="png": self.__file_png = filename else: ValueError ("wrong extension in save file name") # print self.__file_vtk, self.__file_ps, self.__file_dat, self.__file_png if visual: # Initialisation of mayavi if argument visual = True # print "load mayavi" import mayavi, pylab # Tk error without pylab self.myv = mayavi.mayavi() def check_vtk(nr_piece,n,mesh): # print "check_vtk -- 0" if visual or self.__file_vtk!="": # print "mesh_info" mesh_info = ocaml.mesh_plotinfo(mesh) # print "check_vtk -- 1" v = self._mesh2vtk(mesh_info,self.__file_vtk,"-"+str(nr_piece),"-"+str(n)) # print "check_vtk -- 2" if visual: # print "visual" # Function executed for argument visual = True self.myv.close_all() vd = self.myv.open_vtk_data(v) dvm = self.myv.get_current_dvm() mm = dvm.get_current_module_mgr() md = self.myv.load_module('SurfaceMap',0) # reverse LUT luthandler = mm.get_scalar_lut_handler() luthandler.set_lut_red_blue() # display legend, vertically with shadow effect luthandler.sc_bar.SetVisibility(1) luthandler.sc_bar.GetTitleTextProperty().SetShadow(1) luthandler.sc_bar.GetLabelTextProperty().SetShadow(1) luthandler.sc_bar.GetPositionCoordinate().SetValue(0.01,0.15) luthandler.sc_bar.SetOrientationToVertical() luthandler.sc_bar.SetWidth(0.14) luthandler.sc_bar.SetHeight(0.85) # luthandler.sc_bar.SetTitle('in2circ') self.myv.renwin.z_plus_view() vd2 = self.myv.open_vtk_data(v) dvm = self.myv.get_current_dvm() mm = dvm.get_current_module_mgr() md2 = self.myv.load_module('SurfaceMap',0) md2.mapper.ScalarVisibilityOff() md2.actor.GetProperty().SetRepresentationToWireframe() self.myv.renwin.z_plus_view() self.myv.Render() # if angles analysis has been requested plot histogram in pylab now if angles: angles_data = self._findAngles(mesh_info) n, bins, patches = pylab.hist(angles_data, range(0,180,5)) pylab.xlabel('Internal angle in degrees') pylab.ylabel('Number of occurrences') pylab.title('Histogram of internal angles of %d triangles' % (len(mesh_info[2][2]))) pylab.axvline(x=60, color='r') pylab.savefig(self.__file_png[:-4]+str(globals()['fig_number'])+'.png') globals()['fig_number'] = globals()['fig_number'] + 1 pylab.show() #(screws with Tk events) pylab.clf() # attempt to save time series of angles data for quality vs. time plot # this temporary hack saves the median angle for the highest count bin highest = 0 modal = 0 for i in range(len(n)): if n[i] > highest: highest = n[i] modal = i median = (bins[modal] + bins[modal-1])/2. globals()['angles_time'].append(median) raw_input('Hit Any Key to Continue') def no_driver(nr_piece,n,mesh): """Function executed for argument visual = False """ # print "no_driver" check_vtk(nr_piece,n,mesh) pass def fun_from_driver(nr_piece,n,mesh): """Function that glues together the user-defined function and the (possible) visualisation of the mesh during relaxation process. """ check_vtk(nr_piece,n,mesh) # print "*********************fun_from_driver" driver.driver_do(nr_piece,n,mesh) #user-defined function check_save() # check if the mesh has to be saved if driver == []: # no driver is given: use the default one self.driver = ocaml.make_mg_gendriver(globals()['default_iterations'], no_driver) else: # print self.__file_vtk self.driver = ocaml.make_mg_gendriver(driver.every_nr_steps,fun_from_driver) if bbox != []: # overwrite bbox defined at object initialisation self.bbox = bbox # print self.bbox # print self.obj obj_length = len(self.obj) # number of objects to mesh raw_mesh = ocaml.mesh_bodies_raw(self.driver,self.mesher,\ self.bbox[0],self.bbox[1],obj_length,\ self.obj,rod_length,self.density) if self.__file_ps != "": ocaml.mesh2d_ps(raw_mesh,self.__file_ps,[50.0,50.0,300.0,300.0]) if self.__file_dat != "": ocaml.mesh_writefile(self.__file_dat,raw_mesh) # to display final results in visual mode if visual: mesh_info = ocaml.mesh_plotinfo(raw_mesh) v = self._mesh2vtk(mesh_info,self.__file_vtk) self.myv.close_all() vd = self.myv.open_vtk_data(v) dvm = self.myv.get_current_dvm() mm = dvm.get_current_module_mgr() md = self.myv.load_module('SurfaceMap',0) # reverse LUT luthandler = mm.get_scalar_lut_handler() luthandler.set_lut_red_blue() # display legend, vertically with shadow effect luthandler.sc_bar.SetVisibility(1) luthandler.sc_bar.GetTitleTextProperty().SetShadow(1) luthandler.sc_bar.GetLabelTextProperty().SetShadow(1) luthandler.sc_bar.GetPositionCoordinate().SetValue(0.01,0.15) luthandler.sc_bar.SetOrientationToVertical() luthandler.sc_bar.SetWidth(0.14) luthandler.sc_bar.SetHeight(0.85) # luthandler.sc_bar.SetTitle('in2circ') self.myv.renwin.z_plus_view() vd2 = self.myv.open_vtk_data(v) dvm = self.myv.get_current_dvm() mm = dvm.get_current_module_mgr() md2 = self.myv.load_module('SurfaceMap',0) md2.mapper.ScalarVisibilityOff() md2.actor.GetProperty().SetRepresentationToWireframe() self.myv.renwin.z_plus_view() self.myv.Render() if self.__file_png: # if angles analysis has been requested plot histogram in pylab now if angles: angles_data = self._findAngles(mesh_info) n, bins, patches = pylab.hist(angles_data, range(0,180,5)) pylab.clf() pylab.xlabel('Internal angle in degrees') pylab.ylabel('Number of occurrences') pylab.title('Histogram of internal angles of mesh triangles') pylab.axvline(x=60, color='r') pylab.savefig(self.__file_png[:-4]+str(globals()['fig_number'])+'.png') globals()['fig_number'] = globals()['fig_number'] + 1 pylab.show() #(screws with Tk events) # also save time plot of angles pylab.clf() total_iterations = globals()['default_iterations']*len(globals()['angles_time']) xvalues = range(0,total_iterations,globals()['default_iterations']) pylab.plot(xvalues,globals()['angles_time'],'k+') pylab.hold(True) pylab.plot(xvalues,globals()['angles_time']) pylab.xlabel('Number of iterations') pylab.ylabel('Modal internal angle (2D) in degrees') pylab.title('Plot of mesh quality against time') pylab.savefig(self.__file_png[:-4]+'_time.png') raw_input('Hit Any Key to Exit.') else: mesh_info = ocaml.mesh_plotinfo(raw_mesh) raw_input('Hit Any Key to Exit.')
def __init__(self, objects = [], rod_length = 0.5, bbox = [[],[]], density="", periodic = False, visual = False, fixed_points = [], fun=[], fun_call_interval = 1000): """ Class to define the parameters for the meshing algorithm. mesh( objects:obj list - objects to be meshed rod_length:float - desired length of connection between nodes bbox:[float list,float list] - outer bounding box density:string - density function of nodes ditribution periodic:bool - periodic boundary conditions in the outer box visual:bool - use of the visualisation package fixed_points: float list list - set of fixed points to be used in the mesh fun - function to be called every interval steps fun_call_interval:int - interval of the function calling ). The rod_length is the desired length of the connections between the mesh nodes, a value which is weighted with the density function (given in C code). The bbox defines the outer boundary box of the mesh. The function fun is executed every fun_call_interval steps and its arguments are nr_piece = index of the meshing object iteration_nr = number of iteration in the relaxation process mesh = mesh as a python list of lists (value returned by mesh_it()) The visual flag and the periodic flag are used to visualise and impose periodic boundary conditions on the outer box, respectively. If periodic boundary conditions are used, the density function must respect the related contraints. """ self.obj = [] if type(objects) == types.ListType : for obj in objects: self.obj.append(obj.obj) else: raise ValueError("Error: wrong list of objects to mesh.") self.rod = rod_length self.bbox = bbox self.density = density if periodic: self.periodic = 1 else: self.periodic = 0 if visual: #import m.visual pass if fun == []: self.fun_driver = self._default_fun else: self.fun_driver = fun self.fun_call_interval = fun_call_interval self.fixed_points = fixed_points # add fixed points coming from objects for obj in objects: for pt in obj.fxd_pts: self.fixed += pt self.mesher = 0 # flag for default/copied mesher self.my_mesher = ocaml.mesher_defaults # default mesher self.driver = ocaml.make_mg_gendriver(self.fun_call_interval, self.extended_fun_driver) self.raw_mesh = []