Enhanced MODFLOW Result Representation with Python, VTK and Paraview - Tutorial
/MODFLOW model output representation is key to understand the groundwater flow regime, to study the interaction with surface water and depending ecosystems and to evaluate the impact to anthropogenic and climate change requirements. Until now, there has been few open source software capable of generating 3D representations and those software had limited options for color scales, cross sections and other graphical tools. On the research for more options we found Paraview, a open source software for data representation designed to analyze extremely large datasets using distributed memory computing resources.
In order to represent MODFLOW output into Paraview, a VTK file for unstructured grids is needed, this VTK type is called VTU where the "U" comes from unestructured. The tutorial shows the complete procedure to process a MODFLOW model output into a VTU file and the representation in Paraview.
Photo Gallery
Tutorial
Input files
Files for this tutorial can be downloaded here
Code
This is the complete code used in this tutorial.
# coding: utf-8
# # Import the required packages and open model files
# In[1]:
# import the required libraries
import os, re
import numpy as np
from workingFunctions import Functions #functions from the workingFunctions.py file
# In[2]:
#change directory to the script path
os.chdir('C:/Users\Saul\Documents\Ih_PlayaroundwithVTK') #use your own path
#open the DIS, BAS and FHD and DRN files
disLines= open('Model/Modelo3.dis').readlines() #discretization data
basLines= open('Model/Modelo3.bas').readlines() #active / inactive data
fhdLines= open('Model/Modelo3.fhd').readlines() #water head data
drnLines= open('Model/Modelo3.drn').readlines() #drain package data
#create a empty dictionay to store the model features
modDis = {}
modBas = {}
modFhd = {}
modDrn = {}
# # Working with the DIS (Discretization Data) data
# ### General model features as modDis dict
# In[3]:
#get the extreme coordinates form the dis header
for line in disLines[:5]:
line = re.sub('\(|\)|,',' ',line) #change the (, ) and , character in the dis file
if "Lower left corner" in line:
line = line.split()
modDis["vertexXmin"]=float(line[4])
modDis["vertexYmin"]=float(line[5])
elif "Upper right corner" in line:
line = line.split()
modDis["vertexXmax"]=float(line[4])
modDis["vertexYmax"]=float(line[5])
#get the number of layers, rows, columns, cell and vertex numbers
linelaycolrow = disLines[6].split()
modDis["cellLays"] = int(linelaycolrow[0])
modDis["cellRows"] = int(linelaycolrow[1])
modDis["cellCols"] = int(linelaycolrow[2])
modDis["vertexLays"] = modDis["cellLays"] + 1
modDis["vertexRows"] = modDis["cellRows"] + 1
modDis["vertexCols"] = modDis["cellCols"] + 1
modDis["vertexperlay"] = modDis["vertexRows"] * modDis["vertexCols"]
modDis["cellsperlay"] = modDis["cellRows"] * modDis["cellCols"]
# ### Get the DIS Breakers
# In[4]:
#get the grid breakers
modDis['disBreakers']={}
breakerValues = ["INTERNAL","CONSTANT"]
vertexLay=0
for item in breakerValues:
for line in disLines:
if item in line:
if 'DELR' in line: #DELR is cell width along rows
modDis['disBreakers']['DELR']=disLines.index(line)
elif 'DELC' in line: #DELC is cell width along columns
modDis['disBreakers']['DELC']=disLines.index(line)
else:
modDis['disBreakers']['vertexLay'+str(vertexLay)]=disLines.index(line)
vertexLay+=1
# ### Get the DEL Info
# In[5]:
modDis['DELR'] = Functions.getListFromDEL(modDis['disBreakers']['DELR'],disLines,modDis['cellCols'])
modDis['DELC'] = Functions.getListFromDEL(modDis['disBreakers']['DELC'],disLines,modDis['cellRows'])
# ### Get the Cell Centroid Z
# In[6]:
modDis['cellCentroidZList']={}
for lay in range(modDis['vertexLays']):
#add auxiliar variables to identify breakers
lineaBreaker = modDis['disBreakers']['vertexLay'+str(lay)]
#two cases in breaker line
if 'INTERNAL' in disLines[lineaBreaker]:
lista = Functions.getListFromBreaker(lineaBreaker,modDis,disLines)
modDis['cellCentroidZList']['lay'+str(lay)]=lista
elif 'CONSTANT' in disLines[lineaBreaker]:
constElevation = float(disLines[lineaBreaker].split()[1])
modDis['cellCentroidZList']['lay'+str(lay)]= [constElevation for x in range(modDis["cellsperlay"])]
else:
pass
# ### List of arrays of cells and vertex coord
# In[7]:
modDis['vertexEasting'] = np.array([modDis['vertexXmin']+np.sum(modDis['DELR'][:col]) for col in range(modDis['vertexCols'])])
modDis['vertexNorthing'] = np.array([modDis['vertexYmax']-np.sum(modDis['DELC'][:row]) for row in range(modDis['vertexRows'])])
modDis['cellEasting'] = np.array([modDis['vertexXmin']+np.sum(modDis['DELR'][:col])+modDis['DELR'][col]/2 for col in range(modDis['cellCols'])])
modDis['cellNorthing'] = np.array([modDis['vertexYmax']-np.sum(modDis['DELC'][:row])-modDis['DELC'][row]/2 for row in range(modDis['cellRows'])])
# ### Interpolation from Z cell centroid to z vertex
# # Get the BAS Info
# ### Get the grid breakers
# In[8]:
#empty dict to store BAS breakers
modBas['basBreakers']={}
breakerValues = ["INTERNAL","CONSTANT"]
#store the breakers in the dict
lay=0
for item in breakerValues:
for line in basLines:
if item in line:
if 'IBOUND' in line:
modBas['basBreakers']['lay'+str(lay)]=basLines.index(line)
lay+=1
else:
pass
# ### Store ibound per lay
# In[9]:
#empty dict to store cell ibound per layer
modBas['cellIboundList']={}
for lay in range(modDis['cellLays']):
#add auxiliar variables to identify breakers
lineaBreaker = modBas['basBreakers']['lay'+str(lay)]
#two cases in breaker line
if 'INTERNAL' in basLines[lineaBreaker]:
lista = Functions.getListFromBreaker(lineaBreaker,modDis,basLines)
modBas['cellIboundList']['lay'+str(lay)]=lista
elif 'CONSTANT' in basLines[lineaBreaker]:
constElevation = float(disLines[lineaBreaker].split()[1]) #todavia no he probado esto
modBas['cellIboundList']['lay'+str(lay)]= [constElevation for x in range(modDis["cellsperlay"])]
else:
pass
# ### Store Cell Centroids as a Numpy array
# In[10]:
#empty list to store cell centroid
cellCentroidList = []
#numpy array of cell centroid
for row in range(modDis['cellRows']):
for col in range(modDis['cellCols']):
cellCentroidList.append([modDis['cellEasting'][col],modDis['cellNorthing'][row]])
#store cell centroids as numpy array
modDis['cellCentroids']=np.asarray(cellCentroidList)
# ### Grid of XYZ Vertex Coordinates
# In[11]:
modDis['vertexXgrid'] = np.repeat(modDis['vertexEasting'].reshape(modDis['vertexCols'],1),modDis['vertexRows'],axis=1).T
modDis['vertexYgrid'] = np.repeat(modDis['vertexNorthing'],modDis['vertexCols']).reshape(modDis['vertexRows'],modDis['vertexCols'])
modDis['vertexZGrid'] = Functions.interpolateCelltoVertex(modDis,'cellCentroidZList')
# # Get the HDS Info
# ### Get the grid breakers
# In[12]:
#empty dict to store HDS breakers
modFhd['fhdBreakers']={}
#store the breakers in the dict
lay=0
for line in fhdLines:
if 'HEAD' in line:
modFhd['fhdBreakers']['lay'+str(lay)]=fhdLines.index(line)
lay+=1
else:
pass
# ### Store heads per lay
# In[13]:
#empty dict to store cell heads per layer
modFhd['cellHeadGrid']={}
for lay in range(modDis['cellLays']):
#add auxiliar variables to identify breakers
lineaBreaker = modFhd['fhdBreakers']['lay'+str(lay)]
lista = Functions.getListFromBreaker(lineaBreaker,modDis,fhdLines)
array = np.asarray(lista).reshape(modDis['cellRows'],modDis['cellCols'])
modFhd['cellHeadGrid']['lay'+str(lay)]=array
# ### Arrange to transform cell centroid heads to vertex heads
# In[14]:
#empty temporal dictionary to store transformed heads
vertexHeadGridCentroid = {}
#arrange to hace positive heads in all vertex of an active cell
for lay in range(modDis['cellLays']):
matrix = np.zeros([modDis['vertexRows'],modDis['vertexCols']])
for row in range(modDis['cellRows']):
for col in range(modDis['cellCols']):
headLay = modFhd['cellHeadGrid']['lay'+str(lay)]
neighcartesianlist = [headLay[row-1,col-1],headLay[row-1,col],headLay[row,col-1],headLay[row,col]]
headList = []
for item in neighcartesianlist:
if item > -1e+20:
headList.append(item)
if len(headList) > 0:
headMean = sum(headList)/len(headList)
else:
headMean = -1e+20
matrix[row,col]=headMean
matrix[-1,:-1] = modFhd['cellHeadGrid']['lay'+str(lay)][-1,:]
matrix[:-1,-1] = modFhd['cellHeadGrid']['lay'+str(lay)][:,-1]
matrix[-1,-1] = modFhd['cellHeadGrid']['lay'+str(lay)][-1,-1]
vertexHeadGridCentroid['lay'+str(lay)]=matrix
# In[15]:
modFhd['vertexHeadGrid'] = {}
for lay in range(modDis['vertexLays']):
anyGrid = vertexHeadGridCentroid
if lay == modDis['cellLays']:
modFhd['vertexHeadGrid']['lay'+str(lay)] = anyGrid['lay'+str(lay-1)]
elif lay == 0:
modFhd['vertexHeadGrid']['lay0'] = anyGrid['lay0']
else:
value = np.where(anyGrid['lay'+str(lay)]>-1e+20,
anyGrid['lay'+str(lay)],
(anyGrid['lay'+str(lay-1)] + anyGrid['lay'+str(lay)])/2
)
modFhd['vertexHeadGrid']['lay'+str(lay)] = value
# # Get the DRN Info
# In[16]:
### Get the list of drain cells with attributes
# In[17]:
modDrn['DrainNumber'] = int(drnLines[2].split()[0])
modDrn['DrainCells'] = []
for item in range(modDrn['DrainNumber']-4):
anyLine = drnLines[item + 4].split()
anyList = [ int(anyLine[0]), int(anyLine[1]), int(anyLine[2]), float(anyLine[3]), float(anyLine[4])]
modDrn['DrainCells'].append(anyList)
# # Water Tables on Cell and Vextex
# ### Water Table on Cell
# In[18]:
#empty numpy array for the water table
waterTableCellGrid = np.zeros((modDis['cellRows'],modDis['cellCols']))
#obtain the first positive or real head from the head array
for row in range(modDis['cellRows']):
for col in range(modDis['cellCols']):
anyList = []
for lay in range(modDis['cellLays']):
anyList.append(modFhd['cellHeadGrid']['lay' + str(lay)][row,col])
a = np.asarray(anyList)
if list(a[a>-1e+10]) != []: #just in case there are some inactive zones
waterTableCellGrid[row,col] = a[a>-1e+10][0]
else: waterTableCellGrid[row,col] = -1e+10
# In[19]:
### Water Table on Vertex
# In[20]:
#empty numpy array for the water table
waterTableVertexGrid = np.zeros((modDis['vertexRows'],modDis['vertexCols']))
#obtain the first positive or real head from the head array
for row in range(modDis['vertexRows']):
for col in range(modDis['vertexCols']):
anyList = []
for lay in range(modDis['cellLays']):
anyList.append(modFhd['vertexHeadGrid']['lay' + str(lay)][row,col])
a = np.asarray(anyList)
if list(a[a>-1e+10]) != []: #just in case there are some inactive zones
waterTableVertexGrid[row,col] = a[a>-1e+10][0]
else: waterTableVertexGrid[row,col] = -1e+10
# ### Water Table on Cells and Vertex as List
# In[21]:
listWaterTableCell = list(waterTableCellGrid.flatten())
waterTableListVertex = list(waterTableVertexGrid.flatten())
# # Lists for the VTK file
# ### Definition of xyz points for all vertex
# In[22]:
#empty list to store all vertex XYZ
vertexXYZPoints = []
#definition of xyz points for all vertex
for lay in range(modDis['vertexLays']):
for row in range(modDis['vertexRows']):
for col in range(modDis['vertexCols']):
xyz=[
modDis['vertexEasting'][col],
modDis['vertexNorthing'][row],
modDis['vertexZGrid']['lay'+str(lay)][row, col]
]
vertexXYZPoints.append(xyz)
# ### Definition of xyz points for Water Table
# In[23]:
#empty list to store all vertex Water Table XYZ
vertexWaterTableXYZPoints = []
#definition of xyz points for all vertex
for row in range(modDis['vertexRows']):
for col in range(modDis['vertexCols']):
if waterTableVertexGrid[row, col] > -1e+10:
waterTable = waterTableVertexGrid[row, col]
else:
waterTable = 1000
xyz=[
modDis['vertexEasting'][col],
modDis['vertexNorthing'][row],
waterTable
]
vertexWaterTableXYZPoints.append(xyz)
# ### Definition of xyz points for Drain Cells
# In[24]:
#empty list to store drain vertex XYZ list
listDrainCellQuadXYZPoints = []
#definition of xyz points for all drain vertex
for row in range(modDis['vertexRows']):
for col in range(modDis['vertexCols']):
xyz=[
modDis['vertexEasting'][col],
modDis['vertexNorthing'][row],
modDis['vertexZGrid']['lay0'][row,col]
]
listDrainCellQuadXYZPoints.append(xyz)
# ### Definition of IBound list for all cell
# In[25]:
#empty list to store all ibound
listIBound = []
#definition of IBOUND
for lay in range(modDis['cellLays']):
for item in modBas['cellIboundList']['lay'+str(lay)]:
listIBound.append(item)
# ### Definition of all Cell Heads and Vertex Heads
# In[26]:
#empty list to store all cell heads
listCellHead = []
#definition of cellHead
for lay in range(modDis['cellLays']):
for item in list(modFhd['cellHeadGrid']['lay'+str(lay)].flatten()):
listCellHead.append(item)
# In[27]:
#empty list to store all vertex heads
listVertexHead = []
#definition of vertexHead
for lay in range(modDis['vertexLays']):
for item in list(modFhd['vertexHeadGrid']['lay'+str(lay)].flatten()):
listVertexHead.append(item)
# ### Definition of Cell Ibound List
# In[28]:
#empty list to store drain cells IO
listDrainsCellsIO = []
#definition of drain cells
modDrn['DrainCellsGrid'] = np.zeros((modDis['cellRows'],modDis['cellCols']))
for item in modDrn['DrainCells']:
modDrn['DrainCellsGrid'][item[1],item[2]] = 1
listDrainsCellsIO = list(modDrn['DrainCellsGrid'].flatten())
# # Hexahedrons and Quads sequences for the VTK File
# ### List of Layer Quad Sequences (Works only for a single layer)
# In[29]:
#empty list to store cell coordinates
listLayerQuadSequence = []
#definition of hexahedrons cell coordinates
for row in range(modDis['cellRows']):
for col in range(modDis['cellCols']):
pt0 = modDis['vertexCols']*(row+1)+col
pt1 = modDis['vertexCols']*(row+1)+col+1
pt2 = modDis['vertexCols']*(row)+col+1
pt3 = modDis['vertexCols']*(row)+col
anyList = [pt0,pt1,pt2,pt3]
listLayerQuadSequence.append(anyList)
# ### List of Hexa Sequences
# In[30]:
#empty list to store cell coordinates
listHexaSequence = []
#definition of hexahedrons cell coordinates
for lay in range(modDis['cellLays']):
for row in range(modDis['cellRows']):
for col in range(modDis['cellCols']):
pt0 = modDis['vertexperlay']*(lay+1)+modDis['vertexCols']*(row+1)+col
pt1 = modDis['vertexperlay']*(lay+1)+modDis['vertexCols']*(row+1)+col+1
pt2 = modDis['vertexperlay']*(lay+1)+modDis['vertexCols']*(row)+col+1
pt3 = modDis['vertexperlay']*(lay+1)+modDis['vertexCols']*(row)+col
pt4 = modDis['vertexperlay']*(lay)+modDis['vertexCols']*(row+1)+col
pt5 = modDis['vertexperlay']*(lay)+modDis['vertexCols']*(row+1)+col+1
pt6 = modDis['vertexperlay']*(lay)+modDis['vertexCols']*(row)+col+1
pt7 = modDis['vertexperlay']*(lay)+modDis['vertexCols']*(row)+col
anyList = [pt0,pt1,pt2,pt3,pt4,pt5,pt6,pt7]
listHexaSequence.append(anyList)
# # Active Cells Hexahedrons and Quads
# ### Cell Heads and Hexa Sequences
# In[31]:
listHexaSequenceDef = []
listCellHeadDef = []
for i in range(len(listCellHead)):
if listCellHead[i] > -1e-10:
listHexaSequenceDef.append(listHexaSequence[i])
listCellHeadDef.append(listCellHead[i])
# ### Active Cells and Hexa Sequences
# In[32]:
listActiveHexaSequenceDef = []
listIBoundDef = []
#filter hexahedrons and heads for active cells
for i in range(len(listIBound)):
if listIBound[i] > 0:
listActiveHexaSequenceDef.append(listHexaSequence[i])
listIBoundDef.append(listIBound[i])
# ### Water Table Quads and Cells
# In[33]:
listWaterTableQuadSequenceDef = []
listWaterTableCellDef = []
for item in range(len(listWaterTableCell)):
if listWaterTableCell[item] > -1e10:
listWaterTableQuadSequenceDef.append(listLayerQuadSequence[item])
listWaterTableCellDef.append(listWaterTableCell[item])
# ### Drain Cells Quads and Cells
# In[34]:
# Get the secuence and values for cell with drains
listDrainsCellsIODef = []
listDrainsCellsSecuenceDef = []
for item in range(len(listDrainsCellsIO)):
if listDrainsCellsIO[item] > 0:
listDrainsCellsIODef.append(listDrainsCellsIO[item])
listDrainsCellsSecuenceDef.append(listLayerQuadSequence[item])
# # VTK creation
# ### Summary of lists for the vtk creation
# In[35]:
### Point sets
# vertexXYZPoints for XYZ in all cell vertex
# vertexWaterTableXYZPoints for XYZ in all water table quad vertex
# listDrainCellQuadXYZPoints for XYZ in all drain cells quad vertex
### Quad and Hexa secuences
# listHexaSequenceDef for Head Hexa Sequence in all active cells
# listActiveHexaSequenceDef for Active Hexa Sequence in all active cells
# listWaterTableQuadSequenceDef for Water Table Quad Sequence in all active cells
# listDrainsCellsSecuenceDef for Drain Cell Quad Sequence in drain cells
### Cell data
# listCellHeadDef for filtered active cells
# listIBoundDef
# listWaterTableCellDef for filtered water table cells
# listDrainsCellsIODef for filtered drains cells
### Point data
# listVertexHead for heads in all cells
# ### Heads on Vertex and Cells VTK
# In[36]:
textoVtk = open('VTUFiles/VTU_Heads.vtu','w')
#add header
textoVtk.write('<VTKFile type="UnstructuredGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64">\n')
textoVtk.write(' <UnstructuredGrid>\n')
textoVtk.write(' <Piece NumberOfPoints="'+str(len(vertexXYZPoints))+'" NumberOfCells="'+str(len(listHexaSequenceDef))+'">\n')
#point data
textoVtk.write(' <PointData Scalars="Heads">\n')
textoVtk.write(' <DataArray type="Float64" Name="Heads" format="ascii">\n')
for item in range(len(listVertexHead)):
textvalue = str(listVertexHead[item])
if item == 0:
textoVtk.write(' ' + textvalue + ' ')
elif item % 20 == 0:
textoVtk.write(textvalue + '\n ')
else:
textoVtk.write(textvalue + ' ')
textoVtk.write('\n')
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </PointData>\n')
#cell data
textoVtk.write(' <CellData Scalars="Model">\n')
textoVtk.write(' <DataArray type="Float64" Name="CellHead" format="ascii" RangeMin="1" RangeMax="1">\n')
for item in range(len(listCellHeadDef)): #cell list
textvalue = str(int(listCellHeadDef[item]))
if item == 0:
textoVtk.write(' ' + textvalue + ' ')
elif item % 20 == 0:
textoVtk.write(textvalue + '\n ')
else:
textoVtk.write(textvalue + ' ')
textoVtk.write('\n')
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </CellData>\n')
#points definition
textoVtk.write(' <Points>\n')
textoVtk.write(' <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="ascii">\n')
for item in range(len(vertexXYZPoints)):
tuplevalue = tuple(vertexXYZPoints[item])
if item == 0:
textoVtk.write(" %.2f %.2f %.2f " % tuplevalue)
elif item % 4 == 0:
textoVtk.write("%.2f %.2f %.2f \n " % tuplevalue)
elif item == len(vertexXYZPoints)-1:
textoVtk.write("%.2f %.2f %.2f \n" % tuplevalue)
else:
textoVtk.write("%.2f %.2f %.2f " % tuplevalue)
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </Points>\n')
#cell connectivity
textoVtk.write(' <Cells>\n')
textoVtk.write(' <DataArray type="Int64" Name="connectivity" format="ascii">\n')
for item in range(len(listHexaSequenceDef)):
textoVtk.write(' ')
textoVtk.write('%s %s %s %s %s %s %s %s \n' % tuple(listHexaSequenceDef[item]))
textoVtk.write(' </DataArray>\n')
#cell offset
textoVtk.write(' <DataArray type="Int64" Name="offsets" format="ascii">\n')
for item in range(len(listHexaSequenceDef)):
offset = str((item+1)*8)
if item == 0:
textoVtk.write(' ' + offset + ' ')
elif item % 20 == 0:
textoVtk.write(offset + ' \n ')
elif item == len(listHexaSequenceDef)-1:
textoVtk.write(offset + ' \n')
else:
textoVtk.write(offset + ' ')
textoVtk.write(' </DataArray>\n')
#cell type
textoVtk.write(' <DataArray type="UInt8" Name="types" format="ascii">\n')
for item in range(len(listHexaSequenceDef)):
if item == 0:
textoVtk.write(' ' + '12 ')
elif item % 20 == 0:
textoVtk.write('12 \n ')
elif item == len(listHexaSequenceDef)-1:
textoVtk.write('12 \n')
else:
textoVtk.write('12 ')
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </Cells>\n')
#footer
textoVtk.write(' </Piece>\n')
textoVtk.write(' </UnstructuredGrid>\n')
textoVtk.write('</VTKFile>\n')
textoVtk.close()
# ### Active Cell VTK
# In[37]:
textoVtk = open('VTUFiles/VTU_Active.vtu','w')
#add header
textoVtk.write('<VTKFile type="UnstructuredGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64">\n')
textoVtk.write(' <UnstructuredGrid>\n')
textoVtk.write(' <Piece NumberOfPoints="'+str(len(vertexXYZPoints))+'" NumberOfCells="'+str(len(listActiveHexaSequenceDef))+'">\n')
#cell data
textoVtk.write(' <CellData Scalars="Model">\n')
textoVtk.write(' <DataArray type="Int32" Name="Active" format="ascii">\n')
for item in range(len(listIBoundDef)): #cell list
textvalue = str(int(listIBoundDef[item]))
if item == 0:
textoVtk.write(' ' + textvalue + ' ')
elif item % 20 == 0:
textoVtk.write(textvalue + '\n ')
else:
textoVtk.write(textvalue + ' ')
textoVtk.write('\n')
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </CellData>\n')
#points definition
textoVtk.write(' <Points>\n')
textoVtk.write(' <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="ascii">\n')
for item in range(len(vertexXYZPoints)):
tuplevalue = tuple(vertexXYZPoints[item])
if item == 0:
textoVtk.write(" %.2f %.2f %.2f " % tuplevalue)
elif item % 4 == 0:
textoVtk.write('%.2f %.2f %.2f \n ' % tuplevalue)
elif item == len(vertexXYZPoints)-1:
textoVtk.write("%.2f %.2f %.2f \n" % tuplevalue)
else:
textoVtk.write("%.2f %.2f %.2f " % tuplevalue)
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </Points>\n')
#cell connectivity
textoVtk.write(' <Cells>\n')
textoVtk.write(' <DataArray type="Int64" Name="connectivity" format="ascii">\n')
for item in range(len(listActiveHexaSequenceDef)):
textoVtk.write(' ')
textoVtk.write('%s %s %s %s %s %s %s %s \n' % tuple(listActiveHexaSequenceDef[item]))
textoVtk.write(' </DataArray>\n')
#cell offsets
textoVtk.write(' <DataArray type="Int64" Name="offsets" format="ascii">\n')
for item in range(len(listActiveHexaSequenceDef)):
offset = str((item+1)*8)
if item == 0:
textoVtk.write(' ' + offset + ' ')
elif item % 20 == 0:
textoVtk.write(offset + ' \n ')
elif item == len(listActiveHexaSequenceDef)-1:
textoVtk.write(offset + ' \n')
else:
textoVtk.write(offset + ' ')
textoVtk.write(' </DataArray>\n')
#cell types
textoVtk.write(' <DataArray type="UInt8" Name="types" format="ascii">\n')
for item in range(len(listActiveHexaSequenceDef)):
if item == 0:
textoVtk.write(' ' + '12 ')
elif item % 20 == 0:
textoVtk.write('12 \n ')
elif item == len(listActiveHexaSequenceDef)-1:
textoVtk.write('12 \n')
else:
textoVtk.write('12 ')
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </Cells>\n')
#footer
textoVtk.write(' </Piece>\n')
textoVtk.write(' </UnstructuredGrid>\n')
textoVtk.write('</VTKFile>\n')
textoVtk.close()
# ### Water Table VTK
# In[38]:
textoVtk = open('VTUFiles/VTU_WaterTable.vtu','w')
#add header
textoVtk.write('<VTKFile type="UnstructuredGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64">\n')
textoVtk.write(' <UnstructuredGrid>\n')
textoVtk.write(' <Piece NumberOfPoints="'+str(len(vertexWaterTableXYZPoints))+'" NumberOfCells="'+
str(len(listWaterTableCellDef))+'">\n')
#cell data
textoVtk.write(' <CellData Scalars="Water Table">\n')
textoVtk.write(' <DataArray type="Float64" Name="Heads" format="ascii">\n')
for item in range(len(listWaterTableCellDef)):
textvalue = str(listWaterTableCellDef[item])
if item == 0:
textoVtk.write(' ' + textvalue + ' ')
elif item % 20 == 0:
textoVtk.write(textvalue + '\n ')
else:
textoVtk.write(textvalue + ' ')
textoVtk.write('\n')
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </CellData>\n')
#points definition
textoVtk.write(' <Points>\n')
textoVtk.write(' <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="ascii">\n')
for item in range(len(vertexWaterTableXYZPoints)):
tuplevalue = tuple(vertexWaterTableXYZPoints[item])
if item == 0:
textoVtk.write(" %.2f %.2f %.2f " % tuplevalue)
elif item % 4 == 0:
textoVtk.write('%.2f %.2f %.2f \n ' % tuplevalue)
elif item == len(vertexWaterTableXYZPoints)-1:
textoVtk.write("%.2f %.2f %.2f \n" % tuplevalue)
else:
textoVtk.write("%.2f %.2f %.2f " % tuplevalue)
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </Points>\n')
#cell connectivity
textoVtk.write(' <Cells>\n')
textoVtk.write(' <DataArray type="Int64" Name="connectivity" format="ascii">\n')
for item in range(len(listWaterTableQuadSequenceDef)):
textoVtk.write(' ')
textoVtk.write('%s %s %s %s \n' % tuple(listWaterTableQuadSequenceDef[item]))
textoVtk.write(' </DataArray>\n')
#cell offsets
textoVtk.write(' <DataArray type="Int64" Name="offsets" format="ascii">\n')
for item in range(len(listWaterTableQuadSequenceDef)):
offset = str((item+1)*4)
if item == 0:
textoVtk.write(' ' + offset + ' ')
elif item % 20 == 0:
textoVtk.write(offset + ' \n ')
elif item == len(listWaterTableQuadSequenceDef)-1:
textoVtk.write(offset + ' \n')
else:
textoVtk.write(offset + ' ')
textoVtk.write(' </DataArray>\n')
#cell types
textoVtk.write(' <DataArray type="UInt8" Name="types" format="ascii">\n')
for item in range(len(listWaterTableQuadSequenceDef)):
if item == 0:
textoVtk.write(' ' + '9 ')
elif item % 20 == 0:
textoVtk.write('9 \n ')
elif item == len(listWaterTableQuadSequenceDef)-1:
textoVtk.write('9 \n')
else:
textoVtk.write('9 ')
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </Cells>\n')
#footer
textoVtk.write(' </Piece>\n')
textoVtk.write(' </UnstructuredGrid>\n')
textoVtk.write('</VTKFile>\n')
textoVtk.close()
# # Drain Cell VTK
# In[39]:
textoVtk = open('VTUFiles/VTU_DrainCells.vtu','w')
#add header
textoVtk.write('<VTKFile type="UnstructuredGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64">\n')
textoVtk.write(' <UnstructuredGrid>\n')
textoVtk.write(' <Piece NumberOfPoints="'+str(len(listDrainCellQuadXYZPoints))
+'" NumberOfCells="'+str(len(listDrainsCellsSecuenceDef))+'">\n')
#cell data
textoVtk.write(' <CellData Scalars="Water Table">\n')
textoVtk.write(' <DataArray type="Float64" Name="Heads" format="ascii">\n')
for item in range(len(listDrainsCellsIODef)):
textvalue = str(listDrainsCellsIODef[item])
if item == 0:
textoVtk.write(' ' + textvalue + ' ')
elif item % 20 == 0:
textoVtk.write(textvalue + '\n ')
else:
textoVtk.write(textvalue + ' ')
textoVtk.write('\n')
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </CellData>\n')
#points definition
textoVtk.write(' <Points>\n')
textoVtk.write(' <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="ascii">\n')
for item in range(len(listDrainCellQuadXYZPoints)):
tuplevalue = tuple(listDrainCellQuadXYZPoints[item])
if item == 0:
textoVtk.write(" %.2f %.2f %.2f " % tuplevalue)
elif item % 4 == 0:
textoVtk.write('%.2f %.2f %.2f \n ' % tuplevalue)
elif item == len(listDrainCellQuadXYZPoints)-1:
textoVtk.write("%.2f %.2f %.2f \n" % tuplevalue)
else:
textoVtk.write("%.2f %.2f %.2f " % tuplevalue)
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </Points>\n')
#cell definition
textoVtk.write(' <Cells>\n')
textoVtk.write(' <DataArray type="Int64" Name="connectivity" format="ascii">\n')
for item in range(len(listDrainsCellsSecuenceDef)):
textoVtk.write(' ')
textoVtk.write('%s %s %s %s \n' % tuple(listDrainsCellsSecuenceDef[item]))
textoVtk.write(' </DataArray>\n')
textoVtk.write(' <DataArray type="Int64" Name="offsets" format="ascii">\n')
for item in range(len(listDrainsCellsSecuenceDef)):
offset = str((item+1)*4)
if item == 0:
textoVtk.write(' ' + offset + ' ')
elif item % 20 == 0:
textoVtk.write(offset + ' \n ')
elif item == len(listDrainsCellsSecuenceDef)-1:
textoVtk.write(offset + ' \n')
else:
textoVtk.write(offset + ' ')
textoVtk.write(' </DataArray>\n')
textoVtk.write(' <DataArray type="UInt8" Name="types" format="ascii">\n')
for item in range(len(listDrainsCellsSecuenceDef)):
if item == 0:
textoVtk.write(' ' + '9 ')
elif item % 20 == 0:
textoVtk.write('9 \n ')
elif item == len(listDrainsCellsSecuenceDef)-1:
textoVtk.write('9 \n')
else:
textoVtk.write('9 ')
textoVtk.write(' </DataArray>\n')
textoVtk.write(' </Cells>\n')
#footer
textoVtk.write(' </Piece>\n')
textoVtk.write(' </UnstructuredGrid>\n')
textoVtk.write('</VTKFile>\n')
textoVtk.close()
This is the script for the auxiliary functions.
import math
import numpy as np
from scipy.interpolate import griddata
class Functions:
def __init__(self, name):
self.name = name
def getListFromDEL(initbreaker,disLines,celldim):
if 'CONSTANT' in disLines[initbreaker]:
constElevation = float(disLines[initbreaker].split()[1])
anyLines = [constElevation for x in range(celldim)]
elif 'INTERNAL' in disLines[initbreaker]:
#empty array and number of lines
anyLines = []
#final breaker
finalbreaker = initbreaker+1+math.ceil(celldim/10)
#append to list all items
for linea in range(initbreaker+1,finalbreaker,1):
listaitem = [float(item) for item in disLines[linea].split()]
for item in listaitem: anyLines.append(item)
else:
anylines = []
return np.asarray(anyLines)
def getListFromBreaker(initbreaker,modDis,fileLines):
#empty array and number of lines
anyLines = []
finalbreaker = initbreaker+1+math.ceil(modDis['cellCols']/10)*modDis['cellRows']
#append to list all items
for linea in range(initbreaker+1,finalbreaker,1):
listaitem = [float(item) for item in fileLines[linea].split()]
for item in listaitem: anyLines.append(item)
return anyLines
#function that return a dictionary of z values on the vertex
def interpolateCelltoVertex(modDis,item):
dictZVertex = {}
for lay in modDis[item].keys():
values = np.asarray(modDis[item][lay])
grid_z = griddata(modDis['cellCentroids'], values,
(modDis['vertexXgrid'], modDis['vertexYgrid']),
method='nearest')
dictZVertex[lay]=grid_z
return dictZVertex
