#!/usr/local/bin/python from SimpleFemModel import * import os import sys sys.path.reverse() from xml.dom.ext.reader import Sax2 from xml.dom.DOMImplementation import implementation from xml.dom import ext from xml.dom.NodeFilter import NodeFilter import Scientific.MPI sys.path.append("../MDWebServices/Utilities") from Utilities import * class XMLFemModel(SimpleFemModel): """The XMLFemModel class acts as a container to hold a description of a mesh and associated elements and boundary conditions.""" # constructor that reads a model description from an XML repository via a web service def __init__(self,soapAction,webService,meshUUID,attributeUUID,lengthScale,randomNumberSeed,myProc,parallel,topoUUID=0): self.soapAction = soapAction self.webService = webService self.meshUUID = meshUUID self.attributeUUID = attributeUUID self.topologyUUID = topoUUID self.lengthScale = lengthScale self.randomNumberSeed = randomNumberSeed self.nodes = {} self.elem = {} self.materials = {} self.myProc = myProc self.parallel = parallel self.requestfile = "request.xml" #"request"+str(myProc)+".xml" self.responsefile = "response.xml" #"response"+str(myProc)+".xml" self.meshNamespace = "\"http://www.tc.cornell.edu/~heber/2004/11/mesh\"" self.topologyNamespace = "\"http://www.tc.cornell.edu/~heber/2003/11/VLFRTopology\"" def GetNodesAndElements(self,meshPortion="entire",meshMax=None,meshMin=None,subMeshNodes=None): """Reads the entire or partial mesh from an XML repository """ # read the node coordinates if meshPortion == "entire": xqueryText = """ declare default namespace=""" + self.meshNamespace + """ declare namespace myNS="http://www.tc.cornell.edu/~heber/Vertices.xsd" { for $v in /Mesh/Vertices/Vertices3D/vertex return } """ elif meshPortion == "cube": xqueryText = """ declare default namespace=""" + self.meshNamespace + """ declare namespace myNS="http://www.tc.cornell.edu/~heber/Vertices.xsd" { for $v in /Mesh/Vertices/Vertices3D/vertex where ($v/attribute::x gt """ + str(meshMin[0]) + """ and $v/attribute::x lt """ + str(meshMax[0]) + """ and $v/attribute::y gt """ + str(meshMin[1]) + """ and $v/attribute::y lt """ + str(meshMax[1]) + """ and $v/attribute::z gt """ + str(meshMin[2]) + """ and $v/attribute::z lt """ + str(meshMax[2]) + """) return } """ if meshPortion != "connectivity": self.ConstructSoapEnvelope(self.meshUUID,xqueryText) walker = self.CallWebService() while 1: node = walker.currentNode if node.tagName == "soap:Header": next = walker.nextSibling() node = walker.currentNode if node.tagName == "vertex": atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "id": VertexID = atts[k].value elif atts[k].localName == "x": x = atts[k].value elif atts[k].localName == "y": y = atts[k].value elif atts[k].localName == "z": z = atts[k].value self.nodes[int(VertexID)] = (self.lengthScale*float(x),self.lengthScale*float(y),self.lengthScale*float(z)) next = walker.nextNode() if next is None: break else: for nodeID in subMeshNodes: self.nodes[nodeID] = self.GetNodeCoord(nodeID,0) print "Got Nodes" #the element data and material numbers if meshPortion == "entire": xqueryText = """ declare default namespace=""" + self.meshNamespace + """ declare namespace myNS="http://www.tc.cornell.edu/~heber/Regions.xsd" { for $r in /Mesh/Mappings/RegionMaps/region return { for $t in $r/tet return } } """ else: whereString = "(" for j in xrange(4): whereString = whereString + "(" for i in xrange(len(self.GetNodeIds())): whereString = whereString + "$t/attribute::v" + str(j) + "=" + str(self.GetNodeIds()[i]) if i < len(self.GetNodeIds())-1: whereString = whereString + " or " whereString = whereString + ")" if j < 3: whereString = whereString + " or " whereString = whereString + ")" xqueryText = """ declare default namespace=""" + self.meshNamespace + """ declare namespace myNS="http://www.tc.cornell.edu/~heber/Regions.xsd" { for $r in /Mesh/Mappings/RegionMaps/region return { for $t in $r/tet where """ + whereString + """ return } } """ self.ConstructSoapEnvelope(self.meshUUID,xqueryText) walker = self.CallWebService() orientFile = open("orientations.dat","w") while 1: node = walker.currentNode #print node.tagName if node.tagName == "soap:Header": next = walker.nextSibling() node = walker.currentNode elif node.tagName == "detail": break elif node.tagName == "faultstring": print "ERROR with Xquery ",xqueryText sys.exit(1) elif node.tagName == "region" and node.hasChildNodes(): atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "id": materialID = int(atts[k].value) # for now, the materials only consist of different grains # and we make up random orientations here orientation = GetRandomRotationMatrix(self.randomNumberSeed+materialID) orientFile.write(str(orientation)+"\n") self.materials[materialID] = orientation elif node.tagName == "tet": atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "id": id = int(atts[k].value) elif atts[k].localName == "v0": v0 = int(atts[k].value) elif atts[k].localName == "v1": v1 = int(atts[k].value) elif atts[k].localName == "v2": v2 = int(atts[k].value) elif atts[k].localName == "v3": v3 = int(atts[k].value) self.elem[id] = ("Tet2I",materialID,[v0,v1,v2,v3]) next = walker.nextNode() if next is None: next = walker.previousNode() next = walker.nextSibling() next = walker.nextSibling() if next is None: break print "Got Elements" # Get coordinates of any missing nodes newnodes = {} for elemID in self.GetElemIds(): for nodeID in self.GetElemData(elemID)[2]: if nodeID not in self.nodes.keys(): newnodes[nodeID] = self.GetNodeCoord(nodeID,0) self.nodes.update(newnodes) self.CornerNodeIds = self.nodes.keys()[:] def GetKinematicBCs(self,caseID): # Get dictionary of all possible boundary conditions in attributes file xqueryText = """ declare default namespace="http://www.tc.cornell.edu/~heber/2004/04/attributes" declare namespace myNS="http://www.tc.cornell.edu/~heber/Attributes.xsd" { for $b in /Attributes/BoundaryConditions/boundaryCondition return $b } """ self.ConstructSoapEnvelope(self.attributeUUID,xqueryText) walker = self.CallWebService() boundaryConditions={} while 1: node = walker.currentNode #print node.tagName if node.tagName == "soap:Header": next = walker.nextSibling() node = walker.currentNode elif node.tagName == "detail": break elif node.tagName == "faultstring": print "ERROR with Xquery ",xqueryText sys.exit(1) elif node.tagName == "boundaryCondition" and node.hasChildNodes(): atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "id": id = int(atts[k].value) elif atts[k].localName == "type": dim = str(atts[k].value[-1]) elif node.tagName == "condition": atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "vals": value = float(atts[k].value) boundaryConditions[id] = (dim,value) next = walker.nextNode() if next is None: next = walker.previousNode() next = walker.nextSibling() next = walker.nextSibling() if next is None: break # Get Case Insensitive bindings xqueryText = """ declare default namespace="http://www.tc.cornell.edu/~heber/2004/04/attributes" declare namespace myNS="http://www.tc.cornell.edu/~heber/Attributes.xsd" { for $bind in /Attributes/Bindings/binding where $bind/@val_xmlns = xs:anyURI("xpointer(/Attributes/BoundaryConditions/boundaryCondition/@id)") return $bind } """ self.ConstructSoapEnvelope(self.attributeUUID,xqueryText) walker = self.CallWebService() self.faceDisplacements={} while 1: node = walker.currentNode #print node.tagName if node.tagName == "soap:Header": next = walker.nextSibling() node = walker.currentNode elif node.tagName == "detail": break elif node.tagName == "faultstring": print "ERROR with Xquery ",xqueryText sys.exit(1) elif node.tagName == "i_rel": atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "vals": BCId = int(atts[k].value) elif atts[k].localName == "keys": faceIds = string.splitfields(atts[k].value) for id in faceIds: self.faceDisplacements[int(id)] = boundaryConditions[BCId] next = walker.nextNode() if next is None: next = walker.previousNode() next = walker.nextSibling() next = walker.nextSibling() if next is None: break ## # Get Case Sensitive bindings ## xqueryText = """ ## declare default namespace="http://www.tc.cornell.edu/~heber/2004/04/attributes" ## declare namespace myNS="http://www.tc.cornell.edu/~heber/Attributes.xsd" ## ## { for $case in /Attributes/Cases/case ## where $case/attribute::id="""+str(caseID)+""" ## return ## {for $bind in $case/Bindings/binding ## where xs:anyURI($bind/@val_xmlns) = xs:anyURI("xpointer(/Attributes/BoundaryConditions/boundaryCondition/@id)") ## return $bind ## } ## } ## ## """ ## self.ConstructSoapEnvelope(self.attributeUUID,xqueryText) ## walker = self.CallWebService() ## while 1: ## node = walker.currentNode ## #print node.tagName ## if node.tagName == "soap:Header": ## next = walker.nextSibling() ## node = walker.currentNode ## elif node.tagName == "detail": ## break ## elif node.tagName == "faultstring": ## print "ERROR with Xquery ",xqueryText ## sys.exit(1) ## elif node.tagName == "i_rel": ## atts = node.attributes ## for k in node.attributes.keys(): ## if atts[k].localName == "vals": ## BCId = int(atts[k].value) ## elif atts[k].localName == "keys": ## faceIds = string.splitfields(atts[k].value) ## for id in faceIds: ## self.faceDisplacements[int(id)] = boundaryConditions[BCId] ## next = walker.nextNode() ## if next is None: ## next = walker.previousNode() ## next = walker.nextSibling() ## next = walker.nextSibling() ## if next is None: break def GetFaceTrianglesFromRepository(self): # find triples of vertices forming triangles on each face xqueryText = """declare default namespace=""" + self.meshNamespace + """ declare namespace myNS="http://www.tc.cornell.edu/~heber/Faces.xsd" { for $r in /Mesh/Mappings/FaceMaps/face return { for $t in $r/triangle return } } """ self.faceTriangles = {} method = "GetFaceElements" self.ConstructSoapEnvelope(self.meshUUID,xqueryText) walker = self.CallWebService() while 1: node = walker.currentNode if node.tagName == "soap:Header": next = walker.nextSibling() elif node.tagName == "detail": break elif node.tagName == "faultstring": print "ERROR with Xquery ",xqueryText sys.exit(1) elif node.tagName == "face": atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "id": faceID = int(atts[k].value) triangles = [] elif node.tagName == "tri": atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "v0": v0 = int(atts[k].value) elif atts[k].localName == "v1": v1 = int(atts[k].value) elif atts[k].localName == "v2": v2 = int(atts[k].value) triangles.append((v0,v1,v2)) next = walker.nextNode() if next is None: if faceID in self.faceDisplacements.keys(): self.faceTriangles[faceID]=triangles next = walker.previousNode() next = walker.nextSibling() if next is None: break def GetInternalFaces(self): # find internal faces, materials, vertex-loops. # get materials and orientations if they haven't already been retrieved if self.materials == {}: xqueryText = """ declare default namespace=""" + self.meshNamespace + """ declare namespace myNS="http://www.tc.cornell.edu/~heber/Regions.xsd" { for $r in /Mesh/Mappings/RegionMaps/region return } """ self.ConstructSoapEnvelope(self.meshUUID,xqueryText) walker = self.CallWebService() orientFile = open("orientations.dat","w") while 1: node = walker.currentNode if node.tagName == "soap:Header": next = walker.nextSibling() node = walker.currentNode elif node.tagName == "detail": break elif node.tagName == "faultstring": print "ERROR with Xquery ",xqueryText sys.exit(1) elif node.tagName == "region":# and node.hasChildNodes(): atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "id": materialID = int(atts[k].value) # for now, the materials only consist of different grains # and we make up random orientations here orientation = GetRandomRotationMatrix(self.randomNumberSeed+materialID) orientFile.write(str(orientation)+"\n") self.materials[materialID] = orientation next = walker.nextNode() if next is None: next = walker.previousNode() next = walker.nextSibling() next = walker.nextSibling() if next is None: break # get internal face ids with loops and regions whereString = "(" for i in xrange(len(self.materials.keys())): whereString = whereString + "$f/attribute::region_out = " + str(self.materials.keys()[i]) if i < len(self.materials.keys())-1: whereString = whereString + " or " whereString = whereString + ")" xqueryText = """declare default namespace=""" + self.topologyNamespace + """ declare namespace myNS="http://www.tc.cornell.edu/~heber/Faces.xsd" { for $f in /VLFRTopology/Faces/face where """ + whereString + """ return } """ self.internalFaces = {} self.ConstructSoapEnvelope(self.topologyUUID,xqueryText) walker = self.CallWebService() while 1: node = walker.currentNode if node.tagName == "soap:Header": next = walker.nextSibling() elif node.tagName == "detail": break elif node.tagName == "faultstring": print "ERROR with Xquery ",xqueryText sys.exit(1) elif node.tagName == "face": atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "id": faceID = int(atts[k].value) elif atts[k].localName == "loops": loops = int(atts[k].value) elif atts[k].localName == "region_in": region_in = int(atts[k].value) elif atts[k].localName == "region_out": region_out = int(atts[k].value) self.internalFaces[faceID] = [loops,region_in,region_out] next = walker.nextNode() if next is None: next = walker.previousNode() next = walker.nextSibling() if next is None: break # get vertices so we can find orientation of face xqueryText = """declare default namespace=""" + self.topologyNamespace + """ declare namespace myNS="http://www.tc.cornell.edu/~heber/Faces.xsd" { for $v in /VLFRTopology/Vertices/vertex return $v } """ self.topologicalVertices = {} self.ConstructSoapEnvelope(self.topologyUUID,xqueryText) walker = self.CallWebService() while 1: node = walker.currentNode if node.tagName == "soap:Header": next = walker.nextSibling() node = walker.currentNode if node.tagName == "vertex": atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "id": VertexID = atts[k].value elif atts[k].localName == "x": x = atts[k].value elif atts[k].localName == "y": y = atts[k].value elif atts[k].localName == "z": z = atts[k].value self.topologicalVertices[int(VertexID)] = (self.lengthScale*float(x),self.lengthScale*float(y),self.lengthScale*float(z)) next = walker.nextNode() if next is None: break for i in xrange(len(self.internalFaces.keys())): faceID = self.internalFaces.keys()[i] self.internalFaces[faceID].append([]) xqueryText = """declare default namespace=""" + self.topologyNamespace + """ declare namespace myNS="http://www.tc.cornell.edu/~heber/Faces.xsd" { for $l in /VLFRTopology/Loops/loop where $l/attribute::id = """ + str(abs(self.internalFaces[faceID][0])) + """ return } """ self.ConstructSoapEnvelope(self.topologyUUID,xqueryText) walker = self.CallWebService() while 1: node = walker.currentNode if node.tagName == "soap:Header": next = walker.nextSibling() elif node.tagName == "detail": break elif node.tagName == "faultstring": print "ERROR with Xquery ",xqueryText sys.exit(1) elif node.tagName == "loop": atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "vertices": vertexIDs = string.splitfields(atts[k].value) for vertexID in vertexIDs: self.internalFaces[faceID][3].append(int(vertexID)) next = walker.nextNode() if next is None: break def Make10Noded(self): self.edgeNodeMap = {} for elemID in self.GetElemIds(): # for some reason these need to be in a very specific order cornerNodes = self.GetElemData(elemID)[2] for i in xrange(1,len(cornerNodes)): for j in xrange(1,i+1): newEdgeNodeID = self.GetEdgeNode((cornerNodes[i-j],cornerNodes[i])) self.elem[elemID][2].append(newEdgeNodeID) def GetNodeCoord(self,id,vec3d=1): if id in self.nodes.keys(): Xcoord = self.nodes[id][0] Ycoord = self.nodes[id][1] Zcoord = self.nodes[id][2] else: xqueryText = """ declare default namespace=""" + self.meshNamespace + """ declare namespace myNS="http://www.tc.cornell.edu/~heber/Vertices.xsd" { for $v in /Mesh/Vertices/Vertices3D/vertex where $v/attribute::id = """ + str(id) + """ return } """ self.ConstructSoapEnvelope(self.meshUUID,xqueryText) walker = self.CallWebService() self.nodes = {} while 1: node = walker.currentNode if node.tagName == "soap:Header": next = walker.nextSibling() node = walker.currentNode if node.tagName == "vertex": atts = node.attributes for k in node.attributes.keys(): if atts[k].localName == "x": x = atts[k].value elif atts[k].localName == "y": y = atts[k].value elif atts[k].localName == "z": z = atts[k].value next = walker.nextNode() if next is None: break Xcoord = self.lengthScale*float(x) Ycoord = self.lengthScale*float(y) Zcoord = self.lengthScale*float(z) if vec3d: return Vec3D(Xcoord,Ycoord,Zcoord) else: return (Xcoord,Ycoord,Zcoord) def ConstructSoapEnvelope(self,uuid,xqueryText,printRequest=0): if self.myProc == 0: # Construct the request SOAP Envelope doc = implementation.createDocument(None,None,None) envelope = doc.createElement('soap:Envelope') envelope.setAttribute('xmlns:soap','http://schemas.xmlsoap.org/soap/envelope/') envelope.setAttribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance') envelope.setAttribute('xmlns:xsd','http://www.w3.org/2001/XMLSchema') doc.appendChild(envelope) body = doc.createElement('soap:Body') envelope.appendChild(body) XQueryRequest = doc.createElement('XQueryRequest') XQueryRequest.setAttribute('xmlns',self.soapAction) body.appendChild(XQueryRequest) uuidElem = doc.createElement('uuid') uuidElem.appendChild(doc.createTextNode(uuid)) XQueryRequest.appendChild(uuidElem) xquery = doc.createElement('xquery') xquery.appendChild(doc.createTextNode(xqueryText)) XQueryRequest.appendChild(xquery) if printRequest: print "The request:" ext.PrettyPrint(doc) # Write it to a file f = open(self.requestfile,'w') ext.PrettyPrint(doc,f) print >> f, '' f.close() def CallWebService(self,printResponse=0): #returns xml "walker" to xml structure if self.myProc == 0: stat = os.system("""curl -s --data-binary @""" + self.requestfile + """ -H 'SOAPAction: """ + "\"" + self.soapAction + "/XQuery\"\'" """ -H 'Content-Type: text/xml' """ + self.webService + """ > """ + self.responsefile) if stat <> 0: print "curl exited with status", stat # Read the response SOAP Envelope from the file if self.parallel: Scientific.MPI.world.barrier() doc = Sax2.FromXmlFile(self.responsefile) if printResponse: print "The response:" ext.PrettyPrint(doc) walker = doc.createTreeWalker(doc.documentElement,NodeFilter.SHOW_ELEMENT, None, 0) return walker # if calling directly from command line or web service if __name__ == "__main__": soapAction = "http://www.tc.cornell.edu/~heber" webService = "http://cmiws.tc.cornell.edu/XMLRepository/default.asmx" meshUUID = "fd4aafc5-b7c0-4f79-a7c5-70a648e9b649" attributeUUID = "6bb65170-bb99-4402-a0f3-0a44280f9368" topologyUUID = "6bc35972-fe4f-40ed-a154-e07e26c0784d" model = XMLFemModel(soapAction,webService,meshUUID,attributeUUID,1,5,0,0,topologyUUID) model.GetInternalFaces() print model.materials print model.internalFaces print model.topologicalVertices #model.GetNodesAndElements() #print "NODES" #print model.nodes #print "MATERIALS" #print model.materials #print "ELEMENTS" #print model.elem ## print "BOUNDARY CONDITIONS" ## print model.faceDisplacements ## print "FACE TRIANGLES" ## print model.faceTriangles