#line to be revoluted s1.Line( point1=(R,-H/2.), point2=(R,H/2.) ) #CREATING A LOCAL COORDINATE SYSTEM TO USE IN THE BOUNDARY CONDITIONS csysCyl = partCyl.DatumCsysByThreePoints( name='CSYSCylinder', coordSysType=CYLINDRICAL, origin=(0,0,0), point1=(1,0,0), point2=(1,0,-1) ) #CREATING THE CYLINDER SHELL GEOMETRY myCyl = partCyl.BaseShellRevolve( sketch=s1, angle=360.0, flipRevolveDirection=OFF ) #PROPERTY - assigning the property to the corresponding faces partCyl.SectionAssignment( region=Region( faces=partCyl.faces.findAt(((-R,0,0),)) ), sectionName='AluminumPlate' ) #DEFINING THE MESH SEEDS ALONG ALL EDGES partCyl.PartitionEdgeByParam( edges=partCyl.edges.findAt( ((R,0,0),) ), parameter=PLpoint ) partCyl.seedEdgeBySize(edges= partCyl.edges.findAt( ((R,-H/2,0),) ), size=ELSIZE, deviationFactor=0.1, constraint=FINER) partCyl.seedEdgeBySize(edges= partCyl.edges.findAt( ((R, H/2,0),) ), size=ELSIZE, deviationFactor=0.1, constraint=FINER) partCyl.seedEdgeBySize(edges= partCyl.edges.findAt( ((R,-H/4,0),) ), size=ELSIZE,
def create(self): from abaqus import mdb from abaqusConstants import (SIDE1, SUPERIMPOSE, COPLANAR_EDGES, MIDDLE, XZPLANE, SWEEP, FIXED) from regionToolset import Region cc = self.impconf.conecyl mod = mdb.models[cc.model_name] p = mod.parts[cc.part_name_shell] ra = mod.rootAssembly datums = p.datums d = self.d r, z = cc.r_z_from_pt(self.pt) x, y, z = self.x, self.y, self.z alpharad = cc.alpharad drill_offset_rad = np.deg2rad(self.drill_offset_deg) thetarad = np.deg2rad(self.thetadeg) thetadeg = self.thetadeg thetadeg1 = self.thetadeg1 thetadeg2 = self.thetadeg2 # line defining the z axis _p1 = p.DatumPointByCoordinate(coords=(0, 0, 0)) _p2 = p.DatumPointByCoordinate(coords=(0, 0, 1)) zaxis = p.DatumAxisByTwoPoint(point1=datums[_p1.id], point2=datums[_p2.id]) # line defining the cutting axis self.p1coord = np.array((x, y, z)) dx = d * cos(alpharad - drill_offset_rad) * cos(thetarad) dy = d * cos(alpharad - drill_offset_rad) * sin(thetarad) dz = d * sin(alpharad - drill_offset_rad) self.p0coord = np.array((x - dx, y - dy, z - dz)) self.p2coord = np.array((x + dx, y + dy, z + dz)) p1 = p.DatumPointByCoordinate(coords=self.p1coord) p2 = p.DatumPointByCoordinate(coords=self.p2coord) drillaxis = p.DatumAxisByTwoPoint(point1=datums[p1.id], point2=datums[p2.id]) #TODO get vertices where to pass the cutting plane plow = self.p1coord.copy() pup = self.p1coord.copy() rlow, zlow = cc.r_z_from_pt(self.ptlow) plow[2] = zlow rup, zup = cc.r_z_from_pt(self.ptup) pup[2] = zup diag1pt = p.DatumPointByCoordinate(coords=cyl2rec(rup, thetadeg2, zup)) diag2pt = p.DatumPointByCoordinate(coords=cyl2rec(rup, thetadeg1, zup)) diag3pt = p.DatumPointByCoordinate( coords=cyl2rec(rlow, thetadeg1, zlow)) diag4pt = p.DatumPointByCoordinate( coords=cyl2rec(rlow, thetadeg2, zlow)) diag1 = p.DatumPlaneByThreePoints(point1=datums[p1.id], point2=datums[p2.id], point3=datums[diag1pt.id]) diag2 = p.DatumPlaneByThreePoints(point1=datums[p1.id], point2=datums[p2.id], point3=datums[diag2pt.id]) diag3 = p.DatumPlaneByThreePoints(point1=datums[p1.id], point2=datums[p2.id], point3=datums[diag3pt.id]) diag4 = p.DatumPlaneByThreePoints(point1=datums[p1.id], point2=datums[p2.id], point3=datums[diag4pt.id]) c1 = cyl2rec(0.5 * (rup + r), thetadeg + 0.5 * self.offsetdeg, 0.5 * (z + zup)) c2 = cyl2rec(0.5 * (rup + r), thetadeg - 0.5 * self.offsetdeg, 0.5 * (z + zup)) c3 = cyl2rec(0.5 * (rlow + r), thetadeg - 0.5 * self.offsetdeg, 0.5 * (z + zlow)) c4 = cyl2rec(0.5 * (rlow + r), thetadeg + 0.5 * self.offsetdeg, 0.5 * (z + zlow)) #TODO try / except blocks needed due to an Abaqus bug try: face1 = p.faces.findAt(c1) p.PartitionFaceByDatumPlane(datumPlane=datums[diag1.id], faces=face1) except: pass try: face2 = p.faces.findAt(c2) p.PartitionFaceByDatumPlane(datumPlane=datums[diag2.id], faces=face2) except: pass try: face3 = p.faces.findAt(c3) p.PartitionFaceByDatumPlane(datumPlane=datums[diag3.id], faces=face3) except: pass try: face4 = p.faces.findAt(c4) p.PartitionFaceByDatumPlane(datumPlane=datums[diag4.id], faces=face4) except: pass sketchplane = p.DatumPlaneByPointNormal(point=datums[p2.id], normal=datums[drillaxis.id]) sketchstrans = p.MakeSketchTransform( sketchPlane=datums[sketchplane.id], sketchUpEdge=datums[zaxis.id], sketchPlaneSide=SIDE1, origin=self.p2coord) sketch = mod.ConstrainedSketch(name='__profile__', sheetSize=10. * d, gridSpacing=d / 10., transform=sketchstrans) sketch.setPrimaryObject(option=SUPERIMPOSE) p.projectReferencesOntoSketch(sketch=sketch, filter=COPLANAR_EDGES) sketch.CircleByCenterPerimeter(center=(0.0, 0), point1=(0.0, d / 2.)) #TODO try / except blocks needed due to an Abaqus bug try: p.PartitionFaceBySketchDistance(sketchPlane=datums[sketchplane.id], sketchUpEdge=datums[zaxis.id], faces=p.faces, sketchPlaneSide=SIDE1, sketch=sketch, distance=1.5 * d) except: pass sketch.unsetPrimaryObject() del mod.sketches['__profile__'] while True: faceList = [ f[0] for f in p.faces.getClosest(coordinates=((x, y, z), ), searchTolerance=(d / 2. - 0.5)).values() ] if not faceList: break #TODO try / except blocks needed due to an Abaqus bug try: p.RemoveFaces(faceList=faceList, deleteCells=False) except: pass # Seed edges around cutout area numel_per_edge = int(np.ceil(self.offsetdeg / 360.0 * cc.numel_r)) edge_coords = [ (rup, 0.5 * (thetadeg1 + thetadeg), zup), (rup, 0.5 * (thetadeg2 + thetadeg), zup), (rlow, 0.5 * (thetadeg1 + thetadeg), zlow), (rlow, 0.5 * (thetadeg2 + thetadeg), zlow), (0.5 * (rlow + r), thetadeg1, 0.5 * (zlow + z)), (0.5 * (rup + r), thetadeg1, 0.5 * (zup + z)), (0.5 * (rlow + r), thetadeg2, 0.5 * (zlow + z)), (0.5 * (rup + r), thetadeg2, 0.5 * (zup + z)), ] edge_coords = [cyl2rec(*c) for c in edge_coords] edgeList = [ e[0] for e in p.edges.getClosest(coordinates=edge_coords, searchTolerance=1.).values() ] p.seedEdgeByNumber(edges=edgeList, number=numel_per_edge, constraint=FIXED) # Seed radial edges about the cutout edge_coords = [ (r, 0.5 * (thetadeg2 + thetadeg), z), (0.5 * (rup + r), 0.5 * (thetadeg2 + thetadeg), 0.5 * (zup + z)), (0.5 * (rup + r), thetadeg, 0.5 * (zup + z)), (0.5 * (rup + r), 0.5 * (thetadeg1 + thetadeg), 0.5 * (zup + z)), (r, 0.5 * (thetadeg1 + thetadeg), z), (0.5 * (rlow + r), 0.5 * (thetadeg1 + thetadeg), 0.5 * (zlow + z)), (0.5 * (rlow + r), thetadeg, 0.5 * (zlow + z)), (0.5 * (rlow + r), 0.5 * (thetadeg2 + thetadeg), 0.5 * (zlow + z)), ] edge_coords = [cyl2rec(*c) for c in edge_coords] edgeList = [ e[0] for e in p.edges.getClosest(coordinates=edge_coords, searchTolerance=1.).values() ] p.seedEdgeByNumber(edges=edgeList, number=self.numel_radial_edge, constraint=FIXED) # Mesh control for cutout faces try: p.setMeshControls(regions=p.faces, technique=SWEEP) except: warn( "Unable to set mesh control to 'SWEEP', please check the mesh around your cutout(s)" ) p.generateMesh() for pload in cc.impconf.ploads: if (pload.pt == self.pt and pload.thetadeg == self.thetadeg and pload.name in mod.loads.keys()): warn( "Cutout is in the same location as perturbation load, moving PL to cutout edge" ) inst_shell = ra.instances['INST_SHELL'] coords = cyl2rec(r, thetadeg + np.rad2deg(self.d / 2. / r), z) new_vertex = inst_shell.vertices.getClosest( coordinates=[coords], searchTolerance=1.).values()[0][0] #TODO Unfortunately you cannot simply pass a vertex or list of vertices # It has to be some internal abaqus sequence type... work around that: index = inst_shell.vertices.index(new_vertex) region = Region(vertices=inst_shell.vertices[index:index + 1]) mod.loads[pload.name].setValues(region=region) if self.prop_around_cutout is not None: self.create_prop_around_cutout()
def create(self): r"""Creates the uneven top edge imperfections The uneven top edge will be represented by many GAP elements created in such a way to consider all the imperfections contained in the current :class:`.UnevenTopEdge` object. The output file ``cc.model_name + '_top_edge.gaps'`` will be created, where ``cc`` is the :class:`.ConeCyl` object that contains this :class:`.UnevenTopEdge` object. The following steps are executed: - get the `\theta` coordinate of the top nodes from the shell and top resin rings - get imperfection from the ``shims`` attribute - get any additional imperfection of the top edge represented by ``measured_u3s`` - include effect of the misalignment angle ``betadeg`` Assumptions: - for a given `\theta` coordinate the uneven displacement is the same for all the shell and resin ring nodes, but the load asymmetry angle ``self.betadeg`` may change this equality. The contribution due to `\beta` is given by: .. math:: \Delta u_3 = R_{top} tan(\beta) cos(\theta-\omega) .. note:: Must be called from Abaqus """ from abaqus import mdb from abaqusConstants import (PIN_MPC, DOF_MODE_MPC) from regionToolset import Region from desicos.abaqus.abaqus_functions import edit_keywords cc = self.impconf.conecyl mod = mdb.models[cc.model_name] ra = mod.rootAssembly def calc_gaps(nodes, yx=True): # calculating gaps # theta according to the assembly coordinate system coords = np.array([n.coordinates for n in nodes]) if yx: theta_nodes = np.arctan2(coords[:, 1], coords[:, 0]) else: theta_nodes = np.arctan2(-coords[:, 2], coords[:, 0]) # contributions from measured edge imperfection if self.measured_u3s is not None: measured_u3s = np.asarray(self.measured_u3s) else: measured_u3s = np.zeros((2, 100)) measured_u3s[0, :] = np.linspace(0, 360, 100) # calculating u3 for each node u3_nodes = interp(rad2deg(theta_nodes), measured_u3s[0, :], measured_u3s[1, :], period=360) # applying load asymmetry according to cc.betarad and omega betadeg = self.betadeg if self.betadeg is not None else 0. betarad = deg2rad(betadeg) omegadeg = self.omegadeg if self.omegadeg is not None else 0. omegarad = deg2rad(omegadeg) u3_nodes -= cc.rtop * np.tan(betarad) * np.cos(theta_nodes - omegarad) # contributions from shims hs = np.zeros_like(theta_nodes) for s in self.shims: trad1 = deg2rad(s.thetadeg) trad2 = deg2rad(s.thetadeg + 360 * s.width / (2 * pi * cc.rtop)) thetarads = [trad1 - 0.001, trad1, trad2, trad2 + 0.001] u3s = [0, s.thick, s.thick, 0] tmp = interp(theta_nodes, thetarads, u3s, period=2 * pi) hs += tmp u3_nodes -= hs # applying scaling_factor u3_nodes *= self.scaling_factor # calculating gap values gaps = u3_nodes - u3_nodes.min() return gaps if not self.uneven_plate: # shell part = mod.parts[cc.part_name_shell] wdw = 2 * cc.rtop zmin = cc.H - cc.resin_top_h * 1.001 zmax = 1.001 * cc.H nodes = part.nodes.getByBoundingBox(-wdw, -wdw, zmin, +wdw, +wdw, zmax) coords = np.array([n.coordinates for n in nodes]) coords[:, 2] -= calc_gaps(nodes) labels = [n.label for n in nodes] meshNodeArray = nodes.sequenceFromLabels(labels) part.editNode(nodes=meshNodeArray, coordinates=coords) # top inner ring if cc.resin_add_TIR: mesh_arrays = [] coords_list = [] part = mod.parts['Top_IR'] coords = np.array([n.coordinates for n in part.nodes]) gaps = calc_gaps(part.nodes, yx=False) coords[:, 1] -= gaps part.editNode(nodes=part.nodes, coordinates=coords) # top outer ring if cc.resin_add_TOR: mesh_arrays = [] coords_list = [] part = mod.parts['Top_OR'] coords = np.array([n.coordinates for n in part.nodes]) gaps = calc_gaps(part.nodes, yx=False) coords[:, 1] -= gaps part.editNode(nodes=part.nodes, coordinates=coords) nodes_shell = np.array(ra.sets['shell_top_edges'].nodes) nodes_all = nodes_shell tshell = sum(cc.plyts) cosa = np.cos(cc.alpharad) if cc.resin_add_TIR: nodes_TIR_assembly = np.array(ra.sets['Top_IR_faces'].nodes) coords = np.array([n.coordinates for n in nodes_TIR_assembly]) r_nodes = np.sqrt(coords[:, 0]**2 + coords[:, 1]**2) # taking nodes that are not pinned to the shell check = (r_nodes < (cc.rtop - cosa * 0.51 * tshell)) nodes_all = np.hstack((nodes_all, nodes_TIR_assembly[check])) if cc.bc_fix_top_side_u3: tmp = np.array(ra.sets['Top_IR_faces_side'].nodes) coords = np.array([n.coordinates for n in tmp]) # taking nodes that are not on the top edge check = (coords[:, 2] < (cc.H - 0.1)) nodes_all = np.hstack((nodes_all, tmp[check])) if cc.resin_add_TOR: nodes_TOR_assembly = np.array(ra.sets['Top_OR_faces'].nodes) coords = np.array([n.coordinates for n in nodes_TOR_assembly]) r_nodes = np.sqrt(coords[:, 0]**2 + coords[:, 1]**2) # taking nodes that are not pinned to the shell check = (r_nodes > (cc.rtop + cosa * 0.51 * tshell)) nodes_all = np.hstack((nodes_all, nodes_TOR_assembly[check])) if cc.bc_fix_top_side_u3: tmp = np.array(ra.sets['Top_OR_faces_side'].nodes) coords = np.array([n.coordinates for n in tmp]) # taking nodes that are not on the top edge check = (coords[:, 2] < (cc.H - 0.1)) nodes_all = np.hstack((nodes_all, tmp[check])) # creating GAP elements rps_gap = [] text = '' gaps = calc_gaps(nodes_all) for node, gap in zip(nodes_all, gaps): coord = list(node.coordinates) coord[2] += gap rp = ra.ReferencePoint(point=coord) inst_name = node.instanceName #TODO really bad approach, but couldn' find any other way to # get the actual node id that is printed in the .inp # file rp_id = int(rp.name.split('-')[1]) + 2 # rps_gap.append(rp) gap_name = 'gap_{0}_{1:d}'.format(inst_name, 2000000 + node.label) inst_node = '{0}.{1:d}'.format(inst_name, node.label) text += ('\n*Element, type=GAPUNI, elset={0}'.format(gap_name)) text += ('\n{0:d},{1:d},{2}'.format(2000000 + node.label, rp_id, inst_node)) text += '\n*GAP, elset={0}'.format(gap_name) text += '\n{0:f},0,0,-1\n'.format(gap) top_name_gaps = '{0}_top_edge.gaps'.format(cc.model_name) with open(top_name_gaps, 'w') as f: f.write(text) pattern = '*Instance' if self.impconf.uneven_bottom_edge: bottom_name_gaps = '{0}_bottom_edge.gaps'.format(cc.model_name) text = '*INCLUDE, INPUT={0}'.format(bottom_name_gaps) text += '\n**\n*INCLUDE, INPUT={0}'.format(top_name_gaps) else: text = '*INCLUDE, INPUT={0}'.format(top_name_gaps) edit_keywords(mod=mod, text=text, before_pattern=pattern, insert=True) set_RP_top = ra.sets['RP_top'] rps = ra.referencePoints rps_gap_datums = [rps[rp.id] for rp in rps_gap] region = Region(referencePoints=rps_gap_datums) ra_cyl_csys = ra.features['ra_cyl_csys'] ra_cyl_csys = ra.datums[ra_cyl_csys.id] mod.MultipointConstraint(name='MPC_RP_GAPs_top_edge', controlPoint=set_RP_top, surface=region, mpcType=PIN_MPC, userMode=DOF_MODE_MPC, userType=0, csys=ra_cyl_csys)
def mesh_part(self, mesh_params): """Mesh the model. The following functions are used in succession: + **seedPart()**: *deviationFactor* and *minSizeFactor* are set to 0.1 and *constraint* is not supported. + **setMeshControls()**: The following parameters are not supported: *technique*, *algorithm*, *minTransition*, *sizeGrowth*, *allowMapped*. + **setElementType()**: The following constraints exist: - *region* is set to all faces/cells of the structure. - The *elemTypes* tuple is determined by *mesh_params.elem_code* and *mesh_params.elem_library*. Args: mesh_params(MeshParams): Special namedtuple describing the mesh applied to the model. See class for full description of options. Raises: ValueError: If *mesh_params.elem_shape* is invalid. ValueError: If *mesh_params.elem_shape* does not correspond to the structure's dimensionality. ValueError: If *mesh_params.elem_library* is invalid. ValueError: If *mesh_params.elem_code is invalid. KeyError: If *mesh_params.elem_code* does not correspond to a SymbolicConstant. ValueError: If *mesh_params.elem_code* does not correspond to an element. AbaqusException: Various exceptions raised by the Abaqus API. """ logger.debug('Meshing the part.') import abaqusConstants as abqConst # So as no to pollute the namespace. abaqusConstants_vars = vars(abqConst) # Validate and set mesh_params.elem_shape. elem_shape_str = mesh_params.elem_shape if elem_shape_str.upper( ) in auxetic_structure_params.all_elem_shape_list: elem_shape = abaqusConstants_vars[elem_shape_str.upper()] else: raise ValueError("invalid value '%s' for mesh_params.elem_shape." % elem_shape_str) # Make sure element shape is consistant with the structure's dimensionality. if self.is_solid and (elem_shape in [QUAD, QUAD_DOMINATED, TRI]): raise ValueError("Structure is a solid," + " but mesh_params.elem_shape is set to '%s'." % elem_shape) if self.is_shell and (elem_shape in [HEX, HEX_DOMINATED, TET, WEDGE]): raise ValueError("Structure is a shell," + " but mesh_params.elem_shape is set to '%s'." % elem_shape) # Validate and set mesh_params.elem_library. if mesh_params.elem_library.upper( ) in auxetic_structure_params.all_elem_library_list: elem_library = abaqusConstants_vars[ mesh_params.elem_library.upper()] # Validate and set mesh_params.elem_code. ## If it's not an iterable, convert into one. if isinstance(mesh_params.elem_code, str): elem_code_iter = (mesh_params.elem_code, ) elif isinstance(mesh_params.elem_code, Iterable): elem_code_iter = mesh_params.elem_code else: raise ValueError('Invalid value for mesh_params.elem_code.') ## Validate over a loop. elem_type_list = [] for elem_code_str in elem_code_iter: # Raises KeyError if elem_code_str is not a SymbolicConstant. # Does not actually check if it's a valid element code. code = abaqusConstants_vars[elem_code_str.upper()] # Create ElemType objects. new_elem_type = ElemType(elemCode=code, elemLibrary=elem_library) if str(type(new_elem_type)) == "<type 'ElemType'>": elem_type_list.append(new_elem_type) else: #Should be None, but I'm not completely sure. raise ValueError( "Invalid value '%s' in mesh_params.elem_code." % code) # Seed the part. part = self.part_main if mesh_params.seed_size is None: raise ValueError('mesh_params.seed_size has not been specified.') part.seedPart(size=mesh_params.seed_size, deviationFactor=0.1, minSizeFactor=0.1) logger.debug('Seed generated.') # Set mesh controls and element type(s). if self.is_shell: part.setMeshControls(regions=part.faces, elemShape=elem_shape) part.setElementType(regions=Region(faces=part.faces), elemTypes=elem_type_list) elif self.is_solid: part.setMeshControls(regions=part.cells, elemShape=elem_shape) part.setElementType(regions=Region(cells=part.cells), elemTypes=elem_type_list) else: raise RuntimeError( 'Both self.is_shell and self.is_solid are False.' + ' This should not happen.') part.generateMesh() logger.debug('Mesh generated.') # Get text stats of element codes and types for logging. # This is a possible bottleneck. #TODO: test for 500K+ elements. elem_stats = dict() for elem in part.elements: elem_type_name = elem.type.name if elem_type_name in elem_stats.keys(): elem_stats[elem_type_name] += 1 else: elem_stats[elem_type_name] = 1 elem_stats_str = elem_stats.__repr__().replace(': ', ':').replace( '{', '').replace('}', '') logger.info("Mesh generation completed with" + " the following number of Abaqus/%s elements: %s." % (elem_library.name.capitalize(), elem_stats_str))
def assign_material(self, material_params): """Assign material properties to the auxetic structure. Note that *material_params.material_data* is not validated. Duck-Typing is used for calling the API and some errors are caught by the API itself, but ultimately any bad values are carried to the CAE model. Args: material_params(MaterialParams): Special namedtuple describing the material used for modeling and analysis. See class for full description of options. Raises: ValueError: If *material_params.hyperelastic* is invalid. ValueError: If *material_params.hyperelastic* is invalid. AbaqusException: Various exceptions raised by the Abaqus API. """ logger.debug('Defining material properties for the structure.') model = self.model part = self.part_main logger.debug('Defining material properties.') material = model.Material(name='material') # Define Elastic property. if material_params.elastic is None: pass elif len(material_params.elastic) == 2: material.Elastic(table=(material_params.elastic, )) logger.debug('Defined elastic property.') else: raise ValueError( 'material_params.elastic must be a Tuple containing two floats.' ) # Define material Density. if material_params.density is not None: material.Density(table=((material_params.density, ), )) logger.debug('Defined material density.') # Define Hyperelastic property. if material_params.hyperelastic is not None: if len(material_params.hyperelastic) == 2: type = material_params.hyperelastic[0] data = material_params.hyperelastic[1] else: raise ValueError( 'material_params.hyperelastic must be a Tuple.') if type == 'ogden': material.Hyperelastic(materialType=ISOTROPIC, type=OGDEN, volumetricResponse=VOLUMETRIC_DATA, table=()) material.hyperelastic.UniaxialTestData(table=data) elif type == 'marlow': material.Hyperelastic(materialType=ISOTROPIC, type=MARLOW, table=()) material.hyperelastic.UniaxialTestData(table=data) else: raise ValueError( 'Invalid value for material_params.hyperelastic[0]') logger.debug( 'Defined hyperelastic property based on the %s material model.', type) logger.debug('Assigning section to the structure.') section = model.HomogeneousSolidSection(name='section', material=material.name, thickness=1.0) region = Region(faces=part.faces, cells=part.cells) part.SectionAssignment(region=region, sectionName=section.name, offset=0.0, offsetType=MIDDLE_SURFACE, offsetField='', thicknessAssignment=FROM_SECTION) logger.debug('Assigned section to the structure.') logger.info('Defined material properties for the structure.')
def periodicBC(modelName, xmin, ymin, xmax, ymax, dispVector): activeModel = mdb.models[modelName] assembly = activeModel.rootAssembly part = activeModel.parts['Specimen'] partEdges = part.edges partInstance = assembly.instances['Specimen'] xmid = ymid = (abs(xmin)+abs(xmax))/2.0 + xmin # Creating faces tol = 0.001 face1Edges = partEdges.getByBoundingBox(xmax-tol, ymin-tol, -1.0, xmax+tol, ymax+tol, 1.0) face1 = part.Set(edges=face1Edges, name='Face 1') face2Edges = partEdges.getByBoundingBox(xmin-tol, ymax-tol, -1.0, xmax+tol, ymax+tol, 1.0) face2 = part.Set(edges=face2Edges, name='Face 2') face3Edges = partEdges.getByBoundingBox(xmin-tol, ymin-tol, -1.0, xmin+tol, ymax+tol, 1.0) face3 = part.Set(edges=face3Edges, name='Face 3') face4Edges = partEdges.getByBoundingBox(xmin-tol, ymin-tol, -1.0, xmax+tol, ymin+tol, 1.0) face4 = part.Set(edges=face4Edges, name='Face 4') # Creating vertices partVertices = part.vertices vertex1 = part.Set(vertices=partVertices.findAt(((xmax, ymax, 0.0), ), ), name='Vertex 1') vertex2 = part.Set(vertices=partVertices.findAt(((xmin, ymax, 0.0), ), ), name='Vertex 2') vertex3 = part.Set(vertices=partVertices.findAt(((xmin, ymin, 0.0), ), ), name='Vertex 3') vertex4 = part.Set(vertices=partVertices.findAt(((xmax, ymin, 0.0), ), ), name='Vertex 4') masterNode1ID = assembly.ReferencePoint(point=(xmid, ymid, 1.0)).id masterNode2ID = assembly.ReferencePoint(point=(xmid, ymid, 2.0)).id masterNode1 = assembly.referencePoints[masterNode1ID] masterNode2 = assembly.referencePoints[masterNode2ID] masterNodeSet1 = assembly.Set(referencePoints=(masterNode1, ), name='MasterNode1') masterNodeSet2 = assembly.Set(referencePoints=(masterNode2, ), name='MasterNode2') masterNodeRegion1 = Region( referencePoints=(assembly.referencePoints[masterNode1ID], )) masterNodeRegion2 = Region( referencePoints=(assembly.referencePoints[masterNode1ID], )) # Construction Pairs of nodes # Face 1 and 3 (right-left) face13Paired = [] face13Paired.append(SortListOfNodes(face1, 1)) face13Paired.append(SortListOfNodes(face3, 1)) # Face 2 and 4 (top-bottom) face24Paired = [] face24Paired.append(TakeVertexOut(SortListOfNodes(face2, 0))) face24Paired.append(TakeVertexOut(SortListOfNodes(face4, 0))) # Top and Bottom faces (2 & 4) for i in range(len(face24Paired[0])): part.Set(name='MasterFace24-'+str(i), nodes=(part.nodes[face24Paired[0][i]:face24Paired[0][i]+1],)) part.Set(name='SlaveFace24-'+str(i), nodes=(part.nodes[face24Paired[1][i]:face24Paired[1][i]+1],)) # (6.14, i=1) activeModel.Equation(name='Constraint24-1-'+str(i), terms=((1.0, 'Specimen.MasterFace24-'+str(i), 1), (-1.0, 'Specimen.SlaveFace24-'+str(i), 1), (1.0, 'MasterNode2', 1))) # (6.14, i=2) activeModel.Equation(name='Constraint24-2-'+str(i), terms=((1.0, 'Specimen.MasterFace24-'+str(i), 2), (-1.0, 'Specimen.SlaveFace24-'+str(i), 2), (1.0, 'MasterNode2', 1))) # Left and Right faces (1 & 3) for j in range(len(face13Paired[0])): part.Set(name='MasterFace13-'+str(j), nodes=(part.nodes[face13Paired[0][j]:face13Paired[0][j]+1],)) part.Set(name='SlaveFace13-'+str(j), nodes=(part.nodes[face13Paired[1][j]:face13Paired[1][j]+1],)) # (6.13, i=1) activeModel.Equation(name='Constraint13-1-'+str(j), terms=((1.0, 'Specimen.MasterFace13-'+str(j), 1), (-1.0, 'Specimen.SlaveFace13-'+str(j), 1), (1.0, 'MasterNode1', 1))) # (6.13, i=2) activeModel.Equation(name='Constraint13-2-'+str(j), terms=((1.0, 'Specimen.MasterFace13-'+str(j), 2), (-1.0, 'Specimen.SlaveFace13-'+str(j), 2), (1.0, 'MasterNode1', 2))) # Apply BCs to master nodes if dispVector[0]: activeModel.DisplacementBC(amplitude=UNSET, createStepName='Loading Step', distributionType=UNIFORM, fieldName='', fixed=OFF, localCsys=None, name='BC-13', region=masterNodeRegion1, u1=dispVector[0], u2=UNSET, ur3=UNSET) if dispVector[1]: activeModel.DisplacementBC(amplitude=UNSET, createStepName='Loading Step', distributionType=UNIFORM, fieldName='', fixed=OFF, localCsys=None, name='BC-24', region=masterNodeRegion2, u1=UNSET, u2=dispVector[1], ur3=UNSET) activeModel.rootAssembly.regenerate()
def create(self): #TODO # for each stringer create a method that will create its part and # translate at the Assembly level already. The part name should be the # stringer name added by an identification number # probably it will be easier to handle the identification number by # creating a StringerConfiguration class, analogously to the # imperfection configuration class from desicos.abaqus import abaqus_functions from regionToolset import Region from abaqus import mdb, session from abaqusConstants import (STANDALONE, THREE_D, DEFORMABLE_BODY, FIXED, QUAD, STRUCTURED, ON, XZPLANE, CARTESIAN, LAMINA, COMPUTED, SURFACE_TO_SURFACE, OFF) cc = self.stringerconf.conecyl mod = mdb.models[cc.model_name] vp = session.viewports[session.currentViewportName] count = 1 for part_name in mod.parts.keys(): if 'Stringer' in part_name: count += 1 self.name = 'StringerBladeComposite_{0:02d}'.format(count) thetarad = np.deg2rad(self.thetadeg) L = cc.L sina = sin(cc.alpharad) cosa = cos(cc.alpharad) rbot = cc.rbot rtop = cc.rtop wbot = self.wbot wtop = self.wtop point1 = (0, 0) point2 = (-wbot, 0) point3 = (-L*sina - wtop, L*cosa) point4 = (-L*sina, L*cosa) # creating part s = mod.ConstrainedSketch(name='__profile__', sheetSize=L) g, v, d, c = s.geometry, s.vertices, s.dimensions, s.constraints s.setPrimaryObject(option=STANDALONE) s.Line(point1=point1, point2=point2) s.Line(point1=point2, point2=point3) s.Line(point1=point3, point2=point4) s.Line(point1=point4, point2=point1) part = mod.Part(name=self.name, dimensionality=THREE_D, type=DEFORMABLE_BODY) part.BaseShell(sketch=s) s.unsetPrimaryObject() vp.setValues(displayedObject=part) del mod.sketches['__profile__'] # partitioning along the meridian for pt in cc.pts: plane = part.DatumPlaneByPrincipalPlane( principalPlane=XZPLANE, offset=pt*cc.H) part.PartitionFaceByDatumPlane(datumPlane=part.datums[plane.id], faces=part.faces) # material properties same_laminaprop = True for laminaprop in self.laminaprops: if laminaprop != self.laminaprops[0]: same_lamiaprop = False break material_type = LAMINA if same_laminaprop: mat_name = 'MatStringer_{0:02d}'.format(count) mat_names = [mat_name for _ in self.laminaprops] myMat = mod.Material(name=mat_name) myMat.Elastic(table=(laminaprop,), type=material_type) else: mat_names = [] for i, laminaprop in enumerate(self.laminaprops): mat_name = 'MatStringer_{0:02d}_ply_{0:02d}'.format(count, i+1) mat_names.append(mat_name) myMat = mod.Material(name=mat_name) myMat.Elastic(table=(laminaprop,), type=material_type) csys_name = 'CsysStringer_{0:02d}'.format(count) csys = part.DatumCsysByThreePoints(point1=(-L*sina, L*cosa, 0), point2=(-wbot, 0, 0), name=csys_name, coordSysType=CARTESIAN, origin=(0.0, 0.0, 0.0)) csys_datum = part.datums[csys.id] abaqus_functions.create_composite_layup( name='LayupStringer_{0:02d}'.format(count), stack=self.stack, plyts=self.plyts, mat_names=mat_names, part=part, part_csys=csys_datum, region=Region(faces=part.faces), axis_normal=3) # meshing part # flange edge = part.edges.findAt((-wbot/2., 0., 0.)) part.seedEdgeByNumber(edges=(edge,), number=self.numel_flange, constraint=FIXED) # meridian coords = [] for f in np.linspace(0.01, 0.99, 100): Li = f*L coords.append(((-Li*sina, Li*cosa, 0.),)) edges = part.edges.findAt(*coords) part.seedEdgeBySize(edges=edges, size=cc.mesh_size, constraint=FIXED) part.setMeshControls(regions=part.faces, elemShape=QUAD, technique=STRUCTURED) part.generateMesh() # assemblying part ra = mod.rootAssembly ra.Instance(name=self.name, part=part, dependent=ON) ra.rotate(instanceList=(self.name,), axisPoint=(0.0, 0.0, 0.0), axisDirection=(1.0, 0.0, 0.0), angle=90.0) if self.thetadeg > 0: ra.rotate(instanceList=(self.name,), axisPoint=(0.0, 0.0, 0.0), axisDirection=(0.0, 0.0, 1.0), angle=self.thetadeg) ra.translate(instanceList=(self.name,), vector=(rbot*cos(thetarad), rbot*sin(thetarad), 0.)) vp.setValues(displayedObject=ra) # tieing stringer to the shell surface inst_shell = ra.instances['INST_SHELL'] side2Faces1 = inst_shell.faces region1 = Region(side2Faces=side2Faces1) inst_stringer_faces = ra.instances[self.name].faces region2 = Region(side2Faces=inst_stringer_faces) tie_name = 'TieStringer_{0:02d}'.format(count) mod.Tie(name=tie_name, master=region1, slave=region2, positionToleranceMethod=COMPUTED, adjust=OFF, tieRotations=ON, constraintEnforcement=SURFACE_TO_SURFACE, thickness=ON) # output request hist_name = 'HistoryOutStringer_{0:02d}'.format(count) mod.FieldOutputRequest(name=hist_name, createStepName=cc.step1Name, variables=('U',))
def periodicBC(modelName, xmin, ymin, xmax, ymax, strain): activeModel = mdb.models[modelName] assembly = activeModel.rootAssembly part = activeModel.parts['Specimen'] partEdges = part.edges partInstance = assembly.instances['Specimen'] xmid = ymid = (abs(xmin) + abs(xmax)) / 2.0 + xmin # Creating faces tol = 0.001 face1Edges = partEdges.getByBoundingBox(xmax - tol, ymin - tol, -1.0, xmax + tol, ymax + tol, 1.0) face1 = part.Set(edges=face1Edges, name='Face 1') face2Edges = partEdges.getByBoundingBox(xmin - tol, ymax - tol, -1.0, xmax + tol, ymax + tol, 1.0) face2 = part.Set(edges=face2Edges, name='Face 2') face3Edges = partEdges.getByBoundingBox(xmin - tol, ymin - tol, -1.0, xmin + tol, ymax + tol, 1.0) face3 = part.Set(edges=face3Edges, name='Face 3') face4Edges = partEdges.getByBoundingBox(xmin - tol, ymin - tol, -1.0, xmax + tol, ymin + tol, 1.0) face4 = part.Set(edges=face4Edges, name='Face 4') # Creating vertices partVertices = part.vertices vertex1 = part.Set(vertices=partVertices.findAt(((xmax, ymax, 0.0), ), ), name='Vertex 1') vertex2 = part.Set(vertices=partVertices.findAt(((xmin, ymax, 0.0), ), ), name='Vertex 2') vertex3 = part.Set(vertices=partVertices.findAt(((xmin, ymin, 0.0), ), ), name='Vertex 3') vertex4 = part.Set(vertices=partVertices.findAt(((xmax, ymin, 0.0), ), ), name='Vertex 4') masterNodeID = part.ReferencePoint(point=(xmid, ymid, 0.0)).id masterNode = part.referencePoints[masterNodeID] masterNodeSet = part.Set(referencePoints=(masterNode, ), name='MasterNode') masterNodeRegion = Region( referencePoints=(partInstance.referencePoints[masterNodeID], )) activeModel.DisplacementBC(amplitude=UNSET, createStepName='Loading Step', distributionType=UNIFORM, fieldName='', fixed=OFF, localCsys=None, name='BC-1', region=masterNodeRegion, u1=1.0, u2=UNSET, ur3=UNSET) # Construction Pairs of nodes # Face 1 and 3 (right-left) face13Paired = [] face13Paired.append(TakeVertexOut(SortListOfNodes(face1, 1))) face13Paired.append(TakeVertexOut(SortListOfNodes(face3, 1))) # Face 2 and 4 (top-bottom) face24Paired = [] face24Paired.append(TakeVertexOut(SortListOfNodes(face2, 0))) face24Paired.append(TakeVertexOut(SortListOfNodes(face4, 0))) # Create constraint equations # Vertices # Master V1 (Contained in 1 and 3) activeModel.Equation( name='ConstraintV1-V3-1', terms=((1.0, 'Specimen.Vertex 1', 1), (-1.0, 'Specimen.Vertex 3', 1), (-strain[0] * (vertex1.nodes[-1].coordinates[0] - vertex3.nodes[-1].coordinates[0]) + -strain[2] / 2. * (vertex1.nodes[-1].coordinates[1] - vertex3.nodes[-1].coordinates[1]), 'Specimen.MasterNode', 1))) activeModel.Equation( name='ConstraintV1-V3-2', terms=((1.0, 'Specimen.Vertex 1', 2), (-1.0, 'Specimen.Vertex 3', 2), (-strain[2] / 2. * (vertex1.nodes[-1].coordinates[0] - vertex3.nodes[-1].coordinates[0]) + -strain[1] * (vertex1.nodes[-1].coordinates[1] - vertex3.nodes[-1].coordinates[1]), 'Specimen.MasterNode', 1))) # Master V2 (Contained in 2 and 4) activeModel.Equation( name='ConstraintV2-V4-1', terms=((1.0, 'Specimen.Vertex 2', 1), (-1.0, 'Specimen.Vertex 4', 1), (strain[2] / 2. * (vertex4.nodes[-1].coordinates[1] - vertex2.nodes[-1].coordinates[1]) + strain[0] * (vertex4.nodes[-1].coordinates[0] - vertex2.nodes[-1].coordinates[0]), 'Specimen.MasterNode', 1))) activeModel.Equation( name='ConstraintV2-V4-2', terms=((1.0, 'Specimen.Vertex 2', 2), (-1.0, 'Specimen.Vertex 4', 2), (-strain[1] * (vertex2.nodes[-1].coordinates[1] - vertex4.nodes[-1].coordinates[1]) - strain[2] / 2. * (vertex2.nodes[-1].coordinates[0] - vertex4.nodes[-1].coordinates[0]), 'Specimen.MasterNode', 1))) # For the edges for ii in range(len(face13Paired[0])): part.Set(name='MasterFace13-' + str(ii), nodes=(part.nodes[face13Paired[0][ii]:face13Paired[0][ii] + 1], )) part.Set(name='SlaveFace13-' + str(ii), nodes=(part.nodes[face13Paired[1][ii]:face13Paired[1][ii] + 1], )) # (6.13, i=1) activeModel.Equation( name='Constraint13-1-' + str(ii), terms=((1.0, 'Specimen.MasterFace13-' + str(ii), 1), (-1.0, 'Specimen.SlaveFace13-' + str(ii), 1), (-strain[0] * (part.nodes[face13Paired[0][ii]].coordinates[0] - part.nodes[face13Paired[1][ii]].coordinates[0]), 'Specimen.MasterNode', 1))) # (6.13, i=2) activeModel.Equation( name='Constraint13-2-' + str(ii), terms=((1.0, 'Specimen.MasterFace13-' + str(ii), 2), (-1.0, 'Specimen.SlaveFace13-' + str(ii), 2), (-strain[2] / 2. * (part.nodes[face13Paired[0][ii]].coordinates[0] - part.nodes[face13Paired[1][ii]].coordinates[0]), 'Specimen.MasterNode', 1))) for ii in range(len(face24Paired[0])): part.Set(name='MasterFace24-' + str(ii), nodes=(part.nodes[face24Paired[0][ii]:face24Paired[0][ii] + 1], )) part.Set(name='SlaveFace24-' + str(ii), nodes=(part.nodes[face24Paired[1][ii]:face24Paired[1][ii] + 1], )) # (6.14, i=1) activeModel.Equation( name='Constraint24-1-' + str(ii), terms=((1.0, 'Specimen.MasterFace24-' + str(ii), 1), (-1.0, 'Specimen.SlaveFace24-' + str(ii), 1), (-strain[2] / 2. * (part.nodes[face24Paired[0][ii]].coordinates[1] - part.nodes[face24Paired[1][ii]].coordinates[1]), 'Specimen.MasterNode', 1))) # (6.14, i=2) activeModel.Equation( name='Constraint24-2-' + str(ii), terms=((1.0, 'Specimen.MasterFace24-' + str(ii), 2), (-1.0, 'Specimen.SlaveFace24-' + str(ii), 2), (-strain[1] * (part.nodes[face24Paired[0][ii]].coordinates[1] - part.nodes[face24Paired[1][ii]].coordinates[1]), 'Specimen.MasterNode', 1))) activeModel.rootAssembly.regenerate()