Mesh node placement

Hi all,

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?

The aim is to ensure that the nodes like the ones marked in orange have the same radius as the node lying on one of the straight domain edges.

The geometry and mesh were generated using the attached journal file
test.jou (1.6 KB)

Thanks,
-Christos

Hi @xef,

There are a few ways you could do this.

  1. 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
  1. 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}" )
  1. 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")