Hi @Norbert_Hofbauer
The .cub5 is generated by some random particle placement. So the basis is the same but the random particle placement makes the cub5 look different.
The whole script is here and “particles.xlsx” is in the attachment
import sys
sys.path.append("C:\Program Files\Coreform Cubit 2022.4\\bin")
import cubit
import numpy as np
import pandas as pd
import pathlib as pl
import logging
logging.basicConfig(level=logging.DEBUG, filename="console.log", filemode="w", format="%(asctime)s - [%(levelname)s] - %(message)s")
cubit.init(["cubit", "-nojournal"])
cubit.reset()
# reading the particle position file
particles_fp = pl.Path("particles.xlsx")
particles_df = pd.concat([pd.read_excel(particles_fp, sheet_name="real"), pd.read_excel(particles_fp, sheet_name="ghost")])
particles_df = particles_df.reset_index()
# creating spheres
for id, particle in particles_df.iterrows():
if particle.x == 200.0: # please ignore why I'm doing this
continue
cubit.cmd(f"create sphere radius {particle['radius']}")
cubit.cmd(f"move volume {cubit.get_entities('volume')[-1]} location {particle.x} {particle.y} {particle.z}")
# creating epoxy
rve_size = 18.0
cubit.cmd(f"create brick x {rve_size} y {rve_size} z {rve_size}")
cubit.cmd(f"move volume {cubit.get_last_id('volume')} x {rve_size / 2.} y {rve_size / 2.} z {rve_size / 2.} include_merged")
# boolean operations
# intersection - to remove ghost spheres parts outside the cube
cubit.cmd("intersect volume all")
cubit.cmd(f"create brick x {rve_size} y {rve_size} z {rve_size}")
cubit.cmd(f"move volume {cubit.get_last_id('volume')} x {rve_size / 2.} y {rve_size / 2.} z {rve_size / 2.} include_merged")
# remove overlap and merge
for i in cubit.get_entities("volume")[:-1]:
cubit.cmd(f"remove overlap volume {cubit.get_entities('volume')[-1]} {i} modify volume {cubit.get_entities('volume')[-1]}")
cubit.cmd("merge volume all")
# creating blocks
cubit.cmd(f"block 1 add volume {cubit.get_entities('volume')[-1]}")
cubit.cmd(f"block 1 name Epoxy")
for i in cubit.get_entities("volume")[:-1]:
cubit.cmd(f"block 2 add volume {i}")
cubit.cmd("block 2 name xSP")
cubit.cmd("block all element type tetra10")
# creating materials
cubit.cmd('create material "Epoxy" property_group "CUBIT-ABAQUS" id 1')
cubit.cmd('modify material "Epoxy" scalar_properties "MODULUS" 561 "POISSON" 0.3 "YIELD_STRENGTH" 17.17')
cubit.cmd('block 1 material "Epoxy"')
cubit.cmd('create material "xSP" property_group "CUBIT-ABAQUS" id 2')
cubit.cmd('modify material "xSP" scalar_properties "MODULUS" 20e3 "POISSON" 0.3 "YIELD_STRENGTH" 800.0')
cubit.cmd('block 2 material "xSP"')
# --------------------------- Meshing ----------------------------- #
# imprinting volumes so that we have same curves and vertices on opposite side
real_vol_limit = cubit.get_last_id("volume")
displacements = [[rve_size, 0, 0], [-2 * rve_size, 0, 0], [rve_size, rve_size, 0], [0, -2.0 * rve_size, 0], [0, rve_size, rve_size], [0, 0, -2.0 * rve_size]]
for i, displacement in enumerate(displacements):
if i == 0:
for vid in cubit.get_entities("volume"):
cubit.cmd(f"volume {vid} copy move x {displacement[0]} y {displacement[1]} z {displacement[2]}")
cubit.cmd("imprint volume all")
else:
for vid in range(real_vol_limit, cubit.get_last_id("volume") + 1):
cubit.cmd(f"volume {vid} move x {displacement[0]} y {displacement[1]} z {displacement[2]}")
cubit.cmd("imprint volume all")
# deleting extra volumes
cubit.cmd(f"delete volume {' '.join(map(str, range(real_vol_limit + 1, cubit.get_last_id('volume') + 1)))}")
# imprint/merge
cubit.cmd("imprint volume all")
cubit.cmd("merge volume all")
# meshing edges
edge_size = 0.5
for dir in ["xy", "yz", "xz"]:
for i, j in [[0, 0], [0, rve_size], [rve_size, 0], [rve_size, rve_size]]:
cubit.cmd(f"curve all with {dir[0]}_coord={i} and {dir[1]}_coord={j} size {edge_size}")
cubit.cmd(f"curve all with {dir[0]}_coord={i} and {dir[1]}_coord={j} scheme equal")
cubit.cmd(f'mesh curve all with {dir[0]}_coord={i} and {dir[1]}_coord={j}')
# mesh faces and imprint/merge the mesh on the opposite side
cubit.cmd('set maximum arc_span 15')
mesh_factor = 6
for dir in ["x", "y", "z"]:
# meshing
surface_ids = cubit.parse_cubit_list("surface", f"with {dir}_coord==0")
cubit.cmd(f"surface {' '.join(map(str, surface_ids))} size auto factor {mesh_factor} propagate")
cubit.cmd(f"surface {' '.join(map(str, surface_ids))} scheme trimesh")
cubit.cmd(f"mesh surface {' '.join(map(str, surface_ids))}")
for sid in surface_ids:
cubit.cmd(f"surface {sid} copy move {dir} {rve_size}")
# imprinting
cubit.cmd(f"merge surface all with {dir}_coord={rve_size}")
cubit.cmd(f"delete body all with is_sheetbody")
# meshing other surfaces
unmeshed_surface_ids = cubit.parse_cubit_list('surface', 'with not is_meshed')
cubit.cmd(f"surface {' '.join(map(str, unmeshed_surface_ids))} size auto factor {mesh_factor} propagate")
cubit.cmd(f"surface {' '.join(map(str, unmeshed_surface_ids))} scheme trimesh")
cubit.cmd(f"mesh surface {' '.join(map(str, unmeshed_surface_ids))}")
# volume mesh
cubit.cmd(f"volume all scheme tetmesh")
cubit.cmd(f"set tetmesher hpc on")
cubit.cmd("mesh volume all")
# renumbering nodes for periodic BC script success
cubit.cmd(f"renumber node all in Volume all start_id 1 uniqueids")
cubit.cmd(f"renumber node all in Volume all start_id 1 uniqueids")
# export cub5 data
cubit.cmd('save cub5 "M:\HL2\RVE_generation\cubit\perfect_bonding\geometry_pb.cub5" overwrite journal')
# export abaqus input file
cubit.cmd('export abaqus "M:\HL2\RVE_generation\cubit\perfect_bonding\geometry_pb.inp" overwrite everything')
particles.zip (18.8 KB)
The .cub5 file is in the link below as it is too large to attach.
I would like my periodic mesh without zero (or really small volume) elements. In case you could also check and correct other quality aspects like distortion, then the simulations run smoother. But it is secondary, 0 volume elements elimination is primary.
I really appreciate your help. Thank you.