def fase_iniciacion(param, sigma, crit, a_i,ac, da, W, MAT): """Devuelve los ciclos de la fase de iniciacion de una grieta, conocida la tension media desde la superficie hasta la punta de la misma. INPUTS: param = Fatemi-Socie o Smith-Watson-Topper en un punto sigma = tension x en ese punto crit = parametro a utilizar a_i = (m) tamaño de la grieta de iniciacion ac = plana o eliptica (0 o 0.5) da = paso para realizar los calculos W = (m) anchura del especimen MAT = indice asignado del material OUTPUT: N_i = ciclos de la fase de iniciacion""" #Calcula los ciclos totales hasta el fallo N_t = ciclos_totales(param, crit, MAT) #ind_a se utiliza para la propia fase de propagacion por lo #que en la fase de iniciacion no es una variable relevante y puede tomar #cualquier valor ind_a = 0 #Calculos los ciclos que necesita la grieta para propagarse N_p = fase_propagacion(sigma, ind_a, a_i,ac, da, W, MAT) #Calculamos los ciclos de iniciacion N_i = N_t - N_p #Si el numero es negativo devuelve 0 if N_i < 0: N_i = 0.0 #Para ciclos muy altos solo se tiene en cuenta la iniciación para evitar #errores que se producen en la integración de la propagación if N_t > 1.5e7: N_i = N_t return N_i
def principal(par, W, MAT, ac, exp_max, exp_min, ruta_exp, ruta_curvas=None, main_path=""): """Estima la vida a fatiga. INPUTS: par = parametro para el modelo de iniciacion W = (m) anchura del especimen MAT = indice asignado al material ac = propagacion plana o eliptica exp_max = nombre del archivo con la tensiones y defs maximas exp_min = nombre del archivo con la tensiones y defs minimas ruta_curvas = ubicación de las curvas de iniciación OUTPUTS: resultados.dat = actualiza el archivo de resultados con la longitud de iniciacion y los ciclos de iniciacion, propagacion y total para que se produzca el fallo a_inic = longitud de grieta de iniciación v_ai_mm = vector de longitudes de grietas en mm N_t_min = Ciclos de iniciación N_t = Vector de ciclos totales N_p = Vector de ciclos de propagación N_i = Vector de ciclos de iniciación N_a = Vector de ciclos de propagación a partir de la iniciación exp_id.dat = archivo con los datos de las curvas de vida""" print('Datos Experimentales:\n {}.dat\n {}.dat\n'.format( exp_max, exp_min)) #exp_id obtiene a partir del nombre del archivo con los datos un #identificador del experimento. Dependiendo del nombre del archivo debe #modificarse. pattern = r"\d+_\d+_\d+" exp_id = re.search(pattern, exp_max).group() #Obtenemos las rutas a las carpetas necesarias para los calculos # cwd = os.getcwd() # ruta_exp = cwd + '/datos_experimentales' ruta_datos = main_path + '/resultados/datos/{}'.format(par) if ruta_curvas is None: ruta_curvas = main_path + '/curvas_inic/{}'.format(ac) data_interp = np.loadtxt("{}/MAT_{}.dat".format(ruta_curvas, par)) else: data_interp = np.loadtxt(ruta_curvas) #Cargamos los datos de las curvas de iniciación del material #Separamos las curvas en las variables necesarias x_interp = data_interp[0, 1:] #Eje x de la matriz de interpolación y_interp = data_interp[1:, 0] #Eje y de la matriz de interpolación m_N_i = data_interp[1:, 1:] #Matriz con los ciclos de iniciación #Creamos la función de interpolación function_interp = interp2d(x_interp, y_interp, m_N_i, kind='quintic', bounds_error=False) #Cargamos los datos experimentales y generamos el vector de FS o SWT x, sxx_max, s_max, e_max, e_min = lectura_datos(ruta_exp, exp_max, exp_min) param = parametro(par, MAT, x, s_max, e_max, e_min) a_i_min = round(x[1], 8) #Tamaño mínimo de longitud de grieta de #iniciacion. Redondeamos para evitar errores #numericos. a_i_max = round(x[-1], 8) #Tamaño máximo de longitud de grieta de iniciacion da = a_i_min #Paso entre longitudes de grietas #Creamos el vector de longitudes de grieta de iniciacion v_ai = np.arange(a_i_min, a_i_max, da) #Vector de longitudes de grieta en m v_ai_mm = v_ai * 1e3 #Vector de longitudes de grieta en mm #Calculamos los ciclos de iniciación, de propagación y totales para cada #longitud de grieta de iniciacion #Inicializamos los ciclos N_i = np.zeros_like(v_ai) N_p = np.zeros_like(v_ai) N_t = np.zeros_like(v_ai) for i, a in enumerate(v_ai): ind_a = indice_a(a, x) #Indice asociado a esa longitud de grieta param_med = np.mean( param[:ind_a + 1]) #Valor medio del parametro para la interpolacion #Realizamos la interpolacion para calcular los ciclos de iniciacion N_i[i] = function_interp(a, param_med)[0] #La interpolacion puede dar valores menores que 0 para ciclos muy bajos if N_i[i] < 0: N_i[i] = 0 #Calculamos los ciclos de propagacion N_p[i] = fase_propagacion(sxx_max, ind_a, a, ac, da, W, MAT) #Ciclos totales N_t[i] = N_i[i] + N_p[i] #Calculamos el numero de ciclos hasta el fallo y la longitud de iniciación #de la grieta, que se producen en el mínimo de la curva de ciclos totales N_t_min = np.min(N_t) i_N_t_min = np.argmin(N_t) N_i_min = N_i[i_N_t_min] N_p_min = N_p[i_N_t_min] a_inic = v_ai_mm[i_N_t_min] #Pintamos la figura con la evolucion de la longitud de grieta y guardamos #en un archivo los datos ciclos = open(ruta_datos + '/{}.dat'.format(exp_id), 'w') ciclos.write('{:<5}\t{:<12}\t{:<12}\t{:<12}\t{:<12}'.format( 'a_i', 'N_t', 'N_i', 'N_p', 'N_a')) N_a = [] #Vector de ciclos con la evolución de la grieta for i, ai in enumerate(v_ai): #Hasta la longitud de iniciacion crece como los ciclos de iniciacion if ai <= a_inic * 1e-3: n_a = N_i[i] N_a.append(n_a) #A partir de la longitud de iniciacion crece de acuerdo con los ciclos #de propagacion else: n_a = N_a[-1] + N_p[i - 1] - N_p[i] N_a.append(n_a) n_i = N_i[i] n_p = N_p[i] ciclos.write('\n{:.3f}\t{:.6e}\t{:.6e}\t{:.6e}\t{:.6e}'.format( ai * 1e3, n_i + n_p, n_i, n_p, n_a)) ciclos.close() cols = [ 'exp_id', 'param', 'N_t_min', 'N_i_min', 'N_p_min', 'N_i_perc', 'N_p_perc', 'a_inic(mm)' ] values = [ exp_id, par, N_t_min, N_i_min, N_p_min, str(float(N_i_min) / N_t_min * 100) + "%", str(float(N_p_min) / N_t_min * 100) + "%", a_inic ] result_dict = dict(zip(cols, values)) if os.path.isfile(main_path + "/resultados_generales/resultados.xlsx"): df = pd.read_excel(main_path + "/resultados_generales/resultados.xlsx") if len(df[df["exp_id"] == exp_id][df["param"] == par]) > 0: df = df.drop( df[df["exp_id"] == exp_id][df["param"] == par].index[0]) df = df.append(result_dict, ignore_index=True) else: df = pd.DataFrame([result_dict]) df.to_excel(main_path + "/resultados_generales/resultados.xlsx", index=False) print('Longitud de iniciación de la grieta: {} mm'.format(a_inic)) print('Numero de ciclos hasta el fallo: {}\n'.format(N_t_min)) return a_inic, v_ai_mm, N_t_min, N_t, N_p, N_i, N_a
def principal(par, W, MAT, ac, trat, exp_max, exp_min): """Estima la vida a fatiga. INPUTS: par = parametro para el modelo de iniciacion W = (m) anchura del especimen MAT = indice asignado al material ac = propagacion plana o eliptica trat = tratamiento superficial exp_max = nombre del archivo con la tensiones y defs maximas exp_min = nombre del archivo con la tensiones y defs minimas OUTPUTS: resultados.dat = actualiza el archivo de resultados con la longitud de iniciacion y los ciclos de iniciacion, propagacion y total para que se produzca el fallo a_inic = longitud de grieta de iniciación v_ai_mm = vector de longitudes de grietas en mm N_t_min = Ciclos de iniciación N_t = Vector de ciclos totales N_p = Vector de ciclos de propagación N_i = Vector de ciclos de iniciación N_a = Vector de ciclos de propagación a partir de la iniciación exp_id.dat = archivo con los datos de las curvas de vida""" print('Datos Experimentales:\n {}.dat\n {}.dat\n'.format( exp_max, exp_min)) #exp_id obtiene a partir del nombre del archivo con los datos un #identificador del experimento. Dependiendo del nombre del archivo debe #modificarse. pattern = r"\d+_\d+_\d+" exp_id = re.search(pattern, exp_max).group() #Obtenemos las rutas a las carpetas necesarias para los calculos cwd = os.getcwd() ruta_exp = cwd + '/datos_experimentales/{}'.format(trat) ruta_curvas = cwd + '/curvas_inic/{}'.format(ac) ruta_datos = cwd + '/resultados/{}/datos/{}'.format(trat, par) #Cargamos los datos de las curvas de iniciación del material data_interp = np.loadtxt("{}/MAT_{}.dat".format(ruta_curvas, par)) #Separamos las curvas en las variables necesarias x_interp = data_interp[0, 1:] #Eje x de la matriz de interpolación y_interp = data_interp[1:, 0] #Eje y de la matriz de interpolación m_N_i = data_interp[1:, 1:] #Matriz con los ciclos de iniciación #Creamos la función de interpolación function_interp = interp2d(x_interp, y_interp, m_N_i, kind='quintic', bounds_error=False) #Cargamos los datos experimentales y generamos el vector de FS o SWT x, sxx_max, s_max, e_max, e_min = lectura_datos(ruta_exp, exp_max, exp_min) param = parametro(par, MAT, x, s_max, e_max, e_min) a_i_min = round(x[1], 8) #Tamaño mínimo de longitud de grieta de #iniciacion. Redondeamos para evitar errores #numericos. a_i_max = round(x[-1], 8) #Tamaño máximo de longitud de grieta de iniciacion da = a_i_min #Paso entre longitudes de grietas #Creamos el vector de longitudes de grieta de iniciacion v_ai = np.arange(a_i_min, a_i_max, da) #Vector de longitudes de grieta en m v_ai_mm = v_ai * 1e3 #Vector de longitudes de grieta en mm #Calculamos los ciclos de iniciación, de propagación y totales para cada #longitud de grieta de iniciacion #Inicializamos los ciclos N_i = np.zeros_like(v_ai) N_p = np.zeros_like(v_ai) N_t = np.zeros_like(v_ai) for i, a in enumerate(v_ai): ind_a = indice_a(a, x) #Indice asociado a esa longitud de grieta param_med = np.mean( param[:ind_a + 1]) #Valor medio del parametro para la interpolacion #Realizamos la interpolacion para calcular los ciclos de iniciacion N_i[i] = function_interp(a, param_med)[0] #La interpolacion puede dar valores menores que 0 para ciclos muy bajos if N_i[i] < 0: N_i[i] = 0 #Calculamos los ciclos de propagacion N_p[i] = fase_propagacion(sxx_max, ind_a, a, ac, da, W, MAT) #Ciclos totales N_t[i] = N_i[i] + N_p[i] #Calculamos el numero de ciclos hasta el fallo y la longitud de iniciación #de la grieta, que se producen en el mínimo de la curva de ciclos totales N_t_min = np.min(N_t) i_N_t_min = np.argmin(N_t) N_i_min = N_i[i_N_t_min] N_p_min = N_p[i_N_t_min] a_inic = v_ai_mm[i_N_t_min] #Pintamos la figura con la evolucion de la longitud de grieta y guardamos #en un archivo los datos ciclos = open(ruta_datos + '/{}.dat'.format(exp_id), 'w') ciclos.write('{:<5}\t{:<12}\t{:<12}\t{:<12}\t{:<12}'.format( 'a_i', 'N_t', 'N_i', 'N_p', 'N_a')) N_a = [] #Vector de ciclos con la evolución de la grieta for i, ai in enumerate(v_ai): #Hasta la longitud de iniciacion crece como los ciclos de iniciacion if ai <= a_inic * 1e-3: n_a = N_i[i] N_a.append(n_a) #A partir de la longitud de iniciacion crece de acuerdo con los ciclos #de propagacion else: n_a = N_a[-1] + N_p[i - 1] - N_p[i] N_a.append(n_a) n_i = N_i[i] n_p = N_p[i] ciclos.write('\n{:.3f}\t{:.6e}\t{:.6e}\t{:.6e}\t{:.6e}'.format( ai * 1e3, n_i + n_p, n_i, n_p, n_a)) ciclos.close() lines = np.loadtxt('resultados_generales/resultados_{}.dat'.format(trat), dtype=str, skiprows=1).tolist() # Se reescriben las lineas que ya estaban en el archivo. EL if else es debido # a que el formato de lines varía según haya una línea de resultados escrita # o mas de una. results = open('resultados_generales/resultados_{}.dat'.format(trat), 'w') results.write( '{:<13}\t{:<}\t{:<12}\t{:<12}\t{:<12}\t{:<5}\t{:<5}\t{:<}'.format( 'exp_id', 'param', 'N_t_min', 'N_i_min', 'N_p_min', '% N_i', '% N_p', 'a_inic (mm)')) if len(lines[0][0]) == 1: #Solo se escriben los resultados que no pertenezcan al calculo actual if lines[0] != exp_id or lines[1] != par: results.write('\n') for j in i: results.write('{}\t'.format(j)) else: for i in lines: #Solo se escriben los resultados que no pertenezcan al calculo actual if i[0] != exp_id or i[1] != par: results.write('\n') for j in i: results.write('{}\t'.format(j)) #Se escribe en el archivo el calculo actual results.write( '\n{}\t{}\t{:.6e}\t{:.6e}\t{:.6e}\t{:.1%}\t{:.1%}\t{:.3f}'.format( exp_id, par, N_t_min, N_i_min, N_p_min, float(N_i_min) / N_t_min, float(N_p_min) / N_t_min, a_inic)) results.close() print('Longitud de iniciación de la grieta: {} mm'.format(a_inic)) print('Numero de ciclos hasta el fallo: {}\n'.format(N_t_min)) return a_inic, v_ai_mm, N_t_min, N_t, N_p, N_i, N_a
def principal(par, W, MAT, exp_max, exp_min): """Estima la vida a fatiga. INPUTS: par = parametro para el modelo de iniciacion W = (m) anchura del especimen MAT = indice asignado al material exp_max = nombre del archivo con la tensiones y defs maximas exp_min = nombre del archivo con la tensiones y defs minimas OUTPUTS: resultados.dat = actualiza el archivo de resultados con la longitud de iniciacion y los ciclos de iniciacion, propagacion y total para que se produzca el fallo exp_id.dat = archivo con los datos de las curvas de vida""" print('Datos Experimentales:\n {}.dat\n {}.dat\n'.format( exp_max, exp_min)) #exp_id obtiene a partir del nombre del archivo con los datos un #identificador del experimento. Dependiendo del nombre del archivo debe #modificarse. exp_id = exp_max[16:] #Obtenemos las rutas a las carpetas necesarias para los calculos cwd = os.getcwd() ruta_exp = cwd + '/datos_exp' ruta_curvas = cwd + '/curvas_inic' ruta_fig = cwd + '/resultados/grafs/' + par ruta_datos = cwd + '/resultados/datos/' + par #Cargamos los datos de las curvas de iniciación del material data_interp = np.loadtxt("{}/MAT{}_{}.dat".format(ruta_curvas, MAT, par)) #Separamos las curvas en las variables necesarias x_interp = data_interp[0, 1:] #Eje x de la matriz de interpolación y_interp = data_interp[1:, 0] #Eje y de la matriz de interpolación m_N_i = data_interp[1:, 1:] #Matriz con los ciclos de iniciación #Creamos la función de interpolación function_interp = interp2d(x_interp, y_interp, m_N_i, kind='quintic', bounds_error=False) #Cargamos los datos experimentales y generamos el vector de FS o SWT x, sxx_max, s_max, e_max, e_min = lectura_datos(ruta_exp, exp_max, exp_min) param = parametro(par, MAT, x, s_max, e_max, e_min) a_i_min = round(x[1], 8) #Tamaño mínimo de longitud de grieta de #iniciacion. Redondeamos para evitar errores #numericos. a_i_max = round(x[-1], 8) #Tamaño máximo de longitud de grieta de iniciacion da = a_i_min #Paso entre longitudes de grietas #Creamos el vector de longitudes de grieta de iniciacion v_ai = np.arange(a_i_min, a_i_max, da) #Vector de longitudes de grieta en m v_ai_mm = v_ai * 1e3 #Vector de longitudes de grieta en mm #Calculamos los ciclos de iniciación, de propagación y totales para cada #longitud de grieta de iniciacion #Inicializamos los ciclos N_i = np.zeros_like(v_ai) N_p = np.zeros_like(v_ai) N_t = np.zeros_like(v_ai) for i, a in enumerate(v_ai): ind_a = indice_a(a, x) #Indice asociado a esa longitud de grieta param_med = np.mean( param[:ind_a + 1]) #Valor medio del parametro para la interpolacion #Realizamos la interpolacion para calcular los ciclos de iniciacion N_i[i] = function_interp(a, param_med)[0] #La interpolacion puede dar valores menores que 0 para ciclos muy bajos if N_i[i] < 0: N_i[i] = 0 #Calculamos los ciclos de propagacion N_p[i] = fase_propagacion(sxx_max, ind_a, a, da, W, MAT) #Ciclos totales N_t[i] = N_i[i] + N_p[i] #Pintamos los curvas de iniciación, de propagación y totales plt.close(exp_id + '_' + par) plt.figure(exp_id + '_' + par) plt.yscale('log') plt.xlabel('Longitud de iniciacion (mm)') plt.ylabel('Ciclos') plot_inic = [] plot_prop = [] plot_tot = [] plot_inic += plt.plot(v_ai_mm, N_i, 'b') plot_prop += plt.plot(v_ai_mm, N_p, 'k') plot_tot += plt.plot(v_ai_mm, N_t, 'r') #Calculamos el numero de ciclos hasta el fallo y la longitud de iniciación #de la grieta, que se producen en el mínimo de la curva de ciclos totales N_t_min = np.min(N_t) i_N_t_min = np.argmin(N_t) N_i_min = N_i[i_N_t_min] N_p_min = N_p[i_N_t_min] a_inic = v_ai_mm[i_N_t_min] #Pintamos el punto donde se da el minimo plt.plot(a_inic, N_t_min, 'ro') plt.ylim([1e3, 1e8]) plt.xlim([0.0, a_i_max * 1e3]) plt.legend([plot_inic[0], plot_prop[0], plot_tot[0]], ['Vida de iniciacion', 'Vida de propagacion', 'Vida total'], loc=0) plt.show() #Guardamos la figura y la cerramos plt.savefig(ruta_fig + '/{}.png'.format(exp_id)) plt.close(exp_id + '_' + par) #Pintamos la figura con la evolucion de la longitud de grieta y guardamos #en un archivo los datos ciclos = open(ruta_datos + '/{}.dat'.format(exp_id), 'w') ciclos.write('{:<5}\t{:<12}\t{:<12}\t{:<12}\t{:<12}'.format( 'a_i', 'N_t', 'N_i', 'N_p', 'N_a')) N_a = [] #Vector de ciclos con la evolución de la grieta for i, ai in enumerate(v_ai): #Hasta la longitud de iniciacion crece como los ciclos de iniciacion if ai <= a_inic * 1e-3: n_a = N_i[i] N_a.append(n_a) #A partir de la longitud de iniciacion crece de acuerdo con los ciclos #de propagacion else: n_a = N_a[-1] + N_p[i - 1] - N_p[i] N_a.append(n_a) n_i = N_i[i] n_p = N_p[i] ciclos.write('\n{:.3f}\t{:.6e}\t{:.6e}\t{:.6e}\t{:.6e}'.format( i * 1e3, n_i + n_p, n_i, n_p, n_a)) ciclos.close() plt.figure('Longitud de grieta') plt.xscale('log') plt.xlabel('Ciclos') plt.ylabel('Longitud de grieta (mm)') plt.plot(N_a, v_ai_mm, 'k') plt.xlim([5e2, 1e8]) plt.show() #represantamos la matriz de ciclos a través de un countour plot XX, YY = np.meshgrid(x_interp, y_interp) # malla de la matriz breaks = np.logspace(1, 10, 10) #intervalos de los niveles fig, ax = plt.subplots() cs = ax.contourf(XX, YY, m_N_i, breaks, locator=ticker.LogLocator()) fig.colorbar(cs, ticks=breaks) plt.show() #Generamos/actualizamos el archivo con los resultados para la estimacion lines = np.loadtxt('resultados.dat', dtype=str, skiprows=1).tolist() results = open('resultados.dat', 'w') results.write( '{:<13}\t{:<}\t{:<12}\t{:<12}\t{:<12}\t{:<5}\t{:<5}\t{:<}'.format( 'exp_id', 'param', 'N_t_min', 'N_i_min', 'N_p_min', '% N_i', '% N_p', 'a_inic (mm)')) #Se reescriben las lineas que ya estaban en el archivo. EL if else es debido #a que el formato de lines varía según haya una línea de resultados escrita #o mas de una. if len(lines[0][0]) == 1: #Solo se escriben los resultados que no pertenezcan al calculo actual if lines[0] != exp_id or lines[1] != par: results.write('\n') for j in i: results.write('{}\t'.format(j)) else: for i in lines: #Solo se escriben los resultados que no pertenezcan al calculo actual if i[0] != exp_id or i[1] != par: results.write('\n') for j in i: results.write('{}\t'.format(j)) #Se escribe en el archivo el calculo actual results.write( '\n{}\t{}\t{:.6e}\t{:.6e}\t{:.6e}\t{:.1%}\t{:.1%}\t{:.3f}'.format( exp_id, par, N_t_min, N_i_min, N_p_min, float(N_i_min) / N_t_min, float(N_p_min) / N_t_min, a_inic)) results.close() print('Longitud de iniciación de la grieta: {} mm'.format(a_inic)) print('Numero de ciclos hasta el fallo: {}\n'.format(N_t_min))