Hello Everyone,
So sorry To write the whole code here. I try to make a domain with some cycles in it with different physical groups. But unfortunately, the result shows that they are not connected! And the flow can not diffuse through the cycles. How can I connect the surfaces together?
I know that gmsh.model.occ.fragment glue the surfaces together, but unfortunately, it is not working in my code! It’s several days that I am struggling with it, but no success. Therefore, I put the whole code here.
Thanks in advance.
import gmsh
import numpy as np
scale_of_Mesh = 1e-7
domain_size = np.array([5, 5])
RadiusOfIonomers= 0.5
sphere_positions= np.array([[2.18503937, 1.88976378, 1.7519685, 4.78346457, 0.25590551, 4.68503937],
[3.22834646, 3.68110236, 3.11023622, 1.31889764, 2.91338583, 2.18503937]])
sphere_radii= np.array([0.39215686, 0.39215686 ,0.39215686, 0.39215686 ,0.39215686, 0.39215686])
def translate_Microstructure(sphere_positions, sphere_radii, domain_size):
gmsh.initialize()
gmsh.option.setNumber("Geometry.Tolerance", 1e-20)
gmsh.option.setNumber("Mesh.MshFileVersion", 2.0)
gmsh.option.setNumber("Mesh.ScalingFactor", scale_of_Mesh)
gmsh.model.add("Microstructure_2D")
X_ionmerslist=[]
Y_ionmerslist=[]
for i in range (0, sphere_positions.shape[1]):
Xionomers = sphere_positions[0,i]
Yionomers = sphere_positions[1,i]
X_ionmerslist.append(Xionomers)
Y_ionmerslist.append(Yionomers)
domain = gmsh.model.occ.addRectangle(0,0,0, domain_size[0],domain_size[1], 1)
carbon_circles = []
ionomer_circles = []
for i in range(0, sphere_positions.shape[1]):
x_ = sphere_positions[0,i]
y_ = sphere_positions[1,i]
r_ = sphere_radii[i]
carbon_circles.append(gmsh.model.occ.addDisk(x_, y_, 0, r_, r_ ))
for i in range(0, len(X_ionmerslist)):
xIomer = X_ionmerslist[i]
yIonomer = Y_ionmerslist[i]
rIonomer = RadiusOfIonomers
Ionomer_thickness =0# (ionomer_radius_factor-1)*sphere_radii[i]
offset_x = 0 #(random.randrange(-20,20))/100
offset_y = 0 #(random.randrange(-20,20))/100
ionomer_circles.append(gmsh.model.occ.addDisk(xIomer + offset_x, yIonomer + offset_y, 0, rIonomer+Ionomer_thickness, rIonomer+Ionomer_thickness ))
# Fuse all the Ionomer together
if len(ionomer_circles) > 1:
all_ionomer_temp, _ = gmsh.model.occ.fuse( [(2, ionomer_circles[0])] , [(2, ionomer_circles[1])])
elif len(ionomer_circles) == 1:
all_ionomer_temp = [(2, ionomer_circles[0])]
else:
assert 'No Ionomer in the microstructure'
for i in range(2, len(ionomer_circles)):
all_ionomer_temp, _ = gmsh.model.occ.fuse( all_ionomer_temp, [(2, ionomer_circles[i])])
# Fuse all the carbon together
if len(carbon_circles ) > 1:
carbon, _ = gmsh.model.occ.fuse( [(2, carbon_circles[0])] , [(2, carbon_circles[1])])
elif len(carbon_circles ) == 1:
carbon = [(2, carbon_circles[0])]
else:
assert 'No Carbon in the microstructure'
for i in range(2, len(carbon_circles)):
carbon, _ = gmsh.model.occ.fuse( carbon, [(2, carbon_circles[i])])
# ionomer = all_ionomer_temp - carbon
ionomer_and_carbon, fragmentation_list = gmsh.model.occ.fragment(all_ionomer_temp, carbon) # ionomer_and_carbon: fragment returns a list of both, ionomer and the carbon
ionomer_temp_list = []
carbon_temp_list = []
for i in range(0, len(fragmentation_list)):
if i < len(all_ionomer_temp):
for element in fragmentation_list[i]:
ionomer_temp_list.append(element)
else:
for element in fragmentation_list[i]:
carbon_temp_list.append(element)
for car in carbon_temp_list:
ionomer_temp_list.remove(car)
domain_fragment_ionomer, fragmentation_list = gmsh.model.occ.fragment( [(2,domain)], ionomer_and_carbon )
void = fragmentation_list[0]
out = [] # element not in fragmentation_list[0] --> therefore not inside the domain
ionomer = [] # element in fragmentation_list[0] and the element in ionomer_and_carbon[i] is in the ionomer_temp_list[i-1]
carbon = [] # element in fragmentation_list[0] and the element in ionomer_and_carbon[i] is in the carbon_temp_list[i-1]
for i in range(1, len(fragmentation_list)):
temp_list = fragmentation_list[i]
for element in temp_list:
if element not in void:
out.append(element)
domain_fragment_ionomer.remove(element)
else:
void.remove(element)
if ionomer_and_carbon[i-1] in ionomer_temp_list:
ionomer.append(element)
else:
carbon.append(element)
gmsh.model.occ.dilate(carbon, x=0, y=0, z=0, a=scale_of_Mesh, b=scale_of_Mesh, c=1)
gmsh.model.occ.dilate(ionomer, x=0, y=0, z=0, a=scale_of_Mesh, b=scale_of_Mesh, c=1)
gmsh.model.occ.dilate(void, x=0, y=0, z=0, a=scale_of_Mesh, b=scale_of_Mesh, c=1)
gmsh.model.occ.synchronize()
gmsh.model.removeEntities(out, True) # Delete outside parts recursively: also delete the curves outside
def sort_Boundary(bcs_lis):
inside_domain = []
edge_of_domain = []
LeftOfedge =[]
RightOfedge=[]
epsilon_bcs = 1e-12 * scale_of_Mesh
for i in range(0, len(bcs_lis)):
temp = bcs_lis[i]
com = gmsh.model.occ.getCenterOfMass(temp[0], abs(temp[1]))
temp_idx = abs(temp[1])
if com[0] <= epsilon_bcs:
LeftOfedge.append(temp_idx)
if com[0] >= domain_size[0]*scale_of_Mesh-epsilon_bcs:
RightOfedge.append(temp_idx)
if com[0] <= epsilon_bcs or com[1] <= epsilon_bcs or com[0] >= domain_size[0]*scale_of_Mesh - epsilon_bcs \
or com[1] >= domain_size[1]*scale_of_Mesh-epsilon_bcs:
edge_of_domain.append(temp_idx)
else:
inside_domain.append(temp_idx)
return inside_domain, edge_of_domain, LeftOfedge , RightOfedge
carbon_Boundary_tuple = gmsh.model.getBoundary(carbon)
carbon_boundary_inside, carbon_boundary_edge,_,_ = sort_Boundary(carbon_Boundary_tuple)
void_Boundary_tuple = gmsh.model.getBoundary(void)
_, void_boundary_edge,Leftline,Rightline = sort_Boundary(void_Boundary_tuple)
carbon_material_marker = 1 # marker for the surfaces with carbon
carbon_bcs_inside_marker = 2 # marker for the boundaries of carbon inside the domain
ionomer_material_marker = 4 # marker of the ionomer surfaces in the domain
void_marker = 7 # marker of the void surfaces in the domain
void_bcs_edge_marker = 8 # marker of the boundaries of the void with the edge of the domain
# mark Carbon
carbon_idx = []
for car in carbon:
carbon_idx.append( car[1] )
gmsh.model.addPhysicalGroup(2, carbon_idx, carbon_material_marker)
gmsh.model.setPhysicalName(2, carbon_material_marker, "Carbon")
gmsh.model.addPhysicalGroup(1, carbon_boundary_inside, carbon_bcs_inside_marker)
gmsh.model.setPhysicalName(1, carbon_bcs_inside_marker, "Carbon_BCS_inside")
# mark Ionomer
ionomer_idx = []
for ion in ionomer:
ionomer_idx.append( ion[1] )
gmsh.model.addPhysicalGroup(2, ionomer_idx, ionomer_material_marker)
gmsh.model.setPhysicalName(2, ionomer_material_marker, "Ionomer")
# mark void
void_idx = []
for voi in void:
void_idx.append( voi[1] )
gmsh.model.addPhysicalGroup(2, void_idx, void_marker)
gmsh.model.setPhysicalName(2, void_marker, "Void")
gmsh.model.addPhysicalGroup(1, void_boundary_edge, void_bcs_edge_marker)
gmsh.model.setPhysicalName(1, void_bcs_edge_marker, "Void_BCS_Edge")
#LeftandRightLine
gmsh.model.addPhysicalGroup(1, Leftline, 101)
gmsh.model.setPhysicalName(1, 101, "Left Line")
gmsh.model.addPhysicalGroup(1, Rightline, 202)
gmsh.model.setPhysicalName(1, 202, "Right Line")
# Decrease Mesh-Size when the mesh gets close to the carbon and ionomer boundaries (inside of domain)
field_close_to_carbon_marker1 = 1
field_close_to_carbon_marker2 = 2
resolution_close_to_carbon = 1e-1 * scale_of_Mesh
max_resolution = 2
gmsh.model.mesh.field.add("Distance", field_close_to_carbon_marker1)
gmsh.model.mesh.field.setNumbers(field_close_to_carbon_marker1, "CurvesList", carbon_boundary_inside)
gmsh.model.mesh.field.setNumber(field_close_to_carbon_marker1, "NumPointsPerCurve", 100)
gmsh.model.mesh.field.add("Threshold", field_close_to_carbon_marker2)
gmsh.model.mesh.field.setNumber(field_close_to_carbon_marker2, "IField", field_close_to_carbon_marker1)
gmsh.model.mesh.field.setNumber(field_close_to_carbon_marker2, "LcMin", resolution_close_to_carbon)
gmsh.model.mesh.field.setNumber(field_close_to_carbon_marker2, "LcMax", max_resolution)
gmsh.model.mesh.field.setNumber(field_close_to_carbon_marker2, "DistMin", 0)
gmsh.model.mesh.field.setNumber(field_close_to_carbon_marker2, "DistMax", 2)
min_mesh_size_field_marker = 20
gmsh.model.mesh.field.add("Min", min_mesh_size_field_marker)
gmsh.model.mesh.field.setNumbers(min_mesh_size_field_marker, "FieldsList", [field_close_to_carbon_marker2])
gmsh.model.mesh.field.setAsBackgroundMesh(min_mesh_size_field_marker)
gmsh.option.setNumber("Mesh.Smoothing", 100)
gmsh.model.mesh.generate(2)
gmsh.fltk.run()
gmsh.finalize()
if __name__ == "__main__":
translate_Microstructure(sphere_positions, sphere_radii, domain_size)