You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GMSH Python API 2D矩形融合失败求助:存在界面及TrimmedCurve问题

解决Gmsh Python API矩形融合不彻底及TrimmedCurve问题

核心问题分析

  • 融合后残留界面:原代码几何坐标计算逻辑错误,导致矩形未真正共边,布尔融合无法识别为可合并的相邻实体
  • TrimmedCurve生成:布尔运算后残留的修剪曲线,会引发有限元软件导入兼容性问题,需通过几何清理消除

解决方案步骤

1. 修正几何坐标错位问题

原循环内矩形的y坐标计算逻辑冲突,导致实体位置错位无法共边。修改为使用实时更新的y变量定位:

# Build subsequent horizontal and vertical segments
x = length
y = 0.0
direction = 1

for i in range(1, n_bends):
    y += direction * (cap_length - width)

    if i % 2 == 1:
        # channel odd - 使用实时更新的y坐标
        gmsh.model.occ.addRectangle(x=length, y=y, z=0,
                                    dx=-length, dy=width)
        # end cap odd
        gmsh.model.occ.addRectangle(x=0, y=y, z=0,
                                    dx=-width, dy=cap_length)
        direction *= -1

    elif i % 2 == 0:
        # channel even - 使用实时更新的y坐标
        gmsh.model.occ.addRectangle(x=0, y=y, z=0,
                                    dx=length, dy=width)
        # end cap even
        gmsh.model.occ.addRectangle(x=length, y=y, z=0,
                                    dx=width, dy=cap_length)
        direction *= -1

2. 优化布尔融合与几何清理流程

添加多轮几何清理,采用逐步融合方式确保实体完全合并,消除TrimmedCurve:

# Synchronize to create the area(s)
gmsh.model.occ.synchronize()

# 第一步:删除重复几何实体,确保共边完全重合
gmsh.model.occ.removeAllDuplicates()
gmsh.model.occ.synchronize()

# 获取所有曲面实体
surface_dimTags = gmsh.model.getEntities(dim=2)
print("初始曲面数量:", len(surface_dimTags))

# 第二步:逐步融合所有曲面,避免批量融合的识别误差
if len(surface_dimTags) > 1:
    target = surface_dimTags[0]
    for tag in surface_dimTags[1:]:
        result = gmsh.model.occ.fuse([target], [tag], removeObject=True, removeTool=True)
        target = result[0][0]  # 更新目标为融合后的曲面
    gmsh.model.occ.synchronize()

# 第三步:再次清理重复实体,彻底消除TrimmedCurve
gmsh.model.occ.removeAllDuplicates()
gmsh.model.occ.synchronize()

# 确认最终曲面数量
final_surfaces = gmsh.model.getEntities(dim=2)
print("最终曲面数量:", len(final_surfaces))

3. 替代方案:直接生成无修剪曲面

若仍存在TrimmedCurve,可跳过布尔运算,直接通过边界线生成曲面:

  1. 用addLine创建连续边界曲线
  2. 通过addCurveLoop组成闭合环
  3. 用addPlaneSurface生成单一曲面
    该方法完全避免修剪曲线,兼容性更强。

完整修正代码

import gmsh
import sys
import os

cm = 1e-2
mm = 1e-3
μm = 1e-6

# Initialize Gmsh
gmsh.initialize()
gmsh.model.add("Serpentine")

# for compatibility with Firedrake
# gmsh.option.setNumber("Mesh.MshFileVersion", 2.2)  # write MSH 2.2
gmsh.option.setNumber("Mesh.Binary", 0)            # ASCII
gmsh.option.setNumber("Mesh.SaveAll", 0)           # only physical groups (fine)
gmsh.model.mesh.setOrder(1)                        # first-order elements

# Parameters
length = 4.0 * mm  # 2.0 cm
width  = 1.6 * mm
height = 1.6 * mm  # not used in 2D, kept to minimize diffs

inlet_pad = 2 * width
cap_length = 3 * width

n_bends = 2  # minimum is 2, 1 should also be ok, but doesn't work right now.

# Use OpenCASCADE for area creation (2D)
# create first channel
gmsh.model.occ.addRectangle(x=-inlet_pad, y=0, z=0,
                            dx=length + inlet_pad, dy=width, tag=1)

# end cap 1
gmsh.model.occ.addRectangle(x=length, y=0, z=0,
                            dx=width, dy=cap_length)

# Build subsequent horizontal and vertical segments
x = length
y = 0.0
direction = 1

for i in range(1, n_bends):
    y += direction * (cap_length - width)

    if i % 2 == 1:
        # channel odd
        gmsh.model.occ.addRectangle(x=length, y=y, z=0,
                                    dx=-length, dy=width)
        # end cap odd
        gmsh.model.occ.addRectangle(x=0, y=y, z=0,
                                    dx=-width, dy=cap_length)
        direction *= -1

    elif i % 2 == 0:
        # channel even
        gmsh.model.occ.addRectangle(x=0, y=y, z=0,
                                    dx=length, dy=width)
        # end cap even
        gmsh.model.occ.addRectangle(x=length, y=y, z=0,
                                    dx=width, dy=cap_length)
        direction *= -1

# Synchronize to create the area(s)
gmsh.model.occ.synchronize()

# 清理重复实体
gmsh.model.occ.removeAllDuplicates()
gmsh.model.occ.synchronize()

# get surface entity dimTags
surface_dimTags = gmsh.model.getEntities(dim=2)
print("初始曲面数量:", len(surface_dimTags))

# 逐步融合所有曲面
if len(surface_dimTags) > 1:
    target = surface_dimTags[0]
    for tag in surface_dimTags[1:]:
        result = gmsh.model.occ.fuse([target], [tag], removeObject=True, removeTool=True)
        target = result[0][0]
    gmsh.model.occ.synchronize()

# 再次清理重复实体,消除TrimmedCurve
gmsh.model.occ.removeAllDuplicates()
gmsh.model.occ.synchronize()

# 确认最终曲面数量
final_surfaces = gmsh.model.getEntities(dim=2)
print("最终曲面数量:", len(final_surfaces))

# Define a characteristic length for mesh elements
lc = 2.0 * cm / 100

# Set the mesh size for all 0D entities (points)
gmsh.model.mesh.setSize(dimTags=gmsh.model.getEntities(0), size=lc)
gmsh.option.setNumber("Mesh.CharacteristicLengthMin", lc / 2.0)
gmsh.option.setNumber("Mesh.CharacteristicLengthMax", lc)
gmsh.option.setNumber("Mesh.MeshSizeFromCurvature", 100)

# Generate mesh (2D)
gmsh.model.mesh.generate(dim=2)

# Optionally save the mesh
meshes_dir = "meshes"
os.makedirs(meshes_dir, exist_ok=True)

mesh_filename = os.path.join(meshes_dir, "Serpentine_2D.msh")
gmsh.write(mesh_filename)
# save .vtk file for easy visualization
gmsh.write(mesh_filename.replace(".msh", ".vtk"))

# Launch GUI (optional)
if 'close' not in sys.argv:
    gmsh.fltk.run()

# Finalize
gmsh.finalize()

内容的提问来源于stack exchange,提问作者Nick Brady

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 12:44:51