is there a way to force the mesh nodes of a segment of a spherical domain with a hole at the center like the one shown below to lie on spherical surfaces?
If you are confident that all the nodes are near their target radius (e.g., you’re confident that you can define a target radius and tolerance, such that only the nodes you want to “snap” to that radius fall within the tolerance band) then you could move the nodes using Python… something like:
#!python
import numpy
def snap_nodes_near_radius( target_radius, abs_tol ):
near_nodes = []
N = cubit.get_entities( "node" )
for nid in N:
x,y,z = cubit.get_nodal_coordinates( nid )
r = numpy.sqrt( x**2 + y**2 + z**2 )
if abs( r - target_radius ) <= abs_tol:
near_nodes.append( nid )
cubit.cmd( f"draw node {cubit.get_id_string( near_nodes )}" )
for nid in near_nodes:
x,y,z = cubit.get_nodal_coordinates( nid )
r = numpy.sqrt( x**2 + y**2 + z**2 )
r_diff = target_radius - r
norm_rad_vec = numpy.array( [x, y, z] ) / numpy.linalg.norm( [x, y, z] )
dx, dy, dz = r_diff * norm_rad_vec
cubit.cmd( f"node {nid} move X {dx} Y {dy} Z {dz}" )
return near_nodes
If you don’t have too many layers (e.g., no more than a few hundred) you might also find it preferable to simply produce webcuts at each desired radius. For ease of defining sets (blocks, sidesets, nodesets) I’d recommend assigning sets prior to your additional webcutting. Something like:
#!python
import numpy
rmin = 76
rmax = 100
N = 10
r = numpy.linspace( rmin, rmax, N )[1:-1]
for ri in r:
cubit.cmd( f"sphere radius {ri}" )
tool_bid = cubit.get_last_id( "body" )
cubit.cmd( f"webcut volume in block 1 tool body {tool_bid}" )
cubit.cmd( f"delete body {tool_bid}" )
You might try a few differ sweep options under the Advanced settings. For example, try with/without Redistribute Nodes, different Transform Methods, etc. This is the least-likely to solve your problem, IMO, but might be “close enough”.
What you could also do is to smooth the faces to a target surface. For this you would need to set fullhex on to have access to the inner faces of the volumes.
set developer on
set fullhex on
create sphere radius 81
#!python
import numpy
def get_faces(surface_id,distance):
face_ids = cubit.parse_cubit_list( "face", f"all" )
print(face_ids)
surface = cubit.surface(surface_id)
return_face_ids=[]
for fid in face_ids:
location = numpy.array(cubit.get_center_point("face",fid))
new_location = numpy.array(surface.closest_point_trimmed(location))
delta = new_location - location
current_distance = numpy.linalg.norm(delta)
if current_distance<=distance:
return_face_ids.append(fid)
return return_face_ids
face_ids = get_faces(65,5e-1)
cubit.cmd(f"draw face {' '.join(str(id) for id in face_ids)}")
cubit.cmd(f"smooth face {' '.join(str(id) for id in face_ids)} scheme laplacian target surface 65")