Dear Coreform team,
I have a 3D model in shape of cuboid with complex non-planar surface at the top.
Here, I try to post minimal, reproducible example. You can see the geometry at the figure. There is box inside the main volume - a “yellow volume” which should have finer hexahedra elements compared to the “green & purple” volumes.
I want to keep the bottom and lateral outer edges of the model straight, while using the Sculpt. I do not mind if the edges of the “yellow volume” box get rounded during the process of creating mesh.
If I use Sculpt option “capture = 4” based on the recommedation at https://forum.coreform.com/t/maintan-sharp-edges-when-using-parallel-sculpt/990/5
I obtain hexahedra elements with negative Jacobian quality metric (middle part of the figure). If I use Sculpt without this option, I get rounded edges at the outer sides (right part of the figure). Moreover, even the place of webcut is rounded/deformed.
My questions:
Q1: Is there a way to keep straight edges while avoiding negative Jacobian elements with Sculpt? My original model has a complex non-planar top surface, so hexahedra meshing with Sculpt is the best option for me.
Q2: I was thinking of using the meshed model with rounded edges (right part of figure), but shift/move the nodes of lateral & bottom faces into corresponding virtual plane surfaces. In order to make edges straight. Do you think that this could be done in Cubit Python?
Here is the Python code in order to create Sculpt input files:
#!python
import numpy
import cubit
topsurface = "topo.if0.csv"
zdepthVol1 = -300
vol2size = 100
zoffsetVol2 = -20
planeWebcutDepth = zdepthVol1 + 100
def main():
set_performance_mode( True )
cubit.cmd( "reset" )
data = read_dat_file(topsurface)
create_surface(data)
surface_id = cubit.get_last_id( "surface" )
vol1_id = create_vol1(surface_id, zdepthVol1)
box_id = create_box_vol2(vol1_id, vol2size, zoffsetVol2)
cubit.cmd(f"webcut vol {vol1_id} with sheet body {box_id}")
cubit.cmd(f"delete body {box_id}")
cubit.cmd(f"webcut volume {vol1_id} with plane zplane offset {planeWebcutDepth}")
set_performance_mode( False )
cubit.cmd("compress all")
cubit.cmd("imprint all")
cubit.cmd("merge all")
cubit.cmd( "sculpt volume all no_execute no_combine no_import no_show no_clean fileroot 'nonplanar_box'" )
def read_dat_file( dat_filename ):
data = {}
x, y, z = [ [], [], [] ]
f = open( dat_filename, "r" )
fLines = f.readlines()
for fLine in fLines:
fLine = fLine.strip().split( "," )
row_id = int( fLine[0] )
if ( row_id in data.keys() ) == False:
data[row_id] = { "x": [], "y": [], "z": [] }
data[row_id]["x"].append( float( fLine[1] ) )
data[row_id]["y"].append( float( fLine[2] ) )
data[row_id]["z"].append( float( fLine[3] ) )
return data
def create_surface( data ):
row_ids = list( data.keys() )
curves_in_surface = []
for row_id in row_ids:
row_data = data[row_id]
x, y, z = [ row_data["x"], row_data["y"], row_data["z"] ]
vertices_in_curve = []
for i in range( 0, len( x ) ):
cubit.cmd( f"create vertex {x[i]} {y[i]} {z[i]}" )
vertices_in_curve.append( cubit.get_last_id( "vertex" ) )
cubit.cmd( f"create curve spline location vertex {cubit.get_id_string( vertices_in_curve )} delete" )
curves_in_surface.append( cubit.get_last_id( "curve" ) )
cubit.cmd( f"create surface skin curve {cubit.get_id_string( curves_in_surface )}" )
cubit.cmd( f"delete curve {cubit.get_id_string( curves_in_surface )}" )
def create_vol1(surf_id, depth):
cubit.cmd( f"sweep surface {surf_id} target plane zplane offset {depth} direction 0 0 -1 keep" )
targ_vol_id = cubit.get_last_id( "volume" )
return targ_vol_id
def create_box_vol2(vol_id, sizevol2, zoff):
bounded_box = cubit.get_bounding_box("volume", vol_id)
if (bounded_box[2] <= sizevol2 or bounded_box[5] <= sizevol2 or bounded_box[8] <= sizevol2):
raise RuntimeError("Vol 2 bigger than Vol 1!")
cubit.cmd(f"create brick x {sizevol2}")
vol2_id = cubit.get_last_id("volume")
cubit.cmd(f"move volume {vol2_id} x {bounded_box[2]/2} y {bounded_box[5]/2} z {zoff}")
bounded_box_vol2 = cubit.get_bounding_box("volume", vol2_id)
if (bounded_box_vol2[7] < bounded_box[7]):
raise RuntimeError("Vol 2 must be higher than Vol 1!")
surfs = cubit.get_relatives("volume", vol2_id, "surface")
top_surf = None
top_z = float("-inf")
for s in surfs:
x, y, z = cubit.surface(s).center_point()
if z > top_z:
top_z = z
top_surf = s
if top_surf is None:
raise RuntimeError("Failed to identify top surface.")
#print(f"Identified top surface: {top_surf} (centroid z = {top_z})")
cubit.cmd(f"remove surface {top_surf} noextend")
cubit.cmd("create sheet body surface all")
return cubit.get_last_id( "body" )
def set_performance_mode( status=True ):
if status == True:
cubit.cmd( "undo off" )
cubit.cmd( "info off" )
cubit.cmd( "echo off" )
cubit.cmd( "warning off" )
cubit.cmd( "journal off" )
cubit.cmd( "graphics off" )
elif status == False:
cubit.cmd( "undo off" )
cubit.cmd( "info on" )
cubit.cmd( "echo on" )
cubit.cmd( "warning on" )
cubit.cmd( "journal off" )
cubit.cmd( "graphics on" )
main()
topo.if0.csv (2.5 MB)
I use the following Sculpt input file:
$ Input file created
BEGIN SCULPT
nelx = 24
nely = 24
nelz = 26
xmin = -35.128975
ymin = -35.128975
zmin = -340.555496
xmax = 335.128975
ymax = 335.128975
zmax = 60.557284
exodus_file = nonplanar_box.diatom_result
diatom_file = nonplanar_box.diatom
$ My Parameters
cell_size = 10.000000
adapt_type = 8
adapt_material = 2 2 0.05 -2 0
capture = 4
END SCULPT
I would appreciate any help.
