Files
kaiju/kaipy/kaixdmf.py
2024-02-21 13:29:50 -07:00

208 lines
5.9 KiB
Python

#Various routines to help scripts that create XMF files from H5 data
import numpy as np
import h5py
import kaipy.kaiH5 as kh5
import xml.etree.ElementTree as et
import kaipy.kdefs as kdefs
#Add grid info to step
#Geom is topology subelement, iDims is grid size string
def AddGrid(fname,Geom,iDims,coordStrs):
for coordStr in coordStrs:
xC = et.SubElement(Geom,"DataItem")
xC.set("Dimensions",iDims)
xC.set("NumberType","Float")
xC.set("Precision","4")
xC.set("Format","HDF")
text = fname+":/"+coordStr
xC.text = text
#Add data to slice
def AddData(Grid,fname,vID,vLoc,xDims,s0=None):
if (vLoc != 'Other'):
#Add attribute
vAtt = et.SubElement(Grid,"Attribute")
vAtt.set("Name",vID)
vAtt.set("AttributeType","Scalar")
vAtt.set("Center",vLoc)
#Add data item
aDI = et.SubElement(vAtt,"DataItem")
aDI.set("Dimensions",xDims)
aDI.set("NumberType","Float")
aDI.set("Precision","4")
aDI.set("Format","HDF")
if (s0 is None):
aDI.text ="%s:/%s"%(fname,vID)
else:
aDI.text = "%s:/Step#%d/%s"%(fname,s0,vID)
#Add data item to passed element
def AddDI(elt,h5F,nStp,cDims,vId):
aDI = et.SubElement(elt,"DataItem")
aDI.set("Dimensions",cDims)
aDI.set("NumberType","Float")
aDI.set("Precision","4")
aDI.set("Format","HDF")
if (nStp>=0):
aDI.text = "%s:/Step#%d/%s"%(h5F,nStp,vId)
else:
aDI.text ="%s:/%s"%(h5F,vId)
#Get root variables
def getRootVars(fname,gDims):
#Dims = kh5.getDims(fname,doFlip=False) #Do kji ordering
with h5py.File(fname,'r') as hf:
vIds = []
vLocs = []
for k in hf.keys():
#Don't include stuff that starts with step or X,Y,Z
vID = str(k)
doV = True
if ("Step" in vID or kdefs.grpTimeCache in vID ):
doV = False
if ((vID == "X") or (vID=="Y") or (vID=="Z")):
doV = False
if (doV):
Nv = hf[k].shape
vLoc = getLoc(gDims,Nv)
if (vLoc != "Other"):
vIds.append(vID)
vLocs.append(vLoc)
else:
print("Excluding %s"%(vID))
return vIds,vLocs
#Get variables in initial Step
def getVars(fname,gId,gDims,recursive=False):
def getVarName(gId, k, recursive):
if recursive:
# Want to keep the group name, since all vars need to be at the same level in xdmf
spl = gId.split('/')
return '/'.join(spl[1:]) + '/' + str(k)
else:
return str(k)
with h5py.File(fname,'r') as hf:
stp0 = hf[gId]
vIds = []
vLocs = []
for k in stp0.keys():
vID = getVarName(gId,k,recursive)
# If its a group, recursively call this function to get to the vars and add them to the list
if type(stp0[k]) == h5py._hl.group.Group:
vIdR, vLR = getVars(fname, gId+'/'+k, gDims, recursive=True)
for vi, vl in zip(vIdR, vLR):
vIds.append(vi)
vLocs.append(vl)
else:
Nv = stp0[k].shape
vLoc = getLoc(gDims,Nv)
if (vLoc != "Other"):
vIds.append(vID)
vLocs.append(vLoc)
else:
print("Excluding %s"%(vID))
return vIds,vLocs
def AddVectors(Grid,fname,vIds,cDims,vDims,Nd,nStp):
#Velocity (2D)
if ( (Nd == 2) and ("Vx" in vIds) and ("Vy" in vIds) ):
vAtt = et.SubElement(Grid,"Attribute")
vAtt.set("Name","VecV")
vAtt.set("AttributeType","Vector")
vAtt.set("Center","Cell")
fDI = et.SubElement(vAtt,"DataItem")
fDI.set("ItemType","Function")
fDI.set("Dimensions",vDims)
fDI.set("Function","JOIN($0 , $1)")
AddDI(fDI,fname,nStp,cDims,"Vx")
AddDI(fDI,fname,nStp,cDims,"Vy")
#Velocity (3D)
if ( (Nd == 3) and ("Vx" in vIds) and ("Vy" in vIds) and ("Vz" in vIds)):
vAtt = et.SubElement(Grid,"Attribute")
vAtt.set("Name","VecV")
vAtt.set("AttributeType","Vector")
vAtt.set("Center","Cell")
fDI = et.SubElement(vAtt,"DataItem")
fDI.set("ItemType","Function")
fDI.set("Dimensions",vDims)
fDI.set("Function","JOIN($0 , $1 , $2)")
AddDI(fDI,fname,nStp,cDims,"Vx")
AddDI(fDI,fname,nStp,cDims,"Vy")
AddDI(fDI,fname,nStp,cDims,"Vz")
#Magnetic field (2D)
if ( (Nd == 2) and ("Bx" in vIds) and ("By" in vIds) ):
vAtt = et.SubElement(Grid,"Attribute")
vAtt.set("Name","VecB")
vAtt.set("AttributeType","Vector")
vAtt.set("Center","Cell")
fDI = et.SubElement(vAtt,"DataItem")
fDI.set("ItemType","Function")
fDI.set("Dimensions",vDims)
fDI.set("Function","JOIN($0 , $1)")
AddDI(fDI,fname,nStp,cDims,"Bx")
AddDI(fDI,fname,nStp,cDims,"By")
if ( (Nd == 3) and ("Bx" in vIds) and ("By" in vIds) and ("Bz" in vIds)):
vAtt = et.SubElement(Grid,"Attribute")
vAtt.set("Name","VecB")
vAtt.set("AttributeType","Vector")
vAtt.set("Center","Cell")
fDI = et.SubElement(vAtt,"DataItem")
fDI.set("ItemType","Function")
fDI.set("Dimensions",vDims)
fDI.set("Function","JOIN($0 , $1 , $2)")
AddDI(fDI,fname,nStp,cDims,"Bx")
AddDI(fDI,fname,nStp,cDims,"By")
AddDI(fDI,fname,nStp,cDims,"Bz")
#Decide on centering
def getLoc(gDims,vDims):
vDims = np.array(vDims,dtype=int)
dimLocs = []
if len(gDims) != len(vDims):
return "Other"
for d in range(len(gDims)):
Ngd = gDims[d]-1
Nvd = vDims[d]
if Ngd == Nvd:
dimLocs.append("Cell")
elif Ngd == Nvd-1:
dimLocs.append("Node")
else:
dimLocs.append("Other")
if "Other" in dimLocs:
return "Other"
#If all the same, we have consensus
if all(x == dimLocs[0] for x in dimLocs):
return dimLocs[0]
else:
return "Other"
def addHyperslab(Grid,vName,dSetDimStr,vdimStr,startStr,strideStr,numStr,origDSetDimStr,fileText):
vAtt = et.SubElement(Grid, "Attribute")
vAtt.set("Name",vName)
vAtt.set("AttributeType","Scalar")
vAtt.set("Center","Node")
slabDI = et.SubElement(vAtt, "DataItem")
slabDI.set("ItemType","HyperSlab")
slabDI.set("Dimensions",dSetDimStr)
slabDI.set("Type","HyperSlab") # Not sure if redundant, but it works
cutDI = et.SubElement(slabDI,"DataItem")
cutDI.set("Dimensions",vdimStr)
cutDI.set("Format","XML")
cutDI.text = "\n{}\n{}\n{}\n".format(startStr,strideStr,numStr)
datDI = et.SubElement(slabDI,"DataItem")
datDI.set("Dimensions",origDSetDimStr)
datDI.set("DataType","Float")
datDI.set("Precision","4")
datDI.set("Format","HDF")
datDI.text = fileText