Files
LaGriT/PyLaGriT/examples/ideas_mesh/ideas_mesh.py

195 lines
6.4 KiB
Python
Raw Normal View History

2025-12-17 11:00:57 +08:00
import optparse
import shutil, distutils.dir_util, os, sys, glob
import numpy
import math
import matplotlib.pyplot as plt
from pylagrit import PyLaGriT
#
# Create parser and options
#
p = optparse.OptionParser()
p.add_option('--dem-file', help='DEM data file name including path', type='string', dest='dem_filename' )
p.add_option('--exo-file', help='Exodus II mesh output including path', type='string', dest='exo_filename')
p.add_option('--dry-run', help='Show commands and diagnostics but no execution', default=False, dest='dry_run', action='store_true')
p.add_option('--plot', help='Show commands and diagnostics but no execution', default=False, dest='plot', action='store_true')
#
(opts,args) = p.parse_args()
print(opts.dem_filename)
print(opts.dry_run)
# Input: DEM data
dem_file_fullname=opts.dem_filename
dem_file_noext, dem_file_ext=os.path.splitext(opts.dem_filename)
dem_file_base=os.path.basename(opts.dem_filename).rstrip(dem_file_ext)
dem_file_path=os.path.dirname(opts.dem_filename)
# Output: Exodus II mesh
exo_file_fullname=opts.exo_filename
exo_file_noext, exo_file_ext=os.path.splitext(opts.exo_filename)
exo_file_base=os.path.basename(opts.exo_filename).rstrip(exo_file_ext)
exo_file_path=os.path.dirname(opts.exo_filename)
# Output: XML region specifications for the new mesh
xml_file_fullname=exo_file_path+exo_file_base+'.xml'
# DEM parsing
#
with open(dem_file_fullname) as dem_header:
for line in dem_header:
if ("ncols" in line):
nx=int(line.split()[1])
elif ("nrows" in line):
ny=int(line.split()[1])
elif ("xllcorner" in line):
xll_corner=float(line.split()[1])
elif ("yllcorner" in line):
yll_corner=float(line.split()[1])
elif ("cellsize" in line):
dx=float(line.split()[1])
dy=dx
elif ("NODATA_value" in line):
no_data_value=int(line.split()[1])
break
print(nx, ny, xll_corner, yll_corner, dx, dy, no_data_value)
dem_header.close()
d = numpy.flipud(numpy.genfromtxt(dem_file_fullname,skip_header=6))
#plt.matshow(d)
# Create mesh based on ncols and nrows in file, could automatically read
x = numpy.linspace(xll_corner,dx*(nx-1),nx)
y = numpy.linspace(yll_corner,dy*(ny-1),ny)
x=numpy.arange(xll_corner,dx*nx,dx)
y=numpy.arange(yll_corner,dy*ny,dy)
xx, yy = numpy.meshgrid(x,y)
# Write avs file
fh = open(dem_file_base+'.avs','w')
# Find number of data values and write avs header
N = numpy.where(numpy.isnan(d)==False)[0].shape[0]
fh.write(str(N)+' 0 0 0 0\n')
# Collect data into avs format
# JDM: Not sure if this should be nx*ny?
davs = numpy.zeros([nx*ny,4])
ind = 0
for i,row in enumerate(d):
for j,v in enumerate(row):
davs[ind,:] = [ind + 1, xx[i,j], yy[i,j], v]
ind += 1
# Write data to avs file
numpy.savetxt(fh,davs,fmt=['%4d','%.1lf','%.1lf','%.8lf'])
fh.close()
# Crank up pylagrit
lg = PyLaGriT()
# Read in elevations in avs fromat
m = lg.read(dem_file_base+'.avs')
# Take a look, change paraview exe
# Will need to use glyph filter to view points
#m.paraview(exe='paraview')
# Copy z values over to attribute
m.addatt('z_save',vtype='vdouble',rank='scalar')
m.copyatt('zic','z_save')
# Not sure why this has to be done, but not data elements don't get removed otherwise
m.setatt('zic',0.)
# Create connected quad mesh surface
m2 = lg.create()
#m2.createpts_xyz((nx,ny,1),[xx.min(),yy.min(),0.],[xx.max(),yy.max(),0],rz_switch=[1,1,1],connect=True)
m2.createpts_xyz((nx,ny,1),[xx.min(),yy.min(),0.],[xx.max(),yy.max(),0],rz_switch=[1,1,1])
# Create temporary z value attribute
m2.addatt('z_save',vtype='vdouble',rank='scalar')
# Interpolate elevations to z_save
m2.interpolate_voronoi('z_save',m,'z_save')
# Find nodes associated with nodata
pdel = m2.pset_attribute('z_save',-9999)
# Create element set from these nodes and remove elements
edel = pdel.eltset()
m2.rmpoint_eltset(edel)
# Copy temp z values over to actual a values
#m2.copyatt('z_save','zic')
# Take a look to make sure everything is ok
#m2.paraview(exe='paraview')
m3 = m2.copypts(elem_type='triplane')
m3.connect()
# To lazy to add to pylagrit now, and don't know how to make it intuitive
# Creates edge_max element attribute containing max edge length
m3.sendline('quality/edge_max/y')
# Query created attribute
#m3.printatt('edgemax')
m3.minmax('edgemax')
# Figure out max desired edge length
max_edge = numpy.sqrt(dx**2+dy**2)
# Identify elements with longer edges
edel = m3.eltset_attribute('edgemax',max_edge*2.05,'gt')
m3.rmpoint_eltset(edel)
#m3 = m2.grid2grid_quadtotri2()
#m3=m2
# Create temporary z value attribute
m3.addatt('z_save',vtype='vdouble',rank='scalar')
# Interpolate elevations to z_save
m3.interpolate_voronoi('z_save',m,'z_save')
# Find nodes associated with nodata
pdel = m3.pset_attribute('z_save',-9999)
# Create element set from these nodes and remove elements
edel = pdel.eltset()
m3.rmpoint_eltset(edel)
# Copy temp z values over to actual a values
m3.copyatt('z_save','zic')
# Take a look to make sure everything is ok
#m2.paraview(exe='paraview')
# Create top surface avs
m3.dump('top.inp')
## Subtract 1 from z values of top and dump into bottom surface avs
m3.math('sub',1,'zic',cmosrc=m3)
m3.dump('mid.inp')
m3.setatt('zic',0.0)
m3.dump('bot.inp')
# Stack the layers in a new mesh object
stack = lg.create()
stack.stack_layers('avs',['bot.inp 1','mid.inp 1,3','top.inp 1,0'],flip_opt=True)
stack_hex = stack.stack_fill()
# Automatically create face sets based on normal vectors and layer id
#fs = stack_hex.create_boundary_facesets(base_name='faceset_bounds',stacked_layers=True)
#fs = stack_hex.create_boundary_facesets(base_name='faceset_bounds',stacked_layers=False)
# Diagnostic
#stack_hex.sendline('quality volume itetclr')
# Write exo file with boundary facesets
#stack_hex.dump_exo(exo_file_fullname,facesets=fs.values())
stack_hex.dump_exo(exo_file_fullname)
# Write region and faceset identifier file for ats_xml
matnames = {10000:'computational domain peat'}
facenames = {1:'bottom face',
2:'surface',
3:'front',
4:'right',
5:'back',
6:'left'}
# Dump ats style xml for mesh, can provide options for other schemas easily also
#stack_hex.dump_ats_xml(xml_file_fullname,exo_file_fullname,matnames=matnames,facenames=facenames)
stack_hex.dump_ats_xml(xml_file_fullname,exo_file_fullname,matnames=matnames,facenames=facenames)
# Take a look
if opts.plot:
stack_hex.paraview(exe='/Applications/paraview.app/Contents/MacOS/paraview')