#!/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