Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
A Simple Optimization Test Case for MMA

This example demonstrates the use of NEKO-TOP with the Method of Moving Asymptotes (MMA) to solve a simple unconstrained optimization problem on a 3D field design. For this example, we read a simple mesh file (box.nmsh)—typically a spectral element mesh for a box generated by the genmeshbox tool in Neko.

Problem Description

In the driver.f90 file, the distribution of a scalar field in the mesh is defined as the design field (des) using the simplefield_design_t type.

‍Note: The design variables are defined at every GLL point in the mesh.

Each GLL node has one design variable associated with it, so the total number of design variables equals the number of GLL points in the mesh.

The simplefield_design_t has four vectors:

type(vector_t) :: values
type(vector_t) :: x_coord
type(vector_t) :: y_coord
type(vector_t) :: z_coord

These represent the design variable value, and the x-, y-, and z-coordinates of its corresponding GLL point. All four vectors have a length equal to the total number of GLL points in the mesh. For simplicity, in this file, we use des.values instead of des.values.x. (Please check the vector_t description in Neko)


Objective Function

Minimize the mean squared difference between the design variable at each mesh node and the node’s physical coordinate:

\[ f(\mathbf{x}) = \frac{1}{n} \sum_{j=1}^{n} \big(\texttt{des.values}(j) - \texttt{des.x}(j)\big)^2 \]

where:

  • \(\texttt{des.x}(j)\) is the x-coordinate of node \(j\).
  • \(\texttt{des.values}(j)\) is the value of the scalar field at the \(j\)-th GLL node.
  • \(n\) is the total number of GLL points in the mesh.

The sensitivity (gradient) of the objective with respect to each design variable, assuming \([d_1, d_2, \ldots, d_n]\) denote the vector of design variables, is:

\[ \frac{\partial f}{\partial d_j} = \frac{2}{n} \left( \texttt{des.values}(j) - \texttt{des.x}(j) \right) \]

Constraints

None (unconstrained problem).


Interpretation

The full optimization problem can be stated as:

\[ \begin{aligned} &\min \frac{1}{n} \sum_{j=1}^n (d_j - x_j)^2, \ & d_j \in [\texttt{xmin}, \texttt{xmax}], \quad j=1,\ldots,n, \end{aligned} \]

where:

  • \(\mathbf{d} = [d_1, d_2, \ldots, d_n]\) represents the design variables.
  • \(x_j\) is the x-coordinate at the \(j\)-th GLL point.

Since the objective is minimized when the design field matches the x-coordinates, the expected optimal solution is:

\[ d_j = x_j, \quad \forall j=1,\ldots,n \]

If the mesh $x$-coordinates exceed the design variable bounds "xmin": 0.0 and "xmax": 5.0, the optimizer will cap the design variables accordingly.


Files

  • driver.f90: Main program that sets up and runs the optimization problem.
  • example_problem.f90: Contains custom definition for the objective function and sensitivity.
  • box.nmsh: Mesh file defining the spectral element grid.

Mesh Generation

The mesh file box.nmsh can be generated using the mesh.sh script with the following syntax:

./mesh.sh -b x0 x1 y0 y1 z0 z1 nelx nely nelz periodic_x periodic_y periodic_z

For detailed usage, refer to the mesh.sh documentation in the Neko-top repository.

A quick example of how to use mesh.sh:

./mesh.sh -b 0 10 0 1 0 1 64 4 4 .false. .false. .false.

This creates a 3D box mesh with:

  • Physical dimensions: x = 0–10, y = 0–1, z = 0–1
  • Element counts: 64 elements along x, 4 along y, and 4 along z
  • Periodicity: No periodicity in any direction

The output mesh is saved at:

/path/to/neko-top/data_local/box.nmsh

Ensure the environment is correctly set up before running the script. Typically, this can be done by creating a prepare.env file in the main directory of Neko-top to configure the necessary dependency paths for mesh.sh:

export NEKO_DIR=/path/to/neko-top/external/neko
export JSON_FORTRAN_DIR=/path/to/neko-top/external/json-fortran
export HDF5_DIR=/path/to/neko-top/external/hdf5