Skip to content

Commit

Permalink
Merge pull request #1455 from brighthe/develop
Browse files Browse the repository at this point in the history
完善 SOPTX
  • Loading branch information
weihuayi authored Jan 17, 2025
2 parents bd99057 + e2d9a1e commit 94ab250
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 9 deletions.
2 changes: 1 addition & 1 deletion app/soptx/soptx/opt/mma.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,8 @@ def optimize(self, rho: TensorLike, **kwargs) -> Tuple[TensorLike, OptimizationH

# MMA 方法
volfrac = self.constraint.volume_fraction
# 体积约束对设计变量的标准化梯度
fval = bm.sum(rho_phys[:]) / (volfrac * obj_grad.shape[0]) - 1
# 体积约束对设计变量的标准化梯度
dfdx = con_grad[:, None].T / (volfrac * con_grad.shape[0]) # (m, n)
rho_new, low, upp = self._solve_subproblem(
xval=rho[:, None], fval=fval,
Expand Down
3 changes: 3 additions & 0 deletions app/soptx/soptx/pde/cantilever_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
from builtins import list

class Cantilever2dData1:
'''
模型来源论文: Efficient topology optimization in MATLAB using 88 lines of code
'''
def __init__(self,
xmin: float, xmax: float,
ymin: float, ymax: float):
Expand Down
3 changes: 3 additions & 0 deletions app/soptx/soptx/pde/cantilever_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@


class Cantilever3dData1:
'''
模型来源论文: An efficient 3D topology optimization code written in Matlab
'''
def __init__(self,
xmin: float=0, xmax: float=60,
ymin: float=0, ymax: float=20,
Expand Down
3 changes: 3 additions & 0 deletions app/soptx/soptx/pde/mbb_beam_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
from builtins import list

class MBBBeam2dData1:
'''
模型来源论文: Efficient topology optimization in MATLAB using 88 lines of code
'''
def __init__(self,
xmin: float=0, xmax: float=60,
ymin: float=0, ymax: float=20):
Expand Down
27 changes: 19 additions & 8 deletions app/soptx/soptx/tests/test_cantilever_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,30 +192,41 @@ def run_optimization_test(config: TestConfig) -> Dict[str, Any]:
}

if __name__ == "__main__":
base_dir = '/home/heliang/FEALPy_Development/fealpy/app/soptx/soptx/vtu'

# 使用 OC 优化器的配置
'''
参数来源论文: Efficient topology optimization in MATLAB using 88 lines of code
'''
filter_type = 'sensitivity'
optimizer_type = 'oc'
config1 = TestConfig(
nx=160, ny=100,
volume_fraction=0.4,
filter_radius=6.0,
filter_type='sensitivity',
max_iterations=100,
save_dir='/home/heliang/FEALPy_Development/fealpy/app/soptx/soptx/tests/cantilever_2d_oc',
filter_type=filter_type, # 指定使用灵敏度滤波器
save_dir=f'{base_dir}/cantilever_2d_{filter_type}_{optimizer_type}',
mesh_type='uniform_mesh_2d',
assembly_method=AssemblyMethod.FAST_STRESS_UNIFORM,
optimizer_type='oc' # 指定使用 OC 优化器
optimizer_type=optimizer_type, # 指定使用 OC 优化器
max_iterations=200,
tolerance=0.01
)

# 使用 MMA 优化器的配置
filter_type = 'sensitivity'
optimizer_type = 'mma'
config2 = TestConfig(
nx=160, ny=100,
volume_fraction=0.4,
filter_radius=6.0,
filter_type='density',
max_iterations=100,
save_dir='/home/heliang/FEALPy_Development/fealpy/app/soptx/soptx/tests/cantilever_2d_mma',
filter_type=filter_type, # 指定使用灵敏度滤波器
save_dir=f'{base_dir}/cantilever_2d_{filter_type}_{optimizer_type}',
mesh_type='uniform_mesh_2d',
assembly_method=AssemblyMethod.FAST_STRESS_UNIFORM,
optimizer_type='mma' # 指定使用 MMA 优化器
optimizer_type=optimizer_type, # 指定使用 OC 优化器
max_iterations=200,
tolerance=0.01
)

result = run_optimization_test(config2)
Expand Down
6 changes: 6 additions & 0 deletions app/soptx/soptx/tests/test_cantilever_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ def run_optimization_test(config: TestConfig) -> Dict[str, Any]:
base_dir = '/home/heliang/FEALPy_Development/fealpy/app/soptx/soptx/vtu'

# 使用 OC 优化器的配置
'''
参数来源论文: An efficient 3D topology optimization code written in Matlab
'''
filter_type = 'density'
optimizer_type = 'oc'
config1 = TestConfig(
Expand All @@ -209,6 +212,9 @@ def run_optimization_test(config: TestConfig) -> Dict[str, Any]:
)

# 使用 MMA 优化器的配置
'''
参数来源论文: An efficient 3D topology optimization code written in Matlab
'''
filter_type = 'density'
optimizer_type = 'mma'
config2 = TestConfig(
Expand Down
234 changes: 234 additions & 0 deletions app/soptx/soptx/tests/test_mbb_beam_2d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
"""2D 悬臂梁"""

from dataclasses import dataclass
from typing import Literal, Optional, Union, Dict, Any
from pathlib import Path

from fealpy.backend import backend_manager as bm
from fealpy.mesh import UniformMesh2d, TriangleMesh
from fealpy.functionspace import LagrangeFESpace, TensorFunctionSpace

from soptx.material import (
ElasticMaterialConfig,
ElasticMaterialProperties,
SIMPInterpolation
)
from soptx.pde import MBBBeam2dData1
from soptx.solver import (ElasticFEMSolver, AssemblyMethod)
from soptx.filter import (Filter, FilterConfig)
from soptx.opt import ComplianceObjective, VolumeConstraint

from soptx.opt import OCOptimizer, save_optimization_history
from soptx.opt import MMAOptimizer

@dataclass
class TestConfig:
"""Configuration for topology optimization test cases."""
# Required parameters (no default values)
nx: int
ny: int
volume_fraction: float
filter_radius: float
filter_type: Literal['sensitivity', 'density', 'heaviside']

save_dir: Union[str, Path]
mesh_type: Literal['uniform_mesh_2d', 'triangle_mesh']
assembly_method: AssemblyMethod

# Optional parameters (with default values)
elastic_modulus: float = 1.0
poisson_ratio: float = 0.3
minimal_modulus: float = 1e-9
penalty_factor: float = 3.0
projection_beta: Optional[float] = None # Only for Heaviside projection

# 新增优化器类型参数
optimizer_type: Literal['oc', 'mma'] = 'oc' # 默认使用 OC 方法
max_iterations: int = 100
tolerance: float = 0.01

# OC 优化器的参数
move_limit: float = 0.2
damping_coef: float = 0.5
initial_lambda: float = 1e9
bisection_tol: float = 1e-3

# MMA 优化器的参数
asymp_init: float = 0.5
asymp_incr: float = 1.2
asymp_decr: float = 0.7


def create_base_components(config: TestConfig):
"""Create basic components needed for topology optimization based on configuration."""
extent = [0, config.nx, 0, config.ny]
h = [1.0, 1.0]
if config.mesh_type == 'uniform_mesh_2d':
origin = [0.0, 0.0]
mesh = UniformMesh2d(
extent=extent, h=h, origin=origin,
ipoints_ordering='yx', flip_direction=None,
device='cpu'
)
elif config.mesh_type == "triangle_mesh":
mesh = TriangleMesh.from_box(box=[0, config.nx*h[0], 0, config.ny*h[1]],
nx=config.nx, ny=config.ny, device='cpu')

p = 1
space_C = LagrangeFESpace(mesh=mesh, p=p, ctype='C')
tensor_space_C = TensorFunctionSpace(space_C, (-1, 2))
print(f"gdof:", {tensor_space_C.number_of_global_dofs()})
space_D = LagrangeFESpace(mesh=mesh, p=p-1, ctype='D')

# Create material properties
material_config = ElasticMaterialConfig(
elastic_modulus=config.elastic_modulus,
minimal_modulus=config.minimal_modulus,
poisson_ratio=config.poisson_ratio,
plane_assumption="plane_stress"
)
interpolation_model = SIMPInterpolation(penalty_factor=config.penalty_factor)
material_properties = ElasticMaterialProperties(
config=material_config,
interpolation_model=interpolation_model
)

pde = MBBBeam2dData1(
xmin=0, xmax=extent[1] * h[0],
ymin=0, ymax=extent[3] * h[1]
)

solver = ElasticFEMSolver(
material_properties=material_properties,
tensor_space=tensor_space_C,
pde=pde,
assembly_method=config.assembly_method,
solver_type = 'direct',
solver_params = {'solver_type': 'mumps'}
# solver_type='cg',
# solver_params={'maxiter': 1000, 'atol': 1e-8, 'rtol': 1e-8}
)

array = config.volume_fraction * bm.ones(mesh.number_of_cells(), dtype=bm.float64)
rho = space_D.function(array)

return mesh, space_D, material_properties, solver, rho

def run_optimization_test(config: TestConfig) -> Dict[str, Any]:
"""Run topology optimization test with given configuration."""
# Create base components
mesh, space_D, material_properties, solver, rho = create_base_components(config)
NC = mesh.number_of_cells()

# Create filter based on configuration
filter_config = FilterConfig(
filter_type={'sensitivity': 0, 'density': 1, 'heaviside': 2}[config.filter_type],
filter_radius=config.filter_radius)
filter_obj = Filter(filter_config)
filter_obj.initialize(mesh)

# Create optimization components
objective = ComplianceObjective(
material_properties=material_properties,
solver=solver)

constraint = VolumeConstraint(
mesh=mesh,
volume_fraction=config.volume_fraction)

# 根据配置创建优化器
if config.optimizer_type == 'oc':
optimizer = OCOptimizer(
objective=objective,
constraint=constraint,
filter=filter_obj,
options={
'max_iterations': config.max_iterations,
'move_limit': config.move_limit,
'damping': config.damping_coef,
'tolerance': config.tolerance,
'initial_lambda': config.initial_lambda,
'bisection_tol': config.bisection_tol
}
)
elif config.optimizer_type == 'mma':
optimizer = MMAOptimizer(
objective=objective,
constraint=constraint,
filter=filter_obj,
options={
'max_iterations': config.max_iterations,
'tolerance': config.tolerance,
'm': 1,
'n': NC,
'xmin': bm.zeros(NC, dtype=bm.float64).reshape(-1, 1),
'xmax': bm.ones(NC, dtype=bm.float64).reshape(-1, 1),
"a0": 1,
"a": bm.zeros(1, dtype=bm.float64).reshape(-1, 1),
'c': 1e4 * bm.ones(1, dtype=bm.float64).reshape(-1, 1),
'd': bm.zeros(1, dtype=bm.float64).reshape(-1,),
}
)
else:
raise ValueError(f"Unsupported optimizer type: {config.optimizer_type}")

# Prepare optimization parameters
opt_params = {}
if config.filter_type == 'heaviside' and config.projection_beta is not None:
opt_params['beta'] = config.projection_beta

# Run optimization
rho_opt, history = optimizer.optimize(rho=rho[:], **opt_params)

# Save results
save_path = Path(config.save_dir)
save_path.mkdir(parents=True, exist_ok=True)
save_optimization_history(mesh, history, str(save_path))

return {
'optimal_density': rho_opt,
'history': history,
'mesh': mesh
}

if __name__ == "__main__":
base_dir = '/home/heliang/FEALPy_Development/fealpy/app/soptx/soptx/vtu'

filter_type = 'sensitivity'
optimizer_type = 'oc'
'''
参数来源论文: Efficient topology optimization in MATLAB using 88 lines of code
'''
config1 = TestConfig(
nx=60, ny=20,
volume_fraction=0.5,
filter_radius=2.4,
filter_type=filter_type, # 指定使用灵敏度滤波器
save_dir=f'{base_dir}/mbb_beam_2d_{filter_type}_{optimizer_type}',
mesh_type='uniform_mesh_2d',
assembly_method=AssemblyMethod.FAST_STRESS_UNIFORM,
optimizer_type=optimizer_type, # 指定使用 OC 优化器
max_iterations=200,
tolerance=0.01
)

filter_type = 'density'
optimizer_type = 'oc'
'''
参数来源论文: Efficient topology optimization in MATLAB using 88 lines of code
'''
config2 = TestConfig(
nx=60, ny=20,
volume_fraction=0.5,
filter_radius=2.4,
filter_type=filter_type, # 指定使用密度滤波器
save_dir=f'{base_dir}/mbb_beam_2d_{filter_type}_{optimizer_type}',
mesh_type='uniform_mesh_2d',
assembly_method=AssemblyMethod.FAST_STRESS_UNIFORM,
optimizer_type=optimizer_type, # 指定使用 OC 优化器
max_iterations=200,
tolerance=0.01
)

result = run_optimization_test(config2)

0 comments on commit 94ab250

Please sign in to comment.