def find_pin_locations(input_file): """Fnid the locations of roller pins for 4-point bending models. returns the z coordinate values of the inner and outer pin locations. """ with open(input_file) as f: input_lines = f.readlines() # Bending model input files will have pins # e.g., # # c top load pin mesh line Reaction Node # c number of nodes in list = 33 # c 3452 0.000000E+00 0.000000E+00 -1.250000E+00 # ... start_index = util.find_first_line_matching( input_lines, "c top load pin mesh line Reaction Node") first_node_line = input_lines[start_index + 2] (rest, pin_location) = first_node_line.rsplit(maxsplit=1) outer_pin_location = float(pin_location) # # and # # c bottom load pin mesh line # c number of nodes in list = 25 # c 3299 1.000000E+00 -1.000000E+00 -6.250000E-01 # ... start_index = util.find_first_line_matching( input_lines, "c bottom load pin mesh line") first_node_line = input_lines[start_index + 2] (rest, pin_location) = first_node_line.rsplit(maxsplit=1) inner_pin_location = float(pin_location) return (inner_pin_location, outer_pin_location)
def find_J_list(input_lines, output_lines): """Calculate J values from the contents of a WARP3D input and output file. J values are calculated at each position around the crack front for each load step. """ start_index = util.find_first_line_matching(input_lines, 'c Analysis Load Step Data') (_, steps) = input_lines[start_index + 1].rsplit(maxsplit=1) # print("Steps: {0}".format(steps)) steps = int(steps) start_index = util.find_first_line_matching(input_lines, 'c Crack Node Data') (_, crack_nodes) = input_lines[start_index + 14].rsplit(maxsplit=1) # print("Crack nodes: {0}".format(crack_nodes)) crack_nodes = int(crack_nodes) # Create list of phi and J values for the corner nodes and # number of load steps phi_table = np.zeros((int((crack_nodes + 1) / 2), )) J_table = np.zeros((steps, int((crack_nodes + 1) / 2), 10)) j = 0 label_list = [] for i in range(start_index + 16, start_index + 16 + crack_nodes, 2): line = input_lines[i] # print(line) (c, node_id, phi, label, _) = line.split(maxsplit=4) phi_table[j] = float(phi) label_list.append(label) j = j + 1 start_index = 0 for step in range(steps): # print("step: "+str(step)) start_index = util.find_first_line_containing( output_lines, "loading: history1 step:", # analysis:ignore start=start_index) # analysis:ignore for label in label_list: start_index = util.find_first_line_containing(output_lines, "domain id: " + label, start=start_index) # print("label: "+label) J_column = label_list.index(label) J_row = step for i in range(10): start_index = util.find_first_line_containing( output_lines, "killed ele", # analysis:ignore start=start_index + 1) # analysis:ignore # print("line: "+output_lines[start_index+1]) J = output_lines[start_index + 1].split()[10] J_table[J_row, J_column, i] = float(J) return (phi_table, J_table)
def modify_bc(bc, input_file, model_type): """Adjust the boundary condition applied to a tension or bending model. Returns nothing, raises a ValueError if model_type is not 'tension' or 'bending'. """ # bc = bc[0] # only needed for minimize, not for newton print("BC = {0:.3e}: ".format(bc), end='', flush=True) with open(input_file) as f: input_lines = f.readlines() if model_type == 'tension': # If we're a tension case, want to adjust non-zero w constraints to # some value. # - Find line starting with "constraints" # - Find next line starting with "c *echo off" # - In that range, adjust lines like # " 10294 u 0.000000E+00 w 1.000000E+00" to a new w value start_index = util.find_first_line_matching(input_lines, "constraints") + 1 end_index = util.find_first_line_matching(input_lines, "c *echo off", start_index) for i in range(start_index, end_index): line = input_lines[i] if 'w' in line: (rest, w_value) = line.rsplit(maxsplit=1) w_value = float(w_value) if not (w_value == 0): input_lines[i] = "{0} {1:.6e}\n".format(rest, bc) elif model_type == 'bending': # If we're a bending case, want to adjust element tractions to some # value. # - Find line starting with "loading set1" # - Find next line starting with "c" # - In that range, adjust lines like # " 2571 face 2 traction ty 3.52000000E-01" to a new ty value start_index = util.find_first_line_matching(input_lines, "loading set1") + 1 end_index = util.find_first_line_matching(input_lines, "c", start_index) for i in range(start_index, end_index): line = input_lines[i] if 'traction ty' in line: (rest, ty_value) = line.rsplit(maxsplit=1) ty_value = float(ty_value) if not (ty_value == 0): input_lines[i] = "{0} {1:.8e}\n".format(rest, bc) else: raise (ValueError, "model_type must be either 'tension' or 'bending'") with open(input_file, 'w') as f: f.writelines(input_lines)
def find_J(input_lines, output_lines): """Calculate J values from the contents of a WARP3D input and output file. J values are calculated at each position around the crack front for each load step. """ start_index = util.find_first_line_matching(input_lines, 'c Analysis Load Step Data') (_, steps) = input_lines[start_index + 1].rsplit(maxsplit=1) # print("Steps: {0}".format(steps)) steps = int(steps) start_index = util.find_first_line_matching(input_lines, 'c Crack Node Data') (_, crack_nodes) = input_lines[start_index + 14].rsplit(maxsplit=1) # print("Crack nodes: {0}".format(crack_nodes)) crack_nodes = int(crack_nodes) # Create list of phi and J values for the corner nodes and # number of load steps phi_table = np.zeros((int((crack_nodes + 1) / 2), )) J_table = np.zeros((steps, int((crack_nodes + 1) / 2))) j = 0 label_list = [] for i in range(start_index + 16, start_index + 16 + crack_nodes, 2): line = input_lines[i] # print(line) (c, node_id, phi, label, _) = line.split(maxsplit=4) phi_table[j] = float(phi) label_list.append(label) j = j + 1 start_index = 0 for step in range(steps): start_index = util.find_first_line_containing( output_lines, "loading: history1 step:", # analysis:ignore start=start_index) # analysis:ignore for label in label_list: J_column = label_list.index(label) J_row = step # Need this line after adding interaction integrals (T stress)q start_index = util.find_first_line_containing( output_lines, "J-integral components", start=start_index) start_index = util.find_first_line_containing( output_lines, "average minimum maximum", # analysis:ignore start=start_index + 1) # analysis:ignore (_, _, J) = output_lines[start_index + 1].split(maxsplit=2) J_table[J_row, J_column] = float(J) return (phi_table, J_table)
def add_rigid_plane(model_filename=None, stiffness=None, origin=None, size=None): if model_filename is None: raise ValueError("Missing model_filename") if stiffness is None: raise ValueError("Missing rigid plane stiffness") if origin is None: raise ValueError("Missing rigid plane origin") if size is None: raise ValueError("Missing rigid plane size") plane_string = """ contact surface surface 1 plane point {0} {1} 0 point {0} {2} 0 point {3} {1} 0 $ relative normal vector ends up as (0, 0, -1) stiffness {4} """.format(origin[0], origin[1], origin[1]+size[1], origin[0]+size[0], stiffness) # print(plane_string) with open(model_filename) as f: model_lines = f.readlines() start_index = util.find_first_line_matching(model_lines, "c ANALYSIS PARAMETERS")-2 model_lines.insert(start_index, plane_string) with open(model_filename, 'w') as f: f.writelines(model_lines)
def get_elt_type(elt_file): with open(elt_file) as f: elt_lines = f.readlines() # If we're a bending case, will have specified ty tractions on elements. # - Find line starting with "Notes:" (including quotes) # - On next line, look for "*use bottom load pin plate ty " # (without quotes) start_index = util.find_first_line_matching( elt_lines, '"Notes:"')+1 if not(start_index == -1): # Found the notes line notes_content = elt_lines[start_index] if "*use bottom load pin plate ty " in notes_content: elt_type = 'bending' else: elt_type = 'tension' else: elt_type = 'tension' # Extra sanity check: bending models should have two pin definitions. # May or may not be possible in the FEACrack GUI, but they have # to be present to locate the force and reaction roller locations. # First an outer roller definition: # "RigidSurfaceData_Radius",.75 # "RigidSurfaceData_PinLocation",10 # and then an inner roller definition: # "RigidSurfaceData_Radius",.75 # "RigidSurfaceData_PinLocation",5 if elt_type == 'bending': outer_roller_radius_index = util.find_first_line_containing( elt_lines, '"RigidSurfaceData_Radius",') outer_roller_location_index = util.find_first_line_containing( elt_lines, '"RigidSurfaceData_PinLocation",') if (outer_roller_radius_index == -1) or (outer_roller_location_index == -1): elt_type = 'invalid' extra_info = "No rollers fully defined" else: inner_roller_radius_index = util.find_first_line_containing( elt_lines, '"RigidSurfaceData_Radius",', outer_roller_radius_index+1) inner_roller_location_index = util.find_first_line_containing( elt_lines, '"RigidSurfaceData_PinLocation",', outer_roller_location_index+1) if (inner_roller_radius_index == -1) or (inner_roller_location_index == -1): elt_type = 'invalid' extra_info = "Only one roller fully defined" if (elt_type == 'invalid'): raise ValueError("Malformed .elt file for bending: {0}".format( extra_info)) else: return elt_type
def get_model_type(input_file): """Detect if a WARP3D input file is for a tension model or a bending model. Returns 'tension' for tension models, 'bending' for bending models, and raises a ValueError otherwise. """ with open(input_file) as f: input_lines = f.readlines() # If we're a tension case, will have non-zero w constraints on nodes. # - Find line starting with "constraints" # - Find next line starting with "c *echo off" # - In that range, find lines like # " 10294 u 0.000000E+00 w 1.000000E+00" start_index = util.find_first_line_matching(input_lines, "constraints") + 1 end_index = util.find_first_line_matching(input_lines, "c *echo off", start_index) for i in range(start_index, end_index): line = input_lines[i] if 'w' in line: (rest, w_value) = line.rsplit(maxsplit=1) w_value = float(w_value) if not (w_value == 0): return 'tension' # If we're a bending case, will have ty tractions on elements. # - Find line starting with "loading set1" # - Find next line starting with "c" # - In that range, find lines like # " 2571 face 2 traction ty 3.52000000E-01" start_index = util.find_first_line_matching(input_lines, "loading set1") + 1 end_index = util.find_first_line_matching(input_lines, "c", start_index) for i in range(start_index, end_index): line = input_lines[i] if 'ty' in line: (rest, ty_value) = line.rsplit(maxsplit=1) ty_value = float(ty_value) if not (ty_value == 0): return 'bending' raise ValueError("Could not detect model type")
def change_material_properties(inp_filename, E=None, Sys=None, n=None, stress_strain_table=None): """Write a new WARP3D input file with specific material properties. Returns the name of the final WARP3D input file. """ # Sanity check parameters if inp_filename is None: raise ValueError(('inp_filename must be the filename ' 'of the .inp file for this specific geometry')) elif (E is None) or (Sys is None): raise ValueError('E and Sys must both be values') elif not((n is None) ^ (stress_strain_table is None)): raise ValueError(('1 and only 1 of n and stress_strain_table ' 'must have a value')) # inp_filename = get_generic_inp_filename(global_elt_filename, # a, c, L, W, t) model_filename = get_specific_inp_filename(inp_filename, E, n) bpf_filename = get_bpf_filename(model_filename) shutil.copy(inp_filename, model_filename) with open(model_filename) as f: model_lines = f.readlines() # Find lines in the .inp file corresponding to material properties # Adjust material properties to match either LPPL or stress-strain table # values # Look for "stress-strain curve 1" and "c" to find stress-strain data start_index = util.find_first_line_matching( model_lines, "stress-strain curve 1")+1 if start_index == 0: raise ValueError("Didn't find start of stress-strain curve") end_index = util.find_first_line_matching( model_lines, "c", start_index) if end_index == -1: raise ValueError("Didn't find end of stress-strain curve") # Decide on contents of replacement stress-strain data if n is None: # stress-strain table in use, just plug in those values instead stress_strain_table_formatted = stress_strain_formatted( stress_strain_table) else: # LPPL in use, calculate 20 entries for stress-strain table stress_strain_table_formatted = lppl_formatted(E, Sys, n) model_lines[start_index:end_index] = stress_strain_table_formatted # Look for "material mat1" to find elastic properties 3 lines below E_line_index = util.find_first_line_matching(model_lines, "material mat1")+3 (E_label, E_orig, nu_label, nu) = model_lines[E_line_index].split() new_e_line = "{0} {1:6e} {2} {3}\n".format(E_label, E, nu_label, nu) model_lines[E_line_index] = new_e_line # Fix comments that describe material properties, too. start_index = util.find_first_line_matching(model_lines, "c Mesh Material Data")+1 end_index = util.find_first_line_matching(model_lines, "c Mesh Material Data", start_index) mat_notes = """c number of material groups = 1 c material group = 1 c material type = total-strain vs stress table c modulus of elasticity = {0} c poisson ratio = 3.0000001E-01 c number of table rows = 20 c total-strain stress """.format(E) for line in stress_strain_table_formatted: mat_notes = mat_notes+"c {0}".format(line) model_lines[start_index:end_index] = mat_notes # Fix line setting which binary packet file (bpf) is written bpf_index = util.find_first_line_containing(model_lines, 'binary packets on file') bpf_line = " binary packets on file '{0}'\n".format(bpf_filename) model_lines[bpf_index] = bpf_line with open(model_filename, 'w') as f: f.writelines(model_lines) return model_filename