Examples
Optimization of a stiffened roof
This exemple is located in directory examples/OPT_stiffPanel
.
Problem description
The problem of the stiffened roof is derived from the initial shape optimization problem of a roof under vertical uniform load [BWDC05, KB06]. Two stiffeners are added to the initial square plate. We introduce two embedded surfaces to define these stiffeners as shown in Fig. 5.
The square plate can be defined from 4 control points:
1, -5.00, -5.00, 0.00
2, 5.00, -5.00, 0.00
3, -5.00, 5.00, 0.00
4, 5.00, 5.00, 0.00
And the connectivity table, defining patch 2, of type U3 (shell) made of a single element:
Based on the square plate, a hull is defined, made of 8 control points, four of which are those of the plate:
1, -5.00, -5.00, 0.00
2, 5.00, -5.00, 0.00
3, -5.00, 5.00, 0.00
4, 5.00, 5.00, 0.00
5, -5.00, -5.00, 0.60
6, 5.00, -5.00, 0.60
7, -5.00, 5.00, 0.60
8, 5.00, 5.00, 0.60
Connectivity table, defining patch 1, of type U0 (hull) made of a single element:
*Element,type=U0,elset=MappingEls
1, 8,7,6,5,4,3,2,1
The stiffeners are defined in the parametric space of the hull, and are defined as linear plates for the sake of simplicity:
9, 0.30, 0.00, 0.00
10, 0.30, 1.00, 0.00
11, 0.30, 0.00, 1.00
12, 0.30, 1.00, 1.00
17, 0.70, 0.00, 0.00
18, 0.70, 1.00, 0.00
19, 0.70, 0.00, 1.00
20, 0.70, 1.00, 1.00
Connectivity table, defining the stiffeners as patches 3 and 10, of tye U30 (embedded shells):
*Element,type=U30,elset=SurfaceEls
3, 12,11,10,9
10, 20,19,18,17
Then, curve elements are defined to represent the interface between the stiffeners and the square plate. Let us consider the interface between stiffener patch 3 and square plate patch 2. Patch 4 is the interface seen from patch 2 (defined in physical space) and patch 5 is the interface seen from patch 3 (defined in hull parametric space). Control points are:
9, 0.30, 0.00, 0.00
10, 0.30, 1.00, 0.00
13, 0.00, 0.00, 0.00
14, 1.00, 0.00, 0.00
Connectivity table:
*Element,type=U00,elset=CurveEls
4, 10,9
5, 14,13
This interface will take into account displacements coupling and a duplicate (patches 6 and 7) is made to handle rotations coupling.
The same is made for the second stiffener (patches 11 and 12 for displacements, 13 and 14 for rotations).
Then, Lagrange patchs are defined to handle Lagrange multipliers for the coupling:
patch 8 for coupling between patch 2 and 3 (displacements)
patch 9 for coupling between patch 2 and 3 (rotations)
patch 15 for coupling between patch 2 and 10 (displacements)
patch 16 for coupling between patch 2 and 10 (rotations)
Those patchs are made of a single control point, located at arbitrary location.
A summary of control points and patches indices is made in Fig. 6.
Optimization of stiffeners position
This case is defined in the Python script examples/OPT_stiffPanel/optim_stiff_position.py
.
The aim of the optimization process is to minimize the compliance of teh structure while keeping the volume below a 10% variation.
Optimization model
To allow shape modifications, the initial model is refined to obtain the optimization model. Plate and hull are elevated to degree 3 and 2 subdivisions are performed in 1st and 2nd parametrc directions:
nb_deg[:2, 0:2] = 2
nb_ref[:2, 0:2] = 2
Stiffeners and linked curves are elevated to degree 2 in the the first parametric direction:
nb_deg[0, np.array([3, 4, 6, 10, 11, 13])-1] = 1
The design variables are chosen to move the control points of the stiffeners. A shape modification function can be defined:
def movestiffener(coords0, igapara, var):
"""
Shape modification function : move stiffeners control points
"""
igapara._COORDS[:, :] = coords0[:, :]
# Move 1st stiffener
igapara._COORDS[0, igapara._indCPbyPatch[2][cpS[:]]-1] =\
0.50*var[:int(nb_varS/2)]
igapara._COORDS[0, igapara._indCPbyPatch[2][cpS[:]+cpS.size]-1] =\
0.50*var[:int(nb_varS/2)]
# Move 2nd stiffener
igapara._COORDS[0, igapara._indCPbyPatch[9][cpS[:]]-1] =\
1. - 0.50*var[int(nb_varS/2):]
igapara._COORDS[0, igapara._indCPbyPatch[9][cpS[:]+cpS.size]-1] =\
1. - 0.50*var[int(nb_varS/2):]
return None
There are 6 designe variables, allowing to move the control points of the stiffeners. To obtain the initial stiffeners position shown in Fig. 5, an initialization is made with:
movestiffener(modeleIGA._COORDS.copy(), modeleIGA,
np.array([0., 0.7, 0., 0., 0.7, 0.]))
Anaysis model
The analysis model is defined by refining the optimization model:
# plate
nb_deg[:2, :2] = 0
nb_ref[:2, :2] = 3
# stiffeners and linked curves
nb_deg[0, np.array([3, 4, 6, 10, 11, 13])-1] = 1
nb_ref[0, np.array([3, 4, 6, 10, 11, 13])-1] = 6
nb_deg[1, np.array([3, 10])-1] = 2
nb_ref[1, np.array([3, 10])-1] = 2
nb_ref[0, np.array([5, 7, 12, 14])-1] = 6
# Lagrange multipliers
nb_deg[0, np.array([8, 15])-1] = 2
nb_deg[0, np.array([9, 16])-1] = 1
nb_ref[0, np.array([8, 9, 15, 16])-1] = 5
An OPTmodelling
object is built to define the optimization problem. It takes as arguments the optimization model, the number of design variables, the shape modification function and the refinements from optimization to analysis model:
optPB = OPTmodelling(modeleIGA, nb_varS, movestiffener,
nb_degreeElevationByDirection=nb_deg,
nb_refinementByDirection=nb_ref)
Sensibilities computation
A function is defined to compute relative compliance and its gradient with respect to design variables xC
:
def comp(xC, gradC):
"""
Compliance and gradient of compliance computation
(relative to initial value)
"""
ci = optPB.compute_compliance_discrete(xC)/c0
if gradC.size > 0:
global i
i += 1
gradC[:] = optPB.compute_gradCompliance_cplgOnly_AN(xC)/c0
gradC[:] += optPB.compute_gradCompliance_AN(xC)/c0
return ci
Another function compute ralative volume variation and its gradient:
def vol(xV, gradV):
"""
Volume and gradient of volume computation
(relative to initial value)
"""
global listpatch
if gradV.size > 0:
gradV[:] = optPB.compute_gradVolume_AN(xV, listpatch)/V0
return optPB.compute_volume(xV, listpatch)/V0 - 1.
Finally, an nlopt.opt
object is built to solve the optimization problem, defining the objective function, constrainst functions, the bounds of design variables and various options:
Optimization problem solving
minimize = nlopt.opt(nlopt.LD_SLSQP, nb_varS)
minimize.set_min_objective(comp)
minimize.add_inequality_constraint(vol, 1e-5)
minimize.set_ftol_rel(1.0e-06)
minimize.set_xtol_rel(1.0e-06)
minimize.set_maxeval(400)
minimize.set_lower_bounds(0.*np.ones(nb_varS))
minimize.set_upper_bounds(1.*np.ones(nb_varS))
x = minimize.optimize(x0)
Optimization results are shown in Fig. 7.