def predict(self, c_p, m_p, method='tanaka'): # usage:完成预测过程,输出SIF变幅、FCGR、循环次数、有效性判定 # NOTE:参数全部引用自函数外部,不适合从其它文件调用 # input parameter: # load:实验施加的载荷峰值,应当为1个数,可从外部的数组中取一个调用 # return parameter: # cracklength:给定的裂纹长度,mm # dk_predict:计算的SIF变幅,Mpa.m0.5 # dadn:估计的FCGR,mm/cycles # valid:有效性判断结果 _ = self.evaluate_sif_range_k1() _ = self.evaluate_sif_range_k2() _ = self.calculate_sif_range_eff(method=method) self.fcg_rate = mts_analysis.ParisCalculating(c=c_p, m=m_p, dk=self.sif_range_eff) self.cycle = experiment_predict.CycleIntegrateBySimpson( c=c_p, m=m_p, dk=self.sif_range_eff, cracklength=self.cracklength) for seq, value in enumerate(self.cracklength): self.valid.append( mts_analysis.LigamentValidCheck(w=self.width, a=value, dk=self.sif_range_eff[seq], ys=self.yieldstrength, r=self.stressratio)) return self.cracklength, self.sif_range_eff, self.fcg_rate, self.cycle, self.valid
def AlphaCalculate(fade_rate, amplitude, dadn, dk, kc, a, a_range, a_amplitude, stress_ratio, numofaverage=7, error_ratio=0.2): # 放弃 # 移动平均 kc_Manual_averaged2, dk_Manual_averaged2 = \ DoubleDataSelectMovingAverage(data=kc, reference=dk, ratio=error_ratio, numofaverage=numofaverage) _, a_Manual_averaged2 = \ DoubleDataSelectMovingAverage(data=kc, reference=a, ratio=error_ratio, numofaverage=numofaverage) _, dadn_Manual_averaged2 = \ DoubleDataSelectMovingAverage(data=kc, reference=dadn, ratio=error_ratio, numofaverage=numofaverage) # 数据筛选a_range dadn_selecting_average2, dk_selecting_averaged2, kc_selecting_averaged2, a_selecting_averaged2 = \ mts_analysis.FCGDataSelectByThreshold(dadn=dadn_Manual_averaged2, dk=dk_Manual_averaged2, n=kc_Manual_averaged2, a=a_Manual_averaged2, threshold=a_range[0], target='a', keepbigger=1) dadn_selected_averaged2, dk_selected_averaged2, kc_selected_averaged2, a_selected_averaged2 = \ mts_analysis.FCGDataSelectByThreshold(dadn=dadn_selecting_average2, dk=dk_selecting_averaged2, n=kc_selecting_averaged2, a=a_selecting_averaged2, threshold=a_range[1], target='a', keepbigger=0) # 拟合数据准备 kmin_selected_averaged2 = dk_selected_averaged2 * ( stress_ratio / (1 - stress_ratio)) # Kmin计算 kmax_selected_averaged2 = dk_selected_averaged2 * (1 / (1 - stress_ratio) ) # Kmax计算 c_p, m_p = paris_and_walker.ParisParameter(r=stress_ratio) # Paris参数读取 betas = (a_selected_averaged2 - a_amplitude) / a_amplitude # 裂纹长度无量纲量 # 计算参数alpha alpha_e = [] for beta in betas: if beta < 0: alpha_e.append(2 / np.pi) else: alpha_e.append(amplitude * np.exp(-fade_rate * beta)) alpha_e = np.array(alpha_e) # 基于参数计算有效应力强度因子 dkeff_alpha_e = kmax_selected_averaged2 - alpha_e * kc_selected_averaged2 - ( 1 - alpha_e) * kmin_selected_averaged2 # 计算dadn dadn_alpha_e = mts_analysis.ParisCalculating(c=c_p, m=m_p, dk=dkeff_alpha_e) return dk_selected_averaged2, dkeff_alpha_e, dadn_alpha_e, alpha_e, betas, a_selected_averaged2
def evaluate_fcg_rate_by_paris(self, c_p, m_p): self.fcg_rate = mts_analysis.ParisCalculating(c=c_p, m=m_p, dk=self.sif_range_eff) return self.fcg_rate
''' 数据读取处理 ''' specimen_data = [] for sequence in sequences: specimen_data.append( mts_class.SpecimenBasic(name=sequence, stress_ratio=r, threshold=0)) # 创建实例 for specimen in specimen_data: specimen.read_experimental_data() # 读取和计算 ''' Paris拟合和Walker模型效果对比 ''' dadn_paris_Manual = mts_analysis.ParisCalculating(c=c_p, m=m_p, dk=np.array( specimen.dk_Manual)) ''' 数据保存 ''' if filesave: for specimen in specimen_data: data = np.array([ specimen.n_Manual, specimen.a_Manual, specimen.dk_Manual, specimen.dadn_Manual, specimen.kc_Manual ]) name = [ "Original_Cycles", "Original_CrackLength/mm", "Original_SIFRange/MPam0.5", "Original_FCGRate/mm per cycle", "Original_ClosureSIF/MPam0.5" ]
# dkeff计算 dkeff_Manual_2pi = closureanalysis.dKeffCalculation(kmax=dk_Manual / (1 - r), kclose=kc_Manual, kmin=dk_Manual * (r / (1 - r)), method='2/PI') # 移动平均 dkeff_Manual_averaged0, dk_Manual_averaged0 = \ closureanalysis.DoubleDataSelectMovingAverage(data=dkeff_Manual_2pi, reference=dk_Manual, ratio=ratio, numofaverage=numofaverage) _, a_Manual_averaged0 = \ closureanalysis.DoubleDataSelectMovingAverage(data=dkeff_Manual_2pi, reference=a_Manual, ratio=ratio, numofaverage=numofaverage) # 计算基于裂纹闭合效应的dadn(2/PI法) dadn_paris_dkeff_2pi = mts_analysis.ParisCalculating(c=c_p, m=m_p, dk=dkeff_Manual_averaged0) ''' 传统dkeff法(basic) ''' # dkeff计算 dkeff_Manual_bac = closureanalysis.dKeffCalculation(kmax=dk_Manual / (1 - r), kclose=kc_Manual, kmin=dk_Manual * (r / (1 - r)), method='basic') # 移动平均 dkeff_Manual_averaged1, dk_Manual_averaged1 = \ closureanalysis.DoubleDataSelectMovingAverage(data=dkeff_Manual_bac, reference=dk_Manual, ratio=ratio, numofaverage=numofaverage) _, a_Manual_averaged1 = \
def AlphaModifiedCalculate(alpha_fade_rate, alpha_amplitude, pmax, stress_ratio, thickness, width, a_amplitude, a_list, c_ca, m_ca, a_start, a_end, dadn_start): # Modified Alpha模型计算函数 # 该函数通过由已知起点(通常为a_kc_max_cal)和终点(通常为a_retard_end)的裂纹长度值和裂纹扩展速率 # 采用直线拟合得到Kop的值,代入已知的Alpha模型参数值计算 # 得到该段裂纹闭合效应主导的裂纹扩展速率模型 # input parameters: # alpha_fade_rate: 模型衰减率参数 # alpha_amplitude: 模型峰值参数,常取2/pi # pmax, stress_ratio: 载荷峰值,应力比 # thickness, width: CT试件几何参数厚度和宽度 # a_amplitude: 模型起点a0 # a_list:要计算的裂纹长度值的数组 # c_ca, m_ca:该应力比下的Paris公式参数 # a_start, a_end: 要输出的裂纹长度起止点 # dadn_start: 输入a0对应的dadn速率,通过反转Paris公式计算其dkeff # return parameters: # dk: 输入的a_list计算对应的dk # dkeff_alpha_e: 输入的a_list对应的alpha模型下的dkeff # dadn_alpha_e: 输入的a_list由alpha模型计算得到的dadn # alpha_e: a_list各值对应的alpha值 # betas:a_list各值对应的无量纲裂纹长度参数值 kmax = mts_analysis.DeltaKCalculating(b=thickness, w=width, a=a_list, pmax=pmax, pmin=0) kmin = mts_analysis.DeltaKCalculating(b=thickness, w=width, a=a_list, pmax=pmax * stress_ratio, pmin=0) dk = kmax - kmin # 计算无量纲量 betas = (a_list - a_amplitude) / a_amplitude # 计算系数alpha alpha_e = [] for beta in betas: if beta < 0: alpha_e.append(2 / np.pi) else: alpha_e.append(alpha_amplitude * np.exp(-alpha_fade_rate * beta)) alpha_e = np.array(alpha_e) # 计算Kop dk_start = mts_analysis.DeltaKCalculating(b=thickness, w=width, a=a_start, pmax=pmax, pmin=pmax * stress_ratio) dk_end = mts_analysis.DeltaKCalculating(b=thickness, w=width, a=a_end, pmax=pmax, pmin=pmax * stress_ratio) dkeff_start = mts_analysis.ParisInverseCalculation(c=c_ca, m=m_ca, dadn=dadn_start) print("The Effective SIF when beta=0:" + str(dkeff_start)) pi = np.pi kop_start = pi / 2 * (dk_start / (1 - stress_ratio) - dkeff_start - (1 - 2 / pi) * dk_start * stress_ratio / (1 - stress_ratio)) print("The Open SIF when beta=0 based on Alpha Method:" + str(kop_start)) kop_end = dk_end * (stress_ratio / (1 - stress_ratio)) dk_fit = [dk_start[0], dk_end] kop_fit = [kop_start[0], kop_end] k_kopfit_cal, b_kopfit_cal = mixed_model.LogLinearFit(y=kop_fit, x=dk_fit) kop_cal = mixed_model.LogLinearFittedCalculate(k=k_kopfit_cal, b=b_kopfit_cal, x=dk) # 计算dKeff dkeff_alpha_e = kmax - alpha_e * kop_cal - (1 - alpha_e) * kmin # 计算dadn dadn_alpha_e = mts_analysis.ParisCalculating(c=c_ca, m=m_ca, dk=dkeff_alpha_e) return dk, dkeff_alpha_e, dadn_alpha_e, alpha_e, betas
def Alpha2(sequence, stress_ratio, error_ratio, numofaverage, a_range, amplitude=0, fade_rate=0, fitting=0, model='paris'): # usage: 采用提出的Alpha方法先拟合出幅度系数M,再根据其计算dadn结果 # input parameter: # sequence: 试件名(与MTS中一致,将直接读取文件) # stress_ratio:实验应力比 # error_ratio:进行数据筛选的误差带半宽度,详细注释见函数DoubleDataSelectMovingAverage # numofaverage:进行移动平均的数据个数,详细注释见函数DoubleDataSelectMovingAverage # a_range:拟合的数据范围,格式为数组[a_begin, a_end],a_begin推荐为dkeff_basic的谷值或dadn的谷值, # a_end要注意截止在数据开始离散之前 # fade_rate:幂函数中的指数系数,直接指定,常见[5,8] # amplitude: 幂函数中的幅度系数,可定2/pi # 注:函数自动将对输入为0的项先拟合参数再进行计算,若均不为零则直接计算不进行拟合 # fitting: 若fitting为1,则输出拟合时对标的dkeff_experiment值,以用于计算lost # model: 设定计算过程中采用的model,默认采用paris,可选walker # return parameter: # Ce1: 计算得到的幅度系数 # dk_selected_averaged2, dkeff_alpha_e, dadn_alpha_e:对应的裂纹扩展参数 # alpha_e:对应的参数alpha # 数据读入 dadn_Manual, n_Manual, dk_Manual, a_Manual, kc_Manual = \ BasicDataDispose(sequence=sequence, r=stress_ratio) if model == 'walker': c_w, m_w, gamma = paris_and_walker.WalkerParameter(data=1) else: c_p, m_p = paris_and_walker.ParisParameter(r=stress_ratio) # 移动平均 kc_Manual_averaged2, dk_Manual_averaged2 = \ DoubleDataSelectMovingAverage(data=kc_Manual, reference=dk_Manual, ratio=error_ratio, numofaverage=numofaverage) _, a_Manual_averaged2 = \ DoubleDataSelectMovingAverage(data=kc_Manual, reference=a_Manual, ratio=error_ratio, numofaverage=numofaverage) _, dadn_Manual_averaged2 = \ DoubleDataSelectMovingAverage(data=kc_Manual, reference=dadn_Manual, ratio=error_ratio, numofaverage=numofaverage) # 数据筛选a_range dadn_selecting_average2, dk_selecting_averaged2, kc_selecting_averaged2, a_selecting_averaged2 = \ mts_analysis.FCGDataSelectByThreshold(dadn=dadn_Manual_averaged2, dk=dk_Manual_averaged2, n=kc_Manual_averaged2, a=a_Manual_averaged2, threshold=a_range[0], target='a', keepbigger=1) dadn_selected_averaged2, dk_selected_averaged2, kc_selected_averaged2, a_selected_averaged2 = \ mts_analysis.FCGDataSelectByThreshold(dadn=dadn_selecting_average2, dk=dk_selecting_averaged2, n=kc_selecting_averaged2, a=a_selecting_averaged2, threshold=a_range[1], target='a', keepbigger=0) # 拟合数据准备 kmin_selected_averaged2 = dk_selected_averaged2 * ( stress_ratio / (1 - stress_ratio)) # Kmin计算 kmax_selected_averaged2 = dk_selected_averaged2 * (1 / (1 - stress_ratio) ) # Kmax计算 if model == 'walker': dkeff_experiment_averaged2 = ( (dadn_selected_averaged2 / c_w)**(1 / m_w)) / ( (1 - stress_ratio)**(gamma - 1)) else: dkeff_experiment_averaged2 = (dadn_selected_averaged2 / c_p)**( 1 / m_p) # 拟合时的真值dkeff,由Paris给出 beta = (a_selected_averaged2 - a_range[0]) / a_range[0] # 裂纹长度无量纲量 # 拟合,得到幅度或衰减系数 if fade_rate != 0 and amplitude == 0: def residual_alpha_e(p): Ce = p return dkeff_experiment_averaged2 - ( kmax_selected_averaged2 - (Ce * np.exp(-fade_rate * beta)) * kc_selected_averaged2 - (1 - (Ce * np.exp(-fade_rate * beta))) * kmin_selected_averaged2) k = opt.leastsq(residual_alpha_e, np.array([1])) Ce1 = k[0] elif amplitude != 0 and fade_rate == 0: def residual_alpha_e(p): n = p return dkeff_experiment_averaged2 - ( kmax_selected_averaged2 - (amplitude * np.exp(-n * beta)) * kc_selected_averaged2 - (1 - (amplitude * np.exp(-n * beta))) * kmin_selected_averaged2) k = opt.leastsq(residual_alpha_e, np.array([1])) fade_rate = k[0] Ce1 = amplitude elif amplitude != 0 and fade_rate != 0: Ce1 = amplitude elif amplitude == 0 and fade_rate == 0: def residual_alpha_e(p): Ce, n = p return dkeff_experiment_averaged2 - ( kmax_selected_averaged2 - (Ce * np.exp(-n * beta)) * kc_selected_averaged2 - (1 - (Ce * np.exp(-n * beta))) * kmin_selected_averaged2) k = opt.leastsq(residual_alpha_e, np.array([1, 1])) Ce1, fade_rate = k[0] # 计算参数alpha alpha_e = Ce1 * np.exp(-fade_rate * beta) print("alpha幂函数拟合:试件名:", sequence, "幅度:", Ce1, "衰减速率:", fade_rate) # 计算dkeff_alpha和对应的dadn dkeff_alpha_e = kmax_selected_averaged2 - alpha_e * kc_selected_averaged2 - ( 1 - alpha_e) * kmin_selected_averaged2 if model == 'walker': dadn_alpha_e = mts_analysis.WalkerCalculating(c0=c_w, gamma=gamma, m0=m_w, r=stress_ratio, dk=dkeff_alpha_e) else: dadn_alpha_e = mts_analysis.ParisCalculating(c=c_p, m=m_p, dk=dkeff_alpha_e) if fitting: return Ce1, fade_rate, dk_selected_averaged2, dkeff_alpha_e, dadn_alpha_e, alpha_e, dkeff_experiment_averaged2 else: return Ce1, fade_rate, dk_selected_averaged2, dkeff_alpha_e, dadn_alpha_e, alpha_e
aol=specimen.a_ol_applied, rol=plz_ol, plasticzonefactor=plz_factor, m1=m1_2, c=c_ca, m=m_ca, eta=0) # 2/PI法: # dkeff计算 dkeff_Manual_2pi = closureanalysis.dKeffCalculation( kmax=specimen.dk / (1 - specimen.stress_ratio), kclose=specimen.kc, kmin=specimen.dk * (specimen.stress_ratio / (1 - specimen.stress_ratio)), method='2/PI') dkeff_2pi, dk_2pi = \ closureanalysis.DoubleDataSelectMovingAverage(data=dkeff_Manual_2pi, reference=specimen.dk, ratio=0.2, numofaverage=7) _, a_2pi = \ closureanalysis.DoubleDataSelectMovingAverage(data=dkeff_Manual_2pi, reference=specimen.a, ratio=0.2, numofaverage=7) dadn_2pi = mts_analysis.ParisCalculating(c=c_ca, m=m_ca, dk=dkeff_2pi) # Try: mix try 1 # 采用logistic sigmoid函数分配两种 # logistic sigmoid单调递增,表征crack closure sigmas = 1 / (1 + np.exp(-kappa * betas)) dadn_mixed_1 = dadn_wheeler * (1 - sigmas) + dadn_alpha_e * sigmas # 绘图部分 # Plotting plt.figure(num=1, figsize=(8, 6)) plt.scatter(specimen.dk, specimen.dadn, lw=1, marker='+', label='Experiment') if moving_average: plt.scatter(dk_ave, dadn_ave, lw=1, marker='*', label='Moving average') plt.plot(dk_wheeler2, dadn_wheeler2,
dadn_Manual2, n_Manual2, dk_Manual2, a_Manual2, _ = \ closureanalysis.BasicDataDispose(sequence=sequence[1], r=stress_ratio[1]) dadn_Manual3, n_Manual3, dk_Manual3, a_Manual3, _ = \ closureanalysis.BasicDataDispose(sequence=sequence[2], r=stress_ratio[2]) dadn_Manual4, n_Manual4, dk_Manual4, a_Manual4, _ = \ closureanalysis.BasicDataDispose(sequence=sequence[3], r=stress_ratio[3]) dadn_Manual5, n_Manual5, dk_Manual5, a_Manual5, _ = \ closureanalysis.BasicDataDispose(sequence=sequence[4], r=stress_ratio[4]) # CA曲线计算 dk_paris = np.linspace(15, 25, 9) dadn_paris = mts_analysis.ParisCalculating(c=c_CA, m=m_CA, dk=dk_paris) plt.figure(num=1, figsize=(10, 8)) plt.scatter(dk_Manual1, dadn_Manual1, lw=1, marker='+', label='CA') plt.scatter(dk_Manual2, dadn_Manual2, lw=1, marker='*', label='OLR=1.5') plt.scatter(dk_Manual3, dadn_Manual3, lw=1, marker='2', label='OLR=2.0') #plt.scatter(dk_Manual4, dadn_Manual4, lw=1, marker='3', label='OLR=2.5') #plt.scatter(dk_Manual5, dadn_Manual5, lw=1, marker='1', label='OLR=4.0') plt.plot(dk_paris, dadn_paris, label='CA_Paris', color='black', linewidth=2) plt.axis([ min(dk_Manual1), max(dk_Manual1), min(dadn_Manual1), max(dadn_Manual1) * 1.2 ]) plt.yticks(np.linspace(min(dadn_Manual3) * 0.5, max(dadn_Manual1), 6))
c_p, m_p = paris_and_walker.ParisParameter(r=r) # 数据读取 dadn_Manual, n_Manual, dk_Manual, a_Manual, kc_Manual = closureanalysis.BasicDataDispose(sequence=sequence[0], r=r) dkeff_Manual = closureanalysis.dKeffCalculation(kmax=dk_Manual/(1-r), kclose=kc_Manual, kmin=dk_Manual*(r/(1-r)), method='basic') # moving average numofaverage = 7 ratio = 0.5 dadn_Manual_averaged, dk_Manual_averaged = \ closureanalysis.DoubleDataSelectMovingAverage(data=dadn_Manual, reference=dk_Manual, ratio=ratio, numofaverage=numofaverage) # 无高载Paris虚线 dadn_paris_Manual = mts_analysis.ParisCalculating(c=c_p, m=m_p, dk=dk_Manual) # ploting plt.figure(num=1, figsize=(10, 8)) plt.scatter(dk_Manual, dadn_Manual, label='$ExperimentData$', color='red', marker='.') plt.scatter(dk_Manual_averaged, dadn_Manual_averaged, label='$MovingAverage$', color='blue', marker='.') plt.plot(dk_Manual, dadn_paris_Manual, label='$Paris for CA$', color='black', linewidth=2) plt.axis([min(dk_Manual) * 0.95, max(dk_Manual) * 1.05, min(dadn_Manual) * 0.95, max(dadn_Manual) * 1.05]) plt.xlabel("DeltaK Applied (MPa*m^0.5)") plt.xscale('log') plt.ylabel("da/dN (mm/cycle)") plt.yscale('log') plt.xticks(np.linspace(min(dk_Manual), max(dk_Manual), 6)) plt.title('da/dN - dK ' + sequence[0] + '(MTS Result)') plt.legend() plt.grid()