def generateBaseMesh(cls, region, options): """ Generate the base tricubic Hermite mesh. :param region: Zinc region to define model in. Must be empty. :param options: Dict containing options. See getDefaultOptions(). :return: list of AnnotationGroup """ # set dependent outer diameter used in atria2 options['LV outlet outer diameter'] = options[ 'LV outlet inner diameter'] + 2.0 * options[ 'LV outlet wall thickness'] fm = region.getFieldmodule() fm.beginChange() coordinates = findOrCreateFieldCoordinates(fm) cache = fm.createFieldcache() # generate heartventriclesbase2 model and put atria2 on it ventriclesAnnotationGroups = MeshType_3d_heartventriclesbase2.generateBaseMesh( region, options) atriaAnnotationGroups = MeshType_3d_heartatria2.generateBaseMesh( region, options) annotationGroups = mergeAnnotationGroups(ventriclesAnnotationGroups, atriaAnnotationGroups) fm.endChange() return annotationGroups
def generateBaseMesh(cls, region, options): """ Generate the base tricubic Hermite mesh. :param region: Zinc region to define model in. Must be empty. :param options: Dict containing options. See getDefaultOptions(). :return: list of AnnotationGroup """ # set dependent outer diameter used in atria2 options['Aorta outer plus diameter'] = options[ 'LV outlet inner diameter'] + 2.0 * options[ 'LV outlet wall thickness'] elementsCountAroundAtrialSeptum = options[ 'Number of elements around atrial septum'] elementsCountAroundLeftAtriumFreeWall = options[ 'Number of elements around left atrium free wall'] elementsCountAroundLeftAtrium = elementsCountAroundLeftAtriumFreeWall + elementsCountAroundAtrialSeptum elementsCountAroundRightAtriumFreeWall = options[ 'Number of elements around right atrium free wall'] elementsCountAroundRightAtrium = elementsCountAroundRightAtriumFreeWall + elementsCountAroundAtrialSeptum useCrossDerivatives = False fm = region.getFieldmodule() coordinates = findOrCreateFieldCoordinates(fm) cache = fm.createFieldcache() mesh = fm.findMeshByDimension(3) # generate heartventriclesbase1 model and put atria1 on it ventriclesAnnotationGroups = MeshType_3d_heartventriclesbase1.generateBaseMesh( region, options) atriaAnnotationGroups = MeshType_3d_heartatria1.generateBaseMesh( region, options) annotationGroups = mergeAnnotationGroups(ventriclesAnnotationGroups, atriaAnnotationGroups) lFibrousRingGroup = findOrCreateAnnotationGroupForTerm( annotationGroups, region, get_heart_term("left fibrous ring")) rFibrousRingGroup = findOrCreateAnnotationGroupForTerm( annotationGroups, region, get_heart_term("right fibrous ring")) # annotation fiducial points markerGroup = findOrCreateFieldGroup(fm, "marker") markerName = findOrCreateFieldStoredString(fm, name="marker_name") markerLocation = findOrCreateFieldStoredMeshLocation( fm, mesh, name="marker_location") nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) markerPoints = findOrCreateFieldNodeGroup(markerGroup, nodes).getNodesetGroup() markerTemplateInternal = nodes.createNodetemplate() markerTemplateInternal.defineField(markerName) markerTemplateInternal.defineField(markerLocation) ############## # Create nodes ############## nodeIdentifier = max(1, getMaximumNodeIdentifier(nodes) + 1) # discover left and right fibrous ring nodes from ventricles and atria # because nodes are iterated in identifier order, the lowest and first are on the lv outlet cfb, right and left on lower outer layers # left fibrous ring lavNodeId = [[[], []], [[], []]] # [n3][n2][n1] iter = lFibrousRingGroup.getNodesetGroup(nodes).createNodeiterator() # left fibrous ring, bottom row cfbNodeId = iter.next().getIdentifier() cfbLeftNodeId = iter.next().getIdentifier() for n1 in range(elementsCountAroundLeftAtrium): lavNodeId[0][0].append(iter.next().getIdentifier()) lavNodeId[1][0].append(cfbNodeId) lavNodeId[1][0].append(cfbLeftNodeId) for n1 in range(elementsCountAroundLeftAtriumFreeWall - 1): lavNodeId[1][0].append(iter.next().getIdentifier()) for n1 in range(elementsCountAroundAtrialSeptum - 1): lavNodeId[1][0].append(None) # no outer node on interatrial septum # left fibrous ring, top row for n1 in range(elementsCountAroundLeftAtrium): lavNodeId[0][1].append(iter.next().getIdentifier()) for n1 in range(elementsCountAroundLeftAtriumFreeWall + 1): lavNodeId[1][1].append(iter.next().getIdentifier()) for n1 in range(elementsCountAroundAtrialSeptum - 1): lavNodeId[1][1].append(None) # no outer node on interatrial septum # right fibrous ring ravNodeId = [[[], []], [[], []]] # [n3][n2][n1] iter = rFibrousRingGroup.getNodesetGroup(nodes).createNodeiterator() cfbNodeId = iter.next().getIdentifier() cfbRightNodeId = iter.next().getIdentifier() # right fibrous ring, bottom row for n1 in range(elementsCountAroundRightAtrium): ravNodeId[0][0].append(iter.next().getIdentifier()) for n1 in range(elementsCountAroundRightAtriumFreeWall - 1): ravNodeId[1][0].append(iter.next().getIdentifier()) ravNodeId[1][0].append(cfbRightNodeId) ravNodeId[1][0].append(cfbNodeId) for n1 in range(elementsCountAroundAtrialSeptum - 1): ravNodeId[1][0].append(None) # no outer node on interatrial septum # right fibrous ring, top row for n1 in range(elementsCountAroundRightAtrium): ravNodeId[0][1].append(iter.next().getIdentifier()) cfbUpperNodeId = iter.next().getIdentifier( ) # cfb from left will be first for n1 in range(elementsCountAroundRightAtriumFreeWall): ravNodeId[1][1].append(iter.next().getIdentifier()) ravNodeId[1][1].append(cfbUpperNodeId) for n1 in range(elementsCountAroundAtrialSeptum - 1): ravNodeId[1][1].append(None) # no outer node on interatrial septum #for n2 in range(2): # print('n2', n2) # print('lavNodeId[0]', lavNodeId[0][n2]) # print('lavNodeId[1]', lavNodeId[1][n2]) # print('ravNodeId[0]', ravNodeId[0][n2]) # print('ravNodeId[1]', ravNodeId[1][n2]) ################# # Create elements ################# lFibrousRingMeshGroup = lFibrousRingGroup.getMeshGroup(mesh) rFibrousRingMeshGroup = rFibrousRingGroup.getMeshGroup(mesh) elementIdentifier = getMaximumElementIdentifier(mesh) + 1 elementtemplate1 = mesh.createElementtemplate() elementtemplate1.setElementShapeType(Element.SHAPE_TYPE_CUBE) # create fibrous ring elements bicubichermitelinear = eftfactory_bicubichermitelinear( mesh, useCrossDerivatives, linearAxis=2, d_ds1=Node.VALUE_LABEL_D_DS1, d_ds2=Node.VALUE_LABEL_D_DS3) eftFibrousRing = bicubichermitelinear.createEftBasic() # left fibrous ring, starting at crux / collapsed posterior interatrial sulcus cruxElementId = None for e in range(-1, elementsCountAroundLeftAtriumFreeWall): eft1 = eftFibrousRing n1 = e nids = [ lavNodeId[0][0][n1], lavNodeId[0][0][n1 + 1], lavNodeId[0][1][n1], lavNodeId[0][1][n1 + 1], lavNodeId[1][0][n1], lavNodeId[1][0][n1 + 1], lavNodeId[1][1][n1], lavNodeId[1][1][n1 + 1] ] scalefactors = None meshGroups = [lFibrousRingMeshGroup] if e == -1: # interatrial groove straddles left and right atria, collapsed to 6 node wedge nids[0] = ravNodeId[0][0][ elementsCountAroundRightAtriumFreeWall] nids[2] = ravNodeId[0][1][ elementsCountAroundRightAtriumFreeWall] nids.pop(6) nids.pop(4) eft1 = bicubichermitelinear.createEftNoCrossDerivatives() setEftScaleFactorIds(eft1, [1], []) scalefactors = [-1.0] remapEftNodeValueLabel(eft1, [1, 3], Node.VALUE_LABEL_D_DS1, [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS3, [])]) remapEftNodeValueLabel(eft1, [2, 4], Node.VALUE_LABEL_D_DS1, [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS3, [1])]) remapEftNodeValueLabel(eft1, [5, 6, 7, 8], Node.VALUE_LABEL_D_DS1, []) # reverse d3 on cfb: remapEftNodeValueLabel(eft1, [5], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS3, [1])]) remapEftNodeValueLabel(eft1, [6], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, [0]), (Node.VALUE_LABEL_D_DS3, [1])]) remapEftNodeValueLabel(eft1, [7], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS3, [])]) remapEftNodeValueLabel(eft1, [8], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS3, [])]) ln_map = [1, 2, 3, 4, 5, 5, 6, 6] remapEftLocalNodes(eft1, 6, ln_map) meshGroups += [rFibrousRingMeshGroup] elif e == 0: # general linear map d3 adjacent to collapsed sulcus eft1 = bicubichermitelinear.createEftNoCrossDerivatives() setEftScaleFactorIds(eft1, [1], []) scalefactors = [-1.0] # reverse d1, d3 on cfb, left cfb: scaleEftNodeValueLabels( eft1, [6], [Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS3], [1]) remapEftNodeValueLabel(eft1, [5], Node.VALUE_LABEL_D_DS1, [(Node.VALUE_LABEL_D_DS1, [1])]) remapEftNodeValueLabel(eft1, [5], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS3, [1])]) remapEftNodeValueLabel(eft1, [7], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS3, [])]) elif e == 1: # reverse d1, d3 on left cfb: eft1 = bicubichermitelinear.createEftNoCrossDerivatives() setEftScaleFactorIds(eft1, [1], []) scalefactors = [-1.0] remapEftNodeValueLabel(eft1, [5], Node.VALUE_LABEL_D_DS1, [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS3, [])]) remapEftNodeValueLabel(eft1, [5], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS3, [1])]) elif e == (elementsCountAroundLeftAtriumFreeWall - 1): # general linear map d3 adjacent to collapsed sulcus eft1 = bicubichermitelinear.createEftNoCrossDerivatives() setEftScaleFactorIds(eft1, [1], []) scalefactors = [-1.0] remapEftNodeValueLabel(eft1, [6, 8], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS3, [])]) result = elementtemplate1.defineField(coordinates, -1, eft1) element = mesh.createElement(elementIdentifier, elementtemplate1) result2 = element.setNodesByIdentifier(eft1, nids) result3 = element.setScaleFactors( eft1, scalefactors) if scalefactors else None #print('create element fibrous ring left', elementIdentifier, result, result2, result3, nids) elementIdentifier += 1 for meshGroup in meshGroups: meshGroup.addElement(element) # right fibrous ring, starting at crux / collapsed posterior interatrial sulcus for e in range(-1, elementsCountAroundRightAtriumFreeWall): eft1 = eftFibrousRing n1 = e nids = [ ravNodeId[0][0][n1], ravNodeId[0][0][n1 + 1], ravNodeId[0][1][n1], ravNodeId[0][1][n1 + 1], ravNodeId[1][0][n1], ravNodeId[1][0][n1 + 1], ravNodeId[1][1][n1], ravNodeId[1][1][n1 + 1] ] scalefactors = None meshGroups = [rFibrousRingMeshGroup] if e == -1: # interatrial groove straddles left and right atria, collapsed to 6 node wedge nids[0] = lavNodeId[0][0][ elementsCountAroundLeftAtriumFreeWall] nids[2] = lavNodeId[0][1][ elementsCountAroundLeftAtriumFreeWall] nids.pop(6) nids.pop(4) eft1 = bicubichermitelinear.createEftNoCrossDerivatives() setEftScaleFactorIds(eft1, [1], []) scalefactors = [-1.0] remapEftNodeValueLabel(eft1, [1, 3], Node.VALUE_LABEL_D_DS1, [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS3, [])]) remapEftNodeValueLabel(eft1, [2, 4], Node.VALUE_LABEL_D_DS1, [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS3, [1])]) remapEftNodeValueLabel(eft1, [5, 6, 7, 8], Node.VALUE_LABEL_D_DS1, []) remapEftNodeValueLabel(eft1, [5, 7], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS3, [])]) remapEftNodeValueLabel(eft1, [6, 8], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS3, [])]) ln_map = [1, 2, 3, 4, 5, 5, 6, 6] remapEftLocalNodes(eft1, 6, ln_map) meshGroups += [lFibrousRingMeshGroup] cruxElementId = elementIdentifier elif e == 0: # general linear map d3 adjacent to collapsed crux/posterior sulcus eft1 = bicubichermitelinear.createEftNoCrossDerivatives() setEftScaleFactorIds(eft1, [1], []) scalefactors = [-1.0] remapEftNodeValueLabel(eft1, [5, 7], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS3, [])]) elif e == (elementsCountAroundRightAtriumFreeWall - 2): # reverse d1, d3 on right cfb: eft1 = bicubichermitelinear.createEftNoCrossDerivatives() setEftScaleFactorIds(eft1, [1], []) scalefactors = [-1.0] remapEftNodeValueLabel(eft1, [6], Node.VALUE_LABEL_D_DS1, [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS3, [1])]) remapEftNodeValueLabel(eft1, [6], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS3, [1])]) elif e == (elementsCountAroundRightAtriumFreeWall - 1): # general linear map d3 adjacent to collapsed cfb/anterior sulcus eft1 = bicubichermitelinear.createEftNoCrossDerivatives() setEftScaleFactorIds(eft1, [1], []) scalefactors = [-1.0] # reverse d1, d3 on right cfb, cfb: scaleEftNodeValueLabels( eft1, [5], [Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS3], [1]) remapEftNodeValueLabel(eft1, [6], Node.VALUE_LABEL_D_DS1, [(Node.VALUE_LABEL_D_DS1, [1])]) remapEftNodeValueLabel(eft1, [6], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS3, [1])]) remapEftNodeValueLabel(eft1, [8], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS3, [])]) result = elementtemplate1.defineField(coordinates, -1, eft1) element = mesh.createElement(elementIdentifier, elementtemplate1) result2 = element.setNodesByIdentifier(eft1, nids) result3 = element.setScaleFactors( eft1, scalefactors) if scalefactors else None #print('create element fibrous ring right', elementIdentifier, result, result2, result3, nids) elementIdentifier += 1 for meshGroup in meshGroups: meshGroup.addElement(element) # fibrous ring septum: meshGroups = [lFibrousRingMeshGroup, rFibrousRingMeshGroup] for e in range(elementsCountAroundAtrialSeptum): eft1 = eftFibrousRing nlm = e - elementsCountAroundAtrialSeptum nlp = nlm + 1 nrm = -e nrp = nrm - 1 nids = [ lavNodeId[0][0][nlm], lavNodeId[0][0][nlp], lavNodeId[0][1][nlm], lavNodeId[0][1][nlp], ravNodeId[0][0][nrm], ravNodeId[0][0][nrp], ravNodeId[0][1][nrm], ravNodeId[0][1][nrp] ] eft1 = bicubichermitelinear.createEftNoCrossDerivatives() setEftScaleFactorIds(eft1, [1], []) scalefactors = [-1.0] if e == 0: # general linear map d3 adjacent to collapsed posterior interventricular sulcus scaleEftNodeValueLabels(eft1, [5, 6, 7, 8], [Node.VALUE_LABEL_D_DS1], [1]) scaleEftNodeValueLabels(eft1, [6, 8], [Node.VALUE_LABEL_D_DS3], [1]) remapEftNodeValueLabel(eft1, [1, 3], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS3, [])]) remapEftNodeValueLabel(eft1, [5, 7], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS3, [1])]) elif e == (elementsCountAroundAtrialSeptum - 1): # general linear map d3 adjacent to cfb scaleEftNodeValueLabels(eft1, [5, 6, 7, 8], [Node.VALUE_LABEL_D_DS1], [1]) scaleEftNodeValueLabels(eft1, [5, 7], [Node.VALUE_LABEL_D_DS3], [1]) remapEftNodeValueLabel(eft1, [2, 4], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS3, [])]) remapEftNodeValueLabel(eft1, [6, 8], Node.VALUE_LABEL_D_DS3, [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS3, [1])]) else: scaleEftNodeValueLabels( eft1, [5, 6, 7, 8], [Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS3], [1]) result = elementtemplate1.defineField(coordinates, -1, eft1) element = mesh.createElement(elementIdentifier, elementtemplate1) result2 = element.setNodesByIdentifier(eft1, nids) result3 = element.setScaleFactors( eft1, scalefactors) if scalefactors else None #print('create element fibrous ring septum', elementIdentifier, result, result2, result3, nids) elementIdentifier += 1 for meshGroup in meshGroups: meshGroup.addElement(element) # annotation fiducial points cruxElement = mesh.findElementByIdentifier(cruxElementId) cruxXi = [0.5, 0.5, 1.0] cache.setMeshLocation(cruxElement, cruxXi) result, cruxCoordinates = coordinates.evaluateReal(cache, 3) markerPoint = markerPoints.createNode(nodeIdentifier, markerTemplateInternal) nodeIdentifier += 1 cache.setNode(markerPoint) markerName.assignString(cache, "crux of heart") markerLocation.assignMeshLocation(cache, cruxElement, cruxXi) return annotationGroups
def createNodesAndElements(region, x, d1, d2, d3, xFlat, d1Flat, d2Flat, xOrgan, d1Organ, d2Organ, organCoordinateFieldName, elementsCountAround, elementsCountAlong, elementsCountThroughWall, annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, firstNodeIdentifier, firstElementIdentifier, useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd): """ Create nodes and elements for the coordinates and flat coordinates fields. :param x, d1, d2, d3: coordinates and derivatives of coordinates field. :param xFlat, d1Flat, d2Flat, d3Flat: coordinates and derivatives of flat coordinates field. :param xOrgan, d1Organ, d2Organ, d3Organ, organCoordinateFieldName: coordinates, derivatives and name of organ coordinates field. :param elementsCountAround: Number of elements around tube. :param elementsCountAlong: Number of elements along tube. :param elementsCountThroughWall: Number of elements through wall. :param annotationGroupsAround: Annotation groups of elements around. :param annotationGroupsAlong: Annotation groups of elements along. :param annotationGroupsThroughWall: Annotation groups of elements through wall. :param firstNodeIdentifier, firstElementIdentifier: first node and element identifier to use. :param useCubicHermiteThroughWall: use linear when false :param useCrossDerivatives: use cross derivatives when true :return nodeIdentifier, elementIdentifier, allAnnotationGroups """ nodeIdentifier = firstNodeIdentifier elementIdentifier = firstElementIdentifier zero = [0.0, 0.0, 0.0] fm = region.getFieldmodule() fm.beginChange() cache = fm.createFieldcache() # Coordinates field coordinates = findOrCreateFieldCoordinates(fm) nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) nodetemplate = nodes.createNodetemplate() nodetemplate.defineField(coordinates) nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_VALUE, 1) nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS1, 1) nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS2, 1) if useCrossDerivatives: nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D2_DS1DS2, 1) if useCubicHermiteThroughWall: nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS3, 1) if useCrossDerivatives: nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D2_DS1DS3, 1) nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D2_DS2DS3, 1) nodetemplate.setValueNumberOfVersions( coordinates, -1, Node.VALUE_LABEL_D3_DS1DS2DS3, 1) mesh = fm.findMeshByDimension(3) if useCubicHermiteThroughWall: eftfactory = eftfactory_tricubichermite(mesh, useCrossDerivatives) else: eftfactory = eftfactory_bicubichermitelinear(mesh, useCrossDerivatives) eft = eftfactory.createEftBasic() elementtemplate = mesh.createElementtemplate() elementtemplate.setElementShapeType(Element.SHAPE_TYPE_CUBE) result = elementtemplate.defineField(coordinates, -1, eft) if xFlat: # Flat coordinates field bicubichermitelinear = eftfactory_bicubichermitelinear( mesh, useCrossDerivatives) eftFlat1 = bicubichermitelinear.createEftBasic() eftFlat2 = bicubichermitelinear.createEftOpenTube() flatCoordinates = findOrCreateFieldCoordinates(fm, name="flat coordinates") flatNodetemplate1 = nodes.createNodetemplate() flatNodetemplate1.defineField(flatCoordinates) flatNodetemplate1.setValueNumberOfVersions(flatCoordinates, -1, Node.VALUE_LABEL_VALUE, 1) flatNodetemplate1.setValueNumberOfVersions(flatCoordinates, -1, Node.VALUE_LABEL_D_DS1, 1) flatNodetemplate1.setValueNumberOfVersions(flatCoordinates, -1, Node.VALUE_LABEL_D_DS2, 1) if useCrossDerivatives: flatNodetemplate1.setValueNumberOfVersions( flatCoordinates, -1, Node.VALUE_LABEL_D2_DS1DS2, 1) flatNodetemplate2 = nodes.createNodetemplate() flatNodetemplate2.defineField(flatCoordinates) flatNodetemplate2.setValueNumberOfVersions(flatCoordinates, -1, Node.VALUE_LABEL_VALUE, 2) flatNodetemplate2.setValueNumberOfVersions(flatCoordinates, -1, Node.VALUE_LABEL_D_DS1, 2) flatNodetemplate2.setValueNumberOfVersions(flatCoordinates, -1, Node.VALUE_LABEL_D_DS2, 2) if useCrossDerivatives: flatNodetemplate2.setValueNumberOfVersions( flatCoordinates, -1, Node.VALUE_LABEL_D2_DS1DS2, 2) flatElementtemplate1 = mesh.createElementtemplate() flatElementtemplate1.setElementShapeType(Element.SHAPE_TYPE_CUBE) flatElementtemplate1.defineField(flatCoordinates, -1, eftFlat1) flatElementtemplate2 = mesh.createElementtemplate() flatElementtemplate2.setElementShapeType(Element.SHAPE_TYPE_CUBE) flatElementtemplate2.defineField(flatCoordinates, -1, eftFlat2) if xOrgan: # Organ coordinates field bicubichermitelinear = eftfactory_bicubichermitelinear( mesh, useCrossDerivatives) eftOrgan = bicubichermitelinear.createEftBasic() organCoordinates = findOrCreateFieldCoordinates( fm, name=organCoordinateFieldName) organNodetemplate = nodes.createNodetemplate() organNodetemplate.defineField(organCoordinates) organNodetemplate.setValueNumberOfVersions(organCoordinates, -1, Node.VALUE_LABEL_VALUE, 1) organNodetemplate.setValueNumberOfVersions(organCoordinates, -1, Node.VALUE_LABEL_D_DS1, 1) organNodetemplate.setValueNumberOfVersions(organCoordinates, -1, Node.VALUE_LABEL_D_DS2, 1) if useCrossDerivatives: organNodetemplate.setValueNumberOfVersions( organCoordinates, -1, Node.VALUE_LABEL_D2_DS1DS2, 1) organElementtemplate = mesh.createElementtemplate() organElementtemplate.setElementShapeType(Element.SHAPE_TYPE_CUBE) organElementtemplate.defineField(organCoordinates, -1, eftOrgan) # Create nodes # Coordinates field for n in range(len(x)): node = nodes.createNode(nodeIdentifier, nodetemplate) cache.setNode(node) coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, x[n]) coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, d1[n]) coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, d2[n]) coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, d3[n]) if useCrossDerivatives: coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D2_DS1DS2, 1, zero) coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D2_DS1DS3, 1, zero) coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D2_DS2DS3, 1, zero) coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D3_DS1DS2DS3, 1, zero) # print('NodeIdentifier = ', nodeIdentifier, x[n], d1[n], d2[n]) nodeIdentifier = nodeIdentifier + 1 # Flat coordinates field if xFlat: nodeIdentifier = firstNodeIdentifier for n2 in range(elementsCountAlong + 1): for n3 in range(elementsCountThroughWall + 1): for n1 in range(elementsCountAround): i = n2 * (elementsCountAround + 1) * (elementsCountThroughWall + 1) + (elementsCountAround + 1) * n3 + n1 node = nodes.findNodeByIdentifier(nodeIdentifier) node.merge(flatNodetemplate2 if n1 == 0 else flatNodetemplate1) cache.setNode(node) # print('NodeIdentifier', nodeIdentifier, 'version 1, xList Index =', i+1) flatCoordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, xFlat[i]) flatCoordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, d1Flat[i]) flatCoordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, d2Flat[i]) if useCrossDerivatives: flatCoordinates.setNodeParameters( cache, -1, Node.VALUE_LABEL_D2_DS1DS2, 1, zero) if n1 == 0: # print('NodeIdentifier', nodeIdentifier, 'version 2, xList Index =', i+elementsCountAround+1) flatCoordinates.setNodeParameters( cache, -1, Node.VALUE_LABEL_VALUE, 2, xFlat[i + elementsCountAround]) flatCoordinates.setNodeParameters( cache, -1, Node.VALUE_LABEL_D_DS1, 2, d1Flat[i + elementsCountAround]) flatCoordinates.setNodeParameters( cache, -1, Node.VALUE_LABEL_D_DS2, 2, d2Flat[i + elementsCountAround]) if useCrossDerivatives: flatCoordinates.setNodeParameters( cache, -1, Node.VALUE_LABEL_D2_DS1DS2, 2, zero) nodeIdentifier = nodeIdentifier + 1 # Organ coordinates field if xOrgan: nodeIdentifier = firstNodeIdentifier for n in range(len(xOrgan)): node = nodes.findNodeByIdentifier(nodeIdentifier) node.merge(organNodetemplate) cache.setNode(node) organCoordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, xOrgan[n]) organCoordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, d1Organ[n]) organCoordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, d2Organ[n]) if useCrossDerivatives: organCoordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D2_DS1DS2, 1, zero) nodeIdentifier = nodeIdentifier + 1 # create elements elementtemplate3 = mesh.createElementtemplate() elementtemplate3.setElementShapeType(Element.SHAPE_TYPE_CUBE) radiansPerElementAround = math.pi * 2.0 / elementsCountAround allAnnotationGroups = [] if closedProximalEnd: # Create apex for e3 in range(elementsCountThroughWall): for e1 in range(elementsCountAround): va = e1 vb = (e1 + 1) % elementsCountAround eft1 = eftfactory.createEftShellPoleBottom(va * 100, vb * 100) elementtemplate3.defineField(coordinates, -1, eft1) element = mesh.createElement(elementIdentifier, elementtemplate3) bni1 = e3 + 1 bni2 = elementsCountThroughWall + 1 + elementsCountAround * e3 + e1 + 1 bni3 = elementsCountThroughWall + 1 + elementsCountAround * e3 + ( e1 + 1) % elementsCountAround + 1 nodeIdentifiers = [ bni1, bni2, bni3, bni1 + 1, bni2 + elementsCountAround, bni3 + elementsCountAround ] element.setNodesByIdentifier(eft1, nodeIdentifiers) # set general linear map coefficients radiansAround = e1 * radiansPerElementAround radiansAroundNext = ( (e1 + 1) % elementsCountAround) * radiansPerElementAround scalefactors = [ -1.0, math.sin(radiansAround), math.cos(radiansAround), radiansPerElementAround, math.sin(radiansAroundNext), math.cos(radiansAroundNext), radiansPerElementAround, math.sin(radiansAround), math.cos(radiansAround), radiansPerElementAround, math.sin(radiansAroundNext), math.cos(radiansAroundNext), radiansPerElementAround ] result = element.setScaleFactors(eft1, scalefactors) elementIdentifier = elementIdentifier + 1 annotationGroups = annotationGroupsAround[e1] + annotationGroupsAlong[0] + \ annotationGroupsThroughWall[e3] if annotationGroups: allAnnotationGroups = mergeAnnotationGroups( allAnnotationGroups, annotationGroups) for annotationGroup in annotationGroups: meshGroup = annotationGroup.getMeshGroup(mesh) meshGroup.addElement(element) # Create regular elements now = elementsCountAround * (elementsCountThroughWall + 1) for e2 in range(1 if closedProximalEnd else 0, elementsCountAlong): for e3 in range(elementsCountThroughWall): for e1 in range(elementsCountAround): if closedProximalEnd: bni11 = (e2 - 1) * now + e3 * elementsCountAround + e1 + 1 + ( elementsCountThroughWall + 1) bni12 = (e2-1) * now + e3 * elementsCountAround + (e1 + 1) % elementsCountAround + 1 + \ (elementsCountThroughWall + 1) bni21 = (e2 - 1) * now + ( e3 + 1) * elementsCountAround + e1 + 1 + ( elementsCountThroughWall + 1) bni22 = (e2-1) * now + (e3 + 1) * elementsCountAround + (e1 + 1) % elementsCountAround + 1 + \ (elementsCountThroughWall + 1) else: bni11 = e2 * now + e3 * elementsCountAround + e1 + 1 bni12 = e2 * now + e3 * elementsCountAround + ( e1 + 1) % elementsCountAround + 1 bni21 = e2 * now + (e3 + 1) * elementsCountAround + e1 + 1 bni22 = e2 * now + (e3 + 1) * elementsCountAround + ( e1 + 1) % elementsCountAround + 1 nodeIdentifiers = [ bni11, bni12, bni11 + now, bni12 + now, bni21, bni22, bni21 + now, bni22 + now ] onOpening = e1 > elementsCountAround - 2 element = mesh.createElement(elementIdentifier, elementtemplate) element.setNodesByIdentifier(eft, nodeIdentifiers) if xFlat: element.merge(flatElementtemplate2 if onOpening else flatElementtemplate1) element.setNodesByIdentifier( eftFlat2 if onOpening else eftFlat1, nodeIdentifiers) if xOrgan: element.merge(organElementtemplate) element.setNodesByIdentifier(eftOrgan, nodeIdentifiers) elementIdentifier = elementIdentifier + 1 annotationGroups = annotationGroupsAround[e1] + annotationGroupsAlong[e2] + \ annotationGroupsThroughWall[e3] if annotationGroups: allAnnotationGroups = mergeAnnotationGroups( allAnnotationGroups, annotationGroups) for annotationGroup in annotationGroups: meshGroup = annotationGroup.getMeshGroup(mesh) meshGroup.addElement(element) fm.endChange() return nodeIdentifier, elementIdentifier, allAnnotationGroups