Hi, I am generating my mesh and boundary conditions in GMSH. I use meshio to generate an XDMF file for use in legacy FEniCS code:
import gmsh
import meshio
# Função para inicializar o GMSH e configurar opções
def initialize_gmsh():
gmsh.initialize()
gmsh.option.setNumber("General.Terminal", 1) # Ativa saída no terminal
gmsh.model.add("modelo_4_retangulos") # Adiciona o modelo
# Função para criar pontos e linhas para um retângulo
def create_rectangle(x_min, y_min, x_max, y_max):
geom = gmsh.model.geo
p1 = geom.addPoint(x_min, y_min, 0)
p2 = geom.addPoint(x_max, y_min, 0)
p3 = geom.addPoint(x_max, y_max, 0)
p4 = geom.addPoint(x_min, y_max, 0)
l1 = geom.addLine(p1, p2) # Linha inferior
l2 = geom.addLine(p2, p3) # Linha direita
l3 = geom.addLine(p3, p4) # Linha superior
l4 = geom.addLine(p4, p1) # Linha esquerda
loop = geom.addCurveLoop([l1, l2, l3, l4])
return loop, [l1, l2, l3, l4] # Retorna também as linhas
# Função para configurar a malha transfinita
def set_transfinite_mesh(curves, nx, ny):
for i, tag in enumerate(curves):
gmsh.model.geo.mesh.setTransfiniteCurve(tag, (nx if i % 2 == 0 else ny) + 1)
# Função principal para gerar a malha com condições de contorno
def generate_mesh():
geom = gmsh.model.geo
# Dimensões dos retângulos
small_width, small_height = 1, 1 # Dimensões dos retângulos pequenos
large_width, large_height = 3, 2 # Dimensões do retângulo maior (domínio de projeto)
# Cria os quatro retângulos
loop1, curves1 = create_rectangle(0, 0, small_width, small_height) # Retângulo pequeno inferior esquerdo
loop2, curves2 = create_rectangle(small_width, 0, small_width + large_width, large_height / 2) # Retângulo grande inferior
loop3, curves3 = create_rectangle(small_width, large_height / 2, small_width + large_width, large_height) # Retângulo grande superior
loop4, curves4 = create_rectangle(small_width + large_width, 0, small_width + large_width + small_width, small_height) # Retângulo pequeno inferior direito
# Define a malha transfinita para cada conjunto de curvas
set_transfinite_mesh(curves1, 10, 10) # Retângulo pequeno inferior esquerdo
set_transfinite_mesh(curves2, 30, 10) # Retângulo grande inferior
set_transfinite_mesh(curves3, 30, 10) # Retângulo grande superior
set_transfinite_mesh(curves4, 10, 10) # Retângulo pequeno inferior direito
# Adiciona condições de contorno (grupos físicos)
gmsh.model.addPhysicalGroup(1, [curves1[3]], 201) # Inlet (vertical esquerda do primeiro retângulo)
gmsh.model.setPhysicalName(1, 201, "Inlet")
gmsh.model.addPhysicalGroup(1, [curves4[1]], 202) # Outlet (vertical direita do último retângulo)
gmsh.model.setPhysicalName(1, 202, "Outlet")
# Paredes: todas as demais arestas externas
walls = [
curves1[0], # Linha inferior do 1º retângulo
curves1[2], # Linha superior do 1º retângulo
curves2[0], # Linha superior do 2º retângulo
curves3[1], # Linha direita do 3º retângulo
curves3[2], # Linha superior do 3º retângulo
curves3[3], # Linha esquerda do 3º retângulo
curves4[0], # Linha inferior do 4º retângulo
curves4[2], # Linha superior do 4º retângulo
]
# Define o grupo de paredes
gmsh.model.addPhysicalGroup(1, walls, 203) # Paredes externas
gmsh.model.setPhysicalName(1, 203, "Walls")
# Cria superfícies
s1 = geom.addPlaneSurface([loop1])
s2 = geom.addPlaneSurface([loop2])
s3 = geom.addPlaneSurface([loop3])
s4 = geom.addPlaneSurface([loop4])
# Define o grupo físico para as superfícies (domínio)
gmsh.model.addPhysicalGroup(2, [s1, s2, s3, s4], 101)
gmsh.model.setPhysicalName(2, 101, "Domain")
# Define malha estruturada nas superfícies
geom.mesh.setTransfiniteSurface(s1)
geom.mesh.setTransfiniteSurface(s2)
geom.mesh.setTransfiniteSurface(s3)
geom.mesh.setTransfiniteSurface(s4)
# Sincroniza a geometria
geom.synchronize()
# Gera a malha
gmsh.model.mesh.generate(2)
# Salva a malha no formato .msh
gmsh.write("heatsink.msh")
# Converte msh em um único xdmf
def convert_msh_to_xdmf(msh_filename, xdmf_filename):
# Lê o arquivo .msh usando meshio
mesh = meshio.read(msh_filename)
# Filtra as células de domínio e fronteiras
cells = [("triangle", mesh.cells_dict["triangle"]),
("line", mesh.cells_dict["line"])]
# Armazena os dados do domínio e das fronteiras
cell_data = {"gmsh:physical": [mesh.cell_data_dict["gmsh:physical"]["triangle"],
mesh.cell_data_dict["gmsh:physical"]["line"]]}
# Cria a malha combinada
combined_mesh = meshio.Mesh(
points=mesh.points,
cells=cells,
cell_data=cell_data
)
# Salva a malha combinada no formato .xdmf
meshio.write(xdmf_filename, combined_mesh)
# Função para finalizar o GMSH
def finalize_gmsh():
gmsh.finalize()
# Executa o fluxo completo de GMSH e Meshio
def main():
initialize_gmsh() # Inicializa GMSH
generate_mesh() # Gera a malha com condições de contorno
gmsh.fltk.run() # Abre a interface gráfica (opcional)
convert_msh_to_xdmf("heatsink.msh", "heatsink.xdmf") # Converte a malha em um único arquivo .xdmf
finalize_gmsh() # Finaliza GMSH
if __name__ == "__main__":
main()
I have already tried several ways to import this mesh and boundaries, following responses in older threads, but I haven’t been successful, as some problem always comes up. Could someone help me by explaining the proper way to do it?