def default_traits_view(self): ''' Generates the view from the param items. ''' param_items = [Item(name) for name in self.param_keys] ctrl_items = [Item(name) for name in self.ctrl_keys] view = View(VGroup(*param_items, id='stats.spirrid.rf.params'), VGroup(*ctrl_items, id='stats.spirrid.rf.ctrl'), kind='modal', height=0.3, width=0.2, scrollable=True, resizable=True, buttons=['OK', 'Cancel'], id='stats.spirrid.rf') return view
def default_traits_view(self): ''' Generates the view from the param items. ''' rf_param_items = [ Item('model.' + name, format_str='%g') for name in self.model.param_keys ] plot_param_items = [ Item('eps_max'), Item('n_eps'), Item('x_name', label='x-axis'), Item('y_name', label='y-axis') ] control_items = [ Item('show', show_label=False), Item('clear', show_label=False), ] view = View(HSplit( VGroup(*rf_param_items, label='Function Parameters', id='stats.spirrid_bak.rf_model_view.rf_params', scrollable=True), VGroup(*plot_param_items, label='Plot Parameters', id='stats.spirrid_bak.rf_model_view.plot_params'), VGroup( Item('model.comment', show_label=False, style='readonly'), label='Comment', id='stats.spirrid_bak.rf_model_view.comment', scrollable=True, ), VGroup(HGroup(*control_items), Item('figure', editor=MPLFigureEditor(), resizable=True, show_label=False), label='Plot', id='stats.spirrid_bak.rf_model_view.plot'), dock='tab', id='stats.spirrid_bak.rf_model_view.split'), kind='modal', resizable=True, dock='tab', buttons=['Ok', 'Cancel'], id='stats.spirrid_bak.rf_model_view') return view
class ECBLCalibStateModelView(ModelView): '''Model in a viewable window. ''' model = Instance(ECBLCalibState) def _model_default(self): return ECBLCalibState() cs_state = Property(Instance(ECBCrossSectionState), depends_on = 'model') @cached_property def _get_cs_state(self): return self.model.cs_state data_changed = Event figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor = 'white') return figure replot = Button() def _replot_fired(self): ax = self.figure.add_subplot(1, 1, 1) self.model.calibrated_ecb_law.plot(ax) self.data_changed = True clear = Button() def _clear_fired(self): self.figure.clear() self.data_changed = True calibrated_ecb_law = Property(Instance(ECBLBase), depends_on = 'model') @cached_property def _get_calibrated_ecb_law(self): return self.model.calibrated_ecb_law view = View(HSplit(VGroup( Item('cs_state', label = 'Cross section', show_label = False), Item('model@', show_label = False), Item('calibrated_ecb_law@', show_label = False, resizable = True), ), Group(HGroup( Item('replot', show_label = False), Item('clear', show_label = False), ), Item('figure', editor = MPLFigureEditor(), resizable = True, show_label = False), id = 'simexdb.plot_sheet', label = 'plot sheet', dock = 'tab', ), ), width = 0.5, height = 0.4, buttons = ['OK', 'Cancel'], resizable = True)
def default_traits_view(self): ''' Generates the view from the param items. ''' #rf_param_items = [ Item( 'model.' + name, format_str = '%g' ) for name in self.model.param_keys ] D2_plot_param_items = [ VGroup(Item('max_x', label='max x value'), Item('x_points', label='No of plot points')) ] if hasattr(self.rf, 'get_q_x'): D3_plot_param_items = [ VGroup(Item('min_x', label='min x value'), Item('max_x', label='max x value'), Item('min_y', label='min y value'), Item('max_y', label='max y value')) ] else: D3_plot_param_items = [] control_items = [ Item('show', show_label=False), Item('clear', show_label=False), ] view = View( HSplit( VGroup(Item('@rf', show_label=False), label='Function parameters', id='stats.spirrid_bak.rf_model_view.rf_params', scrollable=True), VGroup(HGroup(*D2_plot_param_items), label='plot parameters', id='stats.spirrid_bak.rf_model_view.2Dplot_params'), # VGroup( HGroup( *D3_plot_param_items ), # label = '3D plot parameters', # id = 'stats.spirrid_bak.rf_model_view.3Dplot_params' ), VGroup( Item('model.comment', show_label=False, style='readonly'), label='Comment', id='stats.spirrid_bak.rf_model_view.comment', scrollable=True, ), VGroup(HGroup(*control_items), Item('figure', editor=MPLFigureEditor(), resizable=True, show_label=False), label='Plot', id='stats.spirrid_bak.rf_model_view.plot'), dock='tab', id='stats.spirrid_bak.rf_model_view.split'), kind='modal', resizable=True, dock='tab', buttons=[OKButton], id='stats.spirrid_bak.rf_model_view') return view
def default_traits_view(self): '''checks the number of shape parameters of the distribution and adds them to the view instance''' label = str(self.distribution.name) if self.distribution.shapes == None: params = Item() if self.mean == infty: moments = Item(label='No finite moments defined') else: moments = Item('mean', label='mean'), \ Item('variance', label='variance'), \ Item('stdev', label='st. deviation', style='readonly') elif len(self.distribution.shapes) == 1: params = Item('shape', label='shape') if self.mean == infty: moments = Item(label='No finite moments defined') else: moments = Item('mean', label='mean'), \ Item('variance', label='variance'), \ Item('stdev', label='st. deviation', style='readonly'), \ Item('skewness', label='skewness'), \ Item('kurtosis', label='kurtosis'), else: params = Item() moments = Item() view = View(VGroup(Label(label, emphasized=True), Group(params, Item('loc', label='location'), Item('scale', label='scale'), Item('loc_zero', label='loc = 0.0'), show_border=True, label='parameters', id='pdistrib.distribution.params'), Group( moments, id='pdistrib.distribution.moments', show_border=True, label='moments', ), id='pdistrib.distribution.vgroup'), kind='live', resizable=True, id='pdistrib.distribution.view') return view
class ExpBT3PT(ExType): '''Experiment: Bending Test Three Point ''' # label = Str('three point bending test') implements(IExType) file_ext = 'raw' #-------------------------------------------------------------------- # register a change of the traits with metadata 'input' #-------------------------------------------------------------------- input_change = Event @on_trait_change('+input, ccs.input_change, +ironing_param') def _set_input_change(self): self.input_change = True #-------------------------------------------------------------------------------- # specify inputs: #-------------------------------------------------------------------------------- length = Float(0.46, unit='m', input=True, table_field=True, auto_set=False, enter_set=True) width = Float(0.1, unit='m', input=True, table_field=True, auto_set=False, enter_set=True) thickness = Float(0.02, unit='m', input=True, table_field=True, auto_set=False, enter_set=True) # age of the concrete at the time of testing age = Int(33, unit='d', input=True, table_field=True, auto_set=False, enter_set=True) loading_rate = Float(4.0, unit='mm/min', input=True, table_field=True, auto_set=False, enter_set=True) #-------------------------------------------------------------------------- # composite cross section #-------------------------------------------------------------------------- ccs = Instance(CompositeCrossSection) def _ccs_default(self): '''default settings ''' # fabric_layout_key = 'MAG-07-03' # fabric_layout_key = '2D-02-06a' fabric_layout_key = '2D-05-11' # fabric_layout_key = '2D-09-12' # concrete_mixture_key = 'PZ-0708-1' # concrete_mixture_key = 'FIL-10-09' concrete_mixture_key = 'barrelshell' orientation_fn_key = 'all0' # orientation_fn_key = 'all90' # orientation_fn_key = '90_0' n_layers = 6 s_tex_z = 0.020 / (n_layers + 1) ccs = CompositeCrossSection(fabric_layup_list=[ plain_concrete(s_tex_z * 0.5), FabricLayUp(n_layers=n_layers, orientation_fn_key=orientation_fn_key, s_tex_z=s_tex_z, fabric_layout_key=fabric_layout_key), plain_concrete(s_tex_z * 0.5) ], concrete_mixture_key=concrete_mixture_key) return ccs #-------------------------------------------------------------------------- # Get properties of the composite #-------------------------------------------------------------------------- # E-modulus of the composite at the time of testing E_c = Property(Float, unit='MPa', depends_on='input_change', table_field=True) def _get_E_c(self): return self.ccs.get_E_c_time(self.age) # E-modulus of the composite after 28 days E_c28 = DelegatesTo('ccs', listenable=False) # reinforcement ration of the composite rho_c = DelegatesTo('ccs', listenable=False) #-------------------------------------------------------------------------------- # define processing #-------------------------------------------------------------------------------- # flag distinguishes weather data from a displacement gauge is available # stored in a separate ASC-file with a corresponding file name # flag_ASC_file = Bool(False) def _read_data_array(self): ''' Read the experiment data. ''' if exists(self.data_file): print 'READ FILE' file_split = self.data_file.split('.') # first check if a '.csv' file exists. If yes use the # data stored in the '.csv'-file and ignore # the data in the '.raw' file! # file_name = file_split[0] + '.csv' if not os.path.exists(file_name): file_name = file_split[0] + '.raw' if not os.path.exists(file_name): raise IOError, 'file %s does not exist' % file_name print 'file_name', file_name _data_array = loadtxt_bending(file_name) self.data_array = _data_array # check if a '.ASC'-file exists. If yes append this information # to the data array. # file_name = file_split[0] + '.ASC' if not os.path.exists(file_name): print 'NOTE: no data from displacement gauge is available (no .ASC file)' self.flag_ASC_file = False else: print 'NOTE: additional data from displacement gauge for center deflection is available (.ASC-file loaded)!' self.flag_ASC_file = True # add data array read in from .ASC-file; the values are assigned by '_set_array_attribs' based on the # read in values in 'names_and_units' read in from the corresponding .DAT-file # self.data_array_ASC = loadtxt(file_name, delimiter=';') else: print 'WARNING: data_file with path %s does not exist == False' % ( self.data_file) names_and_units = Property(depends_on='data_file') @cached_property def _get_names_and_units(self): '''names and units corresponding to the returned '_data_array' by 'loadtxt_bending' ''' names = ['w_raw', 'eps_c_raw', 'F_raw'] units = ['mm', '1*E-3', 'N'] print 'names, units from .raw-file', names, units return names, units names_and_units_ASC = Property(depends_on='data_file') @cached_property def _get_names_and_units_ASC(self): ''' Extract the names and units of the measured data. The order of the names in the .DAT-file corresponds to the order of the .ASC-file. ''' file_split = self.data_file.split('.') file_name = file_split[0] + '.DAT' data_file = open(file_name, 'r') lines = data_file.read().split() names = [] units = [] for i in range(len(lines)): if lines[i] == '#BEGINCHANNELHEADER': name = lines[i + 1].split(',')[1] unit = lines[i + 3].split(',')[1] names.append(name) units.append(unit) print 'names, units extracted from .DAT-file', names, units return names, units factor_list_ASC = Property(depends_on='data_file') def _get_factor_list_ASC(self): return self.names_and_units_ASC[0] def _set_array_attribs(self): '''Set the measured data as named attributes defining slices into the processed data array. ''' for i, factor in enumerate(self.factor_list): self.add_trait( factor, Array(value=self.processed_data_array[:, i], transient=True)) if self.flag_ASC_file: for i, factor in enumerate(self.factor_list_ASC): self.add_trait( factor, Array(value=self.data_array_ASC[:, i], transient=True)) elastomer_law = Property(depends_on='input_change') @cached_property def _get_elastomer_law(self): elastomer_path = os.path.join(simdb.exdata_dir, 'bending_tests', 'three_point', '2011-06-10_BT-3PT-12c-6cm-0-TU_ZiE', 'elastomer_f-w.raw') _data_array_elastomer = loadtxt_bending(elastomer_path) # force [kN]: # NOTE: after conversion 'F_elastomer' is a positive value # F_elastomer = -0.001 * _data_array_elastomer[:, 2].flatten() # displacement [mm]: # NOTE: after conversion 'w_elastomer' is a positive value # w_elastomer = -1.0 * _data_array_elastomer[:, 0].flatten() mfn_displacement_elastomer = MFnLineArray(xdata=F_elastomer, ydata=w_elastomer) return frompyfunc(mfn_displacement_elastomer.get_value, 1, 1) w_wo_elast = Property(depends_on='input_change') @cached_property def _get_w_wo_elast(self): # use the machine displacement for the center displacement: # subtract the deformation of the elastomer cushion between the cylinder # and change sign in positive values for vertical displacement [mm] # return self.w_raw - self.elastomer_law(self.F_raw) M_ASC = Property(Array('float_'), depends_on='input_change') @cached_property def _get_M_ASC(self): return self.F_ASC * self.length / 4.0 M_raw = Property(Array('float_'), depends_on='input_change') @cached_property def _get_M_raw(self): return self.F_raw * self.length / 4.0 # # get only the ascending branch of the response curve # # # max_force_idx = Property(Int) # def _get_max_force_idx(self): # '''get the index of the maximum force''' # return argmax(-self.Kraft) # # f_asc = Property(Array) # def _get_f_asc(self): # '''get only the ascending branch of the response curve''' # return -self.Kraft[:self.max_force_idx + 1] K_bending_elast = Property(Array('float_'), depends_on='input_change') @cached_property def _get_K_bending_elast(self): '''calculate the analytical bending stiffness of the beam (3 point bending) ''' t = self.thickness w = self.width L = self.length # coposite E-modulus # E_c = self.E_c # moment of inertia # I_yy = t**3 * w / 12. delta_11 = (L**3) / 48 / E_c / I_yy # [MN/m]=[kN/mm] bending stiffness with respect to a force applied at center of the beam # K_bending_elast = 1 / delta_11 # print 'K_bending_elast', K_bending_elast return K_bending_elast F_cr = Property(Array('float_'), depends_on='input_change') @cached_property def _get_F_cr(self): '''calculate the analytical cracking load of the beam ''' t = self.thickness w = self.width L = self.length # approx. flectural tensile strength # f_cfl = 6. # MPa # resistant moment # W_yy = t**2 * w / 6. # analytical cracking load of the beam # corresponds to l = 0.46m and f_cfl = approx. 8.4 MPa# # F_cr = W_yy * f_cfl * 1000. / L # [kN] return F_cr def process_source_data(self): '''read in the measured data from file and assign attributes after array processing. ''' super(ExpBT3PT, self).process_source_data() #--------------------------------------------- # process data from .raw file (machine data) #--------------------------------------------- # convert machine force [N] to [kN] and return only positive values # self.F_raw *= -0.001 # convert machine displacement [mm] to positive values # and remove offset # self.w_raw *= -1.0 self.w_raw -= self.w_raw[0] # convert [permille] to [-] and return only positive values # self.eps_c_raw *= -0.001 # access the derived arrays to initiate their processing # self.w_wo_elast self.M_raw #--------------------------------------------- # process data from .ASC file (displacement gauge) #--------------------------------------------- # only if separate ASC.-file with force-displacement data from displacement gauge is available # if self.flag_ASC_file == True: self.F_ASC = -1.0 * self.Kraft # remove offset and change sign to return positive displacement values # if hasattr(self, "WA50"): self.WA50 *= -1 self.WA50 -= self.WA50[0] WA50_avg = np.average(self.WA50) if hasattr(self, "W10_u"): self.W10_u *= -1 self.W10_u -= self.W10_u[0] W10_u_avg = np.average(self.W10_u) # check which displacement gauge has been used depending on weather two names are listed in .DAT file or only one # and assign values to 'w_ASC' # if hasattr(self, "W10_u") and hasattr(self, "WA50"): if W10_u_avg > WA50_avg: self.w_ASC = self.W10_u print 'self.W10_u assigned to self.w_ASC' else: self.w_ASC = self.WA50 print 'self.WA50 assigned to self.w_ASC' elif hasattr(self, "W10_u"): self.w_ASC = self.W10_u print 'self.W10_u assigned to self.w_ASC' elif hasattr(self, "WA50"): self.w_ASC = self.WA50 print 'self.WA50 assigned to self.w_ASC' # convert strain from [permille] to [-], # switch to positive values for compressive strains # and remove offset # self.eps_c_ASC = -0.001 * self.DMS_l self.eps_c_ASC -= self.eps_c_ASC[0] # access the derived arrays to initiate their processing # self.M_ASC #-------------------------------------------------------------------------------- # plot templates #-------------------------------------------------------------------------------- plot_templates = { 'force / machine displacement (incl. w_elast)': '_plot_force_machine_displacement', 'force / machine displacement (without w_elast)': '_plot_force_machine_displacement_wo_elast', 'force / machine displacement (without w_elast, interpolated)': '_plot_force_machine_displacement_wo_elast_interpolated', 'force / machine displacement (analytical offset)': '_plot_force_machine_displacement_wo_elast_analytical_offset', 'force / gauge displacement': '_plot_force_gauge_displacement', 'force / gauge displacement (analytical offset)': '_plot_force_gauge_displacement_with_analytical_offset', 'force / gauge displacement (interpolated)': '_plot_force_gauge_displacement_interpolated', # 'smoothed force / gauge displacement' : '_plot_smoothed_force_gauge_displacement', # 'smoothed force / machine displacement' : '_plot_smoothed_force_machine_displacement_wo_elast', # 'moment / eps_c (ASC)': '_plot_moment_eps_c_ASC', 'moment / eps_c (raw)': '_plot_moment_eps_c_raw', # # 'smoothed moment / eps_c (ASC)' : '_plot_smoothed_moment_eps_c_ASC', # 'smoothed moment / eps_c (raw)' : '_plot_smoothed_moment_eps_c_raw', # # 'analytical bending stiffness' : '_plot_analytical_bending_stiffness' } default_plot_template = 'force / deflection (displacement gauge)' def _plot_analytical_bending_stiffness(self, axes, color='red', linewidth=1., linestyle='--'): '''plot the analytical bending stiffness of the beam (3 point bending) ''' t = self.thickness w = self.width L = self.length # composite E-modulus # E_c = self.E_c # moment of inertia # I_yy = t**3 * w / 12. delta_11 = L**3 / 48 / E_c / I_yy K_linear = 1 / delta_11 # [MN/m] bending stiffness with respect to a force applied at center of the beam w_linear = 2 * np.array([0., 1.]) F_linear = 2 * np.array([0., K_linear]) axes.plot(w_linear, F_linear, linestyle='--') def _plot_force_machine_displacement_wo_elast(self, axes, color='blue', linewidth=1., linestyle='-'): # get the index of the maximum stress # max_force_idx = argmax(self.F_raw) # get only the ascending branch of the response curve # f_asc = self.F_raw[:max_force_idx + 1] w_asc = self.w_wo_elast[:max_force_idx + 1] axes.plot(w_asc, f_asc, color=color, linewidth=linewidth, linestyle=linestyle) # plot analytical bending stiffness # w_linear = 2 * np.array([0., 1.]) F_linear = 2 * np.array([0., self.K_bending_elast]) axes.plot(w_linear, F_linear, linestyle='--') # xkey = 'deflection [mm]' # ykey = 'force [kN]' # axes.set_xlabel('%s' % (xkey,)) # axes.set_ylabel('%s' % (ykey,)) def _plot_force_machine_displacement_wo_elast_interpolated( self, axes, color='green', linewidth=1., linestyle='-'): # get the index of the maximum stress # max_force_idx = argmax(self.F_raw) # get only the ascending branch of the response curve # f_asc = self.F_raw[:max_force_idx + 1] w_asc = np.copy(self.w_wo_elast[:max_force_idx + 1]) # interpolate the starting point of the center deflection curve based on the slope of the curve # (remove offset in measured displacement where there is still no force measured) # idx_10 = np.where(f_asc > f_asc[-1] * 0.10)[0][0] idx_8 = np.where(f_asc > f_asc[-1] * 0.08)[0][0] f8 = f_asc[idx_8] f10 = f_asc[idx_10] w8 = w_asc[idx_8] w10 = w_asc[idx_10] m = (f10 - f8) / (w10 - w8) delta_w = f8 / m w0 = w8 - delta_w * 0.9 # print 'w0', w0 f_asc_interpolated = np.hstack([0., f_asc[idx_8:]]) w_asc_interpolated = np.hstack([w0, w_asc[idx_8:]]) # print 'type( w_asc_interpolated )', type(w_asc_interpolated) w_asc_interpolated -= float(w0) axes.plot(w_asc_interpolated, f_asc_interpolated, color=color, linewidth=linewidth, linestyle=linestyle) # fw_arr = np.hstack([f_asc_interpolated[:, None], w_asc_interpolated[:, None]]) # print 'fw_arr.shape', fw_arr.shape # np.savetxt('BT-3PT-12c-6cm-TU_f-w_interpolated.csv', fw_arr, delimiter=';') # plot analytical bending stiffness # w_linear = 2 * np.array([0., 1.]) F_linear = 2 * np.array([0., self.K_bending_elast]) axes.plot(w_linear, F_linear, linestyle='--') def _plot_force_machine_displacement_wo_elast_analytical_offset( self, axes, color='green', linewidth=1., linestyle='-'): # get the index of the maximum stress # max_force_idx = argmax(self.F_raw) # get only the ascending branch of the response curve # f_asc = self.F_raw[:max_force_idx + 1] w_asc = np.copy(self.w_wo_elast[:max_force_idx + 1]) M_asc = f_asc * self.length / 4. eps_c_asc = self.eps_c_raw[:max_force_idx + 1] t = self.thickness w = self.width # coposite E-modulus # E_c = self.E_c # resistant moment # W_yy = t**2 * w / 6. K_I_analytic = W_yy * E_c # [MN/m] bending stiffness with respect to center moment K_I_analytic *= 1000. # [kN/m] bending stiffness with respect to center moment # interpolate the starting point of the center deflection curve based on the slope of the curve # (remove offset in measured displacement where there is still no force measured) # idx_lin = np.where(M_asc <= K_I_analytic * eps_c_asc)[0][0] idx_lin = int(idx_lin * 0.7) # idx_lin = 50 # idx_lin = np.where(M_asc - M_asc[0] / eps_c_asc <= 0.90 * K_I_analytic)[0][0] print 'idx_lin', idx_lin print 'F_asc[idx_lin]', f_asc[idx_lin] print 'M_asc[idx_lin]', M_asc[idx_lin] print 'w_asc[idx_lin]', w_asc[idx_lin] w_lin_epsc = w_asc[idx_lin] w_lin_analytic = f_asc[idx_lin] / self.K_bending_elast f_asc_offset_analytic = f_asc[idx_lin:] w_asc_offset_analytic = w_asc[idx_lin:] w_asc_offset_analytic -= np.array([w_lin_epsc]) w_asc_offset_analytic += np.array([w_lin_analytic]) axes.plot(w_asc_offset_analytic, f_asc_offset_analytic, color=color, linewidth=linewidth, linestyle=linestyle) # plot analytical bending stiffness # w_linear = 2 * np.array([0., 1.]) F_linear = 2 * np.array([0., self.K_bending_elast]) axes.plot(w_linear, F_linear, linestyle='--') def _plot_force_machine_displacement(self, axes, color='black', linewidth=1., linestyle='-'): xdata = self.w_raw ydata = self.F_raw axes.plot(xdata, ydata, color=color, linewidth=linewidth, linestyle=linestyle) # xkey = 'deflection [mm]' # ykey = 'force [kN]' # axes.set_xlabel('%s' % (xkey,)) # axes.set_ylabel('%s' % (ykey,)) # plot analytical bending stiffness # w_linear = 2 * np.array([0., 1.]) F_linear = 2 * np.array([0., self.K_bending_elast]) axes.plot(w_linear, F_linear, linestyle='--') def _plot_force_gauge_displacement_with_analytical_offset( self, axes, color='black', linewidth=1., linestyle='-'): # skip the first values (= first seconds of testing) # and start with the analytical bending stiffness instead to avoid artificial offset of F-w-diagram # # w_max = np.max(self.w_ASC) # cut_idx = np.where(self.w_ASC > 0.001 * w_max)[0] cut_idx = np.where(self.w_ASC > 0.01)[0] print 'F_cr ', self.F_cr # cut_idx = np.where(self.F_ASC > 0.6 * self.F_cr)[0] print 'cut_idx', cut_idx[0] print 'w_ASC[cut_idx[0]]', self.w_ASC[cut_idx[0]] xdata = np.copy(self.w_ASC[cut_idx]) ydata = np.copy(self.F_ASC[cut_idx]) # specify offset if force does not start at the origin with value 0. F_0 = ydata[0] print 'F_0 ', F_0 offset_w = F_0 / self.K_bending_elast xdata -= xdata[0] xdata += offset_w f_asc_interpolated = np.hstack([0, ydata]) w_asc_interpolated = np.hstack([0, xdata]) # fw_arr = np.hstack([f_asc_interpolated[:, None], w_asc_interpolated[:, None]]) # print 'fw_arr.shape', fw_arr.shape # np.savetxt('BT-3PT-6c-2cm-TU_f-w_interpolated.csv', fw_arr, delimiter=';') xdata = self.w_raw ydata = self.F_raw axes.plot(xdata, ydata, color='blue', linewidth=linewidth, linestyle=linestyle) axes.plot(w_asc_interpolated, f_asc_interpolated, color=color, linewidth=linewidth, linestyle=linestyle) # xkey = 'deflection [mm]' # ykey = 'force [kN]' # axes.set_xlabel('%s' % (xkey,)) # axes.set_ylabel('%s' % (ykey,)) # plot analytical bending stiffness # w_linear = 2 * np.array([0., 1.]) F_linear = 2 * np.array([0., self.K_bending_elast]) axes.plot(w_linear, F_linear, linestyle='--') def _plot_force_gauge_displacement(self, axes, offset_w=0., color='black', linewidth=1., linestyle='-'): xdata = self.w_ASC ydata = self.F_ASC # specify offset if force does not start at the origin xdata += offset_w axes.plot(xdata, ydata, color=color, linewidth=linewidth, linestyle=linestyle) # xkey = 'deflection [mm]' # ykey = 'force [kN]' # axes.set_xlabel('%s' % (xkey,)) # axes.set_ylabel('%s' % (ykey,)) # fw_arr = np.hstack([xdata[:, None], ydata[:, None]]) # print 'fw_arr.shape', fw_arr.shape # np.savetxt('BT-3PT-6c-2cm-TU-80cm-V3_f-w_asc.csv', fw_arr, delimiter=';') # plot analytical bending stiffness # w_linear = 2 * np.array([0., 1.]) F_linear = 2 * np.array([0., self.K_bending_elast]) axes.plot(w_linear, F_linear, linestyle='--') def _plot_smoothed_force_gauge_displacement(self, axes): # get the index of the maximum stress # max_force_idx = argmax(self.F_ASC) # get only the ascending branch of the response curve # F_asc = self.F_ASC[:max_force_idx + 1] w_asc = self.w_ASC[:max_force_idx + 1] n_points = int(self.n_fit_window_fraction * len(w_asc)) F_smooth = smooth(F_asc, n_points, 'flat') w_smooth = smooth(w_asc, n_points, 'flat') axes.plot(w_smooth, F_smooth, color='blue', linewidth=2) def _plot_force_gauge_displacement_interpolated(self, axes, color='green', linewidth=1., linestyle='-'): '''get only the ascending branch of the meassured load-displacement curve)''' # get the index of the maximum stress # max_force_idx = argmax(self.F_ASC) # get only the ascending branch of the response curve # f_asc = self.F_ASC[:max_force_idx + 1] w_asc = self.w_ASC[:max_force_idx + 1] # interpolate the starting point of the center deflection curve based on the slope of the curve # (remove offset in measured displacement where there is still no force measured) # idx_10 = np.where(f_asc > f_asc[-1] * 0.10)[0][0] idx_8 = np.where(f_asc > f_asc[-1] * 0.08)[0][0] f8 = f_asc[idx_8] f10 = f_asc[idx_10] w8 = w_asc[idx_8] w10 = w_asc[idx_10] m = (f10 - f8) / (w10 - w8) delta_w = f8 / m w0 = w8 - delta_w * 0.9 print 'w0', w0 f_asc_interpolated = np.hstack([0., f_asc[idx_8:]]) w_asc_interpolated = np.hstack([w0, w_asc[idx_8:]]) print 'type( w_asc_interpolated )', type(w_asc_interpolated) w_asc_interpolated -= float(w0) # w_offset = f_asc[idx_10] / self.K_bending_elast # f_asc_interpolated = np.hstack([0., f_asc[ idx_10: ]]) # w_asc_interpolated = np.hstack([0, w_asc[ idx_10: ] - w_asc[idx_10] + w_offset]) axes.plot(w_asc_interpolated, f_asc_interpolated, color=color, linewidth=linewidth, linestyle=linestyle) # plot analytical bending stiffness # w_linear = 2 * np.array([0., 1.]) F_linear = 2 * np.array([0., self.K_bending_elast]) axes.plot(w_linear, F_linear, linestyle='--') def _plot_smoothed_force_machine_displacement_wo_elast(self, axes): # get the index of the maximum stress # max_force_idx = argmax(self.F_raw) # get only the ascending branch of the response curve # F_asc = self.F_raw[:max_force_idx + 1] w_asc = self.w_wo_elast[:max_force_idx + 1] n_points = int(self.n_fit_window_fraction * len(w_asc)) F_smooth = smooth(F_asc, n_points, 'flat') w_smooth = smooth(w_asc, n_points, 'flat') axes.plot(w_smooth, F_smooth, color='blue', linewidth=2) # plot analytical bending stiffness # w_linear = 2 * np.array([0., 1.]) F_linear = 2 * np.array([0., self.K_bending_elast]) axes.plot(w_linear, F_linear, linestyle='--') # secant_stiffness_w10 = ( f_smooth[10] - f_smooth[0] ) / ( w_smooth[10] - w_smooth[0] ) # w0_lin = array( [0.0, w_smooth[10] ], dtype = 'float_' ) # f0_lin = array( [0.0, w_smooth[10] * secant_stiffness_w10 ], dtype = 'float_' ) # axes.plot( w0_lin, f0_lin, color = 'black' ) def _plot_moment_eps_c_ASC(self, axes): xkey = 'compressive strain [1*E-3]' ykey = 'moment [kNm]' xdata = self.eps_c_ASC ydata = self.M_ASC axes.set_xlabel('%s' % (xkey, )) axes.set_ylabel('%s' % (ykey, )) axes.plot(xdata, ydata) # plot stiffness in uncracked state t = self.thickness w = self.width # composite E-modulus # E_c = self.E_c # resistant moment # W_yy = t**2 * w / 6. max_M = np.max(self.M_raw) K_linear = W_yy * E_c # [MN/m] bending stiffness with respect to center moment K_linear *= 1000. # [kN/m] bending stiffness with respect to center moment w_linear = np.array([0., max_M / K_linear]) M_linear = np.array([0., max_M]) axes.plot(w_linear, M_linear, linestyle='--') def _plot_moment_eps_c_raw(self, axes, color='black', linewidth=1.5, linestyle='-'): xkey = 'compressive strain [1*E-3]' ykey = 'moment [kNm]' xdata = self.eps_c_raw ydata = self.M_raw axes.set_xlabel('%s' % (xkey, )) axes.set_ylabel('%s' % (ykey, )) axes.plot(xdata, ydata, color=color, linewidth=linewidth, linestyle=linestyle) # plot stiffness in uncracked state t = self.thickness w = self.width # composite E-modulus # E_c = self.E_c # resistant moment # W_yy = t**2 * w / 6. max_M = np.max(self.M_raw) K_linear = W_yy * E_c # [MN/m] bending stiffness with respect to center moment K_linear *= 1000. # [kN/m] bending stiffness with respect to center moment w_linear = np.array([0., max_M / K_linear]) M_linear = np.array([0., max_M]) axes.plot(w_linear, M_linear, linestyle='--') n_fit_window_fraction = Float(0.1) smoothed_M_eps_c_ASC = Property(depends_on='input_change') @cached_property def _get_smoothed_M_eps_c_ASC(self): # get the index of the maximum stress max_idx = argmax(self.M_ASC) # get only the ascending branch of the response curve m_asc = self.M_ASC[:max_idx + 1] eps_c_asc = self.eps_c_ASC[:max_idx + 1] n_points = int(self.n_fit_window_fraction * len(eps_c_asc)) m_smoothed = smooth(m_asc, n_points, 'flat') eps_c_smoothed = smooth(eps_c_asc, n_points, 'flat') return m_smoothed, eps_c_smoothed smoothed_eps_c_ASC = Property def _get_smoothed_eps_c_ASC(self): return self.smoothed_M_eps_c_ASC[1] smoothed_M_ASC = Property def _get_smoothed_M_ASC(self): return self.smoothed_M_eps_c_ASC[0] def _plot_smoothed_moment_eps_c_ASC(self, axes): axes.plot(self.smoothed_eps_c_ASC, self.smoothed_M_ASC, color='blue', linewidth=2) smoothed_M_eps_c_raw = Property(depends_on='input_change') @cached_property def _get_smoothed_M_eps_c_raw(self): # get the index of the maximum stress max_idx = argmax(self.M_raw) # get only the ascending branch of the response curve m_asc = self.M_raw[:max_idx + 1] eps_c_asc = self.eps_c_raw[:max_idx + 1] n_points = int(self.n_fit_window_fraction * len(eps_c_asc)) m_smoothed = smooth(m_asc, n_points, 'flat') eps_c_smoothed = smooth(eps_c_asc, n_points, 'flat') return m_smoothed, eps_c_smoothed smoothed_eps_c_raw = Property def _get_smoothed_eps_c_raw(self): return self.smoothed_M_eps_c_raw[1] smoothed_M_raw = Property def _get_smoothed_M_raw(self): return self.smoothed_M_eps_c_raw[0] def _plot_smoothed_moment_eps_c_raw(self, axes): axes.plot(self.smoothed_eps_c_raw, self.smoothed_M_raw, color='blue', linewidth=2) #-------------------------------------------------------------------------------- # view #-------------------------------------------------------------------------------- traits_view = View(VGroup( Group(Item('length', format_str="%.3f"), Item('width', format_str="%.3f"), Item('thickness', format_str="%.3f"), label='geometry'), Group(Item('loading_rate'), Item('age'), label='loading rate and age'), Group(Item('E_c', show_label=True, style='readonly', format_str="%.0f"), Item('ccs@', show_label=False), label='composite cross section')), scrollable=True, resizable=True, height=0.8, width=0.6)
class SPIRRIDModelView(ModelView): title = Str('spirrid exec ctrl') model = Instance(SPIRRID) ins = Instance(NoOfFibers) def _ins_default(self): return NoOfFibers() eval = Button def _eval_fired(self): Specimen_Volume = self.ins.Lx * self.ins.Ly * self.ins.Lz self.no_of_fibers_in_specimen = ( Specimen_Volume * self.ins.Fiber_volume_fraction / 100) / ( pi * (self.ins.Fiber_diameter / 20)**2 * self.ins.Fiber_Length / 10) prob_crackbridging_fiber = (self.ins.Fiber_Length / (10 * 2)) / self.ins.Lx self.mean_parallel_links = prob_crackbridging_fiber * self.no_of_fibers_in_specimen self.stdev_parallel_links = (prob_crackbridging_fiber * self.no_of_fibers_in_specimen * (1 - prob_crackbridging_fiber))**0.5 run = Button(desc='Run the computation') def _run_fired(self): self.evaluate() run_legend = Str('mean response', desc='Legend to be added to the plot of the results') min_eps = Float(0.0, desc='minimum value of the control variable') max_eps = Float(1.0, desc='maximum value of the control variable') n_eps = Int(100, desc='resolution of the control variable') plot_title = Str('response', desc='diagram title') label_x = Str('epsilon', desc='label of the horizontal axis') label_y = Str('sigma', desc='label of the vertical axis') stdev = Bool(True) mean_parallel_links = Float(1., desc='mean number of parallel links (fibers)') stdev_parallel_links = Float( 0., desc='stdev of number of parallel links (fibers)') no_of_fibers_in_specimen = Float( 0., desc='Number of Fibers in the specimen', ) data_changed = Event(True) def evaluate(self): self.model.set( min_eps=0.00, max_eps=self.max_eps, n_eps=self.n_eps, ) # evaluate the mean curve self.model.mean_curve # evaluate the variance if the stdev bool is True if self.stdev: self.model.var_curve self.data_changed = True traits_view = View(VGroup( HGroup( Item('run_legend', resizable=False, label='Run label', width=80, springy=False), Item('run', show_label=False, resizable=False)), Tabbed( VGroup( Item('model.cached_dG', label='Cached weight factors', resizable=False, springy=False), Item('model.compiled_QdG_loop', label='Compiled loop over the integration product', springy=False), Item('model.compiled_eps_loop', enabled_when='model.compiled_QdG_loop', label='Compiled loop over the control variable', springy=False), scrollable=True, label='Execution configuration', id='spirrid.tview.exec_params', dock='tab', ), VGroup( HGroup(Item('min_eps', label='Min', springy=False, resizable=False), Item('max_eps', label='Max', springy=False, resizable=False), Item('n_eps', label='N', springy=False, resizable=False), label='Simulation range', show_border=True), HGroup(Item('stdev', label='plot standard deviation'), ), HSplit( HGroup( VGroup( Item('mean_parallel_links', label='mean No of fibers'), Item('stdev_parallel_links', label='stdev No of fibers'), )), VGroup( Item('@ins', label='evaluate No of fibers', show_label=False), VGroup( HGroup( Item('eval', show_label=False, resizable=False, label='Evaluate No of Fibers'), Item('no_of_fibers_in_specimen', label='No of Fibers in specimen', style='readonly')))), label='number of parralel fibers', show_border=True, scrollable=True, ), VGroup( Item('plot_title', label='title', resizable=False, springy=False), Item('label_x', label='x', resizable=False, springy=False), Item('label_y', label='y', resizable=False, springy=False), label='title and axes labels', show_border=True, scrollable=True, ), label='Execution control', id='spirrid.tview.view_params', dock='tab', ), scrollable=True, id='spirrid.tview.tabs', dock='tab', ), ), title='SPIRRID', id='spirrid.viewmodel', dock='tab', resizable=True, height=1.0, width=1.0)
class MKYarnPDistrib(HasTraits): implements(IPDistrib) n_int = Int(50, auto_set=False, enter_set=True, input=True) p_s = Float(0.0, auto_set=False, enter_set=True, input=True) p_c = Float(0.0, auto_set=False, enter_set=True, input=True) k_s = Float(0.0, auto_set=False, enter_set=True, input=True) k_c = Float(0.0, auto_set=False, enter_set=True, input=True) x_array = Property(depends_on='+input') @cached_property def _get_x_array(self): a = min(self.p_s, self.p_c) b = max(self.p_s, self.p_c) return linspace(a, b, self.n_int) polynom = Property(depends_on='+input') @cached_property def _get_polynom(self): p_c = self.p_c p_s = self.p_s k_s = self.k_s k_c = self.k_c a = min(self.p_s, self.p_c) b = max(self.p_s, self.p_c) xi = linspace(-0.2, 1.2, 1000) x = (p_c - p_s) * ((k_s + k_c - 2) * xi**3 + (3 - 2 * k_s - k_c) * xi**2 + k_s * xi) + p_s x = sort(x) xi = sort(xi) return MFnLineArray(xdata=x, ydata=xi) cdf_array = Property(depends_on='+input') @cached_property def _get_cdf_array(self): line = self.polynom X = self.x_array pyCDF = frompyfunc(line.get_value, 1, 1) return array(pyCDF(X), dtype='float_') pdf_array = Property(depends_on='+input') @cached_property def _get_pdf_array(self): line = self.polynom X = self.x_array pyf = frompyfunc(line.get_diff, 1, 1) PDF = array(pyf(X), dtype='float_') return PDF dx = Property() def _get_dx(self): return abs(self.p_c - self.p_s) / (self.n_int - 1) def get_pdf_array(self, x_array): line = self.polynom X = x_array pyf = frompyfunc(line.get_diff, 1, 1) PDF = array(pyf(X), dtype='float_') return PDF def integ(self): return trapz(self.pdf_array, x=self.x_array) data_mean = Property(Float, depends_on='+input') @cached_property def _get_data_mean(self): X = self.x_array x = linspace(X[0], X[-1], 300) PDF = self.get_pdf_array(x) data_mean = trapz(x * PDF, x=x) return data_mean data_stdev = Property(Float, depends_on='+input') @cached_property def _get_data_stdev(self): X = self.x_array x = linspace(X[0], X[-1], 300) PDF = self.get_pdf_array(x) data_stdev = sqrt(trapz(x**2 * PDF, x=x) - self.data_mean**2) return data_stdev figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor='white') return figure data_changed = Event @on_trait_change('+input') def refresh(self): figure = self.figure figure.clear() axes = figure.gca() # plot PDF and CDF X = self.x_array x = linspace(X[0], X[-1], 300) PDF = self.get_pdf_array(x) line = self.polynom pyCDF = frompyfunc(line.get_value, 1, 1) CDF = pyCDF(x) axes.plot(x, PDF, lw=1.0, color='blue', \ label='PDF') axes2 = axes.twinx() # plot CDF on a separate axis (tick labels left) axes2.plot(x, CDF, lw=2, color='red', \ label='CDF') # fill the unity area given by integrating PDF along the X-axis axes.fill_between(x, 0, PDF, color='lightblue', alpha=0.8, linewidth=2) # plot mean mean = self.data_mean axes.plot([mean, mean], [0.0, self.get_pdf_array(mean)], lw=1.5, color='black', linestyle='-') # plot stdev stdev = self.data_stdev axes.plot([mean - stdev, mean - stdev], [0.0, self.get_pdf_array(mean - stdev)], lw=1.5, color='black', linestyle='--') axes.plot([mean + stdev, mean + stdev], [0.0, self.get_pdf_array(mean + stdev)], lw=1.5, color='black', linestyle='--') axes.legend(loc='upper center') axes2.legend(loc='upper right') axes.ticklabel_format(scilimits=(-3., 4.)) axes2.ticklabel_format(scilimits=(-3., 4.)) # plot limits on X and Y axes axes.set_ylim(0.0, max(PDF) * 1.15) axes2.set_ylim(0.0, 1.15) axes.set_xlim(X[0], X[-1]) axes2.set_xlim(X[0], X[-1]) self.data_changed = True traits_view = View(HSplit( VGroup(Item('p_c'), Item('p_s'), Item('k_c'), Item('k_s'), Item('data_mean', label='mean', style='readonly'), Item('data_stdev', label='stdev', style='readonly')), VGroup(Item('figure', editor=MPLFigureEditor(), show_label=False, resizable=True), id='mk.figure.view'), ), id='mk.view', buttons=[OKButton, CancelButton], resizable=True, width=600, height=400)
class ECBReinfTexUniform(ECBReinfComponent): '''Cross section characteristics needed for tensile specimens ''' height = DelegatesTo('matrix_cs') '''height of reinforced cross section ''' n_layers = Int(12, auto_set=False, enter_set=True, geo_input=True) '''total number of reinforcement layers [-] ''' n_rovings = Int(23, auto_set=False, enter_set=True, geo_input=True) '''number of rovings in 0-direction of one composite layer of the bending test [-]: ''' A_roving = Float(0.461, auto_set=False, enter_set=True, geo_input=True) '''cross section of one roving [mm**2]''' def convert_eps_tex_u_2_lo(self, eps_tex_u): '''Convert the strain in the lowest reinforcement layer at failure to the strain at the bottom of the cross section''' eps_up = self.state.eps_up return eps_up + (eps_tex_u - eps_up) / self.z_ti_arr[0] * self.height def convert_eps_lo_2_tex_u(self, eps_lo): '''Convert the strain at the bottom of the cross section to the strain in the lowest reinforcement layer at failure''' eps_up = self.state.eps_up return (eps_up + (eps_lo - eps_up) / self.height * self.z_ti_arr[0]) '''Convert the MN to kN ''' #=========================================================================== # material properties #=========================================================================== sig_tex_u = Float(1216., auto_set=False, enter_set=True, tt_input=True) '''Ultimate textile stress measured in the tensile test [MPa] ''' #=========================================================================== # Distribution of reinforcement #=========================================================================== s_tex_z = Property(depends_on=ECB_COMPONENT_AND_EPS_CHANGE) '''spacing between the layers [m]''' @cached_property def _get_s_tex_z(self): return self.height / (self.n_layers + 1) z_ti_arr = Property(depends_on=ECB_COMPONENT_AND_EPS_CHANGE) '''property: distance of each reinforcement layer from the top [m]: ''' @cached_property def _get_z_ti_arr(self): return np.array([ self.height - (i + 1) * self.s_tex_z for i in range(self.n_layers) ], dtype=float) zz_ti_arr = Property '''property: distance of reinforcement layers from the bottom ''' def _get_zz_ti_arr(self): return self.height - self.z_ti_arr #=========================================================================== # Discretization conform to the tex layers #=========================================================================== eps_i_arr = Property(depends_on=ECB_COMPONENT_AND_EPS_CHANGE) '''Strain at the level of the i-th reinforcement layer ''' @cached_property def _get_eps_i_arr(self): # ------------------------------------------------------------------------ # geometric params independent from the value for 'eps_t' # ------------------------------------------------------------------------ height = self.height eps_lo = self.state.eps_lo eps_up = self.state.eps_up # strain at the height of each reinforcement layer [-]: # return eps_up + (eps_lo - eps_up) * self.z_ti_arr / height eps_ti_arr = Property(depends_on=ECB_COMPONENT_AND_EPS_CHANGE) '''Tension strain at the level of the i-th layer of the fabrics ''' @cached_property def _get_eps_ti_arr(self): return (np.fabs(self.eps_i_arr) + self.eps_i_arr) / 2.0 eps_ci_arr = Property(depends_on=ECB_COMPONENT_AND_EPS_CHANGE) '''Compression strain at the level of the i-th layer. ''' @cached_property def _get_eps_ci_arr(self): return (-np.fabs(self.eps_i_arr) + self.eps_i_arr) / 2.0 #=========================================================================== # Effective crack bridge law #=========================================================================== ecb_law_type = Trait('fbm', dict(fbm=ECBLFBM, cubic=ECBLCubic, linear=ECBLLinear, bilinear=ECBLBilinear), tt_input=True) '''Selector of the effective crack bridge law type ['fbm', 'cubic', 'linear', 'bilinear']''' ecb_law = Property(Instance(ECBLBase), depends_on='+tt_input') '''Effective crack bridge law corresponding to ecb_law_type''' @cached_property def _get_ecb_law(self): return self.ecb_law_type_(sig_tex_u=self.sig_tex_u, cs=self) show_ecb_law = Button '''Button launching a separate view of the effective crack bridge law. ''' def _show_ecb_law_fired(self): ecb_law_mw = ConstitutiveLawModelView(model=self.ecb_law) ecb_law_mw.edit_traits(kind='live') return tt_modified = Event sig_ti_arr = Property(depends_on=ECB_COMPONENT_AND_EPS_CHANGE) '''Stresses at the i-th fabric layer. ''' @cached_property def _get_sig_ti_arr(self): return self.ecb_law.mfn_vct(self.eps_ti_arr) f_ti_arr = Property(depends_on=ECB_COMPONENT_AND_EPS_CHANGE) '''force at the height of each reinforcement layer [kN]: ''' @cached_property def _get_f_ti_arr(self): sig_ti_arr = self.sig_ti_arr n_rovings = self.n_rovings A_roving = self.A_roving return sig_ti_arr * n_rovings * A_roving / self.unit_conversion_factor figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor='white') figure.add_axes([0.08, 0.13, 0.85, 0.74]) return figure data_changed = Event replot = Button def _replot_fired(self): self.figure.clear() ax = self.figure.add_subplot(2, 2, 1) self.plot_eps(ax) ax = self.figure.add_subplot(2, 2, 2) self.plot_sig(ax) ax = self.figure.add_subplot(2, 2, 3) self.cc_law.plot(ax) ax = self.figure.add_subplot(2, 2, 4) self.ecb_law.plot(ax) self.data_changed = True def plot_eps(self, ax): #ax = self.figure.gca() d = self.height # eps ti ax.plot([-self.eps_lo, -self.eps_up], [0, self.height], color='black') ax.hlines(self.zz_ti_arr, [0], -self.eps_ti_arr, lw=4, color='red') # eps cj ec = np.hstack([self.eps_cj_arr] + [0, 0]) zz = np.hstack([self.zz_cj_arr] + [0, self.height]) ax.fill(-ec, zz, color='blue') # reinforcement layers eps_range = np.array([max(0.0, self.eps_lo), min(0.0, self.eps_up)], dtype='float') z_ti_arr = np.ones_like(eps_range)[:, None] * self.z_ti_arr[None, :] ax.plot(-eps_range, z_ti_arr, 'k--', color='black') # neutral axis ax.plot(-eps_range, [d, d], 'k--', color='green', lw=2) ax.spines['left'].set_position('zero') ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.spines['left'].set_smart_bounds(True) ax.spines['bottom'].set_smart_bounds(True) ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') def plot_sig(self, ax): d = self.height # f ti ax.hlines(self.zz_ti_arr, [0], -self.f_ti_arr, lw=4, color='red') # f cj f_c = np.hstack([self.f_cj_arr] + [0, 0]) zz = np.hstack([self.zz_cj_arr] + [0, self.height]) ax.fill(-f_c, zz, color='blue') f_range = np.array( [np.max(self.f_ti_arr), np.min(f_c)], dtype='float_') # neutral axis ax.plot(-f_range, [d, d], 'k--', color='green', lw=2) ax.spines['left'].set_position('zero') ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.spines['left'].set_smart_bounds(True) ax.spines['bottom'].set_smart_bounds(True) ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') view = View(HSplit( Group( HGroup( Group(Item('height', springy=True), Item('width'), Item('n_layers'), Item('n_rovings'), Item('A_roving'), label='Geometry', springy=True), Group(Item('eps_up', label='Upper strain', springy=True), Item('eps_lo', label='Lower strain'), label='Strain', springy=True), springy=True, ), HGroup( Group(VGroup(Item('cc_law_type', show_label=False, springy=True), Item('cc_law', label='Edit', show_label=False, springy=True), Item('show_cc_law', label='Show', show_label=False, springy=True), springy=True), Item('f_ck', label='Compressive strength'), Item('n_cj', label='Discretization'), label='Concrete', springy=True), Group(VGroup( Item('ecb_law_type', show_label=False, springy=True), Item('ecb_law', label='Edit', show_label=False, springy=True), Item('show_ecb_law', label='Show', show_label=False, springy=True), springy=True, ), label='Reinforcement', springy=True), springy=True, ), Group( Item('s_tex_z', label='vertical spacing', style='readonly'), label='Layout', ), Group(HGroup( Item('M', springy=True, style='readonly'), Item('N', springy=True, style='readonly'), ), label='Stress resultants'), scrollable=True, ), Group( Item('replot', show_label=False), Item('figure', editor=MPLFigureEditor(), resizable=True, show_label=False), id='simexdb.plot_sheet', label='plot sheet', dock='tab', ), ), width=0.8, height=0.7, resizable=True, buttons=['OK', 'Cancel'])
class SLS(LS): '''Serviceability limit state ''' # ------------------------------------------------------------ # SLS: material parameters (Inputs) # ------------------------------------------------------------ # tensile strength [MPa] f_ctk = Float(4.0, input=True) # flexural tensile strength [MPa] f_m = Float(5.0, input=True) # ------------------------------------------------------------ # SLS - derived params: # ------------------------------------------------------------ # area # A = Property(Float) def _get_A(self): return self.ls_table.D_elem * 1. # moment of inertia # W = Property(Float) def _get_W(self): return 1. * self.ls_table.D_elem**2 / 6. # ------------------------------------------------------------ # SLS: outputs # ------------------------------------------------------------ ls_columns = List([ 'sig_n', 'sig_m', 'eta_n', 'eta_m', 'eta_tot', ]) ls_values = Property(depends_on='+input') @cached_property def _get_ls_values(self): '''get the outputs for SLS ''' n = self.n m = self.m A = self.A W = self.W f_ctk = self.f_ctk f_m = self.f_m sig_n = n / A / 1000. sig_m = abs(m / W) / 1000. eta_n = sig_n / f_ctk eta_m = sig_m / f_m eta_tot = eta_n + eta_m return { 'sig_n': sig_n, 'sig_m': sig_m, 'eta_n': eta_n, 'eta_m': eta_m, 'eta_tot': eta_tot } sig_n = Property def _get_sig_n(self): return self.ls_values['sig_n'] sig_m = Property def _get_sig_m(self): return self.ls_values['sig_m'] eta_n = Property def _get_eta_n(self): return self.ls_values['eta_n'] eta_m = Property def _get_eta_m(self): return self.ls_values['eta_m'] eta_tot = Property def _get_eta_tot(self): return self.ls_values['eta_tot'] assess_name = 'max_eta_tot' # assess_name = 'max_sig1_up' # # max_sig1_up = Property( depends_on = '+input' ) # @cached_property # def _get_max_sig1_up( self ): # return ndmax( self.sig1_up ) # @todo: make it possible to select the assess value: # # assess_name = Enum( values = 'columns' ) # def _assess_name_default( self ): # return self.columns[-1] max_eta_tot = Property(depends_on='+input') @cached_property def _get_max_eta_tot(self): return ndmax(self.eta_tot) #------------------------------- # ls view #------------------------------- # @todo: the dynamic selection of the columns to be displayed # does not work in connection with the LSArrayAdapter traits_view = View( VGroup( HGroup( Item(name='f_ctk', label='Tensile strength concrete [MPa]: f_ctk '), Item(name='f_m', label='Flexural tensile trength concrete [MPa]: f_m ')), VGroup( Include('ls_group'), # @todo: currently LSArrayAdapter must be called both # in SLS and ULS separately to configure columns # arrangement individually # Item('ls_array', show_label=False, editor=TabularEditor(adapter=LSArrayAdapter()))), ), resizable=True, scrollable=True, height=1000, width=1100)
class YMBMicro(HasTraits): ''' Yarn-Matrix-Bond Microstructure analysis ''' data = Instance(IYMBData) view_3d = Property(Instance(YMBView3D)) @cached_property def _get_view_3d(self): return YMBView3D(data=self.data) cut_view = Property(Instance(YMBView2D)) @cached_property def _get_cut_view(self): return YMBView2D(data=self.data) slider = Property(Instance(YMBSlider), depends_on='data.input_change') @cached_property def _get_slider(self): return YMBSlider(data=self.data) histogram = Property(Instance(YMBHist), depends_on='data.input_change') @cached_property def _get_histogram(self): return YMBHist(slider=self.slider) auto_correl_data = Property(Instance(YMBAutoCorrel), depends_on='data.input_change') @cached_property def _get_auto_correl_data(self): return YMBAutoCorrel(data=self.data) auto_correl = Property(Instance(YMBAutoCorrelView), depends_on='data.input_change') @cached_property def _get_auto_correl(self): return YMBAutoCorrelView(correl_data=self.auto_correl_data) cross_correl = Property(Instance(YMBCrossCorrel), depends_on='data.input_change') @cached_property def _get_cross_correl(self): return YMBCrossCorrel(data=self.data) pullout = Instance(YMBPullOut) def _pullout_default(self): return YMBPullOut(data=self.data) ymb_tree = Property(Instance(YMBTree)) @cached_property def _get_ymb_tree(self): return YMBTree(ymb_micro=self) # The main view view = View( VGroup( Group(Item('data@', show_label=False), label='Data source'), Group( Item(name='ymb_tree', id='ymb_tree', editor=tree_editor, show_label=False, resizable=True), orientation='vertical', show_labels=True, show_left=True, ), dock='tab', id='qdc.ymb.split', ), id='qdc.ymb', dock='horizontal', drop_class=HasTraits, # handler = TreeHandler(), resizable=True, scrollable=True, title='Yarn-Matrix-Bond Microstructure Lab', handler=TitleHandler(), width=.8, height=.5)
class PDistrib(HasTraits): implements = IPDistrib def __init__(self, **kw): super(PDistrib, self).__init__(**kw) self.on_trait_change(self.refresh, 'distr_type.changed,quantile,n_segments') self.refresh() # puts all chosen continuous distributions distributions defined # in the scipy.stats.distributions module as a list of strings # into the Enum trait # distr_choice = Enum(distr_enum) distr_choice = Enum('sin2x', 'weibull_min', 'sin_distr', 'uniform', 'norm', 'piecewise_uniform', 'gamma') distr_dict = { 'sin2x': sin2x, 'uniform': uniform, 'norm': norm, 'weibull_min': weibull_min, 'sin_distr': sin_distr, 'piecewise_uniform': piecewise_uniform, 'gamma': gamma } # instantiating the continuous distributions distr_type = Property(Instance(Distribution), depends_on='distr_choice') @cached_property def _get_distr_type(self): return Distribution(self.distr_dict[self.distr_choice]) # change monitor - accumulate the changes in a single event trait changed = Event @on_trait_change('distr_choice, distr_type.changed, quantile, n_segments') def _set_changed(self): self.changed = True #------------------------------------------------------------------------ # Methods setting the statistical modments #------------------------------------------------------------------------ mean = Property def _get_mean(self): return self.distr_type.mean def _set_mean(self, value): self.distr_type.mean = value variance = Property def _get_variance(self): return self.distr_type.mean def _set_variance(self, value): self.distr_type.mean = value #------------------------------------------------------------------------ # Methods preparing visualization #------------------------------------------------------------------------ quantile = Float(1e-14, auto_set=False, enter_set=True) range = Property(Tuple(Float), depends_on=\ 'distr_type.changed, quantile') @cached_property def _get_range(self): return (self.distr_type.distr.ppf(self.quantile), self.distr_type.distr.ppf(1 - self.quantile)) n_segments = Int(500, auto_set=False, enter_set=True) dx = Property(Float, depends_on=\ 'distr_type.changed, quantile, n_segments') @cached_property def _get_dx(self): range_length = self.range[1] - self.range[0] return range_length / self.n_segments #------------------------------------------------------------------------- # Discretization of the distribution domain #------------------------------------------------------------------------- x_array = Property(Array('float_'), depends_on=\ 'distr_type.changed,'\ 'quantile, n_segments') @cached_property def _get_x_array(self): '''Get the intrinsic discretization of the distribution respecting its bounds. ''' return linspace(self.range[0], self.range[1], self.n_segments + 1) #=========================================================================== # Access function to the scipy distribution #=========================================================================== def pdf(self, x): return self.distr_type.distr.pdf(x) def cdf(self, x): return self.distr_type.distr.cdf(x) def rvs(self, n): return self.distr_type.distr.rvs(n) def ppf(self, e): return self.distr_type.distr.ppf(e) #=========================================================================== # PDF - permanent array #=========================================================================== pdf_array = Property(Array('float_'), depends_on=\ 'distr_type.changed,'\ 'quantile, n_segments') @cached_property def _get_pdf_array(self): '''Get pdf values in intrinsic positions''' return self.distr_type.distr.pdf(self.x_array) def get_pdf_array(self, x_array): '''Get pdf values in externally specified positions''' return self.distr_type.distr.pdf(x_array) #=========================================================================== # CDF permanent array #=========================================================================== cdf_array = Property(Array('float_'), depends_on=\ 'distr_type.changed,'\ 'quantile, n_segments') @cached_property def _get_cdf_array(self): '''Get cdf values in intrinsic positions''' return self.distr_type.distr.cdf(self.x_array) def get_cdf_array(self, x_array): '''Get cdf values in externally specified positions''' return self.distr_type.distr.cdf(x_array) #------------------------------------------------------------------------- # Randomization #------------------------------------------------------------------------- def get_rvs_array(self, n_samples): return self.distr_type.distr.rvs(n_samples) figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor='white') return figure data_changed = Event def plot(self, fig): figure = fig figure.clear() axes = figure.gca() # plot PDF axes.plot(self.x_array, self.pdf_array, lw=1.0, color='blue', \ label='PDF') axes2 = axes.twinx() # plot CDF on a separate axis (tick labels left) axes2.plot(self.x_array, self.cdf_array, lw=2, color='red', \ label='CDF') # fill the unity area given by integrating PDF along the X-axis axes.fill_between(self.x_array, 0, self.pdf_array, color='lightblue', alpha=0.8, linewidth=2) # plot mean mean = self.distr_type.distr.stats('m') axes.plot([mean, mean], [0.0, self.distr_type.distr.pdf(mean)], lw=1.5, color='black', linestyle='-') # plot stdev stdev = sqrt(self.distr_type.distr.stats('v')) axes.plot([mean - stdev, mean - stdev], [0.0, self.distr_type.distr.pdf(mean - stdev)], lw=1.5, color='black', linestyle='--') axes.plot([mean + stdev, mean + stdev], [0.0, self.distr_type.distr.pdf(mean + stdev)], lw=1.5, color='black', linestyle='--') axes.legend(loc='center left') axes2.legend(loc='center right') axes.ticklabel_format(scilimits=(-3., 4.)) axes2.ticklabel_format(scilimits=(-3., 4.)) # plot limits on X and Y axes axes.set_ylim(0.0, max(self.pdf_array) * 1.15) axes2.set_ylim(0.0, 1.15) range = self.range[1] - self.range[0] axes.set_xlim(self.x_array[0] - 0.05 * range, self.x_array[-1] + 0.05 * range) axes2.set_xlim(self.x_array[0] - 0.05 * range, self.x_array[-1] + 0.05 * range) def refresh(self): self.plot(self.figure) self.data_changed = True icon = Property(Instance(ImageResource), depends_on='distr_type.changed,quantile,n_segments') @cached_property def _get_icon(self): fig = plt.figure(figsize=(4, 4), facecolor='white') self.plot(fig) tf_handle, tf_name = tempfile.mkstemp('.png') fig.savefig(tf_name, dpi=35) return ImageResource(name=tf_name) traits_view = View(HSplit(VGroup( Group( Item('distr_choice', show_label=False), Item('@distr_type', show_label=False), ), id='pdistrib.distr_type.pltctrls', label='Distribution parameters', scrollable=True, ), Tabbed( Group( Item('figure', editor=MPLFigureEditor(), show_label=False, resizable=True), scrollable=True, label='Plot', ), Group(Item('quantile', label='quantile'), Item('n_segments', label='plot points'), label='Plot parameters'), label='Plot', id='pdistrib.figure.params', dock='tab', ), dock='tab', id='pdistrib.figure.view'), id='pdistrib.view', dock='tab', title='Statistical distribution', buttons=['Ok', 'Cancel'], scrollable=True, resizable=True, width=600, height=400)
class LCCTable(HasTraits): '''Loading Case Manager. Generates and sorts the loading case combinations of all specified loading cases. ''' # define ls # ls = Trait('ULS', {'ULS': ULS, 'SLS': SLS}) # lcc-instance for the view # lcc = Instance(LCC) #------------------------------- # Define loading cases: #------------------------------- # path to the directory containing the state data files # data_dir = Directory # list of load cases # lc_list_ = List(Instance(LC)) lc_list = Property(List, depends_on='+filter') def _set_lc_list(self, value): self.lc_list_ = value def _get_lc_list(self): # for lc in self.lc_list_: # if lc.data_filter != self.data_filter: # lc.data_filter = self.data_filter return self.lc_list_ lcc_table_columns = Property(depends_on='lc_list_, +filter') def _get_lcc_table_columns(self): return [ ObjectColumn(label='Id', name='lcc_id') ] + \ [ ObjectColumn(label=lc.name, name=lc.name) for idx, lc in enumerate(self.lc_list) ] + \ [ ObjectColumn(label='assess_value', name='assess_value') ] geo_columns = Property(List(Str), depends_on='lc_list_, +filter') def _get_geo_columns(self): '''derive the order of the geo columns from the first element in 'lc_list'. The internal consistency is checked separately in the 'check_consistency' method. ''' return self.lc_list[0].geo_columns sr_columns = Property(List(Str), depends_on='lc_list_, +filter') def _get_sr_columns(self): '''derive the order of the stress resultants from the first element in 'lc_list'. The internal consistency is checked separately in the 'check_consistency' method. ''' return self.lc_list[0].sr_columns #------------------------------- # check consistency #------------------------------- def _check_for_consistency(self): ''' check input files for consitency: ''' return True #------------------------------- # lc_arr #------------------------------- lc_arr = Property(Array) def _get_lc_arr(self): '''stack stress resultants arrays of all loading cases together. This yields an array of shape ( n_lc, n_elems, n_sr ) ''' sr_arr_list = [lc.sr_arr for lc in self.lc_list] # for x in sr_arr_list: # print x.shape return array(sr_arr_list) #------------------------------- # Array dimensions: #------------------------------- n_sr = Property(Int) def _get_n_sr(self): return len(self.sr_columns) n_lc = Property(Int) def _get_n_lc(self): return len(self.lc_list) n_lcc = Property(Int) def _get_n_lcc(self): return self.combi_arr.shape[0] n_elems = Property(Int) def _get_n_elems(self): return self.lc_list[0].sr_arr.shape[0] #------------------------------- # auxilary method for get_combi_arr #------------------------------- def _product(self, args): """ Get all possible permutations of the security factors without changing the order of the loading cases. The method corresponds to the build-in function 'itertools.product'. Instead of returning a generator object a list of all possible permutations is returned. As argument a list of list needs to be defined. In the original version of 'itertools.product' the function takes a tuple as argument ("*args"). """ pools = map(tuple, args) # within original version args defined as *args result = [[]] for pool in pools: result = [x + [y] for x in result for y in pool] return result # ------------------------------------------------------------ # 'combi_arr' - array containing indices of all loading case combinations: # ------------------------------------------------------------ # list of indices of the position of the imposed loads in 'lc_list' # # imposed_idx_list = Property( List, depends_on = 'lc_list_, lc_list_.+input' ) imposed_idx_list = Property(List, depends_on='lc_list_') @cached_property def _get_imposed_idx_list(self): '''list of indices for the imposed loads ''' imposed_idx_list = [] for i_lc, lc in enumerate(self.lc_list): cat = lc.category if cat == 'imposed-load': imposed_idx_list.append(i_lc) return imposed_idx_list # array containing the psi with name 'psi_key' for the specified # loading cases defined in 'lc_list'. For dead-loads no value for # psi exists. In this case a value of 1.0 is defined. # This yields an array of shape ( n_lc, ) # def _get_psi_arr(self, psi_key): '''psi_key must be defined as: 'psi_0', 'psi_1', or 'psi_2' Returns an 1d-array of shape ( n_lc, ) ''' # get list of ones (used for dead-loads): # psi_list = [1] * len(self.lc_list) # overwrite ones with psi-values in case of imposed-loads: # for imposed_idx in self.imposed_idx_list: psi_value = getattr(self.lc_list[imposed_idx], psi_key) psi_list[imposed_idx] = psi_value return array(psi_list, dtype='float_') # list containing names of the loading cases # lc_name_list = Property(List, depends_on='lc_list_') @cached_property def _get_lc_name_list(self): '''list of names of all loading cases ''' return [lc.name for lc in self.lc_list] show_lc_characteristic = Bool(True) # combination array: # combi_arr = Property(Array, depends_on='lc_list_, combination_SLS') @cached_property def _get_combi_arr(self): '''array containing the security and combination factors corresponding to the specified loading cases. This yields an array of shape ( n_lcc, n_lc ) Properties defined in the subclasses 'LCCTableULS', 'LCCTableSLS': - 'gamma_list' = list of security factors (gamma) - 'psi_lead' = combination factors (psi) of the leading imposed load - 'psi_non_lead' = combination factors (psi) of the non-leading imposed loads ''' # printouts: # if self.ls == 'ULS': print '*** load case combinations for limit state ULS ***' else: print '*** load case combinations for limit state SLS ***' print '*** SLS combination used: % s ***' % (self.combination_SLS) #--------------------------------------------------------------- # get permutations of safety factors ('gamma') #--------------------------------------------------------------- # permutation_list = self._product(self.gamma_list) combi_arr = array(permutation_list) # check if imposed loads are defined # if not no further processing of 'combi_arr' is necessary: # if self.imposed_idx_list == []: # if option is set to 'True' the loading case combination table # is enlarged with an identity matrix in order to see the # characteristic values of each loading case. # if self.show_lc_characteristic: combi_arr = vstack([identity(self.n_lc), combi_arr]) return combi_arr #--------------------------------------------------------------- # get leading and non leading combination factors ('psi') #--------------------------------------------------------------- # go through all possible cases of leading imposed loads # For the currently investigated imposed loading case the # psi value is taken from 'psi_leading_arr' for all other # imposed loads the psi value is taken from 'psi_non_lead_arr' # Properties are defined in the subclasses # psi_lead_arr = self.psi_lead_arr psi_non_lead_arr = self.psi_non_lead_arr # for SLS limit state case 'rare' all imposed loads are multiplied # with 'psi_2'. In this case no distinction between leading or # non-leading imposed loads needs to be performed. # if all(psi_lead_arr == psi_non_lead_arr): combi_arr_psi = combi_arr * psi_lead_arr # generate a list or arrays obtained by multiplication # with the psi-factors. # This yields a list of length = number of imposed-loads. # else: combi_arr_psi_list = [] for imposed_idx in self.imposed_idx_list: # copy in order to preserve initial state of the array # and avoid in place modification psi_arr = copy(psi_non_lead_arr) psi_arr[imposed_idx] = psi_lead_arr[imposed_idx] combi_arr_lead_i = combi_arr[where( combi_arr[:, imposed_idx] != 0)] * psi_arr combi_arr_psi_list.append(combi_arr_lead_i) combi_arr_psi_no_0 = vstack(combi_arr_psi_list) # missing cases without any dead load have to be added # get combinations with all!! imposed = 0 # lcc_all_imposed_zero = where( (combi_arr[:, self.imposed_idx_list] == 0).all(axis=1)) # add to combinations # combi_arr_psi = vstack( (combi_arr[lcc_all_imposed_zero], combi_arr_psi_no_0)) #--------------------------------------------------------------- # get exclusive loading cases ('exclusive_to') #--------------------------------------------------------------- # get a list of lists containing the indices of the loading cases # that are defined exclusive to each other. # The list still contains duplicates, e.g. [1,2] and [2,1] # exclusive_list = [] for i_lc, lc in enumerate(self.lc_list): # get related load case number # for exclusive_name in lc.exclusive_to: if exclusive_name in self.lc_name_list: exclusive_idx = self.lc_name_list.index(exclusive_name) exclusive_list.append([i_lc, exclusive_idx]) # eliminate the duplicates in 'exclusive_list' # exclusive_list_unique = [] for exclusive_list_entry in exclusive_list: if sorted(exclusive_list_entry) not in exclusive_list_unique: exclusive_list_unique.append(sorted(exclusive_list_entry)) # delete the rows in combination array that contain # loading case combinations with imposed-loads that have been defined # as exclusive to each other. # combi_arr_psi_exclusive = combi_arr_psi # print 'combi_arr_psi_exclusive', combi_arr_psi_exclusive for exclusive_list_entry in exclusive_list_unique: # check where maximum one value of the exclusive load cases is unequal to one # LC1 LC2 LC3 (all LCs are defined as exclusive to each other) # # e.g. 1.5 0.9 0.8 (example of 'combi_arr_psi') # 1.5 0.0 0.0 # 0.0 0.0 0.0 (combination with all imposed loads = 0 after multiplication wit psi and gamma) # ... ... ... # # this would yield the following mask_arr (containing ones or zeros): # e.g. 1.0 1.0 1.0 --> sum = 3 --> true combi --> accepted combination # 1.0 0.0 0.0 --> sum = 1 --> false combi --> no accepted combination # e.g. 0.0 0.0 0.0 --> sum = 0 --> true combi --> accepted combination (only body-loads) # ... ... ... # mask_arr = where( combi_arr_psi_exclusive[:, exclusive_list_entry] != 0, 1.0, 0.0) # print 'mask_arr', mask_arr true_combi = where(sum(mask_arr, axis=1) <= 1.0) # print 'true_combi', true_combi combi_arr_psi_exclusive = combi_arr_psi_exclusive[true_combi] #--------------------------------------------------------------- # create array with only unique load case combinations #--------------------------------------------------------------- # If the psi values of an imposed-load are defined as zero this # may led to zero entries in 'combi_arr'. This would yield rows # in 'combi_arr' which are duplicates. Those rows are removed. # Add first row in 'combi_arr_psi_exclusive' to '_unique' array # This array must have shape (1, n_lc) in order to use 'axis'-option # combi_arr_psi_exclusive_unique = combi_arr_psi_exclusive[0][None, :] for row in combi_arr_psi_exclusive: # Check if all factors in one row are equal to the rows in 'unique' array. # If this is not the case for any row the combination is added to 'unique'. # Broadcasting is used for the bool evaluation: # if (row == combi_arr_psi_exclusive_unique).all( axis=1.0).any() == False: combi_arr_psi_exclusive_unique = vstack( (combi_arr_psi_exclusive_unique, row)) # if option is set to 'True' the loading case combination table # is enlarged with an identity matrix in order to see the # characteristic values of each loading case. # # if self.show_lc_characteristic: # combi_arr_psi_exclusive_unique = vstack( [ identity( self.n_lc ), combi_arr_psi_exclusive_unique ] ) return combi_arr_psi_exclusive_unique #------------------------------- # lcc_arr #------------------------------- lcc_arr = Property(Array, depends_on='lc_list_') @cached_property def _get_lcc_arr(self): '''Array of all loading case combinations following the loading cases define in 'lc_list' and the combinations defined in 'combi_arr'. This yields an array of shape ( n_lcc, n_elems, n_sr ) ''' self._check_for_consistency() combi_arr = self.combi_arr # 'combi_arr' is of shape ( n_lcc, n_lc ) # 'lc_arr' is of shape ( n_lc, n_elems, n_sr ) # lc_arr = self.lc_arr # Broadcasting is used to generate array containing the multiplied lc's # yielding an array of shape ( n_lcc, n_lc, n_elems, n_sr ) # lc_combi_arr = lc_arr[None, :, :, :] * combi_arr[:, :, None, None] # Then the sum over index 'n_lc' is evaluated yielding # an array of all loading case combinations. # This yields an array of shape ( n_lcc, n_elem, n_sr ) # lcc_arr = sum(lc_combi_arr, axis=1) return lcc_arr #------------------------------- # lcc_lists #------------------------------- lcc_list = Property(List, depends_on='lc_list_') @cached_property def _get_lcc_list(self): '''list of loading case combinations (instances of LCC) ''' combi_arr = self.combi_arr lcc_arr = self.lcc_arr sr_columns = self.sr_columns geo_columns = self.geo_columns n_lcc = self.n_lcc # return a dictionary of the stress resultants # this is used by LSTable to determine the stress # resultants of the current limit state # lcc_list = [] for i_lcc in range(n_lcc): state_data_dict = {} for i_sr, name in enumerate(sr_columns): state_data_dict[name] = lcc_arr[i_lcc, :, i_sr][:, None] geo_data_dict = self.geo_data_dict lcc = LCC( # lcc_table = self, factors=combi_arr[i_lcc, :], lcc_id=i_lcc, ls_table=LSTable(geo_data=geo_data_dict, state_data=state_data_dict, ls=self.ls)) for idx, lc in enumerate(self.lc_list): lcc.add_trait(lc.name, Int(combi_arr[i_lcc, idx])) lcc_list.append(lcc) return lcc_list #------------------------------- # geo_arr #------------------------------- geo_data_dict = Property(Dict, depends_on='lc_list_') @cached_property def _get_geo_data_dict(self): '''Array of global coords derived from the first loading case defined in lc_list. Coords are identical for all LC's. ''' return self.lc_list[0].geo_data_dict #------------------------------- # min/max-values #------------------------------- def get_min_max_state_data(self): ''' get the surrounding curve of all 'lcc' values ''' lcc_arr = self.lcc_arr min_arr = ndmin(lcc_arr, axis=0) max_arr = ndmax(lcc_arr, axis=0) return min_arr, max_arr #-------------------------------------- # use for case 'max N*' nach ZiE # Fall 'maximale Normalkraft' nach ZiE #-------------------------------------- # max_sr_grouped_dict = Property( Dict ) # @cached_property # def _get_max_sr_grouped_dict( self ): # ''' get the surrounding curve for each stress resultant # shape lcc_array ( n_lcc, n_elems, n_sr ) # ''' # sr_columns = self.sr_columns # lcc_arr = self.lcc_arr # dict = {} # for i, sr in enumerate( self.sr_columns ): # idx_1 = argmax( abs( lcc_arr[:, :, i] ), axis = 0 ) # idx_2 = arange( 0, idx_1.shape[0], 1 ) # dict[sr] = lcc_arr[idx_1, idx_2, :] # return dict #-------------------------------------- # use for case 'max eta' nach ZiE # Fall max Ausnutzungsgrad nach ZiE #-------------------------------------- max_sr_grouped_dict = Property(Dict) @cached_property def _get_max_sr_grouped_dict(self): '''evaluate eta and prepare plot ''' sr_columns = self.sr_columns lcc_arr = self.lcc_arr # ## N_s6cm_d results from 'V_op_d'*1.5 # assume a distribution of stresses as for a simple # supported beam with cantilever corresponding # to the distance of the screws to each other and to the edge # of the TRC shell (33cm/17cm) # N_s6cm_d = lcc_arr[:, :, 2] * (17. + 33. + 1.) / 33. # ## V_s6cm_d results from 'N_ip_d'/2 # assume an equal distribution (50% each) of the # normal forces to each screw # V_s6cm_d = lcc_arr[:, :, 0] * 0.56 # V_s6cm_d = ( ( lcc_arr[:, :, 0] / 2 ) ** 2 + ( lcc_arr[:, :, 1] * 1.5 ) ** 2 ) ** 0.5 # resistance ac characteristic value obtained from the # experiment and EN DIN 1990 # N_ck = 28.3 V_ck = 63.8 gamma_s = 1.5 eta_N = N_s6cm_d / (N_ck / gamma_s) eta_V = abs(V_s6cm_d / (V_ck / gamma_s)) eta_inter = (eta_N) + (eta_V) idx_max_hinge = eta_inter.argmax(axis=0) dict = {} for i, sr in enumerate(self.sr_columns): idx_1 = idx_max_hinge idx_2 = arange(0, idx_1.shape[0], 1) dict[sr] = lcc_arr[idx_1, idx_2, :] return dict def export_hf_max_grouped(self, filename): """exports the hinge forces as consistent pairs for the two case 'max_eta' or 'max_N*' """ from matplotlib import pyplot sr_columns = self.sr_columns dict = self.max_sr_grouped_dict length_xy_quarter = self.length_xy_quarter def save_bar_plot(x, y, filename='bla', title='Title', xlabel='xlabel', ylabel='ylavel', width=0.1, xmin=0, xmax=1000, ymin=-1000, ymax=1000, figsize=[10, 5]): fig = pyplot.figure(facecolor="white", figsize=figsize) ax1 = fig.add_subplot(1, 1, 1) ax1.bar(x, y, width=width, align='center', color='green') ax1.set_xlim(xmin, xmax) ax1.set_ylim(ymin, ymax) ax1.set_xlabel(xlabel, fontsize=22) ax1.set_ylabel(ylabel, fontsize=22) if title == 'N_ip max': title = 'Fall max $\eta$' # title = 'Fall max $N^{*}$' if title == 'V_ip max': title = 'max $V_{ip}$' if title == 'V_op max': title = 'Fall max $V^{*}$' ax1.set_title(title) fig.savefig(filename, orientation='portrait', bbox_inches='tight') pyplot.clf() X = array(self.geo_data_dict['X_hf']) Y = array(self.geo_data_dict['Y_hf']) # symmetric axes # idx_sym = where(abs(Y[:, 0] - 2.0 * length_xy_quarter) <= 0.0001) X_sym = X[idx_sym].reshape(-1) idx_r0_r1 = where(abs(X[:, 0] - 2.0 * length_xy_quarter) <= 0.0001) X_r0_r1 = Y[idx_r0_r1].reshape(-1) for sr in sr_columns: F_int = dict[sr] # first row N_ip, second V_ip third V_op F_sym = F_int[idx_sym, :].reshape(-1, len(sr_columns)) F_r0_r1 = F_int[idx_r0_r1, :].reshape(-1, len(sr_columns)) save_bar_plot(X_sym, F_sym[:, 0].reshape(-1), xlabel='$X$ [m]', ylabel='$N^{*}_{Ed}$ [kN]', filename=filename + 'N_ip' + '_sym_' + sr + '_max', title=sr + ' max', xmin=0.0, xmax=3.5 * length_xy_quarter, figsize=[10, 5], ymin=-30, ymax=+30) if self.link_type == 'inc_V_ip': save_bar_plot(X_sym, F_sym[:, 1].reshape(-1), xlabel='$X$ [m]', ylabel='$V_{ip}$ [kN]', filename=filename + 'V_ip' + '_sym_' + sr + '_max', title=sr + ' max', xmin=0.0, xmax=3.5 * length_xy_quarter, figsize=[10, 5], ymin=-30, ymax=+30) save_bar_plot(X_sym, F_sym[:, 2].reshape(-1), xlabel='$X$ [m]', ylabel='$V^{*}_{Ed}$ [kN]', filename=filename + 'V_op' + '_sym_' + sr + '_max', title=sr + ' max', xmin=0.0, xmax=3.5 * length_xy_quarter, figsize=[10, 5], ymin=-10, ymax=+10) # r0_r1 # save_bar_plot(X_r0_r1, F_r0_r1[:, 0].reshape(-1), xlabel='$Y$ [m]', ylabel='$N^{*}_{Ed}$ [kN]', filename=filename + 'N_ip' + '_r0_r1_' + sr + '_max', title=sr + ' max', xmin=0.0, xmax=2.0 * length_xy_quarter, figsize=[5, 5], ymin=-30, ymax=+30) if self.link_type == 'inc_V_ip': save_bar_plot(X_r0_r1, F_r0_r1[:, 1].reshape(-1), xlabel='$Y$ [m]', ylabel='$V_{ip}$ [kN]', filename=filename + 'V_ip' + '_r0_r1_' + sr + '_max', title=sr + ' max', xmin=0.0, xmax=2.0 * length_xy_quarter, figsize=[5, 5], ymin=-30, ymax=+30) save_bar_plot(X_r0_r1, F_r0_r1[:, 2].reshape(-1), xlabel='$Y$ [m]', ylabel='$V^{*}_{Ed}$ [kN]', filename=filename + 'V_op' + '_r0_r1_' + sr + '_max', title=sr + ' max', xmin=0.0, xmax=2.0 * length_xy_quarter, figsize=[5, 5], ymin=-10, ymax=+10) def plot_interaction_s6cm(self): """get the maximum values (consistent pairs of N and V) and plot them in an interaction plot """ lcc_arr = self.lcc_arr # ## F_Edt results from 'V_op_d'*1.5 # assume a distribution of stresses as for a simple # supported beam with cantilever corresponding # to the distance of the screws to each other and to the edge # of the TRC shell (33cm/17cm) # F_Edt = lcc_arr[:, :, 2] * (17. + 33. + 1.) / 33. # ## F_EdV1 results from 'N_ip_d'/2 # assume an equal distribution (50% each) of the # normal forces to each screw # F_EdV1 = lcc_arr[:, :, 0] * 0.56 # V_s6cm_d = ( ( lcc_arr[:, :, 0] / 2 ) ** 2 + ( lcc_arr[:, :, 1] * 1.5 ) ** 2 ) ** 0.5 # resistance ac characteristic value obtained from the # experiment and EN DIN 1990 # F_Rkt = 28.3 F_RkV1 = 63.8 gamma_M = 1.5 eta_t = abs(F_Edt / (F_Rkt / gamma_M)) eta_V1 = abs(F_EdV1 / (F_RkV1 / gamma_M)) print 'eta_t.shape', eta_t.shape print 'eta_V1.shape', eta_V1.shape # self.interaction_plot(abs(F_Edt), abs(F_EdV1)) self.interaction_plot(eta_t, eta_V1) # eta_inter = ( eta_N ) + ( eta_V ) # # idx_max_hinge = eta_inter.argmax( axis = 0 ) # idx_hinge = arange( 0, len( idx_max_hinge ), 1 ) # plot_eta_N = eta_N[idx_max_hinge, idx_hinge] # plot_eta_V = eta_V[idx_max_hinge, idx_hinge] # self.interaction_plot( plot_eta_N, plot_eta_V ) def interaction_plot(self, eta_N, eta_V): from matplotlib import font_manager ticks_font = font_manager.FontProperties(family='Times', style='normal', size=18, weight='normal', stretch='normal') from matplotlib import pyplot fig = pyplot.figure(facecolor="white", figsize=[10, 10]) ax1 = fig.add_subplot(1, 1, 1) # x = arange(0, 1.01, 0.01) # y15 = (1 - x ** 1.5) ** (1 / 1.5) # y = (1 - x) ax1.set_xlabel('$F_\mathrm{Ed,V1}/F_\mathrm{Rd,V1}$', fontsize=24) ax1.set_ylabel('$F_\mathrm{Ed,t}/F_\mathrm{Rd,t}$', fontsize=24) # ax1.set_xlabel('$|N_\mathrm{Ed}|$' , fontsize=32) # ax1.set_ylabel('$|V_\mathrm{Ed}|$', fontsize=32) # ax1.plot(x , y, '--', color='black' # , linewidth=2.0) # ax1.plot(x , y15, '--', color='black' # , linewidth=2.0) ax1.plot(eta_V, eta_N, 'wo', markersize=3) # ax1.plot(eta_V, eta_N, 'o', color='green', markersize=8) # ax1.plot( eta_V[where( limit < 1 )] , eta_N[where( limit < 1 )], 'o', markersize = 8 ) # ax1.plot( eta_V[where( limit > 1 )] , eta_N[where( limit > 1 )], 'o', color = 'red', markersize = 8 ) for xlabel_i in ax1.get_xticklabels(): xlabel_i.set_fontsize(24) xlabel_i.set_family('serif') for ylabel_i in ax1.get_yticklabels(): ylabel_i.set_fontsize(24) ylabel_i.set_family('serif') # ax1.plot( x , 1 - x, '--', color = 'black', label = 'lineare Interaktion' ) ax1.set_xlim(0, 1.0) ax1.set_ylim(0, 1.0) ax1.legend() pyplot.show() pyplot.clf() # choose linking type (in-plane shear dof blocked or not) # link_type = Enum('exc_V_ip', 'inc_V_ip') # length of the shell (needed to plot the hinge forces plots correctly) # length_xy_quarter = 3.5 # m def export_hf_lc(self): """exports the hinge forces for each loading case separately """ from matplotlib import pyplot sr_columns = self.sr_columns dict = self.max_sr_grouped_dict length_xy_quarter = self.length_xy_quarter def save_bar_plot(x, y, filename='bla', xlabel='xlabel', ylabel='ylavel', ymin=-10, ymax=10, width=0.1, xmin=0, xmax=1000, figsize=[10, 5]): fig = pyplot.figure(facecolor="white", figsize=figsize) ax1 = fig.add_subplot(1, 1, 1) ax1.bar(x, y, width=width, align='center', color='blue') ax1.set_xlim(xmin, xmax) ax1.set_ylim(ymin, ymax) ax1.set_xlabel(xlabel, fontsize=22) ax1.set_ylabel(ylabel, fontsize=22) fig.savefig(filename, orientation='portrait', bbox_inches='tight') pyplot.clf() X = array(self.geo_data_dict['X_hf']) Y = array(self.geo_data_dict['Y_hf']) # symmetric axes # idx_sym = where(abs(Y[:, 0] - 2.0 * length_xy_quarter) <= 0.0001) X_sym = X[idx_sym].reshape(-1) idx_r0_r1 = where(abs(X[:, 0] - 2.0 * length_xy_quarter) <= 0.0001) X_r0_r1 = Y[idx_r0_r1].reshape(-1) F_int = self.lc_arr for i, lc_name in enumerate(self.lc_name_list): filename = self.lc_list[i].plt_export max_N_ip = max(int(ndmax(F_int[i, :, 0], axis=0)) + 1, 1) max_V_ip = max(int(ndmax(F_int[i, :, 1], axis=0)) + 1, 1) max_V_op = max(int(ndmax(F_int[i, :, 2], axis=0)) + 1, 1) F_int_lc = F_int[i, :, :] # first row N_ip, second V_ip third V_op F_sym = F_int_lc[idx_sym, :].reshape(-1, len(sr_columns)) F_r0_r1 = F_int_lc[idx_r0_r1, :].reshape(-1, len(sr_columns)) save_bar_plot( X_sym, F_sym[:, 0].reshape(-1), # xlabel = '$X$ [m]', ylabel = '$N^{ip}$ [kN]', xlabel='$X$ [m]', ylabel='$N^{*}$ [kN]', filename=filename + 'N_ip' + '_sym', xmin=0.0, xmax=3.5 * length_xy_quarter, ymin=-max_N_ip, ymax=max_N_ip, figsize=[10, 5]) save_bar_plot(X_sym, F_sym[:, 1].reshape(-1), xlabel='$X$ [m]', ylabel='$V_{ip}$ [kN]', filename=filename + 'V_ip' + '_sym', xmin=0.0, xmax=3.5 * length_xy_quarter, ymin=-max_V_ip, ymax=max_V_ip, figsize=[10, 5]) save_bar_plot( X_sym, F_sym[:, 2].reshape(-1), # xlabel = '$X$ [m]', ylabel = '$V_{op}$ [kN]', xlabel='$X$ [m]', ylabel='$V^{*}$ [kN]', filename=filename + 'V_op' + '_sym', xmin=0.0, xmax=3.5 * length_xy_quarter, ymin=-max_V_op, ymax=max_V_op, figsize=[10, 5]) # r0_r1 # save_bar_plot( X_r0_r1, F_r0_r1[:, 0].reshape(-1), # xlabel = '$Y$ [m]', ylabel = '$N_{ip}$ [kN]', xlabel='$Y$ [m]', ylabel='$N^{*}$ [kN]', filename=filename + 'N_ip' + '_r0_r1', xmin=0.0, xmax=2.0 * length_xy_quarter, ymin=-max_N_ip, ymax=max_N_ip, figsize=[5, 5]) save_bar_plot(X_r0_r1, F_r0_r1[:, 1].reshape(-1), xlabel='$Y$ [m]', ylabel='$V_{ip}$ [kN]', filename=filename + 'V_ip' + '_r0_r1', xmin=0.0, xmax=2.0 * length_xy_quarter, ymin=-max_V_ip, ymax=max_V_ip, figsize=[5, 5]) save_bar_plot( X_r0_r1, F_r0_r1[:, 2].reshape(-1), # xlabel = '$Y$ [m]', ylabel = '$V_{op}$ [kN]', xlabel='$Y$ [m]', ylabel='$V^{*}$ [kN]', filename=filename + 'V_op' + '_r0_r1', xmin=0.0, xmax=2.0 * length_xy_quarter, ymin=-max_V_op, ymax=max_V_op, figsize=[5, 5]) # ------------------------------------------------------------ # View # ------------------------------------------------------------ traits_view = View(VGroup( VSplit( Item('lcc_list', editor=lcc_list_editor, show_label=False), Item('lcc@', show_label=False), ), ), resizable=True, scrollable=True, height=1.0, width=1.0)
class DoublePulloutSym(RF): implements(IRF) title = Str('symetrical yarn pullout') xi = Float(0.0179, auto_set=False, enter_set=True, input=True, distr=['weibull_min', 'uniform']) tau_fr = Float(2.5, auto_set=False, enter_set=True, input=True, distr=['uniform', 'norm']) # free length l = Float(0.0, auto_set=False, enter_set=True, input=True, distr=['uniform']) d = Float(26e-3, auto_set=False, input=True, enter_set=True, distr=['uniform', 'weibull_min']) E_mod = Float(72.0e3, auto_set=False, enter_set=True, input=True, distr=['uniform']) # slack theta = Float(0.01, auto_set=False, enter_set=True, input=True, distr=['uniform', 'norm']) phi = Float(1., auto_set=False, enter_set=True, input=True, distr=['uniform', 'norm']) # embedded length L = Float(1., auto_set=False, enter_set=True, input=True, distr=['uniform']) free_fiber_end = Bool(True, input=True) w = Float(enter_set=True, input=True, ctrl_range=(0, 1, 10)) weave_code = ''' ''' def __call__(self, w, tau_fr, l, d, E_mod, theta, xi, phi, L): '''Return the force for a prescribed crack opening displacement w. ''' A = pi * d**2 / 4. l = l * (1 + theta) w = w - theta * l Tau = tau_fr * phi * d * pi P_ = 0.5 * (-l * Tau + sqrt(l**2 * Tau**2 + 4 * w * H(w) * E_mod * A * Tau)) # one sided pullout P_ = ( -l * Tau + sqrt( l ** 2 * Tau ** 2 + 2 * w * H( w ) * E_mod * A * Tau ) ) if self.free_fiber_end: # ------ FREE LENGTH ------- # frictional force along the bond length P_fr = Tau * (L - l) # if pullout_criterion positive - embedded # otherwise pulled out # pull_out_criterion = P_fr - P_ P_ = P_ * H(pull_out_criterion) + P_fr * H(-pull_out_criterion) else: # -------------------------- # ------ clamped fiber end --------- v = L * (l * Tau + Tau * L) / E_mod / A P_ = P_ * H(Tau * L - P_) + (Tau * L + (w - v) / (l + 2 * L) * A * E_mod) * H(P_ - Tau * L) # ---------------------------------- P = P_ * H(A * E_mod * xi - P_) return P figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor='white') return figure changed = Event @on_trait_change('+input') def _set_changed(self): self.changed = True data_changed = Event @on_trait_change('+input') def refresh(self): figure = self.figure figure.clear() axes = figure.gca() P_fn = lambda w: self.__call__(w, self.tau_fr, self.l, self.d, self. E_mod, self.theta, self.xi, self.phi, self.L) pyF = frompyfunc(P_fn, 1, 1) w_arr = linspace(0.0, 1.0, 100) P_arr = array(pyF(w_arr), dtype='float_') axes.plot(w_arr, P_arr, lw=1.0, color='blue') self.data_changed = True group_attribs = VGroup( Item('tau_fr'), Item('l'), Item('d'), Item('E_mod'), Item('theta'), Item('xi'), Item('phi'), Item('L'), Item('free_fiber_end'), ), traits_view = View( group_attribs, scrollable=True, resizable=True, id='mk.figure.attribs', dock='tab', ) traits_view_diag = View(HSplit( group_attribs, VGroup(Item('figure', editor=MPLFigureEditor(), show_label=False, resizable=True), id='mk.figure.view'), ), id='mk.view', buttons=['OK', 'Cancel'], resizable=True, width=600, height=400)
class ImageProcessing(HasTraits): def __init__(self, **kw): super(ImageProcessing, self).__init__(**kw) self.on_trait_change(self.refresh, '+params') self.refresh() image_path = Str def rgb2gray(self, rgb): return np.dot(rgb[..., :3], [0.299, 0.587, 0.144]) filter = Bool(False, params=True) block_size = Range(1, 100, params=True) offset = Range(1, 20, params=True) denoise = Bool(False, params=True) denoise_spatial = Range(1, 100, params=True) processed_image = Property def _get_processed_image(self): # read image image = mpimg.imread(self.image_path) mask = image[:, :, 1] > 150. image[mask] = 255. #plt.imshow(image) #plt.show() # convert to grayscale image = self.rgb2gray(image) # crop image image = image[100:1000, 200:1100] mask = mask[100:1000, 200:1100] image = image - np.min(image) image[mask] *= 255. / np.max(image[mask]) if self.filter == True: image = denoise_bilateral(image, sigma_spatial=self.denoise_spatial) if self.denoise == True: image = threshold_adaptive(image, self.block_size, offset=self.offset) return image, mask edge_detection_method = Enum('canny', 'sobel', 'roberts', params=True) canny_sigma = Range(2.832, 5, params=True) canny_low = Range(5.92, 100, params=True) canny_high = Range(0.1, 100, params=True) edges = Property def _get_edges(self): img_edg, mask = self.processed_image if self.edge_detection_method == 'canny': img_edg = canny(img_edg, sigma=self.canny_sigma, low_threshold=self.canny_low, high_threshold=self.canny_high) elif self.edge_detection_method == 'roberts': img_edg = roberts(img_edg) elif self.edge_detection_method == 'sobel': img_edg = sobel(img_edg) img_edg = img_edg > 0.0 return img_edg radii = Int(80, params=True) radius_low = Int(40, params=True) radius_high = Int(120, params=True) step = Int(2, params=True) hough_circles = Property def _get_hough_circles(self): hough_radii = np.arange(self.radius_low, self.radius_high, self.step)[::-1] hough_res = hough_circle(self.edges, hough_radii) centers = [] accums = [] radii = [] # For each radius, extract num_peaks circles num_peaks = 3 for radius, h in zip(hough_radii, hough_res): peaks = peak_local_max(h, num_peaks=num_peaks) centers.extend(peaks) print 'circle centers = ', peaks accums.extend(h[peaks[:, 0], peaks[:, 1]]) radii.extend([radius] * num_peaks) im = mpimg.imread(self.image_path) # crop image im = im[100:1000, 200:1100] for idx in np.arange(len(centers)): center_x, center_y = centers[idx] radius = radii[idx] cx, cy = circle_perimeter(center_y, center_x, radius) mask = (cx < im.shape[0]) * (cy < im.shape[1]) im[cy[mask], cx[mask]] = (220., 20., 20.) return im eval_edges = Button def _eval_edges_fired(self): edges = self.figure_edges edges.clear() axes_edges = edges.gca() axes_edges.imshow(self.edges, plt.gray()) self.data_changed = True eval_circles = Button def _eval_circles_fired(self): circles = self.figure_circles circles.clear() axes_circles = circles.gca() axes_circles.imshow(self.hough_circles, plt.gray()) self.data_changed = True figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor='white') return figure figure_edges = Instance(Figure) def _figure_edges_default(self): figure = Figure(facecolor='white') return figure figure_circles = Instance(Figure) def _figure_circles_default(self): figure = Figure(facecolor='white') return figure data_changed = Event def plot(self, fig, fig2): figure = fig figure.clear() axes = figure.gca() img, mask = self.processed_image axes.imshow(img, plt.gray()) def refresh(self): self.plot(self.figure, self.figure_edges) self.data_changed = True traits_view = View(HGroup( Group(Item('filter', label='filter'), Item('block_size'), Item('offset'), Item('denoise', label='denoise'), Item('denoise_spatial'), label='Filters'), Group( Item('figure', editor=MPLFigureEditor(), show_label=False, resizable=True), scrollable=True, label='Plot', ), ), Tabbed( VGroup(Item('edge_detection_method'), Item('canny_sigma'), Item('canny_low'), Item('canny_high'), Item('eval_edges', label='Evaluate'), Item('figure_edges', editor=MPLFigureEditor(), show_label=False, resizable=True), scrollable=True, label='Plot_edges'), ), Tabbed( VGroup(Item('radii'), Item('radius_low'), Item('radius_high'), Item('step'), Item('eval_circles'), Item('figure_circles', editor=MPLFigureEditor(), show_label=False, resizable=True), scrollable=True, label='Plot_circles'), ), id='imview', dock='tab', title='Image processing', scrollable=True, resizable=True, width=600, height=400)
class LS(HasTraits): '''Limit state class ''' # backward link to the info shell to access the # input data when calculating # the limit-state-specific values # ls_table = WeakRef # parameters of the limit state # dir = Enum(DIRLIST) stress_res = Enum(SRLIST) #------------------------------- # ls columns #------------------------------- # defined in the subclasses # ls_columns = List show_ls_columns = Bool(True) #------------------------------- # sr columns #------------------------------- # stress resultant columns - for ULS this is defined in the subclasses # sr_columns = List(['m', 'n']) show_sr_columns = Bool(True) # stress resultant columns - generated from the parameter combination # dir and stress_res - one of MX, NX, MY, NY # m_varname = Property(Str) def _get_m_varname(self): # e.g. mx_N appendix = self.dir + '_' + self.stress_res return 'm' + appendix n_varname = Property(Str) def _get_n_varname(self): # e.g. nx_N appendix = self.dir + '_' + self.stress_res return 'n' + appendix n = Property(Float) def _get_n(self): return getattr(self.ls_table, self.n_varname) m = Property(Float) def _get_m(self): return getattr(self.ls_table, self.m_varname) #------------------------------- # geo columns form info shell #------------------------------- geo_columns = List(['elem_no', 'X', 'Y', 'Z', 'D_elem']) show_geo_columns = Bool(True) elem_no = Property(Float) def _get_elem_no(self): return self.ls_table.elem_no X = Property(Float) def _get_X(self): return self.ls_table.X Y = Property(Float) def _get_Y(self): return self.ls_table.Y Z = Property(Float) def _get_Z(self): return self.ls_table.Z D_elem = Property(Float) def _get_D_elem(self): return self.ls_table.D_elem #------------------------------- # state columns form info shell #------------------------------- # state_columns = List( ['mx', 'my', 'mxy', 'nx', 'ny', 'nxy' ] ) state_columns = List([ 'mx', 'my', 'mxy', 'nx', 'ny', 'nxy', 'sigx_lo', 'sigy_lo', 'sigxy_lo', 'sig1_lo', 'sig2_lo', 'alpha_sig_lo', 'sigx_up', 'sigy_up', 'sigxy_up', 'sig1_up', 'sig2_up', 'alpha_sig_up', ]) show_state_columns = Bool(True) mx = Property(Float) def _get_mx(self): return self.ls_table.mx my = Property(Float) def _get_my(self): return self.ls_table.my mxy = Property(Float) def _get_mxy(self): return self.ls_table.mxy nx = Property(Float) def _get_nx(self): return self.ls_table.nx ny = Property(Float) def _get_ny(self): return self.ls_table.ny nxy = Property(Float) def _get_nxy(self): return self.ls_table.nxy # evaluate principal stresses # upper face: # sigx_up = Property(Float) def _get_sigx_up(self): return self.ls_table.sigx_up sigy_up = Property(Float) def _get_sigy_up(self): return self.ls_table.sigy_up sigxy_up = Property(Float) def _get_sigxy_up(self): return self.ls_table.sigxy_up sig1_up = Property(Float) def _get_sig1_up(self): return self.ls_table.sig1_up sig2_up = Property(Float) def _get_sig2_up(self): return self.ls_table.sig2_up alpha_sig_up = Property(Float) def _get_alpha_sig_up(self): return self.ls_table.alpha_sig_up # lower face: # sigx_lo = Property(Float) def _get_sigx_lo(self): return self.ls_table.sigx_lo sigy_lo = Property(Float) def _get_sigy_lo(self): return self.ls_table.sigy_lo sigxy_lo = Property(Float) def _get_sigxy_lo(self): return self.ls_table.sigxy_lo sig1_lo = Property(Float) def _get_sig1_lo(self): return self.ls_table.sig1_lo sig2_lo = Property(Float) def _get_sig2_lo(self): return self.ls_table.sig2_lo alpha_sig_lo = Property(Float) def _get_alpha_sig_lo(self): return self.ls_table.alpha_sig_lo #------------------------------- # ls table #------------------------------- # all columns associated with the limit state including the corresponding # stress resultants # columns = Property(List, depends_on='show_geo_columns, show_state_columns,\ show_sr_columns, show_ls_columns') @cached_property def _get_columns(self): columns = [] if self.show_geo_columns: columns += self.geo_columns if self.show_state_columns: columns += self.state_columns if self.show_sr_columns: columns += self.sr_columns if self.show_ls_columns: columns += self.ls_columns return columns # select column used for sorting the data in selected sorting order # sort_column = Enum(values='columns') def _sort_column_default(self): return self.columns[-1] sort_order = Enum('descending', 'ascending', 'unsorted') #------------------------------------------------------- # get the maximum value of the selected variable # 'max_in_column' of the current sheet (only one sheet) #------------------------------------------------------- # get the maximum value of the chosen column # max_in_column = Enum(values='columns') def _max_in_column_default(self): return self.columns[-1] max_value = Property(depends_on='max_in_column') def _get_max_value(self): col = getattr(self, self.max_in_column)[:, 0] return max(col) #------------------------------------------------------- # get the maximum value and the corresponding case of # the selected variable 'max_in_column' in all (!) sheets #------------------------------------------------------- max_value_all = Property(depends_on='max_in_column') def _get_max_value_all(self): return self.ls_table.max_value_and_case[ self.max_in_column]['max_value'] max_case = Property(depends_on='max_in_column') def _get_max_case(self): return self.ls_table.max_value_and_case[self.max_in_column]['max_case'] #------------------------------------------------------- # get ls_table for View #------------------------------------------------------- # stack columns together for table used by TabularEditor # ls_array = Property( Array, depends_on='sort_column, sort_order, show_geo_columns, \ show_state_columns, show_sr_columns, show_ls_columns' ) @cached_property def _get_ls_array(self): arr_list = [getattr(self, col) for col in self.columns] # get the array currently selected by the sort_column enumeration # sort_arr = getattr(self, self.sort_column)[:, 0] sort_idx = argsort(sort_arr) ls_array = hstack(arr_list) if self.sort_order == 'descending': return ls_array[sort_idx[::-1]] if self.sort_order == 'ascending': return ls_array[sort_idx] if self.sort_order == 'unsorted': return ls_array #--------------------------------- # plot outputs in mlab-window #--------------------------------- plot_column = Enum(values='columns') plot = Button def _plot_fired(self): X = self.ls_table.X[:, 0] Y = self.ls_table.Y[:, 0] Z = self.ls_table.Z[:, 0] plot_col = getattr(self, self.plot_column)[:, 0] if self.plot_column == 'n_tex': plot_col = where(plot_col < 0, 0, plot_col) mlab.figure(figure="SFB532Demo", bgcolor=(1.0, 1.0, 1.0), fgcolor=(0.0, 0.0, 0.0)) mlab.points3d( X, Y, (-1.0) * Z, plot_col, # colormap = "gist_rainbow", # colormap = "Reds", colormap="YlOrBr", mode="cube", scale_factor=0.15) mlab.scalarbar(title=self.plot_column, orientation='vertical') mlab.show # name of the trait that is used to assess the evaluated design # assess_name = Str('') #------------------------------- # ls group #------------------------------- # @todo: the dynamic selection of the columns to be displayed # does not work in connection with the LSArrayAdapter ls_group = VGroup( HGroup( #Item( 'assess_name' ), Item('max_in_column'), Item('max_value', style='readonly', format_str='%6.2f'), Item('max_value_all', style='readonly', format_str='%6.2f'), Item('max_case', style='readonly', label='found in case: '), ), HGroup( Item('sort_column'), Item('sort_order'), Item('show_geo_columns', label='show geo'), Item('show_state_columns', label='show state'), Item('show_sr_columns', label='show sr'), Item('plot_column'), Item('plot'), ), )
class ULS(LS): '''Ultimate limit state ''' #-------------------------------------------------------- # ULS: material parameters (Inputs) #-------------------------------------------------------- # gamma-factor gamma = Float(1.5, input=True) # long term reduction factor beta = Float(1.0, input=True) # INDEX l: longitudinal direction of the textile (MAG-02-02-06a) # characteristic tensile strength of the tensile specimen [N/mm2] f_tk_l = Float(537, input=True) # design value of the tensile strength of the tensile specimen [N/mm2] # containing a gamma-factor of 1.5 and d long term reduction factor of 0.7 # f_td_l = 251 f_td_l = Property(Float, depends_on='+input') def _get_f_td_l(self): return self.beta * self.f_tk_l / self.gamma # cross sectional area of the reinforcement [mm2/m] a_t_l = Float(71.65, input=True) # INDEX q: orthogonal direction of the textile (MAG-02-02-06a) # characteristic tensile strength of the tensile specimen [N/mm2] f_tk_q = Float(511, input=True) # design value of the tensile strength of the tensile specimen [kN/m] # f_td_q = 238 f_td_q = Property(Float, depends_on='+input') def _get_f_td_q(self): return self.beta * self.f_tk_q / self.gamma # cross sectional area of the reinforcement [mm2/m] a_t_q = Float(53.31, input=True) # tensile strength of the textile reinforcement [kN/m] f_Rtex_l = Property(Float, depends_on='+input') def _get_f_Rtex_l(self): return self.a_t_l * self.f_td_l / 1000. # tensile strength of the textile reinforcement [kN/m] f_Rtex_q = Property(Float) def _get_f_Rtex_q(self, depends_on='+input'): return self.a_t_q * self.f_td_q / 1000. # tensile strength of the textile reinforcement [kN/m] # as simplification the lower value of 0- and 90-direction is taken # # sig_composite,exp = 103.4 kN/14cm/6cm = 12.3 MPa # f_tex,exp = 103.4 kN/14cm/12layers = 61.5 kN/m # f_tex,k = f_tex,exp * 0,81 (EN-DIN 1990) = 0.82*61.5 kN/m = 50.4 kN/m # f_tex,d = f_tex,k / 1,5 = 33.6 kN/m # f_Rtex_l = f_Rtex_q = 34.3 print 'NOTE: f_Rtex_l = f_Rtex_q = set to %g kN/m !' % (f_Rtex_l) k_fl = 7.95 / 6.87 print 'NOTE: k_fl = set to %g [-] !' % (k_fl) # ------------------------------------------------------------ # ULS - derived params: # ------------------------------------------------------------ # Parameters for the cracked state (GdT): # assumptions! # (resultierende statische Nutzhoehe) # d = Property(Float) def _get_d(self): return 0.75 * self.ls_table.D_elem # (Abstand Schwereachse zur resultierende Bewehrungslage) # chose the same amount of reinforcement at the top as at the bottom # i.e. zs = zs1 = zs2 # zs = Property(Float) def _get_zs(self): return self.d - self.ls_table.D_elem / 2. # (Innerer Hebelarm) # z = Property(Float) def _get_z(self): return 0.9 * self.d # ------------------------------------------------------------ # ULS: outputs # ------------------------------------------------------------ ls_columns = List([ 'e', 'm_Eds', 'f_t', 'f_t_sig', 'beta_l', 'beta_q', 'f_Rtex', 'k_fl_NM', 'n_tex' ]) sr_columns = ['m', 'n', 'alpha', 'd', 'zs', 'z'] alpha_varname = Property() def _get_alpha_varname(self): return 'alpha_' + self.stress_res alpha = Property def _get_alpha(self): return getattr(self.ls_table, self.alpha_varname) ls_values = Property(depends_on='+input') @cached_property def _get_ls_values(self): '''get the outputs for ULS ''' #------------------------------------------------- # VAR 1:use simplified reinforced concrete approach #------------------------------------------------- n = self.n m = self.m alpha = self.alpha zs = self.zs z = self.z f_Rtex_l = self.f_Rtex_l f_Rtex_q = self.f_Rtex_q # (Exzentrizitaet) e = abs(m / n) e[n == 0] = 1E9 # if normal force is zero set e to very large value # moment at the height of the resulting reinforcement layer: m_Eds = abs(m) - zs * n # tensile force in the reinforcement for bending and compression f_t = m_Eds / z + n # check if the two conditions are true: cond1 = n > 0 cond2 = e < zs bool_arr = cond1 * cond2 # in case of pure tension in the cross section: f_t[bool_arr] = n[bool_arr] * (zs[bool_arr] + e[bool_arr]) / ( zs[bool_arr] + zs[bool_arr]) #------------------------------------------------- # VAR 2:use principal stresses to calculate the resulting tensile force #------------------------------------------------- # princ_stress_eval = True # princ_stress_eval = False f_t_sig = self.sig1_lo * self.D_elem * 1000. if princ_stress_eval == True: print "NOTE: the principle tensile stresses are used to evaluate 'n_tex'" # resulting tensile force of the composite cross section[kN] # the entire (!) cross section is used! # as the maximum value of the tensile stresses at the top or the bottom # i.e. sig1_max = min( 0, max( self.sig1_up, self.sig1_lo ) ) #--------------------------------------------------------- # initialize arrays t be filled by case distinction: #--------------------------------------------------------- # f_t_sig = zeros_like(self.sig1_up) alpha = zeros_like(self.sig1_up) k_fl_NM = ones_like(self.sig1_up) # absolute value of the bending stress created by mx or my sig_b = (abs(self.sig1_lo) + abs(self.sig1_up)) / 2 #--------------------------------------------------------- # conditions for case distinction #--------------------------------------------------------- cond_t_up = self.sig1_up > 0. # compression stress upper side cond_t_lo = self.sig1_lo > 0. # compression stress lower side cond_u_gt_l = abs(self.sig1_up) > abs( self.sig1_lo ) # absolute value of upper stress greater then lower stress cond_l_gt_u = abs(self.sig1_lo) > abs( self.sig1_up ) # absolute value of lower stress greater then lower stress cond_u_eq_l = abs(self.sig1_up) == abs( self.sig1_lo ) # absolute values of upper stress equals lower stress cond_b = self.sig1_up * self.sig1_lo < 0 # bending case cond_u_gt_0 = self.sig1_up > 0 # value of upper stress greater then 0. cond_l_gt_0 = self.sig1_lo > 0 # value of lower stress greater then 0. cond_c_up = self.sig1_up < 0. # compression stress upper side cond_c_lo = self.sig1_lo < 0. # compression stress lower side #--------------------------------------------------------- # tension case: #--------------------------------------------------------- # sig_up > sig_lo bool_arr = cond_t_up * cond_t_lo * cond_u_gt_l alpha[bool_arr] = self.alpha_sig_up[bool_arr] k_fl_NM[bool_arr] = 1.0 f_t_sig[bool_arr] = self.sig1_up[bool_arr] * self.D_elem[ bool_arr] * 1000. # sig_lo > sig_up bool_arr = cond_t_up * cond_t_lo * cond_l_gt_u alpha[bool_arr] = self.alpha_sig_lo[bool_arr] k_fl_NM[bool_arr] = 1.0 f_t_sig[bool_arr] = self.sig1_lo[bool_arr] * self.D_elem[ bool_arr] * 1000. # sig_lo = sig_up bool_arr = cond_t_up * cond_t_lo * cond_u_eq_l alpha[bool_arr] = (self.alpha_sig_lo[bool_arr] + self.alpha_sig_up[bool_arr]) / 2. k_fl_NM[bool_arr] = 1.0 f_t_sig[bool_arr] = self.sig1_lo[bool_arr] * self.D_elem[ bool_arr] * 1000. #--------------------------------------------------------- # bending case (= different signs) #--------------------------------------------------------- # bending with tension at the lower side # AND sig_N > 0 (--> bending and tension; sig1_lo results from bending and tension) bool_arr = cond_b * cond_l_gt_0 * cond_l_gt_u alpha[bool_arr] = self.alpha_sig_lo[bool_arr] k_fl_NM[ bool_arr ] = 1.0 + ( self.k_fl - 1.0 ) * \ ( 1.0 - ( sig_b[ bool_arr ] - abs( self.sig1_up[ bool_arr] ) ) / self.sig1_lo[ bool_arr ] ) f_t_sig[bool_arr] = self.sig1_lo[bool_arr] * self.D_elem[ bool_arr] * 1000. / k_fl_NM[bool_arr] # bending with tension at the lower side # AND sig_N < 0 (--> bending and compression; sig1_lo results only from bending) bool_arr = cond_b * cond_l_gt_0 * cond_u_gt_l alpha[bool_arr] = self.alpha_sig_lo[bool_arr] k_fl_NM[bool_arr] = self.k_fl f_t_sig[bool_arr] = self.sig1_lo[bool_arr] * self.D_elem[ bool_arr] * 1000. / k_fl_NM[bool_arr] # bending with tension at the upper side # AND sig_N > 0 (--> bending and tension; sig1_up results from bending and tension) bool_arr = cond_b * cond_u_gt_0 * cond_u_gt_l alpha[bool_arr] = self.alpha_sig_up[bool_arr] k_fl_NM[ bool_arr ] = 1.0 + ( self.k_fl - 1.0 ) * \ ( 1.0 - ( sig_b[ bool_arr ] - abs( self.sig1_lo[ bool_arr] ) ) / self.sig1_up[ bool_arr ] ) f_t_sig[bool_arr] = self.sig1_up[bool_arr] * self.D_elem[ bool_arr] * 1000. / k_fl_NM[bool_arr] # bending with tension at the upper side # AND sig_N < 0 (--> bending and compression; sig1_up results only from bending) bool_arr = cond_b * cond_u_gt_0 * cond_l_gt_u alpha[bool_arr] = self.alpha_sig_up[bool_arr] k_fl_NM[bool_arr] = self.k_fl f_t_sig[bool_arr] = self.sig1_up[bool_arr] * self.D_elem[ bool_arr] * 1000. / k_fl_NM[bool_arr] #--------------------------------------------------------- # compression case: #--------------------------------------------------------- bool_arr = cond_c_up * cond_c_lo # deflection angle is of minor interest use this simplification alpha[bool_arr] = (self.alpha_sig_up[bool_arr] + self.alpha_sig_up[bool_arr]) / 2. f_t_sig[bool_arr] = 0. k_fl_NM[bool_arr] = 1.0 #------------------------------------------------------------ # get angel of deflection of the textile reinforcement #------------------------------------------------------------ # angel of deflection of the textile reinforcement for dimensioning in x-direction # distinguished between longitudinal (l) and transversal (q) direction # # ASSUMPTION: worst case angle used # # as first step use the worst case reduction due to deflection possible (at 55 degrees) # beta_l = 55. * pi / 180. * ones_like( alpha ) # beta_q = ( 90. - 55. ) * pi / 180. * ones_like( alpha ) # @todo: as second step use the value for an alternating layup (i.e. deflection angle) # @todo: get the correct formula for the demonstrator arrangement # i.e. the RFEM coordinate system orientation # print "NOTE: deflection angle is used to evaluate 'n_tex'" beta_l = 90 - abs(alpha) # [degree] beta_q = abs(alpha) # [degree] # resulting strength of the bi-directional textile considering the # deflection of the reinforcement in the loading direction: f_Rtex = f_Rtex_l * cos( beta_l * pi / 180. ) * ( 1 - beta_l / 90. ) + \ f_Rtex_q * cos( beta_q * pi / 180. ) * ( 1 - beta_q / 90. ) # f_Rtex= 11.65 kN/m corresponds to sig_Rtex = 585 MPa # # f_Rtex = 11.65 * ones_like( alpha ) # f_Rtex= 10.9 kN/m corresponds to sig_Rtex = 678 MPa # with 1/3*( 679 + 690 + 667 ) = 678 MPa # # f_Rtex = 10.9 * ones_like( alpha ) # f_Rtex = 10.00 kN/m corresponds to sig_Rtex = 610 MPa # # f_Rtex = 10.00 * ones_like( alpha ) # print 'NOTE: f_Rtex set to %g kN/m !' % ( f_Rtex[0] ) if princ_stress_eval == False: # necessary number of reinforcement layers n_tex = f_t / f_Rtex return { 'e': e, 'm_Eds': m_Eds, 'f_t': f_t, 'f_t_sig': f_t_sig, 'beta_l': beta_l, 'beta_q': beta_q, 'f_Rtex': f_Rtex, 'n_tex': n_tex } elif princ_stress_eval == True: # NOTE: as the entire (!) cross section is used to calculate 'f_tex_sig' # the number of layers is evaluated also directly for the entire (!) # cross section! # n_tex = f_t_sig / f_Rtex return { 'e': e, 'm_Eds': m_Eds, 'f_t': f_t, 'f_t_sig': f_t_sig, 'beta_l': beta_l, 'beta_q': beta_q, 'f_Rtex': f_Rtex, 'n_tex': n_tex, 'k_fl_NM': k_fl_NM } e = Property def _get_e(self): return self.ls_values['e'] m_Eds = Property def _get_m_Eds(self): return self.ls_values['m_Eds'] f_t = Property def _get_f_t(self): return self.ls_values['f_t'] f_t_sig = Property def _get_f_t_sig(self): return self.ls_values['f_t_sig'] beta_l = Property def _get_beta_l(self): return self.ls_values['beta_l'] beta_q = Property def _get_beta_q(self): return self.ls_values['beta_q'] f_Rtex = Property def _get_f_Rtex(self): return self.ls_values['f_Rtex'] k_fl_NM = Property def _get_k_fl_NM(self): return self.ls_values['k_fl_NM'] n_tex = Property def _get_n_tex(self): return self.ls_values['n_tex'] assess_name = 'max_n_tex' max_n_tex = Property(depends_on='+input') @cached_property def _get_max_n_tex(self): return ndmax(self.n_tex) # assess_name = 'max_sig1_up' # max_sig1_up = Property( depends_on = '+input' ) # @cached_property # def _get_max_sig1_up( self ): # return ndmax( self.sig1_up ) # assess_name = 'max_sig1_lo' # max_sig1_lo = Property( depends_on = '+input' ) # @cached_property # def _get_max_sig1_lo( self ): # return ndmax( self.sig1_lo ) #------------------------------- # ls view #------------------------------- # @todo: the dynamic selection of the columns to be displayed # does not work in connection with the LSArrayAdapter traits_view = View(VGroup( HGroup( VGroup(Item(name='gamma', label='safety factor material [-]: gamma '), Item(name='beta', label='reduction long term durability [-]: beta '), label='safety factors'), VGroup(Item(name='f_tk_l', label='characteristic strength textil [MPa]: f_tk_l ', format_str="%.1f"), Item(name='f_td_l', label='design strength textil [MPa]: f_td_l ', style='readonly', format_str="%.1f"), Item(name='a_t_l', label='cross sectional area textil [mm^2]: a_t_l ', style='readonly', format_str="%.1f"), Item(name='f_Rtex_l', label='design strength textil [kN/m]: f_Rtex_l ', style='readonly', format_str="%.0f"), label='material properties (longitudinal)'), VGroup(Item(name='f_tk_q', label='characteristic strength textil [MPa]: f_tk_q ', format_str="%.1f"), Item(name='f_td_q', label='design strength textil [MPa]: f_td_q ', style='readonly', format_str="%.1f"), Item(name='a_t_q', label='cross sectional area textil [mm^2]: a_t_q ', style='readonly', format_str="%.1f"), Item(name='f_Rtex_q', label='design strength textil [kN/m]: f_Rtex_q ', style='readonly', format_str="%.0f"), label='material Properties (transversal)'), ), VGroup( Include('ls_group'), Item('ls_array', show_label=False, editor=TabularEditor(adapter=LSArrayAdapter()))), ), resizable=True, scrollable=True, height=1000, width=1100)
class GridReinforcement(HasTraits): ''' Class delivering reinforcement ratio for a grid reinforcement of a cross section ''' h = Float( 30, auto_set=False, enter_set=True, # [mm] desc='the height of the cross section', modified=True) w = Float( 100, auto_set=False, enter_set=True, # [mm] desc='the width of the cross section', modified=True) n_f_h = Float( 9, auto_set=False, enter_set=True, # [-] desc='the number of fibers in the height direction', modified=True) n_f_w = Float( 12, auto_set=False, enter_set=True, # [-] desc='the number of fibers in the width direction', modified=True) a_f = Float( 0.89, auto_set=False, enter_set=True, # [m] desc='the cross sectional area of a single fiber', modified=True) A_tot = Property(Float, depends_on='+modified') def _get_A_tot(self): return self.h * self.w A_f = Property(Float, depends_on='+modified') def _get_A_f(self): n_f = self.n_f_h * self.n_f_w a_f = self.a_f return a_f * n_f rho = Property(Float, depends_on='+modified') @cached_property def _get_rho(self): return self.A_f / self.A_tot traits_view = View( VGroup( Group(Item('h', label='height'), Item('w', label='width'), label='cross section dimensions', orientation='vertical'), Group(Item('a_f', label='area of a single fiber'), Item('n_f_h', label='# in height direction'), Item('n_f_w', label='# in width direction'), label='layout of the fiber grid', orientation='vertical'), Item('rho', label='current reinforcement ratio', style='readonly', emphasized=True), # label = 'Cross section parameters', id='scm.cs.params', ), id='scm.cs', dock='horizontal', resizable=True, height=0.8, width=0.8)
class SimCrackLoc( IBVModel ): '''Model assembling the components for studying the restrained crack localization. ''' shape = Int( 1, desc = 'Number of finite elements', ps_levsls = ( 10, 40, 4 ) ) length = Float( 1, desc = 'Length of the simulated region' ) #------------------------------------------------------- # Material model for the matrix #------------------------------------------------------- mats_m = Instance( MATS1DCrackLoc ) def _mats_m_default( self ): E_m = 1 mats_m = MATS1DCrackLoc( E = E_m, R = 0.5, epsilon_0 = 0.001, epsilon_f = 0.01 ) return mats_m mats_f = Instance( MATS1DElastic ) def _mats_f_default( self ): E_f = 0 mats_f = MATS1DElastic( E = E_f ) return mats_f mats_b = Instance( MATS1DElastic ) def _mats_b_default( self ): E_b = 0 mats_b = MATS1DElastic( E = E_b ) return mats_b mats = Instance( MATS1D5Bond ) def _mats_default( self ): # Material model construction mats = MATS1D5Bond( mats_phase1 = self.mats_m, mats_phase2 = self.mats_f, mats_ifslip = self.mats_b, mats_ifopen = MATS1DElastic( E = 0 ) # elastic function of open - inactive ) return mats #------------------------------------------------------- # Finite element type #------------------------------------------------------- fets = Instance( FETSEval ) def _fets_default( self ): #return FETS1D52L8ULRH( mats_eval = self.mats ) return FETS1D52L4ULRH( mats_eval = self.mats ) #return FETS1D2L3U( mats_eval = self.mats ) run = Button @on_trait_change( 'run' ) def peval( self ): '''Evaluation procedure. ''' #mv = MATS1DDamageView( model = mats_eval ) #mv.configure_traits() self.mats_m.reset_state() # Discretization # length = self.length domain = FEGrid( coord_min = ( 0., length / 5. ), coord_max = ( length, 0. ), shape = ( self.shape, 1 ), fets_eval = self.fets ) right_dofs = domain[-1, -1, -1, :].dofs[0, :, 0] print 'concrete_dofs', id( domain ), domain[:, 0, :, 0].dofs # Response tracers self.stress_strain = RTraceGraph( name = 'Fi,right over u_right (iteration)' , var_y = 'F_int', idx_y = right_dofs[0], var_x = 'U_k', idx_x = right_dofs[0] ) self.eps_m_field = RTraceDomainListField( name = 'eps_m' , position = 'int_pnts', var = 'eps1', idx = 0, warp = True ) self.eps_f_field = RTraceDomainListField( name = 'eps_f' , position = 'int_pnts', var = 'eps2', idx = 0, warp = True ) # Response tracers self.sig_m_field = RTraceDomainListField( name = 'sig_m' , position = 'int_pnts', var = 'mats_phase1_sig_app', idx = 0 ) self.sig_f_field = RTraceDomainListField( name = 'sig_f' , position = 'int_pnts', var = 'mats_phase2_sig_app', idx = 0 ) self.omega_m_field = RTraceDomainListField( name = 'omega_m' , position = 'int_pnts', var = 'mats_phase1_omega', idx = 0, warp = True ) # damage_onset_displ = self.mats_m.epsilon_0 * self.length go_behind = 1.5 finish_displ = go_behind * damage_onset_displ n_steps = 20 step_size = ( finish_displ - damage_onset_displ ) / n_steps tmax = 1 + n_steps def ls( t ): if t <= 1: return t else: return 1.0 + ( t - 1.0 ) / n_steps * ( go_behind - 1 ) ts = TSCrackLoc( dof_resultants = True, on_update = self.plot, sdomain = domain, bcond_list = [# define the left clamping BCSlice( var = 'u', value = 0., dims = [0], slice = domain[ 0, 0, 0, :] ), # loading at the right edge BCSlice( var = 'f', value = 1, dims = [0], slice = domain[-1, -1, -1, 0], time_function = ls ), # BCSlice(var='u', value = finish_displ, dims = [0], slice = domain[-1,-1,-1, 0], # time_function = ls ), # fix horizontal displacement in the top layer BCSlice( var = 'u', value = 0., dims = [0], slice = domain[:, -1, :, -1] ), # fix the vertical displacement all over the domain BCSlice( var = 'u', value = 0., dims = [1], slice = domain[ :, :, :, :] ) ], rtrace_list = [ self.stress_strain, self.eps_m_field, self.eps_f_field, self.sig_m_field, self.sig_f_field, self.omega_m_field ] ) # Add the time-loop control tloop = TLoop( tstepper = ts, KMAX = 200, debug = True, tolerance = 1e-5, tline = TLine( min = 0.0, step = 1.0, max = 1.0 ) ) print ts.rte_dict.keys() U = tloop.eval() self.plot() return array( [ U[right_dofs[-1]] ], dtype = 'float_' ) #--------------------------------------------------------------- # PLOT OBJECT #------------------------------------------------------------------- figure_ld = Instance( Figure ) def _figure_ld_default( self ): figure = Figure( facecolor = 'white' ) figure.add_axes( [0.12, 0.13, 0.85, 0.74] ) return figure #--------------------------------------------------------------- # PLOT OBJECT #------------------------------------------------------------------- figure_eps = Instance( Figure ) def _figure_eps_default( self ): figure = Figure( facecolor = 'white' ) figure.add_axes( [0.12, 0.13, 0.85, 0.74] ) return figure #--------------------------------------------------------------- # PLOT OBJECT #------------------------------------------------------------------- figure_omega = Instance( Figure ) def _figure_omega_default( self ): figure = Figure( facecolor = 'white' ) figure.add_axes( [0.12, 0.13, 0.85, 0.74] ) return figure #--------------------------------------------------------------- # PLOT OBJECT #------------------------------------------------------------------- figure_sig = Instance( Figure ) def _figure_sig_default( self ): figure = Figure( facecolor = 'white' ) figure.add_axes( [0.12, 0.13, 0.85, 0.74] ) return figure def plot( self ): self.stress_strain.refresh() t = self.stress_strain.trace ax = self.figure_ld.axes[0] ax.clear() ax.plot( t.xdata, t.ydata, linewidth = 2, color = 'blue' ) ax = self.figure_eps.axes[0] ax.clear() ef = self.eps_m_field.subfields[0] xdata = ef.vtk_X[:, 0] ydata = ef.field_arr[:, 0] idata = argsort( xdata ) ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'grey' ) ef = self.eps_f_field.subfields[0] xdata = ef.vtk_X[:, 0] ydata = ef.field_arr[:, 0] idata = argsort( xdata ) ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'red' ) ax.legend( ['eps_m', 'eps_f'] ) ax = self.figure_sig.axes[0] ax.clear() ef = self.sig_m_field.subfields[0] xdata = ef.vtk_X[:, 0] ydata = ef.field_arr[:, 0] idata = argsort( xdata ) ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'grey' ) ef = self.sig_f_field.subfields[0] xdata = ef.vtk_X[:, 0] ydata = ef.field_arr[:, 0] idata = argsort( xdata ) ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'red' ) ax.legend( ['sig_m', 'sig_f'] ) ax = self.figure_omega.axes[0] ax.clear() ef = self.omega_m_field.subfields[0] xdata = ef.vtk_X[:, 0] ydata = ef.field_arr[:, 0] idata = argsort( xdata ) ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'brown' ) ax.legend( ['omega_m'] ) self.data_changed = True def get_sim_outputs( self ): ''' Specifies the results and their order returned by the model evaluation. ''' return [ SimOut( name = 'right end displacement', unit = 'm' ) ] data_changed = Event toolbar = ToolBar( Action( name = "Run", tooltip = 'Start computation', image = ImageResource( 'kt-start' ), action = "start_study" ), Action( name = "Pause", tooltip = 'Pause computation', image = ImageResource( 'kt-pause' ), action = "pause_study" ), Action( name = "Stop", tooltip = 'Stop computation', image = ImageResource( 'kt-stop' ), action = "stop_study" ), image_size = ( 32, 32 ), show_tool_names = False, show_divider = True, name = 'view_toolbar' ), traits_view = View( HSplit( VSplit( Item( 'run', show_label = False ), VGroup( Item( 'shape' ), Item( 'n_sjteps' ), Item( 'length' ), label = 'parameters', id = 'crackloc.viewmodel.factor.geometry', dock = 'tab', scrollable = True, ), VGroup( Item( 'mats_m@', show_label = False ), label = 'Matrix', dock = 'tab', id = 'crackloc.viewmodel.factor.matrix', scrollable = True ), VGroup( Item( 'mats_f@', show_label = False ), label = 'Fiber', dock = 'tab', id = 'crackloc.viewmodel.factor.fiber', scrollable = True ), VGroup( Item( 'mats_b@', show_label = False ), label = 'Bond', dock = 'tab', id = 'crackloc.viewmodel.factor.bond', scrollable = True ), id = 'crackloc.viewmodel.left', label = 'studied factors', layout = 'tabbed', dock = 'tab', ), VSplit( VGroup( Item( 'figure_ld', editor = MPLFigureEditor(), resizable = True, show_label = False ), label = 'stress-strain', id = 'crackloc.viewmode.figure_ld_window', dock = 'tab', ), VGroup( Item( 'figure_eps', editor = MPLFigureEditor(), resizable = True, show_label = False ), label = 'strains profile', id = 'crackloc.viewmode.figure_eps_window', dock = 'tab', ), VGroup( Item( 'figure_sig', editor = MPLFigureEditor(), resizable = True, show_label = False ), label = 'stress profile', id = 'crackloc.viewmode.figure_sig_window', dock = 'tab', ), VGroup( Item( 'figure_omega', editor = MPLFigureEditor(), resizable = True, show_label = False ), label = 'omega profile', id = 'crackloc.viewmode.figure_omega_window', dock = 'tab', ), id = 'crackloc.viewmodel.right', ), id = 'crackloc.viewmodel.splitter', ), title = 'SimVisage Component: Crack localization', id = 'crackloc.viewmodel', dock = 'tab', resizable = True, height = 0.8, width = 0.8, buttons = [OKButton] )
class PDistribView(ModelView): def __init__(self, **kw): super(PDistribView, self).__init__(**kw) self.on_trait_change( self.refresh, 'model.distr_type.changed, model.quantile, model.n_segments') self.refresh() model = Instance(PDistrib) figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor='white') return figure data_changed = Event def plot(self, fig): figure = fig figure.clear() axes = figure.gca() # plot PDF axes.plot(self.model.x_array, self.model.pdf_array, lw=1.0, color='blue', label='PDF') axes2 = axes.twinx() # plot CDF on a separate axis (tick labels left) axes2.plot(self.model.x_array, self.model.cdf_array, lw=2, color='red', label='CDF') # fill the unity area given by integrating PDF along the X-axis axes.fill_between(self.model.x_array, 0, self.model.pdf_array, color='lightblue', alpha=0.8, linewidth=2) # plot mean mean = self.model.distr_type.distr.stats('m') axes.plot([mean, mean], [0.0, self.model.distr_type.distr.pdf(mean)], lw=1.5, color='black', linestyle='-') # plot stdev stdev = sqrt(self.model.distr_type.distr.stats('v')) axes.plot([mean - stdev, mean - stdev], [0.0, self.model.distr_type.distr.pdf(mean - stdev)], lw=1.5, color='black', linestyle='--') axes.plot([mean + stdev, mean + stdev], [0.0, self.model.distr_type.distr.pdf(mean + stdev)], lw=1.5, color='black', linestyle='--') axes.legend(loc='center left') axes2.legend(loc='center right') axes.ticklabel_format(scilimits=(-3., 4.)) axes2.ticklabel_format(scilimits=(-3., 4.)) # plot limits on X and Y axes axes.set_ylim(0.0, max(self.model.pdf_array) * 1.15) axes2.set_ylim(0.0, 1.15) range = self.model.range[1] - self.model.range[0] axes.set_xlim(self.model.x_array[0] - 0.05 * range, self.model.x_array[-1] + 0.05 * range) axes2.set_xlim(self.model.x_array[0] - 0.05 * range, self.model.x_array[-1] + 0.05 * range) def refresh(self): self.plot(self.figure) self.data_changed = True icon = Property( Instance(ImageResource), depends_on='model.distr_type.changed, model.quantile, model.n_segments' ) @cached_property def _get_icon(self): import matplotlib.pyplot as plt fig = plt.figure(figsize=(4, 4), facecolor='white') self.plot(fig) tf_handle, tf_name = tempfile.mkstemp('.png') fig.savefig(tf_name, dpi=35) return ImageResource(name=tf_name) traits_view = View(HSplit(VGroup( Group( Item('model.distr_choice', show_label=False), Item('@model.distr_type', show_label=False), ), id='pdistrib.distr_type.pltctrls', label='Distribution parameters', scrollable=True, ), Tabbed( Group( Item('figure', editor=MPLFigureEditor(), show_label=False, resizable=True), scrollable=True, label='Plot', ), Group(Item('model.quantile', label='quantile'), Item('model.n_segments', label='plot points'), label='Plot parameters'), label='Plot', id='pdistrib.figure.params', dock='tab', ), dock='tab', id='pdistrib.figure.view'), id='pdistrib.view', dock='tab', title='Statistical distribution', buttons=[OKButton, CancelButton], scrollable=True, resizable=True, width=600, height=400)
class ExpSH(ExType): '''Experiment: Shell Test ''' # label = Str('slab test') implements(IExType) #-------------------------------------------------------------------- # register a change of the traits with metadata 'input' #-------------------------------------------------------------------- input_change = Event @on_trait_change('+input, ccs.input_change, +ironing_param') def _set_input_change(self): self.input_change = True #-------------------------------------------------------------------------------- # specify inputs: #-------------------------------------------------------------------------------- edge_length = Float(1.25, unit = 'm', input = True, table_field = True, auto_set = False, enter_set = True) thickness = Float(0.03, unit = 'm', input = True, table_field = True, auto_set = False, enter_set = True) # age of the concrete at the time of testing age = Int(28, unit = 'd', input = True, table_field = True, auto_set = False, enter_set = True) loading_rate = Float(0.50, unit = 'mm/min', input = True, table_field = True, auto_set = False, enter_set = True) #-------------------------------------------------------------------------- # composite cross section #-------------------------------------------------------------------------- ccs = Instance(CompositeCrossSection) def _ccs_default(self): '''default settings correspond to setup '7u_MAG-07-03_PZ-0708-1' ''' fabric_layout_key = 'MAG-07-03' # fabric_layout_key = '2D-02-06a' concrete_mixture_key = 'PZ-0708-1' # concrete_mixture_key = 'FIL-10-09' # orientation_fn_key = 'all0' orientation_fn_key = '90_0' n_layers = 10 s_tex_z = 0.030 / (n_layers + 1) ccs = CompositeCrossSection ( fabric_layup_list = [ plain_concrete(s_tex_z * 0.5), FabricLayUp ( n_layers = n_layers, orientation_fn_key = orientation_fn_key, s_tex_z = s_tex_z, fabric_layout_key = fabric_layout_key ), plain_concrete(s_tex_z * 0.5) ], concrete_mixture_key = concrete_mixture_key ) return ccs #-------------------------------------------------------------------------- # Get properties of the composite #-------------------------------------------------------------------------- # E-modulus of the composite at the time of testing E_c = Property(Float, unit = 'MPa', depends_on = 'input_change', table_field = True) def _get_E_c(self): return self.ccs.get_E_c_time(self.age) # E-modulus of the composite after 28 days E_c28 = DelegatesTo('ccs', listenable = False) # reinforcement ration of the composite rho_c = DelegatesTo('ccs', listenable = False) #-------------------------------------------------------------------------------- # define processing #-------------------------------------------------------------------------------- # put this into the ironing procedure processor # jump_rtol = Float(1, auto_set = False, enter_set = True, ironing_param = True) data_array_ironed = Property(Array(float), depends_on = 'data_array, +ironing_param, +axis_selection') @cached_property def _get_data_array_ironed(self): '''remove the jumps in the displacement curves due to resetting the displacement gauges. ''' print '*** curve ironing activated ***' # each column from the data array corresponds to a measured parameter # e.g. displacement at a given point as function of time u = f(t)) # data_array_ironed = copy(self.data_array) for idx in range(self.data_array.shape[1]): # use ironing method only for columns of the displacement gauges. # if self.names_and_units[0][ idx ] != 'Kraft' and \ self.names_and_units[0][ idx ] != 'Bezugskanal' and \ self.names_and_units[0][ idx ] != 'D_1o'and \ self.names_and_units[0][ idx ] != 'D_2o'and \ self.names_and_units[0][ idx ] != 'D_3o'and \ self.names_and_units[0][ idx ] != 'D_4o'and \ self.names_and_units[0][ idx ] != 'D_1u'and \ self.names_and_units[0][ idx ] != 'D_2u'and \ self.names_and_units[0][ idx ] != 'D_3u'and \ self.names_and_units[0][ idx ] != 'D_4u'and \ self.names_and_units[0][ idx ] != 'W30_vo'and \ self.names_and_units[0][ idx ] != 'W30_hi': # 1d-array corresponding to column in data_array data_arr = copy(data_array_ironed[:, idx]) # get the difference between each point and its successor jump_arr = data_arr[1:] - data_arr[0:-1] # get the range of the measured data data_arr_range = max(data_arr) - min(data_arr) # determine the relevant criteria for a jump # based on the data range and the specified tolerances: jump_crit = self.jump_rtol * data_arr_range # get the indexes in 'data_column' after which a # jump exceeds the defined tolerance criteria jump_idx = where(fabs(jump_arr) > jump_crit)[0] print 'number of jumps removed in data_arr_ironed for', self.names_and_units[0][ idx ], ': ', jump_idx.shape[0] # glue the curve at each jump together for jidx in jump_idx: # get the offsets at each jump of the curve shift = data_arr[jidx + 1] - data_arr[jidx] # shift all succeeding values by the calculated offset data_arr[jidx + 1:] -= shift data_array_ironed[:, idx] = data_arr[:] return data_array_ironed @on_trait_change('+ironing_param') def process_source_data(self): '''read in the measured data from file and assign attributes after array processing. NOTE: if center displacement gauge ('WA_M') is missing the measured displacement of the cylinder ('Weg') is used instead. A minor mistake is made depending on how much time passes before the cylinder has contact with the slab. ''' print '*** process source data ***' self._read_data_array() # curve ironing: # self.processed_data_array = self.data_array_ironed # set attributes: # self._set_array_attribs() #-------------------------------------------------------------------------------- # plot templates #-------------------------------------------------------------------------------- plot_templates = {'force / time' : '_plot_force_time', 'force / deflections center' : '_plot_force_deflection_center', 'force / smoothed deflections center' : '_plot_smoothed_force_deflection_center', 'force / deflections' : '_plot_force_deflections', 'force / eps_t' : '_plot_force_eps_t', 'force / eps_c' : '_plot_force_eps_c', 'force / w_elastomer' : '_plot_force_w_elastomer', 'time / deflections' : '_plot_time_deflections' } default_plot_template = 'force / time' def _plot_force_w_elastomer(self, axes): xkey = 'displacement [mm]' ykey = 'force [kN]' W_vl = self.W_vl W_vr = self.W_vr W_hl = self.W_hl W_hr = self.W_hr force = self.Kraft axes.set_xlabel('%s' % (xkey,)) axes.set_ylabel('%s' % (ykey,)) axes.plot(W_vl, force) axes.plot(W_vr, force) axes.plot(W_hl, force) axes.plot(W_hr, force) def _plot_force_time(self, axes): xkey = 'time [s]' ykey = 'force [kN]' xdata = self.Bezugskanal ydata = self.Kraft axes.set_xlabel('%s' % (xkey,)) axes.set_ylabel('%s' % (ykey,)) axes.plot(xdata, ydata # color = c, linewidth = w, linestyle = s ) def _plot_force_deflection_center(self, axes): xkey = 'deflection [mm]' ykey = 'force [kN]' xdata = -self.WD4 ydata = self.Kraft axes.set_xlabel('%s' % (xkey,)) axes.set_ylabel('%s' % (ykey,)) axes.plot(xdata, ydata # color = c, linewidth = w, linestyle = s ) n_fit_window_fraction = Float(0.1) def _plot_smoothed_force_deflection_center(self, axes): xkey = 'deflection [mm]' ykey = 'force [kN]' # get the index of the maximum stress max_force_idx = argmax(self.Kraft) # get only the ascending branch of the response curve f_asc = self.Kraft[:max_force_idx + 1] w_asc = -self.WD4[:max_force_idx + 1] f_max = f_asc[-1] w_max = w_asc[-1] n_points = int(self.n_fit_window_fraction * len(w_asc)) f_smooth = smooth(f_asc, n_points, 'flat') w_smooth = smooth(w_asc, n_points, 'flat') axes.plot(w_smooth, f_smooth, color = 'blue', linewidth = 2) secant_stiffness_w10 = (f_smooth[10] - f_smooth[0]) / (w_smooth[10] - w_smooth[0]) w0_lin = array([0.0, w_smooth[10] ], dtype = 'float_') f0_lin = array([0.0, w_smooth[10] * secant_stiffness_w10 ], dtype = 'float_') axes.set_xlabel('%s' % (xkey,)) axes.set_ylabel('%s' % (ykey,)) def _plot_force_deflections(self, axes): xkey = 'displacement [mm]' ykey = 'force [kN]' # get the index of the maximum stress max_force_idx = argmax(self.Kraft) # get only the ascending branch of the response curve f_asc = self.Kraft[:max_force_idx + 1] WD1 = -self.WD1[:max_force_idx + 1] WD2 = -self.WD2[:max_force_idx + 1] WD3 = -self.WD3[:max_force_idx + 1] WD4 = -self.WD4[:max_force_idx + 1] WD5 = -self.WD5[:max_force_idx + 1] WD6 = -self.WD6[:max_force_idx + 1] WD7 = -self.WD7[:max_force_idx + 1] axes.plot(WD1, f_asc, color = 'blue', linewidth = 1 ) axes.plot(WD2, f_asc, color = 'green', linewidth = 1 ) axes.plot(WD3, f_asc, color = 'red', linewidth = 1 ) axes.plot(WD4, f_asc, color = 'black', linewidth = 3 ) axes.plot(WD5, f_asc, color = 'red', linewidth = 1 ) axes.plot(WD6, f_asc, color = 'green', linewidth = 1 ) axes.plot(WD7, f_asc, color = 'blue', linewidth = 1 ) axes.set_xlabel('%s' % (xkey,)) axes.set_ylabel('%s' % (ykey,)) def _plot_time_deflections(self, axes): xkey = 'time [s]' ykey = 'deflections [mm]' time = self.Bezugskanal WD1 = -self.WD1 WD2 = -self.WD2 WD3 = -self.WD3 WD4 = -self.WD4 WD5 = -self.WD5 WD6 = -self.WD6 WD7 = -self.WD7 axes.plot(time, WD1, color = 'blue', linewidth = 1 ) axes.plot(time, WD2, color = 'green', linewidth = 1 ) axes.plot(time, WD3, color = 'red', linewidth = 1 ) axes.plot(time, WD4, color = 'black', linewidth = 3 ) axes.plot(time, WD5, color = 'red', linewidth = 1 ) axes.plot(time, WD6, color = 'green', linewidth = 1 ) axes.plot(time, WD7, color = 'blue', linewidth = 1 ) axes.set_xlabel('%s' % (xkey,)) axes.set_ylabel('%s' % (ykey,)) def _plot_force_eps_c(self, axes): xkey = 'force [kN]' ykey = 'strain [mm/m]' # get the index of the maximum stress max_force_idx = argmax(self.Kraft) # get only the ascending branch of the response curve f_asc = self.Kraft[:max_force_idx + 1] D_1u = -self.D_1u[:max_force_idx + 1] D_2u = -self.D_2u[:max_force_idx + 1] D_3u = -self.D_3u[:max_force_idx + 1] D_4u = -self.D_4u[:max_force_idx + 1] D_1o = -self.D_1o[:max_force_idx + 1] D_2o = -self.D_2o[:max_force_idx + 1] D_3o = -self.D_3o[:max_force_idx + 1] D_4o = -self.D_4o[:max_force_idx + 1] axes.plot(f_asc, D_1u, color = 'blue', linewidth = 1 ) axes.plot(f_asc, D_2u, color = 'blue', linewidth = 1 ) axes.plot(f_asc, D_3u, color = 'blue', linewidth = 1 ) axes.plot(f_asc, D_4u, color = 'blue', linewidth = 1 ) axes.plot(f_asc, D_1o, color = 'red', linewidth = 1 ) axes.plot(f_asc, D_2o, color = 'red', linewidth = 1 ) axes.plot(f_asc, D_3o, color = 'red', linewidth = 1 ) axes.plot(f_asc, D_4o, color = 'red', linewidth = 1 ) axes.set_xlabel('%s' % (xkey,)) axes.set_ylabel('%s' % (ykey,)) def _plot_force_eps_t(self, axes): xkey = 'strain [mm/m]' ykey = 'force [kN]' # get the index of the maximum stress max_force_idx = argmax(self.Kraft) # get only the ascending branch of the response curve f_asc = self.Kraft[:max_force_idx + 1] eps_vo = -self.W30_vo[:max_force_idx + 1] / 300. eps_hi = -self.W30_hi[:max_force_idx + 1] / 300. axes.plot(eps_vo, f_asc, color = 'blue', linewidth = 1 ) axes.plot(eps_hi, f_asc, color = 'green', linewidth = 1 ) axes.set_xlabel('%s' % (xkey,)) axes.set_ylabel('%s' % (ykey,)) #-------------------------------------------------------------------------------- # view #-------------------------------------------------------------------------------- traits_view = View(VGroup( Group( Item('jump_rtol', format_str = "%.4f"), label = 'curve_ironing' ), Group( Item('thickness', format_str = "%.3f"), Item('edge_length', format_str = "%.3f"), label = 'geometry' ), Group( Item('loading_rate'), Item('age'), label = 'loading rate and age' ), Group( Item('E_c', show_label = True, style = 'readonly', format_str = "%.0f"), Item('ccs@', show_label = False), label = 'composite cross section' ) ), scrollable = True, resizable = True, height = 0.8, width = 0.6 )
class SPIRRIDModelView(ModelView): ''' Size effect depending on the yarn length ''' model = Instance(SPIRRID) def _model_changed(self): self.model.rf = self.rf rf_values = List(IRF) def _rf_values_default(self): return [ Filament() ] rf = Enum(values = 'rf_values') def _rf_default(self): return self.rf_values[0] def _rf_changed(self): # reset the rf in the spirrid model and in the rf_modelview self.model.rf = self.rf self.rf_model_view = RFModelView(model = self.rf) # actually, the view should be reusable but the model switch # did not work for whatever reason # the binding of the view generated by edit_traits does not # react to the change in the 'model' attribute. # # Remember - we are implementing a handler here # that has an associated view. # # self.rf.model_view.model = self.rf rf_model_view = Instance(RFModelView) def _rf_model_view_default(self): return RFModelView(model = self.rf) rv_list = Property(List(RIDVariable), depends_on = 'rf') @cached_property def _get_rv_list(self): return [ RIDVariable(spirrid = self.model, rf = self.rf, varname = nm, trait_value = st) for nm, st in zip(self.rf.param_keys, self.rf.param_values) ] selected_var = Instance(RIDVariable) def _selected_var_default(self): return self.rv_list[0] run = Button(desc = 'Run the computation') def _run_fired(self): self._redraw() sample = Button(desc = 'Show samples') def _sample_fired(self): n_samples = 50 self.model.set( min_eps = 0.00, max_eps = self.max_eps, n_eps = self.n_eps, ) # get the parameter combinations for plotting rvs_theta_arr = self.model.get_rvs_theta_arr(n_samples) eps_arr = self.model.eps_arr figure = self.figure axes = figure.gca() for theta_arr in rvs_theta_arr.T: q_arr = self.rf(eps_arr, *theta_arr) axes.plot(eps_arr, q_arr, color = 'grey') self.data_changed = True run_legend = Str('', desc = 'Legend to be added to the plot of the results') clear = Button def _clear_fired(self): axes = self.figure.axes[0] axes.clear() self.data_changed = True min_eps = Float(0.0, desc = 'minimum value of the control variable') max_eps = Float(1.0, desc = 'maximum value of the control variable') n_eps = Int(100, desc = 'resolution of the control variable') label_eps = Str('epsilon', desc = 'label of the horizontal axis') label_sig = Str('sigma', desc = 'label of the vertical axis') figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor = 'white') #figure.add_axes( [0.08, 0.13, 0.85, 0.74] ) return figure data_changed = Event(True) def _redraw(self): figure = self.figure axes = figure.gca() self.model.set( min_eps = 0.00, max_eps = self.max_eps, n_eps = self.n_eps, ) mc = self.model.mean_curve axes.plot(mc.xdata, mc.ydata, linewidth = 2, label = self.run_legend) axes.set_xlabel(self.label_eps) axes.set_ylabel(self.label_sig) axes.legend(loc = 'best') self.data_changed = True traits_view_tabbed = View( VGroup( HGroup( Item('run_legend', resizable = False, label = 'Run label', width = 80, springy = False), Item('run', show_label = False, resizable = False), Item('sample', show_label = False, resizable = False), Item('clear', show_label = False, resizable = False, springy = False) ), Tabbed( VGroup( Item('rf', show_label = False), Item('rf_model_view@', show_label = False, resizable = True), label = 'Deterministic model', id = 'spirrid.tview.model', ), Group( Item('rv_list', editor = rv_list_editor, show_label = False), id = 'spirrid.tview.randomization.rv', label = 'Model variables', ), Group( Item('selected_var@', show_label = False, resizable = True), id = 'spirrid.tview.randomization.distr', label = 'Distribution', ), VGroup( Item('model.cached_dG' , label = 'Cached weight factors', resizable = False, springy = False), Item('model.compiled_QdG_loop' , label = 'Compiled loop over the integration product', springy = False), Item('model.compiled_eps_loop' , enabled_when = 'model.compiled_QdG_loop', label = 'Compiled loop over the control variable', springy = False), scrollable = True, label = 'Execution configuration', id = 'spirrid.tview.exec_params', dock = 'tab', ), VGroup( HGroup( Item('min_eps' , label = 'Min', springy = False, resizable = False), Item('max_eps' , label = 'Max', springy = False, resizable = False), Item('n_eps' , label = 'N', springy = False, resizable = False), label = 'Simulation range', show_border = True ), VGroup( Item('label_eps' , label = 'x', resizable = False, springy = False), Item('label_sig' , label = 'y', resizable = False, springy = False), label = 'Axes labels', show_border = True, scrollable = True, ), label = 'Execution control', id = 'spirrid.tview.view_params', dock = 'tab', ), VGroup( Item('figure', editor = MPLFigureEditor(), resizable = True, show_label = False), label = 'Plot sheet', id = 'spirrid.tview.figure_window', dock = 'tab', scrollable = True, ), scrollable = True, id = 'spirrid.tview.tabs', dock = 'tab', ), ), title = 'SPIRRID', id = 'spirrid.viewmodel', dock = 'tab', resizable = True, height = 1.0, width = 1.0 )
class ECBLMNDiagram(HasTraits): # calibrator supplying the effective material law calib = Instance(ECBLCalib) def _calib_default(self): return ECBLCalib(notify_change=self.set_modified) def _calib_changed(self): self.calib.notify_change = self.set_modified modified = Event def set_modified(self): print 'MN:set_modifeid' self.modified = True # cross section cs = DelegatesTo('calib') calibrated_ecb_law = Property(depends_on='modified') @cached_property def _get_calibrated_ecb_law(self): print 'NEW CALIBRATION' return self.calib.calibrated_ecb_law eps_cu = Property() def _get_eps_cu(self): return -self.cs.cc_law.eps_c_u eps_tu = Property() def _get_eps_tu(self): return self.calibrated_ecb_law.eps_tex_u n_eps = Int(5, auto_set=False, enter_set=True) eps_range = Property(depends_on='n_eps') @cached_property def _get_eps_range(self): eps_c_space = np.linspace(self.eps_cu, 0, self.n_eps) eps_t_space = np.linspace(0, self.eps_tu, self.n_eps) eps_ccu = 0.8 * self.eps_cu #eps_cc = self.eps_cu * np.ones_like(eps_c_space) eps_cc = np.linspace(eps_ccu, self.eps_cu, self.n_eps) eps_ct = self.eps_cu * np.ones_like(eps_t_space) eps_tc = self.eps_tu * np.ones_like(eps_c_space) eps_tt = self.eps_tu * np.ones_like(eps_t_space) eps1 = np.vstack([eps_c_space, eps_cc]) eps2 = np.vstack([eps_t_space, eps_ct]) eps3 = np.vstack([eps_tc, eps_c_space]) eps4 = np.vstack([eps_tt, eps_t_space]) return np.hstack([eps1, eps2, eps3, eps4]) n_eps_range = Property(depends_on='n_eps') @cached_property def _get_n_eps_range(self): return self.eps_range.shape[1] #=========================================================================== # MN Diagram #=========================================================================== def _get_MN_fn(self, eps_lo, eps_up): self.cs.set(eps_lo=eps_lo, eps_up=eps_up) return (self.cs.M, self.cs.N) MN_vct = Property(depends_on='modified') def _get_MN_vct(self): return np.vectorize(self._get_MN_fn) MN_arr = Property(depends_on='modified') @cached_property def _get_MN_arr(self): return self.MN_vct(self.eps_range[0, :], self.eps_range[1, :]) #=========================================================================== # f_eps Diagram #=========================================================================== current_eps_idx = Int(0) # , auto_set = False, enter_set = True) def _current_eps_idx_changed(self): self._clear_fired() self._replot_fired() current_eps = Property(depends_on='current_eps_idx') @cached_property def _get_current_eps(self): return self.eps_range[(0, 1), self.current_eps_idx] current_MN = Property(depends_on='current_eps_idx') @cached_property def _get_current_MN(self): return self._get_MN_fn(*self.current_eps) #=========================================================================== # Plotting #=========================================================================== figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor='white') figure.add_axes([0.08, 0.13, 0.85, 0.74]) return figure data_changed = Event clear = Button def _clear_fired(self): self.figure.clear() self.data_changed = True replot = Button def _replot_fired(self): ax = self.figure.add_subplot(2, 2, 1) ax.plot(-self.eps_range, [0, 0.06], color='black') ax.plot(-self.current_eps, [0, 0.06], lw=3, color='red') ax.spines['left'].set_position('zero') ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.spines['left'].set_smart_bounds(True) ax.spines['bottom'].set_smart_bounds(True) ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') ax = self.figure.add_subplot(2, 2, 2) ax.plot(self.MN_arr[0], -self.MN_arr[1], lw=2, color='blue') ax.plot(self.current_MN[0], -self.current_MN[1], 'g.', markersize=20.0, color='red') ax.spines['left'].set_position('zero') ax.spines['bottom'].set_position('zero') ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.spines['left'].set_smart_bounds(True) ax.spines['bottom'].set_smart_bounds(True) ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') ax.grid(b=None, which='major') self.cs.set(eps_lo=self.current_eps[0], eps_up=self.current_eps[1]) ax = self.figure.add_subplot(2, 2, 3) self.cs.plot_eps(ax) ax = self.figure.add_subplot(2, 2, 4) self.cs.plot_sig(ax) self.data_changed = True view = View(HSplit( Group( HGroup( Group(Item('n_eps', springy=True), label='Discretization', springy=True), springy=True, ), HGroup( Group(VGroup( Item( 'cs', label='Cross section', show_label=False, springy=True, editor=InstanceEditor(kind='live'), ), Item( 'calib', label='Calibration', show_label=False, springy=True, editor=InstanceEditor(kind='live'), ), springy=True, ), label='Cross sectoin', springy=True), springy=True, ), scrollable=True, ), Group( HGroup( Item('replot', show_label=False), Item('clear', show_label=False), ), Item( 'current_eps_idx', editor=RangeEditor( low=0, high_name='n_eps_range', format='(%s)', mode='slider', auto_set=False, enter_set=False, ), show_label=False, ), Item('figure', editor=MPLFigureEditor(), resizable=True, show_label=False), id='simexdb.plot_sheet', label='plot sheet', dock='tab', ), ), width=1.0, height=0.8, resizable=True, buttons=['OK', 'Cancel'])
class SimCrackLoc(IBVModel): '''Model assembling the components for studying the restrained crack localization. ''' geo_transform = Instance(FlawCenteredGeoTransform) def _geo_transform_default(self): return FlawCenteredGeoTransform() shape = Int(10, desc='Number of finite elements', ps_levsls=(10, 40, 4), input=True) length = Float(1000, desc='Length of the simulated region', unit='mm', input=True) flaw_position = Float(500, input=True, unit='mm') flaw_radius = Float(100, input=True, unit='mm') reduction_factor = Float(0.9, input=True) elastic_fraction = Float(0.9, input=True) avg_radius = Float(400, input=True, unit='mm') # tensile strength of concrete f_m_t = Float(3.0, input=True, unit='MPa') epsilon_0 = Property(unit='-') def _get_epsilon_0(self): return self.f_m_t / self.E_m epsilon_f = Float(10, input=True, unit='-') h_m = Float(10, input=True, unit='mm') b_m = Float(8, input=True, unit='mm') A_m = Property(unit='m^2') def _get_A_m(self): return self.b_m * self.h_m E_m = Float(30.0e5, input=True, unit='MPa') E_f = Float(70.0e6, input=True, unit='MPa') A_f = Float(1.0, input=True, unit='mm^2') s_crit = Float(0.009, input=True, unit='mm') P_f = Property(depends_on='+input') @cached_property def _get_P_f(self): return sqrt(4 * self.A_f * pi) K_b = Property(depends_on='+input') @cached_property def _get_K_b(self): return self.T_max / self.s_crit tau_max = Float(0.0, input=True, unit='MPa') T_max = Property(depends_on='+input', unit='N/mm') @cached_property def _get_T_max(self): return self.tau_max * self.P_f rho = Property(depends_on='+input') @cached_property def _get_rho(self): return self.A_f / (self.A_f + self.A_m) #------------------------------------------------------- # Material model for the matrix #------------------------------------------------------- mats_m = Property(Instance(MATS1DDamageWithFlaw), depends_on='+input') @cached_property def _get_mats_m(self): mats_m = MATS1DDamageWithFlaw(E=self.E_m * self.A_m, flaw_position=self.flaw_position, flaw_radius=self.flaw_radius, reduction_factor=self.reduction_factor, epsilon_0=self.epsilon_0, epsilon_f=self.epsilon_f) return mats_m mats_f = Instance(MATS1DElastic) def _mats_f_default(self): mats_f = MATS1DElastic(E=self.E_f * self.A_f) return mats_f mats_b = Instance(MATS1DEval) def _mats_b_default(self): mats_b = MATS1DElastic(E=self.K_b) mats_b = MATS1DPlastic(E=self.K_b, sigma_y=self.T_max, K_bar=0., H_bar=0.) # plastic function of slip return mats_b mats_fb = Property(Instance(MATS1D5Bond), depends_on='+input') @cached_property def _get_mats_fb(self): # Material model construction return MATS1D5Bond( mats_phase1=MATS1DElastic(E=0), mats_phase2=self.mats_f, mats_ifslip=self.mats_b, mats_ifopen=MATS1DElastic( E=0) # elastic function of open - inactive ) #------------------------------------------------------- # Finite element type #------------------------------------------------------- fets_m = Property(depends_on='+input') @cached_property def _get_fets_m(self): fets_eval = FETS1D2L(mats_eval=self.mats_m) #fets_eval = FETS1D2L3U( mats_eval = self.mats_m ) return fets_eval fets_fb = Property(depends_on='+input') @cached_property def _get_fets_fb(self): return FETS1D52L4ULRH(mats_eval=self.mats_fb) #return FETS1D52L6ULRH( mats_eval = self.mats_fb ) #return FETS1D52L8ULRH( mats_eval = self.mats_fb ) #-------------------------------------------------------------------------------------- # Mesh integrator #-------------------------------------------------------------------------------------- fe_domain_structure = Property(depends_on='+input') @cached_property def _get_fe_domain_structure(self): '''Root of the domain hierarchy ''' elem_length = self.length / float(self.shape) fe_domain = FEDomain() fe_m_level = FERefinementGrid(name='matrix domain', domain=fe_domain, fets_eval=self.fets_m) fe_grid_m = FEGrid(name='matrix grid', coord_max=(self.length, ), shape=(self.shape, ), level=fe_m_level, fets_eval=self.fets_m, geo_transform=self.geo_transform) fe_fb_level = FERefinementGrid(name='fiber bond domain', domain=fe_domain, fets_eval=self.fets_fb) fe_grid_fb = FEGrid(coord_min=(0., length / 5.), coord_max=(length, 0.), shape=(self.shape, 1), level=fe_fb_level, fets_eval=self.fets_fb, geo_transform=self.geo_transform) return fe_domain, fe_grid_m, fe_grid_fb, fe_m_level, fe_fb_level fe_domain = Property def _get_fe_domain(self): return self.fe_domain_structure[0] fe_grid_m = Property def _get_fe_grid_m(self): return self.fe_domain_structure[1] fe_grid_fb = Property def _get_fe_grid_fb(self): return self.fe_domain_structure[2] fe_m_level = Property def _get_fe_m_level(self): return self.fe_domain_structure[3] fe_fb_level = Property def _get_fe_fb_level(self): return self.fe_domain_structure[4] #--------------------------------------------------------------------------- # Load scaling adapted to the elastic and inelastic regime #--------------------------------------------------------------------------- final_displ = Property(depends_on='+input') @cached_property def _get_final_displ(self): damage_onset_displ = self.mats_m.epsilon_0 * self.length return damage_onset_displ / self.elastic_fraction step_size = Property(depends_on='+input') @cached_property def _get_step_size(self): n_steps = self.n_steps return 1.0 / float(n_steps) time_function = Property(depends_on='+input') @cached_property def _get_time_function(self): '''Get the time function so that the elastic regime is skipped in a single step. ''' step_size = self.step_size elastic_value = self.elastic_fraction * 0.98 * self.reduction_factor inelastic_value = 1.0 - elastic_value def ls(t): if t <= step_size: return (elastic_value / step_size) * t else: return elastic_value + (t - step_size) * (inelastic_value) / ( 1 - step_size) return ls def plot_time_function(self, p): '''Plot the time function. ''' n_steps = self.n_steps mats = self.mats step_size = self.step_size ls_t = linspace(0, step_size * n_steps, n_steps + 1) ls_fn = frompyfunc(self.time_function, 1, 1) ls_v = ls_fn(ls_t) p.subplot(321) p.plot(ls_t, ls_v, 'ro-') final_epsilon = self.final_displ / self.length kappa = linspace(mats.epsilon_0, final_epsilon, 10) omega_fn = frompyfunc(lambda kappa: mats._get_omega(None, kappa), 1, 1) omega = omega_fn(kappa) kappa_scaled = (step_size + (1 - step_size) * (kappa - mats.epsilon_0) / (final_epsilon - mats.epsilon_0)) xdata = hstack([array([0.0], dtype=float), kappa_scaled]) ydata = hstack([array([0.0], dtype=float), omega]) p.plot(xdata, ydata, 'g') p.xlabel('regular time [-]') p.ylabel('scaled time [-]') run = Button @on_trait_change('run') def peval(self): '''Evaluation procedure. ''' #mv = MATS1DDamageView( model = mats_eval ) #mv.configure_traits() right_dof_m = self.fe_grid_m[-1, -1].dofs[0, 0, 0] right_dof_fb = self.fe_grid_fb[-1, -1, -1, -1].dofs[0, 0, 0] # Response tracers A = self.A_m + self.A_f self.sig_eps_m = RTraceGraph(name='F_u_m', var_y='F_int', idx_y=right_dof_m, var_x='U_k', idx_x=right_dof_m, transform_y='y / %g' % A) # Response tracers self.sig_eps_f = RTraceGraph(name='F_u_f', var_y='F_int', idx_y=right_dof_fb, var_x='U_k', idx_x=right_dof_fb, transform_y='y / %g' % A) self.eps_m_field = RTraceDomainListField(name='eps_m', position='int_pnts', var='eps_app', warp=False) self.eps_f_field = RTraceDomainListField(name='eps_f', position='int_pnts', var='mats_phase2_eps_app', warp=False) # Response tracers self.sig_m_field = RTraceDomainListField(name='sig_m', position='int_pnts', var='sig_app') self.sig_f_field = RTraceDomainListField(name='sig_f', position='int_pnts', var='mats_phase2_sig_app') self.omega_m_field = RTraceDomainListField(name='omega_m', position='int_pnts', var='omega', warp=False) self.shear_flow_field = RTraceDomainListField(name='shear flow', position='int_pnts', var='shear_flow', warp=False) self.slip_field = RTraceDomainListField(name='slip', position='int_pnts', var='slip', warp=False) avg_processor = None if self.avg_radius > 0.0: n_dofs = self.fe_domain.n_dofs avg_processor = RTUAvg(sd=self.fe_m_level, n_dofs=n_dofs, avg_fn=QuarticAF(radius=self.avg_radius)) ts = TStepper( u_processor=avg_processor, dof_resultants=True, sdomain=self.fe_domain, bcond_list=[ # define the left clamping BCSlice(var='u', value=0., dims=[0], slice=self.fe_grid_fb[0, 0, 0, :]), # BCSlice( var = 'u', value = 0., dims = [0], slice = self.fe_grid_m[ 0, 0 ] ), # loading at the right edge # BCSlice( var = 'f', value = 1, dims = [0], slice = domain[-1, -1, -1, 0], # time_function = ls ), BCSlice(var='u', value=self.final_displ, dims=[0], slice=self.fe_grid_fb[-1, -1, -1, :], time_function=self.time_function), # BCSlice( var = 'u', value = self.final_displ, dims = [0], slice = self.fe_grid_m[-1, -1], # time_function = self.time_function ), # fix horizontal displacement in the top layer # BCSlice( var = 'u', value = 0., dims = [0], slice = domain[:, -1, :, -1] ), # fix the vertical displacement all over the domain BCSlice(var='u', value=0., dims=[1], slice=self.fe_grid_fb[:, :, :, :]), # # Connect bond and matrix domains BCDofGroup(var='u', value=0., dims=[0], get_link_dof_method=self.fe_grid_fb.get_bottom_dofs, get_dof_method=self.fe_grid_m.get_all_dofs, link_coeffs=[1.]) ], rtrace_list=[ self.sig_eps_m, self.sig_eps_f, self.eps_m_field, self.eps_f_field, self.sig_m_field, self.sig_f_field, self.omega_m_field, self.shear_flow_field, self.slip_field, ]) # Add the time-loop control tloop = TLoop(tstepper=ts, KMAX=300, tolerance=1e-5, debug=False, verbose_iteration=True, verbose_time=False, tline=TLine(min=0.0, step=self.step_size, max=1.0)) tloop.on_accept_time_step = self.plot U = tloop.eval() self.sig_eps_f.refresh() max_sig_m = max(self.sig_eps_m.trace.ydata) return array([U[right_dof_m], max_sig_m], dtype='float_') #-------------------------------------------------------------------------------------- # Tracers #-------------------------------------------------------------------------------------- def plot_sig_eps(self, p): p.set_xlabel('control displacement [mm]') p.set_ylabel('stress [MPa]') self.sig_eps_m.refresh() self.sig_eps_m.trace.plot(p, 'o-') self.sig_eps_f.refresh() self.sig_eps_f.trace.plot(p, 'o-') p.plot(self.sig_eps_m.trace.xdata, self.sig_eps_m.trace.ydata + self.sig_eps_f.trace.ydata, 'o-') def plot_eps(self, p): eps_m = self.eps_m_field.subfields[0] xdata = eps_m.vtk_X[:, 0] ydata = eps_m.field_arr[:, 0, 0] idata = argsort(xdata) p.plot(xdata[idata], ydata[idata], 'o-') eps_f = self.eps_f_field.subfields[1] xdata = eps_f.vtk_X[:, 0] ydata = eps_f.field_arr[:, 0, 0] idata = argsort(xdata) p.plot(xdata[idata], ydata[idata], 'o-') p.set_ylim(ymin=0) p.set_xlabel('bar axis [mm]') p.set_ylabel('strain [-]') def plot_omega(self, p): omega_m = self.omega_m_field.subfields[0] xdata = omega_m.vtk_X[:, 0] ydata = omega_m.field_arr[:] idata = argsort(xdata) p.fill(xdata[idata], ydata[idata], facecolor='gray', alpha=0.2) print 'max omega', max(ydata[idata]) p.set_ylim(ymin=0, ymax=1.0) p.set_xlabel('bar axis [mm]') p.set_ylabel('omega [-]') def plot_sig(self, p): sig_m = self.sig_m_field.subfields[0] xdata = sig_m.vtk_X[:, 0] ydata = sig_m.field_arr[:, 0, 0] idata = argsort(xdata) ymax = max(ydata) p.plot(xdata[idata], ydata[idata], 'o-') sig_f = self.sig_f_field.subfields[1] xdata = sig_f.vtk_X[:, 0] ydata = sig_f.field_arr[:, 0, 0] idata = argsort(xdata) p.plot(xdata[idata], ydata[idata], 'o-') xdata = sig_f.vtk_X[:, 0] ydata = sig_f.field_arr[:, 0, 0] + sig_m.field_arr[:, 0, 0] p.plot(xdata[idata], ydata[idata], 'ro-') p.set_ylim(ymin=0) # , ymax = 1.2 * ymax ) p.set_xlabel('bar axis [mm]') p.set_ylabel('stress [MPa]') def plot_shear_flow(self, p): shear_flow = self.shear_flow_field.subfields[1] xdata = shear_flow.vtk_X[:, 0] ydata = shear_flow.field_arr[:, 0] / self.P_f idata = argsort(xdata) ymax = max(ydata) p.plot(xdata[idata], ydata[idata], 'o-') p.set_xlabel('bar axis [mm]') p.set_ylabel('shear flow [N/m]') def plot_slip(self, p): slip = self.slip_field.subfields[1] xdata = slip.vtk_X[:, 0] ydata = slip.field_arr[:, 0] idata = argsort(xdata) ymax = max(ydata) p.plot(xdata[idata], ydata[idata], 'ro-') p.set_xlabel('bar axis [mm]') p.set_ylabel('slip [N/m]') def plot_tracers(self, p=p): p.subplot(221) self.plot_sig_eps(p) p.subplot(223) self.plot_eps(p) p.subplot(224) self.plot_sig(p) #--------------------------------------------------------------- # PLOT OBJECT #------------------------------------------------------------------- figure_ld = Instance(Figure) def _figure_ld_default(self): figure = Figure(facecolor='white') figure.add_axes([0.12, 0.13, 0.85, 0.74]) return figure #--------------------------------------------------------------- # PLOT OBJECT #------------------------------------------------------------------- figure_eps = Instance(Figure) def _figure_eps_default(self): figure = Figure(facecolor='white') figure.add_axes([0.12, 0.13, 0.85, 0.74]) return figure #--------------------------------------------------------------- # PLOT OBJECT #------------------------------------------------------------------- figure_shear_flow = Instance(Figure) def _figure_shear_flow_default(self): figure = Figure(facecolor='white') figure.add_axes([0.12, 0.13, 0.85, 0.74]) return figure #--------------------------------------------------------------- # PLOT OBJECT #------------------------------------------------------------------- figure_sig = Instance(Figure) def _figure_sig_default(self): figure = Figure(facecolor='white') figure.add_axes([0.12, 0.13, 0.85, 0.74]) return figure #--------------------------------------------------------------- # PLOT OBJECT #------------------------------------------------------------------- figure_shear_flow = Instance(Figure) def _figure_shear_flow_default(self): figure = Figure(facecolor='white') figure.add_axes([0.12, 0.13, 0.85, 0.74]) return figure def plot(self): self.figure_ld.clear() ax = self.figure_ld.gca() self.plot_sig_eps(ax) self.figure_eps.clear() ax = self.figure_eps.gca() self.plot_eps(ax) ax2 = ax.twinx() self.plot_omega(ax2) self.figure_sig.clear() ax = self.figure_sig.gca() self.plot_sig(ax) ax2 = ax.twinx() self.plot_omega(ax2) self.figure_shear_flow.clear() ax = self.figure_shear_flow.gca() self.plot_shear_flow(ax) ax2 = ax.twinx() self.plot_slip(ax2) self.data_changed = True def get_sim_outputs(self): ''' Specifies the results and their order returned by the model evaluation. ''' return [ SimOut(name='right end displacement', unit='m'), SimOut(name='peak load', uni='MPa') ] data_changed = Event toolbar = ToolBar(Action(name="Run", tooltip='Start computation', image=ImageResource('kt-start'), action="start_study"), Action(name="Pause", tooltip='Pause computation', image=ImageResource('kt-pause'), action="pause_study"), Action(name="Stop", tooltip='Stop computation', image=ImageResource('kt-stop'), action="stop_study"), image_size=(32, 32), show_tool_names=False, show_divider=True, name='view_toolbar'), traits_view = View(HSplit( VSplit( Item('run', show_label=False), VGroup( Item('shape'), Item('n_steps'), Item('length'), label='parameters', id='crackloc.viewmodel.factor.geometry', dock='tab', scrollable=True, ), VGroup(Item('E_m'), Item('f_m_t'), Item('avg_radius'), Item('h_m'), Item('b_m'), Item('A_m', style='readonly'), Item('mats_m', show_label=False), label='Matrix', dock='tab', id='crackloc.viewmodel.factor.matrix', scrollable=True), VGroup(Item('E_f'), Item('A_f'), Item('mats_f', show_label=False), label='Fiber', dock='tab', id='crackloc.viewmodel.factor.fiber', scrollable=True), VGroup(Group( Item('tau_max'), Item('s_crit'), Item('P_f', style='readonly', show_label=True), Item('K_b', style='readonly', show_label=True), Item('T_max', style='readonly', show_label=True), ), Item('mats_b', show_label=False), label='Bond', dock='tab', id='crackloc.viewmodel.factor.bond', scrollable=True), VGroup(Item('rho', style='readonly', show_label=True), label='Composite', dock='tab', id='crackloc.viewmodel.factor.jcomposite', scrollable=True), id='crackloc.viewmodel.left', label='studied factors', layout='tabbed', dock='tab', ), VSplit( VGroup( Item('figure_ld', editor=MPLFigureEditor(), resizable=True, show_label=False), label='stress-strain', id='crackloc.viewmode.figure_ld_window', dock='tab', ), VGroup( Item('figure_eps', editor=MPLFigureEditor(), resizable=True, show_label=False), label='strains profile', id='crackloc.viewmode.figure_eps_window', dock='tab', ), VGroup( Item('figure_sig', editor=MPLFigureEditor(), resizable=True, show_label=False), label='stress profile', id='crackloc.viewmode.figure_sig_window', dock='tab', ), VGroup( Item('figure_shear_flow', editor=MPLFigureEditor(), resizable=True, show_label=False), label='bond shear and slip profiles', id='crackloc.viewmode.figure_shear_flow_window', dock='tab', ), id='crackloc.viewmodel.right', ), id='crackloc.viewmodel.splitter', ), title='SimVisage Component: Crack localization', id='crackloc.viewmodel', dock='tab', resizable=True, height=0.8, width=0.8, buttons=[OKButton])
class InfoShellMngr( HasTraits ): '''Assessment tool ''' #------------------------------------------ # specify default data input files: #------------------------------------------ # raw input file for thicknesses (and coordinates) # geo_data_file = Str def _geo_data_file_default( self ): return 'input_geo_data.csv' # raw input file for element numbers, coordinates, and stress_resultants # state_data_file = Str def _state_data_file_default( self ): return 'input_state_data.csv' info_shell_uls = Property( Instance( LSTable ), depends_on = 'state_data_file' ) @cached_property def _get_info_shell_uls( self ): return LSTable( geo_data = self.geo_data, state_data = self.state_data, ls = 'ULS' ) info_shell_sls = Property( Instance( LSTable ), depends_on = 'state_data_file' ) @cached_property def _get_info_shell_sls( self ): return LSTable( geo_data = self.geo_data, state_data = self.state_data, ls = 'SLS' ) #------------------------------------------ # read the geometry data from file # (corrds and thickness): #------------------------------------------ def _read_geo_data( self, file_name ): '''to read the stb-thickness save the xls-worksheet to a csv-file using ';' as filed delimiter and ' ' (blank) as text delimiter. ''' # get the column headings defined in the second row # of the csv thickness input file # "Nr.;X;Y;Z;[mm]" # file = open( file_name, 'r' ) first_line = file.readline() second_line = file.readline() column_headings = second_line.split( ';' ) # remove '\n' from last string element in list column_headings[-1] = column_headings[-1][:-1] column_headings_arr = array( column_headings ) elem_no_idx = where( 'Nr.' == column_headings_arr )[0] X_idx = where( 'X' == column_headings_arr )[0] Y_idx = where( 'Y' == column_headings_arr )[0] Z_idx = where( 'Z' == column_headings_arr )[0] thickness_idx = where( '[mm]' == column_headings_arr )[0] # read the float data: # input_arr = loadtxt( file_name, delimiter = ';', skiprows = 2 ) # element number: # elem_no = input_arr[:, elem_no_idx] # coordinates [m]: # X = input_arr[:, X_idx] Y = input_arr[:, Y_idx] Z = input_arr[:, Z_idx] # element thickness [mm]: # thickness = input_arr[:, thickness_idx] return {'elem_no':elem_no, 'X':X, 'Y':Y, 'Z':Z, 'thickness':thickness } # coordinates and element thickness read from file: # geo_data = Property( Dict, depends_on = 'geo_data_file' ) @cached_property def _get_geo_data( self ): return self._read_geo_data( self.geo_data_file ) #------------------------------------------ # read the state data from file # (elem_no, coords, moments and normal forces): #------------------------------------------ def _Xread_state_data( self, file_name ): '''to read the stb-stress_resultants save the xls-worksheet to a csv-file using ';' as filed delimiter and ' ' (blank) as text delimiter. ''' ###################################################### # this method returns only the MAXIMUM VALUES!!! # @todo: dublicate the elem number and coordinates and add also the minimum values ###################################################### # get the column headings defined in the second row # of the csv soliciotations input file # # column_headings = array(["Nr.","Punkt","X","Y","Z","mx","my","mxy","vx","vy","nx","ny","nxy"]) file = open( file_name, 'r' ) lines = file.readlines() column_headings = lines[1].split( ';' ) # remove '\n' from last string element in list column_headings[-1] = column_headings[-1][:-1] column_headings_arr = array( column_headings ) elem_no_idx = where( 'Nr.' == column_headings_arr )[0] X_idx = where( 'X' == column_headings_arr )[0] Y_idx = where( 'Y' == column_headings_arr )[0] Z_idx = where( 'Z' == column_headings_arr )[0] mx_idx = where( 'mx' == column_headings_arr )[0] my_idx = where( 'my' == column_headings_arr )[0] mxy_idx = where( 'mxy' == column_headings_arr )[0] nx_idx = where( 'nx' == column_headings_arr )[0] ny_idx = where( 'ny' == column_headings_arr )[0] nxy_idx = where( 'nxy' == column_headings_arr )[0] # define arrays containing the information from the raw input file # # @todo: check how loadtxt can be used directly # instead of reading lines line by line? # input_arr = loadtxt( file_name , delimiter=';', skiprows = 2 ) # read max-values (=first row of each double-line): # read stress_resultant csv-input file line by line in steps of two # starting in the third line returning an data array. # n_columns = len( lines[2].split( ';' ) ) # auxiliary line in array sliced off in input array data_array = zeros( n_columns ) for n in range( 2, len( lines ), 2 ): line_split = lines[n].split( ';' ) line_array = array( line_split, dtype = float ) data_array = vstack( [ data_array, line_array ] ) input_arr = data_array[1:, :] # element number: # elem_no = input_arr[:, elem_no_idx] # coordinates [m]: # X = input_arr[:, X_idx] Y = input_arr[:, Y_idx] Z = input_arr[:, Z_idx] # moments [kNm/m] # mx = input_arr[:, mx_idx] my = input_arr[:, my_idx] mxy = input_arr[:, mxy_idx] # normal forces [kN/m]: # nx = input_arr[:, nx_idx] ny = input_arr[:, ny_idx] nxy = input_arr[:, nxy_idx] return { 'elem_no':elem_no, 'X':X, 'Y':Y, 'Z':Z, 'mx':mx, 'my':my, 'mxy':mxy, 'nx':nx, 'ny':ny, 'nxy':nxy } def _read_state_data( self, file_name ): '''to read the stb-stress_resultants save the xls-worksheet to a csv-file using ';' as filed delimiter and ' ' (blank) as text delimiter. ''' ###################################################### # this method returns only the MAXIMUM VALUES!!! # @todo: dublicate the elem number and coordinates and add also the minimum values ###################################################### # get the column headings defined in the second row # of the csv solicitations input file # # column_headings = array(["Nr.","Punkt","X","Y","Z","mx","my","mxy","vx","vy","nx","ny","nxy"]) file = open( file_name, 'r' ) lines = file.readlines() column_headings = lines[1].split( ';' ) # remove '\n' from last string element in list column_headings[-1] = column_headings[-1][:-1] column_headings_arr = array( column_headings ) elem_no_idx = where( 'Nr.' == column_headings_arr )[0] X_idx = where( 'X' == column_headings_arr )[0] Y_idx = where( 'Y' == column_headings_arr )[0] Z_idx = where( 'Z' == column_headings_arr )[0] m1_idx = where( 'm1' == column_headings_arr )[0] m2_idx = where( 'm2' == column_headings_arr )[0] n1_idx = where( 'n1' == column_headings_arr )[0] n2_idx = where( 'n2' == column_headings_arr )[0] # define arrays containing the information from the raw input file # # @todo: check how loadtxt can be used directly # instead of reading lines line by line? # input_arr = loadtxt( file_name , delimiter=';', skiprows = 2 ) # read max-values (=first row of each double-line): # read stress_resultant csv-input file line by line in steps of two # starting in the third line returning an data array. # n_columns = len( lines[2].split( ';' ) ) # auxiliary line in array sliced off in input array data_array = zeros( n_columns ) for n in range( 2, len( lines ), 2 ): line_split = lines[n].split( ';' ) line_array = array( line_split, dtype = float ) data_array = vstack( [ data_array, line_array ] ) input_arr = data_array[1:, :] # element number: # elem_no = input_arr[:, elem_no_idx] # coordinates [m]: # X = input_arr[:, X_idx] Y = input_arr[:, Y_idx] Z = input_arr[:, Z_idx] # moments [kNm/m] # mx = input_arr[:, m1_idx] my = input_arr[:, m2_idx] mxy = zeros_like( input_arr[:, m1_idx] ) # normal forces [kN/m]: # nx = input_arr[:, n1_idx] ny = input_arr[:, n2_idx] nxy = zeros_like( input_arr[:, m1_idx] ) return { 'elem_no':elem_no, 'X':X, 'Y':Y, 'Z':Z, 'mx':mx, 'my':my, 'mxy':mxy, 'nx':nx, 'ny':ny, 'nxy':nxy } # ------------------------------------------------------------ # Read state data from file and assign attributes # ------------------------------------------------------------ # coordinates and stress_resultants read from file: # state_data = Property( Dict, depends_on = 'state_data_file' ) @cached_property def _get_state_data( self ): return self._read_state_data( self.state_data_file ) # ------------------------------------------------------------ # check input files for consistency # ------------------------------------------------------------ @on_trait_change( 'geo_data_file, state_data_file' ) def _check_input_files_for_consistency( self ): '''check if the element order of the thickness input file is identical to the order in the stress_resultant input file ''' if not all( self.geo_data['X'] ) == all( self.state_data['X'] ) or \ not all( self.geo_data['Y'] ) == all( state_data['Y'] ) or \ not all( self.geo_data['Z'] ) == all( state_data['Z'] ): raise ValueError, 'coordinates in file % s and file % s are not identical. Check input files for consistency ! ' \ % ( self.geo_data_file, self.state_data_file ) else: print ' *** input files checked for consistency ( OK ) *** ' return True # ------------------------------------------------------------ # View # ------------------------------------------------------------ traits_view = View( VGroup( Item( 'state_data_file', label = 'Evaluated input file for stress_resultants ', style = 'readonly', emphasized = True ), Item( 'geo_data_file', label = 'Evaluated input file for thicknesses ', style = 'readonly', emphasized = True ), Tabbed( Group( Item( 'info_shell_sls@', show_label = False ), label = 'SLS' ), Group( Item( 'info_shell_uls@', show_label = False ), label = 'ULS' ), ), ), resizable = True, scrollable = True, height = 1000, width = 1100 )
class CBView(ModelView): def __init__(self, **kw): super(CBView, self).__init__(**kw) self.on_trait_change(self.refresh, 'model.+params') self.refresh() model = Instance(Model) figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor='white') return figure figure2 = Instance(Figure) def _figure2_default(self): figure = Figure(facecolor='white') return figure data_changed = Event def plot(self, fig, fig2): figure = fig figure.clear() axes = figure.gca() # plot PDF axes.plot(self.model.w, self.model.model_rand, lw=2.0, color='blue', \ label='model') axes.plot(self.model.w, self.model.interpolate_experiment(self.model.w), lw=1.0, color='black', \ label='experiment') axes.legend(loc='best') # figure2 = fig2 # figure2.clear() # axes = figure2.gca() # # plot PDF # axes.plot(self.model.w2, self.model.model_extrapolate, lw=2.0, color='red', \ # label='model') # axes.legend() def refresh(self): self.plot(self.figure, self.figure2) self.data_changed = True traits_view = View(HSplit(VGroup( Group( Item('model.tau_scale'), Item('model.tau_shape'), Item('model.tau_loc'), Item('model.m'), Item('model.sV0'), Item('model.Ef'), Item('model.w_min'), Item('model.w_max'), Item('model.w_pts'), Item('model.n_int'), Item('model.w2_min'), Item('model.w2_max'), Item('model.w2_pts'), Item('model.sigmamu'), ), id='pdistrib.distr_type.pltctrls', label='Distribution parameters', scrollable=True, ), Tabbed( Group( Item('figure', editor=MPLFigureEditor(), show_label=False, resizable=True), scrollable=True, label='Plot', ), label='Plot', id='pdistrib.figure.params', dock='tab', ), Tabbed( Group( Item('figure2', editor=MPLFigureEditor(), show_label=False, resizable=True), scrollable=True, label='Plot', ), label='Plot', id='pdistrib.figure2', dock='tab', ), dock='tab', id='pdistrib.figure.view'), id='pdistrib.view', dock='tab', title='Statistical distribution', buttons=[OKButton, CancelButton], scrollable=True, resizable=True, width=600, height=400)
class ExpST(ExType): '''Experiment: Slab Test ''' # label = Str('slab test') implements(IExType) #-------------------------------------------------------------------- # register a change of the traits with metadata 'input' #-------------------------------------------------------------------- input_change = Event @on_trait_change('+input, ccs.input_change, +ironing_param') def _set_input_change(self): self.input_change = True #-------------------------------------------------------------------------------- # specify inputs: #-------------------------------------------------------------------------------- edge_length = Float(1.25, unit='m', input=True, table_field=True, auto_set=False, enter_set=True) thickness = Float(0.06, unit='m', input=True, table_field=True, auto_set=False, enter_set=True) # age of the concrete at the time of testing age = Int(28, unit='d', input=True, table_field=True, auto_set=False, enter_set=True) loading_rate = Float(2.0, unit='mm/min', input=True, table_field=True, auto_set=False, enter_set=True) #-------------------------------------------------------------------------- # composite cross section #-------------------------------------------------------------------------- ccs = Instance(CompositeCrossSection) def _ccs_default(self): '''default settings correspond to setup '7u_MAG-07-03_PZ-0708-1' ''' fabric_layout_key = '2D-05-11' # fabric_layout_key = 'MAG-07-03' # fabric_layout_key = '2D-02-06a' # concrete_mixture_key = 'PZ-0708-1' # concrete_mixture_key = 'FIL-10-09' # concrete_mixture_key = 'barrelshell' concrete_mixture_key = 'PZ-0708-1' # orientation_fn_key = 'all0' orientation_fn_key = '90_0' n_layers = 2 s_tex_z = 0.015 / (n_layers + 1) ccs = CompositeCrossSection ( fabric_layup_list=[ plain_concrete(0.035), # plain_concrete(s_tex_z * 0.5), FabricLayUp ( n_layers=n_layers, orientation_fn_key=orientation_fn_key, s_tex_z=s_tex_z, fabric_layout_key=fabric_layout_key ), # plain_concrete(s_tex_z * 0.5) plain_concrete(0.5) ], concrete_mixture_key=concrete_mixture_key ) return ccs #-------------------------------------------------------------------------- # Get properties of the composite #-------------------------------------------------------------------------- # E-modulus of the composite at the time of testing E_c = Property(Float, unit='MPa', depends_on='input_change', table_field=True) def _get_E_c(self): return self.ccs.get_E_c_time(self.age) # E-modulus of the composite after 28 days E_c28 = DelegatesTo('ccs', listenable=False) # reinforcement ration of the composite rho_c = DelegatesTo('ccs', listenable=False) #-------------------------------------------------------------------------------- # define processing #-------------------------------------------------------------------------------- # put this into the ironing procedure processor # jump_rtol = Float(0.1, auto_set=False, enter_set=True, ironing_param=True) data_array_ironed = Property(Array(float), depends_on='data_array, +ironing_param, +axis_selection') @cached_property def _get_data_array_ironed(self): '''remove the jumps in the displacement curves due to resetting the displacement gauges. ''' print '*** curve ironing activated ***' # each column from the data array corresponds to a measured parameter # e.g. displacement at a given point as function of time u = f(t)) # data_array_ironed = copy(self.data_array) for idx in range(self.data_array.shape[1]): # use ironing method only for columns of the displacement gauges. # if self.names_and_units[0][ idx ] != 'Kraft' and \ self.names_and_units[0][ idx ] != 'Bezugskanal' and \ self.names_and_units[0][ idx ] != 'Weg': # 1d-array corresponding to column in data_array data_arr = copy(data_array_ironed[:, idx]) # get the difference between each point and its successor jump_arr = data_arr[1:] - data_arr[0:-1] # get the range of the measured data data_arr_range = max(data_arr) - min(data_arr) # determine the relevant criteria for a jump # based on the data range and the specified tolerances: jump_crit = self.jump_rtol * data_arr_range # get the indexes in 'data_column' after which a # jump exceeds the defined tolerance criteria jump_idx = where(fabs(jump_arr) > jump_crit)[0] print 'number of jumps removed in data_arr_ironed for', self.names_and_units[0][ idx ], ': ', jump_idx.shape[0] # glue the curve at each jump together for jidx in jump_idx: # get the offsets at each jump of the curve shift = data_arr[jidx + 1] - data_arr[jidx] # shift all succeeding values by the calculated offset data_arr[jidx + 1:] -= shift data_array_ironed[:, idx] = data_arr[:] return data_array_ironed @on_trait_change('+ironing_param') def process_source_data(self): '''read in the measured data from file and assign attributes after array processing. NOTE: if center displacement gauge ('WA_M') is missing the measured displacement of the cylinder ('Weg') is used instead. A minor mistake is made depending on how much time passes before the cylinder has contact with the slab. ''' print '*** process source data ***' self._read_data_array() # curve ironing: # self.processed_data_array = self.data_array_ironed # set attributes: # self._set_array_attribs() if 'WA_M' not in self.factor_list: print '*** NOTE: Displacement gauge at center ("WA_M") missing. Cylinder displacement ("Weg") is used instead! ***' self.WA_M = self.Weg #-------------------------------------------------------------------------------- # plot templates #-------------------------------------------------------------------------------- plot_templates = {'force / deflection (all)' : '_plot_force_deflection', # 'force / average deflection (c; ce; e) interpolated' : '_plot_force_deflection_avg_interpolated', # 'force / deflection (center)' : '_plot_force_center_deflection', # 'smoothed force / deflection (center)' : '_plot_force_center_deflection_smoothed', # 'force / deflection (edges)' : '_plot_force_edge_deflection', # 'force / deflection (center-edges)' : '_plot_force_center_edge_deflection', # 'force / average deflection (edges)' : '_plot_force_edge_deflection_avg', # 'force / average deflection (center-edges)' : '_plot_force_center_edge_deflection_avg', # 'force / average deflection (c; ce; e)' : '_plot_force_deflection_avg', # 'force / deflection (center) interpolated' : '_plot_force_center_deflection_interpolated', # 'force / deflection (corner)' : '_plot_force_corner_deflection', # 'edge_deflection_avg (front/back) / edge_deflection_avg (left/right)' : '_plot_edge_deflection_edge_deflection_avg', } default_plot_template = 'force / deflection (center)' n_fit_window_fraction = Float(0.1) # get only the ascending branch of the response curve # max_force_idx = Property(Int) def _get_max_force_idx(self): '''get the index of the maximum force''' return argmax(-self.Kraft) f_asc = Property(Array) def _get_f_asc(self): '''get only the ascending branch of the response curve''' return -self.Kraft[:self.max_force_idx + 1] w_asc = Property(Array) def _get_w_asc(self): '''get only the ascending branch of the response curve''' return -self.WA_M[:self.max_force_idx + 1] n_points = Property(Int) def _get_n_points(self): return int(self.n_fit_window_fraction * len(self.w_asc)) f_smooth = Property() def _get_f_smooth(self): return smooth(self.f_asc, self.n_points, 'flat') w_smooth = Property() def _get_w_smooth(self): return smooth(self.w_asc, self.n_points, 'flat') def _plot_force_deflection(self, axes, offset_w=0., color='blue', linewidth=1.5, linestyle='-'): '''plot the F-w-diagramm for all displacement gauges including maschine displacement ''' xkey = 'deflection [mm]' ykey = 'force [kN]' max_force_idx = self.max_force_idx # max_force_idx = -2 f_asc = -self.Kraft[:max_force_idx + 1] print 'self.factor_list', self.factor_list header_string = '' for i in self.factor_list[2:]: header_string = header_string + i + '; ' T_arr = -getattr(self, i) T_asc = T_arr[:max_force_idx + 1] axes.plot(T_asc, f_asc, label=i) axes.legend() img_dir = os.path.join(simdb.exdata_dir, 'img_dir') # check if directory exist otherwise create # if os.path.isdir(img_dir) == False: os.makedirs(img_dir) test_series_dir = os.path.join(img_dir, 'slab_test_astark') # check if directory exist otherwise create # if os.path.isdir(test_series_dir) == False: os.makedirs(test_series_dir) out_file = os.path.join(test_series_dir, self.key) np.savetxt(out_file, self.processed_data_array, delimiter=';') # workaround for old numpy.savetxt version: f = open(out_file, 'r') temp = f.read() f.close() f = open(out_file, 'w') f.write(header_string) f.write(temp) f.close() def _plot_force_center_deflection(self, axes, offset_w=0., color='blue', linewidth=1.5, linestyle='-'): '''plot the F-w-diagramm for the center (c) deflection ''' xkey = 'deflection [mm]' ykey = 'force [kN]' xdata = -self.WA_M ydata = -self.Kraft xdata += offset_w # axes.set_xlabel('%s' % (xkey,)) # axes.set_ylabel('%s' % (ykey,)) axes.plot(xdata, ydata, color=color, linewidth=linewidth, linestyle=linestyle) def _plot_force_corner_deflection(self, axes): '''plot the F-w-diagramm for the corner deflection (at the center of one of the supports) ''' xkey = 'deflection [mm]' ykey = 'force [kN]' xdata = -self.WA_Eck ydata = -self.Kraft # axes.set_xlabel('%s' % (xkey,)) # axes.set_ylabel('%s' % (ykey,)) axes.plot(xdata, ydata # color = c, linewidth = w, linestyle = s ) def _plot_force_center_deflection_smoothed(self, axes): '''plot the F-w-diagramm for the center (c) deflection (smoothed curves) ''' axes.plot(self.w_smooth, self.f_smooth, color='blue', linewidth=1) # secant_stiffness_w10 = (f_smooth[10] - f_smooth[0]) / (w_smooth[10] - w_smooth[0]) # w0_lin = array([0.0, w_smooth[10] ], dtype = 'float_') # f0_lin = array([0.0, w_smooth[10] * secant_stiffness_w10 ], dtype = 'float_') # axes.plot( w0_lin, f0_lin, color = 'black' ) def _plot_force_center_deflection_interpolated(self, axes, linestyle='-', linewidth=1.5, plot_elastic_stiffness=True): '''plot the F-w-diagramm for the center (c) deflection (interpolated initial stiffness) ''' # get the index of the maximum stress max_force_idx = argmax(-self.Kraft) # get only the ascending branch of the response curve f_asc = -self.Kraft[:max_force_idx + 1] w_m = -self.WA_M[:max_force_idx + 1] # w_m -= 0.17 # axes.plot(w_m, f_asc, color = 'blue', linewidth = 1) # move the starting point of the center deflection curve to the point where the force starts # (remove offset in measured displacement where there is still no force measured) # idx_0 = np.where(f_asc > 0.0)[0][0] f_asc_cut = np.hstack([f_asc[ idx_0: ]]) w_m_cut = np.hstack([w_m[ idx_0: ]]) - w_m[ idx_0 ] # print 'f_asc_cut.shape', f_asc_cut.shape # fw_arr = np.hstack([f_asc_cut[:, None], w_m_cut[:, None]]) # print 'fw_arr.shape', fw_arr.shape # np.savetxt('ST-6c-2cm-TU_bs2_f-w_asc.csv', fw_arr, delimiter=';') axes.plot(w_m_cut, f_asc_cut, color='k', linewidth=linewidth, linestyle=linestyle) # composite E-modulus # E_c = self.E_c print 'E_c', E_c if self.thickness == 0.02 and self.edge_length == 0.80 and plot_elastic_stiffness == True: K_linear = E_c / 24900. * 1.056 # [MN/m]=[kN/mm] bending stiffness with respect to center force max_f = f_asc_cut[-1] w_linear = np.array([0., max_f / K_linear]) f_linear = np.array([0., max_f]) axes.plot(w_linear, f_linear, linewidth=linewidth, linestyle='--', color='k') if self.thickness == 0.03 and self.edge_length == 1.25 and plot_elastic_stiffness == True: K_linear = E_c / 24900. * 1.267 # [MN/m]=[kN/mm] bending stiffness with respect to center force max_f = f_asc_cut[-1] w_linear = np.array([0., max_f / K_linear]) f_linear = np.array([0., max_f]) axes.plot(w_linear, f_linear, linewidth=linewidth, linestyle='--', color='k') if self.thickness == 0.06 and self.edge_length == 1.25 and plot_elastic_stiffness == True: K_linear = E_c / 24900. * 10.14 # [MN/m]=[kN/mm] bending stiffness with respect to center force max_f = f_asc_cut[-1] w_linear = np.array([0., max_f / K_linear]) f_linear = np.array([0., max_f]) axes.plot(w_linear, f_linear, linewidth=linewidth, linestyle='--', color='k') def _plot_force_edge_deflection(self, axes): '''plot the F-w-diagramm for the edge (e) deflections ''' max_force_idx = self.max_force_idx f_asc = self.f_asc w_v_asc = -self.WA_V[:max_force_idx + 1] w_h_asc = -self.WA_H[:max_force_idx + 1] w_l_asc = -self.WA_L[:max_force_idx + 1] w_r_asc = -self.WA_R[:max_force_idx + 1] axes.plot(w_v_asc, f_asc, color='blue', linewidth=1) axes.plot(w_h_asc, f_asc, color='blue', linewidth=1) axes.plot(w_l_asc, f_asc, color='green', linewidth=1) axes.plot(w_r_asc, f_asc, color='green', linewidth=1) def _plot_force_edge_deflection_avg(self, axes): '''plot the average F-w-diagramm for the edge (e) deflections ''' max_force_idx = self.max_force_idx f_asc = self.f_asc w_v_asc = -self.WA_V[:max_force_idx + 1] w_h_asc = -self.WA_H[:max_force_idx + 1] w_l_asc = -self.WA_L[:max_force_idx + 1] w_r_asc = -self.WA_R[:max_force_idx + 1] # get the average displacement values of the corresponding displacement gauges w_vh_asc = (w_v_asc + w_h_asc) / 2 w_lr_asc = (w_l_asc + w_r_asc) / 2 axes.plot(w_vh_asc, f_asc, color='blue', linewidth=1, label='w_vh') axes.plot(w_lr_asc, f_asc, color='blue', linewidth=1, label='w_lr') axes.legend() def _plot_edge_deflection_edge_deflection_avg(self, axes): '''plot the average edge (e) deflections for the front/back and left/right ''' max_force_idx = self.max_force_idx w_v_asc = -self.WA_V[:max_force_idx + 1] w_h_asc = -self.WA_H[:max_force_idx + 1] w_l_asc = -self.WA_L[:max_force_idx + 1] w_r_asc = -self.WA_R[:max_force_idx + 1] # get the average displacement values of the corresponding displacement gauges w_vh_asc = (w_v_asc + w_h_asc) / 2 w_lr_asc = (w_l_asc + w_r_asc) / 2 axes.plot(w_vh_asc, w_lr_asc, color='blue', linewidth=1, label='w_vh / w_lr') axes.plot(np.array([0, w_vh_asc[-1]]), np.array([0, w_vh_asc[-1]]), color='k', linewidth=1, linestyle='-') axes.legend() def _plot_force_center_edge_deflection(self, axes): '''plot the F-w-diagramm for the center-edge (ce) deflections ''' max_force_idx = argmax(-self.Kraft) # get only the ascending branch of the response curve f_asc = -self.Kraft[:max_force_idx + 1] w_ml_asc = -self.WA_ML[:max_force_idx + 1] w_mr_asc = -self.WA_MR[:max_force_idx + 1] axes.plot(w_ml_asc, f_asc, color='blue', linewidth=1, label='w_ml') axes.plot(w_mr_asc, f_asc, color='blue', linewidth=1, label='w_mr') axes.legend() def _plot_force_center_edge_deflection_avg(self, axes): '''plot the average F-w-diagramm for the center-edge (ce) deflections ''' # get the index of the maximum stress max_force_idx = argmax(-self.Kraft) # get only the ascending branch of the response curve f_asc = -self.Kraft[:max_force_idx + 1] w_ml_asc = -self.WA_ML[:max_force_idx + 1] w_mr_asc = -self.WA_MR[:max_force_idx + 1] # get the average displacement values of the corresponding displacement gauges w_mlmr_asc = (w_ml_asc + w_mr_asc) / 2 axes.plot(w_mlmr_asc, f_asc, color='blue', linewidth=1) def _plot_force_deflection_avg(self, axes): '''plot the average F-w-diagramms for the center(c), center-edge (ce) and edge(vh) and edge (lr) deflections ''' # get the index of the maximum stress max_force_idx = argmax(-self.Kraft) # get only the ascending branch of the response curve f_asc = -self.Kraft[:max_force_idx + 1] w_m = -self.WA_M[:max_force_idx + 1] axes.plot(w_m, f_asc, color='blue', linewidth=1) # ## center-edge deflection (ce) w_ml_asc = -self.WA_ML[:max_force_idx + 1] w_mr_asc = -self.WA_MR[:max_force_idx + 1] # get the average displacement values of the corresponding displacement gauges w_mlmr_asc = (w_ml_asc + w_mr_asc) / 2 axes.plot(w_mlmr_asc, f_asc, color='red', linewidth=1) # ## edge deflections (e) w_v_asc = -self.WA_V[:max_force_idx + 1] w_h_asc = -self.WA_H[:max_force_idx + 1] w_l_asc = -self.WA_L[:max_force_idx + 1] w_r_asc = -self.WA_R[:max_force_idx + 1] # get the average displacement values of the corresponding displacement gauges w_vh_asc = (w_v_asc + w_h_asc) / 2 w_lr_asc = (w_l_asc + w_r_asc) / 2 axes.plot(w_vh_asc, f_asc, color='green', linewidth=1, label='w_vh') axes.plot(w_lr_asc, f_asc, color='blue', linewidth=1, label='w_lr') # # set axis-labels # xkey = 'deflection [mm]' # ykey = 'force [kN]' # axes.set_xlabel('%s' % (xkey,)) # axes.set_ylabel('%s' % (ykey,)) def _plot_force_deflection_avg_interpolated(self, axes, linewidth=1): '''plot the average F-w-diagrams for the center(c), center-edge (ce) and edge(vh) and edge (lr) deflections NOTE: center deflection curve is cut at its starting point in order to remove offset in the dispacement meassurement ''' # get the index of the maximum stress max_force_idx = argmax(-self.Kraft) # get only the ascending branch of the response curve f_asc = -self.Kraft[:max_force_idx + 1] w_m = -self.WA_M[:max_force_idx + 1] # w_m -= 0.17 # axes.plot(w_m, f_asc, color = 'blue', linewidth = 1) # move the starting point of the center deflection curve to the point where the force starts # (remove offset in measured displacement where there is still no force measured) # idx_0 = np.where(f_asc > 0.05)[0][0] f_asc_cut = f_asc[ idx_0: ] w_m_cut = w_m[ idx_0: ] - w_m[ idx_0 ] axes.plot(w_m_cut, f_asc_cut, color='k', linewidth=linewidth) # plot machine displacement (hydraulic cylinder) # # Weg_asc = -self.Weg[ :max_force_idx + 1 ] # axes.plot(Weg_asc, f_asc, color='k', linewidth=1.5) # ## center-edge deflection (ce) w_ml_asc = -self.WA_ML[:max_force_idx + 1] w_mr_asc = -self.WA_MR[:max_force_idx + 1] # get the average displacement values of the corresponding displacement gauges w_mlmr_asc = (w_ml_asc + w_mr_asc) / 2 # axes.plot(w_mlmr_asc, f_asc, color='red', linewidth=1) axes.plot(w_ml_asc, f_asc, color='k', linewidth=linewidth) axes.plot(w_mr_asc, f_asc, color='k', linewidth=linewidth) # ## edge deflections (e) w_v_asc = -self.WA_V[:max_force_idx + 1] w_h_asc = -self.WA_H[:max_force_idx + 1] w_l_asc = -self.WA_L[:max_force_idx + 1] w_r_asc = -self.WA_R[:max_force_idx + 1] axes.plot(w_v_asc, f_asc, color='grey', linewidth=linewidth) axes.plot(w_h_asc, f_asc, color='grey', linewidth=linewidth) axes.plot(w_l_asc, f_asc, color='k', linewidth=linewidth) axes.plot(w_r_asc, f_asc, color='k', linewidth=linewidth) # get the average displacement values of the corresponding displacement gauges # w_vh_asc = (w_v_asc + w_h_asc) / 2 # w_lr_asc = (w_l_asc + w_r_asc) / 2 # axes.plot(w_vh_asc, f_asc, color='green', linewidth=1, label='w_vh') # axes.plot(w_lr_asc, f_asc, color='blue', linewidth=1, label='w_lr') # save 'F-w-arr_m-mlmr-vh-lr' in directory "/simdb/simdata/exp_st" # simdata_dir = os.path.join(simdb.simdata_dir, 'exp_st') # if os.path.isdir(simdata_dir) == False: # os.makedirs(simdata_dir) # filename = os.path.join(simdata_dir, 'F-w-arr_m-mlmr-vh-lr_' + self.key + '.csv') # Fw_m_mlmr_vh_lr_arr = np.hstack([f_asc[:, None], w_m[:, None] - w_m[ idx_0 ], w_mlmr_asc[:, None], w_vh_asc[:, None], w_lr_asc[:, None]]) # print 'Fw_m_mlmr_vh_lr_arr' # np.savetxt(filename, Fw_m_mlmr_vh_lr_arr, delimiter=';') # print 'F-w-curves for center, middle, edges saved to file %s' % (filename) #-------------------------------------------------------------------------------- # view #-------------------------------------------------------------------------------- traits_view = View(VGroup( Group( Item('jump_rtol', format_str="%.4f"), label='curve_ironing' ), Group( Item('thickness', format_str="%.3f"), Item('edge_length', format_str="%.3f"), label='geometry' ), Group( Item('loading_rate'), Item('age'), label='loading rate and age' ), Group( Item('E_c', show_label=True, style='readonly', format_str="%.0f"), Item('ccs@', show_label=False), label='composite cross section' ) ), scrollable=True, resizable=True, height=0.8, width=0.6 )
class ExpEM(ExType): '''Experiment: Elastic Modulus Test ''' # label = Str('three point bending test') implements(IExType) file_ext = 'TRA' #-------------------------------------------------------------------- # register a change of the traits with metadata 'input' #-------------------------------------------------------------------- input_change = Event @on_trait_change('+input, ccs.input_change, +ironing_param') def _set_input_change(self): self.input_change = True #-------------------------------------------------------------------------------- # specify inputs: #-------------------------------------------------------------------------------- edge_length = Float(0.06, unit='m', input=True, table_field=True, auto_set=False, enter_set=True) height = Float(0.12, unit='m', input=True, table_field=True, auto_set=False, enter_set=True) gauge_length = Float(0.10, unit='m', input=True, table_field=True, auto_set=False, enter_set=True) # age of the concrete at the time of testing age = Int(39, unit='d', input=True, table_field=True, auto_set=False, enter_set=True) loading_rate = Float(0.6, unit='MPa/s', input=True, table_field=True, auto_set=False, enter_set=True) #-------------------------------------------------------------------------- # composite cross section #-------------------------------------------------------------------------- ccs = Instance(CompositeCrossSection) def _ccs_default(self): '''default settings correspond to setup '7u_MAG-07-03_PZ-0708-1' ''' # fabric_layout_key = 'MAG-07-03' # fabric_layout_key = '2D-02-06a' fabric_layout_key = '2D-05-11' # concrete_mixture_key = 'PZ-0708-1' concrete_mixture_key = 'FIL-10-09' orientation_fn_key = 'all0' # orientation_fn_key = 'all90' # orientation_fn_key = '90_0' n_layers = 12 s_tex_z = 0.060 / (n_layers + 1) ccs = CompositeCrossSection(fabric_layup_list=[ plain_concrete(s_tex_z * 0.5), FabricLayUp(n_layers=n_layers, orientation_fn_key=orientation_fn_key, s_tex_z=s_tex_z, fabric_layout_key=fabric_layout_key), plain_concrete(s_tex_z * 0.5) ], concrete_mixture_key=concrete_mixture_key) return ccs #-------------------------------------------------------------------------- # Get properties of the composite #-------------------------------------------------------------------------- # E-modulus of the composite at the time of testing E_c = Property(Float, unit='MPa', depends_on='input_change', table_field=True) def _get_E_c(self): return self.ccs.get_E_c_time(self.age) # E-modulus of the composite after 28 days E_c28 = DelegatesTo('ccs', listenable=False) # reinforcement ration of the composite rho_c = DelegatesTo('ccs', listenable=False) #-------------------------------------------------------------------------------- # define processing #-------------------------------------------------------------------------------- def _read_data_array(self): ''' Read the experiment data. ''' print 'READ FILE' _data_array = np.loadtxt(self.data_file, delimiter=';', skiprows=2, usecols=(4, 5, 10, 17, 20)) self.data_array = _data_array names_and_units = Property @cached_property def _get_names_and_units(self): ''' Set the names and units of the measured data. ''' names = ['delta_u1', 'delta_u2', 'w', 'F', 'time'] units = ['mm', 'mm', 'mm', 'kN', 's'] return names, units #0#"Arbeit"; #1#"Dehn. abs"; #2#"Dehn. abs (2. Kanal)"; #3#"Dehnung"; #4#"Dehnung (1. Kanal)"; #5#"Dehnung (2. Kanal)"; #6#"Dehnung nominell"; #7#"DeltaE"; #8#"E1 korr"; #9#"E2 korr"; #10#"Kolbenweg"; #11#"Kolbenweg abs."; #12#"Lastrahmen"; #13#"LE-Kanal"; #14#"PrXXXfzeit"; #15#"Querdehnung"; #16#"S korr"; #17#"Standardkraft"; #18#"Vorlaufzeit"; #19#"Weg"; #20#"Zeit"; #21#"Zyklus" # #"Nm"; #"mm"; #"mm"; #"mm"; #"mm"; #"mm"; #"mm"; #"%"; #"mm"; #" "; #"mm"; #"mm"; #" "; #"mm"; #"s"; #"mm"; #" "; #"N"; #"s"; #"mm"; #"s"; #" " #-------------------------------------------------------------------------------- # plot templates #-------------------------------------------------------------------------------- plot_templates = { 'force / displacement': '_plot_force_displacement', 'stress / strain': '_plot_stress_strain', 'stress / time': '_plot_stress_time', } default_plot_template = 'force / displacement' def _plot_force_displacement(self, axes): xkey = 'deflection [mm]' ykey = 'force [kN]' xdata = self.w ydata = self.F / 1000. # convert from [N] to [kN] axes.set_xlabel('%s' % (xkey, )) axes.set_ylabel('%s' % (ykey, )) axes.plot(xdata, ydata # color = c, linewidth = w, linestyle = s ) def _plot_stress_strain(self, axes): sig = (self.F / 1000000.) / (self.edge_length**2 ) # convert from [N] to [MN] eps1 = (self.delta_u1 / 1000.) / self.gauge_length eps2 = (self.delta_u2 / 1000.) / self.gauge_length eps_m = (eps1 + eps2) / 2. axes.plot(eps_m, sig, color='blue', linewidth=2) def _plot_stress_time(self, axes): sig = (self.F / 1000000.) / (self.edge_length**2 ) # convert from [N] to [MN] axes.plot(self.time, sig, color='blue', linewidth=2) def _plot_displ_time(self, axes): axes.plot(self.time, self.displ, color='blue', linewidth=2) #-------------------------------------------------------------------------------- # view #-------------------------------------------------------------------------------- traits_view = View(VGroup( Group(Item('edge_length', format_str="%.3f"), Item('height', format_str="%.3f"), Item('gauge_length', format_str="%.3f"), label='geometry'), Group(Item('loading_rate'), Item('age'), label='loading rate and age'), Group(Item('E_c', show_label=True, style='readonly', format_str="%.0f"), Item('ccs@', show_label=False), label='composite cross section')), scrollable=True, resizable=True, height=0.8, width=0.6)
class ECBCrossSection(ECBCrossSectionState): '''Cross section characteristics needed for tensile specimens ''' matrix_cs = Instance(ECBMatrixCrossSection) def _matrix_cs_default(self): return ECBMatrixCrossSection() reinf = List(ECBReinfComponent) '''Components of the cross section including the matrix and reinforcement. ''' matrix_cs_with_state = Property(depends_on='matrix_cs') @cached_property def _get_matrix_cs_with_state(self): self.matrix_cs.state = self return self.matrix_cs reinf_components_with_state = Property(depends_on='reinf') '''Components linked to the strain state of the cross section ''' @cached_property def _get_reinf_components_with_state(self): for r in self.reinf: r.state = self r.matrix_cs = self.matrix_cs return self.reinf height = DelegatesTo('matrix_cs') unit_conversion_factor = Constant(1000.0) '''Convert the MN to kN ''' #=========================================================================== # State management #=========================================================================== changed = Event '''Notifier of a changed in some component of a cross section ''' @on_trait_change('+eps_input') def _notify_eps_change(self): self.changed = True self.matrix_cs.eps_changed = True for c in self.reinf: c.eps_changed = True #=========================================================================== # Cross-sectional stress resultants #=========================================================================== N = Property(depends_on='changed') '''Get the resulting normal force. ''' @cached_property def _get_N(self): N_matrix = self.matrix_cs_with_state.N return N_matrix + np.sum([c.N for c in self.reinf_components_with_state]) M = Property(depends_on='changed') '''Get the resulting moment. ''' @cached_property def _get_M(self): M_matrix = self.matrix_cs_with_state.M M = M_matrix + np.sum([c.M for c in self.reinf_components_with_state]) return M - self.N * self.height / 2. figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor='white') figure.add_axes([0.08, 0.13, 0.85, 0.74]) return figure data_changed = Event replot = Button def _replot_fired(self): self.figure.clear() ax = self.figure.add_subplot(2, 2, 1) self.plot_eps(ax) ax = self.figure.add_subplot(2, 2, 2) self.plot_sig(ax) ax = self.figure.add_subplot(2, 2, 3) self.cc_law.plot(ax) ax = self.figure.add_subplot(2, 2, 4) self.ecb_law.plot(ax) self.data_changed = True def plot_eps(self, ax): # ax = self.figure.gca() d = self.thickness # eps ti ax.plot([-self.eps_lo, -self.eps_up], [0, self.thickness], color='black') ax.hlines(self.zz_ti_arr, [0], -self.eps_ti_arr, lw=4, color='red') # eps cj ec = np.hstack([self.eps_cj_arr] + [0, 0]) zz = np.hstack([self.zz_cj_arr] + [0, self.thickness ]) ax.fill(-ec, zz, color='blue') # reinforcement layers eps_range = np.array([max(0.0, self.eps_lo), min(0.0, self.eps_up)], dtype='float') z_ti_arr = np.ones_like(eps_range)[:, None] * self.z_ti_arr[None, :] ax.plot(-eps_range, z_ti_arr, 'k--', color='black') # neutral axis ax.plot(-eps_range, [d, d], 'k--', color='green', lw=2) ax.spines['left'].set_position('zero') ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.spines['left'].set_smart_bounds(True) ax.spines['bottom'].set_smart_bounds(True) ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') def plot_sig(self, ax): d = self.thickness # f ti ax.hlines(self.zz_ti_arr, [0], -self.f_ti_arr, lw=4, color='red') # f cj f_c = np.hstack([self.f_cj_arr] + [0, 0]) zz = np.hstack([self.zz_cj_arr] + [0, self.thickness ]) ax.fill(-f_c, zz, color='blue') f_range = np.array([np.max(self.f_ti_arr), np.min(f_c)], dtype='float_') # neutral axis ax.plot(-f_range, [d, d], 'k--', color='green', lw=2) ax.spines['left'].set_position('zero') ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.spines['left'].set_smart_bounds(True) ax.spines['bottom'].set_smart_bounds(True) ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') view = View(HSplit(Group( HGroup( Group(Item('thickness', springy=True), Item('width'), Item('n_layers'), Item('n_rovings'), Item('A_roving'), label='Geometry', springy=True ), Group(Item('eps_up', label='Upper strain', springy=True), Item('eps_lo', label='Lower strain'), label='Strain', springy=True ), springy=True, ), HGroup( Group(VGroup( Item('cc_law_type', show_label=False, springy=True), Item('cc_law', label='Edit', show_label=False, springy=True), Item('show_cc_law', label='Show', show_label=False, springy=True), springy=True ), Item('f_ck', label='Compressive strength'), Item('n_cj', label='Discretization'), label='Concrete', springy=True ), Group(VGroup( Item('ecb_law_type', show_label=False, springy=True), Item('ecb_law', label='Edit', show_label=False, springy=True), Item('show_ecb_law', label='Show', show_label=False, springy=True), springy=True, ), label='Reinforcement', springy=True ), springy=True, ), Group(Item('s_tex_z', label='vertical spacing', style='readonly'), label='Layout', ), Group( HGroup(Item('M', springy=True, style='readonly'), Item('N', springy=True, style='readonly'), ), label='Stress resultants' ), scrollable=True, ), Group(Item('replot', show_label=False), Item('figure', editor=MPLFigureEditor(), resizable=True, show_label=False), id='simexdb.plot_sheet', label='plot sheet', dock='tab', ), ), width=0.8, height=0.7, resizable=True, buttons=['OK', 'Cancel'])
class MKPullOut(HasTraits): rf = Instance(DoublePulloutSym) def _rf_default(self): return DoublePulloutSym(tau_fr=3.14, l=0.0, d=25.5e-3, E_mod=70.0e3, theta=0.0, xi=0.0179, phi=1., L=30.0) #-------------------------------------------------------------------------------- # select the concrete mixture from the concrete database: #-------------------------------------------------------------------------------- param_distribs_key = Enum(MKPullOutParamDistribs.db.keys(), simdb=True, input=True, auto_set=False, enter_set=True) param_distribs_ref = Property(Instance(SimDBClass), depends_on='param_distribs_key') @cached_property def _get_param_distribs_ref(self): return MKPullOutParamDistribs.db[self.param_distribs_key] po = Property(Instance(YarnPullOut), depends_on='param_distribs_key') @cached_property def _get_po(self): pd = self.param_distribs_ref return YarnPullOut(rf=self.rf, pdf_phi=pd.phi, pdf_phi_on=True, pdf_theta=pd.theta, pdf_theta_on=True, pdf_l=pd.ell, pdf_ell_on=True, n_f=1743, w_max=1.2) #-------------------------------------------------------------------------------- # view #-------------------------------------------------------------------------------- traits_view = View( VSplit( VGroup( Spring(), Item('param_distribs_key', label='parameters'), Spring(), Item('param_distribs_ref@', show_label=False), Spring(), id='mkpo.split.pd', label='parameter distributions', dock='tab', ), HSplit( Item('po@', show_label=False), label='Pull Out', id='mkpo.split.pu', scrollable=True, dock='tab', ), dock='tab', id='mkpo.split', orientation='vertical', ), dock='tab', id='mkpo', scrollable=True, resizable=True, height=0.4, width=0.5, buttons=['OK', 'Cancel'], )