-
Notifications
You must be signed in to change notification settings - Fork 244
Adjoint API
This page describes the API for adjoint-based sensitivities in Kratos. It is the reference for developers creating new adjoint elements and response functions.
The main components for the adjoint and sensitivity calculations are the elements and conditions, the scheme and the response function. The elements are responsible for providing adjoint and sensitivity matrices which are gradients of the element residual vector. Everything related to the response function is provided by a separate class derived from the base class ResponseFunction. The response function is independent of the adjoint problem and can be used independently of strategies, schemes or builder and solvers. It uses the values stored in the adjoint variables to calculate sensitivities for a set of design variables given by the user. The scheme defines the left- and right-hand sides of the adjoint problem (transient or steady) based on the contributions from the adjoint element and response function and is independent of the sensitivity calculation. It is used in combination with the ResidualBasedLinearStrategy.
An adjoint variable is defined for each primal variable by prefixing the variable name with ADJOINT. For example, the adjoint variable of DISPLACEMENT
is ADJOINT_DISPLACEMENT
.
Adjoint elements are created in the same way as regular elements. The adjoint element should be a separate class from the primal element. For applications with a relatively large number of linear elements like structural mechanics, the primal element type can be given as a template argument to a single generic adjoint element which stores the element internally and uses the element's public member functions to produce the adjoint matrices. Inheritance can also be used to minimize code duplication between primal and adjoint elements. The element functions and their meaning for the adjoint problem are given below.
The following functions are used in the solution of the adjoint problem:
GetDofList(DofsVectorType& rElementalDofList, ProcessInfo& rCurrentProcessInfo)
Gets the list of adjoint dofs. This is the analog of the list of primal dofs.
CalculateLeftHandSide(MatrixType& rLeftHandSideMatrix, ProcessInfo& rCurrentProcessInfo)
Calculates adjoint matrix as the gradient of the negative residual with respect to the primal variable (e.g., DISPLACEMENT). For structural mechanics, this is the transpose of the stiffness matrix. This is zero if the primal variable is a rate (e.g., VELOCITY for fluid mechanics).
CalculateFirstDerivativesLHS(MatrixType& rLeftHandSideMatrix, ProcessInfo& rCurrentProcessInfo)
Calculates the adjoint matrix as the gradient of the negative residual with respect to first derivatives of the primal variable (e.g., VELOCITY). For structural mechanics, this is the transpose of the damping matrix.
CalculateSecondDerivativesLHS(MatrixType& rLeftHandSideMatrix, ProcessInfo& rCurrentProcessInfo)
Calculates the adjoint matrix as the gradient of the negative residual with respect to second derivatives of the primal variable (e.g., ACCELERATION). This is normally the transpose of the mass matrix.
GetValuesVector(Vector& values, int Step = 0)
Gets the vector of adjoint values for the primal variable (e.g., ADJOINT_DISPLACEMENT).
GetFirstDerivativesVector(Vector& values, int Step = 0)
Gets the vector of adjoint values for first derivatives of primal variable (e.g., ADJOINT_VELOCITY).
GetSecondDerivativesVector(Vector& values, int Step = 0)
Gets the vector of adjoint values for second derivatives of primal variable (e.g., ADJOINT_ACCELERATION).
The following functions are used after the solution of the adjoint problem to calculate sensitivities:
CalculateSensitivityMatrix(const Variable<double>& rDesignVariable, Matrix& rOutput, const ProcessInfo& rCurrentProcessInfo)
CalculateSensitivityMatrix(const Variable<array_1d<double,3>>& rDesignVariable, Matrix& rOutput, const ProcessInfo& rCurrentProcessInfo)
Calculates the transpose of the gradient of the element residual with respect to the design variable. (These functions must be added to the element base class).
The sensitivities depend on the design variable which may be a double
(e.g., THICKNESS) or array_1d<double,3>
(e.g., NODAL_COORDINATES). The row dimension of the output is determined from the dimension of design variable (scalar or array_1d) and its storage type (nodal or elemental).
The response function defines a scalar quantity of interest (e.g., drag), its gradients with respect to primal variables and their derivatives and its gradient with respect to design variables. The set of design variables is stored in the response function.
The following functions should be defined for each response function:
CalculateValue()
Calculates the scalar value of the response function.
CalculateGradient(const Element& rElem, const Matrix& rLHS, Vector& rOutput, ProcessInfo& rProcessInfo)
Calculates the gradient of the response function with respect to the primal variable (e.g., DISPLACEMENT). The rLHS matrix is the left hand side matrix of the corresponding adjoint equation.
CalculateFirstDerivativesGradient(const Element& rElem, const Matrix& rLHS, Vector& rOutput, ProcessInfo& rProcessInfo)
Calculates the gradient of the response function with respect to first derivatives of the primal variable (e.g., VELOCITY).
CalculateSecondDerivativesGradient(const Element& rElem, const Matrix& rLHS, Vector& rOutput, ProcessInfo& rProcessInfo)
Calculates the gradient of the response function with respect to second derivatives of the primal variable (e.g., ACCELERATION).
UpdateSensitivities()
Updates the sensitivities for the design variables based on the most recent adjoint solution. The design variables are specified in the json parameters of the response function.
- Getting Kratos (Last compiled Release)
- Compiling Kratos
- Running an example from GiD
- Kratos input files and I/O
- Data management
- Solving strategies
- Manipulating solution values
- Multiphysics
- Video tutorials
- Style Guide
- Authorship of Kratos files
- Configure .gitignore
- How to configure clang-format
- How to use smart pointer in Kratos
- How to define adjoint elements and response functions
- Visibility and Exposure
- Namespaces and Static Classes
Kratos structure
Conventions
Solvers
Debugging, profiling and testing
- Compiling Kratos in debug mode
- Debugging Kratos using GDB
- Cross-debugging Kratos under Windows
- Debugging Kratos C++ under Windows
- Checking memory usage with Valgind
- Profiling Kratos with MAQAO
- Creating unitary tests
- Using ThreadSanitizer to detect OMP data race bugs
- Debugging Memory with ASAN
HOW TOs
- How to create applications
- Python Tutorials
- Kratos For Dummies (I)
- List of classes and variables accessible via python
- How to use Logger
- How to Create a New Application using cmake
- How to write a JSON configuration file
- How to Access DataBase
- How to use quaternions in Kratos
- How to do Mapping between nonmatching meshes
- How to use Clang-Tidy to automatically correct code
- How to use the Constitutive Law class
- How to use Serialization
- How to use GlobalPointerCommunicator
- How to use PointerMapCommunicator
- How to use the Geometry
- How to use processes for BCs
- How to use Parallel Utilities in futureproofing the code
- Porting to Pybind11 (LEGACY CODE)
- Porting to AMatrix
- How to use Cotire
- Applications: Python-modules
- How to run multiple cases using PyCOMPSs
- How to apply a function to a list of variables
- How to use Kratos Native sparse linear algebra
Utilities
Kratos API
Kratos Structural Mechanics API