fol.controls#
Control strategies provided by FoLax.
Identity control#
Authors: Reza Najian Asl, RezaNajian Date: October, 2024 License: FOL/LICENSE
- class fol.controls.identity_control.IdentityControl(control_name, control_settings, num_vars)[source]#
Bases:
ControlIdentity control mapping control variables directly to controlled variables.
This control implements a trivial identity mapping in which the input control vector is returned unchanged as the controlled variable vector. It is primarily intended for cases where no spatial or functional parameterization is required, such as debugging, testing, or optimization workflows where the control variables already represent the desired physical quantities.
The number of control variables and the number of controlled variables are both equal to
num_varsand are fixed at construction time.- Parameters:
control_name (str) – Name identifier for the control instance.
control_settings (dict) – Configuration dictionary. This argument is accepted for interface consistency but is not used by the identity mapping.
num_vars (int) – Number of control variables and controlled variables.
- ComputeControlledVariables(variable_vector)[source]#
Return the controlled variables corresponding to the input vector.
This identity mapping returns the input control vector unchanged.
- Parameters:
variable_vector (jax.numpy.ndarray) – Control variable vector of length
num_control_vars.- Returns:
Controlled variable vector equal to
variable_vector.- Return type:
jax.numpy.ndarray
- Initialize(reinitialize=False)[source]#
Initialize the identity control.
This method sets the number of control variables and controlled variables to
num_vars. Initialization is idempotent and may be forced to re-run by settingreinitialize=True.- Parameters:
reinitialize (bool, optional) – If
True, forces reinitialization even if already initialized. Default isFalse.- Returns:
None
Dirichlet boundary control#
Authors: Kianoosh Taghikhani, Kianoosh1989 Date: August, 2025 License: FOL/LICENSE
- class fol.controls.dirichlet_control.DirichletControl(control_name, control_settings, fe_mesh, fe_loss)[source]#
Bases:
ControlDirichlet boundary-condition control for finite element problems.
This control maps a user-defined set of learnable Dirichlet boundary DOFs to the global Dirichlet arrays owned by a
fol.loss_functions.fe_loss.FiniteElementLoss. It provides a JAX-friendly mechanism to overwrite selected Dirichlet values from a vector of control variables (e.g., during optimization or inverse problems).The control settings define which DOF components (e.g.,
"Ux","Uy","T") are controlled on which boundary node sets. DuringInitialize(), the class:Ensures the associated FE loss is initialized.
Reads the global Dirichlet indices and values from the FE loss.
Builds a flattened index map (into the FE loss Dirichlet arrays) for the subset of Dirichlet DOFs that are controlled.
Stores segment offsets and sizes so the control vector can be broadcast to the corresponding controlled DOFs efficiently.
- Parameters:
control_name (str) – Name identifier for the control instance.
control_settings (dict) –
Control configuration dictionary. Must contain the key
"learning_boundary"mapping DOF names to a list of boundary node-set names. Example:{ "learning_boundary": { "Ux": ["left", "right"], "Uy": ["top"] } }
fe_mesh (Mesh) – Finite element mesh used to resolve boundary node sets via
fol.mesh_input_output.mesh.Mesh.GetNodeSet().fe_loss (FiniteElementLoss) – FE loss providing the global Dirichlet index/value arrays and the DOF ordering used to compute DOF indices per node.
- settings#
Control configuration dictionary.
- Type:
dict
- loss_function#
Associated FE loss object.
- Type:
- dirichlet_values#
Copy of the FE loss Dirichlet values array (one value per Dirichlet DOF).
- Type:
jax.numpy.ndarray
- dirichlet_indices#
Copy of the FE loss Dirichlet global DOF indices.
- Type:
jax.numpy.ndarray
- learning_dirichlet_indices#
Indices into
dirichlet_indices/dirichlet_valuesfor the subset of Dirichlet DOFs that are controlled.- Type:
jax.numpy.ndarray
- learning_dirichlet_starts#
Segment start offsets for each (dof, boundary) block appended into
learning_dirichlet_indicesduring initialization.- Type:
jax.numpy.ndarray
- learning_dirichlet_sizes#
Segment sizes (number of controlled Dirichlet DOFs) for each (dof, boundary) block appended into
learning_dirichlet_indices.- Type:
jax.numpy.ndarray
- num_control_vars#
Number of DOF components listed in
control_settings["learning_boundary"].- Type:
int
- num_controlled_vars#
Total number of individual Dirichlet DOFs affected by this controller.
- Type:
int
- initialized#
Whether
Initialize()has been executed.- Type:
bool
Notes
The control vector passed to
ComputeControlledVariables()is expanded by repeating each control entry according tolearning_dirichlet_sizes. This implies the control vector is interpreted as one scalar per controlled (dof, boundary) block, broadcast to all nodes in that block.This class does not modify the FE loss object directly. It returns an updated Dirichlet value array that can be used by downstream code.
- ComputeControlledVariables(variable_vector)[source]#
Compute an updated Dirichlet value array from control variables.
The returned array has the same shape as
dirichlet_values. Only the entries corresponding tolearning_dirichlet_indicesare overwritten.- Broadcasting rule:
Each entry in
variable_vectoris repeated according tolearning_dirichlet_sizesand assigned to the corresponding segment inlearning_dirichlet_indices.
- Parameters:
variable_vector (jax.numpy.ndarray) – Control variables to assign. Expected to be a 1D array whose length matches the number of (dof, boundary) blocks created during initialization (i.e.,
len(learning_dirichlet_sizes)).- Returns:
Updated Dirichlet values array with controlled entries overwritten.
- Return type:
jax.numpy.ndarray
- Raises:
ValueError – If
Initializehas not been called, or ifvariable_vectorhas an incompatible length for the configured segments.
- Initialize(reinitialize=False)[source]#
Initialize index mappings for learnable Dirichlet DOFs.
This method constructs the internal flattened index structures that map controlled Dirichlet DOFs to entries of the FE loss Dirichlet arrays.
It populates: -
learning_dirichlet_indices: flattened indices into the FE loss Dirichlet list -learning_dirichlet_starts: start offsets per (dof, boundary) block -learning_dirichlet_sizes: sizes per (dof, boundary) block- Parameters:
reinitialize (bool, optional) – If
True, forces rebuilding the mappings even if already initialized. Defaults toFalse.- Returns:
None
- Raises:
KeyError – If
"learning_boundary"is missing fromcontrol_settings.ValueError – If a DOF name in
"learning_boundary"is not present infe_loss.GetDOFs().
Fourier-based control#
Authors: Reza Najian Asl, RezaNajian Date: April, 2024 License: FOL/LICENSE
- class fol.controls.fourier_control.FourierControl(control_name, control_settings, fe_mesh)[source]#
Bases:
ControlFourier-based parametric control defined over a finite element mesh.
This control maps a compact set of design variables (Fourier coefficients) to a spatially varying scalar field evaluated at mesh nodes. The nodal field is represented as a truncated cosine Fourier series in the x-, y-, and z-directions, then smoothly projected to user-defined bounds using a sigmoid-based scaling.
Formulation#
Let the mesh contain nodes with coordinates
(x_i, y_i, z_i). The user provides one-dimensional frequency arraysx_freqs,y_freqs, andz_freqs. A Cartesian product of these arrays defines a collection of frequency triplets(f_x, f_y, f_z), constructed by callingmeshgrid(x_freqs, y_freqs, z_freqs, indexing="ij")and flattening the result. Each triplet corresponds to exactly one cosine basis function.Given a control vector
aof lengthlen(x_freqs) * len(y_freqs) * len(z_freqs) + 1, the unbounded nodal field value at nodeiis computed as:The first entry
a[0]defines a constant (mean) mode and contributesa[0] / 2to every node.Each remaining entry
a[j]multiplies one cosine basis function associated with a frequency triplet(f_x, f_y, f_z)and contributesa[j] * cos(pi * f_x * x_i) * cos(pi * f_y * y_i) * cos(pi * f_z * z_i)to the nodal value.
The unbounded nodal field
K_iis obtained by summing the constant contribution and all cosine-mode contributions.The nodal field is then mapped to user-defined bounds via a smooth sigmoid projection:
u_i = (max - min) * sigmoid(beta * (K_i - 0.5)) + minThis projection enforces
u_iin[min, max]while preserving differentiability for gradient-based optimization.- param control_name:
Name identifier for the control instance.
- type control_name:
str
- param control_settings:
Dictionary defining the Fourier parameterization. Required keys:
"beta","x_freqs","y_freqs","z_freqs". Optional keys:"min"and"max"defining output bounds.- type control_settings:
dict
- param fe_mesh:
Finite element mesh providing nodal coordinates via
GetNodesX(),GetNodesY(), andGetNodesZ().- type fe_mesh:
Mesh
- settings#
Control configuration dictionary provided at construction.
- Type:
dict
- min#
Lower bound of the controlled field (default:
1e-6if not set).- Type:
float
- max#
Upper bound of the controlled field (default:
1.0if not set).- Type:
float
- beta#
Sigmoid sharpness parameter controlling projection steepness.
- Type:
float
- x_freqs#
Frequency values in the x-direction.
- Type:
jax.numpy.ndarray
- y_freqs#
Frequency values in the y-direction.
- Type:
jax.numpy.ndarray
- z_freqs#
Frequency values in the z-direction.
- Type:
jax.numpy.ndarray
- frquencies_vec#
Flattened array of frequency triplets with shape
(n_modes, 3), wheren_modes = len(x_freqs) * len(y_freqs) * len(z_freqs).- Type:
jax.numpy.ndarray
- num_control_vars#
Number of control variables (Fourier coefficients), equal to
n_modes + 1.- Type:
int
- num_controlled_vars#
Number of controlled variables, equal to the number of mesh nodes.
- Type:
int
- initialized#
Whether
Initialize()has been called.- Type:
bool
Notes
The first coefficient
a[0]is treated as a mean mode and scaled by1/2to match the implemented definition:K = a[0]/2 + sum_j a[j] * cos_x * cos_y * cos_zwhere each
a[j]forj >= 1corresponds to one frequency triplet.- ComputeControlledVariables(variable_vector)[source]#
Evaluate the controlled field at mesh nodes from Fourier coefficients.
This method maps the input control vector to a nodal scalar field by evaluating a truncated cosine Fourier series at each mesh node. The resulting field is passed through a sigmoid transformation to enforce lower and upper bounds.
The first entry of
variable_vectorcorresponds to the constant (mean) mode. The remaining entries correspond to cosine modes defined by the Cartesian product ofx_freqs,y_freqs, andz_freqs.- Parameters:
variable_vector (jax.numpy.ndarray) – One-dimensional array of Fourier coefficients. Its length must equal
num_control_vars.- Returns:
Array of controlled values evaluated at mesh nodes, with shape
(num_nodes,).- Return type:
jax.numpy.ndarray
- Raises:
ValueError – If
Initializehas not been called or if the input vector has an incompatible length.
- Finalize()[source]#
Finalize the control.
This method is called once at the end of a training or optimization process. Derived classes may override it to release resources or perform cleanup. The default base class does not implement any finalization logic.
- Returns:
None
- Initialize(reinitialize=False)[source]#
Initialize the Fourier basis and control dimensions.
This method prepares the frequency grid, determines the number of control variables, and caches frequency combinations for efficient evaluation. Initialization is performed once unless
reinitializeis set toTrue.- Parameters:
reinitialize (bool, optional) – If
True, forces reinitialization even if already initialized. Default isFalse.- Returns:
None
- Raises:
KeyError – If required frequency arrays or parameters are missing from
control_settings.
Voronoi-based control (2D)#
Authors: Kianoosh Taghikhani, kianoosh1989 Date: October, 2024 License: FOL/LICENSE
- class fol.controls.voronoi_control2D.VoronoiControl2D(control_name, control_settings, fe_mesh)[source]#
Bases:
ControlVoronoi-based parametric control in two dimensions.
This control maps a vector of control variables to a nodal scalar field using a Voronoi tessellation defined by a set of seed points in the two-dimensional domain. Each mesh node is assigned the value associated with the nearest seed point, measured by Euclidean distance in the (x, y) plane.
The control variables consist of: - x-coordinates of the Voronoi seed points, - y-coordinates of the Voronoi seed points, - scalar values associated with each seed.
For each mesh node, the controlled value is selected from the seed whose coordinates are closest to the node coordinates. This produces a piecewise-constant field over the mesh, with discontinuities along Voronoi cell boundaries.
The number of control variables is three times the number of seeds, and the number of controlled variables equals the number of mesh nodes.
- Parameters:
control_name (str) – Name identifier for the control instance.
control_settings (dict) – Dictionary defining the Voronoi parameterization. Required entries include
"number_of_seeds"and"E_values". The length of"E_values"must matchnumber_of_seeds.fe_mesh (Mesh) – Finite element mesh providing nodal coordinates.
- ComputeControlledVariables(variable_vector)[source]#
Compute the nodal field induced by the Voronoi control.
This method interprets the input control vector as concatenated arrays of seed x-coordinates, seed y-coordinates, and seed values. For each mesh node, the nearest seed point is identified using Euclidean distance, and the corresponding seed value is assigned to the node.
- Parameters:
variable_vector (jax.numpy.ndarray) – One-dimensional control vector of length
3 * number_of_seeds. The first third contains x-coordinates of the seeds, the second third contains y-coordinates, and the final third contains the scalar values associated with each seed.- Returns:
One-dimensional array of controlled values evaluated at mesh nodes, with length equal to the number of mesh nodes.
- Return type:
jax.numpy.ndarray
- Finalize()[source]#
Finalize the control.
This method is called once at the end of a training or optimization process. Derived classes may override it to release resources or perform cleanup. The default base class does not implement any finalization logic.
- Returns:
None
- Initialize(reinitialize=False)[source]#
Initialize Voronoi seed configuration and control dimensions.
This method reads the number of Voronoi seeds and their associated values from
control_settingsand sets the number of control and controlled variables. Initialization is performed once unlessreinitializeis set toTrue.- Parameters:
reinitialize (bool, optional) – If
True, forces reinitialization even if already initialized. Default isFalse.- Returns:
None
- Raises:
ValueError – If
E_valuesis not provided as a list or tuple, or if its length is incompatible withnumber_of_seeds.
Voronoi-based control (3D)#
Authors: Kianoosh Taghikhani, kianoosh1989 Date: October, 2024 License: FOL/License.txt
- class fol.controls.voronoi_control3D.VoronoiControl3D(control_name, control_settings, fe_mesh)[source]#
Bases:
ControlVoronoi-based parametric control in three dimensions.
This control maps a vector of design variables to a nodal scalar field defined over a three-dimensional finite element mesh. The mapping is based on a Voronoi tessellation induced by a set of seed points in the three-dimensional space.
The control variables represent: - x-coordinates of Voronoi seed points, - y-coordinates of Voronoi seed points, - z-coordinates of Voronoi seed points, - one scalar value associated with each seed.
For each mesh node with coordinates
(X_i, Y_i, Z_i), the controlled value is taken from the seed point that is closest to the node in Euclidean distance. This produces a piecewise-constant field over the mesh, with discontinuities along Voronoi cell boundaries.The number of control variables is four times the number of seeds, and the number of controlled variables equals the number of mesh nodes.
- Parameters:
control_name (str) – Name identifier for the control instance.
control_settings (dict) – Dictionary defining the Voronoi parameterization. Expected keys include
"number_of_seeds"and"E_values". The entry"E_values"is validated during initialization but is not used directly in the control mapping.fe_mesh (Mesh) – Finite element mesh providing nodal coordinates.
- ComputeControlledVariables(variable_vector)[source]#
Compute the nodal field induced by the 3D Voronoi control.
The input control vector is interpreted as a concatenation of:
x-coordinates of the Voronoi seeds,
y-coordinates of the Voronoi seeds,
z-coordinates of the Voronoi seeds,
scalar values associated with each seed.
For each mesh node coordinate
(X_i, Y_i, Z_i), the nearest seed point is identified using Euclidean distance, and the corresponding seed value is assigned to the node.- Parameters:
variable_vector (jax.numpy.ndarray) – One-dimensional control vector of length
4 * number_of_seeds.- Returns:
One-dimensional array of controlled values evaluated at mesh nodes, with length equal to the number of mesh nodes.
- Return type:
jax.numpy.ndarray
Notes
This method does not explicitly validate the length of
variable_vectorand does not explicitly raise exceptions. If the input vector has an incompatible length, indexing or shape errors may occur during JAX tracing or execution.
- Finalize()[source]#
Finalize the control.
This method is called once at the end of a training or optimization process. Derived classes may override it to release resources or perform cleanup. The default base class does not implement any finalization logic.
- Returns:
None
- Initialize(reinitialize=False)[source]#
Initialize Voronoi seed configuration and control dimensions.
This method reads the number of Voronoi seeds from
control_settingsand sets the number of control variables and controlled variables. Initialization is performed once unlessreinitializeis set toTrue.The number of control variables is defined as:
4 * number_of_seeds(x-coordinates, y-coordinates, z-coordinates, and one scalar value per seed)
The number of controlled variables equals the number of mesh nodes.
- Parameters:
reinitialize (bool, optional) – If
True, forces reinitialization even if already initialized. Default isFalse.- Returns:
None
- Raises:
ValueError – If
control_settings["E_values"]is not a tuple or a list.